incyclist-services 1.3.19 → 1.3.21

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.
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.IncyclistXMLParser = void 0;
13
+ const utils_1 = require("../../../utils");
13
14
  const gpx_1 = require("./gpx");
14
15
  const xml_1 = require("./xml");
15
16
  class IncyclistXMLParser extends xml_1.XMLParser {
@@ -49,16 +50,59 @@ class IncyclistXMLParser extends xml_1.XMLParser {
49
50
  route.points = gpx.details.points;
50
51
  });
51
52
  }
53
+ processCuts(data, route) {
54
+ const cuts = data['cuts'];
55
+ cuts === null || cuts === void 0 ? void 0 : cuts.forEach(cut => {
56
+ const timeStr = cut['time'];
57
+ const time = (0, utils_1.parseTime)(timeStr);
58
+ const cutInfo = { time, startFrame: cut['start-frame'], endFrame: cut['end-frame'] };
59
+ const mappings = route.video.mappings;
60
+ const points = route.points;
61
+ if (!mappings || !points)
62
+ return;
63
+ const mappingAtCutIdx = mappings.findIndex(p => p.time === cutInfo.time);
64
+ const mappingAtCut = mappings[mappingAtCutIdx];
65
+ const mappingBeforeCut = mappings[mappingAtCutIdx - 1];
66
+ const distanceToCut = points.map((p, index) => {
67
+ const distance = Math.abs(p.routeDistance - mappingAtCut.distance);
68
+ return { index, distance };
69
+ }).sort((a, b) => a.distance - b.distance);
70
+ const pointAtCut = points[distanceToCut[0].index];
71
+ const pointBeforeCut = points[distanceToCut[0].index - 1];
72
+ const v = mappingAtCut.videoSpeed / 3.6;
73
+ const t = mappingAtCut.time - mappingBeforeCut.time;
74
+ const distanceAtCutStart = pointAtCut.routeDistance - v * t;
75
+ const offset = distanceAtCutStart - pointBeforeCut.routeDistance;
76
+ pointAtCut.routeDistance -= offset;
77
+ pointAtCut.distance -= offset;
78
+ pointAtCut.isCut = true;
79
+ points.forEach((p, idx) => {
80
+ if (idx > distanceToCut[0].index) {
81
+ p.routeDistance -= offset;
82
+ }
83
+ });
84
+ mappingBeforeCut.videoSpeed = mappingAtCut.videoSpeed;
85
+ mappings.forEach((m, idx) => {
86
+ if (idx >= mappingAtCutIdx) {
87
+ m.distance -= Math.round(offset);
88
+ }
89
+ });
90
+ });
91
+ route.distance = route.points[route.points.length - 1].routeDistance;
92
+ }
52
93
  parseVideo(context) {
53
94
  const _super = Object.create(null, {
54
95
  parseVideo: { get: () => super.parseVideo }
55
96
  });
56
97
  return __awaiter(this, void 0, void 0, function* () {
57
98
  yield _super.parseVideo.call(this, context);
58
- const { route } = context;
99
+ const { data, route } = context;
59
100
  const points = route.points;
60
101
  route.video.mappings = points.map((p, idx) => {
61
102
  const time = p.time;
103
+ if (time > 1659) {
104
+ let i = 1;
105
+ }
62
106
  let videoSpeed;
63
107
  if (idx !== points.length - 1) {
64
108
  videoSpeed = (points[idx + 1].routeDistance - p.routeDistance) / (points[idx + 1].time - p.time) * 3.6;
@@ -66,11 +110,16 @@ class IncyclistXMLParser extends xml_1.XMLParser {
66
110
  else {
67
111
  videoSpeed = points[idx - 1].videoSpeed;
68
112
  }
113
+ if (p.distance > 500) {
114
+ }
69
115
  const distance = Math.round(p.routeDistance);
70
116
  const frame = Math.round(p.time * route.video.framerate);
71
117
  delete p.time;
72
118
  return { time, videoSpeed, distance, frame };
73
119
  });
120
+ if (data['cuts']) {
121
+ this.processCuts(data, route);
122
+ }
74
123
  });
75
124
  }
76
125
  }
@@ -8,3 +8,8 @@ export type Altitude = {
8
8
  distance?: string;
9
9
  height?: string;
10
10
  };
11
+ export type CutInfo = {
12
+ time: number;
13
+ startFrame?: number;
14
+ endFrame?: number;
15
+ };
@@ -1,4 +1,5 @@
1
1
  import { FileInfo } from "../../../api";
2
+ import { LatLng } from "../../../utils/geo";
2
3
  export type RouteType = 'gpx' | 'video';
3
4
  export type RouteCategory = 'Imported' | 'Free' | 'Demo' | 'personal';
4
5
  export type RouteState = 'prepared' | 'loading' | 'loaded' | 'error';
@@ -54,11 +55,9 @@ export type DaumEpp = {
54
55
  speedLimit: number;
55
56
  programData: Array<DaumEppProgramEntry>;
56
57
  };
57
- export type RoutePoint = {
58
+ export interface RoutePoint extends LatLng {
58
59
  cnt?: number;
59
60
  heading?: number;
60
- lat: number;
61
- lng: number;
62
61
  routeDistance: number;
63
62
  elevation: number;
64
63
  elevationGain?: number;
@@ -66,7 +65,8 @@ export type RoutePoint = {
66
65
  distance?: number;
67
66
  videoSpeed?: number;
68
67
  videoTime?: number;
69
- };
68
+ isCut?: boolean;
69
+ }
70
70
  export interface VideoRoutePoint extends RoutePoint {
71
71
  videoSpeed: number;
72
72
  videoTime: number;
@@ -1,2 +1,3 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ ;
@@ -85,6 +85,10 @@ class RouteDownloadService extends service_1.IncyclistService {
85
85
  return;
86
86
  }
87
87
  const info = path.parse(url);
88
+ if (!info) {
89
+ this.logEvent({ message: 'no URL specified', description: route.description });
90
+ observer.emit('error', new Error('no URL specified'));
91
+ }
88
92
  const file = path.join(targetDir, info.base);
89
93
  const session = downloadManager.createSession(url, file);
90
94
  observer.setSession(session);
@@ -100,7 +104,7 @@ class RouteDownloadService extends service_1.IncyclistService {
100
104
  session.start();
101
105
  }
102
106
  catch (err) {
103
- this.logError(err, 'downloadRoute', url);
107
+ this.logError(err, 'downloadRoute', { url });
104
108
  observer.emit('error', err);
105
109
  }
106
110
  });
@@ -151,7 +151,7 @@ class UserSettingsService {
151
151
  }
152
152
  updateSettings(data) {
153
153
  return __awaiter(this, void 0, void 0, function* () {
154
- if (!this.isInitialized)
154
+ if (!this.isInitialized || !this.settings)
155
155
  throw new Error('Settings are not yet initialized');
156
156
  try {
157
157
  (0, merge_1.merge)(this.settings, data);
@@ -12,3 +12,4 @@ export declare const getPointBetween: (p1: LatLng, p2: LatLng, offset: number) =
12
12
  export declare const getPointAfter: (p1: LatLng, p2: LatLng, offset: number) => LatLng;
13
13
  export declare const getLatLng: (position: LatLng | Array<number>) => LatLng;
14
14
  export declare const calculateHeaderFromPoints: (p1: LatLng, p2: LatLng) => number;
15
+ export declare function crossing(AB: any, CD: any, AC: any): any;
package/lib/utils/geo.js CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateHeaderFromPoints = exports.getLatLng = exports.getPointAfter = exports.getPointBetween = exports.distanceBetween = exports.calculateDistance = void 0;
3
+ exports.crossing = exports.calculateHeaderFromPoints = exports.getLatLng = exports.getPointAfter = exports.getPointBetween = exports.distanceBetween = exports.calculateDistance = void 0;
4
4
  const math_1 = require("./math");
5
+ const vector_1 = require("./vector");
5
6
  const rEarth = 6378.100;
6
7
  const calculateDistance = (lat1, lon1, lat2, lon2, radius = rEarth * 1000) => {
7
8
  const R = radius;
@@ -72,3 +73,58 @@ const calculateHeaderFromPoints = (p1, p2) => {
72
73
  }
73
74
  };
74
75
  exports.calculateHeaderFromPoints = calculateHeaderFromPoints;
76
+ function crossing(AB, CD, AC) {
77
+ if (AB === undefined || (!vector_1.Vector.isVector(AB) && !Array.isArray(AB)))
78
+ throw new Error('AB is not a vector');
79
+ if (CD === undefined || (!vector_1.Vector.isVector(CD) && !Array.isArray(CD)))
80
+ throw new Error('CD is not a vector');
81
+ if (AC === undefined || (!vector_1.Vector.isVector(AC) && !Array.isArray(AC)))
82
+ throw new Error('AC is not a vector');
83
+ if (AB.isParallel(CD)) {
84
+ if (!AB.isParallel(AC))
85
+ return undefined;
86
+ if (AB.isSameDirection(CD)) {
87
+ if (AB.isSameDirection(AC) && AB.len() >= AC.len())
88
+ return AC;
89
+ else
90
+ return undefined;
91
+ }
92
+ let AD = vector_1.Vector.add(AC, CD);
93
+ if (AB.isParallel(AD) && AB.len() >= AD.len()) {
94
+ let da = AD.len();
95
+ let dc = da - CD.len();
96
+ if (dc >= 0)
97
+ return AD;
98
+ else
99
+ return new vector_1.Vector([0, 0]);
100
+ }
101
+ else {
102
+ return undefined;
103
+ }
104
+ }
105
+ else {
106
+ let x, y;
107
+ if ((0, math_1.abs)(AB.x) < 0.0001) {
108
+ y = AC.x / CD.x * -1;
109
+ x = (AC.y + CD.y * y) / AB.y;
110
+ return vector_1.Vector.multiply(x, AB);
111
+ }
112
+ if ((0, math_1.abs)(AB.y) < 0.0001) {
113
+ y = AC.y / CD.y * -1;
114
+ x = (AC.x + CD.x * y) / AB.x;
115
+ return vector_1.Vector.multiply(x, AB);
116
+ }
117
+ if ((0, math_1.abs)(CD.x) < 0.0001) {
118
+ x = AC.x / AB.x;
119
+ return vector_1.Vector.multiply(x, AB);
120
+ }
121
+ if ((0, math_1.abs)(CD.y) < 0.0001) {
122
+ x = AC.y / AB.y;
123
+ return vector_1.Vector.multiply(x, AB);
124
+ }
125
+ y = (AB.x * AC.y / AB.y - AC.x) / (CD.x - AB.x * CD.y / AB.y);
126
+ x = (AC.y + CD.y * y) / AB.y;
127
+ return vector_1.Vector.multiply(x, AB);
128
+ }
129
+ }
130
+ exports.crossing = crossing;
@@ -4,3 +4,5 @@ export * as math from './math';
4
4
  export * from './nextTick';
5
5
  export * from './formatting';
6
6
  export * from './xml';
7
+ export * from './vector';
8
+ export * from './time';
@@ -33,3 +33,5 @@ exports.math = __importStar(require("./math"));
33
33
  __exportStar(require("./nextTick"), exports);
34
34
  __exportStar(require("./formatting"), exports);
35
35
  __exportStar(require("./xml"), exports);
36
+ __exportStar(require("./vector"), exports);
37
+ __exportStar(require("./time"), exports);
@@ -4,6 +4,9 @@ exports.merge = void 0;
4
4
  function merge(base, data, depth = 0) {
5
5
  if (!base)
6
6
  return;
7
+ if (typeof (data) === 'object' && typeof (base) !== 'object') {
8
+ base = data;
9
+ }
7
10
  let key;
8
11
  for (key in data) {
9
12
  if (typeof (data[key]) === 'object' && depth < 4) {
@@ -0,0 +1 @@
1
+ export declare const parseTime: (time: any) => number;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseTime = void 0;
4
+ const parseTime = (time) => {
5
+ const parts = time.split(':');
6
+ const seconds = Number(parts[2]) + Number(parts[1]) * 60 + Number(parts[0]) * 3600;
7
+ return seconds;
8
+ };
9
+ exports.parseTime = parseTime;
@@ -0,0 +1,23 @@
1
+ export declare class Vector {
2
+ protected _class: string;
3
+ protected _x: number;
4
+ protected _y: number;
5
+ constructor(props: any);
6
+ get x(): number;
7
+ get y(): number;
8
+ eq(v: any): boolean;
9
+ equals(v: any): boolean;
10
+ isParallel(v: any): boolean;
11
+ isSameDirection(v: any): boolean;
12
+ add(v: any): this;
13
+ min(v: any): this;
14
+ multiply(v: any): number | this;
15
+ static add(v1: any, v2: any): Vector;
16
+ static min(v1: any, v2: any): Vector;
17
+ static multiply(v1: any, v2: any): any;
18
+ static eq(v1: any, v2: any): any;
19
+ static isParallel(v1: any, v2: any): any;
20
+ static isVector(v: any): boolean;
21
+ len(): number;
22
+ angle(): number;
23
+ }
@@ -0,0 +1,201 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Vector = void 0;
4
+ const math_1 = require("./math");
5
+ const CLASS_VECTOR = 'vector';
6
+ class Vector {
7
+ constructor(props) {
8
+ if (props === undefined) {
9
+ throw new Error("missing mandatory argument: props");
10
+ }
11
+ if (Array.isArray(props)) {
12
+ if (props.length < 2)
13
+ throw new Error("incorrect value of: props");
14
+ this._x = props[0];
15
+ this._y = props[1];
16
+ }
17
+ if (Vector.isVector(props)) {
18
+ this._x = props.x;
19
+ this._y = props.y;
20
+ }
21
+ if (props.coordinates) {
22
+ if (props.coordinates.x === undefined || props.coordinates.y === undefined)
23
+ throw new Error("incorrect value of: props.coordinates");
24
+ this._x = props.coordinates.x;
25
+ this._y = props.coordinates.y;
26
+ }
27
+ if (props.path) {
28
+ if (props.path.bearing === undefined || props.path.distance === undefined)
29
+ throw new Error("incorrect value of: props.path");
30
+ let d = props.path.distance;
31
+ let alpha = props.path.bearing;
32
+ this._x = d * (0, math_1.sin)(alpha);
33
+ this._y = d * (0, math_1.cos)(alpha);
34
+ }
35
+ this._class = CLASS_VECTOR;
36
+ }
37
+ get x() {
38
+ return this._x;
39
+ }
40
+ get y() {
41
+ return this._y;
42
+ }
43
+ eq(v) {
44
+ return this.equals(v);
45
+ }
46
+ equals(v) {
47
+ if (!Vector.isVector(v) && !Array.isArray(v))
48
+ return false;
49
+ if (Vector.isVector(v))
50
+ return (this._x === v.x && this._y === v.y);
51
+ else
52
+ return (this._x === v[0] && this._y === v[1]);
53
+ }
54
+ isParallel(v) {
55
+ if (!Vector.isVector(v) && !Array.isArray(v))
56
+ return false;
57
+ if (this.eq(v))
58
+ return true;
59
+ if (Vector.isVector(v)) {
60
+ if (this._x === 0 && v.x === 0)
61
+ return true;
62
+ if (this._y === 0 && v.y === 0)
63
+ return true;
64
+ return ((0, math_1.abs)(v.x / this._x - v.y / this._y) < 0.0001);
65
+ }
66
+ else {
67
+ if (v.length < 2)
68
+ return false;
69
+ if (this._x === 0 && v[0] === 0)
70
+ return true;
71
+ if (this._y === 0 && v[1] === 0)
72
+ return true;
73
+ return ((0, math_1.abs)(v[0] / this._x - v[1] / this._y) < 0.0001);
74
+ }
75
+ }
76
+ isSameDirection(v) {
77
+ if (!this.isParallel(v))
78
+ return false;
79
+ let v2 = v;
80
+ if (!Vector.isVector(v))
81
+ v2 = new Vector(v);
82
+ let bearer1 = this.angle();
83
+ let bearer2 = v2.angle();
84
+ return Math.sign(bearer1) === Math.sign(bearer2);
85
+ }
86
+ add(v) {
87
+ if (Array.isArray(v)) {
88
+ if (v.length > 0)
89
+ this._x = this._x + v[0];
90
+ if (v.length > 1)
91
+ this._y = this._y + v[1];
92
+ }
93
+ else if (Vector.isVector(v)) {
94
+ this._x = this._x + v.x;
95
+ this._y = this._y + v.y;
96
+ }
97
+ else {
98
+ throw new Error("invalid argument");
99
+ }
100
+ return this;
101
+ }
102
+ min(v) {
103
+ if (Array.isArray(v)) {
104
+ if (v.length > 0)
105
+ this._x = this._x - v[0];
106
+ if (v.length > 1)
107
+ this._y = this._y - v[1];
108
+ }
109
+ else if (Vector.isVector(v)) {
110
+ this._x = this._x - v.x;
111
+ this._y = this._y - v.y;
112
+ }
113
+ else {
114
+ throw new Error("invalid argument");
115
+ }
116
+ return this;
117
+ }
118
+ multiply(v) {
119
+ if (typeof v === 'number') {
120
+ this._x = v * this._x;
121
+ this._y = v * this._y;
122
+ }
123
+ else if (Array.isArray(v)) {
124
+ let res = 0;
125
+ if (v.length > 0)
126
+ res += (this._x * v[0]);
127
+ if (v.length > 1)
128
+ res += (this._y * v[1]);
129
+ return res;
130
+ }
131
+ else if (Vector.isVector(v)) {
132
+ return (this._x * v.x + this._y * v.y);
133
+ }
134
+ else {
135
+ throw new Error("invalid argument");
136
+ }
137
+ return this;
138
+ }
139
+ static add(v1, v2) {
140
+ let v = new Vector(v1);
141
+ v.add(v2);
142
+ return v;
143
+ }
144
+ static min(v1, v2) {
145
+ let v = new Vector(v1);
146
+ v.min(v2);
147
+ return v;
148
+ }
149
+ static multiply(v1, v2) {
150
+ if (typeof v1 === 'number') {
151
+ if (Vector.isVector(v2) || Array.isArray(v2)) {
152
+ let v = new Vector(v2);
153
+ return v.multiply(v1);
154
+ }
155
+ else {
156
+ throw new Error("invalid argument");
157
+ }
158
+ }
159
+ if (Vector.isVector(v1))
160
+ return v1.multiply(v2);
161
+ if (Array.isArray(v1)) {
162
+ let v = new Vector(v1);
163
+ return v.multiply(v2);
164
+ }
165
+ throw new Error("invalid argument");
166
+ }
167
+ static eq(v1, v2) {
168
+ if (v1 === undefined)
169
+ return false;
170
+ if (Vector.isVector(v1))
171
+ return v1.eq(v2);
172
+ if (Array.isArray(v1)) {
173
+ let v = new Vector(v1);
174
+ return v.eq(v2);
175
+ }
176
+ throw new Error("invalid argument");
177
+ }
178
+ static isParallel(v1, v2) {
179
+ if (v1 === undefined)
180
+ return false;
181
+ if (Vector.isVector(v1))
182
+ return v1.isParallel(v2);
183
+ if (Array.isArray(v1)) {
184
+ let v = new Vector(v1);
185
+ return v.isParallel(v2);
186
+ }
187
+ throw new Error("invalid argument");
188
+ }
189
+ static isVector(v) {
190
+ return (v !== undefined && typeof v === 'object' && v.x !== undefined && v.y !== undefined && v._class !== undefined && v._class === CLASS_VECTOR);
191
+ }
192
+ len() {
193
+ return Math.sqrt(this._x * this._x + this._y * this._y);
194
+ }
195
+ angle() {
196
+ if (this.len() === 0)
197
+ return undefined;
198
+ return (0, math_1.asin)(this._x / this.len());
199
+ }
200
+ }
201
+ exports.Vector = Vector;
@@ -2,6 +2,7 @@ export type JSONObject = string | number | boolean | {
2
2
  [x: string]: JSONObject;
3
3
  } | Array<JSONObject>;
4
4
  export declare const toXml: (obj: JSONObject) => string;
5
+ export declare const removeUTFBom: (str: string) => string;
5
6
  export declare const parseXml: (str: string) => Promise<XmlJSON>;
6
7
  export declare class XmlJSON {
7
8
  private _json;
package/lib/utils/xml.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.XmlJSON = exports.parseXml = exports.toXml = void 0;
12
+ exports.XmlJSON = exports.parseXml = exports.removeUTFBom = exports.toXml = void 0;
13
13
  const xml2js_1 = require("xml2js");
14
14
  const toXml = (obj) => {
15
15
  const keys = Object.keys(obj);
@@ -22,9 +22,16 @@ const toXml = (obj) => {
22
22
  return xml;
23
23
  };
24
24
  exports.toXml = toXml;
25
+ const removeUTFBom = (str) => {
26
+ while (str.charCodeAt(0) === 0 || str.charCodeAt(0) === 0xFEFF || str.charCodeAt(0) === 0xFFFD)
27
+ str = str.substring(1);
28
+ return str;
29
+ };
30
+ exports.removeUTFBom = removeUTFBom;
25
31
  const parseXml = (str) => __awaiter(void 0, void 0, void 0, function* () {
26
32
  return new Promise((resolve, reject) => {
27
- (0, xml2js_1.parseString)(str, (err, result) => {
33
+ const cleanStr = (0, exports.removeUTFBom)(str);
34
+ (0, xml2js_1.parseString)(cleanStr, (err, result) => {
28
35
  if (err) {
29
36
  return reject(err);
30
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.3.19",
3
+ "version": "1.3.21",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.26"
6
6
  },
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "axios": "^1.6.1",
46
- "incyclist-devices": "^2.2.3",
46
+ "incyclist-devices": "^2.2.4",
47
47
  "promise.any": "^2.0.6",
48
48
  "tcx-builder": "^1.1.1",
49
49
  "uuid": "^9.0.0",