mirror of
https://github.com/sstent/go-garth.git
synced 2026-02-05 22:12:24 +00:00
sync
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -20,26 +21,34 @@ type BaseStats struct {
|
||||
|
||||
func (b *BaseStats) List(end time.Time, period int, client *client.Client) ([]interface{}, error) {
|
||||
endDate := utils.FormatEndDate(end)
|
||||
var allData []interface{}
|
||||
var errs []error
|
||||
|
||||
if period > b.PageSize {
|
||||
// Handle pagination - get first page
|
||||
page, err := b.fetchPage(endDate, b.PageSize, client)
|
||||
if err != nil || len(page) == 0 {
|
||||
return page, err
|
||||
for period > 0 {
|
||||
pageSize := b.PageSize
|
||||
if period < pageSize {
|
||||
pageSize = period
|
||||
}
|
||||
|
||||
// Get remaining pages recursively
|
||||
remainingStart := endDate.AddDate(0, 0, -b.PageSize)
|
||||
remainingPeriod := period - b.PageSize
|
||||
remainingData, err := b.List(remainingStart, remainingPeriod, client)
|
||||
page, err := b.fetchPage(endDate, pageSize, client)
|
||||
if err != nil {
|
||||
return page, err
|
||||
errs = append(errs, err)
|
||||
// Continue to next page even if current fails
|
||||
} else {
|
||||
allData = append(page, allData...)
|
||||
}
|
||||
|
||||
return append(remainingData, page...), nil
|
||||
// Move to previous page
|
||||
endDate = endDate.AddDate(0, 0, -pageSize)
|
||||
period -= pageSize
|
||||
}
|
||||
|
||||
return b.fetchPage(endDate, period, client)
|
||||
// Return partial data with aggregated errors
|
||||
var finalErr error
|
||||
if len(errs) > 0 {
|
||||
finalErr = fmt.Errorf("partial failure: %v", errs)
|
||||
}
|
||||
return allData, finalErr
|
||||
}
|
||||
|
||||
func (b *BaseStats) fetchPage(end time.Time, period int, client *client.Client) ([]interface{}, error) {
|
||||
@@ -55,24 +64,26 @@ func (b *BaseStats) fetchPage(end time.Time, period int, client *client.Client)
|
||||
path = strings.Replace(path, "{period}", fmt.Sprintf("%d", period), 1)
|
||||
}
|
||||
|
||||
response, err := client.ConnectAPI(path, "GET", nil)
|
||||
data, err := client.ConnectAPI(path, "GET", nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if response == nil {
|
||||
if len(data) == 0 {
|
||||
return []interface{}{}, nil
|
||||
}
|
||||
|
||||
responseSlice, ok := response.([]interface{})
|
||||
if !ok || len(responseSlice) == 0 {
|
||||
var responseSlice []map[string]interface{}
|
||||
if err := json.Unmarshal(data, &responseSlice); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(responseSlice) == 0 {
|
||||
return []interface{}{}, nil
|
||||
}
|
||||
|
||||
var results []interface{}
|
||||
for _, item := range responseSlice {
|
||||
itemMap := item.(map[string]interface{})
|
||||
|
||||
for _, itemMap := range responseSlice {
|
||||
// Handle nested "values" structure
|
||||
if values, exists := itemMap["values"]; exists {
|
||||
valuesMap := values.(map[string]interface{})
|
||||
|
||||
40
garth/stats/hrv_weekly.go
Normal file
40
garth/stats/hrv_weekly.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const WEEKLY_HRV_PATH = "/wellness-service/wellness/weeklyHrv"
|
||||
|
||||
type WeeklyHRV struct {
|
||||
CalendarDate time.Time `json:"calendar_date"`
|
||||
AverageHRV float64 `json:"average_hrv"`
|
||||
MaxHRV float64 `json:"max_hrv"`
|
||||
MinHRV float64 `json:"min_hrv"`
|
||||
HRVQualifier string `json:"hrv_qualifier"`
|
||||
WellnessDataDaysCount int `json:"wellness_data_days_count"`
|
||||
BaseStats
|
||||
}
|
||||
|
||||
func NewWeeklyHRV() *WeeklyHRV {
|
||||
return &WeeklyHRV{
|
||||
BaseStats: BaseStats{
|
||||
Path: WEEKLY_HRV_PATH + "/{end}/{period}",
|
||||
PageSize: 52,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WeeklyHRV) Validate() error {
|
||||
if w.CalendarDate.IsZero() {
|
||||
return errors.New("calendar_date is required")
|
||||
}
|
||||
if w.AverageHRV < 0 || w.MaxHRV < 0 || w.MinHRV < 0 {
|
||||
return errors.New("HRV values must be non-negative")
|
||||
}
|
||||
if w.MaxHRV < w.MinHRV {
|
||||
return errors.New("max_hrv must be greater than min_hrv")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
36
garth/stats/stress_weekly.go
Normal file
36
garth/stats/stress_weekly.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package stats
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const WEEKLY_STRESS_PATH = "/wellness-service/wellness/weeklyStress"
|
||||
|
||||
type WeeklyStress struct {
|
||||
CalendarDate time.Time `json:"calendar_date"`
|
||||
TotalStressDuration int `json:"total_stress_duration"`
|
||||
AverageStressLevel float64 `json:"average_stress_level"`
|
||||
MaxStressLevel int `json:"max_stress_level"`
|
||||
StressQualifier string `json:"stress_qualifier"`
|
||||
BaseStats
|
||||
}
|
||||
|
||||
func NewWeeklyStress() *WeeklyStress {
|
||||
return &WeeklyStress{
|
||||
BaseStats: BaseStats{
|
||||
Path: WEEKLY_STRESS_PATH + "/{end}/{period}",
|
||||
PageSize: 52,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WeeklyStress) Validate() error {
|
||||
if w.CalendarDate.IsZero() {
|
||||
return errors.New("calendar_date is required")
|
||||
}
|
||||
if w.TotalStressDuration < 0 {
|
||||
return errors.New("total_stress_duration must be non-negative")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user