trackswap 0.0.27 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,26 +1,29 @@
1
- var c=class{constructor(){this.stage="parse"}async process(_){let I=Date.now();if(!_.rawData)throw new Error("FIT data cannot be empty");try{let A=await this.parseWithFitSDK(_.rawData);return _.rawMessages=A,_.performance.parseTime=Date.now()-I,_}catch(A){throw new Error(`FIT parsing failed: ${A.message}`)}}async parseWithFitSDK(_){let{Decoder:I,Stream:A}=await import("@garmin/fitsdk"),T=A.fromBuffer(_);if(!I.isFIT(T))throw new Error("Not a valid FIT file");let R=new I(T),{messages:L,errors:t}=R.read();return t&&t.length>0,L}},x=class{constructor(_){this.getConverters=_;this.stage="extract"}async process(_){let I=Date.now();if(!_.rawMessages)throw new Error("Raw messages cannot be empty");let A={};for(let[T,R]of Object.entries(_.rawMessages)){if(!Array.isArray(R)||R.length===0){A[T]=R;continue}let L=this.getConverters(T);if(L.length===0)A[T]=R;else{let t=L[0];try{let E=t.convertMessages(R,_);A[T]=E}catch(E){_.errors.push(E),A[T]=R}}}return _.rawMessages=A,_.performance.extractTime=Date.now()-I,_}},a=class{constructor(_){this.getStructurePlugins=_;this.stage="structure"}async process(_){let I=Date.now();if(!_.rawMessages)throw new Error("Message data cannot be empty");let A={},T=this.getStructurePlugins();for(let R of T)try{let L=R.structureData(_.rawMessages,_);A={...A,...L}}catch(L){_.errors.push(L)}return _.result=A,_.performance.structureTime=Date.now()-I,_}},e=class{constructor(){this.stage="complete"}async process(_){_.performance.endTime=Date.now();let I=_.performance.endTime-_.performance.startTime;return _.metadata.set("performance",{totalTime:I,parseTime:_.performance.parseTime,extractTime:_.performance.extractTime,structureTime:_.performance.structureTime}),_.stats&&(_.stats.endTime=Date.now(),_.rawMessages&&(_.stats.processedTokens=this.countTotalMessages(_.rawMessages))),_}countTotalMessages(_){let I=0;return Object.values(_).forEach(A=>{Array.isArray(A)&&(I+=A.length)}),I}};import K from"dayjs";var V=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(_){_.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(_){_.metadata.delete(`plugin:${this.name}:initialized`)}async validate(_){return!0}};var J=class extends V{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(I,A){let{sessionMesgs:T,lapMesgs:R,recordMesgs:L,lengthMesgs:t}=I;return T!=null&&T.length?{sessionMesgs:T.map(D=>{let H=K(D.startTime).valueOf(),C=H+D.totalElapsedTime*1e3,N=((R==null?void 0:R.filter(U=>{let B=K(U.startTime).valueOf(),P=B+(U.totalElapsedTime??0)*1e3;return B>=H&&P<=C}))||[]).map(U=>{let B=K(U.startTime).valueOf(),P=B+(U.totalElapsedTime??0)*1e3,RI=(L==null?void 0:L.filter(J_=>{let Q=K(J_.timestamp).valueOf();return Q>=B&&Q<P}))||[],Q_=U.firstLengthIndex??void 0,s_=U.numLengths??void 0,u_=[];if(Q_!==void 0&&s_!==void 0){let J_=Q_+s_;u_=(t==null?void 0:t.filter(Q=>Q.messageIndex>=Q_&&Q.messageIndex<J_))||[]}return{...U,recordMesgs:RI,lengthMesgs:u_,messageIndex:U.messageIndex!==void 0?U.messageIndex:0}});return{...D,lapMesgs:N,messageIndex:D.messageIndex!==void 0?D.messageIndex:0}})}:{}}},z=class extends V{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(I,A){let{courseMesgs:T,lapMesgs:R,recordMesgs:L}=I;if(!(T!=null&&T.length))return{};let t=2e3;return{courseMesgs:T.map(D=>{let H=(R==null?void 0:R.map(C=>{let r=K(C.startTime).valueOf(),N=K(C.timestamp).valueOf(),U=(L==null?void 0:L.filter(B=>{let P=K(B.timestamp).valueOf();return P>=r-t&&P<=N+t}))||[];return{...C,recordMesgs:U}}))||[];return{...D,lapMesgs:H}})}}},p=class extends V{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(I,A){let{fileIdMesgs:T}=I;if(T!=null&&T.length&&T[0]){let R=T[0];A.fileHeader={type:R.type,manufacturer:R.manufacturer,product:R.product}}return{}}};var X=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.structurePlugins=[];this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultPluginsRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new c,new x(_=>this.getConverters(_)),new a(()=>this.structurePlugins),new e]}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let _=[new p,new J,new z];for(let I of _)this.addStructurePlugin(I),this.registeredPlugins.add(I.name);this.defaultPluginsRegistered=!0}addConverterForMessageType(_,I){this.converterPlugins.has(_)||this.converterPlugins.set(_,[]);let A=this.converterPlugins.get(_);A.push(I),A.sort((T,R)=>(T.priority||100)-(R.priority||100))}addStructurePlugin(_){this.structurePlugins.push(_),this.structurePlugins.sort((I,A)=>(I.priority||100)-(A.priority||100))}async registerMessageConverter(_){if(this.registeredPlugins.has(_.name))throw new Error(`Message converter plugin ${_.name} already exists`);_.supportedMessageTypes.forEach(A=>{this.addConverterForMessageType(A,_)}),this.registeredPlugins.add(_.name);let I=_.priority!==void 0?` (priority: ${_.priority})`:"";_.supportedMessageTypes.forEach(A=>{let R=(this.converterPlugins.get(A)||[]).map(L=>`${L.name}(${L.priority||100})`)})}async registerStructurePlugin(_){if(this.registeredPlugins.has(_.name))throw new Error(`Structure plugin ${_.name} already exists`);this.addStructurePlugin(_),this.registeredPlugins.add(_.name);let I=_.priority!==void 0?` (priority: ${_.priority})`:""}async registerMiddleware(_){let I=this.middlewarePlugins.findIndex(T=>T.name===_.name);I!==-1?this.middlewarePlugins[I]=_:(this.middlewarePlugins.push(_),this.middlewarePlugins.sort((T,R)=>(T.priority||100)-(R.priority||100)));let A=[];_.onParse&&A.push("onParse"),_.onExtractMessages&&A.push("onExtractMessages"),_.onStructure&&A.push("onStructure"),_.onComplete&&A.push("onComplete"),_.onError&&A.push("onError"),A.length>0}getConverter(_){let I=this.converterPlugins.get(_);return I&&I.length>0?I[0]:void 0}getConverters(_){return this.converterPlugins.get(_)||[]}unregisterPlugin(_){if(!this.registeredPlugins.has(_))return!1;for(let[T,R]of this.converterPlugins){let L=R.findIndex(t=>t.name===_);L!==-1&&(R.splice(L,1),R.length===0&&this.converterPlugins.delete(T))}let I=this.structurePlugins.findIndex(T=>T.name===_);I!==-1&&this.structurePlugins.splice(I,1);let A=this.middlewarePlugins.findIndex(T=>T.name===_);return A!==-1&&this.middlewarePlugins.splice(A,1),this.registeredPlugins.delete(_),!0}async initialize(){var A;if(this.initialized)return;await this.registerDefaultPlugins();let _=this.createContext(),I=[...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins];for(let T of I)try{await((A=T.initialize)==null?void 0:A.call(T,_))}catch{}this.initialized=!0}async destroy(){var A;if(!this.initialized)return;let _=this.createContext(),I=[...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins];for(let T of I)try{await((A=T.destroy)==null?void 0:A.call(T,_))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(_,I,A){var R;let T=I;for(let L of this.middlewarePlugins){let t=L[_];if(t)try{T=await t.call(L,T,A)||T}catch(E){A.errors.push(E),await((R=L.onError)==null?void 0:R.call(L,E,A))}}return T}async parseByBuffer(_,I={}){var T;await this.initialize();let A=this.createContext();A.rawData=_,A.userData=I.userData,A.metadata.set("decoder",this);try{for(let R of this.processors)try{switch(A=await R.process(A),R.stage){case"parse":A.rawData&&(A.rawData=await this.executeMiddlewareHook("onParse",A.rawData,A));break;case"extract":A.rawMessages&&(A.rawMessages=await this.executeMiddlewareHook("onExtractMessages",A.rawMessages,A));break;case"structure":A.result&&(A.result=await this.executeMiddlewareHook("onStructure",A.result,A));break;case"complete":A.result&&(A.result=await this.executeMiddlewareHook("onComplete",A.result,A));break}}catch(L){A.errors.push(L);for(let t of this.middlewarePlugins)await((T=t.onError)==null?void 0:T.call(t,L,A))}return A.result}catch(R){throw R}}};var LI={file:{course:6,device:1,settings:2,sport:3,activity:4,workout:5,schedules:7,weight:9,totals:10,goals:11,blood_pressure:14,monitoring_a:15,activity_summary:20,monitoring_daily:28,monitoring_b:32,segment_list:35,exd_configuration:40,invalid:0},sport:{generic:0,running:1,cycling:2,transition:3,fitness_equipment:4,swimming:5,basketball:6,soccer:7,tennis:8,american_football:9,training:10,walking:11,cross_country_skiing:12,alpine_skiing:13,snowboarding:14,rowing:15,mountaineering:16,hiking:17,multisport:18,paddling:19,invalid:254},event:{timer:0,workout:3,workout_step:4,power_down:5,power_up:6,off_course:7,session:8,lap:9,course_point:10,battery:11,virtual_partner_pace:12,hr_high_alert:13,hr_low_alert:14,speed_high_alert:15,speed_low_alert:16,cad_high_alert:17,cad_low_alert:18,power_high_alert:19,power_low_alert:20,recovery_hr:21,battery_low:22,time_duration_alert:23,distance_duration_alert:24,calorie_duration_alert:25,activity:26,fitness_equipment:27,length:28,user_marker:32,sport_point:33,calibration:36,front_gear_change:42,rear_gear_change:43,rider_position_change:44,elev_high_alert:45,elev_low_alert:46,comm_timeout:47,invalid:255},event_type:{start:0,stop:1,consecutive_depreciated:2,marker:3,stop_all:4,begin_depreciated:5,end_depreciated:6,end_all_depreciated:7,stop_disable:8,stop_disable_all:9,invalid:255},course_point:{generic:0,summit:1,valley:2,water:3,food:4,danger:5,left:6,right:7,straight:8,first_aid:9,fourth_category:10,third_category:11,second_category:12,first_category:13,hors_category:14,sprint:15,left_fork:16,right_fork:17,middle_fork:18,slight_left:19,sharp_left:20,slight_right:21,sharp_right:22,u_turn:23,segment_start:24,segment_end:25,invalid:255}},M=n=>{let _=LI[n];return{size:1,baseType:0,mapValue:I=>typeof I=="string"?_[I]??255:I,setValue:function(I,A){this.setUint8(I,A)}}},z_={enum_file:M("file"),enum_activity:M("sport"),enum_sport:M("sport"),enum_sub_sport:M("sport"),enum_event:M("event"),enum_event_type:M("event_type"),enum_course_point:M("course_point"),uint8:{size:1,baseType:2,setValue:DataView.prototype.setUint8},sint8:{size:1,baseType:1,setValue:DataView.prototype.setInt8},uint16:{size:2,baseType:132,setValue:DataView.prototype.setUint16},sint16:{size:2,baseType:131,setValue:DataView.prototype.setInt16},uint32:{size:4,baseType:134,setValue:DataView.prototype.setUint32},sint32:{size:4,baseType:133,setValue:DataView.prototype.setInt32},string:{size:0,baseType:7,mapValue:n=>Array.from(m_(n)),setValue:EI},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:n=>Math.round(n*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:n=>Math.round(n*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:n=>Math.round((n+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:n=>Math.round(n*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:n=>{let _;return n instanceof Date?(_=Math.floor(n.getTime()/1e3),_-631065600):typeof n=="string"?(_=Math.floor(new Date(n).getTime()/1e3),_-631065600):n<631065600?Math.floor(n):(n>9999999999?_=Math.floor(n/1e3):_=Math.floor(n),_-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:n=>Math.round(n/180*2147483648)}};function i_(n){return Array.from(m_(n)).length+1}function*m_(n){for(let _ of tI(n))_<128?yield _:_<2048?(yield 192|_>>6,yield 128|_&63):_<65536?(yield 224|_>>12,yield 128|_>>6&63,yield 128|_&63):(yield 240|_>>18,yield 128|_>>12&63,yield 128|_>>6&63,yield 128|_&63);yield 0}function*tI(n){for(let _=0;_<n.length;){let I=n.codePointAt(_);if(I===void 0)break;yield I,_+=I>65535?2:1}}function EI(n,_){for(let I=0;I<_.length;I++)this.setUint8(n+I,_[I])}var nI={file_id:{mesgNum:0,fieldDefns:[{name:"type",number:0,type:"enum_file"},{name:"time_created",number:4,type:"date_time"}]},session:{mesgNum:18,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"},{name:"sport",number:5,type:"enum_sport"},{name:"sub_sport",number:6,type:"enum_sub_sport"},{name:"first_lap_index",number:11,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"end_position_lat",number:5,type:"semicircles"},{name:"end_position_long",number:6,type:"semicircles"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"}]},record:{mesgNum:20,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"position_lat",number:0,type:"semicircles"},{name:"position_long",number:1,type:"semicircles"},{name:"altitude",number:2,type:"altitude"},{name:"distance",number:5,type:"distance"},{name:"heart_rate",number:3,type:"uint8"},{name:"cadence",number:4,type:"uint8"},{name:"speed",number:6,type:"speed"},{name:"power",number:7,type:"uint16"}]},event:{mesgNum:21,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"event",number:0,type:"enum_event"},{name:"event_type",number:1,type:"enum_event_type"},{name:"event_group",number:4,type:"uint8"}]},course:{mesgNum:31,fieldDefns:[{name:"name",number:5,type:"string"},{name:"sport",number:4,type:"enum_sport"},{name:"sub_sport",number:7,type:"enum_sub_sport"}]},activity:{mesgNum:34,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"total_timer_time",number:0,type:"seconds"},{name:"num_sessions",number:1,type:"uint16"},{name:"type",number:2,type:"enum_activity"},{name:"event",number:3,type:"enum_event"},{name:"event_type",number:4,type:"enum_event_type"},{name:"local_timestamp",number:5,type:"date_time"},{name:"event_group",number:6,type:"uint8"}]},course_point:{mesgNum:32,fieldDefns:[{name:"timestamp",number:1,type:"date_time"},{name:"position_lat",number:2,type:"semicircles"},{name:"position_long",number:3,type:"semicircles"},{name:"distance",number:4,type:"distance"},{name:"type",number:5,type:"enum_course_point"}]}},SI=(n,_)=>n.map(I=>({...I,value:_[I.name]})).filter(({value:I})=>I!==void 0),__=class n{static check(_,I,A,T){if(I===void 0)throw new Error(`Message '${_}' not known`);if(A===void 0)throw new Error(`Message '${_}' has no field definitions`);let R=A.map(t=>t.name),L=Object.keys(T).filter(t=>!R.includes(t));if(L.length)throw new Error(`Message '${_}' has no field definitions named '${L}'`)}constructor(_,I,A){let T=nI[I];if(!T)throw new Error(`Unknown message type: ${I}`);let{mesgNum:R,fieldDefns:L}=T;n.check(I,R,L,A),this.localNum=_,this.mesgNum=R,this.fields=SI(L,A)}get mesgDefn(){let _=this.fields.map(({number:I,type:A,value:T})=>{let R=z_[A];if(!R)throw new Error(`Unknown type: ${A}`);let{size:L,baseType:t}=R;return A==="string"?{number:I,size:i_(T),baseType:t}:{number:I,size:L,baseType:t}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:_}}isSameDefn(_){let I=(t,E)=>t.number===E.number&&t.size===E.size&&t.baseType===E.baseType,A=(t,E)=>t.length===E.length&&t.every((D,H)=>I(D,E[H])),{localNum:T,mesgNum:R,fieldDefns:L}=this.mesgDefn;return R===_.mesgNum&&T===_.localNum&&A(L,_.fieldDefns)}get defnRecord(){let{localNum:_,mesgNum:I,fieldDefns:A}=this.mesgDefn,T=6+3*A.length,R=new DataView(new ArrayBuffer(T));R.setUint8(0,64|_),R.setUint8(2,1),R.setUint16(3,I),R.setUint8(5,A.length);let L=6;for(let t of A)R.setUint8(L++,t.number),R.setUint8(L++,t.size),R.setUint8(L++,t.baseType);return R.buffer}get dataRecord(){let{fieldDefns:_}=this.mesgDefn,I=1+_.reduce((R,{size:L})=>R+L,0),A=new DataView(new ArrayBuffer(I));A.setUint8(0,this.localNum);let T=1;for(let{number:R,type:L,value:t}of this.fields){let E=z_[L];if(!E)throw new Error(`Unknown type: ${L}`);let{size:D,setValue:H}=E,C;"mapValue"in E?C=E.mapValue(t):C=t,H&&H.call(A,T,C),T+=D}return A.buffer}};var DI=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],r_=(n,_)=>(n>>>4^DI[n&15^_])&65535,HI=(n,_,I)=>r_(r_(n,_),I),CI=(n,_)=>HI(n,_&15,_>>>4);function p_(n,_=0){let I=_,A=n instanceof ArrayBuffer?new Uint8Array(n):n;for(let T=0;T<A.length;T++)I=CI(I,A[T]);return I}import UI from"dayjs";var c_=14,GI=16,FI=2078,oI=776358228,g=class{constructor(_={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:_.compact??!0,defaultActivity:_.defaultActivity??"cycling",defaultSubActivity:_.defaultSubActivity??"generic"}}async encode(_){return this.reset(),this.buildFITContent(_,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(_){return this.reset(),this.buildFITContent(_,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(_,I="activity"){return this.reset(),this.buildFITContent(_,I),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(_,I){this.buildFileId(_,I),I==="course"?this.buildCourseContent(_):this.buildActivityContent(_)}buildActivityContent(_){let I=_.sessionMesgs||[];if(I.length===0)throw new Error("Activity file must contain at least one Session");let A=0,T=[],R=[];for(let L of I){if(L.lapMesgs&&this.buildEventsFromLaps(L.lapMesgs,T),L.lapMesgs)for(let t of L.lapMesgs)t.recordMesgs&&this.buildRecords(t.recordMesgs);L.lapMesgs&&this.buildLaps(L.lapMesgs),this.buildSession(L),A++,this.buildActivityFromSession(L,R)}T.forEach(L=>this.buildEvent(L)),R.forEach(L=>this.buildActivity(L))}buildCourseContent(_){let I=_.sessionMesgs||[];if(I.length===0)throw new Error("Course file must contain track data");let A=I[0];if(this.buildCourse({name:"course",sport:this.options.defaultActivity}),A.lapMesgs){let T=[];for(let t of A.lapMesgs)t.recordMesgs&&T.push(...t.recordMesgs);T.sort((t,E)=>t.timestamp&&E.timestamp?new Date(t.timestamp).getTime()-new Date(E.timestamp).getTime():(t.distance||0)-(E.distance||0));let R=T[0],L=T[T.length-1];if(A.startTime&&this.buildEvent({timestamp:A.startTime,event:"timer",eventType:"start",eventGroup:0}),T.forEach(t=>this.buildRecord(t)),L.timestamp&&this.buildEvent({timestamp:L.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),A.lapMesgs)for(let t=0;t<A.lapMesgs.length;t++)this.buildLap(A.lapMesgs[t])}}buildFileId(_,I){var T;let A=((T=_.fileIdMesgs)==null?void 0:T[0])||{};this.writeMesg("file_id",{type:I,time_created:A.timeCreated?this.parseTimestamp(A.timeCreated):Date.now(),manufacturer:A.manufacturer,product:A.product,serial_number:A.serialNumber})}buildSession(_){var I;this.writeMesg("session",{timestamp:_.timestamp?_.timestamp:void 0,start_time:_.startTime?_.startTime:void 0,total_elapsed_time:_.totalElapsedTime,total_timer_time:_.totalTimerTime,start_position_lat:_.startPositionLat?this.convertToSemicircles(_.startPositionLat):void 0,start_position_long:_.startPositionLong?this.convertToSemicircles(_.startPositionLong):void 0,total_distance:_.totalDistance,total_ascent:_.totalAscent,total_descent:_.totalDescent,sport:_.sport||this.options.defaultActivity,sub_sport:_.subSport||this.options.defaultSubActivity,first_lap_index:_.firstLapIndex||0,num_laps:_.numLaps||((I=_.lapMesgs)==null?void 0:I.length)||1})}buildLaps(_){_.forEach(I=>this.buildLap(I))}buildLap(_){this.writeMesg("lap",{timestamp:_!=null&&_.timestamp?_.timestamp:void 0,start_time:_!=null&&_.startTime?_.startTime:void 0,start_position_lat:_!=null&&_.startPositionLat?this.convertToSemicircles(_.startPositionLat):void 0,start_position_long:_!=null&&_.startPositionLong?this.convertToSemicircles(_.startPositionLong):void 0,end_position_lat:_!=null&&_.endPositionLat?this.convertToSemicircles(_.endPositionLat):void 0,end_position_long:_!=null&&_.endPositionLong?this.convertToSemicircles(_.endPositionLong):void 0,total_elapsed_time:_==null?void 0:_.totalElapsedTime,total_timer_time:_==null?void 0:_.totalTimerTime,total_distance:_==null?void 0:_.totalDistance,total_ascent:_==null?void 0:_.totalAscent,total_descent:_==null?void 0:_.totalDescent})}buildRecords(_){_.forEach(I=>this.buildRecord(I))}buildRecord(_){this.writeMesg("record",{timestamp:_.timestamp,position_lat:_!=null&&_.positionLat?this.convertToSemicircles(_.positionLat):void 0,position_long:_!=null&&_.positionLong?this.convertToSemicircles(_.positionLong):void 0,altitude:_==null?void 0:_.altitude,enhancedAltitude:_==null?void 0:_.enhancedAltitude,distance:_==null?void 0:_.distance,heart_rate:_==null?void 0:_.heartRate,cadence:_==null?void 0:_.cadence,speed:_==null?void 0:_.speed,enhancedSpeed:_==null?void 0:_.enhancedSpeed,power:_==null?void 0:_.power})}buildEvent(_){this.writeMesg("event",{timestamp:_.timestamp?_.timestamp:void 0,event:_.event,event_type:_.eventType,event_group:_.eventGroup})}buildActivity(_){this.writeMesg("activity",{timestamp:_.timestamp?_.timestamp:void 0,total_timer_time:_.totalTimerTime,num_sessions:_.numSessions,type:_.type,event:_.event,event_type:_.eventType,local_timestamp:_.localTimestamp?this.parseTimestamp(_.localTimestamp):void 0,event_group:_.eventGroup})}buildCourse(_){this.writeMesg("course",{name:_.name,sport:_.sport})}buildEventsFromLaps(_,I){_.forEach((A,T)=>{A.startTime&&I.push({timestamp:A.startTime,event:"timer",eventType:"start",eventGroup:T}),A.timestamp&&I.push({timestamp:A.timestamp,event:"timer",eventType:T===_.length-1?"stop_all":"stop",eventGroup:T})})}buildActivityFromSession(_,I){I.push({timestamp:_.timestamp,totalTimerTime:_.totalTimerTime,numSessions:1,type:_.sport||this.options.defaultActivity,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(_){return typeof _=="number"?_:UI(_).valueOf()}convertToSemicircles(_){if(_!=null)return Math.round(_*2**31/180)}validateRequiredFields(_){if(!_.sessionMesgs||_.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(_,I){let A=Object.fromEntries(Object.entries(I).filter(([t,E])=>E!==void 0));if(Object.keys(A).length===0)return;let T=this.localNum[_];T===void 0&&(T=this.localNum[_]=Object.keys(this.localNum).length);let R=new __(T,_,A),L=this.mesgDefn[T];(!L||!R.isSameDefn(L))&&(this.messages.push(R.defnRecord),this.mesgDefn[T]=R.mesgDefn),this.messages.push(R.dataRecord)}get blob(){let _=[this.header,...this.messages,this.trailer];return new Blob(_,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((_,I)=>_+I.byteLength,0)}get dataCrc(){return this.messages.reduce((_,I)=>p_(I,_),0)}get header(){let _=new DataView(new ArrayBuffer(c_));return _.setUint8(0,c_),_.setUint8(1,GI),_.setUint16(2,FI,!0),_.setUint32(4,this.dataLen,!0),_.setUint32(8,oI),_.setUint16(12,p_(_.buffer.slice(0,12)),!0),_.buffer}get trailer(){let _=new DataView(new ArrayBuffer(2));return _.setUint16(0,this.dataCrc,!0),_.buffer}async encoder(_){return this.encode(_)}};import{Encoder as fI}from"@garmin/fitsdk";var I_=(S=>(S[S.GENERIC=0]="GENERIC",S[S.RUNNING=1]="RUNNING",S[S.CYCLING=2]="CYCLING",S[S.TRANSITION=3]="TRANSITION",S[S.FITNESS_EQUIPMENT=4]="FITNESS_EQUIPMENT",S[S.SWIMMING=5]="SWIMMING",S[S.BASKETBALL=6]="BASKETBALL",S[S.SOCCER=7]="SOCCER",S[S.TENNIS=8]="TENNIS",S[S.AMERICAN_FOOTBALL=9]="AMERICAN_FOOTBALL",S[S.TRAINING=10]="TRAINING",S[S.WALKING=11]="WALKING",S[S.CROSS_COUNTRY_SKIING=12]="CROSS_COUNTRY_SKIING",S[S.ALPINE_SKIING=13]="ALPINE_SKIING",S[S.SNOWBOARDING=14]="SNOWBOARDING",S[S.ROWING=15]="ROWING",S[S.MOUNTAINEERING=16]="MOUNTAINEERING",S[S.HIKING=17]="HIKING",S[S.MULTISPORT=18]="MULTISPORT",S[S.PADDLING=19]="PADDLING",S[S.FLYING=20]="FLYING",S[S.E_BIKING=21]="E_BIKING",S[S.MOTORCYCLING=22]="MOTORCYCLING",S[S.BOATING=23]="BOATING",S[S.DRIVING=24]="DRIVING",S[S.GOLF=25]="GOLF",S[S.HANG_GLIDING=26]="HANG_GLIDING",S[S.HORSEBACK_RIDING=27]="HORSEBACK_RIDING",S[S.HUNTING=28]="HUNTING",S[S.FISHING=29]="FISHING",S[S.INLINE_SKATING=30]="INLINE_SKATING",S[S.ROCK_CLIMBING=31]="ROCK_CLIMBING",S[S.SAILING=32]="SAILING",S[S.ICE_SKATING=33]="ICE_SKATING",S[S.SKY_DIVING=34]="SKY_DIVING",S[S.SNOWSHOEING=35]="SNOWSHOEING",S[S.SNOWMOBILING=36]="SNOWMOBILING",S[S.STAND_UP_PADDLEBOARDING=37]="STAND_UP_PADDLEBOARDING",S[S.SURFING=38]="SURFING",S[S.WAKEBOARDING=39]="WAKEBOARDING",S[S.WATER_SKIING=40]="WATER_SKIING",S[S.KAYAKING=41]="KAYAKING",S[S.RAFTING=42]="RAFTING",S[S.WINDSURFING=43]="WINDSURFING",S[S.KITESURFING=44]="KITESURFING",S[S.TACTICAL=45]="TACTICAL",S[S.JUMPMASTER=46]="JUMPMASTER",S[S.BOXING=47]="BOXING",S[S.FLOOR_CLIMBING=48]="FLOOR_CLIMBING",S[S.BASEBALL=49]="BASEBALL",S[S.DIVING=53]="DIVING",S[S.HIIT=62]="HIIT",S[S.RACKET=64]="RACKET",S[S.WHEELCHAIR_PUSH_WALK=65]="WHEELCHAIR_PUSH_WALK",S[S.WHEELCHAIR_PUSH_RUN=66]="WHEELCHAIR_PUSH_RUN",S[S.MEDITATION=67]="MEDITATION",S[S.DISC_GOLF=69]="DISC_GOLF",S[S.CRICKET=71]="CRICKET",S[S.RUGBY=72]="RUGBY",S[S.HOCKEY=73]="HOCKEY",S[S.LACROSSE=74]="LACROSSE",S[S.VOLLEYBALL=75]="VOLLEYBALL",S[S.WATER_TUBING=76]="WATER_TUBING",S[S.WAKESURFING=77]="WAKESURFING",S[S.MIXED_MARTIAL_ARTS=80]="MIXED_MARTIAL_ARTS",S[S.SNORKELING=82]="SNORKELING",S[S.DANCE=83]="DANCE",S[S.JUMP_ROPE=84]="JUMP_ROPE",S[S.ALL=254]="ALL",S))(I_||{});var A_=(O=>(O[O.GENERIC=0]="GENERIC",O[O.TREADMILL=1]="TREADMILL",O[O.STREET=2]="STREET",O[O.TRAIL=3]="TRAIL",O[O.TRACK=4]="TRACK",O[O.SPIN=5]="SPIN",O[O.INDOOR_CYCLING=6]="INDOOR_CYCLING",O[O.ROAD=7]="ROAD",O[O.MOUNTAIN=8]="MOUNTAIN",O[O.DOWNHILL=9]="DOWNHILL",O[O.RECUMBENT=10]="RECUMBENT",O[O.CYCLOCROSS=11]="CYCLOCROSS",O[O.HAND_CYCLING=12]="HAND_CYCLING",O[O.TRACK_CYCLING=13]="TRACK_CYCLING",O[O.INDOOR_ROWING=14]="INDOOR_ROWING",O[O.ELLIPTICAL=15]="ELLIPTICAL",O[O.STAIR_CLIMBING=16]="STAIR_CLIMBING",O[O.LAP_SWIMMING=17]="LAP_SWIMMING",O[O.OPEN_WATER=18]="OPEN_WATER",O[O.FLEXIBILITY_TRAINING=19]="FLEXIBILITY_TRAINING",O[O.STRENGTH_TRAINING=20]="STRENGTH_TRAINING",O[O.WARM_UP=21]="WARM_UP",O[O.MATCH=22]="MATCH",O[O.EXERCISE=23]="EXERCISE",O[O.CHALLENGE=24]="CHALLENGE",O[O.INDOOR_SKIING=25]="INDOOR_SKIING",O[O.CARDIO_TRAINING=26]="CARDIO_TRAINING",O[O.INDOOR_WALKING=27]="INDOOR_WALKING",O[O.E_BIKE_FITNESS=28]="E_BIKE_FITNESS",O[O.BMX=29]="BMX",O[O.CASUAL_WALKING=30]="CASUAL_WALKING",O[O.SPEED_WALKING=31]="SPEED_WALKING",O[O.BIKE_TO_RUN_TRANSITION=32]="BIKE_TO_RUN_TRANSITION",O[O.RUN_TO_BIKE_TRANSITION=33]="RUN_TO_BIKE_TRANSITION",O[O.SWIM_TO_BIKE_TRANSITION=34]="SWIM_TO_BIKE_TRANSITION",O[O.ATV=35]="ATV",O[O.MOTOCROSS=36]="MOTOCROSS",O[O.BACKCOUNTRY=37]="BACKCOUNTRY",O[O.RESORT=38]="RESORT",O[O.RC_DRONE=39]="RC_DRONE",O[O.WINGSUIT=40]="WINGSUIT",O[O.WHITEWATER=41]="WHITEWATER",O[O.SKATE_SKIING=42]="SKATE_SKIING",O[O.YOGA=43]="YOGA",O[O.PILATES=44]="PILATES",O[O.INDOOR_RUNNING=45]="INDOOR_RUNNING",O[O.GRAVEL_CYCLING=46]="GRAVEL_CYCLING",O[O.E_BIKE_MOUNTAIN=47]="E_BIKE_MOUNTAIN",O[O.COMMUTING=48]="COMMUTING",O[O.MIXED_SURFACE=49]="MIXED_SURFACE",O[O.NAVIGATE=50]="NAVIGATE",O[O.TRACK_ME=51]="TRACK_ME",O[O.MAP=52]="MAP",O[O.SINGLE_GAS_DIVING=53]="SINGLE_GAS_DIVING",O[O.MULTI_GAS_DIVING=54]="MULTI_GAS_DIVING",O[O.GAUGE_DIVING=55]="GAUGE_DIVING",O[O.APNEA_DIVING=56]="APNEA_DIVING",O[O.APNEA_HUNTING=57]="APNEA_HUNTING",O[O.VIRTUAL_ACTIVITY=58]="VIRTUAL_ACTIVITY",O[O.OBSTACLE=59]="OBSTACLE",O[O.BREATHING=62]="BREATHING",O[O.SAIL_RACE=65]="SAIL_RACE",O[O.ULTRA=67]="ULTRA",O[O.INDOOR_CLIMBING=68]="INDOOR_CLIMBING",O[O.BOULDERING=69]="BOULDERING",O[O.HIIT=70]="HIIT",O[O.AMRAP=73]="AMRAP",O[O.EMOM=74]="EMOM",O[O.TABATA=75]="TABATA",O[O.PICKLEBALL=84]="PICKLEBALL",O[O.PADEL=85]="PADEL",O[O.INDOOR_WHEELCHAIR_WALK=86]="INDOOR_WHEELCHAIR_WALK",O[O.INDOOR_WHEELCHAIR_RUN=87]="INDOOR_WHEELCHAIR_RUN",O[O.INDOOR_HAND_CYCLING=88]="INDOOR_HAND_CYCLING",O[O.SQUASH=94]="SQUASH",O[O.BADMINTON=95]="BADMINTON",O[O.RACQUETBALL=96]="RACQUETBALL",O[O.TABLE_TENNIS=97]="TABLE_TENNIS",O[O.FLY_CANOPY=110]="FLY_CANOPY",O[O.FLY_PARAGLIDE=111]="FLY_PARAGLIDE",O[O.FLY_PARAMOTOR=112]="FLY_PARAMOTOR",O[O.FLY_PRESSURIZED=113]="FLY_PRESSURIZED",O[O.FLY_NAVIGATE=114]="FLY_NAVIGATE",O[O.FLY_TIMER=115]="FLY_TIMER",O[O.FLY_ALTIMETER=116]="FLY_ALTIMETER",O[O.FLY_WX=117]="FLY_WX",O[O.FLY_VFR=118]="FLY_VFR",O[O.FLY_IFR=119]="FLY_IFR",O[O.ALL=254]="ALL",O))(A_||{});var WI="development",BI=1,VI=1;function KI(n,_){if(!Number.isFinite(n))throw new Error(`${_} must be a finite number.`)}function T_(n,_){return KI(n,_),Math.abs(n)<=180?Math.round(n*2147483648/180):Math.round(n)}function XI(n){if(!n.name||n.name.trim().length===0)throw new Error("Course name is required.");if(!Array.isArray(n.records)||n.records.length===0)throw new Error("Course must contain at least one record point.");let _=n.records.map((A,T)=>{if(A==null)throw new Error(`Course record #${T+1} is missing.`);if(A.timestamp==null)throw new Error(`Course record #${T+1} is missing timestamp.`);return{...A,positionLat:T_(A.latitude,`records[${T}].latitude`),positionLong:T_(A.longitude,`records[${T}].longitude`)}}),I=(n.coursePoints??[]).map((A,T)=>{if(A==null)throw new Error(`Course point #${T+1} is missing.`);if(A.timestamp==null)throw new Error(`Course point #${T+1} is missing timestamp.`);return{...A,type:A.type??0,positionLat:T_(A.latitude,`coursePoints[${T}].latitude`),positionLong:T_(A.longitude,`coursePoints[${T}].longitude`)}});return{...n,sport:n.sport??2,subSport:n.subSport??0,records:_,coursePoints:I,manufacturer:n.manufacturer??WI,product:n.product??BI,serialNumber:n.serialNumber??VI,timeCreated:n.timeCreated??_[0].timestamp}}function j_(n){let _=XI(n),I=_.records[0],A=_.records[_.records.length-1],T=I.timestamp,R=A.timestamp,L=[{mesgNum:0,data:{type:6,manufacturer:_.manufacturer,product:_.product,serialNumber:_.serialNumber,timeCreated:_.timeCreated}},{mesgNum:31,data:{name:_.name,sport:_.sport,subSport:_.subSport}},{mesgNum:19,data:{startTime:T,timestamp:R,startPositionLat:I.positionLat,startPositionLong:I.positionLong,endPositionLat:A.positionLat,endPositionLong:A.positionLong,totalDistance:A.distance}},{mesgNum:21,data:{timestamp:T,event:0,eventType:0}}];return _.records.forEach(t=>{L.push({mesgNum:20,data:{timestamp:t.timestamp,positionLat:t.positionLat,positionLong:t.positionLong,distance:t.distance,altitude:t.altitude,speed:t.speed}})}),_.coursePoints.forEach((t,E)=>{L.push({mesgNum:32,data:{messageIndex:E,timestamp:t.timestamp,positionLat:t.positionLat,positionLong:t.positionLong,distance:t.distance,type:t.type,name:t.name,favorite:t.favorite}})}),L.push({mesgNum:21,data:{timestamp:R,event:0,eventType:4}}),L}function R_(n){let _=new fI;return j_(n).forEach(A=>{_.onMesg(A.mesgNum,A.data)}),_.close()}var W=class{constructor(){this.version="1.0.0";this.priority=100}supports(_){return this.supportedTags.includes(_)}async initialize(_){_.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(_){_.metadata.delete(`plugin:${this.name}:initialized`)}async validate(_){return!0}parseFloat(_){if(!(typeof _>"u"))return typeof _=="number"?_:typeof _=="string"&&parseFloat(_)||0}parseInt(_){return typeof _=="number"?Math.floor(_):typeof _=="string"&&parseInt(_,10)||0}parseString(_){return String(_||"")}parseBoolean(_){return typeof _=="boolean"?_:typeof _=="string"?_.toLowerCase()==="true":!1}parseDate(_){if(!_)return;let I=new Date(_);return isNaN(I.getTime())?void 0:I}hasRequiredAttributes(_,I){return I.every(A=>{var T;return(T=_.attributes)==null?void 0:T[A]})}extractAttributes(_,I,A){_.attributes&&Object.entries(_.attributes).forEach(([T,R])=>{let L=A[T];L&&L in I&&(I[L]=String(R||""))})}processChildren(_,I,A){var T;(T=_.children)==null||T.forEach(R=>{let L=A[R.tag];L&&L(R,I)})}getChildValue(_,I){var T;let A=(T=_.children)==null?void 0:T.find(R=>R.tag===I);return A!=null&&A.value?String(A.value):void 0}getChildByTag(_,I){var A;return(A=_.children)==null?void 0:A.find(T=>T.tag===I)}getChildrenByTag(_,I){var A;return((A=_.children)==null?void 0:A.filter(T=>T.tag===I))||[]}convertExtensions(_){var A;let I={};return(A=_.children)==null||A.forEach(T=>{I[T.tag]=this.convertExtensionContent(T)}),I}convertExtensionContent(_){var I;if((I=_.children)!=null&&I.length){let A={};return _.children.forEach(T=>{A[T.tag]=this.convertExtensionContent(T)}),A}else return _.value}},w=class{constructor(){this.version="1.0.0";this.description=""}async initialize(_){}async destroy(_){}async validate(_){return!0}async onTokenize(_,I){return _}async onAstGenerate(_,I){return _}async onConvert(_,I){return _}async onComplete(_,I){return _}async onError(_,I){}};var G=class extends W{parseCoordinate(_){let I=this.parseFloat(_);return I===0?void 0:I}parseGPXTime(_){if(!_)return;let I=new Date(_);return isNaN(I.getTime())?void 0:I}extractNumericAttributes(_,I,A){_.attributes&&Object.entries(_.attributes).forEach(([T,R])=>{let L=A[T];L&&L in I&&typeof R<"u"&&(I[L]=this.parseFloat(R))})}},j=class extends w{async onError(_,I){I.warnings.push(`Middleware ${this.name} error: ${_.message}`)}};var L_=class extends G{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(I,A){var R,L;if(!this.hasRequiredAttributes(I,["lat","lon"]))return;let T={lat:this.parseFloat((R=I.attributes)==null?void 0:R.lat),lon:this.parseFloat((L=I.attributes)==null?void 0:L.lon)};return this.processChildren(I,T,{ele:(t,E)=>E.ele=this.parseFloat(t.value),time:(t,E)=>E.time=new Date(this.parseString(t.value)),speed:(t,E)=>E.speed=this.parseFloat(t.value),power:(t,E)=>E.power=this.parseFloat(t.value),cadence:(t,E)=>E.cadence=this.parseFloat(t.value),heartRate:(t,E)=>E.heartRate=this.parseFloat(t.value),course:(t,E)=>E.course=this.parseFloat(t.value),name:(t,E)=>E.name=this.parseString(t.value),cmt:(t,E)=>E.cmt=this.parseString(t.value),desc:(t,E)=>E.desc=this.parseString(t.value),src:(t,E)=>E.src=this.parseString(t.value),sym:(t,E)=>E.sym=this.parseString(t.value),type:(t,E)=>E.type=this.parseString(t.value),fix:(t,E)=>E.fix=this.parseString(t.value),sat:(t,E)=>E.sat=this.parseString(t.value),hdop:(t,E)=>E.hdop=this.parseFloat(t.value),vdop:(t,E)=>E.vdop=this.parseFloat(t.value),pdop:(t,E)=>E.pdop=this.parseFloat(t.value),ageofdgpsdata:(t,E)=>E.ageofdgpsdata=this.parseFloat(t.value),geoidheight:(t,E)=>E.geoidheight=this.parseFloat(t.value),magvar:(t,E)=>E.magvar=this.parseFloat(t.value),dgpsid:(t,E)=>E.dgpsid=this.parseFloat(t.value),extensions:(t,E)=>{let D=A.metadata.get("decoder"),H=D==null?void 0:D.getConverter("extensions");if(H){let C=H.convert(t,A);C&&(this.mapExtensionsToPoint(C,E),E.extensions=C)}},link:(t,E)=>{var C;E.link||(E.link=[]);let D=A.metadata.get("decoder"),H=(C=D==null?void 0:D.getConverter("link"))==null?void 0:C.convert(t,A);H&&E.link&&E.link.push(H)}}),T}mapExtensionsToPoint(I,A){Object.entries(I).forEach(([T,R])=>{if(R!==void 0&&(typeof R=="string"||typeof R=="number")){let L=t=>(Array.isArray(t)?t:[t]).some(D=>{let H=T.toLowerCase(),C=D.toLowerCase();return H===C||H.endsWith(`:${C}`)});L("speed")?A.speed=this.parseFloat(R):L("hr")?A.heartRate=this.parseFloat(R):L(["cad","cadence"])?A.cadence=this.parseFloat(R):L(["PowerInWatts","power"])&&(A.power=this.parseFloat(R))}})}},t_=class extends G{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(I,A){let T={rtept:[]};return this.processChildren(I,T,{name:(R,L)=>L.name=this.parseString(R.value),cmt:(R,L)=>L.cmt=this.parseString(R.value),desc:(R,L)=>L.desc=this.parseString(R.value),src:(R,L)=>L.src=this.parseString(R.value),number:(R,L)=>L.number=this.parseFloat(R.value),type:(R,L)=>L.type=this.parseString(R.value),rtept:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("wpt"))==null?void 0:D.convert(R,A);E&&L.rtept&&L.rtept.push(E)},extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("extensions");E&&(L.extensions=E.convert(R,A))},link:(R,L)=>{var E;L.link||(L.link=[]);let t=A.metadata.get("decoder");(E=R.children)==null||E.forEach(D=>{var C;let H=(C=t==null?void 0:t.getConverter("link"))==null?void 0:C.convert(D,A);H&&L.link&&L.link.push(H)})}}),T}},E_=class extends G{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(I,A){let T={trkseg:[]};return this.processChildren(I,T,{name:(R,L)=>L.name=this.parseString(R.value),cmt:(R,L)=>L.cmt=this.parseString(R.value),desc:(R,L)=>L.desc=this.parseString(R.value),src:(R,L)=>L.src=this.parseString(R.value),number:(R,L)=>L.number=this.parseFloat(R.value),type:(R,L)=>L.type=this.parseString(R.value),trkseg:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("trkseg"))==null?void 0:D.convert(R,A);E&&L.trkseg&&L.trkseg.push(E)},extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("extensions");E&&(L.extensions=E.convert(R,A))},link:(R,L)=>{var E;L.link||(L.link=[]);let t=A.metadata.get("decoder");(E=R.children)==null||E.forEach(D=>{var C;let H=(C=t==null?void 0:t.getConverter("link"))==null?void 0:C.convert(D,A);H&&L.link&&L.link.push(H)})}}),T}},O_=class extends G{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(I,A){let T={trkpt:[]};return this.processChildren(I,T,{trkpt:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("wpt"))==null?void 0:D.convert(R,A);E&&L.trkpt&&L.trkpt.push(E)},extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("extensions");E&&(L.extensions=E.convert(R,A))}}),T}},n_=class extends G{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(I,A){var R;let T={};return(R=I.attributes)!=null&&R.href&&(T.href=I.attributes.href),this.processChildren(I,T,{text:(L,t)=>t.text=this.parseString(L.value),type:(L,t)=>t.type=this.parseString(L.value)}),T}},S_=class extends G{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(I,A){let T={};return this.processChildren(I,T,{name:(R,L)=>L.name=this.parseString(R.value),desc:(R,L)=>L.desc=this.parseString(R.value),keywords:(R,L)=>L.keywords=this.parseString(R.value),time:(R,L)=>L.time=new Date(this.parseString(R.value)),author:(R,L)=>{var E;let t=A.metadata.get("decoder");L.author=(E=t==null?void 0:t.getConverter("author"))==null?void 0:E.convert(R,A)},copyright:(R,L)=>{var E;let t=A.metadata.get("decoder");L.copyright=(E=t==null?void 0:t.getConverter("copyright"))==null?void 0:E.convert(R,A)},bounds:(R,L)=>{var E;let t=A.metadata.get("decoder");L.bounds=(E=t==null?void 0:t.getConverter("bounds"))==null?void 0:E.convert(R,A)},extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("extensions");E&&(L.extensions=E.convert(R,A))},link:(R,L)=>{var D;L.link||(L.link=[]);let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("link"))==null?void 0:D.convert(R,A);E&&L.link&&L.link.push(E)}}),T}},D_=class extends G{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(I,A){var R;let T={};return I.value&&!((R=I.children)!=null&&R.length)?(T.name=this.parseString(I.value),T):(this.processChildren(I,T,{name:(L,t)=>t.name=this.parseString(L.value),email:(L,t)=>{var D;let E=A.metadata.get("decoder");t.email=(D=E==null?void 0:E.getConverter("email"))==null?void 0:D.convert(L,A)},link:(L,t)=>{var D;let E=A.metadata.get("decoder");t.link=(D=E==null?void 0:E.getConverter("link"))==null?void 0:D.convert(L,A)}}),T)}},H_=class extends G{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(I,A){let T={};return this.processChildren(I,T,{id:(R,L)=>L.id=this.parseString(R.value),domain:(R,L)=>L.domain=this.parseString(R.value)}),T}},C_=class extends G{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(I,A){var R;let T={};return(R=I.attributes)!=null&&R.author&&(T.author=I.attributes.author),this.processChildren(I,T,{year:(L,t)=>t.year=this.parseString(L.value),license:(L,t)=>t.license=this.parseString(L.value)}),T}},U_=class extends G{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(I,A){let T={};return this.extractAttributes(I,T,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),T}},G_=class extends G{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(I,A){var R;let T={};return(R=I.children)==null||R.forEach(L=>{this.flattenExtensionElement(L,T)}),T}flattenExtensionElement(I,A){var T,R;if(!((T=I.children)!=null&&T.length)&&I.value!==void 0){A[I.tag]=this.parseExtensionValue(I.value);return}(R=I.children)!=null&&R.length&&I.children.forEach(L=>{this.flattenExtensionElement(L,A)})}parseExtensionValue(I){if(I===void 0)return;let A=String(I),T=parseFloat(A);return!isNaN(T)&&isFinite(T)?T:A}};import{Parser as MI}from"htmlparser2";var B_=(T=>(T.TOKENIZE="tokenize",T.AST_GENERATE="ast_generate",T.CONVERT="convert",T.COMPLETE="complete",T))(B_||{}),F_=class{constructor(){this.stage="tokenize"}async process(_){let I=Date.now();if(!_.xmlContent)throw new Error("XML content cannot be empty");let A=[],T=new MI({onopentag(R,L){A.push({type:"open",tag:R,attributes:L})},ontext(R){let L=R.replace(/\n/g,"").trim();L&&A.push({type:"text",tag:"text",value:L})},onclosetag(R){A.push({type:"close",tag:R})}},{xmlMode:!0});return T.write(_.xmlContent),T.end(),_.tokens=A,_.performance.tokenizeTime=Date.now()-I,_}},o_=class{constructor(){this.stage="ast_generate"}async process(_){var L;let I=Date.now();if(!_.tokens)throw new Error("Tokens cannot be empty");let A=[],T,R=null;for(let t of _.tokens)if(t.type==="open"){let E={tag:t.tag,attributes:t.attributes||{},children:[]};T?R&&((L=R.children)==null||L.push(E)):T=E,A.push(E),R=E}else t.type==="text"&&R?R.value=t.value:t.type==="close"&&(A.pop(),R=A[A.length-1]||null);return _.ast=T,_.performance.astTime=Date.now()-I,_}},f_=class{constructor(_){this.getConverter=_;this.stage="convert"}async process(_){var T;let I=Date.now();if(!_.ast)throw new Error("AST cannot be empty");let A={};return _.ast.attributes&&Object.entries(_.ast.attributes).forEach(([R,L])=>{R.startsWith("xmlns:")?A[R]=L.replace(/&#39;/g,"'"):R==="xsi:schemaLocation"?A[R]=L.replace(/&#39;/g,"'"):A[R]=L}),(T=_.ast.children)==null||T.forEach(R=>{let L=this.getConverter(R.tag);try{let t=L.convert(R,_);t&&this.assignResult(A,R.tag,t)}catch(t){_.errors.push(t)}}),_.result=A,_.performance.convertTime=Date.now()-I,_}assignResult(_,I,A){switch(I){case"metadata":_.metadata=A;break;case"wpt":_.wpt||(_.wpt=[]),_.wpt.push(A);break;case"rte":_.rte||(_.rte=[]),_.rte.push(A);break;case"trk":_.trk||(_.trk=[]),_.trk.push(A);break;case"extensions":_.extensions=A;break}}},W_=class{constructor(){this.stage="complete"}async process(_){_.performance.endTime=Date.now();let I=_.performance.endTime-_.performance.startTime;return _.metadata.set("performance",{totalTime:I,tokenizeTime:_.performance.tokenizeTime,astTime:_.performance.astTime,convertTime:_.performance.convertTime}),_}};var h=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultConvertersRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new F_,new o_,new f_(_=>this.getConverter(_)),new W_]}async registerDefaultConverters(){var I;if(this.defaultConvertersRegistered)return;let _=[new L_,new t_,new E_,new O_,new n_,new S_,new D_,new H_,new C_,new U_,new G_];for(let A of _)(I=A.supportedTags)==null||I.forEach(T=>{this.addConverterForTag(T,A)}),this.registeredPlugins.add(A.name);this.defaultConvertersRegistered=!0}addConverterForTag(_,I){this.converterPlugins.has(_)||this.converterPlugins.set(_,[]);let A=this.converterPlugins.get(_);A.push(I),A.sort((T,R)=>(T.priority||100)-(R.priority||100))}async registerConverter(_){var A,R;if(this.registeredPlugins.has(_.name))throw new Error(`Converter plugin ${_.name} already exists`);(A=_.supportedTags)==null||A.forEach(L=>{this.addConverterForTag(L,_)}),this.registeredPlugins.add(_.name);let I=_.priority!==void 0?` (priority: ${_.priority})`:"";(R=_.supportedTags)==null||R.forEach(L=>{let E=(this.converterPlugins.get(L)||[]).map(D=>`${D.name}(${D.priority||100})`)})}async registerMiddleware(_){let I=this.middlewarePlugins.findIndex(T=>T.name===_.name);I!==-1?this.middlewarePlugins[I]=_:this.middlewarePlugins.push(_);let A=[];_.onTokenize&&A.push("onTokenize"),_.onAstGenerate&&A.push("onAstGenerate"),_.onConvert&&A.push("onConvert"),_.onComplete&&A.push("onComplete"),_.onError&&A.push("onError"),A.length>0}getConverter(_){let I=this.converterPlugins.get(_);return I&&I.length>0?I[0]:void 0}getAllConverters(_){return this.converterPlugins.get(_)||[]}unregisterConverter(_){let I;for(let[A,T]of this.converterPlugins){let R=T.findIndex(L=>L.name===_);R!==-1&&(I=T[R],T.splice(R,1),T.length===0&&this.converterPlugins.delete(A))}I&&this.registeredPlugins.delete(_)}unregisterMiddleware(_){let I=this.middlewarePlugins.findIndex(A=>A.name===_);I!==-1&&this.middlewarePlugins.splice(I,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(_=>_.name)}listProcessors(){return this.processors.map(_=>_.constructor.name)}getConverterDetails(_){let I={};if(_){let A=this.converterPlugins.get(_);A&&(I[_]=A.map(T=>({name:T.name,priority:T.priority||100})))}else for(let[A,T]of this.converterPlugins)I[A]=T.map(R=>({name:R.name,priority:R.priority||100}));return I}getMiddlewareDetails(){return this.middlewarePlugins.map(_=>{let I=[];return _.onTokenize&&I.push("onTokenize"),_.onAstGenerate&&I.push("onAstGenerate"),_.onConvert&&I.push("onConvert"),_.onComplete&&I.push("onComplete"),_.onError&&I.push("onError"),{name:_.name,hooks:I}})}async initialize(){var A;if(this.initialized)return;await this.registerDefaultConverters();let _=this.createContext(),I=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let T of I)try{await((A=T.initialize)==null?void 0:A.call(T,_))}catch{}this.initialized=!0}async destroy(){var A;if(!this.initialized)return;let _=this.createContext(),I=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let T of I)try{await((A=T.destroy)==null?void 0:A.call(T,_))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(_,I,A){var R;let T=I;for(let L of this.middlewarePlugins){let t=L[_];if(t)try{T=await t.call(L,T,A)||T}catch(E){A.errors.push(E),await((R=L.onError)==null?void 0:R.call(L,E,A))}}return T}async parserByBuffer(_){var A;await this.initialize();let I=this.createContext();I.rawData=_,I.xmlContent=_.toString("utf-8"),I.metadata.set("decoder",this);try{for(let T of this.processors)try{switch(I=await T.process(I),T.stage){case"tokenize":I.tokens&&(I.tokens=await this.executeMiddlewareHook("onTokenize",I.tokens,I));break;case"ast_generate":I.ast&&(I.ast=await this.executeMiddlewareHook("onAstGenerate",I.ast,I));break;case"convert":I.result&&(I.result=await this.executeMiddlewareHook("onConvert",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(R){I.errors.push(R);for(let L of this.middlewarePlugins)await((A=L.onError)==null?void 0:A.call(L,R,I))}return I.result}catch(T){throw T}}convertExtensions(_){var L,t;let I={},{attributes:A,tag:T,value:R}=_;if(A&&Object.entries(A).forEach(([E,D])=>{I[E]=D}),(L=_==null?void 0:_.children)!=null&&L.length)(t=_.children)==null||t.forEach(E=>{I[E.tag]=this.convertExtensions(E)});else if(R!==void 0)return R;return I}};import x_ from"dayjs";import gI from"dayjs/plugin/utc.js";var k_={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var Z_={temperature:"Temperature",Depth:"Depth"};x_.extend(gI);var l=class{constructor(_={}){this.formatElevation=_=>{let I=parseFloat(_);return isNaN(I)?_:this.roundTo(I,2).toString()};this.compact=_.compact??!0}async encode(_){let I=this.buildGPXXML(_);return Buffer.from(I,"utf-8")}encodeToString(_){return this.buildGPXXML(_)}buildGPXXML(_){let I=this.buildXMLHeader(),A=this.buildGPXContent(_),R=`${I}${A}
2
- </gpx>`;return this.compact?this.compressXML(R):R}compressXML(_){return _.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(){return['<?xml version="1.0" encoding="UTF-8"?>','<gpx creator="https://gpxonline.net" version="1.1"',' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',' xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'," http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd"," http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd"," http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd",' http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"',' xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"',' xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"',' xmlns:gpxpx="http://www.garmin.com/xmlschemas/PowerExtension/v1"',' xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2"',' xmlns="http://www.topografix.com/GPX/1/1">'].join(`
3
- `)}buildGPXContent(_){let{metadata:I,wpt:A=[],rte:T=[],trk:R=[]}=_,L=[];return I&&L.push(this.buildMetadata(I)),A.forEach(t=>{L.push(this.buildWaypoint(t,"wpt"))}),T.forEach(t=>{L.push(this.buildRoute(t))}),R.forEach(t=>{L.push(this.buildTrack(t))}),L.join(`
1
+ var s=class extends Error{constructor(_,I,t={}){super(I),this.name="TrackSwapError",this.code=_,this.format=t.format,this.cause=t.cause}};function x(n,_,I,t){if(n instanceof s)return n;let A=n instanceof Error?n.message:String(n);return new s(_,`${I}: ${A}`,{format:t,cause:n})}var k=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(_){_.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(_){_.metadata.delete(`plugin:${this.name}:initialized`)}async validate(_){return!0}};var e="trackswap-0.2.0-health-ir-v1",LI=new Set(["timestampCorrelationMesgs","monitoringInfoMesgs","monitoringMesgs","monitoringHrDataMesgs","stressLevelMesgs","respirationRateMesgs","spo2DataMesgs","hrvStatusSummaryMesgs","hrvValueMesgs","sleepLevelMesgs","sleepAssessmentMesgs","napEventMesgs","hsaBodyBatteryDataMesgs","skinTempOvernightMesgs"]),zI=new Set([...LI].filter(n=>n!=="timestampCorrelationMesgs")),jI=new Set(["fileIdMesgs","fileCreatorMesgs","deviceInfoMesgs","deviceSettingsMesgs","softwareMesgs","ohrSettingsMesgs","eventMesgs","activityMesgs","sessionMesgs","lapMesgs","recordMesgs","lengthMesgs","courseMesgs","coursePointMesgs","workoutMesgs","workoutStepMesgs","trainingFileMesgs"]),yI=[{field:"steps",metric:"steps",unit:"count",rolloverModulus:2**32,rolloverBits:32},{field:"distance",metric:"distance_m",unit:"m",rolloverModulus:2**32/100,rolloverBits:32},{field:"activeTime",metric:"active_time_s",unit:"s",rolloverModulus:2**32/1e3,rolloverBits:32},{field:"activeCalories",metric:"active_energy_kcal",unit:"kcal",rolloverModulus:2**16,rolloverBits:16},{field:"calories",metric:"total_energy_kcal",unit:"kcal",rolloverModulus:2**16,rolloverBits:16},{field:"ascent",metric:"ascent_m",unit:"m",rolloverModulus:2**32/1e3,rolloverBits:32},{field:"descent",metric:"descent_m",unit:"m",rolloverModulus:2**32/1e3,rolloverBits:32}];function X(n){return n&&typeof n=="object"?n:{}}function P(n){let _=typeof n=="number"?n:Number(n);return Number.isFinite(_)?_:void 0}function w(n){if(n instanceof Date&&Number.isFinite(n.valueOf()))return n;if(n==null||n==="")return;let _=new Date(n);return Number.isFinite(_.valueOf())?_:void 0}function RI(n){return w(n)?.toISOString().replace(/Z$/,"")}function K(n,_,I){return{messageName:n,messageIndex:_,fieldName:I}}function nI(n,_){return Object.fromEntries(_.map(I=>[I,n[I]]).filter(([,I])=>["number","string","boolean"].includes(typeof I)))}function gI(n){return Object.fromEntries(Object.entries(n).filter(([,_])=>Array.isArray(_)&&_.length>0).map(([_,I])=>[_,I?.length??0]))}function lI(n){let _=[];return((n.activityMesgs?.length??0)>0||(n.sessionMesgs?.length??0)>0)&&_.push("activity"),[...zI].some(I=>(n[I]?.length??0)>0)&&_.push("health"),((n.workoutMesgs?.length??0)>0||(n.workoutStepMesgs?.length??0)>0)&&_.push("workout"),(n.courseMesgs?.length??0)>0&&_.push("course"),_.length===0&&((n.deviceInfoMesgs?.length??0)>0||(n.fileIdMesgs?.length??0)>0)&&_.push("device"),_.length>0?_:["unknown"]}function ZI(n){let _=String(n??"").trim().toLowerCase().replace(/[_\s-]+/g,"");return _.includes("awake")?"awake":_.includes("deep")?"deep":_.includes("light")?"light":_.includes("rem")?"rem":_.includes("unmeasurable")?"unmeasurable":_.includes("sleep")?"sleeping":`vendor:${_||"unknown"}`}function FI(n,_=0){return new Date(n.valueOf()+_*1e3).toISOString().slice(0,10)}function qI(n){return(n.timestampCorrelationMesgs??[]).map(_=>{let I=X(_),t=w(I.timestamp),A=w(I.localTimestamp);return!t||!A?null:{at:t,offsetSeconds:Math.round((A.valueOf()-t.valueOf())/1e3)}}).filter(_=>_!==null).sort((_,I)=>_.at.valueOf()-I.at.valueOf())}function m(n,_){let I;for(let t of n){if(t.at>_)break;I=t.offsetSeconds}return I}function GI(n,_){if(_!==void 0)return new Date(n.valueOf()+_*1e3).toISOString().replace(/Z$/,"")}function uI(n,_,I,t){return _>=n?{value:_-n}:n>=I*.75&&n<I&&_>=0&&_<=I*.25?{value:I-n+_,rolloverBits:t}:null}function iI(n){return n===-100?"off_wrist":n===-200?"motion":n===-300?"invalid":n>=0?"valid":"unknown"}function WI(n,_={},I={}){let t=gI(n),A=Object.fromEntries(Object.entries(t).filter(([H])=>LI.has(H))),T=Object.fromEntries(Object.entries(t).filter(([H])=>!LI.has(H)&&!jI.has(H))),R={sdkProfileVersion:I.sdkProfileVersion,parserVersion:e,messageCounts:t,recognizedMessageCounts:A,unknownMessageCounts:T,invalidValueCounts:{},warnings:[]};_.includeUnknownMessages&&(R.unknownMessages=Object.fromEntries(Object.keys(T).map(H=>[H,n[H]??[]])));let L=[],O=[],D=[],g=[],f=[],W=qI(n),l=H=>{let U=H.offsetSeconds??m(W,H.timestamp);if(H.offsetSeconds=U,H.localTimestamp??=GI(H.timestamp,U),L.push(H),f.push(H.timestamp),H.status!=="valid"){let o=`${H.metric}:${H.status}`;R.invalidValueCounts[o]=(R.invalidValueCounts[o]??0)+1}},M=new Map;(n.monitoringMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp);if(!C){R.warnings.push({code:"GARMIN_HEALTH_NO_TIMESTAMP",message:"Monitoring message has no valid timestamp",source:K("monitoringMesgs",U)});return}f.push(C);let d=P(o.heartRate);d!==void 0&&l({metric:"heart_rate_bpm",timestamp:C,localTimestamp:RI(o.localTimestamp),value:d,unit:"bpm",status:"valid",aggregation:"instant",source:K("monitoringMesgs",U,"heartRate")});let F=P(o.temperature);F!==void 0&&l({metric:"temperature_c",timestamp:C,localTimestamp:RI(o.localTimestamp),value:F,unit:"degC",status:"valid",aggregation:"mean",source:K("monitoringMesgs",U,"temperature")});for(let G of yI){let B=P(o[G.field]);if(B===void 0)continue;let Y=[o.deviceIndex??"device",o.activityType??"activity",G.field].join(":"),p=M.get(Y);if(p&&C>p.timestamp){let Q=uI(p.value,B,G.rolloverModulus,G.rolloverBits);if(Q){Q.rolloverBits&&R.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_ROLLOVER",message:`${G.field} accumulator rolled over at ${Q.rolloverBits} bits`,source:K("monitoringMesgs",U,G.field)});let J=m(W,p.timestamp);O.push({metric:G.metric,startTime:p.timestamp,endTime:C,localStartTime:GI(p.timestamp,J),offsetSeconds:J,value:Q.value,unit:G.unit,status:"valid",activityType:o.activityType===void 0?void 0:String(o.activityType),intensity:o.activityLevel===void 0?void 0:String(o.activityLevel),source:K("monitoringMesgs",U,G.field),attributes:_.health?.retainCumulativeValues===!1?void 0:{rawCumulativeValue:B}})}else R.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_RESET",message:`${G.field} accumulator decreased; a new accumulation window was started`,source:K("monitoringMesgs",U,G.field)})}M.set(Y,{timestamp:C,value:B})}}),(n.monitoringHrDataMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp);if(!C)return;[{field:"currentDayRestingHeartRate",metric:"resting_heart_rate_bpm"},{field:"restingHeartRate",metric:"resting_heart_rate_7_day_bpm"}].forEach(({field:F,metric:G})=>{let B=P(o[F]);B!==void 0&&l({metric:G,timestamp:C,value:B,unit:"bpm",status:"valid",aggregation:"latest",source:K("monitoringHrDataMesgs",U,F)})})}),(n.stressLevelMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.stressLevelTime),d=P(o.stressLevelValue);!C||d===void 0||l({metric:"stress_level",timestamp:C,value:d>=1&&d<=100?d:void 0,unit:"score",status:d>=1&&d<=100?"valid":"invalid",aggregation:"instant",source:K("stressLevelMesgs",U,"stressLevelValue"),attributes:{rawValue:d}})}),(n.respirationRateMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp),d=P(o.respirationRate);if(!C||d===void 0)return;let F=iI(d);l({metric:"respiration_rate_bpm",timestamp:C,value:F==="valid"?d:void 0,unit:"breaths/min",status:F,aggregation:"instant",source:K("respirationRateMesgs",U,"respirationRate"),attributes:F==="valid"?void 0:{rawValue:d}})}),(n.spo2DataMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp),d=P(o.readingSpo2);if(!C||d===void 0)return;let F=P(o.readingConfidence);l({metric:"spo2_percent",timestamp:C,value:d,unit:"percent",status:F!==void 0&&F<=0?"low_confidence":"valid",quality:F,aggregation:"instant",source:K("spo2DataMesgs",U,"readingSpo2"),attributes:{measurementMode:o.mode===void 0?null:String(o.mode)}})}),(n.hrvValueMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp),d=P(o.value);!C||d===void 0||l({metric:"hrv_rmssd_ms",timestamp:C,value:d,unit:"ms",status:"valid",aggregation:"mean",source:K("hrvValueMesgs",U,"value"),attributes:{windowSeconds:300}})}),(n.hrvStatusSummaryMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp);D.push({summaryType:"hrv_status",externalId:`fit:hrv-status:${C?.toISOString()??U}`,startTime:C,metrics:nI(o,["weeklyAverage","lastNightAverage","lastNight5MinHigh","baselineLowUpper","baselineBalancedLower","baselineBalancedUpper","status"]),source:K("hrvStatusSummaryMesgs",U)}),C&&f.push(C)}),(n.monitoringInfoMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp);D.push({summaryType:"device",externalId:`fit:monitoring-info:${C?.toISOString()??U}`,startTime:C,offsetSeconds:C?m(W,C):void 0,metrics:nI(o,["restingMetabolicRate","activityType","cyclesToDistance","cyclesToCalories"]),source:K("monitoringInfoMesgs",U)}),C&&f.push(C)}),(n.skinTempOvernightMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp);if(!C)return;[{field:"averageDeviation",metric:"skin_temperature_deviation_c"},{field:"average7DayDeviation",metric:"skin_temperature_7_day_deviation_c"},{field:"nightlyValue",metric:"skin_temperature_nightly_c"}].forEach(({field:F,metric:G})=>{let B=P(o[F]);B!==void 0&&l({metric:G,timestamp:C,localTimestamp:RI(o.localTimestamp),value:B,unit:"degC",status:"valid",aggregation:"mean",source:K("skinTempOvernightMesgs",U,F)})})});let V=(n.sleepLevelMesgs??[]).map((H,U)=>({message:X(H),messageIndex:U,timestamp:w(X(H).timestamp)})).filter(H=>H.timestamp!==void 0).sort((H,U)=>H.timestamp.valueOf()-U.timestamp.valueOf());if(V.length>=2){let H=X(n.sleepAssessmentMesgs?.[0]),U=[];for(let F=0;F<V.length-1;F+=1){let G=V[F],B=V[F+1];if(B.timestamp<=G.timestamp)continue;let Y={segmentType:ZI(G.message.sleepLevel),startTime:G.timestamp,endTime:B.timestamp,status:"valid",source:K("sleepLevelMesgs",G.messageIndex,"sleepLevel")},p=U.at(-1);p&&p.segmentType===Y.segmentType&&p.endTime.valueOf()===Y.startTime.valueOf()?p.endTime=Y.endTime:U.push(Y)}let o=V[0].timestamp,C=V.at(-1).timestamp;f.push(o,C);let d=m(W,C);g.push({sessionType:"sleep",externalId:`fit:sleep:${o.toISOString()}:${C.toISOString()}`,startTime:o,endTime:C,startOffsetSeconds:m(W,o),endOffsetSeconds:d,calendarDate:FI(C,d),segments:U,metrics:nI(H,["combinedAwakeScore","awakeTimeScore","awakeningsCountScore","deepSleepScore","sleepDurationScore","lightSleepScore","overallSleepScore","sleepQualityScore","sleepRecoveryScore","remSleepScore","sleepRestlessnessScore","awakeningsCount","interruptionsScore","averageStressDuringSleep"]),source:K("sleepLevelMesgs",V[0].messageIndex),attributes:{calendarDateStrategy:d===void 0?"sleep_end_utc_fallback_date":"sleep_end_local_date"}})}else V.length>0&&R.warnings.push({code:"GARMIN_HEALTH_SLEEP_BOUNDARY_INCOMPLETE",message:"Sleep level data does not contain enough boundaries",source:K("sleepLevelMesgs",V[0].messageIndex)});return(n.napEventMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.startTime),d=w(o.endTime),F=o.isDeleted===!0;if(!C||!d||d<C||!F&&d.valueOf()===C.valueOf())return;let G=P(o.startTimezoneOffset),B=P(o.endTimezoneOffset);f.push(C,d),g.push({sessionType:"nap",externalId:`fit:nap:${o.messageIndex??U}:${C.toISOString()}`,startTime:C,endTime:d,startOffsetSeconds:G,endOffsetSeconds:B,calendarDate:FI(d,B??G),deleted:F,segments:[],metrics:{},source:K("napEventMesgs",U),attributes:{source:o.source===void 0?null:String(o.source),feedback:o.feedback===void 0?null:String(o.feedback),updateTimestamp:w(o.updateTimestamp)?.toISOString()??null}})}),(n.hsaBodyBatteryDataMesgs??[]).forEach((H,U)=>{let o=X(H),C=w(o.timestamp),d=P(o.processingInterval)??0;if(!C||d<=0)return;[{field:"level",metric:"body_battery_level",unit:"score"},{field:"charged",metric:"body_battery_charged",unit:"score"},{field:"uncharged",metric:"body_battery_drained",unit:"score"}].forEach(({field:G,metric:B,unit:Y})=>{(Array.isArray(o[G])?o[G]:[]).forEach((Q,J)=>{let Z=P(Q);Z!==void 0&&l({metric:B,timestamp:new Date(C.valueOf()+d*J*1e3),value:Z===-16?void 0:Z,unit:Y,status:Z===-16?"invalid":"valid",aggregation:"instant",source:K("hsaBodyBatteryDataMesgs",U,G),attributes:{sequenceIndex:J,intervalSeconds:d}})})})}),L.sort((H,U)=>H.timestamp.valueOf()-U.timestamp.valueOf()),O.sort((H,U)=>H.startTime.valueOf()-U.startTime.valueOf()),g.sort((H,U)=>H.startTime.valueOf()-U.startTime.valueOf()),f.sort((H,U)=>H.valueOf()-U.valueOf()),{schemaVersion:"1",observedStart:f[0],observedEnd:f.at(-1),timezone:{strategy:W.length>0?"timestamp_correlation":"unknown",offsets:W},points:L,intervals:_.health?.reconstructIntervals===!1?[]:O,summaries:D,sessions:g,diagnostics:R}}var a=class extends k{constructor(){super(...arguments);this.name="HealthStructurePlugin";this.priority=20}structureData(I,t){let A=t.userData?.fitDocumentOptions??{},T=lI(I);return{healthDocument:T.includes("health")?WI(I,A,{sdkProfileVersion:t.metadata.get("fit-sdk-profile-version")}):void 0,fitDocumentMetadata:{detectedKinds:T,messageCounts:gI(I)}}}};var __=(S=>(S[S.GENERIC=0]="GENERIC",S[S.RUNNING=1]="RUNNING",S[S.CYCLING=2]="CYCLING",S[S.TRANSITION=3]="TRANSITION",S[S.FITNESS_EQUIPMENT=4]="FITNESS_EQUIPMENT",S[S.SWIMMING=5]="SWIMMING",S[S.BASKETBALL=6]="BASKETBALL",S[S.SOCCER=7]="SOCCER",S[S.TENNIS=8]="TENNIS",S[S.AMERICAN_FOOTBALL=9]="AMERICAN_FOOTBALL",S[S.TRAINING=10]="TRAINING",S[S.WALKING=11]="WALKING",S[S.CROSS_COUNTRY_SKIING=12]="CROSS_COUNTRY_SKIING",S[S.ALPINE_SKIING=13]="ALPINE_SKIING",S[S.SNOWBOARDING=14]="SNOWBOARDING",S[S.ROWING=15]="ROWING",S[S.MOUNTAINEERING=16]="MOUNTAINEERING",S[S.HIKING=17]="HIKING",S[S.MULTISPORT=18]="MULTISPORT",S[S.PADDLING=19]="PADDLING",S[S.FLYING=20]="FLYING",S[S.E_BIKING=21]="E_BIKING",S[S.MOTORCYCLING=22]="MOTORCYCLING",S[S.BOATING=23]="BOATING",S[S.DRIVING=24]="DRIVING",S[S.GOLF=25]="GOLF",S[S.HANG_GLIDING=26]="HANG_GLIDING",S[S.HORSEBACK_RIDING=27]="HORSEBACK_RIDING",S[S.HUNTING=28]="HUNTING",S[S.FISHING=29]="FISHING",S[S.INLINE_SKATING=30]="INLINE_SKATING",S[S.ROCK_CLIMBING=31]="ROCK_CLIMBING",S[S.SAILING=32]="SAILING",S[S.ICE_SKATING=33]="ICE_SKATING",S[S.SKY_DIVING=34]="SKY_DIVING",S[S.SNOWSHOEING=35]="SNOWSHOEING",S[S.SNOWMOBILING=36]="SNOWMOBILING",S[S.STAND_UP_PADDLEBOARDING=37]="STAND_UP_PADDLEBOARDING",S[S.SURFING=38]="SURFING",S[S.WAKEBOARDING=39]="WAKEBOARDING",S[S.WATER_SKIING=40]="WATER_SKIING",S[S.KAYAKING=41]="KAYAKING",S[S.RAFTING=42]="RAFTING",S[S.WINDSURFING=43]="WINDSURFING",S[S.KITESURFING=44]="KITESURFING",S[S.TACTICAL=45]="TACTICAL",S[S.JUMPMASTER=46]="JUMPMASTER",S[S.BOXING=47]="BOXING",S[S.FLOOR_CLIMBING=48]="FLOOR_CLIMBING",S[S.BASEBALL=49]="BASEBALL",S[S.DIVING=53]="DIVING",S[S.HIIT=62]="HIIT",S[S.RACKET=64]="RACKET",S[S.WHEELCHAIR_PUSH_WALK=65]="WHEELCHAIR_PUSH_WALK",S[S.WHEELCHAIR_PUSH_RUN=66]="WHEELCHAIR_PUSH_RUN",S[S.MEDITATION=67]="MEDITATION",S[S.DISC_GOLF=69]="DISC_GOLF",S[S.CRICKET=71]="CRICKET",S[S.RUGBY=72]="RUGBY",S[S.HOCKEY=73]="HOCKEY",S[S.LACROSSE=74]="LACROSSE",S[S.VOLLEYBALL=75]="VOLLEYBALL",S[S.WATER_TUBING=76]="WATER_TUBING",S[S.WAKESURFING=77]="WAKESURFING",S[S.MIXED_MARTIAL_ARTS=80]="MIXED_MARTIAL_ARTS",S[S.SNORKELING=82]="SNORKELING",S[S.DANCE=83]="DANCE",S[S.JUMP_ROPE=84]="JUMP_ROPE",S[S.ALL=254]="ALL",S))(__||{});var I_=(E=>(E[E.GENERIC=0]="GENERIC",E[E.TREADMILL=1]="TREADMILL",E[E.STREET=2]="STREET",E[E.TRAIL=3]="TRAIL",E[E.TRACK=4]="TRACK",E[E.SPIN=5]="SPIN",E[E.INDOOR_CYCLING=6]="INDOOR_CYCLING",E[E.ROAD=7]="ROAD",E[E.MOUNTAIN=8]="MOUNTAIN",E[E.DOWNHILL=9]="DOWNHILL",E[E.RECUMBENT=10]="RECUMBENT",E[E.CYCLOCROSS=11]="CYCLOCROSS",E[E.HAND_CYCLING=12]="HAND_CYCLING",E[E.TRACK_CYCLING=13]="TRACK_CYCLING",E[E.INDOOR_ROWING=14]="INDOOR_ROWING",E[E.ELLIPTICAL=15]="ELLIPTICAL",E[E.STAIR_CLIMBING=16]="STAIR_CLIMBING",E[E.LAP_SWIMMING=17]="LAP_SWIMMING",E[E.OPEN_WATER=18]="OPEN_WATER",E[E.FLEXIBILITY_TRAINING=19]="FLEXIBILITY_TRAINING",E[E.STRENGTH_TRAINING=20]="STRENGTH_TRAINING",E[E.WARM_UP=21]="WARM_UP",E[E.MATCH=22]="MATCH",E[E.EXERCISE=23]="EXERCISE",E[E.CHALLENGE=24]="CHALLENGE",E[E.INDOOR_SKIING=25]="INDOOR_SKIING",E[E.CARDIO_TRAINING=26]="CARDIO_TRAINING",E[E.INDOOR_WALKING=27]="INDOOR_WALKING",E[E.E_BIKE_FITNESS=28]="E_BIKE_FITNESS",E[E.BMX=29]="BMX",E[E.CASUAL_WALKING=30]="CASUAL_WALKING",E[E.SPEED_WALKING=31]="SPEED_WALKING",E[E.BIKE_TO_RUN_TRANSITION=32]="BIKE_TO_RUN_TRANSITION",E[E.RUN_TO_BIKE_TRANSITION=33]="RUN_TO_BIKE_TRANSITION",E[E.SWIM_TO_BIKE_TRANSITION=34]="SWIM_TO_BIKE_TRANSITION",E[E.ATV=35]="ATV",E[E.MOTOCROSS=36]="MOTOCROSS",E[E.BACKCOUNTRY=37]="BACKCOUNTRY",E[E.RESORT=38]="RESORT",E[E.RC_DRONE=39]="RC_DRONE",E[E.WINGSUIT=40]="WINGSUIT",E[E.WHITEWATER=41]="WHITEWATER",E[E.SKATE_SKIING=42]="SKATE_SKIING",E[E.YOGA=43]="YOGA",E[E.PILATES=44]="PILATES",E[E.INDOOR_RUNNING=45]="INDOOR_RUNNING",E[E.GRAVEL_CYCLING=46]="GRAVEL_CYCLING",E[E.E_BIKE_MOUNTAIN=47]="E_BIKE_MOUNTAIN",E[E.COMMUTING=48]="COMMUTING",E[E.MIXED_SURFACE=49]="MIXED_SURFACE",E[E.NAVIGATE=50]="NAVIGATE",E[E.TRACK_ME=51]="TRACK_ME",E[E.MAP=52]="MAP",E[E.SINGLE_GAS_DIVING=53]="SINGLE_GAS_DIVING",E[E.MULTI_GAS_DIVING=54]="MULTI_GAS_DIVING",E[E.GAUGE_DIVING=55]="GAUGE_DIVING",E[E.APNEA_DIVING=56]="APNEA_DIVING",E[E.APNEA_HUNTING=57]="APNEA_HUNTING",E[E.VIRTUAL_ACTIVITY=58]="VIRTUAL_ACTIVITY",E[E.OBSTACLE=59]="OBSTACLE",E[E.BREATHING=62]="BREATHING",E[E.SAIL_RACE=65]="SAIL_RACE",E[E.ULTRA=67]="ULTRA",E[E.INDOOR_CLIMBING=68]="INDOOR_CLIMBING",E[E.BOULDERING=69]="BOULDERING",E[E.HIIT=70]="HIIT",E[E.AMRAP=73]="AMRAP",E[E.EMOM=74]="EMOM",E[E.TABATA=75]="TABATA",E[E.PICKLEBALL=84]="PICKLEBALL",E[E.PADEL=85]="PADEL",E[E.INDOOR_WHEELCHAIR_WALK=86]="INDOOR_WHEELCHAIR_WALK",E[E.INDOOR_WHEELCHAIR_RUN=87]="INDOOR_WHEELCHAIR_RUN",E[E.INDOOR_HAND_CYCLING=88]="INDOOR_HAND_CYCLING",E[E.SQUASH=94]="SQUASH",E[E.BADMINTON=95]="BADMINTON",E[E.RACQUETBALL=96]="RACQUETBALL",E[E.TABLE_TENNIS=97]="TABLE_TENNIS",E[E.FLY_CANOPY=110]="FLY_CANOPY",E[E.FLY_PARAGLIDE=111]="FLY_PARAGLIDE",E[E.FLY_PARAMOTOR=112]="FLY_PARAMOTOR",E[E.FLY_PRESSURIZED=113]="FLY_PRESSURIZED",E[E.FLY_NAVIGATE=114]="FLY_NAVIGATE",E[E.FLY_TIMER=115]="FLY_TIMER",E[E.FLY_ALTIMETER=116]="FLY_ALTIMETER",E[E.FLY_WX=117]="FLY_WX",E[E.FLY_VFR=118]="FLY_VFR",E[E.FLY_IFR=119]="FLY_IFR",E[E.ALL=254]="ALL",E))(I_||{});function BI(n,_){if(!_)return;let I=_.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();for(let t of Object.keys(n)){if(!Number.isNaN(Number(t))||t.toUpperCase()!==I)continue;let A=n[t];return typeof A=="number"?A:void 0}}function rI(n){let _=n.metadata?.fileName?.trim();if(_)return _;let I=n.metadata?.originType;return I?`${I.toLowerCase()}-course`:"course"}function MI(n){let _=n.activities?.[0],t=[...(n.activities?.flatMap(A=>A.laps??[])??[]).flatMap(A=>A.records??[]),...n.routes?.flatMap(A=>A.records??[])??[],...n.points??[]].filter(A=>A.timestamp!=null&&A.positionLat!=null&&A.positionLong!=null).sort((A,T)=>new Date(A.timestamp).getTime()-new Date(T.timestamp).getTime()).map(A=>({timestamp:A.timestamp,latitude:A.positionLat,longitude:A.positionLong,distance:A.distance,altitude:A.enhancedAltitude??A.altitude,speed:A.enhancedSpeed??A.speed}));if(t.length===0)throw new Error("Cannot build a FIT course without timestamped coordinates");return{name:rI(n),sport:BI(__,_?.sport)??2,subSport:BI(I_,_?.subSport)??0,records:t,timeCreated:t[0].timestamp}}function VI(){return process.env.TRACKSWAP_FIT_DEBUG==="1"||process.env.TRACKSWAP_DEBUG==="1"}function h(...n){VI()}function u(...n){VI()}var t_=class{constructor(){this.stage="parse"}async process(_){let I=Date.now();if(!_.rawData)throw new Error("FIT data cannot be empty");try{let t=await this.parseWithFitSDK(_.rawData,_);return _.rawMessages=t,h("\u{1F389} FIT parsing raw messages:",t),_.performance.parseTime=Date.now()-I,h(`\u{1F527} FIT parsing completed, contains message types: ${Object.keys(t).join(", ")}`),_}catch(t){throw new Error(`FIT parsing failed: ${t.message}`)}}async parseWithFitSDK(_,I){let{Decoder:t,Profile:A,Stream:T}=await import("@garmin/fitsdk"),R=[A.version?.major,A.version?.minor,A.version?.patch].filter(f=>f!==void 0);R.length>0&&I.metadata.set("fit-sdk-profile-version",R.join("."));let L=T.fromBuffer(_);if(!t.isFIT(L))throw new Error("Not a valid FIT file");let O=new t(L),{messages:D,errors:g}=O.read();return g&&g.length>0&&u("FIT parsing warnings:",g),D}};function mI(n){let _={...n};return _.position_lat!=null&&_.positionLat==null&&(_.positionLat=_.position_lat),_.position_long!=null&&_.positionLong==null&&(_.positionLong=_.position_long),_}var A_=class{constructor(_){this.getConverters=_;this.stage="extract"}async process(_){let I=Date.now();if(!_.rawMessages)throw new Error("Raw messages cannot be empty");let t={};for(let[A,T]of Object.entries(_.rawMessages)){if(!Array.isArray(T)||T.length===0){t[A]=T;continue}let R=this.getConverters(A);if(R.length===0)t[A]=A==="recordMesgs"?T.map(L=>mI(L)):T,h(`\u{1F4CB} Message type "${A}" has no converter, using raw data`);else{let L=R[0];try{let O=L.convertMessages(T,_);t[A]=O,h(`\u2705 Message type "${A}" using converter ${L.name}`)}catch(O){_.errors.push(O),t[A]=T,u(`FIT converter "${L.name}" failed for ${A}; raw messages were retained`,O)}}}return _.rawMessages=t,_.performance.extractTime=Date.now()-I,_}},T_=class{constructor(_){this.getStructurePlugins=_;this.stage="structure"}async process(_){let I=Date.now();if(!_.rawMessages)throw new Error("Message data cannot be empty");let t={},A=this.getStructurePlugins();for(let T of A)try{let R=T.structureData(_.rawMessages,_);t={...t,...R},h(`\u{1F527} Structure plugin ${T.name} processing completed`)}catch(R){throw _.errors.push(R),new Error(`FIT structure plugin "${T.name}" failed: ${R.message}`)}return _.result=t,_.performance.structureTime=Date.now()-I,_}},R_=class{constructor(){this.stage="complete"}async process(_){_.performance.endTime=Date.now();let I=_.performance.endTime-_.performance.startTime;return _.metadata.set("performance",{totalTime:I,parseTime:_.performance.parseTime,extractTime:_.performance.extractTime,structureTime:_.performance.structureTime}),_.stats&&(_.stats.endTime=Date.now(),_.rawMessages&&(_.stats.processedTokens=this.countTotalMessages(_.rawMessages))),h(`\u2705 FIT processing completed, total time: ${I}ms`),_}countTotalMessages(_){let I=0;return Object.values(_).forEach(t=>{Array.isArray(t)&&(I+=t.length)}),I}};import b from"dayjs";var n_=class extends k{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(I,t){let{sessionMesgs:A,lapMesgs:T,recordMesgs:R,lengthMesgs:L}=I;if(!A?.length)return u("No structured session found, data structure is incomplete"),{};let O=A.map(f=>{let W=b(f.startTime).valueOf(),l=W+(f.totalElapsedTime??0)*1e3,M=b(f.timestamp).valueOf(),V=Math.max(Number.isFinite(l)?l:Number.NEGATIVE_INFINITY,Number.isFinite(M)?M:Number.NEGATIVE_INFINITY),H=f.firstLapIndex,U=f.numLaps,o=typeof H=="number"&&typeof U=="number"?(T??[]).filter(F=>{let G=F.messageIndex;return typeof G=="number"&&G>=H&&G<H+U}):[],C=(o.length>0?o:(T??[]).filter(F=>{let G=b(F.startTime).valueOf();return Number.isFinite(G)&&G>=W&&G<=V+2e3})).sort((F,G)=>b(F.startTime).valueOf()-b(G.startTime).valueOf()),d=C.map((F,G)=>{let B=b(F.startTime).valueOf(),Y=b(C[G+1]?.startTime).valueOf(),p=B+(F.totalElapsedTime??0)*1e3,Q=Number.isFinite(Y)&&Y>B,J=Q?Y:Math.max(p,V),Z=R?.filter(TI=>{let q=b(TI.timestamp).valueOf();return q>=B&&(Q?q<J:q<=J)})||[],AI=F.firstLengthIndex??void 0,fI=F.numLengths??void 0,dI=[];if(AI!==void 0&&fI!==void 0){let TI=AI+fI;dI=L?.filter(q=>q.messageIndex>=AI&&q.messageIndex<TI)||[]}return{...F,recordMesgs:Z,lengthMesgs:dI,messageIndex:F.messageIndex!==void 0?F.messageIndex:0}});return{...f,lapMesgs:d,messageIndex:f.messageIndex!==void 0?f.messageIndex:0}}),D=new Set;for(let f of O)for(let W of f.lapMesgs??[])for(let l of W.recordMesgs??[])l?.timestamp!=null&&D.add(b(l.timestamp).valueOf());let g=0;for(let f of R??[]){if(f?.timestamp==null)continue;let W=b(f.timestamp).valueOf();D.has(W)||g++}return g>0&&(t.metadata.set("fit-unassigned-record-count",g),u(`SessionStructurePlugin: ${g} record(s) did not fall into any lap time window`)),{sessionMesgs:O}}},L_=class extends k{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(I,t){let{courseMesgs:A,lapMesgs:T,recordMesgs:R}=I;if(!A?.length)return{};let L=2e3;return{courseMesgs:A.map(D=>{let g=T?.map(f=>{let W=b(f.startTime).valueOf(),l=b(f.timestamp).valueOf(),M=R?.filter(V=>{let H=b(V.timestamp).valueOf();return H>=W-L&&H<=l+L})||[];return{...f,recordMesgs:M}})||[];return{...D,lapMesgs:g}})}}},E_=class extends k{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(I,t){let{fileIdMesgs:A,fileCreatorMesgs:T,deviceInfoMesgs:R}=I;if(A?.length&&A[0]){let L=A[0];t.fileHeader={type:L.type,manufacturer:L.manufacturer,product:L.product}}return{fileIdMesgs:A,fileCreatorMesgs:T,deviceInfoMesgs:R}}};var O_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.structurePlugins=[];this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultPluginsRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new t_,new A_(_=>this.getConverters(_)),new T_(()=>this.structurePlugins),new R_],h("\u{1F527} FIT core pipeline processors initialized (fixed and not modifiable)")}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let _=[new E_,new n_,new L_,new a];for(let I of _)this.addStructurePlugin(I),this.registeredPlugins.add(I.name);this.defaultPluginsRegistered=!0,h("\u2705 Default FIT structure plugins auto-registered (FileHeader, Session, Course, etc.)")}addConverterForMessageType(_,I){this.converterPlugins.has(_)||this.converterPlugins.set(_,[]);let t=this.converterPlugins.get(_);t.push(I),t.sort((A,T)=>(A.priority||100)-(T.priority||100))}addStructurePlugin(_){this.structurePlugins.push(_),this.structurePlugins.sort((I,t)=>(I.priority||100)-(t.priority||100))}async registerMessageConverter(_){if(this.registeredPlugins.has(_.name))throw new Error(`Message converter plugin ${_.name} already exists`);_.supportedMessageTypes.forEach(t=>{this.addConverterForMessageType(t,_)}),this.registeredPlugins.add(_.name);let I=_.priority!==void 0?` (priority: ${_.priority})`:"";h(`\u{1F4E6} Registered FIT message converter: ${_.name}${I}, supported message types: ${_.supportedMessageTypes.join(", ")}`),_.supportedMessageTypes.forEach(t=>{let T=(this.converterPlugins.get(t)||[]).map(R=>`${R.name}(${R.priority||100})`);h(` \u{1F4CB} Message type "${t}" converter priority: ${T.join(" > ")}`)})}async registerStructurePlugin(_){if(this.registeredPlugins.has(_.name))throw new Error(`Structure plugin ${_.name} already exists`);this.addStructurePlugin(_),this.registeredPlugins.add(_.name);let I=_.priority!==void 0?` (priority: ${_.priority})`:"";h(`\u{1F3D7}\uFE0F Registered FIT structure plugin: ${_.name}${I}`)}async registerMiddleware(_){let I=this.middlewarePlugins.findIndex(A=>A.name===_.name);I!==-1?(this.middlewarePlugins[I]=_,h(`\u{1F504} Updated FIT middleware: ${_.name}`)):(this.middlewarePlugins.push(_),this.middlewarePlugins.sort((A,T)=>(A.priority||100)-(T.priority||100)),h(`\u{1F50C} Registered FIT middleware: ${_.name}`));let t=[];_.onParse&&t.push("onParse"),_.onExtractMessages&&t.push("onExtractMessages"),_.onStructure&&t.push("onStructure"),_.onComplete&&t.push("onComplete"),_.onError&&t.push("onError"),t.length>0&&h(` \u{1F3A3} Supported hooks: ${t.join(", ")}`)}getConverter(_){let I=this.converterPlugins.get(_);return I&&I.length>0?I[0]:void 0}getConverters(_){return this.converterPlugins.get(_)||[]}unregisterPlugin(_){if(!this.registeredPlugins.has(_))return!1;for(let[A,T]of this.converterPlugins){let R=T.findIndex(L=>L.name===_);R!==-1&&(T.splice(R,1),T.length===0&&this.converterPlugins.delete(A))}let I=this.structurePlugins.findIndex(A=>A.name===_);I!==-1&&this.structurePlugins.splice(I,1);let t=this.middlewarePlugins.findIndex(A=>A.name===_);return t!==-1&&this.middlewarePlugins.splice(t,1),this.registeredPlugins.delete(_),h(`\u{1F5D1}\uFE0F Removed FIT plugin: ${_}`),!0}async initialize(){if(this.initialized)return;await this.registerDefaultPlugins();let _=this.createContext(),I=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(t=>[t.name,t])).values()];for(let t of I)await t.initialize?.(_);this.initialized=!0}async destroy(){if(!this.initialized)return;let _=this.createContext(),I=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(t=>[t.name,t])).values()];for(let t of I)await t.destroy?.(_);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(_,I,t){let A=I;for(let T of this.middlewarePlugins){let R=T[_];if(R)try{A=await R.call(T,A,t)||A}catch(L){t.errors.push(L),await T.onError?.(L,t)}}return A}async parseByBuffer(_,I={}){await this.initialize();let t=this.createContext();t.rawData=_,t.userData=I.userData,t.metadata.set("decoder",this);try{for(let A of this.processors)try{switch(A.stage==="parse"&&t.rawData&&(t.rawData=await this.executeMiddlewareHook("onParse",t.rawData,t)),t=await A.process(t),A.stage){case"parse":break;case"extract":t.rawMessages&&(t.rawMessages=await this.executeMiddlewareHook("onExtractMessages",t.rawMessages,t));break;case"structure":t.result&&(t.result=await this.executeMiddlewareHook("onStructure",t.result,t));break;case"complete":t.result&&(t.result=await this.executeMiddlewareHook("onComplete",t.result,t));break}}catch(T){t.errors.push(T);for(let R of this.middlewarePlugins)await R.onError?.(T,t);throw new Error(`FIT pipeline stage "${A.stage}" failed: ${T.message}`)}return h("\u{1F389} FIT parsing completed",t.result),t.result}catch(A){throw A}}};var cI={file:{course:6,device:1,settings:2,sport:3,activity:4,workout:5,schedules:7,weight:9,totals:10,goals:11,blood_pressure:14,monitoring_a:15,activity_summary:20,monitoring_daily:28,monitoring_b:32,segment_list:35,exd_configuration:40,invalid:0},sport:{generic:0,running:1,cycling:2,transition:3,fitness_equipment:4,swimming:5,basketball:6,soccer:7,tennis:8,american_football:9,training:10,walking:11,cross_country_skiing:12,alpine_skiing:13,snowboarding:14,rowing:15,mountaineering:16,hiking:17,multisport:18,paddling:19,invalid:254},event:{timer:0,workout:3,workout_step:4,power_down:5,power_up:6,off_course:7,session:8,lap:9,course_point:10,battery:11,virtual_partner_pace:12,hr_high_alert:13,hr_low_alert:14,speed_high_alert:15,speed_low_alert:16,cad_high_alert:17,cad_low_alert:18,power_high_alert:19,power_low_alert:20,recovery_hr:21,battery_low:22,time_duration_alert:23,distance_duration_alert:24,calorie_duration_alert:25,activity:26,fitness_equipment:27,length:28,user_marker:32,sport_point:33,calibration:36,front_gear_change:42,rear_gear_change:43,rider_position_change:44,elev_high_alert:45,elev_low_alert:46,comm_timeout:47,invalid:255},event_type:{start:0,stop:1,consecutive_depreciated:2,marker:3,stop_all:4,begin_depreciated:5,end_depreciated:6,end_all_depreciated:7,stop_disable:8,stop_disable_all:9,invalid:255},course_point:{generic:0,summit:1,valley:2,water:3,food:4,danger:5,left:6,right:7,straight:8,first_aid:9,fourth_category:10,third_category:11,second_category:12,first_category:13,hors_category:14,sprint:15,left_fork:16,right_fork:17,middle_fork:18,slight_left:19,sharp_left:20,slight_right:21,sharp_right:22,u_turn:23,segment_start:24,segment_end:25,invalid:255}},y=n=>{let _=cI[n];return{size:1,baseType:0,mapValue:I=>typeof I=="string"?_[I]??255:I,setValue:function(I,t){this.setUint8(I,t)}}},EI={enum_file:y("file"),enum_activity:y("sport"),enum_sport:y("sport"),enum_sub_sport:y("sport"),enum_event:y("event"),enum_event_type:y("event_type"),enum_course_point:y("course_point"),uint8:{size:1,baseType:2,setValue:DataView.prototype.setUint8},sint8:{size:1,baseType:1,setValue:DataView.prototype.setInt8},uint16:{size:2,baseType:132,setValue:DataView.prototype.setUint16},sint16:{size:2,baseType:131,setValue:DataView.prototype.setInt16},uint32:{size:4,baseType:134,setValue:DataView.prototype.setUint32},sint32:{size:4,baseType:133,setValue:DataView.prototype.setInt32},string:{size:0,baseType:7,mapValue:n=>Array.from(hI(n)),setValue:aI},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:n=>Math.round(n*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:n=>Math.round(n*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:n=>Math.round((n+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:n=>Math.round(n*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:n=>{let _;return n instanceof Date?(_=Math.floor(n.getTime()/1e3),_-631065600):typeof n=="string"?(_=Math.floor(new Date(n).getTime()/1e3),_-631065600):n<631065600?Math.floor(n):(n>9999999999?_=Math.floor(n/1e3):_=Math.floor(n),_-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:n=>Math.round(n/180*2147483648)}};function KI(n){return Array.from(hI(n)).length+1}function*hI(n){for(let _ of xI(n))_<128?yield _:_<2048?(yield 192|_>>6,yield 128|_&63):_<65536?(yield 224|_>>12,yield 128|_>>6&63,yield 128|_&63):(yield 240|_>>18,yield 128|_>>12&63,yield 128|_>>6&63,yield 128|_&63);yield 0}function*xI(n){for(let _=0;_<n.length;){let I=n.codePointAt(_);if(I===void 0)break;yield I,_+=I>65535?2:1}}function aI(n,_){for(let I=0;I<_.length;I++)this.setUint8(n+I,_[I])}var _t={file_id:{mesgNum:0,fieldDefns:[{name:"type",number:0,type:"enum_file"},{name:"time_created",number:4,type:"date_time"}]},session:{mesgNum:18,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"},{name:"sport",number:5,type:"enum_sport"},{name:"sub_sport",number:6,type:"enum_sub_sport"},{name:"first_lap_index",number:11,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"start_time",number:2,type:"date_time"},{name:"start_position_lat",number:3,type:"semicircles"},{name:"start_position_long",number:4,type:"semicircles"},{name:"end_position_lat",number:5,type:"semicircles"},{name:"end_position_long",number:6,type:"semicircles"},{name:"total_elapsed_time",number:7,type:"seconds"},{name:"total_timer_time",number:8,type:"seconds"},{name:"total_distance",number:9,type:"distance"},{name:"total_ascent",number:21,type:"uint16"},{name:"total_descent",number:22,type:"uint16"}]},record:{mesgNum:20,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"position_lat",number:0,type:"semicircles"},{name:"position_long",number:1,type:"semicircles"},{name:"altitude",number:2,type:"altitude"},{name:"distance",number:5,type:"distance"},{name:"heart_rate",number:3,type:"uint8"},{name:"cadence",number:4,type:"uint8"},{name:"speed",number:6,type:"speed"},{name:"power",number:7,type:"uint16"}]},event:{mesgNum:21,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"event",number:0,type:"enum_event"},{name:"event_type",number:1,type:"enum_event_type"},{name:"event_group",number:4,type:"uint8"}]},course:{mesgNum:31,fieldDefns:[{name:"name",number:5,type:"string"},{name:"sport",number:4,type:"enum_sport"},{name:"sub_sport",number:7,type:"enum_sub_sport"}]},activity:{mesgNum:34,fieldDefns:[{name:"timestamp",number:253,type:"date_time"},{name:"total_timer_time",number:0,type:"seconds"},{name:"num_sessions",number:1,type:"uint16"},{name:"type",number:2,type:"enum_activity"},{name:"event",number:3,type:"enum_event"},{name:"event_type",number:4,type:"enum_event_type"},{name:"local_timestamp",number:5,type:"date_time"},{name:"event_group",number:6,type:"uint8"}]},course_point:{mesgNum:32,fieldDefns:[{name:"timestamp",number:1,type:"date_time"},{name:"position_lat",number:2,type:"semicircles"},{name:"position_long",number:3,type:"semicircles"},{name:"distance",number:4,type:"distance"},{name:"type",number:5,type:"enum_course_point"}]}},It=(n,_)=>n.map(I=>({...I,value:_[I.name]})).filter(({value:I})=>I!==void 0),S_=class n{static check(_,I,t,A){if(I===void 0)throw new Error(`Message '${_}' not known`);if(t===void 0)throw new Error(`Message '${_}' has no field definitions`);let T=t.map(L=>L.name),R=Object.keys(A).filter(L=>!T.includes(L));if(R.length)throw new Error(`Message '${_}' has no field definitions named '${R}'`)}constructor(_,I,t){let A=_t[I];if(!A)throw new Error(`Unknown message type: ${I}`);let{mesgNum:T,fieldDefns:R}=A;n.check(I,T,R,t),this.localNum=_,this.mesgNum=T,this.fields=It(R,t)}get mesgDefn(){let _=this.fields.map(({number:I,type:t,value:A})=>{let T=EI[t];if(!T)throw new Error(`Unknown type: ${t}`);let{size:R,baseType:L}=T;return t==="string"?{number:I,size:KI(A),baseType:L}:{number:I,size:R,baseType:L}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:_}}isSameDefn(_){let I=(L,O)=>L.number===O.number&&L.size===O.size&&L.baseType===O.baseType,t=(L,O)=>L.length===O.length&&L.every((D,g)=>I(D,O[g])),{localNum:A,mesgNum:T,fieldDefns:R}=this.mesgDefn;return T===_.mesgNum&&A===_.localNum&&t(R,_.fieldDefns)}get defnRecord(){let{localNum:_,mesgNum:I,fieldDefns:t}=this.mesgDefn,A=6+3*t.length,T=new DataView(new ArrayBuffer(A));T.setUint8(0,64|_),T.setUint8(2,1),T.setUint16(3,I),T.setUint8(5,t.length);let R=6;for(let L of t)T.setUint8(R++,L.number),T.setUint8(R++,L.size),T.setUint8(R++,L.baseType);return T.buffer}get dataRecord(){let{fieldDefns:_}=this.mesgDefn,I=1+_.reduce((T,{size:R})=>T+R,0),t=new DataView(new ArrayBuffer(I));t.setUint8(0,this.localNum);let A=1;for(let{number:T,type:R,value:L}of this.fields){let O=EI[R];if(!O)throw new Error(`Unknown type: ${R}`);let{size:D,setValue:g}=O,f;"mapValue"in O?f=O.mapValue(L):f=L,g&&g.call(t,A,f),A+=D}return t.buffer}};var tt=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],wI=(n,_)=>(n>>>4^tt[n&15^_])&65535,At=(n,_,I)=>wI(wI(n,_),I),Tt=(n,_)=>At(n,_&15,_>>>4);function OI(n,_=0){let I=_,t=n instanceof ArrayBuffer?new Uint8Array(n):n;for(let A=0;A<t.length;A++)I=Tt(I,t[A]);return I}import Rt from"dayjs";var XI=14,nt=16,Lt=2078,Et=776358228,D_=class{constructor(_={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:_.compact??!0,defaultActivity:_.defaultActivity??"cycling",defaultSubActivity:_.defaultSubActivity??"generic"}}async encode(_){return this.reset(),this.buildFITContent(_,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(_){return this.reset(),this.buildFITContent(_,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(_,I="activity"){return this.reset(),this.buildFITContent(_,I),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(_,I){this.buildFileId(_,I),I==="course"?this.buildCourseContent(_):this.buildActivityContent(_)}buildActivityContent(_){let I=_.sessionMesgs||[];if(I.length===0)throw new Error("Activity file must contain at least one Session");let t=0,A=[],T=[];for(let R of I){if(R.lapMesgs&&this.buildEventsFromLaps(R.lapMesgs,A),R.lapMesgs)for(let L of R.lapMesgs)L.recordMesgs&&this.buildRecords(L.recordMesgs);R.lapMesgs&&this.buildLaps(R.lapMesgs),this.buildSession(R),t++,this.buildActivityFromSession(R,T)}A.forEach(R=>this.buildEvent(R)),T.forEach(R=>this.buildActivity(R))}buildCourseContent(_){let I=_.sessionMesgs||[];if(I.length===0)throw new Error("Course file must contain track data");let t=I[0];if(this.buildCourse({name:"course",sport:this.options.defaultActivity}),t.lapMesgs){let A=[];for(let L of t.lapMesgs)L.recordMesgs&&A.push(...L.recordMesgs);A.sort((L,O)=>L.timestamp&&O.timestamp?new Date(L.timestamp).getTime()-new Date(O.timestamp).getTime():(L.distance||0)-(O.distance||0));let T=A[0],R=A[A.length-1];if(t.startTime&&this.buildEvent({timestamp:t.startTime,event:"timer",eventType:"start",eventGroup:0}),A.forEach(L=>this.buildRecord(L)),R.timestamp&&this.buildEvent({timestamp:R.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),t.lapMesgs)for(let L=0;L<t.lapMesgs.length;L++)this.buildLap(t.lapMesgs[L])}}buildFileId(_,I){let t=_.fileIdMesgs?.[0]||{};this.writeMesg("file_id",{type:I,time_created:t.timeCreated?this.parseTimestamp(t.timeCreated):Date.now(),manufacturer:t.manufacturer,product:t.product,serial_number:t.serialNumber})}buildSession(_){this.writeMesg("session",{timestamp:_.timestamp?_.timestamp:void 0,start_time:_.startTime?_.startTime:void 0,total_elapsed_time:_.totalElapsedTime,total_timer_time:_.totalTimerTime,start_position_lat:_.startPositionLat!=null&&Number.isFinite(_.startPositionLat)?this.convertToSemicircles(_.startPositionLat):void 0,start_position_long:_.startPositionLong!=null&&Number.isFinite(_.startPositionLong)?this.convertToSemicircles(_.startPositionLong):void 0,total_distance:_.totalDistance,total_ascent:_.totalAscent,total_descent:_.totalDescent,sport:_.sport||this.options.defaultActivity,sub_sport:_.subSport||this.options.defaultSubActivity,first_lap_index:_.firstLapIndex||0,num_laps:_.numLaps||_.lapMesgs?.length||1})}buildLaps(_){_.forEach(I=>this.buildLap(I))}buildLap(_){this.writeMesg("lap",{timestamp:_?.timestamp?_.timestamp:void 0,start_time:_?.startTime?_.startTime:void 0,start_position_lat:_?.startPositionLat!=null&&Number.isFinite(_.startPositionLat)?this.convertToSemicircles(_.startPositionLat):void 0,start_position_long:_?.startPositionLong!=null&&Number.isFinite(_.startPositionLong)?this.convertToSemicircles(_.startPositionLong):void 0,end_position_lat:_?.endPositionLat!=null&&Number.isFinite(_.endPositionLat)?this.convertToSemicircles(_.endPositionLat):void 0,end_position_long:_?.endPositionLong!=null&&Number.isFinite(_.endPositionLong)?this.convertToSemicircles(_.endPositionLong):void 0,total_elapsed_time:_?.totalElapsedTime,total_timer_time:_?.totalTimerTime,total_distance:_?.totalDistance,total_ascent:_?.totalAscent,total_descent:_?.totalDescent})}buildRecords(_){_.forEach(I=>this.buildRecord(I))}buildRecord(_){this.writeMesg("record",{timestamp:_.timestamp,position_lat:_?.positionLat!=null&&Number.isFinite(_.positionLat)?this.convertToSemicircles(_.positionLat):void 0,position_long:_?.positionLong!=null&&Number.isFinite(_.positionLong)?this.convertToSemicircles(_.positionLong):void 0,altitude:_?.altitude,enhancedAltitude:_?.enhancedAltitude,distance:_?.distance,heart_rate:_?.heartRate,cadence:_?.cadence,speed:_?.speed,enhancedSpeed:_?.enhancedSpeed,power:_?.power})}buildEvent(_){this.writeMesg("event",{timestamp:_.timestamp?_.timestamp:void 0,event:_.event,event_type:_.eventType,event_group:_.eventGroup})}buildActivity(_){this.writeMesg("activity",{timestamp:_.timestamp?_.timestamp:void 0,total_timer_time:_.totalTimerTime,num_sessions:_.numSessions,type:_.type,event:_.event,event_type:_.eventType,local_timestamp:_.localTimestamp?this.parseTimestamp(_.localTimestamp):void 0,event_group:_.eventGroup})}buildCourse(_){this.writeMesg("course",{name:_.name,sport:_.sport})}buildEventsFromLaps(_,I){_.forEach((t,A)=>{t.startTime&&I.push({timestamp:t.startTime,event:"timer",eventType:"start",eventGroup:A}),t.timestamp&&I.push({timestamp:t.timestamp,event:"timer",eventType:A===_.length-1?"stop_all":"stop",eventGroup:A})})}buildActivityFromSession(_,I){I.push({timestamp:_.timestamp,totalTimerTime:_.totalTimerTime,numSessions:1,type:_.sport||this.options.defaultActivity,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(_){return typeof _=="number"?_:Rt(_).valueOf()}convertToSemicircles(_){if(_!=null&&Number.isFinite(_))return Math.round(_*2**31/180)}validateRequiredFields(_){if(!_.sessionMesgs||_.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(_,I){let t=Object.fromEntries(Object.entries(I).filter(([L,O])=>O!==void 0));if(Object.keys(t).length===0)return;let A=this.localNum[_];A===void 0&&(A=this.localNum[_]=Object.keys(this.localNum).length);let T=new S_(A,_,t),R=this.mesgDefn[A];(!R||!T.isSameDefn(R))&&(this.messages.push(T.defnRecord),this.mesgDefn[A]=T.mesgDefn),this.messages.push(T.dataRecord)}get blob(){let _=[this.header,...this.messages,this.trailer];return new Blob(_,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((_,I)=>_+I.byteLength,0)}get dataCrc(){return this.messages.reduce((_,I)=>OI(I,_),0)}get header(){let _=new DataView(new ArrayBuffer(XI));return _.setUint8(0,XI),_.setUint8(1,nt),_.setUint16(2,Lt,!0),_.setUint32(4,this.dataLen,!0),_.setUint32(8,Et),_.setUint16(12,OI(_.buffer.slice(0,12)),!0),_.buffer}get trailer(){let _=new DataView(new ArrayBuffer(2));return _.setUint16(0,this.dataCrc,!0),_.buffer}async encoder(_){return this.encode(_)}};import{Encoder as Ot}from"@garmin/fitsdk";var St="development",Dt=1,Ht=1;function ot(n,_){if(!Number.isFinite(n))throw new Error(`${_} must be a finite number.`)}function H_(n,_){return ot(n,_),Math.abs(n)<=180?Math.round(n*2147483648/180):Math.round(n)}function Ct(n){if(!n.name||n.name.trim().length===0)throw new Error("Course name is required.");if(!Array.isArray(n.records)||n.records.length===0)throw new Error("Course must contain at least one record point.");let _=n.records.map((t,A)=>{if(t==null)throw new Error(`Course record #${A+1} is missing.`);if(t.timestamp==null)throw new Error(`Course record #${A+1} is missing timestamp.`);return{...t,positionLat:H_(t.latitude,`records[${A}].latitude`),positionLong:H_(t.longitude,`records[${A}].longitude`)}}),I=(n.coursePoints??[]).map((t,A)=>{if(t==null)throw new Error(`Course point #${A+1} is missing.`);if(t.timestamp==null)throw new Error(`Course point #${A+1} is missing timestamp.`);return{...t,type:t.type??0,positionLat:H_(t.latitude,`coursePoints[${A}].latitude`),positionLong:H_(t.longitude,`coursePoints[${A}].longitude`)}});return{...n,sport:n.sport??2,subSport:n.subSport??0,records:_,coursePoints:I,manufacturer:n.manufacturer??St,product:n.product??Dt,serialNumber:n.serialNumber??Ht,timeCreated:n.timeCreated??_[0].timestamp}}function Ut(n){let _=Ct(n),I=_.records[0],t=_.records[_.records.length-1],A=I.timestamp,T=t.timestamp,R=[{mesgNum:0,data:{type:6,manufacturer:_.manufacturer,product:_.product,serialNumber:_.serialNumber,timeCreated:_.timeCreated}},{mesgNum:31,data:{name:_.name,sport:_.sport,subSport:_.subSport}},{mesgNum:19,data:{startTime:A,timestamp:T,startPositionLat:I.positionLat,startPositionLong:I.positionLong,endPositionLat:t.positionLat,endPositionLong:t.positionLong,totalDistance:t.distance}},{mesgNum:21,data:{timestamp:A,event:0,eventType:0}}];return _.records.forEach(L=>{R.push({mesgNum:20,data:{timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,altitude:L.altitude,speed:L.speed}})}),_.coursePoints.forEach((L,O)=>{R.push({mesgNum:32,data:{messageIndex:O,timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,type:L.type,name:L.name,favorite:L.favorite}})}),R.push({mesgNum:21,data:{timestamp:T,event:0,eventType:4}}),R}function pI(n){let _=new Ot;return Ut(n).forEach(t=>{_.onMesg(t.mesgNum,t.data)}),_.close()}var z=class{constructor(){this.version="1.0.0";this.priority=100}supports(_){return this.supportedTags.includes(_)}async initialize(_){_.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(_){_.metadata.delete(`plugin:${this.name}:initialized`)}async validate(_){return!0}parseFloat(_){if(!(typeof _>"u"))return typeof _=="number"?_:typeof _=="string"&&parseFloat(_)||0}parseInt(_){return typeof _=="number"?Math.floor(_):typeof _=="string"&&parseInt(_,10)||0}parseString(_){return String(_||"")}parseBoolean(_){return typeof _=="boolean"?_:typeof _=="string"?_.toLowerCase()==="true":!1}parseDate(_){if(!_)return;let I=new Date(_);return isNaN(I.getTime())?void 0:I}hasRequiredAttributes(_,I){return I.every(t=>_.attributes?.[t])}extractAttributes(_,I,t){_.attributes&&Object.entries(_.attributes).forEach(([A,T])=>{let R=t[A];R&&(I[R]=String(T??""))})}processChildren(_,I,t){_.children?.forEach(A=>{let T=t[A.tag];T&&T(A,I)})}getChildValue(_,I){let t=_.children?.find(A=>A.tag===I);return t?.value?String(t.value):void 0}getChildByTag(_,I){return _.children?.find(t=>t.tag===I)}getChildrenByTag(_,I){return _.children?.filter(t=>t.tag===I)||[]}convertExtensions(_){let I={};return _.children?.forEach(t=>{I[t.tag]=this.convertExtensionContent(t)}),I}convertExtensionContent(_){if(_.children?.length){let I={};return _.children.forEach(t=>{I[t.tag]=this.convertExtensionContent(t)}),I}else return _.value}};var v=class extends z{parseCoordinate(_){let I=this.parseFloat(_);return I===0?void 0:I}parseGPXTime(_){if(!_)return;let I=new Date(_);return isNaN(I.getTime())?void 0:I}extractNumericAttributes(_,I,t){_.attributes&&Object.entries(_.attributes).forEach(([A,T])=>{let R=t[A];R&&R in I&&typeof T<"u"&&(I[R]=this.parseFloat(T))})}};var o_=class extends v{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(I,t){if(!this.hasRequiredAttributes(I,["lat","lon"])){t.warnings.push(`${this.name}: point without latitude or longitude was ignored`);return}let A={lat:this.parseFloat(I.attributes?.lat),lon:this.parseFloat(I.attributes?.lon)};return this.processChildren(I,A,{ele:(T,R)=>R.ele=this.parseFloat(T.value),time:(T,R)=>R.time=new Date(this.parseString(T.value)),speed:(T,R)=>R.speed=this.parseFloat(T.value),power:(T,R)=>R.power=this.parseFloat(T.value),cadence:(T,R)=>R.cadence=this.parseFloat(T.value),heartRate:(T,R)=>R.heartRate=this.parseFloat(T.value),course:(T,R)=>R.course=this.parseFloat(T.value),name:(T,R)=>R.name=this.parseString(T.value),cmt:(T,R)=>R.cmt=this.parseString(T.value),desc:(T,R)=>R.desc=this.parseString(T.value),src:(T,R)=>R.src=this.parseString(T.value),sym:(T,R)=>R.sym=this.parseString(T.value),type:(T,R)=>R.type=this.parseString(T.value),fix:(T,R)=>R.fix=this.parseString(T.value),sat:(T,R)=>R.sat=this.parseString(T.value),hdop:(T,R)=>R.hdop=this.parseFloat(T.value),vdop:(T,R)=>R.vdop=this.parseFloat(T.value),pdop:(T,R)=>R.pdop=this.parseFloat(T.value),ageofdgpsdata:(T,R)=>R.ageofdgpsdata=this.parseFloat(T.value),geoidheight:(T,R)=>R.geoidheight=this.parseFloat(T.value),magvar:(T,R)=>R.magvar=this.parseFloat(T.value),dgpsid:(T,R)=>R.dgpsid=this.parseFloat(T.value),extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("extensions");if(O){let D=O.convert(T,t);D&&(this.mapExtensionsToPoint(D,R),R.extensions=D)}},link:(T,R)=>{R.link||(R.link=[]);let O=t.metadata.get("decoder")?.getConverter("link")?.convert(T,t);O&&R.link&&R.link.push(O)}}),A}mapExtensionsToPoint(I,t){Object.entries(I).forEach(([A,T])=>{if(T!==void 0&&(typeof T=="string"||typeof T=="number")){let R=L=>(Array.isArray(L)?L:[L]).some(D=>{let g=A.toLowerCase(),f=D.toLowerCase();return g===f||g.endsWith(`:${f}`)});R("speed")?t.speed=this.parseFloat(T):R("hr")?t.heartRate=this.parseFloat(T):R(["cad","cadence"])?t.cadence=this.parseFloat(T):R(["PowerInWatts","power"])&&(t.power=this.parseFloat(T))}})}},C_=class extends v{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(I,t){let A={rtept:[]};return this.processChildren(I,A,{name:(T,R)=>R.name=this.parseString(T.value),cmt:(T,R)=>R.cmt=this.parseString(T.value),desc:(T,R)=>R.desc=this.parseString(T.value),src:(T,R)=>R.src=this.parseString(T.value),number:(T,R)=>R.number=this.parseFloat(T.value),type:(T,R)=>R.type=this.parseString(T.value),rtept:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("wpt")?.convert(T,t);O&&R.rtept&&R.rtept.push(O)},extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("extensions");O&&(R.extensions=O.convert(T,t))},link:(T,R)=>{R.link||(R.link=[]);let L=t.metadata.get("decoder");T.children?.forEach(O=>{let D=L?.getConverter("link")?.convert(O,t);D&&R.link&&R.link.push(D)})}}),A}},U_=class extends v{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(I,t){let A={trkseg:[]};return this.processChildren(I,A,{name:(T,R)=>R.name=this.parseString(T.value),cmt:(T,R)=>R.cmt=this.parseString(T.value),desc:(T,R)=>R.desc=this.parseString(T.value),src:(T,R)=>R.src=this.parseString(T.value),number:(T,R)=>R.number=this.parseFloat(T.value),type:(T,R)=>R.type=this.parseString(T.value),trkseg:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("trkseg")?.convert(T,t);O&&R.trkseg&&R.trkseg.push(O)},extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("extensions");O&&(R.extensions=O.convert(T,t))},link:(T,R)=>{R.link||(R.link=[]);let L=t.metadata.get("decoder");T.children?.forEach(O=>{let D=L?.getConverter("link")?.convert(O,t);D&&R.link&&R.link.push(D)})}}),A}},f_=class extends v{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(I,t){let A={trkpt:[]};return this.processChildren(I,A,{trkpt:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("wpt")?.convert(T,t);O&&R.trkpt&&R.trkpt.push(O)},extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("extensions");O&&(R.extensions=O.convert(T,t))}}),A}},d_=class extends v{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(I,t){let A={};return I.attributes?.href&&(A.href=I.attributes.href),this.processChildren(I,A,{text:(T,R)=>R.text=this.parseString(T.value),type:(T,R)=>R.type=this.parseString(T.value)}),A}},F_=class extends v{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(I,t){let A={};return this.processChildren(I,A,{name:(T,R)=>R.name=this.parseString(T.value),desc:(T,R)=>R.desc=this.parseString(T.value),keywords:(T,R)=>R.keywords=this.parseString(T.value),time:(T,R)=>R.time=new Date(this.parseString(T.value)),author:(T,R)=>{let L=t.metadata.get("decoder");R.author=L?.getConverter("author")?.convert(T,t)},copyright:(T,R)=>{let L=t.metadata.get("decoder");R.copyright=L?.getConverter("copyright")?.convert(T,t)},bounds:(T,R)=>{let L=t.metadata.get("decoder");R.bounds=L?.getConverter("bounds")?.convert(T,t)},extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("extensions");O&&(R.extensions=O.convert(T,t))},link:(T,R)=>{R.link||(R.link=[]);let O=t.metadata.get("decoder")?.getConverter("link")?.convert(T,t);O&&R.link&&R.link.push(O)}}),A}},G_=class extends v{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(I,t){let A={};return I.value&&!I.children?.length?(A.name=this.parseString(I.value),A):(this.processChildren(I,A,{name:(T,R)=>R.name=this.parseString(T.value),email:(T,R)=>{let L=t.metadata.get("decoder");R.email=L?.getConverter("email")?.convert(T,t)},link:(T,R)=>{let L=t.metadata.get("decoder");R.link=L?.getConverter("link")?.convert(T,t)}}),A)}},g_=class extends v{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(I,t){let A={};return this.processChildren(I,A,{id:(T,R)=>R.id=this.parseString(T.value),domain:(T,R)=>R.domain=this.parseString(T.value)}),A}},l_=class extends v{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(I,t){let A={};return I.attributes?.author&&(A.author=I.attributes.author),this.processChildren(I,A,{year:(T,R)=>R.year=this.parseString(T.value),license:(T,R)=>R.license=this.parseString(T.value)}),A}},W_=class extends v{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(I,t){let A={};return this.extractAttributes(I,A,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),A}},B_=class extends v{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(I,t){let A={};return I.children?.forEach(T=>{this.flattenExtensionElement(T,A)}),A}flattenExtensionElement(I,t){if(!I.children?.length&&I.value!==void 0){t[I.tag]=this.parseExtensionValue(I.value);return}I.children?.length&&I.children.forEach(A=>{this.flattenExtensionElement(A,t)})}parseExtensionValue(I){if(I===void 0)return;let t=String(I),A=parseFloat(t);return!isNaN(A)&&isFinite(A)?A:t}};import{Parser as ft}from"htmlparser2";var M_=class{constructor(){this.stage="tokenize"}async process(_){let I=Date.now();if(!_.xmlContent)throw new Error("XML content cannot be empty");let t=[],A=new ft({onopentag(T,R){t.push({type:"open",tag:T,attributes:R})},ontext(T){let R=T.replace(/\n/g,"").trim();R&&t.push({type:"text",tag:"text",value:R})},onclosetag(T){t.push({type:"close",tag:T})}},{xmlMode:!0});return A.write(_.xmlContent),A.end(),_.tokens=t,_.performance.tokenizeTime=Date.now()-I,_}},V_=class{constructor(){this.stage="ast_generate"}async process(_){let I=Date.now();if(!_.tokens)throw new Error("Tokens cannot be empty");let t=[],A,T=null;for(let R of _.tokens)if(R.type==="open"){let L={tag:R.tag,attributes:R.attributes||{},children:[]};A?T&&T.children?.push(L):A=L,t.push(L),T=L}else R.type==="text"&&T?T.value=R.value:R.type==="close"&&(t.pop(),T=t[t.length-1]||null);return _.ast=A,_.performance.astTime=Date.now()-I,_}},K_=class{constructor(_){this.getConverter=_;this.stage="convert"}async process(_){let I=Date.now();if(!_.ast)throw new Error("AST cannot be empty");if(_.ast.tag!=="gpx")throw new Error(`Not a valid GPX document: expected <gpx>, received <${_.ast.tag}>`);let t={};return _.ast.attributes&&Object.entries(_.ast.attributes).forEach(([A,T])=>{A.startsWith("xmlns:")?t[A]=T.replace(/&#39;/g,"'"):A==="xsi:schemaLocation"?t[A]=T.replace(/&#39;/g,"'"):t[A]=T}),_.ast.children?.forEach(A=>{let T=this.getConverter(A.tag);if(!T){_.warnings.push(`Unsupported GPX element "${A.tag}" was ignored`);return}try{let R=T.convert(A,_);R&&this.assignResult(t,A.tag,R)}catch(R){throw _.errors.push(R),new Error(`GPX converter "${T.name}" failed for ${A.tag}: ${R.message}`)}}),_.result=t,_.performance.convertTime=Date.now()-I,_}assignResult(_,I,t){switch(I){case"metadata":_.metadata=t;break;case"wpt":_.wpt||(_.wpt=[]),_.wpt.push(t);break;case"rte":_.rte||(_.rte=[]),_.rte.push(t);break;case"trk":_.trk||(_.trk=[]),_.trk.push(t);break;case"extensions":_.extensions=t;break}}},h_=class{constructor(){this.stage="complete"}async process(_){_.performance.endTime=Date.now();let I=_.performance.endTime-_.performance.startTime;return _.metadata.set("performance",{totalTime:I,tokenizeTime:_.performance.tokenizeTime,astTime:_.performance.astTime,convertTime:_.performance.convertTime}),_}};var w_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultConvertersRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new M_,new V_,new K_(_=>this.getConverter(_)),new h_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let _=[new o_,new C_,new U_,new f_,new d_,new F_,new G_,new g_,new l_,new W_,new B_];for(let I of _)I.supportedTags?.forEach(t=>{this.addConverterForTag(t,I)}),this.registeredPlugins.add(I.name);this.defaultConvertersRegistered=!0}addConverterForTag(_,I){this.converterPlugins.has(_)||this.converterPlugins.set(_,[]);let t=this.converterPlugins.get(_);t.push(I),t.sort((A,T)=>(A.priority||100)-(T.priority||100))}async registerConverter(_){if(this.registeredPlugins.has(_.name))throw new Error(`Converter plugin ${_.name} already exists`);_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name)}async registerMiddleware(_){let I=this.middlewarePlugins.findIndex(t=>t.name===_.name);I!==-1?this.middlewarePlugins[I]=_:this.middlewarePlugins.push(_)}getConverter(_){let I=this.converterPlugins.get(_);return I&&I.length>0?I[0]:void 0}getAllConverters(_){return this.converterPlugins.get(_)||[]}unregisterConverter(_){let I;for(let[t,A]of this.converterPlugins){let T=A.findIndex(R=>R.name===_);T!==-1&&(I=A[T],A.splice(T,1),A.length===0&&this.converterPlugins.delete(t))}I&&this.registeredPlugins.delete(_)}unregisterMiddleware(_){let I=this.middlewarePlugins.findIndex(t=>t.name===_);I!==-1&&this.middlewarePlugins.splice(I,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(_=>_.name)}listProcessors(){return this.processors.map(_=>_.constructor.name)}getConverterDetails(_){let I={};if(_){let t=this.converterPlugins.get(_);t&&(I[_]=t.map(A=>({name:A.name,priority:A.priority||100})))}else for(let[t,A]of this.converterPlugins)I[t]=A.map(T=>({name:T.name,priority:T.priority||100}));return I}getMiddlewareDetails(){return this.middlewarePlugins.map(_=>{let I=[];return _.onTokenize&&I.push("onTokenize"),_.onAstGenerate&&I.push("onAstGenerate"),_.onConvert&&I.push("onConvert"),_.onComplete&&I.push("onComplete"),_.onError&&I.push("onError"),{name:_.name,hooks:I}})}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let _=this.createContext(),I=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(t=>[t.name,t])).values()];for(let t of I)await t.initialize?.(_);this.initialized=!0}async destroy(){if(!this.initialized)return;let _=this.createContext(),I=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(t=>[t.name,t])).values()];for(let t of I)await t.destroy?.(_);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(_,I,t){let A=I;for(let T of this.middlewarePlugins){let R=T[_];if(R)try{A=await R.call(T,A,t)||A}catch(L){t.errors.push(L),await T.onError?.(L,t)}}return A}async parserByBuffer(_){await this.initialize();let I=this.createContext();I.rawData=_,I.xmlContent=_.toString("utf-8"),I.metadata.set("decoder",this);for(let t of this.processors)try{switch(I=await t.process(I),t.stage){case"tokenize":I.tokens&&(I.tokens=await this.executeMiddlewareHook("onTokenize",I.tokens,I));break;case"ast_generate":I.ast&&(I.ast=await this.executeMiddlewareHook("onAstGenerate",I.ast,I));break;case"convert":I.result&&(I.result=await this.executeMiddlewareHook("onConvert",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(A){I.errors.push(A);for(let T of this.middlewarePlugins)await T.onError?.(A,I);throw new Error(`GPX pipeline stage "${t.stage}" failed: ${A.message}`)}return I.result}convertExtensions(_){let I={},{attributes:t,tag:A,value:T}=_;if(t&&Object.entries(t).forEach(([R,L])=>{I[R]=L}),_?.children?.length)_.children?.forEach(R=>{I[R.tag]=this.convertExtensions(R)});else if(T!==void 0)return T;return I}};import vI from"dayjs";import dt from"dayjs/plugin/utc.js";var SI={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var DI={temperature:"Temperature",Depth:"Depth"};vI.extend(dt);var X_=class{constructor(_={}){this.formatElevation=_=>{let I=parseFloat(_);return isNaN(I)?_:this.roundTo(I,2).toString()};this.compact=_.compact??!0}async encode(_){let I=this.buildGPXXML(_);return Buffer.from(I,"utf-8")}encodeToString(_){return this.buildGPXXML(_)}buildGPXXML(_){let I=this.buildXMLHeader(),t=this.buildGPXContent(_),T=`${I}${t}
2
+ </gpx>`;return this.compact?this.compressXML(T):T}compressXML(_){return _.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(){return['<?xml version="1.0" encoding="UTF-8"?>','<gpx creator="https://gpxonline.net" version="1.1"',' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"',' xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'," http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd"," http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd"," http://www.garmin.com/xmlschemas/PowerExtension/v1 http://www.garmin.com/xmlschemas/PowerExtensionv1.xsd",' http://www.topografix.com/GPX/gpx_style/0/2 http://www.topografix.com/GPX/gpx_style/0/2/gpx_style.xsd"',' xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1"',' xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3"',' xmlns:gpxpx="http://www.garmin.com/xmlschemas/PowerExtension/v1"',' xmlns:gpx_style="http://www.topografix.com/GPX/gpx_style/0/2"',' xmlns="http://www.topografix.com/GPX/1/1">'].join(`
3
+ `)}buildGPXContent(_){let{metadata:I,wpt:t=[],rte:A=[],trk:T=[]}=_,R=[];return I&&R.push(this.buildMetadata(I)),t.forEach(L=>{R.push(this.buildWaypoint(L,"wpt"))}),A.forEach(L=>{R.push(this.buildRoute(L))}),T.forEach(L=>{R.push(this.buildTrack(L))}),R.join(`
4
4
  `)}buildMetadata(_){let I=["<metadata>"];return this.addOptionalElement(I,"name",_.name),this.addOptionalElement(I,"desc",_.desc),_.author&&I.push(this.buildAuthor(_.author)),_.copyright&&I.push(this.buildCopyright(_.copyright)),_.link&&this.addLinks(I,_.link),_.time&&I.push(this.buildTimeElement(_.time)),this.addOptionalElement(I,"keywords",_.keywords),_.bounds&&I.push(this.buildBounds(_.bounds)),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</metadata>"),I.join(`
5
5
  `)}buildAuthor(_){let I=["<author>"];return this.addOptionalElement(I,"name",_.name),_.email&&I.push(`<email id="${this.escapeXML(_.email.id||"")}" domain="${this.escapeXML(_.email.domain||"")}"/>`),_.link&&I.push(this.buildLink(_.link)),I.push("</author>"),I.join(`
6
6
  `)}buildCopyright(_){let I=[`<copyright author="${this.escapeXML(_.author||"")}">`];return this.addOptionalElement(I,"year",_.year),this.addOptionalElement(I,"license",_.license),I.push("</copyright>"),I.join(`
7
- `)}buildBounds(_){let I=this.escapeXMLAttribute((_.minlat||0).toString()),A=this.escapeXMLAttribute((_.minlon||0).toString()),T=this.escapeXMLAttribute((_.maxlat||0).toString()),R=this.escapeXMLAttribute((_.maxlon||0).toString());return`<bounds minlat="${I}" minlon="${A}" maxlat="${T}" maxlon="${R}"/>`}buildWaypoint(_,I){var T,R,L;if(_.time===void 0)return"";let A=[`<${I} lat="${this.escapeXMLAttribute(_.lat?this.formatCoordinate(_.lat):"")}" lon="${this.escapeXMLAttribute(_.lon?this.formatCoordinate(_.lon):"")}">`];if(this.addOptionalElement(A,"ele",(T=_.ele)==null?void 0:T.toString(),this.formatElevation),_!=null&&_.time&&A.push(this.buildTimeElement(_.time)),this.addOptionalElement(A,"speed",(R=_.speed)==null?void 0:R.toString()),this.addOptionalElement(A,"course",(L=_.course)==null?void 0:L.toString()),this.addStandardWaypointElements(A,_),_.extensions){let t=this.processPointExtensions(_,_.extensions);Object.keys(t).length>0&&A.push(this.buildExtensions(t))}return A.push(`</${I}>`),A.join(`
8
- `)}addStandardWaypointElements(_,I){var A,T,R,L,t,E,D;this.addOptionalElement(_,"magvar",(A=I.magvar)==null?void 0:A.toString()),this.addOptionalElement(_,"geoidheight",(T=I.geoidheight)==null?void 0:T.toString()),this.addOptionalElement(_,"name",I.name),this.addOptionalElement(_,"cmt",I.cmt),this.addOptionalElement(_,"desc",I.desc),this.addOptionalElement(_,"src",I.src),I.link&&this.addLinks(_,I.link),this.addOptionalElement(_,"sym",I.sym),this.addOptionalElement(_,"type",I.type),this.addOptionalElement(_,"fix",I.fix),this.addOptionalElement(_,"sat",I.sat),this.addOptionalElement(_,"hdop",(R=I.hdop)==null?void 0:R.toString()),this.addOptionalElement(_,"vdop",(L=I.vdop)==null?void 0:L.toString()),this.addOptionalElement(_,"pdop",(t=I.pdop)==null?void 0:t.toString()),this.addOptionalElement(_,"ageofdgpsdata",(E=I.ageofdgpsdata)==null?void 0:E.toString()),this.addOptionalElement(_,"dgpsid",(D=I.dgpsid)==null?void 0:D.toString())}buildRoute(_){var A;let I=["<rte>"];return this.addRouteTrackCommonElements(I,_),_.rtept&&((A=_.rtept)==null||A.forEach(T=>{I.push(this.buildWaypoint(T,"rtept"))})),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</rte>"),I.join(`
9
- `)}buildTrack(_){let I=["<trk>"];return this.addRouteTrackCommonElements(I,_),_.trkseg&&_.trkseg.forEach(A=>{I.push(this.buildTrackSegment(A))}),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</trk>"),I.join(`
10
- `)}buildTrackSegment(_){let I=["<trkseg>"];return _.trkpt&&_.trkpt.forEach(A=>{I.push(this.buildWaypoint(A,"trkpt"))}),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</trkseg>"),I.join(`
11
- `)}addRouteTrackCommonElements(_,I){var A;this.addOptionalElement(_,"name",I.name),this.addOptionalElement(_,"cmt",I.cmt),this.addOptionalElement(_,"desc",I.desc),this.addOptionalElement(_,"src",I.src),I.link&&this.addLinks(_,I.link),this.addOptionalElement(_,"number",(A=I.number)==null?void 0:A.toString()),this.addOptionalElement(_,"type",I.type)}processPointExtensions(_,I){let A={};return Object.entries({"gpxtpx:TrackPointExtension":{"gpxtpx:hr":"heartRate","gpxtpx:cad":"cadence","gpxtpx:speed":"speed","gpxtpx:atemp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:temp":"temperature"},"gpxpx:PowerExtension":{"gpxpx:PowerInWatts":"power"},"gpxx:GpxExtensions":{"gpxx:Temperature":"temperature","gpxx:Depth":"depth"}}).forEach(([R,L])=>{let t={},E=!1;Object.entries(L).forEach(([D,H])=>{let C;if(_[H]!==void 0)C=_[H];else if(I)if(I[D]!==void 0)C=I[D];else{let r=D.split(":").pop();Object.entries(I).forEach(([N,U])=>{N.endsWith(`:${r}`)&&U!==void 0&&(C=U)})}C!==void 0&&(t[D]=C,E=!0)}),E&&(A[R]=t)}),A}buildTrackPointExtension(_,I){let A=this.deepClone(I["gpxtpx:TrackPointExtension"]||{}),T=Object.keys(k_);return Object.keys(_).filter(R=>T.includes(R)).forEach(R=>{let L=k_[R];L&&_[R]!==void 0&&(A[`gpxtpx:${L}`]=_[R])}),A}buildPowerExtension(_,I){return this.deepClone(I["gpxpx:PowerExtension"]||{})}buildGpxExtensions(_,I){let A=this.deepClone(I["gpxx:GpxExtensions"]||{}),T=Object.keys(Z_);return Object.keys(_).filter(R=>T.includes(R)).forEach(R=>{let L=Z_[R];L&&_[R]!==void 0&&(A[`gpxx:${L}`]=_[R])}),A}buildExtensions(_){let I=this.buildExtensionContent(_);return I?`<extensions>${I}</extensions>`:""}buildExtensionContent(_){return Object.entries(_).filter(([I])=>!I.startsWith("xmlns")).map(([I,A])=>{if(A&&typeof A=="object"){let T=this.buildExtensionContent(A);return`<${I}>${T}</${I}>`}else if(A!=null)return`<${I}>${this.escapeXML(String(A))}</${I}>`;return""}).filter(I=>I).join("")}buildLink(_){let I=[`<link href="${this.escapeXMLAttribute(_.href||"")}">`];return this.addOptionalElement(I,"text",_.text),this.addOptionalElement(I,"type",_.type),I.push("</link>"),I.join("")}addLinks(_,I){(Array.isArray(I)?I:[I]).forEach(T=>{_.push(this.buildLink(T))})}buildTimeElement(_){return typeof _=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/.test(_)?`<time>${_}</time>`:`<time>${x_(_).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}</time>`}addOptionalElement(_,I,A,T){if(A!=null&&A!==""){let R=T?T(A):this.escapeXML(A);_.push(`<${I}>${R}</${I}>`)}}isValidCoordinate(_,I){return _!=null&&I!==void 0&&I!==null&&!isNaN(_)&&!isNaN(I)}formatCoordinate(_){return this.roundTo(_,6).toString()}roundTo(_,I){let A=Math.pow(10,I);return Math.round(_*A)/A}escapeXML(_){return _.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(_){return typeof _!="string"?String(_||""):_.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\r/g,"&#13;").replace(/\n/g,"&#10;").replace(/\t/g,"&#9;")}deepClone(_){if(_===null||typeof _!="object")return _;if(_ instanceof Date)return new Date(_.getTime());if(Array.isArray(_))return _.map(A=>this.deepClone(A));let I={};for(let A in _)Object.prototype.hasOwnProperty.call(_,A)&&(I[A]=this.deepClone(_[A]));return I}encoder(_){return this.encode(_)}};var q_=class extends j{constructor(){super(...arguments);this.name="performance-middleware";this.description="Monitor parsing performance"}async onTokenize(I,A){return I}async onAstGenerate(I,A){let T=this.countNodes(I);return I}async onComplete(I,A){let T=A.metadata.get("performance");return I}countNodes(I){let A=1;if(I.children)for(let T of I.children)A+=this.countNodes(T);return A}},y_=class extends j{constructor(){super(...arguments);this.name="validation-middleware";this.description="Validate GPX data integrity"}async onComplete(I,A){let T=this.validateGPX(I);return T.length>0&&A.metadata.set("validation-errors",T),I}validateGPX(I){let A=[];if(I.version||A.push("Missing GPX version information"),I.creator||A.push("Missing GPX creator information"),I.trk){for(let T of I.trk)if(T.trkseg){for(let R of T.trkseg)if(R.trkpt)for(let L of R.trkpt)L.time&&A.push("Invalid track point time")}}return A}};async function a_(n){let _=[new q_,new y_];for(let I of _)await n.registerMiddleware(I)}var F=class extends W{parseHeartRate(_){let I=this.parseFloat(_);if(!(typeof I>"u"))return I>0&&I<300?I:void 0}parseTCXTime(_){if(!_)return;let I=new Date(_);return isNaN(I.getTime())?void 0:I}parseDistance(_){let I=this.parseFloat(_);if(!(typeof I>"u"))return I>0?I:void 0}parseSpeed(_){let I=this.parseFloat(_);if(!(typeof I>"u"))return I>=0?I:void 0}parseAltitude(_){return this.parseFloat(_)}parseCoordinate(_){let I=this.parseFloat(_);return I!==0?I:void 0}};var V_=class extends F{constructor(){super(...arguments);this.name="PositionConverter";this.supportedTags=["Position"]}convert(I,A){let T={};return this.processChildren(I,T,{LatitudeDegrees:(R,L)=>L.LatitudeDegrees=this.parseString(R.value),LongitudeDegrees:(R,L)=>L.LongitudeDegrees=this.parseString(R.value)}),T}},K_=class extends F{constructor(){super(...arguments);this.name="TrackpointConverter";this.supportedTags=["Trackpoint"]}convert(I,A){let T={};return this.processChildren(I,T,{Time:(R,L)=>L.Time=this.parseString(R.value),Position:(R,L)=>{var E;let t=A.metadata.get("decoder");L.Position=(E=t==null?void 0:t.getConverter("Position"))==null?void 0:E.convert(R,A)},AltitudeMeters:(R,L)=>L.AltitudeMeters=this.parseFloat(R.value),DistanceMeters:(R,L)=>L.DistanceMeters=this.parseFloat(R.value),HeartRateBpm:(R,L)=>{if(R.value)L.HeartRateBpm=this.parseFloat(R.value);else{let t=this.getChildByTag(R,"Value");t!=null&&t.value&&(L.HeartRateBpm=this.parseFloat(t.value))}},Cadence:(R,L)=>{let t={Low:0,High:0};this.processChildren(R,t,{Low:(E,D)=>D.Low=this.parseFloat(E.value)||0,High:(E,D)=>D.High=this.parseFloat(E.value)||0}),L.Cadence=t},SensorState:(R,L)=>L.SensorState=R.value,Extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("Extensions");E&&(L.Extensions=E.convert(R,A))}}),T}},X_=class extends F{constructor(){super(...arguments);this.name="TrackConverter";this.supportedTags=["Track"]}convert(I,A){let T={Trackpoint:[]};return this.processChildren(I,T,{Trackpoint:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("Trackpoint"))==null?void 0:D.convert(R,A);E&&L.Trackpoint&&L.Trackpoint.push(E)}}),T}},M_=class extends F{constructor(){super(...arguments);this.name="ActivityLapConverter";this.supportedTags=["Lap"]}convert(I,A){let T={};return this.extractAttributes(I,T,{StartTime:"Id"}),this.processChildren(I,T,{TotalTimeSeconds:(R,L)=>L.TotalTimeSeconds=this.parseFloat(R.value),DistanceMeters:(R,L)=>L.DistanceMeters=this.parseFloat(R.value),MaximumSpeed:(R,L)=>L.MaximumSpeed=this.parseFloat(R.value),Calories:(R,L)=>L.Calories=this.parseFloat(R.value),AverageHeartRateBpm:(R,L)=>L.AverageHeartRateBpm=this.parseFloat(R.value),MaximumHeartRateBpm:(R,L)=>L.MaximumHeartRateBpm=this.parseFloat(R.value),Intensity:(R,L)=>L.Intensity=R.value,TriggerMethod:(R,L)=>L.TriggerMethod=R.value,Track:(R,L)=>{var D;L.Track||(L.Track=[]);let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("Track"))==null?void 0:D.convert(R,A);E&&L.Track.push(E)},Notes:(R,L)=>L.Notes=this.parseString(R.value),Extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("Extensions");E&&(L.Extensions=E.convert(R,A))}}),T}},g_=class extends F{constructor(){super(...arguments);this.name="ActivityConverter";this.supportedTags=["Activity"]}convert(I,A){let T={Id:"",Lap:[]};return this.extractAttributes(I,T,{Activity:"Activity"}),this.processChildren(I,T,{Id:(R,L)=>L.Id=this.parseString(R.value),Lap:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("Lap"))==null?void 0:D.convert(R,A);E&&L.Lap.push(E)},Notes:(R,L)=>L.Notes=this.parseString(R.value),Training:(R,L)=>L.Training=this.convertTraining(R),Creator:(R,L)=>L.Creator=this.convertCreator(R),Extensions:(R,L)=>{let t=A.metadata.get("decoder"),E=t==null?void 0:t.getConverter("Extensions");E&&(L.Extensions=E.convert(R,A))}}),T}convertTraining(I){var T;let A={};return I.attributes&&Object.entries(I.attributes).forEach(([R,L])=>{A[R]=L}),(T=I.children)==null||T.forEach(R=>{A[R.tag]=this.convertExtensionContent(R)}),A}convertCreator(I){var T;let A={};return(T=I.children)==null||T.forEach(R=>{A[R.tag]=this.convertExtensionContent(R)}),A}},w_=class extends F{constructor(){super(...arguments);this.name="ActivityListConverter";this.supportedTags=["Activities"]}convert(I,A){let T={Activity:[],MultiActivitySession:[]};return this.processChildren(I,T,{Activity:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("Activity"))==null?void 0:D.convert(R,A);E&&L.Activity&&L.Activity.push(E)},MultiActivitySession:(R,L)=>{var D;let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("MultiActivitySession"))==null?void 0:D.convert(R,A);E&&L.MultiActivitySession&&L.MultiActivitySession.push(E)}}),T}},d_=class extends F{constructor(){super(...arguments);this.name="MultiActivitySessionConverter";this.supportedTags=["MultiActivitySession"]}convert(I,A){let T={};return this.processChildren(I,T,{Id:(R,L)=>L.Id=this.parseString(R.value),FirstActivity:(R,L)=>{var E;let t=A.metadata.get("decoder");L.FirstActivity=(E=t==null?void 0:t.getConverter("FirstActivity"))==null?void 0:E.convert(R,A)},NextActivity:(R,L)=>{var D;L.NextActivity||(L.NextActivity=[]);let t=A.metadata.get("decoder"),E=(D=t==null?void 0:t.getConverter("NextActivity"))==null?void 0:D.convert(R,A);E&&L.NextActivity.push(E)},Notes:(R,L)=>L.Notes=this.parseString(R.value)}),T}},P_=class extends F{constructor(){super(...arguments);this.name="AbstractSourceConverter";this.supportedTags=["Author","Creator"]}convert(I,A){let T={};return this.processChildren(I,T,{Name:(R,L)=>L.Name=this.parseString(R.value)}),T}},h_=class extends F{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["Extensions"]}convert(I,A){let T={};return this.flattenExtensionElement(I,T),T}flattenExtensionElement(I,A){var T,R;if(!((T=I.children)!=null&&T.length)&&I.value!==void 0){A[I.tag]=this.parseExtensionValue(I.value);return}(R=I.children)!=null&&R.length&&I.children.forEach(L=>{this.flattenExtensionElement(L,A)})}parseExtensionValue(I){if(I===void 0)return;let A=String(I),T=parseFloat(A);return!isNaN(T)&&isFinite(T)?T:A}};import{Parser as e_}from"htmlparser2";var l_=class{static tokenizeXML(_){let I=[],A=new e_({onopentag(T,R){I.push({type:"open",tag:T,attributes:R})},ontext(T){let R=T.replace(/\n/g,"").trim();R&&I.push({type:"text",tag:"text",value:R})},onclosetag(T){I.push({type:"close",tag:T})}},{xmlMode:!0});return A.write(_),A.end(),I}static compressXML(_){return _.replace(/>\s+</g,"><").replace(/\s+/g," ").trim()}static formatXML(_,I=2){let A=" ".repeat(I),T="",R=0,L=!1;for(let t=0;t<_.length;t++){let E=_[t],D=_[t+1];E==="<"?(D==="/"?(R--,L||(T+=`
12
- `+A.repeat(R))):D!=="?"&&D!=="!"&&(L||(T+=`
13
- `+A.repeat(R)),R++),L=!0):E===">"&&(L=!1,D==="<"&&_[t+2]==="/"&&R--),T+=E}return T.trim()}static validateXML(_){try{let I=new e_({},{xmlMode:!0});return I.write(_),I.end(),{isValid:!0}}catch(I){return{isValid:!1,error:I.message}}}static extractXMLDeclaration(_){let I=_.match(/<\?xml\s+([^>]+)\?>/);if(!I)return{};let A=I[1],T={},R=A.match(/version=["']([^"']+)["']/);R&&(T.version=R[1]);let L=A.match(/encoding=["']([^"']+)["']/);L&&(T.encoding=L[1]);let t=A.match(/standalone=["']([^"']+)["']/);return t&&(T.standalone=t[1]),T}static escapeXML(_){return _.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}static unescapeXML(_){return _.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&amp;/g,"&")}};var Y_=class{constructor(){this.stage="tokenize";this.name="tokenize-processor"}async process(_){if(!_.xmlContent)throw new Error("TCX data cannot be empty");let I=l_.tokenizeXML(_.xmlContent);if(I.length===0)throw new Error("Not a valid TCX file");return _.tokens=I,_.stats.processedTokens=I.length,_}},v_=class{constructor(){this.stage="ast-generate";this.name="ast-generate-processor"}async process(_){var L;let I=Date.now();if(!_.tokens)throw new Error("Tokens cannot be empty");let A=[],T,R=null;for(let t of _.tokens)if(t.type==="open"){let E={tag:t.tag,attributes:t.attributes||{},children:[]};T?R&&((L=R.children)==null||L.push(E)):T=E,A.push(E),R=E}else t.type==="text"&&R?R.value=t.value:t.type==="close"&&(A.pop(),R=A[A.length-1]||null);return _.ast=T,_.performance.astTime=Date.now()-I,_}},$_=class{constructor(_){this.getConverter=_;this.stage="convert";this.name="convert-processor"}async process(_){if(!_.ast)throw new Error("AST is empty, cannot convert");let I=this.findTCXRoot(_.ast);if(!I)throw new Error("Not a valid TCX file: TrainingCenterDatabase element not found");let A=this.convertAST(I,_);return _.result=A,_.stats.convertedElements=this.countElements(_.ast),_}findTCXRoot(_){if(_.tag==="TrainingCenterDatabase")return _;if(_.children)for(let I of _.children){let A=this.findTCXRoot(I);if(A)return A}}convertAST(_,I){let A=this.getConverter(_.tag);return A?A.convert(_,I):this.genericConvert(_,I)}genericConvert(_,I){let A={};if(_.attributes&&Object.entries(_.attributes).forEach(([T,R])=>{A[T]=R}),_.value!==void 0)if(_.children&&_.children.length>0)A._value=_.value;else return _.value;return _.children&&_.children.forEach(T=>{let R=this.convertAST(T,I);A[T.tag]?(Array.isArray(A[T.tag])||(A[T.tag]=[A[T.tag]]),A[T.tag].push(R)):A[T.tag]=R}),A}countElements(_){let I=1;if(_.children)for(let A of _.children)I+=this.countElements(A);return I}},b_=class{constructor(){this.stage="complete";this.name="complete-processor"}async process(_){if(!_.result)throw new Error("No conversion result found");let I=Date.now(),A=I-_.performance.startTime;return _.performance.endTime=I,_.performance.processingTime=A,_.metadata.set("performance",{processingTime:A,processedTokens:_.stats.processedTokens,convertedElements:_.stats.convertedElements}),_}};var Y=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultConvertersRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new Y_,new v_,new $_(_=>this.getConverter(_)),new b_]}async registerDefaultConverters(){var I;if(this.defaultConvertersRegistered)return;let _=[new V_,new K_,new X_,new M_,new g_,new w_,new d_,new P_,new h_];for(let A of _)(I=A.supportedTags)==null||I.forEach(T=>{this.addConverterForTag(T,A)}),this.registeredPlugins.add(A.name);this.defaultConvertersRegistered=!0}addConverterForTag(_,I){this.converterPlugins.has(_)||this.converterPlugins.set(_,[]);let A=this.converterPlugins.get(_);A.push(I),A.sort((T,R)=>(T.priority||100)-(R.priority||100))}async registerConverter(_){var A,R;if(this.registeredPlugins.has(_.name))throw new Error(`Converter plugin ${_.name} already exists`);(A=_.supportedTags)==null||A.forEach(L=>{this.addConverterForTag(L,_)}),this.registeredPlugins.add(_.name);let I=_.priority!==void 0?` (priority: ${_.priority})`:"";(R=_.supportedTags)==null||R.forEach(L=>{let E=(this.converterPlugins.get(L)||[]).map(D=>`${D.name}(${D.priority||100})`)})}async registerMiddleware(_){let I=this.middlewarePlugins.findIndex(T=>T.name===_.name);I!==-1?this.middlewarePlugins[I]=_:this.middlewarePlugins.push(_);let A=[];_.onTokenize&&A.push("onTokenize"),_.onAstGenerate&&A.push("onAstGenerate"),_.onConvert&&A.push("onConvert"),_.onComplete&&A.push("onComplete"),_.onError&&A.push("onError"),A.length>0}getConverter(_){let I=this.converterPlugins.get(_);return I&&I.length>0?I[0]:void 0}getAllConverters(_){return this.converterPlugins.get(_)||[]}unregisterConverter(_){let I;for(let[A,T]of this.converterPlugins){let R=T.findIndex(L=>L.name===_);R!==-1&&(I=T[R],T.splice(R,1),T.length===0&&this.converterPlugins.delete(A))}I&&this.registeredPlugins.delete(_)}unregisterMiddleware(_){let I=this.middlewarePlugins.findIndex(A=>A.name===_);I!==-1&&this.middlewarePlugins.splice(I,1)}async initialize(){var A;if(this.initialized)return;await this.registerDefaultConverters();let _=this.createContext(),I=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let T of I)try{await((A=T.initialize)==null?void 0:A.call(T,_))}catch{}this.initialized=!0}async destroy(){var A;if(!this.initialized)return;let _=this.createContext(),I=[...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins];for(let T of I)try{await((A=T.destroy)==null?void 0:A.call(T,_))}catch{}this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(_,I,A){var R;let T=I;for(let L of this.middlewarePlugins){let t=L[_];if(t)try{T=await t.call(L,T,A)||T}catch(E){A.errors.push(E),await((R=L.onError)==null?void 0:R.call(L,E,A))}}return T}async parseByBuffer(_){var A;await this.initialize();let I=this.createContext();I.rawData=_,I.xmlContent=_.toString("utf-8"),I.metadata.set("decoder",this);try{for(let T of this.processors)try{switch(I=await T.process(I),T.stage){case"tokenize":I.tokens&&(I.tokens=await this.executeMiddlewareHook("onTokenize",I.tokens,I));break;case"ast-generate":I.ast&&(I.ast=await this.executeMiddlewareHook("onAstGenerate",I.ast,I));break;case"convert":I.result&&(I.result=await this.executeMiddlewareHook("onConvert",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(R){I.errors.push(R);for(let L of this.middlewarePlugins)await((A=L.onError)==null?void 0:A.call(L,R,I))}return I.result}catch(T){throw T}}convertExtensions(_){var L,t;let I={},{attributes:A,tag:T,value:R}=_;if(A&&Object.entries(A).forEach(([E,D])=>{I[E]=D}),(L=_==null?void 0:_.children)!=null&&L.length)(t=_.children)==null||t.forEach(E=>{I[E.tag]=this.convertExtensions(E)});else if(R!==void 0)return R;return I}async parserByBuffer(_){return this.parseByBuffer(_)}async parseByString(_){let I=Buffer.from(_,"utf-8");return this.parseByBuffer(I)}};import _I from"dayjs";import wI from"dayjs/plugin/utc.js";_I.extend(wI);var v=class{constructor(_={}){this.compact=_.compact??!0}async encode(_){let I=this.buildTCXXML(_);return Buffer.from(I,"utf-8")}encodeToString(_){return this.buildTCXXML(_)}buildTCXXML(_){let I=this.buildXMLHeader(_),A=this.buildTCXContent(_),R=`${I}${A}
14
- </TrainingCenterDatabase>`;return this.compact?this.compressXML(R):R}compressXML(_){return _.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(_){let I=_.version||"1.0",A=_.creator||"trackswap",T=_.xmlns||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2",R=_["xmlns:xsi"]||"http://www.w3.org/2001/XMLSchema-instance",L=_["xsi:schemaLocation"]||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd";return['<?xml version="1.0" encoding="UTF-8"?>',`<TrainingCenterDatabase version="${this.escapeXMLAttribute(I)}"`,` creator="${this.escapeXMLAttribute(A)}"`,` xmlns="${this.escapeXMLAttribute(T)}"`,` xmlns:xsi="${this.escapeXMLAttribute(R)}"`,` xsi:schemaLocation="${this.escapeXMLAttribute(L)}">`].join(`
7
+ `)}buildBounds(_){let I=this.escapeXMLAttribute((_.minlat||0).toString()),t=this.escapeXMLAttribute((_.minlon||0).toString()),A=this.escapeXMLAttribute((_.maxlat||0).toString()),T=this.escapeXMLAttribute((_.maxlon||0).toString());return`<bounds minlat="${I}" minlon="${t}" maxlat="${A}" maxlon="${T}"/>`}buildWaypoint(_,I){if(_.time===void 0)return"";let t=_.lat,A=_.lon,T=typeof t=="number"&&Number.isFinite(t)&&t>=-90&&t<=90,R=typeof A=="number"&&Number.isFinite(A)&&A>=-180&&A<=180;if(!T||!R)return"";let L=[`<${I} lat="${this.escapeXMLAttribute(this.formatCoordinate(t))}" lon="${this.escapeXMLAttribute(this.formatCoordinate(A))}">`];if(this.addOptionalElement(L,"ele",_.ele?.toString(),this.formatElevation),_?.time&&L.push(this.buildTimeElement(_.time)),this.addOptionalElement(L,"speed",_.speed?.toString()),this.addOptionalElement(L,"course",_.course?.toString()),this.addStandardWaypointElements(L,_),_.extensions){let O=this.processPointExtensions(_,_.extensions);Object.keys(O).length>0&&L.push(this.buildExtensions(O))}return L.push(`</${I}>`),L.join(`
8
+ `)}addStandardWaypointElements(_,I){this.addOptionalElement(_,"magvar",I.magvar?.toString()),this.addOptionalElement(_,"geoidheight",I.geoidheight?.toString()),this.addOptionalElement(_,"name",I.name),this.addOptionalElement(_,"cmt",I.cmt),this.addOptionalElement(_,"desc",I.desc),this.addOptionalElement(_,"src",I.src),I.link&&this.addLinks(_,I.link),this.addOptionalElement(_,"sym",I.sym),this.addOptionalElement(_,"type",I.type),this.addOptionalElement(_,"fix",I.fix),this.addOptionalElement(_,"sat",I.sat),this.addOptionalElement(_,"hdop",I.hdop?.toString()),this.addOptionalElement(_,"vdop",I.vdop?.toString()),this.addOptionalElement(_,"pdop",I.pdop?.toString()),this.addOptionalElement(_,"ageofdgpsdata",I.ageofdgpsdata?.toString()),this.addOptionalElement(_,"dgpsid",I.dgpsid?.toString())}buildRoute(_){let I=["<rte>"];return this.addRouteTrackCommonElements(I,_),_.rtept&&_.rtept?.forEach(t=>{I.push(this.buildWaypoint(t,"rtept"))}),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</rte>"),I.join(`
9
+ `)}buildTrack(_){let I=["<trk>"];return this.addRouteTrackCommonElements(I,_),_.trkseg&&_.trkseg.forEach(t=>{I.push(this.buildTrackSegment(t))}),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</trk>"),I.join(`
10
+ `)}buildTrackSegment(_){let I=["<trkseg>"];return _.trkpt&&_.trkpt.forEach(t=>{I.push(this.buildWaypoint(t,"trkpt"))}),_.extensions&&I.push(this.buildExtensions(_.extensions)),I.push("</trkseg>"),I.join(`
11
+ `)}addRouteTrackCommonElements(_,I){this.addOptionalElement(_,"name",I.name),this.addOptionalElement(_,"cmt",I.cmt),this.addOptionalElement(_,"desc",I.desc),this.addOptionalElement(_,"src",I.src),I.link&&this.addLinks(_,I.link),this.addOptionalElement(_,"number",I.number?.toString()),this.addOptionalElement(_,"type",I.type)}processPointExtensions(_,I){let t={};return Object.entries({"gpxtpx:TrackPointExtension":{"gpxtpx:hr":"heartRate","gpxtpx:cad":"cadence","gpxtpx:speed":"speed","gpxtpx:atemp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:temp":"temperature"},"gpxpx:PowerExtension":{"gpxpx:PowerInWatts":"power"},"gpxx:GpxExtensions":{"gpxx:Temperature":"temperature","gpxx:Depth":"depth"}}).forEach(([T,R])=>{let L={},O=!1;Object.entries(R).forEach(([D,g])=>{let f;if(_[g]!==void 0)f=_[g];else if(I)if(I[D]!==void 0)f=I[D];else{let W=D.split(":").pop();Object.entries(I).forEach(([l,M])=>{l.endsWith(`:${W}`)&&M!==void 0&&(f=M)})}f!==void 0&&(L[D]=f,O=!0)}),O&&(t[T]=L)}),t}buildTrackPointExtension(_,I){let t=this.deepClone(I["gpxtpx:TrackPointExtension"]||{}),A=Object.keys(SI);return Object.keys(_).filter(T=>A.includes(T)).forEach(T=>{let R=SI[T];R&&_[T]!==void 0&&(t[`gpxtpx:${R}`]=_[T])}),t}buildPowerExtension(_,I){return this.deepClone(I["gpxpx:PowerExtension"]||{})}buildGpxExtensions(_,I){let t=this.deepClone(I["gpxx:GpxExtensions"]||{}),A=Object.keys(DI);return Object.keys(_).filter(T=>A.includes(T)).forEach(T=>{let R=DI[T];R&&_[T]!==void 0&&(t[`gpxx:${R}`]=_[T])}),t}buildExtensions(_){let I=this.buildExtensionContent(_);return I?`<extensions>${I}</extensions>`:""}buildExtensionContent(_){return Object.entries(_).filter(([I])=>!I.startsWith("xmlns")).map(([I,t])=>{if(t&&typeof t=="object"){let A=this.buildExtensionContent(t);return`<${I}>${A}</${I}>`}else if(t!=null)return`<${I}>${this.escapeXML(String(t))}</${I}>`;return""}).filter(I=>I).join("")}buildLink(_){let I=[`<link href="${this.escapeXMLAttribute(_.href||"")}">`];return this.addOptionalElement(I,"text",_.text),this.addOptionalElement(I,"type",_.type),I.push("</link>"),I.join("")}addLinks(_,I){(Array.isArray(I)?I:[I]).forEach(A=>{_.push(this.buildLink(A))})}buildTimeElement(_){return typeof _=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/.test(_)?`<time>${_}</time>`:`<time>${vI(_).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}</time>`}addOptionalElement(_,I,t,A){if(t!=null&&t!==""){let T=A?A(t):this.escapeXML(t);_.push(`<${I}>${T}</${I}>`)}}isValidCoordinate(_,I){return _!=null&&I!==void 0&&I!==null&&!isNaN(_)&&!isNaN(I)}formatCoordinate(_){return this.roundTo(_,6).toString()}roundTo(_,I){let t=Math.pow(10,I);return Math.round(_*t)/t}escapeXML(_){return _.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(_){return typeof _!="string"?String(_||""):_.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\r/g,"&#13;").replace(/\n/g,"&#10;").replace(/\t/g,"&#9;")}deepClone(_){if(_===null||typeof _!="object")return _;if(_ instanceof Date)return new Date(_.getTime());if(Array.isArray(_))return _.map(t=>this.deepClone(t));let I={};for(let t in _)Object.prototype.hasOwnProperty.call(_,t)&&(I[t]=this.deepClone(_[t]));return I}encoder(_){return this.encode(_)}};var N=class extends z{parseHeartRate(_){let I=this.parseFloat(_);if(!(typeof I>"u"))return I>0&&I<300?I:void 0}parseTCXTime(_){if(!_)return;let I=new Date(_);return isNaN(I.getTime())?void 0:I}parseDistance(_){let I=this.parseFloat(_);if(!(typeof I>"u"))return I>0?I:void 0}parseSpeed(_){let I=this.parseFloat(_);if(!(typeof I>"u"))return I>=0?I:void 0}parseAltitude(_){return this.parseFloat(_)}parseCoordinate(_){let I=this.parseFloat(_);return I!==0?I:void 0}};var p_=class extends N{constructor(){super(...arguments);this.name="PositionConverter";this.supportedTags=["Position"]}convert(I,t){let A={};return this.processChildren(I,A,{LatitudeDegrees:(T,R)=>R.LatitudeDegrees=this.parseString(T.value),LongitudeDegrees:(T,R)=>R.LongitudeDegrees=this.parseString(T.value)}),A}},P_=class extends N{constructor(){super(...arguments);this.name="TrackpointConverter";this.supportedTags=["Trackpoint"]}convert(I,t){let A={};return this.processChildren(I,A,{Time:(T,R)=>R.Time=this.parseString(T.value),Position:(T,R)=>{let L=t.metadata.get("decoder");R.Position=L?.getConverter("Position")?.convert(T,t)},AltitudeMeters:(T,R)=>R.AltitudeMeters=this.parseFloat(T.value),DistanceMeters:(T,R)=>R.DistanceMeters=this.parseFloat(T.value),HeartRateBpm:(T,R)=>{if(T.value)R.HeartRateBpm=this.parseFloat(T.value);else{let L=this.getChildByTag(T,"Value");L?.value&&(R.HeartRateBpm=this.parseFloat(L.value))}},Cadence:(T,R)=>{let L={Low:0,High:0};this.processChildren(T,L,{Low:(O,D)=>D.Low=this.parseFloat(O.value)||0,High:(O,D)=>D.High=this.parseFloat(O.value)||0}),R.Cadence=L},SensorState:(T,R)=>R.SensorState=T.value,Extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("Extensions");O&&(R.Extensions=O.convert(T,t))}}),A}},v_=class extends N{constructor(){super(...arguments);this.name="TrackConverter";this.supportedTags=["Track"]}convert(I,t){let A={Trackpoint:[]};return this.processChildren(I,A,{Trackpoint:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("Trackpoint")?.convert(T,t);O&&R.Trackpoint&&R.Trackpoint.push(O)}}),A}},Y_=class extends N{constructor(){super(...arguments);this.name="ActivityLapConverter";this.supportedTags=["Lap"]}convert(I,t){let A={};return this.extractAttributes(I,A,{StartTime:"StartTime"}),this.processChildren(I,A,{TotalTimeSeconds:(T,R)=>R.TotalTimeSeconds=this.parseFloat(T.value),DistanceMeters:(T,R)=>R.DistanceMeters=this.parseFloat(T.value),MaximumSpeed:(T,R)=>R.MaximumSpeed=this.parseFloat(T.value),Calories:(T,R)=>R.Calories=this.parseFloat(T.value),AverageHeartRateBpm:(T,R)=>R.AverageHeartRateBpm=this.parseFloat(T.value),MaximumHeartRateBpm:(T,R)=>R.MaximumHeartRateBpm=this.parseFloat(T.value),Intensity:(T,R)=>R.Intensity=T.value,TriggerMethod:(T,R)=>R.TriggerMethod=T.value,Track:(T,R)=>{R.Track||(R.Track=[]);let O=t.metadata.get("decoder")?.getConverter("Track")?.convert(T,t);O&&R.Track.push(O)},Notes:(T,R)=>R.Notes=this.parseString(T.value),Extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("Extensions");O&&(R.Extensions=O.convert(T,t))}}),A}},s_=class extends N{constructor(){super(...arguments);this.name="ActivityConverter";this.supportedTags=["Activity"]}convert(I,t){let A={Id:"",Lap:[]};return this.extractAttributes(I,A,{Sport:"Sport"}),this.processChildren(I,A,{Id:(T,R)=>R.Id=this.parseString(T.value),Lap:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("Lap")?.convert(T,t);O&&R.Lap.push(O)},Notes:(T,R)=>R.Notes=this.parseString(T.value),Training:(T,R)=>R.Training=this.convertTraining(T),Creator:(T,R)=>R.Creator=this.convertCreator(T),Extensions:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("Extensions");O&&(R.Extensions=O.convert(T,t))}}),A}convertTraining(I){let t={};return I.attributes&&Object.entries(I.attributes).forEach(([A,T])=>{t[A]=T}),I.children?.forEach(A=>{t[A.tag]=this.convertExtensionContent(A)}),t}convertCreator(I){let t={};return I.children?.forEach(A=>{t[A.tag]=this.convertExtensionContent(A)}),t}},b_=class extends N{constructor(){super(...arguments);this.name="ActivityListConverter";this.supportedTags=["Activities"]}convert(I,t){let A={Activity:[],MultiActivitySession:[]};return this.processChildren(I,A,{Activity:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("Activity")?.convert(T,t);O&&R.Activity&&R.Activity.push(O)},MultiActivitySession:(T,R)=>{let O=t.metadata.get("decoder")?.getConverter("MultiActivitySession")?.convert(T,t);O&&R.MultiActivitySession&&R.MultiActivitySession.push(O)}}),A}},N_=class extends N{constructor(){super(...arguments);this.name="MultiActivitySessionConverter";this.supportedTags=["MultiActivitySession"]}convert(I,t){let A={};return this.processChildren(I,A,{Id:(T,R)=>R.Id=this.parseString(T.value),FirstActivity:(T,R)=>{let L=t.metadata.get("decoder");R.FirstActivity=L?.getConverter("FirstActivity")?.convert(T,t)},NextActivity:(T,R)=>{R.NextActivity||(R.NextActivity=[]);let O=t.metadata.get("decoder")?.getConverter("NextActivity")?.convert(T,t);O&&R.NextActivity.push(O)},Notes:(T,R)=>R.Notes=this.parseString(T.value)}),A}},$_=class extends N{constructor(){super(...arguments);this.name="AbstractSourceConverter";this.supportedTags=["Author","Creator"]}convert(I,t){let A={};return this.processChildren(I,A,{Name:(T,R)=>R.Name=this.parseString(T.value)}),A}},Q_=class extends N{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["Extensions"]}convert(I,t){let A={};return this.flattenExtensionElement(I,A),A}flattenExtensionElement(I,t){if(!I.children?.length&&I.value!==void 0){t[I.tag]=this.parseExtensionValue(I.value);return}I.children?.length&&I.children.forEach(A=>{this.flattenExtensionElement(A,t)})}parseExtensionValue(I){if(I===void 0)return;let t=String(I),A=parseFloat(t);return!isNaN(A)&&isFinite(A)?A:t}};import{Parser as YI}from"htmlparser2";var J_=class{static tokenizeXML(_){let I=[],t=new YI({onopentag(A,T){I.push({type:"open",tag:A,attributes:T})},ontext(A){let T=A.replace(/\n/g,"").trim();T&&I.push({type:"text",tag:"text",value:T})},onclosetag(A){I.push({type:"close",tag:A})}},{xmlMode:!0});return t.write(_),t.end(),I}static compressXML(_){return _.replace(/>\s+</g,"><").replace(/\s+/g," ").trim()}static formatXML(_,I=2){let t=" ".repeat(I),A="",T=0,R=!1;for(let L=0;L<_.length;L++){let O=_[L],D=_[L+1];O==="<"?(D==="/"?(T--,R||(A+=`
12
+ `+t.repeat(T))):D!=="?"&&D!=="!"&&(R||(A+=`
13
+ `+t.repeat(T)),T++),R=!0):O===">"&&(R=!1,D==="<"&&_[L+2]==="/"&&T--),A+=O}return A.trim()}static validateXML(_){try{let I=new YI({},{xmlMode:!0});return I.write(_),I.end(),{isValid:!0}}catch(I){return{isValid:!1,error:I.message}}}static extractXMLDeclaration(_){let I=_.match(/<\?xml\s+([^>]+)\?>/);if(!I)return{};let t=I[1],A={},T=t.match(/version=["']([^"']+)["']/);T&&(A.version=T[1]);let R=t.match(/encoding=["']([^"']+)["']/);R&&(A.encoding=R[1]);let L=t.match(/standalone=["']([^"']+)["']/);return L&&(A.standalone=L[1]),A}static escapeXML(_){return _.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}static unescapeXML(_){return _.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&amp;/g,"&")}};var k_=class{constructor(){this.stage="tokenize";this.name="tokenize-processor"}async process(_){if(!_.xmlContent)throw new Error("TCX data cannot be empty");let I=J_.tokenizeXML(_.xmlContent);if(I.length===0)throw new Error("Not a valid TCX file");return _.tokens=I,_.stats.processedTokens=I.length,_}},z_=class{constructor(){this.stage="ast-generate";this.name="ast-generate-processor"}async process(_){let I=Date.now();if(!_.tokens)throw new Error("Tokens cannot be empty");let t=[],A,T=null;for(let R of _.tokens)if(R.type==="open"){let L={tag:R.tag,attributes:R.attributes||{},children:[]};A?T&&T.children?.push(L):A=L,t.push(L),T=L}else R.type==="text"&&T?T.value=R.value:R.type==="close"&&(t.pop(),T=t[t.length-1]||null);return _.ast=A,_.performance.astTime=Date.now()-I,_}},j_=class{constructor(_){this.getConverter=_;this.stage="convert";this.name="convert-processor"}async process(_){if(!_.ast)throw new Error("AST is empty, cannot convert");let I=this.findTCXRoot(_.ast);if(!I)throw new Error("Not a valid TCX file: TrainingCenterDatabase element not found");let t=this.convertAST(I,_);return _.result=t,_.stats.convertedElements=this.countElements(_.ast),_}findTCXRoot(_){if(_.tag==="TrainingCenterDatabase")return _;if(_.children)for(let I of _.children){let t=this.findTCXRoot(I);if(t)return t}}convertAST(_,I){let t=this.getConverter(_.tag);return t?t.convert(_,I):this.genericConvert(_,I)}genericConvert(_,I){let t={};if(_.attributes&&Object.entries(_.attributes).forEach(([A,T])=>{t[A]=T}),_.value!==void 0)if(_.children&&_.children.length>0)t._value=_.value;else return _.value;return _.children&&_.children.forEach(A=>{let T=this.convertAST(A,I);t[A.tag]?(Array.isArray(t[A.tag])||(t[A.tag]=[t[A.tag]]),t[A.tag].push(T)):t[A.tag]=T}),t}countElements(_){let I=1;if(_.children)for(let t of _.children)I+=this.countElements(t);return I}},y_=class{constructor(){this.stage="complete";this.name="complete-processor"}async process(_){if(!_.result)throw new Error("No conversion result found");let I=Date.now(),t=I-_.performance.startTime;return _.performance.endTime=I,_.performance.processingTime=t,_.metadata.set("performance",{processingTime:t,processedTokens:_.stats.processedTokens,convertedElements:_.stats.convertedElements}),_}};var Z_=class{constructor(){this.converterPlugins=new Map;this.registeredPlugins=new Set;this.middlewarePlugins=[];this.processors=[];this.initialized=!1;this.defaultConvertersRegistered=!1;this.initializePipeline()}initializePipeline(){this.processors=[new k_,new z_,new j_(_=>this.getConverter(_)),new y_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let _=[new p_,new P_,new v_,new Y_,new s_,new b_,new N_,new $_,new Q_];for(let I of _)I.supportedTags?.forEach(t=>{this.addConverterForTag(t,I)}),this.registeredPlugins.add(I.name);this.defaultConvertersRegistered=!0}addConverterForTag(_,I){this.converterPlugins.has(_)||this.converterPlugins.set(_,[]);let t=this.converterPlugins.get(_);t.push(I),t.sort((A,T)=>(A.priority||100)-(T.priority||100))}async registerConverter(_){if(this.registeredPlugins.has(_.name))throw new Error(`Converter plugin ${_.name} already exists`);_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name)}async registerMiddleware(_){let I=this.middlewarePlugins.findIndex(t=>t.name===_.name);I!==-1?this.middlewarePlugins[I]=_:this.middlewarePlugins.push(_)}getConverter(_){let I=this.converterPlugins.get(_);return I&&I.length>0?I[0]:void 0}getAllConverters(_){return this.converterPlugins.get(_)||[]}unregisterConverter(_){let I;for(let[t,A]of this.converterPlugins){let T=A.findIndex(R=>R.name===_);T!==-1&&(I=A[T],A.splice(T,1),A.length===0&&this.converterPlugins.delete(t))}I&&this.registeredPlugins.delete(_)}unregisterMiddleware(_){let I=this.middlewarePlugins.findIndex(t=>t.name===_);I!==-1&&this.middlewarePlugins.splice(I,1)}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let _=this.createContext(),I=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(t=>[t.name,t])).values()];for(let t of I)await t.initialize?.(_);this.initialized=!0}async destroy(){if(!this.initialized)return;let _=this.createContext(),I=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(t=>[t.name,t])).values()];for(let t of I)await t.destroy?.(_);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(_,I,t){let A=I;for(let T of this.middlewarePlugins){let R=T[_];if(R)try{A=await R.call(T,A,t)||A}catch(L){t.errors.push(L),await T.onError?.(L,t)}}return A}async parseByBuffer(_){await this.initialize();let I=this.createContext();I.rawData=_,I.xmlContent=_.toString("utf-8"),I.metadata.set("decoder",this);for(let t of this.processors)try{switch(I=await t.process(I),t.stage){case"tokenize":I.tokens&&(I.tokens=await this.executeMiddlewareHook("onTokenize",I.tokens,I));break;case"ast-generate":I.ast&&(I.ast=await this.executeMiddlewareHook("onAstGenerate",I.ast,I));break;case"convert":I.result&&(I.result=await this.executeMiddlewareHook("onConvert",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(A){I.errors.push(A);for(let T of this.middlewarePlugins)await T.onError?.(A,I);throw new Error(`TCX pipeline stage "${t.stage}" failed: ${A.message}`)}return I.result}convertExtensions(_){let I={},{attributes:t,tag:A,value:T}=_;if(t&&Object.entries(t).forEach(([R,L])=>{I[R]=L}),_?.children?.length)_.children?.forEach(R=>{I[R.tag]=this.convertExtensions(R)});else if(T!==void 0)return T;return I}async parserByBuffer(_){return this.parseByBuffer(_)}async parseByString(_){let I=Buffer.from(_,"utf-8");return this.parseByBuffer(I)}};import sI from"dayjs";import Ft from"dayjs/plugin/utc.js";sI.extend(Ft);var q_=class{constructor(_={}){this.compact=_.compact??!0}async encode(_){let I=this.buildTCXXML(_);return Buffer.from(I,"utf-8")}encodeToString(_){return this.buildTCXXML(_)}buildTCXXML(_){let I=this.buildXMLHeader(_),t=this.buildTCXContent(_),T=`${I}${t}
14
+ </TrainingCenterDatabase>`;return this.compact?this.compressXML(T):T}compressXML(_){return _.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(_){let I=_.version||"1.0",t=_.creator||"trackswap",A=_.xmlns||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2",T=_["xmlns:xsi"]||"http://www.w3.org/2001/XMLSchema-instance",R=_["xsi:schemaLocation"]||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www8.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd";return['<?xml version="1.0" encoding="UTF-8"?>',`<TrainingCenterDatabase version="${this.escapeXMLAttribute(I)}"`,` creator="${this.escapeXMLAttribute(t)}"`,` xmlns="${this.escapeXMLAttribute(A)}"`,` xmlns:xsi="${this.escapeXMLAttribute(T)}"`,` xsi:schemaLocation="${this.escapeXMLAttribute(R)}">`].join(`
15
15
  `)}buildTCXContent(_){let I=[];return _.Folders&&I.push(this.buildFolders(_.Folders)),_.Activities&&I.push(this.buildActivities(_.Activities)),_.Workouts&&I.push(this.buildWorkouts(_.Workouts)),_.Courses&&I.push(this.buildCourses(_.Courses)),_.Author&&I.push(this.buildAuthor(_.Author)),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.join(`
16
16
  `)}buildFolders(_){let I=["<Folders>"];return _.History&&I.push(this.buildHistory(_.History)),_.Workouts&&I.push(this.buildWorkouts(_.Workouts)),_.Courses,I.push("</Folders>"),I.join(`
17
17
  `)}buildHistory(_){let I=["<History>"];return _.Running&&I.push(`<Running>${this.buildHistoryFolder(_.Running)}</Running>`),_.Biking&&I.push(`<Biking>${this.buildHistoryFolder(_.Biking)}</Biking>`),_.Other&&I.push(`<Other>${this.buildHistoryFolder(_.Other)}</Other>`),_.MultiActivity&&I.push(`<MultiActivity>${this.buildHistoryFolder(_.MultiActivity)}</MultiActivity>`),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.push("</History>"),I.join(`
18
- `)}buildHistoryFolder(_){return""}buildActivities(_){let I=["<Activities>"];return _.Activity&&_.Activity.forEach(A=>{I.push(this.buildActivity(A))}),_.MultiActivitySession&&_.MultiActivitySession.forEach(A=>{I.push(this.buildMultiActivitySession(A))}),I.push("</Activities>"),I.join(`
19
- `)}buildActivity(_){let A=[`<Activity Activity="${_.Activity||"Other"}">`];return A.push(`<Id>${this.formatTime(_.Id)}</Id>`),_.Lap&&_.Lap.length>0&&_.Lap.forEach(T=>{A.push(this.buildActivityLap(T))}),this.addOptionalElement(A,"Notes",_.Notes),_.Training,_.Creator,_.Extensions&&A.push(this.buildExtensions(_.Extensions)),A.push("</Activity>"),A.join(`
20
- `)}buildActivityLap(_){let I=["<Lap>"];return this.addOptionalNumericElement(I,"TotalTimeSeconds",_.TotalTimeSeconds),this.addOptionalNumericElement(I,"DistanceMeters",_.DistanceMeters),this.addOptionalNumericElement(I,"MaximumSpeed",_.MaximumSpeed),this.addOptionalNumericElement(I,"Calories",_.Calories),_.AverageHeartRateBpm&&I.push(`<AverageHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t"><Value>${_.AverageHeartRateBpm}</Value></AverageHeartRateBpm>`),_.MaximumHeartRateBpm&&I.push(`<MaximumHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t"><Value>${_.MaximumHeartRateBpm}</Value></MaximumHeartRateBpm>`),this.addOptionalElement(I,"Intensity",_.Intensity),_.Cadence&&I.push(this.buildCadence(_.Cadence)),this.addOptionalElement(I,"TriggerMethod",_.TriggerMethod),_.Track&&_.Track.forEach(A=>{I.push(this.buildTrack(A))}),this.addOptionalElement(I,"Notes",_.Notes),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.push("</Lap>"),I.join(`
21
- `)}buildTrack(_){let I=["<Track>"];return _.Trackpoint&&_.Trackpoint.forEach(A=>{I.push(this.buildTrackpoint(A))}),I.push("</Track>"),I.join(`
18
+ `)}buildHistoryFolder(_){return""}buildActivities(_){let I=["<Activities>"];return _.Activity&&_.Activity.forEach(t=>{I.push(this.buildActivity(t))}),_.MultiActivitySession&&_.MultiActivitySession.forEach(t=>{I.push(this.buildMultiActivitySession(t))}),I.push("</Activities>"),I.join(`
19
+ `)}buildActivity(_){let t=[`<Activity Sport="${_.Sport||"Other"}">`];return t.push(`<Id>${this.formatTime(_.Id)}</Id>`),_.Lap&&_.Lap.length>0&&_.Lap.forEach(A=>{t.push(this.buildActivityLap(A))}),this.addOptionalElement(t,"Notes",_.Notes),_.Training,_.Creator,_.Extensions&&t.push(this.buildExtensions(_.Extensions)),t.push("</Activity>"),t.join(`
20
+ `)}buildActivityLap(_){let t=[`<Lap${_.StartTime?` StartTime="${this.escapeXMLAttribute(this.formatTime(_.StartTime))}"`:""}>`];return this.addOptionalNumericElement(t,"TotalTimeSeconds",_.TotalTimeSeconds),this.addOptionalNumericElement(t,"DistanceMeters",_.DistanceMeters),this.addOptionalNumericElement(t,"MaximumSpeed",_.MaximumSpeed),this.addOptionalNumericElement(t,"Calories",_.Calories),_.AverageHeartRateBpm&&t.push(`<AverageHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t"><Value>${_.AverageHeartRateBpm}</Value></AverageHeartRateBpm>`),_.MaximumHeartRateBpm&&t.push(`<MaximumHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t"><Value>${_.MaximumHeartRateBpm}</Value></MaximumHeartRateBpm>`),this.addOptionalElement(t,"Intensity",_.Intensity),_.Cadence&&t.push(this.buildCadence(_.Cadence)),this.addOptionalElement(t,"TriggerMethod",_.TriggerMethod),_.Track&&_.Track.forEach(A=>{t.push(this.buildTrack(A))}),this.addOptionalElement(t,"Notes",_.Notes),_.Extensions&&t.push(this.buildExtensions(_.Extensions)),t.push("</Lap>"),t.join(`
21
+ `)}buildTrack(_){let I=["<Track>"];return _.Trackpoint&&_.Trackpoint.forEach(t=>{I.push(this.buildTrackpoint(t))}),I.push("</Track>"),I.join(`
22
22
  `)}buildTrackpoint(_){let I=["<Trackpoint>"];return _.Time?(I.push(`<Time>${this.formatTime(_.Time)}</Time>`),_.Position&&I.push(this.buildPosition(_.Position)),this.addOptionalNumericElement(I,"AltitudeMeters",_.AltitudeMeters),this.addOptionalNumericElement(I,"DistanceMeters",_.DistanceMeters),_.HeartRateBpm&&I.push(`<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t"><Value>${_.HeartRateBpm}</Value></HeartRateBpm>`),_.Cadence&&I.push(this.buildCadence(_.Cadence)),this.addOptionalElement(I,"SensorState",_.SensorState),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.push("</Trackpoint>"),I.join(`
23
- `)):""}buildPosition(_){let I=["<Position>"];return _!=null&&_.LatitudeDegrees&&I.push(`<LatitudeDegrees>${this.formatCoordinate(parseFloat(_.LatitudeDegrees))}</LatitudeDegrees>`),_!=null&&_.LongitudeDegrees&&I.push(`<LongitudeDegrees>${this.formatCoordinate(parseFloat(_.LongitudeDegrees))}</LongitudeDegrees>`),I.push("</Position>"),I.join("")}buildCadence(_){return`<Cadence><Low>${_.Low}</Low><High>${_.High}</High></Cadence>`}buildMultiActivitySession(_){let I=["<MultiActivitySession>"];return _.Id&&I.push(`<Id>${this.formatTime(_.Id)}</Id>`),_.FirstActivity&&I.push(this.buildFirstActivity(_.FirstActivity)),_.NextActivity&&_.NextActivity.forEach(A=>{I.push(this.buildNextActivity(A))}),this.addOptionalElement(I,"Notes",_.Notes),I.push("</MultiActivitySession>"),I.join(`
23
+ `)):""}buildGeoCoords(_){let I=[];return _?.LatitudeDegrees&&I.push(`<LatitudeDegrees>${this.formatCoordinate(parseFloat(_.LatitudeDegrees))}</LatitudeDegrees>`),_?.LongitudeDegrees&&I.push(`<LongitudeDegrees>${this.formatCoordinate(parseFloat(_.LongitudeDegrees))}</LongitudeDegrees>`),I.join("")}wrapGeoTag(_,I){if(!I)return"";let t=this.buildGeoCoords(I);return t?`<${_}>${t}</${_}>`:""}buildPosition(_){let I=this.buildGeoCoords(_);return I?`<Position>${I}</Position>`:""}buildCadence(_){return`<Cadence><Low>${_.Low}</Low><High>${_.High}</High></Cadence>`}buildMultiActivitySession(_){let I=["<MultiActivitySession>"];return _.Id&&I.push(`<Id>${this.formatTime(_.Id)}</Id>`),_.FirstActivity&&I.push(this.buildFirstActivity(_.FirstActivity)),_.NextActivity&&_.NextActivity.forEach(t=>{I.push(this.buildNextActivity(t))}),this.addOptionalElement(I,"Notes",_.Notes),I.push("</MultiActivitySession>"),I.join(`
24
24
  `)}buildFirstActivity(_){let I=["<FirstActivity>"];return _.Activity&&I.push(this.buildActivity(_.Activity)),I.push("</FirstActivity>"),I.join(`
25
25
  `)}buildNextActivity(_){let I=["<NextActivity>"];return _.Transition&&I.push(`<Transition>${this.buildActivityLap(_.Transition)}</Transition>`),_.Activity&&I.push(this.buildActivity(_.Activity)),I.push("</NextActivity>"),I.join(`
26
- `)}buildWorkouts(_){return"<Workouts></Workouts>"}buildCourses(_){return"<Courses></Courses>"}buildAuthor(_){let I=["<Author>"];return this.addOptionalElement(I,"Name",_.Name),I.push("</Author>"),I.join("")}buildExtensions(_){let I=this.buildExtensionContent(_);return I?`<Extensions>${I}</Extensions>`:""}buildExtensionContent(_){return Object.entries(_).filter(([I])=>!I.startsWith("xmlns")).map(([I,A])=>{if(A&&typeof A=="object"){let T=this.buildExtensionContent(A);return`<${I}>${T}</${I}>`}else if(A!=null)return`<${I}>${this.escapeXML(String(A))}</${I}>`;return""}).filter(I=>I).join("")}formatTime(_){return typeof _=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(_)?_:_I(_).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}addOptionalElement(_,I,A,T){if(A!=null&&A!==""){let R=T?T(A):this.escapeXML(A);_.push(`<${I}>${R}</${I}>`)}}addOptionalNumericElement(_,I,A){A!=null&&!isNaN(A)&&_.push(`<${I}>${A}</${I}>`)}isValidCoordinate(_,I){return _!=null&&I!==void 0&&I!==null&&!isNaN(_)&&!isNaN(I)}formatCoordinate(_){return this.roundTo(_,6).toString()}roundTo(_,I){let A=Math.pow(10,I);return Math.round(_*A)/A}escapeXML(_){return _.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(_){return typeof _!="string"?String(_||""):_.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\r/g,"&#13;").replace(/\n/g,"&#10;").replace(/\t/g,"&#9;")}deepClone(_){if(_===null||typeof _!="object")return _;if(_ instanceof Date)return new Date(_.getTime());if(Array.isArray(_))return _.map(A=>this.deepClone(A));let I={};for(let A in _)Object.prototype.hasOwnProperty.call(_,A)&&(I[A]=this.deepClone(_[A]));return I}encoder(_){return this.encode(_)}};import dI from"dayjs";var $=class extends W{convertPoints(_){return _.map(I=>this.convertPoint(I)).filter(I=>I!==void 0)}convertTime(_){if(!_)return;if(typeof _=="number")return _;let I=dI(_);return I.isValid()?I.valueOf():void 0}},b=class{constructor(){this.version="1.0.0";this.priority=100}supports(_){return this.supportedTags.includes(_)}async initialize(_){_.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(_){_.metadata.delete(`plugin:${this.name}:initialized`)}async validate(_){return!0}convertTimeToDate(_){return _?new Date(_):new Date}convertTimeToString(_){return this.convertTimeToDate(_).toISOString()}ensureValidCoordinates(_,I){return _>=-90&&_<=90&&I>=-180&&I<=180}round(_,I=6){let A=Math.pow(10,I);return Math.round(_*A)/A}},II=class extends w{async onError(_,I){I.warnings.push(`Middleware ${this.name} error: ${_.message}`)}validateActivityFile(_){if(!_.metadata)return!1;if(_.routes){for(let I of _.routes)if(!this.validateRoute(I))return!1}if(_.points){for(let I of _.points)if(!this.validatePoint(I))return!1}if(_.activities){for(let I of _.activities)if(!this.validateActivity(I))return!1}return!0}validateActivity(_){return!!(_&&typeof _.index>"u"&&_.laps&&_.laps.length>0)}validateRoute(_){return!!(_.records&&_.records.length>0)}validatePoint(_){return!!_.timestamp}};var AI={heartrate:"heartRate","gpxtpx:hr":"heartRate","ns3:hr":"heartRate","gpxdata:hr":"heartRate","gpxdata:cadence":"cadence","gpxtpx:cad":"cadence","ns3:cad":"cadence",cadence:"cadence","gpxtpx:speed":"speed","ns3:speed":"speed",speed:"speed",power:"power","gpxdata:power":"power","gpxpx:PowerInWatts":"power",PowerInWatts:"power","gpxtpx:temp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:atemp":"atemp","gpxx:Temperature":"temperature","gpxx:Depth":"depth"},o=n=>n*(180/Math.pow(2,31));import TI from"dayjs";import N_ from"dayjs";import{getPreciseDistance as PI}from"geolib";var d=class{calculateRecordsAggMetrics(_){if(!_||_.length===0)return;let I={records:this.preprocessRecords(_)};for(let A=0;A<I.records.length;A++){let T=I.records[A];if(!(!T.positionLat||!T.positionLong)){if(I!=null&&I.startPositionLat||(I.startPositionLat=T.positionLat),I!=null&&I.startPositionLong||(I.startPositionLong=T.positionLong),I.endPositionLat=T.positionLat,I.endPositionLong=T.positionLong,I.timestamp=T.timestamp,I!=null&&I.startTime||(I.startTime=T.timestamp),I.endTime=T.timestamp,I.totalDistance=T.distance,I.totalElapsedTime=N_(T.timestamp).diff(N_(I.startTime),"second"),T!=null&&T.speed&&(I.avgSpeed=I.avgSpeed?(I.avgSpeed+T.speed)/2:T.speed,I.maxSpeed=Math.max(I.maxSpeed||0,T.speed)),T!=null&&T.heartRate&&(I.maxHeartRate=Math.max(I.maxHeartRate||0,T.heartRate),I.minHeartRate=Math.min(I.minHeartRate||T.heartRate,T.heartRate),I.avgHeartRate?I.avgHeartRate=(I.avgHeartRate+T.heartRate)/2:I.avgHeartRate=T.heartRate),T!=null&&T.altitude&&(I.maxAltitude=Math.max(I.maxAltitude||0,T.altitude),I.minAltitude=Math.min(I.minAltitude||T.altitude,T.altitude),I.avgAltitude=I.avgAltitude?(I.avgAltitude+T.altitude)/2:T.altitude,A>0&&_[A-1].altitude)){let R=this.calculateElevationChanges(_[A-1],T);I.totalAscent=(I.totalAscent||0)+R.ascent,I.totalDescent=(I.totalDescent||0)+R.descent}if(T!=null&&T.cadence&&(I.maxCadence=Math.max(I.maxCadence||0,T.cadence),I.avgCadence?I.avgCadence=(I.avgCadence+T.cadence)/2:I.avgCadence=T.cadence),T!=null&&T.power){I.maxPower=Math.max(I.maxPower||0,T.power),I.avgPower?I.avgPower=(I.avgPower+T.power)/2:I.avgPower=T.power;let R=this.calculateAccumulatedPower(A>0?_[A-1]:T,T,I.totalWork||0);I.totalWork=R.newAccumulatedWork,I.normalizedPower=void 0}T!=null&&T.temperature&&(I.avgTemperature?I.avgTemperature=(I.avgTemperature+T.temperature)/2:I.avgTemperature=T.temperature,I.maxTemperature=Math.max(I.maxTemperature||0,T.temperature),I.minTemperature=Math.min(I.minTemperature||T.temperature,T.temperature))}}return I}calculateLapAggMetrics(_){var A;if(!_||_.length===0)return;let I={laps:_,timestamp:((A=_[0])==null?void 0:A.timestamp)||new Date};for(let T=0;T<_.length;T++){let R=_[T];R.startPositionLat&&R.startPositionLong&&!(I!=null&&I.startPositionLat)&&!(I!=null&&I.startPositionLong)&&(I.startPositionLat=R.startPositionLat,I.startPositionLong=R.startPositionLong),R.endPositionLat&&R.endPositionLong&&(I.endPositionLat=R.endPositionLat,I.endPositionLong=R.endPositionLong),R.startTime&&!(I!=null&&I.startTime)&&(I.startTime=R.startTime),R.endTime&&(I.endTime=R.endTime),I.timestamp=R.timestamp||R.endTime||I.timestamp,R.totalDistance&&(I.totalDistance=(I.totalDistance||0)+R.totalDistance),R.totalElapsedTime&&(I.totalElapsedTime=(I.totalElapsedTime||0)+R.totalElapsedTime),R.totalMovingTime&&(I.totalMovingTime=(I.totalMovingTime||0)+R.totalMovingTime),R.totalTimerTime&&(I.totalTimerTime=(I.totalTimerTime||0)+R.totalTimerTime),R.maxSpeed&&(I.maxSpeed=Math.max(I.maxSpeed||0,R.maxSpeed)),R.avgSpeed&&(I.avgSpeed?I.avgSpeed=(I.avgSpeed+R.avgSpeed)/2:I.avgSpeed=R.avgSpeed),R.maxHeartRate&&(I.maxHeartRate=Math.max(I.maxHeartRate||0,R.maxHeartRate)),R.minHeartRate&&(I.minHeartRate=I.minHeartRate?Math.min(I.minHeartRate,R.minHeartRate):R.minHeartRate),R.avgHeartRate&&(I.avgHeartRate?I.avgHeartRate=(I.avgHeartRate+R.avgHeartRate)/2:I.avgHeartRate=R.avgHeartRate),R.maxAltitude&&(I.maxAltitude=Math.max(I.maxAltitude||0,R.maxAltitude)),R.minAltitude&&(I.minAltitude=I.minAltitude?Math.min(I.minAltitude,R.minAltitude):R.minAltitude),R.avgAltitude&&(I.avgAltitude?I.avgAltitude=(I.avgAltitude+R.avgAltitude)/2:I.avgAltitude=R.avgAltitude),R.totalAscent&&(I.totalAscent=(I.totalAscent||0)+R.totalAscent),R.totalDescent&&(I.totalDescent=(I.totalDescent||0)+R.totalDescent),R.maxCadence&&(I.maxCadence=Math.max(I.maxCadence||0,R.maxCadence)),R.avgCadence&&(I.avgCadence?I.avgCadence=(I.avgCadence+R.avgCadence)/2:I.avgCadence=R.avgCadence),R.maxPower&&(I.maxPower=Math.max(I.maxPower||0,R.maxPower)),R.avgPower&&(I.avgPower?I.avgPower=(I.avgPower+R.avgPower)/2:I.avgPower=R.avgPower),R.totalWork&&(I.totalWork=(I.totalWork||0)+R.totalWork),R.maxTemperature&&(I.maxTemperature=Math.max(I.maxTemperature||0,R.maxTemperature)),R.minTemperature&&(I.minTemperature=I.minTemperature?Math.min(I.minTemperature,R.minTemperature):R.minTemperature),R.avgTemperature&&(I.avgTemperature?I.avgTemperature=(I.avgTemperature+R.avgTemperature)/2:I.avgTemperature=R.avgTemperature)}return I}preprocessRecords(_){if(!_||_.length===0)return _;let I=_.filter(L=>L.timestamp).sort((L,t)=>L.timestamp.valueOf()-t.timestamp.valueOf()),A=0,T=0,R=[];for(let L=0;L<I.length;L++){let t=I[L],E={...t};if(L>0){let D=this.calculatePointDistanceByPosition(I[L-1],E)||0;if(E.distance||(T+=D,E.distance=T),t.speed||(E.speed=this.calculateInstantSpeed(I[L-1],E,D)),t.power){let H=this.calculateAccumulatedPower(I[L-1],E,A);E.accumulatedPower=H.accumulatedPower,A=H.newAccumulatedWork}}R.push(E)}return R}calculatePointDistanceByPosition(_,I){if(!(!_.positionLat||!_.positionLong||!I.positionLat||!I.positionLong))try{return PI({latitude:_.positionLat,longitude:_.positionLong},{latitude:I.positionLat,longitude:I.positionLong})}catch{return}}calculateInstantSpeed(_,I,A){if(!_.timestamp||!I.timestamp||!A)return;let T=(N_(I.timestamp).valueOf()-N_(_.timestamp).valueOf())/1e3;if(!(T<=0))return A/T}calculateAccumulatedPower(_,I,A){var E,D;if(_.power===void 0||I.power===void 0||!_.timestamp||!I.timestamp)return{accumulatedPower:A,newAccumulatedWork:A};let T=((E=I.timestamp)==null?void 0:E.valueOf())-((D=_.timestamp)==null?void 0:D.valueOf());if(T<=0)return{accumulatedPower:A,newAccumulatedWork:A};let L=(_.power+I.power)/2*T,t=A+L;return{accumulatedPower:t,newAccumulatedWork:t}}calculateElevationChanges(_,I){let A=0,T=0;return I.altitude!==void 0&&_.altitude!==void 0&&(I.altitude>_.altitude?A=I.altitude-_.altitude:I.altitude<=_.altitude&&(T=_.altitude-I.altitude)),{ascent:A,descent:T}}};function f(n,_=0){let I=Math.pow(10,_);return Math.round(n*I)/I}var k=class extends ${constructor(){super(...arguments);this.name="gpx-to-activity-converter";this.supportedTags=["gpx"];this.convertGPXExtensions=I=>{let A={};return Object.entries(I).forEach(([T,R])=>{if(typeof R<"u"&&R!=="undefined"){let L=AI[T]||T;A[L]=this.autoNumber(R)}}),A}}convert(I,A){if(A.sourceFormat!=="gpx")return;let T=A.sourceData;return this.convertGPX(T)}convertGPX(I){let A={metadata:{originType:"GPX",fileType:"gpx"},activities:[]};return I.wpt&&(A.points=this.convertWpts2Points(I.wpt)),I.trk&&(A.activities=I.trk.map((T,R)=>this.convertTrk2Activity(T,R))),I.rte&&(A.routes=I.rte.map((T,R)=>this.convertTrackSeg2Lap(T,R))),A}convertPoint(I,A,T){let{extensions:R}=I,L=R?this.convertGPXExtensions(R):{};return{lapIndex:T||0,index:A||0,positionLat:I==null?void 0:I.lat,positionLong:I==null?void 0:I.lon,altitude:I==null?void 0:I.ele,heartRate:I==null?void 0:I.heartRate,speed:I==null?void 0:I.speed,power:I==null?void 0:I.power,cadence:I==null?void 0:I.cadence,timestamp:TI(I.time).toDate(),...L}}convertTrk2Activity(I,A){var L;let T=((L=I.trkseg)==null?void 0:L.map((t,E)=>this.convertTrackSeg2Lap(t,E)))||[],R=new d().calculateLapAggMetrics(T);return{index:A,messageIndex:A,laps:T,...R}}convertTrackSeg2Lap(I,A){var t,E;let T=((E=(t=I.trkpt)==null?void 0:t.filter(D=>D!==void 0&&D.time))==null?void 0:E.map((D,H)=>this.convertPoint(D,H,A)))||[],L=new d().calculateRecordsAggMetrics(T);return{index:A,messageIndex:A,...L,records:(L==null?void 0:L.records)||[],lengths:[]}}convertWpts2Points(I){let A=[];for(let T=0;T<I.length;T++){let R=this.convertPoint(I[T],T);R&&A.push(R)}return A}autoNumber(I){return typeof I=="string"&&I.trim()!==""&&!isNaN(I)?Number(I):I}},Z=class extends ${constructor(){super(...arguments);this.name="fit-to-activity-converter";this.supportedTags=["fit"]}convert(I,A){if(A.sourceFormat!=="fit")return;let T=A.sourceData;return this.convertFIT(T)}convertFIT(I){var T,R;let A={metadata:{originType:"FIT",fileType:"fit"},activities:[]};return(T=I.sessionMesgs)!=null&&T.length?A.activities=I.sessionMesgs.map((L,t)=>({index:t,...L,startPositionLat:L!=null&&L.startPositionLat?f(o(Number(L.startPositionLat)),6):void 0,startPositionLong:L!=null&&L.startPositionLong?f(o(Number(L.startPositionLong)),6):void 0,endPositionLat:L!=null&&L.endPositionLat?f(o(Number(L.endPositionLat)),6):void 0,endPositionLong:L!=null&&L.endPositionLong?f(o(Number(L.endPositionLong)),6):void 0,laps:this.convertFITLap2Trackseg(L==null?void 0:L.lapMesgs)})):(R=I.courseMesgs)!=null&&R.length&&(A.routes=I.courseMesgs.map((L,t)=>({index:t,...L,records:this.convertLap2Points(L==null?void 0:L.lapMesgs)}))),A}convertPoint(I,A,T){let{positionLong:R,positionLat:L,altitude:t,enhancedAltitude:E,enhancedSpeed:D,speed:H,...C}=I;return{lapIndex:T||0,index:A||0,positionLat:L?f(o(Number(L)),6):void 0,positionLong:R?f(o(Number(R)),6):void 0,altitude:t||void 0,enhancedAltitude:E||void 0,speed:H||void 0,enhancedSpeed:D||void 0,...C}}convertFITLap2Trackseg(I){var T,R;let A=[];if(!(I!=null&&I.length))return[];for(let L=0;L<I.length;L++){let t=I[L],E=((T=t==null?void 0:t.recordMesgs)==null?void 0:T.map((H,C)=>this.convertPoint(H,C,L)).filter(H=>H!==void 0))||[],D=((R=t==null?void 0:t.lengthMesgs)==null?void 0:R.map((H,C)=>({...H,index:C})))||[];A.push({index:L,...t,startPositionLat:t!=null&&t.startPositionLat?f(o(Number(t.startPositionLat)),6):void 0,startPositionLong:t!=null&&t.startPositionLong?f(o(Number(t.startPositionLong)),6):void 0,endPositionLat:t!=null&&t.endPositionLat?f(o(Number(t.endPositionLat)),6):void 0,endPositionLong:t!=null&&t.endPositionLong?f(o(Number(t.endPositionLong)),6):void 0,records:E,lengths:D})}return A}convertLap2Points(I){var T;let A=[];if(!(I!=null&&I.length))return[];for(let R=0;R<I.length;R++){let t=((T=I[R].recordMesgs)==null?void 0:T.map((E,D)=>this.convertPoint(E,D,R)).filter(E=>E!==void 0))||[];t.length&&(A=[...A,...t])}return A}},q=class extends ${constructor(){super(...arguments);this.name="tcx-to-activity-converter";this.supportedTags=["tcx"]}convert(I,A){if(A.sourceFormat!=="tcx")return;let T=A.sourceData;return this.convertTCX(T)}convertTCX(I){var T,R,L,t;let A={metadata:{originType:"TCX",fileType:"tcx"},activities:[]};return(R=(T=I.Activities)==null?void 0:T.Activity)!=null&&R.length&&(A.activities=I.Activities.Activity.map((E,D)=>this.convertTCXActivityToActivity(E,D))),(t=(L=I.Courses)==null?void 0:L.Course)!=null&&t.length,A}convertTCXActivityToActivity(I,A){var L;let T=((L=I.Lap)==null?void 0:L.map((t,E)=>this.convertTCXLap2Lap(t,E)))||[],R=new d().calculateLapAggMetrics(T);return{index:A,messageIndex:A,laps:T,...R}}convertTCXLap2Lap(I,A){var E;let T=((E=I==null?void 0:I.Track)==null?void 0:E.flatMap(D=>D.Trackpoint))||[],R=(T==null?void 0:T.filter(D=>D!==void 0&&D.Time!==void 0).map((D,H)=>this.convertPoint(D,H)))||[],t=new d().calculateRecordsAggMetrics(R);return{index:A,messageIndex:A,...t,records:(t==null?void 0:t.records)||[],lengths:[]}}convertPoint(I,A,T){let{Position:R,Time:L,DistanceMeters:t,AltitudeMeters:E}=I;return{lapIndex:T||0,index:A||0,positionLat:R!=null&&R.LatitudeDegrees?Number(R.LatitudeDegrees):void 0,positionLong:R!=null&&R.LongitudeDegrees?Number(R.LongitudeDegrees):void 0,timestamp:TI(L).toDate(),distance:t,altitude:E}}};import hI from"dayjs";var y=class extends b{constructor(){super(...arguments);this.name="activity-to-gpx-encoder";this.supportedTags=["gpx"]}encode(I,A){var L,t,E,D,H;if(A.targetFormat!=="gpx"||!((L=I==null?void 0:I.activities)!=null&&L.length))return;let R={version:"1.1",creator:"TrackSwap",metadata:{time:((t=I.activities)==null?void 0:t[0]).timestamp}};return(E=I.points)!=null&&E.length&&(R.wpt=this.convertRecords2Wpts(I.points)),(D=I.routes)!=null&&D.length&&(R.rte=I.routes.map(C=>this.convertRoute2GPXRoute(C))),(H=I.activities)!=null&&H.length&&(R.trk=I.activities.map(C=>this.convertActivity2GPXTrack(C))),R}convertRecords2Wpts(I){return I==null?void 0:I.filter(A=>A.timestamp).map(A=>({lat:A==null?void 0:A.positionLat,lon:A==null?void 0:A.positionLong,ele:A==null?void 0:A.altitude,time:A==null?void 0:A.timestamp,speed:A==null?void 0:A.speed,hdop:A==null?void 0:A.hdop,vdop:A==null?void 0:A.vdop,pdop:A==null?void 0:A.pdop,extensions:this.extractGPXExtensions(A)}))}convertRoute2GPXRoute(I){return{rtept:I.records?this.convertRecords2Wpts(I.records):[]}}convertActivity2GPXTrack(I){var A;return{trkseg:((A=I.laps)==null?void 0:A.map(T=>({trkpt:T.records?this.convertRecords2Wpts(T.records):[]})))||[]}}extractGPXExtensions(I){let A={},T={};return typeof(I==null?void 0:I.heartRate)<"u"&&(T["gpxtpx:hr"]=I.heartRate),typeof(I==null?void 0:I.cadence)<"u"&&(T["gpxtpx:cad"]=I.cadence),typeof(I==null?void 0:I.temperature)<"u"&&(T["gpxtpx:atemp"]=I.temperature),Object.keys(T).length>0&&(A["gpxtpx:TrackPointExtension"]=T),typeof(I==null?void 0:I.power)<"u"&&(A["gpxpx:PowerExtension"]={"gpxpx:PowerInWatts":I.power}),Object.keys(A).length>0?A:void 0}},s=class extends b{constructor(){super(...arguments);this.name="activity-to-fit-encoder";this.supportedTags=["fit"]}encode(I,A){var R,L;if(A.targetFormat!=="fit"||!((R=I==null?void 0:I.activities)!=null&&R.length))return;let T={};return T.sessionMesgs=(L=I.activities)==null?void 0:L.map(t=>this.convertActivity2FITSession(t)),T}convertActivity2FITSession(I){var T;return{...I,event:(I==null?void 0:I.event)||"session",sport:(I==null?void 0:I.sport)||"generic",lapMesgs:((T=I.laps)==null?void 0:T.map(R=>this.convertLap2FITLap(R)))||[]}}convertLap2FITLap(I){var T;return{startTime:I.startTime,...I,recordMesgs:((T=I.records)==null?void 0:T.map(R=>this.convertPoint2FITRecord(R)))||[]}}convertPoint2FITRecord(I){return I}},u=class extends b{constructor(){super(...arguments);this.name="sport-to-tcx-encoder";this.supportedTags=["tcx"]}encode(I,A){var R;if(A.targetFormat!=="tcx"||!((R=I==null?void 0:I.activities)!=null&&R.length))return;let T={Author:{Name:"TrackSwap"}};return T.Activities={Activity:I.activities.map(L=>this.convertActivity2TCXActivity(L))},T}convertActivity2TCXActivity(I){var T;let A="Other";return(I.sport==="Running"||I.sport==="Biking")&&(A=I.sport),{Id:`Activity_${Date.now()}`,Activity:A,Lap:((T=I.laps)==null?void 0:T.map(R=>this.convertLap2TCXLap(R)))||[]}}convertLap2TCXLap(I){let A={TotalTimeSeconds:I.totalElapsedTime,DistanceMeters:I.totalDistance,MaximumSpeed:I.maxSpeed,Calories:I.totalCalories,AverageHeartRateBpm:I.avgHeartRate,MaximumHeartRateBpm:I.maxHeartRate,Intensity:"Active",TriggerMethod:"Manual",Track:I.records?[this.convertRecords2TCXTrack(I.records)]:[]};return(I.avgCadence!==void 0||I.maxCadence!==void 0)&&(A.Cadence={Low:I.avgCadence||0,High:I.maxCadence||0}),A}convertRecords2TCXTrack(I){return{Trackpoint:I.map(A=>this.convertPoint2TCXTrackpoint(A))}}convertPoint2TCXTrackpoint(I){var T,R;let A={Time:hI(I.timestamp).toISOString(),Position:{LatitudeDegrees:(T=I==null?void 0:I.positionLat)==null?void 0:T.toString(),LongitudeDegrees:(R=I==null?void 0:I.positionLong)==null?void 0:R.toString()},AltitudeMeters:I.altitude,DistanceMeters:I.distance};return I.heartRate&&(A.HeartRateBpm=I.heartRate),I.cadence&&(A.Cadence={Low:I.cadence,High:I.cadence256||I.cadence}),I.power&&(A.Extensions={"ns3:TPX":{"ns3:Watts":I.power}}),A}convertRoute2TCXCourse(I){return{Name:`Course_${Date.now()}`,Track:I.records?[this.convertRecords2TCXTrack(I.records)]:[]}}};var i=class{constructor(){this.converters=new Map;this.encoders=new Map;this.registerDefaultConverters(),this.registerDefaultEncoders()}registerDefaultConverters(){this.registerConverter(new k),this.registerConverter(new Z),this.registerConverter(new q)}registerDefaultEncoders(){this.registerEncoder(new y),this.registerEncoder(new s),this.registerEncoder(new u)}registerConverter(_){this.converters.set(_.name,_)}registerEncoder(_){this.encoders.set(_.name,_)}async convertToActivity(_,I){let A={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},sourceFormat:I,sourceData:_,performance:{startTime:Date.now()}};try{let T=this.findConverter(I);if(!T)throw new Error(`No converter found for format "${I}"`);let R=Date.now(),L=T.convert(_,A);if(A.performance.convertTime=Date.now()-R,!L)throw new Error(`Converter "${T.name}" returned empty result`);let t=L;return A.result=t,A.performance.endTime=Date.now(),A.stats.endTime=Date.now(),t}catch(T){throw A.errors.push(T),T}}async encodeActivity(_,I){let A={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},targetFormat:I,performance:{startTime:Date.now()}};try{let T=this.findEncoder(I);if(!T)throw new Error(`No encoder found for format "${I}"`);let R=Date.now(),L=T.encode(_,A);if(A.performance.encodeTime=Date.now()-R,!L)throw new Error(`Encoder "${T.name}" returned empty result`);return A.result=L,A.performance.endTime=Date.now(),A.stats.endTime=Date.now(),L}catch(T){throw A.errors.push(T),T}}findConverter(_){return Array.from(this.converters.values()).find(I=>{var A;return(A=I.supportedTags)==null?void 0:A.includes(_)})}findEncoder(_){return Array.from(this.encoders.values()).find(I=>{var A;return(A=I.supportedTags)==null?void 0:A.includes(_)})}async destroy(){this.converters.clear(),this.encoders.clear()}};var m=class{constructor(){this.gpxDecoder=new h,this.gpxEncoder=new l,this.fitDecoder=new X,this.fitEncoder=new g,this.tcxDecoder=new Y,this.tcxEncoder=new v,this.activityProcessor=new i}async parseGPX(_){try{return await this.gpxDecoder.parserByBuffer(_)}catch(I){throw new Error(`GPX parsing failed: ${I.message}`)}}async parseGPXString(_){let I=Buffer.from(_,"utf-8");return this.parseGPX(I)}async encodeGPX(_){try{return await this.gpxEncoder.encode(_)}catch(I){throw new Error(`GPX encoding failed: ${I.message}`)}}encodeGPXString(_){try{return this.gpxEncoder.encodeToString(_)}catch(I){throw new Error(`GPX encoding failed: ${I.message}`)}}async parseFIT(_){try{return await this.fitDecoder.parseByBuffer(_)}catch(I){throw new Error(`FIT parsing failed: ${I.message}`)}}async encodeFIT(_){try{return await this.fitEncoder.encode(_)}catch(I){throw new Error(`FIT encoding failed: ${I.message}`)}}async encodeFITCourse(_){try{return await this.convertToFITCourse(_)}catch(I){throw new Error(`FIT Course encoding failed: ${I.message}`)}}async convertFITToCourse(_){try{return await this.encodeFITCourse(_)}catch(I){throw new Error(`FIT to Course conversion failed: ${I.message}`)}}async convertToFITCourse(_,I){try{let A=await this.parseToActivity(_,I);if(!A)throw new Error("Activity conversion result is empty");let T=this.buildCoursePlanFromActivityFile(A),R=R_(T);return Buffer.from(R)}catch(A){throw new Error(`File to FIT Course conversion failed: ${A.message}`)}}buildCoursePlanFromActivityFile(_){var R,L,t;let I=(R=_.activities)==null?void 0:R[0],T=[...(((L=_.activities)==null?void 0:L.flatMap(E=>E.laps??[]))??[]).flatMap(E=>E.records??[]),...((t=_.routes)==null?void 0:t.flatMap(E=>E.records??[]))??[],..._.points??[]].filter(E=>E.timestamp!=null&&E.positionLat!=null&&E.positionLong!=null).sort((E,D)=>{let H=new Date(E.timestamp).getTime(),C=new Date(D.timestamp).getTime();return H-C}).map(E=>({timestamp:E.timestamp,latitude:E.positionLat,longitude:E.positionLong,distance:E.distance,altitude:E.enhancedAltitude??E.altitude,speed:E.enhancedSpeed??E.speed}));if(T.length===0)throw new Error("Cannot build CoursePlan: no valid activity records with timestamp and coordinates.");return{name:this.resolveCourseName(_),sport:this.toEnumValue(I_,I==null?void 0:I.sport)??2,subSport:this.toEnumValue(A_,I==null?void 0:I.subSport)??0,records:T,timeCreated:T[0].timestamp}}resolveCourseName(_){var T,R,L;let I=(R=(T=_.metadata)==null?void 0:T.fileName)==null?void 0:R.trim();if(I)return I;let A=(L=_.metadata)==null?void 0:L.originType;return A?`${A.toLowerCase()}-course`:"course"}toEnumValue(_,I){if(!I)return;let A=I.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();for(let T of Object.keys(_))if(Number.isNaN(Number(T))&&T.toUpperCase()===A){let R=_[T];return typeof R=="number"?R:void 0}}async parseTCXString(_){let I=Buffer.from(_,"utf-8");return this.parseTCX(I)}async parseTCX(_){try{let I=await this.tcxDecoder.parseByBuffer(_);if(!I)throw new Error("TCX parsing result is empty");return I}catch(I){throw new Error(`TCX parsing failed: ${I.message}`)}}async encodeTCX(_){try{return await this.tcxEncoder.encode(_)}catch(I){throw new Error(`TCX encoding failed: ${I.message}`)}}async encodeTCXString(_){try{return await this.tcxEncoder.encodeToString(_)}catch(I){throw new Error(`TCX encoding failed: ${I.message}`)}}async convertGPXToActivity(_){return await this.activityProcessor.convertToActivity(_,"gpx")}async convertFITToActivity(_){return await this.activityProcessor.convertToActivity(_,"fit")}async convertTCXToActivity(_){return await this.activityProcessor.convertToActivity(_,"tcx")}async convertActivityToGPX(_){return await this.activityProcessor.encodeActivity(_,"gpx")}async convertActivityToFIT(_){return await this.activityProcessor.encodeActivity(_,"fit")}async convertActivityToTCX(_){return await this.activityProcessor.encodeActivity(_,"tcx")}async convertFile(_,I,A){try{let T=A||this.detectFormat(_);if(T==="unknown"||T==null)throw new Error("Unable to recognize source file format, please specify sourceType parameter");if(T===I)return _;let R;switch(T){case"gpx":let t=await this.parseGPX(_);if(!t)throw new Error("GPX file parsing failed");R=t;break;case"fit":R=await this.parseFIT(_);break;case"tcx":R=await this.parseTCX(_);break;default:throw new Error(`Unsupported source file format: ${T}`)}let L;switch(T){case"gpx":L=await this.convertGPXToActivity(R);break;case"fit":L=await this.convertFITToActivity(R);break;case"tcx":L=await this.convertTCXToActivity(R);break;default:throw new Error(`Unsupported source file format conversion: ${T}`)}switch(I){case"gpx":let t=await this.convertActivityToGPX(L);return await this.encodeGPX(t);case"fit":let E=await this.convertActivityToFIT(L);return await this.encodeFIT(E);case"tcx":let D=await this.convertActivityToTCX(L);return await this.encodeTCX(D);default:throw new Error(`Unsupported target file format: ${I}`)}}catch(T){let R=A||"auto-detect";throw new Error(`${R} to ${I.toUpperCase()} failed: ${T.message}`)}}detectFormat(_){let I=_.toString("utf-8",0,Math.min(1024,_.length));if(_.length>=12&&_.toString("ascii",8,12)===".FIT")return"fit";if(I.includes("<?xml")){if(I.includes("<gpx")||I.includes("http://www.topografix.com/GPX/"))return"gpx";if(I.includes("<TrainingCenterDatabase")||I.includes("http://www.garmin.com/xmlschemas/TrainingCenterDatabase/"))return"tcx"}return"unknown"}async parseFile(_,I){let A=I||this.detectFormat(_);if(A==="unknown")throw new Error("Unable to recognize file format, please specify sourceType parameter");switch(A){case"gpx":let T=await this.parseGPX(_);if(!T)throw new Error("GPX parsing failed");return T;case"fit":return await this.parseFIT(_);case"tcx":return await this.parseTCX(_);default:throw new Error(`Unsupported file format: ${A}`)}}async parseToActivity(_,I){let A=I||this.detectFormat(_);if(A==="unknown")throw new Error("Unable to recognize file format, please specify sourceType parameter");let T;switch(A){case"gpx":let R=await this.parseGPX(_);if(!R)throw new Error("GPX parsing failed");T=await this.convertGPXToActivity(R);break;case"fit":let L=await this.parseFIT(_);L&&(T=await this.convertFITToActivity(L));break;case"tcx":let t=await this.parseTCX(_);T=await this.convertTCXToActivity(t);break;default:throw new Error(`Unsupported file format: ${A}`)}return T}getActivityProcessor(){return this.activityProcessor}getGPXDecoder(){return this.gpxDecoder}getGPXEncoder(){return this.gpxEncoder}getFITDecoder(){return this.fitDecoder}getFITEncoder(){return this.fitEncoder}getTCXDecoder(){return this.tcxDecoder}getTCXEncoder(){return this.tcxEncoder}async destroy(){await this.gpxDecoder.destroy(),await this.fitDecoder.destroy(),await this.tcxDecoder.destroy(),await this.activityProcessor.destroy()}};var fR=m;export{i as ActivityProcessor,s as ActivityToFITEncoder,y as ActivityToGPXEncoder,u as ActivityToTCXEncoder,$ as BaseActivityConverter,b as BaseActivityEncoder,II as BaseActivityMiddleware,X as FITDecoder,g as FITEncoder,Z as FITToActivityConverter,h as GPXDecoder,l as GPXEncoder,k as GPXToActivityConverter,B_ as PipelineStage,Y as TCXDecoder,v as TCXEncoder,q as TCXToActivityConverter,m as TrackSwap,j_ as buildCourseMesgs,fR as default,R_ as encodeCourse,a_ as registerDefaultMiddlewares};
26
+ `)}buildWorkouts(_){return"<Workouts></Workouts>"}buildCourses(_){let I=["<Courses>"];return _.Course?.length&&_.Course.forEach(t=>{I.push(this.buildCourseElement(t))}),I.push("</Courses>"),I.join(`
27
+ `)}buildCourseElement(_){let I=["<Course>"];return this.addOptionalElement(I,"Name",_.Name),this.addOptionalElement(I,"Notes",_.Notes),_.Lap?.length&&_.Lap.forEach(t=>{I.push(this.buildCourseLap(t))}),_.Track?.length&&_.Track.forEach(t=>{I.push(this.buildTrack(t))}),_.CoursePoint?.length&&_.CoursePoint.forEach(t=>{I.push(this.buildCoursePoint(t))}),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.push("</Course>"),I.join(`
28
+ `)}buildCourseLap(_){let I=["<Lap>"];this.addOptionalNumericElement(I,"TotalTimeSeconds",_.TotalTimeSeconds),this.addOptionalNumericElement(I,"DistanceMeters",_.DistanceMeters),I.push(this.wrapGeoTag("BeginPosition",_.BeginPosition)),I.push(this.wrapGeoTag("EndPosition",_.EndPosition)),this.addOptionalNumericElement(I,"BeginAltitudeMeters",_.BeginAltitudeMeters),this.addOptionalNumericElement(I,"EndAltitudeMeters",_.EndAltitudeMeters);let t=_;return t.Track?.length&&t.Track.forEach(A=>{I.push(this.buildTrack(A))}),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.push("</Lap>"),I.join(`
29
+ `)}buildCoursePoint(_){let I=["<CoursePoint>"];return this.addOptionalElement(I,"Name",_.Name),_.Time!==void 0&&_.Time!==null&&I.push(`<Time>${_.Time}</Time>`),_.Position&&I.push(this.buildPosition(_.Position)),this.addOptionalNumericElement(I,"AltitudeMeters",_.AltitudeMeters),this.addOptionalElement(I,"PointType",_.PointType),this.addOptionalElement(I,"Notes",_.Notes),_.Extensions&&I.push(this.buildExtensions(_.Extensions)),I.push("</CoursePoint>"),I.join("")}buildAuthor(_){let I=["<Author>"];return this.addOptionalElement(I,"Name",_.Name),I.push("</Author>"),I.join("")}buildExtensions(_){let I=this.buildExtensionContent(_);return I?`<Extensions>${I}</Extensions>`:""}buildExtensionContent(_){return Object.entries(_).filter(([I])=>!I.startsWith("xmlns")).map(([I,t])=>{if(t&&typeof t=="object"){let A=this.buildExtensionContent(t);return`<${I}>${A}</${I}>`}else if(t!=null)return`<${I}>${this.escapeXML(String(t))}</${I}>`;return""}).filter(I=>I).join("")}formatTime(_){let I=sI(_);if(!I.isValid())throw new Error(`Cannot encode invalid TCX timestamp: ${String(_)}`);return I.toISOString()}addOptionalElement(_,I,t,A){if(t!=null&&t!==""){let T=A?A(t):this.escapeXML(t);_.push(`<${I}>${T}</${I}>`)}}addOptionalNumericElement(_,I,t){t!=null&&!isNaN(t)&&_.push(`<${I}>${t}</${I}>`)}isValidCoordinate(_,I){return _!=null&&I!==void 0&&I!==null&&!isNaN(_)&&!isNaN(I)}formatCoordinate(_){return this.roundTo(_,6).toString()}roundTo(_,I){let t=Math.pow(10,I);return Math.round(_*t)/t}escapeXML(_){return _.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(_){return typeof _!="string"?String(_||""):_.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/'/g,"&apos;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\r/g,"&#13;").replace(/\n/g,"&#10;").replace(/\t/g,"&#9;")}deepClone(_){if(_===null||typeof _!="object")return _;if(_ instanceof Date)return new Date(_.getTime());if(Array.isArray(_))return _.map(t=>this.deepClone(t));let I={};for(let t in _)Object.prototype.hasOwnProperty.call(_,t)&&(I[t]=this.deepClone(_[t]));return I}encoder(_){return this.encode(_)}};import Gt from"dayjs";var i=class extends z{convertPoints(_){return _.map(I=>this.convertPoint(I)).filter(I=>I!==void 0)}convertTime(_){if(!_)return;if(typeof _=="number")return _;let I=Gt(_);return I.isValid()?I.valueOf():void 0}},r=class{constructor(){this.version="1.0.0";this.priority=100}supports(_){return this.supportedTags.includes(_)}async initialize(_){_.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(_){_.metadata.delete(`plugin:${this.name}:initialized`)}async validate(_){return!0}convertTimeToDate(_){return _?new Date(_):new Date}convertTimeToString(_){return this.convertTimeToDate(_).toISOString()}ensureValidCoordinates(_,I){return _>=-90&&_<=90&&I>=-180&&I<=180}round(_,I=6){let t=Math.pow(10,I);return Math.round(_*t)/t}};var bI={heartrate:"heartRate","gpxtpx:hr":"heartRate","ns3:hr":"heartRate","gpxdata:hr":"heartRate","gpxdata:cadence":"cadence","gpxtpx:cad":"cadence","ns3:cad":"cadence",cadence:"cadence","gpxtpx:speed":"speed","ns3:speed":"speed",speed:"speed",power:"power","gpxdata:power":"power","gpxpx:PowerInWatts":"power",PowerInWatts:"power","gpxtpx:temp":"temperature","gpxtpx:wtemp":"wtemp","gpxtpx:atemp":"atemp","gpxx:Temperature":"temperature","gpxx:Depth":"depth"},NI=n=>n*(180/Math.pow(2,31)),$I=2147483647;function $(n,_=6){if(n==null)return;let I=typeof n=="number"?n:Number(n);if(!Number.isFinite(I)||I===$I)return;let t=NI(I),A=Math.pow(10,_);return Math.round(t*A)/A}import i_ from"dayjs";import u_ from"dayjs";import{getPreciseDistance as gt}from"geolib";var j=class{calculateRecordsAggMetrics(_){if(!_||_.length===0)return;let I={records:this.preprocessRecords(_)};for(let t=0;t<I.records.length;t++){let A=I.records[t];if(!(A.positionLat==null||A.positionLong==null||!Number.isFinite(A.positionLat)||!Number.isFinite(A.positionLong))){if(I.startPositionLat==null&&(I.startPositionLat=A.positionLat),I.startPositionLong==null&&(I.startPositionLong=A.positionLong),I.endPositionLat=A.positionLat,I.endPositionLong=A.positionLong,I.timestamp=A.timestamp,I?.startTime||(I.startTime=A.timestamp),I.endTime=A.timestamp,I.totalDistance=A.distance,I.totalElapsedTime=u_(A.timestamp).diff(u_(I.startTime),"second"),A?.speed&&(I.avgSpeed=I.avgSpeed?(I.avgSpeed+A.speed)/2:A.speed,I.maxSpeed=Math.max(I.maxSpeed||0,A.speed)),A?.heartRate&&(I.maxHeartRate=Math.max(I.maxHeartRate||0,A.heartRate),I.minHeartRate=Math.min(I.minHeartRate||A.heartRate,A.heartRate),I.avgHeartRate?I.avgHeartRate=(I.avgHeartRate+A.heartRate)/2:I.avgHeartRate=A.heartRate),A?.altitude&&(I.maxAltitude=Math.max(I.maxAltitude||0,A.altitude),I.minAltitude=Math.min(I.minAltitude||A.altitude,A.altitude),I.avgAltitude=I.avgAltitude?(I.avgAltitude+A.altitude)/2:A.altitude,t>0&&_[t-1].altitude)){let T=this.calculateElevationChanges(_[t-1],A);I.totalAscent=(I.totalAscent||0)+T.ascent,I.totalDescent=(I.totalDescent||0)+T.descent}if(A?.cadence&&(I.maxCadence=Math.max(I.maxCadence||0,A.cadence),I.avgCadence?I.avgCadence=(I.avgCadence+A.cadence)/2:I.avgCadence=A.cadence),A?.power){I.maxPower=Math.max(I.maxPower||0,A.power),I.avgPower?I.avgPower=(I.avgPower+A.power)/2:I.avgPower=A.power;let T=this.calculateAccumulatedPower(t>0?_[t-1]:A,A,I.totalWork||0);I.totalWork=T.newAccumulatedWork,I.normalizedPower=void 0}A?.temperature&&(I.avgTemperature?I.avgTemperature=(I.avgTemperature+A.temperature)/2:I.avgTemperature=A.temperature,I.maxTemperature=Math.max(I.maxTemperature||0,A.temperature),I.minTemperature=Math.min(I.minTemperature||A.temperature,A.temperature))}}return I}calculateLapAggMetrics(_){if(!_||_.length===0)return;let I={laps:_,timestamp:_[0]?.timestamp||new Date};for(let t=0;t<_.length;t++){let A=_[t];A.startPositionLat&&A.startPositionLong&&!I?.startPositionLat&&!I?.startPositionLong&&(I.startPositionLat=A.startPositionLat,I.startPositionLong=A.startPositionLong),A.endPositionLat&&A.endPositionLong&&(I.endPositionLat=A.endPositionLat,I.endPositionLong=A.endPositionLong),A.startTime&&!I?.startTime&&(I.startTime=A.startTime),A.endTime&&(I.endTime=A.endTime),I.timestamp=A.timestamp||A.endTime||I.timestamp,A.totalDistance&&(I.totalDistance=(I.totalDistance||0)+A.totalDistance),A.totalElapsedTime&&(I.totalElapsedTime=(I.totalElapsedTime||0)+A.totalElapsedTime),A.totalMovingTime&&(I.totalMovingTime=(I.totalMovingTime||0)+A.totalMovingTime),A.totalTimerTime&&(I.totalTimerTime=(I.totalTimerTime||0)+A.totalTimerTime),A.maxSpeed&&(I.maxSpeed=Math.max(I.maxSpeed||0,A.maxSpeed)),A.avgSpeed&&(I.avgSpeed?I.avgSpeed=(I.avgSpeed+A.avgSpeed)/2:I.avgSpeed=A.avgSpeed),A.maxHeartRate&&(I.maxHeartRate=Math.max(I.maxHeartRate||0,A.maxHeartRate)),A.minHeartRate&&(I.minHeartRate=I.minHeartRate?Math.min(I.minHeartRate,A.minHeartRate):A.minHeartRate),A.avgHeartRate&&(I.avgHeartRate?I.avgHeartRate=(I.avgHeartRate+A.avgHeartRate)/2:I.avgHeartRate=A.avgHeartRate),A.maxAltitude&&(I.maxAltitude=Math.max(I.maxAltitude||0,A.maxAltitude)),A.minAltitude&&(I.minAltitude=I.minAltitude?Math.min(I.minAltitude,A.minAltitude):A.minAltitude),A.avgAltitude&&(I.avgAltitude?I.avgAltitude=(I.avgAltitude+A.avgAltitude)/2:I.avgAltitude=A.avgAltitude),A.totalAscent&&(I.totalAscent=(I.totalAscent||0)+A.totalAscent),A.totalDescent&&(I.totalDescent=(I.totalDescent||0)+A.totalDescent),A.maxCadence&&(I.maxCadence=Math.max(I.maxCadence||0,A.maxCadence)),A.avgCadence&&(I.avgCadence?I.avgCadence=(I.avgCadence+A.avgCadence)/2:I.avgCadence=A.avgCadence),A.maxPower&&(I.maxPower=Math.max(I.maxPower||0,A.maxPower)),A.avgPower&&(I.avgPower?I.avgPower=(I.avgPower+A.avgPower)/2:I.avgPower=A.avgPower),A.totalWork&&(I.totalWork=(I.totalWork||0)+A.totalWork),A.maxTemperature&&(I.maxTemperature=Math.max(I.maxTemperature||0,A.maxTemperature)),A.minTemperature&&(I.minTemperature=I.minTemperature?Math.min(I.minTemperature,A.minTemperature):A.minTemperature),A.avgTemperature&&(I.avgTemperature?I.avgTemperature=(I.avgTemperature+A.avgTemperature)/2:I.avgTemperature=A.avgTemperature)}return I}preprocessRecords(_){if(!_||_.length===0)return _;let I=_.filter(R=>R.timestamp).sort((R,L)=>R.timestamp.valueOf()-L.timestamp.valueOf()),t=0,A=0,T=[];for(let R=0;R<I.length;R++){let L=I[R],O={...L};if(R>0){let D=this.calculatePointDistanceByPosition(I[R-1],O)||0;if(O.distance||(A+=D,O.distance=A),L.speed||(O.speed=this.calculateInstantSpeed(I[R-1],O,D)),L.power){let g=this.calculateAccumulatedPower(I[R-1],O,t);O.accumulatedPower=g.accumulatedPower,t=g.newAccumulatedWork}}T.push(O)}return T}calculatePointDistanceByPosition(_,I){if(!(_.positionLat==null||_.positionLong==null||I.positionLat==null||I.positionLong==null||!Number.isFinite(_.positionLat)||!Number.isFinite(_.positionLong)||!Number.isFinite(I.positionLat)||!Number.isFinite(I.positionLong)))try{return gt({latitude:_.positionLat,longitude:_.positionLong},{latitude:I.positionLat,longitude:I.positionLong})}catch{return}}calculateInstantSpeed(_,I,t){if(!_.timestamp||!I.timestamp||!t)return;let A=(u_(I.timestamp).valueOf()-u_(_.timestamp).valueOf())/1e3;if(!(A<=0))return t/A}calculateAccumulatedPower(_,I,t){if(_.power===void 0||I.power===void 0||!_.timestamp||!I.timestamp)return{accumulatedPower:t,newAccumulatedWork:t};let A=I.timestamp?.valueOf()-_.timestamp?.valueOf();if(A<=0)return{accumulatedPower:t,newAccumulatedWork:t};let R=(_.power+I.power)/2*A,L=t+R;return{accumulatedPower:L,newAccumulatedWork:L}}calculateElevationChanges(_,I){let t=0,A=0;return I.altitude!==void 0&&_.altitude!==void 0&&(I.altitude>_.altitude?t=I.altitude-_.altitude:I.altitude<=_.altitude&&(A=_.altitude-I.altitude)),{ascent:t,descent:A}}};var r_=class extends i{constructor(){super(...arguments);this.name="gpx-to-activity-converter";this.supportedTags=["gpx"];this.convertGPXExtensions=I=>{let t={};return Object.entries(I).forEach(([A,T])=>{if(typeof T<"u"&&T!=="undefined"){let R=bI[A]||A;t[R]=this.autoNumber(T)}}),t}}convert(I,t){if(t.sourceFormat!=="gpx")return;let A=t.sourceData;return this.convertGPX(A)}convertGPX(I){let t={metadata:{originType:"GPX",fileType:"gpx"},activities:[]};return I.wpt&&(t.points=this.convertWpts2Points(I.wpt)),I.trk&&(t.activities=I.trk.map((A,T)=>this.convertTrk2Activity(A,T))),I.rte&&(t.routes=I.rte.map((A,T)=>this.convertRoute2Lap(A,T))),t}convertPoint(I,t,A){let{extensions:T}=I,R=T?this.convertGPXExtensions(T):{};return{lapIndex:A||0,index:t||0,positionLat:I?.lat,positionLong:I?.lon,altitude:I?.ele,heartRate:I?.heartRate,speed:I?.speed,power:I?.power,cadence:I?.cadence,timestamp:I.time?i_(I.time).toDate():void 0,...R}}convertTrk2Activity(I,t){let A=I.trkseg?.map((R,L)=>this.convertTrackSeg2Lap(R,L))||[],T=new j().calculateLapAggMetrics(A);return{index:t,messageIndex:t,laps:A,...T}}convertTrackSeg2Lap(I,t){return this.convertPoints2Lap(I.trkpt??[],t)}convertRoute2Lap(I,t){return this.convertPoints2Lap(I.rtept??[],t,I.name)}convertPoints2Lap(I,t,A){let T=I.filter(O=>O.time).map((O,D)=>this.convertPoint(O,D,t)),L=new j().calculateRecordsAggMetrics(T);return{index:t,messageIndex:t,routeName:A,...L,records:L?.records||[],lengths:[]}}convertWpts2Points(I){let t=[];for(let A=0;A<I.length;A++){let T=this.convertPoint(I[A],A);T&&t.push(T)}return t}autoNumber(I){return typeof I=="string"&&I.trim()!==""&&!isNaN(I)?Number(I):I}},m_=class extends i{constructor(){super(...arguments);this.name="fit-to-activity-converter";this.supportedTags=["fit"]}convert(I,t){if(t.sourceFormat!=="fit")return;let A=t.sourceData;return this.convertFIT(A)}convertFIT(I){let t={metadata:{originType:"FIT",fileType:"fit"},activities:[]};return I.sessionMesgs?.length?t.activities=I.sessionMesgs.map((A,T)=>({index:T,...A,startPositionLat:$(A?.startPositionLat),startPositionLong:$(A?.startPositionLong),endPositionLat:$(A?.endPositionLat),endPositionLong:$(A?.endPositionLong),laps:this.convertFITLap2Trackseg(A?.lapMesgs)})):I.courseMesgs?.length&&(t.routes=I.courseMesgs.map((A,T)=>({index:T,...A,records:this.convertLap2Points(A?.lapMesgs)}))),t}convertPoint(I,t,A){let{positionLong:T,positionLat:R,altitude:L,enhancedAltitude:O,enhancedSpeed:D,speed:g,...f}=I,W=R??I.position_lat,l=T??I.position_long;return{lapIndex:A||0,index:t||0,positionLat:$(W),positionLong:$(l),altitude:L,enhancedAltitude:O,speed:g,enhancedSpeed:D,...f}}convertFITLap2Trackseg(I){let t=[];if(!I?.length)return[];for(let A=0;A<I.length;A++){let T=I[A],R=T?.recordMesgs?.map((O,D)=>this.convertPoint(O,D,A)).filter(O=>O!==void 0)||[],L=T?.lengthMesgs?.map((O,D)=>({...O,index:D}))||[];t.push({index:A,...T,startPositionLat:$(T?.startPositionLat),startPositionLong:$(T?.startPositionLong),endPositionLat:$(T?.endPositionLat),endPositionLong:$(T?.endPositionLong),records:R,lengths:L})}return t}convertLap2Points(I){let t=[];if(!I?.length)return[];for(let A=0;A<I.length;A++){let R=I[A].recordMesgs?.map((L,O)=>this.convertPoint(L,O,A)).filter(L=>L!==void 0)||[];R.length&&(t=[...t,...R])}return t}},c_=class extends i{constructor(){super(...arguments);this.name="tcx-to-activity-converter";this.supportedTags=["tcx"]}convert(I,t){if(t.sourceFormat!=="tcx")return;let A=t.sourceData;return this.convertTCX(A)}convertTCX(I){let t={metadata:{originType:"TCX",fileType:"tcx"},activities:[]};I.Activities?.Activity?.length&&(t.activities=I.Activities.Activity.map((R,L)=>this.convertTCXActivityToActivity(R,L)));let A=I.Courses?.Course,T=A==null?[]:Array.isArray(A)?A:[A];return T.length&&(t.routes=T.map((R,L)=>this.convertTCXCourseToRoute(R,L))),t}convertTCXCourseToRoute(I,t){let A=[],T=0,R=M=>M==null?[]:Array.isArray(M)?M:[M],L=M=>{for(let V of M??[])for(let H of V.Trackpoint??[])H==null||H.Time===void 0||A.push(this.convertPoint(H,T++,t))};L(R(I.Track));let O=I.Lap==null?[]:Array.isArray(I.Lap)?I.Lap:[I.Lap];for(let M of O)L(R(M.Track));let D=A.length,g=A[0]?.timestamp!=null?i_(A[0].timestamp):i_("2000-01-01T00:00:00Z"),f=I.CoursePoint==null?[]:Array.isArray(I.CoursePoint)?I.CoursePoint:[I.CoursePoint];for(let M of f){let V=this.convertTCXCoursePointToRecord(M,D++,t,g);V&&A.push(V)}let W=new j,l=A.length>0?W.calculateRecordsAggMetrics(A):{records:A};return{index:t,messageIndex:t,routeName:I.Name,...l,records:l?.records??A,lengths:[]}}convertTCXCoursePointToRecord(I,t,A,T){let R=I.Position?.LatitudeDegrees?Number(I.Position.LatitudeDegrees):void 0,L=I.Position?.LongitudeDegrees?Number(I.Position.LongitudeDegrees):void 0;if(R==null&&L==null&&I.AltitudeMeters==null)return;let O=typeof I.Time=="number"&&Number.isFinite(I.Time)?T.add(I.Time,"second").toDate():T.add(t,"second").toDate();return{lapIndex:A,index:t,positionLat:R,positionLong:L,altitude:I.AltitudeMeters,timestamp:O}}convertTCXActivityToActivity(I,t){let A=I.Lap?.map((R,L)=>this.convertTCXLap2Lap(R,L))||[],T=new j().calculateLapAggMetrics(A);return{index:t,messageIndex:t,sport:I.Sport?.toLowerCase(),laps:A,...T}}convertTCXLap2Lap(I,t){let T=(I?.Track?.flatMap(O=>O.Trackpoint)||[])?.filter(O=>O!==void 0&&O.Time!==void 0).map((O,D)=>this.convertPoint(O,D))||[],L=new j().calculateRecordsAggMetrics(T);return{index:t,messageIndex:t,...L,records:L?.records||[],lengths:[]}}convertPoint(I,t,A){let{Position:T,Time:R,DistanceMeters:L,AltitudeMeters:O}=I;return{lapIndex:A||0,index:t||0,positionLat:T?.LatitudeDegrees?Number(T.LatitudeDegrees):void 0,positionLong:T?.LongitudeDegrees?Number(T.LongitudeDegrees):void 0,timestamp:i_(R).toDate(),distance:L,altitude:O}}};import lt from"dayjs";var x_=class extends r{constructor(){super(...arguments);this.name="activity-to-gpx-encoder";this.supportedTags=["gpx"]}encode(I,t){if(t.targetFormat!=="gpx"||!I?.activities?.length&&!I?.routes?.length&&!I?.points?.length)return;let A=I.activities?.[0]?.timestamp??I.routes?.[0]?.records?.[0]?.timestamp??I.points?.[0]?.timestamp??new Date,T=this.countRecordsMissingGpxCoordinates(I),R={version:"1.1",creator:"TrackSwap",metadata:{time:A,...T>0?{desc:`TrackSwap: omitted ${T} trackpoint(s) without valid latitude/longitude.`}:{}}};return I.points?.length&&(R.wpt=this.convertRecords2Wpts(I.points)),I.routes?.length&&(R.rte=I.routes.map(L=>this.convertRoute2GPXRoute(L))),I.activities?.length&&(R.trk=I.activities.map(L=>this.convertActivity2GPXTrack(L))),R}hasValidGpxCoordinates(I){let t=I.positionLat,A=I.positionLong;return typeof t=="number"&&typeof A=="number"&&Number.isFinite(t)&&Number.isFinite(A)&&t>=-90&&t<=90&&A>=-180&&A<=180}countRecordsMissingGpxCoordinates(I){let t=0,A=T=>{for(let R of T??[])R?.timestamp!=null&&(this.hasValidGpxCoordinates(R)||t++)};A(I.points);for(let T of I.activities??[])for(let R of T.laps??[])A(R.records);for(let T of I.routes??[])A(T.records);return t}convertRecords2Wpts(I){return I?.filter(t=>t.timestamp)?.filter(t=>this.hasValidGpxCoordinates(t)).map(t=>({lat:t?.positionLat,lon:t?.positionLong,ele:t?.altitude,time:t?.timestamp,speed:t?.speed,hdop:t?.hdop,vdop:t?.vdop,pdop:t?.pdop,extensions:this.extractGPXExtensions(t)}))??[]}convertRoute2GPXRoute(I){return{rtept:I.records?this.convertRecords2Wpts(I.records):[]}}convertActivity2GPXTrack(I){return{trkseg:I.laps?.map(t=>({trkpt:t.records?this.convertRecords2Wpts(t.records):[]}))||[]}}extractGPXExtensions(I){let t={},A={};return typeof I?.heartRate<"u"&&(A["gpxtpx:hr"]=I.heartRate),typeof I?.cadence<"u"&&(A["gpxtpx:cad"]=I.cadence),typeof I?.temperature<"u"&&(A["gpxtpx:atemp"]=I.temperature),Object.keys(A).length>0&&(t["gpxtpx:TrackPointExtension"]=A),typeof I?.power<"u"&&(t["gpxpx:PowerExtension"]={"gpxpx:PowerInWatts":I.power}),Object.keys(t).length>0?t:void 0}},a_=class extends r{constructor(){super(...arguments);this.name="activity-to-fit-encoder";this.supportedTags=["fit"]}encode(I,t){if(t.targetFormat==="fit"){if(I?.activities?.length){let A={};return A.sessionMesgs=I.activities.map(T=>this.convertActivity2FITSession(T)),A}if(I?.routes?.length){let A={};return A.sessionMesgs=[this.convertRoutesToSyntheticSession(I.routes)],A}}}convertRoutesToSyntheticSession(I){let t=I.map(D=>this.convertLap2FITLap(D)),T=I.flatMap(D=>D.records??[]).filter(D=>D.timestamp!=null).sort((D,g)=>new Date(D.timestamp).getTime()-new Date(g.timestamp).getTime()),R=T[0]?.timestamp??new Date,L=T[T.length-1]?.timestamp??R,O=T.find(D=>D.positionLat!=null&&D.positionLong!=null&&Number.isFinite(D.positionLat)&&Number.isFinite(D.positionLong));return{messageIndex:0,timestamp:L,event:"session",eventType:"stop",startTime:R,startPositionLat:O?.positionLat,startPositionLong:O?.positionLong,sport:"generic",subSport:"generic",lapMesgs:t}}convertActivity2FITSession(I){return{...I,event:I?.event||"session",sport:I?.sport||"generic",lapMesgs:I.laps?.map(A=>this.convertLap2FITLap(A))||[]}}convertLap2FITLap(I){return{startTime:I.startTime,...I,recordMesgs:I.records?.map(A=>this.convertPoint2FITRecord(A))||[]}}convertPoint2FITRecord(I){return I}},e_=class extends r{constructor(){super(...arguments);this.name="sport-to-tcx-encoder";this.supportedTags=["tcx"]}encode(I,t){if(t.targetFormat!=="tcx")return;let A=!!I?.activities?.length,T=!!I?.routes?.length;if(!A&&!T)return;let R={version:"1.0",Author:{Name:"TrackSwap"}};return A&&(R.Activities={Activity:I.activities.map(L=>this.convertActivity2TCXActivity(L))}),T&&(R.Courses={Course:I.routes.map((L,O)=>this.convertRouteToTCXCourse(L,O))}),R}convertActivity2TCXActivity(I){if(!I.laps?.length)throw new Error("Cannot encode a TCX activity without laps");let t="Other",A=I.sport?.toLowerCase();return A==="running"&&(t="Running"),(A==="biking"||A==="cycling")&&(t="Biking"),{Id:this.validTimestamp(I.startTime??I.laps[0]?.startTime??I.laps[0]?.records?.[0]?.timestamp),Sport:t,Lap:I.laps.map(R=>this.convertLap2TCXLap(R))}}convertLap2TCXLap(I){let A={StartTime:this.validTimestamp(I.startTime??I.records?.[0]?.timestamp),TotalTimeSeconds:I.totalElapsedTime,DistanceMeters:I.totalDistance,MaximumSpeed:I.maxSpeed,Calories:I.totalCalories,AverageHeartRateBpm:I.avgHeartRate,MaximumHeartRateBpm:I.maxHeartRate,Intensity:"Active",TriggerMethod:"Manual",Track:I.records?[this.convertRecords2TCXTrack(I.records)]:[]};return(I.avgCadence!==void 0||I.maxCadence!==void 0)&&(A.Cadence={Low:I.avgCadence||0,High:I.maxCadence||0}),A}convertRecords2TCXTrack(I){return{Trackpoint:I.map(t=>this.convertPoint2TCXTrackpoint(t))}}convertPoint2TCXTrackpoint(I){let t={Time:this.validTimestamp(I.timestamp),Position:{LatitudeDegrees:I?.positionLat?.toString(),LongitudeDegrees:I?.positionLong?.toString()},AltitudeMeters:I.altitude,DistanceMeters:I.distance};return I.heartRate&&(t.HeartRateBpm=I.heartRate),I.cadence&&(t.Cadence={Low:I.cadence,High:I.cadence256||I.cadence}),I.power&&(t.Extensions={"ns3:TPX":{"ns3:Watts":I.power}}),t}validTimestamp(I){let t=lt(I);if(!I||!t.isValid())throw new Error("Cannot encode TCX data without valid timestamps");return t.toISOString()}convertRouteToTCXCourse(I,t){return{Name:I.routeName??`Course_${t}`,Track:I.records?[this.convertRecords2TCXTrack(I.records)]:[]}}};var _I=class{constructor(){this.converters=new Map;this.encoders=new Map;this.registerDefaultConverters(),this.registerDefaultEncoders()}registerDefaultConverters(){this.registerConverter(new r_),this.registerConverter(new m_),this.registerConverter(new c_)}registerDefaultEncoders(){this.registerEncoder(new x_),this.registerEncoder(new a_),this.registerEncoder(new e_)}registerConverter(_){this.converters.set(_.name,_)}registerEncoder(_){this.encoders.set(_.name,_)}async convertToActivity(_,I){let t={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},sourceFormat:I,sourceData:_,performance:{startTime:Date.now()}};try{let A=this.findConverter(I);if(!A)throw new Error(`No converter found for format "${I}"`);let T=Date.now(),R=A.convert(_,t);if(t.performance.convertTime=Date.now()-T,!R)throw new Error(`Converter "${A.name}" returned empty result`);let L=R;return t.result=L,t.performance.endTime=Date.now(),t.stats.endTime=Date.now(),L}catch(A){throw t.errors.push(A),A}}async encodeActivity(_,I){let t={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},targetFormat:I,performance:{startTime:Date.now()}};try{let A=this.findEncoder(I);if(!A)throw new Error(`No encoder found for format "${I}"`);let T=Date.now(),R=A.encode(_,t);if(t.performance.encodeTime=Date.now()-T,!R)throw new Error(`Encoder "${A.name}" returned empty result`);return t.result=R,t.performance.endTime=Date.now(),t.stats.endTime=Date.now(),R}catch(A){throw t.errors.push(A),A}}findConverter(_){return Array.from(this.converters.values()).find(I=>I.supportedTags?.includes(_))}findEncoder(_){return Array.from(this.encoders.values()).find(I=>I.supportedTags?.includes(_))}async destroy(){this.converters.clear(),this.encoders.clear()}};var QI=8,Wt=".FIT";function Bt(n){return n.toString("utf8",0,Math.min(n.length,4096)).replace(/^\uFEFF/,"")}function Mt(n){if(n.length>=12&&n.toString("ascii",QI,QI+4)===Wt)return"fit";let _=Bt(n);if(/<gpx\b/i.test(_))return"gpx";if(/<TrainingCenterDatabase\b/i.test(_))return"tcx"}var c=class{constructor(_){this.activities=_}matches(_){return Mt(_)===this.format}},HI=class extends c{constructor(){super(...arguments);this.format="fit"}getDecoder(){return this.decoder??=new O_}getEncoder(){return this.encoder??=new D_}async decode(I,t){let A=await this.getDecoder().parseByBuffer(I,{userData:{fitDocumentOptions:t.fit??{}}});if(!A)throw new Error("FIT decoder returned an empty result");let T=A.fitDocumentMetadata?.detectedKinds??["unknown"],R=T.includes("activity")?await this.activities.convertToActivity(A,"fit"):void 0,L=A.healthDocument?.diagnostics??{parserVersion:e,messageCounts:A.fitDocumentMetadata?.messageCounts??{},recognizedMessageCounts:{},unknownMessageCounts:{},invalidValueCounts:{},warnings:[]},O=A.fileIdMesgs?.[0],D=O,g=A.fileCreatorMesgs?.[0];return{kinds:[...T],facets:{activity:R,health:A.healthDocument},native:A,metadata:{fileType:O?.type,manufacturer:O?.manufacturer,product:O?.garminProduct??O?.product,productName:typeof D?.productName=="string"?D.productName:void 0,serialNumber:O?.serialNumber===void 0?void 0:String(O.serialNumber),createdAt:O?.timeCreated?new Date(O.timeCreated):void 0,softwareVersion:g?.softwareVersion},fitDiagnostics:L,warnings:L.warnings.map(f=>f.message)}}async encodeActivity(I){let t=await this.activities.encodeActivity(I,"fit");return this.getEncoder().encode(t)}async encodeCourse(I){return Buffer.from(pI(MI(I)))}async dispose(){await this.decoder?.destroy()}},oI=class extends c{constructor(){super(...arguments);this.format="gpx"}getDecoder(){return this.decoder??=new w_}getEncoder(){return this.encoder??=new X_}async decode(I){let t=await this.getDecoder().parserByBuffer(I);if(!t)throw new Error("GPX decoder returned an empty result");let A=await this.activities.convertToActivity(t,"gpx"),T=[];return A.activities?.length&&T.push("activity"),A.routes?.length&&T.push("route"),A.points?.length&&T.push("waypoint"),T.length===0&&T.push("unknown"),{kinds:T,facets:{activity:A},native:t,metadata:{title:t.metadata?.name,creator:t.creator,createdAt:t.metadata?.time}}}async encodeActivity(I){let t=await this.activities.encodeActivity(I,"gpx");return this.getEncoder().encode(t)}async dispose(){await this.decoder?.destroy()}},CI=class extends c{constructor(){super(...arguments);this.format="tcx"}getDecoder(){return this.decoder??=new Z_}getEncoder(){return this.encoder??=new q_}async decode(I){let t=await this.getDecoder().parseByBuffer(I);if(!t)throw new Error("TCX decoder returned an empty result");let A=await this.activities.convertToActivity(t,"tcx");return{kinds:A.activities?.length?["activity"]:A.routes?.length?["course"]:["unknown"],facets:{activity:A},native:t,metadata:{creator:t.Author?.Name??t.creator}}}async encodeActivity(I){let t=await this.activities.encodeActivity(I,"tcx");return this.getEncoder().encode(t)}async dispose(){await this.decoder?.destroy()}};function JI(){let n=new _I;return{adapters:[new HI(n),new oI(n),new CI(n)],activities:n}}function kI(n){return n.format==="fit"&&"encodeCourse"in n}var II=class{constructor(_){this.adapters=new Map;for(let I of _){if(this.adapters.has(I.format))throw new s("ADAPTER_CONFLICT",`Multiple adapters registered for format "${I.format}"`,{format:I.format});this.adapters.set(I.format,I)}}get(_){let I=this.adapters.get(_);if(!I)throw new s("FORMAT_UNSUPPORTED",`No adapter registered for format "${_}"`,{format:_});return I}detect(_){for(let I of this.adapters.values())if(I.matches(_))return I.format;throw new s("FORMAT_UNKNOWN","Unable to detect input format")}async dispose(){await Promise.all([...this.adapters.values()].map(_=>_.dispose?.()))}};function UI(n){return typeof n=="string"?Buffer.from(n,"utf8"):Buffer.isBuffer(n)?n:Buffer.from(n.buffer,n.byteOffset,n.byteLength)}function Vt(n){return typeof n=="string"||Buffer.isBuffer(n)||n instanceof Uint8Array}var tI=class{constructor(_={}){this.disposed=!1;let t=[..._.includeBuiltInAdapters===!1?[]:JI().adapters,..._.adapters??[]];this.registry=new II(t)}detect(_){return this.assertActive(),this.registry.detect(UI(_))}async decode(_,I={}){this.assertActive();let t=UI(_),A=I.format??this.registry.detect(t),T=this.registry.get(A),R=Date.now();try{let L=await T.decode(t,I);return{schemaVersion:"2",format:A,kinds:[...new Set(L.kinds)],source:{byteLength:t.byteLength},metadata:L.metadata??{},facets:L.facets,...I.includeNative?{native:L.native}:{},diagnostics:{durationMs:Date.now()-R,warnings:L.warnings??[],fit:L.fitDiagnostics}}}catch(L){throw x(L,"DECODE_FAILED",`Failed to decode ${A.toUpperCase()}`,A)}}async decodeActivity(_,I={}){let t=await this.decode(_,I);if(!t.facets.activity)throw new s("ACTIVITY_NOT_FOUND",`The ${t.format.toUpperCase()} document has no activity facet`,{format:t.format});return t.facets.activity}async encodeActivity(_,I){this.assertActive();try{return await this.registry.get(I.format).encodeActivity(_)}catch(t){throw x(t,"ENCODE_FAILED",`Failed to encode ${I.format.toUpperCase()}`,I.format)}}async transcode(_,I){this.assertActive();let t=UI(_),A=I.sourceFormat??this.registry.detect(t);if(A===I.format)return Buffer.from(t);let T=await this.decodeActivity(t,{format:A});return this.encodeActivity(T,{format:I.format})}async encodeCourse(_,I={}){this.assertActive();let t=Vt(_)?await this.decodeActivity(_,{format:I.sourceFormat}):_,A=this.registry.get("fit");if(!kI(A))throw new s("FORMAT_UNSUPPORTED","The registered FIT adapter does not support course encoding",{format:"fit"});try{return await A.encodeCourse(t)}catch(T){throw x(T,"ENCODE_FAILED","Failed to encode FIT course","fit")}}async dispose(){this.disposed||(this.disposed=!0,await this.registry.dispose())}assertActive(){if(this.disposed)throw new s("DISPOSED","TrackSwap instance is disposed")}};export{$I as FIT_SEMICIRCLE_INVALID_SINT32,e as TRACKSWAP_HEALTH_PARSER_VERSION,tI as TrackSwap,s as TrackSwapError,WI as buildHealthDocumentFromMessages,tI as default,lI as detectFITKinds,$ as normalizeFitSemicircleToDegrees,NI as semicirclesToDegrees};