trackswap 0.2.4 → 0.2.5

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,4 +1,4 @@
1
- var Q=class extends Error{constructor(t,_,I={}){super(_),this.name="TrackSwapError",this.code=t,this.format=I.format,this.cause=I.cause}};function t_(R,t,_,I){if(R instanceof Q)return R;let A=R instanceof Error?R.message:String(R);return new Q(t,`${_}: ${A}`,{format:I,cause:R})}var Z=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}};var n_="trackswap-health-ir-v1",ft=new Set(["timestampCorrelationMesgs","monitoringInfoMesgs","monitoringMesgs","monitoringHrDataMesgs","stressLevelMesgs","respirationRateMesgs","spo2DataMesgs","hrvStatusSummaryMesgs","hrvValueMesgs","sleepLevelMesgs","sleepAssessmentMesgs","napEventMesgs","hsaStepDataMesgs","hsaSpo2DataMesgs","hsaStressDataMesgs","hsaRespirationDataMesgs","hsaHeartRateDataMesgs","hsaBodyBatteryDataMesgs","hsaWristTemperatureDataMesgs","skinTempOvernightMesgs","sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"]),TI=new Set([...ft].filter(R=>R!=="timestampCorrelationMesgs")),nI=new Set(["fileIdMesgs","fileCreatorMesgs","deviceInfoMesgs","deviceSettingsMesgs","softwareMesgs","ohrSettingsMesgs","eventMesgs","activityMesgs","sessionMesgs","lapMesgs","recordMesgs","lengthMesgs","courseMesgs","coursePointMesgs","workoutMesgs","workoutStepMesgs","trainingFileMesgs"]),RI=[{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}],LI=[{field:"ascent",metric:"ascent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"descent",metric:"descent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"moderateActivityMinutes",metric:"moderate_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"},{field:"vigorousActivityMinutes",metric:"vigorous_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"}],dt=631065600,I_=2**16,Xt=18*60*60,EI=new Set([65519,65518]),OI=5;function X(R){return R&&typeof R=="object"?R:{}}function h(R){if(typeof R=="number")return Number.isFinite(R)?R:void 0;if(typeof R!="string"||R.trim()==="")return;let t=Number(R);return Number.isFinite(t)?t:void 0}function v(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R!="string"&&typeof R!="number"||typeof R=="string"&&R.trim()==="")return;let t=new Date(R);return Number.isFinite(t.valueOf())?t:void 0}function Ht(R){return Pt(R)?.toISOString().replace(/Z$/,"")}function Pt(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R=="string"&&!/^\s*[-+]?\d+(?:\.\d+)?\s*$/.test(R))return v(R);let t=h(R);if(!(t===void 0||t<0))return new Date((t+dt)*1e3)}function w(R,t,_){return{messageName:R,messageIndex:t,fieldName:_}}function Ct(R,t){return Object.fromEntries(t.map(_=>[_,R[_]]).filter(([,_])=>typeof _=="number"?Number.isFinite(_):["string","boolean"].includes(typeof _)))}function Yt(R){return Object.fromEntries(Object.entries(R).filter(([,t])=>Array.isArray(t)&&t.length>0).map(([t,_])=>[t,_?.length??0]))}function bt(R){let t=[];return((R.activityMesgs?.length??0)>0||(R.sessionMesgs?.length??0)>0)&&t.push("activity"),[...TI].some(_=>(R[_]?.length??0)>0)&&t.push("health"),((R.workoutMesgs?.length??0)>0||(R.workoutStepMesgs?.length??0)>0)&&t.push("workout"),(R.courseMesgs?.length??0)>0&&t.push("course"),t.length===0&&((R.deviceInfoMesgs?.length??0)>0||(R.fileIdMesgs?.length??0)>0)&&t.push("device"),t.length>0?t:["unknown"]}function SI(R){let t=String(R??"").trim().toLowerCase().replace(/[_\s-]+/g,"");return t.includes("awake")?"awake":t.includes("deep")?"deep":t.includes("light")?"light":t.includes("rem")?"rem":t.includes("unmeasurable")?"unmeasurable":t.includes("sleep")?"sleeping":`vendor:${t||"unknown"}`}function DI(R,t=0){return new Date(R.valueOf()+t*1e3).toISOString().slice(0,10)}function vt(R,t,_=0){return DI(new Date(Math.max(R.valueOf(),t.valueOf()-1)),_)}function Ut(R){let t=h(R);return t===void 0?void 0:t*60}function oI(R,t){let _=[],I=(n,L,E,C,U)=>{let F=v(E.timestamp),B=Pt(E.localTimestamp);if(!F||!B)return;let V=Math.round((B.valueOf()-F.valueOf())/1e3),l=w(n,L,"localTimestamp");if(Math.abs(V)>Xt){t(l);return}_.push({at:F,offsetSeconds:V,priority:C,strategy:U,source:l})};(R.timestampCorrelationMesgs??[]).forEach((n,L)=>{I("timestampCorrelationMesgs",L,X(n),3,"timestamp_correlation")});for(let n of["monitoringInfoMesgs","monitoringMesgs","skinTempOvernightMesgs"])(R[n]??[]).forEach((L,E)=>{I(n,E,X(L),1,"inferred")});(R.napEventMesgs??[]).forEach((n,L)=>{let E=X(n);for(let[C,U]of[["startTime","startTimezoneOffset"],["endTime","endTimezoneOffset"]]){let F=v(E[C]),B=Ut(E[U]);if(!F||B===void 0)continue;let V=w("napEventMesgs",L,U);if(Math.abs(B)>Xt){t(V);continue}_.push({at:F,offsetSeconds:B,priority:2,strategy:"explicit_offset",source:V})}}),_.sort((n,L)=>n.at.valueOf()-L.at.valueOf()||L.priority-n.priority);let A=_.filter((n,L)=>L===0||n.at.valueOf()!==_[L-1].at.valueOf()).map(({at:n,offsetSeconds:L})=>({at:n,offsetSeconds:L})),T=_.find(({strategy:n})=>n==="timestamp_correlation")?.strategy??_.find(({strategy:n})=>n==="explicit_offset")?.strategy??_.find(({strategy:n})=>n==="inferred")?.strategy??"unknown";return{offsets:A,strategy:T}}function HI(R,t){let _=h(R);if(!t||!Number.isInteger(_)||_<0||_>=I_)return;let I=Math.floor(t.valueOf()/1e3)-dt,A=Math.floor(I/I_)*I_+_;return A<I&&(A+=I_),new Date((A+dt)*1e3)}function CI(R){let t,_,I,A,T,n;return(R.monitoringMesgs??[]).map(L=>{let E=X(L),U=v(E.timestamp)??HI(E.timestamp16,t);U&&(t=U),U&&(!_||U>_)&&(I=_,_=U);let F=I;E.activityType!==void 0&&(A=E.activityType),E.deviceIndex!==void 0&&(n=E.deviceIndex);let B=E.intensity??E.activityLevel;return B!==void 0&&(T=B),{message:E,timestamp:U,intervalStartTime:F,deviceIndex:n,activityType:A,intensity:T}})}function q(R,t){let _;for(let I of R){if(I.at>t)break;_=I.offsetSeconds}return _??R[0]?.offsetSeconds}function A_(R,t){if(t!==void 0)return new Date(R.valueOf()+t*1e3).toISOString().replace(/Z$/,"")}function fI(R,t,_,I){return t>=R?{value:t-R}:R>=_*.75&&R<_&&t>=0&&t<=_*.25?{value:_-R+t,rolloverBits:I}:null}function Nt(R){return R>=1&&R<=100?"valid":R===-1?"off_wrist":R===-2?"motion":R===-3?"not_enough_data":R===-4?"recovering":R===-5?"unidentified":R===-16?"gap":R===0||R>100?"invalid":"unknown"}function dI(R){return R>=0&&R<=100?"valid":Nt(R)}function UI(R){return R===255?"invalid":R===254?"motion":R===253?"off_wrist":R===252?"not_enough_data":R===2.4?"gap":R>=1&&R<=100?"valid":"invalid"}function r(R,t,_){return new Date(R.valueOf()+t*_*1e3)}function FI(R){let t=new Map,_={};R.warnings.forEach(I=>{_[I.code]=(_[I.code]??0)+1;let A=t.get(I.code)??[];A.length<OI&&(A.push(I),t.set(I.code,A))}),R.warningCounts=_,R.warnings=[...t.values()].flat()}function GI(R){return R===-1?"off_wrist":R===-2?"motion":R===-3?"invalid":R>0&&R<=100?"valid":"invalid"}function $t(R,t={},_={}){let I=Yt(R),A=Object.fromEntries(Object.entries(I).filter(([o])=>ft.has(o))),T=Object.fromEntries(Object.entries(I).filter(([o])=>!ft.has(o)&&!nI.has(o))),n={sdkProfileVersion:_.sdkProfileVersion,parserVersion:n_,messageCounts:I,recognizedMessageCounts:A,unknownMessageCounts:T,invalidValueCounts:{},warningCounts:{},warnings:[]};t.includeUnknownMessages&&(n.unknownMessages=Object.fromEntries(Object.keys(T).map(o=>[o,R[o]??[]])));let L=[],E=[],C=[],U=[],F=[],B=oI(R,o=>{n.warnings.push({code:"GARMIN_HEALTH_INVALID_TIMEZONE_OFFSET",message:"Ignored an implausible FIT timezone offset",source:o})}),{offsets:V}=B,l=o=>{let d=o.offsetSeconds??q(V,o.timestamp);if(o.offsetSeconds=d,o.localTimestamp??=A_(o.timestamp,d),L.push(o),F.push(o.timestamp),o.status!=="valid"){let D=`${o.metric}:${o.status}`;n.invalidValueCounts[D]=(n.invalidValueCounts[D]??0)+1}},z=new Map;CI(R).forEach(({message:o,timestamp:d,intervalStartTime:D,deviceIndex:f,activityType:H,intensity:g},W)=>{if(!d){n.warnings.push({code:"GARMIN_HEALTH_NO_TIMESTAMP",message:"Monitoring message has no valid timestamp",source:w("monitoringMesgs",W)});return}F.push(d);let s=h(o.heartRate);if(s!==void 0){let G=s>0?"valid":"gap";l({metric:"heart_rate_bpm",timestamp:d,localTimestamp:Ht(o.localTimestamp),value:G==="valid"?s:void 0,unit:"bpm",status:G,aggregation:"instant",source:w("monitoringMesgs",W,"heartRate"),attributes:G==="valid"?void 0:{rawValue:s}})}let M=h(o.temperature);M!==void 0&&l({metric:"temperature_c",timestamp:d,localTimestamp:Ht(o.localTimestamp),value:M,unit:"degC",status:"valid",aggregation:"mean",source:w("monitoringMesgs",W,"temperature")});for(let G of RI){let P=h(o[G.field]);if(P===void 0)continue;let N=[f??"device",H??"activity",G.field].join(":"),Y=z.get(N);if(Y&&d>Y.timestamp){let p=fI(Y.value,P,G.rolloverModulus,G.rolloverBits);if(p){p.rolloverBits&&n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_ROLLOVER",message:`${G.field} accumulator rolled over at ${p.rolloverBits} bits`,source:w("monitoringMesgs",W,G.field)});let K=q(V,Y.timestamp);E.push({metric:G.metric,startTime:Y.timestamp,endTime:d,localStartTime:A_(Y.timestamp,K),offsetSeconds:K,value:p.value,unit:G.unit,status:"valid",activityType:H===void 0?void 0:String(H),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",W,G.field),attributes:t.health?.retainCumulativeValues===!1?void 0:{rawCumulativeValue:P}})}else n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_RESET",message:`${G.field} accumulator decreased; a new accumulation window was started`,source:w("monitoringMesgs",W,G.field)})}z.set(N,{timestamp:d,value:P})}for(let G of LI){let P=h(o[G.field]);if(P===void 0||P<0)continue;let N=P*(G.multiplier??1),Y=G.intervalStrategy==="value_duration"?new Date(d.valueOf()-N*1e3):D;if(!Y||Y>=d)continue;let p=q(V,Y);F.push(Y),E.push({metric:G.metric,startTime:Y,endTime:d,localStartTime:A_(Y,p),offsetSeconds:p,value:N,unit:G.unit,status:"valid",activityType:H===void 0?void 0:String(H),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",W,G.field)})}}),(R.monitoringHrDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp);if(!f)return;[{field:"currentDayRestingHeartRate",metric:"resting_heart_rate_bpm"},{field:"restingHeartRate",metric:"resting_heart_rate_7_day_bpm"}].forEach(({field:g,metric:W})=>{let s=h(D[g]);if(s===void 0)return;let M=s>0?"valid":"invalid";l({metric:W,timestamp:f,value:M==="valid"?s:void 0,unit:"bpm",status:M,aggregation:"latest",source:w("monitoringHrDataMesgs",d,g),attributes:M==="valid"?void 0:{rawValue:s}})})}),(R.stressLevelMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.stressLevelTime),H=h(D.stressLevelValue);if(!f||H===void 0)return;let g=Nt(H);l({metric:"stress_level",timestamp:f,value:g==="valid"?H:void 0,unit:"score",status:g,aggregation:"instant",source:w("stressLevelMesgs",d,"stressLevelValue"),attributes:g==="valid"?void 0:{rawValue:H}})}),(R.respirationRateMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.respirationRate);if(!f||H===void 0)return;let g=GI(H);l({metric:"respiration_rate_bpm",timestamp:f,value:g==="valid"?H:void 0,unit:"breaths/min",status:g,aggregation:"instant",source:w("respirationRateMesgs",d,"respirationRate"),attributes:g==="valid"?void 0:{rawValue:H}})}),(R.spo2DataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.readingSpo2);if(!f||H===void 0)return;let g=h(D.readingConfidence),W=H<=0||H>100?"invalid":g!==void 0&&g<=0?"low_confidence":"valid";l({metric:"spo2_percent",timestamp:f,value:W==="invalid"?void 0:H,unit:"percent",status:W,quality:g,aggregation:"instant",source:w("spo2DataMesgs",d,"readingSpo2"),attributes:{measurementMode:D.mode===void 0?null:String(D.mode),...W==="invalid"?{rawValue:H}:{}}})}),(R.hrvValueMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.value);if(!f||H===void 0)return;let g=H>0?"valid":"invalid";l({metric:"hrv_rmssd_ms",timestamp:f,value:g==="valid"?H:void 0,unit:"ms",status:g,aggregation:"mean",source:w("hrvValueMesgs",d,"value"),attributes:{windowSeconds:300,...g==="valid"?{}:{rawValue:H}}})}),(R.hrvStatusSummaryMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp);C.push({summaryType:"hrv_status",externalId:`fit:hrv-status:${f?.toISOString()??d}`,startTime:f,metrics:Ct(D,["weeklyAverage","lastNightAverage","lastNight5MinHigh","baselineLowUpper","baselineBalancedLower","baselineBalancedUpper","status"]),source:w("hrvStatusSummaryMesgs",d)}),f&&F.push(f)}),(R.monitoringInfoMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp);C.push({summaryType:"device",externalId:`fit:monitoring-info:${f?.toISOString()??d}`,startTime:f,offsetSeconds:f?q(V,f):void 0,metrics:Ct(D,["restingMetabolicRate","activityType","cyclesToDistance","cyclesToCalories"]),source:w("monitoringInfoMesgs",d)}),f&&F.push(f)}),(R.skinTempOvernightMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp);if(!f)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:g,metric:W})=>{let s=h(D[g]);s!==void 0&&l({metric:W,timestamp:f,localTimestamp:Ht(D.localTimestamp),value:s,unit:"degC",status:"valid",aggregation:"mean",source:w("skinTempOvernightMesgs",d,g)})})});let b=(R.sleepLevelMesgs??[]).map((o,d)=>({message:X(o),messageIndex:d,timestamp:v(X(o).timestamp)})).filter(o=>o.timestamp!==void 0).sort((o,d)=>o.timestamp.valueOf()-d.timestamp.valueOf());if(b.length>=2){let o=X(R.sleepAssessmentMesgs?.[0]),d=[];for(let g=0;g<b.length-1;g+=1){let W=b[g],s=b[g+1];if(s.timestamp<=W.timestamp)continue;let M={segmentType:SI(W.message.sleepLevel),startTime:W.timestamp,endTime:s.timestamp,status:"valid",source:w("sleepLevelMesgs",W.messageIndex,"sleepLevel")},G=d.at(-1);G&&G.segmentType===M.segmentType&&G.endTime.valueOf()===M.startTime.valueOf()?G.endTime=M.endTime:d.push(M)}let D=b[0].timestamp,f=b.at(-1).timestamp;F.push(D,f);let H=q(V,f);U.push({sessionType:"sleep",externalId:`fit:sleep:${D.toISOString()}:${f.toISOString()}`,startTime:D,endTime:f,startOffsetSeconds:q(V,D),endOffsetSeconds:H,calendarDate:vt(D,f,H),segments:d,metrics:Ct(o,["combinedAwakeScore","awakeTimeScore","awakeningsCountScore","deepSleepScore","sleepDurationScore","lightSleepScore","overallSleepScore","sleepQualityScore","sleepRecoveryScore","remSleepScore","sleepRestlessnessScore","awakeningsCount","interruptionsScore","averageStressDuringSleep"]),source:w("sleepLevelMesgs",b[0].messageIndex),attributes:{calendarDateStrategy:H===void 0?"sleep_end_utc_fallback_date":"sleep_end_local_date"}})}else b.length>0&&n.warnings.push({code:"GARMIN_HEALTH_SLEEP_BOUNDARY_INCOMPLETE",message:"Sleep level data does not contain enough boundaries",source:w("sleepLevelMesgs",b[0].messageIndex)});for(let o of["sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"])(R[o]??[]).forEach((d,D)=>{let f=X(d),H=v(f.timestamp);!H||f.severity===void 0||(F.push(H),C.push({summaryType:"sleep",externalId:`fit:${o}:${f.messageIndex??D}:${H.toISOString()}`,startTime:H,offsetSeconds:q(V,H),metrics:{severity:String(f.severity)},source:w(o,D,"severity")}))});return(R.napEventMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.startTime),H=v(D.endTime),g=D.isDeleted===!0;if(!f||!H||H<f||!g&&H.valueOf()===f.valueOf())return;let W=Ut(D.startTimezoneOffset),s=Ut(D.endTimezoneOffset);F.push(f,H),U.push({sessionType:"nap",externalId:`fit:nap:${D.messageIndex??d}:${f.toISOString()}`,startTime:f,endTime:H,startOffsetSeconds:W,endOffsetSeconds:s,calendarDate:vt(f,H,s??W),deleted:g,segments:[],metrics:{},source:w("napEventMesgs",d),attributes:{source:D.source===void 0?null:String(D.source),feedback:D.feedback===void 0?null:String(D.feedback),updateTimestamp:v(D.updateTimestamp)?.toISOString()??null}})}),(R.hsaStepDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval),g=Array.isArray(D.steps)?D.steps:[];!f||!H||H<=0||EI.has(H)||g.forEach((W,s)=>{let M=h(W);if(M===void 0||M<0)return;let G=r(f,H,s),P=new Date(G.valueOf()+H*1e3),N=q(V,G);F.push(G,P),E.push({metric:"steps",startTime:G,endTime:P,localStartTime:A_(G,N),offsetSeconds:N,value:M,unit:"count",status:"valid",source:w("hsaStepDataMesgs",d,"steps"),attributes:{sequenceIndex:s,intervalSeconds:H}})})}),(R.hsaSpo2DataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval),g=Array.isArray(D.readingSpo2)?D.readingSpo2:[],W=Array.isArray(D.confidence)?D.confidence:[];!f||!H||H<=0||g.forEach((s,M)=>{let G=h(s);if(G===void 0)return;let P=h(W[M]),N=G<70||G>100||G===240?"invalid":P!==void 0&&P<=0?"low_confidence":"valid";l({metric:"spo2_percent",timestamp:r(f,H,M),value:N==="invalid"?void 0:G,unit:"percent",status:N,quality:P,aggregation:"instant",source:w("hsaSpo2DataMesgs",d,"readingSpo2"),attributes:{sequenceIndex:M,intervalSeconds:H,...N==="invalid"?{rawValue:G}:{}}})})}),(R.hsaStressDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval),g=Array.isArray(D.stressLevel)?D.stressLevel:[];!f||!H||H<=0||g.forEach((W,s)=>{let M=h(W);if(M===void 0)return;let G=dI(M);l({metric:"stress_level",timestamp:r(f,H,s),value:G==="valid"?M:void 0,unit:"score",status:G,aggregation:"instant",source:w("hsaStressDataMesgs",d,"stressLevel"),attributes:{sequenceIndex:s,intervalSeconds:H,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaRespirationDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval),g=Array.isArray(D.respirationRate)?D.respirationRate:[];!f||!H||H<=0||g.forEach((W,s)=>{let M=h(W);if(M===void 0)return;let G=UI(M);l({metric:"respiration_rate_bpm",timestamp:r(f,H,s),value:G==="valid"?M:void 0,unit:"breaths/min",status:G,aggregation:"instant",source:w("hsaRespirationDataMesgs",d,"respirationRate"),attributes:{sequenceIndex:s,intervalSeconds:H,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaHeartRateDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval),g=Array.isArray(D.heartRate)?D.heartRate:[],W=h(D.status);!f||!H||H<=0||g.forEach((s,M)=>{let G=h(s);if(G===void 0)return;let P=G===0?"gap":W===1?"valid":W===0?"low_confidence":"unknown";l({metric:"heart_rate_bpm",timestamp:r(f,H,M),value:P==="gap"?void 0:G,unit:"bpm",status:P,aggregation:"instant",source:w("hsaHeartRateDataMesgs",d,"heartRate"),attributes:{sequenceIndex:M,intervalSeconds:H,measurementStatus:W??null,...P==="gap"?{rawValue:G}:{}}})})}),(R.hsaWristTemperatureDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval),g=Array.isArray(D.value)?D.value:[];!f||!H||H<=0||g.forEach((W,s)=>{let M=h(W);M!==void 0&&l({metric:"wrist_temperature_c",timestamp:r(f,H,s),value:M,unit:"degC",status:"valid",aggregation:"instant",source:w("hsaWristTemperatureDataMesgs",d,"value"),attributes:{sequenceIndex:s,intervalSeconds:H}})})}),(R.hsaBodyBatteryDataMesgs??[]).forEach((o,d)=>{let D=X(o),f=v(D.timestamp),H=h(D.processingInterval)??0;if(!f||H<=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:W,metric:s,unit:M})=>{(Array.isArray(D[W])?D[W]:[]).forEach((P,N)=>{let Y=h(P);if(Y===void 0)return;let p=W==="level"&&Y===-16?"gap":W==="level"&&(Y<0||Y>100)?"invalid":"valid";l({metric:s,timestamp:r(f,H,N),value:p==="valid"?Y:void 0,unit:M,status:p,aggregation:"instant",source:w("hsaBodyBatteryDataMesgs",d,W),attributes:{sequenceIndex:N,intervalSeconds:H,...p==="valid"?{}:{rawValue:Y}}})})})}),L.sort((o,d)=>o.timestamp.valueOf()-d.timestamp.valueOf()),E.sort((o,d)=>o.startTime.valueOf()-d.startTime.valueOf()),U.sort((o,d)=>o.startTime.valueOf()-d.startTime.valueOf()),F.sort((o,d)=>o.valueOf()-d.valueOf()),FI(n),{schemaVersion:"1",observedStart:F[0],observedEnd:F.at(-1),timezone:{strategy:B.strategy,offsets:V},points:L,intervals:t.health?.reconstructIntervals===!1?[]:E,summaries:C,sessions:U,diagnostics:n}}var T_=class extends Z{constructor(){super(...arguments);this.name="HealthStructurePlugin";this.priority=20}structureData(_,I){let A=I.userData?.fitDocumentOptions??{},T=bt(_);return{healthDocument:T.includes("health")?$t(_,A,{sdkProfileVersion:I.metadata.get("fit-sdk-profile-version")}):void 0,fitDocumentMetadata:{detectedKinds:T,messageCounts:Yt(_)}}}};var R_=(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))(R_||{});var L_=(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))(L_||{});function kt(R,t){if(!t)return;let _=t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();for(let I of Object.keys(R)){if(!Number.isNaN(Number(I))||I.toUpperCase()!==_)continue;let A=R[I];return typeof A=="number"?A:void 0}}function gI(R){let t=R.metadata?.fileName?.trim();if(t)return t;let _=R.metadata?.originType;return _?`${_.toLowerCase()}-course`:"course"}function Qt(R){let t=R.activities?.[0],I=[...(R.activities?.flatMap(A=>A.laps??[])??[]).flatMap(A=>A.records??[]),...R.routes?.flatMap(A=>A.records??[])??[],...R.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(I.length===0)throw new Error("Cannot build a FIT course without timestamped coordinates");return{name:gI(R),sport:kt(R_,t?.sport)??2,subSport:kt(L_,t?.subSport)??0,records:I,timeCreated:I[0].timestamp}}function Jt(){return process.env.TRACKSWAP_FIT_DEBUG==="1"||process.env.TRACKSWAP_DEBUG==="1"}function $(...R){Jt()}function a(...R){Jt()}var E_=class{constructor(){this.stage="parse"}async process(t){let _=Date.now();if(!t.rawData)throw new Error("FIT data cannot be empty");try{let I=await this.parseWithFitSDK(t.rawData,t);return t.rawMessages=I,$("\u{1F389} FIT parsing raw messages:",I),t.performance.parseTime=Date.now()-_,$(`\u{1F527} FIT parsing completed, contains message types: ${Object.keys(I).join(", ")}`),t}catch(I){throw new Error(`FIT parsing failed: ${I.message}`)}}async parseWithFitSDK(t,_){let{Decoder:I,Profile:A,Stream:T}=await import("@garmin/fitsdk"),n=[A.version?.major,A.version?.minor,A.version?.patch].filter(F=>F!==void 0);n.length>0&&_.metadata.set("fit-sdk-profile-version",n.join("."));let L=T.fromBuffer(t);if(!I.isFIT(L))throw new Error("Not a valid FIT file");let E=new I(L),{messages:C,errors:U}=E.read();return U&&U.length>0&&a("FIT parsing warnings:",U),C}};function lI(R){let t={...R};return t.position_lat!=null&&t.positionLat==null&&(t.positionLat=t.position_lat),t.position_long!=null&&t.positionLong==null&&(t.positionLong=t.position_long),t}var O_=class{constructor(t){this.getConverters=t;this.stage="extract"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Raw messages cannot be empty");let I={};for(let[A,T]of Object.entries(t.rawMessages)){if(!Array.isArray(T)||T.length===0){I[A]=T;continue}let n=this.getConverters(A);if(n.length===0)I[A]=A==="recordMesgs"?T.map(L=>lI(L)):T,$(`\u{1F4CB} Message type "${A}" has no converter, using raw data`);else{let L=n[0];try{let E=L.convertMessages(T,t);I[A]=E,$(`\u2705 Message type "${A}" using converter ${L.name}`)}catch(E){t.errors.push(E),I[A]=T,a(`FIT converter "${L.name}" failed for ${A}; raw messages were retained`,E)}}}return t.rawMessages=I,t.performance.extractTime=Date.now()-_,t}},S_=class{constructor(t){this.getStructurePlugins=t;this.stage="structure"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Message data cannot be empty");let I={...t.rawMessages},A=this.getStructurePlugins();for(let T of A)try{let n=T.structureData(t.rawMessages,t);I={...I,...n},$(`\u{1F527} Structure plugin ${T.name} processing completed`)}catch(n){throw t.errors.push(n),new Error(`FIT structure plugin "${T.name}" failed: ${n.message}`)}return t.result=I,t.performance.structureTime=Date.now()-_,t}},D_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,parseTime:t.performance.parseTime,extractTime:t.performance.extractTime,structureTime:t.performance.structureTime}),t.stats&&(t.stats.endTime=Date.now(),t.rawMessages&&(t.stats.processedTokens=this.countTotalMessages(t.rawMessages))),$(`\u2705 FIT processing completed, total time: ${_}ms`),t}countTotalMessages(t){let _=0;return Object.values(t).forEach(I=>{Array.isArray(I)&&(_+=I.length)}),_}};import k from"dayjs";var o_=class extends Z{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(_,I){let{sessionMesgs:A,lapMesgs:T,recordMesgs:n,lengthMesgs:L,setMesgs:E}=_;if(!A?.length)return a("No structured session found, data structure is incomplete"),{};let C=A.map((B,V)=>{let l=k(B.startTime).valueOf(),z=l+(B.totalElapsedTime??0)*1e3,b=k(B.timestamp).valueOf(),o=Math.max(Number.isFinite(z)?z:Number.NEGATIVE_INFINITY,Number.isFinite(b)?b:Number.NEGATIVE_INFINITY),d=A[V+1],D=d?k(d.startTime).valueOf():Number.NaN,f=Number.isFinite(D)&&D>l,H=(n??[]).filter(p=>{let K=k(p.timestamp).valueOf();return!Number.isFinite(K)||K<l?!1:f?K<D:K<=o+2e3}),g=B.firstLapIndex,W=B.numLaps,s=typeof g=="number"&&typeof W=="number"?(T??[]).filter(p=>{let K=p.messageIndex;return typeof K=="number"&&K>=g&&K<g+W}):[],M=(s.length>0?s:(T??[]).filter(p=>{let K=k(p.startTime).valueOf();return Number.isFinite(K)&&K>=l&&K<=o+2e3})).sort((p,K)=>k(p.startTime).valueOf()-k(K.startTime).valueOf()),G=M.length>0?H:A.length===1?[...n??[]]:(n??[]).filter(p=>{let K=k(p.timestamp).valueOf();return Number.isFinite(K)?(V===0||K>=l)&&(!f||K<D):V===0}),P=(E??[]).filter(p=>{let K=k(p.startTime??p.timestamp).valueOf();return Number.isFinite(K)?K<l?!1:f?K<D:K<=o+2e3:A.length===1}),N=M.length>0?M:G.length>0?[{...B,messageIndex:typeof B.firstLapIndex=="number"?B.firstLapIndex:V,recordMesgs:G}]:[];if(M.length===0&&N.length===1){let p=Number(I.metadata.get("fit-synthetic-lap-count")??0);I.metadata.set("fit-synthetic-lap-count",p+1)}let Y=N.map((p,K)=>{let Ot=k(p.startTime).valueOf(),Vt=N[K+1]?.startTime,St=Vt==null?Number.NaN:k(Vt).valueOf(),II=Ot+(p.totalElapsedTime??0)*1e3,pt=Number.isFinite(St)&&St>Ot,ht=pt?St:Math.max(II,o),AI=M.length===0?G:G.filter(ot=>{let c=k(ot.timestamp).valueOf();return c>=Ot&&(pt?c<ht:c<=ht+2e3)}),Dt=p.firstLengthIndex??void 0,Kt=p.numLengths??void 0,wt=[];if(Dt!==void 0&&Kt!==void 0){let ot=Dt+Kt;wt=L?.filter(c=>c.messageIndex>=Dt&&c.messageIndex<ot)||[]}return{...p,recordMesgs:AI,lengthMesgs:wt,messageIndex:p.messageIndex!==void 0?p.messageIndex:0}});return{...B,lapMesgs:Y,setMesgs:P}}),U=new Set;for(let B of C)for(let V of B.lapMesgs??[])for(let l of V.recordMesgs??[])l?.timestamp!=null&&U.add(k(l.timestamp).valueOf());let F=0;for(let B of n??[]){if(B?.timestamp==null)continue;let V=k(B.timestamp).valueOf();U.has(V)||F++}return F>0&&(I.metadata.set("fit-unassigned-record-count",F),a(`SessionStructurePlugin: ${F} record(s) did not fall into any lap time window`)),{sessionMesgs:C}}},H_=class extends Z{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(_,I){let{courseMesgs:A,lapMesgs:T,recordMesgs:n}=_;if(!A?.length)return{};let L=2e3;return{courseMesgs:A.map(C=>{let U=T?.map(F=>{let B=k(F.startTime).valueOf(),V=k(F.timestamp).valueOf(),l=n?.filter(z=>{let b=k(z.timestamp).valueOf();return b>=B-L&&b<=V+L})||[];return{...F,recordMesgs:l}})||[];return{...C,lapMesgs:U}})}}},C_=class extends Z{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(_,I){let{fileIdMesgs:A,fileCreatorMesgs:T,deviceInfoMesgs:n}=_;if(A?.length&&A[0]){let L=A[0];I.fileHeader={type:L.type,manufacturer:L.manufacturer,product:L.product}}return{fileIdMesgs:A,fileCreatorMesgs:T,deviceInfoMesgs:n}}};var f_=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 E_,new O_(t=>this.getConverters(t)),new S_(()=>this.structurePlugins),new D_],$("\u{1F527} FIT core pipeline processors initialized (fixed and not modifiable)")}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let t=[new C_,new o_,new H_,new T_];for(let _ of t)this.addStructurePlugin(_),this.registeredPlugins.add(_.name);this.defaultPluginsRegistered=!0,$("\u2705 Default FIT structure plugins auto-registered (FileHeader, Session, Course, etc.)")}addConverterForMessageType(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((A,T)=>(A.priority||100)-(T.priority||100))}addStructurePlugin(t){this.structurePlugins.push(t),this.structurePlugins.sort((_,I)=>(_.priority||100)-(I.priority||100))}async registerMessageConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Message converter plugin ${t.name} already exists`);t.supportedMessageTypes.forEach(I=>{this.addConverterForMessageType(I,t)}),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";$(`\u{1F4E6} Registered FIT message converter: ${t.name}${_}, supported message types: ${t.supportedMessageTypes.join(", ")}`),t.supportedMessageTypes.forEach(I=>{let T=(this.converterPlugins.get(I)||[]).map(n=>`${n.name}(${n.priority||100})`);$(` \u{1F4CB} Message type "${I}" converter priority: ${T.join(" > ")}`)})}async registerStructurePlugin(t){if(this.registeredPlugins.has(t.name))throw new Error(`Structure plugin ${t.name} already exists`);this.addStructurePlugin(t),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";$(`\u{1F3D7}\uFE0F Registered FIT structure plugin: ${t.name}${_}`)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(A=>A.name===t.name);_!==-1?(this.middlewarePlugins[_]=t,$(`\u{1F504} Updated FIT middleware: ${t.name}`)):(this.middlewarePlugins.push(t),this.middlewarePlugins.sort((A,T)=>(A.priority||100)-(T.priority||100)),$(`\u{1F50C} Registered FIT middleware: ${t.name}`));let I=[];t.onParse&&I.push("onParse"),t.onExtractMessages&&I.push("onExtractMessages"),t.onStructure&&I.push("onStructure"),t.onComplete&&I.push("onComplete"),t.onError&&I.push("onError"),I.length>0&&$(` \u{1F3A3} Supported hooks: ${I.join(", ")}`)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getConverters(t){return this.converterPlugins.get(t)||[]}unregisterPlugin(t){if(!this.registeredPlugins.has(t))return!1;for(let[A,T]of this.converterPlugins){let n=T.findIndex(L=>L.name===t);n!==-1&&(T.splice(n,1),T.length===0&&this.converterPlugins.delete(A))}let _=this.structurePlugins.findIndex(A=>A.name===t);_!==-1&&this.structurePlugins.splice(_,1);let I=this.middlewarePlugins.findIndex(A=>A.name===t);return I!==-1&&this.middlewarePlugins.splice(I,1),this.registeredPlugins.delete(t),$(`\u{1F5D1}\uFE0F Removed FIT plugin: ${t}`),!0}async initialize(){if(this.initialized)return;await this.registerDefaultPlugins();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let A=_;for(let T of this.middlewarePlugins){let n=T[t];if(n)try{A=await n.call(T,A,I)||A}catch(L){I.errors.push(L),await T.onError?.(L,I)}}return A}async parseByBuffer(t,_={}){await this.initialize();let I=this.createContext();I.rawData=t,I.userData=_.userData,I.metadata.set("decoder",this);try{for(let A of this.processors)try{switch(A.stage==="parse"&&I.rawData&&(I.rawData=await this.executeMiddlewareHook("onParse",I.rawData,I)),I=await A.process(I),A.stage){case"parse":break;case"extract":I.rawMessages&&(I.rawMessages=await this.executeMiddlewareHook("onExtractMessages",I.rawMessages,I));break;case"structure":I.result&&(I.result=await this.executeMiddlewareHook("onStructure",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(T){I.errors.push(T);for(let n of this.middlewarePlugins)await n.onError?.(T,I);throw new Error(`FIT pipeline stage "${A.stage}" failed: ${T.message}`)}return $("\u{1F389} FIT parsing completed",I.result),I.result}catch(A){throw A}}};var WI={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=R=>{let t=WI[R];return{size:1,baseType:0,mapValue:_=>typeof _=="string"?t[_]??255:_,setValue:function(_,I){this.setUint8(_,I)}}},Ft={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:R=>Array.from(jt(R)),setValue:sI},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round(R*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round((R+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>{let t;return R instanceof Date?(t=Math.floor(R.getTime()/1e3),t-631065600):typeof R=="string"?(t=Math.floor(new Date(R).getTime()/1e3),t-631065600):R<631065600?Math.floor(R):(R>9999999999?t=Math.floor(R/1e3):t=Math.floor(R),t-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:R=>Math.round(R/180*2147483648)}};function zt(R){return Array.from(jt(R)).length+1}function*jt(R){for(let t of MI(R))t<128?yield t:t<2048?(yield 192|t>>6,yield 128|t&63):t<65536?(yield 224|t>>12,yield 128|t>>6&63,yield 128|t&63):(yield 240|t>>18,yield 128|t>>12&63,yield 128|t>>6&63,yield 128|t&63);yield 0}function*MI(R){for(let t=0;t<R.length;){let _=R.codePointAt(t);if(_===void 0)break;yield _,t+=_>65535?2:1}}function sI(R,t){for(let _=0;_<t.length;_++)this.setUint8(R+_,t[_])}var VI={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:"message_index",number:254,type:"uint16"},{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:25,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{name:"message_index",number:254,type:"uint16"},{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"}]}},pI=(R,t)=>R.map(_=>({..._,value:t[_.name]})).filter(({value:_})=>_!==void 0),d_=class R{static check(t,_,I,A){if(_===void 0)throw new Error(`Message '${t}' not known`);if(I===void 0)throw new Error(`Message '${t}' has no field definitions`);let T=I.map(L=>L.name),n=Object.keys(A).filter(L=>!T.includes(L));if(n.length)throw new Error(`Message '${t}' has no field definitions named '${n}'`)}constructor(t,_,I){let A=VI[_];if(!A)throw new Error(`Unknown message type: ${_}`);let{mesgNum:T,fieldDefns:n}=A;R.check(_,T,n,I),this.localNum=t,this.mesgNum=T,this.fields=pI(n,I)}get mesgDefn(){let t=this.fields.map(({number:_,type:I,value:A})=>{let T=Ft[I];if(!T)throw new Error(`Unknown type: ${I}`);let{size:n,baseType:L}=T;return I==="string"?{number:_,size:zt(A),baseType:L}:{number:_,size:n,baseType:L}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:t}}isSameDefn(t){let _=(L,E)=>L.number===E.number&&L.size===E.size&&L.baseType===E.baseType,I=(L,E)=>L.length===E.length&&L.every((C,U)=>_(C,E[U])),{localNum:A,mesgNum:T,fieldDefns:n}=this.mesgDefn;return T===t.mesgNum&&A===t.localNum&&I(n,t.fieldDefns)}get defnRecord(){let{localNum:t,mesgNum:_,fieldDefns:I}=this.mesgDefn,A=6+3*I.length,T=new DataView(new ArrayBuffer(A));T.setUint8(0,64|t),T.setUint8(2,1),T.setUint16(3,_),T.setUint8(5,I.length);let n=6;for(let L of I)T.setUint8(n++,L.number),T.setUint8(n++,L.size),T.setUint8(n++,L.baseType);return T.buffer}get dataRecord(){let{fieldDefns:t}=this.mesgDefn,_=1+t.reduce((T,{size:n})=>T+n,0),I=new DataView(new ArrayBuffer(_));I.setUint8(0,this.localNum);let A=1;for(let{number:T,type:n,value:L}of this.fields){let E=Ft[n];if(!E)throw new Error(`Unknown type: ${n}`);let{size:C,setValue:U}=E,F;"mapValue"in E?F=E.mapValue(L):F=L,U&&U.call(I,A,F),A+=C}return I.buffer}};var hI=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],yt=(R,t)=>(R>>>4^hI[R&15^t])&65535,KI=(R,t,_)=>yt(yt(R,t),_),wI=(R,t)=>KI(R,t&15,t>>>4);function Gt(R,t=0){let _=t,I=R instanceof ArrayBuffer?new Uint8Array(R):R;for(let A=0;A<I.length;A++)_=wI(_,I[A]);return _}import XI from"dayjs";var Zt=14,vI=16,PI=2078,YI=776358228,U_=class{constructor(t={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:t.compact??!0,defaultActivity:t.defaultActivity??"cycling",defaultSubActivity:t.defaultSubActivity??"generic"}}async encode(t){return this.reset(),this.buildFITContent(t,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(t){return this.reset(),this.buildFITContent(t,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(t,_="activity"){return this.reset(),this.buildFITContent(t,_),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(t,_){this.buildFileId(t,_),_==="course"?this.buildCourseContent(t):this.buildActivityContent(t)}buildActivityContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Activity file must contain at least one Session");let I=[],A=[],T=0;for(let[n,L]of _.entries()){let E=(L.lapMesgs??[]).map((U,F)=>({...U,messageIndex:T+F})),C={...L,messageIndex:n,firstLapIndex:T,numLaps:E.length,lapMesgs:E};E.length>0&&this.buildEventsFromLaps(E,I);for(let U of E)U.recordMesgs&&this.buildRecords(U.recordMesgs);E.length>0&&this.buildLaps(E),this.buildSession(C),this.buildActivityFromSession(C,A),T+=E.length}I.forEach(n=>this.buildEvent(n)),A.forEach(n=>this.buildActivity(n))}buildCourseContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Course file must contain track data");let I=_[0];if(this.buildCourse({name:"course",sport:this.options.defaultActivity}),I.lapMesgs){let A=[];for(let L of I.lapMesgs)L.recordMesgs&&A.push(...L.recordMesgs);A.sort((L,E)=>L.timestamp&&E.timestamp?new Date(L.timestamp).getTime()-new Date(E.timestamp).getTime():(L.distance||0)-(E.distance||0));let T=A[0],n=A[A.length-1];if(I.startTime&&this.buildEvent({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:0}),A.forEach(L=>this.buildRecord(L)),n.timestamp&&this.buildEvent({timestamp:n.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),I.lapMesgs)for(let L=0;L<I.lapMesgs.length;L++)this.buildLap(I.lapMesgs[L])}}buildFileId(t,_){let I=t.fileIdMesgs?.[0]||{};this.writeMesg("file_id",{type:_,time_created:I.timeCreated?this.parseTimestamp(I.timeCreated):Date.now(),manufacturer:I.manufacturer,product:I.product,serial_number:I.serialNumber})}buildSession(t){this.writeMesg("session",{message_index:t.messageIndex,timestamp:t.timestamp?t.timestamp:void 0,start_time:t.startTime?t.startTime:void 0,total_elapsed_time:t.totalElapsedTime,total_timer_time:t.totalTimerTime,start_position_lat:t.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,total_distance:t.totalDistance,total_ascent:t.totalAscent,total_descent:t.totalDescent,sport:t.sport||this.options.defaultActivity,sub_sport:t.subSport||this.options.defaultSubActivity,first_lap_index:t.firstLapIndex??0,num_laps:t.numLaps??t.lapMesgs?.length??0})}buildLaps(t){t.forEach(_=>this.buildLap(_))}buildLap(t){this.writeMesg("lap",{message_index:t.messageIndex,timestamp:t?.timestamp?t.timestamp:void 0,start_time:t?.startTime?t.startTime:void 0,start_position_lat:t?.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t?.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,end_position_lat:t?.endPositionLat!=null&&Number.isFinite(t.endPositionLat)?t.endPositionLat:void 0,end_position_long:t?.endPositionLong!=null&&Number.isFinite(t.endPositionLong)?t.endPositionLong:void 0,total_elapsed_time:t?.totalElapsedTime,total_timer_time:t?.totalTimerTime,total_distance:t?.totalDistance,total_ascent:t?.totalAscent,total_descent:t?.totalDescent})}buildRecords(t){t.forEach(_=>this.buildRecord(_))}buildRecord(t){this.writeMesg("record",{timestamp:t.timestamp,position_lat:t?.positionLat!=null&&Number.isFinite(t.positionLat)?t.positionLat:void 0,position_long:t?.positionLong!=null&&Number.isFinite(t.positionLong)?t.positionLong:void 0,altitude:t?.altitude,enhancedAltitude:t?.enhancedAltitude,distance:t?.distance,heart_rate:t?.heartRate,cadence:t?.cadence,speed:t?.speed,enhancedSpeed:t?.enhancedSpeed,power:t?.power})}buildEvent(t){this.writeMesg("event",{timestamp:t.timestamp?t.timestamp:void 0,event:t.event,event_type:t.eventType,event_group:t.eventGroup})}buildActivity(t){this.writeMesg("activity",{timestamp:t.timestamp?t.timestamp:void 0,total_timer_time:t.totalTimerTime,num_sessions:t.numSessions,type:t.type,event:t.event,event_type:t.eventType,local_timestamp:t.localTimestamp?this.parseTimestamp(t.localTimestamp):void 0,event_group:t.eventGroup})}buildCourse(t){this.writeMesg("course",{name:t.name,sport:t.sport})}buildEventsFromLaps(t,_){t.forEach((I,A)=>{I.startTime&&_.push({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:A}),I.timestamp&&_.push({timestamp:I.timestamp,event:"timer",eventType:A===t.length-1?"stop_all":"stop",eventGroup:A})})}buildActivityFromSession(t,_){_.push({timestamp:t.timestamp,totalTimerTime:t.totalTimerTime,numSessions:1,type:t.sport||this.options.defaultActivity,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(t){return typeof t=="number"?t:XI(t).valueOf()}validateRequiredFields(t){if(!t.sessionMesgs||t.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(t,_){let I=Object.fromEntries(Object.entries(_).filter(([L,E])=>E!==void 0));if(Object.keys(I).length===0)return;let A=this.localNum[t];A===void 0&&(A=this.localNum[t]=Object.keys(this.localNum).length);let T=new d_(A,t,I),n=this.mesgDefn[A];(!n||!T.isSameDefn(n))&&(this.messages.push(T.defnRecord),this.mesgDefn[A]=T.mesgDefn),this.messages.push(T.dataRecord)}get blob(){let t=[this.header,...this.messages,this.trailer];return new Blob(t,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((t,_)=>t+_.byteLength,0)}get dataCrc(){return this.messages.reduce((t,_)=>Gt(_,t),0)}get header(){let t=new DataView(new ArrayBuffer(Zt));return t.setUint8(0,Zt),t.setUint8(1,vI),t.setUint16(2,PI,!0),t.setUint32(4,this.dataLen,!0),t.setUint32(8,YI),t.setUint16(12,Gt(t.buffer.slice(0,12)),!0),t.buffer}get trailer(){let t=new DataView(new ArrayBuffer(2));return t.setUint16(0,this.dataCrc,!0),t.buffer}async encoder(t){return this.encode(t)}};import{Encoder as bI}from"@garmin/fitsdk";var NI="development",$I=1,kI=1;function QI(R,t){if(!Number.isFinite(R))throw new Error(`${t} must be a finite number.`)}function F_(R,t){return QI(R,t),Math.abs(R)<=180?Math.round(R*2147483648/180):Math.round(R)}function JI(R){if(!R.name||R.name.trim().length===0)throw new Error("Course name is required.");if(!Array.isArray(R.records)||R.records.length===0)throw new Error("Course must contain at least one record point.");let t=R.records.map((I,A)=>{if(I==null)throw new Error(`Course record #${A+1} is missing.`);if(I.timestamp==null)throw new Error(`Course record #${A+1} is missing timestamp.`);return{...I,positionLat:F_(I.latitude,`records[${A}].latitude`),positionLong:F_(I.longitude,`records[${A}].longitude`)}}),_=(R.coursePoints??[]).map((I,A)=>{if(I==null)throw new Error(`Course point #${A+1} is missing.`);if(I.timestamp==null)throw new Error(`Course point #${A+1} is missing timestamp.`);return{...I,type:I.type??0,positionLat:F_(I.latitude,`coursePoints[${A}].latitude`),positionLong:F_(I.longitude,`coursePoints[${A}].longitude`)}});return{...R,sport:R.sport??2,subSport:R.subSport??0,records:t,coursePoints:_,manufacturer:R.manufacturer??NI,product:R.product??$I,serialNumber:R.serialNumber??kI,timeCreated:R.timeCreated??t[0].timestamp}}function zI(R){let t=JI(R),_=t.records[0],I=t.records[t.records.length-1],A=_.timestamp,T=I.timestamp,n=[{mesgNum:0,data:{type:6,manufacturer:t.manufacturer,product:t.product,serialNumber:t.serialNumber,timeCreated:t.timeCreated}},{mesgNum:31,data:{name:t.name,sport:t.sport,subSport:t.subSport}},{mesgNum:19,data:{startTime:A,timestamp:T,startPositionLat:_.positionLat,startPositionLong:_.positionLong,endPositionLat:I.positionLat,endPositionLong:I.positionLong,totalDistance:I.distance}},{mesgNum:21,data:{timestamp:A,event:0,eventType:0}}];return t.records.forEach(L=>{n.push({mesgNum:20,data:{timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,altitude:L.altitude,speed:L.speed}})}),t.coursePoints.forEach((L,E)=>{n.push({mesgNum:32,data:{messageIndex:E,timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,type:L.type,name:L.name,favorite:L.favorite}})}),n.push({mesgNum:21,data:{timestamp:T,event:0,eventType:4}}),n}function qt(R){let t=new bI;return zI(R).forEach(I=>{t.onMesg(I.mesgNum,I.data)}),t.close()}var u=class{constructor(){this.version="1.0.0";this.priority=100}supports(t){return this.supportedTags.includes(t)}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}parseFloat(t){if(!(typeof t>"u"))return typeof t=="number"?t:typeof t=="string"&&parseFloat(t)||0}parseInt(t){return typeof t=="number"?Math.floor(t):typeof t=="string"&&parseInt(t,10)||0}parseString(t){return String(t||"")}parseBoolean(t){return typeof t=="boolean"?t:typeof t=="string"?t.toLowerCase()==="true":!1}parseDate(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}hasRequiredAttributes(t,_){return _.every(I=>t.attributes?.[I])}extractAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([A,T])=>{let n=I[A];n&&(_[n]=String(T??""))})}processChildren(t,_,I){t.children?.forEach(A=>{let T=I[A.tag];T&&T(A,_)})}getChildValue(t,_){let I=t.children?.find(A=>A.tag===_);return I?.value?String(I.value):void 0}getChildByTag(t,_){return t.children?.find(I=>I.tag===_)}getChildrenByTag(t,_){return t.children?.filter(I=>I.tag===_)||[]}convertExtensions(t){let _={};return t.children?.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}convertExtensionContent(t){if(t.children?.length){let _={};return t.children.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}else return t.value}};var J=class extends u{parseCoordinate(t){let _=this.parseFloat(t);return _===0?void 0:_}parseGPXTime(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}extractNumericAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([A,T])=>{let n=I[A];n&&n in _&&typeof T<"u"&&(_[n]=this.parseFloat(T))})}};var G_=class extends J{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(_,I){if(!this.hasRequiredAttributes(_,["lat","lon"])){I.warnings.push(`${this.name}: point without latitude or longitude was ignored`);return}let A={lat:this.parseFloat(_.attributes?.lat),lon:this.parseFloat(_.attributes?.lon)};return this.processChildren(_,A,{ele:(T,n)=>n.ele=this.parseFloat(T.value),time:(T,n)=>n.time=new Date(this.parseString(T.value)),speed:(T,n)=>n.speed=this.parseFloat(T.value),power:(T,n)=>n.power=this.parseFloat(T.value),cadence:(T,n)=>n.cadence=this.parseFloat(T.value),heartRate:(T,n)=>n.heartRate=this.parseFloat(T.value),course:(T,n)=>n.course=this.parseFloat(T.value),name:(T,n)=>n.name=this.parseString(T.value),cmt:(T,n)=>n.cmt=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),src:(T,n)=>n.src=this.parseString(T.value),sym:(T,n)=>n.sym=this.parseString(T.value),type:(T,n)=>n.type=this.parseString(T.value),fix:(T,n)=>n.fix=this.parseString(T.value),sat:(T,n)=>n.sat=this.parseFloat(T.value),hdop:(T,n)=>n.hdop=this.parseFloat(T.value),vdop:(T,n)=>n.vdop=this.parseFloat(T.value),pdop:(T,n)=>n.pdop=this.parseFloat(T.value),ageofdgpsdata:(T,n)=>n.ageofdgpsdata=this.parseFloat(T.value),geoidheight:(T,n)=>n.geoidheight=this.parseFloat(T.value),magvar:(T,n)=>n.magvar=this.parseFloat(T.value),dgpsid:(T,n)=>n.dgpsid=this.parseFloat(T.value),extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");if(E){let C=E.convert(T,I);C&&(this.mapExtensionsToPoint(C,n),n.extensions=C)}},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}mapExtensionsToPoint(_,I){Object.entries(_).forEach(([A,T])=>{if(T!==void 0&&(typeof T=="string"||typeof T=="number")){let n=L=>(Array.isArray(L)?L:[L]).some(C=>{let U=A.toLowerCase(),F=C.toLowerCase();return U===F||U.endsWith(`:${F}`)});n("speed")?I.speed=this.parseFloat(T):n("hr")?I.heartRate=this.parseFloat(T):n(["cad","cadence"])?I.cadence=this.parseFloat(T):n(["PowerInWatts","power"])&&(I.power=this.parseFloat(T))}})}},g_=class extends J{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(_,I){let A={rtept:[]};return this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),cmt:(T,n)=>n.cmt=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),src:(T,n)=>n.src=this.parseString(T.value),number:(T,n)=>n.number=this.parseFloat(T.value),type:(T,n)=>n.type=this.parseString(T.value),rtept:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(T,I);E&&n.rtept&&n.rtept.push(E)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}},l_=class extends J{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(_,I){let A={trkseg:[]};return this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),cmt:(T,n)=>n.cmt=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),src:(T,n)=>n.src=this.parseString(T.value),number:(T,n)=>n.number=this.parseFloat(T.value),type:(T,n)=>n.type=this.parseString(T.value),trkseg:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("trkseg")?.convert(T,I);E&&n.trkseg&&n.trkseg.push(E)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}},W_=class extends J{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(_,I){let A={trkpt:[]};return this.processChildren(_,A,{trkpt:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(T,I);E&&n.trkpt&&n.trkpt.push(E)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))}}),A}},M_=class extends J{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(_,I){let A={};return _.attributes?.href&&(A.href=_.attributes.href),this.processChildren(_,A,{text:(T,n)=>n.text=this.parseString(T.value),type:(T,n)=>n.type=this.parseString(T.value)}),A}},s_=class extends J{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(_,I){let A={};return this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),keywords:(T,n)=>n.keywords=this.parseString(T.value),time:(T,n)=>n.time=new Date(this.parseString(T.value)),author:(T,n)=>{let L=I.metadata.get("decoder");n.author=L?.getConverter("author")?.convert(T,I)},copyright:(T,n)=>{let L=I.metadata.get("decoder");n.copyright=L?.getConverter("copyright")?.convert(T,I)},bounds:(T,n)=>{let L=I.metadata.get("decoder");n.bounds=L?.getConverter("bounds")?.convert(T,I)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}},B_=class extends J{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(_,I){let A={};return _.value&&!_.children?.length?(A.name=this.parseString(_.value),A):(this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),email:(T,n)=>{let L=I.metadata.get("decoder");n.email=L?.getConverter("email")?.convert(T,I)},link:(T,n)=>{let L=I.metadata.get("decoder");n.link=L?.getConverter("link")?.convert(T,I)}}),A)}},V_=class extends J{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(_,I){return{id:_.attributes?.id,domain:_.attributes?.domain}}},p_=class extends J{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(_,I){let A={};return _.attributes?.author&&(A.author=_.attributes.author),this.processChildren(_,A,{year:(T,n)=>n.year=this.parseString(T.value),license:(T,n)=>n.license=this.parseString(T.value)}),A}},h_=class extends J{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(_,I){let A={};return this.extractAttributes(_,A,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),A}},K_=class extends J{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(_,I){let A={};return _.children?.forEach(T=>{this.flattenExtensionElement(T,A)}),A}flattenExtensionElement(_,I){if(!_.children?.length&&_.value!==void 0){I[_.tag]=this.parseExtensionValue(_.value);return}_.children?.length&&_.children.forEach(A=>{this.flattenExtensionElement(A,I)})}parseExtensionValue(_){if(_===void 0)return;let I=String(_),A=parseFloat(I);return!isNaN(A)&&isFinite(A)?A:I}};import{Parser as jI}from"htmlparser2";var w_=class{constructor(){this.stage="tokenize"}async process(t){let _=Date.now();if(!t.xmlContent)throw new Error("XML content cannot be empty");let I=[],A=new jI({onopentag(T,n){I.push({type:"open",tag:T,attributes:n})},ontext(T){let n=T.replace(/\n/g,"").trim();n&&I.push({type:"text",tag:"text",value:n})},onclosetag(T){I.push({type:"close",tag:T})}},{xmlMode:!0});return A.write(t.xmlContent),A.end(),t.tokens=I,t.performance.tokenizeTime=Date.now()-_,t}},X_=class{constructor(){this.stage="ast_generate"}async process(t){let _=Date.now();if(!t.tokens)throw new Error("Tokens cannot be empty");let I=[],A,T=null;for(let n of t.tokens)if(n.type==="open"){let L={tag:n.tag,attributes:n.attributes||{},children:[]};A?T&&T.children?.push(L):A=L,I.push(L),T=L}else n.type==="text"&&T?T.value=n.value:n.type==="close"&&(I.pop(),T=I[I.length-1]||null);return t.ast=A,t.performance.astTime=Date.now()-_,t}},v_=class{constructor(t){this.getConverter=t;this.stage="convert"}async process(t){let _=Date.now();if(!t.ast)throw new Error("AST cannot be empty");if(t.ast.tag!=="gpx")throw new Error(`Not a valid GPX document: expected <gpx>, received <${t.ast.tag}>`);let I={};return t.ast.attributes&&Object.entries(t.ast.attributes).forEach(([A,T])=>{A.startsWith("xmlns:")?I[A]=T.replace(/&#39;/g,"'"):A==="xsi:schemaLocation"?I[A]=T.replace(/&#39;/g,"'"):I[A]=T}),t.ast.children?.forEach(A=>{let T=this.getConverter(A.tag);if(!T){t.warnings.push(`Unsupported GPX element "${A.tag}" was ignored`);return}try{let n=T.convert(A,t);n&&this.assignResult(I,A.tag,n)}catch(n){throw t.errors.push(n),new Error(`GPX converter "${T.name}" failed for ${A.tag}: ${n.message}`)}}),t.result=I,t.performance.convertTime=Date.now()-_,t}assignResult(t,_,I){switch(_){case"metadata":t.metadata=I;break;case"wpt":t.wpt||(t.wpt=[]),t.wpt.push(I);break;case"rte":t.rte||(t.rte=[]),t.rte.push(I);break;case"trk":t.trk||(t.trk=[]),t.trk.push(I);break;case"extensions":t.extensions=I;break}}},P_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,tokenizeTime:t.performance.tokenizeTime,astTime:t.performance.astTime,convertTime:t.performance.convertTime}),t}};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 w_,new X_,new v_(t=>this.getConverter(t)),new P_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let t=[new G_,new g_,new l_,new W_,new M_,new s_,new B_,new V_,new p_,new h_,new K_];for(let _ of t)_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name);this.defaultConvertersRegistered=!0}addConverterForTag(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((A,T)=>(A.priority||100)-(T.priority||100))}async registerConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Converter plugin ${t.name} already exists`);t.supportedTags?.forEach(_=>{this.addConverterForTag(_,t)}),this.registeredPlugins.add(t.name)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t.name);_!==-1?this.middlewarePlugins[_]=t:this.middlewarePlugins.push(t)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getAllConverters(t){return this.converterPlugins.get(t)||[]}unregisterConverter(t){let _;for(let[I,A]of this.converterPlugins){let T=A.findIndex(n=>n.name===t);T!==-1&&(_=A[T],A.splice(T,1),A.length===0&&this.converterPlugins.delete(I))}_&&this.registeredPlugins.delete(t)}unregisterMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t);_!==-1&&this.middlewarePlugins.splice(_,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(t=>t.name)}listProcessors(){return this.processors.map(t=>t.constructor.name)}getConverterDetails(t){let _={};if(t){let I=this.converterPlugins.get(t);I&&(_[t]=I.map(A=>({name:A.name,priority:A.priority||100})))}else for(let[I,A]of this.converterPlugins)_[I]=A.map(T=>({name:T.name,priority:T.priority||100}));return _}getMiddlewareDetails(){return this.middlewarePlugins.map(t=>{let _=[];return t.onTokenize&&_.push("onTokenize"),t.onAstGenerate&&_.push("onAstGenerate"),t.onConvert&&_.push("onConvert"),t.onComplete&&_.push("onComplete"),t.onError&&_.push("onError"),{name:t.name,hooks:_}})}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let A=_;for(let T of this.middlewarePlugins){let n=T[t];if(n)try{A=await n.call(T,A,I)||A}catch(L){I.errors.push(L),await T.onError?.(L,I)}}return A}async parserByBuffer(t){await this.initialize();let _=this.createContext();_.rawData=t,_.xmlContent=t.toString("utf-8"),_.metadata.set("decoder",this);for(let I of this.processors)try{switch(_=await I.process(_),I.stage){case"tokenize":_.tokens&&(_.tokens=await this.executeMiddlewareHook("onTokenize",_.tokens,_));break;case"ast_generate":_.ast&&(_.ast=await this.executeMiddlewareHook("onAstGenerate",_.ast,_));break;case"convert":_.result&&(_.result=await this.executeMiddlewareHook("onConvert",_.result,_));break;case"complete":_.result&&(_.result=await this.executeMiddlewareHook("onComplete",_.result,_));break}}catch(A){_.errors.push(A);for(let T of this.middlewarePlugins)await T.onError?.(A,_);throw new Error(`GPX pipeline stage "${I.stage}" failed: ${A.message}`)}return _.result}convertExtensions(t){let _={},{attributes:I,tag:A,value:T}=t;if(I&&Object.entries(I).forEach(([n,L])=>{_[n]=L}),t?.children?.length)t.children?.forEach(n=>{_[n.tag]=this.convertExtensions(n)});else if(T!==void 0)return T;return _}};import it from"dayjs";import yI from"dayjs/plugin/utc.js";var gt={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var lt={temperature:"Temperature",Depth:"Depth"};it.extend(yI);var b_=class{constructor(t={}){this.formatElevation=t=>{let _=parseFloat(t);return isNaN(_)?t:this.roundTo(_,2).toString()};this.compact=t.compact??!0}async encode(t){let _=this.buildGPXXML(t);return Buffer.from(_,"utf-8")}encodeToString(t){return this.buildGPXXML(t)}buildGPXXML(t){let _=this.buildXMLHeader(t),I=this.buildGPXContent(t),T=`${_}${I}
1
+ var k=class extends Error{constructor(t,_,I={}){super(_),this.name="TrackSwapError",this.code=t,this.format=I.format,this.cause=I.cause}};function t_(R,t,_,I){if(R instanceof k)return R;let A=R instanceof Error?R.message:String(R);return new k(t,`${_}: ${A}`,{format:I,cause:R})}var y=class{constructor(){this.version="1.0.0";this.priority=100}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}};var n_="trackswap-health-ir-v1",Ct=new Set(["timestampCorrelationMesgs","monitoringInfoMesgs","monitoringMesgs","monitoringHrDataMesgs","stressLevelMesgs","respirationRateMesgs","spo2DataMesgs","hrvStatusSummaryMesgs","hrvValueMesgs","sleepLevelMesgs","sleepAssessmentMesgs","napEventMesgs","hsaStepDataMesgs","hsaSpo2DataMesgs","hsaStressDataMesgs","hsaRespirationDataMesgs","hsaHeartRateDataMesgs","hsaBodyBatteryDataMesgs","hsaWristTemperatureDataMesgs","skinTempOvernightMesgs","sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"]),AI=new Set([...Ct].filter(R=>R!=="timestampCorrelationMesgs")),TI=new Set(["fileIdMesgs","fileCreatorMesgs","deviceInfoMesgs","deviceSettingsMesgs","softwareMesgs","ohrSettingsMesgs","eventMesgs","activityMesgs","sessionMesgs","lapMesgs","recordMesgs","lengthMesgs","courseMesgs","coursePointMesgs","workoutMesgs","workoutStepMesgs","trainingFileMesgs"]),nI=[{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}],RI=[{field:"ascent",metric:"ascent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"descent",metric:"descent_m",unit:"m",intervalStrategy:"previous_timestamp"},{field:"moderateActivityMinutes",metric:"moderate_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"},{field:"vigorousActivityMinutes",metric:"vigorous_activity_time_s",unit:"s",multiplier:60,intervalStrategy:"value_duration"}],ft=631065600,I_=2**16,Kt=18*60*60,LI=new Set([65519,65518]),EI=5;function v(R){return R&&typeof R=="object"?R:{}}function K(R){if(typeof R=="number")return Number.isFinite(R)?R:void 0;if(typeof R!="string"||R.trim()==="")return;let t=Number(R);return Number.isFinite(t)?t:void 0}function P(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R!="string"&&typeof R!="number"||typeof R=="string"&&R.trim()==="")return;let t=new Date(R);return Number.isFinite(t.valueOf())?t:void 0}function ot(R){return Xt(R)?.toISOString().replace(/Z$/,"")}function Xt(R){if(R instanceof Date&&Number.isFinite(R.valueOf()))return R;if(typeof R=="string"&&!/^\s*[-+]?\d+(?:\.\d+)?\s*$/.test(R))return P(R);let t=K(R);if(!(t===void 0||t<0))return new Date((t+ft)*1e3)}function w(R,t,_){return{messageName:R,messageIndex:t,fieldName:_}}function Ht(R,t){return Object.fromEntries(t.map(_=>[_,R[_]]).filter(([,_])=>typeof _=="number"?Number.isFinite(_):["string","boolean"].includes(typeof _)))}function vt(R){return Object.fromEntries(Object.entries(R).filter(([,t])=>Array.isArray(t)&&t.length>0).map(([t,_])=>[t,_?.length??0]))}function Pt(R){let t=[];return((R.activityMesgs?.length??0)>0||(R.sessionMesgs?.length??0)>0)&&t.push("activity"),[...AI].some(_=>(R[_]?.length??0)>0)&&t.push("health"),((R.workoutMesgs?.length??0)>0||(R.workoutStepMesgs?.length??0)>0)&&t.push("workout"),(R.courseMesgs?.length??0)>0&&t.push("course"),t.length===0&&((R.deviceInfoMesgs?.length??0)>0||(R.fileIdMesgs?.length??0)>0)&&t.push("device"),t.length>0?t:["unknown"]}function OI(R){let t=String(R??"").trim().toLowerCase().replace(/[_\s-]+/g,"");return t.includes("awake")?"awake":t.includes("deep")?"deep":t.includes("light")?"light":t.includes("rem")?"rem":t.includes("unmeasurable")?"unmeasurable":t.includes("sleep")?"sleeping":`vendor:${t||"unknown"}`}function SI(R,t=0){return new Date(R.valueOf()+t*1e3).toISOString().slice(0,10)}function wt(R,t,_=0){return SI(new Date(Math.max(R.valueOf(),t.valueOf()-1)),_)}function dt(R){let t=K(R);return t===void 0?void 0:t*60}function DI(R,t){let _=[],I=(n,L,E,C,U)=>{let F=P(E.timestamp),V=Xt(E.localTimestamp);if(!F||!V)return;let p=Math.round((V.valueOf()-F.valueOf())/1e3),W=w(n,L,"localTimestamp");if(Math.abs(p)>Kt){t(W);return}_.push({at:F,offsetSeconds:p,priority:C,strategy:U,source:W})};(R.timestampCorrelationMesgs??[]).forEach((n,L)=>{I("timestampCorrelationMesgs",L,v(n),3,"timestamp_correlation")});for(let n of["monitoringInfoMesgs","monitoringMesgs","skinTempOvernightMesgs"])(R[n]??[]).forEach((L,E)=>{I(n,E,v(L),1,"inferred")});(R.napEventMesgs??[]).forEach((n,L)=>{let E=v(n);for(let[C,U]of[["startTime","startTimezoneOffset"],["endTime","endTimezoneOffset"]]){let F=P(E[C]),V=dt(E[U]);if(!F||V===void 0)continue;let p=w("napEventMesgs",L,U);if(Math.abs(V)>Kt){t(p);continue}_.push({at:F,offsetSeconds:V,priority:2,strategy:"explicit_offset",source:p})}}),_.sort((n,L)=>n.at.valueOf()-L.at.valueOf()||L.priority-n.priority);let A=_.filter((n,L)=>L===0||n.at.valueOf()!==_[L-1].at.valueOf()).map(({at:n,offsetSeconds:L})=>({at:n,offsetSeconds:L})),T=_.find(({strategy:n})=>n==="timestamp_correlation")?.strategy??_.find(({strategy:n})=>n==="explicit_offset")?.strategy??_.find(({strategy:n})=>n==="inferred")?.strategy??"unknown";return{offsets:A,strategy:T}}function oI(R,t){let _=K(R);if(!t||!Number.isInteger(_)||_<0||_>=I_)return;let I=Math.floor(t.valueOf()/1e3)-ft,A=Math.floor(I/I_)*I_+_;return A<I&&(A+=I_),new Date((A+ft)*1e3)}function HI(R){let t,_,I,A,T,n;return(R.monitoringMesgs??[]).map(L=>{let E=v(L),U=P(E.timestamp)??oI(E.timestamp16,t);U&&(t=U),U&&(!_||U>_)&&(I=_,_=U);let F=I;E.activityType!==void 0&&(A=E.activityType),E.deviceIndex!==void 0&&(n=E.deviceIndex);let V=E.intensity??E.activityLevel;return V!==void 0&&(T=V),{message:E,timestamp:U,intervalStartTime:F,deviceIndex:n,activityType:A,intensity:T}})}function Z(R,t){let _;for(let I of R){if(I.at>t)break;_=I.offsetSeconds}return _??R[0]?.offsetSeconds}function A_(R,t){if(t!==void 0)return new Date(R.valueOf()+t*1e3).toISOString().replace(/Z$/,"")}function CI(R,t,_,I){return t>=R?{value:t-R}:R>=_*.75&&R<_&&t>=0&&t<=_*.25?{value:_-R+t,rolloverBits:I}:null}function Yt(R){return R>=1&&R<=100?"valid":R===-1?"off_wrist":R===-2?"motion":R===-3?"not_enough_data":R===-4?"recovering":R===-5?"unidentified":R===-16?"gap":R===0||R>100?"invalid":"unknown"}function fI(R){return R>=0&&R<=100?"valid":Yt(R)}function dI(R){return R===255?"invalid":R===254?"motion":R===253?"off_wrist":R===252?"not_enough_data":R===2.4?"gap":R>=1&&R<=100?"valid":"invalid"}function i(R,t,_){return new Date(R.valueOf()+t*_*1e3)}function UI(R){let t=new Map,_={};R.warnings.forEach(I=>{_[I.code]=(_[I.code]??0)+1;let A=t.get(I.code)??[];A.length<EI&&(A.push(I),t.set(I.code,A))}),R.warningCounts=_,R.warnings=[...t.values()].flat()}function FI(R){return R===-1?"off_wrist":R===-2?"motion":R===-3?"invalid":R>0&&R<=100?"valid":"invalid"}function bt(R,t={},_={}){let I=vt(R),A=Object.fromEntries(Object.entries(I).filter(([H])=>Ct.has(H))),T=Object.fromEntries(Object.entries(I).filter(([H])=>!Ct.has(H)&&!TI.has(H))),n={sdkProfileVersion:_.sdkProfileVersion,parserVersion:n_,messageCounts:I,recognizedMessageCounts:A,unknownMessageCounts:T,invalidValueCounts:{},warningCounts:{},warnings:[]};t.includeUnknownMessages&&(n.unknownMessages=Object.fromEntries(Object.keys(T).map(H=>[H,R[H]??[]])));let L=[],E=[],C=[],U=[],F=[],V=DI(R,H=>{n.warnings.push({code:"GARMIN_HEALTH_INVALID_TIMEZONE_OFFSET",message:"Ignored an implausible FIT timezone offset",source:H})}),{offsets:p}=V,W=H=>{let d=H.offsetSeconds??Z(p,H.timestamp);if(H.offsetSeconds=d,H.localTimestamp??=A_(H.timestamp,d),L.push(H),F.push(H.timestamp),H.status!=="valid"){let D=`${H.metric}:${H.status}`;n.invalidValueCounts[D]=(n.invalidValueCounts[D]??0)+1}},J=new Map;HI(R).forEach(({message:H,timestamp:d,intervalStartTime:D,deviceIndex:f,activityType:o,intensity:g},l)=>{if(!d){n.warnings.push({code:"GARMIN_HEALTH_NO_TIMESTAMP",message:"Monitoring message has no valid timestamp",source:w("monitoringMesgs",l)});return}F.push(d);let B=K(H.heartRate);if(B!==void 0){let G=B>0?"valid":"gap";W({metric:"heart_rate_bpm",timestamp:d,localTimestamp:ot(H.localTimestamp),value:G==="valid"?B:void 0,unit:"bpm",status:G,aggregation:"instant",source:w("monitoringMesgs",l,"heartRate"),attributes:G==="valid"?void 0:{rawValue:B}})}let M=K(H.temperature);M!==void 0&&W({metric:"temperature_c",timestamp:d,localTimestamp:ot(H.localTimestamp),value:M,unit:"degC",status:"valid",aggregation:"mean",source:w("monitoringMesgs",l,"temperature")});for(let G of nI){let X=K(H[G.field]);if(X===void 0)continue;let N=[f??"device",o??"activity",G.field].join(":"),s=J.get(N);if(s&&d>s.timestamp){let h=CI(s.value,X,G.rolloverModulus,G.rolloverBits);if(h){h.rolloverBits&&n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_ROLLOVER",message:`${G.field} accumulator rolled over at ${h.rolloverBits} bits`,source:w("monitoringMesgs",l,G.field)});let m=Z(p,s.timestamp);E.push({metric:G.metric,startTime:s.timestamp,endTime:d,localStartTime:A_(s.timestamp,m),offsetSeconds:m,value:h.value,unit:G.unit,status:"valid",activityType:o===void 0?void 0:String(o),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",l,G.field),attributes:t.health?.retainCumulativeValues===!1?void 0:{rawCumulativeValue:X}})}else n.warnings.push({code:"GARMIN_HEALTH_ACCUMULATOR_RESET",message:`${G.field} accumulator decreased; a new accumulation window was started`,source:w("monitoringMesgs",l,G.field)})}J.set(N,{timestamp:d,value:X})}for(let G of RI){let X=K(H[G.field]);if(X===void 0||X<0)continue;let N=X*(G.multiplier??1),s=G.intervalStrategy==="value_duration"?new Date(d.valueOf()-N*1e3):D;if(!s||s>=d)continue;let h=Z(p,s);F.push(s),E.push({metric:G.metric,startTime:s,endTime:d,localStartTime:A_(s,h),offsetSeconds:h,value:N,unit:G.unit,status:"valid",activityType:o===void 0?void 0:String(o),intensity:g===void 0?void 0:String(g),source:w("monitoringMesgs",l,G.field)})}}),(R.monitoringHrDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp);if(!f)return;[{field:"currentDayRestingHeartRate",metric:"resting_heart_rate_bpm"},{field:"restingHeartRate",metric:"resting_heart_rate_7_day_bpm"}].forEach(({field:g,metric:l})=>{let B=K(D[g]);if(B===void 0)return;let M=B>0?"valid":"invalid";W({metric:l,timestamp:f,value:M==="valid"?B:void 0,unit:"bpm",status:M,aggregation:"latest",source:w("monitoringHrDataMesgs",d,g),attributes:M==="valid"?void 0:{rawValue:B}})})}),(R.stressLevelMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.stressLevelTime),o=K(D.stressLevelValue);if(!f||o===void 0)return;let g=Yt(o);W({metric:"stress_level",timestamp:f,value:g==="valid"?o:void 0,unit:"score",status:g,aggregation:"instant",source:w("stressLevelMesgs",d,"stressLevelValue"),attributes:g==="valid"?void 0:{rawValue:o}})}),(R.respirationRateMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.respirationRate);if(!f||o===void 0)return;let g=FI(o);W({metric:"respiration_rate_bpm",timestamp:f,value:g==="valid"?o:void 0,unit:"breaths/min",status:g,aggregation:"instant",source:w("respirationRateMesgs",d,"respirationRate"),attributes:g==="valid"?void 0:{rawValue:o}})}),(R.spo2DataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.readingSpo2);if(!f||o===void 0)return;let g=K(D.readingConfidence),l=o<=0||o>100?"invalid":g!==void 0&&g<=0?"low_confidence":"valid";W({metric:"spo2_percent",timestamp:f,value:l==="invalid"?void 0:o,unit:"percent",status:l,quality:g,aggregation:"instant",source:w("spo2DataMesgs",d,"readingSpo2"),attributes:{measurementMode:D.mode===void 0?null:String(D.mode),...l==="invalid"?{rawValue:o}:{}}})}),(R.hrvValueMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.value);if(!f||o===void 0)return;let g=o>0?"valid":"invalid";W({metric:"hrv_rmssd_ms",timestamp:f,value:g==="valid"?o:void 0,unit:"ms",status:g,aggregation:"mean",source:w("hrvValueMesgs",d,"value"),attributes:{windowSeconds:300,...g==="valid"?{}:{rawValue:o}}})}),(R.hrvStatusSummaryMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp);C.push({summaryType:"hrv_status",externalId:`fit:hrv-status:${f?.toISOString()??d}`,startTime:f,metrics:Ht(D,["weeklyAverage","lastNightAverage","lastNight5MinHigh","baselineLowUpper","baselineBalancedLower","baselineBalancedUpper","status"]),source:w("hrvStatusSummaryMesgs",d)}),f&&F.push(f)}),(R.monitoringInfoMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp);C.push({summaryType:"device",externalId:`fit:monitoring-info:${f?.toISOString()??d}`,startTime:f,offsetSeconds:f?Z(p,f):void 0,metrics:Ht(D,["restingMetabolicRate","activityType","cyclesToDistance","cyclesToCalories"]),source:w("monitoringInfoMesgs",d)}),f&&F.push(f)}),(R.skinTempOvernightMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp);if(!f)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:g,metric:l})=>{let B=K(D[g]);B!==void 0&&W({metric:l,timestamp:f,localTimestamp:ot(D.localTimestamp),value:B,unit:"degC",status:"valid",aggregation:"mean",source:w("skinTempOvernightMesgs",d,g)})})});let Y=(R.sleepLevelMesgs??[]).map((H,d)=>({message:v(H),messageIndex:d,timestamp:P(v(H).timestamp)})).filter(H=>H.timestamp!==void 0).sort((H,d)=>H.timestamp.valueOf()-d.timestamp.valueOf());if(Y.length>=2){let H=v(R.sleepAssessmentMesgs?.[0]),d=[];for(let g=0;g<Y.length-1;g+=1){let l=Y[g],B=Y[g+1];if(B.timestamp<=l.timestamp)continue;let M={segmentType:OI(l.message.sleepLevel),startTime:l.timestamp,endTime:B.timestamp,status:"valid",source:w("sleepLevelMesgs",l.messageIndex,"sleepLevel")},G=d.at(-1);G&&G.segmentType===M.segmentType&&G.endTime.valueOf()===M.startTime.valueOf()?G.endTime=M.endTime:d.push(M)}let D=Y[0].timestamp,f=Y.at(-1).timestamp;F.push(D,f);let o=Z(p,f);U.push({sessionType:"sleep",externalId:`fit:sleep:${D.toISOString()}:${f.toISOString()}`,startTime:D,endTime:f,startOffsetSeconds:Z(p,D),endOffsetSeconds:o,calendarDate:wt(D,f,o),segments:d,metrics:Ht(H,["combinedAwakeScore","awakeTimeScore","awakeningsCountScore","deepSleepScore","sleepDurationScore","lightSleepScore","overallSleepScore","sleepQualityScore","sleepRecoveryScore","remSleepScore","sleepRestlessnessScore","awakeningsCount","interruptionsScore","averageStressDuringSleep"]),source:w("sleepLevelMesgs",Y[0].messageIndex),attributes:{calendarDateStrategy:o===void 0?"sleep_end_utc_fallback_date":"sleep_end_local_date"}})}else Y.length>0&&n.warnings.push({code:"GARMIN_HEALTH_SLEEP_BOUNDARY_INCOMPLETE",message:"Sleep level data does not contain enough boundaries",source:w("sleepLevelMesgs",Y[0].messageIndex)});for(let H of["sleepDisruptionSeverityPeriodMesgs","sleepDisruptionOvernightSeverityMesgs"])(R[H]??[]).forEach((d,D)=>{let f=v(d),o=P(f.timestamp);!o||f.severity===void 0||(F.push(o),C.push({summaryType:"sleep",externalId:`fit:${H}:${f.messageIndex??D}:${o.toISOString()}`,startTime:o,offsetSeconds:Z(p,o),metrics:{severity:String(f.severity)},source:w(H,D,"severity")}))});return(R.napEventMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.startTime),o=P(D.endTime),g=D.isDeleted===!0;if(!f||!o||o<f||!g&&o.valueOf()===f.valueOf())return;let l=dt(D.startTimezoneOffset),B=dt(D.endTimezoneOffset);F.push(f,o),U.push({sessionType:"nap",externalId:`fit:nap:${D.messageIndex??d}:${f.toISOString()}`,startTime:f,endTime:o,startOffsetSeconds:l,endOffsetSeconds:B,calendarDate:wt(f,o,B??l),deleted:g,segments:[],metrics:{},source:w("napEventMesgs",d),attributes:{source:D.source===void 0?null:String(D.source),feedback:D.feedback===void 0?null:String(D.feedback),updateTimestamp:P(D.updateTimestamp)?.toISOString()??null}})}),(R.hsaStepDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval),g=Array.isArray(D.steps)?D.steps:[];!f||!o||o<=0||LI.has(o)||g.forEach((l,B)=>{let M=K(l);if(M===void 0||M<0)return;let G=i(f,o,B),X=new Date(G.valueOf()+o*1e3),N=Z(p,G);F.push(G,X),E.push({metric:"steps",startTime:G,endTime:X,localStartTime:A_(G,N),offsetSeconds:N,value:M,unit:"count",status:"valid",source:w("hsaStepDataMesgs",d,"steps"),attributes:{sequenceIndex:B,intervalSeconds:o}})})}),(R.hsaSpo2DataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval),g=Array.isArray(D.readingSpo2)?D.readingSpo2:[],l=Array.isArray(D.confidence)?D.confidence:[];!f||!o||o<=0||g.forEach((B,M)=>{let G=K(B);if(G===void 0)return;let X=K(l[M]),N=G<70||G>100||G===240?"invalid":X!==void 0&&X<=0?"low_confidence":"valid";W({metric:"spo2_percent",timestamp:i(f,o,M),value:N==="invalid"?void 0:G,unit:"percent",status:N,quality:X,aggregation:"instant",source:w("hsaSpo2DataMesgs",d,"readingSpo2"),attributes:{sequenceIndex:M,intervalSeconds:o,...N==="invalid"?{rawValue:G}:{}}})})}),(R.hsaStressDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval),g=Array.isArray(D.stressLevel)?D.stressLevel:[];!f||!o||o<=0||g.forEach((l,B)=>{let M=K(l);if(M===void 0)return;let G=fI(M);W({metric:"stress_level",timestamp:i(f,o,B),value:G==="valid"?M:void 0,unit:"score",status:G,aggregation:"instant",source:w("hsaStressDataMesgs",d,"stressLevel"),attributes:{sequenceIndex:B,intervalSeconds:o,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaRespirationDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval),g=Array.isArray(D.respirationRate)?D.respirationRate:[];!f||!o||o<=0||g.forEach((l,B)=>{let M=K(l);if(M===void 0)return;let G=dI(M);W({metric:"respiration_rate_bpm",timestamp:i(f,o,B),value:G==="valid"?M:void 0,unit:"breaths/min",status:G,aggregation:"instant",source:w("hsaRespirationDataMesgs",d,"respirationRate"),attributes:{sequenceIndex:B,intervalSeconds:o,...G==="valid"?{}:{rawValue:M}}})})}),(R.hsaHeartRateDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval),g=Array.isArray(D.heartRate)?D.heartRate:[],l=K(D.status);!f||!o||o<=0||g.forEach((B,M)=>{let G=K(B);if(G===void 0)return;let X=G===0?"gap":l===1?"valid":l===0?"low_confidence":"unknown";W({metric:"heart_rate_bpm",timestamp:i(f,o,M),value:X==="gap"?void 0:G,unit:"bpm",status:X,aggregation:"instant",source:w("hsaHeartRateDataMesgs",d,"heartRate"),attributes:{sequenceIndex:M,intervalSeconds:o,measurementStatus:l??null,...X==="gap"?{rawValue:G}:{}}})})}),(R.hsaWristTemperatureDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval),g=Array.isArray(D.value)?D.value:[];!f||!o||o<=0||g.forEach((l,B)=>{let M=K(l);M!==void 0&&W({metric:"wrist_temperature_c",timestamp:i(f,o,B),value:M,unit:"degC",status:"valid",aggregation:"instant",source:w("hsaWristTemperatureDataMesgs",d,"value"),attributes:{sequenceIndex:B,intervalSeconds:o}})})}),(R.hsaBodyBatteryDataMesgs??[]).forEach((H,d)=>{let D=v(H),f=P(D.timestamp),o=K(D.processingInterval)??0;if(!f||o<=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:l,metric:B,unit:M})=>{(Array.isArray(D[l])?D[l]:[]).forEach((X,N)=>{let s=K(X);if(s===void 0)return;let h=l==="level"&&s===-16?"gap":l==="level"&&(s<0||s>100)?"invalid":"valid";W({metric:B,timestamp:i(f,o,N),value:h==="valid"?s:void 0,unit:M,status:h,aggregation:"instant",source:w("hsaBodyBatteryDataMesgs",d,l),attributes:{sequenceIndex:N,intervalSeconds:o,...h==="valid"?{}:{rawValue:s}}})})})}),L.sort((H,d)=>H.timestamp.valueOf()-d.timestamp.valueOf()),E.sort((H,d)=>H.startTime.valueOf()-d.startTime.valueOf()),U.sort((H,d)=>H.startTime.valueOf()-d.startTime.valueOf()),F.sort((H,d)=>H.valueOf()-d.valueOf()),UI(n),{schemaVersion:"1",observedStart:F[0],observedEnd:F.at(-1),timezone:{strategy:V.strategy,offsets:p},points:L,intervals:t.health?.reconstructIntervals===!1?[]:E,summaries:C,sessions:U,diagnostics:n}}var T_=class extends y{constructor(){super(...arguments);this.name="HealthStructurePlugin";this.priority=20}structureData(_,I){let A=I.userData?.fitDocumentOptions??{},T=Pt(_);return{healthDocument:T.includes("health")?bt(_,A,{sdkProfileVersion:I.metadata.get("fit-sdk-profile-version")}):void 0,fitDocumentMetadata:{detectedKinds:T,messageCounts:vt(_)}}}};var R_=(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))(R_||{});var L_=(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))(L_||{});function Nt(R,t){if(!t)return;let _=t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"").toUpperCase();for(let I of Object.keys(R)){if(!Number.isNaN(Number(I))||I.toUpperCase()!==_)continue;let A=R[I];return typeof A=="number"?A:void 0}}function GI(R){let t=R.metadata?.fileName?.trim();if(t)return t;let _=R.metadata?.originType;return _?`${_.toLowerCase()}-course`:"course"}function $t(R){let t=R.activities?.[0],I=[...(R.activities?.flatMap(A=>A.laps??[])??[]).flatMap(A=>A.records??[]),...R.routes?.flatMap(A=>A.records??[])??[],...R.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(I.length===0)throw new Error("Cannot build a FIT course without timestamped coordinates");return{name:GI(R),sport:Nt(R_,t?.sport)??2,subSport:Nt(L_,t?.subSport)??0,records:I,timeCreated:I[0].timestamp}}function kt(){return process.env.TRACKSWAP_FIT_DEBUG==="1"||process.env.TRACKSWAP_DEBUG==="1"}function b(...R){kt()}function a(...R){kt()}var E_=class{constructor(){this.stage="parse"}async process(t){let _=Date.now();if(!t.rawData)throw new Error("FIT data cannot be empty");try{let I=await this.parseWithFitSDK(t.rawData,t);return t.rawMessages=I,b("\u{1F389} FIT parsing raw messages:",I),t.performance.parseTime=Date.now()-_,b(`\u{1F527} FIT parsing completed, contains message types: ${Object.keys(I).join(", ")}`),t}catch(I){throw new Error(`FIT parsing failed: ${I.message}`)}}async parseWithFitSDK(t,_){let{Decoder:I,Profile:A,Stream:T}=await import("@garmin/fitsdk"),n=[A.version?.major,A.version?.minor,A.version?.patch].filter(F=>F!==void 0);n.length>0&&_.metadata.set("fit-sdk-profile-version",n.join("."));let L=T.fromBuffer(t);if(!I.isFIT(L))throw new Error("Not a valid FIT file");let E=new I(L),{messages:C,errors:U}=E.read();return U&&U.length>0&&a("FIT parsing warnings:",U),C}};function gI(R){let t={...R};return t.position_lat!=null&&t.positionLat==null&&(t.positionLat=t.position_lat),t.position_long!=null&&t.positionLong==null&&(t.positionLong=t.position_long),t}var O_=class{constructor(t){this.getConverters=t;this.stage="extract"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Raw messages cannot be empty");let I={};for(let[A,T]of Object.entries(t.rawMessages)){if(!Array.isArray(T)||T.length===0){I[A]=T;continue}let n=this.getConverters(A);if(n.length===0)I[A]=A==="recordMesgs"?T.map(L=>gI(L)):T,b(`\u{1F4CB} Message type "${A}" has no converter, using raw data`);else{let L=n[0];try{let E=L.convertMessages(T,t);I[A]=E,b(`\u2705 Message type "${A}" using converter ${L.name}`)}catch(E){t.errors.push(E),I[A]=T,a(`FIT converter "${L.name}" failed for ${A}; raw messages were retained`,E)}}}return t.rawMessages=I,t.performance.extractTime=Date.now()-_,t}},S_=class{constructor(t){this.getStructurePlugins=t;this.stage="structure"}async process(t){let _=Date.now();if(!t.rawMessages)throw new Error("Message data cannot be empty");let I={...t.rawMessages},A=this.getStructurePlugins();for(let T of A)try{let n=T.structureData(t.rawMessages,t);I={...I,...n},b(`\u{1F527} Structure plugin ${T.name} processing completed`)}catch(n){throw t.errors.push(n),new Error(`FIT structure plugin "${T.name}" failed: ${n.message}`)}return t.result=I,t.performance.structureTime=Date.now()-_,t}},D_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,parseTime:t.performance.parseTime,extractTime:t.performance.extractTime,structureTime:t.performance.structureTime}),t.stats&&(t.stats.endTime=Date.now(),t.rawMessages&&(t.stats.processedTokens=this.countTotalMessages(t.rawMessages))),b(`\u2705 FIT processing completed, total time: ${_}ms`),t}countTotalMessages(t){let _=0;return Object.values(t).forEach(I=>{Array.isArray(I)&&(_+=I.length)}),_}};import $ from"dayjs";var o_=class extends y{constructor(){super(...arguments);this.name="SessionStructurePlugin";this.priority=10}structureData(_,I){let{sessionMesgs:A,lapMesgs:T,recordMesgs:n,lengthMesgs:L,setMesgs:E}=_;if(!A?.length)return a("No structured session found, data structure is incomplete"),{};let C=A.map((V,p)=>{let W=$(V.startTime).valueOf(),J=W+(V.totalElapsedTime??0)*1e3,Y=$(V.timestamp).valueOf(),H=Math.max(Number.isFinite(J)?J:Number.NEGATIVE_INFINITY,Number.isFinite(Y)?Y:Number.NEGATIVE_INFINITY),d=A[p+1],D=d?$(d.startTime).valueOf():Number.NaN,f=Number.isFinite(D)&&D>W,o=V.firstLapIndex,g=V.numLaps,l=typeof o=="number"&&typeof g=="number"?(T??[]).filter(s=>{let h=s.messageIndex;return typeof h=="number"&&h>=o&&h<o+g}):[],B=(l.length===g&&l.length>0?l:(T??[]).filter(s=>{let h=$(s.startTime).valueOf();return Number.isFinite(h)&&h>=W&&h<=H+2e3})).sort((s,h)=>$(s.startTime).valueOf()-$(h.startTime).valueOf()),M=A.length===1?[...n??[]]:(n??[]).filter(s=>{let h=$(s.timestamp).valueOf();return Number.isFinite(h)?(p===0||h>=W)&&(!f||h<D):p===0}),G=(E??[]).filter(s=>{let h=$(s.startTime??s.timestamp).valueOf();return Number.isFinite(h)?h<W?!1:f?h<D:h<=H+2e3:A.length===1}),X=B.length>0?B:M.length>0?[{...V,messageIndex:typeof V.firstLapIndex=="number"?V.firstLapIndex:p,recordMesgs:M}]:[];if(B.length===0&&X.length===1){let s=Number(I.metadata.get("fit-synthetic-lap-count")??0);I.metadata.set("fit-synthetic-lap-count",s+1)}let N=X.map((s,h)=>{let m=$(s.startTime).valueOf(),st=X[h+1]?.startTime,Ot=st==null?Number.NaN:$(st).valueOf(),_I=m+(s.totalElapsedTime??0)*1e3,Vt=Number.isFinite(Ot)&&Ot>m,tI=Vt?Ot:Math.max(_I,H),II=B.length===0?M:M.filter(Dt=>{let c=$(Dt.timestamp).valueOf();return Number.isFinite(c)?(h===0||c>=m)&&(!Vt||c<tI):h===0}),St=s.firstLengthIndex??void 0,pt=s.numLengths??void 0,ht=[];if(St!==void 0&&pt!==void 0){let Dt=St+pt;ht=L?.filter(c=>c.messageIndex>=St&&c.messageIndex<Dt)||[]}return{...s,recordMesgs:II,lengthMesgs:ht,messageIndex:s.messageIndex!==void 0?s.messageIndex:0}});return{...V,lapMesgs:N,setMesgs:G}}),U=new Set;for(let V of C)for(let p of V.lapMesgs??[])for(let W of p.recordMesgs??[])W?.timestamp!=null&&U.add($(W.timestamp).valueOf());let F=0;for(let V of n??[]){if(V?.timestamp==null)continue;let p=$(V.timestamp).valueOf();U.has(p)||F++}return F>0&&(I.metadata.set("fit-unassigned-record-count",F),a(`SessionStructurePlugin: ${F} record(s) did not fall into any lap time window`)),{sessionMesgs:C}}},H_=class extends y{constructor(){super(...arguments);this.name="CourseStructurePlugin";this.priority=10}structureData(_,I){let{courseMesgs:A,lapMesgs:T,recordMesgs:n}=_;if(!A?.length)return{};let L=2e3;return{courseMesgs:A.map(C=>{let U=T?.map(F=>{let V=$(F.startTime).valueOf(),p=$(F.timestamp).valueOf(),W=n?.filter(J=>{let Y=$(J.timestamp).valueOf();return Y>=V-L&&Y<=p+L})||[];return{...F,recordMesgs:W}})||[];return{...C,lapMesgs:U}})}}},C_=class extends y{constructor(){super(...arguments);this.name="FileHeaderPlugin";this.priority=1}structureData(_,I){let{fileIdMesgs:A,fileCreatorMesgs:T,deviceInfoMesgs:n}=_;if(A?.length&&A[0]){let L=A[0];I.fileHeader={type:L.type,manufacturer:L.manufacturer,product:L.product}}return{fileIdMesgs:A,fileCreatorMesgs:T,deviceInfoMesgs:n}}};var f_=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 E_,new O_(t=>this.getConverters(t)),new S_(()=>this.structurePlugins),new D_],b("\u{1F527} FIT core pipeline processors initialized (fixed and not modifiable)")}async registerDefaultPlugins(){if(this.defaultPluginsRegistered)return;let t=[new C_,new o_,new H_,new T_];for(let _ of t)this.addStructurePlugin(_),this.registeredPlugins.add(_.name);this.defaultPluginsRegistered=!0,b("\u2705 Default FIT structure plugins auto-registered (FileHeader, Session, Course, etc.)")}addConverterForMessageType(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((A,T)=>(A.priority||100)-(T.priority||100))}addStructurePlugin(t){this.structurePlugins.push(t),this.structurePlugins.sort((_,I)=>(_.priority||100)-(I.priority||100))}async registerMessageConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Message converter plugin ${t.name} already exists`);t.supportedMessageTypes.forEach(I=>{this.addConverterForMessageType(I,t)}),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";b(`\u{1F4E6} Registered FIT message converter: ${t.name}${_}, supported message types: ${t.supportedMessageTypes.join(", ")}`),t.supportedMessageTypes.forEach(I=>{let T=(this.converterPlugins.get(I)||[]).map(n=>`${n.name}(${n.priority||100})`);b(` \u{1F4CB} Message type "${I}" converter priority: ${T.join(" > ")}`)})}async registerStructurePlugin(t){if(this.registeredPlugins.has(t.name))throw new Error(`Structure plugin ${t.name} already exists`);this.addStructurePlugin(t),this.registeredPlugins.add(t.name);let _=t.priority!==void 0?` (priority: ${t.priority})`:"";b(`\u{1F3D7}\uFE0F Registered FIT structure plugin: ${t.name}${_}`)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(A=>A.name===t.name);_!==-1?(this.middlewarePlugins[_]=t,b(`\u{1F504} Updated FIT middleware: ${t.name}`)):(this.middlewarePlugins.push(t),this.middlewarePlugins.sort((A,T)=>(A.priority||100)-(T.priority||100)),b(`\u{1F50C} Registered FIT middleware: ${t.name}`));let I=[];t.onParse&&I.push("onParse"),t.onExtractMessages&&I.push("onExtractMessages"),t.onStructure&&I.push("onStructure"),t.onComplete&&I.push("onComplete"),t.onError&&I.push("onError"),I.length>0&&b(` \u{1F3A3} Supported hooks: ${I.join(", ")}`)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getConverters(t){return this.converterPlugins.get(t)||[]}unregisterPlugin(t){if(!this.registeredPlugins.has(t))return!1;for(let[A,T]of this.converterPlugins){let n=T.findIndex(L=>L.name===t);n!==-1&&(T.splice(n,1),T.length===0&&this.converterPlugins.delete(A))}let _=this.structurePlugins.findIndex(A=>A.name===t);_!==-1&&this.structurePlugins.splice(_,1);let I=this.middlewarePlugins.findIndex(A=>A.name===t);return I!==-1&&this.middlewarePlugins.splice(I,1),this.registeredPlugins.delete(t),b(`\u{1F5D1}\uFE0F Removed FIT plugin: ${t}`),!0}async initialize(){if(this.initialized)return;await this.registerDefaultPlugins();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.structurePlugins,...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let A=_;for(let T of this.middlewarePlugins){let n=T[t];if(n)try{A=await n.call(T,A,I)||A}catch(L){I.errors.push(L),await T.onError?.(L,I)}}return A}async parseByBuffer(t,_={}){await this.initialize();let I=this.createContext();I.rawData=t,I.userData=_.userData,I.metadata.set("decoder",this);try{for(let A of this.processors)try{switch(A.stage==="parse"&&I.rawData&&(I.rawData=await this.executeMiddlewareHook("onParse",I.rawData,I)),I=await A.process(I),A.stage){case"parse":break;case"extract":I.rawMessages&&(I.rawMessages=await this.executeMiddlewareHook("onExtractMessages",I.rawMessages,I));break;case"structure":I.result&&(I.result=await this.executeMiddlewareHook("onStructure",I.result,I));break;case"complete":I.result&&(I.result=await this.executeMiddlewareHook("onComplete",I.result,I));break}}catch(T){I.errors.push(T);for(let n of this.middlewarePlugins)await n.onError?.(T,I);throw new Error(`FIT pipeline stage "${A.stage}" failed: ${T.message}`)}return b("\u{1F389} FIT parsing completed",I.result),I.result}catch(A){throw A}}};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}},r=R=>{let t=lI[R];return{size:1,baseType:0,mapValue:_=>typeof _=="string"?t[_]??255:_,setValue:function(_,I){this.setUint8(_,I)}}},Ut={enum_file:r("file"),enum_activity:r("sport"),enum_sport:r("sport"),enum_sub_sport:r("sport"),enum_event:r("event"),enum_event_type:r("event_type"),enum_course_point:r("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:R=>Array.from(Jt(R)),setValue:MI},distance:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},speed:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round(R*100)},altitude:{size:2,baseType:132,setValue:DataView.prototype.setUint16,mapValue:R=>Math.round((R+500)*5)},seconds:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>Math.round(R*1e3)},date_time:{size:4,baseType:134,setValue:DataView.prototype.setUint32,mapValue:R=>{let t;return R instanceof Date?(t=Math.floor(R.getTime()/1e3),t-631065600):typeof R=="string"?(t=Math.floor(new Date(R).getTime()/1e3),t-631065600):R<631065600?Math.floor(R):(R>9999999999?t=Math.floor(R/1e3):t=Math.floor(R),t-631065600)}},semicircles:{size:4,baseType:133,setValue:DataView.prototype.setInt32,mapValue:R=>Math.round(R/180*2147483648)}};function Qt(R){return Array.from(Jt(R)).length+1}function*Jt(R){for(let t of WI(R))t<128?yield t:t<2048?(yield 192|t>>6,yield 128|t&63):t<65536?(yield 224|t>>12,yield 128|t>>6&63,yield 128|t&63):(yield 240|t>>18,yield 128|t>>12&63,yield 128|t>>6&63,yield 128|t&63);yield 0}function*WI(R){for(let t=0;t<R.length;){let _=R.codePointAt(t);if(_===void 0)break;yield _,t+=_>65535?2:1}}function MI(R,t){for(let _=0;_<t.length;_++)this.setUint8(R+_,t[_])}var sI={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:"message_index",number:254,type:"uint16"},{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:25,type:"uint16"},{name:"num_laps",number:26,type:"uint16"}]},lap:{mesgNum:19,fieldDefns:[{name:"message_index",number:254,type:"uint16"},{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"}]}},VI=(R,t)=>R.map(_=>({..._,value:t[_.name]})).filter(({value:_})=>_!==void 0),d_=class R{static check(t,_,I,A){if(_===void 0)throw new Error(`Message '${t}' not known`);if(I===void 0)throw new Error(`Message '${t}' has no field definitions`);let T=I.map(L=>L.name),n=Object.keys(A).filter(L=>!T.includes(L));if(n.length)throw new Error(`Message '${t}' has no field definitions named '${n}'`)}constructor(t,_,I){let A=sI[_];if(!A)throw new Error(`Unknown message type: ${_}`);let{mesgNum:T,fieldDefns:n}=A;R.check(_,T,n,I),this.localNum=t,this.mesgNum=T,this.fields=VI(n,I)}get mesgDefn(){let t=this.fields.map(({number:_,type:I,value:A})=>{let T=Ut[I];if(!T)throw new Error(`Unknown type: ${I}`);let{size:n,baseType:L}=T;return I==="string"?{number:_,size:Qt(A),baseType:L}:{number:_,size:n,baseType:L}});return{localNum:this.localNum,mesgNum:this.mesgNum,fieldDefns:t}}isSameDefn(t){let _=(L,E)=>L.number===E.number&&L.size===E.size&&L.baseType===E.baseType,I=(L,E)=>L.length===E.length&&L.every((C,U)=>_(C,E[U])),{localNum:A,mesgNum:T,fieldDefns:n}=this.mesgDefn;return T===t.mesgNum&&A===t.localNum&&I(n,t.fieldDefns)}get defnRecord(){let{localNum:t,mesgNum:_,fieldDefns:I}=this.mesgDefn,A=6+3*I.length,T=new DataView(new ArrayBuffer(A));T.setUint8(0,64|t),T.setUint8(2,1),T.setUint16(3,_),T.setUint8(5,I.length);let n=6;for(let L of I)T.setUint8(n++,L.number),T.setUint8(n++,L.size),T.setUint8(n++,L.baseType);return T.buffer}get dataRecord(){let{fieldDefns:t}=this.mesgDefn,_=1+t.reduce((T,{size:n})=>T+n,0),I=new DataView(new ArrayBuffer(_));I.setUint8(0,this.localNum);let A=1;for(let{number:T,type:n,value:L}of this.fields){let E=Ut[n];if(!E)throw new Error(`Unknown type: ${n}`);let{size:C,setValue:U}=E,F;"mapValue"in E?F=E.mapValue(L):F=L,U&&U.call(I,A,F),A+=C}return I.buffer}};var pI=[0,52225,55297,5120,61441,15360,10240,58369,40961,27648,30720,46081,20480,39937,34817,17408],zt=(R,t)=>(R>>>4^pI[R&15^t])&65535,hI=(R,t,_)=>zt(zt(R,t),_),KI=(R,t)=>hI(R,t&15,t>>>4);function Ft(R,t=0){let _=t,I=R instanceof ArrayBuffer?new Uint8Array(R):R;for(let A=0;A<I.length;A++)_=KI(_,I[A]);return _}import wI from"dayjs";var jt=14,XI=16,vI=2078,PI=776358228,U_=class{constructor(t={}){this.localNum={};this.mesgDefn=[];this.messages=[];this.options={compact:t.compact??!0,defaultActivity:t.defaultActivity??"cycling",defaultSubActivity:t.defaultSubActivity??"generic"}}async encode(t){return this.reset(),this.buildFITContent(t,"activity"),Buffer.from(await this.blob.arrayBuffer())}async encodeCourse(t){return this.reset(),this.buildFITContent(t,"course"),Buffer.from(await this.blob.arrayBuffer())}async encodeToBlob(t,_="activity"){return this.reset(),this.buildFITContent(t,_),this.blob}reset(){this.localNum={},this.mesgDefn=[],this.messages=[]}buildFITContent(t,_){this.buildFileId(t,_),_==="course"?this.buildCourseContent(t):this.buildActivityContent(t)}buildActivityContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Activity file must contain at least one Session");let I=[],A=[],T=0;for(let[n,L]of _.entries()){let E=(L.lapMesgs??[]).map((U,F)=>({...U,messageIndex:T+F})),C={...L,messageIndex:n,firstLapIndex:T,numLaps:E.length,lapMesgs:E};E.length>0&&this.buildEventsFromLaps(E,I);for(let U of E)U.recordMesgs&&this.buildRecords(U.recordMesgs);E.length>0&&this.buildLaps(E),this.buildSession(C),this.buildActivityFromSession(C,A),T+=E.length}I.forEach(n=>this.buildEvent(n)),A.forEach(n=>this.buildActivity(n))}buildCourseContent(t){let _=t.sessionMesgs||[];if(_.length===0)throw new Error("Course file must contain track data");let I=_[0];if(this.buildCourse({name:"course",sport:this.options.defaultActivity}),I.lapMesgs){let A=[];for(let L of I.lapMesgs)L.recordMesgs&&A.push(...L.recordMesgs);A.sort((L,E)=>L.timestamp&&E.timestamp?new Date(L.timestamp).getTime()-new Date(E.timestamp).getTime():(L.distance||0)-(E.distance||0));let T=A[0],n=A[A.length-1];if(I.startTime&&this.buildEvent({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:0}),A.forEach(L=>this.buildRecord(L)),n.timestamp&&this.buildEvent({timestamp:n.timestamp,event:"timer",eventType:"stop_all",eventGroup:0}),I.lapMesgs)for(let L=0;L<I.lapMesgs.length;L++)this.buildLap(I.lapMesgs[L])}}buildFileId(t,_){let I=t.fileIdMesgs?.[0]||{};this.writeMesg("file_id",{type:_,time_created:I.timeCreated?this.parseTimestamp(I.timeCreated):Date.now(),manufacturer:I.manufacturer,product:I.product,serial_number:I.serialNumber})}buildSession(t){this.writeMesg("session",{message_index:t.messageIndex,timestamp:t.timestamp?t.timestamp:void 0,start_time:t.startTime?t.startTime:void 0,total_elapsed_time:t.totalElapsedTime,total_timer_time:t.totalTimerTime,start_position_lat:t.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,total_distance:t.totalDistance,total_ascent:t.totalAscent,total_descent:t.totalDescent,sport:t.sport||this.options.defaultActivity,sub_sport:t.subSport||this.options.defaultSubActivity,first_lap_index:t.firstLapIndex??0,num_laps:t.numLaps??t.lapMesgs?.length??0})}buildLaps(t){t.forEach(_=>this.buildLap(_))}buildLap(t){this.writeMesg("lap",{message_index:t.messageIndex,timestamp:t?.timestamp?t.timestamp:void 0,start_time:t?.startTime?t.startTime:void 0,start_position_lat:t?.startPositionLat!=null&&Number.isFinite(t.startPositionLat)?t.startPositionLat:void 0,start_position_long:t?.startPositionLong!=null&&Number.isFinite(t.startPositionLong)?t.startPositionLong:void 0,end_position_lat:t?.endPositionLat!=null&&Number.isFinite(t.endPositionLat)?t.endPositionLat:void 0,end_position_long:t?.endPositionLong!=null&&Number.isFinite(t.endPositionLong)?t.endPositionLong:void 0,total_elapsed_time:t?.totalElapsedTime,total_timer_time:t?.totalTimerTime,total_distance:t?.totalDistance,total_ascent:t?.totalAscent,total_descent:t?.totalDescent})}buildRecords(t){t.forEach(_=>this.buildRecord(_))}buildRecord(t){this.writeMesg("record",{timestamp:t.timestamp,position_lat:t?.positionLat!=null&&Number.isFinite(t.positionLat)?t.positionLat:void 0,position_long:t?.positionLong!=null&&Number.isFinite(t.positionLong)?t.positionLong:void 0,altitude:t?.altitude,enhancedAltitude:t?.enhancedAltitude,distance:t?.distance,heart_rate:t?.heartRate,cadence:t?.cadence,speed:t?.speed,enhancedSpeed:t?.enhancedSpeed,power:t?.power})}buildEvent(t){this.writeMesg("event",{timestamp:t.timestamp?t.timestamp:void 0,event:t.event,event_type:t.eventType,event_group:t.eventGroup})}buildActivity(t){this.writeMesg("activity",{timestamp:t.timestamp?t.timestamp:void 0,total_timer_time:t.totalTimerTime,num_sessions:t.numSessions,type:t.type,event:t.event,event_type:t.eventType,local_timestamp:t.localTimestamp?this.parseTimestamp(t.localTimestamp):void 0,event_group:t.eventGroup})}buildCourse(t){this.writeMesg("course",{name:t.name,sport:t.sport})}buildEventsFromLaps(t,_){t.forEach((I,A)=>{I.startTime&&_.push({timestamp:I.startTime,event:"timer",eventType:"start",eventGroup:A}),I.timestamp&&_.push({timestamp:I.timestamp,event:"timer",eventType:A===t.length-1?"stop_all":"stop",eventGroup:A})})}buildActivityFromSession(t,_){_.push({timestamp:t.timestamp,totalTimerTime:t.totalTimerTime,numSessions:1,type:t.sport||this.options.defaultActivity,event:"activity",eventType:"stop",eventGroup:0})}parseTimestamp(t){return typeof t=="number"?t:wI(t).valueOf()}validateRequiredFields(t){if(!t.sessionMesgs||t.sessionMesgs.length===0)throw new Error("FIT file must contain at least one Session")}writeMesg(t,_){let I=Object.fromEntries(Object.entries(_).filter(([L,E])=>E!==void 0));if(Object.keys(I).length===0)return;let A=this.localNum[t];A===void 0&&(A=this.localNum[t]=Object.keys(this.localNum).length);let T=new d_(A,t,I),n=this.mesgDefn[A];(!n||!T.isSameDefn(n))&&(this.messages.push(T.defnRecord),this.mesgDefn[A]=T.mesgDefn),this.messages.push(T.dataRecord)}get blob(){let t=[this.header,...this.messages,this.trailer];return new Blob(t,{type:"application/octet-stream"})}get dataLen(){return this.messages.reduce((t,_)=>t+_.byteLength,0)}get dataCrc(){return this.messages.reduce((t,_)=>Ft(_,t),0)}get header(){let t=new DataView(new ArrayBuffer(jt));return t.setUint8(0,jt),t.setUint8(1,XI),t.setUint16(2,vI,!0),t.setUint32(4,this.dataLen,!0),t.setUint32(8,PI),t.setUint16(12,Ft(t.buffer.slice(0,12)),!0),t.buffer}get trailer(){let t=new DataView(new ArrayBuffer(2));return t.setUint16(0,this.dataCrc,!0),t.buffer}async encoder(t){return this.encode(t)}};import{Encoder as YI}from"@garmin/fitsdk";var bI="development",NI=1,$I=1;function kI(R,t){if(!Number.isFinite(R))throw new Error(`${t} must be a finite number.`)}function F_(R,t){return kI(R,t),Math.abs(R)<=180?Math.round(R*2147483648/180):Math.round(R)}function QI(R){if(!R.name||R.name.trim().length===0)throw new Error("Course name is required.");if(!Array.isArray(R.records)||R.records.length===0)throw new Error("Course must contain at least one record point.");let t=R.records.map((I,A)=>{if(I==null)throw new Error(`Course record #${A+1} is missing.`);if(I.timestamp==null)throw new Error(`Course record #${A+1} is missing timestamp.`);return{...I,positionLat:F_(I.latitude,`records[${A}].latitude`),positionLong:F_(I.longitude,`records[${A}].longitude`)}}),_=(R.coursePoints??[]).map((I,A)=>{if(I==null)throw new Error(`Course point #${A+1} is missing.`);if(I.timestamp==null)throw new Error(`Course point #${A+1} is missing timestamp.`);return{...I,type:I.type??0,positionLat:F_(I.latitude,`coursePoints[${A}].latitude`),positionLong:F_(I.longitude,`coursePoints[${A}].longitude`)}});return{...R,sport:R.sport??2,subSport:R.subSport??0,records:t,coursePoints:_,manufacturer:R.manufacturer??bI,product:R.product??NI,serialNumber:R.serialNumber??$I,timeCreated:R.timeCreated??t[0].timestamp}}function JI(R){let t=QI(R),_=t.records[0],I=t.records[t.records.length-1],A=_.timestamp,T=I.timestamp,n=[{mesgNum:0,data:{type:6,manufacturer:t.manufacturer,product:t.product,serialNumber:t.serialNumber,timeCreated:t.timeCreated}},{mesgNum:31,data:{name:t.name,sport:t.sport,subSport:t.subSport}},{mesgNum:19,data:{startTime:A,timestamp:T,startPositionLat:_.positionLat,startPositionLong:_.positionLong,endPositionLat:I.positionLat,endPositionLong:I.positionLong,totalDistance:I.distance}},{mesgNum:21,data:{timestamp:A,event:0,eventType:0}}];return t.records.forEach(L=>{n.push({mesgNum:20,data:{timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,altitude:L.altitude,speed:L.speed}})}),t.coursePoints.forEach((L,E)=>{n.push({mesgNum:32,data:{messageIndex:E,timestamp:L.timestamp,positionLat:L.positionLat,positionLong:L.positionLong,distance:L.distance,type:L.type,name:L.name,favorite:L.favorite}})}),n.push({mesgNum:21,data:{timestamp:T,event:0,eventType:4}}),n}function yt(R){let t=new YI;return JI(R).forEach(I=>{t.onMesg(I.mesgNum,I.data)}),t.close()}var q=class{constructor(){this.version="1.0.0";this.priority=100}supports(t){return this.supportedTags.includes(t)}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}parseFloat(t){if(!(typeof t>"u"))return typeof t=="number"?t:typeof t=="string"&&parseFloat(t)||0}parseInt(t){return typeof t=="number"?Math.floor(t):typeof t=="string"&&parseInt(t,10)||0}parseString(t){return String(t||"")}parseBoolean(t){return typeof t=="boolean"?t:typeof t=="string"?t.toLowerCase()==="true":!1}parseDate(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}hasRequiredAttributes(t,_){return _.every(I=>t.attributes?.[I])}extractAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([A,T])=>{let n=I[A];n&&(_[n]=String(T??""))})}processChildren(t,_,I){t.children?.forEach(A=>{let T=I[A.tag];T&&T(A,_)})}getChildValue(t,_){let I=t.children?.find(A=>A.tag===_);return I?.value?String(I.value):void 0}getChildByTag(t,_){return t.children?.find(I=>I.tag===_)}getChildrenByTag(t,_){return t.children?.filter(I=>I.tag===_)||[]}convertExtensions(t){let _={};return t.children?.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}convertExtensionContent(t){if(t.children?.length){let _={};return t.children.forEach(I=>{_[I.tag]=this.convertExtensionContent(I)}),_}else return t.value}};var Q=class extends q{parseCoordinate(t){let _=this.parseFloat(t);return _===0?void 0:_}parseGPXTime(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}extractNumericAttributes(t,_,I){t.attributes&&Object.entries(t.attributes).forEach(([A,T])=>{let n=I[A];n&&n in _&&typeof T<"u"&&(_[n]=this.parseFloat(T))})}};var G_=class extends Q{constructor(){super(...arguments);this.name="wpt-converter";this.supportedTags=["wpt","trkpt","rtept"];this.version="1.0.0"}convert(_,I){if(!this.hasRequiredAttributes(_,["lat","lon"])){I.warnings.push(`${this.name}: point without latitude or longitude was ignored`);return}let A={lat:this.parseFloat(_.attributes?.lat),lon:this.parseFloat(_.attributes?.lon)};return this.processChildren(_,A,{ele:(T,n)=>n.ele=this.parseFloat(T.value),time:(T,n)=>n.time=new Date(this.parseString(T.value)),speed:(T,n)=>n.speed=this.parseFloat(T.value),power:(T,n)=>n.power=this.parseFloat(T.value),cadence:(T,n)=>n.cadence=this.parseFloat(T.value),heartRate:(T,n)=>n.heartRate=this.parseFloat(T.value),course:(T,n)=>n.course=this.parseFloat(T.value),name:(T,n)=>n.name=this.parseString(T.value),cmt:(T,n)=>n.cmt=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),src:(T,n)=>n.src=this.parseString(T.value),sym:(T,n)=>n.sym=this.parseString(T.value),type:(T,n)=>n.type=this.parseString(T.value),fix:(T,n)=>n.fix=this.parseString(T.value),sat:(T,n)=>n.sat=this.parseFloat(T.value),hdop:(T,n)=>n.hdop=this.parseFloat(T.value),vdop:(T,n)=>n.vdop=this.parseFloat(T.value),pdop:(T,n)=>n.pdop=this.parseFloat(T.value),ageofdgpsdata:(T,n)=>n.ageofdgpsdata=this.parseFloat(T.value),geoidheight:(T,n)=>n.geoidheight=this.parseFloat(T.value),magvar:(T,n)=>n.magvar=this.parseFloat(T.value),dgpsid:(T,n)=>n.dgpsid=this.parseFloat(T.value),extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");if(E){let C=E.convert(T,I);C&&(this.mapExtensionsToPoint(C,n),n.extensions=C)}},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}mapExtensionsToPoint(_,I){Object.entries(_).forEach(([A,T])=>{if(T!==void 0&&(typeof T=="string"||typeof T=="number")){let n=L=>(Array.isArray(L)?L:[L]).some(C=>{let U=A.toLowerCase(),F=C.toLowerCase();return U===F||U.endsWith(`:${F}`)});n("speed")?I.speed=this.parseFloat(T):n("hr")?I.heartRate=this.parseFloat(T):n(["cad","cadence"])?I.cadence=this.parseFloat(T):n(["PowerInWatts","power"])&&(I.power=this.parseFloat(T))}})}},g_=class extends Q{constructor(){super(...arguments);this.name="rte-converter";this.supportedTags=["rte"]}convert(_,I){let A={rtept:[]};return this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),cmt:(T,n)=>n.cmt=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),src:(T,n)=>n.src=this.parseString(T.value),number:(T,n)=>n.number=this.parseFloat(T.value),type:(T,n)=>n.type=this.parseString(T.value),rtept:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(T,I);E&&n.rtept&&n.rtept.push(E)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}},l_=class extends Q{constructor(){super(...arguments);this.name="trk-converter";this.supportedTags=["trk"]}convert(_,I){let A={trkseg:[]};return this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),cmt:(T,n)=>n.cmt=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),src:(T,n)=>n.src=this.parseString(T.value),number:(T,n)=>n.number=this.parseFloat(T.value),type:(T,n)=>n.type=this.parseString(T.value),trkseg:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("trkseg")?.convert(T,I);E&&n.trkseg&&n.trkseg.push(E)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}},W_=class extends Q{constructor(){super(...arguments);this.name="trkseg-converter";this.supportedTags=["trkseg"]}convert(_,I){let A={trkpt:[]};return this.processChildren(_,A,{trkpt:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("wpt")?.convert(T,I);E&&n.trkpt&&n.trkpt.push(E)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))}}),A}},M_=class extends Q{constructor(){super(...arguments);this.name="link-converter";this.supportedTags=["link"]}convert(_,I){let A={};return _.attributes?.href&&(A.href=_.attributes.href),this.processChildren(_,A,{text:(T,n)=>n.text=this.parseString(T.value),type:(T,n)=>n.type=this.parseString(T.value)}),A}},B_=class extends Q{constructor(){super(...arguments);this.name="metadata-converter";this.supportedTags=["metadata"]}convert(_,I){let A={};return this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),desc:(T,n)=>n.desc=this.parseString(T.value),keywords:(T,n)=>n.keywords=this.parseString(T.value),time:(T,n)=>n.time=new Date(this.parseString(T.value)),author:(T,n)=>{let L=I.metadata.get("decoder");n.author=L?.getConverter("author")?.convert(T,I)},copyright:(T,n)=>{let L=I.metadata.get("decoder");n.copyright=L?.getConverter("copyright")?.convert(T,I)},bounds:(T,n)=>{let L=I.metadata.get("decoder");n.bounds=L?.getConverter("bounds")?.convert(T,I)},extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("extensions");E&&(n.extensions=E.convert(T,I))},link:(T,n)=>{n.link||(n.link=[]);let E=I.metadata.get("decoder")?.getConverter("link")?.convert(T,I);E&&n.link&&n.link.push(E)}}),A}},s_=class extends Q{constructor(){super(...arguments);this.name="person-converter";this.supportedTags=["author"]}convert(_,I){let A={};return _.value&&!_.children?.length?(A.name=this.parseString(_.value),A):(this.processChildren(_,A,{name:(T,n)=>n.name=this.parseString(T.value),email:(T,n)=>{let L=I.metadata.get("decoder");n.email=L?.getConverter("email")?.convert(T,I)},link:(T,n)=>{let L=I.metadata.get("decoder");n.link=L?.getConverter("link")?.convert(T,I)}}),A)}},V_=class extends Q{constructor(){super(...arguments);this.name="email-converter";this.supportedTags=["email"]}convert(_,I){return{id:_.attributes?.id,domain:_.attributes?.domain}}},p_=class extends Q{constructor(){super(...arguments);this.name="copyright-converter";this.supportedTags=["copyright"]}convert(_,I){let A={};return _.attributes?.author&&(A.author=_.attributes.author),this.processChildren(_,A,{year:(T,n)=>n.year=this.parseString(T.value),license:(T,n)=>n.license=this.parseString(T.value)}),A}},h_=class extends Q{constructor(){super(...arguments);this.name="bounds-converter";this.supportedTags=["bounds"]}convert(_,I){let A={};return this.extractAttributes(_,A,{minlat:"minlat",minlon:"minlon",maxlat:"maxlat",maxlon:"maxlon"}),A}},K_=class extends Q{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["extensions"]}convert(_,I){let A={};return _.children?.forEach(T=>{this.flattenExtensionElement(T,A)}),A}flattenExtensionElement(_,I){if(!_.children?.length&&_.value!==void 0){I[_.tag]=this.parseExtensionValue(_.value);return}_.children?.length&&_.children.forEach(A=>{this.flattenExtensionElement(A,I)})}parseExtensionValue(_){if(_===void 0)return;let I=String(_),A=parseFloat(I);return!isNaN(A)&&isFinite(A)?A:I}};import{Parser as zI}from"htmlparser2";var w_=class{constructor(){this.stage="tokenize"}async process(t){let _=Date.now();if(!t.xmlContent)throw new Error("XML content cannot be empty");let I=[],A=new zI({onopentag(T,n){I.push({type:"open",tag:T,attributes:n})},ontext(T){let n=T.replace(/\n/g,"").trim();n&&I.push({type:"text",tag:"text",value:n})},onclosetag(T){I.push({type:"close",tag:T})}},{xmlMode:!0});return A.write(t.xmlContent),A.end(),t.tokens=I,t.performance.tokenizeTime=Date.now()-_,t}},X_=class{constructor(){this.stage="ast_generate"}async process(t){let _=Date.now();if(!t.tokens)throw new Error("Tokens cannot be empty");let I=[],A,T=null;for(let n of t.tokens)if(n.type==="open"){let L={tag:n.tag,attributes:n.attributes||{},children:[]};A?T&&T.children?.push(L):A=L,I.push(L),T=L}else n.type==="text"&&T?T.value=n.value:n.type==="close"&&(I.pop(),T=I[I.length-1]||null);return t.ast=A,t.performance.astTime=Date.now()-_,t}},v_=class{constructor(t){this.getConverter=t;this.stage="convert"}async process(t){let _=Date.now();if(!t.ast)throw new Error("AST cannot be empty");if(t.ast.tag!=="gpx")throw new Error(`Not a valid GPX document: expected <gpx>, received <${t.ast.tag}>`);let I={};return t.ast.attributes&&Object.entries(t.ast.attributes).forEach(([A,T])=>{A.startsWith("xmlns:")?I[A]=T.replace(/&#39;/g,"'"):A==="xsi:schemaLocation"?I[A]=T.replace(/&#39;/g,"'"):I[A]=T}),t.ast.children?.forEach(A=>{let T=this.getConverter(A.tag);if(!T){t.warnings.push(`Unsupported GPX element "${A.tag}" was ignored`);return}try{let n=T.convert(A,t);n&&this.assignResult(I,A.tag,n)}catch(n){throw t.errors.push(n),new Error(`GPX converter "${T.name}" failed for ${A.tag}: ${n.message}`)}}),t.result=I,t.performance.convertTime=Date.now()-_,t}assignResult(t,_,I){switch(_){case"metadata":t.metadata=I;break;case"wpt":t.wpt||(t.wpt=[]),t.wpt.push(I);break;case"rte":t.rte||(t.rte=[]),t.rte.push(I);break;case"trk":t.trk||(t.trk=[]),t.trk.push(I);break;case"extensions":t.extensions=I;break}}},P_=class{constructor(){this.stage="complete"}async process(t){t.performance.endTime=Date.now();let _=t.performance.endTime-t.performance.startTime;return t.metadata.set("performance",{totalTime:_,tokenizeTime:t.performance.tokenizeTime,astTime:t.performance.astTime,convertTime:t.performance.convertTime}),t}};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 w_,new X_,new v_(t=>this.getConverter(t)),new P_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let t=[new G_,new g_,new l_,new W_,new M_,new B_,new s_,new V_,new p_,new h_,new K_];for(let _ of t)_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name);this.defaultConvertersRegistered=!0}addConverterForTag(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((A,T)=>(A.priority||100)-(T.priority||100))}async registerConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Converter plugin ${t.name} already exists`);t.supportedTags?.forEach(_=>{this.addConverterForTag(_,t)}),this.registeredPlugins.add(t.name)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t.name);_!==-1?this.middlewarePlugins[_]=t:this.middlewarePlugins.push(t)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getAllConverters(t){return this.converterPlugins.get(t)||[]}unregisterConverter(t){let _;for(let[I,A]of this.converterPlugins){let T=A.findIndex(n=>n.name===t);T!==-1&&(_=A[T],A.splice(T,1),A.length===0&&this.converterPlugins.delete(I))}_&&this.registeredPlugins.delete(t)}unregisterMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t);_!==-1&&this.middlewarePlugins.splice(_,1)}listConverters(){return Array.from(this.converterPlugins.keys())}listConverterPlugins(){return Array.from(this.registeredPlugins)}listMiddlewares(){return this.middlewarePlugins.map(t=>t.name)}listProcessors(){return this.processors.map(t=>t.constructor.name)}getConverterDetails(t){let _={};if(t){let I=this.converterPlugins.get(t);I&&(_[t]=I.map(A=>({name:A.name,priority:A.priority||100})))}else for(let[I,A]of this.converterPlugins)_[I]=A.map(T=>({name:T.name,priority:T.priority||100}));return _}getMiddlewareDetails(){return this.middlewarePlugins.map(t=>{let _=[];return t.onTokenize&&_.push("onTokenize"),t.onAstGenerate&&_.push("onAstGenerate"),t.onConvert&&_.push("onConvert"),t.onComplete&&_.push("onComplete"),t.onError&&_.push("onError"),{name:t.name,hooks:_}})}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let A=_;for(let T of this.middlewarePlugins){let n=T[t];if(n)try{A=await n.call(T,A,I)||A}catch(L){I.errors.push(L),await T.onError?.(L,I)}}return A}async parserByBuffer(t){await this.initialize();let _=this.createContext();_.rawData=t,_.xmlContent=t.toString("utf-8"),_.metadata.set("decoder",this);for(let I of this.processors)try{switch(_=await I.process(_),I.stage){case"tokenize":_.tokens&&(_.tokens=await this.executeMiddlewareHook("onTokenize",_.tokens,_));break;case"ast_generate":_.ast&&(_.ast=await this.executeMiddlewareHook("onAstGenerate",_.ast,_));break;case"convert":_.result&&(_.result=await this.executeMiddlewareHook("onConvert",_.result,_));break;case"complete":_.result&&(_.result=await this.executeMiddlewareHook("onComplete",_.result,_));break}}catch(A){_.errors.push(A);for(let T of this.middlewarePlugins)await T.onError?.(A,_);throw new Error(`GPX pipeline stage "${I.stage}" failed: ${A.message}`)}return _.result}convertExtensions(t){let _={},{attributes:I,tag:A,value:T}=t;if(I&&Object.entries(I).forEach(([n,L])=>{_[n]=L}),t?.children?.length)t.children?.forEach(n=>{_[n.tag]=this.convertExtensions(n)});else if(T!==void 0)return T;return _}};import qt from"dayjs";import jI from"dayjs/plugin/utc.js";var Gt={temperature:"atemp",wtemp:"wtemp",heartRate:"hr",cadence:"cad"};var gt={temperature:"Temperature",Depth:"Depth"};qt.extend(jI);var b_=class{constructor(t={}){this.formatElevation=t=>{let _=parseFloat(t);return isNaN(_)?t:this.roundTo(_,2).toString()};this.compact=t.compact??!0}async encode(t){let _=this.buildGPXXML(t);return Buffer.from(_,"utf-8")}encodeToString(t){return this.buildGPXXML(t)}buildGPXXML(t){let _=this.buildXMLHeader(t),I=this.buildGPXContent(t),T=`${_}${I}
2
2
  </gpx>`;return this.compact?this.compressXML(T):T}compressXML(t){return t.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(t){let _=this.escapeXMLAttribute(t.creator||"TrackSwap"),I=this.escapeXMLAttribute(t.version||"1.1");return['<?xml version="1.0" encoding="UTF-8"?>',`<gpx creator="${_}" version="${I}"`,' 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
3
  `)}buildGPXContent(t){let{metadata:_,wpt:I=[],rte:A=[],trk:T=[],extensions:n}=t,L=[];return _&&L.push(this.buildMetadata(_)),I.forEach(E=>{L.push(this.buildWaypoint(E,"wpt"))}),A.forEach(E=>{L.push(this.buildRoute(E))}),T.forEach(E=>{L.push(this.buildTrack(E))}),n&&L.push(this.buildExtensions(n)),L.join(`
4
4
  `)}buildMetadata(t){let _=["<metadata>"];return this.addOptionalElement(_,"name",t.name),this.addOptionalElement(_,"desc",t.desc),t.author&&_.push(this.buildAuthor(t.author)),t.copyright&&_.push(this.buildCopyright(t.copyright)),t.link&&this.addLinks(_,t.link),t.time&&_.push(this.buildTimeElement(t.time)),this.addOptionalElement(_,"keywords",t.keywords),t.bounds&&_.push(this.buildBounds(t.bounds)),t.extensions&&_.push(this.buildExtensions(t.extensions)),_.push("</metadata>"),_.join(`
@@ -8,9 +8,9 @@ var Q=class extends Error{constructor(t,_,I={}){super(_),this.name="TrackSwapErr
8
8
  `)}addStandardWaypointElements(t,_){this.addOptionalElement(t,"magvar",_.magvar?.toString()),this.addOptionalElement(t,"geoidheight",_.geoidheight?.toString()),this.addOptionalElement(t,"name",_.name),this.addOptionalElement(t,"cmt",_.cmt),this.addOptionalElement(t,"desc",_.desc),this.addOptionalElement(t,"src",_.src),_.link&&this.addLinks(t,_.link),this.addOptionalElement(t,"sym",_.sym),this.addOptionalElement(t,"type",_.type),this.addOptionalElement(t,"fix",_.fix),this.addOptionalElement(t,"sat",_.sat?.toString()),this.addOptionalElement(t,"hdop",_.hdop?.toString()),this.addOptionalElement(t,"vdop",_.vdop?.toString()),this.addOptionalElement(t,"pdop",_.pdop?.toString()),this.addOptionalElement(t,"ageofdgpsdata",_.ageofdgpsdata?.toString()),this.addOptionalElement(t,"dgpsid",_.dgpsid?.toString())}buildRoute(t){let _=["<rte>"];return this.addRouteTrackCommonElements(_,t),t.extensions&&_.push(this.buildExtensions(t.extensions)),t.rtept&&t.rtept?.forEach(I=>{_.push(this.buildWaypoint(I,"rtept"))}),_.push("</rte>"),_.join(`
9
9
  `)}buildTrack(t){let _=["<trk>"];return this.addRouteTrackCommonElements(_,t),t.extensions&&_.push(this.buildExtensions(t.extensions)),t.trkseg&&t.trkseg.forEach(I=>{_.push(this.buildTrackSegment(I))}),_.push("</trk>"),_.join(`
10
10
  `)}buildTrackSegment(t){let _=["<trkseg>"];return t.trkpt&&t.trkpt.forEach(I=>{_.push(this.buildWaypoint(I,"trkpt"))}),t.extensions&&_.push(this.buildExtensions(t.extensions)),_.push("</trkseg>"),_.join(`
11
- `)}addRouteTrackCommonElements(t,_){this.addOptionalElement(t,"name",_.name),this.addOptionalElement(t,"cmt",_.cmt),this.addOptionalElement(t,"desc",_.desc),this.addOptionalElement(t,"src",_.src),_.link&&this.addLinks(t,_.link),this.addOptionalElement(t,"number",_.number?.toString()),this.addOptionalElement(t,"type",_.type)}processPointExtensions(t,_){let I={};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,n])=>{let L={},E=!1;Object.entries(n).forEach(([C,U])=>{let F;if(t[U]!==void 0)F=t[U];else if(_)if(_[C]!==void 0)F=_[C];else{let B=C.split(":").pop();Object.entries(_).forEach(([V,l])=>{V.endsWith(`:${B}`)&&l!==void 0&&(F=l)})}F!==void 0&&(L[C]=F,E=!0)}),E&&(I[T]=L)}),I}buildTrackPointExtension(t,_){let I=this.deepClone(_["gpxtpx:TrackPointExtension"]||{}),A=Object.keys(gt);return Object.keys(t).filter(T=>A.includes(T)).forEach(T=>{let n=gt[T];n&&t[T]!==void 0&&(I[`gpxtpx:${n}`]=t[T])}),I}buildPowerExtension(t,_){return this.deepClone(_["gpxpx:PowerExtension"]||{})}buildGpxExtensions(t,_){let I=this.deepClone(_["gpxx:GpxExtensions"]||{}),A=Object.keys(lt);return Object.keys(t).filter(T=>A.includes(T)).forEach(T=>{let n=lt[T];n&&t[T]!==void 0&&(I[`gpxx:${n}`]=t[T])}),I}buildExtensions(t){let _=this.buildExtensionContent(t);return _?`<extensions>${_}</extensions>`:""}buildExtensionContent(t){return Object.entries(t).filter(([_])=>!_.startsWith("xmlns")).map(([_,I])=>{if(I&&typeof I=="object"){let A=this.buildExtensionContent(I);return`<${_}>${A}</${_}>`}else if(I!=null)return`<${_}>${this.escapeXML(String(I))}</${_}>`;return""}).filter(_=>_).join("")}buildLink(t){let _=[`<link href="${this.escapeXMLAttribute(t.href||"")}">`];return this.addOptionalElement(_,"text",t.text),this.addOptionalElement(_,"type",t.type),_.push("</link>"),_.join("")}addLinks(t,_){(Array.isArray(_)?_:[_]).forEach(A=>{t.push(this.buildLink(A))})}buildTimeElement(t){return typeof t=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/.test(t)?`<time>${t}</time>`:`<time>${it(t).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}</time>`}addOptionalElement(t,_,I,A){if(I!=null&&I!==""){let T=A?A(I):this.escapeXML(I);t.push(`<${_}>${T}</${_}>`)}}isValidCoordinate(t,_){return t!=null&&_!==void 0&&_!==null&&!isNaN(t)&&!isNaN(_)}formatCoordinate(t){return this.roundTo(t,6).toString()}roundTo(t,_){let I=Math.pow(10,_);return Math.round(t*I)/I}escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(t){return typeof t!="string"?String(t||""):t.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(t){if(t===null||typeof t!="object")return t;if(t instanceof Date)return new Date(t.getTime());if(Array.isArray(t))return t.map(I=>this.deepClone(I));let _={};for(let I in t)Object.prototype.hasOwnProperty.call(t,I)&&(_[I]=this.deepClone(t[I]));return _}encoder(t){return this.encode(t)}};var j=class extends u{parseHeartRate(t){let _=this.parseFloat(t);if(!(typeof _>"u"))return _>0&&_<300?_:void 0}parseTCXTime(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}parseDistance(t){let _=this.parseFloat(t);if(!(typeof _>"u"))return _>0?_:void 0}parseSpeed(t){let _=this.parseFloat(t);if(!(typeof _>"u"))return _>=0?_:void 0}parseAltitude(t){return this.parseFloat(t)}parseCoordinate(t){let _=this.parseFloat(t);return _!==0?_:void 0}};var N_=class extends j{constructor(){super(...arguments);this.name="PositionConverter";this.supportedTags=["Position"]}convert(_,I){let A={};return this.processChildren(_,A,{LatitudeDegrees:(T,n)=>n.LatitudeDegrees=this.parseString(T.value),LongitudeDegrees:(T,n)=>n.LongitudeDegrees=this.parseString(T.value)}),A}},$_=class extends j{constructor(){super(...arguments);this.name="TrackpointConverter";this.supportedTags=["Trackpoint"]}convert(_,I){let A={};return this.processChildren(_,A,{Time:(T,n)=>n.Time=this.parseString(T.value),Position:(T,n)=>{let L=I.metadata.get("decoder");n.Position=L?.getConverter("Position")?.convert(T,I)},AltitudeMeters:(T,n)=>n.AltitudeMeters=this.parseFloat(T.value),DistanceMeters:(T,n)=>n.DistanceMeters=this.parseFloat(T.value),HeartRateBpm:(T,n)=>{if(T.value)n.HeartRateBpm=this.parseFloat(T.value);else{let L=this.getChildByTag(T,"Value");L?.value&&(n.HeartRateBpm=this.parseFloat(L.value))}},Cadence:(T,n)=>{let L={Low:0,High:0};this.processChildren(T,L,{Low:(E,C)=>C.Low=this.parseFloat(E.value)||0,High:(E,C)=>C.High=this.parseFloat(E.value)||0}),n.Cadence=L},SensorState:(T,n)=>n.SensorState=T.value,Extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Extensions");E&&(n.Extensions=E.convert(T,I))}}),A}},k_=class extends j{constructor(){super(...arguments);this.name="TrackConverter";this.supportedTags=["Track"]}convert(_,I){let A={Trackpoint:[]};return this.processChildren(_,A,{Trackpoint:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Trackpoint")?.convert(T,I);E&&n.Trackpoint&&n.Trackpoint.push(E)}}),A}},Q_=class extends j{constructor(){super(...arguments);this.name="ActivityLapConverter";this.supportedTags=["Lap"]}convert(_,I){let A={};return this.extractAttributes(_,A,{StartTime:"StartTime"}),this.processChildren(_,A,{TotalTimeSeconds:(T,n)=>n.TotalTimeSeconds=this.parseFloat(T.value),DistanceMeters:(T,n)=>n.DistanceMeters=this.parseFloat(T.value),MaximumSpeed:(T,n)=>n.MaximumSpeed=this.parseFloat(T.value),Calories:(T,n)=>n.Calories=this.parseFloat(T.value),AverageHeartRateBpm:(T,n)=>n.AverageHeartRateBpm=this.parseFloat(T.value),MaximumHeartRateBpm:(T,n)=>n.MaximumHeartRateBpm=this.parseFloat(T.value),Intensity:(T,n)=>n.Intensity=T.value,TriggerMethod:(T,n)=>n.TriggerMethod=T.value,Track:(T,n)=>{n.Track||(n.Track=[]);let E=I.metadata.get("decoder")?.getConverter("Track")?.convert(T,I);E&&n.Track.push(E)},Notes:(T,n)=>n.Notes=this.parseString(T.value),Extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Extensions");E&&(n.Extensions=E.convert(T,I))}}),A}},J_=class extends j{constructor(){super(...arguments);this.name="ActivityConverter";this.supportedTags=["Activity"]}convert(_,I){let A={Id:"",Lap:[]};return this.extractAttributes(_,A,{Sport:"Sport"}),this.processChildren(_,A,{Id:(T,n)=>n.Id=this.parseString(T.value),Lap:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Lap")?.convert(T,I);E&&n.Lap.push(E)},Notes:(T,n)=>n.Notes=this.parseString(T.value),Training:(T,n)=>n.Training=this.convertTraining(T),Creator:(T,n)=>n.Creator=this.convertCreator(T),Extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Extensions");E&&(n.Extensions=E.convert(T,I))}}),A}convertTraining(_){let I={};return _.attributes&&Object.entries(_.attributes).forEach(([A,T])=>{I[A]=T}),_.children?.forEach(A=>{I[A.tag]=this.convertExtensionContent(A)}),I}convertCreator(_){let I={};return _.children?.forEach(A=>{I[A.tag]=this.convertExtensionContent(A)}),I}},z_=class extends j{constructor(){super(...arguments);this.name="ActivityListConverter";this.supportedTags=["Activities"]}convert(_,I){let A={Activity:[],MultiActivitySession:[]};return this.processChildren(_,A,{Activity:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Activity")?.convert(T,I);E&&n.Activity&&n.Activity.push(E)},MultiActivitySession:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("MultiActivitySession")?.convert(T,I);E&&n.MultiActivitySession&&n.MultiActivitySession.push(E)}}),A}},j_=class extends j{constructor(){super(...arguments);this.name="MultiActivitySessionConverter";this.supportedTags=["MultiActivitySession"]}convert(_,I){let A={};return this.processChildren(_,A,{Id:(T,n)=>n.Id=this.parseString(T.value),FirstActivity:(T,n)=>{let L=I.metadata.get("decoder");n.FirstActivity=L?.getConverter("FirstActivity")?.convert(T,I)},NextActivity:(T,n)=>{n.NextActivity||(n.NextActivity=[]);let E=I.metadata.get("decoder")?.getConverter("NextActivity")?.convert(T,I);E&&n.NextActivity.push(E)},Notes:(T,n)=>n.Notes=this.parseString(T.value)}),A}},y_=class extends j{constructor(){super(...arguments);this.name="AbstractSourceConverter";this.supportedTags=["Author","Creator"]}convert(_,I){let A={};return this.processChildren(_,A,{Name:(T,n)=>n.Name=this.parseString(T.value)}),A}},Z_=class extends j{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["Extensions"]}convert(_,I){let A={};return this.flattenExtensionElement(_,A),A}flattenExtensionElement(_,I){if(!_.children?.length&&_.value!==void 0){I[_.tag]=this.parseExtensionValue(_.value);return}_.children?.length&&_.children.forEach(A=>{this.flattenExtensionElement(A,I)})}parseExtensionValue(_){if(_===void 0)return;let I=String(_),A=parseFloat(I);return!isNaN(A)&&isFinite(A)?A:I}};import{Parser as rt}from"htmlparser2";var q_=class{static tokenizeXML(t){let _=[],I=new rt({onopentag(A,T){_.push({type:"open",tag:A,attributes:T})},ontext(A){let T=A.replace(/\n/g,"").trim();T&&_.push({type:"text",tag:"text",value:T})},onclosetag(A){_.push({type:"close",tag:A})}},{xmlMode:!0});return I.write(t),I.end(),_}static compressXML(t){return t.replace(/>\s+</g,"><").replace(/\s+/g," ").trim()}static formatXML(t,_=2){let I=" ".repeat(_),A="",T=0,n=!1;for(let L=0;L<t.length;L++){let E=t[L],C=t[L+1];E==="<"?(C==="/"?(T--,n||(A+=`
11
+ `)}addRouteTrackCommonElements(t,_){this.addOptionalElement(t,"name",_.name),this.addOptionalElement(t,"cmt",_.cmt),this.addOptionalElement(t,"desc",_.desc),this.addOptionalElement(t,"src",_.src),_.link&&this.addLinks(t,_.link),this.addOptionalElement(t,"number",_.number?.toString()),this.addOptionalElement(t,"type",_.type)}processPointExtensions(t,_){let I={};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,n])=>{let L={},E=!1;Object.entries(n).forEach(([C,U])=>{let F;if(t[U]!==void 0)F=t[U];else if(_)if(_[C]!==void 0)F=_[C];else{let V=C.split(":").pop();Object.entries(_).forEach(([p,W])=>{p.endsWith(`:${V}`)&&W!==void 0&&(F=W)})}F!==void 0&&(L[C]=F,E=!0)}),E&&(I[T]=L)}),I}buildTrackPointExtension(t,_){let I=this.deepClone(_["gpxtpx:TrackPointExtension"]||{}),A=Object.keys(Gt);return Object.keys(t).filter(T=>A.includes(T)).forEach(T=>{let n=Gt[T];n&&t[T]!==void 0&&(I[`gpxtpx:${n}`]=t[T])}),I}buildPowerExtension(t,_){return this.deepClone(_["gpxpx:PowerExtension"]||{})}buildGpxExtensions(t,_){let I=this.deepClone(_["gpxx:GpxExtensions"]||{}),A=Object.keys(gt);return Object.keys(t).filter(T=>A.includes(T)).forEach(T=>{let n=gt[T];n&&t[T]!==void 0&&(I[`gpxx:${n}`]=t[T])}),I}buildExtensions(t){let _=this.buildExtensionContent(t);return _?`<extensions>${_}</extensions>`:""}buildExtensionContent(t){return Object.entries(t).filter(([_])=>!_.startsWith("xmlns")).map(([_,I])=>{if(I&&typeof I=="object"){let A=this.buildExtensionContent(I);return`<${_}>${A}</${_}>`}else if(I!=null)return`<${_}>${this.escapeXML(String(I))}</${_}>`;return""}).filter(_=>_).join("")}buildLink(t){let _=[`<link href="${this.escapeXMLAttribute(t.href||"")}">`];return this.addOptionalElement(_,"text",t.text),this.addOptionalElement(_,"type",t.type),_.push("</link>"),_.join("")}addLinks(t,_){(Array.isArray(_)?_:[_]).forEach(A=>{t.push(this.buildLink(A))})}buildTimeElement(t){return typeof t=="string"&&/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?$/.test(t)?`<time>${t}</time>`:`<time>${qt(t).utc().format("YYYY-MM-DDTHH:mm:ss[Z]")}</time>`}addOptionalElement(t,_,I,A){if(I!=null&&I!==""){let T=A?A(I):this.escapeXML(I);t.push(`<${_}>${T}</${_}>`)}}isValidCoordinate(t,_){return t!=null&&_!==void 0&&_!==null&&!isNaN(t)&&!isNaN(_)}formatCoordinate(t){return this.roundTo(t,6).toString()}roundTo(t,_){let I=Math.pow(10,_);return Math.round(t*I)/I}escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(t){return typeof t!="string"?String(t||""):t.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(t){if(t===null||typeof t!="object")return t;if(t instanceof Date)return new Date(t.getTime());if(Array.isArray(t))return t.map(I=>this.deepClone(I));let _={};for(let I in t)Object.prototype.hasOwnProperty.call(t,I)&&(_[I]=this.deepClone(t[I]));return _}encoder(t){return this.encode(t)}};var z=class extends q{parseHeartRate(t){let _=this.parseFloat(t);if(!(typeof _>"u"))return _>0&&_<300?_:void 0}parseTCXTime(t){if(!t)return;let _=new Date(t);return isNaN(_.getTime())?void 0:_}parseDistance(t){let _=this.parseFloat(t);if(!(typeof _>"u"))return _>0?_:void 0}parseSpeed(t){let _=this.parseFloat(t);if(!(typeof _>"u"))return _>=0?_:void 0}parseAltitude(t){return this.parseFloat(t)}parseCoordinate(t){let _=this.parseFloat(t);return _!==0?_:void 0}};var N_=class extends z{constructor(){super(...arguments);this.name="PositionConverter";this.supportedTags=["Position"]}convert(_,I){let A={};return this.processChildren(_,A,{LatitudeDegrees:(T,n)=>n.LatitudeDegrees=this.parseString(T.value),LongitudeDegrees:(T,n)=>n.LongitudeDegrees=this.parseString(T.value)}),A}},$_=class extends z{constructor(){super(...arguments);this.name="TrackpointConverter";this.supportedTags=["Trackpoint"]}convert(_,I){let A={};return this.processChildren(_,A,{Time:(T,n)=>n.Time=this.parseString(T.value),Position:(T,n)=>{let L=I.metadata.get("decoder");n.Position=L?.getConverter("Position")?.convert(T,I)},AltitudeMeters:(T,n)=>n.AltitudeMeters=this.parseFloat(T.value),DistanceMeters:(T,n)=>n.DistanceMeters=this.parseFloat(T.value),HeartRateBpm:(T,n)=>{if(T.value)n.HeartRateBpm=this.parseFloat(T.value);else{let L=this.getChildByTag(T,"Value");L?.value&&(n.HeartRateBpm=this.parseFloat(L.value))}},Cadence:(T,n)=>{let L={Low:0,High:0};this.processChildren(T,L,{Low:(E,C)=>C.Low=this.parseFloat(E.value)||0,High:(E,C)=>C.High=this.parseFloat(E.value)||0}),n.Cadence=L},SensorState:(T,n)=>n.SensorState=T.value,Extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Extensions");E&&(n.Extensions=E.convert(T,I))}}),A}},k_=class extends z{constructor(){super(...arguments);this.name="TrackConverter";this.supportedTags=["Track"]}convert(_,I){let A={Trackpoint:[]};return this.processChildren(_,A,{Trackpoint:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Trackpoint")?.convert(T,I);E&&n.Trackpoint&&n.Trackpoint.push(E)}}),A}},Q_=class extends z{constructor(){super(...arguments);this.name="ActivityLapConverter";this.supportedTags=["Lap"]}convert(_,I){let A={};return this.extractAttributes(_,A,{StartTime:"StartTime"}),this.processChildren(_,A,{TotalTimeSeconds:(T,n)=>n.TotalTimeSeconds=this.parseFloat(T.value),DistanceMeters:(T,n)=>n.DistanceMeters=this.parseFloat(T.value),MaximumSpeed:(T,n)=>n.MaximumSpeed=this.parseFloat(T.value),Calories:(T,n)=>n.Calories=this.parseFloat(T.value),AverageHeartRateBpm:(T,n)=>n.AverageHeartRateBpm=this.parseFloat(T.value),MaximumHeartRateBpm:(T,n)=>n.MaximumHeartRateBpm=this.parseFloat(T.value),Intensity:(T,n)=>n.Intensity=T.value,TriggerMethod:(T,n)=>n.TriggerMethod=T.value,Track:(T,n)=>{n.Track||(n.Track=[]);let E=I.metadata.get("decoder")?.getConverter("Track")?.convert(T,I);E&&n.Track.push(E)},Notes:(T,n)=>n.Notes=this.parseString(T.value),Extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Extensions");E&&(n.Extensions=E.convert(T,I))}}),A}},J_=class extends z{constructor(){super(...arguments);this.name="ActivityConverter";this.supportedTags=["Activity"]}convert(_,I){let A={Id:"",Lap:[]};return this.extractAttributes(_,A,{Sport:"Sport"}),this.processChildren(_,A,{Id:(T,n)=>n.Id=this.parseString(T.value),Lap:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Lap")?.convert(T,I);E&&n.Lap.push(E)},Notes:(T,n)=>n.Notes=this.parseString(T.value),Training:(T,n)=>n.Training=this.convertTraining(T),Creator:(T,n)=>n.Creator=this.convertCreator(T),Extensions:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Extensions");E&&(n.Extensions=E.convert(T,I))}}),A}convertTraining(_){let I={};return _.attributes&&Object.entries(_.attributes).forEach(([A,T])=>{I[A]=T}),_.children?.forEach(A=>{I[A.tag]=this.convertExtensionContent(A)}),I}convertCreator(_){let I={};return _.children?.forEach(A=>{I[A.tag]=this.convertExtensionContent(A)}),I}},z_=class extends z{constructor(){super(...arguments);this.name="ActivityListConverter";this.supportedTags=["Activities"]}convert(_,I){let A={Activity:[],MultiActivitySession:[]};return this.processChildren(_,A,{Activity:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("Activity")?.convert(T,I);E&&n.Activity&&n.Activity.push(E)},MultiActivitySession:(T,n)=>{let E=I.metadata.get("decoder")?.getConverter("MultiActivitySession")?.convert(T,I);E&&n.MultiActivitySession&&n.MultiActivitySession.push(E)}}),A}},j_=class extends z{constructor(){super(...arguments);this.name="MultiActivitySessionConverter";this.supportedTags=["MultiActivitySession"]}convert(_,I){let A={};return this.processChildren(_,A,{Id:(T,n)=>n.Id=this.parseString(T.value),FirstActivity:(T,n)=>{let L=I.metadata.get("decoder");n.FirstActivity=L?.getConverter("FirstActivity")?.convert(T,I)},NextActivity:(T,n)=>{n.NextActivity||(n.NextActivity=[]);let E=I.metadata.get("decoder")?.getConverter("NextActivity")?.convert(T,I);E&&n.NextActivity.push(E)},Notes:(T,n)=>n.Notes=this.parseString(T.value)}),A}},y_=class extends z{constructor(){super(...arguments);this.name="AbstractSourceConverter";this.supportedTags=["Author","Creator"]}convert(_,I){let A={};return this.processChildren(_,A,{Name:(T,n)=>n.Name=this.parseString(T.value)}),A}},Z_=class extends z{constructor(){super(...arguments);this.name="extensions-converter";this.supportedTags=["Extensions"]}convert(_,I){let A={};return this.flattenExtensionElement(_,A),A}flattenExtensionElement(_,I){if(!_.children?.length&&_.value!==void 0){I[_.tag]=this.parseExtensionValue(_.value);return}_.children?.length&&_.children.forEach(A=>{this.flattenExtensionElement(A,I)})}parseExtensionValue(_){if(_===void 0)return;let I=String(_),A=parseFloat(I);return!isNaN(A)&&isFinite(A)?A:I}};import{Parser as ut}from"htmlparser2";var q_=class{static tokenizeXML(t){let _=[],I=new ut({onopentag(A,T){_.push({type:"open",tag:A,attributes:T})},ontext(A){let T=A.replace(/\n/g,"").trim();T&&_.push({type:"text",tag:"text",value:T})},onclosetag(A){_.push({type:"close",tag:A})}},{xmlMode:!0});return I.write(t),I.end(),_}static compressXML(t){return t.replace(/>\s+</g,"><").replace(/\s+/g," ").trim()}static formatXML(t,_=2){let I=" ".repeat(_),A="",T=0,n=!1;for(let L=0;L<t.length;L++){let E=t[L],C=t[L+1];E==="<"?(C==="/"?(T--,n||(A+=`
12
12
  `+I.repeat(T))):C!=="?"&&C!=="!"&&(n||(A+=`
13
- `+I.repeat(T)),T++),n=!0):E===">"&&(n=!1,C==="<"&&t[L+2]==="/"&&T--),A+=E}return A.trim()}static validateXML(t){try{let _=new rt({},{xmlMode:!0});return _.write(t),_.end(),{isValid:!0}}catch(_){return{isValid:!1,error:_.message}}}static extractXMLDeclaration(t){let _=t.match(/<\?xml\s+([^>]+)\?>/);if(!_)return{};let I=_[1],A={},T=I.match(/version=["']([^"']+)["']/);T&&(A.version=T[1]);let n=I.match(/encoding=["']([^"']+)["']/);n&&(A.encoding=n[1]);let L=I.match(/standalone=["']([^"']+)["']/);return L&&(A.standalone=L[1]),A}static escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}static unescapeXML(t){return t.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&amp;/g,"&")}};var u_=class{constructor(){this.stage="tokenize";this.name="tokenize-processor"}async process(t){if(!t.xmlContent)throw new Error("TCX data cannot be empty");let _=q_.tokenizeXML(t.xmlContent);if(_.length===0)throw new Error("Not a valid TCX file");return t.tokens=_,t.stats.processedTokens=_.length,t}},i_=class{constructor(){this.stage="ast-generate";this.name="ast-generate-processor"}async process(t){let _=Date.now();if(!t.tokens)throw new Error("Tokens cannot be empty");let I=[],A,T=null;for(let n of t.tokens)if(n.type==="open"){let L={tag:n.tag,attributes:n.attributes||{},children:[]};A?T&&T.children?.push(L):A=L,I.push(L),T=L}else n.type==="text"&&T?T.value=n.value:n.type==="close"&&(I.pop(),T=I[I.length-1]||null);return t.ast=A,t.performance.astTime=Date.now()-_,t}},r_=class{constructor(t){this.getConverter=t;this.stage="convert";this.name="convert-processor"}async process(t){if(!t.ast)throw new Error("AST is empty, cannot convert");let _=this.findTCXRoot(t.ast);if(!_)throw new Error("Not a valid TCX file: TrainingCenterDatabase element not found");let I=this.convertAST(_,t);return t.result=I,t.stats.convertedElements=this.countElements(t.ast),t}findTCXRoot(t){if(t.tag==="TrainingCenterDatabase")return t;if(t.children)for(let _ of t.children){let I=this.findTCXRoot(_);if(I)return I}}convertAST(t,_){let I=this.getConverter(t.tag);return I?I.convert(t,_):this.genericConvert(t,_)}genericConvert(t,_){let I={};if(t.attributes&&Object.entries(t.attributes).forEach(([A,T])=>{I[A]=T}),t.value!==void 0)if(t.children&&t.children.length>0)I._value=t.value;else return t.value;return t.children&&t.children.forEach(A=>{let T=this.convertAST(A,_);I[A.tag]?(Array.isArray(I[A.tag])||(I[A.tag]=[I[A.tag]]),I[A.tag].push(T)):I[A.tag]=T}),I}countElements(t){let _=1;if(t.children)for(let I of t.children)_+=this.countElements(I);return _}},m_=class{constructor(){this.stage="complete";this.name="complete-processor"}async process(t){if(!t.result)throw new Error("No conversion result found");let _=Date.now(),I=_-t.performance.startTime;return t.performance.endTime=_,t.performance.processingTime=I,t.metadata.set("performance",{processingTime:I,processedTokens:t.stats.processedTokens,convertedElements:t.stats.convertedElements}),t}};var c_=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 u_,new i_,new r_(t=>this.getConverter(t)),new m_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let t=[new N_,new $_,new k_,new Q_,new J_,new z_,new j_,new y_,new Z_];for(let _ of t)_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name);this.defaultConvertersRegistered=!0}addConverterForTag(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((A,T)=>(A.priority||100)-(T.priority||100))}async registerConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Converter plugin ${t.name} already exists`);t.supportedTags?.forEach(_=>{this.addConverterForTag(_,t)}),this.registeredPlugins.add(t.name)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t.name);_!==-1?this.middlewarePlugins[_]=t:this.middlewarePlugins.push(t)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getAllConverters(t){return this.converterPlugins.get(t)||[]}unregisterConverter(t){let _;for(let[I,A]of this.converterPlugins){let T=A.findIndex(n=>n.name===t);T!==-1&&(_=A[T],A.splice(T,1),A.length===0&&this.converterPlugins.delete(I))}_&&this.registeredPlugins.delete(t)}unregisterMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t);_!==-1&&this.middlewarePlugins.splice(_,1)}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let A=_;for(let T of this.middlewarePlugins){let n=T[t];if(n)try{A=await n.call(T,A,I)||A}catch(L){I.errors.push(L),await T.onError?.(L,I)}}return A}async parseByBuffer(t){await this.initialize();let _=this.createContext();_.rawData=t,_.xmlContent=t.toString("utf-8"),_.metadata.set("decoder",this);for(let I of this.processors)try{switch(_=await I.process(_),I.stage){case"tokenize":_.tokens&&(_.tokens=await this.executeMiddlewareHook("onTokenize",_.tokens,_));break;case"ast-generate":_.ast&&(_.ast=await this.executeMiddlewareHook("onAstGenerate",_.ast,_));break;case"convert":_.result&&(_.result=await this.executeMiddlewareHook("onConvert",_.result,_));break;case"complete":_.result&&(_.result=await this.executeMiddlewareHook("onComplete",_.result,_));break}}catch(A){_.errors.push(A);for(let T of this.middlewarePlugins)await T.onError?.(A,_);throw new Error(`TCX pipeline stage "${I.stage}" failed: ${A.message}`)}return _.result}convertExtensions(t){let _={},{attributes:I,tag:A,value:T}=t;if(I&&Object.entries(I).forEach(([n,L])=>{_[n]=L}),t?.children?.length)t.children?.forEach(n=>{_[n.tag]=this.convertExtensions(n)});else if(T!==void 0)return T;return _}async parserByBuffer(t){return this.parseByBuffer(t)}async parseByString(t){let _=Buffer.from(t,"utf-8");return this.parseByBuffer(_)}};import mt from"dayjs";import ZI from"dayjs/plugin/utc.js";mt.extend(ZI);var a_=class{constructor(t={}){this.compact=t.compact??!0}async encode(t){let _=this.buildTCXXML(t);return Buffer.from(_,"utf-8")}encodeToString(t){return this.buildTCXXML(t)}buildTCXXML(t){let _=this.buildXMLHeader(t),I=this.buildTCXContent(t),T=`${_}${I}
13
+ `+I.repeat(T)),T++),n=!0):E===">"&&(n=!1,C==="<"&&t[L+2]==="/"&&T--),A+=E}return A.trim()}static validateXML(t){try{let _=new ut({},{xmlMode:!0});return _.write(t),_.end(),{isValid:!0}}catch(_){return{isValid:!1,error:_.message}}}static extractXMLDeclaration(t){let _=t.match(/<\?xml\s+([^>]+)\?>/);if(!_)return{};let I=_[1],A={},T=I.match(/version=["']([^"']+)["']/);T&&(A.version=T[1]);let n=I.match(/encoding=["']([^"']+)["']/);n&&(A.encoding=n[1]);let L=I.match(/standalone=["']([^"']+)["']/);return L&&(A.standalone=L[1]),A}static escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}static unescapeXML(t){return t.replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&quot;/g,'"').replace(/&#39;/g,"'").replace(/&amp;/g,"&")}};var u_=class{constructor(){this.stage="tokenize";this.name="tokenize-processor"}async process(t){if(!t.xmlContent)throw new Error("TCX data cannot be empty");let _=q_.tokenizeXML(t.xmlContent);if(_.length===0)throw new Error("Not a valid TCX file");return t.tokens=_,t.stats.processedTokens=_.length,t}},i_=class{constructor(){this.stage="ast-generate";this.name="ast-generate-processor"}async process(t){let _=Date.now();if(!t.tokens)throw new Error("Tokens cannot be empty");let I=[],A,T=null;for(let n of t.tokens)if(n.type==="open"){let L={tag:n.tag,attributes:n.attributes||{},children:[]};A?T&&T.children?.push(L):A=L,I.push(L),T=L}else n.type==="text"&&T?T.value=n.value:n.type==="close"&&(I.pop(),T=I[I.length-1]||null);return t.ast=A,t.performance.astTime=Date.now()-_,t}},r_=class{constructor(t){this.getConverter=t;this.stage="convert";this.name="convert-processor"}async process(t){if(!t.ast)throw new Error("AST is empty, cannot convert");let _=this.findTCXRoot(t.ast);if(!_)throw new Error("Not a valid TCX file: TrainingCenterDatabase element not found");let I=this.convertAST(_,t);return t.result=I,t.stats.convertedElements=this.countElements(t.ast),t}findTCXRoot(t){if(t.tag==="TrainingCenterDatabase")return t;if(t.children)for(let _ of t.children){let I=this.findTCXRoot(_);if(I)return I}}convertAST(t,_){let I=this.getConverter(t.tag);return I?I.convert(t,_):this.genericConvert(t,_)}genericConvert(t,_){let I={};if(t.attributes&&Object.entries(t.attributes).forEach(([A,T])=>{I[A]=T}),t.value!==void 0)if(t.children&&t.children.length>0)I._value=t.value;else return t.value;return t.children&&t.children.forEach(A=>{let T=this.convertAST(A,_);I[A.tag]?(Array.isArray(I[A.tag])||(I[A.tag]=[I[A.tag]]),I[A.tag].push(T)):I[A.tag]=T}),I}countElements(t){let _=1;if(t.children)for(let I of t.children)_+=this.countElements(I);return _}},m_=class{constructor(){this.stage="complete";this.name="complete-processor"}async process(t){if(!t.result)throw new Error("No conversion result found");let _=Date.now(),I=_-t.performance.startTime;return t.performance.endTime=_,t.performance.processingTime=I,t.metadata.set("performance",{processingTime:I,processedTokens:t.stats.processedTokens,convertedElements:t.stats.convertedElements}),t}};var c_=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 u_,new i_,new r_(t=>this.getConverter(t)),new m_]}async registerDefaultConverters(){if(this.defaultConvertersRegistered)return;let t=[new N_,new $_,new k_,new Q_,new J_,new z_,new j_,new y_,new Z_];for(let _ of t)_.supportedTags?.forEach(I=>{this.addConverterForTag(I,_)}),this.registeredPlugins.add(_.name);this.defaultConvertersRegistered=!0}addConverterForTag(t,_){this.converterPlugins.has(t)||this.converterPlugins.set(t,[]);let I=this.converterPlugins.get(t);I.push(_),I.sort((A,T)=>(A.priority||100)-(T.priority||100))}async registerConverter(t){if(this.registeredPlugins.has(t.name))throw new Error(`Converter plugin ${t.name} already exists`);t.supportedTags?.forEach(_=>{this.addConverterForTag(_,t)}),this.registeredPlugins.add(t.name)}async registerMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t.name);_!==-1?this.middlewarePlugins[_]=t:this.middlewarePlugins.push(t)}getConverter(t){let _=this.converterPlugins.get(t);return _&&_.length>0?_[0]:void 0}getAllConverters(t){return this.converterPlugins.get(t)||[]}unregisterConverter(t){let _;for(let[I,A]of this.converterPlugins){let T=A.findIndex(n=>n.name===t);T!==-1&&(_=A[T],A.splice(T,1),A.length===0&&this.converterPlugins.delete(I))}_&&this.registeredPlugins.delete(t)}unregisterMiddleware(t){let _=this.middlewarePlugins.findIndex(I=>I.name===t);_!==-1&&this.middlewarePlugins.splice(_,1)}async initialize(){if(this.initialized)return;await this.registerDefaultConverters();let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.initialize?.(t);this.initialized=!0}async destroy(){if(!this.initialized)return;let t=this.createContext(),_=[...new Map([...Array.from(this.converterPlugins.values()).flat(),...this.middlewarePlugins].map(I=>[I.name,I])).values()];for(let I of _)await I.destroy?.(t);this.initialized=!1}createContext(){return{metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},performance:{startTime:Date.now()}}}async executeMiddlewareHook(t,_,I){let A=_;for(let T of this.middlewarePlugins){let n=T[t];if(n)try{A=await n.call(T,A,I)||A}catch(L){I.errors.push(L),await T.onError?.(L,I)}}return A}async parseByBuffer(t){await this.initialize();let _=this.createContext();_.rawData=t,_.xmlContent=t.toString("utf-8"),_.metadata.set("decoder",this);for(let I of this.processors)try{switch(_=await I.process(_),I.stage){case"tokenize":_.tokens&&(_.tokens=await this.executeMiddlewareHook("onTokenize",_.tokens,_));break;case"ast-generate":_.ast&&(_.ast=await this.executeMiddlewareHook("onAstGenerate",_.ast,_));break;case"convert":_.result&&(_.result=await this.executeMiddlewareHook("onConvert",_.result,_));break;case"complete":_.result&&(_.result=await this.executeMiddlewareHook("onComplete",_.result,_));break}}catch(A){_.errors.push(A);for(let T of this.middlewarePlugins)await T.onError?.(A,_);throw new Error(`TCX pipeline stage "${I.stage}" failed: ${A.message}`)}return _.result}convertExtensions(t){let _={},{attributes:I,tag:A,value:T}=t;if(I&&Object.entries(I).forEach(([n,L])=>{_[n]=L}),t?.children?.length)t.children?.forEach(n=>{_[n.tag]=this.convertExtensions(n)});else if(T!==void 0)return T;return _}async parserByBuffer(t){return this.parseByBuffer(t)}async parseByString(t){let _=Buffer.from(t,"utf-8");return this.parseByBuffer(_)}};import it from"dayjs";import yI from"dayjs/plugin/utc.js";it.extend(yI);var a_=class{constructor(t={}){this.compact=t.compact??!0}async encode(t){let _=this.buildTCXXML(t);return Buffer.from(_,"utf-8")}encodeToString(t){return this.buildTCXXML(t)}buildTCXXML(t){let _=this.buildXMLHeader(t),I=this.buildTCXContent(t),T=`${_}${I}
14
14
  </TrainingCenterDatabase>`;return this.compact?this.compressXML(T):T}compressXML(t){return t.replace(/>\s+</g,"><").replace(/^\s+|\s+$/gm,"").replace(/\s+/g," ").trim()}buildXMLHeader(t){let _=t.version||"1.0",I=t.creator||"trackswap",A=t.xmlns||"http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2",T=t["xmlns:xsi"]||"http://www.w3.org/2001/XMLSchema-instance",n=t["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(_)}"`,` creator="${this.escapeXMLAttribute(I)}"`,` xmlns="${this.escapeXMLAttribute(A)}"`,` xmlns:xsi="${this.escapeXMLAttribute(T)}"`,` xsi:schemaLocation="${this.escapeXMLAttribute(n)}">`].join(`
15
15
  `)}buildTCXContent(t){let _=[];return t.Folders&&_.push(this.buildFolders(t.Folders)),t.Activities&&_.push(this.buildActivities(t.Activities)),t.Workouts&&_.push(this.buildWorkouts(t.Workouts)),t.Courses&&_.push(this.buildCourses(t.Courses)),t.Author&&_.push(this.buildAuthor(t.Author)),t.Extensions&&_.push(this.buildExtensions(t.Extensions)),_.join(`
16
16
  `)}buildFolders(t){let _=["<Folders>"];return t.History&&_.push(this.buildHistory(t.History)),t.Workouts&&_.push(this.buildWorkouts(t.Workouts)),t.Courses,_.push("</Folders>"),_.join(`
@@ -26,4 +26,4 @@ var Q=class extends Error{constructor(t,_,I={}){super(_),this.name="TrackSwapErr
26
26
  `)}buildWorkouts(t){return"<Workouts></Workouts>"}buildCourses(t){let _=["<Courses>"];return t.Course?.length&&t.Course.forEach(I=>{_.push(this.buildCourseElement(I))}),_.push("</Courses>"),_.join(`
27
27
  `)}buildCourseElement(t){let _=["<Course>"];return this.addOptionalElement(_,"Name",t.Name),this.addOptionalElement(_,"Notes",t.Notes),t.Lap?.length&&t.Lap.forEach(I=>{_.push(this.buildCourseLap(I))}),t.Track?.length&&t.Track.forEach(I=>{_.push(this.buildTrack(I))}),t.CoursePoint?.length&&t.CoursePoint.forEach(I=>{_.push(this.buildCoursePoint(I))}),t.Extensions&&_.push(this.buildExtensions(t.Extensions)),_.push("</Course>"),_.join(`
28
28
  `)}buildCourseLap(t){let _=["<Lap>"];this.addOptionalNumericElement(_,"TotalTimeSeconds",t.TotalTimeSeconds),this.addOptionalNumericElement(_,"DistanceMeters",t.DistanceMeters),_.push(this.wrapGeoTag("BeginPosition",t.BeginPosition)),_.push(this.wrapGeoTag("EndPosition",t.EndPosition)),this.addOptionalNumericElement(_,"BeginAltitudeMeters",t.BeginAltitudeMeters),this.addOptionalNumericElement(_,"EndAltitudeMeters",t.EndAltitudeMeters);let I=t;return I.Track?.length&&I.Track.forEach(A=>{_.push(this.buildTrack(A))}),t.Extensions&&_.push(this.buildExtensions(t.Extensions)),_.push("</Lap>"),_.join(`
29
- `)}buildCoursePoint(t){let _=["<CoursePoint>"];return this.addOptionalElement(_,"Name",t.Name),t.Time!==void 0&&t.Time!==null&&_.push(`<Time>${t.Time}</Time>`),t.Position&&_.push(this.buildPosition(t.Position)),this.addOptionalNumericElement(_,"AltitudeMeters",t.AltitudeMeters),this.addOptionalElement(_,"PointType",t.PointType),this.addOptionalElement(_,"Notes",t.Notes),t.Extensions&&_.push(this.buildExtensions(t.Extensions)),_.push("</CoursePoint>"),_.join("")}buildAuthor(t){let _=["<Author>"];return this.addOptionalElement(_,"Name",t.Name),_.push("</Author>"),_.join("")}buildExtensions(t){let _=this.buildExtensionContent(t);return _?`<Extensions>${_}</Extensions>`:""}buildExtensionContent(t){return Object.entries(t).filter(([_])=>!_.startsWith("xmlns")).map(([_,I])=>{if(I&&typeof I=="object"){let A=this.buildExtensionContent(I);return`<${_}>${A}</${_}>`}else if(I!=null)return`<${_}>${this.escapeXML(String(I))}</${_}>`;return""}).filter(_=>_).join("")}formatTime(t){let _=mt(t);if(!_.isValid())throw new Error(`Cannot encode invalid TCX timestamp: ${String(t)}`);return _.toISOString()}addOptionalElement(t,_,I,A){if(I!=null&&I!==""){let T=A?A(I):this.escapeXML(I);t.push(`<${_}>${T}</${_}>`)}}addOptionalNumericElement(t,_,I){I!=null&&!isNaN(I)&&t.push(`<${_}>${I}</${_}>`)}isValidCoordinate(t,_){return t!=null&&_!==void 0&&_!==null&&!isNaN(t)&&!isNaN(_)}formatCoordinate(t){return this.roundTo(t,6).toString()}roundTo(t,_){let I=Math.pow(10,_);return Math.round(t*I)/I}escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(t){return typeof t!="string"?String(t||""):t.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(t){if(t===null||typeof t!="object")return t;if(t instanceof Date)return new Date(t.getTime());if(Array.isArray(t))return t.map(I=>this.deepClone(I));let _={};for(let I in t)Object.prototype.hasOwnProperty.call(t,I)&&(_[I]=this.deepClone(t[I]));return _}encoder(t){return this.encode(t)}};import qI from"dayjs";var x=class extends u{convertPoints(t){return t.map(_=>this.convertPoint(_)).filter(_=>_!==void 0)}convertTime(t){if(!t)return;if(typeof t=="number")return t;let _=qI(t);return _.isValid()?_.valueOf():void 0}},e=class{constructor(){this.version="1.0.0";this.priority=100}supports(t){return this.supportedTags.includes(t)}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}convertTimeToDate(t){return t?new Date(t):new Date}convertTimeToString(t){return this.convertTimeToDate(t).toISOString()}ensureValidCoordinates(t,_){return t>=-90&&t<=90&&_>=-180&&_<=180}round(t,_=6){let I=Math.pow(10,_);return Math.round(t*I)/I}};var ct={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"},at=R=>R*(180/Math.pow(2,31)),xt=2147483647;function y(R,t=6){if(R==null)return;let _=typeof R=="number"?R:Number(R);if(!Number.isFinite(_)||_===xt)return;let I=at(_),A=Math.pow(10,t);return Math.round(I*A)/A}import e_ from"dayjs";import{Profile as iI}from"@garmin/fitsdk";import x_ from"dayjs";import{getPreciseDistance as uI}from"geolib";var i=class{calculateRecordsAggMetrics(t){if(!t||t.length===0)return;let _={records:this.preprocessRecords(t)};for(let I=0;I<_.records.length;I++){let A=_.records[I];if(!(A.positionLat==null||A.positionLong==null||!Number.isFinite(A.positionLat)||!Number.isFinite(A.positionLong))){if(_.startPositionLat==null&&(_.startPositionLat=A.positionLat),_.startPositionLong==null&&(_.startPositionLong=A.positionLong),_.endPositionLat=A.positionLat,_.endPositionLong=A.positionLong,_.timestamp=A.timestamp,_?.startTime||(_.startTime=A.timestamp),_.endTime=A.timestamp,_.totalDistance=A.distance,_.totalElapsedTime=x_(A.timestamp).diff(x_(_.startTime),"second"),A?.speed&&(_.avgSpeed=_.avgSpeed?(_.avgSpeed+A.speed)/2:A.speed,_.maxSpeed=Math.max(_.maxSpeed||0,A.speed)),A?.heartRate&&(_.maxHeartRate=Math.max(_.maxHeartRate||0,A.heartRate),_.minHeartRate=Math.min(_.minHeartRate||A.heartRate,A.heartRate),_.avgHeartRate?_.avgHeartRate=(_.avgHeartRate+A.heartRate)/2:_.avgHeartRate=A.heartRate),A?.altitude&&(_.maxAltitude=Math.max(_.maxAltitude||0,A.altitude),_.minAltitude=Math.min(_.minAltitude||A.altitude,A.altitude),_.avgAltitude=_.avgAltitude?(_.avgAltitude+A.altitude)/2:A.altitude,I>0&&t[I-1].altitude)){let T=this.calculateElevationChanges(t[I-1],A);_.totalAscent=(_.totalAscent||0)+T.ascent,_.totalDescent=(_.totalDescent||0)+T.descent}if(A?.cadence&&(_.maxCadence=Math.max(_.maxCadence||0,A.cadence),_.avgCadence?_.avgCadence=(_.avgCadence+A.cadence)/2:_.avgCadence=A.cadence),A?.power){_.maxPower=Math.max(_.maxPower||0,A.power),_.avgPower?_.avgPower=(_.avgPower+A.power)/2:_.avgPower=A.power;let T=this.calculateAccumulatedPower(I>0?t[I-1]:A,A,_.totalWork||0);_.totalWork=T.newAccumulatedWork,_.normalizedPower=void 0}A?.temperature&&(_.avgTemperature?_.avgTemperature=(_.avgTemperature+A.temperature)/2:_.avgTemperature=A.temperature,_.maxTemperature=Math.max(_.maxTemperature||0,A.temperature),_.minTemperature=Math.min(_.minTemperature||A.temperature,A.temperature))}}return _}calculateLapAggMetrics(t){if(!t||t.length===0)return;let _={laps:t,timestamp:t[0]?.timestamp||new Date};for(let I=0;I<t.length;I++){let A=t[I];A.startPositionLat&&A.startPositionLong&&!_?.startPositionLat&&!_?.startPositionLong&&(_.startPositionLat=A.startPositionLat,_.startPositionLong=A.startPositionLong),A.endPositionLat&&A.endPositionLong&&(_.endPositionLat=A.endPositionLat,_.endPositionLong=A.endPositionLong),A.startTime&&!_?.startTime&&(_.startTime=A.startTime),A.endTime&&(_.endTime=A.endTime),_.timestamp=A.timestamp||A.endTime||_.timestamp,A.totalDistance&&(_.totalDistance=(_.totalDistance||0)+A.totalDistance),A.totalElapsedTime&&(_.totalElapsedTime=(_.totalElapsedTime||0)+A.totalElapsedTime),A.totalMovingTime&&(_.totalMovingTime=(_.totalMovingTime||0)+A.totalMovingTime),A.totalTimerTime&&(_.totalTimerTime=(_.totalTimerTime||0)+A.totalTimerTime),A.maxSpeed&&(_.maxSpeed=Math.max(_.maxSpeed||0,A.maxSpeed)),A.avgSpeed&&(_.avgSpeed?_.avgSpeed=(_.avgSpeed+A.avgSpeed)/2:_.avgSpeed=A.avgSpeed),A.maxHeartRate&&(_.maxHeartRate=Math.max(_.maxHeartRate||0,A.maxHeartRate)),A.minHeartRate&&(_.minHeartRate=_.minHeartRate?Math.min(_.minHeartRate,A.minHeartRate):A.minHeartRate),A.avgHeartRate&&(_.avgHeartRate?_.avgHeartRate=(_.avgHeartRate+A.avgHeartRate)/2:_.avgHeartRate=A.avgHeartRate),A.maxAltitude&&(_.maxAltitude=Math.max(_.maxAltitude||0,A.maxAltitude)),A.minAltitude&&(_.minAltitude=_.minAltitude?Math.min(_.minAltitude,A.minAltitude):A.minAltitude),A.avgAltitude&&(_.avgAltitude?_.avgAltitude=(_.avgAltitude+A.avgAltitude)/2:_.avgAltitude=A.avgAltitude),A.totalAscent&&(_.totalAscent=(_.totalAscent||0)+A.totalAscent),A.totalDescent&&(_.totalDescent=(_.totalDescent||0)+A.totalDescent),A.maxCadence&&(_.maxCadence=Math.max(_.maxCadence||0,A.maxCadence)),A.avgCadence&&(_.avgCadence?_.avgCadence=(_.avgCadence+A.avgCadence)/2:_.avgCadence=A.avgCadence),A.maxPower&&(_.maxPower=Math.max(_.maxPower||0,A.maxPower)),A.avgPower&&(_.avgPower?_.avgPower=(_.avgPower+A.avgPower)/2:_.avgPower=A.avgPower),A.totalWork&&(_.totalWork=(_.totalWork||0)+A.totalWork),A.maxTemperature&&(_.maxTemperature=Math.max(_.maxTemperature||0,A.maxTemperature)),A.minTemperature&&(_.minTemperature=_.minTemperature?Math.min(_.minTemperature,A.minTemperature):A.minTemperature),A.avgTemperature&&(_.avgTemperature?_.avgTemperature=(_.avgTemperature+A.avgTemperature)/2:_.avgTemperature=A.avgTemperature)}return _}preprocessRecords(t){if(!t||t.length===0)return t;let _=t.filter(n=>n.timestamp).sort((n,L)=>n.timestamp.valueOf()-L.timestamp.valueOf()),I=0,A=0,T=[];for(let n=0;n<_.length;n++){let L=_[n],E={...L};if(n>0){let C=this.calculatePointDistanceByPosition(_[n-1],E)||0;if(E.distance||(A+=C,E.distance=A),L.speed||(E.speed=this.calculateInstantSpeed(_[n-1],E,C)),L.power){let U=this.calculateAccumulatedPower(_[n-1],E,I);E.accumulatedPower=U.accumulatedPower,I=U.newAccumulatedWork}}T.push(E)}return T}calculatePointDistanceByPosition(t,_){if(!(t.positionLat==null||t.positionLong==null||_.positionLat==null||_.positionLong==null||!Number.isFinite(t.positionLat)||!Number.isFinite(t.positionLong)||!Number.isFinite(_.positionLat)||!Number.isFinite(_.positionLong)))try{return uI({latitude:t.positionLat,longitude:t.positionLong},{latitude:_.positionLat,longitude:_.positionLong})}catch{return}}calculateInstantSpeed(t,_,I){if(!t.timestamp||!_.timestamp||!I)return;let A=(x_(_.timestamp).valueOf()-x_(t.timestamp).valueOf())/1e3;if(!(A<=0))return I/A}calculateAccumulatedPower(t,_,I){if(t.power===void 0||_.power===void 0||!t.timestamp||!_.timestamp)return{accumulatedPower:I,newAccumulatedWork:I};let A=_.timestamp?.valueOf()-t.timestamp?.valueOf();if(A<=0)return{accumulatedPower:I,newAccumulatedWork:I};let n=(t.power+_.power)/2*A,L=I+n;return{accumulatedPower:L,newAccumulatedWork:L}}calculateElevationChanges(t,_){let I=0,A=0;return _.altitude!==void 0&&t.altitude!==void 0&&(_.altitude>t.altitude?I=_.altitude-t.altitude:_.altitude<=t.altitude&&(A=t.altitude-_.altitude)),{ascent:I,descent:A}}};var _t=class extends x{constructor(){super(...arguments);this.name="gpx-to-activity-converter";this.supportedTags=["gpx"];this.convertGPXExtensions=_=>{let I={};return Object.entries(_).forEach(([A,T])=>{if(typeof T<"u"&&T!=="undefined"){let n=ct[A]||A;I[n]=this.autoNumber(T)}}),I}}convert(_,I){if(I.sourceFormat!=="gpx")return;let A=I.sourceData;return this.convertGPX(A)}convertGPX(_){let I={metadata:{originType:"GPX",fileType:"gpx"},activities:[]};return _.wpt&&(I.points=this.convertWpts2Points(_.wpt)),_.trk&&(I.activities=_.trk.map((A,T)=>this.convertTrk2Activity(A,T))),_.rte&&(I.routes=_.rte.map((A,T)=>this.convertRoute2Lap(A,T))),I}convertPoint(_,I,A){let{extensions:T}=_,n=T?this.convertGPXExtensions(T):{};return{lapIndex:A||0,index:I||0,positionLat:_?.lat,positionLong:_?.lon,altitude:_?.ele,heartRate:_?.heartRate,speed:_?.speed,power:_?.power,cadence:_?.cadence,course:_?.course,magvar:_?.magvar,geoidheight:_?.geoidheight,pointName:_?.name,comment:_?.cmt,description:_?.desc,source:_?.src,links:_?.link,symbol:_?.sym,pointType:_?.type,fix:_?.fix,sat:_?.sat,hdop:_?.hdop,vdop:_?.vdop,pdop:_?.pdop,ageofdgpsdata:_?.ageofdgpsdata,dgpsid:_?.dgpsid,gpxExtensions:_?.extensions,timestamp:_.time?e_(_.time).toDate():void 0,...n}}convertTrk2Activity(_,I){let A=_.trkseg?.map((n,L)=>this.convertTrackSeg2Lap(n,L))||[],T=new i().calculateLapAggMetrics(A);return{index:I,messageIndex:I,activityName:_.name,comment:_.cmt,description:_.desc,source:_.src,links:_.link,activityNumber:_.number,sport:_.type,gpxExtensions:_.extensions,laps:A,...T}}convertTrackSeg2Lap(_,I){return{...this.convertPoints2Lap(_.trkpt??[],I),gpxExtensions:_.extensions}}convertRoute2Lap(_,I){return{...this.convertPoints2Lap(_.rtept??[],I,_.name),comment:_.cmt,description:_.desc,source:_.src,links:_.link,routeNumber:_.number,routeType:_.type,gpxExtensions:_.extensions}}convertPoints2Lap(_,I,A){let T=_.map((U,F)=>this.convertPoint(U,F,I)),L=new i().calculateRecordsAggMetrics(T),E=new Map((L?.records??[]).map(U=>[U.index,U])),C=T.map(U=>E.get(U.index)??U);return{index:I,messageIndex:I,routeName:A,...L,records:C,lengths:[]}}convertWpts2Points(_){let I=[];for(let A=0;A<_.length;A++){let T=this.convertPoint(_[A],A);T&&I.push(T)}return I}autoNumber(_){return typeof _=="string"&&_.trim()!==""&&!isNaN(_)?Number(_):_}},tt=class extends x{constructor(){super(...arguments);this.name="fit-to-activity-converter";this.supportedTags=["fit"]}convert(_,I){if(I.sourceFormat!=="fit")return;let A=I.sourceData;return this.convertFIT(A)}convertFIT(_){let I={metadata:{originType:"FIT",fileType:"fit"},activities:[]};return _.sessionMesgs?.length?I.activities=_.sessionMesgs.map((A,T)=>({index:T,...A,startPositionLat:y(A?.startPositionLat),startPositionLong:y(A?.startPositionLong),endPositionLat:y(A?.endPositionLat),endPositionLong:y(A?.endPositionLong),laps:this.convertFITLap2Trackseg(A?.lapMesgs),strengthSets:this.convertFITStrengthSets(A?.setMesgs)})):_.courseMesgs?.length&&(I.routes=_.courseMesgs.map((A,T)=>({index:T,...A,records:this.convertLap2Points(A?.lapMesgs)}))),I}convertFITStrengthSets(_){return(_??[]).map((I,A)=>{let T=Array.isArray(I.category)?I.category:I.category==null?[]:[I.category],n=Array.isArray(I.categorySubtype)?I.categorySubtype:I.categorySubtype==null?[]:[I.categorySubtype],L=T.map((E,C)=>{let U=n[C],F=typeof U=="number"&&Number.isFinite(U)?U:void 0,V=`${String(E)}ExerciseName`,l=iI.types?.[V];return{category:E,...F===void 0?{}:{categorySubtype:F},...F===void 0||!l?.[F]?{}:{name:l[F]}}});return{...I,index:A,exercises:L}})}convertPoint(_,I,A){let{positionLong:T,positionLat:n,altitude:L,enhancedAltitude:E,enhancedSpeed:C,speed:U,...F}=_,B=n??_.position_lat,V=T??_.position_long;return{lapIndex:A||0,index:I||0,positionLat:y(B),positionLong:y(V),altitude:L,enhancedAltitude:E,speed:U,enhancedSpeed:C,...F}}convertFITLap2Trackseg(_){let I=[];if(!_?.length)return[];for(let A=0;A<_.length;A++){let T=_[A],n=T?.recordMesgs?.map((E,C)=>this.convertPoint(E,C,A)).filter(E=>E!==void 0)||[],L=T?.lengthMesgs?.map((E,C)=>({...E,index:C}))||[];I.push({index:A,...T,startPositionLat:y(T?.startPositionLat),startPositionLong:y(T?.startPositionLong),endPositionLat:y(T?.endPositionLat),endPositionLong:y(T?.endPositionLong),records:n,lengths:L})}return I}convertLap2Points(_){let I=[];if(!_?.length)return[];for(let A=0;A<_.length;A++){let n=_[A].recordMesgs?.map((L,E)=>this.convertPoint(L,E,A)).filter(L=>L!==void 0)||[];n.length&&(I=[...I,...n])}return I}},It=class extends x{constructor(){super(...arguments);this.name="tcx-to-activity-converter";this.supportedTags=["tcx"]}convert(_,I){if(I.sourceFormat!=="tcx")return;let A=I.sourceData;return this.convertTCX(A)}convertTCX(_){let I={metadata:{originType:"TCX",fileType:"tcx"},activities:[]};_.Activities?.Activity?.length&&(I.activities=_.Activities.Activity.map((n,L)=>this.convertTCXActivityToActivity(n,L)));let A=_.Courses?.Course,T=A==null?[]:Array.isArray(A)?A:[A];return T.length&&(I.routes=T.map((n,L)=>this.convertTCXCourseToRoute(n,L))),I}convertTCXCourseToRoute(_,I){let A=[],T=0,n=l=>l==null?[]:Array.isArray(l)?l:[l],L=l=>{for(let z of l??[])for(let b of z.Trackpoint??[])b==null||b.Time===void 0||A.push(this.convertPoint(b,T++,I))};L(n(_.Track));let E=_.Lap==null?[]:Array.isArray(_.Lap)?_.Lap:[_.Lap];for(let l of E)L(n(l.Track));let C=A.length,U=A[0]?.timestamp!=null?e_(A[0].timestamp):e_("2000-01-01T00:00:00Z"),F=_.CoursePoint==null?[]:Array.isArray(_.CoursePoint)?_.CoursePoint:[_.CoursePoint];for(let l of F){let z=this.convertTCXCoursePointToRecord(l,C++,I,U);z&&A.push(z)}let B=new i,V=A.length>0?B.calculateRecordsAggMetrics(A):{records:A};return{index:I,messageIndex:I,routeName:_.Name,...V,records:V?.records??A,lengths:[]}}convertTCXCoursePointToRecord(_,I,A,T){let n=_.Position?.LatitudeDegrees?Number(_.Position.LatitudeDegrees):void 0,L=_.Position?.LongitudeDegrees?Number(_.Position.LongitudeDegrees):void 0;if(n==null&&L==null&&_.AltitudeMeters==null)return;let E=typeof _.Time=="number"&&Number.isFinite(_.Time)?T.add(_.Time,"second").toDate():T.add(I,"second").toDate();return{lapIndex:A,index:I,positionLat:n,positionLong:L,altitude:_.AltitudeMeters,timestamp:E}}convertTCXActivityToActivity(_,I){let A=_.Lap?.map((n,L)=>this.convertTCXLap2Lap(n,L))||[],T=new i().calculateLapAggMetrics(A);return{index:I,messageIndex:I,sport:_.Sport?.toLowerCase(),laps:A,...T}}convertTCXLap2Lap(_,I){let T=(_?.Track?.flatMap(E=>E.Trackpoint)||[])?.filter(E=>E!==void 0&&E.Time!==void 0).map((E,C)=>this.convertPoint(E,C))||[],L=new i().calculateRecordsAggMetrics(T);return{index:I,messageIndex:I,...L,records:L?.records||[],lengths:[]}}convertPoint(_,I,A){let{Position:T,Time:n,DistanceMeters:L,AltitudeMeters:E}=_;return{lapIndex:A||0,index:I||0,positionLat:T?.LatitudeDegrees?Number(T.LatitudeDegrees):void 0,positionLong:T?.LongitudeDegrees?Number(T.LongitudeDegrees):void 0,timestamp:e_(n).toDate(),distance:L,altitude:E}}};import rI from"dayjs";var At=class extends e{constructor(){super(...arguments);this.name="activity-to-gpx-encoder";this.supportedTags=["gpx"]}encode(_,I){if(I.targetFormat!=="gpx"||!_?.activities?.length&&!_?.routes?.length&&!_?.points?.length)return;let A=_.activities?.[0]?.timestamp??_.routes?.[0]?.records?.[0]?.timestamp??_.points?.[0]?.timestamp??new Date,T=this.countRecordsMissingGpxCoordinates(_),n={version:"1.1",creator:"TrackSwap",metadata:{time:A,...T>0?{desc:`TrackSwap: omitted ${T} trackpoint(s) without valid latitude/longitude.`}:{}}};return _.points?.length&&(n.wpt=this.convertRecords2Wpts(_.points)),_.routes?.length&&(n.rte=_.routes.map(L=>this.convertRoute2GPXRoute(L))),_.activities?.length&&(n.trk=_.activities.map(L=>this.convertActivity2GPXTrack(L))),n}hasValidGpxCoordinates(_){let I=_.positionLat,A=_.positionLong;return typeof I=="number"&&typeof A=="number"&&Number.isFinite(I)&&Number.isFinite(A)&&I>=-90&&I<=90&&A>=-180&&A<=180}countRecordsMissingGpxCoordinates(_){let I=0,A=T=>{for(let n of T??[])this.hasValidGpxCoordinates(n)||I++};A(_.points);for(let T of _.activities??[])for(let n of T.laps??[])A(n.records);for(let T of _.routes??[])A(T.records);return I}convertRecords2Wpts(_){return _?.filter(I=>this.hasValidGpxCoordinates(I)).map(I=>({lat:I?.positionLat,lon:I?.positionLong,ele:I?.altitude,time:I?.timestamp,speed:I?.speed,course:I?.course,magvar:I?.magvar,geoidheight:I?.geoidheight,name:I?.pointName,cmt:I?.comment,desc:I?.description,src:I?.source,link:I?.links,sym:I?.symbol,type:I?.pointType,fix:I?.fix,sat:I?.sat,hdop:I?.hdop,vdop:I?.vdop,pdop:I?.pdop,ageofdgpsdata:I?.ageofdgpsdata,dgpsid:I?.dgpsid,extensions:this.extractGPXExtensions(I)}))??[]}convertRoute2GPXRoute(_){return{name:_.routeName,cmt:_.comment,desc:_.description,src:_.source,link:_.links,number:_.routeNumber,type:_.routeType,extensions:_.gpxExtensions,rtept:_.records?this.convertRecords2Wpts(_.records):[]}}convertActivity2GPXTrack(_){return{name:_.activityName,cmt:_.comment,desc:_.description,src:_.source,link:_.links,number:_.activityNumber,type:_.sport,extensions:_.gpxExtensions,trkseg:_.laps?.map(I=>({trkpt:I.records?this.convertRecords2Wpts(I.records):[],extensions:I.gpxExtensions}))||[]}}extractGPXExtensions(_){let I={..._.gpxExtensions??{}},A={...I["gpxtpx:TrackPointExtension"]??{}};return typeof _?.heartRate<"u"&&(A["gpxtpx:hr"]=_.heartRate),typeof _?.cadence<"u"&&(A["gpxtpx:cad"]=_.cadence),typeof _?.speed<"u"&&(A["gpxtpx:speed"]=_.speed),typeof _?.temperature<"u"&&(A["gpxtpx:atemp"]=_.temperature),Object.keys(A).length>0&&(I["gpxtpx:TrackPointExtension"]=A),typeof _?.power<"u"&&(I["gpxpx:PowerExtension"]={"gpxpx:PowerInWatts":_.power}),Object.keys(I).length>0?I:void 0}},Tt=class extends e{constructor(){super(...arguments);this.name="activity-to-fit-encoder";this.supportedTags=["fit"]}encode(_,I){if(I.targetFormat==="fit"){if(_?.activities?.length){let A={};return A.sessionMesgs=_.activities.map(T=>this.convertActivity2FITSession(T)),A}if(_?.routes?.length){let A={};return A.sessionMesgs=[this.convertRoutesToSyntheticSession(_.routes)],A}}}convertRoutesToSyntheticSession(_){let I=_.map(C=>this.convertLap2FITLap(C)),T=_.flatMap(C=>C.records??[]).filter(C=>C.timestamp!=null).sort((C,U)=>new Date(C.timestamp).getTime()-new Date(U.timestamp).getTime()),n=T[0]?.timestamp??new Date,L=T[T.length-1]?.timestamp??n,E=T.find(C=>C.positionLat!=null&&C.positionLong!=null&&Number.isFinite(C.positionLat)&&Number.isFinite(C.positionLong));return{messageIndex:0,timestamp:L,event:"session",eventType:"stop",startTime:n,startPositionLat:E?.positionLat,startPositionLong:E?.positionLong,sport:"generic",subSport:"generic",lapMesgs:I}}convertActivity2FITSession(_){return{..._,event:_?.event||"session",sport:_?.sport||"generic",lapMesgs:_.laps?.map(A=>this.convertLap2FITLap(A))||[]}}convertLap2FITLap(_){return{startTime:_.startTime,..._,recordMesgs:_.records?.map(A=>this.convertPoint2FITRecord(A))||[]}}convertPoint2FITRecord(_){return _}},nt=class extends e{constructor(){super(...arguments);this.name="sport-to-tcx-encoder";this.supportedTags=["tcx"]}encode(_,I){if(I.targetFormat!=="tcx")return;let A=!!_?.activities?.length,T=!!_?.routes?.length;if(!A&&!T)return;let n={version:"1.0",Author:{Name:"TrackSwap"}};return A&&(n.Activities={Activity:_.activities.map(L=>this.convertActivity2TCXActivity(L))}),T&&(n.Courses={Course:_.routes.map((L,E)=>this.convertRouteToTCXCourse(L,E))}),n}convertActivity2TCXActivity(_){if(!_.laps?.length)throw new Error("Cannot encode a TCX activity without laps");let I="Other",A=_.sport?.toLowerCase();return A==="running"&&(I="Running"),(A==="biking"||A==="cycling")&&(I="Biking"),{Id:this.validTimestamp(_.startTime??_.laps[0]?.startTime??_.laps[0]?.records?.[0]?.timestamp),Sport:I,Lap:_.laps.map(n=>this.convertLap2TCXLap(n))}}convertLap2TCXLap(_){let A={StartTime:this.validTimestamp(_.startTime??_.records?.[0]?.timestamp),TotalTimeSeconds:_.totalElapsedTime,DistanceMeters:_.totalDistance,MaximumSpeed:_.maxSpeed,Calories:_.totalCalories,AverageHeartRateBpm:_.avgHeartRate,MaximumHeartRateBpm:_.maxHeartRate,Intensity:"Active",TriggerMethod:"Manual",Track:_.records?[this.convertRecords2TCXTrack(_.records)]:[]};return(_.avgCadence!==void 0||_.maxCadence!==void 0)&&(A.Cadence={Low:_.avgCadence||0,High:_.maxCadence||0}),A}convertRecords2TCXTrack(_){return{Trackpoint:_.map(I=>this.convertPoint2TCXTrackpoint(I))}}convertPoint2TCXTrackpoint(_){let I={Time:this.validTimestamp(_.timestamp),Position:{LatitudeDegrees:_?.positionLat?.toString(),LongitudeDegrees:_?.positionLong?.toString()},AltitudeMeters:_.altitude,DistanceMeters:_.distance};return _.heartRate&&(I.HeartRateBpm=_.heartRate),_.cadence&&(I.Cadence={Low:_.cadence,High:_.cadence256||_.cadence}),_.power&&(I.Extensions={"ns3:TPX":{"ns3:Watts":_.power}}),I}validTimestamp(_){let I=rI(_);if(!_||!I.isValid())throw new Error("Cannot encode TCX data without valid timestamps");return I.toISOString()}convertRouteToTCXCourse(_,I){return{Name:_.routeName??`Course_${I}`,Track:_.records?[this.convertRecords2TCXTrack(_.records)]:[]}}};var Rt=class{constructor(){this.converters=new Map;this.encoders=new Map;this.registerDefaultConverters(),this.registerDefaultEncoders()}registerDefaultConverters(){this.registerConverter(new _t),this.registerConverter(new tt),this.registerConverter(new It)}registerDefaultEncoders(){this.registerEncoder(new At),this.registerEncoder(new Tt),this.registerEncoder(new nt)}registerConverter(t){this.converters.set(t.name,t)}registerEncoder(t){this.encoders.set(t.name,t)}async convertToActivity(t,_){let I={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},sourceFormat:_,sourceData:t,performance:{startTime:Date.now()}};try{let A=this.findConverter(_);if(!A)throw new Error(`No converter found for format "${_}"`);let T=Date.now(),n=A.convert(t,I);if(I.performance.convertTime=Date.now()-T,!n)throw new Error(`Converter "${A.name}" returned empty result`);let L=n;return I.result=L,I.performance.endTime=Date.now(),I.stats.endTime=Date.now(),L}catch(A){throw I.errors.push(A),A}}async encodeActivity(t,_){let I={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},targetFormat:_,performance:{startTime:Date.now()}};try{let A=this.findEncoder(_);if(!A)throw new Error(`No encoder found for format "${_}"`);let T=Date.now(),n=A.encode(t,I);if(I.performance.encodeTime=Date.now()-T,!n)throw new Error(`Encoder "${A.name}" returned empty result`);return I.result=n,I.performance.endTime=Date.now(),I.stats.endTime=Date.now(),n}catch(A){throw I.errors.push(A),A}}findConverter(t){return Array.from(this.converters.values()).find(_=>_.supportedTags?.includes(t))}findEncoder(t){return Array.from(this.encoders.values()).find(_=>_.supportedTags?.includes(t))}async destroy(){this.converters.clear(),this.encoders.clear()}};var et=8,mI=".FIT";function cI(R){return(R?.activities??[]).reduce((t,_)=>t+(_.laps??[]).reduce((I,A)=>I+(A.records?.length??0),0),0)}function aI(R,t){let _=R.recordMesgs?.length??0,I=cI(t);if(_!==I)throw new Q("FIT_ACTIVITY_DATA_LOSS",`FIT activity record count mismatch: decoded ${_}, canonicalized ${I}`,{format:"fit"})}function xI(R){return R.toString("utf8",0,Math.min(R.length,4096)).replace(/^\uFEFF/,"")}function eI(R){if(R.length>=12&&R.toString("ascii",et,et+4)===mI)return"fit";let t=xI(R);if(/<gpx\b/i.test(t))return"gpx";if(/<TrainingCenterDatabase\b/i.test(t))return"tcx"}var __=class{constructor(t){this.activities=t}matches(t){return eI(t)===this.format}},Wt=class extends __{constructor(){super(...arguments);this.format="fit"}getDecoder(){return this.decoder??=new f_}getEncoder(){return this.encoder??=new U_}async decode(_,I){let A=await this.getDecoder().parseByBuffer(_,{userData:{fitDocumentOptions:I.fit??{}}});if(!A)throw new Error("FIT decoder returned an empty result");let T=A.fitDocumentMetadata?.detectedKinds??["unknown"],n=T.includes("activity")?await this.activities.convertToActivity(A,"fit"):void 0;T.includes("activity")&&aI(A,n);let L=A.healthDocument?.diagnostics??{parserVersion:n_,messageCounts:A.fitDocumentMetadata?.messageCounts??{},recognizedMessageCounts:{},unknownMessageCounts:{},invalidValueCounts:{},warningCounts:{},warnings:[]},E=A.fileIdMesgs?.[0],C=E,U=A.fileCreatorMesgs?.[0];return{kinds:[...T],facets:{activity:n,health:A.healthDocument},native:A,metadata:{fileType:E?.type,manufacturer:E?.manufacturer,product:E?.garminProduct??E?.product,productName:typeof C?.productName=="string"?C.productName:void 0,serialNumber:E?.serialNumber===void 0?void 0:String(E.serialNumber),createdAt:E?.timeCreated?new Date(E.timeCreated):void 0,softwareVersion:U?.softwareVersion},fitDiagnostics:L,warnings:L.warnings.map(F=>F.message)}}async encodeActivity(_){let I=await this.activities.encodeActivity(_,"fit");return this.getEncoder().encode(I)}async encodeCourse(_){return Buffer.from(qt(Qt(_)))}async dispose(){await this.decoder?.destroy()}},Mt=class extends __{constructor(){super(...arguments);this.format="gpx"}getDecoder(){return this.decoder??=new Y_}getEncoder(){return this.encoder??=new b_}async decode(_){let I=await this.getDecoder().parserByBuffer(_);if(!I)throw new Error("GPX decoder returned an empty result");let A=await this.activities.convertToActivity(I,"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:I,metadata:{title:I.metadata?.name,creator:I.creator,createdAt:I.metadata?.time}}}async encodeActivity(_){let I=await this.activities.encodeActivity(_,"gpx");return this.getEncoder().encode(I)}async dispose(){await this.decoder?.destroy()}},st=class extends __{constructor(){super(...arguments);this.format="tcx"}getDecoder(){return this.decoder??=new c_}getEncoder(){return this.encoder??=new a_}async decode(_){let I=await this.getDecoder().parseByBuffer(_);if(!I)throw new Error("TCX decoder returned an empty result");let A=await this.activities.convertToActivity(I,"tcx");return{kinds:A.activities?.length?["activity"]:A.routes?.length?["course"]:["unknown"],facets:{activity:A},native:I,metadata:{creator:I.Author?.Name??I.creator}}}async encodeActivity(_){let I=await this.activities.encodeActivity(_,"tcx");return this.getEncoder().encode(I)}async dispose(){await this.decoder?.destroy()}};function _I(){let R=new Rt;return{adapters:[new Wt(R),new Mt(R),new st(R)],activities:R}}function tI(R){return R.format==="fit"&&"encodeCourse"in R}var Lt=class{constructor(t){this.adapters=new Map;for(let _ of t){if(this.adapters.has(_.format))throw new Q("ADAPTER_CONFLICT",`Multiple adapters registered for format "${_.format}"`,{format:_.format});this.adapters.set(_.format,_)}}get(t){let _=this.adapters.get(t);if(!_)throw new Q("FORMAT_UNSUPPORTED",`No adapter registered for format "${t}"`,{format:t});return _}detect(t){for(let _ of this.adapters.values())if(_.matches(t))return _.format;throw new Q("FORMAT_UNKNOWN","Unable to detect input format")}async dispose(){await Promise.all([...this.adapters.values()].map(t=>t.dispose?.()))}};function Bt(R){return typeof R=="string"?Buffer.from(R,"utf8"):Buffer.isBuffer(R)?R:Buffer.from(R.buffer,R.byteOffset,R.byteLength)}function _A(R){return typeof R=="string"||Buffer.isBuffer(R)||R instanceof Uint8Array}var Et=class{constructor(t={}){this.disposed=!1;let I=[...t.includeBuiltInAdapters===!1?[]:_I().adapters,...t.adapters??[]];this.registry=new Lt(I)}detect(t){return this.assertActive(),this.registry.detect(Bt(t))}async decode(t,_={}){this.assertActive();let I=Bt(t),A=_.format??this.registry.detect(I),T=this.registry.get(A),n=Date.now();try{let L=await T.decode(I,_);return{schemaVersion:"2",format:A,kinds:[...new Set(L.kinds)],source:{byteLength:I.byteLength},metadata:L.metadata??{},facets:L.facets,..._.includeNative?{native:L.native}:{},diagnostics:{durationMs:Date.now()-n,warnings:L.warnings??[],fit:L.fitDiagnostics}}}catch(L){throw t_(L,"DECODE_FAILED",`Failed to decode ${A.toUpperCase()}`,A)}}async decodeActivity(t,_={}){let I=await this.decode(t,_);if(!I.facets.activity)throw new Q("ACTIVITY_NOT_FOUND",`The ${I.format.toUpperCase()} document has no activity facet`,{format:I.format});return I.facets.activity}async encodeActivity(t,_){this.assertActive();try{return await this.registry.get(_.format).encodeActivity(t)}catch(I){throw t_(I,"ENCODE_FAILED",`Failed to encode ${_.format.toUpperCase()}`,_.format)}}async transcode(t,_){this.assertActive();let I=Bt(t),A=_.sourceFormat??this.registry.detect(I);if(A===_.format)return Buffer.from(I);let T=await this.decodeActivity(I,{format:A});return this.encodeActivity(T,{format:_.format})}async encodeCourse(t,_={}){this.assertActive();let I=_A(t)?await this.decodeActivity(t,{format:_.sourceFormat}):t,A=this.registry.get("fit");if(!tI(A))throw new Q("FORMAT_UNSUPPORTED","The registered FIT adapter does not support course encoding",{format:"fit"});try{return await A.encodeCourse(I)}catch(T){throw t_(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 Q("DISPOSED","TrackSwap instance is disposed")}};export{xt as FIT_SEMICIRCLE_INVALID_SINT32,n_ as TRACKSWAP_HEALTH_PARSER_VERSION,Et as TrackSwap,Q as TrackSwapError,$t as buildHealthDocumentFromMessages,Et as default,bt as detectFITKinds,y as normalizeFitSemicircleToDegrees,at as semicirclesToDegrees};
29
+ `)}buildCoursePoint(t){let _=["<CoursePoint>"];return this.addOptionalElement(_,"Name",t.Name),t.Time!==void 0&&t.Time!==null&&_.push(`<Time>${t.Time}</Time>`),t.Position&&_.push(this.buildPosition(t.Position)),this.addOptionalNumericElement(_,"AltitudeMeters",t.AltitudeMeters),this.addOptionalElement(_,"PointType",t.PointType),this.addOptionalElement(_,"Notes",t.Notes),t.Extensions&&_.push(this.buildExtensions(t.Extensions)),_.push("</CoursePoint>"),_.join("")}buildAuthor(t){let _=["<Author>"];return this.addOptionalElement(_,"Name",t.Name),_.push("</Author>"),_.join("")}buildExtensions(t){let _=this.buildExtensionContent(t);return _?`<Extensions>${_}</Extensions>`:""}buildExtensionContent(t){return Object.entries(t).filter(([_])=>!_.startsWith("xmlns")).map(([_,I])=>{if(I&&typeof I=="object"){let A=this.buildExtensionContent(I);return`<${_}>${A}</${_}>`}else if(I!=null)return`<${_}>${this.escapeXML(String(I))}</${_}>`;return""}).filter(_=>_).join("")}formatTime(t){let _=it(t);if(!_.isValid())throw new Error(`Cannot encode invalid TCX timestamp: ${String(t)}`);return _.toISOString()}addOptionalElement(t,_,I,A){if(I!=null&&I!==""){let T=A?A(I):this.escapeXML(I);t.push(`<${_}>${T}</${_}>`)}}addOptionalNumericElement(t,_,I){I!=null&&!isNaN(I)&&t.push(`<${_}>${I}</${_}>`)}isValidCoordinate(t,_){return t!=null&&_!==void 0&&_!==null&&!isNaN(t)&&!isNaN(_)}formatCoordinate(t){return this.roundTo(t,6).toString()}roundTo(t,_){let I=Math.pow(10,_);return Math.round(t*I)/I}escapeXML(t){return t.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}escapeXMLAttribute(t){return typeof t!="string"?String(t||""):t.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(t){if(t===null||typeof t!="object")return t;if(t instanceof Date)return new Date(t.getTime());if(Array.isArray(t))return t.map(I=>this.deepClone(I));let _={};for(let I in t)Object.prototype.hasOwnProperty.call(t,I)&&(_[I]=this.deepClone(t[I]));return _}encoder(t){return this.encode(t)}};import ZI from"dayjs";var x=class extends q{convertPoints(t){return t.map(_=>this.convertPoint(_)).filter(_=>_!==void 0)}convertTime(t){if(!t)return;if(typeof t=="number")return t;let _=ZI(t);return _.isValid()?_.valueOf():void 0}},e=class{constructor(){this.version="1.0.0";this.priority=100}supports(t){return this.supportedTags.includes(t)}async initialize(t){t.metadata.set(`plugin:${this.name}:initialized`,!0)}async destroy(t){t.metadata.delete(`plugin:${this.name}:initialized`)}async validate(t){return!0}convertTimeToDate(t){return t?new Date(t):new Date}convertTimeToString(t){return this.convertTimeToDate(t).toISOString()}ensureValidCoordinates(t,_){return t>=-90&&t<=90&&_>=-180&&_<=180}round(t,_=6){let I=Math.pow(10,_);return Math.round(t*I)/I}};var rt={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"},mt=R=>R*(180/Math.pow(2,31)),ct=2147483647;function j(R,t=6){if(R==null)return;let _=typeof R=="number"?R:Number(R);if(!Number.isFinite(_)||_===ct)return;let I=mt(_),A=Math.pow(10,t);return Math.round(I*A)/A}import e_ from"dayjs";import{Profile as uI}from"@garmin/fitsdk";import x_ from"dayjs";import{getPreciseDistance as qI}from"geolib";var u=class{calculateRecordsAggMetrics(t){if(!t||t.length===0)return;let _={records:this.preprocessRecords(t)};for(let I=0;I<_.records.length;I++){let A=_.records[I];if(!(A.positionLat==null||A.positionLong==null||!Number.isFinite(A.positionLat)||!Number.isFinite(A.positionLong))){if(_.startPositionLat==null&&(_.startPositionLat=A.positionLat),_.startPositionLong==null&&(_.startPositionLong=A.positionLong),_.endPositionLat=A.positionLat,_.endPositionLong=A.positionLong,_.timestamp=A.timestamp,_?.startTime||(_.startTime=A.timestamp),_.endTime=A.timestamp,_.totalDistance=A.distance,_.totalElapsedTime=x_(A.timestamp).diff(x_(_.startTime),"second"),A?.speed&&(_.avgSpeed=_.avgSpeed?(_.avgSpeed+A.speed)/2:A.speed,_.maxSpeed=Math.max(_.maxSpeed||0,A.speed)),A?.heartRate&&(_.maxHeartRate=Math.max(_.maxHeartRate||0,A.heartRate),_.minHeartRate=Math.min(_.minHeartRate||A.heartRate,A.heartRate),_.avgHeartRate?_.avgHeartRate=(_.avgHeartRate+A.heartRate)/2:_.avgHeartRate=A.heartRate),A?.altitude&&(_.maxAltitude=Math.max(_.maxAltitude||0,A.altitude),_.minAltitude=Math.min(_.minAltitude||A.altitude,A.altitude),_.avgAltitude=_.avgAltitude?(_.avgAltitude+A.altitude)/2:A.altitude,I>0&&t[I-1].altitude)){let T=this.calculateElevationChanges(t[I-1],A);_.totalAscent=(_.totalAscent||0)+T.ascent,_.totalDescent=(_.totalDescent||0)+T.descent}if(A?.cadence&&(_.maxCadence=Math.max(_.maxCadence||0,A.cadence),_.avgCadence?_.avgCadence=(_.avgCadence+A.cadence)/2:_.avgCadence=A.cadence),A?.power){_.maxPower=Math.max(_.maxPower||0,A.power),_.avgPower?_.avgPower=(_.avgPower+A.power)/2:_.avgPower=A.power;let T=this.calculateAccumulatedPower(I>0?t[I-1]:A,A,_.totalWork||0);_.totalWork=T.newAccumulatedWork,_.normalizedPower=void 0}A?.temperature&&(_.avgTemperature?_.avgTemperature=(_.avgTemperature+A.temperature)/2:_.avgTemperature=A.temperature,_.maxTemperature=Math.max(_.maxTemperature||0,A.temperature),_.minTemperature=Math.min(_.minTemperature||A.temperature,A.temperature))}}return _}calculateLapAggMetrics(t){if(!t||t.length===0)return;let _={laps:t,timestamp:t[0]?.timestamp||new Date};for(let I=0;I<t.length;I++){let A=t[I];A.startPositionLat&&A.startPositionLong&&!_?.startPositionLat&&!_?.startPositionLong&&(_.startPositionLat=A.startPositionLat,_.startPositionLong=A.startPositionLong),A.endPositionLat&&A.endPositionLong&&(_.endPositionLat=A.endPositionLat,_.endPositionLong=A.endPositionLong),A.startTime&&!_?.startTime&&(_.startTime=A.startTime),A.endTime&&(_.endTime=A.endTime),_.timestamp=A.timestamp||A.endTime||_.timestamp,A.totalDistance&&(_.totalDistance=(_.totalDistance||0)+A.totalDistance),A.totalElapsedTime&&(_.totalElapsedTime=(_.totalElapsedTime||0)+A.totalElapsedTime),A.totalMovingTime&&(_.totalMovingTime=(_.totalMovingTime||0)+A.totalMovingTime),A.totalTimerTime&&(_.totalTimerTime=(_.totalTimerTime||0)+A.totalTimerTime),A.maxSpeed&&(_.maxSpeed=Math.max(_.maxSpeed||0,A.maxSpeed)),A.avgSpeed&&(_.avgSpeed?_.avgSpeed=(_.avgSpeed+A.avgSpeed)/2:_.avgSpeed=A.avgSpeed),A.maxHeartRate&&(_.maxHeartRate=Math.max(_.maxHeartRate||0,A.maxHeartRate)),A.minHeartRate&&(_.minHeartRate=_.minHeartRate?Math.min(_.minHeartRate,A.minHeartRate):A.minHeartRate),A.avgHeartRate&&(_.avgHeartRate?_.avgHeartRate=(_.avgHeartRate+A.avgHeartRate)/2:_.avgHeartRate=A.avgHeartRate),A.maxAltitude&&(_.maxAltitude=Math.max(_.maxAltitude||0,A.maxAltitude)),A.minAltitude&&(_.minAltitude=_.minAltitude?Math.min(_.minAltitude,A.minAltitude):A.minAltitude),A.avgAltitude&&(_.avgAltitude?_.avgAltitude=(_.avgAltitude+A.avgAltitude)/2:_.avgAltitude=A.avgAltitude),A.totalAscent&&(_.totalAscent=(_.totalAscent||0)+A.totalAscent),A.totalDescent&&(_.totalDescent=(_.totalDescent||0)+A.totalDescent),A.maxCadence&&(_.maxCadence=Math.max(_.maxCadence||0,A.maxCadence)),A.avgCadence&&(_.avgCadence?_.avgCadence=(_.avgCadence+A.avgCadence)/2:_.avgCadence=A.avgCadence),A.maxPower&&(_.maxPower=Math.max(_.maxPower||0,A.maxPower)),A.avgPower&&(_.avgPower?_.avgPower=(_.avgPower+A.avgPower)/2:_.avgPower=A.avgPower),A.totalWork&&(_.totalWork=(_.totalWork||0)+A.totalWork),A.maxTemperature&&(_.maxTemperature=Math.max(_.maxTemperature||0,A.maxTemperature)),A.minTemperature&&(_.minTemperature=_.minTemperature?Math.min(_.minTemperature,A.minTemperature):A.minTemperature),A.avgTemperature&&(_.avgTemperature?_.avgTemperature=(_.avgTemperature+A.avgTemperature)/2:_.avgTemperature=A.avgTemperature)}return _}preprocessRecords(t){if(!t||t.length===0)return t;let _=t.filter(n=>n.timestamp).sort((n,L)=>n.timestamp.valueOf()-L.timestamp.valueOf()),I=0,A=0,T=[];for(let n=0;n<_.length;n++){let L=_[n],E={...L};if(n>0){let C=this.calculatePointDistanceByPosition(_[n-1],E)||0;if(E.distance||(A+=C,E.distance=A),L.speed||(E.speed=this.calculateInstantSpeed(_[n-1],E,C)),L.power){let U=this.calculateAccumulatedPower(_[n-1],E,I);E.accumulatedPower=U.accumulatedPower,I=U.newAccumulatedWork}}T.push(E)}return T}calculatePointDistanceByPosition(t,_){if(!(t.positionLat==null||t.positionLong==null||_.positionLat==null||_.positionLong==null||!Number.isFinite(t.positionLat)||!Number.isFinite(t.positionLong)||!Number.isFinite(_.positionLat)||!Number.isFinite(_.positionLong)))try{return qI({latitude:t.positionLat,longitude:t.positionLong},{latitude:_.positionLat,longitude:_.positionLong})}catch{return}}calculateInstantSpeed(t,_,I){if(!t.timestamp||!_.timestamp||!I)return;let A=(x_(_.timestamp).valueOf()-x_(t.timestamp).valueOf())/1e3;if(!(A<=0))return I/A}calculateAccumulatedPower(t,_,I){if(t.power===void 0||_.power===void 0||!t.timestamp||!_.timestamp)return{accumulatedPower:I,newAccumulatedWork:I};let A=_.timestamp?.valueOf()-t.timestamp?.valueOf();if(A<=0)return{accumulatedPower:I,newAccumulatedWork:I};let n=(t.power+_.power)/2*A,L=I+n;return{accumulatedPower:L,newAccumulatedWork:L}}calculateElevationChanges(t,_){let I=0,A=0;return _.altitude!==void 0&&t.altitude!==void 0&&(_.altitude>t.altitude?I=_.altitude-t.altitude:_.altitude<=t.altitude&&(A=t.altitude-_.altitude)),{ascent:I,descent:A}}};var _t=class extends x{constructor(){super(...arguments);this.name="gpx-to-activity-converter";this.supportedTags=["gpx"];this.convertGPXExtensions=_=>{let I={};return Object.entries(_).forEach(([A,T])=>{if(typeof T<"u"&&T!=="undefined"){let n=rt[A]||A;I[n]=this.autoNumber(T)}}),I}}convert(_,I){if(I.sourceFormat!=="gpx")return;let A=I.sourceData;return this.convertGPX(A)}convertGPX(_){let I={metadata:{originType:"GPX",fileType:"gpx"},activities:[]};return _.wpt&&(I.points=this.convertWpts2Points(_.wpt)),_.trk&&(I.activities=_.trk.map((A,T)=>this.convertTrk2Activity(A,T))),_.rte&&(I.routes=_.rte.map((A,T)=>this.convertRoute2Lap(A,T))),I}convertPoint(_,I,A){let{extensions:T}=_,n=T?this.convertGPXExtensions(T):{};return{lapIndex:A||0,index:I||0,positionLat:_?.lat,positionLong:_?.lon,altitude:_?.ele,heartRate:_?.heartRate,speed:_?.speed,power:_?.power,cadence:_?.cadence,course:_?.course,magvar:_?.magvar,geoidheight:_?.geoidheight,pointName:_?.name,comment:_?.cmt,description:_?.desc,source:_?.src,links:_?.link,symbol:_?.sym,pointType:_?.type,fix:_?.fix,sat:_?.sat,hdop:_?.hdop,vdop:_?.vdop,pdop:_?.pdop,ageofdgpsdata:_?.ageofdgpsdata,dgpsid:_?.dgpsid,gpxExtensions:_?.extensions,timestamp:_.time?e_(_.time).toDate():void 0,...n}}convertTrk2Activity(_,I){let A=_.trkseg?.map((n,L)=>this.convertTrackSeg2Lap(n,L))||[],T=new u().calculateLapAggMetrics(A);return{index:I,messageIndex:I,activityName:_.name,comment:_.cmt,description:_.desc,source:_.src,links:_.link,activityNumber:_.number,sport:_.type,gpxExtensions:_.extensions,laps:A,...T}}convertTrackSeg2Lap(_,I){return{...this.convertPoints2Lap(_.trkpt??[],I),gpxExtensions:_.extensions}}convertRoute2Lap(_,I){return{...this.convertPoints2Lap(_.rtept??[],I,_.name),comment:_.cmt,description:_.desc,source:_.src,links:_.link,routeNumber:_.number,routeType:_.type,gpxExtensions:_.extensions}}convertPoints2Lap(_,I,A){let T=_.map((U,F)=>this.convertPoint(U,F,I)),L=new u().calculateRecordsAggMetrics(T),E=new Map((L?.records??[]).map(U=>[U.index,U])),C=T.map(U=>E.get(U.index)??U);return{index:I,messageIndex:I,routeName:A,...L,records:C,lengths:[]}}convertWpts2Points(_){let I=[];for(let A=0;A<_.length;A++){let T=this.convertPoint(_[A],A);T&&I.push(T)}return I}autoNumber(_){return typeof _=="string"&&_.trim()!==""&&!isNaN(_)?Number(_):_}},tt=class extends x{constructor(){super(...arguments);this.name="fit-to-activity-converter";this.supportedTags=["fit"]}convert(_,I){if(I.sourceFormat!=="fit")return;let A=I.sourceData;return this.convertFIT(A)}convertFIT(_){let I={metadata:{originType:"FIT",fileType:"fit"},activities:[]};return _.sessionMesgs?.length?I.activities=_.sessionMesgs.map((A,T)=>({index:T,...A,startPositionLat:j(A?.startPositionLat),startPositionLong:j(A?.startPositionLong),endPositionLat:j(A?.endPositionLat),endPositionLong:j(A?.endPositionLong),laps:this.convertFITLap2Trackseg(A?.lapMesgs),strengthSets:this.convertFITStrengthSets(A?.setMesgs)})):_.courseMesgs?.length&&(I.routes=_.courseMesgs.map((A,T)=>({index:T,...A,records:this.convertLap2Points(A?.lapMesgs)}))),I}convertFITStrengthSets(_){return(_??[]).map((I,A)=>{let T=Array.isArray(I.category)?I.category:I.category==null?[]:[I.category],n=Array.isArray(I.categorySubtype)?I.categorySubtype:I.categorySubtype==null?[]:[I.categorySubtype],L=T.map((E,C)=>{let U=n[C],F=typeof U=="number"&&Number.isFinite(U)?U:void 0,p=`${String(E)}ExerciseName`,W=uI.types?.[p];return{category:E,...F===void 0?{}:{categorySubtype:F},...F===void 0||!W?.[F]?{}:{name:W[F]}}});return{...I,index:A,exercises:L}})}convertPoint(_,I,A){let{positionLong:T,positionLat:n,altitude:L,enhancedAltitude:E,enhancedSpeed:C,speed:U,...F}=_,V=n??_.position_lat,p=T??_.position_long;return{lapIndex:A||0,index:I||0,positionLat:j(V),positionLong:j(p),altitude:L,enhancedAltitude:E,speed:U,enhancedSpeed:C,...F}}convertFITLap2Trackseg(_){let I=[];if(!_?.length)return[];for(let A=0;A<_.length;A++){let T=_[A],n=T?.recordMesgs?.map((E,C)=>this.convertPoint(E,C,A)).filter(E=>E!==void 0)||[],L=T?.lengthMesgs?.map((E,C)=>({...E,index:C}))||[];I.push({index:A,...T,startPositionLat:j(T?.startPositionLat),startPositionLong:j(T?.startPositionLong),endPositionLat:j(T?.endPositionLat),endPositionLong:j(T?.endPositionLong),records:n,lengths:L})}return I}convertLap2Points(_){let I=[];if(!_?.length)return[];for(let A=0;A<_.length;A++){let n=_[A].recordMesgs?.map((L,E)=>this.convertPoint(L,E,A)).filter(L=>L!==void 0)||[];n.length&&(I=[...I,...n])}return I}},It=class extends x{constructor(){super(...arguments);this.name="tcx-to-activity-converter";this.supportedTags=["tcx"]}convert(_,I){if(I.sourceFormat!=="tcx")return;let A=I.sourceData;return this.convertTCX(A)}convertTCX(_){let I={metadata:{originType:"TCX",fileType:"tcx"},activities:[]};_.Activities?.Activity?.length&&(I.activities=_.Activities.Activity.map((n,L)=>this.convertTCXActivityToActivity(n,L)));let A=_.Courses?.Course,T=A==null?[]:Array.isArray(A)?A:[A];return T.length&&(I.routes=T.map((n,L)=>this.convertTCXCourseToRoute(n,L))),I}convertTCXCourseToRoute(_,I){let A=[],T=0,n=W=>W==null?[]:Array.isArray(W)?W:[W],L=W=>{for(let J of W??[])for(let Y of J.Trackpoint??[])Y==null||Y.Time===void 0||A.push(this.convertPoint(Y,T++,I))};L(n(_.Track));let E=_.Lap==null?[]:Array.isArray(_.Lap)?_.Lap:[_.Lap];for(let W of E)L(n(W.Track));let C=A.length,U=A[0]?.timestamp!=null?e_(A[0].timestamp):e_("2000-01-01T00:00:00Z"),F=_.CoursePoint==null?[]:Array.isArray(_.CoursePoint)?_.CoursePoint:[_.CoursePoint];for(let W of F){let J=this.convertTCXCoursePointToRecord(W,C++,I,U);J&&A.push(J)}let V=new u,p=A.length>0?V.calculateRecordsAggMetrics(A):{records:A};return{index:I,messageIndex:I,routeName:_.Name,...p,records:p?.records??A,lengths:[]}}convertTCXCoursePointToRecord(_,I,A,T){let n=_.Position?.LatitudeDegrees?Number(_.Position.LatitudeDegrees):void 0,L=_.Position?.LongitudeDegrees?Number(_.Position.LongitudeDegrees):void 0;if(n==null&&L==null&&_.AltitudeMeters==null)return;let E=typeof _.Time=="number"&&Number.isFinite(_.Time)?T.add(_.Time,"second").toDate():T.add(I,"second").toDate();return{lapIndex:A,index:I,positionLat:n,positionLong:L,altitude:_.AltitudeMeters,timestamp:E}}convertTCXActivityToActivity(_,I){let A=_.Lap?.map((n,L)=>this.convertTCXLap2Lap(n,L))||[],T=new u().calculateLapAggMetrics(A);return{index:I,messageIndex:I,sport:_.Sport?.toLowerCase(),laps:A,...T}}convertTCXLap2Lap(_,I){let T=(_?.Track?.flatMap(E=>E.Trackpoint)||[])?.filter(E=>E!==void 0&&E.Time!==void 0).map((E,C)=>this.convertPoint(E,C))||[],L=new u().calculateRecordsAggMetrics(T);return{index:I,messageIndex:I,...L,records:L?.records||[],lengths:[]}}convertPoint(_,I,A){let{Position:T,Time:n,DistanceMeters:L,AltitudeMeters:E}=_;return{lapIndex:A||0,index:I||0,positionLat:T?.LatitudeDegrees?Number(T.LatitudeDegrees):void 0,positionLong:T?.LongitudeDegrees?Number(T.LongitudeDegrees):void 0,timestamp:e_(n).toDate(),distance:L,altitude:E}}};import iI from"dayjs";var At=class extends e{constructor(){super(...arguments);this.name="activity-to-gpx-encoder";this.supportedTags=["gpx"]}encode(_,I){if(I.targetFormat!=="gpx"||!_?.activities?.length&&!_?.routes?.length&&!_?.points?.length)return;let A=_.activities?.[0]?.timestamp??_.routes?.[0]?.records?.[0]?.timestamp??_.points?.[0]?.timestamp??new Date,T=this.countRecordsMissingGpxCoordinates(_),n={version:"1.1",creator:"TrackSwap",metadata:{time:A,...T>0?{desc:`TrackSwap: omitted ${T} trackpoint(s) without valid latitude/longitude.`}:{}}};return _.points?.length&&(n.wpt=this.convertRecords2Wpts(_.points)),_.routes?.length&&(n.rte=_.routes.map(L=>this.convertRoute2GPXRoute(L))),_.activities?.length&&(n.trk=_.activities.map(L=>this.convertActivity2GPXTrack(L))),n}hasValidGpxCoordinates(_){let I=_.positionLat,A=_.positionLong;return typeof I=="number"&&typeof A=="number"&&Number.isFinite(I)&&Number.isFinite(A)&&I>=-90&&I<=90&&A>=-180&&A<=180}countRecordsMissingGpxCoordinates(_){let I=0,A=T=>{for(let n of T??[])this.hasValidGpxCoordinates(n)||I++};A(_.points);for(let T of _.activities??[])for(let n of T.laps??[])A(n.records);for(let T of _.routes??[])A(T.records);return I}convertRecords2Wpts(_){return _?.filter(I=>this.hasValidGpxCoordinates(I)).map(I=>({lat:I?.positionLat,lon:I?.positionLong,ele:I?.altitude,time:I?.timestamp,speed:I?.speed,course:I?.course,magvar:I?.magvar,geoidheight:I?.geoidheight,name:I?.pointName,cmt:I?.comment,desc:I?.description,src:I?.source,link:I?.links,sym:I?.symbol,type:I?.pointType,fix:I?.fix,sat:I?.sat,hdop:I?.hdop,vdop:I?.vdop,pdop:I?.pdop,ageofdgpsdata:I?.ageofdgpsdata,dgpsid:I?.dgpsid,extensions:this.extractGPXExtensions(I)}))??[]}convertRoute2GPXRoute(_){return{name:_.routeName,cmt:_.comment,desc:_.description,src:_.source,link:_.links,number:_.routeNumber,type:_.routeType,extensions:_.gpxExtensions,rtept:_.records?this.convertRecords2Wpts(_.records):[]}}convertActivity2GPXTrack(_){return{name:_.activityName,cmt:_.comment,desc:_.description,src:_.source,link:_.links,number:_.activityNumber,type:_.sport,extensions:_.gpxExtensions,trkseg:_.laps?.map(I=>({trkpt:I.records?this.convertRecords2Wpts(I.records):[],extensions:I.gpxExtensions}))||[]}}extractGPXExtensions(_){let I={..._.gpxExtensions??{}},A={...I["gpxtpx:TrackPointExtension"]??{}};return typeof _?.heartRate<"u"&&(A["gpxtpx:hr"]=_.heartRate),typeof _?.cadence<"u"&&(A["gpxtpx:cad"]=_.cadence),typeof _?.speed<"u"&&(A["gpxtpx:speed"]=_.speed),typeof _?.temperature<"u"&&(A["gpxtpx:atemp"]=_.temperature),Object.keys(A).length>0&&(I["gpxtpx:TrackPointExtension"]=A),typeof _?.power<"u"&&(I["gpxpx:PowerExtension"]={"gpxpx:PowerInWatts":_.power}),Object.keys(I).length>0?I:void 0}},Tt=class extends e{constructor(){super(...arguments);this.name="activity-to-fit-encoder";this.supportedTags=["fit"]}encode(_,I){if(I.targetFormat==="fit"){if(_?.activities?.length){let A={};return A.sessionMesgs=_.activities.map(T=>this.convertActivity2FITSession(T)),A}if(_?.routes?.length){let A={};return A.sessionMesgs=[this.convertRoutesToSyntheticSession(_.routes)],A}}}convertRoutesToSyntheticSession(_){let I=_.map(C=>this.convertLap2FITLap(C)),T=_.flatMap(C=>C.records??[]).filter(C=>C.timestamp!=null).sort((C,U)=>new Date(C.timestamp).getTime()-new Date(U.timestamp).getTime()),n=T[0]?.timestamp??new Date,L=T[T.length-1]?.timestamp??n,E=T.find(C=>C.positionLat!=null&&C.positionLong!=null&&Number.isFinite(C.positionLat)&&Number.isFinite(C.positionLong));return{messageIndex:0,timestamp:L,event:"session",eventType:"stop",startTime:n,startPositionLat:E?.positionLat,startPositionLong:E?.positionLong,sport:"generic",subSport:"generic",lapMesgs:I}}convertActivity2FITSession(_){return{..._,event:_?.event||"session",sport:_?.sport||"generic",lapMesgs:_.laps?.map(A=>this.convertLap2FITLap(A))||[]}}convertLap2FITLap(_){return{startTime:_.startTime,..._,recordMesgs:_.records?.map(A=>this.convertPoint2FITRecord(A))||[]}}convertPoint2FITRecord(_){return _}},nt=class extends e{constructor(){super(...arguments);this.name="sport-to-tcx-encoder";this.supportedTags=["tcx"]}encode(_,I){if(I.targetFormat!=="tcx")return;let A=!!_?.activities?.length,T=!!_?.routes?.length;if(!A&&!T)return;let n={version:"1.0",Author:{Name:"TrackSwap"}};return A&&(n.Activities={Activity:_.activities.map(L=>this.convertActivity2TCXActivity(L))}),T&&(n.Courses={Course:_.routes.map((L,E)=>this.convertRouteToTCXCourse(L,E))}),n}convertActivity2TCXActivity(_){if(!_.laps?.length)throw new Error("Cannot encode a TCX activity without laps");let I="Other",A=_.sport?.toLowerCase();return A==="running"&&(I="Running"),(A==="biking"||A==="cycling")&&(I="Biking"),{Id:this.validTimestamp(_.startTime??_.laps[0]?.startTime??_.laps[0]?.records?.[0]?.timestamp),Sport:I,Lap:_.laps.map(n=>this.convertLap2TCXLap(n))}}convertLap2TCXLap(_){let A={StartTime:this.validTimestamp(_.startTime??_.records?.[0]?.timestamp),TotalTimeSeconds:_.totalElapsedTime,DistanceMeters:_.totalDistance,MaximumSpeed:_.maxSpeed,Calories:_.totalCalories,AverageHeartRateBpm:_.avgHeartRate,MaximumHeartRateBpm:_.maxHeartRate,Intensity:"Active",TriggerMethod:"Manual",Track:_.records?[this.convertRecords2TCXTrack(_.records)]:[]};return(_.avgCadence!==void 0||_.maxCadence!==void 0)&&(A.Cadence={Low:_.avgCadence||0,High:_.maxCadence||0}),A}convertRecords2TCXTrack(_){return{Trackpoint:_.map(I=>this.convertPoint2TCXTrackpoint(I))}}convertPoint2TCXTrackpoint(_){let I={Time:this.validTimestamp(_.timestamp),Position:{LatitudeDegrees:_?.positionLat?.toString(),LongitudeDegrees:_?.positionLong?.toString()},AltitudeMeters:_.altitude,DistanceMeters:_.distance};return _.heartRate&&(I.HeartRateBpm=_.heartRate),_.cadence&&(I.Cadence={Low:_.cadence,High:_.cadence256||_.cadence}),_.power&&(I.Extensions={"ns3:TPX":{"ns3:Watts":_.power}}),I}validTimestamp(_){let I=iI(_);if(!_||!I.isValid())throw new Error("Cannot encode TCX data without valid timestamps");return I.toISOString()}convertRouteToTCXCourse(_,I){return{Name:_.routeName??`Course_${I}`,Track:_.records?[this.convertRecords2TCXTrack(_.records)]:[]}}};var Rt=class{constructor(){this.converters=new Map;this.encoders=new Map;this.registerDefaultConverters(),this.registerDefaultEncoders()}registerDefaultConverters(){this.registerConverter(new _t),this.registerConverter(new tt),this.registerConverter(new It)}registerDefaultEncoders(){this.registerEncoder(new At),this.registerEncoder(new Tt),this.registerEncoder(new nt)}registerConverter(t){this.converters.set(t.name,t)}registerEncoder(t){this.encoders.set(t.name,t)}async convertToActivity(t,_){let I={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},sourceFormat:_,sourceData:t,performance:{startTime:Date.now()}};try{let A=this.findConverter(_);if(!A)throw new Error(`No converter found for format "${_}"`);let T=Date.now(),n=A.convert(t,I);if(I.performance.convertTime=Date.now()-T,!n)throw new Error(`Converter "${A.name}" returned empty result`);let L=n;return I.result=L,I.performance.endTime=Date.now(),I.stats.endTime=Date.now(),L}catch(A){throw I.errors.push(A),A}}async encodeActivity(t,_){let I={metadata:new Map,errors:[],warnings:[],stats:{startTime:Date.now(),processedTokens:0,convertedElements:0},targetFormat:_,performance:{startTime:Date.now()}};try{let A=this.findEncoder(_);if(!A)throw new Error(`No encoder found for format "${_}"`);let T=Date.now(),n=A.encode(t,I);if(I.performance.encodeTime=Date.now()-T,!n)throw new Error(`Encoder "${A.name}" returned empty result`);return I.result=n,I.performance.endTime=Date.now(),I.stats.endTime=Date.now(),n}catch(A){throw I.errors.push(A),A}}findConverter(t){return Array.from(this.converters.values()).find(_=>_.supportedTags?.includes(t))}findEncoder(t){return Array.from(this.encoders.values()).find(_=>_.supportedTags?.includes(t))}async destroy(){this.converters.clear(),this.encoders.clear()}};var at=8,rI=".FIT";function mI(R){return(R?.activities??[]).reduce((t,_)=>t+(_.laps??[]).reduce((I,A)=>I+(A.records?.length??0),0),0)}function cI(R,t){let _=R.recordMesgs?.length??0,I=mI(t);if(_!==I)throw new k("FIT_ACTIVITY_DATA_LOSS",`FIT activity record count mismatch: decoded ${_}, canonicalized ${I}`,{format:"fit"})}function aI(R){return R.toString("utf8",0,Math.min(R.length,4096)).replace(/^\uFEFF/,"")}function xI(R){if(R.length>=12&&R.toString("ascii",at,at+4)===rI)return"fit";let t=aI(R);if(/<gpx\b/i.test(t))return"gpx";if(/<TrainingCenterDatabase\b/i.test(t))return"tcx"}var __=class{constructor(t){this.activities=t}matches(t){return xI(t)===this.format}},lt=class extends __{constructor(){super(...arguments);this.format="fit"}getDecoder(){return this.decoder??=new f_}getEncoder(){return this.encoder??=new U_}async decode(_,I){let A=await this.getDecoder().parseByBuffer(_,{userData:{fitDocumentOptions:I.fit??{}}});if(!A)throw new Error("FIT decoder returned an empty result");let T=A.fitDocumentMetadata?.detectedKinds??["unknown"],n=T.includes("activity")?await this.activities.convertToActivity(A,"fit"):void 0;T.includes("activity")&&cI(A,n);let L=A.healthDocument?.diagnostics??{parserVersion:n_,messageCounts:A.fitDocumentMetadata?.messageCounts??{},recognizedMessageCounts:{},unknownMessageCounts:{},invalidValueCounts:{},warningCounts:{},warnings:[]},E=A.fileIdMesgs?.[0],C=E,U=A.fileCreatorMesgs?.[0];return{kinds:[...T],facets:{activity:n,health:A.healthDocument},native:A,metadata:{fileType:E?.type,manufacturer:E?.manufacturer,product:E?.garminProduct??E?.product,productName:typeof C?.productName=="string"?C.productName:void 0,serialNumber:E?.serialNumber===void 0?void 0:String(E.serialNumber),createdAt:E?.timeCreated?new Date(E.timeCreated):void 0,softwareVersion:U?.softwareVersion},fitDiagnostics:L,warnings:L.warnings.map(F=>F.message)}}async encodeActivity(_){let I=await this.activities.encodeActivity(_,"fit");return this.getEncoder().encode(I)}async encodeCourse(_){return Buffer.from(yt($t(_)))}async dispose(){await this.decoder?.destroy()}},Wt=class extends __{constructor(){super(...arguments);this.format="gpx"}getDecoder(){return this.decoder??=new Y_}getEncoder(){return this.encoder??=new b_}async decode(_){let I=await this.getDecoder().parserByBuffer(_);if(!I)throw new Error("GPX decoder returned an empty result");let A=await this.activities.convertToActivity(I,"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:I,metadata:{title:I.metadata?.name,creator:I.creator,createdAt:I.metadata?.time}}}async encodeActivity(_){let I=await this.activities.encodeActivity(_,"gpx");return this.getEncoder().encode(I)}async dispose(){await this.decoder?.destroy()}},Mt=class extends __{constructor(){super(...arguments);this.format="tcx"}getDecoder(){return this.decoder??=new c_}getEncoder(){return this.encoder??=new a_}async decode(_){let I=await this.getDecoder().parseByBuffer(_);if(!I)throw new Error("TCX decoder returned an empty result");let A=await this.activities.convertToActivity(I,"tcx");return{kinds:A.activities?.length?["activity"]:A.routes?.length?["course"]:["unknown"],facets:{activity:A},native:I,metadata:{creator:I.Author?.Name??I.creator}}}async encodeActivity(_){let I=await this.activities.encodeActivity(_,"tcx");return this.getEncoder().encode(I)}async dispose(){await this.decoder?.destroy()}};function xt(){let R=new Rt;return{adapters:[new lt(R),new Wt(R),new Mt(R)],activities:R}}function et(R){return R.format==="fit"&&"encodeCourse"in R}var Lt=class{constructor(t){this.adapters=new Map;for(let _ of t){if(this.adapters.has(_.format))throw new k("ADAPTER_CONFLICT",`Multiple adapters registered for format "${_.format}"`,{format:_.format});this.adapters.set(_.format,_)}}get(t){let _=this.adapters.get(t);if(!_)throw new k("FORMAT_UNSUPPORTED",`No adapter registered for format "${t}"`,{format:t});return _}detect(t){for(let _ of this.adapters.values())if(_.matches(t))return _.format;throw new k("FORMAT_UNKNOWN","Unable to detect input format")}async dispose(){await Promise.all([...this.adapters.values()].map(t=>t.dispose?.()))}};function Bt(R){return typeof R=="string"?Buffer.from(R,"utf8"):Buffer.isBuffer(R)?R:Buffer.from(R.buffer,R.byteOffset,R.byteLength)}function eI(R){return typeof R=="string"||Buffer.isBuffer(R)||R instanceof Uint8Array}var Et=class{constructor(t={}){this.disposed=!1;let I=[...t.includeBuiltInAdapters===!1?[]:xt().adapters,...t.adapters??[]];this.registry=new Lt(I)}detect(t){return this.assertActive(),this.registry.detect(Bt(t))}async decode(t,_={}){this.assertActive();let I=Bt(t),A=_.format??this.registry.detect(I),T=this.registry.get(A),n=Date.now();try{let L=await T.decode(I,_);return{schemaVersion:"2",format:A,kinds:[...new Set(L.kinds)],source:{byteLength:I.byteLength},metadata:L.metadata??{},facets:L.facets,..._.includeNative?{native:L.native}:{},diagnostics:{durationMs:Date.now()-n,warnings:L.warnings??[],fit:L.fitDiagnostics}}}catch(L){throw t_(L,"DECODE_FAILED",`Failed to decode ${A.toUpperCase()}`,A)}}async decodeActivity(t,_={}){let I=await this.decode(t,_);if(!I.facets.activity)throw new k("ACTIVITY_NOT_FOUND",`The ${I.format.toUpperCase()} document has no activity facet`,{format:I.format});return I.facets.activity}async encodeActivity(t,_){this.assertActive();try{return await this.registry.get(_.format).encodeActivity(t)}catch(I){throw t_(I,"ENCODE_FAILED",`Failed to encode ${_.format.toUpperCase()}`,_.format)}}async transcode(t,_){this.assertActive();let I=Bt(t),A=_.sourceFormat??this.registry.detect(I);if(A===_.format)return Buffer.from(I);let T=await this.decodeActivity(I,{format:A});return this.encodeActivity(T,{format:_.format})}async encodeCourse(t,_={}){this.assertActive();let I=eI(t)?await this.decodeActivity(t,{format:_.sourceFormat}):t,A=this.registry.get("fit");if(!et(A))throw new k("FORMAT_UNSUPPORTED","The registered FIT adapter does not support course encoding",{format:"fit"});try{return await A.encodeCourse(I)}catch(T){throw t_(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 k("DISPOSED","TrackSwap instance is disposed")}};export{ct as FIT_SEMICIRCLE_INVALID_SINT32,n_ as TRACKSWAP_HEALTH_PARSER_VERSION,Et as TrackSwap,k as TrackSwapError,bt as buildHealthDocumentFromMessages,Et as default,Pt as detectFITKinds,j as normalizeFitSemicircleToDegrees,mt as semicirclesToDegrees};