@dra2020/district-analytics 3.0.1 → 3.3.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 +2692 -816
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +258 -357
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/_api.d.ts +2 -1
- package/dist/src/geofeature.d.ts +2 -0
- package/dist/src/score.d.ts +1 -1
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -89264,13 +89264,24 @@ module.exports = g;
|
|
|
89264
89264
|
//
|
|
89265
89265
|
// THE NODE PACKAGE API
|
|
89266
89266
|
//
|
|
89267
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
89268
|
+
if (mod && mod.__esModule) return mod;
|
|
89269
|
+
var result = {};
|
|
89270
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
89271
|
+
result["default"] = mod;
|
|
89272
|
+
return result;
|
|
89273
|
+
};
|
|
89267
89274
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89275
|
+
const C = __importStar(__webpack_require__(/*! ./config */ "./src/config.ts"));
|
|
89268
89276
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
89269
89277
|
class Scorer {
|
|
89270
89278
|
constructor() {
|
|
89271
89279
|
}
|
|
89272
|
-
score(
|
|
89273
|
-
return score_1.scorePlan(
|
|
89280
|
+
score(profile, overridesJSON) {
|
|
89281
|
+
return score_1.scorePlan(profile, overridesJSON);
|
|
89282
|
+
}
|
|
89283
|
+
populationDeviationThreshold(bLegislative) {
|
|
89284
|
+
return C.popdevThreshold(bLegislative);
|
|
89274
89285
|
}
|
|
89275
89286
|
}
|
|
89276
89287
|
exports.Scorer = Scorer;
|
|
@@ -89300,27 +89311,33 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
89300
89311
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89301
89312
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
89302
89313
|
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
89314
|
+
const C = __importStar(__webpack_require__(/*! ./config */ "./src/config.ts"));
|
|
89303
89315
|
const normalize_1 = __webpack_require__(/*! ./normalize */ "./src/normalize.ts");
|
|
89304
89316
|
function scoreCountySplitting(rawValue, nCounties, nDistricts) {
|
|
89305
89317
|
const _normalizer = new normalize_1.Normalizer(rawValue);
|
|
89306
|
-
const
|
|
89307
|
-
|
|
89308
|
-
_normalizer.
|
|
89318
|
+
const best = C.countySplittingRange()[C.BEG];
|
|
89319
|
+
const worst = countySplitThreshold(nCounties, nDistricts);
|
|
89320
|
+
_normalizer.clip(best, worst);
|
|
89321
|
+
_normalizer.unitize(best, worst);
|
|
89309
89322
|
_normalizer.invert();
|
|
89310
89323
|
_normalizer.rescale();
|
|
89311
89324
|
return _normalizer.normalizedNum;
|
|
89312
89325
|
}
|
|
89313
89326
|
exports.scoreCountySplitting = scoreCountySplitting;
|
|
89314
89327
|
function countySplitThreshold(nCounties, nDistricts) {
|
|
89315
|
-
const
|
|
89316
|
-
const
|
|
89328
|
+
const m = C.allowableSplitsMultiplier();
|
|
89329
|
+
const worst = C.countySplittingRange()[1];
|
|
89330
|
+
const nAllowableSplits = Math.min(m * (nDistricts - 1));
|
|
89331
|
+
const threshold = ((nAllowableSplits * worst) + ((nCounties - nAllowableSplits) * 1.0)) / nCounties;
|
|
89317
89332
|
return threshold;
|
|
89318
89333
|
}
|
|
89319
89334
|
exports.countySplitThreshold = countySplitThreshold;
|
|
89320
89335
|
function scoreDistrictSplitting(rawValue) {
|
|
89321
89336
|
const _normalizer = new normalize_1.Normalizer(rawValue);
|
|
89322
|
-
|
|
89323
|
-
|
|
89337
|
+
const best = C.districtSplittingRange()[C.BEG];
|
|
89338
|
+
const worst = C.districtSplittingRange()[C.END];
|
|
89339
|
+
_normalizer.clip(best, worst);
|
|
89340
|
+
_normalizer.unitize(best, worst);
|
|
89324
89341
|
_normalizer.invert();
|
|
89325
89342
|
_normalizer.rescale();
|
|
89326
89343
|
return _normalizer.normalizedNum;
|
|
@@ -89593,7 +89610,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
89593
89610
|
};
|
|
89594
89611
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89595
89612
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
89596
|
-
const
|
|
89613
|
+
const C = __importStar(__webpack_require__(/*! ./config */ "./src/config.ts"));
|
|
89597
89614
|
const normalize_1 = __webpack_require__(/*! ./normalize */ "./src/normalize.ts");
|
|
89598
89615
|
// Migrated from district-analytics:
|
|
89599
89616
|
// Measures of compactness compare district shapes to various ideally compact
|
|
@@ -89715,8 +89732,10 @@ function calcReock(area, diameter) {
|
|
|
89715
89732
|
exports.calcReock = calcReock;
|
|
89716
89733
|
function scoreReock(rawValue) {
|
|
89717
89734
|
const _normalizer = new normalize_1.Normalizer(rawValue);
|
|
89718
|
-
|
|
89719
|
-
|
|
89735
|
+
const worst = C.reockRange()[C.BEG];
|
|
89736
|
+
const best = C.reockRange()[C.END];
|
|
89737
|
+
_normalizer.clip(worst, best);
|
|
89738
|
+
_normalizer.unitize(worst, best);
|
|
89720
89739
|
_normalizer.rescale();
|
|
89721
89740
|
return _normalizer.normalizedNum;
|
|
89722
89741
|
}
|
|
@@ -89734,12 +89753,12 @@ function doPolsbyPopper(g, bLog = false) {
|
|
|
89734
89753
|
if (districtProps) {
|
|
89735
89754
|
let a = districtProps[0 /* Area */];
|
|
89736
89755
|
let p = districtProps[1 /* Perimeter */];
|
|
89737
|
-
let
|
|
89756
|
+
let polsby = calcPolsbyPopper(a, p);
|
|
89738
89757
|
// Save each district score
|
|
89739
|
-
scores.push(
|
|
89758
|
+
scores.push(polsby);
|
|
89740
89759
|
// Echo the results by district
|
|
89741
89760
|
if (bLog)
|
|
89742
|
-
console.log("Polsby-Popper for district", districtID, "=",
|
|
89761
|
+
console.log("Polsby-Popper for district", districtID, "=", polsby);
|
|
89743
89762
|
}
|
|
89744
89763
|
else {
|
|
89745
89764
|
console.log("No shape or no geopropertes in Polsby-Popper ...");
|
|
@@ -89762,14 +89781,202 @@ function calcPolsbyPopper(area, perimeter) {
|
|
|
89762
89781
|
exports.calcPolsbyPopper = calcPolsbyPopper;
|
|
89763
89782
|
function scorePolsbyPopper(rawValue) {
|
|
89764
89783
|
const _normalizer = new normalize_1.Normalizer(rawValue);
|
|
89765
|
-
|
|
89766
|
-
|
|
89784
|
+
const worst = C.polsbyRange()[C.BEG];
|
|
89785
|
+
const best = C.polsbyRange()[C.END];
|
|
89786
|
+
_normalizer.clip(worst, best);
|
|
89787
|
+
_normalizer.unitize(worst, best);
|
|
89767
89788
|
_normalizer.rescale();
|
|
89768
89789
|
return _normalizer.normalizedNum;
|
|
89769
89790
|
}
|
|
89770
89791
|
exports.scorePolsbyPopper = scorePolsbyPopper;
|
|
89771
89792
|
|
|
89772
89793
|
|
|
89794
|
+
/***/ }),
|
|
89795
|
+
|
|
89796
|
+
/***/ "./src/config.json":
|
|
89797
|
+
/*!*************************!*\
|
|
89798
|
+
!*** ./src/config.json ***!
|
|
89799
|
+
\*************************/
|
|
89800
|
+
/*! exports provided: partisan, traditionalPrinciples, default */
|
|
89801
|
+
/***/ (function(module) {
|
|
89802
|
+
|
|
89803
|
+
module.exports = JSON.parse("{\"partisan\":{\"bias\":{\"range\":[0,0.2],\"weight\":[50,80]},\"impact\":{\"weight\":[50,0],\"threshold\":4},\"competitiveness\":{\"overall\":{\"range\":[0,0.67],\"weight\":25},\"marginal\":{\"range\":[0,0.85],\"weight\":75},\"range\":[0.45,0.55],\"distribution\":[0.25,0.75],\"weight\":[0,20]},\"weight\":[100,80]},\"traditionalPrinciples\":{\"compactness\":{\"reock\":{\"range\":[0.25,0.5],\"weight\":50},\"polsby\":{\"range\":[0.1,0.5],\"weight\":50},\"weight\":[0,50]},\"splitting\":{\"county\":{\"range\":[1,1.71],\"allowableSplitsMultiplier\":1.5,\"weight\":50},\"district\":{\"range\":[1,1.5],\"weight\":50},\"weight\":[0,50]},\"popdev\":{\"range\":[[0.0075,0.002],[0.1,-1]],\"weight\":[0,0]},\"weight\":[0,20]}}");
|
|
89804
|
+
|
|
89805
|
+
/***/ }),
|
|
89806
|
+
|
|
89807
|
+
/***/ "./src/config.ts":
|
|
89808
|
+
/*!***********************!*\
|
|
89809
|
+
!*** ./src/config.ts ***!
|
|
89810
|
+
\***********************/
|
|
89811
|
+
/*! no static exports found */
|
|
89812
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
89813
|
+
|
|
89814
|
+
"use strict";
|
|
89815
|
+
|
|
89816
|
+
//
|
|
89817
|
+
// THRESHOLDS, SCALES, AND WEIGHTS FOR SCORING MODEL
|
|
89818
|
+
//
|
|
89819
|
+
// * A layer of functions over config.json, so that they can be overridden dynamically (TODO)
|
|
89820
|
+
//
|
|
89821
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
89822
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
89823
|
+
};
|
|
89824
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89825
|
+
// Defaults
|
|
89826
|
+
const config_json_1 = __importDefault(__webpack_require__(/*! ./config.json */ "./src/config.json"));
|
|
89827
|
+
exports.BEG = 0;
|
|
89828
|
+
exports.END = 1;
|
|
89829
|
+
// PARTISAN
|
|
89830
|
+
function biasWeight(context, overridesJSON) {
|
|
89831
|
+
const bW = config_json_1.default.partisan.bias.weight[context];
|
|
89832
|
+
return bW;
|
|
89833
|
+
}
|
|
89834
|
+
exports.biasWeight = biasWeight;
|
|
89835
|
+
function biasRange(overridesJSON) {
|
|
89836
|
+
const range = config_json_1.default.partisan.bias.range;
|
|
89837
|
+
return range;
|
|
89838
|
+
}
|
|
89839
|
+
exports.biasRange = biasRange;
|
|
89840
|
+
function impactWeight(context, overridesJSON) {
|
|
89841
|
+
const iW = config_json_1.default.partisan.impact.weight[context];
|
|
89842
|
+
return iW;
|
|
89843
|
+
}
|
|
89844
|
+
exports.impactWeight = impactWeight;
|
|
89845
|
+
// The maximum # of unearned seats that scores positively
|
|
89846
|
+
function unearnedThreshold(overridesJSON) {
|
|
89847
|
+
const threshold = config_json_1.default.partisan.impact.threshold;
|
|
89848
|
+
return threshold;
|
|
89849
|
+
}
|
|
89850
|
+
exports.unearnedThreshold = unearnedThreshold;
|
|
89851
|
+
function competitivenessWeight(context, overridesJSON) {
|
|
89852
|
+
const cW = config_json_1.default.partisan.competitiveness.weight[context];
|
|
89853
|
+
return cW;
|
|
89854
|
+
}
|
|
89855
|
+
exports.competitivenessWeight = competitivenessWeight;
|
|
89856
|
+
function competitiveRange(overridesJSON) {
|
|
89857
|
+
const range = config_json_1.default.partisan.competitiveness.range;
|
|
89858
|
+
return range;
|
|
89859
|
+
}
|
|
89860
|
+
exports.competitiveRange = competitiveRange;
|
|
89861
|
+
function competitiveDistribution(overridesJSON) {
|
|
89862
|
+
const dist = config_json_1.default.partisan.competitiveness.distribution;
|
|
89863
|
+
return dist;
|
|
89864
|
+
}
|
|
89865
|
+
exports.competitiveDistribution = competitiveDistribution;
|
|
89866
|
+
function overallCompetitivenessRange(overridesJSON) {
|
|
89867
|
+
const range = config_json_1.default.partisan.competitiveness.overall.range;
|
|
89868
|
+
return range;
|
|
89869
|
+
}
|
|
89870
|
+
exports.overallCompetitivenessRange = overallCompetitivenessRange;
|
|
89871
|
+
function marginalCompetitivenessRange(overridesJSON) {
|
|
89872
|
+
const range = config_json_1.default.partisan.competitiveness.marginal.range;
|
|
89873
|
+
return range;
|
|
89874
|
+
}
|
|
89875
|
+
exports.marginalCompetitivenessRange = marginalCompetitivenessRange;
|
|
89876
|
+
function marginalCompetitivenessWeight(overridesJSON) {
|
|
89877
|
+
const mcW = config_json_1.default.partisan.competitiveness.marginal.weight;
|
|
89878
|
+
return mcW;
|
|
89879
|
+
}
|
|
89880
|
+
exports.marginalCompetitivenessWeight = marginalCompetitivenessWeight;
|
|
89881
|
+
function overallCompetitivenessWeight(overridesJSON) {
|
|
89882
|
+
const ocW = config_json_1.default.partisan.competitiveness.overall.weight;
|
|
89883
|
+
return ocW;
|
|
89884
|
+
}
|
|
89885
|
+
exports.overallCompetitivenessWeight = overallCompetitivenessWeight;
|
|
89886
|
+
// TRADITIONAL DISTRICTING PRINCIPLES
|
|
89887
|
+
function compactnessWeight(context, overridesJSON) {
|
|
89888
|
+
const cW = config_json_1.default.traditionalPrinciples.compactness.weight[context];
|
|
89889
|
+
return cW;
|
|
89890
|
+
}
|
|
89891
|
+
exports.compactnessWeight = compactnessWeight;
|
|
89892
|
+
function reockWeight(overridesJSON) {
|
|
89893
|
+
const rW = config_json_1.default.traditionalPrinciples.compactness.reock.weight;
|
|
89894
|
+
return rW;
|
|
89895
|
+
}
|
|
89896
|
+
exports.reockWeight = reockWeight;
|
|
89897
|
+
function reockRange(overridesJSON) {
|
|
89898
|
+
const range = config_json_1.default.traditionalPrinciples.compactness.reock.range;
|
|
89899
|
+
return range;
|
|
89900
|
+
}
|
|
89901
|
+
exports.reockRange = reockRange;
|
|
89902
|
+
function polsbyWeight(overridesJSON) {
|
|
89903
|
+
const ppW = config_json_1.default.traditionalPrinciples.compactness.polsby.weight;
|
|
89904
|
+
return ppW;
|
|
89905
|
+
}
|
|
89906
|
+
exports.polsbyWeight = polsbyWeight;
|
|
89907
|
+
function polsbyRange(overridesJSON) {
|
|
89908
|
+
const range = config_json_1.default.traditionalPrinciples.compactness.polsby.range;
|
|
89909
|
+
return range;
|
|
89910
|
+
}
|
|
89911
|
+
exports.polsbyRange = polsbyRange;
|
|
89912
|
+
function splittingWeight(context, overridesJSON) {
|
|
89913
|
+
const sW = config_json_1.default.traditionalPrinciples.splitting.weight[context];
|
|
89914
|
+
return sW;
|
|
89915
|
+
}
|
|
89916
|
+
exports.splittingWeight = splittingWeight;
|
|
89917
|
+
function countySplittingWeight(overridesJSON) {
|
|
89918
|
+
const csW = config_json_1.default.traditionalPrinciples.splitting.county.weight;
|
|
89919
|
+
return csW;
|
|
89920
|
+
}
|
|
89921
|
+
exports.countySplittingWeight = countySplittingWeight;
|
|
89922
|
+
function countySplittingRange(overridesJSON) {
|
|
89923
|
+
const range = config_json_1.default.traditionalPrinciples.splitting.county.range;
|
|
89924
|
+
return range;
|
|
89925
|
+
}
|
|
89926
|
+
exports.countySplittingRange = countySplittingRange;
|
|
89927
|
+
function allowableSplitsMultiplier(overridesJSON) {
|
|
89928
|
+
const m = config_json_1.default.traditionalPrinciples.splitting.county.allowableSplitsMultiplier;
|
|
89929
|
+
return m;
|
|
89930
|
+
}
|
|
89931
|
+
exports.allowableSplitsMultiplier = allowableSplitsMultiplier;
|
|
89932
|
+
function districtSplittingWeight(overridesJSON) {
|
|
89933
|
+
const dsW = config_json_1.default.traditionalPrinciples.splitting.district.weight;
|
|
89934
|
+
return dsW;
|
|
89935
|
+
}
|
|
89936
|
+
exports.districtSplittingWeight = districtSplittingWeight;
|
|
89937
|
+
function districtSplittingRange(overridesJSON) {
|
|
89938
|
+
const range = config_json_1.default.traditionalPrinciples.splitting.district.range;
|
|
89939
|
+
return range;
|
|
89940
|
+
}
|
|
89941
|
+
exports.districtSplittingRange = districtSplittingRange;
|
|
89942
|
+
function popdevWeight(context, overridesJSON) {
|
|
89943
|
+
const pdW = config_json_1.default.traditionalPrinciples.popdev.weight[context];
|
|
89944
|
+
return pdW;
|
|
89945
|
+
}
|
|
89946
|
+
exports.popdevWeight = popdevWeight;
|
|
89947
|
+
// NOTE - Raw ranges, not inverted (i.e., smaller is better)
|
|
89948
|
+
// NOTE - This could be optimized to not calc LD values for CD's (or do it once)
|
|
89949
|
+
function popdevRange(bLegislative, overridesJSON) {
|
|
89950
|
+
const cdRange = config_json_1.default.traditionalPrinciples.popdev.range[0 /* Congressional */];
|
|
89951
|
+
const worstCD = cdRange[exports.BEG];
|
|
89952
|
+
const bestCD = cdRange[exports.END];
|
|
89953
|
+
const ldRange = config_json_1.default.traditionalPrinciples.popdev.range[1 /* StateLegislative */];
|
|
89954
|
+
const iRange = bLegislative ? ldRange : cdRange;
|
|
89955
|
+
const worst = iRange[exports.BEG];
|
|
89956
|
+
const best = bLegislative ? (bestCD / worstCD) * iRange[exports.BEG] : iRange[exports.END];
|
|
89957
|
+
// Invert the range, so bigger is better.
|
|
89958
|
+
return [worst, best];
|
|
89959
|
+
}
|
|
89960
|
+
exports.popdevRange = popdevRange;
|
|
89961
|
+
// NOTE - Raw threshold, not inverted (i.e., smaller is better)
|
|
89962
|
+
function popdevThreshold(bLegislative, overridesJSON) {
|
|
89963
|
+
const threshold = popdevRange(bLegislative)[exports.BEG];
|
|
89964
|
+
return threshold;
|
|
89965
|
+
}
|
|
89966
|
+
exports.popdevThreshold = popdevThreshold;
|
|
89967
|
+
// OVERALL SCORE
|
|
89968
|
+
function partisanWeight(context, overridesJSON) {
|
|
89969
|
+
const pW = config_json_1.default.partisan.weight[context];
|
|
89970
|
+
return pW;
|
|
89971
|
+
}
|
|
89972
|
+
exports.partisanWeight = partisanWeight;
|
|
89973
|
+
function traditionalPrinciplesWeight(context, overridesJSON) {
|
|
89974
|
+
const tpW = config_json_1.default.traditionalPrinciples.weight[context];
|
|
89975
|
+
return tpW;
|
|
89976
|
+
}
|
|
89977
|
+
exports.traditionalPrinciplesWeight = traditionalPrinciplesWeight;
|
|
89978
|
+
|
|
89979
|
+
|
|
89773
89980
|
/***/ }),
|
|
89774
89981
|
|
|
89775
89982
|
/***/ "./src/equal.ts":
|
|
@@ -89793,7 +90000,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
89793
90000
|
};
|
|
89794
90001
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89795
90002
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
89796
|
-
const
|
|
90003
|
+
const C = __importStar(__webpack_require__(/*! ./config */ "./src/config.ts"));
|
|
89797
90004
|
const normalize_1 = __webpack_require__(/*! ./normalize */ "./src/normalize.ts");
|
|
89798
90005
|
// Migrated from district-analytics
|
|
89799
90006
|
// Expect a full dict of district IDs & values (which might be zero = empty)
|
|
@@ -89814,7 +90021,11 @@ function doPopulationDeviation(e, targetSize, bLegislative, bLog = false) {
|
|
|
89814
90021
|
// Round the raw value to the desired level of precision
|
|
89815
90022
|
const popDev = U.trim((max - min) / targetSize);
|
|
89816
90023
|
const score = scorePopulationDeviation(popDev, bLegislative);
|
|
89817
|
-
const
|
|
90024
|
+
const threshold = C.popdevThreshold(bLegislative);
|
|
90025
|
+
const notes = {
|
|
90026
|
+
'maxDeviation': max - min,
|
|
90027
|
+
'threshold': threshold
|
|
90028
|
+
};
|
|
89818
90029
|
// Populate the measurement
|
|
89819
90030
|
const m = {
|
|
89820
90031
|
raw: popDev,
|
|
@@ -89826,11 +90037,11 @@ function doPopulationDeviation(e, targetSize, bLegislative, bLog = false) {
|
|
|
89826
90037
|
exports.doPopulationDeviation = doPopulationDeviation;
|
|
89827
90038
|
function scorePopulationDeviation(rawValue, bLegislative) {
|
|
89828
90039
|
const _normalizer = new normalize_1.Normalizer(rawValue);
|
|
89829
|
-
|
|
89830
|
-
const
|
|
90040
|
+
// Raw range in not inverted (i.e., smaller is better)
|
|
90041
|
+
const range = C.popdevRange(bLegislative);
|
|
89831
90042
|
_normalizer.invert();
|
|
89832
|
-
_normalizer.clip(
|
|
89833
|
-
_normalizer.unitize(
|
|
90043
|
+
_normalizer.clip(1.0 - range[C.BEG], 1.0 - range[C.END]);
|
|
90044
|
+
_normalizer.unitize(1.0 - range[C.BEG], 1.0 - range[C.END]);
|
|
89834
90045
|
_normalizer.rescale();
|
|
89835
90046
|
return _normalizer.normalizedNum;
|
|
89836
90047
|
}
|
|
@@ -89839,10 +90050,129 @@ exports.scorePopulationDeviation = scorePopulationDeviation;
|
|
|
89839
90050
|
|
|
89840
90051
|
/***/ }),
|
|
89841
90052
|
|
|
89842
|
-
/***/ "./src/
|
|
89843
|
-
|
|
89844
|
-
!*** ./src/
|
|
89845
|
-
|
|
90053
|
+
/***/ "./src/index.ts":
|
|
90054
|
+
/*!**********************!*\
|
|
90055
|
+
!*** ./src/index.ts ***!
|
|
90056
|
+
\**********************/
|
|
90057
|
+
/*! no static exports found */
|
|
90058
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
90059
|
+
|
|
90060
|
+
"use strict";
|
|
90061
|
+
|
|
90062
|
+
//
|
|
90063
|
+
// SCORE PACKAGE API
|
|
90064
|
+
//
|
|
90065
|
+
function __export(m) {
|
|
90066
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
90067
|
+
}
|
|
90068
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90069
|
+
__export(__webpack_require__(/*! ./_api */ "./src/_api.ts"));
|
|
90070
|
+
var types_1 = __webpack_require__(/*! ./types */ "./src/types.ts");
|
|
90071
|
+
exports.sampleProfile = types_1.sampleProfile;
|
|
90072
|
+
exports.sampleScorecard = types_1.sampleScorecard;
|
|
90073
|
+
|
|
90074
|
+
|
|
90075
|
+
/***/ }),
|
|
90076
|
+
|
|
90077
|
+
/***/ "./src/normalize.ts":
|
|
90078
|
+
/*!**************************!*\
|
|
90079
|
+
!*** ./src/normalize.ts ***!
|
|
90080
|
+
\**************************/
|
|
90081
|
+
/*! no static exports found */
|
|
90082
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
90083
|
+
|
|
90084
|
+
"use strict";
|
|
90085
|
+
|
|
90086
|
+
//
|
|
90087
|
+
// NORMALIZATION UTILITIES
|
|
90088
|
+
//
|
|
90089
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
90090
|
+
if (mod && mod.__esModule) return mod;
|
|
90091
|
+
var result = {};
|
|
90092
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
90093
|
+
result["default"] = mod;
|
|
90094
|
+
return result;
|
|
90095
|
+
};
|
|
90096
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90097
|
+
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
90098
|
+
class Normalizer {
|
|
90099
|
+
constructor(rawValue) {
|
|
90100
|
+
this.rawNum = rawValue;
|
|
90101
|
+
this.wipNum = this.rawNum;
|
|
90102
|
+
}
|
|
90103
|
+
// *Don't* transform the input.
|
|
90104
|
+
identity() {
|
|
90105
|
+
return this.wipNum;
|
|
90106
|
+
}
|
|
90107
|
+
positive() {
|
|
90108
|
+
this.wipNum = Math.abs(this.wipNum);
|
|
90109
|
+
return this.wipNum;
|
|
90110
|
+
}
|
|
90111
|
+
// Invert a value in the unit range [0.0–1.0] (so that bigger is better).
|
|
90112
|
+
invert() {
|
|
90113
|
+
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90114
|
+
console.assert(((this.wipNum >= 0.0) && (this.wipNum <= 1.0)), "Inverting: " + S.OUT_OF_RANGE_MSG, this.wipNum);
|
|
90115
|
+
this.wipNum = 1.0 - this.wipNum;
|
|
90116
|
+
return this.wipNum;
|
|
90117
|
+
}
|
|
90118
|
+
// Constrain the value to be within a specified range.
|
|
90119
|
+
clip(begin_range, end_range) {
|
|
90120
|
+
// Handle the ends of the range being given either order
|
|
90121
|
+
const min_range = Math.min(begin_range, end_range);
|
|
90122
|
+
const max_range = Math.max(begin_range, end_range);
|
|
90123
|
+
this.wipNum = Math.max(Math.min(this.wipNum, max_range), min_range);
|
|
90124
|
+
return this.wipNum;
|
|
90125
|
+
}
|
|
90126
|
+
// Recast the value as the delta from a baseline value. NOOP if it is zero.
|
|
90127
|
+
// NOTE - Values can be + or -.
|
|
90128
|
+
rebase(base) {
|
|
90129
|
+
this.wipNum = this.wipNum - base;
|
|
90130
|
+
return this.wipNum;
|
|
90131
|
+
}
|
|
90132
|
+
// Re-scale a value into the [0.0 – 1.0] range, using a given range.
|
|
90133
|
+
// NOTE - This assumes that values have alrady been clipped into the range.
|
|
90134
|
+
unitize(begin_range, end_range) {
|
|
90135
|
+
const min_range = Math.min(begin_range, end_range);
|
|
90136
|
+
const max_range = Math.max(begin_range, end_range);
|
|
90137
|
+
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90138
|
+
console.assert(((this.wipNum >= min_range) && (this.wipNum <= max_range)), "Unitizing: " + S.OUT_OF_RANGE_MSG, this.wipNum);
|
|
90139
|
+
const ranged = this.wipNum - min_range;
|
|
90140
|
+
this.wipNum = Math.abs(ranged / (end_range - begin_range));
|
|
90141
|
+
return this.wipNum;
|
|
90142
|
+
}
|
|
90143
|
+
// Decay a value in the unit range [0.0–1.0] by its distance from zero.
|
|
90144
|
+
// NOTE - If the range is already such that "bigger is better," then the closer
|
|
90145
|
+
// the value is to 1.0 (the best) the *less* it will decay.
|
|
90146
|
+
decay(fn = 0 /* Gravity */) {
|
|
90147
|
+
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90148
|
+
console.assert(((this.wipNum >= 0.0) && (this.wipNum <= 1.0)), "Decaying: " + S.OUT_OF_RANGE_MSG, this.wipNum);
|
|
90149
|
+
switch (fn) {
|
|
90150
|
+
case 0 /* Gravity */: {
|
|
90151
|
+
this.wipNum = Math.pow(this.wipNum, S.DISTANCE_WEIGHT);
|
|
90152
|
+
return this.wipNum;
|
|
90153
|
+
}
|
|
90154
|
+
default: {
|
|
90155
|
+
throw new Error("Decay function not recognized.");
|
|
90156
|
+
}
|
|
90157
|
+
}
|
|
90158
|
+
}
|
|
90159
|
+
// Translate a value in the unit range to the user-friendly range [0 – 100].
|
|
90160
|
+
rescale() {
|
|
90161
|
+
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90162
|
+
console.assert(((this.wipNum >= 0.0) && (this.wipNum <= 1.0)), "Rescaling: " + S.OUT_OF_RANGE_MSG, this.wipNum);
|
|
90163
|
+
this.normalizedNum = Math.round(this.wipNum * S.NORMALIZED_RANGE);
|
|
90164
|
+
return this.normalizedNum;
|
|
90165
|
+
}
|
|
90166
|
+
}
|
|
90167
|
+
exports.Normalizer = Normalizer;
|
|
90168
|
+
|
|
90169
|
+
|
|
90170
|
+
/***/ }),
|
|
90171
|
+
|
|
90172
|
+
/***/ "./src/partisan.ts":
|
|
90173
|
+
/*!*************************!*\
|
|
90174
|
+
!*** ./src/partisan.ts ***!
|
|
90175
|
+
\*************************/
|
|
89846
90176
|
/*! no static exports found */
|
|
89847
90177
|
/***/ (function(module, exports, __webpack_require__) {
|
|
89848
90178
|
|
|
@@ -89861,48 +90191,61 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
89861
90191
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89862
90192
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
89863
90193
|
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
90194
|
+
const C = __importStar(__webpack_require__(/*! ./config */ "./src/config.ts"));
|
|
89864
90195
|
const normalize_1 = __webpack_require__(/*! ./normalize */ "./src/normalize.ts");
|
|
89865
90196
|
// NOTE - I'm passing T.VfArray's into everything. District indices = array indices.
|
|
89866
90197
|
// NOTE - I do not (cannot) assume that the values are sorted.
|
|
89867
90198
|
// SCORE BIAS & COMPETITIVENESS
|
|
89868
|
-
/* SCORECARD FIELDS:
|
|
90199
|
+
/* SCORECARD FIELDS <<< TODO: Update
|
|
89869
90200
|
|
|
89870
90201
|
* ^S# [BestS] = the Democratic seats closest to proportional
|
|
89871
90202
|
* ^S% [BestSf] = the corresponding Democratic seat share
|
|
89872
|
-
*
|
|
90203
|
+
* S! [FptpS] = the estimated number of Democratic seats using first past the post
|
|
89873
90204
|
* S# [ProbableS] = the estimated Democratic seats, using seat probabilities
|
|
89874
90205
|
* S% [ProbableSf] = the estimated Democratic seat share fraction, calculated as S# / N
|
|
90206
|
+
* UE# [UnearnedS] = the number of unearned seats (R = positive; D = negative)
|
|
89875
90207
|
* B% [Bias]= the bias calculated as S% – ^S%
|
|
89876
90208
|
* B$ [BiasScore] = the bias score normalized [0–100]
|
|
89877
90209
|
|
|
89878
90210
|
* R# [R] = the responsiveness at V%
|
|
89879
90211
|
* Rd [Rd] = the estimated # of responsive districts (using probabilities)
|
|
89880
90212
|
* Rd% [Rdf] = the estimated # of responsive districts, as a fraction of N
|
|
90213
|
+
|
|
90214
|
+
* C [C] = the number of districts that fall into the range [45–55%]
|
|
89881
90215
|
* Cd [Cd] = the estimated # of competitive districts, using probabilities & a narrower [0.25–0.75] range
|
|
89882
90216
|
* Cd% [Cdf] = the estimated # of competitive districts, as a fraction of N
|
|
90217
|
+
* [beg, end] [Mrange] = the 1–N indices for the first and last district that separate the likely result and the proportional result
|
|
90218
|
+
* Md [Md] = the competitiveness of the marginal districts
|
|
89883
90219
|
* Md% [Mdf] = the probability that the marginal seats will flip, so S% => ^S%
|
|
89884
90220
|
* C$ [CompetitiveScore] = the competitiveness score normalized [0–100]
|
|
89885
90221
|
|
|
89886
|
-
*
|
|
90222
|
+
* F$ = the combined partisan score normalize [0–100]
|
|
89887
90223
|
|
|
89888
90224
|
*/
|
|
89889
|
-
function scorePartisan(Vf, VfArray,
|
|
90225
|
+
function scorePartisan(Vf, VfArray, bAll = false, bConstrained = true) {
|
|
89890
90226
|
const N = VfArray.length;
|
|
89891
90227
|
const BestS = bestSeats(N, Vf);
|
|
89892
90228
|
const BestSf = bestSeatShare(BestS, N);
|
|
89893
|
-
const FptpS =
|
|
89894
|
-
const
|
|
90229
|
+
const FptpS = bAll ? estFPTPSeats(VfArray) : undefined;
|
|
90230
|
+
const range = bConstrained ? C.competitiveDistribution() : undefined;
|
|
90231
|
+
const ProbableS = estProbableSeats(VfArray, range);
|
|
89895
90232
|
const ProbableSf = estProbableSeatShare(ProbableS, N);
|
|
89896
90233
|
const Bias = estBias(ProbableSf, BestSf);
|
|
89897
|
-
const
|
|
89898
|
-
const
|
|
89899
|
-
const
|
|
89900
|
-
const
|
|
89901
|
-
const
|
|
89902
|
-
const
|
|
90234
|
+
const biasScore = scoreBias(Bias, Vf, ProbableSf, N);
|
|
90235
|
+
const UnearnedS = estUnearnedSeats(BestS, ProbableS);
|
|
90236
|
+
const impactScore = scoreImpact(UnearnedS);
|
|
90237
|
+
const bInferSV = (bAll || (!bConstrained));
|
|
90238
|
+
const inferredSVpoints = bInferSV ? inferSVpoints(Vf, VfArray, range) : undefined;
|
|
90239
|
+
const R = bInferSV ? estResponsiveness(Vf, inferredSVpoints) : undefined;
|
|
90240
|
+
const Rd = bInferSV ? estResponsiveDistricts(VfArray) : undefined;
|
|
90241
|
+
const Rdf = bInferSV ? estResponsiveDistrictsShare(Rd, N) : undefined;
|
|
90242
|
+
const Cn = countCompetitiveDistricts(VfArray);
|
|
90243
|
+
const Cd = bConstrained ? estCompetitiveDistricts(VfArray) : Rd;
|
|
89903
90244
|
const Cdf = estCompetitiveDistrictsShare(Cd, N);
|
|
89904
|
-
const
|
|
89905
|
-
const
|
|
90245
|
+
const Mrange = findMarginalDistricts(Vf, VfArray, N);
|
|
90246
|
+
const Md = estMarginalCompetitiveDistricts(Mrange, VfArray);
|
|
90247
|
+
const Mdf = estMarginalCompetitiveShare(Md, Mrange);
|
|
90248
|
+
const competitivenessScore = scoreCompetitiveness(Mdf, Cdf);
|
|
89906
90249
|
const biasScoring = {
|
|
89907
90250
|
BestS: BestS,
|
|
89908
90251
|
BestSf: BestSf,
|
|
@@ -89910,61 +90253,73 @@ function scorePartisan(Vf, VfArray, all = false) {
|
|
|
89910
90253
|
ProbableS: ProbableS,
|
|
89911
90254
|
ProbableSf: ProbableSf,
|
|
89912
90255
|
Bias: Bias,
|
|
89913
|
-
|
|
90256
|
+
score: biasScore
|
|
89914
90257
|
};
|
|
89915
|
-
|
|
89916
|
-
|
|
89917
|
-
|
|
89918
|
-
|
|
89919
|
-
|
|
89920
|
-
|
|
89921
|
-
|
|
89922
|
-
|
|
89923
|
-
|
|
89924
|
-
|
|
89925
|
-
|
|
89926
|
-
|
|
89927
|
-
|
|
89928
|
-
|
|
89929
|
-
|
|
89930
|
-
|
|
89931
|
-
|
|
89932
|
-
|
|
89933
|
-
|
|
89934
|
-
|
|
90258
|
+
const impactScoring = {
|
|
90259
|
+
UnearnedS: UnearnedS,
|
|
90260
|
+
score: impactScore
|
|
90261
|
+
};
|
|
90262
|
+
let competitiveScoring = {
|
|
90263
|
+
R: R,
|
|
90264
|
+
Rd: Rd,
|
|
90265
|
+
Rdf: Rdf,
|
|
90266
|
+
C: Cn,
|
|
90267
|
+
Cd: Cd,
|
|
90268
|
+
Cdf: Cdf,
|
|
90269
|
+
Mrange: Mrange,
|
|
90270
|
+
Md: Md,
|
|
90271
|
+
Mdf: Mdf,
|
|
90272
|
+
score: competitivenessScore
|
|
90273
|
+
};
|
|
90274
|
+
if (bAll) {
|
|
90275
|
+
competitiveScoring.R = R;
|
|
90276
|
+
competitiveScoring.Rd = Rd;
|
|
90277
|
+
competitiveScoring.Rdf = Rdf;
|
|
90278
|
+
}
|
|
90279
|
+
// Weight bias, impact, and competitiveness into partisan scores to compare
|
|
90280
|
+
// plans across states and within a state.
|
|
90281
|
+
const bS = biasScoring.score;
|
|
90282
|
+
const iS = impactScoring.score;
|
|
90283
|
+
const cS = competitiveScoring.score;
|
|
90284
|
+
const acrossStatesPartisanScore = weightPartisan(bS, iS, cS, 0 /* AcrossStates */);
|
|
90285
|
+
const withinStatesPartisanScore = weightPartisan(bS, iS, cS, 1 /* WithinAState */);
|
|
89935
90286
|
const s = {
|
|
89936
90287
|
bias: biasScoring,
|
|
89937
|
-
|
|
90288
|
+
impact: impactScoring,
|
|
90289
|
+
competitiveness: competitiveScoring,
|
|
90290
|
+
score: acrossStatesPartisanScore,
|
|
90291
|
+
score2: withinStatesPartisanScore
|
|
89938
90292
|
};
|
|
89939
90293
|
return s;
|
|
89940
90294
|
}
|
|
89941
90295
|
exports.scorePartisan = scorePartisan;
|
|
89942
|
-
function weightPartisan(
|
|
89943
|
-
|
|
90296
|
+
function weightPartisan(bS, iS, cS, context) {
|
|
90297
|
+
const bW = C.biasWeight(context);
|
|
90298
|
+
const iW = C.impactWeight(context);
|
|
90299
|
+
const cW = C.competitivenessWeight(context);
|
|
90300
|
+
const score = Math.round(((bS * bW) + (iS * iW) + (cS * cW)) / (bW + iW + cW));
|
|
90301
|
+
return score;
|
|
89944
90302
|
}
|
|
89945
90303
|
exports.weightPartisan = weightPartisan;
|
|
89946
|
-
function
|
|
89947
|
-
console.log('XX, Name, N, V%, ^S#, ^S%,
|
|
90304
|
+
function printPartisanScorecardHeader() {
|
|
90305
|
+
console.log('XX, Name, N, 1/N%, V%, ^S#, ^S%, S!, S#, S%, B%, B$, UE#, I$, R#, Rd, Rd%, C#, Cd, Cd%, beg, end, Md, Md%, C$, <P$, >P$');
|
|
89948
90306
|
}
|
|
89949
|
-
exports.
|
|
89950
|
-
function
|
|
89951
|
-
console.log('%s, %s, %i, %f, %i, %f, %i, %f, %f, %f, %i, %f, %f, %f, %f, %f, %f, %f, %i', xx, name, N, Vf, s.bias.BestS, s.bias.BestSf, s.bias.FptpS, s.bias.ProbableS, s.bias.ProbableSf, s.bias.Bias, s.bias.
|
|
90307
|
+
exports.printPartisanScorecardHeader = printPartisanScorecardHeader;
|
|
90308
|
+
function printPartisanScorecardRow(xx, name, N, Vf, s) {
|
|
90309
|
+
console.log('%s, %s, %i, %f, %f, %i, %f, %i, %f, %f, %f, %i, %f, %i, %f, %f, %f, %i, %f, %f, %i, %i, %f, %f, %i, %i, %i', xx, name, N, U.trim(1 / N), Vf, s.bias.BestS, s.bias.BestSf, s.bias.FptpS, s.bias.ProbableS, s.bias.ProbableSf, s.bias.Bias, s.bias.score, s.impact.UnearnedS, s.impact.score, s.competitiveness.R, s.competitiveness.Rd, s.competitiveness.Rdf, s.competitiveness.C, s.competitiveness.Cd, s.competitiveness.Cdf, s.competitiveness.Mrange[C.BEG], s.competitiveness.Mrange[C.END], s.competitiveness.Md, s.competitiveness.Mdf, s.competitiveness.score, s.score, s.score2);
|
|
89952
90310
|
}
|
|
89953
|
-
exports.
|
|
90311
|
+
exports.printPartisanScorecardRow = printPartisanScorecardRow;
|
|
89954
90312
|
function scoreBias(rawBias, Vf, Sf, N) {
|
|
89955
90313
|
if (isAntimajoritarian(Vf, Sf)) {
|
|
89956
90314
|
return 0;
|
|
89957
90315
|
}
|
|
89958
90316
|
else {
|
|
89959
90317
|
const _normalizer = new normalize_1.Normalizer(rawBias);
|
|
89960
|
-
const
|
|
89961
|
-
const
|
|
89962
|
-
const best = S.BIAS_BEST;
|
|
90318
|
+
const worst = C.biasRange()[C.BEG];
|
|
90319
|
+
const best = C.biasRange()[C.END];
|
|
89963
90320
|
_normalizer.clip(worst, best);
|
|
89964
90321
|
_normalizer.unitize(worst, best);
|
|
89965
90322
|
_normalizer.invert();
|
|
89966
|
-
// TODO - SCORE: Would also decaying raw values (e.g., by squaring them) be too
|
|
89967
|
-
// much with a small range (like 10% or one seat)?
|
|
89968
90323
|
// _normalizer.decay();
|
|
89969
90324
|
_normalizer.rescale();
|
|
89970
90325
|
const score = _normalizer.normalizedNum;
|
|
@@ -89972,6 +90327,20 @@ function scoreBias(rawBias, Vf, Sf, N) {
|
|
|
89972
90327
|
}
|
|
89973
90328
|
}
|
|
89974
90329
|
exports.scoreBias = scoreBias;
|
|
90330
|
+
// Normalize unearned seats
|
|
90331
|
+
function scoreImpact(rawUE) {
|
|
90332
|
+
const _normalizer = new normalize_1.Normalizer(rawUE);
|
|
90333
|
+
const worst = C.unearnedThreshold();
|
|
90334
|
+
const best = 0.0;
|
|
90335
|
+
_normalizer.positive();
|
|
90336
|
+
_normalizer.clip(worst, best);
|
|
90337
|
+
_normalizer.unitize(worst, best);
|
|
90338
|
+
_normalizer.invert();
|
|
90339
|
+
_normalizer.rescale();
|
|
90340
|
+
const score = _normalizer.normalizedNum;
|
|
90341
|
+
return score;
|
|
90342
|
+
}
|
|
90343
|
+
exports.scoreImpact = scoreImpact;
|
|
89975
90344
|
function isAntimajoritarian(Vf, Sf) {
|
|
89976
90345
|
const bDem = ((Vf < 0.5) && (Sf > 0.5)) ? true : false;
|
|
89977
90346
|
const bRep = (((1 - Vf) < 0.5) && ((1 - Sf) > 0.5)) ? true : false;
|
|
@@ -89983,16 +90352,24 @@ function scoreCompetitiveness(rawMarginal, rawOverall) {
|
|
|
89983
90352
|
// But the practical max is more like 2/3's, so unitize that range to [0.0–1.0].
|
|
89984
90353
|
// Then scale the values to [0–100].
|
|
89985
90354
|
const _overall = new normalize_1.Normalizer(rawOverall);
|
|
89986
|
-
|
|
89987
|
-
|
|
90355
|
+
let worst = C.overallCompetitivenessRange()[C.BEG];
|
|
90356
|
+
let best = C.overallCompetitivenessRange()[C.END];
|
|
90357
|
+
_overall.clip(worst, best);
|
|
90358
|
+
_overall.unitize(worst, best);
|
|
89988
90359
|
_overall.rescale();
|
|
89989
|
-
const
|
|
90360
|
+
const ocS = _overall.normalizedNum;
|
|
89990
90361
|
// Normalize marginal competitiveness
|
|
89991
90362
|
const _marginal = new normalize_1.Normalizer(rawMarginal);
|
|
90363
|
+
worst = C.marginalCompetitivenessRange()[C.BEG];
|
|
90364
|
+
best = C.marginalCompetitivenessRange()[C.END];
|
|
90365
|
+
_marginal.clip(worst, best);
|
|
90366
|
+
_marginal.unitize(worst, best);
|
|
89992
90367
|
_marginal.rescale();
|
|
89993
|
-
const
|
|
90368
|
+
const mcS = _marginal.normalizedNum;
|
|
90369
|
+
const mcW = C.marginalCompetitivenessWeight();
|
|
90370
|
+
const ocW = C.overallCompetitivenessWeight();
|
|
89994
90371
|
// Then combine the results
|
|
89995
|
-
const score = Math.round(((
|
|
90372
|
+
const score = Math.round(((mcW * mcS) + (ocW * ocS)) / (mcW + ocW));
|
|
89996
90373
|
return score;
|
|
89997
90374
|
}
|
|
89998
90375
|
exports.scoreCompetitiveness = scoreCompetitiveness;
|
|
@@ -90002,23 +90379,40 @@ const { erf } = __webpack_require__(/*! mathjs */ "./node_modules/mathjs/main/es
|
|
|
90002
90379
|
// console.log("erf(-0.5) =", erf(-0.5)); // returns -0.5204998778130465
|
|
90003
90380
|
// console.log("erf(4) =", erf(4)); // returns 0.9999999845827421
|
|
90004
90381
|
// Estimate the probability of a seat win for district, given a Vf
|
|
90005
|
-
function estSeatProbability(Vf) {
|
|
90382
|
+
function estSeatProbability(Vf, range) {
|
|
90383
|
+
if (range) {
|
|
90384
|
+
const _normalizer = new normalize_1.Normalizer(Vf);
|
|
90385
|
+
// The end points of a compressed probability distribution
|
|
90386
|
+
// NOTE - These aren't the points where races start or stop being contested,
|
|
90387
|
+
// just the end points of a distribution that yields the desired behavior
|
|
90388
|
+
// in the typical competitive range [45-55%].
|
|
90389
|
+
const distBeg = range[C.BEG];
|
|
90390
|
+
const distEnd = range[C.END];
|
|
90391
|
+
_normalizer.clip(distBeg, distEnd);
|
|
90392
|
+
_normalizer.unitize(distBeg, distEnd);
|
|
90393
|
+
return seatProbabilityFn(_normalizer.wipNum);
|
|
90394
|
+
}
|
|
90395
|
+
else {
|
|
90396
|
+
return seatProbabilityFn(Vf);
|
|
90397
|
+
}
|
|
90398
|
+
}
|
|
90399
|
+
exports.estSeatProbability = estSeatProbability;
|
|
90400
|
+
function seatProbabilityFn(Vf) {
|
|
90006
90401
|
// Python: 0.5 * (1 + erf((vpi - 0.50) / (0.02 * sqrt(8))))
|
|
90007
90402
|
return U.trim(0.5 * (1.0 + erf((Vf - 0.50) / (0.02 * Math.sqrt(8)))));
|
|
90008
90403
|
}
|
|
90009
|
-
exports.estSeatProbability = estSeatProbability;
|
|
90010
90404
|
// Estimate the number of responsive districts [R(d)], given a set of Vf's
|
|
90011
90405
|
function estDistrictResponsiveness(Vf) {
|
|
90012
90406
|
// Python: 1 - 4 * (est_seat_probability(vpi) - 0.5)**2
|
|
90013
90407
|
return U.trim(1.0 - 4.0 * Math.pow((estSeatProbability(Vf) - 0.5), 2));
|
|
90014
90408
|
}
|
|
90015
90409
|
exports.estDistrictResponsiveness = estDistrictResponsiveness;
|
|
90016
|
-
function inferSVpoints(Vf, VfArray) {
|
|
90410
|
+
function inferSVpoints(Vf, VfArray, range) {
|
|
90017
90411
|
const nDistricts = VfArray.length;
|
|
90018
90412
|
let SVpoints = [];
|
|
90019
90413
|
for (let shiftedVf of shiftRange()) {
|
|
90020
90414
|
const shiftedVPI = shiftDistricts(Vf, VfArray, shiftedVf);
|
|
90021
|
-
const shiftedSf = estProbableSeats(shiftedVPI) / nDistricts;
|
|
90415
|
+
const shiftedSf = estProbableSeats(shiftedVPI, range) / nDistricts;
|
|
90022
90416
|
SVpoints.push({ v: shiftedVf, s: shiftedSf });
|
|
90023
90417
|
}
|
|
90024
90418
|
return SVpoints;
|
|
@@ -90056,8 +90450,9 @@ function shiftRange() {
|
|
|
90056
90450
|
}
|
|
90057
90451
|
// ESTIMATE BIAS ("FAIR")
|
|
90058
90452
|
// ^S# - The # of Democratic seats closest to proportional @ statewide Vf
|
|
90453
|
+
// The "expected number of seats" from http://bit.ly/2Fcuf4q
|
|
90059
90454
|
function bestSeats(N, Vf) {
|
|
90060
|
-
return Math.round(N * Vf);
|
|
90455
|
+
return Math.round((N * Vf) - S.EPSILON);
|
|
90061
90456
|
}
|
|
90062
90457
|
exports.bestSeats = bestSeats;
|
|
90063
90458
|
// ^S% - The corresponding Democratic seat share
|
|
@@ -90066,9 +90461,9 @@ function bestSeatShare(bestS, N) {
|
|
|
90066
90461
|
}
|
|
90067
90462
|
exports.bestSeatShare = bestSeatShare;
|
|
90068
90463
|
// S# - The estimated # of Democratic seats @ statewide Vf, using seat probabilities
|
|
90069
|
-
function estProbableSeats(VfArray) {
|
|
90464
|
+
function estProbableSeats(VfArray, range) {
|
|
90070
90465
|
// Python: sum([est_seat_probability(vpi) for vpi in vpi_by_district])
|
|
90071
|
-
return U.trim(U.sumArray(VfArray.map(v => estSeatProbability(v))));
|
|
90466
|
+
return U.trim(U.sumArray(VfArray.map(v => estSeatProbability(v, range))));
|
|
90072
90467
|
}
|
|
90073
90468
|
exports.estProbableSeats = estProbableSeats;
|
|
90074
90469
|
// S% - The estimated Democratic seat share fraction @ statewide Vf
|
|
@@ -90094,6 +90489,13 @@ function estBias(estSeatShare, bestSeatShare) {
|
|
|
90094
90489
|
return U.trim(Math.abs(estSeatShare - bestSeatShare));
|
|
90095
90490
|
}
|
|
90096
90491
|
exports.estBias = estBias;
|
|
90492
|
+
// UE# - The estimated # of unearned seats
|
|
90493
|
+
// UE_# from http://bit.ly/2Fcuf4q
|
|
90494
|
+
function estUnearnedSeats(best, probable) {
|
|
90495
|
+
// NOTE - + values = unearned R seats; – values = unearned D seats
|
|
90496
|
+
return U.trim(best - probable);
|
|
90497
|
+
}
|
|
90498
|
+
exports.estUnearnedSeats = estUnearnedSeats;
|
|
90097
90499
|
// ESTIMATE RESPONSIVENESS ("COMPETITIVE")
|
|
90098
90500
|
// R# - Estimate responsiveness at the statewide vote share
|
|
90099
90501
|
function estResponsiveness(Vf, inferredSVpoints) {
|
|
@@ -90148,6 +90550,14 @@ function estResponsiveDistrictsShare(Rd, N) {
|
|
|
90148
90550
|
}
|
|
90149
90551
|
exports.estResponsiveDistrictsShare = estResponsiveDistrictsShare;
|
|
90150
90552
|
// ESTIMATE COMPETITIVENESS (ENHANCED)
|
|
90553
|
+
// C - Count the # of competitive districts, defined as v in [45–55%]
|
|
90554
|
+
function countCompetitiveDistricts(VfArray) {
|
|
90555
|
+
return U.trim(U.sumArray(VfArray.map(v => isCompetitive(v))));
|
|
90556
|
+
}
|
|
90557
|
+
exports.countCompetitiveDistricts = countCompetitiveDistricts;
|
|
90558
|
+
function isCompetitive(v) {
|
|
90559
|
+
return ((v >= C.competitiveRange()[C.BEG]) && (v <= C.competitiveRange()[C.END])) ? 1 : 0;
|
|
90560
|
+
}
|
|
90151
90561
|
// Cd - The estimated # of competitive districts
|
|
90152
90562
|
function estCompetitiveDistricts(VfArray) {
|
|
90153
90563
|
return U.trim(U.sumArray(VfArray.map(v => estDistrictCompetitiveness(v))));
|
|
@@ -90156,8 +90566,14 @@ exports.estCompetitiveDistricts = estCompetitiveDistricts;
|
|
|
90156
90566
|
// Re-scale a Democratic vote share to the competitive range (e.g., 45–55%).
|
|
90157
90567
|
function estDistrictCompetitiveness(Vf) {
|
|
90158
90568
|
const _normalizer = new normalize_1.Normalizer(Vf);
|
|
90159
|
-
|
|
90160
|
-
|
|
90569
|
+
// The end points of a compressed probability distribution
|
|
90570
|
+
// NOTE - These aren't the points where races start or stop being contested,
|
|
90571
|
+
// just the end points of a distribution that yields the desired behavior
|
|
90572
|
+
// in the typical competitive range [45-55%].
|
|
90573
|
+
const distBeg = C.competitiveDistribution()[C.BEG];
|
|
90574
|
+
const distEnd = C.competitiveDistribution()[C.END];
|
|
90575
|
+
_normalizer.clip(distBeg, distEnd);
|
|
90576
|
+
_normalizer.unitize(distBeg, distEnd);
|
|
90161
90577
|
const dC = estDistrictResponsiveness(_normalizer.wipNum);
|
|
90162
90578
|
return dC;
|
|
90163
90579
|
}
|
|
@@ -90167,9 +90583,30 @@ function estCompetitiveDistrictsShare(Cd, N) {
|
|
|
90167
90583
|
return U.trim(Cd / N);
|
|
90168
90584
|
}
|
|
90169
90585
|
exports.estCompetitiveDistrictsShare = estCompetitiveDistrictsShare;
|
|
90586
|
+
// Md - The estimated # of "marginal" districts in and around the likely FPTP
|
|
90587
|
+
// seats & the best seat split that are competitive.
|
|
90588
|
+
function estMarginalCompetitiveDistricts(Mrange, VfArray) {
|
|
90589
|
+
const minId = Mrange[C.BEG];
|
|
90590
|
+
const maxId = Mrange[C.END];
|
|
90591
|
+
// Sort the array values, and subset it to those districts
|
|
90592
|
+
// NOTE - I'm *not* keeping track of the district indexes right now
|
|
90593
|
+
let subsetVfArray = VfArray.sort().slice(minId - 1, maxId);
|
|
90594
|
+
// Est. competitive districts on that array
|
|
90595
|
+
const Md = U.sumArray(subsetVfArray.map(v => estDistrictCompetitiveness(v)));
|
|
90596
|
+
return U.trim(Md);
|
|
90597
|
+
}
|
|
90598
|
+
exports.estMarginalCompetitiveDistricts = estMarginalCompetitiveDistricts;
|
|
90170
90599
|
// Md% - The estimated competitiveness of the "marginal" districts in and around
|
|
90171
90600
|
// the likely FPTP seats & the best seat split as a fraction
|
|
90172
|
-
function estMarginalCompetitiveShare(
|
|
90601
|
+
function estMarginalCompetitiveShare(Md, Mrange) {
|
|
90602
|
+
const minId = Mrange[C.BEG];
|
|
90603
|
+
const maxId = Mrange[C.END];
|
|
90604
|
+
// Est. competitive district share on that result
|
|
90605
|
+
const MdShare = U.trim(estCompetitiveDistrictsShare(Md, maxId - minId + 1));
|
|
90606
|
+
return U.trim(MdShare);
|
|
90607
|
+
}
|
|
90608
|
+
exports.estMarginalCompetitiveShare = estMarginalCompetitiveShare;
|
|
90609
|
+
function findMarginalDistricts(Vf, VfArray, N) {
|
|
90173
90610
|
const bestS = bestSeats(N, Vf);
|
|
90174
90611
|
const fptpS = estFPTPSeats(VfArray);
|
|
90175
90612
|
// Find the marginal districts IDs (indexed 1–N)
|
|
@@ -90188,24 +90625,16 @@ function estMarginalCompetitiveShare(Vf, VfArray, N) {
|
|
|
90188
90625
|
minId = Math.max((N - bestS) - 1, 1);
|
|
90189
90626
|
maxId = Math.min((N - bestS) + 1, N);
|
|
90190
90627
|
}
|
|
90191
|
-
|
|
90192
|
-
// Sort the array values, and subset it to those districts
|
|
90193
|
-
// NOTE - I'm *not* keeping track of the district indexes right now
|
|
90194
|
-
let subsetVfArray = VfArray.sort().slice(minId - 1, maxId);
|
|
90195
|
-
// Est. competitive districts on that array
|
|
90196
|
-
const Md = U.sumArray(subsetVfArray.map(v => estDistrictCompetitiveness(v)));
|
|
90197
|
-
// Est. competitive district share on that result
|
|
90198
|
-
const MdShare = U.trim(estCompetitiveDistrictsShare(Md, deltaS));
|
|
90199
|
-
return U.trim(MdShare);
|
|
90628
|
+
return [minId, maxId];
|
|
90200
90629
|
}
|
|
90201
|
-
exports.
|
|
90630
|
+
exports.findMarginalDistricts = findMarginalDistricts;
|
|
90202
90631
|
|
|
90203
90632
|
|
|
90204
90633
|
/***/ }),
|
|
90205
90634
|
|
|
90206
|
-
/***/ "./src/
|
|
90635
|
+
/***/ "./src/score.ts":
|
|
90207
90636
|
/*!**********************!*\
|
|
90208
|
-
!*** ./src/
|
|
90637
|
+
!*** ./src/score.ts ***!
|
|
90209
90638
|
\**********************/
|
|
90210
90639
|
/*! no static exports found */
|
|
90211
90640
|
/***/ (function(module, exports, __webpack_require__) {
|
|
@@ -90213,148 +90642,29 @@ exports.estMarginalCompetitiveShare = estMarginalCompetitiveShare;
|
|
|
90213
90642
|
"use strict";
|
|
90214
90643
|
|
|
90215
90644
|
//
|
|
90216
|
-
//
|
|
90645
|
+
// OVERALL SCORING FRAMEWORK
|
|
90217
90646
|
//
|
|
90218
|
-
function
|
|
90219
|
-
|
|
90220
|
-
}
|
|
90647
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
90648
|
+
if (mod && mod.__esModule) return mod;
|
|
90649
|
+
var result = {};
|
|
90650
|
+
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
90651
|
+
result["default"] = mod;
|
|
90652
|
+
return result;
|
|
90653
|
+
};
|
|
90221
90654
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90222
|
-
|
|
90223
|
-
|
|
90224
|
-
exports.sampleProfile = types_1.sampleProfile;
|
|
90225
|
-
exports.sampleScorecard = types_1.sampleScorecard;
|
|
90226
|
-
|
|
90227
|
-
|
|
90228
|
-
/***/ }),
|
|
90229
|
-
|
|
90230
|
-
/***/ "./src/normalize.ts":
|
|
90231
|
-
/*!**************************!*\
|
|
90232
|
-
!*** ./src/normalize.ts ***!
|
|
90233
|
-
\**************************/
|
|
90234
|
-
/*! no static exports found */
|
|
90235
|
-
/***/ (function(module, exports, __webpack_require__) {
|
|
90236
|
-
|
|
90237
|
-
"use strict";
|
|
90238
|
-
|
|
90239
|
-
//
|
|
90240
|
-
// NORMALIZATION UTILITIES
|
|
90241
|
-
//
|
|
90242
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
90243
|
-
if (mod && mod.__esModule) return mod;
|
|
90244
|
-
var result = {};
|
|
90245
|
-
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
90246
|
-
result["default"] = mod;
|
|
90247
|
-
return result;
|
|
90248
|
-
};
|
|
90249
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90250
|
-
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
90251
|
-
class Normalizer {
|
|
90252
|
-
constructor(rawValue) {
|
|
90253
|
-
this.rawNum = rawValue;
|
|
90254
|
-
this.wipNum = this.rawNum;
|
|
90255
|
-
}
|
|
90256
|
-
// *Don't* transform the input.
|
|
90257
|
-
identity() {
|
|
90258
|
-
return this.wipNum;
|
|
90259
|
-
}
|
|
90260
|
-
// TODO - Do I need this? If so, add TEST cases.
|
|
90261
|
-
positive() {
|
|
90262
|
-
this.wipNum = Math.abs(this.wipNum);
|
|
90263
|
-
return this.wipNum;
|
|
90264
|
-
}
|
|
90265
|
-
// Invert a value in the unit range [0.0–1.0] (so that bigger is better).
|
|
90266
|
-
invert() {
|
|
90267
|
-
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90268
|
-
console.assert(((this.wipNum >= 0.0) && (this.wipNum <= 1.0)), S.OUT_OF_RANGE_MSG);
|
|
90269
|
-
this.wipNum = 1.0 - this.wipNum;
|
|
90270
|
-
return this.wipNum;
|
|
90271
|
-
}
|
|
90272
|
-
// Constrain the value to be within a specified range.
|
|
90273
|
-
clip(begin_range, end_range) {
|
|
90274
|
-
// Handle the ends of the range being given either order
|
|
90275
|
-
const min_range = Math.min(begin_range, end_range);
|
|
90276
|
-
const max_range = Math.max(begin_range, end_range);
|
|
90277
|
-
this.wipNum = Math.max(Math.min(this.wipNum, max_range), min_range);
|
|
90278
|
-
return this.wipNum;
|
|
90279
|
-
}
|
|
90280
|
-
// Recast the value as the delta from a baseline value. NOOP if it is zero.
|
|
90281
|
-
// NOTE - Values can be + or -.
|
|
90282
|
-
rebase(base) {
|
|
90283
|
-
this.wipNum = this.wipNum - base;
|
|
90284
|
-
return this.wipNum;
|
|
90285
|
-
}
|
|
90286
|
-
// Re-scale a value into the [0.0 – 1.0] range, using a given range.
|
|
90287
|
-
// NOTE - This assumes that values have alrady been clipped into the range.
|
|
90288
|
-
unitize(begin_range, end_range) {
|
|
90289
|
-
const min_range = Math.min(begin_range, end_range);
|
|
90290
|
-
const max_range = Math.max(begin_range, end_range);
|
|
90291
|
-
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90292
|
-
console.assert(((this.wipNum >= min_range) && (this.wipNum <= max_range)), S.OUT_OF_RANGE_MSG);
|
|
90293
|
-
const ranged = this.wipNum - min_range;
|
|
90294
|
-
this.wipNum = Math.abs(ranged / (end_range - begin_range));
|
|
90295
|
-
return this.wipNum;
|
|
90296
|
-
}
|
|
90297
|
-
// Decay a value in the unit range [0.0–1.0] by its distance from zero.
|
|
90298
|
-
// NOTE - If the range is already such that "bigger is better," then the closer
|
|
90299
|
-
// the value is to 1.0 (the best) the *less* it will decay.
|
|
90300
|
-
decay(fn = 0 /* Gravity */) {
|
|
90301
|
-
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90302
|
-
console.assert(((this.wipNum >= 0.0) && (this.wipNum <= 1.0)), S.OUT_OF_RANGE_MSG);
|
|
90303
|
-
switch (fn) {
|
|
90304
|
-
case 0 /* Gravity */: {
|
|
90305
|
-
this.wipNum = Math.pow(this.wipNum, S.DISTANCE_WEIGHT);
|
|
90306
|
-
return this.wipNum;
|
|
90307
|
-
}
|
|
90308
|
-
default: {
|
|
90309
|
-
throw new Error("Decay function not recognized.");
|
|
90310
|
-
}
|
|
90311
|
-
}
|
|
90312
|
-
}
|
|
90313
|
-
// Translate a value in the unit range to the user-friendly range [0 – 100].
|
|
90314
|
-
rescale() {
|
|
90315
|
-
// TODO - DAVID: Can we make this throw an Error and expect that in unit test?
|
|
90316
|
-
console.assert(((this.wipNum >= 0.0) && (this.wipNum <= 1.0)), S.OUT_OF_RANGE_MSG);
|
|
90317
|
-
this.normalizedNum = Math.round(this.wipNum * S.NORMALIZED_RANGE);
|
|
90318
|
-
return this.normalizedNum;
|
|
90319
|
-
}
|
|
90320
|
-
}
|
|
90321
|
-
exports.Normalizer = Normalizer;
|
|
90322
|
-
|
|
90323
|
-
|
|
90324
|
-
/***/ }),
|
|
90325
|
-
|
|
90326
|
-
/***/ "./src/score.ts":
|
|
90327
|
-
/*!**********************!*\
|
|
90328
|
-
!*** ./src/score.ts ***!
|
|
90329
|
-
\**********************/
|
|
90330
|
-
/*! no static exports found */
|
|
90331
|
-
/***/ (function(module, exports, __webpack_require__) {
|
|
90332
|
-
|
|
90333
|
-
"use strict";
|
|
90334
|
-
|
|
90335
|
-
//
|
|
90336
|
-
// OVERALL SCORING FRAMEWORK
|
|
90337
|
-
//
|
|
90338
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
90339
|
-
if (mod && mod.__esModule) return mod;
|
|
90340
|
-
var result = {};
|
|
90341
|
-
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
90342
|
-
result["default"] = mod;
|
|
90343
|
-
return result;
|
|
90344
|
-
};
|
|
90345
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90346
|
-
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
90655
|
+
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
90656
|
+
const C = __importStar(__webpack_require__(/*! ./config */ "./src/config.ts"));
|
|
90347
90657
|
const compact_1 = __webpack_require__(/*! ./compact */ "./src/compact.ts");
|
|
90348
90658
|
const cohesive_1 = __webpack_require__(/*! ./cohesive */ "./src/cohesive.ts");
|
|
90349
90659
|
const equal_1 = __webpack_require__(/*! ./equal */ "./src/equal.ts");
|
|
90350
|
-
const
|
|
90660
|
+
const partisan_1 = __webpack_require__(/*! ./partisan */ "./src/partisan.ts");
|
|
90351
90661
|
// TODO - Score opportunity for minority representation
|
|
90352
|
-
function scorePlan(p) {
|
|
90353
|
-
//
|
|
90662
|
+
function scorePlan(p, overridesJSON) {
|
|
90663
|
+
// TRADITIONAL DISTRICTING PRINCIPLES ("best") subcategories - compactness, splitting, population deviation
|
|
90354
90664
|
// Compactness
|
|
90355
90665
|
const reockM = compact_1.doReock(p.compactnessProfile.GeometryByDistrict);
|
|
90356
90666
|
const polsbyM = compact_1.doPolsbyPopper(p.compactnessProfile.GeometryByDistrict);
|
|
90357
|
-
const compactnessScore =
|
|
90667
|
+
const compactnessScore = weightCompactness(reockM.normalized, polsbyM.normalized);
|
|
90358
90668
|
const cS = {
|
|
90359
90669
|
score: compactnessScore,
|
|
90360
90670
|
reock: reockM,
|
|
@@ -90366,51 +90676,77 @@ function scorePlan(p) {
|
|
|
90366
90676
|
const cT = cohesive_1.totalCounties(CxD);
|
|
90367
90677
|
const countyM = cohesive_1.doCountySplittingReduced(CxD, dT, cT);
|
|
90368
90678
|
const districtM = cohesive_1.doDistrictSplittingReduced(CxD, dT, cT);
|
|
90369
|
-
const splittingScore =
|
|
90679
|
+
const splittingScore = weightSplitting(countyM.normalized, districtM.normalized);
|
|
90370
90680
|
const sS = {
|
|
90371
90681
|
score: splittingScore,
|
|
90372
90682
|
county: countyM,
|
|
90373
90683
|
district: districtM
|
|
90374
90684
|
};
|
|
90375
90685
|
// Population deviation
|
|
90376
|
-
const
|
|
90377
|
-
// Combine
|
|
90378
|
-
const
|
|
90379
|
-
// Populate the "best" scorecard
|
|
90380
|
-
const
|
|
90381
|
-
|
|
90686
|
+
const pdS = equal_1.doPopulationDeviation(p.populationProfile.TotalPopByDistrict, p.populationProfile.targetSize, p.legislativeDistricts);
|
|
90687
|
+
// Combine traditional principles into a score to compare plans w/in a state
|
|
90688
|
+
const tpScore = weightTradtionalPrinciples(cS.score, sS.score, pdS.normalized, 1 /* WithinAState */);
|
|
90689
|
+
// Populate the "best" traditional principles scorecard
|
|
90690
|
+
const tpS = {
|
|
90691
|
+
score: tpScore,
|
|
90382
90692
|
compactness: cS,
|
|
90383
90693
|
splitting: sS,
|
|
90384
|
-
populationDeviation:
|
|
90694
|
+
populationDeviation: pdS
|
|
90385
90695
|
};
|
|
90386
|
-
//
|
|
90387
|
-
|
|
90388
|
-
|
|
90389
|
-
|
|
90390
|
-
|
|
90391
|
-
const score = Math.round(((S.FAIR_WEIGHT * pS.score) + (S.BEST_WEIGHT * bS.BestScore)) / (S.FAIR_WEIGHT + S.BEST_WEIGHT));
|
|
90696
|
+
// PARTISAN ("fair") subcategories - bias, impact, & competitiveness (plus lots of supporting measures)
|
|
90697
|
+
const pS = partisan_1.scorePartisan(p.partisanProfile.statewideVf, p.partisanProfile.VfArray);
|
|
90698
|
+
// Combine the partisan/partisan & traditional principles/best scores into an overall
|
|
90699
|
+
// score for comparing plans w/in a state
|
|
90700
|
+
const score = weightBestFair(pS.score2, tpS.score, 1 /* WithinAState */);
|
|
90392
90701
|
// Roll up an overall scorecard
|
|
90393
90702
|
const scorecard = {
|
|
90394
|
-
|
|
90395
|
-
|
|
90396
|
-
|
|
90703
|
+
partisan: pS,
|
|
90704
|
+
traditionalPrinciples: tpS,
|
|
90705
|
+
score: score
|
|
90397
90706
|
};
|
|
90398
90707
|
return scorecard;
|
|
90399
90708
|
}
|
|
90400
90709
|
exports.scorePlan = scorePlan;
|
|
90710
|
+
// HELPERS
|
|
90711
|
+
function weightCompactness(rS, ppS) {
|
|
90712
|
+
const rW = C.reockWeight();
|
|
90713
|
+
const ppW = C.polsbyWeight();
|
|
90714
|
+
const score = Math.round(((rS * rW) + (ppS * ppW)) / (rW + ppW));
|
|
90715
|
+
return score;
|
|
90716
|
+
}
|
|
90717
|
+
exports.weightCompactness = weightCompactness;
|
|
90718
|
+
function weightSplitting(csS, dsS) {
|
|
90719
|
+
const csW = C.countySplittingWeight();
|
|
90720
|
+
const dsW = C.districtSplittingWeight();
|
|
90721
|
+
const score = Math.round(((csS * csW) + (dsS * dsW)) / (csW + dsW));
|
|
90722
|
+
return score;
|
|
90723
|
+
}
|
|
90724
|
+
exports.weightSplitting = weightSplitting;
|
|
90725
|
+
function weightTradtionalPrinciples(cS, sS, pdS, context) {
|
|
90726
|
+
const cW = C.compactnessWeight(context);
|
|
90727
|
+
const sW = C.splittingWeight(context);
|
|
90728
|
+
const pdW = C.popdevWeight(context);
|
|
90729
|
+
const score = Math.round(((cS * cW) + (sS * sW) + (pdS * pdW)) / (cW + sW + pdW));
|
|
90730
|
+
return score;
|
|
90731
|
+
}
|
|
90732
|
+
exports.weightTradtionalPrinciples = weightTradtionalPrinciples;
|
|
90733
|
+
function weightBestFair(pS, tpS, context) {
|
|
90734
|
+
const pW = C.partisanWeight(context);
|
|
90735
|
+
const tpW = C.traditionalPrinciplesWeight(context);
|
|
90736
|
+
const score = Math.round(((pS * pW) + (tpS * tpW)) / (pW + tpW));
|
|
90737
|
+
return score;
|
|
90738
|
+
}
|
|
90739
|
+
exports.weightBestFair = weightBestFair;
|
|
90740
|
+
function printScorecardHeader() {
|
|
90741
|
+
console.log('XX, Name, N, V%, ^S#, S#, B%, B$, UE#, I$, C#, Cd, Md, C$, <P$, >P$, Rc, Rc$, Pc, Pc$, G$, Cs, Cs$, Ds, Ds$, S$, Eq, Eq$, T$, $$$');
|
|
90742
|
+
}
|
|
90743
|
+
exports.printScorecardHeader = printScorecardHeader;
|
|
90744
|
+
function printScorecardRow(xx, name, N, Vf, s) {
|
|
90745
|
+
console.log('%s, %s, %i, %f, %i, %f, %f, %i, %f, %i, %i, %f, %f, %i, %i, %i, %f, %i, %f, %i, %i, %f, %i, %f, %i, %i, %f, %i, %i, %i', xx, name, N, U.trim(Vf), s.partisan.bias.BestS, s.partisan.bias.ProbableS, s.partisan.bias.Bias, s.partisan.bias.score, s.partisan.impact.UnearnedS, s.partisan.impact.score, s.partisan.competitiveness.C, s.partisan.competitiveness.Cd, s.partisan.competitiveness.Md, s.partisan.competitiveness.score, s.partisan.score, s.partisan.score2, s.traditionalPrinciples.compactness.reock.raw, s.traditionalPrinciples.compactness.reock.normalized, s.traditionalPrinciples.compactness.polsby.raw, s.traditionalPrinciples.compactness.polsby.normalized, s.traditionalPrinciples.compactness.score, s.traditionalPrinciples.splitting.county.raw, s.traditionalPrinciples.splitting.county.normalized, s.traditionalPrinciples.splitting.district.raw, s.traditionalPrinciples.splitting.district.normalized, s.traditionalPrinciples.splitting.score, s.traditionalPrinciples.populationDeviation.raw, s.traditionalPrinciples.populationDeviation.normalized, s.traditionalPrinciples.score, s.score);
|
|
90746
|
+
}
|
|
90747
|
+
exports.printScorecardRow = printScorecardRow;
|
|
90401
90748
|
|
|
90402
90749
|
|
|
90403
|
-
/***/ }),
|
|
90404
|
-
|
|
90405
|
-
/***/ "./src/scoring-defaults.json":
|
|
90406
|
-
/*!***********************************!*\
|
|
90407
|
-
!*** ./src/scoring-defaults.json ***!
|
|
90408
|
-
\***********************************/
|
|
90409
|
-
/*! exports provided: fair, best, default */
|
|
90410
|
-
/***/ (function(module) {
|
|
90411
|
-
|
|
90412
|
-
module.exports = JSON.parse("{\"fair\":{\"unbiased\":{\"worst\":0.1,\"best\":0,\"weight\":80},\"competitive\":{\"worst\":0,\"best\":0.67,\"weight\":20,\"min\":0.25,\"max\":0.75,\"marginal\":75,\"overall\":25},\"weight\":80},\"best\":{\"compact\":{\"reock\":{\"worst\":0.25,\"best\":0.5,\"weight\":50},\"polsby\":{\"worst\":0.1,\"best\":0.5,\"weight\":50},\"weight\":50},\"cohesive\":{\"county\":{\"best\":1,\"worst\":1.71,\"allowableSplitsMultiplier\":1.5,\"weight\":50},\"district\":{\"best\":1,\"worst\":1.5,\"weight\":50},\"weight\":50},\"equal\":{\"worst\":0.0075,\"best\":0.002,\"stateLeg\":{\"worst\":0.1},\"weight\":0},\"weight\":20}}");
|
|
90413
|
-
|
|
90414
90750
|
/***/ }),
|
|
90415
90751
|
|
|
90416
90752
|
/***/ "./src/settings.ts":
|
|
@@ -90425,16 +90761,13 @@ module.exports = JSON.parse("{\"fair\":{\"unbiased\":{\"worst\":0.1,\"best\":0,\
|
|
|
90425
90761
|
//
|
|
90426
90762
|
// GLOBAL CONSTANTS
|
|
90427
90763
|
//
|
|
90428
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
90429
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
90430
|
-
};
|
|
90431
90764
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90432
90765
|
// Normalized scores [0-100]
|
|
90433
90766
|
exports.NORMALIZED_RANGE = 100;
|
|
90434
90767
|
// Square deviations from the ideal
|
|
90435
90768
|
exports.DISTANCE_WEIGHT = 2;
|
|
90436
90769
|
// Out of range message
|
|
90437
|
-
exports.OUT_OF_RANGE_MSG = "
|
|
90770
|
+
exports.OUT_OF_RANGE_MSG = "%f out of range";
|
|
90438
90771
|
// A small delta to use when testing ranges of values
|
|
90439
90772
|
exports.EPSILON = 1 / Math.pow(10, 6);
|
|
90440
90773
|
// Keep 4 decimals for fractions [0.0–1.0], i.e., 2 for %'s [0–100]
|
|
@@ -90442,68 +90775,6 @@ exports.PRECISION = 4;
|
|
|
90442
90775
|
// "Roughly equal" = average census block size / 2
|
|
90443
90776
|
exports.AVERAGE_BLOCK_SIZE = 30;
|
|
90444
90777
|
exports.EQUAL_TOLERANCE = exports.AVERAGE_BLOCK_SIZE / 2;
|
|
90445
|
-
// SCORING PARAMETERS
|
|
90446
|
-
const scoring_defaults_json_1 = __importDefault(__webpack_require__(/*! ./scoring-defaults.json */ "./src/scoring-defaults.json"));
|
|
90447
|
-
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
|
-
return undefined;
|
|
90455
|
-
}
|
|
90456
|
-
exports.readOverrides = readOverrides;
|
|
90457
|
-
let overrides = readOverrides();
|
|
90458
|
-
// 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;
|
|
90461
|
-
// SCALES FOR NORMALIZING RAW VALUES
|
|
90462
|
-
// 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;
|
|
90467
|
-
// 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;
|
|
90473
|
-
// 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;
|
|
90476
|
-
exports.POPEQ_MIN = 1.0 - exports.POPDEV_WORST;
|
|
90477
|
-
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;
|
|
90479
|
-
exports.POPDEV_BEST_LD = ((exports.POPDEV_BEST / exports.POPDEV_WORST) * exports.POPDEV_WORST_LD);
|
|
90480
|
-
exports.POPEQ_MIN_LD = 1.0 - exports.POPDEV_WORST_LD;
|
|
90481
|
-
exports.POPEQ_MAX_LD = 1.0 - exports.POPDEV_BEST_LD;
|
|
90482
|
-
// Bias & competitiveness scales
|
|
90483
|
-
// TODO - SCORE:
|
|
90484
|
-
// * How wide a range do we want for bias? 10%? 20%?
|
|
90485
|
-
// * 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;
|
|
90488
|
-
// 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;
|
|
90491
|
-
// 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;
|
|
90499
|
-
// TODO - SCORE: What kind of relative weighting do we want between marginal and
|
|
90500
|
-
// 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;
|
|
90507
90778
|
|
|
90508
90779
|
|
|
90509
90780
|
/***/ }),
|
|
@@ -90524,9 +90795,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
90524
90795
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
90525
90796
|
};
|
|
90526
90797
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
90527
|
-
const sample_profile_json_1 = __importDefault(__webpack_require__(/*! ../testdata/
|
|
90798
|
+
const sample_profile_json_1 = __importDefault(__webpack_require__(/*! ../testdata/samples/sample-profile.json */ "./testdata/samples/sample-profile.json"));
|
|
90528
90799
|
exports.sampleProfile = sample_profile_json_1.default;
|
|
90529
|
-
const sample_scorecard_json_1 = __importDefault(__webpack_require__(/*! ../testdata/
|
|
90800
|
+
const sample_scorecard_json_1 = __importDefault(__webpack_require__(/*! ../testdata/samples/sample-scorecard.json */ "./testdata/samples/sample-scorecard.json"));
|
|
90530
90801
|
exports.sampleScorecard = sample_scorecard_json_1.default;
|
|
90531
90802
|
|
|
90532
90803
|
|
|
@@ -90603,35 +90874,1846 @@ function deepCopy(src) {
|
|
|
90603
90874
|
else
|
|
90604
90875
|
return src;
|
|
90605
90876
|
}
|
|
90606
|
-
exports.deepCopy = deepCopy;
|
|
90877
|
+
exports.deepCopy = deepCopy;
|
|
90878
|
+
|
|
90879
|
+
|
|
90880
|
+
/***/ }),
|
|
90881
|
+
|
|
90882
|
+
/***/ "./testdata/samples/sample-profile.json":
|
|
90883
|
+
/*!**********************************************!*\
|
|
90884
|
+
!*** ./testdata/samples/sample-profile.json ***!
|
|
90885
|
+
\**********************************************/
|
|
90886
|
+
/*! exports provided: state, planName, nDistricts, nCounties, legislativeDistricts, populationProfile, compactnessProfile, splittingProfile, partisanProfile, demographicProfile, default */
|
|
90887
|
+
/***/ (function(module) {
|
|
90888
|
+
|
|
90889
|
+
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]]}}");
|
|
90890
|
+
|
|
90891
|
+
/***/ }),
|
|
90892
|
+
|
|
90893
|
+
/***/ "./testdata/samples/sample-scorecard.json":
|
|
90894
|
+
/*!************************************************!*\
|
|
90895
|
+
!*** ./testdata/samples/sample-scorecard.json ***!
|
|
90896
|
+
\************************************************/
|
|
90897
|
+
/*! exports provided: score, traditionalPrinciples, partisan, default */
|
|
90898
|
+
/***/ (function(module) {
|
|
90899
|
+
|
|
90900
|
+
module.exports = JSON.parse("{\"score\":5,\"traditionalPrinciples\":{\"score\":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}}},\"partisan\":{\"bias\":{\"BestS\":7,\"BestSf\":0.5385,\"ProbableS\":4.1925,\"ProbableSf\":0.3225,\"Bias\":0.216,\"score\":0},\"impact\":{\"UnearnedS\":2.8075,\"score\":0},\"competitiveness\":{\"C\":6,\"Cd\":0.7266,\"Cdf\":0.0559,\"Mrange\":[5,11],\"Md\":0.7134,\"Mdf\":0.1019,\"score\":10},\"score\":3,\"score2\":2}}");
|
|
90901
|
+
|
|
90902
|
+
/***/ })
|
|
90903
|
+
|
|
90904
|
+
/******/ });
|
|
90905
|
+
});
|
|
90906
|
+
|
|
90907
|
+
|
|
90908
|
+
/***/ }),
|
|
90909
|
+
|
|
90910
|
+
/***/ "./node_modules/@dra2020/dra-types/dist/dra-types.js":
|
|
90911
|
+
/*!***********************************************************!*\
|
|
90912
|
+
!*** ./node_modules/@dra2020/dra-types/dist/dra-types.js ***!
|
|
90913
|
+
\***********************************************************/
|
|
90914
|
+
/*! no static exports found */
|
|
90915
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
90916
|
+
|
|
90917
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
90918
|
+
if(true)
|
|
90919
|
+
module.exports = factory();
|
|
90920
|
+
else {}
|
|
90921
|
+
})(global, function() {
|
|
90922
|
+
return /******/ (function(modules) { // webpackBootstrap
|
|
90923
|
+
/******/ // The module cache
|
|
90924
|
+
/******/ var installedModules = {};
|
|
90925
|
+
/******/
|
|
90926
|
+
/******/ // The require function
|
|
90927
|
+
/******/ function __webpack_require__(moduleId) {
|
|
90928
|
+
/******/
|
|
90929
|
+
/******/ // Check if module is in cache
|
|
90930
|
+
/******/ if(installedModules[moduleId]) {
|
|
90931
|
+
/******/ return installedModules[moduleId].exports;
|
|
90932
|
+
/******/ }
|
|
90933
|
+
/******/ // Create a new module (and put it into the cache)
|
|
90934
|
+
/******/ var module = installedModules[moduleId] = {
|
|
90935
|
+
/******/ i: moduleId,
|
|
90936
|
+
/******/ l: false,
|
|
90937
|
+
/******/ exports: {}
|
|
90938
|
+
/******/ };
|
|
90939
|
+
/******/
|
|
90940
|
+
/******/ // Execute the module function
|
|
90941
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
90942
|
+
/******/
|
|
90943
|
+
/******/ // Flag the module as loaded
|
|
90944
|
+
/******/ module.l = true;
|
|
90945
|
+
/******/
|
|
90946
|
+
/******/ // Return the exports of the module
|
|
90947
|
+
/******/ return module.exports;
|
|
90948
|
+
/******/ }
|
|
90949
|
+
/******/
|
|
90950
|
+
/******/
|
|
90951
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
90952
|
+
/******/ __webpack_require__.m = modules;
|
|
90953
|
+
/******/
|
|
90954
|
+
/******/ // expose the module cache
|
|
90955
|
+
/******/ __webpack_require__.c = installedModules;
|
|
90956
|
+
/******/
|
|
90957
|
+
/******/ // define getter function for harmony exports
|
|
90958
|
+
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
90959
|
+
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
90960
|
+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
90961
|
+
/******/ }
|
|
90962
|
+
/******/ };
|
|
90963
|
+
/******/
|
|
90964
|
+
/******/ // define __esModule on exports
|
|
90965
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
90966
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
90967
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
90968
|
+
/******/ }
|
|
90969
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
90970
|
+
/******/ };
|
|
90971
|
+
/******/
|
|
90972
|
+
/******/ // create a fake namespace object
|
|
90973
|
+
/******/ // mode & 1: value is a module id, require it
|
|
90974
|
+
/******/ // mode & 2: merge all properties of value into the ns
|
|
90975
|
+
/******/ // mode & 4: return value when already ns object
|
|
90976
|
+
/******/ // mode & 8|1: behave like require
|
|
90977
|
+
/******/ __webpack_require__.t = function(value, mode) {
|
|
90978
|
+
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
90979
|
+
/******/ if(mode & 8) return value;
|
|
90980
|
+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
90981
|
+
/******/ var ns = Object.create(null);
|
|
90982
|
+
/******/ __webpack_require__.r(ns);
|
|
90983
|
+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
90984
|
+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
90985
|
+
/******/ return ns;
|
|
90986
|
+
/******/ };
|
|
90987
|
+
/******/
|
|
90988
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
90989
|
+
/******/ __webpack_require__.n = function(module) {
|
|
90990
|
+
/******/ var getter = module && module.__esModule ?
|
|
90991
|
+
/******/ function getDefault() { return module['default']; } :
|
|
90992
|
+
/******/ function getModuleExports() { return module; };
|
|
90993
|
+
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
90994
|
+
/******/ return getter;
|
|
90995
|
+
/******/ };
|
|
90996
|
+
/******/
|
|
90997
|
+
/******/ // Object.prototype.hasOwnProperty.call
|
|
90998
|
+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
90999
|
+
/******/
|
|
91000
|
+
/******/ // __webpack_public_path__
|
|
91001
|
+
/******/ __webpack_require__.p = "";
|
|
91002
|
+
/******/
|
|
91003
|
+
/******/
|
|
91004
|
+
/******/ // Load entry module and return exports
|
|
91005
|
+
/******/ return __webpack_require__(__webpack_require__.s = "./lib/all.ts");
|
|
91006
|
+
/******/ })
|
|
91007
|
+
/************************************************************************/
|
|
91008
|
+
/******/ ({
|
|
91009
|
+
|
|
91010
|
+
/***/ "./lib/all.ts":
|
|
91011
|
+
/*!********************!*\
|
|
91012
|
+
!*** ./lib/all.ts ***!
|
|
91013
|
+
\********************/
|
|
91014
|
+
/*! no static exports found */
|
|
91015
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91016
|
+
|
|
91017
|
+
"use strict";
|
|
91018
|
+
|
|
91019
|
+
function __export(m) {
|
|
91020
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
91021
|
+
}
|
|
91022
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91023
|
+
__export(__webpack_require__(/*! ./dra-types */ "./lib/dra-types.ts"));
|
|
91024
|
+
|
|
91025
|
+
|
|
91026
|
+
/***/ }),
|
|
91027
|
+
|
|
91028
|
+
/***/ "./lib/dra-types.ts":
|
|
91029
|
+
/*!**************************!*\
|
|
91030
|
+
!*** ./lib/dra-types.ts ***!
|
|
91031
|
+
\**************************/
|
|
91032
|
+
/*! no static exports found */
|
|
91033
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91034
|
+
|
|
91035
|
+
"use strict";
|
|
91036
|
+
|
|
91037
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91038
|
+
// Public libraries
|
|
91039
|
+
const Hash = __webpack_require__(/*! object-hash */ "object-hash");
|
|
91040
|
+
const Util = __webpack_require__(/*! @dra2020/util */ "@dra2020/util");
|
|
91041
|
+
// Canonical hashing of splitblock data
|
|
91042
|
+
function hash(o) {
|
|
91043
|
+
return Hash(o, { respectType: false,
|
|
91044
|
+
unorderedArrays: true,
|
|
91045
|
+
unorderedObjects: true,
|
|
91046
|
+
excludeKeys: (k) => (k === 'id' || k === 'chunk')
|
|
91047
|
+
});
|
|
91048
|
+
}
|
|
91049
|
+
function vgeoidToGeoid(vgeoid) {
|
|
91050
|
+
let re = /vfeature_([^_]*)_.*/;
|
|
91051
|
+
let a = re.exec(vgeoid);
|
|
91052
|
+
if (a == null || a.length != 2)
|
|
91053
|
+
return '';
|
|
91054
|
+
else
|
|
91055
|
+
return a[1];
|
|
91056
|
+
}
|
|
91057
|
+
exports.vgeoidToGeoid = vgeoidToGeoid;
|
|
91058
|
+
function vgeoidToChunk(vgeoid) {
|
|
91059
|
+
// vgeoid is string of form: "vfeature_[geoid]_[chunkid]_[hash]"
|
|
91060
|
+
// the contents are chunked into a file of form "vfeature_chunk_[chunkid]"
|
|
91061
|
+
// So extract the chunk ID and download that.
|
|
91062
|
+
let re = /vfeature_([^_]*)_([^_*])_(.*)/;
|
|
91063
|
+
let a = re.exec(vgeoid);
|
|
91064
|
+
if (a && a.length == 4)
|
|
91065
|
+
vgeoid = `vfeature_chunk_${a[2]}`;
|
|
91066
|
+
else
|
|
91067
|
+
vgeoid = null;
|
|
91068
|
+
return vgeoid;
|
|
91069
|
+
}
|
|
91070
|
+
exports.vgeoidToChunk = vgeoidToChunk;
|
|
91071
|
+
function vgeoidToHash(vgeoid) {
|
|
91072
|
+
// vgeoid is string of form: "vfeature_[geoid]_[chunkid]_[hash]"
|
|
91073
|
+
let re = /vfeature_([^_]*)_([^_*])_(.*)/;
|
|
91074
|
+
let a = re.exec(vgeoid);
|
|
91075
|
+
if (a && a.length == 4)
|
|
91076
|
+
vgeoid = a[3];
|
|
91077
|
+
else
|
|
91078
|
+
vgeoid = null;
|
|
91079
|
+
return vgeoid;
|
|
91080
|
+
}
|
|
91081
|
+
exports.vgeoidToHash = vgeoidToHash;
|
|
91082
|
+
function isVfeature(geoid) {
|
|
91083
|
+
return geoid.indexOf('vfeature') === 0;
|
|
91084
|
+
}
|
|
91085
|
+
exports.isVfeature = isVfeature;
|
|
91086
|
+
function splitToCacheKey(s) {
|
|
91087
|
+
if (s.id === undefined)
|
|
91088
|
+
s.id = hash(s);
|
|
91089
|
+
if (s.chunk === undefined)
|
|
91090
|
+
s.chunk = "0";
|
|
91091
|
+
return `_${s.state}_${s.datasource}_vfeature_${s.geoid}_${s.chunk}_${s.id}.geojson`;
|
|
91092
|
+
}
|
|
91093
|
+
exports.splitToCacheKey = splitToCacheKey;
|
|
91094
|
+
function splitToChunkKey(s) {
|
|
91095
|
+
if (s.chunk === undefined)
|
|
91096
|
+
s.chunk = "0";
|
|
91097
|
+
return `_${s.state}_${s.datasource}_vfeature_chunk_${s.chunk}.geojson`;
|
|
91098
|
+
}
|
|
91099
|
+
exports.splitToChunkKey = splitToChunkKey;
|
|
91100
|
+
function splitToPrefix(s) {
|
|
91101
|
+
if (s.blocks === undefined) {
|
|
91102
|
+
let re = /_([^_]*)_(.*)_vfeature.*\.geojson$/;
|
|
91103
|
+
let a = re.exec(s.id);
|
|
91104
|
+
if (a && a.length == 3)
|
|
91105
|
+
return `_${a[1]}_${a[2]}`;
|
|
91106
|
+
return s.id;
|
|
91107
|
+
}
|
|
91108
|
+
return `_${s.state}_${s.datasource}`;
|
|
91109
|
+
}
|
|
91110
|
+
exports.splitToPrefix = splitToPrefix;
|
|
91111
|
+
function cacheKeysToChunkHash(keys) {
|
|
91112
|
+
return hash(keys);
|
|
91113
|
+
}
|
|
91114
|
+
exports.cacheKeysToChunkHash = cacheKeysToChunkHash;
|
|
91115
|
+
let reNumeric = /^(\D*)(\d*)(\D*)$/;
|
|
91116
|
+
let reDistrictNumber = /^\d+$/;
|
|
91117
|
+
let reDistrictNumeric = /^\d/;
|
|
91118
|
+
// Normalize any numeric part to have no padded leading zeros
|
|
91119
|
+
function canonicalDistrictID(districtID) {
|
|
91120
|
+
let a = reNumeric.exec(districtID);
|
|
91121
|
+
if (a && a.length == 4) {
|
|
91122
|
+
if (a[2].length > 0)
|
|
91123
|
+
a[2] = String(Number(a[2]));
|
|
91124
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
91125
|
+
}
|
|
91126
|
+
return districtID;
|
|
91127
|
+
}
|
|
91128
|
+
exports.canonicalDistrictID = canonicalDistrictID;
|
|
91129
|
+
// Normalize any numeric part to have four digits with padded leading zeros
|
|
91130
|
+
function canonicalSortingDistrictID(districtID) {
|
|
91131
|
+
let a = reNumeric.exec(districtID);
|
|
91132
|
+
if (a && a.length == 4) {
|
|
91133
|
+
let s = a[2];
|
|
91134
|
+
if (s.length > 0) {
|
|
91135
|
+
switch (s.length) {
|
|
91136
|
+
case 1:
|
|
91137
|
+
s = `000${s}`;
|
|
91138
|
+
break;
|
|
91139
|
+
case 2:
|
|
91140
|
+
s = `00${s}`;
|
|
91141
|
+
break;
|
|
91142
|
+
case 3:
|
|
91143
|
+
s = `0${s}`;
|
|
91144
|
+
break;
|
|
91145
|
+
}
|
|
91146
|
+
a[2] = s;
|
|
91147
|
+
}
|
|
91148
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
91149
|
+
}
|
|
91150
|
+
return districtID;
|
|
91151
|
+
}
|
|
91152
|
+
exports.canonicalSortingDistrictID = canonicalSortingDistrictID;
|
|
91153
|
+
// Return numeric part of districtID (or -1 if there is none)
|
|
91154
|
+
function canonicalNumericFromDistrictID(districtID) {
|
|
91155
|
+
let a = reNumeric.exec(districtID);
|
|
91156
|
+
if (a && a.length == 4) {
|
|
91157
|
+
let s = a[2];
|
|
91158
|
+
if (s.length > 0)
|
|
91159
|
+
return Number(s);
|
|
91160
|
+
}
|
|
91161
|
+
return -1;
|
|
91162
|
+
}
|
|
91163
|
+
exports.canonicalNumericFromDistrictID = canonicalNumericFromDistrictID;
|
|
91164
|
+
function canonicalDistrictIDFromNumber(districtID, n) {
|
|
91165
|
+
let a = reNumeric.exec(districtID);
|
|
91166
|
+
if (a && a.length == 4) {
|
|
91167
|
+
a[2] = String(n);
|
|
91168
|
+
districtID = `${a[1]}${a[2]}${a[3]}`;
|
|
91169
|
+
}
|
|
91170
|
+
else
|
|
91171
|
+
districtID = String(n);
|
|
91172
|
+
return districtID;
|
|
91173
|
+
}
|
|
91174
|
+
exports.canonicalDistrictIDFromNumber = canonicalDistrictIDFromNumber;
|
|
91175
|
+
function canonicalDistrictIDOrdering(order) {
|
|
91176
|
+
let keys = Object.keys(order);
|
|
91177
|
+
let i;
|
|
91178
|
+
let a = [];
|
|
91179
|
+
let template = undefined;
|
|
91180
|
+
keys = keys.map((s) => canonicalSortingDistrictID(s));
|
|
91181
|
+
keys.sort();
|
|
91182
|
+
order = {};
|
|
91183
|
+
for (i = 0; i < keys.length; i++)
|
|
91184
|
+
order[canonicalDistrictID(keys[i])] = i + 1;
|
|
91185
|
+
// Remove water districts
|
|
91186
|
+
if (order['ZZZ'])
|
|
91187
|
+
delete order['ZZZ'];
|
|
91188
|
+
if (order['ZZ'])
|
|
91189
|
+
delete order['ZZ'];
|
|
91190
|
+
return order;
|
|
91191
|
+
}
|
|
91192
|
+
exports.canonicalDistrictIDOrdering = canonicalDistrictIDOrdering;
|
|
91193
|
+
let reArray = [
|
|
91194
|
+
/^(\d\d[^\s,"']*)[\s]*,[\s]*([^\s'"]+)[\s]*$/,
|
|
91195
|
+
/^["'](\d\d[^"']*)["'][\s]*,[\s]*["']([^"']*)["'][\s]*$/,
|
|
91196
|
+
/^(\d\d[^\s,]*)[\s]*,[\s]*["']([^"']*)["'][\s]*$/,
|
|
91197
|
+
/^["'](\d\d[^"']*)["'][\s]*,[\s]*([^\s]+)[\s]*$/,
|
|
91198
|
+
];
|
|
91199
|
+
function parseCSVLine(line) {
|
|
91200
|
+
if (line == null || line == '')
|
|
91201
|
+
return null;
|
|
91202
|
+
for (let i = 0; i < reArray.length; i++) {
|
|
91203
|
+
let a = reArray[i].exec(line);
|
|
91204
|
+
if (a && a.length === 3)
|
|
91205
|
+
return { geoid: a[1], districtID: a[2] };
|
|
91206
|
+
}
|
|
91207
|
+
return null;
|
|
91208
|
+
}
|
|
91209
|
+
exports.parseCSVLine = parseCSVLine;
|
|
91210
|
+
function blockmapToState(blockMap) {
|
|
91211
|
+
for (var id in blockMap)
|
|
91212
|
+
if (blockMap.hasOwnProperty(id))
|
|
91213
|
+
return geoidToState(id);
|
|
91214
|
+
return null;
|
|
91215
|
+
}
|
|
91216
|
+
exports.blockmapToState = blockmapToState;
|
|
91217
|
+
// blockToVTD:
|
|
91218
|
+
// Take BlockMapping (simple map of GEOID to districtID) and a per-state map of block-level GEOID to VTD
|
|
91219
|
+
// and return the output mapping of VTD to districtID, as well a data structure that describes any VTD's
|
|
91220
|
+
// that need to be split between districtIDs. Also returns the DistrictOrder structure that defines the
|
|
91221
|
+
// districtIDs that were used by the file.
|
|
91222
|
+
//
|
|
91223
|
+
// The state (as specified by the first two digits of the GEOID) is also determined. If the GEOID's do
|
|
91224
|
+
// not all specify the same state, the mapping is considered invalid and the outValid flag is set to false.
|
|
91225
|
+
//
|
|
91226
|
+
function blockmapToVTDmap(blockMap, stateMap) {
|
|
91227
|
+
let res = {
|
|
91228
|
+
inBlockMap: blockMap,
|
|
91229
|
+
inStateMap: stateMap,
|
|
91230
|
+
outValid: true,
|
|
91231
|
+
outState: null,
|
|
91232
|
+
outMap: {},
|
|
91233
|
+
outOrder: {},
|
|
91234
|
+
outDistrictToSplit: {}
|
|
91235
|
+
};
|
|
91236
|
+
let bmGather = {};
|
|
91237
|
+
let revMap = {};
|
|
91238
|
+
let id;
|
|
91239
|
+
if (stateMap)
|
|
91240
|
+
for (id in stateMap)
|
|
91241
|
+
if (stateMap.hasOwnProperty(id))
|
|
91242
|
+
revMap[stateMap[id]] = null;
|
|
91243
|
+
// First aggregate into features across all the blocks
|
|
91244
|
+
for (id in blockMap)
|
|
91245
|
+
if (blockMap.hasOwnProperty(id)) {
|
|
91246
|
+
let state = geoidToState(id);
|
|
91247
|
+
if (res.outState == null)
|
|
91248
|
+
res.outState = state;
|
|
91249
|
+
else if (res.outState !== state) {
|
|
91250
|
+
res.outValid = false;
|
|
91251
|
+
break;
|
|
91252
|
+
}
|
|
91253
|
+
let districtID = canonicalDistrictID(blockMap[id]);
|
|
91254
|
+
// Just ignore ZZZ (water) blocks
|
|
91255
|
+
if (districtID === 'ZZZ')
|
|
91256
|
+
continue;
|
|
91257
|
+
let n = id.length;
|
|
91258
|
+
let geoid;
|
|
91259
|
+
// Simple test for block id (vs. voting district or block group) id
|
|
91260
|
+
if (n >= 15) {
|
|
91261
|
+
if (stateMap && stateMap[id] !== undefined)
|
|
91262
|
+
geoid = stateMap[id];
|
|
91263
|
+
else {
|
|
91264
|
+
geoid = id.substr(0, 12); // heuristic for mapping blockID to blockgroupID
|
|
91265
|
+
if (revMap[geoid] === undefined) {
|
|
91266
|
+
res.outValid = false;
|
|
91267
|
+
break;
|
|
91268
|
+
}
|
|
91269
|
+
}
|
|
91270
|
+
}
|
|
91271
|
+
else
|
|
91272
|
+
geoid = id;
|
|
91273
|
+
if (res.outOrder[districtID] === undefined)
|
|
91274
|
+
res.outOrder[districtID] = 0;
|
|
91275
|
+
let districtToBlocks = bmGather[geoid];
|
|
91276
|
+
if (districtToBlocks === undefined)
|
|
91277
|
+
bmGather[geoid] = { [districtID]: { [id]: true } };
|
|
91278
|
+
else {
|
|
91279
|
+
let thisDistrict = districtToBlocks[districtID];
|
|
91280
|
+
if (thisDistrict === undefined) {
|
|
91281
|
+
thisDistrict = {};
|
|
91282
|
+
districtToBlocks[districtID] = thisDistrict;
|
|
91283
|
+
}
|
|
91284
|
+
thisDistrict[id] = true;
|
|
91285
|
+
}
|
|
91286
|
+
}
|
|
91287
|
+
// Now determine actual mapping of blocks to features, looking for split features
|
|
91288
|
+
for (let geoid in bmGather)
|
|
91289
|
+
if (bmGather.hasOwnProperty(geoid)) {
|
|
91290
|
+
let districtToBlocks = bmGather[geoid];
|
|
91291
|
+
if (Util.countKeys(districtToBlocks) == 1) {
|
|
91292
|
+
res.outMap[geoid] = Util.nthKey(districtToBlocks);
|
|
91293
|
+
}
|
|
91294
|
+
else {
|
|
91295
|
+
for (let districtID in districtToBlocks)
|
|
91296
|
+
if (districtToBlocks.hasOwnProperty(districtID)) {
|
|
91297
|
+
let split = { state: '', datasource: '', geoid: geoid, blocks: Object.keys(districtToBlocks[districtID]) };
|
|
91298
|
+
let splits = res.outDistrictToSplit[districtID];
|
|
91299
|
+
if (splits === undefined) {
|
|
91300
|
+
splits = [];
|
|
91301
|
+
res.outDistrictToSplit[districtID] = splits;
|
|
91302
|
+
}
|
|
91303
|
+
splits.push(split);
|
|
91304
|
+
}
|
|
91305
|
+
}
|
|
91306
|
+
}
|
|
91307
|
+
res.outOrder = canonicalDistrictIDOrdering(res.outOrder);
|
|
91308
|
+
return res;
|
|
91309
|
+
}
|
|
91310
|
+
exports.blockmapToVTDmap = blockmapToVTDmap;
|
|
91311
|
+
exports.GEOIDToState = {
|
|
91312
|
+
'01': 'AL',
|
|
91313
|
+
'02': 'AK',
|
|
91314
|
+
'04': 'AZ',
|
|
91315
|
+
'05': 'AR',
|
|
91316
|
+
'06': 'CA',
|
|
91317
|
+
'08': 'CO',
|
|
91318
|
+
'09': 'CT',
|
|
91319
|
+
'10': 'DE',
|
|
91320
|
+
'12': 'FL',
|
|
91321
|
+
'13': 'GA',
|
|
91322
|
+
'15': 'HI',
|
|
91323
|
+
'16': 'ID',
|
|
91324
|
+
'17': 'IL',
|
|
91325
|
+
'18': 'IN',
|
|
91326
|
+
'19': 'IA',
|
|
91327
|
+
'20': 'KS',
|
|
91328
|
+
'21': 'KY',
|
|
91329
|
+
'22': 'LA',
|
|
91330
|
+
'23': 'ME',
|
|
91331
|
+
'24': 'MD',
|
|
91332
|
+
'25': 'MA',
|
|
91333
|
+
'26': 'MI',
|
|
91334
|
+
'27': 'MN',
|
|
91335
|
+
'28': 'MS',
|
|
91336
|
+
'29': 'MO',
|
|
91337
|
+
'30': 'MT',
|
|
91338
|
+
'31': 'NE',
|
|
91339
|
+
'32': 'NV',
|
|
91340
|
+
'33': 'NH',
|
|
91341
|
+
'34': 'NJ',
|
|
91342
|
+
'35': 'NM',
|
|
91343
|
+
'36': 'NY',
|
|
91344
|
+
'37': 'NC',
|
|
91345
|
+
'38': 'ND',
|
|
91346
|
+
'39': 'OH',
|
|
91347
|
+
'40': 'OK',
|
|
91348
|
+
'41': 'OR',
|
|
91349
|
+
'42': 'PA',
|
|
91350
|
+
'44': 'RI',
|
|
91351
|
+
'45': 'SC',
|
|
91352
|
+
'46': 'SD',
|
|
91353
|
+
'47': 'TN',
|
|
91354
|
+
'48': 'TX',
|
|
91355
|
+
'49': 'UT',
|
|
91356
|
+
'50': 'VT',
|
|
91357
|
+
'51': 'VA',
|
|
91358
|
+
'53': 'WA',
|
|
91359
|
+
'54': 'WV',
|
|
91360
|
+
'55': 'WI',
|
|
91361
|
+
'56': 'WY',
|
|
91362
|
+
};
|
|
91363
|
+
exports.StateToGEOID = {
|
|
91364
|
+
'AL': '01',
|
|
91365
|
+
'AK': '02',
|
|
91366
|
+
'AZ': '04',
|
|
91367
|
+
'AR': '05',
|
|
91368
|
+
'CA': '06',
|
|
91369
|
+
'CO': '08',
|
|
91370
|
+
'CT': '09',
|
|
91371
|
+
'DE': '10',
|
|
91372
|
+
'FL': '12',
|
|
91373
|
+
'GA': '13',
|
|
91374
|
+
'HI': '15',
|
|
91375
|
+
'ID': '16',
|
|
91376
|
+
'IL': '17',
|
|
91377
|
+
'IN': '18',
|
|
91378
|
+
'IA': '19',
|
|
91379
|
+
'KS': '20',
|
|
91380
|
+
'KY': '21',
|
|
91381
|
+
'LA': '22',
|
|
91382
|
+
'ME': '23',
|
|
91383
|
+
'MD': '24',
|
|
91384
|
+
'MA': '25',
|
|
91385
|
+
'MI': '26',
|
|
91386
|
+
'MN': '27',
|
|
91387
|
+
'MS': '28',
|
|
91388
|
+
'MO': '29',
|
|
91389
|
+
'MT': '30',
|
|
91390
|
+
'NE': '31',
|
|
91391
|
+
'NV': '32',
|
|
91392
|
+
'NH': '33',
|
|
91393
|
+
'NJ': '34',
|
|
91394
|
+
'NM': '35',
|
|
91395
|
+
'NY': '36',
|
|
91396
|
+
'NC': '37',
|
|
91397
|
+
'ND': '38',
|
|
91398
|
+
'OH': '39',
|
|
91399
|
+
'OK': '40',
|
|
91400
|
+
'OR': '41',
|
|
91401
|
+
'PA': '42',
|
|
91402
|
+
'RI': '44',
|
|
91403
|
+
'SC': '45',
|
|
91404
|
+
'SD': '46',
|
|
91405
|
+
'TN': '47',
|
|
91406
|
+
'TX': '48',
|
|
91407
|
+
'UT': '49',
|
|
91408
|
+
'VT': '50',
|
|
91409
|
+
'VA': '51',
|
|
91410
|
+
'WA': '53',
|
|
91411
|
+
'WV': '54',
|
|
91412
|
+
'WI': '55',
|
|
91413
|
+
'WY': '56',
|
|
91414
|
+
};
|
|
91415
|
+
function geoidToState(geoid) {
|
|
91416
|
+
let re = /^(..).*$/;
|
|
91417
|
+
let a = re.exec(geoid);
|
|
91418
|
+
if (a == null || a.length != 2)
|
|
91419
|
+
return null;
|
|
91420
|
+
return exports.GEOIDToState[a[1]];
|
|
91421
|
+
}
|
|
91422
|
+
exports.geoidToState = geoidToState;
|
|
91423
|
+
|
|
91424
|
+
|
|
91425
|
+
/***/ }),
|
|
91426
|
+
|
|
91427
|
+
/***/ "@dra2020/util":
|
|
91428
|
+
/*!********************************!*\
|
|
91429
|
+
!*** external "@dra2020/util" ***!
|
|
91430
|
+
\********************************/
|
|
91431
|
+
/*! no static exports found */
|
|
91432
|
+
/***/ (function(module, exports) {
|
|
91433
|
+
|
|
91434
|
+
module.exports = __webpack_require__(/*! @dra2020/util */ "./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js");
|
|
91435
|
+
|
|
91436
|
+
/***/ }),
|
|
91437
|
+
|
|
91438
|
+
/***/ "object-hash":
|
|
91439
|
+
/*!******************************!*\
|
|
91440
|
+
!*** external "object-hash" ***!
|
|
91441
|
+
\******************************/
|
|
91442
|
+
/*! no static exports found */
|
|
91443
|
+
/***/ (function(module, exports) {
|
|
91444
|
+
|
|
91445
|
+
module.exports = __webpack_require__(/*! object-hash */ "./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js");
|
|
91446
|
+
|
|
91447
|
+
/***/ })
|
|
91448
|
+
|
|
91449
|
+
/******/ });
|
|
91450
|
+
});
|
|
91451
|
+
|
|
91452
|
+
|
|
91453
|
+
/***/ }),
|
|
91454
|
+
|
|
91455
|
+
/***/ "./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js":
|
|
91456
|
+
/*!*********************************************************************************!*\
|
|
91457
|
+
!*** ./node_modules/@dra2020/dra-types/node_modules/@dra2020/util/dist/util.js ***!
|
|
91458
|
+
\*********************************************************************************/
|
|
91459
|
+
/*! no static exports found */
|
|
91460
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91461
|
+
|
|
91462
|
+
(function webpackUniversalModuleDefinition(root, factory) {
|
|
91463
|
+
if(true)
|
|
91464
|
+
module.exports = factory();
|
|
91465
|
+
else {}
|
|
91466
|
+
})(global, function() {
|
|
91467
|
+
return /******/ (function(modules) { // webpackBootstrap
|
|
91468
|
+
/******/ // The module cache
|
|
91469
|
+
/******/ var installedModules = {};
|
|
91470
|
+
/******/
|
|
91471
|
+
/******/ // The require function
|
|
91472
|
+
/******/ function __webpack_require__(moduleId) {
|
|
91473
|
+
/******/
|
|
91474
|
+
/******/ // Check if module is in cache
|
|
91475
|
+
/******/ if(installedModules[moduleId]) {
|
|
91476
|
+
/******/ return installedModules[moduleId].exports;
|
|
91477
|
+
/******/ }
|
|
91478
|
+
/******/ // Create a new module (and put it into the cache)
|
|
91479
|
+
/******/ var module = installedModules[moduleId] = {
|
|
91480
|
+
/******/ i: moduleId,
|
|
91481
|
+
/******/ l: false,
|
|
91482
|
+
/******/ exports: {}
|
|
91483
|
+
/******/ };
|
|
91484
|
+
/******/
|
|
91485
|
+
/******/ // Execute the module function
|
|
91486
|
+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
91487
|
+
/******/
|
|
91488
|
+
/******/ // Flag the module as loaded
|
|
91489
|
+
/******/ module.l = true;
|
|
91490
|
+
/******/
|
|
91491
|
+
/******/ // Return the exports of the module
|
|
91492
|
+
/******/ return module.exports;
|
|
91493
|
+
/******/ }
|
|
91494
|
+
/******/
|
|
91495
|
+
/******/
|
|
91496
|
+
/******/ // expose the modules object (__webpack_modules__)
|
|
91497
|
+
/******/ __webpack_require__.m = modules;
|
|
91498
|
+
/******/
|
|
91499
|
+
/******/ // expose the module cache
|
|
91500
|
+
/******/ __webpack_require__.c = installedModules;
|
|
91501
|
+
/******/
|
|
91502
|
+
/******/ // define getter function for harmony exports
|
|
91503
|
+
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
91504
|
+
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
91505
|
+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
91506
|
+
/******/ }
|
|
91507
|
+
/******/ };
|
|
91508
|
+
/******/
|
|
91509
|
+
/******/ // define __esModule on exports
|
|
91510
|
+
/******/ __webpack_require__.r = function(exports) {
|
|
91511
|
+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
91512
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
91513
|
+
/******/ }
|
|
91514
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
91515
|
+
/******/ };
|
|
91516
|
+
/******/
|
|
91517
|
+
/******/ // create a fake namespace object
|
|
91518
|
+
/******/ // mode & 1: value is a module id, require it
|
|
91519
|
+
/******/ // mode & 2: merge all properties of value into the ns
|
|
91520
|
+
/******/ // mode & 4: return value when already ns object
|
|
91521
|
+
/******/ // mode & 8|1: behave like require
|
|
91522
|
+
/******/ __webpack_require__.t = function(value, mode) {
|
|
91523
|
+
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
91524
|
+
/******/ if(mode & 8) return value;
|
|
91525
|
+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
91526
|
+
/******/ var ns = Object.create(null);
|
|
91527
|
+
/******/ __webpack_require__.r(ns);
|
|
91528
|
+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
91529
|
+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
91530
|
+
/******/ return ns;
|
|
91531
|
+
/******/ };
|
|
91532
|
+
/******/
|
|
91533
|
+
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
91534
|
+
/******/ __webpack_require__.n = function(module) {
|
|
91535
|
+
/******/ var getter = module && module.__esModule ?
|
|
91536
|
+
/******/ function getDefault() { return module['default']; } :
|
|
91537
|
+
/******/ function getModuleExports() { return module; };
|
|
91538
|
+
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
91539
|
+
/******/ return getter;
|
|
91540
|
+
/******/ };
|
|
91541
|
+
/******/
|
|
91542
|
+
/******/ // Object.prototype.hasOwnProperty.call
|
|
91543
|
+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
91544
|
+
/******/
|
|
91545
|
+
/******/ // __webpack_public_path__
|
|
91546
|
+
/******/ __webpack_require__.p = "";
|
|
91547
|
+
/******/
|
|
91548
|
+
/******/
|
|
91549
|
+
/******/ // Load entry module and return exports
|
|
91550
|
+
/******/ return __webpack_require__(__webpack_require__.s = "./lib/all.ts");
|
|
91551
|
+
/******/ })
|
|
91552
|
+
/************************************************************************/
|
|
91553
|
+
/******/ ({
|
|
91554
|
+
|
|
91555
|
+
/***/ "./lib/all.ts":
|
|
91556
|
+
/*!********************!*\
|
|
91557
|
+
!*** ./lib/all.ts ***!
|
|
91558
|
+
\********************/
|
|
91559
|
+
/*! no static exports found */
|
|
91560
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91561
|
+
|
|
91562
|
+
"use strict";
|
|
91563
|
+
|
|
91564
|
+
function __export(m) {
|
|
91565
|
+
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
|
|
91566
|
+
}
|
|
91567
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91568
|
+
__export(__webpack_require__(/*! ./util */ "./lib/util.ts"));
|
|
91569
|
+
__export(__webpack_require__(/*! ./countedhash */ "./lib/countedhash.ts"));
|
|
91570
|
+
__export(__webpack_require__(/*! ./indexedarray */ "./lib/indexedarray.ts"));
|
|
91571
|
+
|
|
91572
|
+
|
|
91573
|
+
/***/ }),
|
|
91574
|
+
|
|
91575
|
+
/***/ "./lib/countedhash.ts":
|
|
91576
|
+
/*!****************************!*\
|
|
91577
|
+
!*** ./lib/countedhash.ts ***!
|
|
91578
|
+
\****************************/
|
|
91579
|
+
/*! no static exports found */
|
|
91580
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91581
|
+
|
|
91582
|
+
"use strict";
|
|
91583
|
+
|
|
91584
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91585
|
+
class CountedHash {
|
|
91586
|
+
constructor() {
|
|
91587
|
+
this.n = 0;
|
|
91588
|
+
this.val = {};
|
|
91589
|
+
}
|
|
91590
|
+
get length() { return this.n; }
|
|
91591
|
+
test(id) {
|
|
91592
|
+
return id != '' && this.val[id] !== undefined;
|
|
91593
|
+
}
|
|
91594
|
+
set(id) {
|
|
91595
|
+
if (id != '' && !this.test(id)) {
|
|
91596
|
+
this.n++;
|
|
91597
|
+
this.val[id] = true;
|
|
91598
|
+
}
|
|
91599
|
+
}
|
|
91600
|
+
clear(id) {
|
|
91601
|
+
if (this.test(id)) {
|
|
91602
|
+
this.n--;
|
|
91603
|
+
delete this.val[id];
|
|
91604
|
+
}
|
|
91605
|
+
}
|
|
91606
|
+
empty() {
|
|
91607
|
+
this.n = 0;
|
|
91608
|
+
this.val = {};
|
|
91609
|
+
}
|
|
91610
|
+
asArray() {
|
|
91611
|
+
let a = [];
|
|
91612
|
+
this.forEach(id => { a.push(id); });
|
|
91613
|
+
return a;
|
|
91614
|
+
}
|
|
91615
|
+
asString() {
|
|
91616
|
+
for (var id in this.val)
|
|
91617
|
+
if (this.val.hasOwnProperty(id))
|
|
91618
|
+
return id;
|
|
91619
|
+
return '';
|
|
91620
|
+
}
|
|
91621
|
+
forEach(f) {
|
|
91622
|
+
for (var id in this.val)
|
|
91623
|
+
if (this.val.hasOwnProperty(id))
|
|
91624
|
+
f(id);
|
|
91625
|
+
}
|
|
91626
|
+
}
|
|
91627
|
+
exports.CountedHash = CountedHash;
|
|
91628
|
+
|
|
91629
|
+
|
|
91630
|
+
/***/ }),
|
|
91631
|
+
|
|
91632
|
+
/***/ "./lib/indexedarray.ts":
|
|
91633
|
+
/*!*****************************!*\
|
|
91634
|
+
!*** ./lib/indexedarray.ts ***!
|
|
91635
|
+
\*****************************/
|
|
91636
|
+
/*! no static exports found */
|
|
91637
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91638
|
+
|
|
91639
|
+
"use strict";
|
|
91640
|
+
|
|
91641
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91642
|
+
class IndexedArray {
|
|
91643
|
+
constructor() {
|
|
91644
|
+
this.o = {};
|
|
91645
|
+
this.a = null;
|
|
91646
|
+
}
|
|
91647
|
+
ensure() {
|
|
91648
|
+
if (this.a === null) {
|
|
91649
|
+
this.a = [];
|
|
91650
|
+
for (let p in this.o)
|
|
91651
|
+
if (this.o.hasOwnProperty(p))
|
|
91652
|
+
this.a.push(p);
|
|
91653
|
+
this.a.sort((a, b) => { a = a.toUpperCase(); b = b.toUpperCase(); return a < b ? -1 : (a > b ? 1 : 0); });
|
|
91654
|
+
}
|
|
91655
|
+
}
|
|
91656
|
+
asArray() {
|
|
91657
|
+
this.ensure();
|
|
91658
|
+
return this.a;
|
|
91659
|
+
}
|
|
91660
|
+
get length() { this.ensure(); return this.a.length; }
|
|
91661
|
+
test(s) {
|
|
91662
|
+
return !!s && this.o[s] !== undefined;
|
|
91663
|
+
}
|
|
91664
|
+
set(s) {
|
|
91665
|
+
if (!!s && !this.test(s)) {
|
|
91666
|
+
this.o[s] = true;
|
|
91667
|
+
this.a = null;
|
|
91668
|
+
}
|
|
91669
|
+
}
|
|
91670
|
+
setAll(a) {
|
|
91671
|
+
if (a && a.length)
|
|
91672
|
+
for (let i = 0; i < a.length; i++)
|
|
91673
|
+
this.set(a[i]);
|
|
91674
|
+
}
|
|
91675
|
+
clear(s) {
|
|
91676
|
+
if (this.test(s)) {
|
|
91677
|
+
delete this.o[s];
|
|
91678
|
+
this.a = null;
|
|
91679
|
+
}
|
|
91680
|
+
}
|
|
91681
|
+
at(i) {
|
|
91682
|
+
this.ensure();
|
|
91683
|
+
if (i < 0 || i >= this.a.length)
|
|
91684
|
+
return undefined;
|
|
91685
|
+
return this.a[i];
|
|
91686
|
+
}
|
|
91687
|
+
empty() {
|
|
91688
|
+
this.o = {};
|
|
91689
|
+
this.a = null;
|
|
91690
|
+
}
|
|
91691
|
+
forEach(f) {
|
|
91692
|
+
for (var s in this.o)
|
|
91693
|
+
if (this.o.hasOwnProperty(s))
|
|
91694
|
+
f(s);
|
|
91695
|
+
}
|
|
91696
|
+
}
|
|
91697
|
+
exports.IndexedArray = IndexedArray;
|
|
91698
|
+
|
|
91699
|
+
|
|
91700
|
+
/***/ }),
|
|
91701
|
+
|
|
91702
|
+
/***/ "./lib/util.ts":
|
|
91703
|
+
/*!*********************!*\
|
|
91704
|
+
!*** ./lib/util.ts ***!
|
|
91705
|
+
\*********************/
|
|
91706
|
+
/*! no static exports found */
|
|
91707
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
91708
|
+
|
|
91709
|
+
"use strict";
|
|
91710
|
+
|
|
91711
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91712
|
+
function Now() { return (new Date()).toJSON(); }
|
|
91713
|
+
exports.Now = Now;
|
|
91714
|
+
class Elapsed {
|
|
91715
|
+
constructor(bStart = true) {
|
|
91716
|
+
this.tStart = undefined;
|
|
91717
|
+
this.tDur = undefined;
|
|
91718
|
+
if (bStart)
|
|
91719
|
+
this.start();
|
|
91720
|
+
}
|
|
91721
|
+
start() {
|
|
91722
|
+
if (process && process.hrtime)
|
|
91723
|
+
this.tStart = process.hrtime();
|
|
91724
|
+
else
|
|
91725
|
+
this.tStart = performance.now();
|
|
91726
|
+
if (this.tDur)
|
|
91727
|
+
this.tDur = undefined;
|
|
91728
|
+
}
|
|
91729
|
+
end() {
|
|
91730
|
+
if (this.tStart === undefined)
|
|
91731
|
+
this.start();
|
|
91732
|
+
if (process && process.hrtime)
|
|
91733
|
+
this.tDur = process.hrtime(this.tStart);
|
|
91734
|
+
else
|
|
91735
|
+
this.tDur = performance.now() - this.tStart;
|
|
91736
|
+
}
|
|
91737
|
+
ms() {
|
|
91738
|
+
if (this.tDur === undefined)
|
|
91739
|
+
this.end();
|
|
91740
|
+
if (process && process.hrtime)
|
|
91741
|
+
return Math.round((this.tDur[0] * 1000) + (this.tDur[1] / 1000000));
|
|
91742
|
+
else
|
|
91743
|
+
return this.tDur;
|
|
91744
|
+
}
|
|
91745
|
+
nano() {
|
|
91746
|
+
if (this.tDur === undefined)
|
|
91747
|
+
this.end();
|
|
91748
|
+
if (process && process.hrtime)
|
|
91749
|
+
return (this.tDur[0] * 1000000000) + this.tDur[1];
|
|
91750
|
+
else
|
|
91751
|
+
return this.tDur * 1000000;
|
|
91752
|
+
}
|
|
91753
|
+
}
|
|
91754
|
+
exports.Elapsed = Elapsed;
|
|
91755
|
+
class Deadline {
|
|
91756
|
+
constructor(msDelta) {
|
|
91757
|
+
this.msDelta = msDelta;
|
|
91758
|
+
this.elapsed = new Elapsed();
|
|
91759
|
+
}
|
|
91760
|
+
done() {
|
|
91761
|
+
this.elapsed.end();
|
|
91762
|
+
return this.elapsed.ms() > this.msDelta;
|
|
91763
|
+
}
|
|
91764
|
+
}
|
|
91765
|
+
exports.Deadline = Deadline;
|
|
91766
|
+
function createGuid() {
|
|
91767
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
91768
|
+
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
91769
|
+
return v.toString(16);
|
|
91770
|
+
});
|
|
91771
|
+
}
|
|
91772
|
+
exports.createGuid = createGuid;
|
|
91773
|
+
function _sizeof(a, loops) {
|
|
91774
|
+
if (a === null || a === undefined)
|
|
91775
|
+
return 0;
|
|
91776
|
+
switch (typeof a) {
|
|
91777
|
+
default: return 0;
|
|
91778
|
+
case 'number': return 8;
|
|
91779
|
+
case 'boolean': return 4;
|
|
91780
|
+
case 'string': return a.length * 2;
|
|
91781
|
+
case 'object':
|
|
91782
|
+
{
|
|
91783
|
+
if (loops.has(a))
|
|
91784
|
+
return 0;
|
|
91785
|
+
else
|
|
91786
|
+
loops.set(a, true);
|
|
91787
|
+
let t = 0;
|
|
91788
|
+
if (Array.isArray(a)) {
|
|
91789
|
+
for (let i = 0; i < a.length; i++)
|
|
91790
|
+
t += _sizeof(a[i], loops);
|
|
91791
|
+
t += 8; // length
|
|
91792
|
+
}
|
|
91793
|
+
else if (Buffer.isBuffer(a)) {
|
|
91794
|
+
t = a.length;
|
|
91795
|
+
}
|
|
91796
|
+
else if (a.hasOwnProperty === undefined)
|
|
91797
|
+
return t;
|
|
91798
|
+
else {
|
|
91799
|
+
for (var key in a)
|
|
91800
|
+
if (a.hasOwnProperty && a.hasOwnProperty(key)) {
|
|
91801
|
+
t += _sizeof(key, loops); // this is a good estimate of download size, but poor estimate of internal size
|
|
91802
|
+
// because of JS object templating vs. naive hashtables
|
|
91803
|
+
t += _sizeof(a[key], loops);
|
|
91804
|
+
}
|
|
91805
|
+
}
|
|
91806
|
+
return t;
|
|
91807
|
+
}
|
|
91808
|
+
}
|
|
91809
|
+
}
|
|
91810
|
+
function sizeof(a) {
|
|
91811
|
+
let loops = new WeakMap();
|
|
91812
|
+
let n = _sizeof(a, loops);
|
|
91813
|
+
return n;
|
|
91814
|
+
}
|
|
91815
|
+
exports.sizeof = sizeof;
|
|
91816
|
+
function depthof(a) {
|
|
91817
|
+
if (a === null || a === undefined)
|
|
91818
|
+
return 1;
|
|
91819
|
+
switch (typeof a) {
|
|
91820
|
+
default: return 1;
|
|
91821
|
+
case 'number': return 1;
|
|
91822
|
+
case 'boolean': return 1;
|
|
91823
|
+
case 'string': return 1;
|
|
91824
|
+
case 'object':
|
|
91825
|
+
{
|
|
91826
|
+
let d = 0;
|
|
91827
|
+
if (Array.isArray(a))
|
|
91828
|
+
return a.length > 0 ? (1 + depthof(a[0])) : 2; // still return 2 for empty array
|
|
91829
|
+
else if (Buffer.isBuffer(a))
|
|
91830
|
+
return 2;
|
|
91831
|
+
else if (a.hasOwnProperty === undefined)
|
|
91832
|
+
return 1;
|
|
91833
|
+
else {
|
|
91834
|
+
for (var key in a)
|
|
91835
|
+
if (a.hasOwnProperty(key))
|
|
91836
|
+
return 1 + depthof(a[key]);
|
|
91837
|
+
return 2; // or 2 for empty object
|
|
91838
|
+
}
|
|
91839
|
+
}
|
|
91840
|
+
}
|
|
91841
|
+
}
|
|
91842
|
+
exports.depthof = depthof;
|
|
91843
|
+
function isEmpty(o) {
|
|
91844
|
+
if (o === null || o === undefined)
|
|
91845
|
+
return true;
|
|
91846
|
+
for (var p in o)
|
|
91847
|
+
if (o.hasOwnProperty(p))
|
|
91848
|
+
return false;
|
|
91849
|
+
return true;
|
|
91850
|
+
}
|
|
91851
|
+
exports.isEmpty = isEmpty;
|
|
91852
|
+
function countKeys(o) {
|
|
91853
|
+
if (o === undefined || typeof o !== 'object')
|
|
91854
|
+
return -1;
|
|
91855
|
+
let count = 0;
|
|
91856
|
+
for (let p in o)
|
|
91857
|
+
if (o.hasOwnProperty(p))
|
|
91858
|
+
count++;
|
|
91859
|
+
return count;
|
|
91860
|
+
}
|
|
91861
|
+
exports.countKeys = countKeys;
|
|
91862
|
+
function nthProperty(o, n = 0) {
|
|
91863
|
+
for (let p in o)
|
|
91864
|
+
if (o.hasOwnProperty(p)) {
|
|
91865
|
+
if (n <= 0)
|
|
91866
|
+
return o[p];
|
|
91867
|
+
n--;
|
|
91868
|
+
}
|
|
91869
|
+
return undefined;
|
|
91870
|
+
}
|
|
91871
|
+
exports.nthProperty = nthProperty;
|
|
91872
|
+
function nthKey(o, n = 0) {
|
|
91873
|
+
for (let p in o)
|
|
91874
|
+
if (o.hasOwnProperty(p)) {
|
|
91875
|
+
if (n <= 0)
|
|
91876
|
+
return p;
|
|
91877
|
+
n--;
|
|
91878
|
+
}
|
|
91879
|
+
return undefined;
|
|
91880
|
+
}
|
|
91881
|
+
exports.nthKey = nthKey;
|
|
91882
|
+
function partialEqual(o, subset) {
|
|
91883
|
+
for (let p in subset)
|
|
91884
|
+
if (subset.hasOwnProperty(p))
|
|
91885
|
+
if (o[p] !== subset[p])
|
|
91886
|
+
return false;
|
|
91887
|
+
return true;
|
|
91888
|
+
}
|
|
91889
|
+
exports.partialEqual = partialEqual;
|
|
91890
|
+
function deepEqual(o1, o2, options) {
|
|
91891
|
+
if (typeof o1 !== typeof o2)
|
|
91892
|
+
return false;
|
|
91893
|
+
if (typeof o1 !== 'object')
|
|
91894
|
+
return o1 === o2;
|
|
91895
|
+
// Special case array
|
|
91896
|
+
if (Array.isArray(o1)) {
|
|
91897
|
+
if (!Array.isArray(o2))
|
|
91898
|
+
return false;
|
|
91899
|
+
if (o1.length != o2.length)
|
|
91900
|
+
return false;
|
|
91901
|
+
if (options && options.unorderedArrays) {
|
|
91902
|
+
o1 = o1.sort();
|
|
91903
|
+
o2 = o2.sort();
|
|
91904
|
+
}
|
|
91905
|
+
for (let i = 0; i < o1.length; i++)
|
|
91906
|
+
if (!deepEqual(o1[i], o2[i], options))
|
|
91907
|
+
return false;
|
|
91908
|
+
return true;
|
|
91909
|
+
}
|
|
91910
|
+
// Special case object
|
|
91911
|
+
if (o1.hasOwnProperty === undefined || o2.hasOwnProperty === undefined)
|
|
91912
|
+
return o1 === o2;
|
|
91913
|
+
for (let p in o1)
|
|
91914
|
+
if (o1.hasOwnProperty(p)) {
|
|
91915
|
+
if (options && options.omitKey[p])
|
|
91916
|
+
continue;
|
|
91917
|
+
if (o2[p] === undefined)
|
|
91918
|
+
return false;
|
|
91919
|
+
if (!deepEqual(o1[p], o2[p], options))
|
|
91920
|
+
return false;
|
|
91921
|
+
}
|
|
91922
|
+
// If any properties in o2 aren't in o1, not equal
|
|
91923
|
+
for (let p in o2)
|
|
91924
|
+
if (o2.hasOwnProperty(p)) {
|
|
91925
|
+
if (options && options.omitKey[p])
|
|
91926
|
+
continue;
|
|
91927
|
+
if (o1[p] === undefined)
|
|
91928
|
+
return false;
|
|
91929
|
+
}
|
|
91930
|
+
return true;
|
|
91931
|
+
}
|
|
91932
|
+
exports.deepEqual = deepEqual;
|
|
91933
|
+
const Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
91934
|
+
function prettyDate(d) {
|
|
91935
|
+
if (d == null)
|
|
91936
|
+
return 'unknown';
|
|
91937
|
+
let mmm = Months[d.getMonth()];
|
|
91938
|
+
let dd = d.getDate();
|
|
91939
|
+
let yyyy = d.getFullYear();
|
|
91940
|
+
let hh = d.getHours();
|
|
91941
|
+
let m = d.getMinutes();
|
|
91942
|
+
let mm = m < 10 ? `0${m}` : String(m);
|
|
91943
|
+
let ampm = hh >= 12 ? 'PM' : 'AM';
|
|
91944
|
+
if (hh > 12)
|
|
91945
|
+
hh -= 12;
|
|
91946
|
+
return `${mmm} ${dd}, ${yyyy} at ${hh}:${mm} ${ampm}`;
|
|
91947
|
+
}
|
|
91948
|
+
exports.prettyDate = prettyDate;
|
|
91949
|
+
function relativeDate(d) {
|
|
91950
|
+
if (d == null)
|
|
91951
|
+
return 'unknown';
|
|
91952
|
+
let now = new Date();
|
|
91953
|
+
let yyyyNow = now.getFullYear();
|
|
91954
|
+
let mmmNow = Months[now.getMonth()];
|
|
91955
|
+
let ddNow = now.getDate();
|
|
91956
|
+
let mmm = Months[d.getMonth()];
|
|
91957
|
+
let dd = d.getDate();
|
|
91958
|
+
let yyyy = d.getFullYear();
|
|
91959
|
+
let hh = d.getHours();
|
|
91960
|
+
let m = d.getMinutes();
|
|
91961
|
+
let mm = m < 10 ? `0${m}` : String(m);
|
|
91962
|
+
let ampm = hh >= 12 ? 'PM' : 'AM';
|
|
91963
|
+
if (hh > 12)
|
|
91964
|
+
hh -= 12;
|
|
91965
|
+
if (yyyyNow === yyyy && mmmNow === mmm && ddNow === dd)
|
|
91966
|
+
return `Today at ${hh}:${mm} ${ampm}`;
|
|
91967
|
+
else if (yyyyNow === yyyy)
|
|
91968
|
+
return `${mmm} ${dd}`;
|
|
91969
|
+
else
|
|
91970
|
+
return `${mmm} ${dd}, ${yyyy}`;
|
|
91971
|
+
}
|
|
91972
|
+
exports.relativeDate = relativeDate;
|
|
91973
|
+
const OneMinute = 1000 * 60;
|
|
91974
|
+
const OneHour = OneMinute * 60;
|
|
91975
|
+
const OneDay = OneHour * 24;
|
|
91976
|
+
function recentDate(d) {
|
|
91977
|
+
if (d == null)
|
|
91978
|
+
return 'u';
|
|
91979
|
+
let now = new Date();
|
|
91980
|
+
let msNow = now.getTime();
|
|
91981
|
+
let msThen = d.getTime();
|
|
91982
|
+
let msDelta = msNow - msThen;
|
|
91983
|
+
// Within the hour, display in minutes
|
|
91984
|
+
if (msDelta < OneHour)
|
|
91985
|
+
return `${Math.round(msDelta / OneMinute) + 1}m`;
|
|
91986
|
+
// Within the day, display in hours
|
|
91987
|
+
else if (msDelta < OneDay)
|
|
91988
|
+
return `${Math.round(msDelta / OneHour) + 1}h`;
|
|
91989
|
+
// Otherwise, display using relativeDate
|
|
91990
|
+
else
|
|
91991
|
+
return relativeDate(d);
|
|
91992
|
+
}
|
|
91993
|
+
exports.recentDate = recentDate;
|
|
91994
|
+
function textToHtml(sText) {
|
|
91995
|
+
let lines = sText.split('\n');
|
|
91996
|
+
let aHtml = [];
|
|
91997
|
+
let inTable = false;
|
|
91998
|
+
aHtml.push('<body>');
|
|
91999
|
+
for (let i = 0; i < lines.length; i++) {
|
|
92000
|
+
let line = lines[i];
|
|
92001
|
+
let isRow = line.indexOf('|') === 0;
|
|
92002
|
+
if (inTable && !isRow) {
|
|
92003
|
+
aHtml.push('</tbody></table>');
|
|
92004
|
+
inTable = false;
|
|
92005
|
+
}
|
|
92006
|
+
if (isRow && !inTable) {
|
|
92007
|
+
inTable = true;
|
|
92008
|
+
aHtml.push('<table border="1" cellspacing="0" cellpadding="2"><tbody>');
|
|
92009
|
+
}
|
|
92010
|
+
if (isRow) {
|
|
92011
|
+
let cells = line.split('|');
|
|
92012
|
+
if (cells.length > 2) {
|
|
92013
|
+
aHtml.push('<tr>');
|
|
92014
|
+
for (let j = 1; j < cells.length - 1; j++)
|
|
92015
|
+
aHtml.push(`<td>${cells[j]}</td>`);
|
|
92016
|
+
aHtml.push('</tr>');
|
|
92017
|
+
}
|
|
92018
|
+
}
|
|
92019
|
+
else
|
|
92020
|
+
aHtml.push(`<div>${line} </div>`);
|
|
92021
|
+
}
|
|
92022
|
+
if (inTable)
|
|
92023
|
+
aHtml.push('</tbody></table>');
|
|
92024
|
+
aHtml.push('</body>');
|
|
92025
|
+
return aHtml.join('');
|
|
92026
|
+
}
|
|
92027
|
+
exports.textToHtml = textToHtml;
|
|
92028
|
+
function shallowCopy(src) {
|
|
92029
|
+
if (src === null || src === undefined)
|
|
92030
|
+
return src;
|
|
92031
|
+
switch (typeof src) {
|
|
92032
|
+
case 'boolean':
|
|
92033
|
+
case 'number':
|
|
92034
|
+
case 'string':
|
|
92035
|
+
case 'symbol':
|
|
92036
|
+
case 'function':
|
|
92037
|
+
default:
|
|
92038
|
+
return src;
|
|
92039
|
+
case 'object':
|
|
92040
|
+
if (Array.isArray(src))
|
|
92041
|
+
return src.slice();
|
|
92042
|
+
else {
|
|
92043
|
+
let copy = {};
|
|
92044
|
+
for (var p in src)
|
|
92045
|
+
if (src.hasOwnProperty(p))
|
|
92046
|
+
copy[p] = src[p];
|
|
92047
|
+
return copy;
|
|
92048
|
+
}
|
|
92049
|
+
}
|
|
92050
|
+
}
|
|
92051
|
+
exports.shallowCopy = shallowCopy;
|
|
92052
|
+
function shallowAssign(o1, o2) {
|
|
92053
|
+
if (o1 === null || o1 === undefined)
|
|
92054
|
+
o1 = {};
|
|
92055
|
+
if (o2 === null || o2 === undefined)
|
|
92056
|
+
return o1;
|
|
92057
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
92058
|
+
return o1;
|
|
92059
|
+
for (var p in o2)
|
|
92060
|
+
if (o2.hasOwnProperty(p))
|
|
92061
|
+
o1[p] = o2[p];
|
|
92062
|
+
return o1;
|
|
92063
|
+
}
|
|
92064
|
+
exports.shallowAssign = shallowAssign;
|
|
92065
|
+
function shallowDelete(o1, o2) {
|
|
92066
|
+
if (o1 == null || o2 == null)
|
|
92067
|
+
return o1;
|
|
92068
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
92069
|
+
return o1;
|
|
92070
|
+
for (var p in o2)
|
|
92071
|
+
if (o2.hasOwnProperty(p))
|
|
92072
|
+
delete o1[p];
|
|
92073
|
+
return o1;
|
|
92074
|
+
}
|
|
92075
|
+
exports.shallowDelete = shallowDelete;
|
|
92076
|
+
function shallowAssignImmutable(o1, o2) {
|
|
92077
|
+
if (o1 === null || o1 === undefined)
|
|
92078
|
+
o1 = {};
|
|
92079
|
+
if (o2 === null || o2 === undefined)
|
|
92080
|
+
return o1;
|
|
92081
|
+
if (typeof o2 !== 'object' || typeof o1 !== 'object')
|
|
92082
|
+
return o1;
|
|
92083
|
+
// First determine whether o2 changes any properties, if it has, make new instance
|
|
92084
|
+
let oNew = o1;
|
|
92085
|
+
for (let p in o2)
|
|
92086
|
+
if (o2.hasOwnProperty(p)) {
|
|
92087
|
+
if (o1[p] != o2[p]) {
|
|
92088
|
+
oNew = shallowCopy(o1);
|
|
92089
|
+
break;
|
|
92090
|
+
}
|
|
92091
|
+
}
|
|
92092
|
+
if (oNew !== o1)
|
|
92093
|
+
shallowAssign(oNew, o2);
|
|
92094
|
+
return oNew;
|
|
92095
|
+
}
|
|
92096
|
+
exports.shallowAssignImmutable = shallowAssignImmutable;
|
|
92097
|
+
function shallowEqual(o1, o2) {
|
|
92098
|
+
if (o1 === undefined || o2 === undefined || typeof o1 !== 'object' || typeof o2 !== 'object')
|
|
92099
|
+
return o1 === o2;
|
|
92100
|
+
if (Array.isArray(o1) && Array.isArray(o2)) {
|
|
92101
|
+
if (o1.length != o2.length)
|
|
92102
|
+
return false;
|
|
92103
|
+
for (let i = 0; i < o1.length; i++)
|
|
92104
|
+
if (o1[i] !== o2[i])
|
|
92105
|
+
return false;
|
|
92106
|
+
return true;
|
|
92107
|
+
}
|
|
92108
|
+
else {
|
|
92109
|
+
let p;
|
|
92110
|
+
for (p in o1)
|
|
92111
|
+
if (o1.hasOwnProperty(p))
|
|
92112
|
+
if (o1[p] !== o2[p])
|
|
92113
|
+
return false;
|
|
92114
|
+
for (p in o2)
|
|
92115
|
+
if (o2.hasOwnProperty(p))
|
|
92116
|
+
if (o1[p] === undefined)
|
|
92117
|
+
return false;
|
|
92118
|
+
return true;
|
|
92119
|
+
}
|
|
92120
|
+
}
|
|
92121
|
+
exports.shallowEqual = shallowEqual;
|
|
92122
|
+
function deepCopy(src) {
|
|
92123
|
+
// Beware typeof oddities
|
|
92124
|
+
if (src === null || src === undefined)
|
|
92125
|
+
return src;
|
|
92126
|
+
if (typeof src === 'object') {
|
|
92127
|
+
if (Array.isArray(src)) {
|
|
92128
|
+
let dst = [];
|
|
92129
|
+
for (let i = 0; i < src.length; i++)
|
|
92130
|
+
dst.push(deepCopy(src[i]));
|
|
92131
|
+
return dst;
|
|
92132
|
+
}
|
|
92133
|
+
else {
|
|
92134
|
+
if (src.hasOwnProperty === undefined)
|
|
92135
|
+
return src;
|
|
92136
|
+
let dst = {};
|
|
92137
|
+
for (var p in src)
|
|
92138
|
+
if (src.hasOwnProperty(p))
|
|
92139
|
+
dst[p] = deepCopy(src[p]);
|
|
92140
|
+
return dst;
|
|
92141
|
+
}
|
|
92142
|
+
}
|
|
92143
|
+
else
|
|
92144
|
+
return src;
|
|
92145
|
+
}
|
|
92146
|
+
exports.deepCopy = deepCopy;
|
|
92147
|
+
function deepAccum(accum, o) {
|
|
92148
|
+
if (accum == null)
|
|
92149
|
+
accum = {};
|
|
92150
|
+
if (o == null)
|
|
92151
|
+
return accum;
|
|
92152
|
+
for (let p in o)
|
|
92153
|
+
if (o.hasOwnProperty(p)) {
|
|
92154
|
+
let vs = o[p];
|
|
92155
|
+
let vd = accum[p];
|
|
92156
|
+
if (typeof vs === 'number') {
|
|
92157
|
+
if (vd !== undefined && typeof vd !== 'number')
|
|
92158
|
+
throw 'deepAccum: unexpected type mismatch';
|
|
92159
|
+
accum[p] = (vd === undefined ? 0 : vd) + vs;
|
|
92160
|
+
}
|
|
92161
|
+
else if (typeof vs === 'object') {
|
|
92162
|
+
if (vd === undefined) {
|
|
92163
|
+
vd = {};
|
|
92164
|
+
accum[p] = vd;
|
|
92165
|
+
}
|
|
92166
|
+
else if (typeof vd !== 'object')
|
|
92167
|
+
throw 'deepAccum: unexpected type mismatch';
|
|
92168
|
+
deepAccum(vd, vs);
|
|
92169
|
+
}
|
|
92170
|
+
}
|
|
92171
|
+
}
|
|
92172
|
+
exports.deepAccum = deepAccum;
|
|
92173
|
+
function precisionRound(n, p) {
|
|
92174
|
+
let f = Math.pow(10, p);
|
|
92175
|
+
return Math.round(n * f) / f;
|
|
92176
|
+
}
|
|
92177
|
+
exports.precisionRound = precisionRound;
|
|
92178
|
+
function percentString(num, den, precision = 0) {
|
|
92179
|
+
if (den == 0)
|
|
92180
|
+
return '(-)';
|
|
92181
|
+
let p = precisionRound((num / den) * 100, precision);
|
|
92182
|
+
return String(p) + '%';
|
|
92183
|
+
}
|
|
92184
|
+
exports.percentString = percentString;
|
|
92185
|
+
function hash(s) {
|
|
92186
|
+
let hash = 5381;
|
|
92187
|
+
let i = s.length;
|
|
92188
|
+
while (i)
|
|
92189
|
+
hash = (hash * 33) ^ s.charCodeAt(--i);
|
|
92190
|
+
/* JavaScript does bitwise operations (like XOR, above) on 32-bit signed
|
|
92191
|
+
* integers. Since we want the results to be always positive, convert the
|
|
92192
|
+
* signed int to an unsigned by doing an unsigned bitshift. */
|
|
92193
|
+
return hash >>> 0;
|
|
92194
|
+
}
|
|
92195
|
+
exports.hash = hash;
|
|
92196
|
+
function hashObject(o) {
|
|
92197
|
+
return hash(o ? JSON.stringify(o) : '');
|
|
92198
|
+
}
|
|
92199
|
+
exports.hashObject = hashObject;
|
|
92200
|
+
const HexTable = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
|
92201
|
+
function toHex(n) {
|
|
92202
|
+
if (n < 0 || n > 255)
|
|
92203
|
+
throw ('only 0 to 255 supported now');
|
|
92204
|
+
n = Math.floor(n);
|
|
92205
|
+
return HexTable[n >> 4] + HexTable[n & 15];
|
|
92206
|
+
}
|
|
92207
|
+
exports.toHex = toHex;
|
|
92208
|
+
function toRGBA(color, alpha) {
|
|
92209
|
+
let r;
|
|
92210
|
+
let g;
|
|
92211
|
+
let b;
|
|
92212
|
+
switch (color) {
|
|
92213
|
+
case 'white':
|
|
92214
|
+
r = 255;
|
|
92215
|
+
g = 255;
|
|
92216
|
+
b = 255;
|
|
92217
|
+
break;
|
|
92218
|
+
case 'black':
|
|
92219
|
+
r = 0;
|
|
92220
|
+
g = 0;
|
|
92221
|
+
b = 0;
|
|
92222
|
+
break;
|
|
92223
|
+
default:
|
|
92224
|
+
r = parseInt(color.substr(1, 2), 16);
|
|
92225
|
+
g = parseInt(color.substr(3, 2), 16);
|
|
92226
|
+
b = parseInt(color.substr(5, 2), 16);
|
|
92227
|
+
break;
|
|
92228
|
+
}
|
|
92229
|
+
return `rgba(${String(r)}, ${String(g)}, ${String(b)}, ${String(alpha)})`;
|
|
92230
|
+
}
|
|
92231
|
+
exports.toRGBA = toRGBA;
|
|
92232
|
+
function toRGBAIntensity(color, intensity, alpha) {
|
|
92233
|
+
// for now assume color is black
|
|
92234
|
+
let g = precisionRound(255 * intensity, 0);
|
|
92235
|
+
return `rgba(${String(g)}, ${String(g)}, ${String(g)}, ${String(alpha)})`;
|
|
92236
|
+
}
|
|
92237
|
+
exports.toRGBAIntensity = toRGBAIntensity;
|
|
92238
|
+
// Geo functions
|
|
92239
|
+
function distance(x0, y0, x1, y1) {
|
|
92240
|
+
return Math.hypot(x0 - x1, y0 - y1);
|
|
92241
|
+
}
|
|
92242
|
+
exports.distance = distance;
|
|
92243
|
+
function deg2rad(num) { return num * Math.PI / 180; }
|
|
92244
|
+
exports.deg2rad = deg2rad;
|
|
92245
|
+
function rad2deg(num) { return num / Math.PI * 180; }
|
|
92246
|
+
exports.rad2deg = rad2deg;
|
|
92247
|
+
// Restricts lon to range [-180..180]
|
|
92248
|
+
function wrapLon(lon) {
|
|
92249
|
+
let worlds = Math.floor((lon + 180) / 360);
|
|
92250
|
+
return lon - (worlds * 360);
|
|
92251
|
+
}
|
|
92252
|
+
exports.wrapLon = wrapLon;
|
|
92253
|
+
|
|
92254
|
+
|
|
92255
|
+
/***/ })
|
|
92256
|
+
|
|
92257
|
+
/******/ });
|
|
92258
|
+
});
|
|
92259
|
+
|
|
92260
|
+
|
|
92261
|
+
/***/ }),
|
|
92262
|
+
|
|
92263
|
+
/***/ "./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js":
|
|
92264
|
+
/*!***************************************************************************!*\
|
|
92265
|
+
!*** ./node_modules/@dra2020/dra-types/node_modules/object-hash/index.js ***!
|
|
92266
|
+
\***************************************************************************/
|
|
92267
|
+
/*! no static exports found */
|
|
92268
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
92269
|
+
|
|
92270
|
+
"use strict";
|
|
92271
|
+
|
|
92272
|
+
|
|
92273
|
+
var crypto = __webpack_require__(/*! crypto */ "crypto");
|
|
92274
|
+
|
|
92275
|
+
/**
|
|
92276
|
+
* Exported function
|
|
92277
|
+
*
|
|
92278
|
+
* Options:
|
|
92279
|
+
*
|
|
92280
|
+
* - `algorithm` hash algo to be used by this instance: *'sha1', 'md5'
|
|
92281
|
+
* - `excludeValues` {true|*false} hash object keys, values ignored
|
|
92282
|
+
* - `encoding` hash encoding, supports 'buffer', '*hex', 'binary', 'base64'
|
|
92283
|
+
* - `ignoreUnknown` {true|*false} ignore unknown object types
|
|
92284
|
+
* - `replacer` optional function that replaces values before hashing
|
|
92285
|
+
* - `respectFunctionProperties` {*true|false} consider function properties when hashing
|
|
92286
|
+
* - `respectFunctionNames` {*true|false} consider 'name' property of functions for hashing
|
|
92287
|
+
* - `respectType` {*true|false} Respect special properties (prototype, constructor)
|
|
92288
|
+
* when hashing to distinguish between types
|
|
92289
|
+
* - `unorderedArrays` {true|*false} Sort all arrays before hashing
|
|
92290
|
+
* - `unorderedSets` {*true|false} Sort `Set` and `Map` instances before hashing
|
|
92291
|
+
* * = default
|
|
92292
|
+
*
|
|
92293
|
+
* @param {object} object value to hash
|
|
92294
|
+
* @param {object} options hashing options
|
|
92295
|
+
* @return {string} hash value
|
|
92296
|
+
* @api public
|
|
92297
|
+
*/
|
|
92298
|
+
exports = module.exports = objectHash;
|
|
92299
|
+
|
|
92300
|
+
function objectHash(object, options){
|
|
92301
|
+
options = applyDefaults(object, options);
|
|
92302
|
+
|
|
92303
|
+
return hash(object, options);
|
|
92304
|
+
}
|
|
92305
|
+
|
|
92306
|
+
/**
|
|
92307
|
+
* Exported sugar methods
|
|
92308
|
+
*
|
|
92309
|
+
* @param {object} object value to hash
|
|
92310
|
+
* @return {string} hash value
|
|
92311
|
+
* @api public
|
|
92312
|
+
*/
|
|
92313
|
+
exports.sha1 = function(object){
|
|
92314
|
+
return objectHash(object);
|
|
92315
|
+
};
|
|
92316
|
+
exports.keys = function(object){
|
|
92317
|
+
return objectHash(object, {excludeValues: true, algorithm: 'sha1', encoding: 'hex'});
|
|
92318
|
+
};
|
|
92319
|
+
exports.MD5 = function(object){
|
|
92320
|
+
return objectHash(object, {algorithm: 'md5', encoding: 'hex'});
|
|
92321
|
+
};
|
|
92322
|
+
exports.keysMD5 = function(object){
|
|
92323
|
+
return objectHash(object, {algorithm: 'md5', encoding: 'hex', excludeValues: true});
|
|
92324
|
+
};
|
|
92325
|
+
|
|
92326
|
+
// Internals
|
|
92327
|
+
var hashes = crypto.getHashes ? crypto.getHashes().slice() : ['sha1', 'md5'];
|
|
92328
|
+
hashes.push('passthrough');
|
|
92329
|
+
var encodings = ['buffer', 'hex', 'binary', 'base64'];
|
|
92330
|
+
|
|
92331
|
+
function applyDefaults(object, sourceOptions){
|
|
92332
|
+
sourceOptions = sourceOptions || {};
|
|
92333
|
+
|
|
92334
|
+
// create a copy rather than mutating
|
|
92335
|
+
var options = {};
|
|
92336
|
+
options.algorithm = sourceOptions.algorithm || 'sha1';
|
|
92337
|
+
options.encoding = sourceOptions.encoding || 'hex';
|
|
92338
|
+
options.excludeValues = sourceOptions.excludeValues ? true : false;
|
|
92339
|
+
options.algorithm = options.algorithm.toLowerCase();
|
|
92340
|
+
options.encoding = options.encoding.toLowerCase();
|
|
92341
|
+
options.ignoreUnknown = sourceOptions.ignoreUnknown !== true ? false : true; // default to false
|
|
92342
|
+
options.respectType = sourceOptions.respectType === false ? false : true; // default to true
|
|
92343
|
+
options.respectFunctionNames = sourceOptions.respectFunctionNames === false ? false : true;
|
|
92344
|
+
options.respectFunctionProperties = sourceOptions.respectFunctionProperties === false ? false : true;
|
|
92345
|
+
options.unorderedArrays = sourceOptions.unorderedArrays !== true ? false : true; // default to false
|
|
92346
|
+
options.unorderedSets = sourceOptions.unorderedSets === false ? false : true; // default to false
|
|
92347
|
+
options.unorderedObjects = sourceOptions.unorderedObjects === false ? false : true; // default to true
|
|
92348
|
+
options.replacer = sourceOptions.replacer || undefined;
|
|
92349
|
+
options.excludeKeys = sourceOptions.excludeKeys || undefined;
|
|
92350
|
+
|
|
92351
|
+
if(typeof object === 'undefined') {
|
|
92352
|
+
throw new Error('Object argument required.');
|
|
92353
|
+
}
|
|
92354
|
+
|
|
92355
|
+
// if there is a case-insensitive match in the hashes list, accept it
|
|
92356
|
+
// (i.e. SHA256 for sha256)
|
|
92357
|
+
for (var i = 0; i < hashes.length; ++i) {
|
|
92358
|
+
if (hashes[i].toLowerCase() === options.algorithm.toLowerCase()) {
|
|
92359
|
+
options.algorithm = hashes[i];
|
|
92360
|
+
}
|
|
92361
|
+
}
|
|
92362
|
+
|
|
92363
|
+
if(hashes.indexOf(options.algorithm) === -1){
|
|
92364
|
+
throw new Error('Algorithm "' + options.algorithm + '" not supported. ' +
|
|
92365
|
+
'supported values: ' + hashes.join(', '));
|
|
92366
|
+
}
|
|
92367
|
+
|
|
92368
|
+
if(encodings.indexOf(options.encoding) === -1 &&
|
|
92369
|
+
options.algorithm !== 'passthrough'){
|
|
92370
|
+
throw new Error('Encoding "' + options.encoding + '" not supported. ' +
|
|
92371
|
+
'supported values: ' + encodings.join(', '));
|
|
92372
|
+
}
|
|
92373
|
+
|
|
92374
|
+
return options;
|
|
92375
|
+
}
|
|
92376
|
+
|
|
92377
|
+
/** Check if the given function is a native function */
|
|
92378
|
+
function isNativeFunction(f) {
|
|
92379
|
+
if ((typeof f) !== 'function') {
|
|
92380
|
+
return false;
|
|
92381
|
+
}
|
|
92382
|
+
var exp = /^function\s+\w*\s*\(\s*\)\s*{\s+\[native code\]\s+}$/i;
|
|
92383
|
+
return exp.exec(Function.prototype.toString.call(f)) != null;
|
|
92384
|
+
}
|
|
92385
|
+
|
|
92386
|
+
function hash(object, options) {
|
|
92387
|
+
var hashingStream;
|
|
92388
|
+
|
|
92389
|
+
if (options.algorithm !== 'passthrough') {
|
|
92390
|
+
hashingStream = crypto.createHash(options.algorithm);
|
|
92391
|
+
} else {
|
|
92392
|
+
hashingStream = new PassThrough();
|
|
92393
|
+
}
|
|
92394
|
+
|
|
92395
|
+
if (typeof hashingStream.write === 'undefined') {
|
|
92396
|
+
hashingStream.write = hashingStream.update;
|
|
92397
|
+
hashingStream.end = hashingStream.update;
|
|
92398
|
+
}
|
|
92399
|
+
|
|
92400
|
+
var hasher = typeHasher(options, hashingStream);
|
|
92401
|
+
hasher.dispatch(object);
|
|
92402
|
+
if (!hashingStream.update) {
|
|
92403
|
+
hashingStream.end('');
|
|
92404
|
+
}
|
|
92405
|
+
|
|
92406
|
+
if (hashingStream.digest) {
|
|
92407
|
+
return hashingStream.digest(options.encoding === 'buffer' ? undefined : options.encoding);
|
|
92408
|
+
}
|
|
92409
|
+
|
|
92410
|
+
var buf = hashingStream.read();
|
|
92411
|
+
if (options.encoding === 'buffer') {
|
|
92412
|
+
return buf;
|
|
92413
|
+
}
|
|
92414
|
+
|
|
92415
|
+
return buf.toString(options.encoding);
|
|
92416
|
+
}
|
|
90607
92417
|
|
|
92418
|
+
/**
|
|
92419
|
+
* Expose streaming API
|
|
92420
|
+
*
|
|
92421
|
+
* @param {object} object Value to serialize
|
|
92422
|
+
* @param {object} options Options, as for hash()
|
|
92423
|
+
* @param {object} stream A stream to write the serializiation to
|
|
92424
|
+
* @api public
|
|
92425
|
+
*/
|
|
92426
|
+
exports.writeToStream = function(object, options, stream) {
|
|
92427
|
+
if (typeof stream === 'undefined') {
|
|
92428
|
+
stream = options;
|
|
92429
|
+
options = {};
|
|
92430
|
+
}
|
|
90608
92431
|
|
|
90609
|
-
|
|
92432
|
+
options = applyDefaults(object, options);
|
|
90610
92433
|
|
|
90611
|
-
|
|
90612
|
-
|
|
90613
|
-
!*** ./testdata/profiles/sample-profile.json ***!
|
|
90614
|
-
\***********************************************/
|
|
90615
|
-
/*! exports provided: state, planName, nDistricts, nCounties, legislativeDistricts, populationProfile, compactnessProfile, splittingProfile, partisanProfile, demographicProfile, default */
|
|
90616
|
-
/***/ (function(module) {
|
|
92434
|
+
return typeHasher(options, stream).dispatch(object);
|
|
92435
|
+
};
|
|
90617
92436
|
|
|
90618
|
-
|
|
92437
|
+
function typeHasher(options, writeTo, context){
|
|
92438
|
+
context = context || [];
|
|
92439
|
+
var write = function(str) {
|
|
92440
|
+
if (writeTo.update) {
|
|
92441
|
+
return writeTo.update(str, 'utf8');
|
|
92442
|
+
} else {
|
|
92443
|
+
return writeTo.write(str, 'utf8');
|
|
92444
|
+
}
|
|
92445
|
+
};
|
|
90619
92446
|
|
|
90620
|
-
|
|
92447
|
+
return {
|
|
92448
|
+
dispatch: function(value){
|
|
92449
|
+
if (options.replacer) {
|
|
92450
|
+
value = options.replacer(value);
|
|
92451
|
+
}
|
|
90621
92452
|
|
|
90622
|
-
|
|
90623
|
-
|
|
90624
|
-
|
|
90625
|
-
|
|
90626
|
-
/*! exports provided: score, best, fair, default */
|
|
90627
|
-
/***/ (function(module) {
|
|
92453
|
+
var type = typeof value;
|
|
92454
|
+
if (value === null) {
|
|
92455
|
+
type = 'null';
|
|
92456
|
+
}
|
|
90628
92457
|
|
|
90629
|
-
|
|
92458
|
+
//console.log("[DEBUG] Dispatch: ", value, "->", type, " -> ", "_" + type);
|
|
90630
92459
|
|
|
90631
|
-
|
|
92460
|
+
return this['_' + type](value);
|
|
92461
|
+
},
|
|
92462
|
+
_object: function(object) {
|
|
92463
|
+
var pattern = (/\[object (.*)\]/i);
|
|
92464
|
+
var objString = Object.prototype.toString.call(object);
|
|
92465
|
+
var objType = pattern.exec(objString);
|
|
92466
|
+
if (!objType) { // object type did not match [object ...]
|
|
92467
|
+
objType = 'unknown:[' + objString + ']';
|
|
92468
|
+
} else {
|
|
92469
|
+
objType = objType[1]; // take only the class name
|
|
92470
|
+
}
|
|
90632
92471
|
|
|
90633
|
-
|
|
90634
|
-
|
|
92472
|
+
objType = objType.toLowerCase();
|
|
92473
|
+
|
|
92474
|
+
var objectNumber = null;
|
|
92475
|
+
|
|
92476
|
+
if ((objectNumber = context.indexOf(object)) >= 0) {
|
|
92477
|
+
return this.dispatch('[CIRCULAR:' + objectNumber + ']');
|
|
92478
|
+
} else {
|
|
92479
|
+
context.push(object);
|
|
92480
|
+
}
|
|
92481
|
+
|
|
92482
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer && Buffer.isBuffer(object)) {
|
|
92483
|
+
write('buffer:');
|
|
92484
|
+
return write(object);
|
|
92485
|
+
}
|
|
92486
|
+
|
|
92487
|
+
if(objType !== 'object' && objType !== 'function') {
|
|
92488
|
+
if(this['_' + objType]) {
|
|
92489
|
+
this['_' + objType](object);
|
|
92490
|
+
} else if (options.ignoreUnknown) {
|
|
92491
|
+
return write('[' + objType + ']');
|
|
92492
|
+
} else {
|
|
92493
|
+
throw new Error('Unknown object type "' + objType + '"');
|
|
92494
|
+
}
|
|
92495
|
+
}else{
|
|
92496
|
+
var keys = Object.keys(object);
|
|
92497
|
+
if (options.unorderedObjects) {
|
|
92498
|
+
keys = keys.sort();
|
|
92499
|
+
}
|
|
92500
|
+
// Make sure to incorporate special properties, so
|
|
92501
|
+
// Types with different prototypes will produce
|
|
92502
|
+
// a different hash and objects derived from
|
|
92503
|
+
// different functions (`new Foo`, `new Bar`) will
|
|
92504
|
+
// produce different hashes.
|
|
92505
|
+
// We never do this for native functions since some
|
|
92506
|
+
// seem to break because of that.
|
|
92507
|
+
if (options.respectType !== false && !isNativeFunction(object)) {
|
|
92508
|
+
keys.splice(0, 0, 'prototype', '__proto__', 'constructor');
|
|
92509
|
+
}
|
|
92510
|
+
|
|
92511
|
+
if (options.excludeKeys) {
|
|
92512
|
+
keys = keys.filter(function(key) { return !options.excludeKeys(key); });
|
|
92513
|
+
}
|
|
92514
|
+
|
|
92515
|
+
write('object:' + keys.length + ':');
|
|
92516
|
+
var self = this;
|
|
92517
|
+
return keys.forEach(function(key){
|
|
92518
|
+
self.dispatch(key);
|
|
92519
|
+
write(':');
|
|
92520
|
+
if(!options.excludeValues) {
|
|
92521
|
+
self.dispatch(object[key]);
|
|
92522
|
+
}
|
|
92523
|
+
write(',');
|
|
92524
|
+
});
|
|
92525
|
+
}
|
|
92526
|
+
},
|
|
92527
|
+
_array: function(arr, unordered){
|
|
92528
|
+
unordered = typeof unordered !== 'undefined' ? unordered :
|
|
92529
|
+
options.unorderedArrays !== false; // default to options.unorderedArrays
|
|
92530
|
+
|
|
92531
|
+
var self = this;
|
|
92532
|
+
write('array:' + arr.length + ':');
|
|
92533
|
+
if (!unordered || arr.length <= 1) {
|
|
92534
|
+
return arr.forEach(function(entry) {
|
|
92535
|
+
return self.dispatch(entry);
|
|
92536
|
+
});
|
|
92537
|
+
}
|
|
92538
|
+
|
|
92539
|
+
// the unordered case is a little more complicated:
|
|
92540
|
+
// since there is no canonical ordering on objects,
|
|
92541
|
+
// i.e. {a:1} < {a:2} and {a:1} > {a:2} are both false,
|
|
92542
|
+
// we first serialize each entry using a PassThrough stream
|
|
92543
|
+
// before sorting.
|
|
92544
|
+
// also: we can’t use the same context array for all entries
|
|
92545
|
+
// since the order of hashing should *not* matter. instead,
|
|
92546
|
+
// we keep track of the additions to a copy of the context array
|
|
92547
|
+
// and add all of them to the global context array when we’re done
|
|
92548
|
+
var contextAdditions = [];
|
|
92549
|
+
var entries = arr.map(function(entry) {
|
|
92550
|
+
var strm = new PassThrough();
|
|
92551
|
+
var localContext = context.slice(); // make copy
|
|
92552
|
+
var hasher = typeHasher(options, strm, localContext);
|
|
92553
|
+
hasher.dispatch(entry);
|
|
92554
|
+
// take only what was added to localContext and append it to contextAdditions
|
|
92555
|
+
contextAdditions = contextAdditions.concat(localContext.slice(context.length));
|
|
92556
|
+
return strm.read().toString();
|
|
92557
|
+
});
|
|
92558
|
+
context = context.concat(contextAdditions);
|
|
92559
|
+
entries.sort();
|
|
92560
|
+
return this._array(entries, false);
|
|
92561
|
+
},
|
|
92562
|
+
_date: function(date){
|
|
92563
|
+
return write('date:' + date.toJSON());
|
|
92564
|
+
},
|
|
92565
|
+
_symbol: function(sym){
|
|
92566
|
+
return write('symbol:' + sym.toString());
|
|
92567
|
+
},
|
|
92568
|
+
_error: function(err){
|
|
92569
|
+
return write('error:' + err.toString());
|
|
92570
|
+
},
|
|
92571
|
+
_boolean: function(bool){
|
|
92572
|
+
return write('bool:' + bool.toString());
|
|
92573
|
+
},
|
|
92574
|
+
_string: function(string){
|
|
92575
|
+
write('string:' + string.length + ':');
|
|
92576
|
+
write(string.toString());
|
|
92577
|
+
},
|
|
92578
|
+
_function: function(fn){
|
|
92579
|
+
write('fn:');
|
|
92580
|
+
if (isNativeFunction(fn)) {
|
|
92581
|
+
this.dispatch('[native]');
|
|
92582
|
+
} else {
|
|
92583
|
+
this.dispatch(fn.toString());
|
|
92584
|
+
}
|
|
92585
|
+
|
|
92586
|
+
if (options.respectFunctionNames !== false) {
|
|
92587
|
+
// Make sure we can still distinguish native functions
|
|
92588
|
+
// by their name, otherwise String and Function will
|
|
92589
|
+
// have the same hash
|
|
92590
|
+
this.dispatch("function-name:" + String(fn.name));
|
|
92591
|
+
}
|
|
92592
|
+
|
|
92593
|
+
if (options.respectFunctionProperties) {
|
|
92594
|
+
this._object(fn);
|
|
92595
|
+
}
|
|
92596
|
+
},
|
|
92597
|
+
_number: function(number){
|
|
92598
|
+
return write('number:' + number.toString());
|
|
92599
|
+
},
|
|
92600
|
+
_xml: function(xml){
|
|
92601
|
+
return write('xml:' + xml.toString());
|
|
92602
|
+
},
|
|
92603
|
+
_null: function() {
|
|
92604
|
+
return write('Null');
|
|
92605
|
+
},
|
|
92606
|
+
_undefined: function() {
|
|
92607
|
+
return write('Undefined');
|
|
92608
|
+
},
|
|
92609
|
+
_regexp: function(regex){
|
|
92610
|
+
return write('regex:' + regex.toString());
|
|
92611
|
+
},
|
|
92612
|
+
_uint8array: function(arr){
|
|
92613
|
+
write('uint8array:');
|
|
92614
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92615
|
+
},
|
|
92616
|
+
_uint8clampedarray: function(arr){
|
|
92617
|
+
write('uint8clampedarray:');
|
|
92618
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92619
|
+
},
|
|
92620
|
+
_int8array: function(arr){
|
|
92621
|
+
write('uint8array:');
|
|
92622
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92623
|
+
},
|
|
92624
|
+
_uint16array: function(arr){
|
|
92625
|
+
write('uint16array:');
|
|
92626
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92627
|
+
},
|
|
92628
|
+
_int16array: function(arr){
|
|
92629
|
+
write('uint16array:');
|
|
92630
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92631
|
+
},
|
|
92632
|
+
_uint32array: function(arr){
|
|
92633
|
+
write('uint32array:');
|
|
92634
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92635
|
+
},
|
|
92636
|
+
_int32array: function(arr){
|
|
92637
|
+
write('uint32array:');
|
|
92638
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92639
|
+
},
|
|
92640
|
+
_float32array: function(arr){
|
|
92641
|
+
write('float32array:');
|
|
92642
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92643
|
+
},
|
|
92644
|
+
_float64array: function(arr){
|
|
92645
|
+
write('float64array:');
|
|
92646
|
+
return this.dispatch(Array.prototype.slice.call(arr));
|
|
92647
|
+
},
|
|
92648
|
+
_arraybuffer: function(arr){
|
|
92649
|
+
write('arraybuffer:');
|
|
92650
|
+
return this.dispatch(new Uint8Array(arr));
|
|
92651
|
+
},
|
|
92652
|
+
_url: function(url) {
|
|
92653
|
+
return write('url:' + url.toString(), 'utf8');
|
|
92654
|
+
},
|
|
92655
|
+
_map: function(map) {
|
|
92656
|
+
write('map:');
|
|
92657
|
+
var arr = Array.from(map);
|
|
92658
|
+
return this._array(arr, options.unorderedSets !== false);
|
|
92659
|
+
},
|
|
92660
|
+
_set: function(set) {
|
|
92661
|
+
write('set:');
|
|
92662
|
+
var arr = Array.from(set);
|
|
92663
|
+
return this._array(arr, options.unorderedSets !== false);
|
|
92664
|
+
},
|
|
92665
|
+
_blob: function() {
|
|
92666
|
+
if (options.ignoreUnknown) {
|
|
92667
|
+
return write('[blob]');
|
|
92668
|
+
}
|
|
92669
|
+
|
|
92670
|
+
throw Error('Hashing Blob objects is currently not supported\n' +
|
|
92671
|
+
'(see https://github.com/puleos/object-hash/issues/26)\n' +
|
|
92672
|
+
'Use "options.replacer" or "options.ignoreUnknown"\n');
|
|
92673
|
+
},
|
|
92674
|
+
_domwindow: function() { return write('domwindow'); },
|
|
92675
|
+
/* Node.js standard native objects */
|
|
92676
|
+
_process: function() { return write('process'); },
|
|
92677
|
+
_timer: function() { return write('timer'); },
|
|
92678
|
+
_pipe: function() { return write('pipe'); },
|
|
92679
|
+
_tcp: function() { return write('tcp'); },
|
|
92680
|
+
_udp: function() { return write('udp'); },
|
|
92681
|
+
_tty: function() { return write('tty'); },
|
|
92682
|
+
_statwatcher: function() { return write('statwatcher'); },
|
|
92683
|
+
_securecontext: function() { return write('securecontext'); },
|
|
92684
|
+
_connection: function() { return write('connection'); },
|
|
92685
|
+
_zlib: function() { return write('zlib'); },
|
|
92686
|
+
_context: function() { return write('context'); },
|
|
92687
|
+
_nodescript: function() { return write('nodescript'); },
|
|
92688
|
+
_httpparser: function() { return write('httpparser'); },
|
|
92689
|
+
_dataview: function() { return write('dataview'); },
|
|
92690
|
+
_signal: function() { return write('signal'); },
|
|
92691
|
+
_fsevent: function() { return write('fsevent'); },
|
|
92692
|
+
_tlswrap: function() { return write('tlswrap'); }
|
|
92693
|
+
};
|
|
92694
|
+
}
|
|
92695
|
+
|
|
92696
|
+
// Mini-implementation of stream.PassThrough
|
|
92697
|
+
// We are far from having need for the full implementation, and we can
|
|
92698
|
+
// make assumptions like "many writes, then only one final read"
|
|
92699
|
+
// and we can ignore encoding specifics
|
|
92700
|
+
function PassThrough() {
|
|
92701
|
+
return {
|
|
92702
|
+
buf: '',
|
|
92703
|
+
|
|
92704
|
+
write: function(b) {
|
|
92705
|
+
this.buf += b;
|
|
92706
|
+
},
|
|
92707
|
+
|
|
92708
|
+
end: function(b) {
|
|
92709
|
+
this.buf += b;
|
|
92710
|
+
},
|
|
92711
|
+
|
|
92712
|
+
read: function() {
|
|
92713
|
+
return this.buf;
|
|
92714
|
+
}
|
|
92715
|
+
};
|
|
92716
|
+
}
|
|
90635
92717
|
|
|
90636
92718
|
|
|
90637
92719
|
/***/ }),
|
|
@@ -98601,11 +100683,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
98601
100683
|
return result;
|
|
98602
100684
|
};
|
|
98603
100685
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
100686
|
+
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "./node_modules/@dra2020/dra-score/dist/dra-score.bundle.js"));
|
|
98604
100687
|
const preprocess_1 = __webpack_require__(/*! ./preprocess */ "./src/preprocess.ts");
|
|
98605
100688
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
98606
100689
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
98607
100690
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
98608
100691
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
100692
|
+
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
98609
100693
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
98610
100694
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
98611
100695
|
class AnalyticsSession {
|
|
@@ -98625,45 +100709,48 @@ class AnalyticsSession {
|
|
|
98625
100709
|
this.features = new D.Features(this, SessionRequest['data'], this.config['datasets']);
|
|
98626
100710
|
this.plan = new D.Plan(this, SessionRequest['plan']);
|
|
98627
100711
|
this.districts = new D.Districts(this, SessionRequest['districtShapes']);
|
|
98628
|
-
// TODO -
|
|
98629
|
-
|
|
98630
|
-
|
|
98631
|
-
|
|
98632
|
-
|
|
98633
|
-
|
|
98634
|
-
|
|
98635
|
-
|
|
98636
|
-
|
|
98637
|
-
|
|
98638
|
-
|
|
100712
|
+
// TODO - SCORE: Toggle
|
|
100713
|
+
if (this.useLegacy()) {
|
|
100714
|
+
console.log("Using legacy district-analytics.");
|
|
100715
|
+
// NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
100716
|
+
// we could want them to passed into an analytics session as data, along with
|
|
100717
|
+
// everything else. For now, this keeps branching out of the main code.
|
|
100718
|
+
results_1.doConfigureScales(this);
|
|
100719
|
+
}
|
|
100720
|
+
else {
|
|
100721
|
+
console.log("Using dra-score analytics.");
|
|
100722
|
+
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
100723
|
+
results_1.doConfigureScales(this);
|
|
100724
|
+
}
|
|
98639
100725
|
}
|
|
98640
100726
|
processConfig(config) {
|
|
98641
100727
|
// NOTE - Session settings are required:
|
|
98642
100728
|
// - Analytics suites can be defaulted to all with [], but
|
|
98643
100729
|
// - Dataset keys must be explicitly specified with 'dataset'
|
|
98644
|
-
// TODO -
|
|
98645
|
-
|
|
98646
|
-
// If the config passed in has no suites = [], use the default suites
|
|
98647
|
-
if (U.isArrayEmpty(config['suites'])) {
|
|
98648
|
-
config['suites'] = defaultSuites;
|
|
98649
|
-
}
|
|
100730
|
+
// TODO - SCORE: Delete
|
|
100731
|
+
config['suites'] = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
|
|
98650
100732
|
// Default the Census & redistricting cycle to 2010
|
|
98651
100733
|
if (!(U.keyExists('cycle', config)))
|
|
98652
100734
|
config['cycle'] = 2010;
|
|
98653
100735
|
return config;
|
|
98654
100736
|
}
|
|
100737
|
+
// TODO - SCORE: Toggle = Invert this logic
|
|
100738
|
+
useLegacy() {
|
|
100739
|
+
// TODO - SCORE: Opt-out
|
|
100740
|
+
return (U.keyExists('useScore', this.config) && (this.config['useScore'] != null) && (!(this.config['useScore']))) ? true : false;
|
|
100741
|
+
// TODO - SCORE: Opt-in
|
|
100742
|
+
// return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
|
|
100743
|
+
}
|
|
98655
100744
|
// Using the the data in the analytics session, calculate all the
|
|
98656
100745
|
// analytics & validations, saving/updating the individual test results.
|
|
98657
|
-
analyzePlan(bLog = false) {
|
|
100746
|
+
analyzePlan(bLog = false, overridesJSON) {
|
|
98658
100747
|
try {
|
|
98659
100748
|
preprocess_1.doPreprocessData(this, bLog);
|
|
98660
100749
|
analyze_1.doAnalyzeDistricts(this, bLog);
|
|
98661
100750
|
analyze_1.doAnalyzePlan(this, bLog);
|
|
98662
100751
|
// TODO - SCORE
|
|
98663
100752
|
this._profile = score_1.profilePlan(this, bLog);
|
|
98664
|
-
|
|
98665
|
-
this._scorecard = score_1.scorePlan(this._profile, bLog);
|
|
98666
|
-
// TODO - SCORE
|
|
100753
|
+
this._scorecard = score_1.scorePlan(this, this._profile, bLog, overridesJSON);
|
|
98667
100754
|
results_1.doAnalyzePostProcessing(this, bLog);
|
|
98668
100755
|
}
|
|
98669
100756
|
catch (_a) {
|
|
@@ -98684,13 +100771,6 @@ class AnalyticsSession {
|
|
|
98684
100771
|
getPlanScorecard(bLog = false) {
|
|
98685
100772
|
return this._scorecard;
|
|
98686
100773
|
}
|
|
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
100774
|
// TODO - SCORE
|
|
98695
100775
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
98696
100776
|
getRequirementsChecklist(bLog = false) {
|
|
@@ -98699,19 +100779,82 @@ class AnalyticsSession {
|
|
|
98699
100779
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
98700
100780
|
getDiscontiguousDistrictFeatures(bLog = false) {
|
|
98701
100781
|
// Get the (possibly empty) list of discontiguous district IDs
|
|
98702
|
-
|
|
98703
|
-
|
|
100782
|
+
const contiguousTest = this.getTest(1 /* Contiguous */);
|
|
100783
|
+
const discontiguousDistrictIDs = contiguousTest['details']['discontiguousDistricts'] || [];
|
|
98704
100784
|
// Convert them into a (possibly empty) list of features
|
|
98705
100785
|
let discontiguousDistrictFeatures = { type: 'FeatureCollection', features: [] };
|
|
98706
100786
|
if (!(U.isArrayEmpty(discontiguousDistrictIDs))) {
|
|
98707
100787
|
for (let id of discontiguousDistrictIDs) {
|
|
98708
100788
|
let poly = this.districts.getDistrictShapeByID(id);
|
|
98709
|
-
if (poly)
|
|
98710
|
-
|
|
100789
|
+
if (poly) {
|
|
100790
|
+
// If a district has a shape & it is not contiguous, by definition,
|
|
100791
|
+
// it will be a Multipolygon, i.e., it will have multiple pieces, some
|
|
100792
|
+
// possibly embedded w/in other districts. Get & add all the pieces.
|
|
100793
|
+
const districtParts = geofeature_1.polyParts(poly);
|
|
100794
|
+
discontiguousDistrictFeatures.features.push(...districtParts.features);
|
|
100795
|
+
// discontiguousDistrictFeatures.features.push(poly);
|
|
100796
|
+
}
|
|
98711
100797
|
}
|
|
98712
100798
|
}
|
|
98713
100799
|
return discontiguousDistrictFeatures;
|
|
98714
100800
|
}
|
|
100801
|
+
// Comments clipped from dra-client geodistrict.ts.
|
|
100802
|
+
// Discontiguous polygons are:
|
|
100803
|
+
// 1. All polygons in a multi-polygon; and
|
|
100804
|
+
// 2. All holes in a otherwise cohesive polygon.
|
|
100805
|
+
// Note that all non-cohesive features are always simple polygons.
|
|
100806
|
+
/*
|
|
100807
|
+
let i: number, j: number;
|
|
100808
|
+
let nPoly: number = 0;
|
|
100809
|
+
for (i = 0;nPoly == 0 && i < this.cacheDistricts.features.length;i++)
|
|
100810
|
+
{
|
|
100811
|
+
let f = this.cacheDistricts.features[i];
|
|
100812
|
+
|
|
100813
|
+
if (f.geometry.type === 'MultiPolygon')
|
|
100814
|
+
nPoly += f.geometry.coordinates.length;
|
|
100815
|
+
else if (f.geometry.type === 'Polygon' && f.geometry.coordinates.length)
|
|
100816
|
+
nPoly += (f.geometry.coordinates.length - 1);
|
|
100817
|
+
}
|
|
100818
|
+
if (nPoly)
|
|
100819
|
+
{
|
|
100820
|
+
this.cacheNoncohesive = {type: 'FeatureCollection', features: []};
|
|
100821
|
+
let af: any = this.cacheNoncohesive.features;
|
|
100822
|
+
let oUnique: any = {};
|
|
100823
|
+
|
|
100824
|
+
// First add discontiguous polygons
|
|
100825
|
+
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
100826
|
+
{
|
|
100827
|
+
let f = this.cacheDistricts.features[i];
|
|
100828
|
+
|
|
100829
|
+
if (f.geometry.type === 'MultiPolygon')
|
|
100830
|
+
{
|
|
100831
|
+
// Push all non-contiguous polygons
|
|
100832
|
+
for (j = 0;j < f.geometry.coordinates.length;j++)
|
|
100833
|
+
{
|
|
100834
|
+
let p: any = f.geometry.coordinates[j];
|
|
100835
|
+
oUnique[Hash.qhash(p[0])] = true;
|
|
100836
|
+
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: p}});
|
|
100837
|
+
}
|
|
100838
|
+
}
|
|
100839
|
+
}
|
|
100840
|
+
|
|
100841
|
+
// Now add unique holes
|
|
100842
|
+
for (i = 0;i < this.cacheDistricts.features.length;i++)
|
|
100843
|
+
{
|
|
100844
|
+
let f = this.cacheDistricts.features[i];
|
|
100845
|
+
|
|
100846
|
+
if (f.geometry.type === 'Polygon')
|
|
100847
|
+
{
|
|
100848
|
+
// Push all holes from this polygon
|
|
100849
|
+
for (j = 1;j < f.geometry.coordinates.length;j++)
|
|
100850
|
+
{
|
|
100851
|
+
let p: any = f.geometry.coordinates[j];
|
|
100852
|
+
if (oUnique[Hash.qhash(p)] === undefined)
|
|
100853
|
+
af.push({type: 'Feature', properties: {id: `${af.length + 1}`}, geometry: {type: 'Polygon', coordinates: [p]}});
|
|
100854
|
+
}
|
|
100855
|
+
}
|
|
100856
|
+
}
|
|
100857
|
+
} */
|
|
98715
100858
|
// HELPERS USED INTERNALLY
|
|
98716
100859
|
// Get an individual test, so you can drive UI with the results.
|
|
98717
100860
|
getTest(testID) {
|
|
@@ -98727,9 +100870,21 @@ class AnalyticsSession {
|
|
|
98727
100870
|
// Return a pointer to the the test entry for this test
|
|
98728
100871
|
return this.tests[testID];
|
|
98729
100872
|
}
|
|
98730
|
-
// NOTE - Not sure why this has to be up here
|
|
100873
|
+
// NOTE - Not sure why this has to be up here ...
|
|
98731
100874
|
populationDeviationThreshold() {
|
|
98732
|
-
|
|
100875
|
+
// TODO - SCORE: Toggle
|
|
100876
|
+
if (this.useLegacy()) {
|
|
100877
|
+
return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
|
|
100878
|
+
}
|
|
100879
|
+
else {
|
|
100880
|
+
// NOTE - This assumes the plan has been profiled
|
|
100881
|
+
const scorer = new Score.Scorer();
|
|
100882
|
+
const popdev = scorer.populationDeviationThreshold(this.legislativeDistricts);
|
|
100883
|
+
return popdev;
|
|
100884
|
+
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
100885
|
+
// NOTE - The plan may not have been scored yet, i.e., no scorecard yet.
|
|
100886
|
+
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
100887
|
+
}
|
|
98733
100888
|
}
|
|
98734
100889
|
}
|
|
98735
100890
|
exports.AnalyticsSession = AnalyticsSession;
|
|
@@ -98905,7 +101060,6 @@ class Districts {
|
|
|
98905
101060
|
let outerThis = this;
|
|
98906
101061
|
// Default the pop dev % for the dummy Unassigned district to 0%.
|
|
98907
101062
|
// Default the pop dev % for real (1–N) but empty districts to 100%.
|
|
98908
|
-
// TODO - SCORE
|
|
98909
101063
|
let popDevPct = (i > 0) ? (targetSize / targetSize) : 0 / targetSize;
|
|
98910
101064
|
// Get the geoIDs assigned to the district
|
|
98911
101065
|
// Guard against empty districts
|
|
@@ -98932,7 +101086,6 @@ class Districts {
|
|
|
98932
101086
|
// NOTE - SPLITTING
|
|
98933
101087
|
// Total population by counties w/in a district,
|
|
98934
101088
|
// except the dummy unassigned district 0
|
|
98935
|
-
// TODO - VFEATURE
|
|
98936
101089
|
if (i > 0)
|
|
98937
101090
|
countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
|
|
98938
101091
|
// Democratic and Republican vote totals
|
|
@@ -99106,10 +101259,7 @@ class Districts {
|
|
|
99106
101259
|
compact_1.extractDistrictProperties(this._session, bLog);
|
|
99107
101260
|
}
|
|
99108
101261
|
getCountyIndex(geoID) {
|
|
99109
|
-
// TODO - VFEATURE
|
|
99110
101262
|
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
99111
|
-
// let countyGeoID = U.parseGeoID(geoID)['county'] as string;
|
|
99112
|
-
// let countyFIPS = U.getFIPSFromCountyGeoID(countyGeoID);
|
|
99113
101263
|
let countyIndex = this._session.counties.indexFromFIPS(countyFIPS);
|
|
99114
101264
|
return countyIndex;
|
|
99115
101265
|
}
|
|
@@ -99358,11 +101508,45 @@ exports.doAnalyzeDistricts = doAnalyzeDistricts;
|
|
|
99358
101508
|
// NOTE - I could make this table-driven, but I'm thinking that the explicit
|
|
99359
101509
|
// calls might make chunking for aync easier.
|
|
99360
101510
|
function doAnalyzePlan(s, bLog = false) {
|
|
99361
|
-
// TODO -
|
|
99362
|
-
|
|
99363
|
-
|
|
99364
|
-
|
|
99365
|
-
|
|
101511
|
+
// TODO - SCORE: Toggle
|
|
101512
|
+
if (s.useLegacy()) {
|
|
101513
|
+
// Disable most legacy analytics
|
|
101514
|
+
// Get the requested suites, and only execute those tests
|
|
101515
|
+
let requestedSuites = s.config['suites'];
|
|
101516
|
+
// Tests in the "Legal" suite, i.e., pass/ fail constraints
|
|
101517
|
+
if (requestedSuites.includes(0 /* Legal */)) {
|
|
101518
|
+
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
101519
|
+
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
101520
|
+
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
101521
|
+
s.tests[4 /* PopulationDeviation */] = equal_1.doPopulationDeviation(s, bLog);
|
|
101522
|
+
// NOTE - I can't check whether a population deviation is legal or not, until
|
|
101523
|
+
// the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
101524
|
+
// the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
101525
|
+
// from PopulationDeviation, as part of scorecard or test log preparation.
|
|
101526
|
+
// Create an empty test entry here though ...
|
|
101527
|
+
s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
|
|
101528
|
+
}
|
|
101529
|
+
// Tests in the "Fair" suite
|
|
101530
|
+
if (requestedSuites.includes(1 /* Fair */)) {
|
|
101531
|
+
s.tests[11 /* SeatsBias */] = political_1.doSeatsBias(s, bLog);
|
|
101532
|
+
s.tests[12 /* VotesBias */] = political_1.doVotesBias(s, bLog);
|
|
101533
|
+
s.tests[13 /* Responsiveness */] = political_1.doResponsiveness(s, bLog);
|
|
101534
|
+
s.tests[14 /* ResponsiveDistricts */] = political_1.doResponsiveDistricts(s, bLog);
|
|
101535
|
+
s.tests[15 /* EfficiencyGap */] = political_1.doEfficiencyGap(s, bLog);
|
|
101536
|
+
s.tests[16 /* MajorityMinorityDistricts */] = minority_1.doMajorityMinorityDistricts(s, bLog);
|
|
101537
|
+
}
|
|
101538
|
+
// Tests in the "Best" suite, i.e., criteria for better/worse
|
|
101539
|
+
if (requestedSuites.includes(2 /* Best */)) {
|
|
101540
|
+
s.tests[5 /* Reock */] = compact_1.doReock(s, bLog);
|
|
101541
|
+
s.tests[6 /* PolsbyPopper */] = compact_1.doPolsbyPopper(s, bLog);
|
|
101542
|
+
s.tests[7 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
101543
|
+
s.tests[10 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
|
|
101544
|
+
s.tests[8 /* CountySplitting */] = cohesive_1.doCountySplitting(s, bLog);
|
|
101545
|
+
s.tests[9 /* DistrictSplitting */] = cohesive_1.doDistrictSplitting(s, bLog);
|
|
101546
|
+
}
|
|
101547
|
+
}
|
|
101548
|
+
else {
|
|
101549
|
+
// TODO - SCORE: Except these. Continue to do these here vs. dra-score.
|
|
99366
101550
|
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
99367
101551
|
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
99368
101552
|
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
@@ -99373,24 +101557,8 @@ function doAnalyzePlan(s, bLog = false) {
|
|
|
99373
101557
|
// from PopulationDeviation, as part of scorecard or test log preparation.
|
|
99374
101558
|
// Create an empty test entry here though ...
|
|
99375
101559
|
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
101560
|
s.tests[7 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
99391
101561
|
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
101562
|
}
|
|
99395
101563
|
// Enable a Test Log and Scorecard to be generated
|
|
99396
101564
|
s.bPlanAnalyzed = true;
|
|
@@ -99987,6 +102155,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
99987
102155
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
99988
102156
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
99989
102157
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
102158
|
+
// TODO - SCORE: Delete
|
|
99990
102159
|
function doPopulationDeviation(s, bLog = false) {
|
|
99991
102160
|
let test = s.getTest(4 /* PopulationDeviation */);
|
|
99992
102161
|
let targetSize = s.state.totalPop / s.state.nDistricts;
|
|
@@ -100025,8 +102194,8 @@ function doHasEqualPopulations(s, bLog = false) {
|
|
|
100025
102194
|
let test = s.getTest(3 /* EqualPopulation */);
|
|
100026
102195
|
// Get the normalized population deviation %
|
|
100027
102196
|
let popDevTest = s.getTest(4 /* PopulationDeviation */);
|
|
100028
|
-
|
|
100029
|
-
|
|
102197
|
+
const popDevPct = popDevTest['score'];
|
|
102198
|
+
const popDevNormalized = popDevTest['normalizedScore'];
|
|
100030
102199
|
// Populate the test entry
|
|
100031
102200
|
if (popDevNormalized > 0) {
|
|
100032
102201
|
test['score'] = true;
|
|
@@ -100068,6 +102237,23 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
100068
102237
|
};
|
|
100069
102238
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
100070
102239
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "./node_modules/@dra2020/poly/dist/poly.js"));
|
|
102240
|
+
// HELPER
|
|
102241
|
+
function polyParts(poly) {
|
|
102242
|
+
let parts = { type: 'FeatureCollection', features: [] };
|
|
102243
|
+
let af = parts.features;
|
|
102244
|
+
if (poly.geometry.type === 'MultiPolygon') {
|
|
102245
|
+
// Push all non-contiguous polygons
|
|
102246
|
+
for (let j = 0; j < poly.geometry.coordinates.length; j++) {
|
|
102247
|
+
let onePoly = poly.geometry.coordinates[j];
|
|
102248
|
+
af.push({ type: 'Feature', properties: { id: `${af.length + 1}` }, geometry: { type: 'Polygon', coordinates: onePoly } });
|
|
102249
|
+
}
|
|
102250
|
+
}
|
|
102251
|
+
else {
|
|
102252
|
+
parts.features.push(poly);
|
|
102253
|
+
}
|
|
102254
|
+
return parts;
|
|
102255
|
+
}
|
|
102256
|
+
exports.polyParts = polyParts;
|
|
100071
102257
|
// CARTESIAN SHIMS OVER 'POLY' FUNCTIONS
|
|
100072
102258
|
// TODO - POLY: Confirm Cartesian calculations
|
|
100073
102259
|
function gfArea(poly) {
|
|
@@ -100369,10 +102555,7 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
100369
102555
|
// Sum total population across the state
|
|
100370
102556
|
s.state.totalPop += value;
|
|
100371
102557
|
// Get the county FIPS code for the feature
|
|
100372
|
-
// TODO - VFEATURE
|
|
100373
102558
|
let countyFIPS = U.parseGeoID(geoID)['county'];
|
|
100374
|
-
// let county = U.parseGeoID(geoID)['county'] as string;
|
|
100375
|
-
// let countyFIPS = U.getFIPSFromCountyGeoID(county);
|
|
100376
102559
|
// If a subtotal for the county doesn't exist, initialize one
|
|
100377
102560
|
if (!(U.keyExists(countyFIPS, totalByCounty))) {
|
|
100378
102561
|
totalByCounty[countyFIPS] = 0;
|
|
@@ -100390,8 +102573,8 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
100390
102573
|
let fipsCodes = U.getObjectKeys(totalByCounty);
|
|
100391
102574
|
// Sort the results
|
|
100392
102575
|
fipsCodes = fipsCodes.sort();
|
|
100393
|
-
//
|
|
100394
|
-
// Add a dummy county, for county-district splitting analysis
|
|
102576
|
+
// NOTE - This was added for the legacy SPLITTING implementation.
|
|
102577
|
+
// Add a dummy county, for county-district splitting analysis.
|
|
100395
102578
|
fipsCodes.unshift('000');
|
|
100396
102579
|
// Create the ID-ordinal map
|
|
100397
102580
|
for (let i in fipsCodes) {
|
|
@@ -100481,6 +102664,7 @@ const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
|
100481
102664
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
100482
102665
|
const state_reqs_json_1 = __importDefault(__webpack_require__(/*! ../static/state-reqs.json */ "./static/state-reqs.json"));
|
|
100483
102666
|
// Example
|
|
102667
|
+
// TODO - DELETE?
|
|
100484
102668
|
let sampleRequirements = {
|
|
100485
102669
|
score: 2 /* Red */,
|
|
100486
102670
|
metrics: {
|
|
@@ -100504,6 +102688,7 @@ let sampleRequirements = {
|
|
|
100504
102688
|
stateReqs: "https://www.brennancenter.org/sites/default/files/publications/2019_06_50States_FINALsinglepages_20.pdf"
|
|
100505
102689
|
}
|
|
100506
102690
|
};
|
|
102691
|
+
// TODO - DELETE
|
|
100507
102692
|
let sampleCompactness = {
|
|
100508
102693
|
score: 60,
|
|
100509
102694
|
metrics: {
|
|
@@ -100516,6 +102701,7 @@ let sampleCompactness = {
|
|
|
100516
102701
|
},
|
|
100517
102702
|
resources: {}
|
|
100518
102703
|
};
|
|
102704
|
+
// TODO - DELETE
|
|
100519
102705
|
let sampleSplitting = {
|
|
100520
102706
|
score: 73,
|
|
100521
102707
|
metrics: {
|
|
@@ -100533,7 +102719,7 @@ let sampleSplitting = {
|
|
|
100533
102719
|
datasets: {},
|
|
100534
102720
|
resources: {}
|
|
100535
102721
|
};
|
|
100536
|
-
// TODO -
|
|
102722
|
+
// TODO - DELETE
|
|
100537
102723
|
let samplePartisan = {
|
|
100538
102724
|
score: 100,
|
|
100539
102725
|
metrics: {
|
|
@@ -100548,7 +102734,7 @@ let samplePartisan = {
|
|
|
100548
102734
|
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
100549
102735
|
}
|
|
100550
102736
|
};
|
|
100551
|
-
// TODO -
|
|
102737
|
+
// TODO - DELETE
|
|
100552
102738
|
let sampleMinority = {
|
|
100553
102739
|
score: null,
|
|
100554
102740
|
metrics: {
|
|
@@ -100575,6 +102761,7 @@ let sampleMinority = {
|
|
|
100575
102761
|
},
|
|
100576
102762
|
resources: {}
|
|
100577
102763
|
};
|
|
102764
|
+
// TODO - DELETE
|
|
100578
102765
|
exports.samplePlanAnalytics = {
|
|
100579
102766
|
requirements: sampleRequirements,
|
|
100580
102767
|
compactness: sampleCompactness,
|
|
@@ -100583,232 +102770,6 @@ exports.samplePlanAnalytics = {
|
|
|
100583
102770
|
partisan: samplePartisan,
|
|
100584
102771
|
minority: sampleMinority
|
|
100585
102772
|
};
|
|
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
102773
|
function prepareRequirementsChecklist(s, bLog = false) {
|
|
100813
102774
|
if (!(s.bPostProcessingDone)) {
|
|
100814
102775
|
doAnalyzePostProcessing(s);
|
|
@@ -100816,34 +102777,40 @@ function prepareRequirementsChecklist(s, bLog = false) {
|
|
|
100816
102777
|
// REQUIREMENTS CATEGORY
|
|
100817
102778
|
let paRequirements;
|
|
100818
102779
|
{
|
|
100819
|
-
|
|
100820
|
-
|
|
100821
|
-
|
|
100822
|
-
|
|
102780
|
+
const completeTest = s.getTest(0 /* Complete */);
|
|
102781
|
+
const contiguousTest = s.getTest(1 /* Contiguous */);
|
|
102782
|
+
const freeOfHolesTest = s.getTest(2 /* FreeOfHoles */);
|
|
102783
|
+
const equalPopulationTest = s.getTest(3 /* EqualPopulation */);
|
|
100823
102784
|
// Combine individual checks into an overall score
|
|
100824
|
-
//
|
|
102785
|
+
// NOTE - Until we add three-state support top to bottom in
|
|
100825
102786
|
// requirements/validations, map booleans to tri-states here.
|
|
100826
|
-
|
|
100827
|
-
|
|
100828
|
-
|
|
100829
|
-
|
|
102787
|
+
const completeMetric = U.mapBooleanToTriState(completeTest['score']);
|
|
102788
|
+
const contiguousMetric = U.mapBooleanToTriState(contiguousTest['score']);
|
|
102789
|
+
const freeOfHolesMetric = U.mapBooleanToTriState(freeOfHolesTest['score']);
|
|
102790
|
+
const equalPopulationMetric = U.mapBooleanToTriState(equalPopulationTest['score']);
|
|
100830
102791
|
let reqScore = 0 /* Green */;
|
|
100831
|
-
|
|
102792
|
+
const checks = [completeMetric, contiguousMetric, freeOfHolesMetric, equalPopulationMetric];
|
|
100832
102793
|
if (checks.includes(1 /* Yellow */))
|
|
100833
102794
|
reqScore = 1 /* Yellow */;
|
|
100834
102795
|
if (checks.includes(2 /* Red */))
|
|
100835
102796
|
reqScore = 2 /* Red */;
|
|
100836
102797
|
// Get values to support details entries
|
|
100837
|
-
|
|
100838
|
-
|
|
100839
|
-
|
|
100840
|
-
|
|
100841
|
-
|
|
100842
|
-
|
|
100843
|
-
|
|
102798
|
+
const unassignedFeaturesDetail = U.deepCopy(completeTest['details']['unassignedFeatures']) || [];
|
|
102799
|
+
const emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
102800
|
+
const discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
102801
|
+
const embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
102802
|
+
// TODO - SCORE: DELETE - This code is hooked correctly to use dra-score
|
|
102803
|
+
// const scorecard = s._scorecard as Score.Scorecard;
|
|
102804
|
+
// const populationDeviation = scorecard.best.populationDeviation.raw;
|
|
102805
|
+
const populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
102806
|
+
// console.log("Population deviations =", populationDeviationDetail, populationDeviation);
|
|
102807
|
+
// const deviationThreshold = scorecard.best.populationDeviation.notes['threshold'];
|
|
102808
|
+
const deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
102809
|
+
// console.log("Population deviation thresholds =", deviationThresholdDetail, deviationThreshold);
|
|
102810
|
+
const xx = s.state.xx;
|
|
100844
102811
|
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
100845
|
-
|
|
100846
|
-
|
|
102812
|
+
const stateReqsDict = state_reqs_json_1.default;
|
|
102813
|
+
const reqLinkToStateReqs = stateReqsDict[xx];
|
|
100847
102814
|
// Populate the category
|
|
100848
102815
|
paRequirements = {
|
|
100849
102816
|
score: reqScore,
|
|
@@ -101106,19 +103073,30 @@ exports.doConfigureScales = doConfigureScales;
|
|
|
101106
103073
|
// Postprocess analytics - Normalize numeric results and derive secondary tests.
|
|
101107
103074
|
// Do this after analytics have been run and before preparing a test log or scorecard.
|
|
101108
103075
|
function doAnalyzePostProcessing(s, bLog = false) {
|
|
101109
|
-
//
|
|
101110
|
-
|
|
101111
|
-
|
|
101112
|
-
|
|
101113
|
-
|
|
101114
|
-
|
|
101115
|
-
|
|
101116
|
-
|
|
101117
|
-
|
|
101118
|
-
|
|
101119
|
-
|
|
103076
|
+
// TODO - SCORE: Toggle
|
|
103077
|
+
if (s.useLegacy()) {
|
|
103078
|
+
// Normalize the raw scores for all the numerics tests
|
|
103079
|
+
let testResults = U.getNumericObjectKeys(testDefns);
|
|
103080
|
+
for (let testID of testResults) {
|
|
103081
|
+
if (testDefns[testID]['normalize']) {
|
|
103082
|
+
let testResult = s.getTest(testID);
|
|
103083
|
+
let rawScore = testResult['score'];
|
|
103084
|
+
let normalizedScore;
|
|
103085
|
+
normalizedScore = U.normalize(rawScore, s.testScales[testID]);
|
|
103086
|
+
testResult['normalizedScore'] = normalizedScore;
|
|
103087
|
+
// Add the scale used to normalize the raw score to the details
|
|
103088
|
+
testResult['details']['scale'] = s.testScales[testID].scale;
|
|
103089
|
+
}
|
|
101120
103090
|
}
|
|
101121
103091
|
}
|
|
103092
|
+
else {
|
|
103093
|
+
// Just populate the normalized population deviation score in the test
|
|
103094
|
+
const scorecard = s._scorecard;
|
|
103095
|
+
let test = s.getTest(4 /* PopulationDeviation */);
|
|
103096
|
+
test['normalizedScore'] = scorecard.traditionalPrinciples.populationDeviation.normalized;
|
|
103097
|
+
// TODO - DELETE
|
|
103098
|
+
// test['normalizedScore'] = scorecard.best.populationDeviation.normalized;
|
|
103099
|
+
}
|
|
101122
103100
|
// Derive secondary tests
|
|
101123
103101
|
analyze_1.doDeriveSecondaryTests(s, bLog);
|
|
101124
103102
|
// Toggle the semaphore, so postprocessing isn't for both the testlog & scorecard
|
|
@@ -101163,7 +103141,7 @@ function profilePlan(s, bLog = false) {
|
|
|
101163
103141
|
const geoPropsByDistrict = makeArrayOfGeoProps(s, bLog);
|
|
101164
103142
|
const splits = makeNakedCxD(s);
|
|
101165
103143
|
const summaryRow = s.districts.numberOfRows() - 1;
|
|
101166
|
-
const statewideVf = s.districts.statistics[D.DistrictField.DemPct][summaryRow];
|
|
103144
|
+
const statewideVf = U.trim(s.districts.statistics[D.DistrictField.DemPct][summaryRow], 6);
|
|
101167
103145
|
const vpiArray = U.deepCopy(s.districts.statistics[D.DistrictField.DemPct].slice(1, -1));
|
|
101168
103146
|
const demographicsByDistrict = makeArrayOfDemographics(s);
|
|
101169
103147
|
const profile = {
|
|
@@ -101201,13 +103179,11 @@ function makeNakedCxD(s, bLog = false) {
|
|
|
101201
103179
|
let CxD = [];
|
|
101202
103180
|
// Remove the unassigned & total dummy "districts"
|
|
101203
103181
|
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
101204
|
-
// TODO - SCORE: OH has an extra county!?!
|
|
101205
103182
|
const splits = U.deepCopy(adornedCxD[districtID].slice(1));
|
|
101206
103183
|
CxD.push(splits);
|
|
101207
103184
|
}
|
|
101208
103185
|
return CxD;
|
|
101209
103186
|
}
|
|
101210
|
-
// TODO - SCORE: Convert dict of geo props to array by district index
|
|
101211
103187
|
function makeArrayOfGeoProps(s, bLog = false) {
|
|
101212
103188
|
let geometryByDistrict = [];
|
|
101213
103189
|
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
|
|
@@ -101241,9 +103217,30 @@ function makeArrayOfDemographics(s, bLog = false) {
|
|
|
101241
103217
|
return demographicsArray;
|
|
101242
103218
|
}
|
|
101243
103219
|
// SCORE A PLAN
|
|
101244
|
-
function scorePlan(p, bLog = false) {
|
|
103220
|
+
function scorePlan(s, p, bLog = false, overridesJSON) {
|
|
101245
103221
|
let scorer = new Score.Scorer();
|
|
101246
|
-
|
|
103222
|
+
const scorecard = scorer.score(p, overridesJSON);
|
|
103223
|
+
// TODO - SCORE: Toggle: Before returning, create a dummy population deviation
|
|
103224
|
+
// test, for doHasEqualPopulations() to use later. This is preserving the old
|
|
103225
|
+
// calling sequence.
|
|
103226
|
+
let test = s.getTest(4 /* PopulationDeviation */);
|
|
103227
|
+
// TODO - SCORE: U.trim(popDev)???
|
|
103228
|
+
// const popDev = scorecard.best.populationDeviation.raw;
|
|
103229
|
+
// Get the raw population deviation
|
|
103230
|
+
const popDev = scorecard.traditionalPrinciples.populationDeviation.raw;
|
|
103231
|
+
// Populate the test entry
|
|
103232
|
+
test['score'] = popDev;
|
|
103233
|
+
test['details'] = { 'maxDeviation': scorecard.traditionalPrinciples.populationDeviation.notes['maxDeviation'] };
|
|
103234
|
+
// TODO - DELETE
|
|
103235
|
+
// test['details'] = { 'maxDeviation': scorecard.best.populationDeviation.notes['maxDeviation'] };
|
|
103236
|
+
// Populate the N+1 summary "district" in district.statistics
|
|
103237
|
+
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
103238
|
+
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
103239
|
+
let summaryRow = s.districts.numberOfRows() - 1;
|
|
103240
|
+
totalPop[summaryRow] = p.populationProfile.targetSize;
|
|
103241
|
+
popDevPct[summaryRow] = popDev;
|
|
103242
|
+
//
|
|
103243
|
+
return scorecard;
|
|
101247
103244
|
}
|
|
101248
103245
|
exports.scorePlan = scorePlan;
|
|
101249
103246
|
|
|
@@ -101305,6 +103302,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
101305
103302
|
return result;
|
|
101306
103303
|
};
|
|
101307
103304
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
103305
|
+
const DT = __importStar(__webpack_require__(/*! @dra2020/dra-types */ "./node_modules/@dra2020/dra-types/dist/dra-types.js"));
|
|
101308
103306
|
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
101309
103307
|
// PLAN HELPERS
|
|
101310
103308
|
// Is a "neighbor" in state?
|
|
@@ -101332,7 +103330,6 @@ function getDistrict(plan, geoID) {
|
|
|
101332
103330
|
}
|
|
101333
103331
|
exports.getDistrict = getDistrict;
|
|
101334
103332
|
// WORKING WITH GEOIDS
|
|
101335
|
-
// TODO - VFEATURE
|
|
101336
103333
|
function parseGeoID(geoID) {
|
|
101337
103334
|
let bVfeature = false;
|
|
101338
103335
|
// Rewrite vfeature GEOIDs to enable lexical parsing of higher-level parts
|
|
@@ -101340,12 +103337,7 @@ function parseGeoID(geoID) {
|
|
|
101340
103337
|
// Example: vfeature_39153153ASV_0_28e0bc2c8163e5982e1da2d61e2388a8325c575e
|
|
101341
103338
|
if (geoID.indexOf('vfeature') >= 0) {
|
|
101342
103339
|
bVfeature = true;
|
|
101343
|
-
|
|
101344
|
-
let parentGeoID = geoID.slice(9);
|
|
101345
|
-
// Strip off trailing goo
|
|
101346
|
-
const uPos = parentGeoID.indexOf('_');
|
|
101347
|
-
parentGeoID = parentGeoID.slice(0, uPos);
|
|
101348
|
-
geoID = parentGeoID;
|
|
103340
|
+
geoID = DT.vgeoidToGeoid(geoID);
|
|
101349
103341
|
}
|
|
101350
103342
|
const parts = {
|
|
101351
103343
|
vfeature: bVfeature,
|
|
@@ -101353,29 +103345,9 @@ function parseGeoID(geoID) {
|
|
|
101353
103345
|
county: geoID.substring(2, 5),
|
|
101354
103346
|
rest: geoID.slice(5)
|
|
101355
103347
|
};
|
|
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
103348
|
return parts;
|
|
101370
103349
|
}
|
|
101371
103350
|
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
103351
|
function isWaterOnly(geoID) {
|
|
101380
103352
|
let waterOnlySignature = 'ZZZZZZ';
|
|
101381
103353
|
if (geoID.indexOf(waterOnlySignature) >= 0)
|
|
@@ -102276,113 +104248,6 @@ function formatNumber(n) {
|
|
|
102276
104248
|
let p = S.PRECISION;
|
|
102277
104249
|
return n.toLocaleString('en-US', { minimumFractionDigits: p, maximumFractionDigits: p });
|
|
102278
104250
|
}
|
|
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
104251
|
function echoDistrictStatistics(ds) {
|
|
102387
104252
|
console.log("District Statistics:");
|
|
102388
104253
|
for (let row of ds.table) {
|
|
@@ -102493,6 +104358,17 @@ module.exports = require("assert");
|
|
|
102493
104358
|
|
|
102494
104359
|
/***/ }),
|
|
102495
104360
|
|
|
104361
|
+
/***/ "crypto":
|
|
104362
|
+
/*!*************************!*\
|
|
104363
|
+
!*** external "crypto" ***!
|
|
104364
|
+
\*************************/
|
|
104365
|
+
/*! no static exports found */
|
|
104366
|
+
/***/ (function(module, exports) {
|
|
104367
|
+
|
|
104368
|
+
module.exports = require("crypto");
|
|
104369
|
+
|
|
104370
|
+
/***/ }),
|
|
104371
|
+
|
|
102496
104372
|
/***/ "fs":
|
|
102497
104373
|
/*!*********************!*\
|
|
102498
104374
|
!*** external "fs" ***!
|