Skip to content

Commit e7fd24f

Browse files
committed
Merge branch 'master' into jf_deduplication
2 parents 6c40d9f + 2b1f38f commit e7fd24f

File tree

132 files changed

+4106
-634
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+4106
-634
lines changed

data/blood/glucose/glucose.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,25 @@ const (
1010
MmolL = "mmol/L"
1111
Mmoll = "mmol/l"
1212

13+
MmolLMinute = "mmol/L/minute"
14+
1315
MgdL = "mg/dL"
1416
Mgdl = "mg/dl"
1517

18+
MgdLMinute = "mg/dL/minute"
19+
1620
MmolLMinimum float64 = 0.0
1721
MmolLMaximum float64 = 55.0
1822

23+
MmolLMinuteMinimum float64 = -5.5
24+
MmolLMinuteMaximum float64 = 5.5
25+
1926
MgdLMinimum float64 = 0.0
2027
MgdLMaximum float64 = 1000.0
2128

29+
MgdLMinuteMinimum float64 = -100.0
30+
MgdLMinuteMaximum float64 = 100.0
31+
2232
// MmolLToMgdLConversionFactor is MgdL Per MmolL.
2333
//
2434
// Reminder: The molecular mass of glucose is ≈ 180 g/mol.
@@ -34,6 +44,10 @@ func Units() []string {
3444
return []string{MmolL, Mmoll, MgdL, Mgdl}
3545
}
3646

47+
func RateUnits() []string {
48+
return []string{MmolLMinute, MgdLMinute}
49+
}
50+
3751
func ValueRangeForUnits(units *string) (float64, float64) {
3852
if units != nil {
3953
switch *units {
@@ -60,7 +74,41 @@ func NormalizeValueForUnits(value *float64, units *string) *float64 {
6074
if value != nil && units != nil {
6175
switch *units {
6276
case MgdL, Mgdl:
63-
intValue := int(*value/MmolLToMgdLConversionFactor*MmolLToMgdLPrecisionFactor + 0.5)
77+
intValue := int(*value/MmolLToMgdLConversionFactor*MmolLToMgdLPrecisionFactor + math.Copysign(0.5, *value))
78+
floatValue := float64(intValue) / MmolLToMgdLPrecisionFactor
79+
return &floatValue
80+
}
81+
}
82+
return value
83+
}
84+
85+
func ValueRangeForRateUnits(rateUnits *string) (float64, float64) {
86+
if rateUnits != nil {
87+
switch *rateUnits {
88+
case MmolLMinute:
89+
return MmolLMinuteMinimum, MmolLMinuteMaximum
90+
case MgdLMinute:
91+
return MgdLMinuteMinimum, MgdLMinuteMaximum
92+
}
93+
}
94+
return -math.MaxFloat64, math.MaxFloat64
95+
}
96+
97+
func NormalizeRateUnits(rateUnits *string) *string {
98+
if rateUnits != nil {
99+
switch *rateUnits {
100+
case MmolLMinute, MgdLMinute:
101+
return pointer.FromString(MmolLMinute)
102+
}
103+
}
104+
return rateUnits
105+
}
106+
107+
func NormalizeValueForRateUnits(value *float64, rateUnits *string) *float64 {
108+
if value != nil && rateUnits != nil {
109+
switch *rateUnits {
110+
case MgdLMinute:
111+
intValue := int(*value/MmolLToMgdLConversionFactor*MmolLToMgdLPrecisionFactor + math.Copysign(0.5, *value))
64112
floatValue := float64(intValue) / MmolLToMgdLPrecisionFactor
65113
return &floatValue
66114
}

data/blood/glucose/glucose_test.go

Lines changed: 96 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ var _ = Describe("Glucose", func() {
1919
Expect(glucose.Mmoll).To(Equal("mmol/l"))
2020
})
2121

22+
It("has MmolLMinute", func() {
23+
Expect(glucose.MmolLMinute).To(Equal("mmol/L/minute"))
24+
})
25+
2226
It("has MgdL", func() {
2327
Expect(glucose.MgdL).To(Equal("mg/dL"))
2428
})
@@ -27,6 +31,10 @@ var _ = Describe("Glucose", func() {
2731
Expect(glucose.Mgdl).To(Equal("mg/dl"))
2832
})
2933

34+
It("has MgdLMinute", func() {
35+
Expect(glucose.MgdLMinute).To(Equal("mg/dL/minute"))
36+
})
37+
3038
It("has MmolLMinimum", func() {
3139
Expect(glucose.MmolLMinimum).To(Equal(0.0))
3240
})
@@ -35,6 +43,14 @@ var _ = Describe("Glucose", func() {
3543
Expect(glucose.MmolLMaximum).To(Equal(55.0))
3644
})
3745

46+
It("has MmolLMinuteMinimum", func() {
47+
Expect(glucose.MmolLMinuteMinimum).To(Equal(-5.5))
48+
})
49+
50+
It("has MmolLMinuteMaximum", func() {
51+
Expect(glucose.MmolLMinuteMaximum).To(Equal(5.5))
52+
})
53+
3854
It("has MgdLMinimum", func() {
3955
Expect(glucose.MgdLMinimum).To(Equal(0.0))
4056
})
@@ -43,6 +59,14 @@ var _ = Describe("Glucose", func() {
4359
Expect(glucose.MgdLMaximum).To(Equal(1000.0))
4460
})
4561

62+
It("has MgdLMinuteMinimum", func() {
63+
Expect(glucose.MgdLMinuteMinimum).To(Equal(-100.0))
64+
})
65+
66+
It("has MgdLMinuteMaximum", func() {
67+
Expect(glucose.MgdLMinuteMaximum).To(Equal(100.0))
68+
})
69+
4670
It("has MmolLToMgdLConversionFactor", func() {
4771
Expect(glucose.MmolLToMgdLConversionFactor).To(Equal(18.01559))
4872
})
@@ -57,6 +81,12 @@ var _ = Describe("Glucose", func() {
5781
})
5882
})
5983

84+
Context("RateUnits", func() {
85+
It("returns the expected units", func() {
86+
Expect(glucose.RateUnits()).To(ConsistOf("mmol/L/minute", "mg/dL/minute"))
87+
})
88+
})
89+
6090
DescribeTable("ValueRangeForUnits",
6191
func(units *string, expectedLower float64, expectedUpper float64) {
6292
actualLower, actualUpper := glucose.ValueRangeForUnits(units)
@@ -125,28 +155,87 @@ var _ = Describe("Glucose", func() {
125155
}
126156
})
127157
})
158+
128159
Context("NormalizeValueForUnitsWithFullPrecision", func() {
129160
DescribeTable("given value and units",
130161
func(value *float64, units *string, expectedValue *float64) {
131162
actualValue := glucose.NormalizeValueForUnitsWithFullPrecision(value, units)
132-
if expectedValue == nil {
133-
Expect(actualValue).To(BeNil())
134-
} else {
135-
Expect(actualValue).ToNot(BeNil())
136-
Expect(*actualValue).To(Equal(*expectedValue))
137-
}
163+
Expect(actualValue).To(Equal(expectedValue))
138164
},
139165
Entry("returns nil for nil value", nil, pointer.FromString("mmol/L"), nil),
140166
Entry("returns unchanged value for nil units", pointer.FromFloat64(10.0), nil, pointer.FromFloat64(10.0)),
141167
Entry("returns unchanged value for unknown units", pointer.FromFloat64(10.0), pointer.FromString("unknown"), pointer.FromFloat64(10.0)),
142168
Entry("returns unchanged value for mmol/L units", pointer.FromFloat64(10.0), pointer.FromString("mmol/L"), pointer.FromFloat64(10.0)),
143169
Entry("returns unchanged value for mmol/l units", pointer.FromFloat64(10.0), pointer.FromString("mmol/l"), pointer.FromFloat64(10.0)),
144-
145170
Entry("returns converted value for mg/dL units", pointer.FromFloat64(140.0), pointer.FromString("mg/dL"), pointer.FromFloat64(7.771047187463747)),
146171
Entry("returns converted value for mg/dL units", pointer.FromFloat64(100.0), pointer.FromString("mg/dL"), pointer.FromFloat64(5.550747991045533)),
147172
Entry("returns converted value for mg/dl units", pointer.FromFloat64(80.0), pointer.FromString("mg/dl"), pointer.FromFloat64(4.440598392836427)),
148173
Entry("returns converted value for mg/dl units", pointer.FromFloat64(69.0), pointer.FromString("mg/dl"), pointer.FromFloat64(3.830016113821418)),
149174
Entry("returns converted value for mg/dl units", pointer.FromFloat64(50.0), pointer.FromString("mg/dl"), pointer.FromFloat64(2.7753739955227665)),
150175
)
151176
})
177+
178+
DescribeTable("ValueRangeForRateUnits",
179+
func(rateUnits *string, expectedLower float64, expectedUpper float64) {
180+
actualLower, actualUpper := glucose.ValueRangeForRateUnits(rateUnits)
181+
Expect(actualLower).To(Equal(expectedLower))
182+
Expect(actualUpper).To(Equal(expectedUpper))
183+
},
184+
Entry("returns no range for nil", nil, -math.MaxFloat64, math.MaxFloat64),
185+
Entry("returns no range for unknown units", pointer.FromString("unknown"), -math.MaxFloat64, math.MaxFloat64),
186+
Entry("returns expected range for mmol/L/minute units", pointer.FromString("mmol/L/minute"), -5.5, 5.5),
187+
Entry("returns expected range for mg/dL/minute units", pointer.FromString("mg/dL/minute"), -100.0, 100.0),
188+
)
189+
190+
DescribeTable("NormalizeRateUnits",
191+
func(rateUnits *string, expectedRateUnits *string) {
192+
actualRateUnits := glucose.NormalizeRateUnits(rateUnits)
193+
if expectedRateUnits == nil {
194+
Expect(actualRateUnits).To(BeNil())
195+
} else {
196+
Expect(actualRateUnits).ToNot(BeNil())
197+
Expect(*actualRateUnits).To(Equal(*expectedRateUnits))
198+
}
199+
},
200+
Entry("returns nil for nil", nil, nil),
201+
Entry("returns unchanged units for unknown units", pointer.FromString("unknown"), pointer.FromString("unknown")),
202+
Entry("returns mmol/L/minute for mmol/L/minute", pointer.FromString("mmol/L/minute"), pointer.FromString("mmol/L/minute")),
203+
Entry("returns mmol/L/minute for mg/dL/minute", pointer.FromString("mg/dL/minute"), pointer.FromString("mmol/L/minute")),
204+
)
205+
206+
Context("NormalizeValueForRateUnits", func() {
207+
DescribeTable("given value and units",
208+
func(value *float64, rateUnits *string, expectedValue *float64) {
209+
actualValue := glucose.NormalizeValueForRateUnits(value, rateUnits)
210+
if expectedValue == nil {
211+
Expect(actualValue).To(BeNil())
212+
} else {
213+
Expect(actualValue).ToNot(BeNil())
214+
Expect(*actualValue).To(Equal(*expectedValue))
215+
}
216+
},
217+
218+
Entry("returns nil for nil value", nil, pointer.FromString("mmol/L/minute"), nil),
219+
Entry("returns unchanged value for nil units", pointer.FromFloat64(1.0), nil, pointer.FromFloat64(1.0)),
220+
Entry("returns unchanged value for unknown units", pointer.FromFloat64(1.0), pointer.FromString("unknown"), pointer.FromFloat64(1.0)),
221+
Entry("returns unchanged value for mmol/L/minute units", pointer.FromFloat64(1.0), pointer.FromString("mmol/L/minute"), pointer.FromFloat64(1.0)),
222+
Entry("returns converted value for mg/dL/minute units", pointer.FromFloat64(18.0), pointer.FromString("mg/dL/minute"), pointer.FromFloat64(0.99913)),
223+
)
224+
225+
It("properly normalizes a range of mmol/L/minute values", func() {
226+
for value := glucose.MmolLMinuteMinimum; value <= glucose.MmolLMinuteMaximum; value += 0.1 {
227+
normalizedValue := glucose.NormalizeValueForRateUnits(pointer.FromFloat64(float64(value)), pointer.FromString("mmol/L/minute"))
228+
Expect(normalizedValue).ToNot(BeNil())
229+
Expect(*normalizedValue).To(Equal(value))
230+
}
231+
})
232+
233+
It("properly normalizes a range of mg/dL/minute values", func() {
234+
for value := int(glucose.MgdLMinuteMinimum); value <= int(glucose.MgdLMinuteMaximum); value++ {
235+
normalizedValue := glucose.NormalizeValueForRateUnits(pointer.FromFloat64(float64(value)), pointer.FromString("mg/dL/minute"))
236+
Expect(normalizedValue).ToNot(BeNil())
237+
Expect(int(*normalizedValue*18.01559 + math.Copysign(0.5, float64(value)))).To(Equal(value))
238+
}
239+
})
240+
})
152241
})

data/blood/glucose/test/target.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,26 @@ func ExpectNormalizedValue(value *float64, expectedValue *float64, units *string
8484
}
8585
}
8686

87+
func ExpectNormalizedRateUnits(value *string, expectedValue *string) {
88+
if expectedValue != nil {
89+
gomega.Expect(value).ToNot(gomega.BeNil())
90+
gomega.Expect(*value).To(gomega.Equal(*dataBloodGlucose.NormalizeRateUnits(expectedValue)))
91+
*expectedValue = *value
92+
} else {
93+
gomega.Expect(value).To(gomega.BeNil())
94+
}
95+
}
96+
97+
func ExpectNormalizedRateValue(value *float64, expectedValue *float64, units *string) {
98+
if expectedValue != nil {
99+
gomega.Expect(value).ToNot(gomega.BeNil())
100+
gomega.Expect(*value).To(gomega.Equal(*dataBloodGlucose.NormalizeValueForRateUnits(expectedValue, units)))
101+
*expectedValue = *value
102+
} else {
103+
gomega.Expect(value).To(gomega.BeNil())
104+
}
105+
}
106+
87107
func ExpectNormalizedTarget(datum *dataBloodGlucose.Target, expectedDatum *dataBloodGlucose.Target, units *string) {
88108
gomega.Expect(datum).ToNot(gomega.BeNil())
89109
gomega.Expect(expectedDatum).ToNot(gomega.BeNil())

data/service/api/v1/partners.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package v1
2+
3+
import (
4+
"net/http"
5+
"os"
6+
7+
dataService "github.com/tidepool-org/platform/data/service"
8+
"github.com/tidepool-org/platform/request"
9+
)
10+
11+
// TODO: https://tidepool.atlassian.net/browse/BACK-3394 - This implementation is a
12+
// temporary placeholder to allow bootstrapping of the Abbott OAuth client workflow.
13+
// Will need to migrate this to environment variables and add minimal authorization.
14+
// For now, though, this is acceptable since it isn't revealing anything that is not
15+
// already available in other locations (i.e. other public repos).
16+
17+
func PartnersSector(dataServiceContext dataService.Context) {
18+
res := dataServiceContext.Response()
19+
req := dataServiceContext.Request()
20+
responder := request.MustNewResponder(res, req)
21+
22+
if partnerSectorIdentifers, ok := namespacePartnerSectorIdentifers[os.Getenv("POD_NAMESPACE")]; ok {
23+
if sectorIdentifier, ok := partnerSectorIdentifers[req.PathParam("partner")]; ok {
24+
responder.Data(http.StatusOK, sectorIdentifier)
25+
return
26+
}
27+
}
28+
29+
responder.Data(http.StatusOK, []string{})
30+
}
31+
32+
var namespacePartnerSectorIdentifers = map[string]map[string][]string{
33+
"external": {
34+
"abbott": {
35+
"https://external.integration.tidepool.org/v1/oauth/abbott/redirect",
36+
"https://external.integration.tidepool.org/v1/oauth/abbott-private-1/redirect",
37+
"https://external.integration.tidepool.org/v1/oauth/abbott-private-2/redirect",
38+
"https://qa1.development.tidepool.org/v1/oauth/abbott/redirect",
39+
"https://qa2.development.tidepool.org/v1/oauth/abbott/redirect",
40+
"https://qa3.development.tidepool.org/v1/oauth/abbott/redirect",
41+
"https://qa4.development.tidepool.org/v1/oauth/abbott/redirect",
42+
"https://qa5.development.tidepool.org/v1/oauth/abbott/redirect",
43+
"https://dev1.dev.tidepool.org/v1/oauth/abbott/redirect",
44+
},
45+
},
46+
}

data/service/api/v1/v1.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ func Routes() []service.Route {
2020
service.Put("/v1/data_sets/:dataSetId", DataSetsUpdate, api.RequireAuth),
2121
service.Get("/v1/time", TimeGet),
2222
service.Post("/v1/users/:userId/data_sets", UsersDataSetsCreate, api.RequireAuth),
23+
24+
service.Get("/v1/partners/:partner/sector", PartnersSector),
2325
}
2426

2527
routes = append(routes, DataSetsRoutes()...)

0 commit comments

Comments
 (0)