@fscharter/flowmap-data 8.0.2-fsc.1

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 (59) hide show
  1. package/dist/FlowmapAggregateAccessors.d.ts +16 -0
  2. package/dist/FlowmapAggregateAccessors.d.ts.map +1 -0
  3. package/dist/FlowmapAggregateAccessors.js +53 -0
  4. package/dist/FlowmapSelectors.d.ts +143 -0
  5. package/dist/FlowmapSelectors.d.ts.map +1 -0
  6. package/dist/FlowmapSelectors.js +881 -0
  7. package/dist/FlowmapState.d.ts +31 -0
  8. package/dist/FlowmapState.d.ts.map +1 -0
  9. package/dist/FlowmapState.js +7 -0
  10. package/dist/cluster/ClusterIndex.d.ts +42 -0
  11. package/dist/cluster/ClusterIndex.d.ts.map +1 -0
  12. package/dist/cluster/ClusterIndex.js +166 -0
  13. package/dist/cluster/cluster.d.ts +51 -0
  14. package/dist/cluster/cluster.d.ts.map +1 -0
  15. package/dist/cluster/cluster.js +267 -0
  16. package/dist/colors.d.ts +103 -0
  17. package/dist/colors.d.ts.map +1 -0
  18. package/dist/colors.js +487 -0
  19. package/dist/getViewStateForLocations.d.ts +23 -0
  20. package/dist/getViewStateForLocations.d.ts.map +1 -0
  21. package/dist/getViewStateForLocations.js +54 -0
  22. package/dist/index.d.ts +14 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +18 -0
  25. package/dist/provider/FlowmapDataProvider.d.ts +21 -0
  26. package/dist/provider/FlowmapDataProvider.d.ts.map +1 -0
  27. package/dist/provider/FlowmapDataProvider.js +22 -0
  28. package/dist/provider/LocalFlowmapDataProvider.d.ts +31 -0
  29. package/dist/provider/LocalFlowmapDataProvider.d.ts.map +1 -0
  30. package/dist/provider/LocalFlowmapDataProvider.js +115 -0
  31. package/dist/selector-functions.d.ts +10 -0
  32. package/dist/selector-functions.d.ts.map +1 -0
  33. package/dist/selector-functions.js +65 -0
  34. package/dist/time.d.ts +24 -0
  35. package/dist/time.d.ts.map +1 -0
  36. package/dist/time.js +131 -0
  37. package/dist/types.d.ts +120 -0
  38. package/dist/types.d.ts.map +1 -0
  39. package/dist/types.js +28 -0
  40. package/dist/util.d.ts +5 -0
  41. package/dist/util.d.ts.map +1 -0
  42. package/dist/util.js +16 -0
  43. package/package.json +48 -0
  44. package/src/FlowmapAggregateAccessors.ts +76 -0
  45. package/src/FlowmapSelectors.ts +1539 -0
  46. package/src/FlowmapState.ts +40 -0
  47. package/src/cluster/ClusterIndex.ts +261 -0
  48. package/src/cluster/cluster.ts +394 -0
  49. package/src/colors.ts +771 -0
  50. package/src/getViewStateForLocations.ts +86 -0
  51. package/src/index.ts +19 -0
  52. package/src/provider/FlowmapDataProvider.ts +81 -0
  53. package/src/provider/LocalFlowmapDataProvider.ts +185 -0
  54. package/src/selector-functions.ts +93 -0
  55. package/src/time.ts +166 -0
  56. package/src/types.ts +172 -0
  57. package/src/util.ts +17 -0
  58. package/tsconfig.json +11 -0
  59. package/typings.d.ts +1 -0
@@ -0,0 +1,267 @@
1
+ /*
2
+ * Copyright (c) Flowmap.gl contributors
3
+ * Copyright (c) 2018-2020 Teralytics
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { min, rollup } from 'd3-array';
7
+ import KDBush from 'kdbush';
8
+ const defaultOptions = {
9
+ minZoom: 0,
10
+ maxZoom: 16,
11
+ radius: 40,
12
+ extent: 512,
13
+ nodeSize: 64,
14
+ makeClusterName: (id, numPoints) => undefined,
15
+ makeClusterId: (id) => `{[${id}]}`,
16
+ };
17
+ export function isLeafPoint(p) {
18
+ const { index } = p;
19
+ return index != null;
20
+ }
21
+ export function isClusterPoint(p) {
22
+ const { id } = p;
23
+ return id != null;
24
+ }
25
+ export function clusterLocations(locations, locationAccessors, getLocationWeight, options) {
26
+ const { getLocationLon, getLocationLat, getLocationId } = locationAccessors;
27
+ const opts = {
28
+ ...defaultOptions,
29
+ ...options,
30
+ };
31
+ const { minZoom, maxZoom, nodeSize, makeClusterName, makeClusterId } = opts;
32
+ const trees = new Array(maxZoom + 1);
33
+ // generate a cluster object for each point and index input points into a KD-tree
34
+ let clusters = new Array();
35
+ let locationsCount = 0;
36
+ for (const location of locations) {
37
+ const x = getLocationLon(location);
38
+ const y = getLocationLat(location);
39
+ clusters.push({
40
+ x: lngX(x), // projected point coordinates
41
+ y: latY(y),
42
+ weight: getLocationWeight(getLocationId(location)),
43
+ zoom: Infinity, // the last zoom the point was processed at
44
+ index: locationsCount, // index of the source feature in the original input array,
45
+ parentId: -1, // parent cluster id
46
+ location,
47
+ });
48
+ locationsCount++;
49
+ }
50
+ const makeBush = (points) => {
51
+ const bush = new KDBush(points.length, nodeSize, Float32Array);
52
+ for (let i = 0; i < points.length; i++) {
53
+ bush.add(points[i].x, points[i].y);
54
+ }
55
+ bush.finish();
56
+ bush.points = points;
57
+ return bush;
58
+ };
59
+ // cluster points on max zoom, then cluster the results on previous zoom, etc.;
60
+ // results in a cluster hierarchy across zoom levels
61
+ trees[maxZoom + 1] = makeBush(clusters);
62
+ let prevZoom = maxZoom + 1;
63
+ for (let z = maxZoom; z >= minZoom; z--) {
64
+ // create a new set of clusters for the zoom and index them with a KD-tree
65
+ const _clusters = cluster(clusters, z, trees[prevZoom], opts);
66
+ if (_clusters.length === clusters.length) {
67
+ // same number of clusters => move the higher level clusters up
68
+ // no need to keep the same data on multiple levels
69
+ trees[z] = trees[prevZoom];
70
+ trees[prevZoom] = undefined;
71
+ prevZoom = z;
72
+ clusters = _clusters;
73
+ }
74
+ else {
75
+ prevZoom = z;
76
+ clusters = _clusters;
77
+ trees[z] = makeBush(clusters);
78
+ }
79
+ }
80
+ if (trees.length === 0) {
81
+ return [];
82
+ }
83
+ const numbersOfClusters = trees.map((d) => d?.points.length);
84
+ const minClusters = min(numbersOfClusters.filter((d) => d > 0));
85
+ let maxAvailZoom = findIndexOfMax(numbersOfClusters) ?? numbersOfClusters.length - 1;
86
+ const numUniqueLocations = countUniqueLocations(locations, locationAccessors);
87
+ if (numUniqueLocations < locationsCount) {
88
+ // Duplicate locations would be clustered together at any zoom level which can lead to having too many zooms.
89
+ // To avoid that, we need to find the max zoom level that has less or equal clusters than unique locations
90
+ // and drop all zoom levels beyond that (except the unclustered level).
91
+ const maxClustersZoom = findLastIndex(numbersOfClusters, (d) => d <= numUniqueLocations);
92
+ if (maxClustersZoom >= 0) {
93
+ // Now, move the unclustered points to the next zoom level to avoid having a gap
94
+ if (maxClustersZoom < maxAvailZoom) {
95
+ trees[maxClustersZoom + 1] = trees[maxAvailZoom];
96
+ trees.splice(maxClustersZoom + 2); // Remove all zoom levels beyond maxClustersZoom
97
+ }
98
+ maxAvailZoom = maxClustersZoom + 1;
99
+ }
100
+ }
101
+ const minAvailZoom = Math.min(maxAvailZoom, minClusters ? numbersOfClusters.lastIndexOf(minClusters) : maxAvailZoom);
102
+ const clusterLevels = new Array();
103
+ prevZoom = NaN;
104
+ for (let zoom = maxAvailZoom; zoom >= minAvailZoom; zoom--) {
105
+ let childrenByParent;
106
+ const tree = trees[zoom];
107
+ if (!tree)
108
+ continue;
109
+ if (trees[prevZoom] && zoom < maxAvailZoom) {
110
+ childrenByParent = rollup(trees[prevZoom].points, (points) => points.map((p) => p.id ? makeClusterId(p.id) : getLocationId(p.location)), (point) => point.parentId);
111
+ }
112
+ const nodes = [];
113
+ for (const point of tree.points) {
114
+ const { x, y, numPoints, location } = point;
115
+ if (isLeafPoint(point)) {
116
+ nodes.push({
117
+ id: getLocationId(location),
118
+ zoom,
119
+ lat: getLocationLat(location),
120
+ lon: getLocationLon(location),
121
+ });
122
+ }
123
+ else if (isClusterPoint(point)) {
124
+ const { id } = point;
125
+ const children = childrenByParent && childrenByParent.get(id);
126
+ if (!children) {
127
+ // Might happen if there are multiple locations with same coordinates
128
+ console.warn(`Omitting cluster with no children, point:`, point);
129
+ continue;
130
+ }
131
+ const cluster = {
132
+ id: makeClusterId(id),
133
+ name: makeClusterName(id, numPoints),
134
+ zoom,
135
+ lat: yLat(y),
136
+ lon: xLng(x),
137
+ children: children ?? [],
138
+ };
139
+ nodes.push(cluster);
140
+ }
141
+ }
142
+ clusterLevels.push({
143
+ zoom,
144
+ nodes,
145
+ });
146
+ prevZoom = zoom;
147
+ }
148
+ return clusterLevels;
149
+ }
150
+ function createCluster(x, y, id, numPoints, weight) {
151
+ return {
152
+ x, // weighted cluster center
153
+ y,
154
+ zoom: Infinity, // the last zoom the cluster was processed at
155
+ id, // encodes index of the first child of the cluster and its zoom level
156
+ parentId: -1, // parent cluster id
157
+ numPoints,
158
+ weight,
159
+ };
160
+ }
161
+ function cluster(points, zoom, tree, options) {
162
+ const clusters = [];
163
+ const { radius, extent } = options;
164
+ const r = radius / (extent * Math.pow(2, zoom));
165
+ // loop through each point
166
+ for (let i = 0; i < points.length; i++) {
167
+ const p = points[i];
168
+ // if we've already visited the point at this zoom level, skip it
169
+ if (p.zoom <= zoom) {
170
+ continue;
171
+ }
172
+ p.zoom = zoom;
173
+ // find all nearby points
174
+ const neighborIds = tree.within(p.x, p.y, r);
175
+ let weight = p.weight || 1;
176
+ let numPoints = isClusterPoint(p) ? p.numPoints : 1;
177
+ let wx = p.x * weight;
178
+ let wy = p.y * weight;
179
+ // encode both zoom and point index on which the cluster originated
180
+ const id = (i << 5) + (zoom + 1);
181
+ for (const neighborId of neighborIds) {
182
+ const b = tree.points[neighborId];
183
+ // filter out neighbors that are already processed
184
+ if (b.zoom <= zoom) {
185
+ continue;
186
+ }
187
+ b.zoom = zoom; // save the zoom (so it doesn't get processed twice)
188
+ const weight2 = b.weight || 1;
189
+ const numPoints2 = b.numPoints || 1;
190
+ wx += b.x * weight2; // accumulate coordinates for calculating weighted center
191
+ wy += b.y * weight2;
192
+ weight += weight2;
193
+ numPoints += numPoints2;
194
+ b.parentId = id;
195
+ }
196
+ if (numPoints === 1) {
197
+ clusters.push(p);
198
+ }
199
+ else {
200
+ p.parentId = id;
201
+ clusters.push(createCluster(wx / weight, wy / weight, id, numPoints, weight));
202
+ }
203
+ }
204
+ return clusters;
205
+ }
206
+ // spherical mercator to longitude/latitude
207
+ function xLng(x) {
208
+ return (x - 0.5) * 360;
209
+ }
210
+ function yLat(y) {
211
+ const y2 = ((180 - y * 360) * Math.PI) / 180;
212
+ return (360 * Math.atan(Math.exp(y2))) / Math.PI - 90;
213
+ }
214
+ // longitude/latitude to spherical mercator in [0..1] range
215
+ function lngX(lng) {
216
+ return lng / 360 + 0.5;
217
+ }
218
+ function latY(lat) {
219
+ const sin = Math.sin((lat * Math.PI) / 180);
220
+ const y = 0.5 - (0.25 * Math.log((1 + sin) / (1 - sin))) / Math.PI;
221
+ return y < 0 ? 0 : y > 1 ? 1 : y;
222
+ }
223
+ function getX(p) {
224
+ return p.x;
225
+ }
226
+ function getY(p) {
227
+ return p.y;
228
+ }
229
+ function countUniqueLocations(locations, locationAccessors) {
230
+ const { getLocationLon, getLocationLat } = locationAccessors;
231
+ const countByLatLon = new Map();
232
+ let uniqueCnt = 0;
233
+ for (const loc of locations) {
234
+ const lon = getLocationLon(loc);
235
+ const lat = getLocationLat(loc);
236
+ const key = `${lon},${lat}`;
237
+ const prev = countByLatLon.get(key);
238
+ if (!prev) {
239
+ uniqueCnt++;
240
+ }
241
+ countByLatLon.set(key, prev ? prev + 1 : 1);
242
+ }
243
+ return uniqueCnt;
244
+ }
245
+ function findIndexOfMax(arr) {
246
+ let max = -Infinity;
247
+ let maxIndex = undefined;
248
+ for (let i = 0; i < arr.length; i++) {
249
+ const value = arr[i];
250
+ if (typeof value === 'number') {
251
+ if (value > max) {
252
+ max = value;
253
+ maxIndex = i;
254
+ }
255
+ }
256
+ }
257
+ return maxIndex;
258
+ }
259
+ function findLastIndex(arr, predicate) {
260
+ for (let i = arr.length - 1; i >= 0; i--) {
261
+ if (predicate(arr[i], i, arr)) {
262
+ return i;
263
+ }
264
+ }
265
+ return -1;
266
+ }
267
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2x1c3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jbHVzdGVyL2NsdXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBQyxHQUFHLEVBQUUsTUFBTSxFQUFDLE1BQU0sVUFBVSxDQUFDO0FBQ3JDLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQWtDNUIsTUFBTSxjQUFjLEdBQVk7SUFDOUIsT0FBTyxFQUFFLENBQUM7SUFDVixPQUFPLEVBQUUsRUFBRTtJQUNYLE1BQU0sRUFBRSxFQUFFO0lBQ1YsTUFBTSxFQUFFLEdBQUc7SUFDWCxRQUFRLEVBQUUsRUFBRTtJQUNaLGVBQWUsRUFBRSxDQUFDLEVBQVUsRUFBRSxTQUFpQixFQUFFLEVBQUUsQ0FBQyxTQUFTO0lBQzdELGFBQWEsRUFBRSxDQUFDLEVBQVUsRUFBRSxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUk7Q0FDM0MsQ0FBQztBQXNCRixNQUFNLFVBQVUsV0FBVyxDQUFJLENBQVc7SUFDeEMsTUFBTSxFQUFDLEtBQUssRUFBQyxHQUFHLENBQWlCLENBQUM7SUFDbEMsT0FBTyxLQUFLLElBQUksSUFBSSxDQUFDO0FBQ3ZCLENBQUM7QUFFRCxNQUFNLFVBQVUsY0FBYyxDQUFJLENBQVc7SUFDM0MsTUFBTSxFQUFDLEVBQUUsRUFBQyxHQUFHLENBQWlCLENBQUM7SUFDL0IsT0FBTyxFQUFFLElBQUksSUFBSSxDQUFDO0FBQ3BCLENBQUM7QUFJRCxNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLFNBQXNCLEVBQ3RCLGlCQUF1QyxFQUN2QyxpQkFBdUMsRUFDdkMsT0FBMEI7SUFFMUIsTUFBTSxFQUFDLGNBQWMsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFDLEdBQUcsaUJBQWlCLENBQUM7SUFDMUUsTUFBTSxJQUFJLEdBQUc7UUFDWCxHQUFHLGNBQWM7UUFDakIsR0FBRyxPQUFPO0tBQ1gsQ0FBQztJQUNGLE1BQU0sRUFBQyxPQUFP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QUVELFNBQVMsY0FBYyxDQUFDLEdBQTJCO0lBQ2pELElBQUksR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDO0lBQ3BCLElBQUksUUFBUSxHQUF1QixTQUFTLENBQUM7SUFFN0MsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNwQyxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFckIsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM5QixJQUFJLEtBQUssR0FBRyxHQUFHLEVBQUUsQ0FBQztnQkFDaEIsR0FBRyxHQUFHLEtBQUssQ0FBQztnQkFDWixRQUFRLEdBQUcsQ0FBQyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQztBQUVELFNBQVMsYUFBYSxDQUNwQixHQUFRLEVBQ1IsU0FBMkQ7SUFFM0QsS0FBSyxJQUFJLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDekMsSUFBSSxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzlCLE9BQU8sQ0FBQyxDQUFDO1FBQ1gsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLENBQUMsQ0FBQyxDQUFDO0FBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKGMpIEZsb3dtYXAuZ2wgY29udHJpYnV0b3JzXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtMjAyMCBUZXJhbHl0aWNzXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCB7bWluLCByb2xsdXB9IGZyb20gJ2QzLWFycmF5JztcbmltcG9ydCBLREJ1c2ggZnJvbSAna2RidXNoJztcbmltcG9ydCB7TG9jYXRpb25XZWlnaHRHZXR0ZXJ9IGZyb20gJy4vQ2x1c3RlckluZGV4JztcbmltcG9ydCB7Q2x1c3RlciwgQ2x1c3RlckxldmVsLCBDbHVzdGVyTm9kZSwgTG9jYXRpb25BY2Nlc3NvcnN9IGZyb20gJy4uL3R5cGVzJztcblxuLyoqXG4gKiBUaGUgY29kZSBpbiB0aGlzIGZpbGUgaXMgYSBiYXNlZCBvbiBodHRwczovL2dpdGh1Yi5jb20vbWFwYm94L3N1cGVyY2x1c3RlclxuICpcbiAqICBJU0MgTGljZW5zZVxuICpcbiAqICBDb3B5cmlnaHQgKGMpIDIwMTYsIE1hcGJveFxuICpcbiAqICBQZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnkgcHVycG9zZVxuICogIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQsIHByb3ZpZGVkIHRoYXQgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2VcbiAqICBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBhcHBlYXIgaW4gYWxsIGNvcGllcy5cbiAqXG4gKiAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxuICogIFJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkRcbiAqICBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcbiAqICBJTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST00gTE9TU1xuICogIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUiBPVEhFUlxuICogIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1IgUEVSRk9STUFOQ0UgT0ZcbiAqICBUSElTIFNPRlRXQVJFLlxuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgT3B0aW9ucyB7XG4gIG1pblpvb206IG51bWJlcjsgLy8gbWluIHpvb20gdG8gZ2VuZXJhdGUgY2x1c3RlcnMgb25cbiAgbWF4Wm9vbTogbnVtYmVyOyAvLyBtYXggem9vbSBsZXZlbCB0byBjbHVzdGVyIHRoZSBwb2ludHMgb25cbiAgcmFkaXVzOiBudW1iZXI7IC8vIGNsdXN0ZXIgcmFkaXVzIGluIHBpeGVsc1xuICBleHRlbnQ6IG51bWJlcjsgLy8gdGlsZSBleHRlbnQgKHJhZGl1cyBpcyBjYWxjdWxhdGVkIHJlbGF0aXZlIHRvIGl0KVxuICBub2RlU2l6ZTogbnVtYmVyOyAvLyBzaXplIG9mIHRoZSBLRC10cmVlIGxlYWYgbm9kZSwgYWZmZWN0cyBwZXJmb3JtYW5jZVxuICBtYWtlQ2x1c3Rlck5hbWU6IChpZDogbnVtYmVyLCBudW1Qb2ludHM6IG51bWJlcikgPT4gc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBtYWtlQ2x1c3RlcklkOiAoaWQ6IG51bWJlcikgPT4gc3RyaW5nO1xufVxuXG5jb25zdCBkZWZhdWx0T3B0aW9uczogT3B0aW9ucyA9IHtcbiAgbWluWm9vbTogMCxcbiAgbWF4Wm9vbTogMTYsXG4gIHJhZGl1czogNDAsXG4gIGV4dGVudDogNTEyLFxuICBub2RlU2l6ZTogNjQsXG4gIG1ha2VDbHVzdGVyTmFtZTogKGlkOiBudW1iZXIsIG51bVBvaW50czogbnVtYmVyKSA9PiB1bmRlZmluZWQsXG4gIG1ha2VDbHVzdGVySWQ6IChpZDogbnVtYmVyKSA9PiBge1ske2lkfV19YCxcbn07XG5cbmludGVyZmFjZSBCYXNlUG9pbnQge1xuICB4OiBudW1iZXI7IC8vIHByb2plY3RlZCBwb2ludCBjb29yZGluYXRlc1xuICB5OiBudW1iZXI7XG4gIHdlaWdodDogbnVtYmVyO1xuICB6b29tOiBudW1iZXI7IC8vIHRoZSBsYXN0IHpvb20gdGhlIHBvaW50IHdhcyBwcm9jZXNzZWQgYXRcbiAgcGFyZW50SWQ6IG51bWJlcjsgLy8gcGFyZW50IGNsdXN0ZXIgaWRcbn1cblxuaW50ZXJmYWNlIExlYWZQb2ludDxMPiBleHRlbmRzIEJhc2VQb2ludCB7XG4gIGluZGV4OiBudW1iZXI7IC8vIGluZGV4IG9mIHRoZSBzb3VyY2UgZmVhdHVyZSBpbiB0aGUgb3JpZ2luYWwgaW5wdXQgYXJyYXksXG4gIGxvY2F0aW9uOiBMO1xufVxuXG5pbnRlcmZhY2UgQ2x1c3RlclBvaW50IGV4dGVuZHMgQmFzZVBvaW50IHtcbiAgaWQ6IG51bWJlcjtcbiAgbnVtUG9pbnRzOiBudW1iZXI7XG59XG5cbnR5cGUgUG9pbnQ8TD4gPSBMZWFmUG9pbnQ8TD4gfCBDbHVzdGVyUG9pbnQ7XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0xlYWZQb2ludDxMPihwOiBQb2ludDxMPik6IHAgaXMgTGVhZlBvaW50PEw+IHtcbiAgY29uc3Qge2luZGV4fSA9IHAgYXMgTGVhZlBvaW50PEw+O1xuICByZXR1cm4gaW5kZXggIT0gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQ2x1c3RlclBvaW50PEw+KHA6IFBvaW50PEw+KTogcCBpcyBDbHVzdGVyUG9pbnQge1xuICBjb25zdCB7aWR9ID0gcCBhcyBDbHVzdGVyUG9pbnQ7XG4gIHJldHVybiBpZCAhPSBudWxsO1xufVxuXG50eXBlIFpvb21MZXZlbEtEQnVzaCA9IGFueTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNsdXN0ZXJMb2NhdGlvbnM8TD4oXG4gIGxvY2F0aW9uczogSXRlcmFibGU8TD4sXG4gIGxvY2F0aW9uQWNjZXNzb3JzOiBMb2NhdGlvbkFjY2Vzc29yczxMPixcbiAgZ2V0TG9jYXRpb25XZWlnaHQ6IExvY2F0aW9uV2VpZ2h0R2V0dGVyLFxuICBvcHRpb25zPzogUGFydGlhbDxPcHRpb25zPixcbik6IENsdXN0ZXJMZXZlbFtdIHtcbiAgY29uc3Qge2dldExvY2F0aW9uTG9uLCBnZXRMb2NhdGlvbkxhdCwgZ2V0TG9jYXRpb25JZH0gPSBsb2NhdGlvbkFjY2Vzc29ycztcbiAgY29uc3Qgb3B0cyA9IHtcbiAgICAuLi5kZWZhdWx0T3B0aW9ucyxcbiAgICAuLi5vcHRpb25zLFxuICB9O1xuICBjb25zdCB7bWluWm9vbSwgbWF4Wm9vbSwgbm9kZVNpemUsIG1ha2VDbHVzdGVyTmFtZSwgbWFrZUNsdXN0ZXJJZH0gPSBvcHRzO1xuXG4gIGNvbnN0IHRyZWVzID0gbmV3IEFycmF5PFpvb21MZXZlbEtEQnVzaD4obWF4Wm9vbSArIDEpO1xuXG4gIC8vIGdlbmVyYXRlIGEgY2x1c3RlciBvYmplY3QgZm9yIGVhY2ggcG9pbnQgYW5kIGluZGV4IGlucHV0IHBvaW50cyBpbnRvIGEgS0QtdHJlZVxuICBsZXQgY2x1c3RlcnMgPSBuZXcgQXJyYXk8UG9pbnQ8TD4+KCk7XG4gIGxldCBsb2NhdGlvbnNDb3VudCA9IDA7XG4gIGZvciAoY29uc3QgbG9jYXRpb24gb2YgbG9jYXRpb25zKSB7XG4gICAgY29uc3QgeCA9IGdldExvY2F0aW9uTG9uKGxvY2F0aW9uKTtcbiAgICBjb25zdCB5ID0gZ2V0TG9jYXRpb25MYXQobG9jYXRpb24pO1xuICAgIGNsdXN0ZXJzLnB1c2goe1xuICAgICAgeDogbG5nWCh4KSwgLy8gcHJvamVjdGVkIHBvaW50IGNvb3JkaW5hdGVzXG4gICAgICB5OiBsYXRZKHkpLFxuICAgICAgd2VpZ2h0OiBnZXRMb2NhdGlvbldlaWdodChnZXRMb2NhdGlvbklkKGxvY2F0aW9uKSksXG4gICAgICB6b29tOiBJbmZpbml0eSwgLy8gdGhlIGxhc3Qgem9vbSB0aGUgcG9pbnQgd2FzIHByb2Nlc3NlZCBhdFxuICAgICAgaW5kZXg6IGxvY2F0aW9uc0NvdW50LCAvLyBpbmRleCBvZiB0aGUgc291cmNlIGZlYXR1cmUgaW4gdGhlIG9yaWdpbmFsIGlucHV0IGFycmF5LFxuICAgICAgcGFyZW50SWQ6IC0xLCAvLyBwYXJlbnQgY2x1c3RlciBpZFxuICAgICAgbG9jYXRpb24sXG4gICAgfSk7XG4gICAgbG9jYXRpb25zQ291bnQrKztcbiAgfVxuXG4gIGNvbnN0IG1ha2VCdXNoID0gKHBvaW50czogUG9pbnQ8TD5bXSkgPT4ge1xuICAgIGNvbnN0IGJ1c2ggPSBuZXcgS0RCdXNoKHBvaW50cy5sZW5ndGgsIG5vZGVTaXplLCBGbG9hdDMyQXJyYXkpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBidXNoLmFkZChwb2ludHNbaV0ueCwgcG9pbnRzW2ldLnkpO1xuICAgIH1cbiAgICBidXNoLmZpbmlzaCgpO1xuICAgIGJ1c2gucG9pbnRzID0gcG9pbnRzO1xuICAgIHJldHVybiBidXNoO1xuICB9O1xuXG4gIC8vIGNsdXN0ZXIgcG9pbnRzIG9uIG1heCB6b29tLCB0aGVuIGNsdXN0ZXIgdGhlIHJlc3VsdHMgb24gcHJldmlvdXMgem9vbSwgZXRjLjtcbiAgLy8gcmVzdWx0cyBpbiBhIGNsdXN0ZXIgaGllcmFyY2h5IGFjcm9zcyB6b29tIGxldmVsc1xuICB0cmVlc1ttYXhab29tICsgMV0gPSBtYWtlQnVzaChjbHVzdGVycyk7XG4gIGxldCBwcmV2Wm9vbSA9IG1heFpvb20gKyAxO1xuXG4gIGZvciAobGV0IHogPSBtYXhab29tOyB6ID49IG1pblpvb207IHotLSkge1xuICAgIC8vIGNyZWF0ZSBhIG5ldyBzZXQgb2YgY2x1c3RlcnMgZm9yIHRoZSB6b29tIGFuZCBpbmRleCB0aGVtIHdpdGggYSBLRC10cmVlXG4gICAgY29uc3QgX2NsdXN0ZXJzID0gY2x1c3RlcihjbHVzdGVycywgeiwgdHJlZXNbcHJldlpvb21dLCBvcHRzKTtcbiAgICBpZiAoX2NsdXN0ZXJzLmxlbmd0aCA9PT0gY2x1c3RlcnMubGVuZ3RoKSB7XG4gICAgICAvLyBzYW1lIG51bWJlciBvZiBjbHVzdGVycyA9PiBtb3ZlIHRoZSBoaWdoZXIgbGV2ZWwgY2x1c3RlcnMgdXBcbiAgICAgIC8vIG5vIG5lZWQgdG8ga2VlcCB0aGUgc2FtZSBkYXRhIG9uIG11bHRpcGxlIGxldmVsc1xuICAgICAgdHJlZXNbel0gPSB0cmVlc1twcmV2Wm9vbV07XG4gICAgICB0cmVlc1twcmV2Wm9vbV0gPSB1bmRlZmluZWQ7XG4gICAgICBwcmV2Wm9vbSA9IHo7XG4gICAgICBjbHVzdGVycyA9IF9jbHVzdGVycztcbiAgICB9IGVsc2Uge1xuICAgICAgcHJldlpvb20gPSB6O1xuICAgICAgY2x1c3RlcnMgPSBfY2x1c3RlcnM7XG4gICAgICB0cmVlc1t6XSA9IG1ha2VCdXNoKGNsdXN0ZXJzKTtcbiAgICB9XG4gIH1cblxuICBpZiAodHJlZXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgY29uc3QgbnVtYmVyc09mQ2x1c3RlcnM6IG51bWJlcltdID0gdHJlZXMubWFwKChkKSA9PiBkPy5wb2ludHMubGVuZ3RoKTtcbiAgY29uc3QgbWluQ2x1c3RlcnMgPSBtaW4obnVtYmVyc09mQ2x1c3RlcnMuZmlsdGVyKChkKSA9PiBkID4gMCkpO1xuXG4gIGxldCBtYXhBdmFpbFpvb20gPVxuICAgIGZpbmRJbmRleE9mTWF4KG51bWJlcnNPZkNsdXN0ZXJzKSA/PyBudW1iZXJzT2ZDbHVzdGVycy5sZW5ndGggLSAxO1xuXG4gIGNvbnN0IG51bVVuaXF1ZUxvY2F0aW9ucyA9IGNvdW50VW5pcXVlTG9jYXRpb25zKGxvY2F0aW9ucywgbG9jYXRpb25BY2Nlc3NvcnMpO1xuICBpZiAobnVtVW5pcXVlTG9jYXRpb25zIDwgbG9jYXRpb25zQ291bnQpIHtcbiAgICAvLyBEdXBsaWNhdGUgbG9jYXRpb25zIHdvdWxkIGJlIGNsdXN0ZXJlZCB0b2dldGhlciBhdCBhbnkgem9vbSBsZXZlbCB3aGljaCBjYW4gbGVhZCB0byBoYXZpbmcgdG9vIG1hbnkgem9vbXMuXG4gICAgLy8gVG8gYXZvaWQgdGhhdCwgd2UgbmVlZCB0byBmaW5kIHRoZSBtYXggem9vbSBsZXZlbCB0aGF0IGhhcyBsZXNzIG9yIGVxdWFsIGNsdXN0ZXJzIHRoYW4gdW5pcXVlIGxvY2F0aW9uc1xuICAgIC8vIGFuZCBkcm9wIGFsbCB6b29tIGxldmVscyBiZXlvbmQgdGhhdCAoZXhjZXB0IHRoZSB1bmNsdXN0ZXJlZCBsZXZlbCkuXG4gICAgY29uc3QgbWF4Q2x1c3RlcnNab29tID0gZmluZExhc3RJbmRleChcbiAgICAgIG51bWJlcnNPZkNsdXN0ZXJzLFxuICAgICAgKGQpID0+IGQgPD0gbnVtVW5pcXVlTG9jYXRpb25zLFxuICAgICk7XG4gICAgaWYgKG1heENsdXN0ZXJzWm9vbSA+PSAwKSB7XG4gICAgICAvLyBOb3csIG1vdmUgdGhlIHVuY2x1c3RlcmVkIHBvaW50cyB0byB0aGUgbmV4dCB6b29tIGxldmVsIHRvIGF2b2lkIGhhdmluZyBhIGdhcFxuICAgICAgaWYgKG1heENsdXN0ZXJzWm9vbSA8IG1heEF2YWlsWm9vbSkge1xuICAgICAgICB0cmVlc1ttYXhDbHVzdGVyc1pvb20gKyAxXSA9IHRyZWVzW21heEF2YWlsWm9vbV07XG4gICAgICAgIHRyZWVzLnNwbGljZShtYXhDbHVzdGVyc1pvb20gKyAyKTsgLy8gUmVtb3ZlIGFsbCB6b29tIGxldmVscyBiZXlvbmQgbWF4Q2x1c3RlcnNab29tXG4gICAgICB9XG4gICAgICBtYXhBdmFpbFpvb20gPSBtYXhDbHVzdGVyc1pvb20gKyAxO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IG1pbkF2YWlsWm9vbSA9IE1hdGgubWluKFxuICAgIG1heEF2YWlsWm9vbSxcbiAgICBtaW5DbHVzdGVycyA/IG51bWJlcnNPZkNsdXN0ZXJzLmxhc3RJbmRleE9mKG1pbkNsdXN0ZXJzKSA6IG1heEF2YWlsWm9vbSxcbiAgKTtcblxuICBjb25zdCBjbHVzdGVyTGV2ZWxzID0gbmV3IEFycmF5PENsdXN0ZXJMZXZlbD4oKTtcbiAgcHJldlpvb20gPSBOYU47XG4gIGZvciAobGV0IHpvb20gPSBtYXhBdmFpbFpvb207IHpvb20gPj0gbWluQXZhaWxab29tOyB6b29tLS0pIHtcbiAgICBsZXQgY2hpbGRyZW5CeVBhcmVudDogTWFwPG51bWJlciwgKHN0cmluZyB8IG51bWJlcilbXT4gfCB1bmRlZmluZWQ7XG4gICAgY29uc3QgdHJlZSA9IHRyZWVzW3pvb21dO1xuICAgIGlmICghdHJlZSkgY29udGludWU7XG4gICAgaWYgKHRyZWVzW3ByZXZab29tXSAmJiB6b29tIDwgbWF4QXZhaWxab29tKSB7XG4gICAgICBjaGlsZHJlbkJ5UGFyZW50ID0gcm9sbHVwKFxuICAgICAgICB0cmVlc1twcmV2Wm9vbV0ucG9pbnRzLFxuICAgICAgICAocG9pbnRzOiBhbnlbXSkgPT5cbiAgICAgICAgICBwb2ludHMubWFwKChwOiBhbnkpID0+XG4gICAgICAgICAgICBwLmlkID8gbWFrZUNsdXN0ZXJJZChwLmlkKSA6IGdldExvY2F0aW9uSWQocC5sb2NhdGlvbiksXG4gICAgICAgICAgKSxcbiAgICAgICAgKHBvaW50OiBhbnkpID0+IHBvaW50LnBhcmVudElkLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBub2RlczogQ2x1c3Rlck5vZGVbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcG9pbnQgb2YgdHJlZS5wb2ludHMpIHtcbiAgICAgIGNvbnN0IHt4LCB5LCBudW1Qb2ludHMsIGxvY2F0aW9ufSA9IHBvaW50O1xuICAgICAgaWYgKGlzTGVhZlBvaW50KHBvaW50KSkge1xuICAgICAgICBub2Rlcy5wdXNoKHtcbiAgICAgICAgICBpZDogZ2V0TG9jYXRpb25JZChsb2NhdGlvbiksXG4gICAgICAgICAgem9vbSxcbiAgICAgICAgICBsYXQ6IGdldExvY2F0aW9uTGF0KGxvY2F0aW9uKSxcbiAgICAgICAgICBsb246IGdldExvY2F0aW9uTG9uKGxvY2F0aW9uKSxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKGlzQ2x1c3RlclBvaW50KHBvaW50KSkge1xuICAgICAgICBjb25zdCB7aWR9ID0gcG9pbnQ7XG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gY2hpbGRyZW5CeVBhcmVudCAmJiBjaGlsZHJlbkJ5UGFyZW50LmdldChpZCk7XG4gICAgICAgIGlmICghY2hpbGRyZW4pIHtcbiAgICAgICAgICAvLyBNaWdodCBoYXBwZW4gaWYgdGhlcmUgYXJlIG11bHRpcGxlIGxvY2F0aW9ucyB3aXRoIHNhbWUgY29vcmRpbmF0ZXNcbiAgICAgICAgICBjb25zb2xlLndhcm4oYE9taXR0aW5nIGNsdXN0ZXIgd2l0aCBubyBjaGlsZHJlbiwgcG9pbnQ6YCwgcG9pbnQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNsdXN0ZXIgPSB7XG4gICAgICAgICAgaWQ6IG1ha2VDbHVzdGVySWQoaWQpLFxuICAgICAgICAgIG5hbWU6IG1ha2VDbHVzdGVyTmFtZShpZCwgbnVtUG9pbnRzKSxcbiAgICAgICAgICB6b29tLFxuICAgICAgICAgIGxhdDogeUxhdCh5KSxcbiAgICAgICAgICBsb246IHhMbmcoeCksXG4gICAgICAgICAgY2hpbGRyZW46IGNoaWxkcmVuID8/IFtdLFxuICAgICAgICB9IGFzIENsdXN0ZXI7XG4gICAgICAgIG5vZGVzLnB1c2goY2x1c3Rlcik7XG4gICAgICB9XG4gICAgfVxuICAgIGNsdXN0ZXJMZXZlbHMucHVzaCh7XG4gICAgICB6b29tLFxuICAgICAgbm9kZXMsXG4gICAgfSk7XG4gICAgcHJldlpvb20gPSB6b29tO1xuICB9XG4gIHJldHVybiBjbHVzdGVyTGV2ZWxzO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVDbHVzdGVyKFxuICB4OiBudW1iZXIsXG4gIHk6IG51bWJlcixcbiAgaWQ6IG51bWJlcixcbiAgbnVtUG9pbnRzOiBudW1iZXIsXG4gIHdlaWdodDogbnVtYmVyLFxuKTogQ2x1c3RlclBvaW50IHtcbiAgcmV0dXJuIHtcbiAgICB4LCAvLyB3ZWlnaHRlZCBjbHVzdGVyIGNlbnRlclxuICAgIHksXG4gICAgem9vbTogSW5maW5pdHksIC8vIHRoZSBsYXN0IHpvb20gdGhlIGNsdXN0ZXIgd2FzIHByb2Nlc3NlZCBhdFxuICAgIGlkLCAvLyBlbmNvZGVzIGluZGV4IG9mIHRoZSBmaXJzdCBjaGlsZCBvZiB0aGUgY2x1c3RlciBhbmQgaXRzIHpvb20gbGV2ZWxcbiAgICBwYXJlbnRJZDogLTEsIC8vIHBhcmVudCBjbHVzdGVyIGlkXG4gICAgbnVtUG9pbnRzLFxuICAgIHdlaWdodCxcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2x1c3RlcjxMPihcbiAgcG9pbnRzOiBQb2ludDxMPltdLFxuICB6b29tOiBudW1iZXIsXG4gIHRyZWU6IFpvb21MZXZlbEtEQnVzaCxcbiAgb3B0aW9uczogT3B0aW9ucyxcbikge1xuICBjb25zdCBjbHVzdGVyczogUG9pbnQ8TD5bXSA9IFtdO1xuICBjb25zdCB7cmFkaXVzLCBleHRlbnR9ID0gb3B0aW9ucztcbiAgY29uc3QgciA9IHJhZGl1cyAvIChleHRlbnQgKiBNYXRoLnBvdygyLCB6b29tKSk7XG5cbiAgLy8gbG9vcCB0aHJvdWdoIGVhY2ggcG9pbnRcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBwID0gcG9pbnRzW2ldO1xuICAgIC8vIGlmIHdlJ3ZlIGFscmVhZHkgdmlzaXRlZCB0aGUgcG9pbnQgYXQgdGhpcyB6b29tIGxldmVsLCBza2lwIGl0XG4gICAgaWYgKHAuem9vbSA8PSB6b29tKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgcC56b29tID0gem9vbTtcblxuICAgIC8vIGZpbmQgYWxsIG5lYXJieSBwb2ludHNcbiAgICBjb25zdCBuZWlnaGJvcklkcyA9IHRyZWUud2l0aGluKHAueCwgcC55LCByKTtcblxuICAgIGxldCB3ZWlnaHQgPSBwLndlaWdodCB8fCAxO1xuICAgIGxldCBudW1Qb2ludHMgPSBpc0NsdXN0ZXJQb2ludChwKSA/IHAubnVtUG9pbnRzIDogMTtcbiAgICBsZXQgd3ggPSBwLnggKiB3ZWlnaHQ7XG4gICAgbGV0IHd5ID0gcC55ICogd2VpZ2h0O1xuXG4gICAgLy8gZW5jb2RlIGJvdGggem9vbSBhbmQgcG9pbnQgaW5kZXggb24gd2hpY2ggdGhlIGNsdXN0ZXIgb3JpZ2luYXRlZFxuICAgIGNvbnN0IGlkID0gKGkgPDwgNSkgKyAoem9vbSArIDEpO1xuXG4gICAgZm9yIChjb25zdCBuZWlnaGJvcklkIG9mIG5laWdoYm9ySWRzKSB7XG4gICAgICBjb25zdCBiID0gdHJlZS5wb2ludHNbbmVpZ2hib3JJZF07XG4gICAgICAvLyBmaWx0ZXIgb3V0IG5laWdoYm9ycyB0aGF0IGFyZSBhbHJlYWR5IHByb2Nlc3NlZFxuICAgICAgaWYgKGIuem9vbSA8PSB6b29tKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgYi56b29tID0gem9vbTsgLy8gc2F2ZSB0aGUgem9vbSAoc28gaXQgZG9lc24ndCBnZXQgcHJvY2Vzc2VkIHR3aWNlKVxuXG4gICAgICBjb25zdCB3ZWlnaHQyID0gYi53ZWlnaHQgfHwgMTtcbiAgICAgIGNvbnN0IG51bVBvaW50czIgPSBiLm51bVBvaW50cyB8fCAxO1xuICAgICAgd3ggKz0gYi54ICogd2VpZ2h0MjsgLy8gYWNjdW11bGF0ZSBjb29yZGluYXRlcyBmb3IgY2FsY3VsYXRpbmcgd2VpZ2h0ZWQgY2VudGVyXG4gICAgICB3eSArPSBiLnkgKiB3ZWlnaHQyO1xuXG4gICAgICB3ZWlnaHQgKz0gd2VpZ2h0MjtcbiAgICAgIG51bVBvaW50cyArPSBudW1Qb2ludHMyO1xuICAgICAgYi5wYXJlbnRJZCA9IGlkO1xuICAgIH1cblxuICAgIGlmIChudW1Qb2ludHMgPT09IDEpIHtcbiAgICAgIGNsdXN0ZXJzLnB1c2gocCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHAucGFyZW50SWQgPSBpZDtcbiAgICAgIGNsdXN0ZXJzLnB1c2goXG4gICAgICAgIGNyZWF0ZUNsdXN0ZXIod3ggLyB3ZWlnaHQsIHd5IC8gd2VpZ2h0LCBpZCwgbnVtUG9pbnRzLCB3ZWlnaHQpLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gY2x1c3RlcnM7XG59XG5cbi8vIHNwaGVyaWNhbCBtZXJjYXRvciB0byBsb25naXR1ZGUvbGF0aXR1ZGVcbmZ1bmN0aW9uIHhMbmcoeDogbnVtYmVyKSB7XG4gIHJldHVybiAoeCAtIDAuNSkgKiAzNjA7XG59XG5cbmZ1bmN0aW9uIHlMYXQoeTogbnVtYmVyKSB7XG4gIGNvbnN0IHkyID0gKCgxODAgLSB5ICogMzYwKSAqIE1hdGguUEkpIC8gMTgwO1xuICByZXR1cm4gKDM2MCAqIE1hdGguYXRhbihNYXRoLmV4cCh5MikpKSAvIE1hdGguUEkgLSA5MDtcbn1cblxuLy8gbG9uZ2l0dWRlL2xhdGl0dWRlIHRvIHNwaGVyaWNhbCBtZXJjYXRvciBpbiBbMC4uMV0gcmFuZ2VcbmZ1bmN0aW9uIGxuZ1gobG5nOiBudW1iZXIpIHtcbiAgcmV0dXJuIGxuZyAvIDM2MCArIDAuNTtcbn1cblxuZnVuY3Rpb24gbGF0WShsYXQ6IG51bWJlcikge1xuICBjb25zdCBzaW4gPSBNYXRoLnNpbigobGF0ICogTWF0aC5QSSkgLyAxODApO1xuICBjb25zdCB5ID0gMC41IC0gKDAuMjUgKiBNYXRoLmxvZygoMSArIHNpbikgLyAoMSAtIHNpbikpKSAvIE1hdGguUEk7XG4gIHJldHVybiB5IDwgMCA/IDAgOiB5ID4gMSA/IDEgOiB5O1xufVxuXG5mdW5jdGlvbiBnZXRYPEw+KHA6IFBvaW50PEw+KSB7XG4gIHJldHVybiBwLng7XG59XG5cbmZ1bmN0aW9uIGdldFk8TD4ocDogUG9pbnQ8TD4pIHtcbiAgcmV0dXJuIHAueTtcbn1cblxuZnVuY3Rpb24gY291bnRVbmlxdWVMb2NhdGlvbnM8TD4oXG4gIGxvY2F0aW9uczogSXRlcmFibGU8TD4sXG4gIGxvY2F0aW9uQWNjZXNzb3JzOiBMb2NhdGlvbkFjY2Vzc29yczxMPixcbikge1xuICBjb25zdCB7Z2V0TG9jYXRpb25Mb24sIGdldExvY2F0aW9uTGF0fSA9IGxvY2F0aW9uQWNjZXNzb3JzO1xuICBjb25zdCBjb3VudEJ5TGF0TG9uID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgbGV0IHVuaXF1ZUNudCA9IDA7XG4gIGZvciAoY29uc3QgbG9jIG9mIGxvY2F0aW9ucykge1xuICAgIGNvbnN0IGxvbiA9IGdldExvY2F0aW9uTG9uKGxvYyk7XG4gICAgY29uc3QgbGF0ID0gZ2V0TG9jYXRpb25MYXQobG9jKTtcbiAgICBjb25zdCBrZXkgPSBgJHtsb259LCR7bGF0fWA7XG4gICAgY29uc3QgcHJldiA9IGNvdW50QnlMYXRMb24uZ2V0KGtleSk7XG4gICAgaWYgKCFwcmV2KSB7XG4gICAgICB1bmlxdWVDbnQrKztcbiAgICB9XG4gICAgY291bnRCeUxhdExvbi5zZXQoa2V5LCBwcmV2ID8gcHJldiArIDEgOiAxKTtcbiAgfVxuICByZXR1cm4gdW5pcXVlQ250O1xufVxuXG5mdW5jdGlvbiBmaW5kSW5kZXhPZk1heChhcnI6IChudW1iZXIgfCB1bmRlZmluZWQpW10pOiBudW1iZXIgfCB1bmRlZmluZWQge1xuICBsZXQgbWF4ID0gLUluZmluaXR5O1xuICBsZXQgbWF4SW5kZXg6IG51bWJlciB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgIGNvbnN0IHZhbHVlID0gYXJyW2ldO1xuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIGlmICh2YWx1ZSA+IG1heCkge1xuICAgICAgICBtYXggPSB2YWx1ZTtcbiAgICAgICAgbWF4SW5kZXggPSBpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtYXhJbmRleDtcbn1cblxuZnVuY3Rpb24gZmluZExhc3RJbmRleDxUPihcbiAgYXJyOiBUW10sXG4gIHByZWRpY2F0ZTogKHZhbHVlOiBULCBpbmRleDogbnVtYmVyLCBhcnJheTogVFtdKSA9PiBib29sZWFuLFxuKTogbnVtYmVyIHtcbiAgZm9yIChsZXQgaSA9IGFyci5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChwcmVkaWNhdGUoYXJyW2ldLCBpLCBhcnIpKSB7XG4gICAgICByZXR1cm4gaTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuIl19
@@ -0,0 +1,103 @@
1
+ import { SettingsState } from './FlowmapState';
2
+ export type ColorScale = (value: number) => RGBA;
3
+ export type RGBA = [number, number, number, number];
4
+ export declare function opacityFloatToInteger(opacity: number): number;
5
+ export declare function opacifyHex(hexCode: string, opacity: number): string;
6
+ export declare function colorAsRgba(color: string | number[]): RGBA;
7
+ export declare enum ColorScheme {
8
+ primary = "#162d3c"
9
+ }
10
+ export declare const GRAYISH: string[];
11
+ export declare const schemeTeal: string[];
12
+ export declare const DEFAULT_COLOR_SCHEME: string[];
13
+ export declare const COLOR_SCHEMES: {
14
+ [key: string]: string[];
15
+ };
16
+ export declare const COLOR_SCHEME_KEYS: string[];
17
+ export declare function getFlowmapColors(settings: SettingsState): Colors | DiffColors;
18
+ export declare function getColors(diffMode: boolean, colorScheme: string | string[] | undefined, darkMode: boolean, fadeEnabled: boolean, fadeOpacityEnabled: boolean, fadeAmount: number, animate: boolean): Colors | DiffColors;
19
+ export declare function createFlowColorScale(domain: [number, number], scheme: string[], animate: boolean | undefined): ColorScale;
20
+ export declare function getFlowColorScale(colors: ColorsRGBA | DiffColorsRGBA, magnitudeExtent: [number, number] | undefined, animate: boolean | undefined): (magnitude: number) => [number, number, number, number];
21
+ export declare function isDiffColors(colors: DiffColors | Colors): colors is DiffColors;
22
+ export declare function isDiffColorsRGBA(colors: DiffColorsRGBA | ColorsRGBA): colors is DiffColorsRGBA;
23
+ export interface FlowColors {
24
+ scheme?: string[];
25
+ highlighted?: string;
26
+ }
27
+ export interface LocationCircleColors {
28
+ inner?: string;
29
+ outgoing?: string;
30
+ incoming?: string;
31
+ highlighted?: string;
32
+ empty?: string;
33
+ outlineEmptyMix?: number;
34
+ }
35
+ export interface LocationAreaColors {
36
+ outline?: string;
37
+ normal?: string;
38
+ selected?: string;
39
+ highlighted?: string;
40
+ connected?: string;
41
+ }
42
+ export interface BaseColors {
43
+ darkMode?: boolean;
44
+ locationAreas?: LocationAreaColors;
45
+ dimmedOpacity?: number;
46
+ outlineColor?: string;
47
+ }
48
+ export interface Colors extends BaseColors {
49
+ flows?: FlowColors;
50
+ locationCircles?: LocationCircleColors;
51
+ }
52
+ export interface FlowAndCircleColors {
53
+ flows?: FlowColors;
54
+ locationCircles?: LocationCircleColors;
55
+ }
56
+ export interface DiffColors extends BaseColors {
57
+ positive?: FlowAndCircleColors;
58
+ negative?: FlowAndCircleColors;
59
+ }
60
+ export interface FlowColorsRGBA {
61
+ scheme: string[];
62
+ highlighted: RGBA;
63
+ }
64
+ export interface LocationCircleColorsRGBA {
65
+ inner: RGBA;
66
+ outgoing: RGBA;
67
+ incoming: RGBA;
68
+ highlighted: RGBA;
69
+ empty: RGBA;
70
+ outlineEmptyMix: number;
71
+ }
72
+ export interface LocationAreaColorsRGBA {
73
+ outline: RGBA;
74
+ normal: RGBA;
75
+ selected: RGBA;
76
+ highlighted: RGBA;
77
+ connected: RGBA;
78
+ }
79
+ export interface BaseColorsRGBA {
80
+ darkMode: boolean;
81
+ locationAreas: LocationAreaColorsRGBA;
82
+ dimmedOpacity: number;
83
+ outlineColor: RGBA;
84
+ }
85
+ export interface ColorsRGBA extends BaseColorsRGBA {
86
+ flows: FlowColorsRGBA;
87
+ locationCircles: LocationCircleColorsRGBA;
88
+ }
89
+ export interface FlowAndCircleColorsRGBA {
90
+ flows: FlowColorsRGBA;
91
+ locationCircles: LocationCircleColorsRGBA;
92
+ }
93
+ export interface DiffColorsRGBA extends BaseColorsRGBA {
94
+ positive: FlowAndCircleColorsRGBA;
95
+ negative: FlowAndCircleColorsRGBA;
96
+ }
97
+ export declare function getColorsRGBA(colors: Colors | undefined): ColorsRGBA;
98
+ export declare function getDiffColorsRGBA(colors: DiffColors | undefined): DiffColorsRGBA;
99
+ export declare function rgbaAsString(color: RGBA): string;
100
+ export declare function midpoint(a: number, b: number, zeroToOne: number): number;
101
+ export declare function mixColorsRGBA(color1: RGBA, color2: RGBA, zeroToOne: number): RGBA;
102
+ export default getColors;
103
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"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"}