Skip to content

Commit

Permalink
Merge 'dev' into 'master' (#119)
Browse files Browse the repository at this point in the history
  • Loading branch information
muktihari authored Sep 24, 2024
1 parent 801454e commit f69ea17
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 48 deletions.
29 changes: 18 additions & 11 deletions src/components/OpenActivity.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import SplitPaceGraph from './SplitPaceGraph.vue'
<h5 class="title">
<img src="@/assets/openivity-header.svg" />
</h5>
<div style="font-size: 0.9em">
<div style="font-size: 1.05em">
Your data stays in your computer: 100% client-side power.
</div>
</div>
Expand All @@ -67,7 +67,7 @@ import SplitPaceGraph from './SplitPaceGraph.vue'
>
</TheNavigatorInput>
<Transition>
<div style="font-size: 0.8em" class="pt-1">
<div style="font-size: 0.9em" class="pt-1">
<span v-if="isActivityServiceReady"> Supported files: *.fit, *.gpx, *.tcx </span>
<span v-else>
Instantiating WebAssembly <i class="fas fa-spinner fa-spin"></i>
Expand Down Expand Up @@ -281,16 +281,23 @@ import SplitPaceGraph from './SplitPaceGraph.vue'
<!-- Tab Content Ends -->
</div>
<!-- Tab Ends -->
<span class="footer pt-3">
<span class="mx-1">
<i class="fa-solid fa-copyright fa-rotate-180"></i> {{ new Date().getFullYear() }}
</span>
<span class="mx-1">
<span class="footer pt-3 mb-4">
<span class="mx-1 fw-bold">
<a href="http://github.com/openivity/openivity.github.io" target="_blank">
<i class="fa-brands fa-github"></i> Code
<i class="fa-brands fa-github"></i> Star on GitHub
</a>
</span>
<span class="mx-1">|</span>
<span class="mx-1 fw-bold">
<a href="http://github.com/sponsors/muktihari" target="_blank">
Buy me a coffee&nbsp;&nbsp;☕
</a>
</span>
<div class="mx-1 pt-1">Openivity's Open Source Project</div>
<div class="mx-1 pt-1">
Openivity's Open Source Project
<i class="fa-solid fa-copyright fa-rotate-180"></i> 2023 -
{{ new Date().getFullYear() }}
</div>
</span>
</div>
</div>
Expand Down Expand Up @@ -933,7 +940,7 @@ export default {

<style scoped>
.title img {
height: 1.5em;
height: 2em;
}

.v-enter-active,
Expand Down Expand Up @@ -985,7 +992,7 @@ export default {
.footer {
display: inline-block;
height: 70px;
font-size: 0.8em;
font-size: 1em;
color: var(--green-text);
}

Expand Down
3 changes: 2 additions & 1 deletion src/components/TheNavigatorInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. -->
<div class="navigator-input mx-auto">
<input
class="form-control form-control-sm"
style="font-size: 1em"
type="file"
:id="id"
multiple
Expand Down Expand Up @@ -53,6 +54,6 @@ export default {
<style>
.navigator-input {
text-align: center;
max-width: 320px;
max-width: 360px;
}
</style>
34 changes: 17 additions & 17 deletions src/wasm/activity-service/activity/activity.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ package activity
import (
"errors"
"strconv"
"time"

"github.com/muktihari/fit/factory"
"github.com/muktihari/fit/kit/datetime"
"github.com/muktihari/fit/profile/filedef"
"github.com/muktihari/fit/profile/mesgdef"
"github.com/muktihari/fit/profile/typedef"
"github.com/muktihari/fit/profile/untyped/fieldnum"
"github.com/muktihari/fit/profile/untyped/mesgnum"
"github.com/muktihari/fit/proto"
)

Expand All @@ -34,6 +36,9 @@ type Activity struct {
Timezone int8
Sessions []Session

SplitSummaries []*mesgdef.SplitSummary // required for FIT file; entries must be unique within each split_type
Activity *mesgdef.Activity // required for FIT file.

// UnrelatedMessages contains all messages not used by our service
// such as DeveloperDataIds, FieldDescriptions, Events, etc.
// We will restore these messages as it is when we recreate the FIT files.
Expand All @@ -49,7 +54,7 @@ func CreateActivity() Activity {

// ToFIT converts Activity into proto.FIT.
func (a *Activity) ToFIT(options *mesgdef.Options) proto.FIT {
size := 1 + len(a.Sessions) + len(a.UnrelatedMessages)
size := 2 + len(a.Sessions) + len(a.SplitSummaries) + len(a.UnrelatedMessages)
for i := range a.Sessions {
ses := &a.Sessions[i]
size += len(ses.Records) + len(ses.Laps)
Expand All @@ -59,14 +64,16 @@ func (a *Activity) ToFIT(options *mesgdef.Options) proto.FIT {
fit.Messages = append(fit.Messages, a.Creator.FileId.ToMesg(options))
fit.Messages = append(fit.Messages, a.UnrelatedMessages...)

var totalTimerTime uint32
var lastTimestamp time.Time
for i := range a.SplitSummaries {
mesg := a.SplitSummaries[i].ToMesg(nil)
mesg.Fields = append([]proto.Field{
factory.CreateField(mesgnum.Session, fieldnum.SessionTimestamp).WithValue(datetime.ToUint32(a.Activity.Timestamp)),
}, mesg.Fields...)
fit.Messages = append(fit.Messages, mesg)
}

for i := range a.Sessions {
ses := &a.Sessions[i]
if ses.Timestamp.After(lastTimestamp) {
lastTimestamp = ses.Timestamp
}
totalTimerTime += ses.TotalTimerTime

for j := range ses.Records {
rec := &ses.Records[j]
Expand All @@ -79,14 +86,7 @@ func (a *Activity) ToFIT(options *mesgdef.Options) proto.FIT {
fit.Messages = append(fit.Messages, ses.Session.ToMesg(options))
}

activityMesg := mesgdef.NewActivity(nil).
SetType(typedef.ActivityAutoMultiSport).
SetTimestamp(lastTimestamp).
SetLocalTimestamp(lastTimestamp.Add(time.Duration(a.Timezone) * time.Hour)).
SetTotalTimerTime(totalTimerTime).
SetNumSessions(uint16(len(a.Sessions)))

fit.Messages = append(fit.Messages, activityMesg.ToMesg(options))
fit.Messages = append(fit.Messages, a.Activity.ToMesg(nil))

filedef.SortMessagesByTimestamp(fit.Messages[1:]) // Exclude FileId

Expand Down
39 changes: 35 additions & 4 deletions src/wasm/activity-service/activity/fit/fit.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/muktihari/fit/encoder"
"github.com/muktihari/fit/kit/datetime"
"github.com/muktihari/fit/profile/filedef"
"github.com/muktihari/fit/profile/mesgdef"
"github.com/muktihari/fit/profile/typedef"
"github.com/muktihari/fit/proto"
"github.com/openivity/activity-service/activity"
Expand Down Expand Up @@ -69,19 +70,19 @@ func (s *DecodeEncoder) Decode(ctx context.Context, r io.Reader) ([]activity.Act
for dec.Next() {
fileId, err := dec.PeekFileId()
if err != nil {
return nil, err
return nil, fmt.Errorf("could not peek: %w", err)
}

if fileId.Type != typedef.FileActivity {
if err = dec.Discard(); err != nil {
return nil, err
return nil, fmt.Errorf("could not discard: %w", err)
}
continue
}

_, err = dec.DecodeWithContext(ctx)
if err != nil {
return nil, err
return nil, fmt.Errorf("could not decode: %w", err)
}

activityFile := lis.File().(*filedef.Activity)
Expand Down Expand Up @@ -130,6 +131,8 @@ func (s *DecodeEncoder) convertToActivity(activityFile *filedef.Activity) activi
act := activity.Activity{
Creator: activity.CreateCreator(&fileId),
Timezone: timezone,
SplitSummaries: activityFile.SplitSummaries,
Activity: activityFile.Activity,
UnrelatedMessages: s.handleUnrelatedMessages(activityFile),
}

Expand Down Expand Up @@ -264,6 +267,10 @@ func (s *DecodeEncoder) handleUnrelatedMessages(activityFile *filedef.Activity)
len(activityFile.WorkoutSteps) +
len(activityFile.HRs) +
len(activityFile.HRVs) +
len(activityFile.GpsMetadatas) +
len(activityFile.TimeInZones) +
len(activityFile.Splits) +
len(activityFile.Sports) +
len(activityFile.UnrelatedMessages)

if activityFile.UserProfile != nil {
Expand Down Expand Up @@ -308,6 +315,18 @@ func (s *DecodeEncoder) handleUnrelatedMessages(activityFile *filedef.Activity)
for i := range activityFile.HRVs {
unrelatedMessages = append(unrelatedMessages, activityFile.HRVs[i].ToMesg(nil))
}
for i := range activityFile.GpsMetadatas {
unrelatedMessages = append(unrelatedMessages, activityFile.GpsMetadatas[i].ToMesg(nil))
}
for i := range activityFile.TimeInZones {
unrelatedMessages = append(unrelatedMessages, activityFile.TimeInZones[i].ToMesg(nil))
}
for i := range activityFile.Splits {
unrelatedMessages = append(unrelatedMessages, activityFile.Splits[i].ToMesg(nil))
}
for i := range activityFile.Sports {
unrelatedMessages = append(unrelatedMessages, activityFile.Sports[i].ToMesg(nil))
}

unrelatedMessages = append(unrelatedMessages, activityFile.UnrelatedMessages...)

Expand All @@ -330,7 +349,7 @@ func (s *DecodeEncoder) Encode(ctx context.Context, activities []activity.Activi

enc.Reset(bufAt,
encoder.WithProtocolVersion(proto.V2),
encoder.WithNormalHeader(15),
encoder.WithHeaderOption(encoder.HeaderOptionNormal, 15),
)
if err := enc.EncodeWithContext(ctx, &fit); err != nil {
return nil, fmt.Errorf("could not encode: %w", err)
Expand All @@ -344,8 +363,10 @@ func (s *DecodeEncoder) Encode(ctx context.Context, activities []activity.Activi

func (s *DecodeEncoder) makeLastSummary(a *activity.Activity) {
var lastTimestamp time.Time
var totalTimerTime uint32
for i := len(a.Sessions) - 1; i >= 0; i-- {
ses := a.Sessions[i]
totalTimerTime += ses.TotalTimerTime

for j := len(ses.Records) - 1; j >= 0; j-- {
rec := ses.Records[j]
Expand All @@ -371,6 +392,16 @@ func (s *DecodeEncoder) makeLastSummary(a *activity.Activity) {
for i := range a.Sessions {
a.Sessions[i].Timestamp = lastTimestamp
}

if a.Activity == nil {
a.Activity = mesgdef.NewActivity(nil)
}

a.Activity.Timestamp = lastTimestamp
a.Activity.LocalTimestamp = lastTimestamp.Add(time.Duration(a.Timezone) * time.Hour)
a.Activity.TotalTimerTime = totalTimerTime
a.Activity.Type = typedef.ActivityAutoMultiSport
a.Activity.NumSessions = uint16(len(a.Sessions))
}

// bytesBufferAt wraps bytes.Buffer to implement io.WriterAt enabling fast encoding.
Expand Down
4 changes: 3 additions & 1 deletion src/wasm/activity-service/activity/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ func (s *Session) EndTime() time.Time {
func NewSessionFromLaps(laps []Lap) Session {
ses := CreateSession(
mesgdef.NewSession(nil).
SetStartTime(laps[0].StartTime))
SetStartTime(laps[0].StartTime).
SetSport(laps[0].Sport),
)

for i := range laps {
aggregator.Aggregate(ses, laps[i].Lap)
Expand Down
8 changes: 5 additions & 3 deletions src/wasm/activity-service/go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
module github.com/openivity/activity-service

go 1.20
go 1.22.0

toolchain go1.23.0

require (
github.com/muktihari/fit v0.21.5
github.com/muktihari/fit v0.23.5
github.com/muktihari/xmltokenizer v0.0.4
golang.org/x/text v0.18.0
)

require (
github.com/google/go-cmp v0.6.0
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0
)
10 changes: 4 additions & 6 deletions src/wasm/activity-service/go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/muktihari/fit v0.21.3 h1:k8EYHMQsNgofQQ7jOxZhh5ayYqNJ33rDfRN+TMXP61A=
github.com/muktihari/fit v0.21.3/go.mod h1:zOEqw3seokejqhepYCI4rYTA6p+zblmXFub+XrJ8BTE=
github.com/muktihari/fit v0.21.5 h1:DspCXWzNv4+zu3leWKExHPjHr2yuiR4OgswlkC1XITw=
github.com/muktihari/fit v0.21.5/go.mod h1:zOEqw3seokejqhepYCI4rYTA6p+zblmXFub+XrJ8BTE=
github.com/muktihari/fit v0.23.5 h1:Fu5JA29+oxH9qx4DjUQo+w1MNx5TqfBhrd6CdNHIBZo=
github.com/muktihari/fit v0.23.5/go.mod h1:99RXB2OVc87XhcQzgHfUtCVE3VCJ4BvgmyWQI08MM4w=
github.com/muktihari/xmltokenizer v0.0.4 h1:x4DZWvfcEAJR+iBPb8XeiWL1J15SY21bCaem76wmmjw=
github.com/muktihari/xmltokenizer v0.0.4/go.mod h1:yTxhndrcpmZEPYqQGSN51MwkzPQgGSkRpqW5ZFBpdF0=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
12 changes: 11 additions & 1 deletion src/wasm/activity-service/manufacturers.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
{ "id": 2, "name": "x10" },
{ "id": 3, "name": "x6" },
{ "id": 4, "name": "Memory Belt" },
{ "id": 5, "name": "Smart Belt" },
{ "id": 6, "name": "t6" },
{ "id": 7, "name": "t6c" },
{ "id": 8, "name": "t6d" },
Expand Down Expand Up @@ -140,11 +141,20 @@
{ "id": 1505, "name": "Rider 310" },
{ "id": 1508, "name": "Rider 530" },
{ "id": 1509, "name": "Rider 330" },
{ "id": 1610, "name": "Rider 10" },
{ "id": 1703, "name": "Aero 60" },
{ "id": 1704, "name": "Rider 450" },
{ "id": 1706, "name": "Rider 410" },
{ "id": 1803, "name": "Rider 15" },
{ "id": 1901, "name": "Rider 420" }
{ "id": 1804, "name": "Rider 860" },
{ "id": 1901, "name": "Rider 420" },
{ "id": 1902, "name": "Rider 750" },
{ "id": 2001, "name": "Rider 320" },
{ "id": 2004, "name": "Rider 15 neo" },
{ "id": 2101, "name": "Rider S500" },
{ "id": 2103, "name": "Rider S800" },
{ "id": 2203, "name": "Rider 750 SE" },
{ "id": 2205, "name": "Rider 460" }
]
},
"289": {
Expand Down
20 changes: 16 additions & 4 deletions src/wasm/activity-service/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (

"github.com/muktihari/fit/profile/basetype"
"github.com/muktihari/fit/profile/typedef"
"github.com/muktihari/fit/profile/untyped/mesgnum"
"github.com/openivity/activity-service/activity"
"github.com/openivity/activity-service/aggregator"
"github.com/openivity/activity-service/service/result"
Expand Down Expand Up @@ -317,6 +316,7 @@ func (s *Service) combineActivity(activities []activity.Activity, manufacturer t
Creator: creator,
Timezone: activities[0].Timezone,
Sessions: activities[0].Sessions,
SplitSummaries: activities[0].SplitSummaries,
UnrelatedMessages: activities[0].UnrelatedMessages,
}

Expand Down Expand Up @@ -362,10 +362,22 @@ func (s *Service) combineActivity(activities []activity.Activity, manufacturer t
newActivity.Sessions = append(newActivity.Sessions, cur.Sessions[1:]...)
}

for j := 0; j < len(cur.UnrelatedMessages); j++ {
if cur.UnrelatedMessages[j].Num == mesgnum.SplitSummary {
continue // TODO: Still failed to upload to Garmin Connect if we include this message.
for _, m := range cur.SplitSummaries {
var ok bool
for _, v := range newActivity.SplitSummaries {
if v.SplitType == m.SplitType {
aggregator.Aggregate(v, m)
ok = true
break
}
}
if !ok {
newActivity.SplitSummaries = append(newActivity.SplitSummaries, m)
}
continue
}

for j := 0; j < len(cur.UnrelatedMessages); j++ {
newActivity.UnrelatedMessages = append(newActivity.UnrelatedMessages, cur.UnrelatedMessages[j])
}
}
Expand Down

0 comments on commit f69ea17

Please sign in to comment.