@@ -805,6 +805,54 @@ function prepareExportData(modifiedData) {
805805 return allMessages ;
806806}
807807
808+ // helper for Strava normalization
809+ function shouldNormalizeRecordDistances ( recordMesgs ) {
810+ if ( ! recordMesgs ?. length ) return false ;
811+
812+ // Hard requirement: at least one record has distance
813+ return recordMesgs . some ( r => r . distance != null ) ;
814+ }
815+
816+ // helper for Strava normalization
817+ function normalizeRecordDistances ( modifiedData ) {
818+ const records = modifiedData . recordMesgs ;
819+ const session = modifiedData . sessionMesgs ?. [ 0 ] ;
820+
821+ if ( ! records || ! session ?. totalDistance ) return ;
822+
823+ if ( ! shouldNormalizeRecordDistances ( records ) ) {
824+ return ;
825+ }
826+
827+ // Use time-weighted interpolation
828+ const moving = records . filter ( r =>
829+ r . timestamp &&
830+ ( r . enhancedSpeed != null || r . cadence != null )
831+ ) ;
832+
833+ if ( moving . length < 2 ) return ;
834+
835+ const t0 = new Date ( moving [ 0 ] . timestamp ) . getTime ( ) ;
836+ const tN = new Date ( moving . at ( - 1 ) . timestamp ) . getTime ( ) ;
837+ const totalTime = tN - t0 ;
838+
839+ if ( totalTime <= 0 ) return ;
840+
841+ let lastDistance = 0 ;
842+
843+ records . forEach ( r => {
844+ if ( r . timestamp && ( r . enhancedSpeed != null || r . cadence != null ) ) {
845+ const t = new Date ( r . timestamp ) . getTime ( ) ;
846+ const frac = Math . min ( Math . max ( ( t - t0 ) / totalTime , 0 ) , 1 ) ;
847+ lastDistance = frac * session . totalDistance ;
848+ }
849+ r . distance = Math . round ( lastDistance * 100 ) / 100 ;
850+ } ) ;
851+
852+ // Strave hard requirement
853+ records . at ( - 1 ) . distance = session . totalDistance ;
854+ }
855+
808856// FIT export handler
809857async function downloadFitFromJson ( ) {
810858 try {
@@ -814,6 +862,11 @@ async function downloadFitFromJson() {
814862 if ( ! modifiedData ) return alert ( "No modified data found in IndexedDB." ) ;
815863
816864 ensureProfileDefinitions ( mesgDefinitions ) ;
865+ // In some cases where heartrate data is missing, instead
866+ // distances are encoded in the record field. These need to be
867+ // updated in order for Strava to show the correct overall
868+ // distance
869+ normalizeRecordDistances ( modifiedData ) ;
817870 const allMessages = prepareExportData ( modifiedData ) ;
818871
819872 const encoder = new Encoder ( { fieldDescriptions } ) ;
0 commit comments