Skip to content

Commit

Permalink
Making schedules generic. Framework organization.
Browse files Browse the repository at this point in the history
  • Loading branch information
loudnate committed Feb 13, 2016
1 parent e5a8212 commit dc27e86
Show file tree
Hide file tree
Showing 21 changed files with 527 additions and 338 deletions.
2 changes: 1 addition & 1 deletion CarbKit/CarbMath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ struct CarbMath {

repeat {
let value = entries.reduce(0.0) { (value, entry) -> Double in
return value + glucoseEffectForCarbEntry(entry, atDate: date, carbRatio: carbRatios.at(entry.startDate), insulinSensitivity: insulinSensitivities.at(entry.startDate), defaultAbsorptionTime: defaultAbsorptionTime, delay: delay)
return value + glucoseEffectForCarbEntry(entry, atDate: date, carbRatio: carbRatios.quantityAt(entry.startDate), insulinSensitivity: insulinSensitivities.quantityAt(entry.startDate), defaultAbsorptionTime: defaultAbsorptionTime, delay: delay)
}

values.append(GlucoseEffect(startDate: date, quantity: HKQuantity(unit: unit, doubleValue: value)))
Expand Down
1 change: 1 addition & 0 deletions InsulinKit/UI/ReservoirTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public class ReservoirTableViewController: UITableViewController {

self.tableView.reloadData()

self.updateTimelyStats(nil)
self.updateTotal()
}
})
Expand Down
43 changes: 43 additions & 0 deletions LoopKit/BasalRateSchedule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// BasalRateSchedule.swift
// Naterade
//
// Created by Nathan Racklyeft on 2/12/16.
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
//

import Foundation


public class BasalRateSchedule: DailyValueSchedule<Double> {

public override init?(dailyItems: [RepeatingScheduleValue<Double>], timeZone: NSTimeZone? = nil) {
super.init(dailyItems: dailyItems, timeZone: timeZone)
}

/**
Calculates the total basal delivery for a day

- returns: The total basal delivery
*/
public func total() -> Double {
var total: Double = 0

for (index, item) in items.enumerate() {
var endTime = maxTimeInterval

if index < items.endIndex - 1 {
endTime = items[index + 1].startTime
}

total += (endTime - item.startTime) / NSTimeInterval(hours: 1) * item.value
}

return total
}

public override func valueAt(time: NSDate) -> Double {
return super.valueAt(time)
}

}
21 changes: 21 additions & 0 deletions LoopKit/CarbRatioSchedule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// CarbRatioSchedule.swift
// Naterade
//
// Created by Nathan Racklyeft on 2/12/16.
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
//

import Foundation
import HealthKit


public class CarbRatioSchedule: DailyQuantitySchedule {
public override init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue<Double>], timeZone: NSTimeZone? = nil) {
super.init(unit: unit, dailyItems: dailyItems, timeZone: timeZone)

guard unit == HKUnit.gramUnit() else {
return nil
}
}
}
57 changes: 57 additions & 0 deletions LoopKit/DailyQuantitySchedule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// DailyQuantitySchedule.swift
// Naterade
//
// Created by Nathan Racklyeft on 2/12/16.
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
//

import Foundation
import HealthKit


public class DailyQuantitySchedule: DailyValueSchedule<Double> {
public let unit: HKUnit

init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue<Double>], timeZone: NSTimeZone?) {
self.unit = unit

super.init(dailyItems: dailyItems, timeZone: timeZone)
}

public required convenience init?(rawValue: RawValue) {
guard let
rawUnit = rawValue["unit"] as? String,
timeZoneName = rawValue["timeZone"] as? String,
rawItems = rawValue["items"] as? [RepeatingScheduleValue.RawValue] else
{
return nil
}

self.init(unit: HKUnit(fromString: rawUnit), dailyItems: rawItems.flatMap { RepeatingScheduleValue(rawValue: $0) }, timeZone: NSTimeZone(name: timeZoneName))
}

public func quantityAt(time: NSDate) -> HKQuantity {
return HKQuantity(unit: unit, doubleValue: valueAt(time))
}

func averageValue() -> Double {
var total: Double = 0

for (index, item) in items.enumerate() {
var endTime = maxTimeInterval

if index < items.endIndex - 1 {
endTime = items[index + 1].startTime
}

total += (endTime - item.startTime) * item.value
}

return total / repeatInterval
}

public func averageQuantity() -> HKQuantity {
return HKQuantity(unit: unit, doubleValue: averageValue())
}
}
120 changes: 14 additions & 106 deletions LoopKit/QuantitySchedule.swift → LoopKit/DailyValueSchedule.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,41 +10,27 @@ import Foundation
import HealthKit


public struct RepeatingScheduleValue {
public struct RepeatingScheduleValue<T: RawRepresentable where T.RawValue: AnyObject> {
public let startTime: NSTimeInterval
public let value: Double
public let value: T

public init(startTime: NSTimeInterval, value: Double) {
public init(startTime: NSTimeInterval, value: T) {
self.startTime = startTime
self.value = value
}
}

public struct AbsoluteScheduleValue: TimelineValue {
public struct AbsoluteScheduleValue<T>: TimelineValue {
public let startDate: NSDate
public let value: Double
}

extension RepeatingScheduleValue: Equatable {
}

public func ==(lhs: RepeatingScheduleValue, rhs: RepeatingScheduleValue) -> Bool {
return lhs.startTime == rhs.startTime && lhs.value == rhs.value
}

extension AbsoluteScheduleValue: Equatable {
}

public func ==(lhs: AbsoluteScheduleValue, rhs: AbsoluteScheduleValue) -> Bool {
return lhs.startDate == rhs.startDate && lhs.value == rhs.value
public let value: T
}

extension RepeatingScheduleValue: RawRepresentable {
public typealias RawValue = [String: AnyObject]

public init?(rawValue: RawValue) {
guard let startTime = rawValue["startTime"] as? Double,
value = rawValue["value"] as? Double else {
value = rawValue["value"] as? T else {
return nil
}

Expand All @@ -54,22 +40,22 @@ extension RepeatingScheduleValue: RawRepresentable {
public var rawValue: RawValue {
return [
"startTime": startTime,
"value": value
"value": value.rawValue
]
}
}


public class DailyValueSchedule: RawRepresentable {
public class DailyValueSchedule<T: RawRepresentable where T.RawValue: AnyObject>: RawRepresentable {
public typealias RawValue = [String: AnyObject]

private let referenceTimeInterval: NSTimeInterval
private let repeatInterval = NSTimeInterval(hours: 24)
let repeatInterval = NSTimeInterval(hours: 24)

public let items: [RepeatingScheduleValue]
public let items: [RepeatingScheduleValue<T>]
public let timeZone: NSTimeZone

init?(dailyItems: [RepeatingScheduleValue], timeZone: NSTimeZone?) {
init?(dailyItems: [RepeatingScheduleValue<T>], timeZone: NSTimeZone?) {
self.items = dailyItems.sort { $0.startTime < $1.startTime }
self.timeZone = timeZone ?? NSTimeZone.localTimeZone()

Expand Down Expand Up @@ -99,7 +85,7 @@ public class DailyValueSchedule: RawRepresentable {
]
}

private var maxTimeInterval: NSTimeInterval {
var maxTimeInterval: NSTimeInterval {
return referenceTimeInterval + repeatInterval
}

Expand All @@ -125,7 +111,7 @@ public class DailyValueSchedule: RawRepresentable {

- returns: A slice of `ScheduleItem` values
*/
public func between(startDate: NSDate, _ endDate: NSDate) -> [AbsoluteScheduleValue] {
public func between(startDate: NSDate, _ endDate: NSDate) -> [AbsoluteScheduleValue<T>] {
guard startDate <= endDate else {
return []
}
Expand Down Expand Up @@ -159,86 +145,8 @@ public class DailyValueSchedule: RawRepresentable {
}
}

public func at(time: NSDate) -> Double {
func valueAt(time: NSDate) -> T {
return between(time, time).first!.value
}


}


public class DailyQuantitySchedule: DailyValueSchedule {
public let unit: HKUnit

public init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue], timeZone: NSTimeZone?) {
self.unit = unit

super.init(dailyItems: dailyItems, timeZone: timeZone)
}

public required convenience init?(rawValue: RawValue) {
guard let
rawUnit = rawValue["unit"] as? String,
timeZoneName = rawValue["timeZone"] as? String,
rawItems = rawValue["items"] as? [RepeatingScheduleValue.RawValue] else
{
return nil
}

self.init(unit: HKUnit(fromString: rawUnit), dailyItems: rawItems.flatMap { RepeatingScheduleValue(rawValue: $0) }, timeZone: NSTimeZone(name: timeZoneName))
}

public func at(time: NSDate) -> HKQuantity {
return HKQuantity(unit: unit, doubleValue: at(time))
}
}


public class InsulinSensitivitySchedule: DailyQuantitySchedule {
public override init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue], timeZone: NSTimeZone? = nil) {
super.init(unit: unit, dailyItems: dailyItems, timeZone: timeZone)

guard unit == HKUnit.milligramsPerDeciliterUnit() || unit == HKUnit.millimolesPerLiterUnit() else {
return nil
}
}
}


public class CarbRatioSchedule: DailyQuantitySchedule {
public override init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue], timeZone: NSTimeZone? = nil) {
super.init(unit: unit, dailyItems: dailyItems, timeZone: timeZone)

guard unit == HKUnit.gramUnit() else {
return nil
}
}
}


public class BasalRateSchedule: DailyValueSchedule {
public override init?(dailyItems: [RepeatingScheduleValue], timeZone: NSTimeZone? = nil) {
super.init(dailyItems: dailyItems, timeZone: timeZone)
}

/**
Calculates the total basal delivery for a day

- returns: The total basal delivery
*/
public func total() -> Double {
var total: Double = 0

for (index, item) in items.enumerate() {
var endTime = maxTimeInterval

if index < items.endIndex - 1 {
endTime = items[index + 1].startTime
}

total += (endTime - item.startTime) / NSTimeInterval(hours: 1) * item.value
}

return total
}
}
22 changes: 22 additions & 0 deletions LoopKit/Double.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Double.swift
// Naterade
//
// Created by Nathan Racklyeft on 2/12/16.
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
//

import Foundation


extension Double: RawRepresentable {
public typealias RawValue = NSNumber

public init?(rawValue: RawValue) {
self = rawValue.doubleValue
}

public var rawValue: RawValue {
return NSNumber(double: self)
}
}
24 changes: 24 additions & 0 deletions LoopKit/GlucoseQuantitySchedule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// GlucoseQuantitySchedule.swift
// Naterade
//
// Created by Nathan Racklyeft on 2/12/16.
// Copyright © 2016 Nathan Racklyeft. All rights reserved.
//

import Foundation
import HealthKit


public class GlucoseQuantitySchedule: DailyQuantitySchedule {
public override init?(unit: HKUnit, dailyItems: [RepeatingScheduleValue<Double>], timeZone: NSTimeZone? = nil) {
super.init(unit: unit, dailyItems: dailyItems, timeZone: timeZone)

guard unit == HKUnit.milligramsPerDeciliterUnit() || unit == HKUnit.millimolesPerLiterUnit() else {
return nil
}
}
}


public typealias InsulinSensitivitySchedule = GlucoseQuantitySchedule
Loading

0 comments on commit dc27e86

Please sign in to comment.