@packtrack/layout 1.0.13 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.built/device/channel.d.ts +1 -1
  2. package/.built/device/index.d.ts +11 -0
  3. package/.built/device/index.js +20 -0
  4. package/.built/district.d.ts +2 -0
  5. package/.built/district.js +4 -3
  6. package/.built/index.d.ts +8 -2
  7. package/.built/index.js +8 -2
  8. package/.built/layout.d.ts +7 -1
  9. package/.built/layout.js +61 -12
  10. package/.built/monitor.d.ts +9 -0
  11. package/.built/monitor.js +15 -0
  12. package/.built/position.d.ts +3 -1
  13. package/.built/position.js +16 -0
  14. package/.built/positioner/point.d.ts +1 -1
  15. package/.built/power-district/activator.d.ts +7 -0
  16. package/.built/power-district/activator.js +8 -0
  17. package/.built/power-district/index.d.ts +14 -0
  18. package/.built/power-district/index.js +17 -0
  19. package/.built/power-district/monitor.d.ts +7 -0
  20. package/.built/power-district/monitor.js +8 -0
  21. package/.built/power-district/reverser.d.ts +7 -0
  22. package/.built/power-district/reverser.js +8 -0
  23. package/.built/span.d.ts +12 -0
  24. package/.built/span.js +77 -0
  25. package/.built/throttle.d.ts +9 -0
  26. package/.built/throttle.js +15 -0
  27. package/package.json +1 -1
  28. package/source/device/channel.ts +2 -2
  29. package/source/district.ts +21 -18
  30. package/source/index.ts +9 -2
  31. package/source/layout.ts +148 -82
  32. package/source/monitor.ts +19 -0
  33. package/source/position.ts +52 -32
  34. package/source/power-district/activator.ts +9 -0
  35. package/source/power-district/index.ts +24 -0
  36. package/source/power-district/monitor.ts +9 -0
  37. package/source/power-district/reverser.ts +9 -0
  38. package/source/span.ts +88 -0
  39. package/source/throttle.ts +19 -0
  40. package/source/power-district.ts +0 -16
  41. /package/source/device/{device.ts → index.ts} +0 -0
@@ -1,4 +1,4 @@
1
- import { Device } from "./device";
1
+ import { Device } from "./index";
2
2
  export declare class Channel {
3
3
  device: Device;
4
4
  name: string;
@@ -0,0 +1,11 @@
1
+ import { Channel } from "./channel";
2
+ export declare class Device {
3
+ identifier: string;
4
+ channels: Channel[];
5
+ lastDiscovery: {
6
+ date: Date;
7
+ address: string;
8
+ };
9
+ constructor(identifier: string);
10
+ dump(): void;
11
+ }
@@ -0,0 +1,20 @@
1
+ export class Device {
2
+ identifier;
3
+ channels = [];
4
+ lastDiscovery;
5
+ constructor(identifier) {
6
+ this.identifier = identifier;
7
+ }
8
+ dump() {
9
+ console.group(`Device ${this.identifier}`);
10
+ if (this.lastDiscovery) {
11
+ console.log(`last discovery: ${this.lastDiscovery.date.toISOString()} ${this.lastDiscovery.address}`);
12
+ }
13
+ console.group('channels');
14
+ for (let channel of this.channels) {
15
+ channel.dump();
16
+ }
17
+ console.groupEnd();
18
+ console.groupEnd();
19
+ }
20
+ }
@@ -1,4 +1,5 @@
1
1
  import { Layout } from "./layout";
2
+ import { Monitor } from "./monitor";
2
3
  import { PowerDistrict } from "./power-district";
3
4
  import { Router } from "./router";
4
5
  import { Section } from "./section";
@@ -9,6 +10,7 @@ export declare class District {
9
10
  powerDistricts: PowerDistrict[];
10
11
  sections: Section[];
11
12
  routers: Router[];
13
+ monitors: Monitor[];
12
14
  constructor(name: string, parent: District | Layout);
13
15
  get domainName(): string;
14
16
  dump(): void;
@@ -6,6 +6,7 @@ export class District {
6
6
  powerDistricts = [];
7
7
  sections = [];
8
8
  routers = [];
9
+ monitors = [];
9
10
  constructor(name, parent) {
10
11
  this.name = name;
11
12
  this.parent = parent;
@@ -48,10 +49,10 @@ export class District {
48
49
  return `
49
50
  subgraph ${this.toDotReference()} {
50
51
  label = ${JSON.stringify(this.name)}
51
-
52
+
52
53
  ${this.sections.map(section => section.toDotDefinition()).join('')}
53
54
  ${this.routers.map(router => router.toDotDefinition()).join('')}
54
-
55
+
55
56
  ${this.children.map(child => child.toDotDefinition()).join('')}
56
57
  }
57
58
  `;
@@ -60,7 +61,7 @@ export class District {
60
61
  return `
61
62
  ${this.sections.map(section => section.toDotConnection()).join('')}
62
63
  ${this.routers.map(router => router.toDotConnection()).join('')}
63
-
64
+
64
65
  ${this.children.map(child => child.toDotConnection()).join('')}
65
66
  `;
66
67
  }
package/.built/index.d.ts CHANGED
@@ -1,14 +1,20 @@
1
1
  export * from './district';
2
2
  export * from './layout';
3
3
  export * from './position';
4
- export * from './power-district';
5
4
  export * from './route';
6
5
  export * from './router';
7
6
  export * from './section';
7
+ export * from './span';
8
8
  export * from './tile';
9
9
  export * from './track';
10
+ export * from './monitor';
11
+ export * from './throttle';
12
+ export * from './power-district/index';
13
+ export * from './power-district/activator';
14
+ export * from './power-district/monitor';
15
+ export * from './power-district/reverser';
10
16
  export * from './positioner/index';
11
17
  export * from './positioner/point';
12
18
  export * from './positioner/responder-type';
13
- export * from './device/device';
19
+ export * from './device/index';
14
20
  export * from './device/channel';
package/.built/index.js CHANGED
@@ -1,14 +1,20 @@
1
1
  export * from './district';
2
2
  export * from './layout';
3
3
  export * from './position';
4
- export * from './power-district';
5
4
  export * from './route';
6
5
  export * from './router';
7
6
  export * from './section';
7
+ export * from './span';
8
8
  export * from './tile';
9
9
  export * from './track';
10
+ export * from './monitor';
11
+ export * from './throttle';
12
+ export * from './power-district/index';
13
+ export * from './power-district/activator';
14
+ export * from './power-district/monitor';
15
+ export * from './power-district/reverser';
10
16
  export * from './positioner/index';
11
17
  export * from './positioner/point';
12
18
  export * from './positioner/responder-type';
13
- export * from './device/device';
19
+ export * from './device/index';
14
20
  export * from './device/channel';
@@ -2,16 +2,22 @@ import { District } from "./district";
2
2
  import { PowerDistrict } from "./power-district";
3
3
  import { Router } from "./router";
4
4
  import { Section } from "./section";
5
- import { Device } from "./device/device";
5
+ import { Device } from "./device/index";
6
6
  import { ResponderType } from "./positioner/responder-type";
7
7
  import { Channel } from "./device/channel";
8
+ import { Monitor } from "./monitor";
9
+ import { Throttle } from "./throttle";
8
10
  export declare class Layout {
9
11
  name: string;
10
12
  districts: District[];
11
13
  devices: Device[];
12
14
  responderType: ResponderType[];
15
+ monitors: Monitor[];
16
+ throttles: Throttle[];
13
17
  get allDistricts(): District[];
14
18
  static from(document: any): Layout;
19
+ loadMonitor(source: any, parent: District | Layout): Monitor;
20
+ loadThrottle(source: any, parent: District | Layout): Throttle;
15
21
  loadDistrict(source: any, parent: District | Layout): District;
16
22
  linkDistrict(source: any, district: District): void;
17
23
  loadSection(source: any, district: District): void;
package/.built/layout.js CHANGED
@@ -5,15 +5,22 @@ import { Router } from "./router";
5
5
  import { Section } from "./section";
6
6
  import { TilePattern, Tile } from "./tile";
7
7
  import { Track } from "./track";
8
- import { Device } from "./device/device";
8
+ import { Device } from "./device/index";
9
9
  import { ResponderType } from "./positioner/responder-type";
10
10
  import { Channel } from "./device/channel";
11
11
  import { PointPositioner } from "./positioner/point";
12
+ import { PowerDistrictActivator } from "./power-district/activator";
13
+ import { PowerDistrictReverser } from "./power-district/reverser";
14
+ import { PowerDistrictMonitor } from "./power-district/monitor";
15
+ import { Monitor } from "./monitor";
16
+ import { Throttle } from "./throttle";
12
17
  export class Layout {
13
18
  name;
14
19
  districts = [];
15
20
  devices = [];
16
21
  responderType = [];
22
+ monitors = [];
23
+ throttles = [];
17
24
  get allDistricts() {
18
25
  const districts = [];
19
26
  function walkDistrict(district) {
@@ -33,28 +40,42 @@ export class Layout {
33
40
  layout.name = railway.getAttribute('name');
34
41
  const version = railway.getAttribute('version');
35
42
  if (version == '1') {
36
- let district = railway.firstChild;
37
- while (district) {
38
- if (district.tagName == 'district') {
39
- layout.districts.push(layout.loadDistrict(district, layout));
43
+ let child = railway.firstChild;
44
+ while (child) {
45
+ if (child.tagName == 'district') {
46
+ layout.districts.push(layout.loadDistrict(child, layout));
40
47
  }
41
- district = district.nextSibling;
48
+ if (child.tagName == 'monitor') {
49
+ layout.monitors.push(layout.loadMonitor(child, layout));
50
+ }
51
+ if (child.tagName == 'throttle') {
52
+ layout.throttles.push(layout.loadThrottle(child, layout));
53
+ }
54
+ child = child.nextSibling;
42
55
  }
43
- district = railway.firstChild;
56
+ child = railway.firstChild;
44
57
  let index = 0;
45
- while (district) {
46
- if (district.tagName == 'district') {
47
- layout.linkDistrict(district, layout.districts[index]);
58
+ while (child) {
59
+ if (child.tagName == 'district') {
60
+ layout.linkDistrict(child, layout.districts[index]);
48
61
  index++;
49
62
  }
50
- district = district.nextSibling;
63
+ child = child.nextSibling;
51
64
  }
52
65
  }
53
66
  else {
54
- throw new Error(`unsupported railway definition file version '${version}'`);
67
+ throw new Error(`Unsupported railway definition file version '${version}'`);
55
68
  }
56
69
  return layout;
57
70
  }
71
+ loadMonitor(source, parent) {
72
+ const montior = new Monitor(this.findDevice(source.getAttribute('device')), parent);
73
+ return montior;
74
+ }
75
+ loadThrottle(source, parent) {
76
+ const throttle = new Throttle(this.findDevice(source.getAttribute('device')), parent);
77
+ return throttle;
78
+ }
58
79
  loadDistrict(source, parent) {
59
80
  const district = new District(source.getAttribute('name'), parent);
60
81
  let child = source.firstChild;
@@ -77,6 +98,9 @@ export class Layout {
77
98
  if (child.tagName == 'district') {
78
99
  district.children.push(this.loadDistrict(child, district));
79
100
  }
101
+ if (child.tagName == 'monitor') {
102
+ district.monitors.push(this.loadMonitor(child, district));
103
+ }
80
104
  child = child.nextSibling;
81
105
  }
82
106
  return district;
@@ -217,6 +241,7 @@ export class Layout {
217
241
  }
218
242
  linkRouter(source, router) {
219
243
  let child = source.firstChild;
244
+ let active;
220
245
  while (child) {
221
246
  if (child.tagName == 'route') {
222
247
  const route = new Route(child.getAttribute('name'), router);
@@ -224,13 +249,37 @@ export class Layout {
224
249
  route.in.out = router;
225
250
  route.out = this.findSection(child.getAttribute('out'), router.district);
226
251
  route.out.in = router;
252
+ if (child.hasAttribute('active')) {
253
+ if (active) {
254
+ throw new Error(`Router '${router.domainName}' has multiple active routes (${active.name}, ${route.name}).`);
255
+ }
256
+ active = route;
257
+ }
227
258
  router.routes.push(route);
228
259
  }
229
260
  child = child.nextSibling;
230
261
  }
262
+ router.activeRoute = active;
231
263
  }
232
264
  loadPowerDistrict(source, district) {
233
265
  const powerDistrict = new PowerDistrict(source.getAttribute('name'), district);
266
+ let actor = source.firstChild;
267
+ while (actor) {
268
+ if (actor.tagName == 'activator' || actor.tagName == 'reverser' || actor.tagName == 'monitor') {
269
+ const device = this.findDevice(actor.getAttribute('device'));
270
+ const channel = this.findChannel(device, actor.getAttribute('channel'));
271
+ if (actor.tagName == 'activator') {
272
+ powerDistrict.activator = new PowerDistrictActivator(device, channel);
273
+ }
274
+ if (actor.tagName == 'reverser') {
275
+ powerDistrict.reverser = new PowerDistrictReverser(device, channel);
276
+ }
277
+ if (actor.tagName == 'monitor') {
278
+ powerDistrict.monitor = new PowerDistrictMonitor(device, channel);
279
+ }
280
+ }
281
+ actor = actor.nextSibling;
282
+ }
234
283
  return powerDistrict;
235
284
  }
236
285
  toDot() {
@@ -0,0 +1,9 @@
1
+ import { Device } from "./device";
2
+ import { District } from "./district";
3
+ import { Layout } from "./layout";
4
+ export declare class Monitor {
5
+ device: Device;
6
+ scope: District | Layout;
7
+ constructor(device: Device, scope: District | Layout);
8
+ dump(): void;
9
+ }
@@ -0,0 +1,15 @@
1
+ import { Layout } from "./layout";
2
+ export class Monitor {
3
+ device;
4
+ scope;
5
+ constructor(device, scope) {
6
+ this.device = device;
7
+ this.scope = scope;
8
+ }
9
+ dump() {
10
+ console.group('Monitor');
11
+ console.log('scope:', this.scope instanceof Layout ? '*' : this.scope.domainName);
12
+ this.device.dump();
13
+ console.groupEnd();
14
+ }
15
+ }
@@ -5,6 +5,8 @@ export declare class SectionPosition {
5
5
  reversed: boolean;
6
6
  constructor(section: Section, offset: number, reversed: boolean);
7
7
  get absolutePosition(): number;
8
- advance(distance: number): any;
8
+ advance(distance: number): SectionPosition;
9
+ private invert;
9
10
  toString(): string;
11
+ toPackTrackValue(): string;
10
12
  }
@@ -6,14 +6,23 @@ export class SectionPosition {
6
6
  this.section = section;
7
7
  this.offset = offset;
8
8
  this.reversed = reversed;
9
+ if (offset > section.length || offset < 0) {
10
+ throw new Error(`Offset ${offset} out of range for section '${section.domainName}' (0 - ${section.length})`);
11
+ }
9
12
  }
13
+ // returns the absolute position of the point inside the section
14
+ // regardless of direction
10
15
  get absolutePosition() {
11
16
  if (this.reversed) {
12
17
  return this.section.length - this.offset;
13
18
  }
14
19
  return this.offset;
15
20
  }
21
+ // TODO verify reverse
16
22
  advance(distance) {
23
+ if (distance < 0) {
24
+ return this.invert().advance(-distance).invert();
25
+ }
17
26
  if (this.offset + distance > this.section.length) {
18
27
  const next = this.section.next(this.reversed);
19
28
  if (!next) {
@@ -23,7 +32,14 @@ export class SectionPosition {
23
32
  }
24
33
  return new SectionPosition(this.section, this.offset + distance, this.reversed);
25
34
  }
35
+ // reverse direction
36
+ invert() {
37
+ return new SectionPosition(this.section, this.section.length - this.offset, !this.reversed);
38
+ }
26
39
  toString() {
27
40
  return `${this.section.name} @ ${this.offset.toFixed(1)} ${this.reversed ? 'backward' : 'forward'}`;
28
41
  }
42
+ toPackTrackValue() {
43
+ return `${this.section.domainName}@${this.offset}${this.reversed ? 'R' : 'F'}`;
44
+ }
29
45
  }
@@ -8,6 +8,6 @@ export declare class PointPositioner extends Positioner {
8
8
  channel: Channel;
9
9
  responder: ResponderType;
10
10
  constructor(track: Track, offset: number, channel: Channel, responder: ResponderType);
11
- get position(): any;
11
+ get position(): import("..").SectionPosition;
12
12
  dump(): void;
13
13
  }
@@ -0,0 +1,7 @@
1
+ import { Channel } from "../device/channel";
2
+ import { Device } from "../device/index";
3
+ export declare class PowerDistrictActivator {
4
+ device: Device;
5
+ channel: Channel;
6
+ constructor(device: Device, channel: Channel);
7
+ }
@@ -0,0 +1,8 @@
1
+ export class PowerDistrictActivator {
2
+ device;
3
+ channel;
4
+ constructor(device, channel) {
5
+ this.device = device;
6
+ this.channel = channel;
7
+ }
8
+ }
@@ -0,0 +1,14 @@
1
+ import { PowerDistrictActivator } from "./activator";
2
+ import { District } from "../district";
3
+ import { PowerDistrictMonitor } from "./monitor";
4
+ import { PowerDistrictReverser } from "./reverser";
5
+ export declare class PowerDistrict {
6
+ name: string;
7
+ district: District;
8
+ activator?: PowerDistrictActivator;
9
+ reverser?: PowerDistrictReverser;
10
+ monitor?: PowerDistrictMonitor;
11
+ constructor(name: string, district: District);
12
+ get domainName(): string;
13
+ dump(): void;
14
+ }
@@ -0,0 +1,17 @@
1
+ export class PowerDistrict {
2
+ name;
3
+ district;
4
+ activator;
5
+ reverser;
6
+ monitor;
7
+ constructor(name, district) {
8
+ this.name = name;
9
+ this.district = district;
10
+ }
11
+ get domainName() {
12
+ return `${this.name}.${this.district.domainName}`;
13
+ }
14
+ dump() {
15
+ console.log(this.name);
16
+ }
17
+ }
@@ -0,0 +1,7 @@
1
+ import { Channel } from "../device/channel";
2
+ import { Device } from "../device/index";
3
+ export declare class PowerDistrictMonitor {
4
+ device: Device;
5
+ channel: Channel;
6
+ constructor(device: Device, channel: Channel);
7
+ }
@@ -0,0 +1,8 @@
1
+ export class PowerDistrictMonitor {
2
+ device;
3
+ channel;
4
+ constructor(device, channel) {
5
+ this.device = device;
6
+ this.channel = channel;
7
+ }
8
+ }
@@ -0,0 +1,7 @@
1
+ import { Channel } from "../device/channel";
2
+ import { Device } from "../device/index";
3
+ export declare class PowerDistrictReverser {
4
+ device: Device;
5
+ channel: Channel;
6
+ constructor(device: Device, channel: Channel);
7
+ }
@@ -0,0 +1,8 @@
1
+ export class PowerDistrictReverser {
2
+ device;
3
+ channel;
4
+ constructor(device, channel) {
5
+ this.device = device;
6
+ this.channel = channel;
7
+ }
8
+ }
@@ -0,0 +1,12 @@
1
+ import { SectionPosition } from "./position";
2
+ import { Section } from "./section";
3
+ export declare class Span {
4
+ head: SectionPosition;
5
+ inside: Section[];
6
+ tail: SectionPosition;
7
+ constructor(head: SectionPosition, inside: Section[], tail: SectionPosition);
8
+ contains(position: SectionPosition): boolean;
9
+ overlap(peer: Span): boolean;
10
+ get length(): number;
11
+ static trail(start: SectionPosition, end: SectionPosition): Span;
12
+ }
package/.built/span.js ADDED
@@ -0,0 +1,77 @@
1
+ export class Span {
2
+ head;
3
+ inside;
4
+ tail;
5
+ constructor(head, inside, tail) {
6
+ this.head = head;
7
+ this.inside = inside;
8
+ this.tail = tail;
9
+ }
10
+ // TODO verify reverse
11
+ contains(position) {
12
+ if (this.inside.includes(position.section)) {
13
+ return true;
14
+ }
15
+ if (position.section == this.head.section) {
16
+ if (this.head.reversed) {
17
+ if (this.head.absolutePosition > position.absolutePosition) {
18
+ return true;
19
+ }
20
+ }
21
+ else {
22
+ if (this.head.offset < position.absolutePosition) {
23
+ return true;
24
+ }
25
+ }
26
+ }
27
+ if (position.section == this.tail.section) {
28
+ if (this.tail.reversed) {
29
+ if (this.tail.absolutePosition < position.absolutePosition) {
30
+ return true;
31
+ }
32
+ }
33
+ else {
34
+ if (this.tail.offset > position.absolutePosition) {
35
+ return true;
36
+ }
37
+ }
38
+ }
39
+ return false;
40
+ }
41
+ overlap(peer) {
42
+ return this.contains(peer.head) || this.contains(peer.tail);
43
+ }
44
+ get length() {
45
+ let length = 0;
46
+ if (this.head.reversed) {
47
+ length += this.head.section.length - this.head.offset;
48
+ }
49
+ else {
50
+ length += this.head.offset;
51
+ }
52
+ for (let section of this.inside) {
53
+ length += section.length;
54
+ }
55
+ if (this.tail.reversed) {
56
+ length += this.tail.section.length - this.tail.offset;
57
+ }
58
+ else {
59
+ length += this.tail.offset;
60
+ }
61
+ return length;
62
+ }
63
+ // TODO verify reverse
64
+ // TODO add efficient algo
65
+ static trail(start, end) {
66
+ let head = start;
67
+ const sections = [];
68
+ const increment = 1;
69
+ while (head.section != end.section) {
70
+ head = head.advance(increment);
71
+ if (head.section != start.section && head.section != end.section && !sections.includes(head.section)) {
72
+ sections.push(head.section);
73
+ }
74
+ }
75
+ return new Span(start, sections, end);
76
+ }
77
+ }
@@ -0,0 +1,9 @@
1
+ import { Device } from "./device";
2
+ import { District } from "./district";
3
+ import { Layout } from "./layout";
4
+ export declare class Throttle {
5
+ device: Device;
6
+ scope: District | Layout;
7
+ constructor(device: Device, scope: District | Layout);
8
+ dump(): void;
9
+ }
@@ -0,0 +1,15 @@
1
+ import { Layout } from "./layout";
2
+ export class Throttle {
3
+ device;
4
+ scope;
5
+ constructor(device, scope) {
6
+ this.device = device;
7
+ this.scope = scope;
8
+ }
9
+ dump() {
10
+ console.group('Throttle');
11
+ console.log('scope:', this.scope instanceof Layout ? '*' : this.scope.domainName);
12
+ this.device.dump();
13
+ console.groupEnd();
14
+ }
15
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@packtrack/layout",
3
- "version": "1.0.13",
3
+ "version": "1.2.0",
4
4
  "main": ".built/index.js",
5
5
  "typings": ".built/index.d.ts",
6
6
  "sideEffects": false,
@@ -1,4 +1,4 @@
1
- import { Device } from "./device";
1
+ import { Device } from "./index";
2
2
 
3
3
  export class Channel {
4
4
  constructor(
@@ -11,4 +11,4 @@ export class Channel {
11
11
  }
12
12
 
13
13
  publish(data: any) {}
14
- }
14
+ }