@dra2020/baseclient 1.0.173 → 1.0.174

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.
@@ -14,14 +14,18 @@ export declare class MultiBlockMapping {
14
14
  entries: Entry[];
15
15
  stamp: number;
16
16
  constructor(tag?: string, bm?: BlockMapping);
17
- add(tag: string, bm: BlockMapping): void;
17
+ add(tag: string, bm: BlockMapping, rbm?: ReverseBlockMapping): void;
18
+ addFrom(src: MultiBlockMapping, tag?: string): void;
18
19
  remove(tag: string): void;
20
+ has(tag: string): boolean;
19
21
  map(blockid: string): string;
20
22
  multimap(blockid: string): string[];
21
23
  bmOf(tag: string): BlockMapping;
24
+ rbmOf(tag: string): ReverseBlockMapping;
22
25
  mapmain(blockid: string): string;
23
26
  rev(geoid: string): string[];
24
- forEach(cb: (blockid: string) => void): void;
27
+ forEachBase(cb: (blockid: string) => void, tag?: string): void;
28
+ forEachBlock(cb: (blockid: string) => void): void;
25
29
  forEachRev(cb: (geoidid: string, blocks: string[]) => void): void;
26
30
  }
27
31
  export {};
@@ -21,6 +21,16 @@ export function reverseBlockMapping(bm: BlockMapping): ReverseBlockMapping
21
21
  return rev;
22
22
  }
23
23
 
24
+ // A set of block mappings consulted as one, without copying any of them.
25
+ //
26
+ // Entries are either independent (e.g. one per state of a multi-state map, whose block ids never
27
+ // overlap) or overlapping (a base mapping followed by overrides such as precinct updates). Overlapping
28
+ // entries must be added in priority order: map() and rev() walk from the last entry back, so a later
29
+ // entry wins.
30
+ //
31
+ // A full block mapping, and the reverse mapping computed from it, are large (TX has ~670K blocks), so
32
+ // combining mappings shares them rather than copying: add() takes an already-computed reverse mapping,
33
+ // and addFrom() takes both from another MultiBlockMapping.
24
34
  export class MultiBlockMapping
25
35
  {
26
36
  entries: Entry[];
@@ -34,14 +44,32 @@ export class MultiBlockMapping
34
44
  this.entries.push({ tag, bm });
35
45
  }
36
46
 
37
- add(tag: string, bm: BlockMapping): void
47
+ // Adds or replaces the entry for tag. Pass rbm when the reverse mapping of bm is already computed,
48
+ // so it is shared rather than built again.
49
+ add(tag: string, bm: BlockMapping, rbm?: ReverseBlockMapping): void
38
50
  {
39
- this.entries.forEach(e => { if (e.tag === tag) { e.bm = bm; delete e.rbm; bm = null } });
40
- if (bm)
41
- this.entries.push({ tag, bm });
51
+ let e = this.entries.find(e => e.tag === tag);
52
+ if (e)
53
+ {
54
+ e.bm = bm;
55
+ if (rbm) e.rbm = rbm; else delete e.rbm;
56
+ }
57
+ else
58
+ this.entries.push(rbm ? { tag, bm, rbm } : { tag, bm });
42
59
  this.stamp++;
43
60
  }
44
61
 
62
+ // Adds the entry for tag from another mapping - or, with no tag, all of its entries in order - sharing
63
+ // both the block mapping and its reverse mapping. The reverse mapping is computed on the source first
64
+ // if need be, so that it is built once, there, and not separately in each mapping that shares it.
65
+ addFrom(src: MultiBlockMapping, tag?: string): void
66
+ {
67
+ src.entries.forEach(e => {
68
+ if (tag === undefined || e.tag === tag)
69
+ this.add(e.tag, e.bm, src.rbmOf(e.tag));
70
+ });
71
+ }
72
+
45
73
  remove(tag: string): void
46
74
  {
47
75
  for (let i = this.entries.length-1; i >= 0; i--)
@@ -52,6 +80,11 @@ export class MultiBlockMapping
52
80
  }
53
81
  }
54
82
 
83
+ has(tag: string): boolean
84
+ {
85
+ return this.entries.some(e => e.tag === tag);
86
+ }
87
+
55
88
  map(blockid: string): string
56
89
  {
57
90
  // Walk backwards to pick up overrides first
@@ -77,6 +110,17 @@ export class MultiBlockMapping
77
110
  return e ? e.bm : null;
78
111
  }
79
112
 
113
+ // The reverse mapping of the entry for tag, computed on first use.
114
+ rbmOf(tag: string): ReverseBlockMapping
115
+ {
116
+ let e = this.entries.find(e => e.tag === tag);
117
+ if (! e) return null;
118
+ if (! e.rbm) e.rbm = reverseBlockMapping(e.bm);
119
+ return e.rbm;
120
+ }
121
+
122
+ // Maps through the first entry only. Meaningful only where that entry is the base mapping and the
123
+ // rest are overrides; for independent entries (a multi-state mapping) use map().
80
124
  mapmain(blockid: string): string
81
125
  {
82
126
  return this.entries.length ? this.entries[0].bm[blockid] : undefined;
@@ -95,11 +139,21 @@ export class MultiBlockMapping
95
139
  return undefined;
96
140
  }
97
141
 
98
- // Just walks first map
99
- forEach(cb: (blockid: string) => void): void
142
+ // Walks the blocks of one entry: the one for tag, or with no tag the first. This is the right walk
143
+ // over "all blocks" only when that entry is a base mapping covering them and the others are overrides
144
+ // of it - it sees nothing of a multi-state mapping but its first state. See forEachBlock.
145
+ forEachBase(cb: (blockid: string) => void, tag?: string): void
146
+ {
147
+ let e = tag === undefined ? this.entries[0] : this.entries.find(e => e.tag === tag);
148
+ if (e)
149
+ Object.keys(e.bm).forEach(blockid => cb(blockid));
150
+ }
151
+
152
+ // Walks the blocks of every entry. A block mapped by several entries (a base and its overrides) is
153
+ // visited once for each of them; independent entries (a multi-state mapping) never repeat a block.
154
+ forEachBlock(cb: (blockid: string) => void): void
100
155
  {
101
- if (this.entries.length)
102
- Object.keys(this.entries[0].bm).forEach(blockid => cb(blockid));
156
+ this.entries.forEach(e => Object.keys(e.bm).forEach(blockid => cb(blockid)));
103
157
  }
104
158
 
105
159
  // Walk maps in reverse order, careful to not invoke on same geoid
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dra2020/baseclient",
3
- "version": "1.0.173",
3
+ "version": "1.0.174",
4
4
  "description": "Utility functions for Javascript projects.",
5
5
  "main": "dist/baseclient.js",
6
6
  "types": "./dist/all/all.d.ts",