@dra2020/district-analytics 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +2124 -531
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +247 -356
- 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/dist/src/score.d.ts +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -89269,8 +89269,8 @@ const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
|
89269
89269
|
class Scorer {
|
|
89270
89270
|
constructor() {
|
|
89271
89271
|
}
|
|
89272
|
-
score(
|
|
89273
|
-
return score_1.scorePlan(
|
|
89272
|
+
score(profile, overridesJSON) {
|
|
89273
|
+
return score_1.scorePlan(profile, overridesJSON);
|
|
89274
89274
|
}
|
|
89275
89275
|
}
|
|
89276
89276
|
exports.Scorer = Scorer;
|
|
@@ -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) {
|
|
90353
90357
|
// BEST subcategories - compactness, splitting, population deviation
|
|
90354
90358
|
// Compactness
|
|
90355
90359
|
const reockM = compact_1.doReock(p.compactnessProfile.GeometryByDistrict);
|
|
@@ -90402,10 +90406,10 @@ exports.scorePlan = scorePlan;
|
|
|
90402
90406
|
|
|
90403
90407
|
/***/ }),
|
|
90404
90408
|
|
|
90405
|
-
/***/ "./src/
|
|
90406
|
-
|
|
90407
|
-
!*** ./src/
|
|
90408
|
-
|
|
90409
|
+
/***/ "./src/settings.json":
|
|
90410
|
+
/*!***************************!*\
|
|
90411
|
+
!*** ./src/settings.json ***!
|
|
90412
|
+
\***************************/
|
|
90409
90413
|
/*! exports provided: fair, best, default */
|
|
90410
90414
|
/***/ (function(module) {
|
|
90411
90415
|
|
|
@@ -90443,39 +90447,33 @@ exports.PRECISION = 4;
|
|
|
90443
90447
|
exports.AVERAGE_BLOCK_SIZE = 30;
|
|
90444
90448
|
exports.EQUAL_TOLERANCE = exports.AVERAGE_BLOCK_SIZE / 2;
|
|
90445
90449
|
// SCORING PARAMETERS
|
|
90446
|
-
const
|
|
90450
|
+
const settings_json_1 = __importDefault(__webpack_require__(/*! ./settings.json */ "./src/settings.json"));
|
|
90451
|
+
// TODO - DELETE
|
|
90447
90452
|
function readOverrides() {
|
|
90448
|
-
// TODO - TERRY: Replumb this to:
|
|
90449
|
-
// - Respond to an environment variable or config.json, and
|
|
90450
|
-
// - Read settings.json at runtime from S3
|
|
90451
|
-
// - Otherwise return false/null, so the conditionals below work
|
|
90452
|
-
// - Note the utils/settings interdependency
|
|
90453
|
-
// return U.readJSON('scoring-overrides.json');
|
|
90454
90453
|
return undefined;
|
|
90455
90454
|
}
|
|
90456
|
-
|
|
90457
|
-
let overrides = readOverrides();
|
|
90455
|
+
const overrides = readOverrides();
|
|
90458
90456
|
// SETTINGS FOR PARTISAN SCORING
|
|
90459
|
-
exports.MIN_CONTESTED = overrides ? overrides.fair.competitive.min :
|
|
90460
|
-
exports.MAX_CONTESTED = overrides ? overrides.fair.competitive.max :
|
|
90457
|
+
exports.MIN_CONTESTED = overrides ? overrides.fair.competitive.min : settings_json_1.default.fair.competitive.min;
|
|
90458
|
+
exports.MAX_CONTESTED = overrides ? overrides.fair.competitive.max : settings_json_1.default.fair.competitive.max;
|
|
90461
90459
|
// SCALES FOR NORMALIZING RAW VALUES
|
|
90462
90460
|
// Compactness scales
|
|
90463
|
-
exports.REOCK_WORST = overrides ? overrides.best.compact.reock.worst :
|
|
90464
|
-
exports.REOCK_BEST = overrides ? overrides.best.compact.reock.best :
|
|
90465
|
-
exports.POLSBY_WORST = overrides ? overrides.best.compact.polsby.worst :
|
|
90466
|
-
exports.POLSBY_BEST = overrides ? overrides.best.compact.polsby.best :
|
|
90461
|
+
exports.REOCK_WORST = overrides ? overrides.best.compact.reock.worst : settings_json_1.default.best.compact.reock.worst;
|
|
90462
|
+
exports.REOCK_BEST = overrides ? overrides.best.compact.reock.best : settings_json_1.default.best.compact.reock.best;
|
|
90463
|
+
exports.POLSBY_WORST = overrides ? overrides.best.compact.polsby.worst : settings_json_1.default.best.compact.polsby.worst;
|
|
90464
|
+
exports.POLSBY_BEST = overrides ? overrides.best.compact.polsby.best : settings_json_1.default.best.compact.polsby.best;
|
|
90467
90465
|
// County-District splitting scales (not inverted)
|
|
90468
|
-
exports.COUNTY_BEST = overrides ? overrides.best.cohesive.county.best :
|
|
90469
|
-
exports.COUNTY_WORST = overrides ? overrides.best.cohesive.county.worst :
|
|
90470
|
-
exports.ALLOWABLE_SPLITS_MULTIPLIER = overrides ? overrides.best.cohesive.county.allowableSplitsMultiplier :
|
|
90471
|
-
exports.DISTRICT_BEST = overrides ? overrides.best.cohesive.district.best :
|
|
90472
|
-
exports.DISTRICT_WORST = overrides ? overrides.best.cohesive.district.worst :
|
|
90466
|
+
exports.COUNTY_BEST = overrides ? overrides.best.cohesive.county.best : settings_json_1.default.best.cohesive.county.best;
|
|
90467
|
+
exports.COUNTY_WORST = overrides ? overrides.best.cohesive.county.worst : settings_json_1.default.best.cohesive.county.worst;
|
|
90468
|
+
exports.ALLOWABLE_SPLITS_MULTIPLIER = overrides ? overrides.best.cohesive.county.allowableSplitsMultiplier : settings_json_1.default.best.cohesive.county.allowableSplitsMultiplier;
|
|
90469
|
+
exports.DISTRICT_BEST = overrides ? overrides.best.cohesive.district.best : settings_json_1.default.best.cohesive.district.best;
|
|
90470
|
+
exports.DISTRICT_WORST = overrides ? overrides.best.cohesive.district.worst : settings_json_1.default.best.cohesive.district.worst;
|
|
90473
90471
|
// Population deviation thresholds & scales (inverted)
|
|
90474
|
-
exports.POPDEV_WORST = overrides ? overrides.best.equal.worst :
|
|
90475
|
-
exports.POPDEV_BEST = overrides ? overrides.best.equal.best :
|
|
90472
|
+
exports.POPDEV_WORST = overrides ? overrides.best.equal.worst : settings_json_1.default.best.equal.worst;
|
|
90473
|
+
exports.POPDEV_BEST = overrides ? overrides.best.equal.best : settings_json_1.default.best.equal.best;
|
|
90476
90474
|
exports.POPEQ_MIN = 1.0 - exports.POPDEV_WORST;
|
|
90477
90475
|
exports.POPEQ_MAX = 1.0 - exports.POPDEV_BEST;
|
|
90478
|
-
exports.POPDEV_WORST_LD = overrides ? overrides.best.equal.stateLeg.worst :
|
|
90476
|
+
exports.POPDEV_WORST_LD = overrides ? overrides.best.equal.stateLeg.worst : settings_json_1.default.best.equal.stateLeg.worst;
|
|
90479
90477
|
exports.POPDEV_BEST_LD = ((exports.POPDEV_BEST / exports.POPDEV_WORST) * exports.POPDEV_WORST_LD);
|
|
90480
90478
|
exports.POPEQ_MIN_LD = 1.0 - exports.POPDEV_WORST_LD;
|
|
90481
90479
|
exports.POPEQ_MAX_LD = 1.0 - exports.POPDEV_BEST_LD;
|
|
@@ -90483,27 +90481,27 @@ exports.POPEQ_MAX_LD = 1.0 - exports.POPDEV_BEST_LD;
|
|
|
90483
90481
|
// TODO - SCORE:
|
|
90484
90482
|
// * How wide a range do we want for bias? 10%? 20%?
|
|
90485
90483
|
// * Do we want it to be state-specific? E.g., one seat?
|
|
90486
|
-
exports.BIAS_WORST = overrides ? overrides.fair.unbiased.worst :
|
|
90487
|
-
exports.BIAS_BEST = overrides ? overrides.fair.unbiased.best :
|
|
90484
|
+
exports.BIAS_WORST = overrides ? overrides.fair.unbiased.worst : settings_json_1.default.fair.unbiased.worst;
|
|
90485
|
+
exports.BIAS_BEST = overrides ? overrides.fair.unbiased.best : settings_json_1.default.fair.unbiased.best;
|
|
90488
90486
|
// The range for raw overall competitiveness values
|
|
90489
|
-
exports.COMPETITIVE_WORST = overrides ? overrides.fair.competitive.worst :
|
|
90490
|
-
exports.COMPETITIVE_BEST = overrides ? overrides.fair.competitive.best :
|
|
90487
|
+
exports.COMPETITIVE_WORST = overrides ? overrides.fair.competitive.worst : settings_json_1.default.fair.competitive.worst;
|
|
90488
|
+
exports.COMPETITIVE_BEST = overrides ? overrides.fair.competitive.best : settings_json_1.default.fair.competitive.best;
|
|
90491
90489
|
// WEIGHTS FOR COMBINING NORMALIZED VALUES
|
|
90492
|
-
exports.REOCK_WEIGHT = overrides ? overrides.best.compact.reock.weight :
|
|
90493
|
-
exports.POLSBY_WEIGHT = overrides ? overrides.best.compact.polsby.weight :
|
|
90494
|
-
exports.COUNTY_WEIGHT = overrides ? overrides.best.cohesive.county.weight :
|
|
90495
|
-
exports.DISTRICT_WEIGHT = overrides ? overrides.best.cohesive.district.weight :
|
|
90496
|
-
exports.COMPACTNESS_WEIGHT = overrides ? overrides.best.compact.weight :
|
|
90497
|
-
exports.SPLITTING_WEIGHT = overrides ? overrides.best.cohesive.weight :
|
|
90498
|
-
exports.POPDEV_WEIGHT = overrides ? overrides.best.equal.weight :
|
|
90490
|
+
exports.REOCK_WEIGHT = overrides ? overrides.best.compact.reock.weight : settings_json_1.default.best.compact.reock.weight;
|
|
90491
|
+
exports.POLSBY_WEIGHT = overrides ? overrides.best.compact.polsby.weight : settings_json_1.default.best.compact.polsby.weight;
|
|
90492
|
+
exports.COUNTY_WEIGHT = overrides ? overrides.best.cohesive.county.weight : settings_json_1.default.best.cohesive.county.weight;
|
|
90493
|
+
exports.DISTRICT_WEIGHT = overrides ? overrides.best.cohesive.district.weight : settings_json_1.default.best.cohesive.district.weight;
|
|
90494
|
+
exports.COMPACTNESS_WEIGHT = overrides ? overrides.best.compact.weight : settings_json_1.default.best.compact.weight;
|
|
90495
|
+
exports.SPLITTING_WEIGHT = overrides ? overrides.best.cohesive.weight : settings_json_1.default.best.cohesive.weight;
|
|
90496
|
+
exports.POPDEV_WEIGHT = overrides ? overrides.best.equal.weight : settings_json_1.default.best.equal.weight;
|
|
90499
90497
|
// TODO - SCORE: What kind of relative weighting do we want between marginal and
|
|
90500
90498
|
// overall competitiveness?
|
|
90501
|
-
exports.MARGINAL_WEIGHT = overrides ? overrides.fair.competitive.marginal :
|
|
90502
|
-
exports.OVERALL_WEIGHT = overrides ? overrides.fair.competitive.overall :
|
|
90503
|
-
exports.BIAS_WEIGHT = overrides ? overrides.fair.unbiased.weight :
|
|
90504
|
-
exports.COMPETITIVE_WEIGHT = overrides ? overrides.fair.competitive.weight :
|
|
90505
|
-
exports.FAIR_WEIGHT = overrides ? overrides.fair.weight :
|
|
90506
|
-
exports.BEST_WEIGHT = overrides ? overrides.best.weight :
|
|
90499
|
+
exports.MARGINAL_WEIGHT = overrides ? overrides.fair.competitive.marginal : settings_json_1.default.fair.competitive.marginal;
|
|
90500
|
+
exports.OVERALL_WEIGHT = overrides ? overrides.fair.competitive.overall : settings_json_1.default.fair.competitive.overall;
|
|
90501
|
+
exports.BIAS_WEIGHT = overrides ? overrides.fair.unbiased.weight : settings_json_1.default.fair.unbiased.weight;
|
|
90502
|
+
exports.COMPETITIVE_WEIGHT = overrides ? overrides.fair.competitive.weight : settings_json_1.default.fair.competitive.weight;
|
|
90503
|
+
exports.FAIR_WEIGHT = overrides ? overrides.fair.weight : settings_json_1.default.fair.weight;
|
|
90504
|
+
exports.BEST_WEIGHT = overrides ? overrides.best.weight : settings_json_1.default.best.weight;
|
|
90507
90505
|
|
|
90508
90506
|
|
|
90509
90507
|
/***/ }),
|
|
@@ -90603,35 +90601,1846 @@ function deepCopy(src) {
|
|
|
90603
90601
|
else
|
|
90604
90602
|
return src;
|
|
90605
90603
|
}
|
|
90606
|
-
exports.deepCopy = deepCopy;
|
|
90604
|
+
exports.deepCopy = deepCopy;
|
|
90605
|
+
|
|
90606
|
+
|
|
90607
|
+
/***/ }),
|
|
90608
|
+
|
|
90609
|
+
/***/ "./testdata/profiles/sample-profile.json":
|
|
90610
|
+
/*!***********************************************!*\
|
|
90611
|
+
!*** ./testdata/profiles/sample-profile.json ***!
|
|
90612
|
+
\***********************************************/
|
|
90613
|
+
/*! exports provided: state, planName, nDistricts, nCounties, legislativeDistricts, populationProfile, compactnessProfile, splittingProfile, partisanProfile, demographicProfile, default */
|
|
90614
|
+
/***/ (function(module) {
|
|
90615
|
+
|
|
90616
|
+
module.exports = JSON.parse("{\"state\":\"NC\",\"planName\":\"Sample profile\",\"nDistricts\":13,\"nCounties\":100,\"legislativeDistricts\":false,\"populationProfile\":{\"TotalPopByDistrict\":[725807,721754,732627,733218,730051,729580,728476,729721,731507,724085,733447,730845,729710],\"targetSize\":729294},\"compactnessProfile\":{\"GeometryByDistrict\":[[1.5773977911324972,10.187637000340999,2.6574300583946115],[0.7058475358440041,7.6543777040386445,1.7632772181381422],[2.920140664739499,9.983421957097065,2.733997011824872],[0.19139679136850038,3.5473804553379114,0.9224411598627837],[1.0389865962844946,6.505473449741405,2.1061393959539023],[1.0334553158144995,6.472595447414713,1.6394147493749138],[1.6241801669130118,8.040301088673953,1.952917034583555],[0.7706765524270006,7.015983900119356,2.1886348192462464],[0.9976965229710011,8.405282685068,2.5604335810665138],[0.676265120610002,5.866361656441843,1.7264712385837822],[1.719226531340005,10.410671767954964,3.1586859214584764],[0.11329460131899982,2.3038812649606695,0.5379072920877442],[0.48373856130249987,5.267369326010034,1.45173753753012]]},\"splittingProfile\":{\"CountyPopByDistrict\":[[0,0,0,0,0,0,0,0,21282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240299,56552,0,0,0,12197,0,59916,0,0,54691,0,0,0,24669,0,0,0,0,0,0,0,0,0,0,0,0,24505,0,0,0,0,0,0,22099,0,0,0,0,0,0,0,74235,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45422,0,20972,13228,0,0,0,55740,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60619,0,0,0,0,0,0,0,114678,0,0,0,0,0,0,0,109245,0,0,0,0,0,0,0,0,0,0,0,0,95840,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,324879,0,0,0,0,0,16493,0,0],[0,0,0,0,0,0,0,47759,0,0,0,0,0,0,0,9980,66469,0,0,0,0,14793,0,0,0,103505,0,23547,33920,0,0,0,0,0,0,0,0,0,0,0,21362,0,0,0,0,0,0,0,5810,0,0,0,10153,0,59495,0,0,0,0,0,0,0,0,0,0,0,0,177772,0,13144,40661,0,13453,0,86397,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4407,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27288,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133801,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,572129,0,0,0,0,0,0,0,0],[0,0,37198,11155,0,27281,17797,0,0,0,0,0,0,0,0,0,0,0,6051,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,350670,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47401,73673,0,0,0,0,0,0,0,0,51079,0,69340,0,38406,0],[0,151131,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23719,0,63505,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,158500,0,0,0,0,0,0,0,0,0,0,0,57866,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39464,0,0,141752,0,0,93643,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,8316,107431,0,0,0,0,0,0,0,0,0,0,0,0,0,58098,0,0,0,0,0,0,58505,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55188,0,0,0,0,0,0,0,0,0,0,0,0,0,202667,0,0,0,0,0,52217,0,0,0,0,0,0,0,0,0,0,63431,0,0,0,0,0,0,0,0,0,0,0,0,0,122623,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,178011,0,0,0,0,0,0,0,0,0,0,0,0,242290,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46952,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27798,88247,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,85838,0,0,0,60585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,26948,0,0,0,0,25045,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,75524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185734,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,46639,134168,0,0,0,0,36157,0,0,0,0,0,0,201292,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,108857,0,0,0,0,0,0,144479,0,0,0,0,98078,0,0,0,0,0,0,0,0,0,0,0,0,206086,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,78265,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20510,0,0,0,0,0,67810,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,126417,90912,0,83029,0,0,0,0,0,27444,0,10587,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8861,0,0,0,0,0,59036,106740,0,0,0,0,40271,0,0,0,0,0,44996,33922,20764,0,0,15579,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13981,33090,0,0,0,0,0,0,0,0,0,0,0,17818],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,730845,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,162878,41240,0,0,0,0,0,0,0,0,0,0,325932,0,0,0,0,0,0,0,150509,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,49151,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]},\"partisanProfile\":{\"statewideVf\":0.515036,\"VfArray\":[0.4235,0.428588,0.43388,0.443866,0.454505,0.456985,0.458005,0.458134,0.463947,0.473144,0.718314,0.73662,0.775817]},\"demographicProfile\":{\"DemographicsByDistrict\":[[0.462,0.538,0.0659,0.4445,0.0219,0.0009,0.013],[0.7063,0.2937,0.0714,0.1968,0.0203,0.001,0.0113],[0.7125,0.2875,0.0537,0.2118,0.0163,0.0021,0.0104],[0.6162,0.3838,0.0869,0.2239,0.0715,0.0012,0.0101],[0.7767,0.2233,0.0669,0.1402,0.013,0.0008,0.0077],[0.7112,0.2888,0.0715,0.1985,0.0136,0.0008,0.0102],[0.7086,0.2914,0.0695,0.2023,0.0097,0.0011,0.0142],[0.6698,0.3302,0.0725,0.224,0.0229,0.0029,0.0188],[0.6406,0.3594,0.0594,0.1962,0.0222,0.001,0.0862],[0.8193,0.1807,0.0451,0.1158,0.0141,0.0007,0.008],[0.8956,0.1044,0.0433,0.0327,0.0103,0.0012,0.0197],[0.4657,0.5343,0.1215,0.3618,0.0507,0.0017,0.011],[0.698,0.302,0.0572,0.2117,0.0286,0.0009,0.0095]]}}");
|
|
90617
|
+
|
|
90618
|
+
/***/ }),
|
|
90619
|
+
|
|
90620
|
+
/***/ "./testdata/profiles/sample-scorecard.json":
|
|
90621
|
+
/*!*************************************************!*\
|
|
90622
|
+
!*** ./testdata/profiles/sample-scorecard.json ***!
|
|
90623
|
+
\*************************************************/
|
|
90624
|
+
/*! exports provided: score, best, fair, default */
|
|
90625
|
+
/***/ (function(module) {
|
|
90626
|
+
|
|
90627
|
+
module.exports = JSON.parse("{\"score\":5,\"best\":{\"BestScore\":18,\"compactness\":{\"score\":35,\"reock\":{\"raw\":0.3373,\"normalized\":35,\"notes\":{}},\"polsby\":{\"raw\":0.2418,\"normalized\":35,\"notes\":{}}},\"splitting\":{\"score\":0,\"county\":{\"raw\":1.1474,\"normalized\":0,\"notes\":{}},\"district\":{\"raw\":1.4839,\"normalized\":3,\"notes\":{}}},\"populationDeviation\":{\"raw\":0.016,\"normalized\":0,\"notes\":{\"maxDeviation\":11693}}},\"fair\":{\"bias\":{\"BestS\":7,\"BestSf\":0.5385,\"ProbableS\":4.1925,\"ProbableSf\":0.3225,\"Bias\":0.216,\"normalized\":0,\"notes\":{}},\"competitiveness\":{\"Cd\":0.7266,\"Cdf\":0.0559,\"Mdf\":0.1019,\"normalized\":10,\"notes\":{}},\"score\":2,\"notes\":{}}}");
|
|
90628
|
+
|
|
90629
|
+
/***/ })
|
|
90630
|
+
|
|
90631
|
+
/******/ });
|
|
90632
|
+
});
|
|
90633
|
+
|
|
90634
|
+
|
|
90635
|
+
/***/ }),
|
|
90636
|
+
|
|
90637
|
+
/***/ "./node_modules/@dra2020/dra-types/dist/dra-types.js":
|
|
90638
|
+
/*!***********************************************************!*\
|
|
90639
|
+
!*** ./node_modules/@dra2020/dra-types/dist/dra-types.js ***!
|
|
90640
|
+
\***********************************************************/
|
|
90641
|
+
/*! no static exports found */
|
|
90642
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
90643
|
+
|
|
90644
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
90645
|
+
if(true)
|
|
90646
|
+
module.exports = factory();
|
|
90647
|
+
else {}
|
|
90648
|
+
})(global, function() {
|
|
90649
|
+
return /******/ (function(modules) { // webpackBootstrap
|
|
90650
|
+
/******/ // The module cache
|
|
90651
|
+
/******/ var installedModules = {};
|
|
90652
|
+
/******/
|
|
90653
|
+
/******/ // The require function
|
|
90654
|
+
/******/ function __webpack_require__(moduleId) {
|
|
90655
|
+
/******/
|
|
90656
|
+
/******/ // Check if module is in cache
|
|
90657
|
+
/******/ if(installedModules[moduleId]) {
|
|
90658
|
+
/******/ return installedModules[moduleId].exports;
|
|
90659
|
+
/******/ }
|
|
90660
|
+
/******/ // Create a new module (and put it into the cache)
|
|
90661
|
+
/******/ var module = installedModules[moduleId] = {
|
|
90662
|
+
/******/ i: moduleId,
|
|
90663
|
+
/******/ l: false,
|
|
90664
|
+
/******/ exports: {}
|
|
90665
|
+
/******/ };
|
|
90666
|
+
/******/
|
|
90667
|
+
/******/ // Execute the module function
|
|
90668
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
90669
|
+
/******/
|
|
90670
|
+
/******/ // Flag the module as loaded
|
|
90671
|
+
/******/ module.l = true;
|
|
90672
|
+
/******/
|
|
90673
|
+
/******/ // Return the exports of the module
|
|
90674
|
+
/******/ return module.exports;
|
|
90675
|
+
/******/ }
|
|
90676
|
+
/******/
|
|
90677
|
+
/******/
|
|
90678
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
90679
|
+
/******/ __webpack_require__.m = modules;
|
|
90680
|
+
/******/
|
|
90681
|
+
/******/ // expose the module cache
|
|
90682
|
+
/******/ __webpack_require__.c = installedModules;
|
|
90683
|
+
/******/
|
|
90684
|
+
/******/ // define getter function for harmony exports
|
|
90685
|
+
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
90686
|
+
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
90687
|
+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
90688
|
+
/******/ }
|
|
90689
|
+
/******/ };
|
|
90690
|
+
/******/
|
|
90691
|
+
/******/ // define __esModule on exports
|
|
90692
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
90693
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
90694
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
90695
|
+
/******/ }
|
|
90696
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
90697
|
+
/******/ };
|
|
90698
|
+
/******/
|
|
90699
|
+
/******/ // create a fake namespace object
|
|
90700
|
+
/******/ // mode & 1: value is a module id, require it
|
|
90701
|
+
/******/ // mode & 2: merge all properties of value into the ns
|
|
90702
|
+
/******/ // mode & 4: return value when already ns object
|
|
90703
|
+
/******/ // mode & 8|1: behave like require
|
|
90704
|
+
/******/ __webpack_require__.t = function(value, mode) {
|
|
90705
|
+
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
90706
|
+
/******/ if(mode & 8) return value;
|
|
90707
|
+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
90708
|
+
/******/ var ns = Object.create(null);
|
|
90709
|
+
/******/ __webpack_require__.r(ns);
|
|
90710
|
+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
90711
|
+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
90712
|
+
/******/ return ns;
|
|
90713
|
+
/******/ };
|
|
90714
|
+
/******/
|
|
90715
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
90716
|
+
/******/ __webpack_require__.n = function(module) {
|
|
90717
|
+
/******/ var getter = module && module.__esModule ?
|
|
90718
|
+
/******/ function getDefault() { return module['default']; } :
|
|
90719
|
+
/******/ function getModuleExports() { return module; };
|
|
90720
|
+
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
90721
|
+
/******/ return getter;
|
|
90722
|
+
/******/ };
|
|
90723
|
+
/******/
|
|
90724
|
+
/******/ // Object.prototype.hasOwnProperty.call
|
|
90725
|
+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
90726
|
+
/******/
|
|
90727
|
+
/******/ // __webpack_public_path__
|
|
90728
|
+
/******/ __webpack_require__.p = "";
|
|
90729
|
+
/******/
|
|
90730
|
+
/******/
|
|
90731
|
+
/******/ // Load entry module and return exports
|
|
90732
|
+
/******/ return __webpack_require__(__webpack_require__.s = "./lib/all.ts");
|
|
90733
|
+
/******/ })
|
|
90734
|
+
/************************************************************************/
|
|
90735
|
+
/******/ ({
|
|
90736
|
+
|
|
90737
|
+
/***/ "./lib/all.ts":
|
|
90738
|
+
/*!********************!*\
|
|
90739
|
+
!*** ./lib/all.ts ***!
|
|
90740
|
+
\********************/
|
|
90741
|
+
/*! no static exports found */
|
|
90742
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
90743
|
+
|
|
90744
|
+
"use strict";
|
|
90745
|
+
|
|
90746
|
+
function __export(m) {
|
|
90747
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
90748
|
+
}
|
|
90749
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90750
|
+
__export(__webpack_require__(/*! ./dra-types */ "./lib/dra-types.ts"));
|
|
90751
|
+
|
|
90752
|
+
|
|
90753
|
+
/***/ }),
|
|
90754
|
+
|
|
90755
|
+
/***/ "./lib/dra-types.ts":
|
|
90756
|
+
/*!**************************!*\
|
|
90757
|
+
!*** ./lib/dra-types.ts ***!
|
|
90758
|
+
\**************************/
|
|
90759
|
+
/*! no static exports found */
|
|
90760
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
90761
|
+
|
|
90762
|
+
"use strict";
|
|
90763
|
+
|
|
90764
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90765
|
+
// Public libraries
|
|
90766
|
+
const Hash = __webpack_require__(/*! object-hash */ "object-hash");
|
|
90767
|
+
const Util = __webpack_require__(/*! @dra2020/util */ "@dra2020/util");
|
|
90768
|
+
// Canonical hashing of splitblock data
|
|
90769
|
+
function hash(o) {
|
|
90770
|
+
return Hash(o, { respectType: false,
|
|
90771
|
+
unorderedArrays: true,
|
|
90772
|
+
unorderedObjects: true,
|
|
90773
|
+
excludeKeys: (k) => (k === 'id' || k === 'chunk')
|
|
90774
|
+
});
|
|
90775
|
+
}
|
|
90776
|
+
function vgeoidToGeoid(vgeoid) {
|
|
90777
|
+
let re = /vfeature_([^_]*)_.*/;
|
|
90778
|
+
let a = re.exec(vgeoid);
|
|
90779
|
+
if (a == null || a.length != 2)
|
|
90780
|
+
return '';
|
|
90781
|
+
else
|
|
90782
|
+
return a[1];
|
|
90783
|
+
}
|
|
90784
|
+
exports.vgeoidToGeoid = vgeoidToGeoid;
|
|
90785
|
+
function vgeoidToChunk(vgeoid) {
|
|
90786
|
+
// vgeoid is string of form: "vfeature_[geoid]_[chunkid]_[hash]"
|
|
90787
|
+
// the contents are chunked into a file of form "vfeature_chunk_[chunkid]"
|
|
90788
|
+
// So extract the chunk ID and download that.
|
|
90789
|
+
let re = /vfeature_([^_]*)_([^_*])_(.*)/;
|
|
90790
|
+
let a = re.exec(vgeoid);
|
|
90791
|
+
if (a && a.length == 4)
|
|
90792
|
+
vgeoid = `vfeature_chunk_${a[2]}`;
|
|
90793
|
+
else
|
|
90794
|
+
vgeoid = null;
|
|
90795
|
+
return vgeoid;
|
|
90796
|
+
}
|
|
90797
|
+
exports.vgeoidToChunk = vgeoidToChunk;
|
|
90798
|
+
function vgeoidToHash(vgeoid) {
|
|
90799
|
+
// vgeoid is string of form: "vfeature_[geoid]_[chunkid]_[hash]"
|
|
90800
|
+
let re = /vfeature_([^_]*)_([^_*])_(.*)/;
|
|
90801
|
+
let a = re.exec(vgeoid);
|
|
90802
|
+
if (a && a.length == 4)
|
|
90803
|
+
vgeoid = a[3];
|
|
90804
|
+
else
|
|
90805
|
+
vgeoid = null;
|
|
90806
|
+
return vgeoid;
|
|
90807
|
+
}
|
|
90808
|
+
exports.vgeoidToHash = vgeoidToHash;
|
|
90809
|
+
function isVfeature(geoid) {
|
|
90810
|
+
return geoid.indexOf('vfeature') === 0;
|
|
90811
|
+
}
|
|
90812
|
+
exports.isVfeature = isVfeature;
|
|
90813
|
+
function splitToCacheKey(s) {
|
|
90814
|
+
if (s.id === undefined)
|
|
90815
|
+
s.id = hash(s);
|
|
90816
|
+
if (s.chunk === undefined)
|
|
90817
|
+
s.chunk = "0";
|
|
90818
|
+
return `_${s.state}_${s.datasource}_vfeature_${s.geoid}_${s.chunk}_${s.id}.geojson`;
|
|
90819
|
+
}
|
|
90820
|
+
exports.splitToCacheKey = splitToCacheKey;
|
|
90821
|
+
function splitToChunkKey(s) {
|
|
90822
|
+
if (s.chunk === undefined)
|
|
90823
|
+
s.chunk = "0";
|
|
90824
|
+
return `_${s.state}_${s.datasource}_vfeature_chunk_${s.chunk}.geojson`;
|
|
90825
|
+
}
|
|
90826
|
+
exports.splitToChunkKey = splitToChunkKey;
|
|
90827
|
+
function splitToPrefix(s) {
|
|
90828
|
+
if (s.blocks === undefined) {
|
|
90829
|
+
let re = /_([^_]*)_(.*)_vfeature.*\.geojson$/;
|
|
90830
|
+
let a = re.exec(s.id);
|
|
90831
|
+
if (a && a.length == 3)
|
|
90832
|
+
return `_${a[1]}_${a[2]}`;
|
|
90833
|
+
return s.id;
|
|
90834
|
+
}
|
|
90835
|
+
return `_${s.state}_${s.datasource}`;
|
|
90836
|
+
}
|
|
90837
|
+
exports.splitToPrefix = splitToPrefix;
|
|
90838
|
+
function cacheKeysToChunkHash(keys) {
|
|
90839
|
+
return hash(keys);
|
|
90840
|
+
}
|
|
90841
|
+
exports.cacheKeysToChunkHash = cacheKeysToChunkHash;
|
|
90842
|
+
let reNumeric = /^(\D*)(\d*)(\D*)$/;
|
|
90843
|
+
let reDistrictNumber = /^\d+$/;
|
|
90844
|
+
let reDistrictNumeric = /^\d/;
|
|
90845
|
+
// Normalize any numeric part to have no padded leading zeros
|
|
90846
|
+
function canonicalDistrictID(districtID) {
|
|
90847
|
+
let a = reNumeric.exec(districtID);
|
|
90848
|
+
if (a && a.length == 4) {
|
|
90849
|
+
if (a[2].length > 0)
|
|
90850
|
+
a[2] = String(Number(a[2]));
|
|
90851
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
90852
|
+
}
|
|
90853
|
+
return districtID;
|
|
90854
|
+
}
|
|
90855
|
+
exports.canonicalDistrictID = canonicalDistrictID;
|
|
90856
|
+
// Normalize any numeric part to have four digits with padded leading zeros
|
|
90857
|
+
function canonicalSortingDistrictID(districtID) {
|
|
90858
|
+
let a = reNumeric.exec(districtID);
|
|
90859
|
+
if (a && a.length == 4) {
|
|
90860
|
+
let s = a[2];
|
|
90861
|
+
if (s.length > 0) {
|
|
90862
|
+
switch (s.length) {
|
|
90863
|
+
case 1:
|
|
90864
|
+
s = `000${s}`;
|
|
90865
|
+
break;
|
|
90866
|
+
case 2:
|
|
90867
|
+
s = `00${s}`;
|
|
90868
|
+
break;
|
|
90869
|
+
case 3:
|
|
90870
|
+
s = `0${s}`;
|
|
90871
|
+
break;
|
|
90872
|
+
}
|
|
90873
|
+
a[2] = s;
|
|
90874
|
+
}
|
|
90875
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
90876
|
+
}
|
|
90877
|
+
return districtID;
|
|
90878
|
+
}
|
|
90879
|
+
exports.canonicalSortingDistrictID = canonicalSortingDistrictID;
|
|
90880
|
+
// Return numeric part of districtID (or -1 if there is none)
|
|
90881
|
+
function canonicalNumericFromDistrictID(districtID) {
|
|
90882
|
+
let a = reNumeric.exec(districtID);
|
|
90883
|
+
if (a && a.length == 4) {
|
|
90884
|
+
let s = a[2];
|
|
90885
|
+
if (s.length > 0)
|
|
90886
|
+
return Number(s);
|
|
90887
|
+
}
|
|
90888
|
+
return -1;
|
|
90889
|
+
}
|
|
90890
|
+
exports.canonicalNumericFromDistrictID = canonicalNumericFromDistrictID;
|
|
90891
|
+
function canonicalDistrictIDFromNumber(districtID, n) {
|
|
90892
|
+
let a = reNumeric.exec(districtID);
|
|
90893
|
+
if (a && a.length == 4) {
|
|
90894
|
+
a[2] = String(n);
|
|
90895
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
90896
|
+
}
|
|
90897
|
+
else
|
|
90898
|
+
districtID = String(n);
|
|
90899
|
+
return districtID;
|
|
90900
|
+
}
|
|
90901
|
+
exports.canonicalDistrictIDFromNumber = canonicalDistrictIDFromNumber;
|
|
90902
|
+
function canonicalDistrictIDOrdering(order) {
|
|
90903
|
+
let keys = Object.keys(order);
|
|
90904
|
+
let i;
|
|
90905
|
+
let a = [];
|
|
90906
|
+
let template = undefined;
|
|
90907
|
+
keys = keys.map((s) => canonicalSortingDistrictID(s));
|
|
90908
|
+
keys.sort();
|
|
90909
|
+
order = {};
|
|
90910
|
+
for (i = 0; i < keys.length; i++)
|
|
90911
|
+
order[canonicalDistrictID(keys[i])] = i + 1;
|
|
90912
|
+
// Remove water districts
|
|
90913
|
+
if (order['ZZZ'])
|
|
90914
|
+
delete order['ZZZ'];
|
|
90915
|
+
if (order['ZZ'])
|
|
90916
|
+
delete order['ZZ'];
|
|
90917
|
+
return order;
|
|
90918
|
+
}
|
|
90919
|
+
exports.canonicalDistrictIDOrdering = canonicalDistrictIDOrdering;
|
|
90920
|
+
let reArray = [
|
|
90921
|
+
/^(\d\d[^\s,"']*)[\s]*,[\s]*([^\s'"]+)[\s]*$/,
|
|
90922
|
+
/^["'](\d\d[^"']*)["'][\s]*,[\s]*["']([^"']*)["'][\s]*$/,
|
|
90923
|
+
/^(\d\d[^\s,]*)[\s]*,[\s]*["']([^"']*)["'][\s]*$/,
|
|
90924
|
+
/^["'](\d\d[^"']*)["'][\s]*,[\s]*([^\s]+)[\s]*$/,
|
|
90925
|
+
];
|
|
90926
|
+
function parseCSVLine(line) {
|
|
90927
|
+
if (line == null || line == '')
|
|
90928
|
+
return null;
|
|
90929
|
+
for (let i = 0; i < reArray.length; i++) {
|
|
90930
|
+
let a = reArray[i].exec(line);
|
|
90931
|
+
if (a && a.length === 3)
|
|
90932
|
+
return { geoid: a[1], districtID: a[2] };
|
|
90933
|
+
}
|
|
90934
|
+
return null;
|
|
90935
|
+
}
|
|
90936
|
+
exports.parseCSVLine = parseCSVLine;
|
|
90937
|
+
function blockmapToState(blockMap) {
|
|
90938
|
+
for (var id in blockMap)
|
|
90939
|
+
if (blockMap.hasOwnProperty(id))
|
|
90940
|
+
return geoidToState(id);
|
|
90941
|
+
return null;
|
|
90942
|
+
}
|
|
90943
|
+
exports.blockmapToState = blockmapToState;
|
|
90944
|
+
// blockToVTD:
|
|
90945
|
+
// Take BlockMapping (simple map of GEOID to districtID) and a per-state map of block-level GEOID to VTD
|
|
90946
|
+
// and return the output mapping of VTD to districtID, as well a data structure that describes any VTD's
|
|
90947
|
+
// that need to be split between districtIDs. Also returns the DistrictOrder structure that defines the
|
|
90948
|
+
// districtIDs that were used by the file.
|
|
90949
|
+
//
|
|
90950
|
+
// The state (as specified by the first two digits of the GEOID) is also determined. If the GEOID's do
|
|
90951
|
+
// not all specify the same state, the mapping is considered invalid and the outValid flag is set to false.
|
|
90952
|
+
//
|
|
90953
|
+
function blockmapToVTDmap(blockMap, stateMap) {
|
|
90954
|
+
let res = {
|
|
90955
|
+
inBlockMap: blockMap,
|
|
90956
|
+
inStateMap: stateMap,
|
|
90957
|
+
outValid: true,
|
|
90958
|
+
outState: null,
|
|
90959
|
+
outMap: {},
|
|
90960
|
+
outOrder: {},
|
|
90961
|
+
outDistrictToSplit: {}
|
|
90962
|
+
};
|
|
90963
|
+
let bmGather = {};
|
|
90964
|
+
let revMap = {};
|
|
90965
|
+
let id;
|
|
90966
|
+
if (stateMap)
|
|
90967
|
+
for (id in stateMap)
|
|
90968
|
+
if (stateMap.hasOwnProperty(id))
|
|
90969
|
+
revMap[stateMap[id]] = null;
|
|
90970
|
+
// First aggregate into features across all the blocks
|
|
90971
|
+
for (id in blockMap)
|
|
90972
|
+
if (blockMap.hasOwnProperty(id)) {
|
|
90973
|
+
let state = geoidToState(id);
|
|
90974
|
+
if (res.outState == null)
|
|
90975
|
+
res.outState = state;
|
|
90976
|
+
else if (res.outState !== state) {
|
|
90977
|
+
res.outValid = false;
|
|
90978
|
+
break;
|
|
90979
|
+
}
|
|
90980
|
+
let districtID = canonicalDistrictID(blockMap[id]);
|
|
90981
|
+
// Just ignore ZZZ (water) blocks
|
|
90982
|
+
if (districtID === 'ZZZ')
|
|
90983
|
+
continue;
|
|
90984
|
+
let n = id.length;
|
|
90985
|
+
let geoid;
|
|
90986
|
+
// Simple test for block id (vs. voting district or block group) id
|
|
90987
|
+
if (n >= 15) {
|
|
90988
|
+
if (stateMap && stateMap[id] !== undefined)
|
|
90989
|
+
geoid = stateMap[id];
|
|
90990
|
+
else {
|
|
90991
|
+
geoid = id.substr(0, 12); // heuristic for mapping blockID to blockgroupID
|
|
90992
|
+
if (revMap[geoid] === undefined) {
|
|
90993
|
+
res.outValid = false;
|
|
90994
|
+
break;
|
|
90995
|
+
}
|
|
90996
|
+
}
|
|
90997
|
+
}
|
|
90998
|
+
else
|
|
90999
|
+
geoid = id;
|
|
91000
|
+
if (res.outOrder[districtID] === undefined)
|
|
91001
|
+
res.outOrder[districtID] = 0;
|
|
91002
|
+
let districtToBlocks = bmGather[geoid];
|
|
91003
|
+
if (districtToBlocks === undefined)
|
|
91004
|
+
bmGather[geoid] = { [districtID]: { [id]: true } };
|
|
91005
|
+
else {
|
|
91006
|
+
let thisDistrict = districtToBlocks[districtID];
|
|
91007
|
+
if (thisDistrict === undefined) {
|
|
91008
|
+
thisDistrict = {};
|
|
91009
|
+
districtToBlocks[districtID] = thisDistrict;
|
|
91010
|
+
}
|
|
91011
|
+
thisDistrict[id] = true;
|
|
91012
|
+
}
|
|
91013
|
+
}
|
|
91014
|
+
// Now determine actual mapping of blocks to features, looking for split features
|
|
91015
|
+
for (let geoid in bmGather)
|
|
91016
|
+
if (bmGather.hasOwnProperty(geoid)) {
|
|
91017
|
+
let districtToBlocks = bmGather[geoid];
|
|
91018
|
+
if (Util.countKeys(districtToBlocks) == 1) {
|
|
91019
|
+
res.outMap[geoid] = Util.nthKey(districtToBlocks);
|
|
91020
|
+
}
|
|
91021
|
+
else {
|
|
91022
|
+
for (let districtID in districtToBlocks)
|
|
91023
|
+
if (districtToBlocks.hasOwnProperty(districtID)) {
|
|
91024
|
+
let split = { state: '', datasource: '', geoid: geoid, blocks: Object.keys(districtToBlocks[districtID]) };
|
|
91025
|
+
let splits = res.outDistrictToSplit[districtID];
|
|
91026
|
+
if (splits === undefined) {
|
|
91027
|
+
splits = [];
|
|
91028
|
+
res.outDistrictToSplit[districtID] = splits;
|
|
91029
|
+
}
|
|
91030
|
+
splits.push(split);
|
|
91031
|
+
}
|
|
91032
|
+
}
|
|
91033
|
+
}
|
|
91034
|
+
res.outOrder = canonicalDistrictIDOrdering(res.outOrder);
|
|
91035
|
+
return res;
|
|
91036
|
+
}
|
|
91037
|
+
exports.blockmapToVTDmap = blockmapToVTDmap;
|
|
91038
|
+
exports.GEOIDToState = {
|
|
91039
|
+
'01': 'AL',
|
|
91040
|
+
'02': 'AK',
|
|
91041
|
+
'04': 'AZ',
|
|
91042
|
+
'05': 'AR',
|
|
91043
|
+
'06': 'CA',
|
|
91044
|
+
'08': 'CO',
|
|
91045
|
+
'09': 'CT',
|
|
91046
|
+
'10': 'DE',
|
|
91047
|
+
'12': 'FL',
|
|
91048
|
+
'13': 'GA',
|
|
91049
|
+
'15': 'HI',
|
|
91050
|
+
'16': 'ID',
|
|
91051
|
+
'17': 'IL',
|
|
91052
|
+
'18': 'IN',
|
|
91053
|
+
'19': 'IA',
|
|
91054
|
+
'20': 'KS',
|
|
91055
|
+
'21': 'KY',
|
|
91056
|
+
'22': 'LA',
|
|
91057
|
+
'23': 'ME',
|
|
91058
|
+
'24': 'MD',
|
|
91059
|
+
'25': 'MA',
|
|
91060
|
+
'26': 'MI',
|
|
91061
|
+
'27': 'MN',
|
|
91062
|
+
'28': 'MS',
|
|
91063
|
+
'29': 'MO',
|
|
91064
|
+
'30': 'MT',
|
|
91065
|
+
'31': 'NE',
|
|
91066
|
+
'32': 'NV',
|
|
91067
|
+
'33': 'NH',
|
|
91068
|
+
'34': 'NJ',
|
|
91069
|
+
'35': 'NM',
|
|
91070
|
+
'36': 'NY',
|
|
91071
|
+
'37': 'NC',
|
|
91072
|
+
'38': 'ND',
|
|
91073
|
+
'39': 'OH',
|
|
91074
|
+
'40': 'OK',
|
|
91075
|
+
'41': 'OR',
|
|
91076
|
+
'42': 'PA',
|
|
91077
|
+
'44': 'RI',
|
|
91078
|
+
'45': 'SC',
|
|
91079
|
+
'46': 'SD',
|
|
91080
|
+
'47': 'TN',
|
|
91081
|
+
'48': 'TX',
|
|
91082
|
+
'49': 'UT',
|
|
91083
|
+
'50': 'VT',
|
|
91084
|
+
'51': 'VA',
|
|
91085
|
+
'53': 'WA',
|
|
91086
|
+
'54': 'WV',
|
|
91087
|
+
'55': 'WI',
|
|
91088
|
+
'56': 'WY',
|
|
91089
|
+
};
|
|
91090
|
+
exports.StateToGEOID = {
|
|
91091
|
+
'AL': '01',
|
|
91092
|
+
'AK': '02',
|
|
91093
|
+
'AZ': '04',
|
|
91094
|
+
'AR': '05',
|
|
91095
|
+
'CA': '06',
|
|
91096
|
+
'CO': '08',
|
|
91097
|
+
'CT': '09',
|
|
91098
|
+
'DE': '10',
|
|
91099
|
+
'FL': '12',
|
|
91100
|
+
'GA': '13',
|
|
91101
|
+
'HI': '15',
|
|
91102
|
+
'ID': '16',
|
|
91103
|
+
'IL': '17',
|
|
91104
|
+
'IN': '18',
|
|
91105
|
+
'IA': '19',
|
|
91106
|
+
'KS': '20',
|
|
91107
|
+
'KY': '21',
|
|
91108
|
+
'LA': '22',
|
|
91109
|
+
'ME': '23',
|
|
91110
|
+
'MD': '24',
|
|
91111
|
+
'MA': '25',
|
|
91112
|
+
'MI': '26',
|
|
91113
|
+
'MN': '27',
|
|
91114
|
+
'MS': '28',
|
|
91115
|
+
'MO': '29',
|
|
91116
|
+
'MT': '30',
|
|
91117
|
+
'NE': '31',
|
|
91118
|
+
'NV': '32',
|
|
91119
|
+
'NH': '33',
|
|
91120
|
+
'NJ': '34',
|
|
91121
|
+
'NM': '35',
|
|
91122
|
+
'NY': '36',
|
|
91123
|
+
'NC': '37',
|
|
91124
|
+
'ND': '38',
|
|
91125
|
+
'OH': '39',
|
|
91126
|
+
'OK': '40',
|
|
91127
|
+
'OR': '41',
|
|
91128
|
+
'PA': '42',
|
|
91129
|
+
'RI': '44',
|
|
91130
|
+
'SC': '45',
|
|
91131
|
+
'SD': '46',
|
|
91132
|
+
'TN': '47',
|
|
91133
|
+
'TX': '48',
|
|
91134
|
+
'UT': '49',
|
|
91135
|
+
'VT': '50',
|
|
91136
|
+
'VA': '51',
|
|
91137
|
+
'WA': '53',
|
|
91138
|
+
'WV': '54',
|
|
91139
|
+
'WI': '55',
|
|
91140
|
+
'WY': '56',
|
|
91141
|
+
};
|
|
91142
|
+
function geoidToState(geoid) {
|
|
91143
|
+
let re = /^(..).*$/;
|
|
91144
|
+
let a = re.exec(geoid);
|
|
91145
|
+
if (a == null || a.length != 2)
|
|
91146
|
+
return null;
|
|
91147
|
+
return exports.GEOIDToState[a[1]];
|
|
91148
|
+
}
|
|
91149
|
+
exports.geoidToState = geoidToState;
|
|
91150
|
+
|
|
91151
|
+
|
|
91152
|
+
/***/ }),
|
|
91153
|
+
|
|
91154
|
+
/***/ "@dra2020/util":
|
|
91155
|
+
/*!********************************!*\
|
|
91156
|
+
!*** external "@dra2020/util" ***!
|
|
91157
|
+
\********************************/
|
|
91158
|
+
/*! no static exports found */
|
|
91159
|
+
/***/ (function(module, exports) {
|
|
91160
|
+
|
|
91161
|
+
module.exports = __webpack_require__(/*! @dra2020/util */ "./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js");
|
|
91162
|
+
|
|
91163
|
+
/***/ }),
|
|
91164
|
+
|
|
91165
|
+
/***/ "object-hash":
|
|
91166
|
+
/*!******************************!*\
|
|
91167
|
+
!*** external "object-hash" ***!
|
|
91168
|
+
\******************************/
|
|
91169
|
+
/*! no static exports found */
|
|
91170
|
+
/***/ (function(module, exports) {
|
|
91171
|
+
|
|
91172
|
+
module.exports = __webpack_require__(/*! object-hash */ "./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js");
|
|
91173
|
+
|
|
91174
|
+
/***/ })
|
|
91175
|
+
|
|
91176
|
+
/******/ });
|
|
91177
|
+
});
|
|
91178
|
+
|
|
91179
|
+
|
|
91180
|
+
/***/ }),
|
|
91181
|
+
|
|
91182
|
+
/***/ "./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js":
|
|
91183
|
+
/*!*********************************************************************************!*\
|
|
91184
|
+
!*** ./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js ***!
|
|
91185
|
+
\*********************************************************************************/
|
|
91186
|
+
/*! no static exports found */
|
|
91187
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91188
|
+
|
|
91189
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
91190
|
+
if(true)
|
|
91191
|
+
module.exports = factory();
|
|
91192
|
+
else {}
|
|
91193
|
+
})(global, function() {
|
|
91194
|
+
return /******/ (function(modules) { // webpackBootstrap
|
|
91195
|
+
/******/ // The module cache
|
|
91196
|
+
/******/ var installedModules = {};
|
|
91197
|
+
/******/
|
|
91198
|
+
/******/ // The require function
|
|
91199
|
+
/******/ function __webpack_require__(moduleId) {
|
|
91200
|
+
/******/
|
|
91201
|
+
/******/ // Check if module is in cache
|
|
91202
|
+
/******/ if(installedModules[moduleId]) {
|
|
91203
|
+
/******/ return installedModules[moduleId].exports;
|
|
91204
|
+
/******/ }
|
|
91205
|
+
/******/ // Create a new module (and put it into the cache)
|
|
91206
|
+
/******/ var module = installedModules[moduleId] = {
|
|
91207
|
+
/******/ i: moduleId,
|
|
91208
|
+
/******/ l: false,
|
|
91209
|
+
/******/ exports: {}
|
|
91210
|
+
/******/ };
|
|
91211
|
+
/******/
|
|
91212
|
+
/******/ // Execute the module function
|
|
91213
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
91214
|
+
/******/
|
|
91215
|
+
/******/ // Flag the module as loaded
|
|
91216
|
+
/******/ module.l = true;
|
|
91217
|
+
/******/
|
|
91218
|
+
/******/ // Return the exports of the module
|
|
91219
|
+
/******/ return module.exports;
|
|
91220
|
+
/******/ }
|
|
91221
|
+
/******/
|
|
91222
|
+
/******/
|
|
91223
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
91224
|
+
/******/ __webpack_require__.m = modules;
|
|
91225
|
+
/******/
|
|
91226
|
+
/******/ // expose the module cache
|
|
91227
|
+
/******/ __webpack_require__.c = installedModules;
|
|
91228
|
+
/******/
|
|
91229
|
+
/******/ // define getter function for harmony exports
|
|
91230
|
+
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
91231
|
+
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
91232
|
+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
91233
|
+
/******/ }
|
|
91234
|
+
/******/ };
|
|
91235
|
+
/******/
|
|
91236
|
+
/******/ // define __esModule on exports
|
|
91237
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
91238
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
91239
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
91240
|
+
/******/ }
|
|
91241
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
91242
|
+
/******/ };
|
|
91243
|
+
/******/
|
|
91244
|
+
/******/ // create a fake namespace object
|
|
91245
|
+
/******/ // mode & 1: value is a module id, require it
|
|
91246
|
+
/******/ // mode & 2: merge all properties of value into the ns
|
|
91247
|
+
/******/ // mode & 4: return value when already ns object
|
|
91248
|
+
/******/ // mode & 8|1: behave like require
|
|
91249
|
+
/******/ __webpack_require__.t = function(value, mode) {
|
|
91250
|
+
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
91251
|
+
/******/ if(mode & 8) return value;
|
|
91252
|
+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
91253
|
+
/******/ var ns = Object.create(null);
|
|
91254
|
+
/******/ __webpack_require__.r(ns);
|
|
91255
|
+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
91256
|
+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
91257
|
+
/******/ return ns;
|
|
91258
|
+
/******/ };
|
|
91259
|
+
/******/
|
|
91260
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
91261
|
+
/******/ __webpack_require__.n = function(module) {
|
|
91262
|
+
/******/ var getter = module && module.__esModule ?
|
|
91263
|
+
/******/ function getDefault() { return module['default']; } :
|
|
91264
|
+
/******/ function getModuleExports() { return module; };
|
|
91265
|
+
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
91266
|
+
/******/ return getter;
|
|
91267
|
+
/******/ };
|
|
91268
|
+
/******/
|
|
91269
|
+
/******/ // Object.prototype.hasOwnProperty.call
|
|
91270
|
+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
91271
|
+
/******/
|
|
91272
|
+
/******/ // __webpack_public_path__
|
|
91273
|
+
/******/ __webpack_require__.p = "";
|
|
91274
|
+
/******/
|
|
91275
|
+
/******/
|
|
91276
|
+
/******/ // Load entry module and return exports
|
|
91277
|
+
/******/ return __webpack_require__(__webpack_require__.s = "./lib/all.ts");
|
|
91278
|
+
/******/ })
|
|
91279
|
+
/************************************************************************/
|
|
91280
|
+
/******/ ({
|
|
91281
|
+
|
|
91282
|
+
/***/ "./lib/all.ts":
|
|
91283
|
+
/*!********************!*\
|
|
91284
|
+
!*** ./lib/all.ts ***!
|
|
91285
|
+
\********************/
|
|
91286
|
+
/*! no static exports found */
|
|
91287
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91288
|
+
|
|
91289
|
+
"use strict";
|
|
91290
|
+
|
|
91291
|
+
function __export(m) {
|
|
91292
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
91293
|
+
}
|
|
91294
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91295
|
+
__export(__webpack_require__(/*! ./util */ "./lib/util.ts"));
|
|
91296
|
+
__export(__webpack_require__(/*! ./countedhash */ "./lib/countedhash.ts"));
|
|
91297
|
+
__export(__webpack_require__(/*! ./indexedarray */ "./lib/indexedarray.ts"));
|
|
91298
|
+
|
|
91299
|
+
|
|
91300
|
+
/***/ }),
|
|
91301
|
+
|
|
91302
|
+
/***/ "./lib/countedhash.ts":
|
|
91303
|
+
/*!****************************!*\
|
|
91304
|
+
!*** ./lib/countedhash.ts ***!
|
|
91305
|
+
\****************************/
|
|
91306
|
+
/*! no static exports found */
|
|
91307
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91308
|
+
|
|
91309
|
+
"use strict";
|
|
91310
|
+
|
|
91311
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91312
|
+
class CountedHash {
|
|
91313
|
+
constructor() {
|
|
91314
|
+
this.n = 0;
|
|
91315
|
+
this.val = {};
|
|
91316
|
+
}
|
|
91317
|
+
get length() { return this.n; }
|
|
91318
|
+
test(id) {
|
|
91319
|
+
return id != '' && this.val[id] !== undefined;
|
|
91320
|
+
}
|
|
91321
|
+
set(id) {
|
|
91322
|
+
if (id != '' && !this.test(id)) {
|
|
91323
|
+
this.n++;
|
|
91324
|
+
this.val[id] = true;
|
|
91325
|
+
}
|
|
91326
|
+
}
|
|
91327
|
+
clear(id) {
|
|
91328
|
+
if (this.test(id)) {
|
|
91329
|
+
this.n--;
|
|
91330
|
+
delete this.val[id];
|
|
91331
|
+
}
|
|
91332
|
+
}
|
|
91333
|
+
empty() {
|
|
91334
|
+
this.n = 0;
|
|
91335
|
+
this.val = {};
|
|
91336
|
+
}
|
|
91337
|
+
asArray() {
|
|
91338
|
+
let a = [];
|
|
91339
|
+
this.forEach(id => { a.push(id); });
|
|
91340
|
+
return a;
|
|
91341
|
+
}
|
|
91342
|
+
asString() {
|
|
91343
|
+
for (var id in this.val)
|
|
91344
|
+
if (this.val.hasOwnProperty(id))
|
|
91345
|
+
return id;
|
|
91346
|
+
return '';
|
|
91347
|
+
}
|
|
91348
|
+
forEach(f) {
|
|
91349
|
+
for (var id in this.val)
|
|
91350
|
+
if (this.val.hasOwnProperty(id))
|
|
91351
|
+
f(id);
|
|
91352
|
+
}
|
|
91353
|
+
}
|
|
91354
|
+
exports.CountedHash = CountedHash;
|
|
91355
|
+
|
|
91356
|
+
|
|
91357
|
+
/***/ }),
|
|
91358
|
+
|
|
91359
|
+
/***/ "./lib/indexedarray.ts":
|
|
91360
|
+
/*!*****************************!*\
|
|
91361
|
+
!*** ./lib/indexedarray.ts ***!
|
|
91362
|
+
\*****************************/
|
|
91363
|
+
/*! no static exports found */
|
|
91364
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91365
|
+
|
|
91366
|
+
"use strict";
|
|
91367
|
+
|
|
91368
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91369
|
+
class IndexedArray {
|
|
91370
|
+
constructor() {
|
|
91371
|
+
this.o = {};
|
|
91372
|
+
this.a = null;
|
|
91373
|
+
}
|
|
91374
|
+
ensure() {
|
|
91375
|
+
if (this.a === null) {
|
|
91376
|
+
this.a = [];
|
|
91377
|
+
for (let p in this.o)
|
|
91378
|
+
if (this.o.hasOwnProperty(p))
|
|
91379
|
+
this.a.push(p);
|
|
91380
|
+
this.a.sort((a, b) => { a = a.toUpperCase(); b = b.toUpperCase(); return a < b ? -1 : (a > b ? 1 : 0); });
|
|
91381
|
+
}
|
|
91382
|
+
}
|
|
91383
|
+
asArray() {
|
|
91384
|
+
this.ensure();
|
|
91385
|
+
return this.a;
|
|
91386
|
+
}
|
|
91387
|
+
get length() { this.ensure(); return this.a.length; }
|
|
91388
|
+
test(s) {
|
|
91389
|
+
return !!s && this.o[s] !== undefined;
|
|
91390
|
+
}
|
|
91391
|
+
set(s) {
|
|
91392
|
+
if (!!s && !this.test(s)) {
|
|
91393
|
+
this.o[s] = true;
|
|
91394
|
+
this.a = null;
|
|
91395
|
+
}
|
|
91396
|
+
}
|
|
91397
|
+
setAll(a) {
|
|
91398
|
+
if (a && a.length)
|
|
91399
|
+
for (let i = 0; i < a.length; i++)
|
|
91400
|
+
this.set(a[i]);
|
|
91401
|
+
}
|
|
91402
|
+
clear(s) {
|
|
91403
|
+
if (this.test(s)) {
|
|
91404
|
+
delete this.o[s];
|
|
91405
|
+
this.a = null;
|
|
91406
|
+
}
|
|
91407
|
+
}
|
|
91408
|
+
at(i) {
|
|
91409
|
+
this.ensure();
|
|
91410
|
+
if (i < 0 || i >= this.a.length)
|
|
91411
|
+
return undefined;
|
|
91412
|
+
return this.a[i];
|
|
91413
|
+
}
|
|
91414
|
+
empty() {
|
|
91415
|
+
this.o = {};
|
|
91416
|
+
this.a = null;
|
|
91417
|
+
}
|
|
91418
|
+
forEach(f) {
|
|
91419
|
+
for (var s in this.o)
|
|
91420
|
+
if (this.o.hasOwnProperty(s))
|
|
91421
|
+
f(s);
|
|
91422
|
+
}
|
|
91423
|
+
}
|
|
91424
|
+
exports.IndexedArray = IndexedArray;
|
|
91425
|
+
|
|
91426
|
+
|
|
91427
|
+
/***/ }),
|
|
91428
|
+
|
|
91429
|
+
/***/ "./lib/util.ts":
|
|
91430
|
+
/*!*********************!*\
|
|
91431
|
+
!*** ./lib/util.ts ***!
|
|
91432
|
+
\*********************/
|
|
91433
|
+
/*! no static exports found */
|
|
91434
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91435
|
+
|
|
91436
|
+
"use strict";
|
|
91437
|
+
|
|
91438
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91439
|
+
function Now() { return (new Date()).toJSON(); }
|
|
91440
|
+
exports.Now = Now;
|
|
91441
|
+
class Elapsed {
|
|
91442
|
+
constructor(bStart = true) {
|
|
91443
|
+
this.tStart = undefined;
|
|
91444
|
+
this.tDur = undefined;
|
|
91445
|
+
if (bStart)
|
|
91446
|
+
this.start();
|
|
91447
|
+
}
|
|
91448
|
+
start() {
|
|
91449
|
+
if (process && process.hrtime)
|
|
91450
|
+
this.tStart = process.hrtime();
|
|
91451
|
+
else
|
|
91452
|
+
this.tStart = performance.now();
|
|
91453
|
+
if (this.tDur)
|
|
91454
|
+
this.tDur = undefined;
|
|
91455
|
+
}
|
|
91456
|
+
end() {
|
|
91457
|
+
if (this.tStart === undefined)
|
|
91458
|
+
this.start();
|
|
91459
|
+
if (process && process.hrtime)
|
|
91460
|
+
this.tDur = process.hrtime(this.tStart);
|
|
91461
|
+
else
|
|
91462
|
+
this.tDur = performance.now() - this.tStart;
|
|
91463
|
+
}
|
|
91464
|
+
ms() {
|
|
91465
|
+
if (this.tDur === undefined)
|
|
91466
|
+
this.end();
|
|
91467
|
+
if (process && process.hrtime)
|
|
91468
|
+
return Math.round((this.tDur[0] * 1000) + (this.tDur[1] / 1000000));
|
|
91469
|
+
else
|
|
91470
|
+
return this.tDur;
|
|
91471
|
+
}
|
|
91472
|
+
nano() {
|
|
91473
|
+
if (this.tDur === undefined)
|
|
91474
|
+
this.end();
|
|
91475
|
+
if (process && process.hrtime)
|
|
91476
|
+
return (this.tDur[0] * 1000000000) + this.tDur[1];
|
|
91477
|
+
else
|
|
91478
|
+
return this.tDur * 1000000;
|
|
91479
|
+
}
|
|
91480
|
+
}
|
|
91481
|
+
exports.Elapsed = Elapsed;
|
|
91482
|
+
class Deadline {
|
|
91483
|
+
constructor(msDelta) {
|
|
91484
|
+
this.msDelta = msDelta;
|
|
91485
|
+
this.elapsed = new Elapsed();
|
|
91486
|
+
}
|
|
91487
|
+
done() {
|
|
91488
|
+
this.elapsed.end();
|
|
91489
|
+
return this.elapsed.ms() > this.msDelta;
|
|
91490
|
+
}
|
|
91491
|
+
}
|
|
91492
|
+
exports.Deadline = Deadline;
|
|
91493
|
+
function createGuid() {
|
|
91494
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
91495
|
+
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
91496
|
+
return v.toString(16);
|
|
91497
|
+
});
|
|
91498
|
+
}
|
|
91499
|
+
exports.createGuid = createGuid;
|
|
91500
|
+
function _sizeof(a, loops) {
|
|
91501
|
+
if (a === null || a === undefined)
|
|
91502
|
+
return 0;
|
|
91503
|
+
switch (typeof a) {
|
|
91504
|
+
default: return 0;
|
|
91505
|
+
case 'number': return 8;
|
|
91506
|
+
case 'boolean': return 4;
|
|
91507
|
+
case 'string': return a.length * 2;
|
|
91508
|
+
case 'object':
|
|
91509
|
+
{
|
|
91510
|
+
if (loops.has(a))
|
|
91511
|
+
return 0;
|
|
91512
|
+
else
|
|
91513
|
+
loops.set(a, true);
|
|
91514
|
+
let t = 0;
|
|
91515
|
+
if (Array.isArray(a)) {
|
|
91516
|
+
for (let i = 0; i < a.length; i++)
|
|
91517
|
+
t += _sizeof(a[i], loops);
|
|
91518
|
+
t += 8; // length
|
|
91519
|
+
}
|
|
91520
|
+
else if (Buffer.isBuffer(a)) {
|
|
91521
|
+
t = a.length;
|
|
91522
|
+
}
|
|
91523
|
+
else if (a.hasOwnProperty === undefined)
|
|
91524
|
+
return t;
|
|
91525
|
+
else {
|
|
91526
|
+
for (var key in a)
|
|
91527
|
+
if (a.hasOwnProperty && a.hasOwnProperty(key)) {
|
|
91528
|
+
t += _sizeof(key, loops); // this is a good estimate of download size, but poor estimate of internal size
|
|
91529
|
+
// because of JS object templating vs. naive hashtables
|
|
91530
|
+
t += _sizeof(a[key], loops);
|
|
91531
|
+
}
|
|
91532
|
+
}
|
|
91533
|
+
return t;
|
|
91534
|
+
}
|
|
91535
|
+
}
|
|
91536
|
+
}
|
|
91537
|
+
function sizeof(a) {
|
|
91538
|
+
let loops = new WeakMap();
|
|
91539
|
+
let n = _sizeof(a, loops);
|
|
91540
|
+
return n;
|
|
91541
|
+
}
|
|
91542
|
+
exports.sizeof = sizeof;
|
|
91543
|
+
function depthof(a) {
|
|
91544
|
+
if (a === null || a === undefined)
|
|
91545
|
+
return 1;
|
|
91546
|
+
switch (typeof a) {
|
|
91547
|
+
default: return 1;
|
|
91548
|
+
case 'number': return 1;
|
|
91549
|
+
case 'boolean': return 1;
|
|
91550
|
+
case 'string': return 1;
|
|
91551
|
+
case 'object':
|
|
91552
|
+
{
|
|
91553
|
+
let d = 0;
|
|
91554
|
+
if (Array.isArray(a))
|
|
91555
|
+
return a.length > 0 ? (1 + depthof(a[0])) : 2; // still return 2 for empty array
|
|
91556
|
+
else if (Buffer.isBuffer(a))
|
|
91557
|
+
return 2;
|
|
91558
|
+
else if (a.hasOwnProperty === undefined)
|
|
91559
|
+
return 1;
|
|
91560
|
+
else {
|
|
91561
|
+
for (var key in a)
|
|
91562
|
+
if (a.hasOwnProperty(key))
|
|
91563
|
+
return 1 + depthof(a[key]);
|
|
91564
|
+
return 2; // or 2 for empty object
|
|
91565
|
+
}
|
|
91566
|
+
}
|
|
91567
|
+
}
|
|
91568
|
+
}
|
|
91569
|
+
exports.depthof = depthof;
|
|
91570
|
+
function isEmpty(o) {
|
|
91571
|
+
if (o === null || o === undefined)
|
|
91572
|
+
return true;
|
|
91573
|
+
for (var p in o)
|
|
91574
|
+
if (o.hasOwnProperty(p))
|
|
91575
|
+
return false;
|
|
91576
|
+
return true;
|
|
91577
|
+
}
|
|
91578
|
+
exports.isEmpty = isEmpty;
|
|
91579
|
+
function countKeys(o) {
|
|
91580
|
+
if (o === undefined || typeof o !== 'object')
|
|
91581
|
+
return -1;
|
|
91582
|
+
let count = 0;
|
|
91583
|
+
for (let p in o)
|
|
91584
|
+
if (o.hasOwnProperty(p))
|
|
91585
|
+
count++;
|
|
91586
|
+
return count;
|
|
91587
|
+
}
|
|
91588
|
+
exports.countKeys = countKeys;
|
|
91589
|
+
function nthProperty(o, n = 0) {
|
|
91590
|
+
for (let p in o)
|
|
91591
|
+
if (o.hasOwnProperty(p)) {
|
|
91592
|
+
if (n <= 0)
|
|
91593
|
+
return o[p];
|
|
91594
|
+
n--;
|
|
91595
|
+
}
|
|
91596
|
+
return undefined;
|
|
91597
|
+
}
|
|
91598
|
+
exports.nthProperty = nthProperty;
|
|
91599
|
+
function nthKey(o, n = 0) {
|
|
91600
|
+
for (let p in o)
|
|
91601
|
+
if (o.hasOwnProperty(p)) {
|
|
91602
|
+
if (n <= 0)
|
|
91603
|
+
return p;
|
|
91604
|
+
n--;
|
|
91605
|
+
}
|
|
91606
|
+
return undefined;
|
|
91607
|
+
}
|
|
91608
|
+
exports.nthKey = nthKey;
|
|
91609
|
+
function partialEqual(o, subset) {
|
|
91610
|
+
for (let p in subset)
|
|
91611
|
+
if (subset.hasOwnProperty(p))
|
|
91612
|
+
if (o[p] !== subset[p])
|
|
91613
|
+
return false;
|
|
91614
|
+
return true;
|
|
91615
|
+
}
|
|
91616
|
+
exports.partialEqual = partialEqual;
|
|
91617
|
+
function deepEqual(o1, o2, options) {
|
|
91618
|
+
if (typeof o1 !== typeof o2)
|
|
91619
|
+
return false;
|
|
91620
|
+
if (typeof o1 !== 'object')
|
|
91621
|
+
return o1 === o2;
|
|
91622
|
+
// Special case array
|
|
91623
|
+
if (Array.isArray(o1)) {
|
|
91624
|
+
if (!Array.isArray(o2))
|
|
91625
|
+
return false;
|
|
91626
|
+
if (o1.length != o2.length)
|
|
91627
|
+
return false;
|
|
91628
|
+
if (options && options.unorderedArrays) {
|
|
91629
|
+
o1 = o1.sort();
|
|
91630
|
+
o2 = o2.sort();
|
|
91631
|
+
}
|
|
91632
|
+
for (let i = 0; i < o1.length; i++)
|
|
91633
|
+
if (!deepEqual(o1[i], o2[i], options))
|
|
91634
|
+
return false;
|
|
91635
|
+
return true;
|
|
91636
|
+
}
|
|
91637
|
+
// Special case object
|
|
91638
|
+
if (o1.hasOwnProperty === undefined || o2.hasOwnProperty === undefined)
|
|
91639
|
+
return o1 === o2;
|
|
91640
|
+
for (let p in o1)
|
|
91641
|
+
if (o1.hasOwnProperty(p)) {
|
|
91642
|
+
if (options && options.omitKey[p])
|
|
91643
|
+
continue;
|
|
91644
|
+
if (o2[p] === undefined)
|
|
91645
|
+
return false;
|
|
91646
|
+
if (!deepEqual(o1[p], o2[p], options))
|
|
91647
|
+
return false;
|
|
91648
|
+
}
|
|
91649
|
+
// If any properties in o2 aren't in o1, not equal
|
|
91650
|
+
for (let p in o2)
|
|
91651
|
+
if (o2.hasOwnProperty(p)) {
|
|
91652
|
+
if (options && options.omitKey[p])
|
|
91653
|
+
continue;
|
|
91654
|
+
if (o1[p] === undefined)
|
|
91655
|
+
return false;
|
|
91656
|
+
}
|
|
91657
|
+
return true;
|
|
91658
|
+
}
|
|
91659
|
+
exports.deepEqual = deepEqual;
|
|
91660
|
+
const Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
91661
|
+
function prettyDate(d) {
|
|
91662
|
+
if (d == null)
|
|
91663
|
+
return 'unknown';
|
|
91664
|
+
let mmm = Months[d.getMonth()];
|
|
91665
|
+
let dd = d.getDate();
|
|
91666
|
+
let yyyy = d.getFullYear();
|
|
91667
|
+
let hh = d.getHours();
|
|
91668
|
+
let m = d.getMinutes();
|
|
91669
|
+
let mm = m < 10 ? `0${m}` : String(m);
|
|
91670
|
+
let ampm = hh >= 12 ? 'PM' : 'AM';
|
|
91671
|
+
if (hh > 12)
|
|
91672
|
+
hh -= 12;
|
|
91673
|
+
return `${mmm} ${dd}, ${yyyy} at ${hh}:${mm} ${ampm}`;
|
|
91674
|
+
}
|
|
91675
|
+
exports.prettyDate = prettyDate;
|
|
91676
|
+
function relativeDate(d) {
|
|
91677
|
+
if (d == null)
|
|
91678
|
+
return 'unknown';
|
|
91679
|
+
let now = new Date();
|
|
91680
|
+
let yyyyNow = now.getFullYear();
|
|
91681
|
+
let mmmNow = Months[now.getMonth()];
|
|
91682
|
+
let ddNow = now.getDate();
|
|
91683
|
+
let mmm = Months[d.getMonth()];
|
|
91684
|
+
let dd = d.getDate();
|
|
91685
|
+
let yyyy = d.getFullYear();
|
|
91686
|
+
let hh = d.getHours();
|
|
91687
|
+
let m = d.getMinutes();
|
|
91688
|
+
let mm = m < 10 ? `0${m}` : String(m);
|
|
91689
|
+
let ampm = hh >= 12 ? 'PM' : 'AM';
|
|
91690
|
+
if (hh > 12)
|
|
91691
|
+
hh -= 12;
|
|
91692
|
+
if (yyyyNow === yyyy && mmmNow === mmm && ddNow === dd)
|
|
91693
|
+
return `Today at ${hh}:${mm} ${ampm}`;
|
|
91694
|
+
else if (yyyyNow === yyyy)
|
|
91695
|
+
return `${mmm} ${dd}`;
|
|
91696
|
+
else
|
|
91697
|
+
return `${mmm} ${dd}, ${yyyy}`;
|
|
91698
|
+
}
|
|
91699
|
+
exports.relativeDate = relativeDate;
|
|
91700
|
+
const OneMinute = 1000 * 60;
|
|
91701
|
+
const OneHour = OneMinute * 60;
|
|
91702
|
+
const OneDay = OneHour * 24;
|
|
91703
|
+
function recentDate(d) {
|
|
91704
|
+
if (d == null)
|
|
91705
|
+
return 'u';
|
|
91706
|
+
let now = new Date();
|
|
91707
|
+
let msNow = now.getTime();
|
|
91708
|
+
let msThen = d.getTime();
|
|
91709
|
+
let msDelta = msNow - msThen;
|
|
91710
|
+
// Within the hour, display in minutes
|
|
91711
|
+
if (msDelta < OneHour)
|
|
91712
|
+
return `${Math.round(msDelta / OneMinute) + 1}m`;
|
|
91713
|
+
// Within the day, display in hours
|
|
91714
|
+
else if (msDelta < OneDay)
|
|
91715
|
+
return `${Math.round(msDelta / OneHour) + 1}h`;
|
|
91716
|
+
// Otherwise, display using relativeDate
|
|
91717
|
+
else
|
|
91718
|
+
return relativeDate(d);
|
|
91719
|
+
}
|
|
91720
|
+
exports.recentDate = recentDate;
|
|
91721
|
+
function textToHtml(sText) {
|
|
91722
|
+
let lines = sText.split('\n');
|
|
91723
|
+
let aHtml = [];
|
|
91724
|
+
let inTable = false;
|
|
91725
|
+
aHtml.push('<body>');
|
|
91726
|
+
for (let i = 0; i < lines.length; i++) {
|
|
91727
|
+
let line = lines[i];
|
|
91728
|
+
let isRow = line.indexOf('|') === 0;
|
|
91729
|
+
if (inTable && !isRow) {
|
|
91730
|
+
aHtml.push('</tbody></table>');
|
|
91731
|
+
inTable = false;
|
|
91732
|
+
}
|
|
91733
|
+
if (isRow && !inTable) {
|
|
91734
|
+
inTable = true;
|
|
91735
|
+
aHtml.push('<table border="1" cellspacing="0" cellpadding="2"><tbody>');
|
|
91736
|
+
}
|
|
91737
|
+
if (isRow) {
|
|
91738
|
+
let cells = line.split('|');
|
|
91739
|
+
if (cells.length > 2) {
|
|
91740
|
+
aHtml.push('<tr>');
|
|
91741
|
+
for (let j = 1; j < cells.length - 1; j++)
|
|
91742
|
+
aHtml.push(`<td>${cells[j]}</td>`);
|
|
91743
|
+
aHtml.push('</tr>');
|
|
91744
|
+
}
|
|
91745
|
+
}
|
|
91746
|
+
else
|
|
91747
|
+
aHtml.push(`<div>${line} </div>`);
|
|
91748
|
+
}
|
|
91749
|
+
if (inTable)
|
|
91750
|
+
aHtml.push('</tbody></table>');
|
|
91751
|
+
aHtml.push('</body>');
|
|
91752
|
+
return aHtml.join('');
|
|
91753
|
+
}
|
|
91754
|
+
exports.textToHtml = textToHtml;
|
|
91755
|
+
function shallowCopy(src) {
|
|
91756
|
+
if (src === null || src === undefined)
|
|
91757
|
+
return src;
|
|
91758
|
+
switch (typeof src) {
|
|
91759
|
+
case 'boolean':
|
|
91760
|
+
case 'number':
|
|
91761
|
+
case 'string':
|
|
91762
|
+
case 'symbol':
|
|
91763
|
+
case 'function':
|
|
91764
|
+
default:
|
|
91765
|
+
return src;
|
|
91766
|
+
case 'object':
|
|
91767
|
+
if (Array.isArray(src))
|
|
91768
|
+
return src.slice();
|
|
91769
|
+
else {
|
|
91770
|
+
let copy = {};
|
|
91771
|
+
for (var p in src)
|
|
91772
|
+
if (src.hasOwnProperty(p))
|
|
91773
|
+
copy[p] = src[p];
|
|
91774
|
+
return copy;
|
|
91775
|
+
}
|
|
91776
|
+
}
|
|
91777
|
+
}
|
|
91778
|
+
exports.shallowCopy = shallowCopy;
|
|
91779
|
+
function shallowAssign(o1, o2) {
|
|
91780
|
+
if (o1 === null || o1 === undefined)
|
|
91781
|
+
o1 = {};
|
|
91782
|
+
if (o2 === null || o2 === undefined)
|
|
91783
|
+
return o1;
|
|
91784
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
91785
|
+
return o1;
|
|
91786
|
+
for (var p in o2)
|
|
91787
|
+
if (o2.hasOwnProperty(p))
|
|
91788
|
+
o1[p] = o2[p];
|
|
91789
|
+
return o1;
|
|
91790
|
+
}
|
|
91791
|
+
exports.shallowAssign = shallowAssign;
|
|
91792
|
+
function shallowDelete(o1, o2) {
|
|
91793
|
+
if (o1 == null || o2 == null)
|
|
91794
|
+
return o1;
|
|
91795
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
91796
|
+
return o1;
|
|
91797
|
+
for (var p in o2)
|
|
91798
|
+
if (o2.hasOwnProperty(p))
|
|
91799
|
+
delete o1[p];
|
|
91800
|
+
return o1;
|
|
91801
|
+
}
|
|
91802
|
+
exports.shallowDelete = shallowDelete;
|
|
91803
|
+
function shallowAssignImmutable(o1, o2) {
|
|
91804
|
+
if (o1 === null || o1 === undefined)
|
|
91805
|
+
o1 = {};
|
|
91806
|
+
if (o2 === null || o2 === undefined)
|
|
91807
|
+
return o1;
|
|
91808
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
91809
|
+
return o1;
|
|
91810
|
+
// First determine whether o2 changes any properties, if it has, make new instance
|
|
91811
|
+
let oNew = o1;
|
|
91812
|
+
for (let p in o2)
|
|
91813
|
+
if (o2.hasOwnProperty(p)) {
|
|
91814
|
+
if (o1[p] != o2[p]) {
|
|
91815
|
+
oNew = shallowCopy(o1);
|
|
91816
|
+
break;
|
|
91817
|
+
}
|
|
91818
|
+
}
|
|
91819
|
+
if (oNew !== o1)
|
|
91820
|
+
shallowAssign(oNew, o2);
|
|
91821
|
+
return oNew;
|
|
91822
|
+
}
|
|
91823
|
+
exports.shallowAssignImmutable = shallowAssignImmutable;
|
|
91824
|
+
function shallowEqual(o1, o2) {
|
|
91825
|
+
if (o1 === undefined || o2 === undefined || typeof o1 !== 'object' || typeof o2 !== 'object')
|
|
91826
|
+
return o1 === o2;
|
|
91827
|
+
if (Array.isArray(o1) && Array.isArray(o2)) {
|
|
91828
|
+
if (o1.length != o2.length)
|
|
91829
|
+
return false;
|
|
91830
|
+
for (let i = 0; i < o1.length; i++)
|
|
91831
|
+
if (o1[i] !== o2[i])
|
|
91832
|
+
return false;
|
|
91833
|
+
return true;
|
|
91834
|
+
}
|
|
91835
|
+
else {
|
|
91836
|
+
let p;
|
|
91837
|
+
for (p in o1)
|
|
91838
|
+
if (o1.hasOwnProperty(p))
|
|
91839
|
+
if (o1[p] !== o2[p])
|
|
91840
|
+
return false;
|
|
91841
|
+
for (p in o2)
|
|
91842
|
+
if (o2.hasOwnProperty(p))
|
|
91843
|
+
if (o1[p] === undefined)
|
|
91844
|
+
return false;
|
|
91845
|
+
return true;
|
|
91846
|
+
}
|
|
91847
|
+
}
|
|
91848
|
+
exports.shallowEqual = shallowEqual;
|
|
91849
|
+
function deepCopy(src) {
|
|
91850
|
+
// Beware typeof oddities
|
|
91851
|
+
if (src === null || src === undefined)
|
|
91852
|
+
return src;
|
|
91853
|
+
if (typeof src === 'object') {
|
|
91854
|
+
if (Array.isArray(src)) {
|
|
91855
|
+
let dst = [];
|
|
91856
|
+
for (let i = 0; i < src.length; i++)
|
|
91857
|
+
dst.push(deepCopy(src[i]));
|
|
91858
|
+
return dst;
|
|
91859
|
+
}
|
|
91860
|
+
else {
|
|
91861
|
+
if (src.hasOwnProperty === undefined)
|
|
91862
|
+
return src;
|
|
91863
|
+
let dst = {};
|
|
91864
|
+
for (var p in src)
|
|
91865
|
+
if (src.hasOwnProperty(p))
|
|
91866
|
+
dst[p] = deepCopy(src[p]);
|
|
91867
|
+
return dst;
|
|
91868
|
+
}
|
|
91869
|
+
}
|
|
91870
|
+
else
|
|
91871
|
+
return src;
|
|
91872
|
+
}
|
|
91873
|
+
exports.deepCopy = deepCopy;
|
|
91874
|
+
function deepAccum(accum, o) {
|
|
91875
|
+
if (accum == null)
|
|
91876
|
+
accum = {};
|
|
91877
|
+
if (o == null)
|
|
91878
|
+
return accum;
|
|
91879
|
+
for (let p in o)
|
|
91880
|
+
if (o.hasOwnProperty(p)) {
|
|
91881
|
+
let vs = o[p];
|
|
91882
|
+
let vd = accum[p];
|
|
91883
|
+
if (typeof vs === 'number') {
|
|
91884
|
+
if (vd !== undefined && typeof vd !== 'number')
|
|
91885
|
+
throw 'deepAccum: unexpected type mismatch';
|
|
91886
|
+
accum[p] = (vd === undefined ? 0 : vd) + vs;
|
|
91887
|
+
}
|
|
91888
|
+
else if (typeof vs === 'object') {
|
|
91889
|
+
if (vd === undefined) {
|
|
91890
|
+
vd = {};
|
|
91891
|
+
accum[p] = vd;
|
|
91892
|
+
}
|
|
91893
|
+
else if (typeof vd !== 'object')
|
|
91894
|
+
throw 'deepAccum: unexpected type mismatch';
|
|
91895
|
+
deepAccum(vd, vs);
|
|
91896
|
+
}
|
|
91897
|
+
}
|
|
91898
|
+
}
|
|
91899
|
+
exports.deepAccum = deepAccum;
|
|
91900
|
+
function precisionRound(n, p) {
|
|
91901
|
+
let f = Math.pow(10, p);
|
|
91902
|
+
return Math.round(n * f) / f;
|
|
91903
|
+
}
|
|
91904
|
+
exports.precisionRound = precisionRound;
|
|
91905
|
+
function percentString(num, den, precision = 0) {
|
|
91906
|
+
if (den == 0)
|
|
91907
|
+
return '(-)';
|
|
91908
|
+
let p = precisionRound((num / den) * 100, precision);
|
|
91909
|
+
return String(p) + '%';
|
|
91910
|
+
}
|
|
91911
|
+
exports.percentString = percentString;
|
|
91912
|
+
function hash(s) {
|
|
91913
|
+
let hash = 5381;
|
|
91914
|
+
let i = s.length;
|
|
91915
|
+
while (i)
|
|
91916
|
+
hash = (hash * 33) ^ s.charCodeAt(--i);
|
|
91917
|
+
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
|
|
91918
|
+
* integers. Since we want the results to be always positive, convert the
|
|
91919
|
+
* signed int to an unsigned by doing an unsigned bitshift. */
|
|
91920
|
+
return hash >>> 0;
|
|
91921
|
+
}
|
|
91922
|
+
exports.hash = hash;
|
|
91923
|
+
function hashObject(o) {
|
|
91924
|
+
return hash(o ? JSON.stringify(o) : '');
|
|
91925
|
+
}
|
|
91926
|
+
exports.hashObject = hashObject;
|
|
91927
|
+
const HexTable = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
|
91928
|
+
function toHex(n) {
|
|
91929
|
+
if (n < 0 || n > 255)
|
|
91930
|
+
throw ('only 0 to 255 supported now');
|
|
91931
|
+
n = Math.floor(n);
|
|
91932
|
+
return HexTable[n >> 4] + HexTable[n & 15];
|
|
91933
|
+
}
|
|
91934
|
+
exports.toHex = toHex;
|
|
91935
|
+
function toRGBA(color, alpha) {
|
|
91936
|
+
let r;
|
|
91937
|
+
let g;
|
|
91938
|
+
let b;
|
|
91939
|
+
switch (color) {
|
|
91940
|
+
case 'white':
|
|
91941
|
+
r = 255;
|
|
91942
|
+
g = 255;
|
|
91943
|
+
b = 255;
|
|
91944
|
+
break;
|
|
91945
|
+
case 'black':
|
|
91946
|
+
r = 0;
|
|
91947
|
+
g = 0;
|
|
91948
|
+
b = 0;
|
|
91949
|
+
break;
|
|
91950
|
+
default:
|
|
91951
|
+
r = parseInt(color.substr(1, 2), 16);
|
|
91952
|
+
g = parseInt(color.substr(3, 2), 16);
|
|
91953
|
+
b = parseInt(color.substr(5, 2), 16);
|
|
91954
|
+
break;
|
|
91955
|
+
}
|
|
91956
|
+
return `rgba(${String(r)}, ${String(g)}, ${String(b)}, ${String(alpha)})`;
|
|
91957
|
+
}
|
|
91958
|
+
exports.toRGBA = toRGBA;
|
|
91959
|
+
function toRGBAIntensity(color, intensity, alpha) {
|
|
91960
|
+
// for now assume color is black
|
|
91961
|
+
let g = precisionRound(255 * intensity, 0);
|
|
91962
|
+
return `rgba(${String(g)}, ${String(g)}, ${String(g)}, ${String(alpha)})`;
|
|
91963
|
+
}
|
|
91964
|
+
exports.toRGBAIntensity = toRGBAIntensity;
|
|
91965
|
+
// Geo functions
|
|
91966
|
+
function distance(x0, y0, x1, y1) {
|
|
91967
|
+
return Math.hypot(x0 - x1, y0 - y1);
|
|
91968
|
+
}
|
|
91969
|
+
exports.distance = distance;
|
|
91970
|
+
function deg2rad(num) { return num * Math.PI / 180; }
|
|
91971
|
+
exports.deg2rad = deg2rad;
|
|
91972
|
+
function rad2deg(num) { return num / Math.PI * 180; }
|
|
91973
|
+
exports.rad2deg = rad2deg;
|
|
91974
|
+
// Restricts lon to range [-180..180]
|
|
91975
|
+
function wrapLon(lon) {
|
|
91976
|
+
let worlds = Math.floor((lon + 180) / 360);
|
|
91977
|
+
return lon - (worlds * 360);
|
|
91978
|
+
}
|
|
91979
|
+
exports.wrapLon = wrapLon;
|
|
91980
|
+
|
|
91981
|
+
|
|
91982
|
+
/***/ })
|
|
91983
|
+
|
|
91984
|
+
/******/ });
|
|
91985
|
+
});
|
|
91986
|
+
|
|
91987
|
+
|
|
91988
|
+
/***/ }),
|
|
91989
|
+
|
|
91990
|
+
/***/ "./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js":
|
|
91991
|
+
/*!***************************************************************************!*\
|
|
91992
|
+
!*** ./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js ***!
|
|
91993
|
+
\***************************************************************************/
|
|
91994
|
+
/*! no static exports found */
|
|
91995
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91996
|
+
|
|
91997
|
+
"use strict";
|
|
91998
|
+
|
|
91999
|
+
|
|
92000
|
+
var crypto = __webpack_require__(/*! crypto */ "crypto");
|
|
92001
|
+
|
|
92002
|
+
/**
|
|
92003
|
+
* Exported function
|
|
92004
|
+
*
|
|
92005
|
+
* Options:
|
|
92006
|
+
*
|
|
92007
|
+
* - `algorithm` hash algo to be used by this instance: *'sha1', 'md5'
|
|
92008
|
+
* - `excludeValues` {true|*false} hash object keys, values ignored
|
|
92009
|
+
* - `encoding` hash encoding, supports 'buffer', '*hex', 'binary', 'base64'
|
|
92010
|
+
* - `ignoreUnknown` {true|*false} ignore unknown object types
|
|
92011
|
+
* - `replacer` optional function that replaces values before hashing
|
|
92012
|
+
* - `respectFunctionProperties` {*true|false} consider function properties when hashing
|
|
92013
|
+
* - `respectFunctionNames` {*true|false} consider 'name' property of functions for hashing
|
|
92014
|
+
* - `respectType` {*true|false} Respect special properties (prototype, constructor)
|
|
92015
|
+
* when hashing to distinguish between types
|
|
92016
|
+
* - `unorderedArrays` {true|*false} Sort all arrays before hashing
|
|
92017
|
+
* - `unorderedSets` {*true|false} Sort `Set` and `Map` instances before hashing
|
|
92018
|
+
* * = default
|
|
92019
|
+
*
|
|
92020
|
+
* @param {object} object value to hash
|
|
92021
|
+
* @param {object} options hashing options
|
|
92022
|
+
* @return {string} hash value
|
|
92023
|
+
* @api public
|
|
92024
|
+
*/
|
|
92025
|
+
exports = module.exports = objectHash;
|
|
92026
|
+
|
|
92027
|
+
function objectHash(object, options){
|
|
92028
|
+
options = applyDefaults(object, options);
|
|
92029
|
+
|
|
92030
|
+
return hash(object, options);
|
|
92031
|
+
}
|
|
92032
|
+
|
|
92033
|
+
/**
|
|
92034
|
+
* Exported sugar methods
|
|
92035
|
+
*
|
|
92036
|
+
* @param {object} object value to hash
|
|
92037
|
+
* @return {string} hash value
|
|
92038
|
+
* @api public
|
|
92039
|
+
*/
|
|
92040
|
+
exports.sha1 = function(object){
|
|
92041
|
+
return objectHash(object);
|
|
92042
|
+
};
|
|
92043
|
+
exports.keys = function(object){
|
|
92044
|
+
return objectHash(object, {excludeValues: true, algorithm: 'sha1', encoding: 'hex'});
|
|
92045
|
+
};
|
|
92046
|
+
exports.MD5 = function(object){
|
|
92047
|
+
return objectHash(object, {algorithm: 'md5', encoding: 'hex'});
|
|
92048
|
+
};
|
|
92049
|
+
exports.keysMD5 = function(object){
|
|
92050
|
+
return objectHash(object, {algorithm: 'md5', encoding: 'hex', excludeValues: true});
|
|
92051
|
+
};
|
|
92052
|
+
|
|
92053
|
+
// Internals
|
|
92054
|
+
var hashes = crypto.getHashes ? crypto.getHashes().slice() : ['sha1', 'md5'];
|
|
92055
|
+
hashes.push('passthrough');
|
|
92056
|
+
var encodings = ['buffer', 'hex', 'binary', 'base64'];
|
|
92057
|
+
|
|
92058
|
+
function applyDefaults(object, sourceOptions){
|
|
92059
|
+
sourceOptions = sourceOptions || {};
|
|
92060
|
+
|
|
92061
|
+
// create a copy rather than mutating
|
|
92062
|
+
var options = {};
|
|
92063
|
+
options.algorithm = sourceOptions.algorithm || 'sha1';
|
|
92064
|
+
options.encoding = sourceOptions.encoding || 'hex';
|
|
92065
|
+
options.excludeValues = sourceOptions.excludeValues ? true : false;
|
|
92066
|
+
options.algorithm = options.algorithm.toLowerCase();
|
|
92067
|
+
options.encoding = options.encoding.toLowerCase();
|
|
92068
|
+
options.ignoreUnknown = sourceOptions.ignoreUnknown !== true ? false : true; // default to false
|
|
92069
|
+
options.respectType = sourceOptions.respectType === false ? false : true; // default to true
|
|
92070
|
+
options.respectFunctionNames = sourceOptions.respectFunctionNames === false ? false : true;
|
|
92071
|
+
options.respectFunctionProperties = sourceOptions.respectFunctionProperties === false ? false : true;
|
|
92072
|
+
options.unorderedArrays = sourceOptions.unorderedArrays !== true ? false : true; // default to false
|
|
92073
|
+
options.unorderedSets = sourceOptions.unorderedSets === false ? false : true; // default to false
|
|
92074
|
+
options.unorderedObjects = sourceOptions.unorderedObjects === false ? false : true; // default to true
|
|
92075
|
+
options.replacer = sourceOptions.replacer || undefined;
|
|
92076
|
+
options.excludeKeys = sourceOptions.excludeKeys || undefined;
|
|
92077
|
+
|
|
92078
|
+
if(typeof object === 'undefined') {
|
|
92079
|
+
throw new Error('Object argument required.');
|
|
92080
|
+
}
|
|
92081
|
+
|
|
92082
|
+
// if there is a case-insensitive match in the hashes list, accept it
|
|
92083
|
+
// (i.e. SHA256 for sha256)
|
|
92084
|
+
for (var i = 0; i < hashes.length; ++i) {
|
|
92085
|
+
if (hashes[i].toLowerCase() === options.algorithm.toLowerCase()) {
|
|
92086
|
+
options.algorithm = hashes[i];
|
|
92087
|
+
}
|
|
92088
|
+
}
|
|
92089
|
+
|
|
92090
|
+
if(hashes.indexOf(options.algorithm) === -1){
|
|
92091
|
+
throw new Error('Algorithm "' + options.algorithm + '" not supported. ' +
|
|
92092
|
+
'supported values: ' + hashes.join(', '));
|
|
92093
|
+
}
|
|
92094
|
+
|
|
92095
|
+
if(encodings.indexOf(options.encoding) === -1 &&
|
|
92096
|
+
options.algorithm !== 'passthrough'){
|
|
92097
|
+
throw new Error('Encoding "' + options.encoding + '" not supported. ' +
|
|
92098
|
+
'supported values: ' + encodings.join(', '));
|
|
92099
|
+
}
|
|
92100
|
+
|
|
92101
|
+
return options;
|
|
92102
|
+
}
|
|
92103
|
+
|
|
92104
|
+
/** Check if the given function is a native function */
|
|
92105
|
+
function isNativeFunction(f) {
|
|
92106
|
+
if ((typeof f) !== 'function') {
|
|
92107
|
+
return false;
|
|
92108
|
+
}
|
|
92109
|
+
var exp = /^function\s+\w*\s*\(\s*\)\s*{\s+\[native code\]\s+}$/i;
|
|
92110
|
+
return exp.exec(Function.prototype.toString.call(f)) != null;
|
|
92111
|
+
}
|
|
92112
|
+
|
|
92113
|
+
function hash(object, options) {
|
|
92114
|
+
var hashingStream;
|
|
92115
|
+
|
|
92116
|
+
if (options.algorithm !== 'passthrough') {
|
|
92117
|
+
hashingStream = crypto.createHash(options.algorithm);
|
|
92118
|
+
} else {
|
|
92119
|
+
hashingStream = new PassThrough();
|
|
92120
|
+
}
|
|
92121
|
+
|
|
92122
|
+
if (typeof hashingStream.write === 'undefined') {
|
|
92123
|
+
hashingStream.write = hashingStream.update;
|
|
92124
|
+
hashingStream.end = hashingStream.update;
|
|
92125
|
+
}
|
|
92126
|
+
|
|
92127
|
+
var hasher = typeHasher(options, hashingStream);
|
|
92128
|
+
hasher.dispatch(object);
|
|
92129
|
+
if (!hashingStream.update) {
|
|
92130
|
+
hashingStream.end('');
|
|
92131
|
+
}
|
|
92132
|
+
|
|
92133
|
+
if (hashingStream.digest) {
|
|
92134
|
+
return hashingStream.digest(options.encoding === 'buffer' ? undefined : options.encoding);
|
|
92135
|
+
}
|
|
92136
|
+
|
|
92137
|
+
var buf = hashingStream.read();
|
|
92138
|
+
if (options.encoding === 'buffer') {
|
|
92139
|
+
return buf;
|
|
92140
|
+
}
|
|
92141
|
+
|
|
92142
|
+
return buf.toString(options.encoding);
|
|
92143
|
+
}
|
|
90607
92144
|
|
|
92145
|
+
/**
|
|
92146
|
+
* Expose streaming API
|
|
92147
|
+
*
|
|
92148
|
+
* @param {object} object Value to serialize
|
|
92149
|
+
* @param {object} options Options, as for hash()
|
|
92150
|
+
* @param {object} stream A stream to write the serializiation to
|
|
92151
|
+
* @api public
|
|
92152
|
+
*/
|
|
92153
|
+
exports.writeToStream = function(object, options, stream) {
|
|
92154
|
+
if (typeof stream === 'undefined') {
|
|
92155
|
+
stream = options;
|
|
92156
|
+
options = {};
|
|
92157
|
+
}
|
|
90608
92158
|
|
|
90609
|
-
|
|
92159
|
+
options = applyDefaults(object, options);
|
|
90610
92160
|
|
|
90611
|
-
|
|
90612
|
-
|
|
90613
|
-
!*** ./testdata/profiles/sample-profile.json ***!
|
|
90614
|
-
\***********************************************/
|
|
90615
|
-
/*! exports provided: state, planName, nDistricts, nCounties, legislativeDistricts, populationProfile, compactnessProfile, splittingProfile, partisanProfile, demographicProfile, default */
|
|
90616
|
-
/***/ (function(module) {
|
|
92161
|
+
return typeHasher(options, stream).dispatch(object);
|
|
92162
|
+
};
|
|
90617
92163
|
|
|
90618
|
-
|
|
92164
|
+
function typeHasher(options, writeTo, context){
|
|
92165
|
+
context = context || [];
|
|
92166
|
+
var write = function(str) {
|
|
92167
|
+
if (writeTo.update) {
|
|
92168
|
+
return writeTo.update(str, 'utf8');
|
|
92169
|
+
} else {
|
|
92170
|
+
return writeTo.write(str, 'utf8');
|
|
92171
|
+
}
|
|
92172
|
+
};
|
|
90619
92173
|
|
|
90620
|
-
|
|
92174
|
+
return {
|
|
92175
|
+
dispatch: function(value){
|
|
92176
|
+
if (options.replacer) {
|
|
92177
|
+
value = options.replacer(value);
|
|
92178
|
+
}
|
|
90621
92179
|
|
|
90622
|
-
|
|
90623
|
-
|
|
90624
|
-
|
|
90625
|
-
|
|
90626
|
-
/*! exports provided: score, best, fair, default */
|
|
90627
|
-
/***/ (function(module) {
|
|
92180
|
+
var type = typeof value;
|
|
92181
|
+
if (value === null) {
|
|
92182
|
+
type = 'null';
|
|
92183
|
+
}
|
|
90628
92184
|
|
|
90629
|
-
|
|
92185
|
+
//console.log("[DEBUG] Dispatch: ", value, "->", type, " -> ", "_" + type);
|
|
90630
92186
|
|
|
90631
|
-
|
|
92187
|
+
return this['_' + type](value);
|
|
92188
|
+
},
|
|
92189
|
+
_object: function(object) {
|
|
92190
|
+
var pattern = (/\[object (.*)\]/i);
|
|
92191
|
+
var objString = Object.prototype.toString.call(object);
|
|
92192
|
+
var objType = pattern.exec(objString);
|
|
92193
|
+
if (!objType) { // object type did not match [object ...]
|
|
92194
|
+
objType = 'unknown:[' + objString + ']';
|
|
92195
|
+
} else {
|
|
92196
|
+
objType = objType[1]; // take only the class name
|
|
92197
|
+
}
|
|
90632
92198
|
|
|
90633
|
-
|
|
90634
|
-
|
|
92199
|
+
objType = objType.toLowerCase();
|
|
92200
|
+
|
|
92201
|
+
var objectNumber = null;
|
|
92202
|
+
|
|
92203
|
+
if ((objectNumber = context.indexOf(object)) >= 0) {
|
|
92204
|
+
return this.dispatch('[CIRCULAR:' + objectNumber + ']');
|
|
92205
|
+
} else {
|
|
92206
|
+
context.push(object);
|
|
92207
|
+
}
|
|
92208
|
+
|
|
92209
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(object)) {
|
|
92210
|
+
write('buffer:');
|
|
92211
|
+
return write(object);
|
|
92212
|
+
}
|
|
92213
|
+
|
|
92214
|
+
if(objType !== 'object' && objType !== 'function') {
|
|
92215
|
+
if(this['_' + objType]) {
|
|
92216
|
+
this['_' + objType](object);
|
|
92217
|
+
} else if (options.ignoreUnknown) {
|
|
92218
|
+
return write('[' + objType + ']');
|
|
92219
|
+
} else {
|
|
92220
|
+
throw new Error('Unknown object type "' + objType + '"');
|
|
92221
|
+
}
|
|
92222
|
+
}else{
|
|
92223
|
+
var keys = Object.keys(object);
|
|
92224
|
+
if (options.unorderedObjects) {
|
|
92225
|
+
keys = keys.sort();
|
|
92226
|
+
}
|
|
92227
|
+
// Make sure to incorporate special properties, so
|
|
92228
|
+
// Types with different prototypes will produce
|
|
92229
|
+
// a different hash and objects derived from
|
|
92230
|
+
// different functions (`new Foo`, `new Bar`) will
|
|
92231
|
+
// produce different hashes.
|
|
92232
|
+
// We never do this for native functions since some
|
|
92233
|
+
// seem to break because of that.
|
|
92234
|
+
if (options.respectType !== false && !isNativeFunction(object)) {
|
|
92235
|
+
keys.splice(0, 0, 'prototype', '__proto__', 'constructor');
|
|
92236
|
+
}
|
|
92237
|
+
|
|
92238
|
+
if (options.excludeKeys) {
|
|
92239
|
+
keys = keys.filter(function(key) { return !options.excludeKeys(key); });
|
|
92240
|
+
}
|
|
92241
|
+
|
|
92242
|
+
write('object:' + keys.length + ':');
|
|
92243
|
+
var self = this;
|
|
92244
|
+
return keys.forEach(function(key){
|
|
92245
|
+
self.dispatch(key);
|
|
92246
|
+
write(':');
|
|
92247
|
+
if(!options.excludeValues) {
|
|
92248
|
+
self.dispatch(object[key]);
|
|
92249
|
+
}
|
|
92250
|
+
write(',');
|
|
92251
|
+
});
|
|
92252
|
+
}
|
|
92253
|
+
},
|
|
92254
|
+
_array: function(arr, unordered){
|
|
92255
|
+
unordered = typeof unordered !== 'undefined' ? unordered :
|
|
92256
|
+
options.unorderedArrays !== false; // default to options.unorderedArrays
|
|
92257
|
+
|
|
92258
|
+
var self = this;
|
|
92259
|
+
write('array:' + arr.length + ':');
|
|
92260
|
+
if (!unordered || arr.length <= 1) {
|
|
92261
|
+
return arr.forEach(function(entry) {
|
|
92262
|
+
return self.dispatch(entry);
|
|
92263
|
+
});
|
|
92264
|
+
}
|
|
92265
|
+
|
|
92266
|
+
// the unordered case is a little more complicated:
|
|
92267
|
+
// since there is no canonical ordering on objects,
|
|
92268
|
+
// i.e. {a:1} < {a:2} and {a:1} > {a:2} are both false,
|
|
92269
|
+
// we first serialize each entry using a PassThrough stream
|
|
92270
|
+
// before sorting.
|
|
92271
|
+
// also: we can’t use the same context array for all entries
|
|
92272
|
+
// since the order of hashing should *not* matter. instead,
|
|
92273
|
+
// we keep track of the additions to a copy of the context array
|
|
92274
|
+
// and add all of them to the global context array when we’re done
|
|
92275
|
+
var contextAdditions = [];
|
|
92276
|
+
var entries = arr.map(function(entry) {
|
|
92277
|
+
var strm = new PassThrough();
|
|
92278
|
+
var localContext = context.slice(); // make copy
|
|
92279
|
+
var hasher = typeHasher(options, strm, localContext);
|
|
92280
|
+
hasher.dispatch(entry);
|
|
92281
|
+
// take only what was added to localContext and append it to contextAdditions
|
|
92282
|
+
contextAdditions = contextAdditions.concat(localContext.slice(context.length));
|
|
92283
|
+
return strm.read().toString();
|
|
92284
|
+
});
|
|
92285
|
+
context = context.concat(contextAdditions);
|
|
92286
|
+
entries.sort();
|
|
92287
|
+
return this._array(entries, false);
|
|
92288
|
+
},
|
|
92289
|
+
_date: function(date){
|
|
92290
|
+
return write('date:' + date.toJSON());
|
|
92291
|
+
},
|
|
92292
|
+
_symbol: function(sym){
|
|
92293
|
+
return write('symbol:' + sym.toString());
|
|
92294
|
+
},
|
|
92295
|
+
_error: function(err){
|
|
92296
|
+
return write('error:' + err.toString());
|
|
92297
|
+
},
|
|
92298
|
+
_boolean: function(bool){
|
|
92299
|
+
return write('bool:' + bool.toString());
|
|
92300
|
+
},
|
|
92301
|
+
_string: function(string){
|
|
92302
|
+
write('string:' + string.length + ':');
|
|
92303
|
+
write(string.toString());
|
|
92304
|
+
},
|
|
92305
|
+
_function: function(fn){
|
|
92306
|
+
write('fn:');
|
|
92307
|
+
if (isNativeFunction(fn)) {
|
|
92308
|
+
this.dispatch('[native]');
|
|
92309
|
+
} else {
|
|
92310
|
+
this.dispatch(fn.toString());
|
|
92311
|
+
}
|
|
92312
|
+
|
|
92313
|
+
if (options.respectFunctionNames !== false) {
|
|
92314
|
+
// Make sure we can still distinguish native functions
|
|
92315
|
+
// by their name, otherwise String and Function will
|
|
92316
|
+
// have the same hash
|
|
92317
|
+
this.dispatch("function-name:" + String(fn.name));
|
|
92318
|
+
}
|
|
92319
|
+
|
|
92320
|
+
if (options.respectFunctionProperties) {
|
|
92321
|
+
this._object(fn);
|
|
92322
|
+
}
|
|
92323
|
+
},
|
|
92324
|
+
_number: function(number){
|
|
92325
|
+
return write('number:' + number.toString());
|
|
92326
|
+
},
|
|
92327
|
+
_xml: function(xml){
|
|
92328
|
+
return write('xml:' + xml.toString());
|
|
92329
|
+
},
|
|
92330
|
+
_null: function() {
|
|
92331
|
+
return write('Null');
|
|
92332
|
+
},
|
|
92333
|
+
_undefined: function() {
|
|
92334
|
+
return write('Undefined');
|
|
92335
|
+
},
|
|
92336
|
+
_regexp: function(regex){
|
|
92337
|
+
return write('regex:' + regex.toString());
|
|
92338
|
+
},
|
|
92339
|
+
_uint8array: function(arr){
|
|
92340
|
+
write('uint8array:');
|
|
92341
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92342
|
+
},
|
|
92343
|
+
_uint8clampedarray: function(arr){
|
|
92344
|
+
write('uint8clampedarray:');
|
|
92345
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92346
|
+
},
|
|
92347
|
+
_int8array: function(arr){
|
|
92348
|
+
write('uint8array:');
|
|
92349
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92350
|
+
},
|
|
92351
|
+
_uint16array: function(arr){
|
|
92352
|
+
write('uint16array:');
|
|
92353
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92354
|
+
},
|
|
92355
|
+
_int16array: function(arr){
|
|
92356
|
+
write('uint16array:');
|
|
92357
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92358
|
+
},
|
|
92359
|
+
_uint32array: function(arr){
|
|
92360
|
+
write('uint32array:');
|
|
92361
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92362
|
+
},
|
|
92363
|
+
_int32array: function(arr){
|
|
92364
|
+
write('uint32array:');
|
|
92365
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92366
|
+
},
|
|
92367
|
+
_float32array: function(arr){
|
|
92368
|
+
write('float32array:');
|
|
92369
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92370
|
+
},
|
|
92371
|
+
_float64array: function(arr){
|
|
92372
|
+
write('float64array:');
|
|
92373
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92374
|
+
},
|
|
92375
|
+
_arraybuffer: function(arr){
|
|
92376
|
+
write('arraybuffer:');
|
|
92377
|
+
return this.dispatch(new Uint8Array(arr));
|
|
92378
|
+
},
|
|
92379
|
+
_url: function(url) {
|
|
92380
|
+
return write('url:' + url.toString(), 'utf8');
|
|
92381
|
+
},
|
|
92382
|
+
_map: function(map) {
|
|
92383
|
+
write('map:');
|
|
92384
|
+
var arr = Array.from(map);
|
|
92385
|
+
return this._array(arr, options.unorderedSets !== false);
|
|
92386
|
+
},
|
|
92387
|
+
_set: function(set) {
|
|
92388
|
+
write('set:');
|
|
92389
|
+
var arr = Array.from(set);
|
|
92390
|
+
return this._array(arr, options.unorderedSets !== false);
|
|
92391
|
+
},
|
|
92392
|
+
_blob: function() {
|
|
92393
|
+
if (options.ignoreUnknown) {
|
|
92394
|
+
return write('[blob]');
|
|
92395
|
+
}
|
|
92396
|
+
|
|
92397
|
+
throw Error('Hashing Blob objects is currently not supported\n' +
|
|
92398
|
+
'(see https://github.com/puleos/object-hash/issues/26)\n' +
|
|
92399
|
+
'Use "options.replacer" or "options.ignoreUnknown"\n');
|
|
92400
|
+
},
|
|
92401
|
+
_domwindow: function() { return write('domwindow'); },
|
|
92402
|
+
/* Node.js standard native objects */
|
|
92403
|
+
_process: function() { return write('process'); },
|
|
92404
|
+
_timer: function() { return write('timer'); },
|
|
92405
|
+
_pipe: function() { return write('pipe'); },
|
|
92406
|
+
_tcp: function() { return write('tcp'); },
|
|
92407
|
+
_udp: function() { return write('udp'); },
|
|
92408
|
+
_tty: function() { return write('tty'); },
|
|
92409
|
+
_statwatcher: function() { return write('statwatcher'); },
|
|
92410
|
+
_securecontext: function() { return write('securecontext'); },
|
|
92411
|
+
_connection: function() { return write('connection'); },
|
|
92412
|
+
_zlib: function() { return write('zlib'); },
|
|
92413
|
+
_context: function() { return write('context'); },
|
|
92414
|
+
_nodescript: function() { return write('nodescript'); },
|
|
92415
|
+
_httpparser: function() { return write('httpparser'); },
|
|
92416
|
+
_dataview: function() { return write('dataview'); },
|
|
92417
|
+
_signal: function() { return write('signal'); },
|
|
92418
|
+
_fsevent: function() { return write('fsevent'); },
|
|
92419
|
+
_tlswrap: function() { return write('tlswrap'); }
|
|
92420
|
+
};
|
|
92421
|
+
}
|
|
92422
|
+
|
|
92423
|
+
// Mini-implementation of stream.PassThrough
|
|
92424
|
+
// We are far from having need for the full implementation, and we can
|
|
92425
|
+
// make assumptions like "many writes, then only one final read"
|
|
92426
|
+
// and we can ignore encoding specifics
|
|
92427
|
+
function PassThrough() {
|
|
92428
|
+
return {
|
|
92429
|
+
buf: '',
|
|
92430
|
+
|
|
92431
|
+
write: function(b) {
|
|
92432
|
+
this.buf += b;
|
|
92433
|
+
},
|
|
92434
|
+
|
|
92435
|
+
end: function(b) {
|
|
92436
|
+
this.buf += b;
|
|
92437
|
+
},
|
|
92438
|
+
|
|
92439
|
+
read: function() {
|
|
92440
|
+
return this.buf;
|
|
92441
|
+
}
|
|
92442
|
+
};
|
|
92443
|
+
}
|
|
90635
92444
|
|
|
90636
92445
|
|
|
90637
92446
|
/***/ }),
|
|
@@ -98606,6 +100415,7 @@ const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
|
98606
100415
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
98607
100416
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
98608
100417
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
100418
|
+
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
98609
100419
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
98610
100420
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
98611
100421
|
class AnalyticsSession {
|
|
@@ -98625,45 +100435,48 @@ class AnalyticsSession {
|
|
|
98625
100435
|
this.features = new D.Features(this, SessionRequest['data'], this.config['datasets']);
|
|
98626
100436
|
this.plan = new D.Plan(this, SessionRequest['plan']);
|
|
98627
100437
|
this.districts = new D.Districts(this, SessionRequest['districtShapes']);
|
|
98628
|
-
// TODO -
|
|
98629
|
-
|
|
98630
|
-
|
|
98631
|
-
|
|
98632
|
-
|
|
98633
|
-
|
|
98634
|
-
|
|
98635
|
-
|
|
98636
|
-
|
|
98637
|
-
|
|
98638
|
-
|
|
100438
|
+
// TODO - SCORE: Toggle
|
|
100439
|
+
if (this.useLegacy()) {
|
|
100440
|
+
console.log("Using legacy district-analytics.");
|
|
100441
|
+
// NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
100442
|
+
// we could want them to passed into an analytics session as data, along with
|
|
100443
|
+
// everything else. For now, this keeps branching out of the main code.
|
|
100444
|
+
results_1.doConfigureScales(this);
|
|
100445
|
+
}
|
|
100446
|
+
else {
|
|
100447
|
+
console.log("Using dra-score analytics.");
|
|
100448
|
+
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
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
|
-
// TODO -
|
|
98645
|
-
|
|
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
|
+
// TODO - SCORE: Delete
|
|
100457
|
+
config['suites'] = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
|
|
98650
100458
|
// Default the Census & redistricting cycle to 2010
|
|
98651
100459
|
if (!(U.keyExists('cycle', config)))
|
|
98652
100460
|
config['cycle'] = 2010;
|
|
98653
100461
|
return config;
|
|
98654
100462
|
}
|
|
100463
|
+
// TODO - SCORE: Toggle = Invert this logic
|
|
100464
|
+
useLegacy() {
|
|
100465
|
+
// TODO - SCORE: Opt-out
|
|
100466
|
+
return (U.keyExists('useScore', this.config) && (this.config['useScore'] != null) && (!(this.config['useScore']))) ? true : false;
|
|
100467
|
+
// TODO - SCORE: Opt-in
|
|
100468
|
+
// return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
|
|
100469
|
+
}
|
|
98655
100470
|
// Using the the data in the analytics session, calculate all the
|
|
98656
100471
|
// analytics & validations, saving/updating the individual test results.
|
|
98657
|
-
analyzePlan(bLog = false) {
|
|
100472
|
+
analyzePlan(bLog = false, overridesJSON) {
|
|
98658
100473
|
try {
|
|
98659
100474
|
preprocess_1.doPreprocessData(this, bLog);
|
|
98660
100475
|
analyze_1.doAnalyzeDistricts(this, bLog);
|
|
98661
100476
|
analyze_1.doAnalyzePlan(this, bLog);
|
|
98662
100477
|
// TODO - SCORE
|
|
98663
100478
|
this._profile = score_1.profilePlan(this, bLog);
|
|
98664
|
-
|
|
98665
|
-
this._scorecard = score_1.scorePlan(this._profile, bLog);
|
|
98666
|
-
// TODO - SCORE
|
|
100479
|
+
this._scorecard = score_1.scorePlan(this, this._profile, bLog, overridesJSON);
|
|
98667
100480
|
results_1.doAnalyzePostProcessing(this, bLog);
|
|
98668
100481
|
}
|
|
98669
100482
|
catch (_a) {
|
|
@@ -98684,13 +100497,6 @@ class AnalyticsSession {
|
|
|
98684
100497
|
getPlanScorecard(bLog = false) {
|
|
98685
100498
|
return this._scorecard;
|
|
98686
100499
|
}
|
|
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
100500
|
// TODO - SCORE
|
|
98695
100501
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
98696
100502
|
getRequirementsChecklist(bLog = false) {
|
|
@@ -98699,19 +100505,82 @@ class AnalyticsSession {
|
|
|
98699
100505
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
98700
100506
|
getDiscontiguousDistrictFeatures(bLog = false) {
|
|
98701
100507
|
// Get the (possibly empty) list of discontiguous district IDs
|
|
98702
|
-
|
|
98703
|
-
|
|
100508
|
+
const contiguousTest = this.getTest(1 /* Contiguous */);
|
|
100509
|
+
const discontiguousDistrictIDs = contiguousTest['details']['discontiguousDistricts'] || [];
|
|
98704
100510
|
// Convert them into a (possibly empty) list of features
|
|
98705
100511
|
let discontiguousDistrictFeatures = { type: 'FeatureCollection', features: [] };
|
|
98706
100512
|
if (!(U.isArrayEmpty(discontiguousDistrictIDs))) {
|
|
98707
100513
|
for (let id of discontiguousDistrictIDs) {
|
|
98708
100514
|
let poly = this.districts.getDistrictShapeByID(id);
|
|
98709
|
-
if (poly)
|
|
98710
|
-
|
|
100515
|
+
if (poly) {
|
|
100516
|
+
// If a district has a shape & it is not contiguous, by definition,
|
|
100517
|
+
// it will be a Multipolygon, i.e., it will have multiple pieces, some
|
|
100518
|
+
// possibly embedded w/in other districts. Get & add all the pieces.
|
|
100519
|
+
const districtParts = geofeature_1.polyParts(poly);
|
|
100520
|
+
discontiguousDistrictFeatures.features.push(...districtParts.features);
|
|
100521
|
+
// discontiguousDistrictFeatures.features.push(poly);
|
|
100522
|
+
}
|
|
98711
100523
|
}
|
|
98712
100524
|
}
|
|
98713
100525
|
return discontiguousDistrictFeatures;
|
|
98714
100526
|
}
|
|
100527
|
+
// Comments clipped from dra-client geodistrict.ts.
|
|
100528
|
+
// Discontiguous polygons are:
|
|
100529
|
+
// 1. All polygons in a multi-polygon; and
|
|
100530
|
+
// 2. All holes in a otherwise cohesive polygon.
|
|
100531
|
+
// Note that all non-cohesive features are always simple polygons.
|
|
100532
|
+
/*
|
|
100533
|
+
let i: number, j: number;
|
|
100534
|
+
let nPoly: number = 0;
|
|
100535
|
+
for (i = 0;nPoly == 0 && i < this.cacheDistricts.features.length;i++)
|
|
100536
|
+
{
|
|
100537
|
+
let f = this.cacheDistricts.features[i];
|
|
100538
|
+
|
|
100539
|
+
if (f.geometry.type === 'MultiPolygon')
|
|
100540
|
+
nPoly += f.geometry.coordinates.length;
|
|
100541
|
+
else if (f.geometry.type === 'Polygon' && f.geometry.coordinates.length)
|
|
100542
|
+
nPoly += (f.geometry.coordinates.length - 1);
|
|
100543
|
+
}
|
|
100544
|
+
if (nPoly)
|
|
100545
|
+
{
|
|
100546
|
+
this.cacheNoncohesive = {type: 'FeatureCollection', features: []};
|
|
100547
|
+
let af: any = this.cacheNoncohesive.features;
|
|
100548
|
+
let oUnique: any = {};
|
|
100549
|
+
|
|
100550
|
+
// First add discontiguous polygons
|
|
100551
|
+
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
100552
|
+
{
|
|
100553
|
+
let f = this.cacheDistricts.features[i];
|
|
100554
|
+
|
|
100555
|
+
if (f.geometry.type === 'MultiPolygon')
|
|
100556
|
+
{
|
|
100557
|
+
// Push all non-contiguous polygons
|
|
100558
|
+
for (j = 0;j < f.geometry.coordinates.length;j++)
|
|
100559
|
+
{
|
|
100560
|
+
let p: any = f.geometry.coordinates[j];
|
|
100561
|
+
oUnique[Hash.qhash(p[0])] = true;
|
|
100562
|
+
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: p}});
|
|
100563
|
+
}
|
|
100564
|
+
}
|
|
100565
|
+
}
|
|
100566
|
+
|
|
100567
|
+
// Now add unique holes
|
|
100568
|
+
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
100569
|
+
{
|
|
100570
|
+
let f = this.cacheDistricts.features[i];
|
|
100571
|
+
|
|
100572
|
+
if (f.geometry.type === 'Polygon')
|
|
100573
|
+
{
|
|
100574
|
+
// Push all holes from this polygon
|
|
100575
|
+
for (j = 1;j < f.geometry.coordinates.length;j++)
|
|
100576
|
+
{
|
|
100577
|
+
let p: any = f.geometry.coordinates[j];
|
|
100578
|
+
if (oUnique[Hash.qhash(p)] === undefined)
|
|
100579
|
+
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: [p]}});
|
|
100580
|
+
}
|
|
100581
|
+
}
|
|
100582
|
+
}
|
|
100583
|
+
} */
|
|
98715
100584
|
// HELPERS USED INTERNALLY
|
|
98716
100585
|
// Get an individual test, so you can drive UI with the results.
|
|
98717
100586
|
getTest(testID) {
|
|
@@ -98727,9 +100596,17 @@ class AnalyticsSession {
|
|
|
98727
100596
|
// Return a pointer to the the test entry for this test
|
|
98728
100597
|
return this.tests[testID];
|
|
98729
100598
|
}
|
|
98730
|
-
// NOTE - Not sure why this has to be up here
|
|
100599
|
+
// NOTE - Not sure why this has to be up here ...
|
|
98731
100600
|
populationDeviationThreshold() {
|
|
98732
|
-
|
|
100601
|
+
// TODO - SCORE: Toggle
|
|
100602
|
+
if (this.useLegacy()) {
|
|
100603
|
+
return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
|
|
100604
|
+
}
|
|
100605
|
+
else {
|
|
100606
|
+
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
100607
|
+
// NOTE - The plan may not have been scored yet, i.e., no scorecard yet.
|
|
100608
|
+
return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
|
|
100609
|
+
}
|
|
98733
100610
|
}
|
|
98734
100611
|
}
|
|
98735
100612
|
exports.AnalyticsSession = AnalyticsSession;
|
|
@@ -98905,7 +100782,6 @@ class Districts {
|
|
|
98905
100782
|
let outerThis = this;
|
|
98906
100783
|
// Default the pop dev % for the dummy Unassigned district to 0%.
|
|
98907
100784
|
// Default the pop dev % for real (1–N) but empty districts to 100%.
|
|
98908
|
-
// TODO - SCORE
|
|
98909
100785
|
let popDevPct = (i > 0) ? (targetSize / targetSize) : 0 / targetSize;
|
|
98910
100786
|
// Get the geoIDs assigned to the district
|
|
98911
100787
|
// Guard against empty districts
|
|
@@ -98932,7 +100808,6 @@ class Districts {
|
|
|
98932
100808
|
// NOTE - SPLITTING
|
|
98933
100809
|
// Total population by counties w/in a district,
|
|
98934
100810
|
// except the dummy unassigned district 0
|
|
98935
|
-
// TODO - VFEATURE
|
|
98936
100811
|
if (i > 0)
|
|
98937
100812
|
countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
|
|
98938
100813
|
// Democratic and Republican vote totals
|
|
@@ -99106,10 +100981,7 @@ class Districts {
|
|
|
99106
100981
|
compact_1.extractDistrictProperties(this._session, bLog);
|
|
99107
100982
|
}
|
|
99108
100983
|
getCountyIndex(geoID) {
|
|
99109
|
-
// TODO - VFEATURE
|
|
99110
100984
|
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
99111
|
-
// let countyGeoID = U.parseGeoID(geoID)['county'] as string;
|
|
99112
|
-
// let countyFIPS = U.getFIPSFromCountyGeoID(countyGeoID);
|
|
99113
100985
|
let countyIndex = this._session.counties.indexFromFIPS(countyFIPS);
|
|
99114
100986
|
return countyIndex;
|
|
99115
100987
|
}
|
|
@@ -99358,11 +101230,45 @@ exports.doAnalyzeDistricts = doAnalyzeDistricts;
|
|
|
99358
101230
|
// NOTE - I could make this table-driven, but I'm thinking that the explicit
|
|
99359
101231
|
// calls might make chunking for aync easier.
|
|
99360
101232
|
function doAnalyzePlan(s, bLog = false) {
|
|
99361
|
-
// TODO -
|
|
99362
|
-
|
|
99363
|
-
|
|
99364
|
-
|
|
99365
|
-
|
|
101233
|
+
// TODO - SCORE: Toggle
|
|
101234
|
+
if (s.useLegacy()) {
|
|
101235
|
+
// Disable most legacy analytics
|
|
101236
|
+
// Get the requested suites, and only execute those tests
|
|
101237
|
+
let requestedSuites = s.config['suites'];
|
|
101238
|
+
// Tests in the "Legal" suite, i.e., pass/ fail constraints
|
|
101239
|
+
if (requestedSuites.includes(0 /* Legal */)) {
|
|
101240
|
+
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
101241
|
+
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
101242
|
+
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
101243
|
+
s.tests[4 /* PopulationDeviation */] = equal_1.doPopulationDeviation(s, bLog);
|
|
101244
|
+
// NOTE - I can't check whether a population deviation is legal or not, until
|
|
101245
|
+
// the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
101246
|
+
// the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
101247
|
+
// from PopulationDeviation, as part of scorecard or test log preparation.
|
|
101248
|
+
// Create an empty test entry here though ...
|
|
101249
|
+
s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
|
|
101250
|
+
}
|
|
101251
|
+
// Tests in the "Fair" suite
|
|
101252
|
+
if (requestedSuites.includes(1 /* Fair */)) {
|
|
101253
|
+
s.tests[11 /* SeatsBias */] = political_1.doSeatsBias(s, bLog);
|
|
101254
|
+
s.tests[12 /* VotesBias */] = political_1.doVotesBias(s, bLog);
|
|
101255
|
+
s.tests[13 /* Responsiveness */] = political_1.doResponsiveness(s, bLog);
|
|
101256
|
+
s.tests[14 /* ResponsiveDistricts */] = political_1.doResponsiveDistricts(s, bLog);
|
|
101257
|
+
s.tests[15 /* EfficiencyGap */] = political_1.doEfficiencyGap(s, bLog);
|
|
101258
|
+
s.tests[16 /* MajorityMinorityDistricts */] = minority_1.doMajorityMinorityDistricts(s, bLog);
|
|
101259
|
+
}
|
|
101260
|
+
// Tests in the "Best" suite, i.e., criteria for better/worse
|
|
101261
|
+
if (requestedSuites.includes(2 /* Best */)) {
|
|
101262
|
+
s.tests[5 /* Reock */] = compact_1.doReock(s, bLog);
|
|
101263
|
+
s.tests[6 /* PolsbyPopper */] = compact_1.doPolsbyPopper(s, bLog);
|
|
101264
|
+
s.tests[7 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
101265
|
+
s.tests[10 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
|
|
101266
|
+
s.tests[8 /* CountySplitting */] = cohesive_1.doCountySplitting(s, bLog);
|
|
101267
|
+
s.tests[9 /* DistrictSplitting */] = cohesive_1.doDistrictSplitting(s, bLog);
|
|
101268
|
+
}
|
|
101269
|
+
}
|
|
101270
|
+
else {
|
|
101271
|
+
// TODO - SCORE: Except these. Continue to do these here vs. dra-score.
|
|
99366
101272
|
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
99367
101273
|
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
99368
101274
|
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
@@ -99373,24 +101279,8 @@ function doAnalyzePlan(s, bLog = false) {
|
|
|
99373
101279
|
// from PopulationDeviation, as part of scorecard or test log preparation.
|
|
99374
101280
|
// Create an empty test entry here though ...
|
|
99375
101281
|
s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
|
|
99376
|
-
}
|
|
99377
|
-
// Tests in the "Fair" suite
|
|
99378
|
-
if (requestedSuites.includes(1 /* Fair */)) {
|
|
99379
|
-
s.tests[11 /* SeatsBias */] = political_1.doSeatsBias(s, bLog);
|
|
99380
|
-
s.tests[12 /* VotesBias */] = political_1.doVotesBias(s, bLog);
|
|
99381
|
-
s.tests[13 /* Responsiveness */] = political_1.doResponsiveness(s, bLog);
|
|
99382
|
-
s.tests[14 /* ResponsiveDistricts */] = political_1.doResponsiveDistricts(s, bLog);
|
|
99383
|
-
s.tests[15 /* EfficiencyGap */] = political_1.doEfficiencyGap(s, bLog);
|
|
99384
|
-
s.tests[16 /* MajorityMinorityDistricts */] = minority_1.doMajorityMinorityDistricts(s, bLog);
|
|
99385
|
-
}
|
|
99386
|
-
// Tests in the "Best" suite, i.e., criteria for better/worse
|
|
99387
|
-
if (requestedSuites.includes(2 /* Best */)) {
|
|
99388
|
-
s.tests[5 /* Reock */] = compact_1.doReock(s, bLog);
|
|
99389
|
-
s.tests[6 /* PolsbyPopper */] = compact_1.doPolsbyPopper(s, bLog);
|
|
99390
101282
|
s.tests[7 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
99391
101283
|
s.tests[10 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
|
|
99392
|
-
s.tests[8 /* CountySplitting */] = cohesive_1.doCountySplitting(s, bLog);
|
|
99393
|
-
s.tests[9 /* DistrictSplitting */] = cohesive_1.doDistrictSplitting(s, bLog);
|
|
99394
101284
|
}
|
|
99395
101285
|
// Enable a Test Log and Scorecard to be generated
|
|
99396
101286
|
s.bPlanAnalyzed = true;
|
|
@@ -99987,6 +101877,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
99987
101877
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
99988
101878
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
99989
101879
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
101880
|
+
// TODO - SCORE: Delete
|
|
99990
101881
|
function doPopulationDeviation(s, bLog = false) {
|
|
99991
101882
|
let test = s.getTest(4 /* PopulationDeviation */);
|
|
99992
101883
|
let targetSize = s.state.totalPop / s.state.nDistricts;
|
|
@@ -100025,8 +101916,8 @@ function doHasEqualPopulations(s, bLog = false) {
|
|
|
100025
101916
|
let test = s.getTest(3 /* EqualPopulation */);
|
|
100026
101917
|
// Get the normalized population deviation %
|
|
100027
101918
|
let popDevTest = s.getTest(4 /* PopulationDeviation */);
|
|
100028
|
-
|
|
100029
|
-
|
|
101919
|
+
const popDevPct = popDevTest['score'];
|
|
101920
|
+
const popDevNormalized = popDevTest['normalizedScore'];
|
|
100030
101921
|
// Populate the test entry
|
|
100031
101922
|
if (popDevNormalized > 0) {
|
|
100032
101923
|
test['score'] = true;
|
|
@@ -100068,6 +101959,23 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
100068
101959
|
};
|
|
100069
101960
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
100070
101961
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "./node_modules/@dra2020/poly/dist/poly.js"));
|
|
101962
|
+
// HELPER
|
|
101963
|
+
function polyParts(poly) {
|
|
101964
|
+
let parts = { type: 'FeatureCollection', features: [] };
|
|
101965
|
+
let af = parts.features;
|
|
101966
|
+
if (poly.geometry.type === 'MultiPolygon') {
|
|
101967
|
+
// Push all non-contiguous polygons
|
|
101968
|
+
for (let j = 0; j < poly.geometry.coordinates.length; j++) {
|
|
101969
|
+
let onePoly = poly.geometry.coordinates[j];
|
|
101970
|
+
af.push({ type: 'Feature', properties: { id: `${af.length + 1}` }, geometry: { type: 'Polygon', coordinates: onePoly } });
|
|
101971
|
+
}
|
|
101972
|
+
}
|
|
101973
|
+
else {
|
|
101974
|
+
parts.features.push(poly);
|
|
101975
|
+
}
|
|
101976
|
+
return parts;
|
|
101977
|
+
}
|
|
101978
|
+
exports.polyParts = polyParts;
|
|
100071
101979
|
// CARTESIAN SHIMS OVER 'POLY' FUNCTIONS
|
|
100072
101980
|
// TODO - POLY: Confirm Cartesian calculations
|
|
100073
101981
|
function gfArea(poly) {
|
|
@@ -100369,10 +102277,7 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
100369
102277
|
// Sum total population across the state
|
|
100370
102278
|
s.state.totalPop += value;
|
|
100371
102279
|
// Get the county FIPS code for the feature
|
|
100372
|
-
// TODO - VFEATURE
|
|
100373
102280
|
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
100374
|
-
// let county = U.parseGeoID(geoID)['county'] as string;
|
|
100375
|
-
// let countyFIPS = U.getFIPSFromCountyGeoID(county);
|
|
100376
102281
|
// If a subtotal for the county doesn't exist, initialize one
|
|
100377
102282
|
if (!(U.keyExists(countyFIPS, totalByCounty))) {
|
|
100378
102283
|
totalByCounty[countyFIPS] = 0;
|
|
@@ -100390,8 +102295,8 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
100390
102295
|
let fipsCodes = U.getObjectKeys(totalByCounty);
|
|
100391
102296
|
// Sort the results
|
|
100392
102297
|
fipsCodes = fipsCodes.sort();
|
|
100393
|
-
//
|
|
100394
|
-
// Add a dummy county, for county-district splitting analysis
|
|
102298
|
+
// NOTE - This was added for the legacy SPLITTING implementation.
|
|
102299
|
+
// Add a dummy county, for county-district splitting analysis.
|
|
100395
102300
|
fipsCodes.unshift('000');
|
|
100396
102301
|
// Create the ID-ordinal map
|
|
100397
102302
|
for (let i in fipsCodes) {
|
|
@@ -100481,6 +102386,7 @@ const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
|
100481
102386
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
100482
102387
|
const state_reqs_json_1 = __importDefault(__webpack_require__(/*! ../static/state-reqs.json */ "./static/state-reqs.json"));
|
|
100483
102388
|
// Example
|
|
102389
|
+
// TODO - DELETE?
|
|
100484
102390
|
let sampleRequirements = {
|
|
100485
102391
|
score: 2 /* Red */,
|
|
100486
102392
|
metrics: {
|
|
@@ -100504,6 +102410,7 @@ let sampleRequirements = {
|
|
|
100504
102410
|
stateReqs: "https://www.brennancenter.org/sites/default/files/publications/2019_06_50States_FINALsinglepages_20.pdf"
|
|
100505
102411
|
}
|
|
100506
102412
|
};
|
|
102413
|
+
// TODO - DELETE
|
|
100507
102414
|
let sampleCompactness = {
|
|
100508
102415
|
score: 60,
|
|
100509
102416
|
metrics: {
|
|
@@ -100516,6 +102423,7 @@ let sampleCompactness = {
|
|
|
100516
102423
|
},
|
|
100517
102424
|
resources: {}
|
|
100518
102425
|
};
|
|
102426
|
+
// TODO - DELETE
|
|
100519
102427
|
let sampleSplitting = {
|
|
100520
102428
|
score: 73,
|
|
100521
102429
|
metrics: {
|
|
@@ -100533,7 +102441,7 @@ let sampleSplitting = {
|
|
|
100533
102441
|
datasets: {},
|
|
100534
102442
|
resources: {}
|
|
100535
102443
|
};
|
|
100536
|
-
// TODO -
|
|
102444
|
+
// TODO - DELETE
|
|
100537
102445
|
let samplePartisan = {
|
|
100538
102446
|
score: 100,
|
|
100539
102447
|
metrics: {
|
|
@@ -100548,7 +102456,7 @@ let samplePartisan = {
|
|
|
100548
102456
|
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
100549
102457
|
}
|
|
100550
102458
|
};
|
|
100551
|
-
// TODO -
|
|
102459
|
+
// TODO - DELETE
|
|
100552
102460
|
let sampleMinority = {
|
|
100553
102461
|
score: null,
|
|
100554
102462
|
metrics: {
|
|
@@ -100575,6 +102483,7 @@ let sampleMinority = {
|
|
|
100575
102483
|
},
|
|
100576
102484
|
resources: {}
|
|
100577
102485
|
};
|
|
102486
|
+
// TODO - DELETE
|
|
100578
102487
|
exports.samplePlanAnalytics = {
|
|
100579
102488
|
requirements: sampleRequirements,
|
|
100580
102489
|
compactness: sampleCompactness,
|
|
@@ -100583,232 +102492,6 @@ exports.samplePlanAnalytics = {
|
|
|
100583
102492
|
partisan: samplePartisan,
|
|
100584
102493
|
minority: sampleMinority
|
|
100585
102494
|
};
|
|
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
102495
|
function prepareRequirementsChecklist(s, bLog = false) {
|
|
100813
102496
|
if (!(s.bPostProcessingDone)) {
|
|
100814
102497
|
doAnalyzePostProcessing(s);
|
|
@@ -100816,34 +102499,40 @@ function prepareRequirementsChecklist(s, bLog = false) {
|
|
|
100816
102499
|
// REQUIREMENTS CATEGORY
|
|
100817
102500
|
let paRequirements;
|
|
100818
102501
|
{
|
|
100819
|
-
|
|
100820
|
-
|
|
100821
|
-
|
|
100822
|
-
|
|
102502
|
+
const completeTest = s.getTest(0 /* Complete */);
|
|
102503
|
+
const contiguousTest = s.getTest(1 /* Contiguous */);
|
|
102504
|
+
const freeOfHolesTest = s.getTest(2 /* FreeOfHoles */);
|
|
102505
|
+
const equalPopulationTest = s.getTest(3 /* EqualPopulation */);
|
|
100823
102506
|
// Combine individual checks into an overall score
|
|
100824
|
-
//
|
|
102507
|
+
// NOTE - Until we add three-state support top to bottom in
|
|
100825
102508
|
// requirements/validations, map booleans to tri-states here.
|
|
100826
|
-
|
|
100827
|
-
|
|
100828
|
-
|
|
100829
|
-
|
|
102509
|
+
const completeMetric = U.mapBooleanToTriState(completeTest['score']);
|
|
102510
|
+
const contiguousMetric = U.mapBooleanToTriState(contiguousTest['score']);
|
|
102511
|
+
const freeOfHolesMetric = U.mapBooleanToTriState(freeOfHolesTest['score']);
|
|
102512
|
+
const equalPopulationMetric = U.mapBooleanToTriState(equalPopulationTest['score']);
|
|
100830
102513
|
let reqScore = 0 /* Green */;
|
|
100831
|
-
|
|
102514
|
+
const checks = [completeMetric, contiguousMetric, freeOfHolesMetric, equalPopulationMetric];
|
|
100832
102515
|
if (checks.includes(1 /* Yellow */))
|
|
100833
102516
|
reqScore = 1 /* Yellow */;
|
|
100834
102517
|
if (checks.includes(2 /* Red */))
|
|
100835
102518
|
reqScore = 2 /* Red */;
|
|
100836
102519
|
// Get values to support details entries
|
|
100837
|
-
|
|
100838
|
-
|
|
100839
|
-
|
|
100840
|
-
|
|
100841
|
-
|
|
100842
|
-
|
|
100843
|
-
|
|
102520
|
+
const unassignedFeaturesDetail = U.deepCopy(completeTest['details']['unassignedFeatures']) || [];
|
|
102521
|
+
const emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
102522
|
+
const discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
102523
|
+
const embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
102524
|
+
// TODO - SCORE: DELETE - This code is hooked correctly to use dra-score
|
|
102525
|
+
// const scorecard = s._scorecard as Score.Scorecard;
|
|
102526
|
+
// const populationDeviation = scorecard.best.populationDeviation.raw;
|
|
102527
|
+
const populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
102528
|
+
// console.log("Population deviations =", populationDeviationDetail, populationDeviation);
|
|
102529
|
+
// const deviationThreshold = scorecard.best.populationDeviation.notes['threshold'];
|
|
102530
|
+
const deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
102531
|
+
// console.log("Population deviation thresholds =", deviationThresholdDetail, deviationThreshold);
|
|
102532
|
+
const xx = s.state.xx;
|
|
100844
102533
|
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
100845
|
-
|
|
100846
|
-
|
|
102534
|
+
const stateReqsDict = state_reqs_json_1.default;
|
|
102535
|
+
const reqLinkToStateReqs = stateReqsDict[xx];
|
|
100847
102536
|
// Populate the category
|
|
100848
102537
|
paRequirements = {
|
|
100849
102538
|
score: reqScore,
|
|
@@ -101106,19 +102795,28 @@ exports.doConfigureScales = doConfigureScales;
|
|
|
101106
102795
|
// Postprocess analytics - Normalize numeric results and derive secondary tests.
|
|
101107
102796
|
// Do this after analytics have been run and before preparing a test log or scorecard.
|
|
101108
102797
|
function doAnalyzePostProcessing(s, bLog = false) {
|
|
101109
|
-
//
|
|
101110
|
-
|
|
101111
|
-
|
|
101112
|
-
|
|
101113
|
-
|
|
101114
|
-
|
|
101115
|
-
|
|
101116
|
-
|
|
101117
|
-
|
|
101118
|
-
|
|
101119
|
-
|
|
102798
|
+
// TODO - SCORE: Toggle
|
|
102799
|
+
if (s.useLegacy()) {
|
|
102800
|
+
// Normalize the raw scores for all the numerics tests
|
|
102801
|
+
let testResults = U.getNumericObjectKeys(testDefns);
|
|
102802
|
+
for (let testID of testResults) {
|
|
102803
|
+
if (testDefns[testID]['normalize']) {
|
|
102804
|
+
let testResult = s.getTest(testID);
|
|
102805
|
+
let rawScore = testResult['score'];
|
|
102806
|
+
let normalizedScore;
|
|
102807
|
+
normalizedScore = U.normalize(rawScore, s.testScales[testID]);
|
|
102808
|
+
testResult['normalizedScore'] = normalizedScore;
|
|
102809
|
+
// Add the scale used to normalize the raw score to the details
|
|
102810
|
+
testResult['details']['scale'] = s.testScales[testID].scale;
|
|
102811
|
+
}
|
|
101120
102812
|
}
|
|
101121
102813
|
}
|
|
102814
|
+
else {
|
|
102815
|
+
// Just populate the normalized population deviation score in the test
|
|
102816
|
+
const scorecard = s._scorecard;
|
|
102817
|
+
let test = s.getTest(4 /* PopulationDeviation */);
|
|
102818
|
+
test['normalizedScore'] = scorecard.best.populationDeviation.normalized;
|
|
102819
|
+
}
|
|
101122
102820
|
// Derive secondary tests
|
|
101123
102821
|
analyze_1.doDeriveSecondaryTests(s, bLog);
|
|
101124
102822
|
// Toggle the semaphore, so postprocessing isn't for both the testlog & scorecard
|
|
@@ -101201,13 +102899,11 @@ function makeNakedCxD(s, bLog = false) {
|
|
|
101201
102899
|
let CxD = [];
|
|
101202
102900
|
// Remove the unassigned & total dummy "districts"
|
|
101203
102901
|
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
101204
|
-
// TODO - SCORE: OH has an extra county!?!
|
|
101205
102902
|
const splits = U.deepCopy(adornedCxD[districtID].slice(1));
|
|
101206
102903
|
CxD.push(splits);
|
|
101207
102904
|
}
|
|
101208
102905
|
return CxD;
|
|
101209
102906
|
}
|
|
101210
|
-
// TODO - SCORE: Convert dict of geo props to array by district index
|
|
101211
102907
|
function makeArrayOfGeoProps(s, bLog = false) {
|
|
101212
102908
|
let geometryByDistrict = [];
|
|
101213
102909
|
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
@@ -101241,9 +102937,27 @@ function makeArrayOfDemographics(s, bLog = false) {
|
|
|
101241
102937
|
return demographicsArray;
|
|
101242
102938
|
}
|
|
101243
102939
|
// SCORE A PLAN
|
|
101244
|
-
function scorePlan(p, bLog = false) {
|
|
102940
|
+
function scorePlan(s, p, bLog = false, overridesJSON) {
|
|
101245
102941
|
let scorer = new Score.Scorer();
|
|
101246
|
-
|
|
102942
|
+
const scorecard = scorer.score(p, overridesJSON);
|
|
102943
|
+
// TODO - SCORE: Toggle: Before returning, create a dummy population deviation
|
|
102944
|
+
// test, for doHasEqualPopulations() to use later. This is preserving the old
|
|
102945
|
+
// calling sequence.
|
|
102946
|
+
let test = s.getTest(4 /* PopulationDeviation */);
|
|
102947
|
+
// TODO - SCORE: U.trim(popDev)???
|
|
102948
|
+
// Get the raw population deviation
|
|
102949
|
+
const popDev = scorecard.best.populationDeviation.raw;
|
|
102950
|
+
// Populate the test entry
|
|
102951
|
+
test['score'] = popDev;
|
|
102952
|
+
test['details'] = { 'maxDeviation': scorecard.best.populationDeviation.notes['maxDeviation'] };
|
|
102953
|
+
// Populate the N+1 summary "district" in district.statistics
|
|
102954
|
+
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
102955
|
+
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
102956
|
+
let summaryRow = s.districts.numberOfRows() - 1;
|
|
102957
|
+
totalPop[summaryRow] = p.populationProfile.targetSize;
|
|
102958
|
+
popDevPct[summaryRow] = popDev;
|
|
102959
|
+
//
|
|
102960
|
+
return scorecard;
|
|
101247
102961
|
}
|
|
101248
102962
|
exports.scorePlan = scorePlan;
|
|
101249
102963
|
|
|
@@ -101305,6 +103019,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
101305
103019
|
return result;
|
|
101306
103020
|
};
|
|
101307
103021
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
103022
|
+
const DT = __importStar(__webpack_require__(/*! @dra2020/dra-types */ "./node_modules/@dra2020/dra-types/dist/dra-types.js"));
|
|
101308
103023
|
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
101309
103024
|
// PLAN HELPERS
|
|
101310
103025
|
// Is a "neighbor" in state?
|
|
@@ -101332,7 +103047,6 @@ function getDistrict(plan, geoID) {
|
|
|
101332
103047
|
}
|
|
101333
103048
|
exports.getDistrict = getDistrict;
|
|
101334
103049
|
// WORKING WITH GEOIDS
|
|
101335
|
-
// TODO - VFEATURE
|
|
101336
103050
|
function parseGeoID(geoID) {
|
|
101337
103051
|
let bVfeature = false;
|
|
101338
103052
|
// Rewrite vfeature GEOIDs to enable lexical parsing of higher-level parts
|
|
@@ -101340,12 +103054,7 @@ function parseGeoID(geoID) {
|
|
|
101340
103054
|
// Example: vfeature_39153153ASV_0_28e0bc2c8163e5982e1da2d61e2388a8325c575e
|
|
101341
103055
|
if (geoID.indexOf('vfeature') >= 0) {
|
|
101342
103056
|
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;
|
|
103057
|
+
geoID = DT.vgeoidToGeoid(geoID);
|
|
101349
103058
|
}
|
|
101350
103059
|
const parts = {
|
|
101351
103060
|
vfeature: bVfeature,
|
|
@@ -101353,29 +103062,9 @@ function parseGeoID(geoID) {
|
|
|
101353
103062
|
county: geoID.substring(2, 5),
|
|
101354
103063
|
rest: geoID.slice(5)
|
|
101355
103064
|
};
|
|
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
103065
|
return parts;
|
|
101370
103066
|
}
|
|
101371
103067
|
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
103068
|
function isWaterOnly(geoID) {
|
|
101380
103069
|
let waterOnlySignature = 'ZZZZZZ';
|
|
101381
103070
|
if (geoID.indexOf(waterOnlySignature) >= 0)
|
|
@@ -102276,113 +103965,6 @@ function formatNumber(n) {
|
|
|
102276
103965
|
let p = S.PRECISION;
|
|
102277
103966
|
return n.toLocaleString('en-US', { minimumFractionDigits: p, maximumFractionDigits: p });
|
|
102278
103967
|
}
|
|
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
103968
|
function echoDistrictStatistics(ds) {
|
|
102387
103969
|
console.log("District Statistics:");
|
|
102388
103970
|
for (let row of ds.table) {
|
|
@@ -102493,6 +104075,17 @@ module.exports = require("assert");
|
|
|
102493
104075
|
|
|
102494
104076
|
/***/ }),
|
|
102495
104077
|
|
|
104078
|
+
/***/ "crypto":
|
|
104079
|
+
/*!*************************!*\
|
|
104080
|
+
!*** external "crypto" ***!
|
|
104081
|
+
\*************************/
|
|
104082
|
+
/*! no static exports found */
|
|
104083
|
+
/***/ (function(module, exports) {
|
|
104084
|
+
|
|
104085
|
+
module.exports = require("crypto");
|
|
104086
|
+
|
|
104087
|
+
/***/ }),
|
|
104088
|
+
|
|
102496
104089
|
/***/ "fs":
|
|
102497
104090
|
/*!*********************!*\
|
|
102498
104091
|
!*** external "fs" ***!
|