/
model.go
170 lines (150 loc) · 5.05 KB
/
model.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package rwgps
//go:generate stringer -type=Type -linecomment -output=model_string.go
import (
"time"
"github.com/martinlindhe/unit"
"github.com/rs/zerolog/log"
"github.com/bzimmer/gravl/pkg/providers/activity"
)
// Type of the trip
type Type int
const (
// TypeTrip is a ride which was recorded by GPS
TypeTrip Type = iota // trip
// TypeRoute is a ride which was planned on the RWGPS route builder
TypeRoute // route
)
type UserID int64
const (
Me UserID = 0
)
// Fault is an error
type Fault struct {
Message string `json:"message"`
}
func (f *Fault) Error() string {
return f.Message
}
// User is a user
type User struct {
ID UserID `json:"id"`
Name string `json:"name"`
AuthToken string `json:"auth_token"`
}
type Summary struct {
Avg float64 `json:"avg"`
AvgRaw float64 `json:"_avg"`
Max float64 `json:"max"`
MaxI float64 `json:"max_i"`
MaxRaw float64 `json:"_max"`
Min float64 `json:"min"`
MinI float64 `json:"min_i"`
MinRaw float64 `json:"_min"`
}
type Metrics struct {
AscentTime int `json:"ascentTime"`
Cadence *Summary `json:"cad"`
Calories int `json:"calories"`
CreatedAt time.Time `json:"created_at"`
DescentTime int `json:"descentTime"`
Distance unit.Length `json:"distance" units:"m"`
Duration int `json:"duration"`
Elevation *Summary `json:"ele"`
ElevationGain unit.Length `json:"ele_gain" units:"m"`
ElevationLoss unit.Length `json:"ele_loss" units:"m"`
EndElevation unit.Length `json:"endElevation" units:"m"`
FirstTime int `json:"firstTime"`
Grade *Summary `json:"grade"`
HeartRate *Summary `json:"hr"`
ID int `json:"id"`
MovingPace float64 `json:"movingPace"`
MovingTime int `json:"movingTime"`
NumPoints int `json:"numPoints"`
Pace float64 `json:"pace"`
ParentID int `json:"parent_id"`
ParentType string `json:"parent_type"`
Speed *Summary `json:"speed"`
Stationary bool `json:"stationary"`
StoppedTime int `json:"stoppedTime"`
UpdatedAt *time.Time `json:"updated_at"`
V int `json:"v"`
VAM float64 `json:"vam"`
Watts *Summary `json:"watts"`
}
// TrackPoint represents data about a point along a trip
type TrackPoint struct {
Longitude float64 `json:"x"`
Latitude float64 `json:"y"`
Elevation unit.Length `json:"e" units:"m"`
Distance unit.Length `json:"d" units:"m"`
Time float64 `json:"t"` // seconds since epoch, unix timestamp
Cadence float64 `json:"c"`
Grade float64 `json:"g"`
Speed unit.Speed `json:"s" units:"kph"`
}
// A Trip represents both a planned and completed activity
type Trip struct {
CreatedAt time.Time `json:"created_at"`
DepartedAt time.Time `json:"departed_at"`
Description string `json:"description"`
Distance unit.Length `json:"distance" units:"m"`
Duration int `json:"duration"`
ElevationGain unit.Length `json:"elevation_gain" units:"m"`
ElevationLoss unit.Length `json:"elevation_loss" units:"m"`
ID int64 `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
TrackID string `json:"track_id"`
TrackPoints []*TrackPoint `json:"track_points,omitempty"`
UpdatedAt time.Time `json:"updated_at"`
UserID UserID `json:"user_id"`
Visibility int `json:"visibility"`
FirstLat float64 `json:"first_lat"`
FirstLng float64 `json:"first_lng"`
LastLat float64 `json:"last_lat"`
LastLng float64 `json:"last_lng"`
Metrics *Metrics `json:"metrics,omitempty"`
}
func (t *Trip) Named() *activity.Named {
return &activity.Named{ID: t.ID, Name: t.Name, Date: t.DepartedAt, Source: "rwgps"}
}
type Task struct {
ID int `json:"id"`
Message string `json:"message"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
UserID int `json:"user_id"`
Status int `json:"status"`
}
// Upload is the state representation of an uploaded activity
type Upload struct {
// TaskID of the enqueued request
TaskID int64 `json:"task_id"`
// Success is -1 for failed, 0 for pending, 1 for success
Success int `json:"success"`
// Tasks is a list of queued tasks and their status
Tasks []*Task `json:"queued_tasks"`
}
func (u *Upload) Identifier() activity.UploadID {
return activity.UploadID(u.TaskID)
}
func (u *Upload) Done() bool {
// More at https://ridewithgps.com/api?lang=en
n := len(u.Tasks)
switch n {
case 0:
// this case is for the initial enqueue on upload
return u.Success != 0
case 1:
// this case is for any requests to the status endpoint
return u.Tasks[0].Status != 0
default:
// this case should not exist because status accepts only a single ID
log.Debug().Int("count", n).Msg("> 1 task in rwgps upload response")
var ok = true
for i := 0; ok && i < n; i++ {
ok = ok && u.Tasks[i].Status != 0
}
return ok
}
}