signalk-racer 1.1.1 → 1.1.2
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/.claude/settings.local.json +11 -0
- package/README.md +38 -1
- package/ReleaseNotes.md +4 -0
- package/index.js +11 -8
- package/package.json +1 -1
- package/racer.js +45 -25
- package/tests/racer-maths.test.js +8 -7
- package/tests/racer-ttl.test.js +12 -9
- package/tests/racer-vmg.test.js +118 -114
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(npm test:*)",
|
|
5
|
+
"Bash(git -C /home/gregw/src/signalk-racer tag -l)",
|
|
6
|
+
"Bash(git -C /home/gregw/src/signalk-racer log --oneline -5)",
|
|
7
|
+
"Bash(git -C /home/gregw/src/signalk-racer status -sb)",
|
|
8
|
+
"Bash(git -C /home/gregw/src/signalk-racer remote -v)"
|
|
9
|
+
]
|
|
10
|
+
}
|
|
11
|
+
}
|
package/README.md
CHANGED
|
@@ -189,4 +189,41 @@ npm install
|
|
|
189
189
|
npm link
|
|
190
190
|
cd ~/.signalk
|
|
191
191
|
npm link signalk-racer
|
|
192
|
-
```
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
## 🚀 Releasing
|
|
196
|
+
|
|
197
|
+
Releases are cut manually from a clean `main` checkout and published to npm.
|
|
198
|
+
|
|
199
|
+
### Pre-flight
|
|
200
|
+
|
|
201
|
+
1. Confirm `main` is up to date and clean: `git checkout main && git pull && git status`.
|
|
202
|
+
2. Run the test suite: `npm test`.
|
|
203
|
+
3. Review commits since the last release: `git log $(git describe --tags --abbrev=0)..HEAD --oneline`.
|
|
204
|
+
4. Decide the version bump (semver): `patch` for bug fixes, `minor` for features, `major` for breaking changes.
|
|
205
|
+
|
|
206
|
+
### Cut the release
|
|
207
|
+
|
|
208
|
+
1. Update `ReleaseNotes.md` — add a new entry at the top with the new version and a short bullet list of changes, then `git add ReleaseNotes.md`.
|
|
209
|
+
2. Bump the version and create the git tag in one step (note the non-default tag prefix so it matches the existing `signalk-racer-X.Y.Z` convention):
|
|
210
|
+
```
|
|
211
|
+
npm version <patch|minor|major> --tag-version-prefix=signalk-racer-
|
|
212
|
+
```
|
|
213
|
+
This rewrites `package.json`, includes any staged files (e.g. `ReleaseNotes.md`) in the bump commit, and creates tag `signalk-racer-X.Y.Z`.
|
|
214
|
+
3. Push the commit and the tag:
|
|
215
|
+
```
|
|
216
|
+
git push origin main
|
|
217
|
+
git push origin signalk-racer-X.Y.Z
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Publish to npm
|
|
221
|
+
|
|
222
|
+
1. Confirm npm auth: `npm whoami` (login with `npm login` if needed).
|
|
223
|
+
2. Dry-run the publish to inspect the tarball contents: `npm publish --dry-run`.
|
|
224
|
+
3. Publish: `npm publish` (the package is public and unscoped; no `--access` flag needed).
|
|
225
|
+
|
|
226
|
+
### After release
|
|
227
|
+
|
|
228
|
+
1. Verify on npm: `npm view signalk-racer version` should report the new version.
|
|
229
|
+
2. (Optional) Create a GitHub release from the new tag with notes copied from `ReleaseNotes.md`.
|
package/ReleaseNotes.md
CHANGED
package/index.js
CHANGED
|
@@ -196,19 +196,22 @@ module.exports = (app) => {
|
|
|
196
196
|
});
|
|
197
197
|
|
|
198
198
|
// send multiple deltas, each in the form of { path, value }
|
|
199
|
+
// null values are preserved (meaningful in SignalK for clearing a value);
|
|
200
|
+
// undefined values are dropped to avoid "Delta is missing value" warnings.
|
|
199
201
|
function sendDeltas(updatesArray) {
|
|
200
|
-
const
|
|
202
|
+
const values = updatesArray
|
|
203
|
+
.filter(({value}) => value !== undefined)
|
|
204
|
+
.map(({path, value}) => ({path, value}));
|
|
205
|
+
|
|
206
|
+
if (values.length === 0) return;
|
|
201
207
|
|
|
202
208
|
const delta = {
|
|
203
209
|
context: 'vessels.self',
|
|
204
210
|
updates: [
|
|
205
211
|
{
|
|
206
212
|
source: {label: 'signalk-racer'},
|
|
207
|
-
timestamp:
|
|
208
|
-
values
|
|
209
|
-
path,
|
|
210
|
-
value
|
|
211
|
-
}))
|
|
213
|
+
timestamp: new Date().toISOString(),
|
|
214
|
+
values
|
|
212
215
|
}
|
|
213
216
|
]
|
|
214
217
|
};
|
|
@@ -812,8 +815,8 @@ module.exports = (app) => {
|
|
|
812
815
|
if (cog != null && sog != null) {
|
|
813
816
|
collectVmgSamples(cog, sog, startLine.bearing, toZoneVz, perpToLineVx);
|
|
814
817
|
}
|
|
815
|
-
const ttl = computeTimeToLine(cog, sog, startLine.bearing, toZoneVz, perpToLineVx, ocs, closestEnd);
|
|
816
|
-
const ttb = !ocs && state.timerRunning && state.timeToStart > 0 ? (state.timeToStart - ttl) : null;
|
|
818
|
+
const ttl = computeTimeToLine(cog, sog, startLine.bearing, toZoneVz, perpToLineVx, ocs, closestEnd, state.timeToStart ?? 0);
|
|
819
|
+
const ttb = !ocs && state.timerRunning && state.timeToStart > 0 && ttl != null ? (state.timeToStart - ttl) : null;
|
|
817
820
|
|
|
818
821
|
sendDeltas([
|
|
819
822
|
{path: 'navigation.racing.distanceStartline', value: distanceToLine},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "signalk-racer",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Signalk plugin to calculate values of interest to sail racers, such as: Time to Start; Time of Start, Time to Burn; Distance to Line; Next leg TWA.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"repository": {
|
package/racer.js
CHANGED
|
@@ -8,27 +8,31 @@ let cfg = {
|
|
|
8
8
|
percentile: 0.9
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
let log = {
|
|
11
|
+
let log = {
|
|
12
|
+
debug: () => {
|
|
13
|
+
}
|
|
14
|
+
};
|
|
12
15
|
|
|
13
16
|
function initRacer(config = {}, logger = null) {
|
|
14
|
-
cfg = {
|
|
17
|
+
cfg = {...cfg, ...config};
|
|
15
18
|
if (logger?.debug) log = logger;
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
// VMG sample state is kept private to this module.
|
|
19
|
-
//
|
|
22
|
+
// Each entry has a `sorted` array (ascending, for O(1) percentile) and a
|
|
23
|
+
// `queue` array (insertion-order FIFO, for correct oldest-first eviction).
|
|
20
24
|
const vmgState = {
|
|
21
|
-
vmgToLinePos: [], // VMG towards the line (not OCS to line)
|
|
22
|
-
vmgToLineNeg: [], // VMG away from the line (OCS to line)
|
|
23
|
-
vmgToZonePort: [], // Motion along the line towards the PORT end (pin)
|
|
24
|
-
vmgToZoneStb: [],
|
|
25
|
+
vmgToLinePos: {sorted: [], queue: []}, // VMG towards the line (not OCS to line)
|
|
26
|
+
vmgToLineNeg: {sorted: [], queue: []}, // VMG away from the line (OCS to line)
|
|
27
|
+
vmgToZonePort: {sorted: [], queue: []}, // Motion along the line towards the PORT end (pin)
|
|
28
|
+
vmgToZoneStb: {sorted: [], queue: []}, // Motion along the line towards the STARBOARD end (boat)
|
|
25
29
|
};
|
|
26
30
|
|
|
27
31
|
function resetVmgSamples() {
|
|
28
|
-
vmgState
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
for (const vmg of Object.values(vmgState)) {
|
|
33
|
+
vmg.sorted.length = 0;
|
|
34
|
+
vmg.queue.length = 0;
|
|
35
|
+
}
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
function toDegrees(rad) {
|
|
@@ -41,10 +45,10 @@ function toRadians(deg) {
|
|
|
41
45
|
return deg * (Math.PI / 180);
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
function percentile(
|
|
45
|
-
if (!
|
|
46
|
-
const idx = Math.floor(p * (
|
|
47
|
-
return
|
|
48
|
+
function percentile(vmg, p) {
|
|
49
|
+
if (!vmg.sorted.length) return 0;
|
|
50
|
+
const idx = Math.floor(p * (vmg.sorted.length - 1));
|
|
51
|
+
return vmg.sorted[idx];
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
function collectVmgSamples(cog, sog, lineBearing, toZoneVz, perpToLineVx) {
|
|
@@ -65,20 +69,36 @@ function collectVmgSamples(cog, sog, lineBearing, toZoneVz, perpToLineVx) {
|
|
|
65
69
|
insertSample(vmgState.vmgToZoneStb, -vmgTangent);
|
|
66
70
|
}
|
|
67
71
|
|
|
68
|
-
function insertSample(
|
|
69
|
-
if (value <= 1.0)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
function insertSample(vmg, value) {
|
|
73
|
+
if (value <= 1.0)
|
|
74
|
+
return; // reject low VMGs
|
|
75
|
+
if (vmg.queue.length >= cfg.maxSamples) {
|
|
76
|
+
const oldest = vmg.queue.shift(); // evict oldest from FIFO
|
|
77
|
+
// remove oldest from sorted (binary search)
|
|
78
|
+
let lo = 0, hi = vmg.sorted.length;
|
|
79
|
+
while (lo < hi) {
|
|
80
|
+
const mid = (lo + hi) >> 1;
|
|
81
|
+
if (vmg.sorted[mid] < oldest)
|
|
82
|
+
lo = mid + 1;
|
|
83
|
+
else
|
|
84
|
+
hi = mid;
|
|
85
|
+
}
|
|
86
|
+
vmg.sorted.splice(lo, 1);
|
|
87
|
+
}
|
|
88
|
+
// insert value into sorted (binary search)
|
|
89
|
+
let lo = 0, hi = vmg.sorted.length;
|
|
73
90
|
while (lo < hi) {
|
|
74
91
|
const mid = (lo + hi) >> 1;
|
|
75
|
-
if (
|
|
76
|
-
|
|
92
|
+
if (vmg.sorted[mid] < value)
|
|
93
|
+
lo = mid + 1;
|
|
94
|
+
else
|
|
95
|
+
hi = mid;
|
|
77
96
|
}
|
|
78
|
-
|
|
97
|
+
vmg.sorted.splice(lo, 0, value);
|
|
98
|
+
vmg.queue.push(value);
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
function computeTimeToLine(cog, sog, lineBearing, toZoneVz, perpToLineVx, ocs, closestEnd) {
|
|
101
|
+
function computeTimeToLine(cog, sog, lineBearing, toZoneVz, perpToLineVx, ocs, closestEnd, timeToStart = 0) {
|
|
82
102
|
let vmgNormalSigned = 0;
|
|
83
103
|
let vmgTangentSigned = 0;
|
|
84
104
|
|
|
@@ -146,7 +166,7 @@ function computeTimeToLine(cog, sog, lineBearing, toZoneVz, perpToLineVx, ocs, c
|
|
|
146
166
|
}
|
|
147
167
|
|
|
148
168
|
// If we still somehow have zero (no speed or distances), just return time to start so TTB logic doesn't explode.
|
|
149
|
-
return ttl <= 0 ?
|
|
169
|
+
return ttl <= 0 ? timeToStart : ttl;
|
|
150
170
|
}
|
|
151
171
|
|
|
152
172
|
module.exports = {
|
|
@@ -24,12 +24,13 @@ describe('racer math', () => {
|
|
|
24
24
|
expect(toRadians(undefined)).toBeNull();
|
|
25
25
|
});
|
|
26
26
|
test('percentile: test maths', () => {
|
|
27
|
-
|
|
28
|
-
expect(_percentile([
|
|
29
|
-
expect(_percentile([10
|
|
30
|
-
expect(_percentile([10, 20, 30], 0
|
|
31
|
-
expect(_percentile([10, 20, 30], 0.
|
|
32
|
-
expect(_percentile([10, 20, 30],
|
|
33
|
-
expect(_percentile([
|
|
27
|
+
const vmg = (arr) => ({ sorted: arr, queue: [] });
|
|
28
|
+
expect(_percentile(vmg([]), 0.5)).toBe(0);
|
|
29
|
+
expect(_percentile(vmg([10]), 0.5)).toBe(10);
|
|
30
|
+
expect(_percentile(vmg([10, 20, 30]), 0)).toBe(10);
|
|
31
|
+
expect(_percentile(vmg([10, 20, 30]), 0.5)).toBe(20);
|
|
32
|
+
expect(_percentile(vmg([10, 20, 30]), 0.9)).toBe(20);
|
|
33
|
+
expect(_percentile(vmg([10, 20, 30]), 1)).toBe(30);
|
|
34
|
+
expect(_percentile(vmg([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 0.75)).toBe(7);
|
|
34
35
|
})
|
|
35
36
|
});
|
package/tests/racer-ttl.test.js
CHANGED
|
@@ -14,15 +14,18 @@ describe('racer ttl', () => {
|
|
|
14
14
|
test('timeToLineNoVMG: no VMG', () => {
|
|
15
15
|
resetVmgSamples();
|
|
16
16
|
expect(computeTimeToLine(toRadians(0), 10, 270, 0, 100, false, 'stb')).toBeCloseTo(10);
|
|
17
|
-
|
|
17
|
+
// Fallback: ttl computed as 0, so returns the supplied timeToStart.
|
|
18
|
+
expect(computeTimeToLine(toRadians(0), 10, 270, 100, 0, false, 'stb', 300)).toBe(300);
|
|
19
|
+
// Default timeToStart parameter is 0.
|
|
20
|
+
expect(computeTimeToLine(toRadians(0), 10, 270, 100, 0, false, 'stb')).toBe(0);
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
test('timeToLineSmallVmg: small VMG', () => {
|
|
21
24
|
resetVmgSamples();
|
|
22
|
-
_vmgState.vmgToLinePos.push(1, 1, 1);
|
|
23
|
-
_vmgState.vmgToLineNeg.push(2, 2, 2);
|
|
24
|
-
_vmgState.vmgToZonePort.push(1, 1, 1);
|
|
25
|
-
_vmgState.vmgToZoneStb.push(2, 2, 2);
|
|
25
|
+
_vmgState.vmgToLinePos.sorted.push(1, 1, 1);
|
|
26
|
+
_vmgState.vmgToLineNeg.sorted.push(2, 2, 2);
|
|
27
|
+
_vmgState.vmgToZonePort.sorted.push(1, 1, 1);
|
|
28
|
+
_vmgState.vmgToZoneStb.sorted.push(2, 2, 2);
|
|
26
29
|
|
|
27
30
|
expect(computeTimeToLine(toRadians(-1), 10, 270, 0, 100, false, 'stb')).toBeCloseTo(10);
|
|
28
31
|
expect(computeTimeToLine(toRadians(0), 10, 270, 100, 0, false, 'stb')).toBeCloseTo(100);
|
|
@@ -59,10 +62,10 @@ describe('racer ttl', () => {
|
|
|
59
62
|
|
|
60
63
|
test('timeToLineSmallInstant: small instant', () => {
|
|
61
64
|
resetVmgSamples();
|
|
62
|
-
_vmgState.vmgToLinePos.push(10, 10, 10, 10, 10, 10, 10, 10, 10, 15);
|
|
63
|
-
_vmgState.vmgToLineNeg.push(20, 20, 20, 20, 20, 20, 20, 20, 20, 25);
|
|
64
|
-
_vmgState.vmgToZonePort.push(10, 10, 10, 10, 10, 10, 10, 10, 10, 15);
|
|
65
|
-
_vmgState.vmgToZoneStb.push(20, 20, 20, 20, 20, 20, 20, 20, 20, 25);
|
|
65
|
+
_vmgState.vmgToLinePos.sorted.push(10, 10, 10, 10, 10, 10, 10, 10, 10, 15);
|
|
66
|
+
_vmgState.vmgToLineNeg.sorted.push(20, 20, 20, 20, 20, 20, 20, 20, 20, 25);
|
|
67
|
+
_vmgState.vmgToZonePort.sorted.push(10, 10, 10, 10, 10, 10, 10, 10, 10, 15);
|
|
68
|
+
_vmgState.vmgToZoneStb.sorted.push(20, 20, 20, 20, 20, 20, 20, 20, 20, 25);
|
|
66
69
|
|
|
67
70
|
expect(computeTimeToLine(toRadians(-1), 1, 270, 0, 100, false, 'stb')).toBeCloseTo(10);
|
|
68
71
|
expect(computeTimeToLine(toRadians(0), 1, 270, 100, 0, false, 'stb')).toBeCloseTo(10);
|
package/tests/racer-vmg.test.js
CHANGED
|
@@ -11,154 +11,158 @@ const {
|
|
|
11
11
|
|
|
12
12
|
describe('racer vmg', () => {
|
|
13
13
|
test('resetVmgSamples: test arrays are cleared', () => {
|
|
14
|
-
_vmgState.vmgToLinePos.push(1, 2, 3);
|
|
15
|
-
_vmgState.
|
|
16
|
-
_vmgState.
|
|
17
|
-
_vmgState.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
_vmgState.vmgToLinePos.sorted.push(1, 2, 3);
|
|
15
|
+
_vmgState.vmgToLinePos.queue.push(1, 2, 3);
|
|
16
|
+
_vmgState.vmgToLineNeg.sorted.push(4, 5, 6);
|
|
17
|
+
_vmgState.vmgToLineNeg.queue.push(4, 5, 6);
|
|
18
|
+
_vmgState.vmgToZonePort.sorted.push(7, 8, 9);
|
|
19
|
+
_vmgState.vmgToZonePort.queue.push(7, 8, 9);
|
|
20
|
+
_vmgState.vmgToZoneStb.sorted.push(10, 11, 12);
|
|
21
|
+
_vmgState.vmgToZoneStb.queue.push(10, 11, 12);
|
|
22
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(3);
|
|
23
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(3);
|
|
24
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(3);
|
|
25
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(3);
|
|
22
26
|
resetVmgSamples();
|
|
23
|
-
expect(_vmgState.vmgToLinePos.length).toBe(0);
|
|
24
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(0);
|
|
25
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
26
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(0);
|
|
27
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(0);
|
|
28
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(0);
|
|
29
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
30
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(0);
|
|
27
31
|
});
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
test('collectVmgSamplesEastWestNarrow: test east west line, with perpendicular and narrow approaches', () => {
|
|
31
35
|
resetVmgSamples();
|
|
32
36
|
collectVmgSamples(toRadians(0), 19.7, 270, 0, 0);
|
|
33
|
-
expect(_vmgState.vmgToLinePos.length).toBe(1);
|
|
34
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(19.7);
|
|
35
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(0);
|
|
36
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
37
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(0);
|
|
37
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(1);
|
|
38
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(19.7);
|
|
39
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(0);
|
|
40
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
41
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(0);
|
|
38
42
|
|
|
39
43
|
collectVmgSamples(toRadians(8.21), 19.7, 270, 0, 0);
|
|
40
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
41
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(19.5);
|
|
42
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(19.7);
|
|
43
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(0);
|
|
44
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
45
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(1);
|
|
46
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(2.81);
|
|
44
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
45
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(19.5);
|
|
46
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(19.7);
|
|
47
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(0);
|
|
48
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
49
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(1);
|
|
50
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(2.81);
|
|
47
51
|
});
|
|
48
52
|
|
|
49
53
|
|
|
50
54
|
test('collectVmgSamplesEastWest: test east west line with circle', () => {
|
|
51
55
|
resetVmgSamples();
|
|
52
56
|
collectVmgSamples(toRadians(0), 5, 270, 0, 0);
|
|
53
|
-
expect(_vmgState.vmgToLinePos.length).toBe(1);
|
|
54
|
-
expect(_vmgState.vmgToLinePos[0]).toBe(5);
|
|
55
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(0);
|
|
56
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
57
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(0);
|
|
57
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(1);
|
|
58
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBe(5);
|
|
59
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(0);
|
|
60
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
61
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(0);
|
|
58
62
|
|
|
59
63
|
collectVmgSamples(toRadians(36.87), 5, 270, 0, 0);
|
|
60
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
61
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(4);
|
|
62
|
-
expect(_vmgState.vmgToLinePos[1]).toBe(5);
|
|
63
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(0);
|
|
64
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
65
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(1);
|
|
66
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
64
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
65
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(4);
|
|
66
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBe(5);
|
|
67
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(0);
|
|
68
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
69
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(1);
|
|
70
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
67
71
|
|
|
68
72
|
collectVmgSamples(toRadians(90), 5, 270, 0, 0);
|
|
69
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
70
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(4);
|
|
71
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(5);
|
|
72
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(0);
|
|
73
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
74
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(2);
|
|
75
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
76
|
-
expect(_vmgState.vmgToZoneStb[1]).toBeCloseTo(5);
|
|
73
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
74
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(4);
|
|
75
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(5);
|
|
76
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(0);
|
|
77
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
78
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(2);
|
|
79
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
80
|
+
expect(_vmgState.vmgToZoneStb.sorted[1]).toBeCloseTo(5);
|
|
77
81
|
|
|
78
82
|
collectVmgSamples(toRadians(90 + 36.87), 5, 270, 0, 0);
|
|
79
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
80
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(4);
|
|
81
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(5);
|
|
82
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(1);
|
|
83
|
-
expect(_vmgState.vmgToLineNeg[0]).toBeCloseTo(3);
|
|
84
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
85
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(3);
|
|
86
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
87
|
-
expect(_vmgState.vmgToZoneStb[1]).toBeCloseTo(4);
|
|
88
|
-
expect(_vmgState.vmgToZoneStb[2]).toBeCloseTo(5);
|
|
83
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
84
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(4);
|
|
85
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(5);
|
|
86
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(1);
|
|
87
|
+
expect(_vmgState.vmgToLineNeg.sorted[0]).toBeCloseTo(3);
|
|
88
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
89
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(3);
|
|
90
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
91
|
+
expect(_vmgState.vmgToZoneStb.sorted[1]).toBeCloseTo(4);
|
|
92
|
+
expect(_vmgState.vmgToZoneStb.sorted[2]).toBeCloseTo(5);
|
|
89
93
|
|
|
90
94
|
collectVmgSamples(toRadians(180), 5, 270, 0, 0);
|
|
91
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
92
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(4);
|
|
93
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(5);
|
|
94
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(2);
|
|
95
|
-
expect(_vmgState.vmgToLineNeg[0]).toBeCloseTo(3);
|
|
96
|
-
expect(_vmgState.vmgToLineNeg[1]).toBeCloseTo(5);
|
|
97
|
-
expect(_vmgState.vmgToZonePort.length).toBe(0);
|
|
98
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(3);
|
|
99
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
100
|
-
expect(_vmgState.vmgToZoneStb[1]).toBeCloseTo(4);
|
|
101
|
-
expect(_vmgState.vmgToZoneStb[2]).toBeCloseTo(5);
|
|
95
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
96
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(4);
|
|
97
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(5);
|
|
98
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(2);
|
|
99
|
+
expect(_vmgState.vmgToLineNeg.sorted[0]).toBeCloseTo(3);
|
|
100
|
+
expect(_vmgState.vmgToLineNeg.sorted[1]).toBeCloseTo(5);
|
|
101
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(0);
|
|
102
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(3);
|
|
103
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
104
|
+
expect(_vmgState.vmgToZoneStb.sorted[1]).toBeCloseTo(4);
|
|
105
|
+
expect(_vmgState.vmgToZoneStb.sorted[2]).toBeCloseTo(5);
|
|
102
106
|
|
|
103
107
|
collectVmgSamples(toRadians(180 + 53.13), 5, 270, 0, 0);
|
|
104
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
105
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(4);
|
|
106
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(5);
|
|
107
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(3);
|
|
108
|
-
expect(_vmgState.vmgToLineNeg[0]).toBeCloseTo(3);
|
|
109
|
-
expect(_vmgState.vmgToLineNeg[1]).toBeCloseTo(3);
|
|
110
|
-
expect(_vmgState.vmgToLineNeg[2]).toBeCloseTo(5);
|
|
111
|
-
expect(_vmgState.vmgToZonePort.length).toBe(1);
|
|
112
|
-
expect(_vmgState.vmgToZonePort[0]).toBeCloseTo(4);
|
|
113
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(3);
|
|
114
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
115
|
-
expect(_vmgState.vmgToZoneStb[1]).toBeCloseTo(4);
|
|
116
|
-
expect(_vmgState.vmgToZoneStb[2]).toBeCloseTo(5);
|
|
108
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
109
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(4);
|
|
110
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(5);
|
|
111
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(3);
|
|
112
|
+
expect(_vmgState.vmgToLineNeg.sorted[0]).toBeCloseTo(3);
|
|
113
|
+
expect(_vmgState.vmgToLineNeg.sorted[1]).toBeCloseTo(3);
|
|
114
|
+
expect(_vmgState.vmgToLineNeg.sorted[2]).toBeCloseTo(5);
|
|
115
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(1);
|
|
116
|
+
expect(_vmgState.vmgToZonePort.sorted[0]).toBeCloseTo(4);
|
|
117
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(3);
|
|
118
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
119
|
+
expect(_vmgState.vmgToZoneStb.sorted[1]).toBeCloseTo(4);
|
|
120
|
+
expect(_vmgState.vmgToZoneStb.sorted[2]).toBeCloseTo(5);
|
|
117
121
|
|
|
118
122
|
collectVmgSamples(toRadians(270), 5, 270, 0, 0);
|
|
119
|
-
expect(_vmgState.vmgToLinePos.length).toBe(2);
|
|
120
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(4);
|
|
121
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(5);
|
|
122
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(3);
|
|
123
|
-
expect(_vmgState.vmgToLineNeg[0]).toBeCloseTo(3);
|
|
124
|
-
expect(_vmgState.vmgToLineNeg[1]).toBeCloseTo(3);
|
|
125
|
-
expect(_vmgState.vmgToLineNeg[2]).toBeCloseTo(5);
|
|
126
|
-
expect(_vmgState.vmgToZonePort.length).toBe(2);
|
|
127
|
-
expect(_vmgState.vmgToZonePort[0]).toBeCloseTo(4);
|
|
128
|
-
expect(_vmgState.vmgToZonePort[1]).toBeCloseTo(5);
|
|
129
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(3);
|
|
130
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
131
|
-
expect(_vmgState.vmgToZoneStb[1]).toBeCloseTo(4);
|
|
132
|
-
expect(_vmgState.vmgToZoneStb[2]).toBeCloseTo(5);
|
|
123
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(2);
|
|
124
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(4);
|
|
125
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(5);
|
|
126
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(3);
|
|
127
|
+
expect(_vmgState.vmgToLineNeg.sorted[0]).toBeCloseTo(3);
|
|
128
|
+
expect(_vmgState.vmgToLineNeg.sorted[1]).toBeCloseTo(3);
|
|
129
|
+
expect(_vmgState.vmgToLineNeg.sorted[2]).toBeCloseTo(5);
|
|
130
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(2);
|
|
131
|
+
expect(_vmgState.vmgToZonePort.sorted[0]).toBeCloseTo(4);
|
|
132
|
+
expect(_vmgState.vmgToZonePort.sorted[1]).toBeCloseTo(5);
|
|
133
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(3);
|
|
134
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
135
|
+
expect(_vmgState.vmgToZoneStb.sorted[1]).toBeCloseTo(4);
|
|
136
|
+
expect(_vmgState.vmgToZoneStb.sorted[2]).toBeCloseTo(5);
|
|
133
137
|
|
|
134
138
|
collectVmgSamples(-toRadians(53.13), 5, 270, 0, 0);
|
|
135
|
-
expect(_vmgState.vmgToLinePos.length).toBe(3);
|
|
136
|
-
expect(_vmgState.vmgToLinePos[0]).toBeCloseTo(3);
|
|
137
|
-
expect(_vmgState.vmgToLinePos[1]).toBeCloseTo(4);
|
|
138
|
-
expect(_vmgState.vmgToLinePos[2]).toBeCloseTo(5);
|
|
139
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(3);
|
|
140
|
-
expect(_vmgState.vmgToLineNeg[0]).toBeCloseTo(3);
|
|
141
|
-
expect(_vmgState.vmgToLineNeg[1]).toBeCloseTo(3);
|
|
142
|
-
expect(_vmgState.vmgToLineNeg[2]).toBeCloseTo(5);
|
|
143
|
-
expect(_vmgState.vmgToZonePort.length).toBe(3);
|
|
144
|
-
expect(_vmgState.vmgToZonePort[0]).toBeCloseTo(4);
|
|
145
|
-
expect(_vmgState.vmgToZonePort[1]).toBeCloseTo(4);
|
|
146
|
-
expect(_vmgState.vmgToZonePort[2]).toBeCloseTo(5);
|
|
147
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(3);
|
|
148
|
-
expect(_vmgState.vmgToZoneStb[0]).toBeCloseTo(3);
|
|
149
|
-
expect(_vmgState.vmgToZoneStb[1]).toBeCloseTo(4);
|
|
150
|
-
expect(_vmgState.vmgToZoneStb[2]).toBeCloseTo(5);
|
|
139
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(3);
|
|
140
|
+
expect(_vmgState.vmgToLinePos.sorted[0]).toBeCloseTo(3);
|
|
141
|
+
expect(_vmgState.vmgToLinePos.sorted[1]).toBeCloseTo(4);
|
|
142
|
+
expect(_vmgState.vmgToLinePos.sorted[2]).toBeCloseTo(5);
|
|
143
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(3);
|
|
144
|
+
expect(_vmgState.vmgToLineNeg.sorted[0]).toBeCloseTo(3);
|
|
145
|
+
expect(_vmgState.vmgToLineNeg.sorted[1]).toBeCloseTo(3);
|
|
146
|
+
expect(_vmgState.vmgToLineNeg.sorted[2]).toBeCloseTo(5);
|
|
147
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(3);
|
|
148
|
+
expect(_vmgState.vmgToZonePort.sorted[0]).toBeCloseTo(4);
|
|
149
|
+
expect(_vmgState.vmgToZonePort.sorted[1]).toBeCloseTo(4);
|
|
150
|
+
expect(_vmgState.vmgToZonePort.sorted[2]).toBeCloseTo(5);
|
|
151
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(3);
|
|
152
|
+
expect(_vmgState.vmgToZoneStb.sorted[0]).toBeCloseTo(3);
|
|
153
|
+
expect(_vmgState.vmgToZoneStb.sorted[1]).toBeCloseTo(4);
|
|
154
|
+
expect(_vmgState.vmgToZoneStb.sorted[2]).toBeCloseTo(5);
|
|
151
155
|
|
|
152
156
|
});
|
|
153
157
|
|
|
154
158
|
test('collectVmgSamplesNW2SE: test NW to SE line approached obliquely', () => {
|
|
155
159
|
resetVmgSamples();
|
|
156
160
|
collectVmgSamples(toRadians(0), 19.7, 8.21, 0, 0);
|
|
157
|
-
expect(_vmgState.vmgToLinePos.length).toBe(0);
|
|
158
|
-
expect(_vmgState.vmgToLineNeg.length).toBe(1);
|
|
159
|
-
expect(_vmgState.vmgToLineNeg[0]).toBeCloseTo(2.81);
|
|
160
|
-
expect(_vmgState.vmgToZonePort.length).toBe(1);
|
|
161
|
-
expect(_vmgState.vmgToZonePort[0]).toBeCloseTo(19.5);
|
|
162
|
-
expect(_vmgState.vmgToZoneStb.length).toBe(0);
|
|
161
|
+
expect(_vmgState.vmgToLinePos.sorted.length).toBe(0);
|
|
162
|
+
expect(_vmgState.vmgToLineNeg.sorted.length).toBe(1);
|
|
163
|
+
expect(_vmgState.vmgToLineNeg.sorted[0]).toBeCloseTo(2.81);
|
|
164
|
+
expect(_vmgState.vmgToZonePort.sorted.length).toBe(1);
|
|
165
|
+
expect(_vmgState.vmgToZonePort.sorted[0]).toBeCloseTo(19.5);
|
|
166
|
+
expect(_vmgState.vmgToZoneStb.sorted.length).toBe(0);
|
|
163
167
|
});
|
|
164
168
|
});
|