@dra2020/district-analytics 3.0.1 → 3.1.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/dist/cli.js +2290 -733
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +169 -320
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/_api.d.ts +2 -1
- package/dist/src/geofeature.d.ts +2 -0
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -86,10 +86,10 @@
|
|
|
86
86
|
/************************************************************************/
|
|
87
87
|
/******/ ({
|
|
88
88
|
|
|
89
|
-
/***/ "
|
|
90
|
-
|
|
91
|
-
!***
|
|
92
|
-
|
|
89
|
+
/***/ "../dra-score/dist/dra-score.bundle.js":
|
|
90
|
+
/*!*********************************************!*\
|
|
91
|
+
!*** ../dra-score/dist/dra-score.bundle.js ***!
|
|
92
|
+
\*********************************************/
|
|
93
93
|
/*! no static exports found */
|
|
94
94
|
/***/ (function(module, exports, __webpack_require__) {
|
|
95
95
|
|
|
@@ -89814,7 +89814,11 @@ function doPopulationDeviation(e, targetSize, bLegislative, bLog = false) {
|
|
|
89814
89814
|
// Round the raw value to the desired level of precision
|
|
89815
89815
|
const popDev = U.trim((max - min) / targetSize);
|
|
89816
89816
|
const score = scorePopulationDeviation(popDev, bLegislative);
|
|
89817
|
-
const
|
|
89817
|
+
const threshold = bLegislative ? S.POPDEV_WORST_LD : S.POPDEV_WORST;
|
|
89818
|
+
const notes = {
|
|
89819
|
+
'maxDeviation': max - min,
|
|
89820
|
+
'threshold': threshold
|
|
89821
|
+
};
|
|
89818
89822
|
// Populate the measurement
|
|
89819
89823
|
const m = {
|
|
89820
89824
|
raw: popDev,
|
|
@@ -90349,7 +90353,7 @@ const cohesive_1 = __webpack_require__(/*! ./cohesive */ "./src/cohesive.ts");
|
|
|
90349
90353
|
const equal_1 = __webpack_require__(/*! ./equal */ "./src/equal.ts");
|
|
90350
90354
|
const fair_1 = __webpack_require__(/*! ./fair */ "./src/fair.ts");
|
|
90351
90355
|
// TODO - Score opportunity for minority representation
|
|
90352
|
-
function scorePlan(p) {
|
|
90356
|
+
function scorePlan(p, overridesJSON = undefined) {
|
|
90353
90357
|
// BEST subcategories - compactness, splitting, population deviation
|
|
90354
90358
|
// Compactness
|
|
90355
90359
|
const reockM = compact_1.doReock(p.compactnessProfile.GeometryByDistrict);
|
|
@@ -90636,10 +90640,10 @@ module.exports = JSON.parse("{\"score\":5,\"best\":{\"BestScore\":18,\"compactne
|
|
|
90636
90640
|
|
|
90637
90641
|
/***/ }),
|
|
90638
90642
|
|
|
90639
|
-
/***/ "./node_modules/@dra2020/
|
|
90640
|
-
|
|
90641
|
-
!*** ./node_modules/@dra2020/
|
|
90642
|
-
|
|
90643
|
+
/***/ "./node_modules/@dra2020/dra-types/dist/dra-types.js":
|
|
90644
|
+
/*!***********************************************************!*\
|
|
90645
|
+
!*** ./node_modules/@dra2020/dra-types/dist/dra-types.js ***!
|
|
90646
|
+
\***********************************************************/
|
|
90643
90647
|
/*! no static exports found */
|
|
90644
90648
|
/***/ (function(module, exports, __webpack_require__) {
|
|
90645
90649
|
|
|
@@ -90749,334 +90753,2145 @@ function __export(m) {
|
|
|
90749
90753
|
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
90750
90754
|
}
|
|
90751
90755
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90752
|
-
__export(__webpack_require__(/*! ./
|
|
90753
|
-
__export(__webpack_require__(/*! ./union */ "./lib/union.ts"));
|
|
90756
|
+
__export(__webpack_require__(/*! ./dra-types */ "./lib/dra-types.ts"));
|
|
90754
90757
|
|
|
90755
90758
|
|
|
90756
90759
|
/***/ }),
|
|
90757
90760
|
|
|
90758
|
-
/***/ "./lib/
|
|
90759
|
-
|
|
90760
|
-
!*** ./lib/
|
|
90761
|
-
|
|
90761
|
+
/***/ "./lib/dra-types.ts":
|
|
90762
|
+
/*!**************************!*\
|
|
90763
|
+
!*** ./lib/dra-types.ts ***!
|
|
90764
|
+
\**************************/
|
|
90762
90765
|
/*! no static exports found */
|
|
90763
90766
|
/***/ (function(module, exports, __webpack_require__) {
|
|
90764
90767
|
|
|
90765
90768
|
"use strict";
|
|
90766
90769
|
|
|
90767
90770
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90771
|
+
// Public libraries
|
|
90772
|
+
const Hash = __webpack_require__(/*! object-hash */ "object-hash");
|
|
90768
90773
|
const Util = __webpack_require__(/*! @dra2020/util */ "@dra2020/util");
|
|
90769
|
-
//
|
|
90770
|
-
|
|
90771
|
-
|
|
90772
|
-
|
|
90773
|
-
|
|
90774
|
-
|
|
90775
|
-
|
|
90776
|
-
let p1;
|
|
90777
|
-
let p2;
|
|
90778
|
-
let p3;
|
|
90779
|
-
let dx;
|
|
90780
|
-
let l;
|
|
90781
|
-
let m;
|
|
90782
|
-
let u;
|
|
90783
|
-
let i;
|
|
90784
|
-
let total = 0;
|
|
90785
|
-
let n = p.length;
|
|
90786
|
-
if (n > 2) {
|
|
90787
|
-
for (i = 0; i < n; i++) {
|
|
90788
|
-
if (i === n - 2) {
|
|
90789
|
-
l = n - 2;
|
|
90790
|
-
m = n - 1;
|
|
90791
|
-
u = 0;
|
|
90792
|
-
}
|
|
90793
|
-
else if (i === n - 1) {
|
|
90794
|
-
l = n - 1;
|
|
90795
|
-
m = 0;
|
|
90796
|
-
u = 1;
|
|
90797
|
-
}
|
|
90798
|
-
else {
|
|
90799
|
-
l = i;
|
|
90800
|
-
m = i + 1;
|
|
90801
|
-
u = i + 2;
|
|
90802
|
-
}
|
|
90803
|
-
p1 = p[l];
|
|
90804
|
-
p2 = p[m];
|
|
90805
|
-
p3 = p[u];
|
|
90806
|
-
dx = (Util.deg2rad(p3[0]) - Util.deg2rad(p1[0]));
|
|
90807
|
-
dx *= Math.sin(Util.deg2rad(p2[1]));
|
|
90808
|
-
total += dx;
|
|
90809
|
-
}
|
|
90810
|
-
total *= exports.EARTH_RADIUS * exports.EARTH_RADIUS / 2;
|
|
90811
|
-
}
|
|
90812
|
-
return Math.abs(total);
|
|
90813
|
-
}
|
|
90814
|
-
// Allow bare polygon coordinates array or GeoJSON feature.
|
|
90815
|
-
// Normalize to multipolygon points array.
|
|
90816
|
-
function polyNormalize(poly, options) {
|
|
90817
|
-
if (options === undefined)
|
|
90818
|
-
options = DefaultOptions;
|
|
90819
|
-
// Convert a GeoJSON polygon or multipolygon to the raw list of points
|
|
90820
|
-
if (poly && poly.geometry && poly.geometry.coordinates)
|
|
90821
|
-
poly = poly.geometry.coordinates;
|
|
90822
|
-
// This is really an invalid specification but used internally to represent null polygon
|
|
90823
|
-
if (poly && poly.length == 0)
|
|
90824
|
-
return null;
|
|
90825
|
-
if (Util.depthof(poly) == 4)
|
|
90826
|
-
poly = [poly];
|
|
90827
|
-
return poly;
|
|
90774
|
+
// Canonical hashing of splitblock data
|
|
90775
|
+
function hash(o) {
|
|
90776
|
+
return Hash(o, { respectType: false,
|
|
90777
|
+
unorderedArrays: true,
|
|
90778
|
+
unorderedObjects: true,
|
|
90779
|
+
excludeKeys: (k) => (k === 'id' || k === 'chunk')
|
|
90780
|
+
});
|
|
90828
90781
|
}
|
|
90829
|
-
|
|
90830
|
-
|
|
90831
|
-
|
|
90832
|
-
if (
|
|
90833
|
-
|
|
90834
|
-
|
|
90835
|
-
|
|
90836
|
-
|
|
90837
|
-
|
|
90838
|
-
|
|
90839
|
-
|
|
90840
|
-
|
|
90841
|
-
|
|
90842
|
-
|
|
90782
|
+
function vgeoidToGeoid(vgeoid) {
|
|
90783
|
+
let re = /vfeature_([^_]*)_.*/;
|
|
90784
|
+
let a = re.exec(vgeoid);
|
|
90785
|
+
if (a == null || a.length != 2)
|
|
90786
|
+
return '';
|
|
90787
|
+
else
|
|
90788
|
+
return a[1];
|
|
90789
|
+
}
|
|
90790
|
+
exports.vgeoidToGeoid = vgeoidToGeoid;
|
|
90791
|
+
function vgeoidToChunk(vgeoid) {
|
|
90792
|
+
// vgeoid is string of form: "vfeature_[geoid]_[chunkid]_[hash]"
|
|
90793
|
+
// the contents are chunked into a file of form "vfeature_chunk_[chunkid]"
|
|
90794
|
+
// So extract the chunk ID and download that.
|
|
90795
|
+
let re = /vfeature_([^_]*)_([^_*])_(.*)/;
|
|
90796
|
+
let a = re.exec(vgeoid);
|
|
90797
|
+
if (a && a.length == 4)
|
|
90798
|
+
vgeoid = `vfeature_chunk_${a[2]}`;
|
|
90799
|
+
else
|
|
90800
|
+
vgeoid = null;
|
|
90801
|
+
return vgeoid;
|
|
90802
|
+
}
|
|
90803
|
+
exports.vgeoidToChunk = vgeoidToChunk;
|
|
90804
|
+
function vgeoidToHash(vgeoid) {
|
|
90805
|
+
// vgeoid is string of form: "vfeature_[geoid]_[chunkid]_[hash]"
|
|
90806
|
+
let re = /vfeature_([^_]*)_([^_*])_(.*)/;
|
|
90807
|
+
let a = re.exec(vgeoid);
|
|
90808
|
+
if (a && a.length == 4)
|
|
90809
|
+
vgeoid = a[3];
|
|
90810
|
+
else
|
|
90811
|
+
vgeoid = null;
|
|
90812
|
+
return vgeoid;
|
|
90813
|
+
}
|
|
90814
|
+
exports.vgeoidToHash = vgeoidToHash;
|
|
90815
|
+
function isVfeature(geoid) {
|
|
90816
|
+
return geoid.indexOf('vfeature') === 0;
|
|
90817
|
+
}
|
|
90818
|
+
exports.isVfeature = isVfeature;
|
|
90819
|
+
function splitToCacheKey(s) {
|
|
90820
|
+
if (s.id === undefined)
|
|
90821
|
+
s.id = hash(s);
|
|
90822
|
+
if (s.chunk === undefined)
|
|
90823
|
+
s.chunk = "0";
|
|
90824
|
+
return `_${s.state}_${s.datasource}_vfeature_${s.geoid}_${s.chunk}_${s.id}.geojson`;
|
|
90825
|
+
}
|
|
90826
|
+
exports.splitToCacheKey = splitToCacheKey;
|
|
90827
|
+
function splitToChunkKey(s) {
|
|
90828
|
+
if (s.chunk === undefined)
|
|
90829
|
+
s.chunk = "0";
|
|
90830
|
+
return `_${s.state}_${s.datasource}_vfeature_chunk_${s.chunk}.geojson`;
|
|
90831
|
+
}
|
|
90832
|
+
exports.splitToChunkKey = splitToChunkKey;
|
|
90833
|
+
function splitToPrefix(s) {
|
|
90834
|
+
if (s.blocks === undefined) {
|
|
90835
|
+
let re = /_([^_]*)_(.*)_vfeature.*\.geojson$/;
|
|
90836
|
+
let a = re.exec(s.id);
|
|
90837
|
+
if (a && a.length == 3)
|
|
90838
|
+
return `_${a[1]}_${a[2]}`;
|
|
90839
|
+
return s.id;
|
|
90840
|
+
}
|
|
90841
|
+
return `_${s.state}_${s.datasource}`;
|
|
90842
|
+
}
|
|
90843
|
+
exports.splitToPrefix = splitToPrefix;
|
|
90844
|
+
function cacheKeysToChunkHash(keys) {
|
|
90845
|
+
return hash(keys);
|
|
90846
|
+
}
|
|
90847
|
+
exports.cacheKeysToChunkHash = cacheKeysToChunkHash;
|
|
90848
|
+
let reNumeric = /^(\D*)(\d*)(\D*)$/;
|
|
90849
|
+
let reDistrictNumber = /^\d+$/;
|
|
90850
|
+
let reDistrictNumeric = /^\d/;
|
|
90851
|
+
// Normalize any numeric part to have no padded leading zeros
|
|
90852
|
+
function canonicalDistrictID(districtID) {
|
|
90853
|
+
let a = reNumeric.exec(districtID);
|
|
90854
|
+
if (a && a.length == 4) {
|
|
90855
|
+
if (a[2].length > 0)
|
|
90856
|
+
a[2] = String(Number(a[2]));
|
|
90857
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
90858
|
+
}
|
|
90859
|
+
return districtID;
|
|
90860
|
+
}
|
|
90861
|
+
exports.canonicalDistrictID = canonicalDistrictID;
|
|
90862
|
+
// Normalize any numeric part to have four digits with padded leading zeros
|
|
90863
|
+
function canonicalSortingDistrictID(districtID) {
|
|
90864
|
+
let a = reNumeric.exec(districtID);
|
|
90865
|
+
if (a && a.length == 4) {
|
|
90866
|
+
let s = a[2];
|
|
90867
|
+
if (s.length > 0) {
|
|
90868
|
+
switch (s.length) {
|
|
90869
|
+
case 1:
|
|
90870
|
+
s = `000${s}`;
|
|
90871
|
+
break;
|
|
90872
|
+
case 2:
|
|
90873
|
+
s = `00${s}`;
|
|
90874
|
+
break;
|
|
90875
|
+
case 3:
|
|
90876
|
+
s = `0${s}`;
|
|
90877
|
+
break;
|
|
90878
|
+
}
|
|
90879
|
+
a[2] = s;
|
|
90843
90880
|
}
|
|
90881
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
90844
90882
|
}
|
|
90845
|
-
return
|
|
90846
|
-
}
|
|
90847
|
-
exports.polyArea = polyArea;
|
|
90848
|
-
// Return distance in meters given two lat/lon points
|
|
90849
|
-
function haversine(x1, y1, x2, y2, options) {
|
|
90850
|
-
let dLat = Util.deg2rad(y2 - y1);
|
|
90851
|
-
let dLon = Util.deg2rad(x2 - x1);
|
|
90852
|
-
let c;
|
|
90853
|
-
// Short circuit for using simple cartesian algorithm instead of haversine
|
|
90854
|
-
if (options.noLatitudeCorrection)
|
|
90855
|
-
c = Math.sqrt((dLat * dLat) + (dLon * dLon));
|
|
90856
|
-
else {
|
|
90857
|
-
let lat1 = Util.deg2rad(y1);
|
|
90858
|
-
let lat2 = Util.deg2rad(y2);
|
|
90859
|
-
let a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
90860
|
-
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
|
|
90861
|
-
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
90862
|
-
}
|
|
90863
|
-
return exports.EARTH_RADIUS * c;
|
|
90883
|
+
return districtID;
|
|
90864
90884
|
}
|
|
90865
|
-
|
|
90866
|
-
|
|
90867
|
-
|
|
90868
|
-
|
|
90869
|
-
|
|
90870
|
-
|
|
90871
|
-
|
|
90872
|
-
|
|
90873
|
-
let p = poly[i][0];
|
|
90874
|
-
for (let j = 0; j < p.length - 1; j++)
|
|
90875
|
-
perimeter += haversine(p[j][0], p[j][1], p[j + 1][0], p[j + 1][1], options);
|
|
90876
|
-
if (p.length > 2 && (p[0][0] != p[p.length - 1][0] || p[0][1] != p[p.length - 1][1]))
|
|
90877
|
-
perimeter += haversine(p[0][0], p[0][1], p[p.length - 1][0], p[p.length - 1][1], options);
|
|
90885
|
+
exports.canonicalSortingDistrictID = canonicalSortingDistrictID;
|
|
90886
|
+
// Return numeric part of districtID (or -1 if there is none)
|
|
90887
|
+
function canonicalNumericFromDistrictID(districtID) {
|
|
90888
|
+
let a = reNumeric.exec(districtID);
|
|
90889
|
+
if (a && a.length == 4) {
|
|
90890
|
+
let s = a[2];
|
|
90891
|
+
if (s.length > 0)
|
|
90892
|
+
return Number(s);
|
|
90878
90893
|
}
|
|
90879
|
-
return
|
|
90894
|
+
return -1;
|
|
90880
90895
|
}
|
|
90881
|
-
exports.
|
|
90882
|
-
|
|
90883
|
-
|
|
90884
|
-
|
|
90885
|
-
|
|
90896
|
+
exports.canonicalNumericFromDistrictID = canonicalNumericFromDistrictID;
|
|
90897
|
+
function canonicalDistrictIDFromNumber(districtID, n) {
|
|
90898
|
+
let a = reNumeric.exec(districtID);
|
|
90899
|
+
if (a && a.length == 4) {
|
|
90900
|
+
a[2] = String(n);
|
|
90901
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
90886
90902
|
}
|
|
90903
|
+
else
|
|
90904
|
+
districtID = String(n);
|
|
90905
|
+
return districtID;
|
|
90887
90906
|
}
|
|
90888
|
-
|
|
90889
|
-
|
|
90890
|
-
|
|
90891
|
-
|
|
90892
|
-
|
|
90907
|
+
exports.canonicalDistrictIDFromNumber = canonicalDistrictIDFromNumber;
|
|
90908
|
+
function canonicalDistrictIDOrdering(order) {
|
|
90909
|
+
let keys = Object.keys(order);
|
|
90910
|
+
let i;
|
|
90911
|
+
let a = [];
|
|
90912
|
+
let template = undefined;
|
|
90913
|
+
keys = keys.map((s) => canonicalSortingDistrictID(s));
|
|
90914
|
+
keys.sort();
|
|
90915
|
+
order = {};
|
|
90916
|
+
for (i = 0; i < keys.length; i++)
|
|
90917
|
+
order[canonicalDistrictID(keys[i])] = i + 1;
|
|
90918
|
+
// Remove water districts
|
|
90919
|
+
if (order['ZZZ'])
|
|
90920
|
+
delete order['ZZZ'];
|
|
90921
|
+
if (order['ZZ'])
|
|
90922
|
+
delete order['ZZ'];
|
|
90923
|
+
return order;
|
|
90924
|
+
}
|
|
90925
|
+
exports.canonicalDistrictIDOrdering = canonicalDistrictIDOrdering;
|
|
90926
|
+
let reArray = [
|
|
90927
|
+
/^(\d\d[^\s,"']*)[\s]*,[\s]*([^\s'"]+)[\s]*$/,
|
|
90928
|
+
/^["'](\d\d[^"']*)["'][\s]*,[\s]*["']([^"']*)["'][\s]*$/,
|
|
90929
|
+
/^(\d\d[^\s,]*)[\s]*,[\s]*["']([^"']*)["'][\s]*$/,
|
|
90930
|
+
/^["'](\d\d[^"']*)["'][\s]*,[\s]*([^\s]+)[\s]*$/,
|
|
90931
|
+
];
|
|
90932
|
+
function parseCSVLine(line) {
|
|
90933
|
+
if (line == null || line == '')
|
|
90934
|
+
return null;
|
|
90935
|
+
for (let i = 0; i < reArray.length; i++) {
|
|
90936
|
+
let a = reArray[i].exec(line);
|
|
90937
|
+
if (a && a.length === 3)
|
|
90938
|
+
return { geoid: a[1], districtID: a[2] };
|
|
90893
90939
|
}
|
|
90940
|
+
return null;
|
|
90894
90941
|
}
|
|
90895
|
-
exports.
|
|
90896
|
-
|
|
90897
|
-
|
|
90898
|
-
|
|
90899
|
-
|
|
90900
|
-
|
|
90901
|
-
//
|
|
90902
|
-
function polyToCircle(poly, options) {
|
|
90903
|
-
if (options === undefined)
|
|
90904
|
-
options = DefaultOptions;
|
|
90905
|
-
return makeCircle(polyToExteriorPoints(poly));
|
|
90942
|
+
exports.parseCSVLine = parseCSVLine;
|
|
90943
|
+
function blockmapToState(blockMap) {
|
|
90944
|
+
for (var id in blockMap)
|
|
90945
|
+
if (blockMap.hasOwnProperty(id))
|
|
90946
|
+
return geoidToState(id);
|
|
90947
|
+
return null;
|
|
90906
90948
|
}
|
|
90907
|
-
exports.
|
|
90949
|
+
exports.blockmapToState = blockmapToState;
|
|
90950
|
+
// blockToVTD:
|
|
90951
|
+
// Take BlockMapping (simple map of GEOID to districtID) and a per-state map of block-level GEOID to VTD
|
|
90952
|
+
// and return the output mapping of VTD to districtID, as well a data structure that describes any VTD's
|
|
90953
|
+
// that need to be split between districtIDs. Also returns the DistrictOrder structure that defines the
|
|
90954
|
+
// districtIDs that were used by the file.
|
|
90908
90955
|
//
|
|
90909
|
-
//
|
|
90910
|
-
//
|
|
90956
|
+
// The state (as specified by the first two digits of the GEOID) is also determined. If the GEOID's do
|
|
90957
|
+
// not all specify the same state, the mapping is considered invalid and the outValid flag is set to false.
|
|
90911
90958
|
//
|
|
90912
|
-
function
|
|
90913
|
-
|
|
90914
|
-
|
|
90915
|
-
|
|
90916
|
-
|
|
90917
|
-
|
|
90918
|
-
|
|
90919
|
-
|
|
90920
|
-
|
|
90921
|
-
}
|
|
90922
|
-
|
|
90923
|
-
|
|
90924
|
-
|
|
90925
|
-
|
|
90926
|
-
|
|
90927
|
-
|
|
90928
|
-
|
|
90929
|
-
|
|
90930
|
-
|
|
90931
|
-
|
|
90932
|
-
|
|
90933
|
-
|
|
90934
|
-
|
|
90935
|
-
|
|
90936
|
-
|
|
90937
|
-
|
|
90938
|
-
|
|
90939
|
-
|
|
90940
|
-
|
|
90941
|
-
|
|
90942
|
-
|
|
90943
|
-
|
|
90944
|
-
|
|
90945
|
-
|
|
90946
|
-
|
|
90947
|
-
|
|
90948
|
-
|
|
90949
|
-
|
|
90959
|
+
function blockmapToVTDmap(blockMap, stateMap) {
|
|
90960
|
+
let res = {
|
|
90961
|
+
inBlockMap: blockMap,
|
|
90962
|
+
inStateMap: stateMap,
|
|
90963
|
+
outValid: true,
|
|
90964
|
+
outState: null,
|
|
90965
|
+
outMap: {},
|
|
90966
|
+
outOrder: {},
|
|
90967
|
+
outDistrictToSplit: {}
|
|
90968
|
+
};
|
|
90969
|
+
let bmGather = {};
|
|
90970
|
+
let revMap = {};
|
|
90971
|
+
let id;
|
|
90972
|
+
if (stateMap)
|
|
90973
|
+
for (id in stateMap)
|
|
90974
|
+
if (stateMap.hasOwnProperty(id))
|
|
90975
|
+
revMap[stateMap[id]] = null;
|
|
90976
|
+
// First aggregate into features across all the blocks
|
|
90977
|
+
for (id in blockMap)
|
|
90978
|
+
if (blockMap.hasOwnProperty(id)) {
|
|
90979
|
+
let state = geoidToState(id);
|
|
90980
|
+
if (res.outState == null)
|
|
90981
|
+
res.outState = state;
|
|
90982
|
+
else if (res.outState !== state) {
|
|
90983
|
+
res.outValid = false;
|
|
90984
|
+
break;
|
|
90985
|
+
}
|
|
90986
|
+
let districtID = canonicalDistrictID(blockMap[id]);
|
|
90987
|
+
// Just ignore ZZZ (water) blocks
|
|
90988
|
+
if (districtID === 'ZZZ')
|
|
90989
|
+
continue;
|
|
90990
|
+
let n = id.length;
|
|
90991
|
+
let geoid;
|
|
90992
|
+
// Simple test for block id (vs. voting district or block group) id
|
|
90993
|
+
if (n >= 15) {
|
|
90994
|
+
if (stateMap && stateMap[id] !== undefined)
|
|
90995
|
+
geoid = stateMap[id];
|
|
90996
|
+
else {
|
|
90997
|
+
geoid = id.substr(0, 12); // heuristic for mapping blockID to blockgroupID
|
|
90998
|
+
if (revMap[geoid] === undefined) {
|
|
90999
|
+
res.outValid = false;
|
|
91000
|
+
break;
|
|
91001
|
+
}
|
|
91002
|
+
}
|
|
91003
|
+
}
|
|
90950
91004
|
else
|
|
90951
|
-
|
|
91005
|
+
geoid = id;
|
|
91006
|
+
if (res.outOrder[districtID] === undefined)
|
|
91007
|
+
res.outOrder[districtID] = 0;
|
|
91008
|
+
let districtToBlocks = bmGather[geoid];
|
|
91009
|
+
if (districtToBlocks === undefined)
|
|
91010
|
+
bmGather[geoid] = { [districtID]: { [id]: true } };
|
|
91011
|
+
else {
|
|
91012
|
+
let thisDistrict = districtToBlocks[districtID];
|
|
91013
|
+
if (thisDistrict === undefined) {
|
|
91014
|
+
thisDistrict = {};
|
|
91015
|
+
districtToBlocks[districtID] = thisDistrict;
|
|
91016
|
+
}
|
|
91017
|
+
thisDistrict[id] = true;
|
|
91018
|
+
}
|
|
90952
91019
|
}
|
|
90953
|
-
|
|
90954
|
-
|
|
90955
|
-
|
|
90956
|
-
|
|
90957
|
-
|
|
90958
|
-
|
|
90959
|
-
|
|
90960
|
-
|
|
90961
|
-
|
|
90962
|
-
|
|
90963
|
-
|
|
90964
|
-
|
|
90965
|
-
|
|
90966
|
-
|
|
90967
|
-
|
|
90968
|
-
|
|
90969
|
-
|
|
90970
|
-
|
|
90971
|
-
|
|
90972
|
-
|
|
90973
|
-
|
|
90974
|
-
|
|
90975
|
-
// Select which circle to return
|
|
90976
|
-
if (left === null && right === null)
|
|
90977
|
-
return circ;
|
|
90978
|
-
else if (left === null && right !== null)
|
|
90979
|
-
return right;
|
|
90980
|
-
else if (left !== null && right === null)
|
|
90981
|
-
return left;
|
|
90982
|
-
else if (left !== null && right !== null)
|
|
90983
|
-
return left.r <= right.r ? left : right;
|
|
90984
|
-
else
|
|
90985
|
-
throw "Assertion error";
|
|
90986
|
-
}
|
|
90987
|
-
function makeDiameter(a, b) {
|
|
90988
|
-
const cx = (a.x + b.x) / 2;
|
|
90989
|
-
const cy = (a.y + b.y) / 2;
|
|
90990
|
-
const r0 = Util.distance(cx, cy, a.x, a.y);
|
|
90991
|
-
const r1 = Util.distance(cx, cy, b.x, b.y);
|
|
90992
|
-
return new Circle(cx, cy, Math.max(r0, r1));
|
|
91020
|
+
// Now determine actual mapping of blocks to features, looking for split features
|
|
91021
|
+
for (let geoid in bmGather)
|
|
91022
|
+
if (bmGather.hasOwnProperty(geoid)) {
|
|
91023
|
+
let districtToBlocks = bmGather[geoid];
|
|
91024
|
+
if (Util.countKeys(districtToBlocks) == 1) {
|
|
91025
|
+
res.outMap[geoid] = Util.nthKey(districtToBlocks);
|
|
91026
|
+
}
|
|
91027
|
+
else {
|
|
91028
|
+
for (let districtID in districtToBlocks)
|
|
91029
|
+
if (districtToBlocks.hasOwnProperty(districtID)) {
|
|
91030
|
+
let split = { state: '', datasource: '', geoid: geoid, blocks: Object.keys(districtToBlocks[districtID]) };
|
|
91031
|
+
let splits = res.outDistrictToSplit[districtID];
|
|
91032
|
+
if (splits === undefined) {
|
|
91033
|
+
splits = [];
|
|
91034
|
+
res.outDistrictToSplit[districtID] = splits;
|
|
91035
|
+
}
|
|
91036
|
+
splits.push(split);
|
|
91037
|
+
}
|
|
91038
|
+
}
|
|
91039
|
+
}
|
|
91040
|
+
res.outOrder = canonicalDistrictIDOrdering(res.outOrder);
|
|
91041
|
+
return res;
|
|
90993
91042
|
}
|
|
90994
|
-
|
|
90995
|
-
|
|
90996
|
-
|
|
90997
|
-
|
|
90998
|
-
|
|
90999
|
-
|
|
91000
|
-
|
|
91001
|
-
|
|
91002
|
-
|
|
91003
|
-
|
|
91004
|
-
|
|
91005
|
-
|
|
91043
|
+
exports.blockmapToVTDmap = blockmapToVTDmap;
|
|
91044
|
+
exports.GEOIDToState = {
|
|
91045
|
+
'01': 'AL',
|
|
91046
|
+
'02': 'AK',
|
|
91047
|
+
'04': 'AZ',
|
|
91048
|
+
'05': 'AR',
|
|
91049
|
+
'06': 'CA',
|
|
91050
|
+
'08': 'CO',
|
|
91051
|
+
'09': 'CT',
|
|
91052
|
+
'10': 'DE',
|
|
91053
|
+
'12': 'FL',
|
|
91054
|
+
'13': 'GA',
|
|
91055
|
+
'15': 'HI',
|
|
91056
|
+
'16': 'ID',
|
|
91057
|
+
'17': 'IL',
|
|
91058
|
+
'18': 'IN',
|
|
91059
|
+
'19': 'IA',
|
|
91060
|
+
'20': 'KS',
|
|
91061
|
+
'21': 'KY',
|
|
91062
|
+
'22': 'LA',
|
|
91063
|
+
'23': 'ME',
|
|
91064
|
+
'24': 'MD',
|
|
91065
|
+
'25': 'MA',
|
|
91066
|
+
'26': 'MI',
|
|
91067
|
+
'27': 'MN',
|
|
91068
|
+
'28': 'MS',
|
|
91069
|
+
'29': 'MO',
|
|
91070
|
+
'30': 'MT',
|
|
91071
|
+
'31': 'NE',
|
|
91072
|
+
'32': 'NV',
|
|
91073
|
+
'33': 'NH',
|
|
91074
|
+
'34': 'NJ',
|
|
91075
|
+
'35': 'NM',
|
|
91076
|
+
'36': 'NY',
|
|
91077
|
+
'37': 'NC',
|
|
91078
|
+
'38': 'ND',
|
|
91079
|
+
'39': 'OH',
|
|
91080
|
+
'40': 'OK',
|
|
91081
|
+
'41': 'OR',
|
|
91082
|
+
'42': 'PA',
|
|
91083
|
+
'44': 'RI',
|
|
91084
|
+
'45': 'SC',
|
|
91085
|
+
'46': 'SD',
|
|
91086
|
+
'47': 'TN',
|
|
91087
|
+
'48': 'TX',
|
|
91088
|
+
'49': 'UT',
|
|
91089
|
+
'50': 'VT',
|
|
91090
|
+
'51': 'VA',
|
|
91091
|
+
'53': 'WA',
|
|
91092
|
+
'54': 'WV',
|
|
91093
|
+
'55': 'WI',
|
|
91094
|
+
'56': 'WY',
|
|
91095
|
+
};
|
|
91096
|
+
exports.StateToGEOID = {
|
|
91097
|
+
'AL': '01',
|
|
91098
|
+
'AK': '02',
|
|
91099
|
+
'AZ': '04',
|
|
91100
|
+
'AR': '05',
|
|
91101
|
+
'CA': '06',
|
|
91102
|
+
'CO': '08',
|
|
91103
|
+
'CT': '09',
|
|
91104
|
+
'DE': '10',
|
|
91105
|
+
'FL': '12',
|
|
91106
|
+
'GA': '13',
|
|
91107
|
+
'HI': '15',
|
|
91108
|
+
'ID': '16',
|
|
91109
|
+
'IL': '17',
|
|
91110
|
+
'IN': '18',
|
|
91111
|
+
'IA': '19',
|
|
91112
|
+
'KS': '20',
|
|
91113
|
+
'KY': '21',
|
|
91114
|
+
'LA': '22',
|
|
91115
|
+
'ME': '23',
|
|
91116
|
+
'MD': '24',
|
|
91117
|
+
'MA': '25',
|
|
91118
|
+
'MI': '26',
|
|
91119
|
+
'MN': '27',
|
|
91120
|
+
'MS': '28',
|
|
91121
|
+
'MO': '29',
|
|
91122
|
+
'MT': '30',
|
|
91123
|
+
'NE': '31',
|
|
91124
|
+
'NV': '32',
|
|
91125
|
+
'NH': '33',
|
|
91126
|
+
'NJ': '34',
|
|
91127
|
+
'NM': '35',
|
|
91128
|
+
'NY': '36',
|
|
91129
|
+
'NC': '37',
|
|
91130
|
+
'ND': '38',
|
|
91131
|
+
'OH': '39',
|
|
91132
|
+
'OK': '40',
|
|
91133
|
+
'OR': '41',
|
|
91134
|
+
'PA': '42',
|
|
91135
|
+
'RI': '44',
|
|
91136
|
+
'SC': '45',
|
|
91137
|
+
'SD': '46',
|
|
91138
|
+
'TN': '47',
|
|
91139
|
+
'TX': '48',
|
|
91140
|
+
'UT': '49',
|
|
91141
|
+
'VT': '50',
|
|
91142
|
+
'VA': '51',
|
|
91143
|
+
'WA': '53',
|
|
91144
|
+
'WV': '54',
|
|
91145
|
+
'WI': '55',
|
|
91146
|
+
'WY': '56',
|
|
91147
|
+
};
|
|
91148
|
+
function geoidToState(geoid) {
|
|
91149
|
+
let re = /^(..).*$/;
|
|
91150
|
+
let a = re.exec(geoid);
|
|
91151
|
+
if (a == null || a.length != 2)
|
|
91006
91152
|
return null;
|
|
91007
|
-
|
|
91008
|
-
const y = oy + ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d;
|
|
91009
|
-
const ra = Util.distance(x, y, a.x, a.y);
|
|
91010
|
-
const rb = Util.distance(x, y, b.x, b.y);
|
|
91011
|
-
const rc = Util.distance(x, y, c.x, c.y);
|
|
91012
|
-
return new Circle(x, y, Math.max(ra, rb, rc));
|
|
91013
|
-
}
|
|
91014
|
-
/* Simple mathematical functions */
|
|
91015
|
-
const MULTIPLICATIVE_EPSILON = 1 + 1e-14;
|
|
91016
|
-
function isInCircle(c, p) {
|
|
91017
|
-
return c !== null && Util.distance(p.x, p.y, c.x, c.y) <= c.r * MULTIPLICATIVE_EPSILON;
|
|
91153
|
+
return exports.GEOIDToState[a[1]];
|
|
91018
91154
|
}
|
|
91019
|
-
|
|
91020
|
-
|
|
91021
|
-
|
|
91155
|
+
exports.geoidToState = geoidToState;
|
|
91156
|
+
|
|
91157
|
+
|
|
91158
|
+
/***/ }),
|
|
91159
|
+
|
|
91160
|
+
/***/ "@dra2020/util":
|
|
91161
|
+
/*!********************************!*\
|
|
91162
|
+
!*** external "@dra2020/util" ***!
|
|
91163
|
+
\********************************/
|
|
91164
|
+
/*! no static exports found */
|
|
91165
|
+
/***/ (function(module, exports) {
|
|
91166
|
+
|
|
91167
|
+
module.exports = __webpack_require__(/*! @dra2020/util */ "./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js");
|
|
91168
|
+
|
|
91169
|
+
/***/ }),
|
|
91170
|
+
|
|
91171
|
+
/***/ "object-hash":
|
|
91172
|
+
/*!******************************!*\
|
|
91173
|
+
!*** external "object-hash" ***!
|
|
91174
|
+
\******************************/
|
|
91175
|
+
/*! no static exports found */
|
|
91176
|
+
/***/ (function(module, exports) {
|
|
91177
|
+
|
|
91178
|
+
module.exports = __webpack_require__(/*! object-hash */ "./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js");
|
|
91179
|
+
|
|
91180
|
+
/***/ })
|
|
91181
|
+
|
|
91182
|
+
/******/ });
|
|
91183
|
+
});
|
|
91184
|
+
|
|
91185
|
+
|
|
91186
|
+
/***/ }),
|
|
91187
|
+
|
|
91188
|
+
/***/ "./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js":
|
|
91189
|
+
/*!*********************************************************************************!*\
|
|
91190
|
+
!*** ./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js ***!
|
|
91191
|
+
\*********************************************************************************/
|
|
91192
|
+
/*! no static exports found */
|
|
91193
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91194
|
+
|
|
91195
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
91196
|
+
if(true)
|
|
91197
|
+
module.exports = factory();
|
|
91198
|
+
else {}
|
|
91199
|
+
})(global, function() {
|
|
91200
|
+
return /******/ (function(modules) { // webpackBootstrap
|
|
91201
|
+
/******/ // The module cache
|
|
91202
|
+
/******/ var installedModules = {};
|
|
91203
|
+
/******/
|
|
91204
|
+
/******/ // The require function
|
|
91205
|
+
/******/ function __webpack_require__(moduleId) {
|
|
91206
|
+
/******/
|
|
91207
|
+
/******/ // Check if module is in cache
|
|
91208
|
+
/******/ if(installedModules[moduleId]) {
|
|
91209
|
+
/******/ return installedModules[moduleId].exports;
|
|
91210
|
+
/******/ }
|
|
91211
|
+
/******/ // Create a new module (and put it into the cache)
|
|
91212
|
+
/******/ var module = installedModules[moduleId] = {
|
|
91213
|
+
/******/ i: moduleId,
|
|
91214
|
+
/******/ l: false,
|
|
91215
|
+
/******/ exports: {}
|
|
91216
|
+
/******/ };
|
|
91217
|
+
/******/
|
|
91218
|
+
/******/ // Execute the module function
|
|
91219
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
91220
|
+
/******/
|
|
91221
|
+
/******/ // Flag the module as loaded
|
|
91222
|
+
/******/ module.l = true;
|
|
91223
|
+
/******/
|
|
91224
|
+
/******/ // Return the exports of the module
|
|
91225
|
+
/******/ return module.exports;
|
|
91226
|
+
/******/ }
|
|
91227
|
+
/******/
|
|
91228
|
+
/******/
|
|
91229
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
91230
|
+
/******/ __webpack_require__.m = modules;
|
|
91231
|
+
/******/
|
|
91232
|
+
/******/ // expose the module cache
|
|
91233
|
+
/******/ __webpack_require__.c = installedModules;
|
|
91234
|
+
/******/
|
|
91235
|
+
/******/ // define getter function for harmony exports
|
|
91236
|
+
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
91237
|
+
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
91238
|
+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
91239
|
+
/******/ }
|
|
91240
|
+
/******/ };
|
|
91241
|
+
/******/
|
|
91242
|
+
/******/ // define __esModule on exports
|
|
91243
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
91244
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
91245
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
91246
|
+
/******/ }
|
|
91247
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
91248
|
+
/******/ };
|
|
91249
|
+
/******/
|
|
91250
|
+
/******/ // create a fake namespace object
|
|
91251
|
+
/******/ // mode & 1: value is a module id, require it
|
|
91252
|
+
/******/ // mode & 2: merge all properties of value into the ns
|
|
91253
|
+
/******/ // mode & 4: return value when already ns object
|
|
91254
|
+
/******/ // mode & 8|1: behave like require
|
|
91255
|
+
/******/ __webpack_require__.t = function(value, mode) {
|
|
91256
|
+
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
91257
|
+
/******/ if(mode & 8) return value;
|
|
91258
|
+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
91259
|
+
/******/ var ns = Object.create(null);
|
|
91260
|
+
/******/ __webpack_require__.r(ns);
|
|
91261
|
+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
91262
|
+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
91263
|
+
/******/ return ns;
|
|
91264
|
+
/******/ };
|
|
91265
|
+
/******/
|
|
91266
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
91267
|
+
/******/ __webpack_require__.n = function(module) {
|
|
91268
|
+
/******/ var getter = module && module.__esModule ?
|
|
91269
|
+
/******/ function getDefault() { return module['default']; } :
|
|
91270
|
+
/******/ function getModuleExports() { return module; };
|
|
91271
|
+
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
91272
|
+
/******/ return getter;
|
|
91273
|
+
/******/ };
|
|
91274
|
+
/******/
|
|
91275
|
+
/******/ // Object.prototype.hasOwnProperty.call
|
|
91276
|
+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
91277
|
+
/******/
|
|
91278
|
+
/******/ // __webpack_public_path__
|
|
91279
|
+
/******/ __webpack_require__.p = "";
|
|
91280
|
+
/******/
|
|
91281
|
+
/******/
|
|
91282
|
+
/******/ // Load entry module and return exports
|
|
91283
|
+
/******/ return __webpack_require__(__webpack_require__.s = "./lib/all.ts");
|
|
91284
|
+
/******/ })
|
|
91285
|
+
/************************************************************************/
|
|
91286
|
+
/******/ ({
|
|
91287
|
+
|
|
91288
|
+
/***/ "./lib/all.ts":
|
|
91289
|
+
/*!********************!*\
|
|
91290
|
+
!*** ./lib/all.ts ***!
|
|
91291
|
+
\********************/
|
|
91292
|
+
/*! no static exports found */
|
|
91293
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91294
|
+
|
|
91295
|
+
"use strict";
|
|
91296
|
+
|
|
91297
|
+
function __export(m) {
|
|
91298
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
91022
91299
|
}
|
|
91023
|
-
|
|
91024
|
-
|
|
91025
|
-
|
|
91026
|
-
|
|
91027
|
-
|
|
91028
|
-
|
|
91029
|
-
|
|
91030
|
-
|
|
91031
|
-
|
|
91032
|
-
|
|
91033
|
-
|
|
91034
|
-
|
|
91035
|
-
|
|
91036
|
-
|
|
91037
|
-
|
|
91038
|
-
|
|
91039
|
-
|
|
91040
|
-
|
|
91041
|
-
|
|
91042
|
-
|
|
91043
|
-
|
|
91044
|
-
}
|
|
91045
|
-
|
|
91046
|
-
|
|
91047
|
-
|
|
91048
|
-
|
|
91049
|
-
|
|
91300
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91301
|
+
__export(__webpack_require__(/*! ./util */ "./lib/util.ts"));
|
|
91302
|
+
__export(__webpack_require__(/*! ./countedhash */ "./lib/countedhash.ts"));
|
|
91303
|
+
__export(__webpack_require__(/*! ./indexedarray */ "./lib/indexedarray.ts"));
|
|
91304
|
+
|
|
91305
|
+
|
|
91306
|
+
/***/ }),
|
|
91307
|
+
|
|
91308
|
+
/***/ "./lib/countedhash.ts":
|
|
91309
|
+
/*!****************************!*\
|
|
91310
|
+
!*** ./lib/countedhash.ts ***!
|
|
91311
|
+
\****************************/
|
|
91312
|
+
/*! no static exports found */
|
|
91313
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91314
|
+
|
|
91315
|
+
"use strict";
|
|
91316
|
+
|
|
91317
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91318
|
+
class CountedHash {
|
|
91319
|
+
constructor() {
|
|
91320
|
+
this.n = 0;
|
|
91321
|
+
this.val = {};
|
|
91322
|
+
}
|
|
91323
|
+
get length() { return this.n; }
|
|
91324
|
+
test(id) {
|
|
91325
|
+
return id != '' && this.val[id] !== undefined;
|
|
91326
|
+
}
|
|
91327
|
+
set(id) {
|
|
91328
|
+
if (id != '' && !this.test(id)) {
|
|
91329
|
+
this.n++;
|
|
91330
|
+
this.val[id] = true;
|
|
91050
91331
|
}
|
|
91051
|
-
|
|
91052
|
-
|
|
91053
|
-
|
|
91054
|
-
|
|
91055
|
-
|
|
91056
|
-
j = (n - i) * 2;
|
|
91057
|
-
a.push(a[j - 1]);
|
|
91058
|
-
a.push(-a[j - 2]);
|
|
91332
|
+
}
|
|
91333
|
+
clear(id) {
|
|
91334
|
+
if (this.test(id)) {
|
|
91335
|
+
this.n--;
|
|
91336
|
+
delete this.val[id];
|
|
91059
91337
|
}
|
|
91060
|
-
// Duplicate final point per GeoJSON spec
|
|
91061
|
-
a.push(a[0]);
|
|
91062
|
-
a.push(a[1]);
|
|
91063
|
-
circleOffsets[n] = a;
|
|
91064
91338
|
}
|
|
91065
|
-
|
|
91066
|
-
|
|
91067
|
-
|
|
91068
|
-
|
|
91069
|
-
|
|
91070
|
-
|
|
91071
|
-
|
|
91072
|
-
|
|
91073
|
-
|
|
91074
|
-
|
|
91075
|
-
|
|
91076
|
-
|
|
91077
|
-
|
|
91078
|
-
|
|
91079
|
-
|
|
91339
|
+
empty() {
|
|
91340
|
+
this.n = 0;
|
|
91341
|
+
this.val = {};
|
|
91342
|
+
}
|
|
91343
|
+
asArray() {
|
|
91344
|
+
let a = [];
|
|
91345
|
+
this.forEach(id => { a.push(id); });
|
|
91346
|
+
return a;
|
|
91347
|
+
}
|
|
91348
|
+
asString() {
|
|
91349
|
+
for (var id in this.val)
|
|
91350
|
+
if (this.val.hasOwnProperty(id))
|
|
91351
|
+
return id;
|
|
91352
|
+
return '';
|
|
91353
|
+
}
|
|
91354
|
+
forEach(f) {
|
|
91355
|
+
for (var id in this.val)
|
|
91356
|
+
if (this.val.hasOwnProperty(id))
|
|
91357
|
+
f(id);
|
|
91358
|
+
}
|
|
91359
|
+
}
|
|
91360
|
+
exports.CountedHash = CountedHash;
|
|
91361
|
+
|
|
91362
|
+
|
|
91363
|
+
/***/ }),
|
|
91364
|
+
|
|
91365
|
+
/***/ "./lib/indexedarray.ts":
|
|
91366
|
+
/*!*****************************!*\
|
|
91367
|
+
!*** ./lib/indexedarray.ts ***!
|
|
91368
|
+
\*****************************/
|
|
91369
|
+
/*! no static exports found */
|
|
91370
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91371
|
+
|
|
91372
|
+
"use strict";
|
|
91373
|
+
|
|
91374
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91375
|
+
class IndexedArray {
|
|
91376
|
+
constructor() {
|
|
91377
|
+
this.o = {};
|
|
91378
|
+
this.a = null;
|
|
91379
|
+
}
|
|
91380
|
+
ensure() {
|
|
91381
|
+
if (this.a === null) {
|
|
91382
|
+
this.a = [];
|
|
91383
|
+
for (let p in this.o)
|
|
91384
|
+
if (this.o.hasOwnProperty(p))
|
|
91385
|
+
this.a.push(p);
|
|
91386
|
+
this.a.sort((a, b) => { a = a.toUpperCase(); b = b.toUpperCase(); return a < b ? -1 : (a > b ? 1 : 0); });
|
|
91387
|
+
}
|
|
91388
|
+
}
|
|
91389
|
+
asArray() {
|
|
91390
|
+
this.ensure();
|
|
91391
|
+
return this.a;
|
|
91392
|
+
}
|
|
91393
|
+
get length() { this.ensure(); return this.a.length; }
|
|
91394
|
+
test(s) {
|
|
91395
|
+
return !!s && this.o[s] !== undefined;
|
|
91396
|
+
}
|
|
91397
|
+
set(s) {
|
|
91398
|
+
if (!!s && !this.test(s)) {
|
|
91399
|
+
this.o[s] = true;
|
|
91400
|
+
this.a = null;
|
|
91401
|
+
}
|
|
91402
|
+
}
|
|
91403
|
+
setAll(a) {
|
|
91404
|
+
if (a && a.length)
|
|
91405
|
+
for (let i = 0; i < a.length; i++)
|
|
91406
|
+
this.set(a[i]);
|
|
91407
|
+
}
|
|
91408
|
+
clear(s) {
|
|
91409
|
+
if (this.test(s)) {
|
|
91410
|
+
delete this.o[s];
|
|
91411
|
+
this.a = null;
|
|
91412
|
+
}
|
|
91413
|
+
}
|
|
91414
|
+
at(i) {
|
|
91415
|
+
this.ensure();
|
|
91416
|
+
if (i < 0 || i >= this.a.length)
|
|
91417
|
+
return undefined;
|
|
91418
|
+
return this.a[i];
|
|
91419
|
+
}
|
|
91420
|
+
empty() {
|
|
91421
|
+
this.o = {};
|
|
91422
|
+
this.a = null;
|
|
91423
|
+
}
|
|
91424
|
+
forEach(f) {
|
|
91425
|
+
for (var s in this.o)
|
|
91426
|
+
if (this.o.hasOwnProperty(s))
|
|
91427
|
+
f(s);
|
|
91428
|
+
}
|
|
91429
|
+
}
|
|
91430
|
+
exports.IndexedArray = IndexedArray;
|
|
91431
|
+
|
|
91432
|
+
|
|
91433
|
+
/***/ }),
|
|
91434
|
+
|
|
91435
|
+
/***/ "./lib/util.ts":
|
|
91436
|
+
/*!*********************!*\
|
|
91437
|
+
!*** ./lib/util.ts ***!
|
|
91438
|
+
\*********************/
|
|
91439
|
+
/*! no static exports found */
|
|
91440
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91441
|
+
|
|
91442
|
+
"use strict";
|
|
91443
|
+
|
|
91444
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91445
|
+
function Now() { return (new Date()).toJSON(); }
|
|
91446
|
+
exports.Now = Now;
|
|
91447
|
+
class Elapsed {
|
|
91448
|
+
constructor(bStart = true) {
|
|
91449
|
+
this.tStart = undefined;
|
|
91450
|
+
this.tDur = undefined;
|
|
91451
|
+
if (bStart)
|
|
91452
|
+
this.start();
|
|
91453
|
+
}
|
|
91454
|
+
start() {
|
|
91455
|
+
if (process && process.hrtime)
|
|
91456
|
+
this.tStart = process.hrtime();
|
|
91457
|
+
else
|
|
91458
|
+
this.tStart = performance.now();
|
|
91459
|
+
if (this.tDur)
|
|
91460
|
+
this.tDur = undefined;
|
|
91461
|
+
}
|
|
91462
|
+
end() {
|
|
91463
|
+
if (this.tStart === undefined)
|
|
91464
|
+
this.start();
|
|
91465
|
+
if (process && process.hrtime)
|
|
91466
|
+
this.tDur = process.hrtime(this.tStart);
|
|
91467
|
+
else
|
|
91468
|
+
this.tDur = performance.now() - this.tStart;
|
|
91469
|
+
}
|
|
91470
|
+
ms() {
|
|
91471
|
+
if (this.tDur === undefined)
|
|
91472
|
+
this.end();
|
|
91473
|
+
if (process && process.hrtime)
|
|
91474
|
+
return Math.round((this.tDur[0] * 1000) + (this.tDur[1] / 1000000));
|
|
91475
|
+
else
|
|
91476
|
+
return this.tDur;
|
|
91477
|
+
}
|
|
91478
|
+
nano() {
|
|
91479
|
+
if (this.tDur === undefined)
|
|
91480
|
+
this.end();
|
|
91481
|
+
if (process && process.hrtime)
|
|
91482
|
+
return (this.tDur[0] * 1000000000) + this.tDur[1];
|
|
91483
|
+
else
|
|
91484
|
+
return this.tDur * 1000000;
|
|
91485
|
+
}
|
|
91486
|
+
}
|
|
91487
|
+
exports.Elapsed = Elapsed;
|
|
91488
|
+
class Deadline {
|
|
91489
|
+
constructor(msDelta) {
|
|
91490
|
+
this.msDelta = msDelta;
|
|
91491
|
+
this.elapsed = new Elapsed();
|
|
91492
|
+
}
|
|
91493
|
+
done() {
|
|
91494
|
+
this.elapsed.end();
|
|
91495
|
+
return this.elapsed.ms() > this.msDelta;
|
|
91496
|
+
}
|
|
91497
|
+
}
|
|
91498
|
+
exports.Deadline = Deadline;
|
|
91499
|
+
function createGuid() {
|
|
91500
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
91501
|
+
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
91502
|
+
return v.toString(16);
|
|
91503
|
+
});
|
|
91504
|
+
}
|
|
91505
|
+
exports.createGuid = createGuid;
|
|
91506
|
+
function _sizeof(a, loops) {
|
|
91507
|
+
if (a === null || a === undefined)
|
|
91508
|
+
return 0;
|
|
91509
|
+
switch (typeof a) {
|
|
91510
|
+
default: return 0;
|
|
91511
|
+
case 'number': return 8;
|
|
91512
|
+
case 'boolean': return 4;
|
|
91513
|
+
case 'string': return a.length * 2;
|
|
91514
|
+
case 'object':
|
|
91515
|
+
{
|
|
91516
|
+
if (loops.has(a))
|
|
91517
|
+
return 0;
|
|
91518
|
+
else
|
|
91519
|
+
loops.set(a, true);
|
|
91520
|
+
let t = 0;
|
|
91521
|
+
if (Array.isArray(a)) {
|
|
91522
|
+
for (let i = 0; i < a.length; i++)
|
|
91523
|
+
t += _sizeof(a[i], loops);
|
|
91524
|
+
t += 8; // length
|
|
91525
|
+
}
|
|
91526
|
+
else if (Buffer.isBuffer(a)) {
|
|
91527
|
+
t = a.length;
|
|
91528
|
+
}
|
|
91529
|
+
else if (a.hasOwnProperty === undefined)
|
|
91530
|
+
return t;
|
|
91531
|
+
else {
|
|
91532
|
+
for (var key in a)
|
|
91533
|
+
if (a.hasOwnProperty && a.hasOwnProperty(key)) {
|
|
91534
|
+
t += _sizeof(key, loops); // this is a good estimate of download size, but poor estimate of internal size
|
|
91535
|
+
// because of JS object templating vs. naive hashtables
|
|
91536
|
+
t += _sizeof(a[key], loops);
|
|
91537
|
+
}
|
|
91538
|
+
}
|
|
91539
|
+
return t;
|
|
91540
|
+
}
|
|
91541
|
+
}
|
|
91542
|
+
}
|
|
91543
|
+
function sizeof(a) {
|
|
91544
|
+
let loops = new WeakMap();
|
|
91545
|
+
let n = _sizeof(a, loops);
|
|
91546
|
+
return n;
|
|
91547
|
+
}
|
|
91548
|
+
exports.sizeof = sizeof;
|
|
91549
|
+
function depthof(a) {
|
|
91550
|
+
if (a === null || a === undefined)
|
|
91551
|
+
return 1;
|
|
91552
|
+
switch (typeof a) {
|
|
91553
|
+
default: return 1;
|
|
91554
|
+
case 'number': return 1;
|
|
91555
|
+
case 'boolean': return 1;
|
|
91556
|
+
case 'string': return 1;
|
|
91557
|
+
case 'object':
|
|
91558
|
+
{
|
|
91559
|
+
let d = 0;
|
|
91560
|
+
if (Array.isArray(a))
|
|
91561
|
+
return a.length > 0 ? (1 + depthof(a[0])) : 2; // still return 2 for empty array
|
|
91562
|
+
else if (Buffer.isBuffer(a))
|
|
91563
|
+
return 2;
|
|
91564
|
+
else if (a.hasOwnProperty === undefined)
|
|
91565
|
+
return 1;
|
|
91566
|
+
else {
|
|
91567
|
+
for (var key in a)
|
|
91568
|
+
if (a.hasOwnProperty(key))
|
|
91569
|
+
return 1 + depthof(a[key]);
|
|
91570
|
+
return 2; // or 2 for empty object
|
|
91571
|
+
}
|
|
91572
|
+
}
|
|
91573
|
+
}
|
|
91574
|
+
}
|
|
91575
|
+
exports.depthof = depthof;
|
|
91576
|
+
function isEmpty(o) {
|
|
91577
|
+
if (o === null || o === undefined)
|
|
91578
|
+
return true;
|
|
91579
|
+
for (var p in o)
|
|
91580
|
+
if (o.hasOwnProperty(p))
|
|
91581
|
+
return false;
|
|
91582
|
+
return true;
|
|
91583
|
+
}
|
|
91584
|
+
exports.isEmpty = isEmpty;
|
|
91585
|
+
function countKeys(o) {
|
|
91586
|
+
if (o === undefined || typeof o !== 'object')
|
|
91587
|
+
return -1;
|
|
91588
|
+
let count = 0;
|
|
91589
|
+
for (let p in o)
|
|
91590
|
+
if (o.hasOwnProperty(p))
|
|
91591
|
+
count++;
|
|
91592
|
+
return count;
|
|
91593
|
+
}
|
|
91594
|
+
exports.countKeys = countKeys;
|
|
91595
|
+
function nthProperty(o, n = 0) {
|
|
91596
|
+
for (let p in o)
|
|
91597
|
+
if (o.hasOwnProperty(p)) {
|
|
91598
|
+
if (n <= 0)
|
|
91599
|
+
return o[p];
|
|
91600
|
+
n--;
|
|
91601
|
+
}
|
|
91602
|
+
return undefined;
|
|
91603
|
+
}
|
|
91604
|
+
exports.nthProperty = nthProperty;
|
|
91605
|
+
function nthKey(o, n = 0) {
|
|
91606
|
+
for (let p in o)
|
|
91607
|
+
if (o.hasOwnProperty(p)) {
|
|
91608
|
+
if (n <= 0)
|
|
91609
|
+
return p;
|
|
91610
|
+
n--;
|
|
91611
|
+
}
|
|
91612
|
+
return undefined;
|
|
91613
|
+
}
|
|
91614
|
+
exports.nthKey = nthKey;
|
|
91615
|
+
function partialEqual(o, subset) {
|
|
91616
|
+
for (let p in subset)
|
|
91617
|
+
if (subset.hasOwnProperty(p))
|
|
91618
|
+
if (o[p] !== subset[p])
|
|
91619
|
+
return false;
|
|
91620
|
+
return true;
|
|
91621
|
+
}
|
|
91622
|
+
exports.partialEqual = partialEqual;
|
|
91623
|
+
function deepEqual(o1, o2, options) {
|
|
91624
|
+
if (typeof o1 !== typeof o2)
|
|
91625
|
+
return false;
|
|
91626
|
+
if (typeof o1 !== 'object')
|
|
91627
|
+
return o1 === o2;
|
|
91628
|
+
// Special case array
|
|
91629
|
+
if (Array.isArray(o1)) {
|
|
91630
|
+
if (!Array.isArray(o2))
|
|
91631
|
+
return false;
|
|
91632
|
+
if (o1.length != o2.length)
|
|
91633
|
+
return false;
|
|
91634
|
+
if (options && options.unorderedArrays) {
|
|
91635
|
+
o1 = o1.sort();
|
|
91636
|
+
o2 = o2.sort();
|
|
91637
|
+
}
|
|
91638
|
+
for (let i = 0; i < o1.length; i++)
|
|
91639
|
+
if (!deepEqual(o1[i], o2[i], options))
|
|
91640
|
+
return false;
|
|
91641
|
+
return true;
|
|
91642
|
+
}
|
|
91643
|
+
// Special case object
|
|
91644
|
+
if (o1.hasOwnProperty === undefined || o2.hasOwnProperty === undefined)
|
|
91645
|
+
return o1 === o2;
|
|
91646
|
+
for (let p in o1)
|
|
91647
|
+
if (o1.hasOwnProperty(p)) {
|
|
91648
|
+
if (options && options.omitKey[p])
|
|
91649
|
+
continue;
|
|
91650
|
+
if (o2[p] === undefined)
|
|
91651
|
+
return false;
|
|
91652
|
+
if (!deepEqual(o1[p], o2[p], options))
|
|
91653
|
+
return false;
|
|
91654
|
+
}
|
|
91655
|
+
// If any properties in o2 aren't in o1, not equal
|
|
91656
|
+
for (let p in o2)
|
|
91657
|
+
if (o2.hasOwnProperty(p)) {
|
|
91658
|
+
if (options && options.omitKey[p])
|
|
91659
|
+
continue;
|
|
91660
|
+
if (o1[p] === undefined)
|
|
91661
|
+
return false;
|
|
91662
|
+
}
|
|
91663
|
+
return true;
|
|
91664
|
+
}
|
|
91665
|
+
exports.deepEqual = deepEqual;
|
|
91666
|
+
const Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
91667
|
+
function prettyDate(d) {
|
|
91668
|
+
if (d == null)
|
|
91669
|
+
return 'unknown';
|
|
91670
|
+
let mmm = Months[d.getMonth()];
|
|
91671
|
+
let dd = d.getDate();
|
|
91672
|
+
let yyyy = d.getFullYear();
|
|
91673
|
+
let hh = d.getHours();
|
|
91674
|
+
let m = d.getMinutes();
|
|
91675
|
+
let mm = m < 10 ? `0${m}` : String(m);
|
|
91676
|
+
let ampm = hh >= 12 ? 'PM' : 'AM';
|
|
91677
|
+
if (hh > 12)
|
|
91678
|
+
hh -= 12;
|
|
91679
|
+
return `${mmm} ${dd}, ${yyyy} at ${hh}:${mm} ${ampm}`;
|
|
91680
|
+
}
|
|
91681
|
+
exports.prettyDate = prettyDate;
|
|
91682
|
+
function relativeDate(d) {
|
|
91683
|
+
if (d == null)
|
|
91684
|
+
return 'unknown';
|
|
91685
|
+
let now = new Date();
|
|
91686
|
+
let yyyyNow = now.getFullYear();
|
|
91687
|
+
let mmmNow = Months[now.getMonth()];
|
|
91688
|
+
let ddNow = now.getDate();
|
|
91689
|
+
let mmm = Months[d.getMonth()];
|
|
91690
|
+
let dd = d.getDate();
|
|
91691
|
+
let yyyy = d.getFullYear();
|
|
91692
|
+
let hh = d.getHours();
|
|
91693
|
+
let m = d.getMinutes();
|
|
91694
|
+
let mm = m < 10 ? `0${m}` : String(m);
|
|
91695
|
+
let ampm = hh >= 12 ? 'PM' : 'AM';
|
|
91696
|
+
if (hh > 12)
|
|
91697
|
+
hh -= 12;
|
|
91698
|
+
if (yyyyNow === yyyy && mmmNow === mmm && ddNow === dd)
|
|
91699
|
+
return `Today at ${hh}:${mm} ${ampm}`;
|
|
91700
|
+
else if (yyyyNow === yyyy)
|
|
91701
|
+
return `${mmm} ${dd}`;
|
|
91702
|
+
else
|
|
91703
|
+
return `${mmm} ${dd}, ${yyyy}`;
|
|
91704
|
+
}
|
|
91705
|
+
exports.relativeDate = relativeDate;
|
|
91706
|
+
const OneMinute = 1000 * 60;
|
|
91707
|
+
const OneHour = OneMinute * 60;
|
|
91708
|
+
const OneDay = OneHour * 24;
|
|
91709
|
+
function recentDate(d) {
|
|
91710
|
+
if (d == null)
|
|
91711
|
+
return 'u';
|
|
91712
|
+
let now = new Date();
|
|
91713
|
+
let msNow = now.getTime();
|
|
91714
|
+
let msThen = d.getTime();
|
|
91715
|
+
let msDelta = msNow - msThen;
|
|
91716
|
+
// Within the hour, display in minutes
|
|
91717
|
+
if (msDelta < OneHour)
|
|
91718
|
+
return `${Math.round(msDelta / OneMinute) + 1}m`;
|
|
91719
|
+
// Within the day, display in hours
|
|
91720
|
+
else if (msDelta < OneDay)
|
|
91721
|
+
return `${Math.round(msDelta / OneHour) + 1}h`;
|
|
91722
|
+
// Otherwise, display using relativeDate
|
|
91723
|
+
else
|
|
91724
|
+
return relativeDate(d);
|
|
91725
|
+
}
|
|
91726
|
+
exports.recentDate = recentDate;
|
|
91727
|
+
function textToHtml(sText) {
|
|
91728
|
+
let lines = sText.split('\n');
|
|
91729
|
+
let aHtml = [];
|
|
91730
|
+
let inTable = false;
|
|
91731
|
+
aHtml.push('<body>');
|
|
91732
|
+
for (let i = 0; i < lines.length; i++) {
|
|
91733
|
+
let line = lines[i];
|
|
91734
|
+
let isRow = line.indexOf('|') === 0;
|
|
91735
|
+
if (inTable && !isRow) {
|
|
91736
|
+
aHtml.push('</tbody></table>');
|
|
91737
|
+
inTable = false;
|
|
91738
|
+
}
|
|
91739
|
+
if (isRow && !inTable) {
|
|
91740
|
+
inTable = true;
|
|
91741
|
+
aHtml.push('<table border="1" cellspacing="0" cellpadding="2"><tbody>');
|
|
91742
|
+
}
|
|
91743
|
+
if (isRow) {
|
|
91744
|
+
let cells = line.split('|');
|
|
91745
|
+
if (cells.length > 2) {
|
|
91746
|
+
aHtml.push('<tr>');
|
|
91747
|
+
for (let j = 1; j < cells.length - 1; j++)
|
|
91748
|
+
aHtml.push(`<td>${cells[j]}</td>`);
|
|
91749
|
+
aHtml.push('</tr>');
|
|
91750
|
+
}
|
|
91751
|
+
}
|
|
91752
|
+
else
|
|
91753
|
+
aHtml.push(`<div>${line} </div>`);
|
|
91754
|
+
}
|
|
91755
|
+
if (inTable)
|
|
91756
|
+
aHtml.push('</tbody></table>');
|
|
91757
|
+
aHtml.push('</body>');
|
|
91758
|
+
return aHtml.join('');
|
|
91759
|
+
}
|
|
91760
|
+
exports.textToHtml = textToHtml;
|
|
91761
|
+
function shallowCopy(src) {
|
|
91762
|
+
if (src === null || src === undefined)
|
|
91763
|
+
return src;
|
|
91764
|
+
switch (typeof src) {
|
|
91765
|
+
case 'boolean':
|
|
91766
|
+
case 'number':
|
|
91767
|
+
case 'string':
|
|
91768
|
+
case 'symbol':
|
|
91769
|
+
case 'function':
|
|
91770
|
+
default:
|
|
91771
|
+
return src;
|
|
91772
|
+
case 'object':
|
|
91773
|
+
if (Array.isArray(src))
|
|
91774
|
+
return src.slice();
|
|
91775
|
+
else {
|
|
91776
|
+
let copy = {};
|
|
91777
|
+
for (var p in src)
|
|
91778
|
+
if (src.hasOwnProperty(p))
|
|
91779
|
+
copy[p] = src[p];
|
|
91780
|
+
return copy;
|
|
91781
|
+
}
|
|
91782
|
+
}
|
|
91783
|
+
}
|
|
91784
|
+
exports.shallowCopy = shallowCopy;
|
|
91785
|
+
function shallowAssign(o1, o2) {
|
|
91786
|
+
if (o1 === null || o1 === undefined)
|
|
91787
|
+
o1 = {};
|
|
91788
|
+
if (o2 === null || o2 === undefined)
|
|
91789
|
+
return o1;
|
|
91790
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
91791
|
+
return o1;
|
|
91792
|
+
for (var p in o2)
|
|
91793
|
+
if (o2.hasOwnProperty(p))
|
|
91794
|
+
o1[p] = o2[p];
|
|
91795
|
+
return o1;
|
|
91796
|
+
}
|
|
91797
|
+
exports.shallowAssign = shallowAssign;
|
|
91798
|
+
function shallowDelete(o1, o2) {
|
|
91799
|
+
if (o1 == null || o2 == null)
|
|
91800
|
+
return o1;
|
|
91801
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
91802
|
+
return o1;
|
|
91803
|
+
for (var p in o2)
|
|
91804
|
+
if (o2.hasOwnProperty(p))
|
|
91805
|
+
delete o1[p];
|
|
91806
|
+
return o1;
|
|
91807
|
+
}
|
|
91808
|
+
exports.shallowDelete = shallowDelete;
|
|
91809
|
+
function shallowAssignImmutable(o1, o2) {
|
|
91810
|
+
if (o1 === null || o1 === undefined)
|
|
91811
|
+
o1 = {};
|
|
91812
|
+
if (o2 === null || o2 === undefined)
|
|
91813
|
+
return o1;
|
|
91814
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
91815
|
+
return o1;
|
|
91816
|
+
// First determine whether o2 changes any properties, if it has, make new instance
|
|
91817
|
+
let oNew = o1;
|
|
91818
|
+
for (let p in o2)
|
|
91819
|
+
if (o2.hasOwnProperty(p)) {
|
|
91820
|
+
if (o1[p] != o2[p]) {
|
|
91821
|
+
oNew = shallowCopy(o1);
|
|
91822
|
+
break;
|
|
91823
|
+
}
|
|
91824
|
+
}
|
|
91825
|
+
if (oNew !== o1)
|
|
91826
|
+
shallowAssign(oNew, o2);
|
|
91827
|
+
return oNew;
|
|
91828
|
+
}
|
|
91829
|
+
exports.shallowAssignImmutable = shallowAssignImmutable;
|
|
91830
|
+
function shallowEqual(o1, o2) {
|
|
91831
|
+
if (o1 === undefined || o2 === undefined || typeof o1 !== 'object' || typeof o2 !== 'object')
|
|
91832
|
+
return o1 === o2;
|
|
91833
|
+
if (Array.isArray(o1) && Array.isArray(o2)) {
|
|
91834
|
+
if (o1.length != o2.length)
|
|
91835
|
+
return false;
|
|
91836
|
+
for (let i = 0; i < o1.length; i++)
|
|
91837
|
+
if (o1[i] !== o2[i])
|
|
91838
|
+
return false;
|
|
91839
|
+
return true;
|
|
91840
|
+
}
|
|
91841
|
+
else {
|
|
91842
|
+
let p;
|
|
91843
|
+
for (p in o1)
|
|
91844
|
+
if (o1.hasOwnProperty(p))
|
|
91845
|
+
if (o1[p] !== o2[p])
|
|
91846
|
+
return false;
|
|
91847
|
+
for (p in o2)
|
|
91848
|
+
if (o2.hasOwnProperty(p))
|
|
91849
|
+
if (o1[p] === undefined)
|
|
91850
|
+
return false;
|
|
91851
|
+
return true;
|
|
91852
|
+
}
|
|
91853
|
+
}
|
|
91854
|
+
exports.shallowEqual = shallowEqual;
|
|
91855
|
+
function deepCopy(src) {
|
|
91856
|
+
// Beware typeof oddities
|
|
91857
|
+
if (src === null || src === undefined)
|
|
91858
|
+
return src;
|
|
91859
|
+
if (typeof src === 'object') {
|
|
91860
|
+
if (Array.isArray(src)) {
|
|
91861
|
+
let dst = [];
|
|
91862
|
+
for (let i = 0; i < src.length; i++)
|
|
91863
|
+
dst.push(deepCopy(src[i]));
|
|
91864
|
+
return dst;
|
|
91865
|
+
}
|
|
91866
|
+
else {
|
|
91867
|
+
if (src.hasOwnProperty === undefined)
|
|
91868
|
+
return src;
|
|
91869
|
+
let dst = {};
|
|
91870
|
+
for (var p in src)
|
|
91871
|
+
if (src.hasOwnProperty(p))
|
|
91872
|
+
dst[p] = deepCopy(src[p]);
|
|
91873
|
+
return dst;
|
|
91874
|
+
}
|
|
91875
|
+
}
|
|
91876
|
+
else
|
|
91877
|
+
return src;
|
|
91878
|
+
}
|
|
91879
|
+
exports.deepCopy = deepCopy;
|
|
91880
|
+
function deepAccum(accum, o) {
|
|
91881
|
+
if (accum == null)
|
|
91882
|
+
accum = {};
|
|
91883
|
+
if (o == null)
|
|
91884
|
+
return accum;
|
|
91885
|
+
for (let p in o)
|
|
91886
|
+
if (o.hasOwnProperty(p)) {
|
|
91887
|
+
let vs = o[p];
|
|
91888
|
+
let vd = accum[p];
|
|
91889
|
+
if (typeof vs === 'number') {
|
|
91890
|
+
if (vd !== undefined && typeof vd !== 'number')
|
|
91891
|
+
throw 'deepAccum: unexpected type mismatch';
|
|
91892
|
+
accum[p] = (vd === undefined ? 0 : vd) + vs;
|
|
91893
|
+
}
|
|
91894
|
+
else if (typeof vs === 'object') {
|
|
91895
|
+
if (vd === undefined) {
|
|
91896
|
+
vd = {};
|
|
91897
|
+
accum[p] = vd;
|
|
91898
|
+
}
|
|
91899
|
+
else if (typeof vd !== 'object')
|
|
91900
|
+
throw 'deepAccum: unexpected type mismatch';
|
|
91901
|
+
deepAccum(vd, vs);
|
|
91902
|
+
}
|
|
91903
|
+
}
|
|
91904
|
+
}
|
|
91905
|
+
exports.deepAccum = deepAccum;
|
|
91906
|
+
function precisionRound(n, p) {
|
|
91907
|
+
let f = Math.pow(10, p);
|
|
91908
|
+
return Math.round(n * f) / f;
|
|
91909
|
+
}
|
|
91910
|
+
exports.precisionRound = precisionRound;
|
|
91911
|
+
function percentString(num, den, precision = 0) {
|
|
91912
|
+
if (den == 0)
|
|
91913
|
+
return '(-)';
|
|
91914
|
+
let p = precisionRound((num / den) * 100, precision);
|
|
91915
|
+
return String(p) + '%';
|
|
91916
|
+
}
|
|
91917
|
+
exports.percentString = percentString;
|
|
91918
|
+
function hash(s) {
|
|
91919
|
+
let hash = 5381;
|
|
91920
|
+
let i = s.length;
|
|
91921
|
+
while (i)
|
|
91922
|
+
hash = (hash * 33) ^ s.charCodeAt(--i);
|
|
91923
|
+
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
|
|
91924
|
+
* integers. Since we want the results to be always positive, convert the
|
|
91925
|
+
* signed int to an unsigned by doing an unsigned bitshift. */
|
|
91926
|
+
return hash >>> 0;
|
|
91927
|
+
}
|
|
91928
|
+
exports.hash = hash;
|
|
91929
|
+
function hashObject(o) {
|
|
91930
|
+
return hash(o ? JSON.stringify(o) : '');
|
|
91931
|
+
}
|
|
91932
|
+
exports.hashObject = hashObject;
|
|
91933
|
+
const HexTable = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
|
91934
|
+
function toHex(n) {
|
|
91935
|
+
if (n < 0 || n > 255)
|
|
91936
|
+
throw ('only 0 to 255 supported now');
|
|
91937
|
+
n = Math.floor(n);
|
|
91938
|
+
return HexTable[n >> 4] + HexTable[n & 15];
|
|
91939
|
+
}
|
|
91940
|
+
exports.toHex = toHex;
|
|
91941
|
+
function toRGBA(color, alpha) {
|
|
91942
|
+
let r;
|
|
91943
|
+
let g;
|
|
91944
|
+
let b;
|
|
91945
|
+
switch (color) {
|
|
91946
|
+
case 'white':
|
|
91947
|
+
r = 255;
|
|
91948
|
+
g = 255;
|
|
91949
|
+
b = 255;
|
|
91950
|
+
break;
|
|
91951
|
+
case 'black':
|
|
91952
|
+
r = 0;
|
|
91953
|
+
g = 0;
|
|
91954
|
+
b = 0;
|
|
91955
|
+
break;
|
|
91956
|
+
default:
|
|
91957
|
+
r = parseInt(color.substr(1, 2), 16);
|
|
91958
|
+
g = parseInt(color.substr(3, 2), 16);
|
|
91959
|
+
b = parseInt(color.substr(5, 2), 16);
|
|
91960
|
+
break;
|
|
91961
|
+
}
|
|
91962
|
+
return `rgba(${String(r)}, ${String(g)}, ${String(b)}, ${String(alpha)})`;
|
|
91963
|
+
}
|
|
91964
|
+
exports.toRGBA = toRGBA;
|
|
91965
|
+
function toRGBAIntensity(color, intensity, alpha) {
|
|
91966
|
+
// for now assume color is black
|
|
91967
|
+
let g = precisionRound(255 * intensity, 0);
|
|
91968
|
+
return `rgba(${String(g)}, ${String(g)}, ${String(g)}, ${String(alpha)})`;
|
|
91969
|
+
}
|
|
91970
|
+
exports.toRGBAIntensity = toRGBAIntensity;
|
|
91971
|
+
// Geo functions
|
|
91972
|
+
function distance(x0, y0, x1, y1) {
|
|
91973
|
+
return Math.hypot(x0 - x1, y0 - y1);
|
|
91974
|
+
}
|
|
91975
|
+
exports.distance = distance;
|
|
91976
|
+
function deg2rad(num) { return num * Math.PI / 180; }
|
|
91977
|
+
exports.deg2rad = deg2rad;
|
|
91978
|
+
function rad2deg(num) { return num / Math.PI * 180; }
|
|
91979
|
+
exports.rad2deg = rad2deg;
|
|
91980
|
+
// Restricts lon to range [-180..180]
|
|
91981
|
+
function wrapLon(lon) {
|
|
91982
|
+
let worlds = Math.floor((lon + 180) / 360);
|
|
91983
|
+
return lon - (worlds * 360);
|
|
91984
|
+
}
|
|
91985
|
+
exports.wrapLon = wrapLon;
|
|
91986
|
+
|
|
91987
|
+
|
|
91988
|
+
/***/ })
|
|
91989
|
+
|
|
91990
|
+
/******/ });
|
|
91991
|
+
});
|
|
91992
|
+
|
|
91993
|
+
|
|
91994
|
+
/***/ }),
|
|
91995
|
+
|
|
91996
|
+
/***/ "./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js":
|
|
91997
|
+
/*!***************************************************************************!*\
|
|
91998
|
+
!*** ./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js ***!
|
|
91999
|
+
\***************************************************************************/
|
|
92000
|
+
/*! no static exports found */
|
|
92001
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
92002
|
+
|
|
92003
|
+
"use strict";
|
|
92004
|
+
|
|
92005
|
+
|
|
92006
|
+
var crypto = __webpack_require__(/*! crypto */ "crypto");
|
|
92007
|
+
|
|
92008
|
+
/**
|
|
92009
|
+
* Exported function
|
|
92010
|
+
*
|
|
92011
|
+
* Options:
|
|
92012
|
+
*
|
|
92013
|
+
* - `algorithm` hash algo to be used by this instance: *'sha1', 'md5'
|
|
92014
|
+
* - `excludeValues` {true|*false} hash object keys, values ignored
|
|
92015
|
+
* - `encoding` hash encoding, supports 'buffer', '*hex', 'binary', 'base64'
|
|
92016
|
+
* - `ignoreUnknown` {true|*false} ignore unknown object types
|
|
92017
|
+
* - `replacer` optional function that replaces values before hashing
|
|
92018
|
+
* - `respectFunctionProperties` {*true|false} consider function properties when hashing
|
|
92019
|
+
* - `respectFunctionNames` {*true|false} consider 'name' property of functions for hashing
|
|
92020
|
+
* - `respectType` {*true|false} Respect special properties (prototype, constructor)
|
|
92021
|
+
* when hashing to distinguish between types
|
|
92022
|
+
* - `unorderedArrays` {true|*false} Sort all arrays before hashing
|
|
92023
|
+
* - `unorderedSets` {*true|false} Sort `Set` and `Map` instances before hashing
|
|
92024
|
+
* * = default
|
|
92025
|
+
*
|
|
92026
|
+
* @param {object} object value to hash
|
|
92027
|
+
* @param {object} options hashing options
|
|
92028
|
+
* @return {string} hash value
|
|
92029
|
+
* @api public
|
|
92030
|
+
*/
|
|
92031
|
+
exports = module.exports = objectHash;
|
|
92032
|
+
|
|
92033
|
+
function objectHash(object, options){
|
|
92034
|
+
options = applyDefaults(object, options);
|
|
92035
|
+
|
|
92036
|
+
return hash(object, options);
|
|
92037
|
+
}
|
|
92038
|
+
|
|
92039
|
+
/**
|
|
92040
|
+
* Exported sugar methods
|
|
92041
|
+
*
|
|
92042
|
+
* @param {object} object value to hash
|
|
92043
|
+
* @return {string} hash value
|
|
92044
|
+
* @api public
|
|
92045
|
+
*/
|
|
92046
|
+
exports.sha1 = function(object){
|
|
92047
|
+
return objectHash(object);
|
|
92048
|
+
};
|
|
92049
|
+
exports.keys = function(object){
|
|
92050
|
+
return objectHash(object, {excludeValues: true, algorithm: 'sha1', encoding: 'hex'});
|
|
92051
|
+
};
|
|
92052
|
+
exports.MD5 = function(object){
|
|
92053
|
+
return objectHash(object, {algorithm: 'md5', encoding: 'hex'});
|
|
92054
|
+
};
|
|
92055
|
+
exports.keysMD5 = function(object){
|
|
92056
|
+
return objectHash(object, {algorithm: 'md5', encoding: 'hex', excludeValues: true});
|
|
92057
|
+
};
|
|
92058
|
+
|
|
92059
|
+
// Internals
|
|
92060
|
+
var hashes = crypto.getHashes ? crypto.getHashes().slice() : ['sha1', 'md5'];
|
|
92061
|
+
hashes.push('passthrough');
|
|
92062
|
+
var encodings = ['buffer', 'hex', 'binary', 'base64'];
|
|
92063
|
+
|
|
92064
|
+
function applyDefaults(object, sourceOptions){
|
|
92065
|
+
sourceOptions = sourceOptions || {};
|
|
92066
|
+
|
|
92067
|
+
// create a copy rather than mutating
|
|
92068
|
+
var options = {};
|
|
92069
|
+
options.algorithm = sourceOptions.algorithm || 'sha1';
|
|
92070
|
+
options.encoding = sourceOptions.encoding || 'hex';
|
|
92071
|
+
options.excludeValues = sourceOptions.excludeValues ? true : false;
|
|
92072
|
+
options.algorithm = options.algorithm.toLowerCase();
|
|
92073
|
+
options.encoding = options.encoding.toLowerCase();
|
|
92074
|
+
options.ignoreUnknown = sourceOptions.ignoreUnknown !== true ? false : true; // default to false
|
|
92075
|
+
options.respectType = sourceOptions.respectType === false ? false : true; // default to true
|
|
92076
|
+
options.respectFunctionNames = sourceOptions.respectFunctionNames === false ? false : true;
|
|
92077
|
+
options.respectFunctionProperties = sourceOptions.respectFunctionProperties === false ? false : true;
|
|
92078
|
+
options.unorderedArrays = sourceOptions.unorderedArrays !== true ? false : true; // default to false
|
|
92079
|
+
options.unorderedSets = sourceOptions.unorderedSets === false ? false : true; // default to false
|
|
92080
|
+
options.unorderedObjects = sourceOptions.unorderedObjects === false ? false : true; // default to true
|
|
92081
|
+
options.replacer = sourceOptions.replacer || undefined;
|
|
92082
|
+
options.excludeKeys = sourceOptions.excludeKeys || undefined;
|
|
92083
|
+
|
|
92084
|
+
if(typeof object === 'undefined') {
|
|
92085
|
+
throw new Error('Object argument required.');
|
|
92086
|
+
}
|
|
92087
|
+
|
|
92088
|
+
// if there is a case-insensitive match in the hashes list, accept it
|
|
92089
|
+
// (i.e. SHA256 for sha256)
|
|
92090
|
+
for (var i = 0; i < hashes.length; ++i) {
|
|
92091
|
+
if (hashes[i].toLowerCase() === options.algorithm.toLowerCase()) {
|
|
92092
|
+
options.algorithm = hashes[i];
|
|
92093
|
+
}
|
|
92094
|
+
}
|
|
92095
|
+
|
|
92096
|
+
if(hashes.indexOf(options.algorithm) === -1){
|
|
92097
|
+
throw new Error('Algorithm "' + options.algorithm + '" not supported. ' +
|
|
92098
|
+
'supported values: ' + hashes.join(', '));
|
|
92099
|
+
}
|
|
92100
|
+
|
|
92101
|
+
if(encodings.indexOf(options.encoding) === -1 &&
|
|
92102
|
+
options.algorithm !== 'passthrough'){
|
|
92103
|
+
throw new Error('Encoding "' + options.encoding + '" not supported. ' +
|
|
92104
|
+
'supported values: ' + encodings.join(', '));
|
|
92105
|
+
}
|
|
92106
|
+
|
|
92107
|
+
return options;
|
|
92108
|
+
}
|
|
92109
|
+
|
|
92110
|
+
/** Check if the given function is a native function */
|
|
92111
|
+
function isNativeFunction(f) {
|
|
92112
|
+
if ((typeof f) !== 'function') {
|
|
92113
|
+
return false;
|
|
92114
|
+
}
|
|
92115
|
+
var exp = /^function\s+\w*\s*\(\s*\)\s*{\s+\[native code\]\s+}$/i;
|
|
92116
|
+
return exp.exec(Function.prototype.toString.call(f)) != null;
|
|
92117
|
+
}
|
|
92118
|
+
|
|
92119
|
+
function hash(object, options) {
|
|
92120
|
+
var hashingStream;
|
|
92121
|
+
|
|
92122
|
+
if (options.algorithm !== 'passthrough') {
|
|
92123
|
+
hashingStream = crypto.createHash(options.algorithm);
|
|
92124
|
+
} else {
|
|
92125
|
+
hashingStream = new PassThrough();
|
|
92126
|
+
}
|
|
92127
|
+
|
|
92128
|
+
if (typeof hashingStream.write === 'undefined') {
|
|
92129
|
+
hashingStream.write = hashingStream.update;
|
|
92130
|
+
hashingStream.end = hashingStream.update;
|
|
92131
|
+
}
|
|
92132
|
+
|
|
92133
|
+
var hasher = typeHasher(options, hashingStream);
|
|
92134
|
+
hasher.dispatch(object);
|
|
92135
|
+
if (!hashingStream.update) {
|
|
92136
|
+
hashingStream.end('');
|
|
92137
|
+
}
|
|
92138
|
+
|
|
92139
|
+
if (hashingStream.digest) {
|
|
92140
|
+
return hashingStream.digest(options.encoding === 'buffer' ? undefined : options.encoding);
|
|
92141
|
+
}
|
|
92142
|
+
|
|
92143
|
+
var buf = hashingStream.read();
|
|
92144
|
+
if (options.encoding === 'buffer') {
|
|
92145
|
+
return buf;
|
|
92146
|
+
}
|
|
92147
|
+
|
|
92148
|
+
return buf.toString(options.encoding);
|
|
92149
|
+
}
|
|
92150
|
+
|
|
92151
|
+
/**
|
|
92152
|
+
* Expose streaming API
|
|
92153
|
+
*
|
|
92154
|
+
* @param {object} object Value to serialize
|
|
92155
|
+
* @param {object} options Options, as for hash()
|
|
92156
|
+
* @param {object} stream A stream to write the serializiation to
|
|
92157
|
+
* @api public
|
|
92158
|
+
*/
|
|
92159
|
+
exports.writeToStream = function(object, options, stream) {
|
|
92160
|
+
if (typeof stream === 'undefined') {
|
|
92161
|
+
stream = options;
|
|
92162
|
+
options = {};
|
|
92163
|
+
}
|
|
92164
|
+
|
|
92165
|
+
options = applyDefaults(object, options);
|
|
92166
|
+
|
|
92167
|
+
return typeHasher(options, stream).dispatch(object);
|
|
92168
|
+
};
|
|
92169
|
+
|
|
92170
|
+
function typeHasher(options, writeTo, context){
|
|
92171
|
+
context = context || [];
|
|
92172
|
+
var write = function(str) {
|
|
92173
|
+
if (writeTo.update) {
|
|
92174
|
+
return writeTo.update(str, 'utf8');
|
|
92175
|
+
} else {
|
|
92176
|
+
return writeTo.write(str, 'utf8');
|
|
92177
|
+
}
|
|
92178
|
+
};
|
|
92179
|
+
|
|
92180
|
+
return {
|
|
92181
|
+
dispatch: function(value){
|
|
92182
|
+
if (options.replacer) {
|
|
92183
|
+
value = options.replacer(value);
|
|
92184
|
+
}
|
|
92185
|
+
|
|
92186
|
+
var type = typeof value;
|
|
92187
|
+
if (value === null) {
|
|
92188
|
+
type = 'null';
|
|
92189
|
+
}
|
|
92190
|
+
|
|
92191
|
+
//console.log("[DEBUG] Dispatch: ", value, "->", type, " -> ", "_" + type);
|
|
92192
|
+
|
|
92193
|
+
return this['_' + type](value);
|
|
92194
|
+
},
|
|
92195
|
+
_object: function(object) {
|
|
92196
|
+
var pattern = (/\[object (.*)\]/i);
|
|
92197
|
+
var objString = Object.prototype.toString.call(object);
|
|
92198
|
+
var objType = pattern.exec(objString);
|
|
92199
|
+
if (!objType) { // object type did not match [object ...]
|
|
92200
|
+
objType = 'unknown:[' + objString + ']';
|
|
92201
|
+
} else {
|
|
92202
|
+
objType = objType[1]; // take only the class name
|
|
92203
|
+
}
|
|
92204
|
+
|
|
92205
|
+
objType = objType.toLowerCase();
|
|
92206
|
+
|
|
92207
|
+
var objectNumber = null;
|
|
92208
|
+
|
|
92209
|
+
if ((objectNumber = context.indexOf(object)) >= 0) {
|
|
92210
|
+
return this.dispatch('[CIRCULAR:' + objectNumber + ']');
|
|
92211
|
+
} else {
|
|
92212
|
+
context.push(object);
|
|
92213
|
+
}
|
|
92214
|
+
|
|
92215
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(object)) {
|
|
92216
|
+
write('buffer:');
|
|
92217
|
+
return write(object);
|
|
92218
|
+
}
|
|
92219
|
+
|
|
92220
|
+
if(objType !== 'object' && objType !== 'function') {
|
|
92221
|
+
if(this['_' + objType]) {
|
|
92222
|
+
this['_' + objType](object);
|
|
92223
|
+
} else if (options.ignoreUnknown) {
|
|
92224
|
+
return write('[' + objType + ']');
|
|
92225
|
+
} else {
|
|
92226
|
+
throw new Error('Unknown object type "' + objType + '"');
|
|
92227
|
+
}
|
|
92228
|
+
}else{
|
|
92229
|
+
var keys = Object.keys(object);
|
|
92230
|
+
if (options.unorderedObjects) {
|
|
92231
|
+
keys = keys.sort();
|
|
92232
|
+
}
|
|
92233
|
+
// Make sure to incorporate special properties, so
|
|
92234
|
+
// Types with different prototypes will produce
|
|
92235
|
+
// a different hash and objects derived from
|
|
92236
|
+
// different functions (`new Foo`, `new Bar`) will
|
|
92237
|
+
// produce different hashes.
|
|
92238
|
+
// We never do this for native functions since some
|
|
92239
|
+
// seem to break because of that.
|
|
92240
|
+
if (options.respectType !== false && !isNativeFunction(object)) {
|
|
92241
|
+
keys.splice(0, 0, 'prototype', '__proto__', 'constructor');
|
|
92242
|
+
}
|
|
92243
|
+
|
|
92244
|
+
if (options.excludeKeys) {
|
|
92245
|
+
keys = keys.filter(function(key) { return !options.excludeKeys(key); });
|
|
92246
|
+
}
|
|
92247
|
+
|
|
92248
|
+
write('object:' + keys.length + ':');
|
|
92249
|
+
var self = this;
|
|
92250
|
+
return keys.forEach(function(key){
|
|
92251
|
+
self.dispatch(key);
|
|
92252
|
+
write(':');
|
|
92253
|
+
if(!options.excludeValues) {
|
|
92254
|
+
self.dispatch(object[key]);
|
|
92255
|
+
}
|
|
92256
|
+
write(',');
|
|
92257
|
+
});
|
|
92258
|
+
}
|
|
92259
|
+
},
|
|
92260
|
+
_array: function(arr, unordered){
|
|
92261
|
+
unordered = typeof unordered !== 'undefined' ? unordered :
|
|
92262
|
+
options.unorderedArrays !== false; // default to options.unorderedArrays
|
|
92263
|
+
|
|
92264
|
+
var self = this;
|
|
92265
|
+
write('array:' + arr.length + ':');
|
|
92266
|
+
if (!unordered || arr.length <= 1) {
|
|
92267
|
+
return arr.forEach(function(entry) {
|
|
92268
|
+
return self.dispatch(entry);
|
|
92269
|
+
});
|
|
92270
|
+
}
|
|
92271
|
+
|
|
92272
|
+
// the unordered case is a little more complicated:
|
|
92273
|
+
// since there is no canonical ordering on objects,
|
|
92274
|
+
// i.e. {a:1} < {a:2} and {a:1} > {a:2} are both false,
|
|
92275
|
+
// we first serialize each entry using a PassThrough stream
|
|
92276
|
+
// before sorting.
|
|
92277
|
+
// also: we can’t use the same context array for all entries
|
|
92278
|
+
// since the order of hashing should *not* matter. instead,
|
|
92279
|
+
// we keep track of the additions to a copy of the context array
|
|
92280
|
+
// and add all of them to the global context array when we’re done
|
|
92281
|
+
var contextAdditions = [];
|
|
92282
|
+
var entries = arr.map(function(entry) {
|
|
92283
|
+
var strm = new PassThrough();
|
|
92284
|
+
var localContext = context.slice(); // make copy
|
|
92285
|
+
var hasher = typeHasher(options, strm, localContext);
|
|
92286
|
+
hasher.dispatch(entry);
|
|
92287
|
+
// take only what was added to localContext and append it to contextAdditions
|
|
92288
|
+
contextAdditions = contextAdditions.concat(localContext.slice(context.length));
|
|
92289
|
+
return strm.read().toString();
|
|
92290
|
+
});
|
|
92291
|
+
context = context.concat(contextAdditions);
|
|
92292
|
+
entries.sort();
|
|
92293
|
+
return this._array(entries, false);
|
|
92294
|
+
},
|
|
92295
|
+
_date: function(date){
|
|
92296
|
+
return write('date:' + date.toJSON());
|
|
92297
|
+
},
|
|
92298
|
+
_symbol: function(sym){
|
|
92299
|
+
return write('symbol:' + sym.toString());
|
|
92300
|
+
},
|
|
92301
|
+
_error: function(err){
|
|
92302
|
+
return write('error:' + err.toString());
|
|
92303
|
+
},
|
|
92304
|
+
_boolean: function(bool){
|
|
92305
|
+
return write('bool:' + bool.toString());
|
|
92306
|
+
},
|
|
92307
|
+
_string: function(string){
|
|
92308
|
+
write('string:' + string.length + ':');
|
|
92309
|
+
write(string.toString());
|
|
92310
|
+
},
|
|
92311
|
+
_function: function(fn){
|
|
92312
|
+
write('fn:');
|
|
92313
|
+
if (isNativeFunction(fn)) {
|
|
92314
|
+
this.dispatch('[native]');
|
|
92315
|
+
} else {
|
|
92316
|
+
this.dispatch(fn.toString());
|
|
92317
|
+
}
|
|
92318
|
+
|
|
92319
|
+
if (options.respectFunctionNames !== false) {
|
|
92320
|
+
// Make sure we can still distinguish native functions
|
|
92321
|
+
// by their name, otherwise String and Function will
|
|
92322
|
+
// have the same hash
|
|
92323
|
+
this.dispatch("function-name:" + String(fn.name));
|
|
92324
|
+
}
|
|
92325
|
+
|
|
92326
|
+
if (options.respectFunctionProperties) {
|
|
92327
|
+
this._object(fn);
|
|
92328
|
+
}
|
|
92329
|
+
},
|
|
92330
|
+
_number: function(number){
|
|
92331
|
+
return write('number:' + number.toString());
|
|
92332
|
+
},
|
|
92333
|
+
_xml: function(xml){
|
|
92334
|
+
return write('xml:' + xml.toString());
|
|
92335
|
+
},
|
|
92336
|
+
_null: function() {
|
|
92337
|
+
return write('Null');
|
|
92338
|
+
},
|
|
92339
|
+
_undefined: function() {
|
|
92340
|
+
return write('Undefined');
|
|
92341
|
+
},
|
|
92342
|
+
_regexp: function(regex){
|
|
92343
|
+
return write('regex:' + regex.toString());
|
|
92344
|
+
},
|
|
92345
|
+
_uint8array: function(arr){
|
|
92346
|
+
write('uint8array:');
|
|
92347
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92348
|
+
},
|
|
92349
|
+
_uint8clampedarray: function(arr){
|
|
92350
|
+
write('uint8clampedarray:');
|
|
92351
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92352
|
+
},
|
|
92353
|
+
_int8array: function(arr){
|
|
92354
|
+
write('uint8array:');
|
|
92355
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92356
|
+
},
|
|
92357
|
+
_uint16array: function(arr){
|
|
92358
|
+
write('uint16array:');
|
|
92359
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92360
|
+
},
|
|
92361
|
+
_int16array: function(arr){
|
|
92362
|
+
write('uint16array:');
|
|
92363
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92364
|
+
},
|
|
92365
|
+
_uint32array: function(arr){
|
|
92366
|
+
write('uint32array:');
|
|
92367
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92368
|
+
},
|
|
92369
|
+
_int32array: function(arr){
|
|
92370
|
+
write('uint32array:');
|
|
92371
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92372
|
+
},
|
|
92373
|
+
_float32array: function(arr){
|
|
92374
|
+
write('float32array:');
|
|
92375
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92376
|
+
},
|
|
92377
|
+
_float64array: function(arr){
|
|
92378
|
+
write('float64array:');
|
|
92379
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92380
|
+
},
|
|
92381
|
+
_arraybuffer: function(arr){
|
|
92382
|
+
write('arraybuffer:');
|
|
92383
|
+
return this.dispatch(new Uint8Array(arr));
|
|
92384
|
+
},
|
|
92385
|
+
_url: function(url) {
|
|
92386
|
+
return write('url:' + url.toString(), 'utf8');
|
|
92387
|
+
},
|
|
92388
|
+
_map: function(map) {
|
|
92389
|
+
write('map:');
|
|
92390
|
+
var arr = Array.from(map);
|
|
92391
|
+
return this._array(arr, options.unorderedSets !== false);
|
|
92392
|
+
},
|
|
92393
|
+
_set: function(set) {
|
|
92394
|
+
write('set:');
|
|
92395
|
+
var arr = Array.from(set);
|
|
92396
|
+
return this._array(arr, options.unorderedSets !== false);
|
|
92397
|
+
},
|
|
92398
|
+
_blob: function() {
|
|
92399
|
+
if (options.ignoreUnknown) {
|
|
92400
|
+
return write('[blob]');
|
|
92401
|
+
}
|
|
92402
|
+
|
|
92403
|
+
throw Error('Hashing Blob objects is currently not supported\n' +
|
|
92404
|
+
'(see https://github.com/puleos/object-hash/issues/26)\n' +
|
|
92405
|
+
'Use "options.replacer" or "options.ignoreUnknown"\n');
|
|
92406
|
+
},
|
|
92407
|
+
_domwindow: function() { return write('domwindow'); },
|
|
92408
|
+
/* Node.js standard native objects */
|
|
92409
|
+
_process: function() { return write('process'); },
|
|
92410
|
+
_timer: function() { return write('timer'); },
|
|
92411
|
+
_pipe: function() { return write('pipe'); },
|
|
92412
|
+
_tcp: function() { return write('tcp'); },
|
|
92413
|
+
_udp: function() { return write('udp'); },
|
|
92414
|
+
_tty: function() { return write('tty'); },
|
|
92415
|
+
_statwatcher: function() { return write('statwatcher'); },
|
|
92416
|
+
_securecontext: function() { return write('securecontext'); },
|
|
92417
|
+
_connection: function() { return write('connection'); },
|
|
92418
|
+
_zlib: function() { return write('zlib'); },
|
|
92419
|
+
_context: function() { return write('context'); },
|
|
92420
|
+
_nodescript: function() { return write('nodescript'); },
|
|
92421
|
+
_httpparser: function() { return write('httpparser'); },
|
|
92422
|
+
_dataview: function() { return write('dataview'); },
|
|
92423
|
+
_signal: function() { return write('signal'); },
|
|
92424
|
+
_fsevent: function() { return write('fsevent'); },
|
|
92425
|
+
_tlswrap: function() { return write('tlswrap'); }
|
|
92426
|
+
};
|
|
92427
|
+
}
|
|
92428
|
+
|
|
92429
|
+
// Mini-implementation of stream.PassThrough
|
|
92430
|
+
// We are far from having need for the full implementation, and we can
|
|
92431
|
+
// make assumptions like "many writes, then only one final read"
|
|
92432
|
+
// and we can ignore encoding specifics
|
|
92433
|
+
function PassThrough() {
|
|
92434
|
+
return {
|
|
92435
|
+
buf: '',
|
|
92436
|
+
|
|
92437
|
+
write: function(b) {
|
|
92438
|
+
this.buf += b;
|
|
92439
|
+
},
|
|
92440
|
+
|
|
92441
|
+
end: function(b) {
|
|
92442
|
+
this.buf += b;
|
|
92443
|
+
},
|
|
92444
|
+
|
|
92445
|
+
read: function() {
|
|
92446
|
+
return this.buf;
|
|
92447
|
+
}
|
|
92448
|
+
};
|
|
92449
|
+
}
|
|
92450
|
+
|
|
92451
|
+
|
|
92452
|
+
/***/ }),
|
|
92453
|
+
|
|
92454
|
+
/***/ "./node_modules/@dra2020/poly/dist/poly.js":
|
|
92455
|
+
/*!*************************************************!*\
|
|
92456
|
+
!*** ./node_modules/@dra2020/poly/dist/poly.js ***!
|
|
92457
|
+
\*************************************************/
|
|
92458
|
+
/*! no static exports found */
|
|
92459
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
92460
|
+
|
|
92461
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
92462
|
+
if(true)
|
|
92463
|
+
module.exports = factory();
|
|
92464
|
+
else {}
|
|
92465
|
+
})(global, function() {
|
|
92466
|
+
return /******/ (function(modules) { // webpackBootstrap
|
|
92467
|
+
/******/ // The module cache
|
|
92468
|
+
/******/ var installedModules = {};
|
|
92469
|
+
/******/
|
|
92470
|
+
/******/ // The require function
|
|
92471
|
+
/******/ function __webpack_require__(moduleId) {
|
|
92472
|
+
/******/
|
|
92473
|
+
/******/ // Check if module is in cache
|
|
92474
|
+
/******/ if(installedModules[moduleId]) {
|
|
92475
|
+
/******/ return installedModules[moduleId].exports;
|
|
92476
|
+
/******/ }
|
|
92477
|
+
/******/ // Create a new module (and put it into the cache)
|
|
92478
|
+
/******/ var module = installedModules[moduleId] = {
|
|
92479
|
+
/******/ i: moduleId,
|
|
92480
|
+
/******/ l: false,
|
|
92481
|
+
/******/ exports: {}
|
|
92482
|
+
/******/ };
|
|
92483
|
+
/******/
|
|
92484
|
+
/******/ // Execute the module function
|
|
92485
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
92486
|
+
/******/
|
|
92487
|
+
/******/ // Flag the module as loaded
|
|
92488
|
+
/******/ module.l = true;
|
|
92489
|
+
/******/
|
|
92490
|
+
/******/ // Return the exports of the module
|
|
92491
|
+
/******/ return module.exports;
|
|
92492
|
+
/******/ }
|
|
92493
|
+
/******/
|
|
92494
|
+
/******/
|
|
92495
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
92496
|
+
/******/ __webpack_require__.m = modules;
|
|
92497
|
+
/******/
|
|
92498
|
+
/******/ // expose the module cache
|
|
92499
|
+
/******/ __webpack_require__.c = installedModules;
|
|
92500
|
+
/******/
|
|
92501
|
+
/******/ // define getter function for harmony exports
|
|
92502
|
+
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
92503
|
+
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
92504
|
+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
92505
|
+
/******/ }
|
|
92506
|
+
/******/ };
|
|
92507
|
+
/******/
|
|
92508
|
+
/******/ // define __esModule on exports
|
|
92509
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
92510
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
92511
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
92512
|
+
/******/ }
|
|
92513
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
92514
|
+
/******/ };
|
|
92515
|
+
/******/
|
|
92516
|
+
/******/ // create a fake namespace object
|
|
92517
|
+
/******/ // mode & 1: value is a module id, require it
|
|
92518
|
+
/******/ // mode & 2: merge all properties of value into the ns
|
|
92519
|
+
/******/ // mode & 4: return value when already ns object
|
|
92520
|
+
/******/ // mode & 8|1: behave like require
|
|
92521
|
+
/******/ __webpack_require__.t = function(value, mode) {
|
|
92522
|
+
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
92523
|
+
/******/ if(mode & 8) return value;
|
|
92524
|
+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
92525
|
+
/******/ var ns = Object.create(null);
|
|
92526
|
+
/******/ __webpack_require__.r(ns);
|
|
92527
|
+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
92528
|
+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
92529
|
+
/******/ return ns;
|
|
92530
|
+
/******/ };
|
|
92531
|
+
/******/
|
|
92532
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
92533
|
+
/******/ __webpack_require__.n = function(module) {
|
|
92534
|
+
/******/ var getter = module && module.__esModule ?
|
|
92535
|
+
/******/ function getDefault() { return module['default']; } :
|
|
92536
|
+
/******/ function getModuleExports() { return module; };
|
|
92537
|
+
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
92538
|
+
/******/ return getter;
|
|
92539
|
+
/******/ };
|
|
92540
|
+
/******/
|
|
92541
|
+
/******/ // Object.prototype.hasOwnProperty.call
|
|
92542
|
+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
92543
|
+
/******/
|
|
92544
|
+
/******/ // __webpack_public_path__
|
|
92545
|
+
/******/ __webpack_require__.p = "";
|
|
92546
|
+
/******/
|
|
92547
|
+
/******/
|
|
92548
|
+
/******/ // Load entry module and return exports
|
|
92549
|
+
/******/ return __webpack_require__(__webpack_require__.s = "./lib/all.ts");
|
|
92550
|
+
/******/ })
|
|
92551
|
+
/************************************************************************/
|
|
92552
|
+
/******/ ({
|
|
92553
|
+
|
|
92554
|
+
/***/ "./lib/all.ts":
|
|
92555
|
+
/*!********************!*\
|
|
92556
|
+
!*** ./lib/all.ts ***!
|
|
92557
|
+
\********************/
|
|
92558
|
+
/*! no static exports found */
|
|
92559
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
92560
|
+
|
|
92561
|
+
"use strict";
|
|
92562
|
+
|
|
92563
|
+
function __export(m) {
|
|
92564
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
92565
|
+
}
|
|
92566
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
92567
|
+
__export(__webpack_require__(/*! ./poly */ "./lib/poly.ts"));
|
|
92568
|
+
__export(__webpack_require__(/*! ./union */ "./lib/union.ts"));
|
|
92569
|
+
|
|
92570
|
+
|
|
92571
|
+
/***/ }),
|
|
92572
|
+
|
|
92573
|
+
/***/ "./lib/poly.ts":
|
|
92574
|
+
/*!*********************!*\
|
|
92575
|
+
!*** ./lib/poly.ts ***!
|
|
92576
|
+
\*********************/
|
|
92577
|
+
/*! no static exports found */
|
|
92578
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
92579
|
+
|
|
92580
|
+
"use strict";
|
|
92581
|
+
|
|
92582
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
92583
|
+
const Util = __webpack_require__(/*! @dra2020/util */ "@dra2020/util");
|
|
92584
|
+
// Internal utilities
|
|
92585
|
+
exports.EARTH_RADIUS = 6371000; // Radius of earth in meters
|
|
92586
|
+
const DefaultOptions = {};
|
|
92587
|
+
// Return geographic polygon area in meters^2
|
|
92588
|
+
function polySimpleArea(p, options) {
|
|
92589
|
+
if (options === undefined)
|
|
92590
|
+
options = DefaultOptions;
|
|
92591
|
+
let p1;
|
|
92592
|
+
let p2;
|
|
92593
|
+
let p3;
|
|
92594
|
+
let dx;
|
|
92595
|
+
let l;
|
|
92596
|
+
let m;
|
|
92597
|
+
let u;
|
|
92598
|
+
let i;
|
|
92599
|
+
let total = 0;
|
|
92600
|
+
let n = p.length;
|
|
92601
|
+
if (n > 2) {
|
|
92602
|
+
for (i = 0; i < n; i++) {
|
|
92603
|
+
if (i === n - 2) {
|
|
92604
|
+
l = n - 2;
|
|
92605
|
+
m = n - 1;
|
|
92606
|
+
u = 0;
|
|
92607
|
+
}
|
|
92608
|
+
else if (i === n - 1) {
|
|
92609
|
+
l = n - 1;
|
|
92610
|
+
m = 0;
|
|
92611
|
+
u = 1;
|
|
92612
|
+
}
|
|
92613
|
+
else {
|
|
92614
|
+
l = i;
|
|
92615
|
+
m = i + 1;
|
|
92616
|
+
u = i + 2;
|
|
92617
|
+
}
|
|
92618
|
+
p1 = p[l];
|
|
92619
|
+
p2 = p[m];
|
|
92620
|
+
p3 = p[u];
|
|
92621
|
+
dx = (Util.deg2rad(p3[0]) - Util.deg2rad(p1[0]));
|
|
92622
|
+
dx *= Math.sin(Util.deg2rad(p2[1]));
|
|
92623
|
+
total += dx;
|
|
92624
|
+
}
|
|
92625
|
+
total *= exports.EARTH_RADIUS * exports.EARTH_RADIUS / 2;
|
|
92626
|
+
}
|
|
92627
|
+
return Math.abs(total);
|
|
92628
|
+
}
|
|
92629
|
+
// Allow bare polygon coordinates array or GeoJSON feature.
|
|
92630
|
+
// Normalize to multipolygon points array.
|
|
92631
|
+
function polyNormalize(poly, options) {
|
|
92632
|
+
if (options === undefined)
|
|
92633
|
+
options = DefaultOptions;
|
|
92634
|
+
// Convert a GeoJSON polygon or multipolygon to the raw list of points
|
|
92635
|
+
if (poly && poly.geometry && poly.geometry.coordinates)
|
|
92636
|
+
poly = poly.geometry.coordinates;
|
|
92637
|
+
// This is really an invalid specification but used internally to represent null polygon
|
|
92638
|
+
if (poly && poly.length == 0)
|
|
92639
|
+
return null;
|
|
92640
|
+
if (Util.depthof(poly) == 4)
|
|
92641
|
+
poly = [poly];
|
|
92642
|
+
return poly;
|
|
92643
|
+
}
|
|
92644
|
+
exports.polyNormalize = polyNormalize;
|
|
92645
|
+
// Area of geographic polygon
|
|
92646
|
+
function polyArea(poly, options) {
|
|
92647
|
+
if (options === undefined)
|
|
92648
|
+
options = DefaultOptions;
|
|
92649
|
+
poly = polyNormalize(poly, options);
|
|
92650
|
+
let a = 0;
|
|
92651
|
+
// MultiPolygon is a set of polygons
|
|
92652
|
+
for (let i = 0; poly && i < poly.length; i++) {
|
|
92653
|
+
// Single polygon is exterior ring with interior holes. Holes are subtracted.
|
|
92654
|
+
let p = poly[i];
|
|
92655
|
+
for (let j = 0; j < p.length; j++) {
|
|
92656
|
+
let sp = p[j];
|
|
92657
|
+
a += polySimpleArea(sp, options) * (j == 0 ? 1 : -1);
|
|
92658
|
+
}
|
|
92659
|
+
}
|
|
92660
|
+
return a;
|
|
92661
|
+
}
|
|
92662
|
+
exports.polyArea = polyArea;
|
|
92663
|
+
// Return distance in meters given two lat/lon points
|
|
92664
|
+
function haversine(x1, y1, x2, y2, options) {
|
|
92665
|
+
let dLat = Util.deg2rad(y2 - y1);
|
|
92666
|
+
let dLon = Util.deg2rad(x2 - x1);
|
|
92667
|
+
let c;
|
|
92668
|
+
// Short circuit for using simple cartesian algorithm instead of haversine
|
|
92669
|
+
if (options.noLatitudeCorrection)
|
|
92670
|
+
c = Math.sqrt((dLat * dLat) + (dLon * dLon));
|
|
92671
|
+
else {
|
|
92672
|
+
let lat1 = Util.deg2rad(y1);
|
|
92673
|
+
let lat2 = Util.deg2rad(y2);
|
|
92674
|
+
let a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
92675
|
+
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
|
|
92676
|
+
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
92677
|
+
}
|
|
92678
|
+
return exports.EARTH_RADIUS * c;
|
|
92679
|
+
}
|
|
92680
|
+
// Perimeter of geographic polygon in meters
|
|
92681
|
+
function polyPerimeter(poly, options) {
|
|
92682
|
+
if (options === undefined)
|
|
92683
|
+
options = DefaultOptions;
|
|
92684
|
+
poly = polyNormalize(poly, options);
|
|
92685
|
+
let perimeter = 0;
|
|
92686
|
+
for (let i = 0; poly && i < poly.length; i++) {
|
|
92687
|
+
// Ignore holes so only look at first polyline
|
|
92688
|
+
let p = poly[i][0];
|
|
92689
|
+
for (let j = 0; j < p.length - 1; j++)
|
|
92690
|
+
perimeter += haversine(p[j][0], p[j][1], p[j + 1][0], p[j + 1][1], options);
|
|
92691
|
+
if (p.length > 2 && (p[0][0] != p[p.length - 1][0] || p[0][1] != p[p.length - 1][1]))
|
|
92692
|
+
perimeter += haversine(p[0][0], p[0][1], p[p.length - 1][0], p[p.length - 1][1], options);
|
|
92693
|
+
}
|
|
92694
|
+
return perimeter;
|
|
92695
|
+
}
|
|
92696
|
+
exports.polyPerimeter = polyPerimeter;
|
|
92697
|
+
class Point {
|
|
92698
|
+
constructor(x, y) {
|
|
92699
|
+
this.x = x;
|
|
92700
|
+
this.y = y;
|
|
92701
|
+
}
|
|
92702
|
+
}
|
|
92703
|
+
class Circle {
|
|
92704
|
+
constructor(x, y, r) {
|
|
92705
|
+
this.x = x;
|
|
92706
|
+
this.y = y;
|
|
92707
|
+
this.r = r;
|
|
92708
|
+
}
|
|
92709
|
+
}
|
|
92710
|
+
exports.Circle = Circle;
|
|
92711
|
+
//
|
|
92712
|
+
// Returns the smallest circle that encloses the given polygon.
|
|
92713
|
+
// Runs in expected O(n) time, randomized.
|
|
92714
|
+
// Note: If 0 points are given, null is returned.
|
|
92715
|
+
// If 1 point is given, a circle of radius 0 is returned.
|
|
92716
|
+
//
|
|
92717
|
+
function polyToCircle(poly, options) {
|
|
92718
|
+
if (options === undefined)
|
|
92719
|
+
options = DefaultOptions;
|
|
92720
|
+
return makeCircle(polyToExteriorPoints(poly));
|
|
92721
|
+
}
|
|
92722
|
+
exports.polyToCircle = polyToCircle;
|
|
92723
|
+
//
|
|
92724
|
+
// Returns the circle whose perimeter is equal to the perimeter of the bounding perimeter
|
|
92725
|
+
// of the polygon. Use binary search to find an approximation.
|
|
92726
|
+
//
|
|
92727
|
+
function polyToPolsbyPopperCircle(poly, options) {
|
|
92728
|
+
if (options === undefined)
|
|
92729
|
+
options = DefaultOptions;
|
|
92730
|
+
let c = polyToCircle(poly, options);
|
|
92731
|
+
if (c == null)
|
|
92732
|
+
return c;
|
|
92733
|
+
let p = polyPerimeter(poly, options);
|
|
92734
|
+
c.r = (p / (2 * Math.PI)) / 111139;
|
|
92735
|
+
return c;
|
|
92736
|
+
}
|
|
92737
|
+
exports.polyToPolsbyPopperCircle = polyToPolsbyPopperCircle;
|
|
92738
|
+
function makeCircle(points) {
|
|
92739
|
+
if (points == null)
|
|
92740
|
+
return null;
|
|
92741
|
+
// Clone list to preserve the caller's data, do Durstenfeld shuffle
|
|
92742
|
+
let shuffled = points.slice();
|
|
92743
|
+
for (let i = points.length - 1; i >= 0; i--) {
|
|
92744
|
+
let j = Math.floor(Math.random() * (i + 1));
|
|
92745
|
+
j = Math.max(Math.min(j, i), 0);
|
|
92746
|
+
const temp = shuffled[i];
|
|
92747
|
+
shuffled[i] = shuffled[j];
|
|
92748
|
+
shuffled[j] = temp;
|
|
92749
|
+
}
|
|
92750
|
+
// Progressively add points to circle or recompute circle
|
|
92751
|
+
let c = null;
|
|
92752
|
+
shuffled.forEach((p, i) => {
|
|
92753
|
+
if (c === null || !isInCircle(c, p))
|
|
92754
|
+
c = makeCircleOnePoint(shuffled.slice(0, i + 1), p);
|
|
92755
|
+
});
|
|
92756
|
+
return c;
|
|
92757
|
+
}
|
|
92758
|
+
// One boundary point known
|
|
92759
|
+
function makeCircleOnePoint(points, p) {
|
|
92760
|
+
let c = new Circle(p.x, p.y, 0);
|
|
92761
|
+
points.forEach((q, i) => {
|
|
92762
|
+
if (!isInCircle(c, q)) {
|
|
92763
|
+
if (c.r == 0)
|
|
92764
|
+
c = makeDiameter(p, q);
|
|
92765
|
+
else
|
|
92766
|
+
c = makeCircleTwoPoints(points.slice(0, i + 1), p, q);
|
|
92767
|
+
}
|
|
92768
|
+
});
|
|
92769
|
+
return c;
|
|
92770
|
+
}
|
|
92771
|
+
// Two boundary points known
|
|
92772
|
+
function makeCircleTwoPoints(points, p, q) {
|
|
92773
|
+
const circ = makeDiameter(p, q);
|
|
92774
|
+
let left = null;
|
|
92775
|
+
let right = null;
|
|
92776
|
+
// For each point not in the two-point circle
|
|
92777
|
+
for (const r of points) {
|
|
92778
|
+
if (isInCircle(circ, r))
|
|
92779
|
+
continue;
|
|
92780
|
+
// Form a circumcircle and classify it on left or right side
|
|
92781
|
+
const cross = crossProduct(p.x, p.y, q.x, q.y, r.x, r.y);
|
|
92782
|
+
const c = makeCircumcircle(p, q, r);
|
|
92783
|
+
if (c === null)
|
|
92784
|
+
continue;
|
|
92785
|
+
else if (cross > 0 && (left === null || crossProduct(p.x, p.y, q.x, q.y, c.x, c.y) > crossProduct(p.x, p.y, q.x, q.y, left.x, left.y)))
|
|
92786
|
+
left = c;
|
|
92787
|
+
else if (cross < 0 && (right === null || crossProduct(p.x, p.y, q.x, q.y, c.x, c.y) < crossProduct(p.x, p.y, q.x, q.y, right.x, right.y)))
|
|
92788
|
+
right = c;
|
|
92789
|
+
}
|
|
92790
|
+
// Select which circle to return
|
|
92791
|
+
if (left === null && right === null)
|
|
92792
|
+
return circ;
|
|
92793
|
+
else if (left === null && right !== null)
|
|
92794
|
+
return right;
|
|
92795
|
+
else if (left !== null && right === null)
|
|
92796
|
+
return left;
|
|
92797
|
+
else if (left !== null && right !== null)
|
|
92798
|
+
return left.r <= right.r ? left : right;
|
|
92799
|
+
else
|
|
92800
|
+
throw "Assertion error";
|
|
92801
|
+
}
|
|
92802
|
+
function makeDiameter(a, b) {
|
|
92803
|
+
const cx = (a.x + b.x) / 2;
|
|
92804
|
+
const cy = (a.y + b.y) / 2;
|
|
92805
|
+
const r0 = Util.distance(cx, cy, a.x, a.y);
|
|
92806
|
+
const r1 = Util.distance(cx, cy, b.x, b.y);
|
|
92807
|
+
return new Circle(cx, cy, Math.max(r0, r1));
|
|
92808
|
+
}
|
|
92809
|
+
function makeCircumcircle(a, b, c) {
|
|
92810
|
+
// Mathematical algorithm from Wikipedia: Circumscribed circle
|
|
92811
|
+
const ox = (Math.min(a.x, b.x, c.x) + Math.max(a.x, b.x, c.x)) / 2;
|
|
92812
|
+
const oy = (Math.min(a.y, b.y, c.y) + Math.max(a.y, b.y, c.y)) / 2;
|
|
92813
|
+
const ax = a.x - ox;
|
|
92814
|
+
const ay = a.y - oy;
|
|
92815
|
+
const bx = b.x - ox;
|
|
92816
|
+
const by = b.y - oy;
|
|
92817
|
+
const cx = c.x - ox;
|
|
92818
|
+
const cy = c.y - oy;
|
|
92819
|
+
const d = (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by)) * 2;
|
|
92820
|
+
if (d == 0)
|
|
92821
|
+
return null;
|
|
92822
|
+
const x = ox + ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d;
|
|
92823
|
+
const y = oy + ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d;
|
|
92824
|
+
const ra = Util.distance(x, y, a.x, a.y);
|
|
92825
|
+
const rb = Util.distance(x, y, b.x, b.y);
|
|
92826
|
+
const rc = Util.distance(x, y, c.x, c.y);
|
|
92827
|
+
return new Circle(x, y, Math.max(ra, rb, rc));
|
|
92828
|
+
}
|
|
92829
|
+
/* Simple mathematical functions */
|
|
92830
|
+
const MULTIPLICATIVE_EPSILON = 1 + 1e-14;
|
|
92831
|
+
function isInCircle(c, p) {
|
|
92832
|
+
return c !== null && Util.distance(p.x, p.y, c.x, c.y) <= c.r * MULTIPLICATIVE_EPSILON;
|
|
92833
|
+
}
|
|
92834
|
+
// Returns twice the signed area of the triangle defined by (x0, y0), (x1, y1), (x2, y2).
|
|
92835
|
+
function crossProduct(x0, y0, x1, y1, x2, y2) {
|
|
92836
|
+
return (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
|
|
92837
|
+
}
|
|
92838
|
+
// cache x,y circle offsets for one quadrant indexed by number of segments
|
|
92839
|
+
let circleOffsets = {};
|
|
92840
|
+
function getCircleOffsets(n) {
|
|
92841
|
+
if (circleOffsets[n] === undefined) {
|
|
92842
|
+
let a = [];
|
|
92843
|
+
let incr = (Math.PI / 2) / n;
|
|
92844
|
+
let theta = 0;
|
|
92845
|
+
let i, j;
|
|
92846
|
+
// Compute NE quadrant
|
|
92847
|
+
for (i = 0; i < n; i++, theta += incr) {
|
|
92848
|
+
a.push(Math.sin(theta));
|
|
92849
|
+
a.push(Math.cos(theta));
|
|
92850
|
+
}
|
|
92851
|
+
// Add top of circle
|
|
92852
|
+
a.push(0);
|
|
92853
|
+
a.push(1);
|
|
92854
|
+
// Now flip X and replicate to NW quadrant
|
|
92855
|
+
for (i = 0; i < n; i++) {
|
|
92856
|
+
j = (n - i) * 2;
|
|
92857
|
+
a.push(-a[j - 1]);
|
|
92858
|
+
a.push(a[j - 2]);
|
|
92859
|
+
}
|
|
92860
|
+
// Now flip X and Y and replicate to SW quadrant
|
|
92861
|
+
for (i = 0; i < n; i++) {
|
|
92862
|
+
j = (n - i) * 2;
|
|
92863
|
+
a.push(-a[j - 1]);
|
|
92864
|
+
a.push(-a[j - 2]);
|
|
92865
|
+
}
|
|
92866
|
+
// Add bottom of circle
|
|
92867
|
+
a.push(0);
|
|
92868
|
+
a.push(-1);
|
|
92869
|
+
// Now flip Y and replicate to SE quadrant
|
|
92870
|
+
for (i = 0; i < n; i++) {
|
|
92871
|
+
j = (n - i) * 2;
|
|
92872
|
+
a.push(a[j - 1]);
|
|
92873
|
+
a.push(-a[j - 2]);
|
|
92874
|
+
}
|
|
92875
|
+
// Duplicate final point per GeoJSON spec
|
|
92876
|
+
a.push(a[0]);
|
|
92877
|
+
a.push(a[1]);
|
|
92878
|
+
circleOffsets[n] = a;
|
|
92879
|
+
}
|
|
92880
|
+
return circleOffsets[n];
|
|
92881
|
+
}
|
|
92882
|
+
// Note that this is essentially an inversion of polyToCircle which computes a mathematical
|
|
92883
|
+
// circle given the point values, ignoring latitude correction. This inversion also
|
|
92884
|
+
// ignores that correction which means when plotted on a 2D map looks circular but the edge of
|
|
92885
|
+
// the circle is not a fixed distance (in physical units, e.g. meters) from the center.
|
|
92886
|
+
//
|
|
92887
|
+
function polyFromCircle(c, nSegments, options) {
|
|
92888
|
+
if (options === undefined)
|
|
92889
|
+
options = DefaultOptions;
|
|
92890
|
+
if (c === null || c.r == 0)
|
|
92891
|
+
return null;
|
|
92892
|
+
if (!nSegments || nSegments < 8)
|
|
92893
|
+
nSegments = 8;
|
|
92894
|
+
let poly = [];
|
|
91080
92895
|
let offsets = getCircleOffsets(nSegments);
|
|
91081
92896
|
const n = offsets.length;
|
|
91082
92897
|
for (let i = 0; i < n; i += 2)
|
|
@@ -98606,6 +100421,7 @@ const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
|
98606
100421
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
98607
100422
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
98608
100423
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
100424
|
+
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
98609
100425
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
98610
100426
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
98611
100427
|
class AnalyticsSession {
|
|
@@ -98625,46 +100441,39 @@ class AnalyticsSession {
|
|
|
98625
100441
|
this.features = new D.Features(this, SessionRequest['data'], this.config['datasets']);
|
|
98626
100442
|
this.plan = new D.Plan(this, SessionRequest['plan']);
|
|
98627
100443
|
this.districts = new D.Districts(this, SessionRequest['districtShapes']);
|
|
98628
|
-
// TODO -
|
|
98629
|
-
|
|
98630
|
-
|
|
98631
|
-
|
|
98632
|
-
|
|
98633
|
-
|
|
98634
|
-
|
|
98635
|
-
// NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
98636
|
-
// we could want them to passed into an analytics session as data, along with
|
|
98637
|
-
// everything else. For now, this keeps branching out of the main code.
|
|
98638
|
-
results_1.doConfigureScales(this);
|
|
100444
|
+
// TODO - SCORE: Toggle
|
|
100445
|
+
if (this.useLegacy()) {
|
|
100446
|
+
// NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
100447
|
+
// we could want them to passed into an analytics session as data, along with
|
|
100448
|
+
// everything else. For now, this keeps branching out of the main code.
|
|
100449
|
+
results_1.doConfigureScales(this);
|
|
100450
|
+
}
|
|
98639
100451
|
}
|
|
98640
100452
|
processConfig(config) {
|
|
98641
100453
|
// NOTE - Session settings are required:
|
|
98642
100454
|
// - Analytics suites can be defaulted to all with [], but
|
|
98643
100455
|
// - Dataset keys must be explicitly specified with 'dataset'
|
|
98644
|
-
|
|
98645
|
-
let defaultSuites = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
|
|
98646
|
-
// If the config passed in has no suites = [], use the default suites
|
|
98647
|
-
if (U.isArrayEmpty(config['suites'])) {
|
|
98648
|
-
config['suites'] = defaultSuites;
|
|
98649
|
-
}
|
|
100456
|
+
config['suites'] = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
|
|
98650
100457
|
// Default the Census & redistricting cycle to 2010
|
|
98651
100458
|
if (!(U.keyExists('cycle', config)))
|
|
98652
100459
|
config['cycle'] = 2010;
|
|
98653
100460
|
return config;
|
|
98654
100461
|
}
|
|
100462
|
+
useLegacy() {
|
|
100463
|
+
return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
|
|
100464
|
+
}
|
|
98655
100465
|
// Using the the data in the analytics session, calculate all the
|
|
98656
100466
|
// analytics & validations, saving/updating the individual test results.
|
|
98657
|
-
analyzePlan(bLog = false) {
|
|
100467
|
+
analyzePlan(bLog = false, overridesJSON = undefined) {
|
|
98658
100468
|
try {
|
|
98659
100469
|
preprocess_1.doPreprocessData(this, bLog);
|
|
98660
100470
|
analyze_1.doAnalyzeDistricts(this, bLog);
|
|
98661
|
-
analyze_1.doAnalyzePlan(this, bLog);
|
|
98662
100471
|
// TODO - SCORE
|
|
100472
|
+
analyze_1.doAnalyzePlan(this, bLog);
|
|
98663
100473
|
this._profile = score_1.profilePlan(this, bLog);
|
|
98664
|
-
// this._profile = Score.sampleProfile;
|
|
98665
100474
|
this._scorecard = score_1.scorePlan(this._profile, bLog);
|
|
98666
|
-
// TODO - SCORE
|
|
98667
100475
|
results_1.doAnalyzePostProcessing(this, bLog);
|
|
100476
|
+
//
|
|
98668
100477
|
}
|
|
98669
100478
|
catch (_a) {
|
|
98670
100479
|
console.log("Exception caught by analyzePlan()");
|
|
@@ -98684,13 +100493,6 @@ class AnalyticsSession {
|
|
|
98684
100493
|
getPlanScorecard(bLog = false) {
|
|
98685
100494
|
return this._scorecard;
|
|
98686
100495
|
}
|
|
98687
|
-
/* TODO - SCORE
|
|
98688
|
-
// NOTE - This assumes that analyzePlan() has been run!
|
|
98689
|
-
getPlanAnalytics(bLog: boolean = false): PlanAnalytics
|
|
98690
|
-
{
|
|
98691
|
-
return preparePlanAnalytics(this, bLog);
|
|
98692
|
-
}
|
|
98693
|
-
*/
|
|
98694
100496
|
// TODO - SCORE
|
|
98695
100497
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
98696
100498
|
getRequirementsChecklist(bLog = false) {
|
|
@@ -98699,19 +100501,82 @@ class AnalyticsSession {
|
|
|
98699
100501
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
98700
100502
|
getDiscontiguousDistrictFeatures(bLog = false) {
|
|
98701
100503
|
// Get the (possibly empty) list of discontiguous district IDs
|
|
98702
|
-
|
|
98703
|
-
|
|
100504
|
+
const contiguousTest = this.getTest(1 /* Contiguous */);
|
|
100505
|
+
const discontiguousDistrictIDs = contiguousTest['details']['discontiguousDistricts'] || [];
|
|
98704
100506
|
// Convert them into a (possibly empty) list of features
|
|
98705
100507
|
let discontiguousDistrictFeatures = { type: 'FeatureCollection', features: [] };
|
|
98706
100508
|
if (!(U.isArrayEmpty(discontiguousDistrictIDs))) {
|
|
98707
100509
|
for (let id of discontiguousDistrictIDs) {
|
|
98708
100510
|
let poly = this.districts.getDistrictShapeByID(id);
|
|
98709
|
-
if (poly)
|
|
98710
|
-
|
|
100511
|
+
if (poly) {
|
|
100512
|
+
// If a district has a shape & it is not contiguous, by definition,
|
|
100513
|
+
// it will be a Multipolygon, i.e., it will have multiple pieces, some
|
|
100514
|
+
// possibly embedded w/in other districts. Get & add all the pieces.
|
|
100515
|
+
const districtParts = geofeature_1.polyParts(poly);
|
|
100516
|
+
discontiguousDistrictFeatures.features.push(...districtParts.features);
|
|
100517
|
+
// discontiguousDistrictFeatures.features.push(poly);
|
|
100518
|
+
}
|
|
98711
100519
|
}
|
|
98712
100520
|
}
|
|
98713
100521
|
return discontiguousDistrictFeatures;
|
|
98714
100522
|
}
|
|
100523
|
+
// Comments clipped from dra-client geodistrict.ts.
|
|
100524
|
+
// Discontiguous polygons are:
|
|
100525
|
+
// 1. All polygons in a multi-polygon; and
|
|
100526
|
+
// 2. All holes in a otherwise cohesive polygon.
|
|
100527
|
+
// Note that all non-cohesive features are always simple polygons.
|
|
100528
|
+
/*
|
|
100529
|
+
let i: number, j: number;
|
|
100530
|
+
let nPoly: number = 0;
|
|
100531
|
+
for (i = 0;nPoly == 0 && i < this.cacheDistricts.features.length;i++)
|
|
100532
|
+
{
|
|
100533
|
+
let f = this.cacheDistricts.features[i];
|
|
100534
|
+
|
|
100535
|
+
if (f.geometry.type === 'MultiPolygon')
|
|
100536
|
+
nPoly += f.geometry.coordinates.length;
|
|
100537
|
+
else if (f.geometry.type === 'Polygon' && f.geometry.coordinates.length)
|
|
100538
|
+
nPoly += (f.geometry.coordinates.length - 1);
|
|
100539
|
+
}
|
|
100540
|
+
if (nPoly)
|
|
100541
|
+
{
|
|
100542
|
+
this.cacheNoncohesive = {type: 'FeatureCollection', features: []};
|
|
100543
|
+
let af: any = this.cacheNoncohesive.features;
|
|
100544
|
+
let oUnique: any = {};
|
|
100545
|
+
|
|
100546
|
+
// First add discontiguous polygons
|
|
100547
|
+
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
100548
|
+
{
|
|
100549
|
+
let f = this.cacheDistricts.features[i];
|
|
100550
|
+
|
|
100551
|
+
if (f.geometry.type === 'MultiPolygon')
|
|
100552
|
+
{
|
|
100553
|
+
// Push all non-contiguous polygons
|
|
100554
|
+
for (j = 0;j < f.geometry.coordinates.length;j++)
|
|
100555
|
+
{
|
|
100556
|
+
let p: any = f.geometry.coordinates[j];
|
|
100557
|
+
oUnique[Hash.qhash(p[0])] = true;
|
|
100558
|
+
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: p}});
|
|
100559
|
+
}
|
|
100560
|
+
}
|
|
100561
|
+
}
|
|
100562
|
+
|
|
100563
|
+
// Now add unique holes
|
|
100564
|
+
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
100565
|
+
{
|
|
100566
|
+
let f = this.cacheDistricts.features[i];
|
|
100567
|
+
|
|
100568
|
+
if (f.geometry.type === 'Polygon')
|
|
100569
|
+
{
|
|
100570
|
+
// Push all holes from this polygon
|
|
100571
|
+
for (j = 1;j < f.geometry.coordinates.length;j++)
|
|
100572
|
+
{
|
|
100573
|
+
let p: any = f.geometry.coordinates[j];
|
|
100574
|
+
if (oUnique[Hash.qhash(p)] === undefined)
|
|
100575
|
+
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: [p]}});
|
|
100576
|
+
}
|
|
100577
|
+
}
|
|
100578
|
+
}
|
|
100579
|
+
} */
|
|
98715
100580
|
// HELPERS USED INTERNALLY
|
|
98716
100581
|
// Get an individual test, so you can drive UI with the results.
|
|
98717
100582
|
getTest(testID) {
|
|
@@ -98727,9 +100592,17 @@ class AnalyticsSession {
|
|
|
98727
100592
|
// Return a pointer to the the test entry for this test
|
|
98728
100593
|
return this.tests[testID];
|
|
98729
100594
|
}
|
|
98730
|
-
// NOTE - Not sure why this has to be up here
|
|
100595
|
+
// NOTE - Not sure why this has to be up here ...
|
|
98731
100596
|
populationDeviationThreshold() {
|
|
98732
|
-
|
|
100597
|
+
// TODO - SCORE: Toggle
|
|
100598
|
+
// const bLegacy = this._bLegacy; DELETE
|
|
100599
|
+
if (this.useLegacy()) {
|
|
100600
|
+
return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
|
|
100601
|
+
}
|
|
100602
|
+
else {
|
|
100603
|
+
const scorecard = this._scorecard;
|
|
100604
|
+
return scorecard.best.populationDeviation.notes['threshold'];
|
|
100605
|
+
}
|
|
98733
100606
|
}
|
|
98734
100607
|
}
|
|
98735
100608
|
exports.AnalyticsSession = AnalyticsSession;
|
|
@@ -98905,7 +100778,7 @@ class Districts {
|
|
|
98905
100778
|
let outerThis = this;
|
|
98906
100779
|
// Default the pop dev % for the dummy Unassigned district to 0%.
|
|
98907
100780
|
// Default the pop dev % for real (1–N) but empty districts to 100%.
|
|
98908
|
-
// TODO - SCORE
|
|
100781
|
+
// TODO - SCORE: Why did I mark this?
|
|
98909
100782
|
let popDevPct = (i > 0) ? (targetSize / targetSize) : 0 / targetSize;
|
|
98910
100783
|
// Get the geoIDs assigned to the district
|
|
98911
100784
|
// Guard against empty districts
|
|
@@ -98932,7 +100805,6 @@ class Districts {
|
|
|
98932
100805
|
// NOTE - SPLITTING
|
|
98933
100806
|
// Total population by counties w/in a district,
|
|
98934
100807
|
// except the dummy unassigned district 0
|
|
98935
|
-
// TODO - VFEATURE
|
|
98936
100808
|
if (i > 0)
|
|
98937
100809
|
countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
|
|
98938
100810
|
// Democratic and Republican vote totals
|
|
@@ -99106,10 +100978,7 @@ class Districts {
|
|
|
99106
100978
|
compact_1.extractDistrictProperties(this._session, bLog);
|
|
99107
100979
|
}
|
|
99108
100980
|
getCountyIndex(geoID) {
|
|
99109
|
-
// TODO - VFEATURE
|
|
99110
100981
|
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
99111
|
-
// let countyGeoID = U.parseGeoID(geoID)['county'] as string;
|
|
99112
|
-
// let countyFIPS = U.getFIPSFromCountyGeoID(countyGeoID);
|
|
99113
100982
|
let countyIndex = this._session.counties.indexFromFIPS(countyFIPS);
|
|
99114
100983
|
return countyIndex;
|
|
99115
100984
|
}
|
|
@@ -99358,6 +101227,8 @@ exports.doAnalyzeDistricts = doAnalyzeDistricts;
|
|
|
99358
101227
|
// NOTE - I could make this table-driven, but I'm thinking that the explicit
|
|
99359
101228
|
// calls might make chunking for aync easier.
|
|
99360
101229
|
function doAnalyzePlan(s, bLog = false) {
|
|
101230
|
+
// TODO - SCORE: Toggle
|
|
101231
|
+
// const bLegacy = s._bLegacy;
|
|
99361
101232
|
// TODO - Remove this mechanism. Always run all tests
|
|
99362
101233
|
// Get the requested suites, and only execute those tests
|
|
99363
101234
|
let requestedSuites = s.config['suites'];
|
|
@@ -99404,6 +101275,8 @@ exports.doAnalyzePlan = doAnalyzePlan;
|
|
|
99404
101275
|
// NOTE - Should this be conditionalized on the test suites requested?
|
|
99405
101276
|
// Those are encapsulated in reports.ts right now, so not doing that.
|
|
99406
101277
|
function doDeriveSecondaryTests(s, bLog = false) {
|
|
101278
|
+
// TODO - SCORE: Toggle
|
|
101279
|
+
// const bLegacy = s._bLegacy;
|
|
99407
101280
|
s.tests[3 /* EqualPopulation */] = equal_1.doHasEqualPopulations(s, bLog);
|
|
99408
101281
|
}
|
|
99409
101282
|
exports.doDeriveSecondaryTests = doDeriveSecondaryTests;
|
|
@@ -99987,6 +101860,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
99987
101860
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
99988
101861
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
99989
101862
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
101863
|
+
// TODO - SCORE: Delete
|
|
99990
101864
|
function doPopulationDeviation(s, bLog = false) {
|
|
99991
101865
|
let test = s.getTest(4 /* PopulationDeviation */);
|
|
99992
101866
|
let targetSize = s.state.totalPop / s.state.nDistricts;
|
|
@@ -100022,6 +101896,13 @@ exports.doPopulationDeviation = doPopulationDeviation;
|
|
|
100022
101896
|
// NOTE - This validity check is *derived* and depends on population deviation %
|
|
100023
101897
|
// being computed (above) and normalized in test log & scorecard generation.
|
|
100024
101898
|
function doHasEqualPopulations(s, bLog = false) {
|
|
101899
|
+
// TODO - SCORE: Toggle
|
|
101900
|
+
// const bLegacy = s._bLegacy;
|
|
101901
|
+
const scorecard = s._scorecard;
|
|
101902
|
+
const popDevNormalizedNEW = scorecard.best.populationDeviation.normalized;
|
|
101903
|
+
const bScore = (popDevNormalizedNEW > 0) ? true : false;
|
|
101904
|
+
// TODO - Get scales
|
|
101905
|
+
// TODO - Flow through to RequirementsChecklist
|
|
100025
101906
|
let test = s.getTest(3 /* EqualPopulation */);
|
|
100026
101907
|
// Get the normalized population deviation %
|
|
100027
101908
|
let popDevTest = s.getTest(4 /* PopulationDeviation */);
|
|
@@ -100036,6 +101917,7 @@ function doHasEqualPopulations(s, bLog = false) {
|
|
|
100036
101917
|
}
|
|
100037
101918
|
test['details']['deviation'] = popDevPct;
|
|
100038
101919
|
test['details']['thresholds'] = popDevTest['details']['scale'];
|
|
101920
|
+
console.log("Equal population =", test['score'], bScore);
|
|
100039
101921
|
// Populate the N+1 summary "district" in district.statistics
|
|
100040
101922
|
let bEqualPop = s.districts.statistics[D.DistrictField.bEqualPop];
|
|
100041
101923
|
let summaryRow = s.districts.numberOfRows() - 1;
|
|
@@ -100068,6 +101950,23 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
100068
101950
|
};
|
|
100069
101951
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
100070
101952
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "./node_modules/@dra2020/poly/dist/poly.js"));
|
|
101953
|
+
// HELPER
|
|
101954
|
+
function polyParts(poly) {
|
|
101955
|
+
let parts = { type: 'FeatureCollection', features: [] };
|
|
101956
|
+
let af = parts.features;
|
|
101957
|
+
if (poly.geometry.type === 'MultiPolygon') {
|
|
101958
|
+
// Push all non-contiguous polygons
|
|
101959
|
+
for (let j = 0; j < poly.geometry.coordinates.length; j++) {
|
|
101960
|
+
let onePoly = poly.geometry.coordinates[j];
|
|
101961
|
+
af.push({ type: 'Feature', properties: { id: `${af.length + 1}` }, geometry: { type: 'Polygon', coordinates: onePoly } });
|
|
101962
|
+
}
|
|
101963
|
+
}
|
|
101964
|
+
else {
|
|
101965
|
+
parts.features.push(poly);
|
|
101966
|
+
}
|
|
101967
|
+
return parts;
|
|
101968
|
+
}
|
|
101969
|
+
exports.polyParts = polyParts;
|
|
100071
101970
|
// CARTESIAN SHIMS OVER 'POLY' FUNCTIONS
|
|
100072
101971
|
// TODO - POLY: Confirm Cartesian calculations
|
|
100073
101972
|
function gfArea(poly) {
|
|
@@ -100369,10 +102268,7 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
100369
102268
|
// Sum total population across the state
|
|
100370
102269
|
s.state.totalPop += value;
|
|
100371
102270
|
// Get the county FIPS code for the feature
|
|
100372
|
-
// TODO - VFEATURE
|
|
100373
102271
|
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
100374
|
-
// let county = U.parseGeoID(geoID)['county'] as string;
|
|
100375
|
-
// let countyFIPS = U.getFIPSFromCountyGeoID(county);
|
|
100376
102272
|
// If a subtotal for the county doesn't exist, initialize one
|
|
100377
102273
|
if (!(U.keyExists(countyFIPS, totalByCounty))) {
|
|
100378
102274
|
totalByCounty[countyFIPS] = 0;
|
|
@@ -100390,8 +102286,8 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
100390
102286
|
let fipsCodes = U.getObjectKeys(totalByCounty);
|
|
100391
102287
|
// Sort the results
|
|
100392
102288
|
fipsCodes = fipsCodes.sort();
|
|
100393
|
-
//
|
|
100394
|
-
// Add a dummy county, for county-district splitting analysis
|
|
102289
|
+
// NOTE - This was added for the legacy SPLITTING implementation.
|
|
102290
|
+
// Add a dummy county, for county-district splitting analysis.
|
|
100395
102291
|
fipsCodes.unshift('000');
|
|
100396
102292
|
// Create the ID-ordinal map
|
|
100397
102293
|
for (let i in fipsCodes) {
|
|
@@ -100481,6 +102377,7 @@ const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
|
100481
102377
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
100482
102378
|
const state_reqs_json_1 = __importDefault(__webpack_require__(/*! ../static/state-reqs.json */ "./static/state-reqs.json"));
|
|
100483
102379
|
// Example
|
|
102380
|
+
// TODO - DELETE?
|
|
100484
102381
|
let sampleRequirements = {
|
|
100485
102382
|
score: 2 /* Red */,
|
|
100486
102383
|
metrics: {
|
|
@@ -100504,6 +102401,7 @@ let sampleRequirements = {
|
|
|
100504
102401
|
stateReqs: "https://www.brennancenter.org/sites/default/files/publications/2019_06_50States_FINALsinglepages_20.pdf"
|
|
100505
102402
|
}
|
|
100506
102403
|
};
|
|
102404
|
+
// TODO - DELETE
|
|
100507
102405
|
let sampleCompactness = {
|
|
100508
102406
|
score: 60,
|
|
100509
102407
|
metrics: {
|
|
@@ -100516,6 +102414,7 @@ let sampleCompactness = {
|
|
|
100516
102414
|
},
|
|
100517
102415
|
resources: {}
|
|
100518
102416
|
};
|
|
102417
|
+
// TODO - DELETE
|
|
100519
102418
|
let sampleSplitting = {
|
|
100520
102419
|
score: 73,
|
|
100521
102420
|
metrics: {
|
|
@@ -100533,7 +102432,7 @@ let sampleSplitting = {
|
|
|
100533
102432
|
datasets: {},
|
|
100534
102433
|
resources: {}
|
|
100535
102434
|
};
|
|
100536
|
-
// TODO -
|
|
102435
|
+
// TODO - DELETE
|
|
100537
102436
|
let samplePartisan = {
|
|
100538
102437
|
score: 100,
|
|
100539
102438
|
metrics: {
|
|
@@ -100548,7 +102447,7 @@ let samplePartisan = {
|
|
|
100548
102447
|
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
100549
102448
|
}
|
|
100550
102449
|
};
|
|
100551
|
-
// TODO -
|
|
102450
|
+
// TODO - DELETE
|
|
100552
102451
|
let sampleMinority = {
|
|
100553
102452
|
score: null,
|
|
100554
102453
|
metrics: {
|
|
@@ -100575,6 +102474,7 @@ let sampleMinority = {
|
|
|
100575
102474
|
},
|
|
100576
102475
|
resources: {}
|
|
100577
102476
|
};
|
|
102477
|
+
// TODO - DELETE
|
|
100578
102478
|
exports.samplePlanAnalytics = {
|
|
100579
102479
|
requirements: sampleRequirements,
|
|
100580
102480
|
compactness: sampleCompactness,
|
|
@@ -100583,232 +102483,6 @@ exports.samplePlanAnalytics = {
|
|
|
100583
102483
|
partisan: samplePartisan,
|
|
100584
102484
|
minority: sampleMinority
|
|
100585
102485
|
};
|
|
100586
|
-
/* TODO - SCORE
|
|
100587
|
-
export function preparePlanAnalytics(s: AnalyticsSession, bLog: boolean = false): PlanAnalytics
|
|
100588
|
-
{
|
|
100589
|
-
if (!(s.bPostProcessingDone))
|
|
100590
|
-
{
|
|
100591
|
-
doAnalyzePostProcessing(s);
|
|
100592
|
-
}
|
|
100593
|
-
|
|
100594
|
-
// REQUIREMENTS CATEGORY
|
|
100595
|
-
let paRequirements: RequirementsCategory;
|
|
100596
|
-
|
|
100597
|
-
{
|
|
100598
|
-
let completeTest = s.getTest(T.Test.Complete) as T.TestEntry;
|
|
100599
|
-
let contiguousTest = s.getTest(T.Test.Contiguous) as T.TestEntry;
|
|
100600
|
-
let freeOfHolesTest = s.getTest(T.Test.FreeOfHoles) as T.TestEntry;
|
|
100601
|
-
let equalPopulationTest = s.getTest(T.Test.EqualPopulation) as T.TestEntry;
|
|
100602
|
-
|
|
100603
|
-
// Combine individual checks into an overall score
|
|
100604
|
-
|
|
100605
|
-
// TODO - DASHBOARD: Until we add three-state support top to bottom in
|
|
100606
|
-
// requirements/validations, map booleans to tri-states here.
|
|
100607
|
-
let completeMetric = U.mapBooleanToTriState(completeTest['score'] as boolean);
|
|
100608
|
-
let contiguousMetric = U.mapBooleanToTriState(contiguousTest['score'] as boolean);
|
|
100609
|
-
let freeOfHolesMetric = U.mapBooleanToTriState(freeOfHolesTest['score'] as boolean);
|
|
100610
|
-
let equalPopulationMetric = U.mapBooleanToTriState(equalPopulationTest['score'] as boolean);
|
|
100611
|
-
|
|
100612
|
-
let reqScore: T.TriState = T.TriState.Green;
|
|
100613
|
-
let checks = [completeMetric, contiguousMetric, freeOfHolesMetric, equalPopulationMetric];
|
|
100614
|
-
if (checks.includes(T.TriState.Yellow)) reqScore = T.TriState.Yellow;
|
|
100615
|
-
if (checks.includes(T.TriState.Red)) reqScore = T.TriState.Red;
|
|
100616
|
-
|
|
100617
|
-
// Get values to support details entries
|
|
100618
|
-
let unassignedFeaturesDetail = U.deepCopy(completeTest['details']['unassignedFeatures']) || [];
|
|
100619
|
-
let emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
100620
|
-
let discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
100621
|
-
let embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
100622
|
-
|
|
100623
|
-
let populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
100624
|
-
let deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
100625
|
-
|
|
100626
|
-
let xx: string = s.state.xx;
|
|
100627
|
-
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
100628
|
-
let stateReqsDict: T.Dict = allStateReqs;
|
|
100629
|
-
let reqLinkToStateReqs: string = stateReqsDict[xx];
|
|
100630
|
-
|
|
100631
|
-
// Populate the category
|
|
100632
|
-
paRequirements = {
|
|
100633
|
-
score: reqScore,
|
|
100634
|
-
metrics: {
|
|
100635
|
-
complete: completeMetric,
|
|
100636
|
-
contiguous: contiguousMetric,
|
|
100637
|
-
freeOfHoles: freeOfHolesMetric,
|
|
100638
|
-
equalPopulation: equalPopulationMetric
|
|
100639
|
-
},
|
|
100640
|
-
details: {
|
|
100641
|
-
unassignedFeatures: unassignedFeaturesDetail,
|
|
100642
|
-
emptyDistricts: emptyDistrictsDetail,
|
|
100643
|
-
discontiguousDistricts: discontiguousDistrictsDetail,
|
|
100644
|
-
embeddedDistricts: embeddedDistrictsDetail,
|
|
100645
|
-
populationDeviation: populationDeviationDetail,
|
|
100646
|
-
deviationThreshold: deviationThresholdDetail
|
|
100647
|
-
},
|
|
100648
|
-
datasets: {
|
|
100649
|
-
census: U.deepCopy(s.config['descriptions']['CENSUS']),
|
|
100650
|
-
},
|
|
100651
|
-
resources: {
|
|
100652
|
-
stateReqs: reqLinkToStateReqs
|
|
100653
|
-
}
|
|
100654
|
-
}
|
|
100655
|
-
}
|
|
100656
|
-
|
|
100657
|
-
// COMPACTNESS CATEGORY
|
|
100658
|
-
let paCompactness: CompactnessCategory;
|
|
100659
|
-
{
|
|
100660
|
-
let reockWeight = 0.5;
|
|
100661
|
-
let polsbyWeight = 1.0 - reockWeight;
|
|
100662
|
-
|
|
100663
|
-
let reockTest = s.getTest(T.Test.Reock) as T.TestEntry;
|
|
100664
|
-
let polsbyTest = s.getTest(T.Test.PolsbyPopper) as T.TestEntry;
|
|
100665
|
-
|
|
100666
|
-
let normalizedReock = reockTest['normalizedScore'] as number;
|
|
100667
|
-
let normalizedPolsby = reockTest['normalizedScore'] as number;
|
|
100668
|
-
let compactnessScore = U.trim((reockWeight * normalizedReock) + (polsbyWeight * normalizedPolsby), 0);
|
|
100669
|
-
|
|
100670
|
-
let reockMetric = U.deepCopy(reockTest['score'] as number);
|
|
100671
|
-
let polsbyMetric = U.deepCopy(polsbyTest['score'] as number);
|
|
100672
|
-
|
|
100673
|
-
// Populate the category
|
|
100674
|
-
paCompactness = {
|
|
100675
|
-
score: compactnessScore,
|
|
100676
|
-
metrics: {
|
|
100677
|
-
reock: reockMetric,
|
|
100678
|
-
polsby: polsbyMetric
|
|
100679
|
-
},
|
|
100680
|
-
details: {
|
|
100681
|
-
// None at this time
|
|
100682
|
-
},
|
|
100683
|
-
datasets: {
|
|
100684
|
-
// NOTE - DATASETS
|
|
100685
|
-
shapes: U.deepCopy(s.config['descriptions']['SHAPES'])
|
|
100686
|
-
// shapes: "2010 VTD shapes"
|
|
100687
|
-
},
|
|
100688
|
-
resources: {
|
|
100689
|
-
// None at this time
|
|
100690
|
-
}
|
|
100691
|
-
}
|
|
100692
|
-
}
|
|
100693
|
-
|
|
100694
|
-
// SPLITTING CATEGORY
|
|
100695
|
-
|
|
100696
|
-
let paSplitting: SplittingCategory
|
|
100697
|
-
|
|
100698
|
-
{
|
|
100699
|
-
let unexpectedCountySplittingTest = s.getTest(T.Test.UnexpectedCountySplits) as T.TestEntry;
|
|
100700
|
-
let VTDSplitsTest = s.getTest(T.Test.VTDSplits) as T.TestEntry;
|
|
100701
|
-
let countySplittingTest = s.getTest(T.Test.CountySplitting) as T.TestEntry;
|
|
100702
|
-
let districtSplittingTest = s.getTest(T.Test.DistrictSplitting) as T.TestEntry;
|
|
100703
|
-
|
|
100704
|
-
let unexpectedAffectedMetric = U.deepCopy(unexpectedCountySplittingTest['score']);
|
|
100705
|
-
let countiesSplitUnexpectedlyDetail = U.deepCopy(unexpectedCountySplittingTest['details']['countiesSplitUnexpectedly']);
|
|
100706
|
-
|
|
100707
|
-
let nVTDSplitsMetric = U.deepCopy(VTDSplitsTest['score']);
|
|
100708
|
-
let splitVTDsDetail = U.deepCopy(VTDSplitsTest['details']['splitVTDs']);
|
|
100709
|
-
|
|
100710
|
-
let SqEnt_DCreducedMetric = U.deepCopy(countySplittingTest['score']);
|
|
100711
|
-
let SqEnt_CDreducedMetric = U.deepCopy(districtSplittingTest['score']);
|
|
100712
|
-
|
|
100713
|
-
let countySplittingNormalized = countySplittingTest['normalizedScore'] as number;
|
|
100714
|
-
let districtSplittingNormalized = districtSplittingTest['normalizedScore'] as number;
|
|
100715
|
-
let splittingScore = U.trim((S.COUNTY_SPLITTING_WEIGHT * countySplittingNormalized) +
|
|
100716
|
-
+ (S.DISTRICT_SPLITTING_WEIGHT * districtSplittingNormalized), 0);
|
|
100717
|
-
|
|
100718
|
-
paSplitting = {
|
|
100719
|
-
score: splittingScore,
|
|
100720
|
-
metrics: {
|
|
100721
|
-
sqEnt_DCreduced: SqEnt_DCreducedMetric,
|
|
100722
|
-
sqEnt_CDreduced: SqEnt_CDreducedMetric
|
|
100723
|
-
// NOTE - The un-reduced raw values
|
|
100724
|
-
// sqEnt_DC : SqEnt_DCMetric,
|
|
100725
|
-
// sqEnt_CD : SqEnt_CDMetric
|
|
100726
|
-
},
|
|
100727
|
-
details: {
|
|
100728
|
-
countiesSplitUnexpectedly: countiesSplitUnexpectedlyDetail,
|
|
100729
|
-
unexpectedAffected: unexpectedAffectedMetric,
|
|
100730
|
-
nSplitVTDs: nVTDSplitsMetric,
|
|
100731
|
-
splitVTDs: splitVTDsDetail
|
|
100732
|
-
},
|
|
100733
|
-
datasets: {
|
|
100734
|
-
// None at this time
|
|
100735
|
-
},
|
|
100736
|
-
resources: {
|
|
100737
|
-
// None at this time
|
|
100738
|
-
}
|
|
100739
|
-
}
|
|
100740
|
-
}
|
|
100741
|
-
|
|
100742
|
-
// PARTISAN CATEGORY
|
|
100743
|
-
//
|
|
100744
|
-
// TODO - PARTISAN: This category is still being fleshed out. Just an example below.
|
|
100745
|
-
let paPartisan: PartisanCategory;
|
|
100746
|
-
|
|
100747
|
-
{
|
|
100748
|
-
paPartisan = {
|
|
100749
|
-
score: 100,
|
|
100750
|
-
metrics: {
|
|
100751
|
-
partisanBias: 0.15,
|
|
100752
|
-
responsiveness: 2.0
|
|
100753
|
-
},
|
|
100754
|
-
details: {},
|
|
100755
|
-
datasets: {
|
|
100756
|
-
election: "2016 Presidential, US Senate, Governor, and AG election results"
|
|
100757
|
-
},
|
|
100758
|
-
resources: {
|
|
100759
|
-
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
100760
|
-
}
|
|
100761
|
-
}
|
|
100762
|
-
}
|
|
100763
|
-
|
|
100764
|
-
// MINORITY CATEGORY
|
|
100765
|
-
//
|
|
100766
|
-
// TODO - MINORITY: This category is still being fleshed out. Just an example below.
|
|
100767
|
-
let paMinority: MinorityCategory;
|
|
100768
|
-
|
|
100769
|
-
{
|
|
100770
|
-
paMinority = {
|
|
100771
|
-
score: null,
|
|
100772
|
-
metrics: {
|
|
100773
|
-
nBlack37to50: 1,
|
|
100774
|
-
nBlackMajority: 12,
|
|
100775
|
-
nHispanic37to50: 0,
|
|
100776
|
-
nHispanicMajority: 0,
|
|
100777
|
-
nPacific37to50: 0,
|
|
100778
|
-
nPacificMajority: 0,
|
|
100779
|
-
nAsian37to50: 0,
|
|
100780
|
-
nAsianMajority: 0,
|
|
100781
|
-
nNative37to50: 0,
|
|
100782
|
-
nNativeMajority: 0,
|
|
100783
|
-
nMinority37to50: 0,
|
|
100784
|
-
nMinorityMajority: 0,
|
|
100785
|
-
|
|
100786
|
-
averageDVoteShare: 0.90
|
|
100787
|
-
},
|
|
100788
|
-
details: {
|
|
100789
|
-
vap: true,
|
|
100790
|
-
comboCategories: true
|
|
100791
|
-
},
|
|
100792
|
-
datasets: {
|
|
100793
|
-
vap: "2010 Voting Age Population"
|
|
100794
|
-
},
|
|
100795
|
-
resources: {}
|
|
100796
|
-
}
|
|
100797
|
-
}
|
|
100798
|
-
|
|
100799
|
-
// PLAN ANALYTICS
|
|
100800
|
-
let pa: PlanAnalytics = {
|
|
100801
|
-
requirements: paRequirements,
|
|
100802
|
-
compactness: paCompactness,
|
|
100803
|
-
// TODO - Not implemented yet
|
|
100804
|
-
splitting: paSplitting,
|
|
100805
|
-
partisan: paPartisan,
|
|
100806
|
-
minority: paMinority
|
|
100807
|
-
}
|
|
100808
|
-
|
|
100809
|
-
return pa;
|
|
100810
|
-
}
|
|
100811
|
-
*/
|
|
100812
102486
|
function prepareRequirementsChecklist(s, bLog = false) {
|
|
100813
102487
|
if (!(s.bPostProcessingDone)) {
|
|
100814
102488
|
doAnalyzePostProcessing(s);
|
|
@@ -100816,34 +102490,38 @@ function prepareRequirementsChecklist(s, bLog = false) {
|
|
|
100816
102490
|
// REQUIREMENTS CATEGORY
|
|
100817
102491
|
let paRequirements;
|
|
100818
102492
|
{
|
|
100819
|
-
|
|
100820
|
-
|
|
100821
|
-
|
|
100822
|
-
|
|
102493
|
+
const completeTest = s.getTest(0 /* Complete */);
|
|
102494
|
+
const contiguousTest = s.getTest(1 /* Contiguous */);
|
|
102495
|
+
const freeOfHolesTest = s.getTest(2 /* FreeOfHoles */);
|
|
102496
|
+
const equalPopulationTest = s.getTest(3 /* EqualPopulation */);
|
|
100823
102497
|
// Combine individual checks into an overall score
|
|
100824
|
-
//
|
|
102498
|
+
// NOTE - Until we add three-state support top to bottom in
|
|
100825
102499
|
// requirements/validations, map booleans to tri-states here.
|
|
100826
|
-
|
|
100827
|
-
|
|
100828
|
-
|
|
100829
|
-
|
|
102500
|
+
const completeMetric = U.mapBooleanToTriState(completeTest['score']);
|
|
102501
|
+
const contiguousMetric = U.mapBooleanToTriState(contiguousTest['score']);
|
|
102502
|
+
const freeOfHolesMetric = U.mapBooleanToTriState(freeOfHolesTest['score']);
|
|
102503
|
+
const equalPopulationMetric = U.mapBooleanToTriState(equalPopulationTest['score']);
|
|
100830
102504
|
let reqScore = 0 /* Green */;
|
|
100831
|
-
|
|
102505
|
+
const checks = [completeMetric, contiguousMetric, freeOfHolesMetric, equalPopulationMetric];
|
|
100832
102506
|
if (checks.includes(1 /* Yellow */))
|
|
100833
102507
|
reqScore = 1 /* Yellow */;
|
|
100834
102508
|
if (checks.includes(2 /* Red */))
|
|
100835
102509
|
reqScore = 2 /* Red */;
|
|
100836
102510
|
// Get values to support details entries
|
|
100837
|
-
|
|
100838
|
-
|
|
100839
|
-
|
|
100840
|
-
|
|
100841
|
-
|
|
100842
|
-
|
|
100843
|
-
|
|
102511
|
+
const unassignedFeaturesDetail = U.deepCopy(completeTest['details']['unassignedFeatures']) || [];
|
|
102512
|
+
const emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
102513
|
+
const discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
102514
|
+
const embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
102515
|
+
const scorecard = s._scorecard;
|
|
102516
|
+
const deviationThreshold = scorecard.best.populationDeviation.notes['threshold'];
|
|
102517
|
+
// TODO - SCORE: Toggle
|
|
102518
|
+
const populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
102519
|
+
const deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
102520
|
+
console.log("Population deviation thresholds =", deviationThresholdDetail, deviationThreshold);
|
|
102521
|
+
const xx = s.state.xx;
|
|
100844
102522
|
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
100845
|
-
|
|
100846
|
-
|
|
102523
|
+
const stateReqsDict = state_reqs_json_1.default;
|
|
102524
|
+
const reqLinkToStateReqs = stateReqsDict[xx];
|
|
100847
102525
|
// Populate the category
|
|
100848
102526
|
paRequirements = {
|
|
100849
102527
|
score: reqScore,
|
|
@@ -101106,6 +102784,8 @@ exports.doConfigureScales = doConfigureScales;
|
|
|
101106
102784
|
// Postprocess analytics - Normalize numeric results and derive secondary tests.
|
|
101107
102785
|
// Do this after analytics have been run and before preparing a test log or scorecard.
|
|
101108
102786
|
function doAnalyzePostProcessing(s, bLog = false) {
|
|
102787
|
+
// TODO - SCORE: Toggle
|
|
102788
|
+
// const bLegacy = s._bLegacy;
|
|
101109
102789
|
// Normalize the raw scores for all the numerics tests
|
|
101110
102790
|
let testResults = U.getNumericObjectKeys(testDefns);
|
|
101111
102791
|
for (let testID of testResults) {
|
|
@@ -101149,7 +102829,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
101149
102829
|
return result;
|
|
101150
102830
|
};
|
|
101151
102831
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
101152
|
-
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "
|
|
102832
|
+
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "../dra-score/dist/dra-score.bundle.js"));
|
|
101153
102833
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
101154
102834
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
101155
102835
|
// PROFILE A PLAN
|
|
@@ -101201,13 +102881,11 @@ function makeNakedCxD(s, bLog = false) {
|
|
|
101201
102881
|
let CxD = [];
|
|
101202
102882
|
// Remove the unassigned & total dummy "districts"
|
|
101203
102883
|
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
101204
|
-
// TODO - SCORE: OH has an extra county!?!
|
|
101205
102884
|
const splits = U.deepCopy(adornedCxD[districtID].slice(1));
|
|
101206
102885
|
CxD.push(splits);
|
|
101207
102886
|
}
|
|
101208
102887
|
return CxD;
|
|
101209
102888
|
}
|
|
101210
|
-
// TODO - SCORE: Convert dict of geo props to array by district index
|
|
101211
102889
|
function makeArrayOfGeoProps(s, bLog = false) {
|
|
101212
102890
|
let geometryByDistrict = [];
|
|
101213
102891
|
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
@@ -101305,6 +102983,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
101305
102983
|
return result;
|
|
101306
102984
|
};
|
|
101307
102985
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102986
|
+
const DT = __importStar(__webpack_require__(/*! @dra2020/dra-types */ "./node_modules/@dra2020/dra-types/dist/dra-types.js"));
|
|
101308
102987
|
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
101309
102988
|
// PLAN HELPERS
|
|
101310
102989
|
// Is a "neighbor" in state?
|
|
@@ -101332,7 +103011,6 @@ function getDistrict(plan, geoID) {
|
|
|
101332
103011
|
}
|
|
101333
103012
|
exports.getDistrict = getDistrict;
|
|
101334
103013
|
// WORKING WITH GEOIDS
|
|
101335
|
-
// TODO - VFEATURE
|
|
101336
103014
|
function parseGeoID(geoID) {
|
|
101337
103015
|
let bVfeature = false;
|
|
101338
103016
|
// Rewrite vfeature GEOIDs to enable lexical parsing of higher-level parts
|
|
@@ -101340,12 +103018,7 @@ function parseGeoID(geoID) {
|
|
|
101340
103018
|
// Example: vfeature_39153153ASV_0_28e0bc2c8163e5982e1da2d61e2388a8325c575e
|
|
101341
103019
|
if (geoID.indexOf('vfeature') >= 0) {
|
|
101342
103020
|
bVfeature = true;
|
|
101343
|
-
|
|
101344
|
-
let parentGeoID = geoID.slice(9);
|
|
101345
|
-
// Strip off trailing goo
|
|
101346
|
-
const uPos = parentGeoID.indexOf('_');
|
|
101347
|
-
parentGeoID = parentGeoID.slice(0, uPos);
|
|
101348
|
-
geoID = parentGeoID;
|
|
103021
|
+
geoID = DT.vgeoidToGeoid(geoID);
|
|
101349
103022
|
}
|
|
101350
103023
|
const parts = {
|
|
101351
103024
|
vfeature: bVfeature,
|
|
@@ -101353,29 +103026,9 @@ function parseGeoID(geoID) {
|
|
|
101353
103026
|
county: geoID.substring(2, 5),
|
|
101354
103027
|
rest: geoID.slice(5)
|
|
101355
103028
|
};
|
|
101356
|
-
// let l: number = geoID.length;
|
|
101357
|
-
// if (l >= 11)
|
|
101358
|
-
// {
|
|
101359
|
-
// parts['tract'] = geoID.substring(0, 11);
|
|
101360
|
-
// }
|
|
101361
|
-
// if (l >= 12)
|
|
101362
|
-
// {
|
|
101363
|
-
// parts['bg'] = geoID.substring(0, 12);
|
|
101364
|
-
// }
|
|
101365
|
-
// if (l == 15)
|
|
101366
|
-
// {
|
|
101367
|
-
// parts['block'] = geoID;
|
|
101368
|
-
// }
|
|
101369
103029
|
return parts;
|
|
101370
103030
|
}
|
|
101371
103031
|
exports.parseGeoID = parseGeoID;
|
|
101372
|
-
// TODO - VFEATURE
|
|
101373
|
-
// export function getFIPSFromCountyGeoID(geoID: string): string
|
|
101374
|
-
// {
|
|
101375
|
-
// const fips = geoID.substring(2, 5);
|
|
101376
|
-
// if (isNaN(Number(fips))) console.log("Non-numeric GEOID =", geoID);
|
|
101377
|
-
// return fips;
|
|
101378
|
-
// }
|
|
101379
103032
|
function isWaterOnly(geoID) {
|
|
101380
103033
|
let waterOnlySignature = 'ZZZZZZ';
|
|
101381
103034
|
if (geoID.indexOf(waterOnlySignature) >= 0)
|
|
@@ -102276,113 +103929,6 @@ function formatNumber(n) {
|
|
|
102276
103929
|
let p = S.PRECISION;
|
|
102277
103930
|
return n.toLocaleString('en-US', { minimumFractionDigits: p, maximumFractionDigits: p });
|
|
102278
103931
|
}
|
|
102279
|
-
/* TODO - SCORE: DELETE
|
|
102280
|
-
function echoPlanAnalytics(pa: PlanAnalytics): void
|
|
102281
|
-
{
|
|
102282
|
-
console.log("Plan Analytics:");
|
|
102283
|
-
console.log("");
|
|
102284
|
-
|
|
102285
|
-
console.log("Requirements:");
|
|
102286
|
-
console.log("* Score:", pa.requirements.score);
|
|
102287
|
-
console.log("* Metrics:");
|
|
102288
|
-
console.log(" - Complete:", pa.requirements.metrics.complete);
|
|
102289
|
-
console.log(" - Contiguous:", pa.requirements.metrics.contiguous);
|
|
102290
|
-
console.log(" - Free of holes:", pa.requirements.metrics.freeOfHoles);
|
|
102291
|
-
console.log(" - Equal population:", pa.requirements.metrics.equalPopulation);
|
|
102292
|
-
console.log("* Details:");
|
|
102293
|
-
console.log(" - Empty districts:", prepareListItems(pa.requirements.details.emptyDistricts));
|
|
102294
|
-
console.log(" - Unassigned features:", prepareListItems(pa.requirements.details.unassignedFeatures));
|
|
102295
|
-
console.log(" - Population deviation:", pa.requirements.details.populationDeviation);
|
|
102296
|
-
console.log(" - Deviation threshold:", pa.requirements.details.deviationThreshold);
|
|
102297
|
-
console.log(" - Discontiguous districts:", prepareListItems(pa.requirements.details.discontiguousDistricts));
|
|
102298
|
-
console.log(" - Embedded districts:", prepareListItems(pa.requirements.details.embeddedDistricts));
|
|
102299
|
-
console.log("* Datasets:");
|
|
102300
|
-
console.log("- Shapes:", pa.requirements.datasets.shapes);
|
|
102301
|
-
console.log("- Census:", pa.requirements.datasets.census);
|
|
102302
|
-
console.log("- VAP:", pa.requirements.datasets.vap);
|
|
102303
|
-
console.log("- Election:", pa.requirements.datasets.election);
|
|
102304
|
-
console.log("* Resources:");
|
|
102305
|
-
console.log("- State requirements:", pa.requirements.resources.stateReqs);
|
|
102306
|
-
console.log("");
|
|
102307
|
-
|
|
102308
|
-
console.log("Compactness:");
|
|
102309
|
-
console.log("* Score:", pa.compactness.score);
|
|
102310
|
-
console.log("* Metrics:");
|
|
102311
|
-
console.log(" - Reock:", pa.compactness.metrics.reock);
|
|
102312
|
-
console.log(" - Polsby-Popper:", pa.compactness.metrics.polsby);
|
|
102313
|
-
console.log("* Details:");
|
|
102314
|
-
console.log(" - N/A");
|
|
102315
|
-
console.log("* Datasets:");
|
|
102316
|
-
console.log("- Shapes:", pa.compactness.datasets.shapes);
|
|
102317
|
-
console.log("- Census:", pa.compactness.datasets.census);
|
|
102318
|
-
console.log("- VAP:", pa.compactness.datasets.vap);
|
|
102319
|
-
console.log("- Election:", pa.compactness.datasets.election);
|
|
102320
|
-
console.log("* Resources:");
|
|
102321
|
-
console.log("- N/A");
|
|
102322
|
-
console.log("");
|
|
102323
|
-
|
|
102324
|
-
console.log("Splitting:");
|
|
102325
|
-
console.log("* Score:", pa.splitting.score);
|
|
102326
|
-
console.log("* Metrics:");
|
|
102327
|
-
console.log(" - sqEnt_DCreduced:", pa.splitting.metrics.sqEnt_DCreduced);
|
|
102328
|
-
console.log(" - sqEnt_CDreduced:", pa.splitting.metrics.sqEnt_CDreduced);
|
|
102329
|
-
console.log("* Details:");
|
|
102330
|
-
console.log(" - countiesSplitUnexpectedly:", prepareListItems(pa.splitting.details.countiesSplitUnexpectedly));
|
|
102331
|
-
console.log(" - unexpectedAffected:", pa.splitting.details.unexpectedAffected);
|
|
102332
|
-
console.log(" - splitVTDs:", pa.splitting.details.splitVTDs);
|
|
102333
|
-
console.log("* Datasets:");
|
|
102334
|
-
console.log("- Shapes:", pa.splitting.datasets.shapes);
|
|
102335
|
-
console.log("- Census:", pa.splitting.datasets.census);
|
|
102336
|
-
console.log("- VAP:", pa.splitting.datasets.vap);
|
|
102337
|
-
console.log("- Election:", pa.splitting.datasets.election);
|
|
102338
|
-
console.log("* Resources:");
|
|
102339
|
-
console.log("- N/A");
|
|
102340
|
-
console.log("");
|
|
102341
|
-
|
|
102342
|
-
console.log("Partisan:");
|
|
102343
|
-
console.log("* Score:", pa.partisan.score);
|
|
102344
|
-
console.log("* Metrics:");
|
|
102345
|
-
console.log(" - sqEnt_DCreduced:", pa.partisan.metrics.partisanBias);
|
|
102346
|
-
console.log(" - sqEnt_CDreduced:", pa.partisan.metrics.responsiveness);
|
|
102347
|
-
console.log("* Details:");
|
|
102348
|
-
console.log(" - N/A");
|
|
102349
|
-
console.log("* Datasets:");
|
|
102350
|
-
console.log("- Shapes:", pa.partisan.datasets.shapes);
|
|
102351
|
-
console.log("- Census:", pa.partisan.datasets.census);
|
|
102352
|
-
console.log("- VAP:", pa.partisan.datasets.vap);
|
|
102353
|
-
console.log("- Election:", pa.partisan.datasets.election);
|
|
102354
|
-
console.log("* Resources:");
|
|
102355
|
-
console.log(" - Plan Score:", pa.partisan.resources.planScore);
|
|
102356
|
-
console.log("");
|
|
102357
|
-
|
|
102358
|
-
console.log("Minority:");
|
|
102359
|
-
console.log("* Score:", pa.minority.score);
|
|
102360
|
-
console.log("* Metrics:");
|
|
102361
|
-
console.log(" - nBlack37to50:", pa.minority.metrics.nBlack37to50);
|
|
102362
|
-
console.log(" - nBlackMajority:", pa.minority.metrics.nBlackMajority);
|
|
102363
|
-
console.log(" - nHispanic37to50:", pa.minority.metrics.nHispanic37to50);
|
|
102364
|
-
console.log(" - nHispanicMajority:", pa.minority.metrics.nHispanicMajority);
|
|
102365
|
-
console.log(" - nPacific37to50:", pa.minority.metrics.nPacific37to50);
|
|
102366
|
-
console.log(" - nPacificMajority:", pa.minority.metrics.nPacificMajority);
|
|
102367
|
-
console.log(" - nAsian37to50:", pa.minority.metrics.nAsian37to50);
|
|
102368
|
-
console.log(" - nAsianMajority:", pa.minority.metrics.nAsianMajority);
|
|
102369
|
-
console.log(" - nNative37to50:", pa.minority.metrics.nNative37to50);
|
|
102370
|
-
console.log(" - nNativeMajority:", pa.minority.metrics.nNativeMajority);
|
|
102371
|
-
console.log(" - nMinority37to50:", pa.minority.metrics.nMinority37to50);
|
|
102372
|
-
console.log(" - nMinorityMajority:", pa.minority.metrics.nMinorityMajority);
|
|
102373
|
-
console.log("* Details:");
|
|
102374
|
-
console.log(" - VAP:", pa.minority.details.vap);
|
|
102375
|
-
console.log(" - comboCategoroes:", pa.minority.details.comboCategories);
|
|
102376
|
-
console.log("* Datasets:");
|
|
102377
|
-
console.log("- Shapes:", pa.minority.datasets.shapes);
|
|
102378
|
-
console.log("- Census:", pa.minority.datasets.census);
|
|
102379
|
-
console.log("- VAP:", pa.minority.datasets.vap);
|
|
102380
|
-
console.log("- Election:", pa.minority.datasets.election);
|
|
102381
|
-
console.log("* Resources:");
|
|
102382
|
-
console.log("- N/A");
|
|
102383
|
-
console.log("");
|
|
102384
|
-
}
|
|
102385
|
-
*/
|
|
102386
103932
|
function echoDistrictStatistics(ds) {
|
|
102387
103933
|
console.log("District Statistics:");
|
|
102388
103934
|
for (let row of ds.table) {
|
|
@@ -102493,6 +104039,17 @@ module.exports = require("assert");
|
|
|
102493
104039
|
|
|
102494
104040
|
/***/ }),
|
|
102495
104041
|
|
|
104042
|
+
/***/ "crypto":
|
|
104043
|
+
/*!*************************!*\
|
|
104044
|
+
!*** external "crypto" ***!
|
|
104045
|
+
\*************************/
|
|
104046
|
+
/*! no static exports found */
|
|
104047
|
+
/***/ (function(module, exports) {
|
|
104048
|
+
|
|
104049
|
+
module.exports = require("crypto");
|
|
104050
|
+
|
|
104051
|
+
/***/ }),
|
|
104052
|
+
|
|
102496
104053
|
/***/ "fs":
|
|
102497
104054
|
/*!*********************!*\
|
|
102498
104055
|
!*** external "fs" ***!
|