@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 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(plan) {
89273
- return score_1.scorePlan(plan);
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 notes = { 'maxDeviation': max - min };
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/scoring-defaults.json":
90406
- /*!***********************************!*\
90407
- !*** ./src/scoring-defaults.json ***!
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 scoring_defaults_json_1 = __importDefault(__webpack_require__(/*! ./scoring-defaults.json */ "./src/scoring-defaults.json"));
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
- exports.readOverrides = readOverrides;
90457
- let overrides = readOverrides();
90455
+ const overrides = readOverrides();
90458
90456
  // SETTINGS FOR PARTISAN SCORING
90459
- exports.MIN_CONTESTED = overrides ? overrides.fair.competitive.min : scoring_defaults_json_1.default.fair.competitive.min;
90460
- exports.MAX_CONTESTED = overrides ? overrides.fair.competitive.max : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.best.compact.reock.worst;
90464
- exports.REOCK_BEST = overrides ? overrides.best.compact.reock.best : scoring_defaults_json_1.default.best.compact.reock.best;
90465
- exports.POLSBY_WORST = overrides ? overrides.best.compact.polsby.worst : scoring_defaults_json_1.default.best.compact.polsby.worst;
90466
- exports.POLSBY_BEST = overrides ? overrides.best.compact.polsby.best : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.best.cohesive.county.best;
90469
- exports.COUNTY_WORST = overrides ? overrides.best.cohesive.county.worst : scoring_defaults_json_1.default.best.cohesive.county.worst;
90470
- exports.ALLOWABLE_SPLITS_MULTIPLIER = overrides ? overrides.best.cohesive.county.allowableSplitsMultiplier : scoring_defaults_json_1.default.best.cohesive.county.allowableSplitsMultiplier;
90471
- exports.DISTRICT_BEST = overrides ? overrides.best.cohesive.district.best : scoring_defaults_json_1.default.best.cohesive.district.best;
90472
- exports.DISTRICT_WORST = overrides ? overrides.best.cohesive.district.worst : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.best.equal.worst;
90475
- exports.POPDEV_BEST = overrides ? overrides.best.equal.best : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.fair.unbiased.worst;
90487
- exports.BIAS_BEST = overrides ? overrides.fair.unbiased.best : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.fair.competitive.worst;
90490
- exports.COMPETITIVE_BEST = overrides ? overrides.fair.competitive.best : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.best.compact.reock.weight;
90493
- exports.POLSBY_WEIGHT = overrides ? overrides.best.compact.polsby.weight : scoring_defaults_json_1.default.best.compact.polsby.weight;
90494
- exports.COUNTY_WEIGHT = overrides ? overrides.best.cohesive.county.weight : scoring_defaults_json_1.default.best.cohesive.county.weight;
90495
- exports.DISTRICT_WEIGHT = overrides ? overrides.best.cohesive.district.weight : scoring_defaults_json_1.default.best.cohesive.district.weight;
90496
- exports.COMPACTNESS_WEIGHT = overrides ? overrides.best.compact.weight : scoring_defaults_json_1.default.best.compact.weight;
90497
- exports.SPLITTING_WEIGHT = overrides ? overrides.best.cohesive.weight : scoring_defaults_json_1.default.best.cohesive.weight;
90498
- exports.POPDEV_WEIGHT = overrides ? overrides.best.equal.weight : scoring_defaults_json_1.default.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 : scoring_defaults_json_1.default.fair.competitive.marginal;
90502
- exports.OVERALL_WEIGHT = overrides ? overrides.fair.competitive.overall : scoring_defaults_json_1.default.fair.competitive.overall;
90503
- exports.BIAS_WEIGHT = overrides ? overrides.fair.unbiased.weight : scoring_defaults_json_1.default.fair.unbiased.weight;
90504
- exports.COMPETITIVE_WEIGHT = overrides ? overrides.fair.competitive.weight : scoring_defaults_json_1.default.fair.competitive.weight;
90505
- exports.FAIR_WEIGHT = overrides ? overrides.fair.weight : scoring_defaults_json_1.default.fair.weight;
90506
- exports.BEST_WEIGHT = overrides ? overrides.best.weight : scoring_defaults_json_1.default.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}&nbsp;</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
- /***/ "./testdata/profiles/sample-profile.json":
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
- 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]]}}");
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
- /***/ "./testdata/profiles/sample-scorecard.json":
90623
- /*!*************************************************!*\
90624
- !*** ./testdata/profiles/sample-scorecard.json ***!
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
- 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\":{}}}");
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 - Confirming that the graph includes OUT_OF_STATE neighbors
98629
- // if (U.keyExists(S.OUT_OF_STATE, this.graph._graph)) {
98630
- // console.log("Contiguity graph includes out-of-state neighbors.");
98631
- // }
98632
- // else {
98633
- // console.log("Contiguity graph does NOT include out-of-state neighbors.");
98634
- // }
98635
- // NOTE: I've pulled these out of the individual analytics to here. Eventually,
98636
- // we could want them to passed into an analytics session as data, along with
98637
- // everything else. For now, this keeps branching out of the main code.
98638
- results_1.doConfigureScales(this);
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 - DASHBOARD: Remove this mechanism. Always run everything.
98645
- let defaultSuites = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
98646
- // If the config passed in has no suites = [], use the default suites
98647
- if (U.isArrayEmpty(config['suites'])) {
98648
- config['suites'] = defaultSuites;
98649
- }
100456
+ // 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
- // this._profile = Score.sampleProfile;
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
- let contiguousTest = this.getTest(1 /* Contiguous */);
98703
- let discontiguousDistrictIDs = contiguousTest['details']['discontiguousDistricts'] || [];
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
- discontiguousDistrictFeatures.features.push(poly);
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
- return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
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 - Remove this mechanism. Always run all tests
99362
- // Get the requested suites, and only execute those tests
99363
- let requestedSuites = s.config['suites'];
99364
- // Tests in the "Legal" suite, i.e., pass/ fail constraints
99365
- if (requestedSuites.includes(0 /* Legal */)) {
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
- let popDevPct = popDevTest['score'];
100029
- let popDevNormalized = popDevTest['normalizedScore'];
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
- // TODO - SCORE: This was added for SPLITTING
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 - PARTISAN: This category is still being fleshed out.
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 - SCORE: Add a minority report
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
- let completeTest = s.getTest(0 /* Complete */);
100820
- let contiguousTest = s.getTest(1 /* Contiguous */);
100821
- let freeOfHolesTest = s.getTest(2 /* FreeOfHoles */);
100822
- let equalPopulationTest = s.getTest(3 /* EqualPopulation */);
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
- // TODO - DASHBOARD: Until we add three-state support top to bottom in
102507
+ // NOTE - Until we add three-state support top to bottom in
100825
102508
  // requirements/validations, map booleans to tri-states here.
100826
- let completeMetric = U.mapBooleanToTriState(completeTest['score']);
100827
- let contiguousMetric = U.mapBooleanToTriState(contiguousTest['score']);
100828
- let freeOfHolesMetric = U.mapBooleanToTriState(freeOfHolesTest['score']);
100829
- let equalPopulationMetric = U.mapBooleanToTriState(equalPopulationTest['score']);
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
- let checks = [completeMetric, contiguousMetric, freeOfHolesMetric, equalPopulationMetric];
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
- let unassignedFeaturesDetail = U.deepCopy(completeTest['details']['unassignedFeatures']) || [];
100838
- let emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
100839
- let discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
100840
- let embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
100841
- let populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
100842
- let deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
100843
- let xx = s.state.xx;
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
- let stateReqsDict = state_reqs_json_1.default;
100846
- let reqLinkToStateReqs = stateReqsDict[xx];
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
- // Normalize the raw scores for all the numerics tests
101110
- let testResults = U.getNumericObjectKeys(testDefns);
101111
- for (let testID of testResults) {
101112
- if (testDefns[testID]['normalize']) {
101113
- let testResult = s.getTest(testID);
101114
- let rawScore = testResult['score'];
101115
- let normalizedScore;
101116
- normalizedScore = U.normalize(rawScore, s.testScales[testID]);
101117
- testResult['normalizedScore'] = normalizedScore;
101118
- // Add the scale used to normalize the raw score to the details
101119
- testResult['details']['scale'] = s.testScales[testID].scale;
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
- return scorer.score(p);
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
- // Strip off leading 'vfeature_'
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" ***!