@packtrack/layout 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.built/district.d.ts +2 -0
- package/.built/district.js +4 -3
- package/.built/index.d.ts +20 -17
- package/.built/index.js +20 -17
- package/.built/layout.d.ts +6 -0
- package/.built/layout.js +40 -11
- package/.built/monitor.d.ts +9 -0
- package/.built/monitor.js +15 -0
- package/.built/position.d.ts +3 -1
- package/.built/position.js +16 -0
- package/.built/positioner/point.d.ts +1 -1
- package/.built/source/device/channel.d.ts +2 -2
- package/.built/source/device/channel.js +4 -8
- package/.built/source/device/index.d.ts +10 -0
- package/.built/source/device/index.js +8 -0
- package/.built/source/district.d.ts +3 -7
- package/.built/source/district.js +4 -70
- package/.built/source/layout.d.ts +9 -6
- package/.built/source/layout.js +85 -86
- package/.built/source/monitor.d.ts +8 -0
- package/.built/source/monitor.js +8 -0
- package/.built/source/position.d.ts +3 -1
- package/.built/source/position.js +17 -5
- package/.built/source/positioner/index.d.ts +2 -0
- package/.built/source/positioner/index.js +2 -0
- package/.built/source/positioner/point.d.ts +12 -0
- package/.built/source/positioner/point.js +17 -0
- package/.built/source/positioner/responder-type.d.ts +4 -0
- package/.built/source/positioner/responder-type.js +6 -0
- package/.built/source/power-district/activator.d.ts +7 -0
- package/.built/source/power-district/activator.js +8 -0
- package/.built/source/power-district/index.d.ts +13 -0
- package/.built/source/power-district/index.js +14 -0
- package/.built/source/power-district/monitor.d.ts +7 -0
- package/.built/source/power-district/monitor.js +8 -0
- package/.built/source/power-district/reverser.d.ts +7 -0
- package/.built/source/power-district/reverser.js +8 -0
- package/.built/source/route.d.ts +0 -1
- package/.built/source/route.js +1 -8
- package/.built/source/router.d.ts +0 -4
- package/.built/source/router.js +1 -28
- package/.built/source/section.d.ts +1 -10
- package/.built/source/section.js +8 -57
- package/.built/source/span.d.ts +12 -0
- package/.built/source/span.js +77 -0
- package/.built/source/throttle.d.ts +8 -0
- package/.built/source/throttle.js +8 -0
- package/.built/source/tile.js +2 -7
- package/.built/source/track.d.ts +1 -2
- package/.built/source/track.js +3 -10
- package/.built/span.d.ts +12 -0
- package/.built/span.js +77 -0
- package/.built/throttle.d.ts +9 -0
- package/.built/throttle.js +15 -0
- package/index.ts +23 -0
- package/package.json +4 -4
- package/source/device/channel.ts +4 -4
- package/source/device/index.ts +2 -19
- package/source/district.ts +7 -83
- package/source/layout.ts +52 -74
- package/source/monitor.ts +10 -0
- package/source/position.ts +52 -32
- package/source/positioner/point.ts +2 -11
- package/source/positioner/responder-type.ts +1 -5
- package/source/power-district/index.ts +0 -5
- package/source/route.ts +2 -6
- package/source/router.ts +2 -31
- package/source/section.ts +10 -65
- package/source/span.ts +88 -0
- package/source/throttle.ts +10 -0
- package/source/track.ts +3 -7
- package/tsconfig.json +7 -8
- package/source/index.ts +0 -20
package/source/layout.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { District } from "./district";
|
|
2
|
-
import { PowerDistrict } from "./power-district";
|
|
2
|
+
import { PowerDistrict } from "./power-district/index";
|
|
3
3
|
import { Route } from "./route";
|
|
4
4
|
import { Router } from "./router";
|
|
5
5
|
import { Section } from "./section";
|
|
@@ -12,6 +12,8 @@ import { PointPositioner } from "./positioner/point";
|
|
|
12
12
|
import { PowerDistrictActivator } from "./power-district/activator";
|
|
13
13
|
import { PowerDistrictReverser } from "./power-district/reverser";
|
|
14
14
|
import { PowerDistrictMonitor } from "./power-district/monitor";
|
|
15
|
+
import { Monitor } from "./monitor";
|
|
16
|
+
import { Throttle } from "./throttle";
|
|
15
17
|
|
|
16
18
|
export class Layout {
|
|
17
19
|
name: string;
|
|
@@ -21,6 +23,9 @@ export class Layout {
|
|
|
21
23
|
devices: Device[] = [];
|
|
22
24
|
responderType: ResponderType[] = [];
|
|
23
25
|
|
|
26
|
+
monitors: Monitor[] = [];
|
|
27
|
+
throttles: Throttle[] = [];
|
|
28
|
+
|
|
24
29
|
get allDistricts() {
|
|
25
30
|
const districts: District[] = [];
|
|
26
31
|
|
|
@@ -48,35 +53,55 @@ export class Layout {
|
|
|
48
53
|
const version = railway.getAttribute('version');
|
|
49
54
|
|
|
50
55
|
if (version == '1') {
|
|
51
|
-
let
|
|
56
|
+
let child = railway.firstChild;
|
|
57
|
+
|
|
58
|
+
while (child) {
|
|
59
|
+
if (child.tagName == 'district') {
|
|
60
|
+
layout.districts.push(layout.loadDistrict(child, layout));
|
|
61
|
+
}
|
|
52
62
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
layout.districts.push(layout.loadDistrict(district, layout));
|
|
63
|
+
if (child.tagName == 'monitor') {
|
|
64
|
+
layout.monitors.push(layout.loadMonitor(child, layout));
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
|
|
67
|
+
if (child.tagName == 'throttle') {
|
|
68
|
+
layout.throttles.push(layout.loadThrottle(child, layout));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
child = child.nextSibling;
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
|
|
74
|
+
child = railway.firstChild;
|
|
62
75
|
let index = 0;
|
|
63
76
|
|
|
64
|
-
while (
|
|
65
|
-
if (
|
|
66
|
-
layout.linkDistrict(
|
|
77
|
+
while (child) {
|
|
78
|
+
if (child.tagName == 'district') {
|
|
79
|
+
layout.linkDistrict(child, layout.districts[index]);
|
|
67
80
|
|
|
68
81
|
index++;
|
|
69
82
|
}
|
|
70
83
|
|
|
71
|
-
|
|
84
|
+
child = child.nextSibling;
|
|
72
85
|
}
|
|
73
86
|
} else {
|
|
74
|
-
throw new Error(`
|
|
87
|
+
throw new Error(`Unsupported railway definition file version '${version}'`);
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
return layout;
|
|
78
91
|
}
|
|
79
92
|
|
|
93
|
+
loadMonitor(source, parent: District | Layout) {
|
|
94
|
+
const montior = new Monitor(this.findDevice(source.getAttribute('device')), parent);
|
|
95
|
+
|
|
96
|
+
return montior;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
loadThrottle(source, parent: District | Layout) {
|
|
100
|
+
const throttle = new Throttle(this.findDevice(source.getAttribute('device')), parent);
|
|
101
|
+
|
|
102
|
+
return throttle;
|
|
103
|
+
}
|
|
104
|
+
|
|
80
105
|
loadDistrict(source, parent: District | Layout) {
|
|
81
106
|
const district = new District(source.getAttribute('name'), parent);
|
|
82
107
|
|
|
@@ -107,6 +132,10 @@ export class Layout {
|
|
|
107
132
|
district.children.push(this.loadDistrict(child, district));
|
|
108
133
|
}
|
|
109
134
|
|
|
135
|
+
if (child.tagName == 'monitor') {
|
|
136
|
+
district.monitors.push(this.loadMonitor(child, district));
|
|
137
|
+
}
|
|
138
|
+
|
|
110
139
|
child = child.nextSibling;
|
|
111
140
|
}
|
|
112
141
|
|
|
@@ -314,6 +343,7 @@ export class Layout {
|
|
|
314
343
|
|
|
315
344
|
linkRouter(source, router: Router) {
|
|
316
345
|
let child = source.firstChild;
|
|
346
|
+
let active: Route;
|
|
317
347
|
|
|
318
348
|
while (child) {
|
|
319
349
|
if (child.tagName == 'route') {
|
|
@@ -325,11 +355,21 @@ export class Layout {
|
|
|
325
355
|
route.out = this.findSection(child.getAttribute('out'), router.district);
|
|
326
356
|
route.out.in = router;
|
|
327
357
|
|
|
358
|
+
if (child.hasAttribute('active')) {
|
|
359
|
+
if (active) {
|
|
360
|
+
throw new Error(`Router '${router.domainName}' has multiple active routes (${active.name}, ${route.name}).`);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
active = route;
|
|
364
|
+
}
|
|
365
|
+
|
|
328
366
|
router.routes.push(route);
|
|
329
367
|
}
|
|
330
368
|
|
|
331
369
|
child = child.nextSibling;
|
|
332
370
|
}
|
|
371
|
+
|
|
372
|
+
router.activeRoute = active;
|
|
333
373
|
}
|
|
334
374
|
|
|
335
375
|
loadPowerDistrict(source, district: District) {
|
|
@@ -360,66 +400,4 @@ export class Layout {
|
|
|
360
400
|
|
|
361
401
|
return powerDistrict;
|
|
362
402
|
}
|
|
363
|
-
|
|
364
|
-
toDot() {
|
|
365
|
-
let dot = 'digraph G {';
|
|
366
|
-
|
|
367
|
-
for (let district of this.districts) {
|
|
368
|
-
dot += district.toDotDefinition();
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
for (let district of this.districts) {
|
|
372
|
-
dot += district.toDotConnection();
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return `${dot}}`;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
toSVG(inject = '') {
|
|
379
|
-
const positons = this.districts.map(district => district.findSVGPositions()).flat(Infinity);
|
|
380
|
-
|
|
381
|
-
const width = Math.max(...positons.map(position => position.x));
|
|
382
|
-
const height = Math.max(...positons.map(position => position.y));
|
|
383
|
-
|
|
384
|
-
let svg = `<svg width="100vw" height="100vh" viewBox="0 0 ${width + 1} ${height + 1}" xmlns="http://www.w3.org/2000/svg">
|
|
385
|
-
<style>
|
|
386
|
-
|
|
387
|
-
path {
|
|
388
|
-
fill: none;
|
|
389
|
-
stroke: #000;
|
|
390
|
-
stroke-width: 0.2;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
</style>
|
|
394
|
-
`;
|
|
395
|
-
|
|
396
|
-
for (let district of this.districts) {
|
|
397
|
-
svg += district.toSVG();
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
return `${svg}${inject}</svg>`;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
dump() {
|
|
404
|
-
console.group(`Layout ${this.name}`);
|
|
405
|
-
console.log('devices');
|
|
406
|
-
|
|
407
|
-
for (let device of this.devices) {
|
|
408
|
-
device.dump();
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
console.log('responder types');
|
|
412
|
-
|
|
413
|
-
for (let type of this.responderType) {
|
|
414
|
-
type.dump();
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
console.log('districts');
|
|
418
|
-
|
|
419
|
-
for (let district of this.districts) {
|
|
420
|
-
district.dump();
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
console.groupEnd();
|
|
424
|
-
}
|
|
425
403
|
}
|
package/source/position.ts
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
1
|
import { Section } from './section.js';
|
|
2
2
|
|
|
3
3
|
export class SectionPosition {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
4
|
+
constructor(
|
|
5
|
+
public section: Section,
|
|
6
|
+
public offset: number,
|
|
7
|
+
public reversed: boolean
|
|
8
|
+
) {
|
|
9
|
+
if (offset > section.length || offset < 0) {
|
|
10
|
+
throw new Error(`Offset ${offset} out of range for section '${section.domainName}' (0 - ${section.length})`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// returns the absolute position of the point inside the section
|
|
15
|
+
// regardless of direction
|
|
16
|
+
get absolutePosition() {
|
|
17
|
+
if (this.reversed) {
|
|
18
|
+
return this.section.length - this.offset;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return this.offset;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// TODO verify reverse
|
|
25
|
+
advance(distance: number): SectionPosition {
|
|
26
|
+
if (distance < 0) {
|
|
27
|
+
return this.invert().advance(-distance).invert();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (this.offset + distance > this.section.length) {
|
|
31
|
+
const next = this.section.next(this.reversed);
|
|
32
|
+
|
|
33
|
+
if (!next) {
|
|
34
|
+
throw new Error(`Illegal advancement ${this} + ${distance}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return new SectionPosition(next, 0, this.reversed).advance(this.offset + distance - this.section.length);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return new SectionPosition(this.section, this.offset + distance, this.reversed);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// reverse direction
|
|
44
|
+
private invert() {
|
|
45
|
+
return new SectionPosition(this.section, this.section.length - this.offset, !this.reversed);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
toString() {
|
|
49
|
+
return `${this.section.name} @ ${this.offset.toFixed(1)} ${this.reversed ? 'backward' : 'forward'}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
toPackTrackValue() {
|
|
53
|
+
return `${this.section.domainName}@${this.offset}${this.reversed ? 'R' : 'F'}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Positioner } from "
|
|
1
|
+
import { Positioner } from "./index";
|
|
2
2
|
import { Channel } from "../device/channel";
|
|
3
3
|
import { Track } from "../track";
|
|
4
4
|
import { ResponderType } from "./responder-type";
|
|
@@ -16,13 +16,4 @@ export class PointPositioner extends Positioner {
|
|
|
16
16
|
get position() {
|
|
17
17
|
return this.track.head.advance(this.offset);
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
dump() {
|
|
21
|
-
console.group('Point positioner');
|
|
22
|
-
console.log('offset:', this.offset);
|
|
23
|
-
|
|
24
|
-
this.channel.dump();
|
|
25
|
-
|
|
26
|
-
console.groupEnd();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
19
|
+
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { PowerDistrictActivator } from "./activator";
|
|
2
|
-
import { Device } from "../device/index";
|
|
3
2
|
import { District } from "../district";
|
|
4
3
|
import { PowerDistrictMonitor } from "./monitor";
|
|
5
4
|
import { PowerDistrictReverser } from "./reverser";
|
|
@@ -17,8 +16,4 @@ export class PowerDistrict {
|
|
|
17
16
|
get domainName() {
|
|
18
17
|
return `${this.name}.${this.district.domainName}`;
|
|
19
18
|
}
|
|
20
|
-
|
|
21
|
-
dump() {
|
|
22
|
-
console.log(this.name);
|
|
23
|
-
}
|
|
24
19
|
}
|
package/source/route.ts
CHANGED
|
@@ -4,13 +4,9 @@ import { Section } from "./section";
|
|
|
4
4
|
export class Route {
|
|
5
5
|
in: Section;
|
|
6
6
|
out: Section;
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
constructor(
|
|
9
9
|
public name: string,
|
|
10
10
|
public router: Router,
|
|
11
11
|
) {}
|
|
12
|
-
|
|
13
|
-
dump() {
|
|
14
|
-
console.log(`Route ${this.name}: ${this.in.domainName} → ${this.out.domainName}`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
12
|
+
}
|
package/source/router.ts
CHANGED
|
@@ -5,7 +5,7 @@ export class Router {
|
|
|
5
5
|
activeRoute?: Route;
|
|
6
6
|
|
|
7
7
|
routes: Route[] = [];
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
constructor(
|
|
10
10
|
public name: string,
|
|
11
11
|
public district: District
|
|
@@ -14,33 +14,4 @@ export class Router {
|
|
|
14
14
|
get domainName() {
|
|
15
15
|
return `${this.name}.${this.district.domainName}`;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
dump() {
|
|
19
|
-
console.group(`Router ${this.domainName}`);
|
|
20
|
-
|
|
21
|
-
for (let route of this.routes) {
|
|
22
|
-
route.dump();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
console.groupEnd();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
toDotReference() {
|
|
29
|
-
return `router_${this.name.replace(/-/g, '_')}_${this.district.toDotReference()}`;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
toDotDefinition() {
|
|
33
|
-
return `
|
|
34
|
-
${this.toDotReference()} [ label = ${JSON.stringify(this.name)}, shape = diamond ]
|
|
35
|
-
`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
toDotConnection() {
|
|
39
|
-
return `
|
|
40
|
-
${this.routes.map(route => `
|
|
41
|
-
${route.in.toDotReference()} -> ${this.toDotReference()} [ headlabel = ${JSON.stringify(route.name)} ]
|
|
42
|
-
${this.toDotReference()} -> ${route.out.toDotReference()} [ taillabel = ${JSON.stringify(route.name)} ]
|
|
43
|
-
`).join('')}
|
|
44
|
-
`;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
17
|
+
}
|
package/source/section.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { District } from "./district";
|
|
2
2
|
import { SectionPosition } from "./position";
|
|
3
|
-
import { PowerDistrict } from "./power-district";
|
|
3
|
+
import { PowerDistrict } from "./power-district/index";
|
|
4
4
|
import { Router } from "./router";
|
|
5
5
|
import { Tile } from "./tile";
|
|
6
6
|
import { Track } from "./track";
|
|
7
7
|
|
|
8
8
|
export class Section {
|
|
9
9
|
powerDistrict: PowerDistrict;
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
tracks: Track[] = [];
|
|
12
12
|
tiles: Tile[] = [];
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
in?: Router | Section;
|
|
15
15
|
out?: Router | Section;
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
constructor(
|
|
18
18
|
public name: string,
|
|
19
19
|
public district: District
|
|
@@ -87,14 +87,14 @@ export class Section {
|
|
|
87
87
|
start: 0,
|
|
88
88
|
end: this.tiles[this.tiles.length - 1].pattern.length
|
|
89
89
|
},
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
tiles: [...this.tiles]
|
|
92
92
|
};
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
let start = 0;
|
|
96
96
|
let end = this.length;
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
// only use the position limit if it is within our section
|
|
99
99
|
if (startPosition.section == this) {
|
|
100
100
|
end = startPosition.absolutePosition;
|
|
@@ -131,7 +131,7 @@ export class Section {
|
|
|
131
131
|
if (start <= passed) {
|
|
132
132
|
offset.start = (start + length - passed) * tile.pattern.length / length;
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
|
|
135
135
|
if (end >= passed) {
|
|
136
136
|
offset.end = 0.5; // (start + length - passed) * tile.pattern.length / length;
|
|
137
137
|
}
|
|
@@ -139,29 +139,13 @@ export class Section {
|
|
|
139
139
|
|
|
140
140
|
passed += length;
|
|
141
141
|
}
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
return {
|
|
144
144
|
offset,
|
|
145
145
|
tiles
|
|
146
146
|
};
|
|
147
147
|
}
|
|
148
|
-
|
|
149
|
-
dump() {
|
|
150
|
-
console.group(`Section ${this.domainName}`);
|
|
151
|
-
|
|
152
|
-
console.log('in', this.in?.name ?? 'buffer');
|
|
153
|
-
console.log('out', this.out?.name ?? 'buffer');
|
|
154
|
-
|
|
155
|
-
console.group(`tracks`);
|
|
156
|
-
|
|
157
|
-
for (let track of this.tracks) {
|
|
158
|
-
track.dump();
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
console.groupEnd();
|
|
162
|
-
console.groupEnd();
|
|
163
|
-
}
|
|
164
|
-
|
|
148
|
+
|
|
165
149
|
get length() {
|
|
166
150
|
return this.tracks.reduce((accumulator, track) => accumulator + track.length, 0);
|
|
167
151
|
}
|
|
@@ -227,43 +211,4 @@ export class Section {
|
|
|
227
211
|
tip: new SectionPosition(tip, reversed ? -length : tip.length + length, false)
|
|
228
212
|
};
|
|
229
213
|
}
|
|
230
|
-
|
|
231
|
-
toDotReference() {
|
|
232
|
-
return `section_${this.name.replace(/-/g, '_')}_${this.district.toDotReference()}`;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
toDotDefinition() {
|
|
236
|
-
return `
|
|
237
|
-
${this.toDotReference()} [ label = ${JSON.stringify(`${this.name}\n${this.length}`)}, shape = box ]
|
|
238
|
-
`;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
toDotConnection() {
|
|
242
|
-
return `
|
|
243
|
-
${this.out instanceof Section ? `${this.toDotReference()} -> ${this.out.toDotReference()}` : ''}
|
|
244
|
-
`;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
toSVG() {
|
|
248
|
-
return `
|
|
249
|
-
<g id=${JSON.stringify(this.domainName).split('.').join('_')}>
|
|
250
|
-
<style>
|
|
251
|
-
|
|
252
|
-
g#${this.domainName.split('.').join('_')} path {
|
|
253
|
-
stroke: hsl(${(this.length / this.tileLength)}deg, 100%, 50%);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
</style>
|
|
257
|
-
|
|
258
|
-
${this.tiles.map(tile => tile.toSVG()).join('')}
|
|
259
|
-
</g>
|
|
260
|
-
`;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
findSVGPositions() {
|
|
264
|
-
return this.tiles.map(tile => ({
|
|
265
|
-
x: tile.x,
|
|
266
|
-
y: tile.y
|
|
267
|
-
}));
|
|
268
|
-
}
|
|
269
|
-
}
|
|
214
|
+
}
|
package/source/span.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SectionPosition } from "./position";
|
|
2
|
+
import { Section } from "./section";
|
|
3
|
+
|
|
4
|
+
export class Span {
|
|
5
|
+
constructor(
|
|
6
|
+
public head: SectionPosition,
|
|
7
|
+
public inside: Section[],
|
|
8
|
+
public tail: SectionPosition
|
|
9
|
+
) { }
|
|
10
|
+
|
|
11
|
+
// TODO verify reverse
|
|
12
|
+
contains(position: SectionPosition) {
|
|
13
|
+
if (this.inside.includes(position.section)) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (position.section == this.head.section) {
|
|
18
|
+
if (this.head.reversed) {
|
|
19
|
+
if (this.head.absolutePosition > position.absolutePosition) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
if (this.head.offset < position.absolutePosition) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (position.section == this.tail.section) {
|
|
30
|
+
if (this.tail.reversed) {
|
|
31
|
+
if (this.tail.absolutePosition < position.absolutePosition) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
} else {
|
|
35
|
+
if (this.tail.offset > position.absolutePosition) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
overlap(peer: Span) {
|
|
45
|
+
return this.contains(peer.head) || this.contains(peer.tail);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
get length() {
|
|
49
|
+
let length = 0;
|
|
50
|
+
|
|
51
|
+
if (this.head.reversed) {
|
|
52
|
+
length += this.head.section.length - this.head.offset;
|
|
53
|
+
} else {
|
|
54
|
+
length += this.head.offset;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (let section of this.inside) {
|
|
58
|
+
length += section.length;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (this.tail.reversed) {
|
|
62
|
+
length += this.tail.section.length - this.tail.offset;
|
|
63
|
+
} else {
|
|
64
|
+
length += this.tail.offset;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return length;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// TODO verify reverse
|
|
71
|
+
// TODO add efficient algo
|
|
72
|
+
static trail(start: SectionPosition, end: SectionPosition) {
|
|
73
|
+
let head = start;
|
|
74
|
+
|
|
75
|
+
const sections = [];
|
|
76
|
+
const increment = 1;
|
|
77
|
+
|
|
78
|
+
while (head.section != end.section) {
|
|
79
|
+
head = head.advance(increment);
|
|
80
|
+
|
|
81
|
+
if (head.section != start.section && head.section != end.section && !sections.includes(head.section)) {
|
|
82
|
+
sections.push(head.section);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return new Span(start, sections, end);
|
|
87
|
+
}
|
|
88
|
+
}
|
package/source/track.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Positioner } from "./positioner";
|
|
1
|
+
import { Positioner } from "./positioner/index";
|
|
2
2
|
import { Section } from "./section";
|
|
3
3
|
import { SectionPosition } from "./position";
|
|
4
4
|
|
|
@@ -19,12 +19,8 @@ export class Track {
|
|
|
19
19
|
if (track == this) {
|
|
20
20
|
return new SectionPosition(this.section, offset, false);
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
offset += track.length;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
dump() {
|
|
28
|
-
console.log(this.length);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
26
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"outDir": ".built",
|
|
4
|
-
"module": "esnext",
|
|
5
|
-
"moduleResolution": "node",
|
|
6
3
|
"target": "esnext",
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"outDir": ".built",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"lib": [
|
|
8
|
+
"esnext"
|
|
9
|
+
]
|
|
10
|
+
}
|
|
12
11
|
}
|
package/source/index.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export * from './district';
|
|
2
|
-
export * from './layout';
|
|
3
|
-
export * from './position';
|
|
4
|
-
export * from './route';
|
|
5
|
-
export * from './router';
|
|
6
|
-
export * from './section';
|
|
7
|
-
export * from './tile';
|
|
8
|
-
export * from './track';
|
|
9
|
-
|
|
10
|
-
export * from './power-district/index';
|
|
11
|
-
export * from './power-district/activator';
|
|
12
|
-
export * from './power-district/monitor';
|
|
13
|
-
export * from './power-district/reverser';
|
|
14
|
-
|
|
15
|
-
export * from './positioner/index';
|
|
16
|
-
export * from './positioner/point';
|
|
17
|
-
export * from './positioner/responder-type';
|
|
18
|
-
|
|
19
|
-
export * from './device/index';
|
|
20
|
-
export * from './device/channel';
|