@dra2020/district-analytics 4.3.6 → 5.0.2
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/README.md +1 -1
- package/dist/cli.js +89 -1136
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +87 -1044
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/minority.d.ts +4 -0
- package/package.json +2 -2
|
@@ -121,7 +121,6 @@ const preprocess_1 = __webpack_require__(/*! ./preprocess */ "./src/preprocess.t
|
|
|
121
121
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
122
122
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
123
123
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
124
|
-
// import { doConfigureScales, doAnalyzePostProcessing, RequirementsChecklist} from './results' // TODO - DELETE
|
|
125
124
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
126
125
|
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
127
126
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
@@ -132,7 +131,6 @@ class AnalyticsSession {
|
|
|
132
131
|
this.bOneTimeProcessingDone = false;
|
|
133
132
|
this.bPlanAnalyzed = false;
|
|
134
133
|
this.bPostProcessingDone = false;
|
|
135
|
-
// testScales = {} as T.TestScales; TODO - DELETE
|
|
136
134
|
this.tests = {};
|
|
137
135
|
this.title = SessionRequest['title'];
|
|
138
136
|
this.legislativeDistricts = SessionRequest['legislativeDistricts'];
|
|
@@ -143,42 +141,18 @@ class AnalyticsSession {
|
|
|
143
141
|
this.features = new D.Features(this, SessionRequest['data'], this.config['datasets']);
|
|
144
142
|
this.plan = new D.Plan(this, SessionRequest['plan']);
|
|
145
143
|
this.districts = new D.Districts(this, SessionRequest['districtShapes']);
|
|
146
|
-
// TODO - DELETE
|
|
147
|
-
// if (this.useLegacy())
|
|
148
|
-
// {
|
|
149
|
-
// console.log("Using legacy district-analytics.")
|
|
150
|
-
// // NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
151
|
-
// // we could want them to passed into an analytics session as data, along with
|
|
152
|
-
// // everything else. For now, this keeps branching out of the main code.
|
|
153
|
-
// doConfigureScales(this);
|
|
154
|
-
// }
|
|
155
|
-
// else
|
|
156
|
-
// {
|
|
157
|
-
// console.log("Using dra-score analytics.")
|
|
158
|
-
// // TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
159
|
-
// doConfigureScales(this);
|
|
160
|
-
// }
|
|
161
144
|
}
|
|
162
145
|
processConfig(config) {
|
|
163
146
|
// NOTE - Session settings are required:
|
|
164
147
|
// - Analytics suites can be defaulted to all with [], but
|
|
165
148
|
// - Dataset keys must be explicitly specified with 'dataset'
|
|
166
|
-
//
|
|
149
|
+
// NOTE - Legacy feature: Always calc everything
|
|
167
150
|
config['suites'] = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
|
|
168
151
|
// Default the Census & redistricting cycle to 2010
|
|
169
152
|
if (!(U.keyExists('cycle', config)))
|
|
170
153
|
config['cycle'] = 2010;
|
|
171
154
|
return config;
|
|
172
155
|
}
|
|
173
|
-
/* TODO - DELETE
|
|
174
|
-
useLegacy(): boolean
|
|
175
|
-
{
|
|
176
|
-
// TODO - SCORE: Opt-out
|
|
177
|
-
return (U.keyExists('useScore', this.config) && (this.config['useScore'] != null) && (!(this.config['useScore']))) ? true : false;
|
|
178
|
-
// TODO - SCORE: Opt-in
|
|
179
|
-
// return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
|
|
180
|
-
}
|
|
181
|
-
*/
|
|
182
156
|
// Using the the data in the analytics session, calculate all the
|
|
183
157
|
// analytics & validations, saving/updating the individual test results.
|
|
184
158
|
analyzePlan(bLog = false, overridesJSON) {
|
|
@@ -186,7 +160,6 @@ class AnalyticsSession {
|
|
|
186
160
|
preprocess_1.doPreprocessData(this, bLog);
|
|
187
161
|
analyze_1.doAnalyzeDistricts(this, bLog);
|
|
188
162
|
analyze_1.doAnalyzePlan(this, bLog);
|
|
189
|
-
// TODO - SCORE
|
|
190
163
|
this._profile = score_1.profilePlan(this, bLog);
|
|
191
164
|
this._scorecard = score_1.scorePlan(this, this._profile, bLog, overridesJSON);
|
|
192
165
|
results_1.doAnalyzePostProcessing(this, bLog);
|
|
@@ -201,15 +174,12 @@ class AnalyticsSession {
|
|
|
201
174
|
getDistrictStatistics(bLog = false) {
|
|
202
175
|
return results_2.prepareDistrictStatistics(this, bLog);
|
|
203
176
|
}
|
|
204
|
-
// TODO - SCORE
|
|
205
177
|
getPlanProfile(bLog = false) {
|
|
206
178
|
return this._profile;
|
|
207
179
|
}
|
|
208
|
-
// TODO - SCORE
|
|
209
180
|
getPlanScorecard(bLog = false) {
|
|
210
181
|
return this._scorecard;
|
|
211
182
|
}
|
|
212
|
-
// TODO - SCORE
|
|
213
183
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
214
184
|
getRequirementsChecklist(bLog = false) {
|
|
215
185
|
return results_2.prepareRequirementsChecklist(this, bLog);
|
|
@@ -310,21 +280,10 @@ class AnalyticsSession {
|
|
|
310
280
|
}
|
|
311
281
|
// NOTE - Not sure why this has to be up here ...
|
|
312
282
|
populationDeviationThreshold() {
|
|
313
|
-
// TODO - DELETE
|
|
314
|
-
// if (this.useLegacy())
|
|
315
|
-
// {
|
|
316
|
-
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
317
|
-
// }
|
|
318
|
-
// else
|
|
319
|
-
// {
|
|
320
283
|
// NOTE - This assumes the plan has been profiled
|
|
321
284
|
const scorer = new Score.Scorer();
|
|
322
285
|
const popdev = scorer.populationDeviationThreshold(this.legislativeDistricts);
|
|
323
286
|
return popdev;
|
|
324
|
-
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
325
|
-
// NOTE - The plan may not have been scored yet, i.e., no scorecard yet.
|
|
326
|
-
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
327
|
-
// }
|
|
328
287
|
}
|
|
329
288
|
}
|
|
330
289
|
exports.AnalyticsSession = AnalyticsSession;
|
|
@@ -438,11 +397,11 @@ class Districts {
|
|
|
438
397
|
}
|
|
439
398
|
// This is the workhorse computational routine!
|
|
440
399
|
//
|
|
441
|
-
//
|
|
442
|
-
//
|
|
400
|
+
// NOTE - OPTIMIZE for getting multiple properties from the same feature?
|
|
401
|
+
// NOTE - OPTIMIZE by only re-calc'ing districts that have changed?
|
|
443
402
|
// In this case, special attention to getting county-splits right.
|
|
444
|
-
//
|
|
445
|
-
//
|
|
403
|
+
// NOTE - OPTIMIZE by async'ing this?
|
|
404
|
+
// NOTE - Is there a way to do this programmatically off data? Does it matter?
|
|
446
405
|
recalcStatistics(bLog = false) {
|
|
447
406
|
// Initialize debug counters
|
|
448
407
|
nMissingDataset = 0;
|
|
@@ -453,7 +412,6 @@ class Districts {
|
|
|
453
412
|
let planByDistrict = this._session.plan.byDistrictID();
|
|
454
413
|
let plan = this._session.plan;
|
|
455
414
|
let graph = this._session.graph;
|
|
456
|
-
// NOTE - SPLITTING
|
|
457
415
|
// Add an extra 0th virtual county bucket for county-district splitting analysis
|
|
458
416
|
let nCountyBuckets = this._session.counties.nCounties + 1;
|
|
459
417
|
// INITIALIZE STATE VALUES THAT WILL BE ACCUMULATED
|
|
@@ -479,7 +437,6 @@ class Districts {
|
|
|
479
437
|
// INITIALIZE DISTRICT VALUES THAT WILL BE ACCUMULATED (VS. DERIVED)
|
|
480
438
|
let featurePop;
|
|
481
439
|
let totalPop = 0;
|
|
482
|
-
// NOTE - SPLITTING
|
|
483
440
|
let countySplits = U.initArray(nCountyBuckets, 0);
|
|
484
441
|
let demVotes = 0;
|
|
485
442
|
let repVotes = 0;
|
|
@@ -523,7 +480,6 @@ class Districts {
|
|
|
523
480
|
featurePop = outerThis._session.features.fieldForFeature(f, "CENSUS" /* CENSUS */, "Tot" /* TotalPop */);
|
|
524
481
|
// Total district population
|
|
525
482
|
totalPop += featurePop;
|
|
526
|
-
// NOTE - SPLITTING
|
|
527
483
|
// Total population by counties w/in a district,
|
|
528
484
|
// except the dummy unassigned district 0
|
|
529
485
|
if (i > 0)
|
|
@@ -727,7 +683,7 @@ class Features {
|
|
|
727
683
|
}
|
|
728
684
|
resetDataset(d, k) {
|
|
729
685
|
this._keys[d] = k;
|
|
730
|
-
//
|
|
686
|
+
// NOTE - RECALC: Does anything need to be recalc'd now when a dataset is changed?
|
|
731
687
|
}
|
|
732
688
|
mapGeoIDsToFeatureIDs() {
|
|
733
689
|
for (let i = 0; i < this._session.features.nFeatures(); i++) {
|
|
@@ -842,7 +798,6 @@ class Plan {
|
|
|
842
798
|
// return newPlan;
|
|
843
799
|
// }
|
|
844
800
|
invertPlan() {
|
|
845
|
-
// NOTE - UNASSIGNED
|
|
846
801
|
this._planByDistrictID = invertPlan(this._planByGeoID, this._session);
|
|
847
802
|
this.districtIDs = U.getNumericObjectKeys(this._planByDistrictID);
|
|
848
803
|
}
|
|
@@ -858,7 +813,6 @@ function invertPlan(plan, s) {
|
|
|
858
813
|
let invertedPlan = {};
|
|
859
814
|
// Add a dummy 'unassigned' district
|
|
860
815
|
invertedPlan[S.NOT_ASSIGNED] = new Set();
|
|
861
|
-
// NOTE - UNASSIGNED
|
|
862
816
|
// The feature assignments coming from DRA do not include unassigned ones.
|
|
863
817
|
// - In the DRA-calling context, there's an analytics session with a reference
|
|
864
818
|
// to the features. Loop over all the features to find the unassigned ones,
|
|
@@ -901,7 +855,6 @@ class Graph {
|
|
|
901
855
|
// Ignore the lengths of the shared borders (the values), for now
|
|
902
856
|
// Protect against getting a GEOID that's not in the graph
|
|
903
857
|
if (U.keyExists(node, this._graph)) {
|
|
904
|
-
// NOTE - CONTIGUITY GRAPHS
|
|
905
858
|
// Handle both unweighted & weighted neighbors
|
|
906
859
|
let n = this._graph[node];
|
|
907
860
|
let l = (n instanceof Array) ? n : U.getObjectKeys(n);
|
|
@@ -933,22 +886,7 @@ exports.Graph = Graph;
|
|
|
933
886
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
934
887
|
const valid_1 = __webpack_require__(/*! ./valid */ "./src/valid.ts");
|
|
935
888
|
const equal_1 = __webpack_require__(/*! ./equal */ "./src/equal.ts");
|
|
936
|
-
// import { doPopulationDeviation, doHasEqualPopulations } from './equal'; TODO - DELETE
|
|
937
|
-
// import { doReock, doPolsbyPopper } from './compact'; TODO - DELETE
|
|
938
889
|
const cohesive_1 = __webpack_require__(/*! ./cohesive */ "./src/cohesive.ts");
|
|
939
|
-
/* TODO - DELETE
|
|
940
|
-
import
|
|
941
|
-
{
|
|
942
|
-
doFindCountiesSplitUnexpectedly, doFindSplitVTDs,
|
|
943
|
-
doCountySplitting, doDistrictSplitting
|
|
944
|
-
} from './cohesive';
|
|
945
|
-
import
|
|
946
|
-
{
|
|
947
|
-
doSeatsBias, doVotesBias,
|
|
948
|
-
doResponsiveness, doResponsiveDistricts, doEfficiencyGap
|
|
949
|
-
} from './political';
|
|
950
|
-
import { doMajorityMinorityDistricts } from './minority'
|
|
951
|
-
*/
|
|
952
890
|
// Compile district-level info for plan/map-level analytics
|
|
953
891
|
function doAnalyzeDistricts(s, bLog = false) {
|
|
954
892
|
s.districts.recalcStatistics(bLog);
|
|
@@ -960,56 +898,9 @@ exports.doAnalyzeDistricts = doAnalyzeDistricts;
|
|
|
960
898
|
// NOTE - I could make this table-driven, but I'm thinking that the explicit
|
|
961
899
|
// calls might make chunking for aync easier.
|
|
962
900
|
function doAnalyzePlan(s, bLog = false) {
|
|
963
|
-
// TODO - DELETE
|
|
964
|
-
// if (s.useLegacy())
|
|
965
|
-
// {
|
|
966
|
-
// // Disable most legacy analytics
|
|
967
|
-
// // Get the requested suites, and only execute those tests
|
|
968
|
-
// let requestedSuites = s.config['suites'];
|
|
969
|
-
// // Tests in the "Legal" suite, i.e., pass/ fail constraints
|
|
970
|
-
// if (requestedSuites.includes(T.Suite.Legal))
|
|
971
|
-
// {
|
|
972
|
-
// s.tests[T.Test.Complete] = doIsComplete(s, bLog);
|
|
973
|
-
// s.tests[T.Test.Contiguous] = doIsContiguous(s, bLog);
|
|
974
|
-
// s.tests[T.Test.FreeOfHoles] = doIsFreeOfHoles(s, bLog);
|
|
975
|
-
// // s.tests[T.Test.PopulationDeviation] = doPopulationDeviation(s, bLog); TODO - DELETE
|
|
976
|
-
// // NOTE - I can't check whether a population deviation is legal or not, until
|
|
977
|
-
// // the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
978
|
-
// // the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
979
|
-
// // from PopulationDeviation, as part of scorecard or test log preparation.
|
|
980
|
-
// // Create an empty test entry here though ...
|
|
981
|
-
// s.tests[T.Test.EqualPopulation] = s.getTest(T.Test.EqualPopulation) as T.TestEntry;
|
|
982
|
-
// }
|
|
983
|
-
// // Tests in the "Fair" suite
|
|
984
|
-
// if (requestedSuites.includes(T.Suite.Fair))
|
|
985
|
-
// {
|
|
986
|
-
// /* TODO - DELETE
|
|
987
|
-
// s.tests[T.Test.SeatsBias] = doSeatsBias(s, bLog);
|
|
988
|
-
// s.tests[T.Test.VotesBias] = doVotesBias(s, bLog);
|
|
989
|
-
// s.tests[T.Test.Responsiveness] = doResponsiveness(s, bLog);
|
|
990
|
-
// s.tests[T.Test.ResponsiveDistricts] = doResponsiveDistricts(s, bLog);
|
|
991
|
-
// s.tests[T.Test.EfficiencyGap] = doEfficiencyGap(s, bLog);
|
|
992
|
-
// s.tests[T.Test.MajorityMinorityDistricts] = doMajorityMinorityDistricts(s, bLog);
|
|
993
|
-
// */
|
|
994
|
-
// }
|
|
995
|
-
// // Tests in the "Best" suite, i.e., criteria for better/worse
|
|
996
|
-
// if (requestedSuites.includes(T.Suite.Best))
|
|
997
|
-
// {
|
|
998
|
-
// // s.tests[T.Test.Reock] = doReock(s, bLog); TODO - DELETE
|
|
999
|
-
// // s.tests[T.Test.PolsbyPopper] = doPolsbyPopper(s, bLog); TODO - DELETE
|
|
1000
|
-
// s.tests[T.Test.UnexpectedCountySplits] = doFindCountiesSplitUnexpectedly(s, bLog);
|
|
1001
|
-
// s.tests[T.Test.VTDSplits] = doFindSplitVTDs(s, bLog);
|
|
1002
|
-
// // s.tests[T.Test.CountySplitting] = doCountySplitting(s, bLog); TODO - DELETE
|
|
1003
|
-
// // s.tests[T.Test.DistrictSplitting] = doDistrictSplitting(s, bLog); TODO - DELETE
|
|
1004
|
-
// }
|
|
1005
|
-
// }
|
|
1006
|
-
// else
|
|
1007
|
-
// {
|
|
1008
|
-
// TODO - SCORE: Except these. Continue to do these here vs. dra-score.
|
|
1009
901
|
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
1010
902
|
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
1011
903
|
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
1012
|
-
// s.tests[T.Test.PopulationDeviation] = doPopulationDeviation(s, bLog); TODO - DELETE
|
|
1013
904
|
// NOTE - I can't check whether a population deviation is legal or not, until
|
|
1014
905
|
// the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
1015
906
|
// the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
@@ -1018,7 +909,6 @@ function doAnalyzePlan(s, bLog = false) {
|
|
|
1018
909
|
s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
|
|
1019
910
|
s.tests[5 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
1020
911
|
s.tests[6 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
|
|
1021
|
-
// }
|
|
1022
912
|
// Enable a Test Log and Scorecard to be generated
|
|
1023
913
|
s.bPlanAnalyzed = true;
|
|
1024
914
|
s.bPostProcessingDone = false;
|
|
@@ -1061,277 +951,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
1061
951
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
1062
952
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
1063
953
|
// NOTE - The active code is below the long multi-line section to be deleted.
|
|
1064
|
-
/* TODO - DELETE
|
|
1065
|
-
// CALCULATE ENHANCED SQRT ENTROPY METRIC
|
|
1066
|
-
|
|
1067
|
-
export function doCountySplitting(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
1068
|
-
{
|
|
1069
|
-
let test = s.getTest(T.Test.CountySplitting) as T.TestEntry;
|
|
1070
|
-
|
|
1071
|
-
let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
|
|
1072
|
-
let countyTotals = s.counties.totalPopulation;
|
|
1073
|
-
let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
|
|
1074
|
-
|
|
1075
|
-
let f = calcCountyFractions(CxD, countyTotals);
|
|
1076
|
-
let w = calcCountyWeights(countyTotals);
|
|
1077
|
-
|
|
1078
|
-
let SqEnt_DC = countySplitting(f, w, bLog);
|
|
1079
|
-
|
|
1080
|
-
let CxDreducedC = U.deepCopy(CxD);
|
|
1081
|
-
reduceCSplits(CxDreducedC, districtTotals);
|
|
1082
|
-
|
|
1083
|
-
let fReduced = calcCountyFractions(CxDreducedC, countyTotals);
|
|
1084
|
-
let wReduced = calcCountyWeights(countyTotals);
|
|
1085
|
-
|
|
1086
|
-
let SqEnt_DCreduced = countySplitting(fReduced, wReduced, bLog);
|
|
1087
|
-
|
|
1088
|
-
test['score'] = SqEnt_DCreduced;
|
|
1089
|
-
test['details']['SqEnt_DC'] = SqEnt_DC;
|
|
1090
|
-
|
|
1091
|
-
return test;
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
export function doDistrictSplitting(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
1095
|
-
{
|
|
1096
|
-
let test = s.getTest(T.Test.DistrictSplitting) as T.TestEntry;
|
|
1097
|
-
|
|
1098
|
-
let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
|
|
1099
|
-
let countyTotals = s.counties.totalPopulation;
|
|
1100
|
-
let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
|
|
1101
|
-
|
|
1102
|
-
let g = calcDistrictFractions(CxD, districtTotals);
|
|
1103
|
-
let x = calcDistrictWeights(districtTotals);
|
|
1104
|
-
|
|
1105
|
-
let SqEnt_CD = districtSplitting(g, x, bLog);
|
|
1106
|
-
|
|
1107
|
-
let CxDreducedD = U.deepCopy(CxD);
|
|
1108
|
-
reduceDSplits(CxDreducedD, countyTotals);
|
|
1109
|
-
|
|
1110
|
-
let gReduced = calcDistrictFractions(CxDreducedD, districtTotals);
|
|
1111
|
-
let xReduced = calcDistrictWeights(districtTotals);
|
|
1112
|
-
|
|
1113
|
-
let SqEnt_CDreduced = districtSplitting(gReduced, xReduced, bLog);
|
|
1114
|
-
|
|
1115
|
-
test['score'] = SqEnt_CDreduced;
|
|
1116
|
-
test['details']['SqEnt_CD'] = SqEnt_CD;
|
|
1117
|
-
|
|
1118
|
-
return test;
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
// HELPERS
|
|
1123
|
-
|
|
1124
|
-
// Loop over all the county-district combos, skipping the virtual district 0
|
|
1125
|
-
// and virtual county 0.
|
|
1126
|
-
//
|
|
1127
|
-
// NOTE - The county-district splits and the county & district totals may all,
|
|
1128
|
-
// in general, be fractional/decimal numbers as opposed to integers, due to
|
|
1129
|
-
// dissaggregation & re-aggregation. Hence, comparisons need to approximate
|
|
1130
|
-
// equality.
|
|
1131
|
-
|
|
1132
|
-
// Consolidate districts (rows) consisting of just one county (column)
|
|
1133
|
-
// UP into the dummy district (0).
|
|
1134
|
-
function reduceCSplits(CxDreducedC: number[][], districtTotals: number[]): void
|
|
1135
|
-
{
|
|
1136
|
-
let nD = CxDreducedC.length;
|
|
1137
|
-
let nC = CxDreducedC[0].length;
|
|
1138
|
-
|
|
1139
|
-
for (let j = 1; j < nC; j++)
|
|
1140
|
-
{
|
|
1141
|
-
for (let i = 1; i < nD; i++)
|
|
1142
|
-
{
|
|
1143
|
-
let split_total = CxDreducedC[i][j];
|
|
1144
|
-
|
|
1145
|
-
if (split_total > 0)
|
|
1146
|
-
{
|
|
1147
|
-
if (areRoughlyEqual(split_total, districtTotals[i]))
|
|
1148
|
-
{
|
|
1149
|
-
CxDreducedC[0][j] += split_total;
|
|
1150
|
-
CxDreducedC[i][j] = 0;
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
// Consolidate whole counties (columns) in a district (row) LEFT into the
|
|
1158
|
-
// dummy county (0).
|
|
1159
|
-
function reduceDSplits(CxDreducedD: number[][], countyTotals: number[]): void
|
|
1160
|
-
{
|
|
1161
|
-
let nD = CxDreducedD.length;
|
|
1162
|
-
let nC = CxDreducedD[0].length;
|
|
1163
|
-
|
|
1164
|
-
for (let i = 1; i < nD; i++)
|
|
1165
|
-
{
|
|
1166
|
-
for (let j = 1; j < nC; j++)
|
|
1167
|
-
{
|
|
1168
|
-
let split_total = CxDreducedD[i][j];
|
|
1169
|
-
|
|
1170
|
-
if (split_total > 0)
|
|
1171
|
-
{
|
|
1172
|
-
if (areRoughlyEqual(split_total, countyTotals[j]))
|
|
1173
|
-
{
|
|
1174
|
-
CxDreducedD[i][0] += split_total;
|
|
1175
|
-
CxDreducedD[i][j] = 0;
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
function calcCountyWeights(countyTotals: number[]): number[]
|
|
1183
|
-
{
|
|
1184
|
-
let nC: number = countyTotals.length;
|
|
1185
|
-
let cTotal: number = U.sumArray(countyTotals);
|
|
1186
|
-
|
|
1187
|
-
let w: number[] = U.initArray(nC, 0.0);
|
|
1188
|
-
|
|
1189
|
-
for (let j = 0; j < nC; j++)
|
|
1190
|
-
{
|
|
1191
|
-
w[j] = countyTotals[j] / cTotal;
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
return w;
|
|
1195
|
-
}
|
|
1196
|
-
|
|
1197
|
-
function calcDistrictWeights(districtTotals: number[]): number[]
|
|
1198
|
-
{
|
|
1199
|
-
let nD = districtTotals.length;
|
|
1200
|
-
let dTotal: number = U.sumArray(districtTotals);
|
|
1201
|
-
|
|
1202
|
-
let x: number[] = U.initArray(nD, 0.0);
|
|
1203
|
-
|
|
1204
|
-
for (let i = 0; i < nD; i++)
|
|
1205
|
-
{
|
|
1206
|
-
x[i] = districtTotals[i] / dTotal;
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
return x;
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
function calcCountyFractions(CxDreducedD: number[][], countyTotals: number[]): number[][]
|
|
1213
|
-
{
|
|
1214
|
-
let nD = CxDreducedD.length;
|
|
1215
|
-
let nC = CxDreducedD[0].length;
|
|
1216
|
-
|
|
1217
|
-
let f: number[][] = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
|
|
1218
|
-
|
|
1219
|
-
for (let j = 0; j < nC; j++)
|
|
1220
|
-
{
|
|
1221
|
-
for (let i = 0; i < nD; i++)
|
|
1222
|
-
{
|
|
1223
|
-
if (countyTotals[j] > 0)
|
|
1224
|
-
{
|
|
1225
|
-
f[i][j] = CxDreducedD[i][j] / countyTotals[j];
|
|
1226
|
-
}
|
|
1227
|
-
else
|
|
1228
|
-
{
|
|
1229
|
-
f[i][j] = 0.0;
|
|
1230
|
-
}
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
|
|
1234
|
-
return f;
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
function calcDistrictFractions(CxDreducedC: number[][], districtTotals: number[]): number[][]
|
|
1238
|
-
{
|
|
1239
|
-
let nD = CxDreducedC.length;
|
|
1240
|
-
let nC = CxDreducedC[0].length;
|
|
1241
|
-
|
|
1242
|
-
let g: number[][] = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
|
|
1243
|
-
|
|
1244
|
-
for (let j = 0; j < nC; j++)
|
|
1245
|
-
{
|
|
1246
|
-
for (let i = 0; i < nD; i++)
|
|
1247
|
-
{
|
|
1248
|
-
if (districtTotals[i] > 0)
|
|
1249
|
-
{
|
|
1250
|
-
g[i][j] = CxDreducedC[i][j] / districtTotals[i];
|
|
1251
|
-
}
|
|
1252
|
-
else
|
|
1253
|
-
{
|
|
1254
|
-
g[i][j] = 0.0;
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
return g;
|
|
1260
|
-
}
|
|
1261
|
-
|
|
1262
|
-
// Deal with decimal census "counts" due to disagg/re-agg
|
|
1263
|
-
function areRoughlyEqual(x: number, y: number): boolean
|
|
1264
|
-
{
|
|
1265
|
-
let delta = Math.abs(x - y);
|
|
1266
|
-
let result = (delta < S.EQUAL_TOLERANCE) ? true : false;
|
|
1267
|
-
|
|
1268
|
-
return result;
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
// For all districts in a county, sum the split score.
|
|
1272
|
-
function countySplitScore(j: number, f: number[][], numD: number, bLog: boolean = false): number
|
|
1273
|
-
{
|
|
1274
|
-
let e = 0.0;
|
|
1275
|
-
|
|
1276
|
-
for (let i = 0; i < numD; i++)
|
|
1277
|
-
{
|
|
1278
|
-
e += Math.sqrt(f[i][j]);
|
|
1279
|
-
}
|
|
1280
|
-
|
|
1281
|
-
return e;
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
// For all counties, sum the weighted county splits.
|
|
1285
|
-
function countySplitting(f: number[][], w: number[], bLog: boolean = false): number
|
|
1286
|
-
{
|
|
1287
|
-
let numC = f[0].length;
|
|
1288
|
-
let numD = f.length;
|
|
1289
|
-
|
|
1290
|
-
let e = 0.0;
|
|
1291
|
-
|
|
1292
|
-
for (let j = 0; j < numC; j++)
|
|
1293
|
-
{
|
|
1294
|
-
let splitScore = countySplitScore(j, f, numD, bLog);
|
|
1295
|
-
e += w[j] * splitScore;
|
|
1296
|
-
|
|
1297
|
-
if (bLog) console.log("County splitting =", j, w[j], splitScore, e);
|
|
1298
|
-
}
|
|
1299
|
-
|
|
1300
|
-
return U.trim(e, 3);
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
// For all counties in a district, sum the split score.
|
|
1304
|
-
function districtSplitScore(i: number, g: number[][], numC: number, bLog: boolean = false): number
|
|
1305
|
-
{
|
|
1306
|
-
let e = 0.0;
|
|
1307
|
-
|
|
1308
|
-
for (let j = 0; j < numC; j++)
|
|
1309
|
-
{
|
|
1310
|
-
e += Math.sqrt(g[i][j]);
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
return e;
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
// For all districts, sum the weighted district splits.
|
|
1317
|
-
function districtSplitting(g: number[][], x: number[], bLog: boolean = false): number
|
|
1318
|
-
{
|
|
1319
|
-
let numC = g[0].length;
|
|
1320
|
-
let numD = g.length;
|
|
1321
|
-
|
|
1322
|
-
let e = 0.0;
|
|
1323
|
-
|
|
1324
|
-
for (let i = 0; i < numD; i++)
|
|
1325
|
-
{
|
|
1326
|
-
let splitScore = districtSplitScore(i, g, numC, bLog);
|
|
1327
|
-
e += x[i] * splitScore;
|
|
1328
|
-
|
|
1329
|
-
if (bLog) console.log("District split score =", i, x[i], splitScore, e);
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
return U.trim(e, 3);
|
|
1333
|
-
}
|
|
1334
|
-
*/
|
|
1335
954
|
// ANALYZE SIMPLE COUNTY & VTD SPLITTING
|
|
1336
955
|
/*
|
|
1337
956
|
|
|
@@ -1495,164 +1114,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
1495
1114
|
// NOTE - This file will NOT be empty, when legacy code is deleted.
|
|
1496
1115
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "@dra2020/poly"));
|
|
1497
1116
|
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
1498
|
-
// TODO - DELETE
|
|
1499
|
-
// Measures of compactness compare district shapes to various ideally compact
|
|
1500
|
-
// benchmarks, such as circles. All else equal, more compact districts are better.
|
|
1501
|
-
//
|
|
1502
|
-
// There are four popular measures of compactness. They either focus on how
|
|
1503
|
-
// dispersed or how indented a shapes are.
|
|
1504
|
-
//
|
|
1505
|
-
// These first two measures are the most important:
|
|
1506
|
-
//
|
|
1507
|
-
// Reock is the primary measure of the dispersion of district shapes, calculated
|
|
1508
|
-
// as “the area of the district to the area of the minimum spanning circle that
|
|
1509
|
-
// can enclose the district.”
|
|
1510
|
-
//
|
|
1511
|
-
// R = A / A(Minimum Bounding Circle)
|
|
1512
|
-
// R = A / (π * (D / 2)^2)
|
|
1513
|
-
//
|
|
1514
|
-
// R = 4A / πD^2
|
|
1515
|
-
//
|
|
1516
|
-
// where A is the area of the district and D is the diameter of the minimum
|
|
1517
|
-
// bounding circle.
|
|
1518
|
-
//
|
|
1519
|
-
// Polsby-Popper is the primary measure of the indendentation of district shapes,
|
|
1520
|
-
// calculated as the “the ratio of the area of the district to the area of a circle
|
|
1521
|
-
// whose circumference is equal to the perimeter of the district.”
|
|
1522
|
-
//
|
|
1523
|
-
// PP = A / A(C)
|
|
1524
|
-
//
|
|
1525
|
-
// where C is that circle. In other words:
|
|
1526
|
-
//
|
|
1527
|
-
// P = 2πRc and A(C) = π(P / 2π)^2
|
|
1528
|
-
//
|
|
1529
|
-
// where P is the perimeter of the district and Rc is the radius of the circle.
|
|
1530
|
-
//
|
|
1531
|
-
// Hence, the measure simplifies to:
|
|
1532
|
-
//
|
|
1533
|
-
// PP = 4π * (A / P^2)
|
|
1534
|
-
//
|
|
1535
|
-
// I propose that we use these two, normalize them, and weight equally to determine
|
|
1536
|
-
// our compactness value.
|
|
1537
|
-
//
|
|
1538
|
-
// These second two measures may be used to complement the primary ones above:
|
|
1539
|
-
//
|
|
1540
|
-
// Convex Hull is a secondary measure of the dispersion of district shapes, calculated
|
|
1541
|
-
// as “the ratio of the district area to the area of the minimum convex bounding
|
|
1542
|
-
// polygon (also known as a convex hull) enclosing the district.”
|
|
1543
|
-
//
|
|
1544
|
-
// CH = A / A(Convex Hull)
|
|
1545
|
-
//
|
|
1546
|
-
// where a convex hull is the minimum perimeter that encloses all points in a shape,
|
|
1547
|
-
// basically the shortest unstretched rubber band that fits around the shape.
|
|
1548
|
-
//
|
|
1549
|
-
// Schwartzberg is a secondary measure of the degree of indentation of district
|
|
1550
|
-
// shapes, calculated as “the ratio of the perimeter of the district to the circumference
|
|
1551
|
-
// of a circle whose area is equal to the area of the district.”
|
|
1552
|
-
//
|
|
1553
|
-
// S = 1 / (P / C)
|
|
1554
|
-
//
|
|
1555
|
-
// where P is the perimeter of the district and C is the circumference of the circle.
|
|
1556
|
-
// The radius of the circle is:
|
|
1557
|
-
//
|
|
1558
|
-
// Rc = SQRT(A / π)
|
|
1559
|
-
//
|
|
1560
|
-
// So, the circumference of the circle is:
|
|
1561
|
-
//
|
|
1562
|
-
// C = 2πRc or C = 2π * SQRT(A / π)
|
|
1563
|
-
//
|
|
1564
|
-
// Hence:
|
|
1565
|
-
//
|
|
1566
|
-
// S = 1 (P / 2π * SQRT(A / π))
|
|
1567
|
-
//
|
|
1568
|
-
// S = (2π * SQRT(A / π)) / P
|
|
1569
|
-
//
|
|
1570
|
-
// All these measures produce values between 0 and 1, with 0 being the least compact
|
|
1571
|
-
// and 1 being the most compact. Sometimes these values are multiplied by 100 to
|
|
1572
|
-
// give values between 0 and 100.
|
|
1573
|
-
//
|
|
1574
|
-
// For each measure, the compactness of a set of Congressional districts is the
|
|
1575
|
-
// average of that measure for all the districts.
|
|
1576
|
-
//
|
|
1577
|
-
/* TODO - DELETE
|
|
1578
|
-
// Calculate Reock compactness:
|
|
1579
|
-
// reock = (4 * a) / (math.pi * d**2)
|
|
1580
|
-
// NOTE - Depends on extractDistrictProperties running first
|
|
1581
|
-
export function doReock(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
1582
|
-
{
|
|
1583
|
-
let test = s.getTest(T.Test.Reock) as T.TestEntry;
|
|
1584
|
-
|
|
1585
|
-
// Calculate Reock scores by district
|
|
1586
|
-
let scores: number[] = [];
|
|
1587
|
-
|
|
1588
|
-
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++)
|
|
1589
|
-
{
|
|
1590
|
-
let districtProps = s.districts.getGeoProperties(districtID);
|
|
1591
|
-
// Guard against no shape and no properties
|
|
1592
|
-
if (districtProps)
|
|
1593
|
-
{
|
|
1594
|
-
let a = districtProps[T.DistrictShapeProperty.Area];
|
|
1595
|
-
let d = districtProps[T.DistrictShapeProperty.Diameter];
|
|
1596
|
-
|
|
1597
|
-
let reock = (4 * a) / (Math.PI * d ** 2);
|
|
1598
|
-
|
|
1599
|
-
// Save each district score
|
|
1600
|
-
scores.push(reock);
|
|
1601
|
-
|
|
1602
|
-
// Echo the results by district
|
|
1603
|
-
if (bLog) console.log("Reock for district", districtID, "=", reock);
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
|
|
1607
|
-
// Populate the test entry ... for the shapes that exist!
|
|
1608
|
-
let averageReock = U.avgArray(scores);
|
|
1609
|
-
|
|
1610
|
-
test['score'] = U.trim(averageReock);
|
|
1611
|
-
test['details'] = {}; // TODO - Any details?
|
|
1612
|
-
|
|
1613
|
-
return test;
|
|
1614
|
-
}
|
|
1615
|
-
|
|
1616
|
-
// Calculate Polsby-Popper compactness measures:
|
|
1617
|
-
// polsby_popper = (4 * math.pi) * (a / p**2)
|
|
1618
|
-
// NOTE - Depends on extractDistrictProperties running first
|
|
1619
|
-
export function doPolsbyPopper(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
1620
|
-
{
|
|
1621
|
-
let test = s.getTest(T.Test.PolsbyPopper) as T.TestEntry;
|
|
1622
|
-
|
|
1623
|
-
// Calculate Polsby-Popper scores by district
|
|
1624
|
-
let scores: number[] = [];
|
|
1625
|
-
|
|
1626
|
-
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++)
|
|
1627
|
-
{
|
|
1628
|
-
let districtProps = s.districts.getGeoProperties(districtID);
|
|
1629
|
-
// Guard against no shape and no properties
|
|
1630
|
-
if (districtProps)
|
|
1631
|
-
{
|
|
1632
|
-
let a = districtProps[T.DistrictShapeProperty.Area];
|
|
1633
|
-
let p = districtProps[T.DistrictShapeProperty.Perimeter];
|
|
1634
|
-
|
|
1635
|
-
let polsbyPopper = (4 * Math.PI) * (a / p ** 2);
|
|
1636
|
-
|
|
1637
|
-
// Save each district score
|
|
1638
|
-
scores.push(polsbyPopper);
|
|
1639
|
-
|
|
1640
|
-
// Echo the results by district
|
|
1641
|
-
if (bLog) console.log("Polsby-Popper for district", districtID, "=", polsbyPopper);
|
|
1642
|
-
}
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
// Populate the test entry ... for the shapes that exist!
|
|
1646
|
-
let averagePolsbyPopper = U.avgArray(scores);
|
|
1647
|
-
|
|
1648
|
-
test['score'] = U.trim(averagePolsbyPopper);
|
|
1649
|
-
test['details'] = {}; // TODO - Any details?
|
|
1650
|
-
|
|
1651
|
-
return test;
|
|
1652
|
-
}
|
|
1653
|
-
*/
|
|
1654
1117
|
// HELPER TO EXTRACT PROPERTIES OF DISTRICT SHAPES
|
|
1655
|
-
// TODO -
|
|
1118
|
+
// TODO - Create an array, as opposed to a dict
|
|
1656
1119
|
function extractDistrictProperties(s, bLog = false) {
|
|
1657
1120
|
// NOTE - I am assuming that district IDs are integers 1–N
|
|
1658
1121
|
for (let i = 1; i <= s.state.nDistricts; i++) {
|
|
@@ -1729,52 +1192,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
1729
1192
|
};
|
|
1730
1193
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1731
1194
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
1732
|
-
/* TODO - DELETE
|
|
1733
|
-
export function doPopulationDeviation(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
1734
|
-
{
|
|
1735
|
-
let test = s.getTest(T.Test.PopulationDeviation) as T.TestEntry;
|
|
1736
|
-
|
|
1737
|
-
let targetSize = s.state.totalPop / s.state.nDistricts;
|
|
1738
|
-
|
|
1739
|
-
// Compute the min & max district populations
|
|
1740
|
-
// ... excluding the dummy the 'unassigned' 0 and N+1 summary "districts"
|
|
1741
|
-
let totPopByDistrict = s.districts.statistics[D.DistrictField.TotalPop];
|
|
1742
|
-
totPopByDistrict = totPopByDistrict.slice(1, -1);
|
|
1743
|
-
|
|
1744
|
-
// Remove empty districts
|
|
1745
|
-
totPopByDistrict = totPopByDistrict.filter(x => x > 0);
|
|
1746
|
-
|
|
1747
|
-
let min = 0;
|
|
1748
|
-
let max = 0;
|
|
1749
|
-
|
|
1750
|
-
// If there's more than 1 non-empty district, calculate a non-zero deviation
|
|
1751
|
-
if (totPopByDistrict.length > 1)
|
|
1752
|
-
{
|
|
1753
|
-
min = U.minArray(totPopByDistrict);
|
|
1754
|
-
max = U.maxArray(totPopByDistrict);
|
|
1755
|
-
}
|
|
1756
|
-
|
|
1757
|
-
// Calculate the raw population deviation
|
|
1758
|
-
let popDev = (max - min) / targetSize;
|
|
1759
|
-
|
|
1760
|
-
// Round the raw value to the desired level of precision
|
|
1761
|
-
popDev = U.trim(popDev);
|
|
1762
|
-
|
|
1763
|
-
// Populate the test entry
|
|
1764
|
-
test['score'] = popDev;
|
|
1765
|
-
test['details'] = { 'maxDeviation': max - min };
|
|
1766
|
-
|
|
1767
|
-
// Populate the N+1 summary "district" in district.statistics
|
|
1768
|
-
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
1769
|
-
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
1770
|
-
let summaryRow = s.districts.numberOfRows() - 1;
|
|
1771
|
-
|
|
1772
|
-
totalPop[summaryRow] = targetSize;
|
|
1773
|
-
popDevPct[summaryRow] = popDev;
|
|
1774
|
-
|
|
1775
|
-
return test;
|
|
1776
|
-
}
|
|
1777
|
-
*/
|
|
1778
1195
|
// NOTE - This validity check is *derived* and depends on population deviation %
|
|
1779
1196
|
// being computed (above) and normalized in test log & scorecard generation.
|
|
1780
1197
|
function doHasEqualPopulations(s, bLog = false) {
|
|
@@ -1901,7 +1318,7 @@ function gfPerimeter(poly) {
|
|
|
1901
1318
|
exports.gfPerimeter = gfPerimeter;
|
|
1902
1319
|
// TODO - POLY: Confirm Cartesian calculations w/ Terry
|
|
1903
1320
|
// Cloned from polyPerimeter() in 'poly' and revised to use Cartesian distance
|
|
1904
|
-
// NOTE
|
|
1321
|
+
// NOTE - No conversion of degrees to radians!
|
|
1905
1322
|
function _polygonPerimeter(poly) {
|
|
1906
1323
|
let polyOptions = { noLatitudeCorrection: true }; // Cartesian distance
|
|
1907
1324
|
poly = Poly.polyNormalize(poly, polyOptions);
|
|
@@ -1962,6 +1379,49 @@ __export(__webpack_require__(/*! ./results */ "./src/results.ts"));
|
|
|
1962
1379
|
__export(__webpack_require__(/*! ./types */ "./src/types.ts"));
|
|
1963
1380
|
|
|
1964
1381
|
|
|
1382
|
+
/***/ }),
|
|
1383
|
+
|
|
1384
|
+
/***/ "./src/minority.ts":
|
|
1385
|
+
/*!*************************!*\
|
|
1386
|
+
!*** ./src/minority.ts ***!
|
|
1387
|
+
\*************************/
|
|
1388
|
+
/*! no static exports found */
|
|
1389
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
1390
|
+
|
|
1391
|
+
"use strict";
|
|
1392
|
+
|
|
1393
|
+
//
|
|
1394
|
+
// PROTECTS MINORITIES
|
|
1395
|
+
//
|
|
1396
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
1397
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
1398
|
+
};
|
|
1399
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1400
|
+
const majority_minority_json_1 = __importDefault(__webpack_require__(/*! ../static/majority-minority.json */ "./static/majority-minority.json"));
|
|
1401
|
+
const vra5_preclearance_json_1 = __importDefault(__webpack_require__(/*! ../static/vra5-preclearance.json */ "./static/vra5-preclearance.json"));
|
|
1402
|
+
// import stateContacts from '../static/state-contacts.json';
|
|
1403
|
+
// import demographicDefs from '../static/demographic-defns.json';
|
|
1404
|
+
// TODO - 2020: Update/revise this, when the update comes out in September:
|
|
1405
|
+
// Sources for majority-minority info:
|
|
1406
|
+
// - https://en.wikipedia.org/wiki/List_of_majority-minority_United_States_congressional_districts
|
|
1407
|
+
// - http://www.ncsl.org/Portals/1/Documents/Redistricting/Redistricting_2010.pdf (PP. 80–84)
|
|
1408
|
+
// - https://www.justice.gov/crt/jurisdictions-previously-covered-section-5
|
|
1409
|
+
function getMajorityMinority(s) {
|
|
1410
|
+
const xx = s.state.xx;
|
|
1411
|
+
const mMDict = majority_minority_json_1.default;
|
|
1412
|
+
const stateMM = mMDict[xx];
|
|
1413
|
+
return stateMM;
|
|
1414
|
+
}
|
|
1415
|
+
exports.getMajorityMinority = getMajorityMinority;
|
|
1416
|
+
function getVRASection5(s) {
|
|
1417
|
+
const xx = s.state.xx;
|
|
1418
|
+
const vraPreDict = vra5_preclearance_json_1.default;
|
|
1419
|
+
const stateVRAPre = vraPreDict[xx];
|
|
1420
|
+
return stateVRAPre;
|
|
1421
|
+
}
|
|
1422
|
+
exports.getVRASection5 = getVRASection5;
|
|
1423
|
+
|
|
1424
|
+
|
|
1965
1425
|
/***/ }),
|
|
1966
1426
|
|
|
1967
1427
|
/***/ "./src/political.ts":
|
|
@@ -1979,112 +1439,6 @@ __export(__webpack_require__(/*! ./types */ "./src/types.ts"));
|
|
|
1979
1439
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
1980
1440
|
// NOTE - This file will NOT be empty, when legacy code is deleted.
|
|
1981
1441
|
const assert_1 = __webpack_require__(/*! assert */ "assert");
|
|
1982
|
-
/* TODO - DELETE
|
|
1983
|
-
import * as D from './_data'
|
|
1984
|
-
import { AnalyticsSession } from './_api';
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
// Partisan analytics need the following data:
|
|
1988
|
-
//
|
|
1989
|
-
// An "election model" by geo_id, where each item has 4 pieces of data:
|
|
1990
|
-
//
|
|
1991
|
-
// { geo_id, Democratic votes, Republican votes, Total votes }
|
|
1992
|
-
//
|
|
1993
|
-
// NOTE: D + R <= Total, because there could be third-party or write-in votes.
|
|
1994
|
-
//
|
|
1995
|
-
// An election model can simply represent one election, e.g., President 2012,
|
|
1996
|
-
// or combine multiple elections in some fashion. An election model is used to
|
|
1997
|
-
// computer a single index of the likely partisan weight / lean / preference
|
|
1998
|
-
// for the districts in a plan. An election model and the associated index go
|
|
1999
|
-
// hand in hand. So much so that the index frequently stands in as the name for
|
|
2000
|
-
// both, e.g., Cook's PVI is one example, Nagle's 7s, Hofeller's Formula, NDRC's
|
|
2001
|
-
// DPI.
|
|
2002
|
-
//
|
|
2003
|
-
// I'm labelling this general concept a "Voter Preference Index (VPI)," a
|
|
2004
|
-
// conscious +1 letter play on Cook's "PVI" acronymn.
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
// MEASURING BIAS & RESPONSIVENESS (NAGLE'S METHOD)
|
|
2008
|
-
|
|
2009
|
-
export function doSeatsBias(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
2010
|
-
{
|
|
2011
|
-
let test = s.getTest(T.Test.SeatsBias) as T.TestEntry;
|
|
2012
|
-
|
|
2013
|
-
if (bLog) console.log("TODO - Calculating seats bias ...");
|
|
2014
|
-
|
|
2015
|
-
return test;
|
|
2016
|
-
}
|
|
2017
|
-
|
|
2018
|
-
export function doVotesBias(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
2019
|
-
{
|
|
2020
|
-
let test = s.getTest(T.Test.VotesBias) as T.TestEntry;
|
|
2021
|
-
|
|
2022
|
-
if (bLog) console.log("TODO - Calculating votes bias ...");
|
|
2023
|
-
|
|
2024
|
-
return test;
|
|
2025
|
-
}
|
|
2026
|
-
|
|
2027
|
-
export function doResponsiveness(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
2028
|
-
{
|
|
2029
|
-
let test = s.getTest(T.Test.Responsiveness) as T.TestEntry;
|
|
2030
|
-
|
|
2031
|
-
if (bLog) console.log("TODO - Calculating responsiveness ...");
|
|
2032
|
-
|
|
2033
|
-
return test;
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
export function doResponsiveDistricts(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
2037
|
-
{
|
|
2038
|
-
let test = s.getTest(T.Test.ResponsiveDistricts) as T.TestEntry;
|
|
2039
|
-
|
|
2040
|
-
if (bLog) console.log("TODO - Calculating # of responsive districts ...");
|
|
2041
|
-
|
|
2042
|
-
return test;
|
|
2043
|
-
}
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
// OTHER MEASURES OF PARTISAN BIAS
|
|
2047
|
-
|
|
2048
|
-
// TODO - PARTISAN: This formula might need to be inverted for D vs. R +/-
|
|
2049
|
-
// TODO - Normalize the results.
|
|
2050
|
-
export function doEfficiencyGap(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
2051
|
-
{
|
|
2052
|
-
if (bLog) console.log("TODO - Calculating the efficiency gap ...");
|
|
2053
|
-
|
|
2054
|
-
let test = s.getTest(T.Test.EfficiencyGap) as T.TestEntry;
|
|
2055
|
-
|
|
2056
|
-
// Get partisan statistics by districts.
|
|
2057
|
-
// Use Democratic votes, seats, and shares by convention.
|
|
2058
|
-
let DVotes = s.districts.statistics[D.DistrictField.DemVotes];
|
|
2059
|
-
let DSeats = s.districts.statistics[D.DistrictField.DemSeat];
|
|
2060
|
-
let TPVotes = s.districts.statistics[D.DistrictField.TwoPartyVote];
|
|
2061
|
-
|
|
2062
|
-
// Exclude the dummy unassigned '0' and N+1 summary "districts"
|
|
2063
|
-
DVotes = DVotes.slice(1, -1);
|
|
2064
|
-
DSeats = DSeats.slice(1, -1);
|
|
2065
|
-
TPVotes = TPVotes.slice(1, -1);
|
|
2066
|
-
|
|
2067
|
-
// Calculate D vote share & D seat share
|
|
2068
|
-
let DVoteShare = U.sumArray(DVotes) / U.sumArray(TPVotes);
|
|
2069
|
-
let DSeatShare = U.sumArray(DSeats) / s.state.nDistricts;
|
|
2070
|
-
|
|
2071
|
-
// Finally, calculate the Efficiency Gap
|
|
2072
|
-
let efficiencyGap = (DSeatShare - 0.5) - (2.0 * (DVoteShare - 0.5));
|
|
2073
|
-
|
|
2074
|
-
// Round the raw value to the desired level of precision
|
|
2075
|
-
efficiencyGap = U.trim(efficiencyGap);
|
|
2076
|
-
|
|
2077
|
-
// Populate the test entry
|
|
2078
|
-
test['score'] = efficiencyGap;
|
|
2079
|
-
// test['normalizedScore'] = 0; // TODO - Normalize the raw score
|
|
2080
|
-
test['details'] = {}; // TODO - Add details, if any
|
|
2081
|
-
|
|
2082
|
-
return test;
|
|
2083
|
-
}
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
// HELPERS
|
|
2087
|
-
*/
|
|
2088
1442
|
function fptpWin(demPct) {
|
|
2089
1443
|
// Vote shares should be fractions in the range [0.0 – 1.0]
|
|
2090
1444
|
assert_1.strict((demPct <= 1.0) && (demPct >= 0.));
|
|
@@ -2122,10 +1476,9 @@ function doPreprocessData(s, bLog = false) {
|
|
|
2122
1476
|
if (!s.bOneTimeProcessingDone) {
|
|
2123
1477
|
doPreprocessCountyFeatures(s, bLog);
|
|
2124
1478
|
doPreprocessCensus(s, bLog);
|
|
2125
|
-
doPreprocessElection(s, bLog);
|
|
1479
|
+
// doPreprocessElection(s, bLog);
|
|
2126
1480
|
s.bOneTimeProcessingDone = true;
|
|
2127
1481
|
}
|
|
2128
|
-
// NOTE - UNASSIGNED: Made both the planByGeoID & DistrictID are right
|
|
2129
1482
|
// Invert the plan by district ID
|
|
2130
1483
|
s.plan.invertPlan();
|
|
2131
1484
|
// Create a map of geoIDs to feature IDs
|
|
@@ -2207,7 +1560,6 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
2207
1560
|
// Loop over the counties
|
|
2208
1561
|
for (let county in fipsCodes) {
|
|
2209
1562
|
let fipsCode = fipsCodes[county];
|
|
2210
|
-
// NOTE - SPLITTING
|
|
2211
1563
|
// Skip the dummy county
|
|
2212
1564
|
if (fipsCode == '000')
|
|
2213
1565
|
continue;
|
|
@@ -2231,10 +1583,10 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
2231
1583
|
s.state.expectedAffected = expectedAffected;
|
|
2232
1584
|
}
|
|
2233
1585
|
// PREPROCESS ELECTION RESULTS
|
|
2234
|
-
function doPreprocessElection(s, bLog = false)
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
}
|
|
1586
|
+
// function doPreprocessElection(s: AnalyticsSession, bLog: boolean = false): void
|
|
1587
|
+
// {
|
|
1588
|
+
// if (bLog) console.log("Preprocessing election data ...");
|
|
1589
|
+
// }
|
|
2238
1590
|
|
|
2239
1591
|
|
|
2240
1592
|
/***/ }),
|
|
@@ -2267,234 +1619,6 @@ const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"
|
|
|
2267
1619
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
2268
1620
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
2269
1621
|
const state_reqs_json_1 = __importDefault(__webpack_require__(/*! ../static/state-reqs.json */ "./static/state-reqs.json"));
|
|
2270
|
-
// PLAN ANALYTICS
|
|
2271
|
-
/* TODO - DELETE
|
|
2272
|
-
export type RequirementsCategory = {
|
|
2273
|
-
score: T.TriState;
|
|
2274
|
-
metrics: {
|
|
2275
|
-
complete: T.TriState;
|
|
2276
|
-
contiguous: T.TriState;
|
|
2277
|
-
freeOfHoles: T.TriState;
|
|
2278
|
-
equalPopulation: T.TriState;
|
|
2279
|
-
};
|
|
2280
|
-
details: {
|
|
2281
|
-
unassignedFeatures: string[]; // A possibly empty list of GEOIDs
|
|
2282
|
-
emptyDistricts: number[]; // A possibly empty list of district IDs
|
|
2283
|
-
discontiguousDistricts: number[]; // Ditto
|
|
2284
|
-
embeddedDistricts: number[]; // Ditto
|
|
2285
|
-
populationDeviation: number; // A fraction [0.0 – 1.0] to represent as a %
|
|
2286
|
-
deviationThreshold: number; // A fraction [0.0 – 1.0] to represent as a %
|
|
2287
|
-
};
|
|
2288
|
-
datasets: T.Datasets;
|
|
2289
|
-
resources: {
|
|
2290
|
-
stateReqs: string;
|
|
2291
|
-
};
|
|
2292
|
-
};
|
|
2293
|
-
*/
|
|
2294
|
-
/* TODO - DELETE
|
|
2295
|
-
export type CompactnessCategory = {
|
|
2296
|
-
score: number; // An integer score [0–100]
|
|
2297
|
-
metrics: {
|
|
2298
|
-
reock: number; // A decimal number [0.0–1.0]
|
|
2299
|
-
polsby: number; // A decimal number [0.0–1.0]
|
|
2300
|
-
};
|
|
2301
|
-
details: {
|
|
2302
|
-
// None at this time
|
|
2303
|
-
};
|
|
2304
|
-
datasets: T.Datasets;
|
|
2305
|
-
resources: {
|
|
2306
|
-
// None at this time
|
|
2307
|
-
};
|
|
2308
|
-
};
|
|
2309
|
-
*/
|
|
2310
|
-
/* TODO - DELETE
|
|
2311
|
-
export type SplittingCategory = {
|
|
2312
|
-
score: number; // An integer score [0–100]
|
|
2313
|
-
metrics: {
|
|
2314
|
-
sqEnt_DCreduced: number, // A decimal number [1.0 – < 2.0]
|
|
2315
|
-
sqEnt_CDreduced: number // A decimal number [1.0 – < 2.0]
|
|
2316
|
-
};
|
|
2317
|
-
details: {
|
|
2318
|
-
countiesSplitUnexpectedly: string[], // A possibly empty list of county names
|
|
2319
|
-
unexpectedAffected: number, // A fraction [0.0 – 1.0] to represent as a %
|
|
2320
|
-
nSplitVTDs: number, // An integer, possibly 0
|
|
2321
|
-
splitVTDs: string[] // A possibly empty list of GEOIDs
|
|
2322
|
-
};
|
|
2323
|
-
datasets: T.Datasets;
|
|
2324
|
-
resources: {
|
|
2325
|
-
// None at this time
|
|
2326
|
-
};
|
|
2327
|
-
};
|
|
2328
|
-
*/
|
|
2329
|
-
/* TODO - DELETE
|
|
2330
|
-
export type PartisanCategory = {
|
|
2331
|
-
score: number; // An integer score [0–100]
|
|
2332
|
-
metrics: {
|
|
2333
|
-
partisanBias: 0.15, // TBD
|
|
2334
|
-
responsiveness: 2.0 // TBD
|
|
2335
|
-
};
|
|
2336
|
-
details: {
|
|
2337
|
-
// TODO - Need to flesh this out
|
|
2338
|
-
};
|
|
2339
|
-
datasets: T.Datasets;
|
|
2340
|
-
resources: {
|
|
2341
|
-
planScore?: string;
|
|
2342
|
-
};
|
|
2343
|
-
};
|
|
2344
|
-
*/
|
|
2345
|
-
/* TODO - DELETE
|
|
2346
|
-
export type MinorityCategory = {
|
|
2347
|
-
score: null; // Explicitly NOT scored
|
|
2348
|
-
metrics: {
|
|
2349
|
-
nBlack37to50: number, // Integer >= 0; two-digit maximum
|
|
2350
|
-
nBlackMajority: number, // Ditto
|
|
2351
|
-
nHispanic37to50: number, // Ditto
|
|
2352
|
-
nHispanicMajority: number, // Ditto
|
|
2353
|
-
nPacific37to50: number, // Ditto
|
|
2354
|
-
nPacificMajority: number, // Ditto
|
|
2355
|
-
nAsian37to50: number, // Ditto
|
|
2356
|
-
nAsianMajority: number, // Ditto
|
|
2357
|
-
nNative37to50: number, // Ditto
|
|
2358
|
-
nNativeMajority: number, // Ditto
|
|
2359
|
-
nMinority37to50: number, // Ditto
|
|
2360
|
-
nMinorityMajority: number, // Ditto
|
|
2361
|
-
|
|
2362
|
-
averageDVoteShare: number // A fraction [0.0 – 1.0] to represent as a %
|
|
2363
|
-
};
|
|
2364
|
-
details: {
|
|
2365
|
-
vap: true, // true = using VAP data; false = CVAP data
|
|
2366
|
-
comboCategories: true // true = using combo fields; false = mutually exclusive
|
|
2367
|
-
};
|
|
2368
|
-
datasets: T.Datasets;
|
|
2369
|
-
resources: {
|
|
2370
|
-
// TODO - Add these ...
|
|
2371
|
-
};
|
|
2372
|
-
};
|
|
2373
|
-
*/
|
|
2374
|
-
/* TODO - DELETE
|
|
2375
|
-
export type PlanAnalytics = {
|
|
2376
|
-
requirements: RequirementsCategory;
|
|
2377
|
-
compactness: CompactnessCategory;
|
|
2378
|
-
// TODO - Don't show these categories yet
|
|
2379
|
-
splitting: SplittingCategory;
|
|
2380
|
-
partisan: PartisanCategory;
|
|
2381
|
-
minority: MinorityCategory;
|
|
2382
|
-
}
|
|
2383
|
-
*/
|
|
2384
|
-
// EXAMPLE
|
|
2385
|
-
/* TODO - DELETE
|
|
2386
|
-
let sampleRequirements: RequirementsCategory = {
|
|
2387
|
-
score: T.TriState.Red,
|
|
2388
|
-
metrics: {
|
|
2389
|
-
complete: T.TriState.Green,
|
|
2390
|
-
contiguous: T.TriState.Red,
|
|
2391
|
-
freeOfHoles: T.TriState.Yellow,
|
|
2392
|
-
equalPopulation: T.TriState.Red
|
|
2393
|
-
},
|
|
2394
|
-
details: {
|
|
2395
|
-
unassignedFeatures: [],
|
|
2396
|
-
emptyDistricts: [],
|
|
2397
|
-
discontiguousDistricts: [2],
|
|
2398
|
-
embeddedDistricts: [],
|
|
2399
|
-
populationDeviation: 0.6748,
|
|
2400
|
-
deviationThreshold: 0.75 / 100
|
|
2401
|
-
},
|
|
2402
|
-
datasets: {
|
|
2403
|
-
census: "2010 Census Total Population"
|
|
2404
|
-
},
|
|
2405
|
-
resources: {
|
|
2406
|
-
stateReqs: "https://www.brennancenter.org/sites/default/files/publications/2019_06_50States_FINALsinglepages_20.pdf"
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
*/
|
|
2410
|
-
/* TODO - DELETE
|
|
2411
|
-
let sampleCompactness: CompactnessCategory = {
|
|
2412
|
-
score: 60,
|
|
2413
|
-
metrics: {
|
|
2414
|
-
reock: 0.3773,
|
|
2415
|
-
polsby: 0.3815
|
|
2416
|
-
},
|
|
2417
|
-
details: {},
|
|
2418
|
-
datasets: {
|
|
2419
|
-
shapes: "2010 VTD shapes"
|
|
2420
|
-
},
|
|
2421
|
-
resources: {}
|
|
2422
|
-
}
|
|
2423
|
-
*/
|
|
2424
|
-
/* TODO - DELETE
|
|
2425
|
-
let sampleSplitting: SplittingCategory = {
|
|
2426
|
-
score: 73,
|
|
2427
|
-
metrics: {
|
|
2428
|
-
sqEnt_DCreduced: 1.531,
|
|
2429
|
-
sqEnt_CDreduced: 1.760
|
|
2430
|
-
},
|
|
2431
|
-
details: {
|
|
2432
|
-
countiesSplitUnexpectedly: [
|
|
2433
|
-
"Bladen", "Buncombe", "Catawba", "Cumberland", "Durham", "Guilford", "Iredell", "Johnston", "Pitt", "Rowan", "Wilson"
|
|
2434
|
-
],
|
|
2435
|
-
unexpectedAffected: 0.3096,
|
|
2436
|
-
nSplitVTDs: 12,
|
|
2437
|
-
splitVTDs: ["VTD-01", "VTD-02", "VTD-03", "VTD-04", "VTD-05", "VTD-06", "VTD-07", "VTD-08", "VTD-09", "VTD-10", "VTD-11", "VTD-12"]
|
|
2438
|
-
},
|
|
2439
|
-
datasets: {},
|
|
2440
|
-
resources: {}
|
|
2441
|
-
}
|
|
2442
|
-
*/
|
|
2443
|
-
/* TODO - DELETE
|
|
2444
|
-
let samplePartisan: PartisanCategory = {
|
|
2445
|
-
score: 100,
|
|
2446
|
-
metrics: {
|
|
2447
|
-
partisanBias: 0.15,
|
|
2448
|
-
responsiveness: 2.0
|
|
2449
|
-
},
|
|
2450
|
-
details: {},
|
|
2451
|
-
datasets: {
|
|
2452
|
-
election: "2016 Presidential, US Senate, Governor, and AG election results"
|
|
2453
|
-
},
|
|
2454
|
-
resources: {
|
|
2455
|
-
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
*/
|
|
2459
|
-
/* TODO - DELETE
|
|
2460
|
-
let sampleMinority: MinorityCategory = {
|
|
2461
|
-
score: null,
|
|
2462
|
-
metrics: {
|
|
2463
|
-
nBlack37to50: 1,
|
|
2464
|
-
nBlackMajority: 12,
|
|
2465
|
-
nHispanic37to50: 0,
|
|
2466
|
-
nHispanicMajority: 0,
|
|
2467
|
-
nPacific37to50: 0,
|
|
2468
|
-
nPacificMajority: 0,
|
|
2469
|
-
nAsian37to50: 0,
|
|
2470
|
-
nAsianMajority: 0,
|
|
2471
|
-
nNative37to50: 0,
|
|
2472
|
-
nNativeMajority: 0,
|
|
2473
|
-
nMinority37to50: 0,
|
|
2474
|
-
nMinorityMajority: 0,
|
|
2475
|
-
|
|
2476
|
-
averageDVoteShare: 0.90
|
|
2477
|
-
},
|
|
2478
|
-
details: {
|
|
2479
|
-
vap: true,
|
|
2480
|
-
comboCategories: true
|
|
2481
|
-
},
|
|
2482
|
-
datasets: {
|
|
2483
|
-
vap: "2010 Voting Age Population"
|
|
2484
|
-
},
|
|
2485
|
-
resources: {}
|
|
2486
|
-
}
|
|
2487
|
-
*/
|
|
2488
|
-
/* TODO - DELETE
|
|
2489
|
-
export const samplePlanAnalytics: PlanAnalytics = {
|
|
2490
|
-
requirements: sampleRequirements,
|
|
2491
|
-
compactness: sampleCompactness,
|
|
2492
|
-
// TODO - Don't show these categories yet
|
|
2493
|
-
splitting: sampleSplitting,
|
|
2494
|
-
partisan: samplePartisan,
|
|
2495
|
-
minority: sampleMinority
|
|
2496
|
-
}
|
|
2497
|
-
*/
|
|
2498
1622
|
function prepareRequirementsChecklist(s, bLog = false) {
|
|
2499
1623
|
if (!(s.bPostProcessingDone)) {
|
|
2500
1624
|
doAnalyzePostProcessing(s);
|
|
@@ -2524,14 +1648,8 @@ function prepareRequirementsChecklist(s, bLog = false) {
|
|
|
2524
1648
|
const emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
2525
1649
|
const discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
2526
1650
|
const embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
2527
|
-
// TODO - SCORE: DELETE - This code is hooked correctly to use dra-score
|
|
2528
|
-
// const scorecard = s._scorecard as Score.Scorecard;
|
|
2529
|
-
// const populationDeviation = scorecard.best.populationDeviation.raw;
|
|
2530
1651
|
const populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
2531
|
-
// console.log("Population deviations =", populationDeviationDetail, populationDeviation);
|
|
2532
|
-
// const deviationThreshold = scorecard.best.populationDeviation.notes['threshold'];
|
|
2533
1652
|
const deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
2534
|
-
// console.log("Population deviation thresholds =", deviationThresholdDetail, deviationThreshold);
|
|
2535
1653
|
const xx = s.state.xx;
|
|
2536
1654
|
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
2537
1655
|
const stateReqsDict = state_reqs_json_1.default;
|
|
@@ -2614,8 +1732,8 @@ function prepareDistrictStatistics(s, bLog = false) {
|
|
|
2614
1732
|
s.districts.statistics[D.DistrictField.AsianPct][i],
|
|
2615
1733
|
s.districts.statistics[D.DistrictField.NativePct][i]
|
|
2616
1734
|
];
|
|
2617
|
-
//
|
|
2618
|
-
//
|
|
1735
|
+
// NOTE - Until we add three-state support top to bottom in Requirements,
|
|
1736
|
+
// map booleans to tri-states here.
|
|
2619
1737
|
rawRow[3 /* bEqualPop */] = U.mapBooleanToTriState(rawRow[3 /* bEqualPop */]);
|
|
2620
1738
|
rawRow[4 /* bNotEmpty */] = U.mapBooleanToTriState(rawRow[4 /* bNotEmpty */]);
|
|
2621
1739
|
rawRow[5 /* bContiguous */] = U.mapBooleanToTriState(rawRow[5 /* bContiguous */]);
|
|
@@ -2690,24 +1808,6 @@ const populationDeviationDefn = {
|
|
|
2690
1808
|
externalType: TestType.Percentage,
|
|
2691
1809
|
suites: [0 /* Legal */, 2 /* Best */] // Both so EqualPopulation can be assessed
|
|
2692
1810
|
};
|
|
2693
|
-
/* TODO - DELETE
|
|
2694
|
-
const reockDefn: T.Dict = {
|
|
2695
|
-
ID: T.Test.Reock,
|
|
2696
|
-
name: "Reock",
|
|
2697
|
-
normalize: true,
|
|
2698
|
-
externalType: TestType.Number,
|
|
2699
|
-
suites: [T.Suite.Best]
|
|
2700
|
-
};
|
|
2701
|
-
|
|
2702
|
-
const polsbyPopperDefn: T.Dict = {
|
|
2703
|
-
ID: T.Test.PolsbyPopper,
|
|
2704
|
-
name: "Polsby-Popper",
|
|
2705
|
-
normalize: true,
|
|
2706
|
-
externalType: TestType.Number,
|
|
2707
|
-
suites: [T.Suite.Best]
|
|
2708
|
-
};
|
|
2709
|
-
*/
|
|
2710
|
-
// NOTE - SPLITTING
|
|
2711
1811
|
const unexpectedCountySplitsDefn = {
|
|
2712
1812
|
ID: 5 /* UnexpectedCountySplits */,
|
|
2713
1813
|
name: "Unexpected County Splits",
|
|
@@ -2715,7 +1815,6 @@ const unexpectedCountySplitsDefn = {
|
|
|
2715
1815
|
externalType: TestType.Percentage,
|
|
2716
1816
|
suites: [2 /* Best */]
|
|
2717
1817
|
};
|
|
2718
|
-
// NOTE - SPLITTING
|
|
2719
1818
|
const VTDSplitsDefn = {
|
|
2720
1819
|
ID: 6 /* VTDSplits */,
|
|
2721
1820
|
name: "VTD Splits",
|
|
@@ -2730,87 +1829,16 @@ const testDefns = {
|
|
|
2730
1829
|
[2 /* FreeOfHoles */]: freeOfHolesDefn,
|
|
2731
1830
|
[3 /* EqualPopulation */]: equalPopulationDefn,
|
|
2732
1831
|
[4 /* PopulationDeviation */]: populationDeviationDefn,
|
|
2733
|
-
// [T.Test.Reock]: reockDefn, TODO - DELETE
|
|
2734
|
-
// [T.Test.PolsbyPopper]: polsbyPopperDefn, TODO - DELETE
|
|
2735
1832
|
[5 /* UnexpectedCountySplits */]: unexpectedCountySplitsDefn,
|
|
2736
1833
|
[6 /* VTDSplits */]: VTDSplitsDefn,
|
|
2737
1834
|
};
|
|
2738
|
-
/* TODO - DELETE
|
|
2739
|
-
// NORMALIZE RAW ANALYTICS
|
|
2740
|
-
// Raw numeric analytics, such as population deviation, compactness, etc. are
|
|
2741
|
-
// normalized as part of creating a scorecard, so the code to normalize results
|
|
2742
|
-
// is encapsulated here.
|
|
2743
|
-
|
|
2744
|
-
// Configure scale parameters for normalizing each raw test result.
|
|
2745
|
-
// Scales consist of a minimum & a maximum *raw* value. If the values get
|
|
2746
|
-
// inverted (to make bigger better), these will switch.
|
|
2747
|
-
// This process needs to be separate from the test configuration info above,
|
|
2748
|
-
// because some scales need access to the analytics session object.
|
|
2749
|
-
export function doConfigureScales(s: AnalyticsSession): void
|
|
2750
|
-
{
|
|
2751
|
-
// Scale defn for PopulationDeviation
|
|
2752
|
-
const CDLimit = 0.75 / 100; // Deviation threshold for CD's
|
|
2753
|
-
const LDLimit = 10.00 / 100; // Deviation threshold for LD's
|
|
2754
|
-
|
|
2755
|
-
const CDGoodEnough = 0.20 / 100;
|
|
2756
|
-
const LDGoodEnough = (CDGoodEnough / CDLimit) * LDLimit;
|
|
2757
|
-
const popDevScale = (s.legislativeDistricts) ? [1.0 - LDLimit, 1.0 - LDGoodEnough] : [1.0 - CDLimit, 1.0 - CDGoodEnough];
|
|
2758
|
-
// const scale = [1.0 - CDLimit, 1.0 - CDGoodEnough];
|
|
2759
|
-
|
|
2760
|
-
s.testScales[T.Test.PopulationDeviation] = { scale: popDevScale, bInvertRaw: true };
|
|
2761
|
-
|
|
2762
|
-
s.testScales[T.Test.Reock] = { scale: [0.25, 0.50] };
|
|
2763
|
-
s.testScales[T.Test.PolsbyPopper] = { scale: [0.10, 0.50] };
|
|
2764
|
-
|
|
2765
|
-
const nDistricts = s.state.nDistricts;
|
|
2766
|
-
const nCounties = s.counties.nCounties;
|
|
2767
|
-
|
|
2768
|
-
// NOTE - SPLITTING: Experiment w/ this multiplier. Only allowing the expected
|
|
2769
|
-
// number of county splits seems too stringent, empirically.
|
|
2770
|
-
const allowableCountySplitsMultiplier = 1.5;
|
|
2771
|
-
const nAllowableSplits = Math.min(allowableCountySplitsMultiplier * (nDistricts - 1));
|
|
2772
|
-
const countySplittingThreshold = ((nAllowableSplits * 1.71) + ((nCounties - nAllowableSplits) * 1.0)) / nCounties;
|
|
2773
|
-
const countySplittingScale = [1.0, countySplittingThreshold];
|
|
2774
|
-
s.testScales[T.Test.CountySplitting] = { scale: countySplittingScale, bInvertScaled: true };
|
|
2775
|
-
|
|
2776
|
-
const districtSplittingThreshold = 1.5;
|
|
2777
|
-
const districtSplittingScale = [1.0, districtSplittingThreshold];
|
|
2778
|
-
s.testScales[T.Test.DistrictSplitting] = { scale: districtSplittingScale, bInvertScaled: true };
|
|
2779
|
-
|
|
2780
|
-
// TODO - More analytics ...
|
|
2781
|
-
}
|
|
2782
|
-
*/
|
|
2783
1835
|
// Postprocess analytics - Normalize numeric results and derive secondary tests.
|
|
2784
1836
|
// Do this after analytics have been run and before preparing a test log or scorecard.
|
|
2785
1837
|
function doAnalyzePostProcessing(s, bLog = false) {
|
|
2786
|
-
// TODO - DELETE
|
|
2787
|
-
// if (s.useLegacy())
|
|
2788
|
-
// {
|
|
2789
|
-
// // Normalize the raw scores for all the numerics tests
|
|
2790
|
-
// let testResults = U.getNumericObjectKeys(testDefns);
|
|
2791
|
-
// for (let testID of testResults)
|
|
2792
|
-
// {
|
|
2793
|
-
// if (testDefns[testID]['normalize'])
|
|
2794
|
-
// {
|
|
2795
|
-
// let testResult = s.getTest(testID) as T.TestEntry;
|
|
2796
|
-
// let rawScore = testResult['score'] as number;
|
|
2797
|
-
// let normalizedScore: number;
|
|
2798
|
-
// normalizedScore = U.normalize(rawScore, s.testScales[testID]);
|
|
2799
|
-
// testResult['normalizedScore'] = normalizedScore;
|
|
2800
|
-
// // Add the scale used to normalize the raw score to the details
|
|
2801
|
-
// testResult['details']['scale'] = s.testScales[testID].scale;
|
|
2802
|
-
// }
|
|
2803
|
-
// }
|
|
2804
|
-
// }
|
|
2805
|
-
// else
|
|
2806
|
-
// {
|
|
2807
1838
|
// Just populate the normalized population deviation score in the test
|
|
2808
1839
|
const scorecard = s._scorecard;
|
|
2809
1840
|
let popDev = s.getTest(4 /* PopulationDeviation */);
|
|
2810
1841
|
popDev['normalizedScore'] = scorecard.traditionalPrinciples.populationDeviation.normalized;
|
|
2811
|
-
// TODO - DELETE
|
|
2812
|
-
// test['normalizedScore'] = scorecard.best.populationDeviation.normalized;
|
|
2813
|
-
// TODO - SCORE: Add datasets used to details by tab
|
|
2814
1842
|
const datasets = {
|
|
2815
1843
|
shapes: S.SHAPES,
|
|
2816
1844
|
census: U.deepCopy(s.config['descriptions']['CENSUS']),
|
|
@@ -2821,12 +1849,10 @@ function doAnalyzePostProcessing(s, bLog = false) {
|
|
|
2821
1849
|
scorecard.minority.details['vap'] = datasets.vap;
|
|
2822
1850
|
scorecard.traditionalPrinciples.details['shapes'] = datasets.shapes;
|
|
2823
1851
|
scorecard.traditionalPrinciples.details['census'] = datasets.census;
|
|
2824
|
-
// TODO - SCORE: Add legacy splits details
|
|
2825
1852
|
const simpleSplits = s.getTest(5 /* UnexpectedCountySplits */);
|
|
2826
1853
|
scorecard.traditionalPrinciples.details['unexpectedAffected'] = simpleSplits['score'];
|
|
2827
1854
|
scorecard.traditionalPrinciples.details['countiesSplitUnexpectedly'] = U.deepCopy(simpleSplits['details']['countiesSplitUnexpectedly']);
|
|
2828
1855
|
// NOTE - Add split precincts in dra-client directly
|
|
2829
|
-
// }
|
|
2830
1856
|
// Derive secondary tests
|
|
2831
1857
|
analyze_1.doDeriveSecondaryTests(s, bLog);
|
|
2832
1858
|
// Toggle the semaphore, so postprocessing isn't for both the testlog & scorecard
|
|
@@ -2860,6 +1886,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
2860
1886
|
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "@dra2020/dra-score"));
|
|
2861
1887
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
2862
1888
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
1889
|
+
const M = __importStar(__webpack_require__(/*! ./minority */ "./src/minority.ts"));
|
|
2863
1890
|
// PROFILE A PLAN
|
|
2864
1891
|
function profilePlan(s, bLog = false) {
|
|
2865
1892
|
const state = s.state.xx;
|
|
@@ -2965,26 +1992,23 @@ function getStatewideDemographics(s, bLog = false) {
|
|
|
2965
1992
|
function scorePlan(s, p, bLog = false, overridesJSON) {
|
|
2966
1993
|
let scorer = new Score.Scorer();
|
|
2967
1994
|
const scorecard = scorer.score(p, overridesJSON);
|
|
2968
|
-
//
|
|
2969
|
-
//
|
|
2970
|
-
// calling sequence.
|
|
1995
|
+
// Before returning, create a dummy population deviation test, for
|
|
1996
|
+
// doHasEqualPopulations() to use later.This is preserving the old calling sequence.
|
|
2971
1997
|
let test = s.getTest(4 /* PopulationDeviation */);
|
|
2972
|
-
// TODO - SCORE: U.trim(popDev)???
|
|
2973
|
-
// const popDev = scorecard.best.populationDeviation.raw;
|
|
2974
1998
|
// Get the raw population deviation
|
|
2975
1999
|
const popDev = scorecard.traditionalPrinciples.populationDeviation.raw;
|
|
2976
2000
|
// Populate the test entry
|
|
2977
2001
|
test['score'] = popDev;
|
|
2978
2002
|
test['details'] = { 'maxDeviation': scorecard.traditionalPrinciples.populationDeviation.notes['maxDeviation'] };
|
|
2979
|
-
// TODO - DELETE
|
|
2980
|
-
// test['details'] = { 'maxDeviation': scorecard.best.populationDeviation.notes['maxDeviation'] };
|
|
2981
2003
|
// Populate the N+1 summary "district" in district.statistics
|
|
2982
2004
|
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
2983
2005
|
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
2984
2006
|
let summaryRow = s.districts.numberOfRows() - 1;
|
|
2985
2007
|
totalPop[summaryRow] = p.populationProfile.targetSize;
|
|
2986
2008
|
popDevPct[summaryRow] = popDev;
|
|
2987
|
-
//
|
|
2009
|
+
// Add minority notes
|
|
2010
|
+
scorecard.minority.details['majorityMinority'] = M.getMajorityMinority(s);
|
|
2011
|
+
scorecard.minority.details['vraPreclearance'] = M.getVRASection5(s);
|
|
2988
2012
|
return scorecard;
|
|
2989
2013
|
}
|
|
2990
2014
|
exports.scorePlan = scorePlan;
|
|
@@ -3042,7 +2066,6 @@ exports.SHAPES = "2010 VTD shapes";
|
|
|
3042
2066
|
// TYPE DEFINITIONS
|
|
3043
2067
|
//
|
|
3044
2068
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3045
|
-
// TODO - SCORE
|
|
3046
2069
|
var dra_score_1 = __webpack_require__(/*! @dra2020/dra-score */ "@dra2020/dra-score");
|
|
3047
2070
|
exports.sampleProfile = dra_score_1.sampleProfile;
|
|
3048
2071
|
exports.sampleScorecard = dra_score_1.sampleScorecard;
|
|
@@ -3084,7 +2107,6 @@ function isOutOfState(geoID) {
|
|
|
3084
2107
|
return geoID == S.OUT_OF_STATE;
|
|
3085
2108
|
}
|
|
3086
2109
|
exports.isOutOfState = isOutOfState;
|
|
3087
|
-
// NOTE - UNASSIGNED
|
|
3088
2110
|
// Get the districtID to which a geoID is assigned
|
|
3089
2111
|
function getDistrict(plan, geoID) {
|
|
3090
2112
|
// All geoIDs in a state *should be* assigned to a district (including the
|
|
@@ -3139,7 +2161,6 @@ function normalize(rawScore, testScale) {
|
|
|
3139
2161
|
let coercedValue = Math.min(Math.max(rawScore, rangeMin), rangeMax);
|
|
3140
2162
|
// Scale the bounded value w/in the range [0 - (rangeMax - rangeMin)]
|
|
3141
2163
|
let scaledValue = (coercedValue - rangeMin) / (rangeMax - rangeMin);
|
|
3142
|
-
// NOTE - SPLITTING
|
|
3143
2164
|
// Invert the scaled value if necessary to make bigger = better
|
|
3144
2165
|
if (testScale.bInvertScaled) {
|
|
3145
2166
|
scaledValue = 1.0 - scaledValue;
|
|
@@ -3338,7 +2359,7 @@ function doIsComplete(s, bLog = false) {
|
|
|
3338
2359
|
if (!bAllAssigned) {
|
|
3339
2360
|
let unassignedDistrict = s.plan.geoIDsForDistrictID(S.NOT_ASSIGNED);
|
|
3340
2361
|
unassignedFeatures = Array.from(unassignedDistrict);
|
|
3341
|
-
unassignedFeatures = unassignedFeatures.slice(0, S.NUMBER_OF_ITEMS_TO_REPORT);
|
|
2362
|
+
// unassignedFeatures = unassignedFeatures.slice(0, S.NUMBER_OF_ITEMS_TO_REPORT);
|
|
3342
2363
|
}
|
|
3343
2364
|
// Do all real districts have at least one feature assigned to them?
|
|
3344
2365
|
let emptyDistricts = [];
|
|
@@ -3542,6 +2563,17 @@ function isEmbedded(districtID, geoIDs, plan, graph) {
|
|
|
3542
2563
|
exports.isEmbedded = isEmbedded;
|
|
3543
2564
|
|
|
3544
2565
|
|
|
2566
|
+
/***/ }),
|
|
2567
|
+
|
|
2568
|
+
/***/ "./static/majority-minority.json":
|
|
2569
|
+
/*!***************************************!*\
|
|
2570
|
+
!*** ./static/majority-minority.json ***!
|
|
2571
|
+
\***************************************/
|
|
2572
|
+
/*! exports provided: AL, AK, AZ, AR, CA, CO, CT, DE, FL, GA, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MA, MI, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, OH, OK, OR, PA, RI, SC, SD, TN, TX, UT, VT, VA, WA, WV, WI, WY, default */
|
|
2573
|
+
/***/ (function(module) {
|
|
2574
|
+
|
|
2575
|
+
module.exports = JSON.parse("{\"AL\":{\"Black\":[7],\"Hispanic\":[],\"Pacific\":[]},\"AK\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"AZ\":{\"Black\":[],\"Hispanic\":[2,4,7],\"Pacific\":[]},\"AR\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"CA\":{\"Black\":[13,37,43],\"Hispanic\":[17,18,20,21,28,31,32,34,35,38,39,43,45,47,51],\"Pacific\":[12,13,14,15,17,18,19,27,34,39,45,47,52]},\"CO\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"CT\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"DE\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"FL\":{\"Black\":[5,20,24],\"Hispanic\":[18,21,25],\"Pacific\":[]},\"GA\":{\"Black\":[2,4,5,13],\"Hispanic\":[],\"Pacific\":[]},\"HI\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[2]},\"ID\":{\"Black\":[],\"Hispanic\":[1],\"Pacific\":[]},\"IL\":{\"Black\":[1,2,7],\"Hispanic\":[4],\"Pacific\":[]},\"IN\":{\"Black\":[7],\"Hispanic\":[],\"Pacific\":[]},\"IA\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"KS\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"KY\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"LA\":{\"Black\":[2],\"Hispanic\":[],\"Pacific\":[]},\"ME\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"MD\":{\"Black\":[4,7],\"Hispanic\":[],\"Pacific\":[]},\"MA\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"MI\":{\"Black\":[13,14],\"Hispanic\":[],\"Pacific\":[]},\"MN\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"MS\":{\"Black\":[2],\"Hispanic\":[],\"Pacific\":[]},\"MO\":{\"Black\":[1,5],\"Hispanic\":[],\"Pacific\":[]},\"MT\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"NE\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"NV\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"NH\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"NJ\":{\"Black\":[10,12],\"Hispanic\":[13],\"Pacific\":[6]},\"NM\":{\"Black\":[],\"Hispanic\":[2,13],\"Pacific\":[]},\"NY\":{\"Black\":[5,8,9,13],\"Hispanic\":[12,16],\"Pacific\":[6,7,10]},\"NC\":{\"Black\":[1,12],\"Hispanic\":[],\"Pacific\":[]},\"ND\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"OH\":{\"Black\":[3,11],\"Hispanic\":[],\"Pacific\":[]},\"OK\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"OR\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"PA\":{\"Black\":[2],\"Hispanic\":[],\"Pacific\":[]},\"RI\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"SC\":{\"Black\":[6],\"Hispanic\":[],\"Pacific\":[]},\"SD\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"TN\":{\"Black\":[9],\"Hispanic\":[],\"Pacific\":[]},\"TX\":{\"Black\":[9,18,33],\"Hispanic\":[15,16,19,20,23,27,28,29,32],\"Pacific\":[]},\"UT\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"VT\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"VA\":{\"Black\":[3],\"Hispanic\":[],\"Pacific\":[]},\"WA\":{\"Black\":[],\"Hispanic\":[3],\"Pacific\":[9]},\"WV\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]},\"WI\":{\"Black\":[4],\"Hispanic\":[],\"Pacific\":[]},\"WY\":{\"Black\":[],\"Hispanic\":[],\"Pacific\":[]}}");
|
|
2576
|
+
|
|
3545
2577
|
/***/ }),
|
|
3546
2578
|
|
|
3547
2579
|
/***/ "./static/state-reqs.json":
|
|
@@ -3555,6 +2587,17 @@ module.exports = JSON.parse("{\"AL\":\"https://www.brennancenter.org/sites/defau
|
|
|
3555
2587
|
|
|
3556
2588
|
/***/ }),
|
|
3557
2589
|
|
|
2590
|
+
/***/ "./static/vra5-preclearance.json":
|
|
2591
|
+
/*!***************************************!*\
|
|
2592
|
+
!*** ./static/vra5-preclearance.json ***!
|
|
2593
|
+
\***************************************/
|
|
2594
|
+
/*! exports provided: AL, AK, AZ, CA, FL, GA, LA, MI, MS, NY, NC, SC, SD, TX, VA, default */
|
|
2595
|
+
/***/ (function(module) {
|
|
2596
|
+
|
|
2597
|
+
module.exports = JSON.parse("{\"AL\":\"all\",\"AK\":\"all\",\"AZ\":\"all\",\"CA\":\"parts\",\"FL\":\"parts\",\"GA\":\"all\",\"LA\":\"all\",\"MI\":\"parts\",\"MS\":\"all\",\"NY\":\"parts\",\"NC\":\"parts\",\"SC\":\"all\",\"SD\":\"parts\",\"TX\":\"all\",\"VA\":\"all\"}");
|
|
2598
|
+
|
|
2599
|
+
/***/ }),
|
|
2600
|
+
|
|
3558
2601
|
/***/ "@dra2020/dra-score":
|
|
3559
2602
|
/*!*************************************!*\
|
|
3560
2603
|
!*** external "@dra2020/dra-score" ***!
|