# Project export: SafeSip

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2024
- Tagline: Excessive alcohol consumption can jeopardize personal safety. SafeSip uses machine learning to warn users when their consumption has reached unsafe levels, based on accelerometer movement data.
- Devpost: https://devpost.com/software/safesip-umodkf
- GitHub: https://github.com/aakritil/treehacks
- Team: 2 GitHub contributor(s) — James Bole Pan (12 commits), aakritil (4 commits)

## Devpost submission (written by the team)

### Inspiration

College students are uniquely vulnerable to the dangers of excessive alcohol consumption. Blacking out substantially raises the risk of sexual assault, injury, and legal consequences, especially for younger students. That’s why we’ve created SafeSip, the first low-commitment, easy-to-use app to ensure safe drinking. SafeSip intelligently notifies users if they are likely to black out, based on their movements, giving users the tools they need to stay safe before tragedy strikes.

### What it does

By analyzing users’ gait from smartphone accelerometer data, SafeSip provides an accurate estimate of a user’s intoxication level and warns them to stop alcohol consumption before serious consequences begin. Existing solutions require significant user input, such as manually entering every drink. Yet, as users drink more, they become increasingly careless, either forgetting or choosing not to track drinks, rendering these solutions ineffective. With SafeSip, users only have to press a button to indicate that they have started drinking, and our technology takes care of the rest. SafeSip extends existing research in the field, using machine learning methods to infer transdermal alcohol content (TAC) from accelerometer data. This is something entirely novel: while existing literature has suggested the possibility of doing so, SafeSip is the first working implementation. By accurately estimating a user’s TAC, SafeSip is able to preempt and stop excessive alcohol consumption, preventing students from blacking out. Studies show that people are not aware of the amount they consume while drinking, and informing them can prevent blackouts. Further, SafeSip has in-app tools to track historical alcohol consumption and provide safe-drinking education. With SafeSip, users can ensure that they have a safe and enjoyable drinking experience. SafeSip also prioritizes friends-and-family support, spurring conversations that disrupt perceived support for blackout drinking.

### How we built it

SafeSip is built with an array of different technologies. The native iOS app itself is built in Swift, collecting and streaming movement data using Apple’s Core Motion framework. Our app is connected to the Firebase backend, which handles authentication and storage. A neural network built with PyTorch and hosted on Google Cloud Compute performs the novel TAC prediction.

### Challenges we ran into

Data Wrangling: The dataset we used to train our model was quite unruly. Values were in different formats, timestamps didn’t match up, and data was everywhere. Wrangling and getting everything into a usable format took considerable thought and troubleshooting, requiring us to return to first principles. New to iOS: This was our first time ever building an iOS app. We’re proud to have gone from knowing nothing about Swift to having a working App in 36 hours.

### Accomplishments we're proud of

For three of our four members, this was our first-ever hackathon! We’re proud to have made it through. Making something new! SafeSip is something novel. No one has ever done what we’ve done with deploying real-time TAC-level prediction models leveraging ML and accelerometer data. We’re excited to contribute to the literature on this problem. Learning new tech: This was our first time working with Swift, and front-end technologies in native iOS. We’re very happy with how much we learned, and how the end product looks.

### What we learned

Swift: We’re new to Swift, and we had a lot of fun learning this new tech. Hackathons: We learned how to navigate and manage hackathons. Production-grade ML: We improved on impractical laboratory techniques to create a practical tool that balances speed and performance.

### What's next

More Features: We think there’s a lot more room for new features in SafeSip. A few ideas we had were pass-out detection, which would call an emergency contact once you passed out, using physiological factors to distinguish it from sleep. We also thought of alcoholism alerts, which would alert you if you were drinking too frequently or heavily, based on CDC guidelines. We’re excited by our technology, and think there’s a lot of room for us to make drinking safer. Apple Watch Integration: By integrating with an Apple Watch, we could pull more biometric data, such as heart rate and temperature, allowing us to better estimate TAC, and make more accurate black-out predictions. Broader Integration with Different Wearable Devices: We plan to generalize to other brands of wearable devices leveraging platforms like TerraAPI so that we can provide our services to a broader range of users. CarPlay integration: we could potentially use SafeSip to integrate with CarPlay, ensuring that heavily intoxicated users do not drive. This could be paired with easy access to an Uber/Lyft to ensure user safety.

## README (from the GitHub repository)

# SafeSip: Alcohol black out warning and blood alcohol detector with deep learning and motion sensors 

Excessive alcohol consumption can jeopardize personal safety. SafeSip uses machine learning to warn users when their consumption has reached unsafe levels, based on accelerometer movement data.

<img src="https://github.com/aakritil/treehacks/assets/63487762/f23c82db-b458-42cc-bde5-f556f5964147" width="500" height="350" alt="Landing Pages">

<img src="https://github.com/aakritil/treehacks/assets/63487762/5124b4cd-dc71-4f23-ab91-13d03d87a7cb" width="160" height="350" alt="Main Page">

<img src="https://github.com/aakritil/treehacks/assets/63487762/e4d859fa-d9a2-4663-a26b-a978ddd32fa8" width="160" height="350" alt="Schedule Page">


View our DevPost [here!](https://devpost.com/software/safesip-umodkf)

## Inspiration

College students are uniquely vulnerable to the dangers of excessive alcohol consumption. Blacking out substantially raises the risk of [sexual assault, injury, and legal consequences](https://onlinelibrary.wiley.com/doi/10.1111/acer.15157), especially for younger students. That’s why we’ve created SafeSip, the first low-commitment, easy-to-use app to ensure safe drinking. SafeSip intelligently notifies users if they are likely to black out, based on their movements, giving users the tools they need to stay safe _before_ tragedy strikes.

## What it does

By analyzing users’ gait from smartphone accelerometer data, SafeSip provides an accurate estimate of a user’s intoxication level and warns them to stop alcohol consumption before serious consequences begin. 

Existing solutions require significant user input, such as [manually entering every drink](https://apps.apple.com/us/app/drinkcontrol-alcohol-tracker/id456207840). Yet, as users drink more, they become increasingly careless, either forgetting or choosing not to track drinks, rendering these solutions ineffective. With SafeSip, users only have to press a button to indicate that they have started drinking, and our technology takes care of the rest. SafeSip extends existing research in the field, using machine learning methods to infer transdermal alcohol content (TAC) from accelerometer data. This is something entirely novel: while [existing literature](https://ceur-ws.org/Vol-2429/paper6.pdf) has suggested the possibility of doing so, **SafeSip is the first working implementation**. 

By accurately estimating a user’s TAC, SafeSip is able to preempt and stop excessive alcohol consumption, preventing students from blacking out. Studies show that people [are not aware of the amount they consume while drinking](https://onlinelibrary.wiley.com/doi/pdf/10.1111/dar.13215?casa_token=QKxCYOE25RMAAAAA:IJIrYo8mXYe747S0-qIYAMbekNd7x3GUks8OXxxKCQy9GIoGL_lJ-WMtkUVNS18NQF4k1qaTlOT-uA), and informing them can prevent blackouts.

Further, SafeSip has in-app tools to track historical alcohol consumption and provide safe-drinking education. With SafeSip, users can ensure that they have a safe and enjoyable drinking experience. SafeSip also prioritizes friends-and-family support, spurring conversations that [disrupt perceived support for blackout drinking](https://pubmed.ncbi.nlm.nih.gov/32224219/).


## How we built it

SafeSip is built with an array of different technologies. The native iOS app itself is built in Swift, collecting and streaming movement data using Apple’s Core Motion framework. Our app is connected to the Firebase backend, which handles authentication and storage. A neural network built with PyTorch and hosted on Google Cloud Compute performs the novel TAC prediction. 

## Challenges we ran into

Data Wrangling: The dataset we used to train our model was quite unruly. Values were in different formats, timestamps didn’t match up, and data was everywhere. Wrangling and getting everything into a usable format took considerable thought and troubleshooting, requiring us to return to first principles. 

New to iOS: This was our first time ever building an iOS app. We’re proud to have gone from knowing nothing about Swift to having a working App in 36 hours. 

## Accomplishments that we're proud of

For three of our four members, this was our first-ever hackathon! We’re proud to have made it through. 

Making something new! SafeSip is something novel. No one has ever done what we’ve done with deploying real-time TAC-level prediction models leveraging ML and accelerometer data. We’re excited to contribute to the literature on this problem. 

Learning new tech: This was our first time working with Swift, and front-end technologies in native iOS. We’re very happy with how much we learned, and how the end product looks. 

## What we learned

Swift: We’re new to Swift, and we had a lot of fun learning this new tech. 

Hackathons: We learned how to navigate and manage hackathons. 

Production-grade ML: We improved on impractical laboratory techniques to create a practical tool that balances speed and performance.

## What's next for SafeSip

More Features: We think there’s a lot more room for new features in SafeSip. A few ideas we had were pass-out detection, which would call an emergency contact once you passed out, using [physiological factors](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3093974/) to distinguish it from sleep. We also thought of alcoholism alerts, which would alert you if you were drinking too frequently or heavily, based on [CDC guidelines](https://www.cdc.gov/alcohol/faqs.htm). We’re excited by our technology, and think there’s a lot of room for us to make drinking safer. 

Apple Watch Integration: By integrating with an Apple Watch, we could pull more biometric data, such as heart rate and temperature, allowing us to better estimate TAC, and make more accurate black-out predictions. 

Broader Integration with Different Wearable Devices: We plan to generalize to other brands of wearable devices leveraging platforms like TerraAPI so that we can provide our services to a broader range of users. 

CarPlay integration: we could potentially use SafeSip to integrate with CarPlay, ensuring that heavily intoxicated users do not drive. This could be paired with [easy access to an Uber/Lyft](https://www.uber.com/us/en/u/reasons-to-ride/) to ensure user safety.


## Detected evidence (automated analysis)

Indexed codebase: 154 recognized source files, 558 KB.
- C (language) — detected in the code
- Swift (language) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- Firebase (technology) — claimed on Devpost, not found in the code
- Python (language) — claimed on Devpost, not found in the code
- PyTorch (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 216)

```
.all-contributorsrc
.github/workflows/beta-deployment.yml
.github/workflows/build.yml
.gitignore
CardinalKit-Example/.swiftlint.yml
CardinalKit-Example/CardinalKit_ExampleRelease.entitlements
CardinalKit-Example/CardinalKit-Example.entitlements
CardinalKit-Example/CardinalKit/.DS_Store
CardinalKit-Example/CardinalKit/AppDelegate.swift
CardinalKit-Example/CardinalKit/AppDelegate+CardinalKit.swift
CardinalKit-Example/CardinalKit/Components/Care Team/CareTeamViewControllerRepresentable.swift
CardinalKit-Example/CardinalKit/Components/LaunchUIView.swift
CardinalKit-Example/CardinalKit/Components/MainUIView.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/LoginExistingUserViewController.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/OnboardingPageView.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/OnboardingUIView.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/OnboardingViewController.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/OnboardingViewController+Coordinator.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/PasscodeViewController.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKHealthDataStepViewController.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKHealthRecordsStepViewController.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKInstructionSteps.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKLoginStepViewController.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKMultipleSignInStep.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKSignInView.swift
CardinalKit-Example/CardinalKit/Components/Onboarding/Steps/CKVerifyConsentDocumentStep.swift
CardinalKit-Example/CardinalKit/Components/Profile/DocumentPreviewViewController.swift
CardinalKit-Example/CardinalKit/Components/Profile/ProfileUIView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/ChangePasscodeView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/DocumentView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/HelpView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/PatientIDView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/ReportView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/SendRecordsView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/SupportView.swift
CardinalKit-Example/CardinalKit/Components/Profile/Views/WithdrawView.swift
CardinalKit-Example/CardinalKit/Components/Profile/WithdrawalViewController.swift
CardinalKit-Example/CardinalKit/Components/Schedule/ScheduleViewController.swift
CardinalKit-Example/CardinalKit/Components/Schedule/ScheduleViewControllerRepresentable.swift
CardinalKit-Example/CardinalKit/Components/Schedule/Views/CheckListItemViewController.swift
CardinalKit-Example/CardinalKit/Components/Schedule/Views/SurveyItemViewController.swift
CardinalKit-Example/CardinalKit/Components/Schedule/Views/TestViewController.swift
CardinalKit-Example/CardinalKit/Components/Schedule/Views/TipView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Model/CloudTaskItem.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Model/CoffeeChartDataSource.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Model/LocalTaskItem.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Model/TaskSamples.swift
CardinalKit-Example/CardinalKit/Components/Tasks/TasksUIView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/CloudTaskListItemView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/CoffeePieChartView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/CoffeeUIView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/DataCollectionView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/EducationView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/HotlineUIView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/LearnUIView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/LocalTaskListItemView.swift
CardinalKit-Example/CardinalKit/Components/Tasks/Views/SensorsDemoUIView.swift
CardinalKit-Example/CardinalKit/Library/Auth/CKStudyUser.swift
CardinalKit-Example/CardinalKit/Library/CareKit/CKCareKitManager.swift
CardinalKit-Example/CardinalKit/Library/CareKit/CKCareKitManager+Sample.swift
CardinalKit-Example/CardinalKit/Library/CareKit/CKCareKitRemoteSyncWithFirestore.swift
CardinalKit-Example/CardinalKit/Library/Configuration/CKConfig.swift
CardinalKit-Example/CardinalKit/Library/Configuration/CKPropertyReader.swift
CardinalKit-Example/CardinalKit/Library/EmailHelper.swift
CardinalKit-Example/CardinalKit/Library/Errors.swift
CardinalKit-Example/CardinalKit/Library/Extensions+UIColor.swift
CardinalKit-Example/CardinalKit/Library/HealthKit/CKHealthKitManager.swift
CardinalKit-Example/CardinalKit/Library/HealthKit/CKHealthRecordsManager.swift
CardinalKit-Example/CardinalKit/Library/Metrics.swift
CardinalKit-Example/CardinalKit/Library/Networking/CKNetworkManager.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKConsentManager.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKFHIRTaskViewController.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKORKSerialization.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKResearchSurveysManager.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKTaskViewController.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKUploadFHIRTaskViewControllerDelegate.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/CKUploadToGCPTaskViewControllerDelegate.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/ConsentDocument.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/JsonToSurvey.swift
CardinalKit-Example/CardinalKit/Library/ResearchKit/ORKESerialization.h
CardinalKit-Example/CardinalKit/Library/ResearchKit/ORKESerialization.m
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/FHIRExtensions/FHIRExtensions.swift
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/FHIRToResearchKit/FHIRToResearchKitConversionError.swift
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/FHIRToResearchKit/NavigationRules.swift
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/FHIRToResearchKit/ORKNavigableOrderedTask+FHIR.swift
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/FHIRToResearchKit/Questionnaire+ValueSets.swift
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/FHIRToResearchKit/QuestionnaireItem+ResearchKit.swift
CardinalKit-Example/CardinalKit/Library/ResearchKitOnFHIR/ResearchKitToFHIR/ORKTaskResult+FHIR.swift
CardinalKit-Example/CardinalKit/SceneDelegate.swift
CardinalKit-Example/CardinalKit/SceneDelegate+CardinalKit.swift
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/AppleLogo.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/CardinalKit/CKLogo.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/CardinalKit/CKLogoIcon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/CardinalKit/CKLogoSimple.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/CardinalKit/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/CardinalKit/GraphicOperatingSystem.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/GoogleLogo.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/ActivityIcon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/CoffeeIcon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/DataIcon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/HotlineIcon.appiconset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/SurveyIcon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/List Icons/WatchIcon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/ResearchKit Survey/circle.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/ResearchKit Survey/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/ResearchKit Survey/pentagon.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/ResearchKit Survey/pinwheel.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/ResearchKit Survey/square.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (original)/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (original)/tab_activities.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (original)/tab_dashboard.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (original)/tab_learn.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (original)/tab_profile_main.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (v2)/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (v2)/tab_care.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (v2)/tab_profile.imageset/Contents.json
CardinalKit-Example/CardinalKit/Supporting Files/Assets.xcassets/Tabs (v2)/tab_schedule.imageset/Contents.json
[96 more files omitted for size]
```

### Dependencies

No dependency index available.

### Recent commits (newest first)

- Merge pull request #1 from AkshayM21/patch-1
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- Update README.md
- resolved merge conflict
- Launch Screen set
- pushing
- Updated consent form
- Done with the scheduling mockup
- Tested on James's iPhone
- Updated all logos
- Made the red/green icon
- Merge remote-tracking branch 'refs/remotes/origin/main'
- Added logo
- Aakriti updates

## Key source files (fetched from GitHub, selected and truncated for size)

### Gemfile

```
#
# This source file is part of the Continous Delivery open source project
#
# SPDX-FileCopyrightText: 2022 Paul Schmiedmayer <paul.schmiedmayer@tum.de>
#
# SPDX-License-Identifier: MIT
#

source "https://rubygems.org"

gem "fastlane"
gem "cocoapods"
```

### CardinalKit-Example/.swiftlint.yml

```yaml
#
# This source file is part of the CardinalKit open-source project
#
# SPDX-FileCopyrightText: 2022 Stanford University and the project authors (see CONTRIBUTORS.md)
#
# SPDX-License-Identifier: MIT
#
  
# The whitelist_rules configuration also includes rules that are enabled by default to provide a good overview of all rules.
only_rules:
  # All Images that provide context should have an accessibility label. Purely decorative images can be hidden from accessibility.
  - accessibility_label_for_image
  # Attributes should be on their own lines in functions and types, but on the same line as variables and imports.
  - attributes
  # Prefer using Array(seq) over seq.map { $0 } to convert a sequence into an Array.
  - array_init
  # Prefer the new block based KVO API with keypaths when using Swift 3.2 or later.
  - block_based_kvo
  # Non-constant variables should not be listed in a closure’s capture list to avoid confusion about closures capturing variables at creation time.
  - capture_variable
  # Delegate protocols should be class-only so they can be weakly referenced.
  - class_delegate_protocol
  # Closing brace with closing parenthesis should not have any whitespaces in the middle.
  - closing_brace
  # Closure bodies should not span too many lines.
  - closure_body_length
  # Closure end should have the same indentation as the line that started it.
  - closure_end_indentation
  # Closure parameters should be on the same line as opening brace.
  - closure_parameter_position
  # Closure expressions should have a single space inside each brace.
  - closure_spacing
  # Use commas to separate types in inheritance lists
  - comma_inheritance
  # Prefer at least one space after slashes for comments.
  - comment_spacing
  # All elements in a collection literal should be vertically aligned
  - collection_alignment
  # Colons should be next to the identifier when specifying a type and next to the key in dictionary literals.
  - colon
  # There should be no space before and one after any comma.
  - comma
  # The initializers declared in compiler protocols such as ExpressibleByArrayLiteral shouldn't be called directly.
  - compiler_protocol_init
  # Getter and setters in computed properties and subscripts should be in a consistent order.
  - computed_accessors_order
  # Conditional statements should always return on the next line
  - conditional_returns_on_newline
  # Prefer contains over comparing filter(where:).count to 0.
  - contains_over_filter_count
  # Prefer contains over using filter(where:).isEmpty
  - contains_over_filter_is_empty
  # Prefer `contains` over `first(where:) != nil`
  - contains_over_first_not_nil
  # Prefer contains over range(of:) != nil and range(of:) == nil
  - contains_over_range_nil_comparison
  # if, for, guard, switch, while, and catch statements shouldn't unnecessarily wrap their conditionals or arguments in parentheses.
  - control_statement
  # Types used for hosting only static members should be implemented as a caseless enum to avoid instantiation.
  - convenience_type
  # Complexity of function bodies should be limited.
  - cyclomatic_complexity
  # Availability checks or attributes shouldn’t be using older versions that are satisfied by the deployment target.
  - deployment_target
  # When registering for a notification using a block, the opaque observer that is returned should be stored so it can be removed later.
  - discarded_notification_center_observer
  # Discouraged direct initialization of types that can be harmful. e.g. UIDevice(), Bundle()
  - discouraged_direct_init
  # Prefer initializers over object literals.
  - discouraged_object_literal
  # Prefer non-optional booleans over optional booleans.
  - discouraged_optional_boolean
  # Prefer empty collection over optional collection.
  - discouraged_optional_collection
  # Dictionary literals with duplicated keys will crash in runtime.
  - duplicated_key_in_dictionary_literal
  # Duplicate Imports
  - duplicate_imports
  # Avoid using 'dynamic' and '@inline(__always)' together.
  - dynamic_inline
  # Prefer checking isEmpty over comparing collection to an empty array or dictionary literal.
  - empty_collection_literal
  # Prefer checking `isEmpty` over comparing `count` to zero.
  - empty_count
  # Arguments can be omitted when matching enums with associated types if they are not used.
  - empty_enum_arguments
  # Prefer () -> over Void ->.
  - empty_parameters
  # When using trailing closures, empty parentheses should be avoided after the method call.
  - empty_parentheses_with_trailing_closure
  # Prefer checking `isEmpty` over comparing string to an empty string literal.
  - empty_string
  # Empty XCTest method should be avoided.
  - empty_xctest_method
  # Number of associated values in an enum case should be low
  - enum_case_associated_values_count
  # Explicitly calling .init() should be avoided.
  - explicit_init
  # A fatalError call should have a message.
  - fatal_error_message
  # Files should not span too many lines.
  # See file_length below for the exact configuration.
  - file_length
  # File name should not contain any whitespace.
  - file_name_no_space
  # Prefer using ``.first(where:)`` over ``.filter { }.first` in collections.
  - first_where
  # Prefer flatMap over map followed by reduce([], +).
  - flatmap_over_map_reduce
  # where clauses are preferred over a single if inside a for.
  - for_where
  # Force casts should be avoided.
  - force_cast
  # Force tries should be avoided.
  - force_try
  # Force unwrapping should be avoided.
  - force_unwrapping
  # Prefer to locate parameters with defaults toward the end of the parameter list.
  - function_default_parameter_at_end
  # Functions bodies should not span too many lines.
  # See function_body_length below for the exact configuration.
  - function_body_length
  # Number of function parameters should be low.
  # See function_parameter_count below for the exact configuration.
  - function_parameter_count
  # Generic type
[truncated — 14388 more characters]
```

### CardinalKit-Example/SafeSip ExampleTests/CardinalKit_ExampleTests.swift

```swift
//
//  CardinalKit_ExampleTests.swift
//  CardinalKit ExampleTests
//
//  Created by Vishnu Ravi on 12/24/22.
//  Copyright © 2022 CardinalKit. All rights reserved.
//

@testable import CardinalKit_Example
import XCTest

// swiftlint:disable type_name
final class CardinalKit_ExampleTests: XCTestCase {
    func testReadConfig() {
        let config = CKPropertyReader(file: "CKConfiguration")
        XCTAssertNotNil(config.data)
    }
}

```

### CardinalKit/Source/CKTimer.swift

```swift
//
//  CKTimer.swift
//  CardinalKit
//
//  Created by Santiago Gutierrez on 12/22/20.
//

import Foundation

public class CKTimer: NSObject {
    
    fileprivate let timer = TimerController()
    
    public var delegate: TimerDelegate? {
        didSet {
            timer.delegate = delegate
        }
    }
    
    public override init() {
        super.init()
    }
    
    public func start(withDate startDate: Date = Date()) {
        timer.start(withDate: startDate)
    }
    
    public func stop() {
        timer.stop()
    }
    
}

```

### .github/workflows/build.yml

```yaml
name: Build

on:
  push:
    branches:
      - main
  pull_request:
  workflow_dispatch:
  workflow_call:

jobs:
  build:
    name: Build
    runs-on: macos-12
    steps:
    - uses: actions/checkout@v3
    - uses: maxim-lobanov/setup-xcode@v1
      with:
        xcode-version: latest-stable
    - name: Check Environment
      run: |
          xcodebuild -version
          swift --version
    - uses: actions/cache@v3
      with:
        path: CardinalKit-Example/Pods
        key: ${{ runner.os }}-pods-${{ hashFiles('CardinalKit-Example/Podfile.lock') }}
    - uses: actions/cache@v3
      with:
        path: ~/Library/Caches/org.swift.swiftpm/
        key: ${{ runner.os }}-spm-${{ hashFiles('CardinalKit-Example/CardinalKit.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}
    - name: Build and test
      run: bundler install && bundle exec fastlane build

```

### CardinalKit/Source/CKCoreMotionManager.swift

```swift
//
//  CKCoreMotionManager.swift
//  CardinalKit
//
//  Created by Santiago Gutierrez on 12/21/20.
//

import Foundation

public class CKCoreMotionManager : NSObject {
    
    public static let shared = CKCoreMotionManager()
    
    let motionManager = MotionController()
    
    public var isActive: Bool {
        get {
            return motionManager.isActive
        }
    }
    
    public var delegate: MotionDelegate? {
        didSet {
            motionManager.delegate = delegate
        }
    }
    
    public override init() {
        super.init()
        
        motionManager.syncId = UUID().uuidString
        motionManager.automaticStreaming = true
        motionManager.device = .phone
    }
    
    public func start() {
        motionManager.start()
    }
    
    public func stop() {
        motionManager.stop()
        motionManager.stream()
    }
    
}

```

### CardinalKit-Example/CardinalKit/AppDelegate+CardinalKit.swift

```swift
//
//  AppDelegate+CardinalKit.swift
//
//  Created for the CardinalKit Framework.
//  Copyright © 2019 Stanford University. All rights reserved.
//

import CardinalKit
import Firebase
import Foundation
import ResearchKit


// Extensions add new functionality to an existing class, structure, enumeration, or protocol type.
// https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
extension AppDelegate {
    /**
     Handle special CardinalKit logic for when the app is launched.
    */
    func CKAppLaunch() {
        // (1) setup the CardinalKit SDK
        let options = CKAppOptions()
        CKApp.configure(options)
        
        // (2) if we have already logged in
        if CKStudyUser.shared.isLoggedIn {
            CKStudyUser.shared.save()
            
            // (3) then start the requested HK data collection (if any).
            let manager = CKHealthKitManager.shared
            manager.getHealthAuthorization { _, error in
                if let error = error {
                    print(error)
                }
            }
        }
        CKStudyUser.shared.save()
    }
}

```

### CardinalKit-Example/SafeSip ExampleTests/CKSessionTests.swift

```swift
//
//  CKSessionTests.swift
//  CardinalKit ExampleTests
//
//  Created by Vishnu Ravi on 9/10/23.
//  Copyright © 2023 CardinalKit. All rights reserved.
//

@testable import CardinalKit_Example
import CardinalKit
import XCTest

class CKSessionTests: XCTestCase {    
    // Sample keys and values for testing
    let testKey = "TestKey"
    let testValue = "TestValue"

    // Resetting Keychain
    override func setUp() {
        super.setUp()
        CKSession.removeSecure(key: testKey)
    }
    
    override func tearDown() {
        CKSession.removeSecure(key: testKey)
        super.tearDown()
    }
    
    func testGetSecureReturnsNilWhenNotSet() {
        let value = CKSession.getSecure(key: testKey)
        XCTAssertNil(value)
    }
    
    func testPutSecureSuccessfullyStoresValue() {
        CKSession.putSecure(value: testValue, forKey: testKey)
        
        let retrievedValue = CKSession.getSecure(key: testKey)
        XCTAssertEqual(retrievedValue, testValue)
    }
    
    func testPutSecureRemovesValueWhenSetToNil() {
        CKSession.putSecure(value: testValue, forKey: testKey)
        
        CKSession.putSecure(value: nil, forKey: testKey)
        
        let retrievedValue = CKSession.getSecure(key: testKey)
        XCTAssertNil(retrievedValue)
    }
    
    func testRemoveSecureRemovesValue() {
        CKSession.putSecure(value: testValue, forKey: testKey)
        
        CKSession.removeSecure(key: testKey)
        
        let retrievedValue = CKSession.getSecure(key: testKey)
        XCTAssertNil(retrievedValue)
    }
}


```

### CardinalKit-Example/CardinalKit/SceneDelegate+CardinalKit.swift

```swift
//
//  SceneDelegate+CardinalKit.swift
//  CardinalKit_Example
//
//  Created by Santiago Gutierrez on 10/13/20.
//  Copyright © 2020 CardinalKit. All rights reserved.
//

import ResearchKit
import SwiftUI

// Extensions add new functionality to an existing class, structure, enumeration, or protocol type.
// https://docs.swift.org/swift-book/LanguageGuide/Extensions.html
extension SceneDelegate: ORKPasscodeDelegate {
    /**
     Hide content so it doesn't appear in the app switcher.
    */
    func toggleContainer(hidden: Bool) {
        if let isViewLoaded = window?.rootViewController?.isViewLoaded, isViewLoaded {
            window?.rootViewController?.view.isHidden = hidden
        }
    }
    
    /**
     Blocks the app from use until a validated passcode is entered.
     
     Uses `present()` to trigger an `ORKPasscodeViewController`
    */
    func CKLockApp() {
        // Only lock the app if there is a stored passcode and a passcode controller isn't already being shown.
        guard ORKPasscodeViewController.isPasscodeStoredInKeychain()
                && !(window?.rootViewController?.presentedViewController is ORKPasscodeViewController) else {
            return
        }
        
        window?.makeKeyAndVisible()

        let config = CKPropertyReader(file: "CKConfiguration")
        
        let passcodeViewController = ORKPasscodeViewController.passcodeAuthenticationViewController(
            withText: config.read(query: "Passcode On Return Text"),
            delegate: self
        )
        passcodeViewController.isModalInPresentation = true
        
        window?.rootViewController?.present(passcodeViewController, animated: false, completion: nil)
    }
    
    /**
     Run this code when the application enters the background
     to hide app content from the iOS App Switcher (Privacy/Security).
    */
    func CKLockDidEnterBackground() {
        if ORKPasscodeViewController.isPasscodeStoredInKeychain() {
            toggleContainer(hidden: true)
        }
    }
    
    func passcodeViewControllerDidFinish(withSuccess viewController: UIViewController) {
        // dismiss passcode prompt screen
        toggleContainer(hidden: false)
        viewController.dismiss(animated: false, completion: nil)
    }
    
    func passcodeViewControllerDidFailAuthentication(_ viewController: UIViewController) {
        // Not implemented
    }
}

```

### CardinalKit/Source/CKApp.swift

```swift
//
//  CKAppDelegate.swift
//  CardinalKit
//
//  Created by Santiago Gutierrez on 4/24/20.
//

import Foundation

public struct CKAppOptions {
    public var networkRouteDelegate: CKAPIRouteDelegate?
    public var networkDeliveryDelegate : CKAPIDeliveryDelegate?
    public var networkReceiverDelegate : CKAPIReceiverDelegate?
    public init() {
        networkReceiverDelegate = CKAppNetworkManager()
        networkDeliveryDelegate = CKAppNetworkManager()
    }
}

public class CKApp {
    
    public static let instance = CKApp()
    
    var options = CKAppOptions()
    
    class public func configure(_ options: CKAppOptions? = nil) {
        
        // CardinalKit Options
        if let options = options {
            instance.options = options
        }
        
        // Start listenig for changes in HealthKit items (waits for valid user inherently)
        _ = CKActivityManager.shared.load()
        
        // Realm
        _ = RealmManager.shared.configure()
        
        // Reinstallation/Unistallation
        SessionManager.shared.checkFirstRun()
        
        // Create cache directories with correct permissions
        _ = CacheManager.shared.userContainer
        
        configureWithValidUser()
    }

    class func configureWithValidUser() {
        guard SessionManager.shared.userId != nil else {
            return
        }
        
        // Start listening for network changes
        _ = NetworkTracker.shared
        
        // Start Watch Manager
        //_ = WatchConnectivityManager.shared
    }

    class public func requestData(route: String, onCompletion: @escaping (Any?) -> Void){
        if let delegate = CKApp.instance.options.networkReceiverDelegate {
            delegate.request(route: route, onCompletion: onCompletion)
        }
    }
    
    class public func sendData(route: String, data: Any, params: Any?, onCompletion:((Bool, Error?) -> Void )? = nil){
        if let delegate = CKApp.instance.options.networkDeliveryDelegate{
            delegate.send(route: route, data: data, params: params, onCompletion: onCompletion)
        }
    }
    
    class public func getHealthAuthorization(forTypes typesToCollect:Set<HKSampleType>, _ completion: @escaping (_ success: Bool, _ error: Error?) -> Void)
    {
        CKActivityManager.shared.getHealthAuthorization(forTypes: typesToCollect) {(success, error) in
            completion(success, error)
            
        }
    }
}

```

[143 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]