@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
package/dist/cli.js
CHANGED
|
@@ -91185,7 +91185,7 @@ function calcMinimalInverseResponsiveness(Vf, r) {
|
|
|
91185
91185
|
const bBalanced = isBalanced(Vf);
|
|
91186
91186
|
const ideal = bBalanced ? 0.1 : 0.2;
|
|
91187
91187
|
MIR = (1 / r) - ideal;
|
|
91188
|
-
MIR = U.trim(MIR);
|
|
91188
|
+
MIR = U.trim(Math.max(MIR, 0.0));
|
|
91189
91189
|
}
|
|
91190
91190
|
return MIR;
|
|
91191
91191
|
}
|
|
@@ -101337,7 +101337,6 @@ const preprocess_1 = __webpack_require__(/*! ./preprocess */ "./src/preprocess.t
|
|
|
101337
101337
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
101338
101338
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
101339
101339
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
101340
|
-
// import { doConfigureScales, doAnalyzePostProcessing, RequirementsChecklist} from './results' // TODO - DELETE
|
|
101341
101340
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
101342
101341
|
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
101343
101342
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
@@ -101348,7 +101347,6 @@ class AnalyticsSession {
|
|
|
101348
101347
|
this.bOneTimeProcessingDone = false;
|
|
101349
101348
|
this.bPlanAnalyzed = false;
|
|
101350
101349
|
this.bPostProcessingDone = false;
|
|
101351
|
-
// testScales = {} as T.TestScales; TODO - DELETE
|
|
101352
101350
|
this.tests = {};
|
|
101353
101351
|
this.title = SessionRequest['title'];
|
|
101354
101352
|
this.legislativeDistricts = SessionRequest['legislativeDistricts'];
|
|
@@ -101359,42 +101357,18 @@ class AnalyticsSession {
|
|
|
101359
101357
|
this.features = new D.Features(this, SessionRequest['data'], this.config['datasets']);
|
|
101360
101358
|
this.plan = new D.Plan(this, SessionRequest['plan']);
|
|
101361
101359
|
this.districts = new D.Districts(this, SessionRequest['districtShapes']);
|
|
101362
|
-
// TODO - DELETE
|
|
101363
|
-
// if (this.useLegacy())
|
|
101364
|
-
// {
|
|
101365
|
-
// console.log("Using legacy district-analytics.")
|
|
101366
|
-
// // NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
101367
|
-
// // we could want them to passed into an analytics session as data, along with
|
|
101368
|
-
// // everything else. For now, this keeps branching out of the main code.
|
|
101369
|
-
// doConfigureScales(this);
|
|
101370
|
-
// }
|
|
101371
|
-
// else
|
|
101372
|
-
// {
|
|
101373
|
-
// console.log("Using dra-score analytics.")
|
|
101374
|
-
// // TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
101375
|
-
// doConfigureScales(this);
|
|
101376
|
-
// }
|
|
101377
101360
|
}
|
|
101378
101361
|
processConfig(config) {
|
|
101379
101362
|
// NOTE - Session settings are required:
|
|
101380
101363
|
// - Analytics suites can be defaulted to all with [], but
|
|
101381
101364
|
// - Dataset keys must be explicitly specified with 'dataset'
|
|
101382
|
-
//
|
|
101365
|
+
// NOTE - Legacy feature: Always calc everything
|
|
101383
101366
|
config['suites'] = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
|
|
101384
101367
|
// Default the Census & redistricting cycle to 2010
|
|
101385
101368
|
if (!(U.keyExists('cycle', config)))
|
|
101386
101369
|
config['cycle'] = 2010;
|
|
101387
101370
|
return config;
|
|
101388
101371
|
}
|
|
101389
|
-
/* TODO - DELETE
|
|
101390
|
-
useLegacy(): boolean
|
|
101391
|
-
{
|
|
101392
|
-
// TODO - SCORE: Opt-out
|
|
101393
|
-
return (U.keyExists('useScore', this.config) && (this.config['useScore'] != null) && (!(this.config['useScore']))) ? true : false;
|
|
101394
|
-
// TODO - SCORE: Opt-in
|
|
101395
|
-
// return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
|
|
101396
|
-
}
|
|
101397
|
-
*/
|
|
101398
101372
|
// Using the the data in the analytics session, calculate all the
|
|
101399
101373
|
// analytics & validations, saving/updating the individual test results.
|
|
101400
101374
|
analyzePlan(bLog = false, overridesJSON) {
|
|
@@ -101402,7 +101376,6 @@ class AnalyticsSession {
|
|
|
101402
101376
|
preprocess_1.doPreprocessData(this, bLog);
|
|
101403
101377
|
analyze_1.doAnalyzeDistricts(this, bLog);
|
|
101404
101378
|
analyze_1.doAnalyzePlan(this, bLog);
|
|
101405
|
-
// TODO - SCORE
|
|
101406
101379
|
this._profile = score_1.profilePlan(this, bLog);
|
|
101407
101380
|
this._scorecard = score_1.scorePlan(this, this._profile, bLog, overridesJSON);
|
|
101408
101381
|
results_1.doAnalyzePostProcessing(this, bLog);
|
|
@@ -101417,15 +101390,12 @@ class AnalyticsSession {
|
|
|
101417
101390
|
getDistrictStatistics(bLog = false) {
|
|
101418
101391
|
return results_2.prepareDistrictStatistics(this, bLog);
|
|
101419
101392
|
}
|
|
101420
|
-
// TODO - SCORE
|
|
101421
101393
|
getPlanProfile(bLog = false) {
|
|
101422
101394
|
return this._profile;
|
|
101423
101395
|
}
|
|
101424
|
-
// TODO - SCORE
|
|
101425
101396
|
getPlanScorecard(bLog = false) {
|
|
101426
101397
|
return this._scorecard;
|
|
101427
101398
|
}
|
|
101428
|
-
// TODO - SCORE
|
|
101429
101399
|
// NOTE - This assumes that analyzePlan() has been run!
|
|
101430
101400
|
getRequirementsChecklist(bLog = false) {
|
|
101431
101401
|
return results_2.prepareRequirementsChecklist(this, bLog);
|
|
@@ -101526,21 +101496,10 @@ class AnalyticsSession {
|
|
|
101526
101496
|
}
|
|
101527
101497
|
// NOTE - Not sure why this has to be up here ...
|
|
101528
101498
|
populationDeviationThreshold() {
|
|
101529
|
-
// TODO - DELETE
|
|
101530
|
-
// if (this.useLegacy())
|
|
101531
|
-
// {
|
|
101532
|
-
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
101533
|
-
// }
|
|
101534
|
-
// else
|
|
101535
|
-
// {
|
|
101536
101499
|
// NOTE - This assumes the plan has been profiled
|
|
101537
101500
|
const scorer = new Score.Scorer();
|
|
101538
101501
|
const popdev = scorer.populationDeviationThreshold(this.legislativeDistricts);
|
|
101539
101502
|
return popdev;
|
|
101540
|
-
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
101541
|
-
// NOTE - The plan may not have been scored yet, i.e., no scorecard yet.
|
|
101542
|
-
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
101543
|
-
// }
|
|
101544
101503
|
}
|
|
101545
101504
|
}
|
|
101546
101505
|
exports.AnalyticsSession = AnalyticsSession;
|
|
@@ -101654,11 +101613,11 @@ class Districts {
|
|
|
101654
101613
|
}
|
|
101655
101614
|
// This is the workhorse computational routine!
|
|
101656
101615
|
//
|
|
101657
|
-
//
|
|
101658
|
-
//
|
|
101616
|
+
// NOTE - OPTIMIZE for getting multiple properties from the same feature?
|
|
101617
|
+
// NOTE - OPTIMIZE by only re-calc'ing districts that have changed?
|
|
101659
101618
|
// In this case, special attention to getting county-splits right.
|
|
101660
|
-
//
|
|
101661
|
-
//
|
|
101619
|
+
// NOTE - OPTIMIZE by async'ing this?
|
|
101620
|
+
// NOTE - Is there a way to do this programmatically off data? Does it matter?
|
|
101662
101621
|
recalcStatistics(bLog = false) {
|
|
101663
101622
|
// Initialize debug counters
|
|
101664
101623
|
nMissingDataset = 0;
|
|
@@ -101669,7 +101628,6 @@ class Districts {
|
|
|
101669
101628
|
let planByDistrict = this._session.plan.byDistrictID();
|
|
101670
101629
|
let plan = this._session.plan;
|
|
101671
101630
|
let graph = this._session.graph;
|
|
101672
|
-
// NOTE - SPLITTING
|
|
101673
101631
|
// Add an extra 0th virtual county bucket for county-district splitting analysis
|
|
101674
101632
|
let nCountyBuckets = this._session.counties.nCounties + 1;
|
|
101675
101633
|
// INITIALIZE STATE VALUES THAT WILL BE ACCUMULATED
|
|
@@ -101695,7 +101653,6 @@ class Districts {
|
|
|
101695
101653
|
// INITIALIZE DISTRICT VALUES THAT WILL BE ACCUMULATED (VS. DERIVED)
|
|
101696
101654
|
let featurePop;
|
|
101697
101655
|
let totalPop = 0;
|
|
101698
|
-
// NOTE - SPLITTING
|
|
101699
101656
|
let countySplits = U.initArray(nCountyBuckets, 0);
|
|
101700
101657
|
let demVotes = 0;
|
|
101701
101658
|
let repVotes = 0;
|
|
@@ -101739,7 +101696,6 @@ class Districts {
|
|
|
101739
101696
|
featurePop = outerThis._session.features.fieldForFeature(f, "CENSUS" /* CENSUS */, "Tot" /* TotalPop */);
|
|
101740
101697
|
// Total district population
|
|
101741
101698
|
totalPop += featurePop;
|
|
101742
|
-
// NOTE - SPLITTING
|
|
101743
101699
|
// Total population by counties w/in a district,
|
|
101744
101700
|
// except the dummy unassigned district 0
|
|
101745
101701
|
if (i > 0)
|
|
@@ -101943,7 +101899,7 @@ class Features {
|
|
|
101943
101899
|
}
|
|
101944
101900
|
resetDataset(d, k) {
|
|
101945
101901
|
this._keys[d] = k;
|
|
101946
|
-
//
|
|
101902
|
+
// NOTE - RECALC: Does anything need to be recalc'd now when a dataset is changed?
|
|
101947
101903
|
}
|
|
101948
101904
|
mapGeoIDsToFeatureIDs() {
|
|
101949
101905
|
for (let i = 0; i < this._session.features.nFeatures(); i++) {
|
|
@@ -102058,7 +102014,6 @@ class Plan {
|
|
|
102058
102014
|
// return newPlan;
|
|
102059
102015
|
// }
|
|
102060
102016
|
invertPlan() {
|
|
102061
|
-
// NOTE - UNASSIGNED
|
|
102062
102017
|
this._planByDistrictID = invertPlan(this._planByGeoID, this._session);
|
|
102063
102018
|
this.districtIDs = U.getNumericObjectKeys(this._planByDistrictID);
|
|
102064
102019
|
}
|
|
@@ -102074,7 +102029,6 @@ function invertPlan(plan, s) {
|
|
|
102074
102029
|
let invertedPlan = {};
|
|
102075
102030
|
// Add a dummy 'unassigned' district
|
|
102076
102031
|
invertedPlan[S.NOT_ASSIGNED] = new Set();
|
|
102077
|
-
// NOTE - UNASSIGNED
|
|
102078
102032
|
// The feature assignments coming from DRA do not include unassigned ones.
|
|
102079
102033
|
// - In the DRA-calling context, there's an analytics session with a reference
|
|
102080
102034
|
// to the features. Loop over all the features to find the unassigned ones,
|
|
@@ -102117,7 +102071,6 @@ class Graph {
|
|
|
102117
102071
|
// Ignore the lengths of the shared borders (the values), for now
|
|
102118
102072
|
// Protect against getting a GEOID that's not in the graph
|
|
102119
102073
|
if (U.keyExists(node, this._graph)) {
|
|
102120
|
-
// NOTE - CONTIGUITY GRAPHS
|
|
102121
102074
|
// Handle both unweighted & weighted neighbors
|
|
102122
102075
|
let n = this._graph[node];
|
|
102123
102076
|
let l = (n instanceof Array) ? n : U.getObjectKeys(n);
|
|
@@ -102149,22 +102102,7 @@ exports.Graph = Graph;
|
|
|
102149
102102
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102150
102103
|
const valid_1 = __webpack_require__(/*! ./valid */ "./src/valid.ts");
|
|
102151
102104
|
const equal_1 = __webpack_require__(/*! ./equal */ "./src/equal.ts");
|
|
102152
|
-
// import { doPopulationDeviation, doHasEqualPopulations } from './equal'; TODO - DELETE
|
|
102153
|
-
// import { doReock, doPolsbyPopper } from './compact'; TODO - DELETE
|
|
102154
102105
|
const cohesive_1 = __webpack_require__(/*! ./cohesive */ "./src/cohesive.ts");
|
|
102155
|
-
/* TODO - DELETE
|
|
102156
|
-
import
|
|
102157
|
-
{
|
|
102158
|
-
doFindCountiesSplitUnexpectedly, doFindSplitVTDs,
|
|
102159
|
-
doCountySplitting, doDistrictSplitting
|
|
102160
|
-
} from './cohesive';
|
|
102161
|
-
import
|
|
102162
|
-
{
|
|
102163
|
-
doSeatsBias, doVotesBias,
|
|
102164
|
-
doResponsiveness, doResponsiveDistricts, doEfficiencyGap
|
|
102165
|
-
} from './political';
|
|
102166
|
-
import { doMajorityMinorityDistricts } from './minority'
|
|
102167
|
-
*/
|
|
102168
102106
|
// Compile district-level info for plan/map-level analytics
|
|
102169
102107
|
function doAnalyzeDistricts(s, bLog = false) {
|
|
102170
102108
|
s.districts.recalcStatistics(bLog);
|
|
@@ -102176,56 +102114,9 @@ exports.doAnalyzeDistricts = doAnalyzeDistricts;
|
|
|
102176
102114
|
// NOTE - I could make this table-driven, but I'm thinking that the explicit
|
|
102177
102115
|
// calls might make chunking for aync easier.
|
|
102178
102116
|
function doAnalyzePlan(s, bLog = false) {
|
|
102179
|
-
// TODO - DELETE
|
|
102180
|
-
// if (s.useLegacy())
|
|
102181
|
-
// {
|
|
102182
|
-
// // Disable most legacy analytics
|
|
102183
|
-
// // Get the requested suites, and only execute those tests
|
|
102184
|
-
// let requestedSuites = s.config['suites'];
|
|
102185
|
-
// // Tests in the "Legal" suite, i.e., pass/ fail constraints
|
|
102186
|
-
// if (requestedSuites.includes(T.Suite.Legal))
|
|
102187
|
-
// {
|
|
102188
|
-
// s.tests[T.Test.Complete] = doIsComplete(s, bLog);
|
|
102189
|
-
// s.tests[T.Test.Contiguous] = doIsContiguous(s, bLog);
|
|
102190
|
-
// s.tests[T.Test.FreeOfHoles] = doIsFreeOfHoles(s, bLog);
|
|
102191
|
-
// // s.tests[T.Test.PopulationDeviation] = doPopulationDeviation(s, bLog); TODO - DELETE
|
|
102192
|
-
// // NOTE - I can't check whether a population deviation is legal or not, until
|
|
102193
|
-
// // the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
102194
|
-
// // the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
102195
|
-
// // from PopulationDeviation, as part of scorecard or test log preparation.
|
|
102196
|
-
// // Create an empty test entry here though ...
|
|
102197
|
-
// s.tests[T.Test.EqualPopulation] = s.getTest(T.Test.EqualPopulation) as T.TestEntry;
|
|
102198
|
-
// }
|
|
102199
|
-
// // Tests in the "Fair" suite
|
|
102200
|
-
// if (requestedSuites.includes(T.Suite.Fair))
|
|
102201
|
-
// {
|
|
102202
|
-
// /* TODO - DELETE
|
|
102203
|
-
// s.tests[T.Test.SeatsBias] = doSeatsBias(s, bLog);
|
|
102204
|
-
// s.tests[T.Test.VotesBias] = doVotesBias(s, bLog);
|
|
102205
|
-
// s.tests[T.Test.Responsiveness] = doResponsiveness(s, bLog);
|
|
102206
|
-
// s.tests[T.Test.ResponsiveDistricts] = doResponsiveDistricts(s, bLog);
|
|
102207
|
-
// s.tests[T.Test.EfficiencyGap] = doEfficiencyGap(s, bLog);
|
|
102208
|
-
// s.tests[T.Test.MajorityMinorityDistricts] = doMajorityMinorityDistricts(s, bLog);
|
|
102209
|
-
// */
|
|
102210
|
-
// }
|
|
102211
|
-
// // Tests in the "Best" suite, i.e., criteria for better/worse
|
|
102212
|
-
// if (requestedSuites.includes(T.Suite.Best))
|
|
102213
|
-
// {
|
|
102214
|
-
// // s.tests[T.Test.Reock] = doReock(s, bLog); TODO - DELETE
|
|
102215
|
-
// // s.tests[T.Test.PolsbyPopper] = doPolsbyPopper(s, bLog); TODO - DELETE
|
|
102216
|
-
// s.tests[T.Test.UnexpectedCountySplits] = doFindCountiesSplitUnexpectedly(s, bLog);
|
|
102217
|
-
// s.tests[T.Test.VTDSplits] = doFindSplitVTDs(s, bLog);
|
|
102218
|
-
// // s.tests[T.Test.CountySplitting] = doCountySplitting(s, bLog); TODO - DELETE
|
|
102219
|
-
// // s.tests[T.Test.DistrictSplitting] = doDistrictSplitting(s, bLog); TODO - DELETE
|
|
102220
|
-
// }
|
|
102221
|
-
// }
|
|
102222
|
-
// else
|
|
102223
|
-
// {
|
|
102224
|
-
// TODO - SCORE: Except these. Continue to do these here vs. dra-score.
|
|
102225
102117
|
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
102226
102118
|
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
102227
102119
|
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
102228
|
-
// s.tests[T.Test.PopulationDeviation] = doPopulationDeviation(s, bLog); TODO - DELETE
|
|
102229
102120
|
// NOTE - I can't check whether a population deviation is legal or not, until
|
|
102230
102121
|
// the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
102231
102122
|
// the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
@@ -102234,7 +102125,6 @@ function doAnalyzePlan(s, bLog = false) {
|
|
|
102234
102125
|
s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
|
|
102235
102126
|
s.tests[5 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
102236
102127
|
s.tests[6 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
|
|
102237
|
-
// }
|
|
102238
102128
|
// Enable a Test Log and Scorecard to be generated
|
|
102239
102129
|
s.bPlanAnalyzed = true;
|
|
102240
102130
|
s.bPostProcessingDone = false;
|
|
@@ -102277,277 +102167,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
102277
102167
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
102278
102168
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
102279
102169
|
// NOTE - The active code is below the long multi-line section to be deleted.
|
|
102280
|
-
/* TODO - DELETE
|
|
102281
|
-
// CALCULATE ENHANCED SQRT ENTROPY METRIC
|
|
102282
|
-
|
|
102283
|
-
export function doCountySplitting(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102284
|
-
{
|
|
102285
|
-
let test = s.getTest(T.Test.CountySplitting) as T.TestEntry;
|
|
102286
|
-
|
|
102287
|
-
let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
|
|
102288
|
-
let countyTotals = s.counties.totalPopulation;
|
|
102289
|
-
let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
|
|
102290
|
-
|
|
102291
|
-
let f = calcCountyFractions(CxD, countyTotals);
|
|
102292
|
-
let w = calcCountyWeights(countyTotals);
|
|
102293
|
-
|
|
102294
|
-
let SqEnt_DC = countySplitting(f, w, bLog);
|
|
102295
|
-
|
|
102296
|
-
let CxDreducedC = U.deepCopy(CxD);
|
|
102297
|
-
reduceCSplits(CxDreducedC, districtTotals);
|
|
102298
|
-
|
|
102299
|
-
let fReduced = calcCountyFractions(CxDreducedC, countyTotals);
|
|
102300
|
-
let wReduced = calcCountyWeights(countyTotals);
|
|
102301
|
-
|
|
102302
|
-
let SqEnt_DCreduced = countySplitting(fReduced, wReduced, bLog);
|
|
102303
|
-
|
|
102304
|
-
test['score'] = SqEnt_DCreduced;
|
|
102305
|
-
test['details']['SqEnt_DC'] = SqEnt_DC;
|
|
102306
|
-
|
|
102307
|
-
return test;
|
|
102308
|
-
}
|
|
102309
|
-
|
|
102310
|
-
export function doDistrictSplitting(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102311
|
-
{
|
|
102312
|
-
let test = s.getTest(T.Test.DistrictSplitting) as T.TestEntry;
|
|
102313
|
-
|
|
102314
|
-
let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
|
|
102315
|
-
let countyTotals = s.counties.totalPopulation;
|
|
102316
|
-
let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
|
|
102317
|
-
|
|
102318
|
-
let g = calcDistrictFractions(CxD, districtTotals);
|
|
102319
|
-
let x = calcDistrictWeights(districtTotals);
|
|
102320
|
-
|
|
102321
|
-
let SqEnt_CD = districtSplitting(g, x, bLog);
|
|
102322
|
-
|
|
102323
|
-
let CxDreducedD = U.deepCopy(CxD);
|
|
102324
|
-
reduceDSplits(CxDreducedD, countyTotals);
|
|
102325
|
-
|
|
102326
|
-
let gReduced = calcDistrictFractions(CxDreducedD, districtTotals);
|
|
102327
|
-
let xReduced = calcDistrictWeights(districtTotals);
|
|
102328
|
-
|
|
102329
|
-
let SqEnt_CDreduced = districtSplitting(gReduced, xReduced, bLog);
|
|
102330
|
-
|
|
102331
|
-
test['score'] = SqEnt_CDreduced;
|
|
102332
|
-
test['details']['SqEnt_CD'] = SqEnt_CD;
|
|
102333
|
-
|
|
102334
|
-
return test;
|
|
102335
|
-
}
|
|
102336
|
-
|
|
102337
|
-
|
|
102338
|
-
// HELPERS
|
|
102339
|
-
|
|
102340
|
-
// Loop over all the county-district combos, skipping the virtual district 0
|
|
102341
|
-
// and virtual county 0.
|
|
102342
|
-
//
|
|
102343
|
-
// NOTE - The county-district splits and the county & district totals may all,
|
|
102344
|
-
// in general, be fractional/decimal numbers as opposed to integers, due to
|
|
102345
|
-
// dissaggregation & re-aggregation. Hence, comparisons need to approximate
|
|
102346
|
-
// equality.
|
|
102347
|
-
|
|
102348
|
-
// Consolidate districts (rows) consisting of just one county (column)
|
|
102349
|
-
// UP into the dummy district (0).
|
|
102350
|
-
function reduceCSplits(CxDreducedC: number[][], districtTotals: number[]): void
|
|
102351
|
-
{
|
|
102352
|
-
let nD = CxDreducedC.length;
|
|
102353
|
-
let nC = CxDreducedC[0].length;
|
|
102354
|
-
|
|
102355
|
-
for (let j = 1; j < nC; j++)
|
|
102356
|
-
{
|
|
102357
|
-
for (let i = 1; i < nD; i++)
|
|
102358
|
-
{
|
|
102359
|
-
let split_total = CxDreducedC[i][j];
|
|
102360
|
-
|
|
102361
|
-
if (split_total > 0)
|
|
102362
|
-
{
|
|
102363
|
-
if (areRoughlyEqual(split_total, districtTotals[i]))
|
|
102364
|
-
{
|
|
102365
|
-
CxDreducedC[0][j] += split_total;
|
|
102366
|
-
CxDreducedC[i][j] = 0;
|
|
102367
|
-
}
|
|
102368
|
-
}
|
|
102369
|
-
}
|
|
102370
|
-
}
|
|
102371
|
-
}
|
|
102372
|
-
|
|
102373
|
-
// Consolidate whole counties (columns) in a district (row) LEFT into the
|
|
102374
|
-
// dummy county (0).
|
|
102375
|
-
function reduceDSplits(CxDreducedD: number[][], countyTotals: number[]): void
|
|
102376
|
-
{
|
|
102377
|
-
let nD = CxDreducedD.length;
|
|
102378
|
-
let nC = CxDreducedD[0].length;
|
|
102379
|
-
|
|
102380
|
-
for (let i = 1; i < nD; i++)
|
|
102381
|
-
{
|
|
102382
|
-
for (let j = 1; j < nC; j++)
|
|
102383
|
-
{
|
|
102384
|
-
let split_total = CxDreducedD[i][j];
|
|
102385
|
-
|
|
102386
|
-
if (split_total > 0)
|
|
102387
|
-
{
|
|
102388
|
-
if (areRoughlyEqual(split_total, countyTotals[j]))
|
|
102389
|
-
{
|
|
102390
|
-
CxDreducedD[i][0] += split_total;
|
|
102391
|
-
CxDreducedD[i][j] = 0;
|
|
102392
|
-
}
|
|
102393
|
-
}
|
|
102394
|
-
}
|
|
102395
|
-
}
|
|
102396
|
-
}
|
|
102397
|
-
|
|
102398
|
-
function calcCountyWeights(countyTotals: number[]): number[]
|
|
102399
|
-
{
|
|
102400
|
-
let nC: number = countyTotals.length;
|
|
102401
|
-
let cTotal: number = U.sumArray(countyTotals);
|
|
102402
|
-
|
|
102403
|
-
let w: number[] = U.initArray(nC, 0.0);
|
|
102404
|
-
|
|
102405
|
-
for (let j = 0; j < nC; j++)
|
|
102406
|
-
{
|
|
102407
|
-
w[j] = countyTotals[j] / cTotal;
|
|
102408
|
-
}
|
|
102409
|
-
|
|
102410
|
-
return w;
|
|
102411
|
-
}
|
|
102412
|
-
|
|
102413
|
-
function calcDistrictWeights(districtTotals: number[]): number[]
|
|
102414
|
-
{
|
|
102415
|
-
let nD = districtTotals.length;
|
|
102416
|
-
let dTotal: number = U.sumArray(districtTotals);
|
|
102417
|
-
|
|
102418
|
-
let x: number[] = U.initArray(nD, 0.0);
|
|
102419
|
-
|
|
102420
|
-
for (let i = 0; i < nD; i++)
|
|
102421
|
-
{
|
|
102422
|
-
x[i] = districtTotals[i] / dTotal;
|
|
102423
|
-
}
|
|
102424
|
-
|
|
102425
|
-
return x;
|
|
102426
|
-
}
|
|
102427
|
-
|
|
102428
|
-
function calcCountyFractions(CxDreducedD: number[][], countyTotals: number[]): number[][]
|
|
102429
|
-
{
|
|
102430
|
-
let nD = CxDreducedD.length;
|
|
102431
|
-
let nC = CxDreducedD[0].length;
|
|
102432
|
-
|
|
102433
|
-
let f: number[][] = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
|
|
102434
|
-
|
|
102435
|
-
for (let j = 0; j < nC; j++)
|
|
102436
|
-
{
|
|
102437
|
-
for (let i = 0; i < nD; i++)
|
|
102438
|
-
{
|
|
102439
|
-
if (countyTotals[j] > 0)
|
|
102440
|
-
{
|
|
102441
|
-
f[i][j] = CxDreducedD[i][j] / countyTotals[j];
|
|
102442
|
-
}
|
|
102443
|
-
else
|
|
102444
|
-
{
|
|
102445
|
-
f[i][j] = 0.0;
|
|
102446
|
-
}
|
|
102447
|
-
}
|
|
102448
|
-
}
|
|
102449
|
-
|
|
102450
|
-
return f;
|
|
102451
|
-
}
|
|
102452
|
-
|
|
102453
|
-
function calcDistrictFractions(CxDreducedC: number[][], districtTotals: number[]): number[][]
|
|
102454
|
-
{
|
|
102455
|
-
let nD = CxDreducedC.length;
|
|
102456
|
-
let nC = CxDreducedC[0].length;
|
|
102457
|
-
|
|
102458
|
-
let g: number[][] = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
|
|
102459
|
-
|
|
102460
|
-
for (let j = 0; j < nC; j++)
|
|
102461
|
-
{
|
|
102462
|
-
for (let i = 0; i < nD; i++)
|
|
102463
|
-
{
|
|
102464
|
-
if (districtTotals[i] > 0)
|
|
102465
|
-
{
|
|
102466
|
-
g[i][j] = CxDreducedC[i][j] / districtTotals[i];
|
|
102467
|
-
}
|
|
102468
|
-
else
|
|
102469
|
-
{
|
|
102470
|
-
g[i][j] = 0.0;
|
|
102471
|
-
}
|
|
102472
|
-
}
|
|
102473
|
-
}
|
|
102474
|
-
|
|
102475
|
-
return g;
|
|
102476
|
-
}
|
|
102477
|
-
|
|
102478
|
-
// Deal with decimal census "counts" due to disagg/re-agg
|
|
102479
|
-
function areRoughlyEqual(x: number, y: number): boolean
|
|
102480
|
-
{
|
|
102481
|
-
let delta = Math.abs(x - y);
|
|
102482
|
-
let result = (delta < S.EQUAL_TOLERANCE) ? true : false;
|
|
102483
|
-
|
|
102484
|
-
return result;
|
|
102485
|
-
}
|
|
102486
|
-
|
|
102487
|
-
// For all districts in a county, sum the split score.
|
|
102488
|
-
function countySplitScore(j: number, f: number[][], numD: number, bLog: boolean = false): number
|
|
102489
|
-
{
|
|
102490
|
-
let e = 0.0;
|
|
102491
|
-
|
|
102492
|
-
for (let i = 0; i < numD; i++)
|
|
102493
|
-
{
|
|
102494
|
-
e += Math.sqrt(f[i][j]);
|
|
102495
|
-
}
|
|
102496
|
-
|
|
102497
|
-
return e;
|
|
102498
|
-
}
|
|
102499
|
-
|
|
102500
|
-
// For all counties, sum the weighted county splits.
|
|
102501
|
-
function countySplitting(f: number[][], w: number[], bLog: boolean = false): number
|
|
102502
|
-
{
|
|
102503
|
-
let numC = f[0].length;
|
|
102504
|
-
let numD = f.length;
|
|
102505
|
-
|
|
102506
|
-
let e = 0.0;
|
|
102507
|
-
|
|
102508
|
-
for (let j = 0; j < numC; j++)
|
|
102509
|
-
{
|
|
102510
|
-
let splitScore = countySplitScore(j, f, numD, bLog);
|
|
102511
|
-
e += w[j] * splitScore;
|
|
102512
|
-
|
|
102513
|
-
if (bLog) console.log("County splitting =", j, w[j], splitScore, e);
|
|
102514
|
-
}
|
|
102515
|
-
|
|
102516
|
-
return U.trim(e, 3);
|
|
102517
|
-
}
|
|
102518
|
-
|
|
102519
|
-
// For all counties in a district, sum the split score.
|
|
102520
|
-
function districtSplitScore(i: number, g: number[][], numC: number, bLog: boolean = false): number
|
|
102521
|
-
{
|
|
102522
|
-
let e = 0.0;
|
|
102523
|
-
|
|
102524
|
-
for (let j = 0; j < numC; j++)
|
|
102525
|
-
{
|
|
102526
|
-
e += Math.sqrt(g[i][j]);
|
|
102527
|
-
}
|
|
102528
|
-
|
|
102529
|
-
return e;
|
|
102530
|
-
}
|
|
102531
|
-
|
|
102532
|
-
// For all districts, sum the weighted district splits.
|
|
102533
|
-
function districtSplitting(g: number[][], x: number[], bLog: boolean = false): number
|
|
102534
|
-
{
|
|
102535
|
-
let numC = g[0].length;
|
|
102536
|
-
let numD = g.length;
|
|
102537
|
-
|
|
102538
|
-
let e = 0.0;
|
|
102539
|
-
|
|
102540
|
-
for (let i = 0; i < numD; i++)
|
|
102541
|
-
{
|
|
102542
|
-
let splitScore = districtSplitScore(i, g, numC, bLog);
|
|
102543
|
-
e += x[i] * splitScore;
|
|
102544
|
-
|
|
102545
|
-
if (bLog) console.log("District split score =", i, x[i], splitScore, e);
|
|
102546
|
-
}
|
|
102547
|
-
|
|
102548
|
-
return U.trim(e, 3);
|
|
102549
|
-
}
|
|
102550
|
-
*/
|
|
102551
102170
|
// ANALYZE SIMPLE COUNTY & VTD SPLITTING
|
|
102552
102171
|
/*
|
|
102553
102172
|
|
|
@@ -102711,164 +102330,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
102711
102330
|
// NOTE - This file will NOT be empty, when legacy code is deleted.
|
|
102712
102331
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "./node_modules/@dra2020/poly/dist/poly.js"));
|
|
102713
102332
|
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
102714
|
-
// TODO - DELETE
|
|
102715
|
-
// Measures of compactness compare district shapes to various ideally compact
|
|
102716
|
-
// benchmarks, such as circles. All else equal, more compact districts are better.
|
|
102717
|
-
//
|
|
102718
|
-
// There are four popular measures of compactness. They either focus on how
|
|
102719
|
-
// dispersed or how indented a shapes are.
|
|
102720
|
-
//
|
|
102721
|
-
// These first two measures are the most important:
|
|
102722
|
-
//
|
|
102723
|
-
// Reock is the primary measure of the dispersion of district shapes, calculated
|
|
102724
|
-
// as “the area of the district to the area of the minimum spanning circle that
|
|
102725
|
-
// can enclose the district.”
|
|
102726
|
-
//
|
|
102727
|
-
// R = A / A(Minimum Bounding Circle)
|
|
102728
|
-
// R = A / (π * (D / 2)^2)
|
|
102729
|
-
//
|
|
102730
|
-
// R = 4A / πD^2
|
|
102731
|
-
//
|
|
102732
|
-
// where A is the area of the district and D is the diameter of the minimum
|
|
102733
|
-
// bounding circle.
|
|
102734
|
-
//
|
|
102735
|
-
// Polsby-Popper is the primary measure of the indendentation of district shapes,
|
|
102736
|
-
// calculated as the “the ratio of the area of the district to the area of a circle
|
|
102737
|
-
// whose circumference is equal to the perimeter of the district.”
|
|
102738
|
-
//
|
|
102739
|
-
// PP = A / A(C)
|
|
102740
|
-
//
|
|
102741
|
-
// where C is that circle. In other words:
|
|
102742
|
-
//
|
|
102743
|
-
// P = 2πRc and A(C) = π(P / 2π)^2
|
|
102744
|
-
//
|
|
102745
|
-
// where P is the perimeter of the district and Rc is the radius of the circle.
|
|
102746
|
-
//
|
|
102747
|
-
// Hence, the measure simplifies to:
|
|
102748
|
-
//
|
|
102749
|
-
// PP = 4π * (A / P^2)
|
|
102750
|
-
//
|
|
102751
|
-
// I propose that we use these two, normalize them, and weight equally to determine
|
|
102752
|
-
// our compactness value.
|
|
102753
|
-
//
|
|
102754
|
-
// These second two measures may be used to complement the primary ones above:
|
|
102755
|
-
//
|
|
102756
|
-
// Convex Hull is a secondary measure of the dispersion of district shapes, calculated
|
|
102757
|
-
// as “the ratio of the district area to the area of the minimum convex bounding
|
|
102758
|
-
// polygon (also known as a convex hull) enclosing the district.”
|
|
102759
|
-
//
|
|
102760
|
-
// CH = A / A(Convex Hull)
|
|
102761
|
-
//
|
|
102762
|
-
// where a convex hull is the minimum perimeter that encloses all points in a shape,
|
|
102763
|
-
// basically the shortest unstretched rubber band that fits around the shape.
|
|
102764
|
-
//
|
|
102765
|
-
// Schwartzberg is a secondary measure of the degree of indentation of district
|
|
102766
|
-
// shapes, calculated as “the ratio of the perimeter of the district to the circumference
|
|
102767
|
-
// of a circle whose area is equal to the area of the district.”
|
|
102768
|
-
//
|
|
102769
|
-
// S = 1 / (P / C)
|
|
102770
|
-
//
|
|
102771
|
-
// where P is the perimeter of the district and C is the circumference of the circle.
|
|
102772
|
-
// The radius of the circle is:
|
|
102773
|
-
//
|
|
102774
|
-
// Rc = SQRT(A / π)
|
|
102775
|
-
//
|
|
102776
|
-
// So, the circumference of the circle is:
|
|
102777
|
-
//
|
|
102778
|
-
// C = 2πRc or C = 2π * SQRT(A / π)
|
|
102779
|
-
//
|
|
102780
|
-
// Hence:
|
|
102781
|
-
//
|
|
102782
|
-
// S = 1 (P / 2π * SQRT(A / π))
|
|
102783
|
-
//
|
|
102784
|
-
// S = (2π * SQRT(A / π)) / P
|
|
102785
|
-
//
|
|
102786
|
-
// All these measures produce values between 0 and 1, with 0 being the least compact
|
|
102787
|
-
// and 1 being the most compact. Sometimes these values are multiplied by 100 to
|
|
102788
|
-
// give values between 0 and 100.
|
|
102789
|
-
//
|
|
102790
|
-
// For each measure, the compactness of a set of Congressional districts is the
|
|
102791
|
-
// average of that measure for all the districts.
|
|
102792
|
-
//
|
|
102793
|
-
/* TODO - DELETE
|
|
102794
|
-
// Calculate Reock compactness:
|
|
102795
|
-
// reock = (4 * a) / (math.pi * d**2)
|
|
102796
|
-
// NOTE - Depends on extractDistrictProperties running first
|
|
102797
|
-
export function doReock(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102798
|
-
{
|
|
102799
|
-
let test = s.getTest(T.Test.Reock) as T.TestEntry;
|
|
102800
|
-
|
|
102801
|
-
// Calculate Reock scores by district
|
|
102802
|
-
let scores: number[] = [];
|
|
102803
|
-
|
|
102804
|
-
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++)
|
|
102805
|
-
{
|
|
102806
|
-
let districtProps = s.districts.getGeoProperties(districtID);
|
|
102807
|
-
// Guard against no shape and no properties
|
|
102808
|
-
if (districtProps)
|
|
102809
|
-
{
|
|
102810
|
-
let a = districtProps[T.DistrictShapeProperty.Area];
|
|
102811
|
-
let d = districtProps[T.DistrictShapeProperty.Diameter];
|
|
102812
|
-
|
|
102813
|
-
let reock = (4 * a) / (Math.PI * d ** 2);
|
|
102814
|
-
|
|
102815
|
-
// Save each district score
|
|
102816
|
-
scores.push(reock);
|
|
102817
|
-
|
|
102818
|
-
// Echo the results by district
|
|
102819
|
-
if (bLog) console.log("Reock for district", districtID, "=", reock);
|
|
102820
|
-
}
|
|
102821
|
-
}
|
|
102822
|
-
|
|
102823
|
-
// Populate the test entry ... for the shapes that exist!
|
|
102824
|
-
let averageReock = U.avgArray(scores);
|
|
102825
|
-
|
|
102826
|
-
test['score'] = U.trim(averageReock);
|
|
102827
|
-
test['details'] = {}; // TODO - Any details?
|
|
102828
|
-
|
|
102829
|
-
return test;
|
|
102830
|
-
}
|
|
102831
|
-
|
|
102832
|
-
// Calculate Polsby-Popper compactness measures:
|
|
102833
|
-
// polsby_popper = (4 * math.pi) * (a / p**2)
|
|
102834
|
-
// NOTE - Depends on extractDistrictProperties running first
|
|
102835
|
-
export function doPolsbyPopper(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102836
|
-
{
|
|
102837
|
-
let test = s.getTest(T.Test.PolsbyPopper) as T.TestEntry;
|
|
102838
|
-
|
|
102839
|
-
// Calculate Polsby-Popper scores by district
|
|
102840
|
-
let scores: number[] = [];
|
|
102841
|
-
|
|
102842
|
-
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++)
|
|
102843
|
-
{
|
|
102844
|
-
let districtProps = s.districts.getGeoProperties(districtID);
|
|
102845
|
-
// Guard against no shape and no properties
|
|
102846
|
-
if (districtProps)
|
|
102847
|
-
{
|
|
102848
|
-
let a = districtProps[T.DistrictShapeProperty.Area];
|
|
102849
|
-
let p = districtProps[T.DistrictShapeProperty.Perimeter];
|
|
102850
|
-
|
|
102851
|
-
let polsbyPopper = (4 * Math.PI) * (a / p ** 2);
|
|
102852
|
-
|
|
102853
|
-
// Save each district score
|
|
102854
|
-
scores.push(polsbyPopper);
|
|
102855
|
-
|
|
102856
|
-
// Echo the results by district
|
|
102857
|
-
if (bLog) console.log("Polsby-Popper for district", districtID, "=", polsbyPopper);
|
|
102858
|
-
}
|
|
102859
|
-
}
|
|
102860
|
-
|
|
102861
|
-
// Populate the test entry ... for the shapes that exist!
|
|
102862
|
-
let averagePolsbyPopper = U.avgArray(scores);
|
|
102863
|
-
|
|
102864
|
-
test['score'] = U.trim(averagePolsbyPopper);
|
|
102865
|
-
test['details'] = {}; // TODO - Any details?
|
|
102866
|
-
|
|
102867
|
-
return test;
|
|
102868
|
-
}
|
|
102869
|
-
*/
|
|
102870
102333
|
// HELPER TO EXTRACT PROPERTIES OF DISTRICT SHAPES
|
|
102871
|
-
// TODO -
|
|
102334
|
+
// TODO - Create an array, as opposed to a dict
|
|
102872
102335
|
function extractDistrictProperties(s, bLog = false) {
|
|
102873
102336
|
// NOTE - I am assuming that district IDs are integers 1–N
|
|
102874
102337
|
for (let i = 1; i <= s.state.nDistricts; i++) {
|
|
@@ -102945,52 +102408,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
102945
102408
|
};
|
|
102946
102409
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102947
102410
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
102948
|
-
/* TODO - DELETE
|
|
102949
|
-
export function doPopulationDeviation(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102950
|
-
{
|
|
102951
|
-
let test = s.getTest(T.Test.PopulationDeviation) as T.TestEntry;
|
|
102952
|
-
|
|
102953
|
-
let targetSize = s.state.totalPop / s.state.nDistricts;
|
|
102954
|
-
|
|
102955
|
-
// Compute the min & max district populations
|
|
102956
|
-
// ... excluding the dummy the 'unassigned' 0 and N+1 summary "districts"
|
|
102957
|
-
let totPopByDistrict = s.districts.statistics[D.DistrictField.TotalPop];
|
|
102958
|
-
totPopByDistrict = totPopByDistrict.slice(1, -1);
|
|
102959
|
-
|
|
102960
|
-
// Remove empty districts
|
|
102961
|
-
totPopByDistrict = totPopByDistrict.filter(x => x > 0);
|
|
102962
|
-
|
|
102963
|
-
let min = 0;
|
|
102964
|
-
let max = 0;
|
|
102965
|
-
|
|
102966
|
-
// If there's more than 1 non-empty district, calculate a non-zero deviation
|
|
102967
|
-
if (totPopByDistrict.length > 1)
|
|
102968
|
-
{
|
|
102969
|
-
min = U.minArray(totPopByDistrict);
|
|
102970
|
-
max = U.maxArray(totPopByDistrict);
|
|
102971
|
-
}
|
|
102972
|
-
|
|
102973
|
-
// Calculate the raw population deviation
|
|
102974
|
-
let popDev = (max - min) / targetSize;
|
|
102975
|
-
|
|
102976
|
-
// Round the raw value to the desired level of precision
|
|
102977
|
-
popDev = U.trim(popDev);
|
|
102978
|
-
|
|
102979
|
-
// Populate the test entry
|
|
102980
|
-
test['score'] = popDev;
|
|
102981
|
-
test['details'] = { 'maxDeviation': max - min };
|
|
102982
|
-
|
|
102983
|
-
// Populate the N+1 summary "district" in district.statistics
|
|
102984
|
-
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
102985
|
-
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
102986
|
-
let summaryRow = s.districts.numberOfRows() - 1;
|
|
102987
|
-
|
|
102988
|
-
totalPop[summaryRow] = targetSize;
|
|
102989
|
-
popDevPct[summaryRow] = popDev;
|
|
102990
|
-
|
|
102991
|
-
return test;
|
|
102992
|
-
}
|
|
102993
|
-
*/
|
|
102994
102411
|
// NOTE - This validity check is *derived* and depends on population deviation %
|
|
102995
102412
|
// being computed (above) and normalized in test log & scorecard generation.
|
|
102996
102413
|
function doHasEqualPopulations(s, bLog = false) {
|
|
@@ -103117,7 +102534,7 @@ function gfPerimeter(poly) {
|
|
|
103117
102534
|
exports.gfPerimeter = gfPerimeter;
|
|
103118
102535
|
// TODO - POLY: Confirm Cartesian calculations w/ Terry
|
|
103119
102536
|
// Cloned from polyPerimeter() in 'poly' and revised to use Cartesian distance
|
|
103120
|
-
// NOTE
|
|
102537
|
+
// NOTE - No conversion of degrees to radians!
|
|
103121
102538
|
function _polygonPerimeter(poly) {
|
|
103122
102539
|
let polyOptions = { noLatitudeCorrection: true }; // Cartesian distance
|
|
103123
102540
|
poly = Poly.polyNormalize(poly, polyOptions);
|
|
@@ -103156,127 +102573,64 @@ exports.gfDiameter = gfDiameter;
|
|
|
103156
102573
|
|
|
103157
102574
|
/***/ }),
|
|
103158
102575
|
|
|
103159
|
-
/***/ "./src/
|
|
103160
|
-
|
|
103161
|
-
!*** ./src/
|
|
103162
|
-
|
|
102576
|
+
/***/ "./src/minority.ts":
|
|
102577
|
+
/*!*************************!*\
|
|
102578
|
+
!*** ./src/minority.ts ***!
|
|
102579
|
+
\*************************/
|
|
103163
102580
|
/*! no static exports found */
|
|
103164
102581
|
/***/ (function(module, exports, __webpack_require__) {
|
|
103165
102582
|
|
|
103166
102583
|
"use strict";
|
|
103167
102584
|
|
|
103168
102585
|
//
|
|
103169
|
-
//
|
|
102586
|
+
// PROTECTS MINORITIES
|
|
103170
102587
|
//
|
|
102588
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
102589
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
102590
|
+
};
|
|
103171
102591
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
103172
|
-
|
|
103173
|
-
const
|
|
103174
|
-
|
|
103175
|
-
import
|
|
103176
|
-
|
|
103177
|
-
|
|
103178
|
-
|
|
103179
|
-
//
|
|
103180
|
-
//
|
|
103181
|
-
|
|
103182
|
-
|
|
103183
|
-
|
|
103184
|
-
|
|
103185
|
-
|
|
103186
|
-
//
|
|
103187
|
-
// An election model can simply represent one election, e.g., President 2012,
|
|
103188
|
-
// or combine multiple elections in some fashion. An election model is used to
|
|
103189
|
-
// computer a single index of the likely partisan weight / lean / preference
|
|
103190
|
-
// for the districts in a plan. An election model and the associated index go
|
|
103191
|
-
// hand in hand. So much so that the index frequently stands in as the name for
|
|
103192
|
-
// both, e.g., Cook's PVI is one example, Nagle's 7s, Hofeller's Formula, NDRC's
|
|
103193
|
-
// DPI.
|
|
103194
|
-
//
|
|
103195
|
-
// I'm labelling this general concept a "Voter Preference Index (VPI)," a
|
|
103196
|
-
// conscious +1 letter play on Cook's "PVI" acronymn.
|
|
103197
|
-
|
|
103198
|
-
|
|
103199
|
-
// MEASURING BIAS & RESPONSIVENESS (NAGLE'S METHOD)
|
|
103200
|
-
|
|
103201
|
-
export function doSeatsBias(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103202
|
-
{
|
|
103203
|
-
let test = s.getTest(T.Test.SeatsBias) as T.TestEntry;
|
|
103204
|
-
|
|
103205
|
-
if (bLog) console.log("TODO - Calculating seats bias ...");
|
|
103206
|
-
|
|
103207
|
-
return test;
|
|
103208
|
-
}
|
|
103209
|
-
|
|
103210
|
-
export function doVotesBias(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103211
|
-
{
|
|
103212
|
-
let test = s.getTest(T.Test.VotesBias) as T.TestEntry;
|
|
103213
|
-
|
|
103214
|
-
if (bLog) console.log("TODO - Calculating votes bias ...");
|
|
103215
|
-
|
|
103216
|
-
return test;
|
|
102592
|
+
const majority_minority_json_1 = __importDefault(__webpack_require__(/*! ../static/majority-minority.json */ "./static/majority-minority.json"));
|
|
102593
|
+
const vra5_preclearance_json_1 = __importDefault(__webpack_require__(/*! ../static/vra5-preclearance.json */ "./static/vra5-preclearance.json"));
|
|
102594
|
+
// import stateContacts from '../static/state-contacts.json';
|
|
102595
|
+
// import demographicDefs from '../static/demographic-defns.json';
|
|
102596
|
+
// TODO - 2020: Update/revise this, when the update comes out in September:
|
|
102597
|
+
// Sources for majority-minority info:
|
|
102598
|
+
// - https://en.wikipedia.org/wiki/List_of_majority-minority_United_States_congressional_districts
|
|
102599
|
+
// - http://www.ncsl.org/Portals/1/Documents/Redistricting/Redistricting_2010.pdf (PP. 80–84)
|
|
102600
|
+
// - https://www.justice.gov/crt/jurisdictions-previously-covered-section-5
|
|
102601
|
+
function getMajorityMinority(s) {
|
|
102602
|
+
const xx = s.state.xx;
|
|
102603
|
+
const mMDict = majority_minority_json_1.default;
|
|
102604
|
+
const stateMM = mMDict[xx];
|
|
102605
|
+
return stateMM;
|
|
103217
102606
|
}
|
|
103218
|
-
|
|
103219
|
-
|
|
103220
|
-
|
|
103221
|
-
|
|
103222
|
-
|
|
103223
|
-
|
|
103224
|
-
|
|
103225
|
-
return test;
|
|
103226
|
-
}
|
|
103227
|
-
|
|
103228
|
-
export function doResponsiveDistricts(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103229
|
-
{
|
|
103230
|
-
let test = s.getTest(T.Test.ResponsiveDistricts) as T.TestEntry;
|
|
103231
|
-
|
|
103232
|
-
if (bLog) console.log("TODO - Calculating # of responsive districts ...");
|
|
103233
|
-
|
|
103234
|
-
return test;
|
|
102607
|
+
exports.getMajorityMinority = getMajorityMinority;
|
|
102608
|
+
function getVRASection5(s) {
|
|
102609
|
+
const xx = s.state.xx;
|
|
102610
|
+
const vraPreDict = vra5_preclearance_json_1.default;
|
|
102611
|
+
const stateVRAPre = vraPreDict[xx];
|
|
102612
|
+
return stateVRAPre;
|
|
103235
102613
|
}
|
|
102614
|
+
exports.getVRASection5 = getVRASection5;
|
|
103236
102615
|
|
|
103237
102616
|
|
|
103238
|
-
|
|
103239
|
-
|
|
103240
|
-
// TODO - PARTISAN: This formula might need to be inverted for D vs. R +/-
|
|
103241
|
-
// TODO - Normalize the results.
|
|
103242
|
-
export function doEfficiencyGap(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103243
|
-
{
|
|
103244
|
-
if (bLog) console.log("TODO - Calculating the efficiency gap ...");
|
|
103245
|
-
|
|
103246
|
-
let test = s.getTest(T.Test.EfficiencyGap) as T.TestEntry;
|
|
103247
|
-
|
|
103248
|
-
// Get partisan statistics by districts.
|
|
103249
|
-
// Use Democratic votes, seats, and shares by convention.
|
|
103250
|
-
let DVotes = s.districts.statistics[D.DistrictField.DemVotes];
|
|
103251
|
-
let DSeats = s.districts.statistics[D.DistrictField.DemSeat];
|
|
103252
|
-
let TPVotes = s.districts.statistics[D.DistrictField.TwoPartyVote];
|
|
103253
|
-
|
|
103254
|
-
// Exclude the dummy unassigned '0' and N+1 summary "districts"
|
|
103255
|
-
DVotes = DVotes.slice(1, -1);
|
|
103256
|
-
DSeats = DSeats.slice(1, -1);
|
|
103257
|
-
TPVotes = TPVotes.slice(1, -1);
|
|
103258
|
-
|
|
103259
|
-
// Calculate D vote share & D seat share
|
|
103260
|
-
let DVoteShare = U.sumArray(DVotes) / U.sumArray(TPVotes);
|
|
103261
|
-
let DSeatShare = U.sumArray(DSeats) / s.state.nDistricts;
|
|
103262
|
-
|
|
103263
|
-
// Finally, calculate the Efficiency Gap
|
|
103264
|
-
let efficiencyGap = (DSeatShare - 0.5) - (2.0 * (DVoteShare - 0.5));
|
|
103265
|
-
|
|
103266
|
-
// Round the raw value to the desired level of precision
|
|
103267
|
-
efficiencyGap = U.trim(efficiencyGap);
|
|
103268
|
-
|
|
103269
|
-
// Populate the test entry
|
|
103270
|
-
test['score'] = efficiencyGap;
|
|
103271
|
-
// test['normalizedScore'] = 0; // TODO - Normalize the raw score
|
|
103272
|
-
test['details'] = {}; // TODO - Add details, if any
|
|
102617
|
+
/***/ }),
|
|
103273
102618
|
|
|
103274
|
-
|
|
103275
|
-
|
|
102619
|
+
/***/ "./src/political.ts":
|
|
102620
|
+
/*!**************************!*\
|
|
102621
|
+
!*** ./src/political.ts ***!
|
|
102622
|
+
\**************************/
|
|
102623
|
+
/*! no static exports found */
|
|
102624
|
+
/***/ (function(module, exports, __webpack_require__) {
|
|
103276
102625
|
|
|
102626
|
+
"use strict";
|
|
103277
102627
|
|
|
103278
|
-
//
|
|
103279
|
-
|
|
102628
|
+
//
|
|
102629
|
+
// FAIR/PROPORTIONAL
|
|
102630
|
+
//
|
|
102631
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102632
|
+
// NOTE - This file will NOT be empty, when legacy code is deleted.
|
|
102633
|
+
const assert_1 = __webpack_require__(/*! assert */ "assert");
|
|
103280
102634
|
function fptpWin(demPct) {
|
|
103281
102635
|
// Vote shares should be fractions in the range [0.0 – 1.0]
|
|
103282
102636
|
assert_1.strict((demPct <= 1.0) && (demPct >= 0.));
|
|
@@ -103314,10 +102668,9 @@ function doPreprocessData(s, bLog = false) {
|
|
|
103314
102668
|
if (!s.bOneTimeProcessingDone) {
|
|
103315
102669
|
doPreprocessCountyFeatures(s, bLog);
|
|
103316
102670
|
doPreprocessCensus(s, bLog);
|
|
103317
|
-
doPreprocessElection(s, bLog);
|
|
102671
|
+
// doPreprocessElection(s, bLog);
|
|
103318
102672
|
s.bOneTimeProcessingDone = true;
|
|
103319
102673
|
}
|
|
103320
|
-
// NOTE - UNASSIGNED: Made both the planByGeoID & DistrictID are right
|
|
103321
102674
|
// Invert the plan by district ID
|
|
103322
102675
|
s.plan.invertPlan();
|
|
103323
102676
|
// Create a map of geoIDs to feature IDs
|
|
@@ -103399,7 +102752,6 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
103399
102752
|
// Loop over the counties
|
|
103400
102753
|
for (let county in fipsCodes) {
|
|
103401
102754
|
let fipsCode = fipsCodes[county];
|
|
103402
|
-
// NOTE - SPLITTING
|
|
103403
102755
|
// Skip the dummy county
|
|
103404
102756
|
if (fipsCode == '000')
|
|
103405
102757
|
continue;
|
|
@@ -103423,10 +102775,10 @@ function doPreprocessCensus(s, bLog = false) {
|
|
|
103423
102775
|
s.state.expectedAffected = expectedAffected;
|
|
103424
102776
|
}
|
|
103425
102777
|
// PREPROCESS ELECTION RESULTS
|
|
103426
|
-
function doPreprocessElection(s, bLog = false)
|
|
103427
|
-
|
|
103428
|
-
|
|
103429
|
-
}
|
|
102778
|
+
// function doPreprocessElection(s: AnalyticsSession, bLog: boolean = false): void
|
|
102779
|
+
// {
|
|
102780
|
+
// if (bLog) console.log("Preprocessing election data ...");
|
|
102781
|
+
// }
|
|
103430
102782
|
|
|
103431
102783
|
|
|
103432
102784
|
/***/ }),
|
|
@@ -103459,234 +102811,6 @@ const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"
|
|
|
103459
102811
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
103460
102812
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
103461
102813
|
const state_reqs_json_1 = __importDefault(__webpack_require__(/*! ../static/state-reqs.json */ "./static/state-reqs.json"));
|
|
103462
|
-
// PLAN ANALYTICS
|
|
103463
|
-
/* TODO - DELETE
|
|
103464
|
-
export type RequirementsCategory = {
|
|
103465
|
-
score: T.TriState;
|
|
103466
|
-
metrics: {
|
|
103467
|
-
complete: T.TriState;
|
|
103468
|
-
contiguous: T.TriState;
|
|
103469
|
-
freeOfHoles: T.TriState;
|
|
103470
|
-
equalPopulation: T.TriState;
|
|
103471
|
-
};
|
|
103472
|
-
details: {
|
|
103473
|
-
unassignedFeatures: string[]; // A possibly empty list of GEOIDs
|
|
103474
|
-
emptyDistricts: number[]; // A possibly empty list of district IDs
|
|
103475
|
-
discontiguousDistricts: number[]; // Ditto
|
|
103476
|
-
embeddedDistricts: number[]; // Ditto
|
|
103477
|
-
populationDeviation: number; // A fraction [0.0 – 1.0] to represent as a %
|
|
103478
|
-
deviationThreshold: number; // A fraction [0.0 – 1.0] to represent as a %
|
|
103479
|
-
};
|
|
103480
|
-
datasets: T.Datasets;
|
|
103481
|
-
resources: {
|
|
103482
|
-
stateReqs: string;
|
|
103483
|
-
};
|
|
103484
|
-
};
|
|
103485
|
-
*/
|
|
103486
|
-
/* TODO - DELETE
|
|
103487
|
-
export type CompactnessCategory = {
|
|
103488
|
-
score: number; // An integer score [0–100]
|
|
103489
|
-
metrics: {
|
|
103490
|
-
reock: number; // A decimal number [0.0–1.0]
|
|
103491
|
-
polsby: number; // A decimal number [0.0–1.0]
|
|
103492
|
-
};
|
|
103493
|
-
details: {
|
|
103494
|
-
// None at this time
|
|
103495
|
-
};
|
|
103496
|
-
datasets: T.Datasets;
|
|
103497
|
-
resources: {
|
|
103498
|
-
// None at this time
|
|
103499
|
-
};
|
|
103500
|
-
};
|
|
103501
|
-
*/
|
|
103502
|
-
/* TODO - DELETE
|
|
103503
|
-
export type SplittingCategory = {
|
|
103504
|
-
score: number; // An integer score [0–100]
|
|
103505
|
-
metrics: {
|
|
103506
|
-
sqEnt_DCreduced: number, // A decimal number [1.0 – < 2.0]
|
|
103507
|
-
sqEnt_CDreduced: number // A decimal number [1.0 – < 2.0]
|
|
103508
|
-
};
|
|
103509
|
-
details: {
|
|
103510
|
-
countiesSplitUnexpectedly: string[], // A possibly empty list of county names
|
|
103511
|
-
unexpectedAffected: number, // A fraction [0.0 – 1.0] to represent as a %
|
|
103512
|
-
nSplitVTDs: number, // An integer, possibly 0
|
|
103513
|
-
splitVTDs: string[] // A possibly empty list of GEOIDs
|
|
103514
|
-
};
|
|
103515
|
-
datasets: T.Datasets;
|
|
103516
|
-
resources: {
|
|
103517
|
-
// None at this time
|
|
103518
|
-
};
|
|
103519
|
-
};
|
|
103520
|
-
*/
|
|
103521
|
-
/* TODO - DELETE
|
|
103522
|
-
export type PartisanCategory = {
|
|
103523
|
-
score: number; // An integer score [0–100]
|
|
103524
|
-
metrics: {
|
|
103525
|
-
partisanBias: 0.15, // TBD
|
|
103526
|
-
responsiveness: 2.0 // TBD
|
|
103527
|
-
};
|
|
103528
|
-
details: {
|
|
103529
|
-
// TODO - Need to flesh this out
|
|
103530
|
-
};
|
|
103531
|
-
datasets: T.Datasets;
|
|
103532
|
-
resources: {
|
|
103533
|
-
planScore?: string;
|
|
103534
|
-
};
|
|
103535
|
-
};
|
|
103536
|
-
*/
|
|
103537
|
-
/* TODO - DELETE
|
|
103538
|
-
export type MinorityCategory = {
|
|
103539
|
-
score: null; // Explicitly NOT scored
|
|
103540
|
-
metrics: {
|
|
103541
|
-
nBlack37to50: number, // Integer >= 0; two-digit maximum
|
|
103542
|
-
nBlackMajority: number, // Ditto
|
|
103543
|
-
nHispanic37to50: number, // Ditto
|
|
103544
|
-
nHispanicMajority: number, // Ditto
|
|
103545
|
-
nPacific37to50: number, // Ditto
|
|
103546
|
-
nPacificMajority: number, // Ditto
|
|
103547
|
-
nAsian37to50: number, // Ditto
|
|
103548
|
-
nAsianMajority: number, // Ditto
|
|
103549
|
-
nNative37to50: number, // Ditto
|
|
103550
|
-
nNativeMajority: number, // Ditto
|
|
103551
|
-
nMinority37to50: number, // Ditto
|
|
103552
|
-
nMinorityMajority: number, // Ditto
|
|
103553
|
-
|
|
103554
|
-
averageDVoteShare: number // A fraction [0.0 – 1.0] to represent as a %
|
|
103555
|
-
};
|
|
103556
|
-
details: {
|
|
103557
|
-
vap: true, // true = using VAP data; false = CVAP data
|
|
103558
|
-
comboCategories: true // true = using combo fields; false = mutually exclusive
|
|
103559
|
-
};
|
|
103560
|
-
datasets: T.Datasets;
|
|
103561
|
-
resources: {
|
|
103562
|
-
// TODO - Add these ...
|
|
103563
|
-
};
|
|
103564
|
-
};
|
|
103565
|
-
*/
|
|
103566
|
-
/* TODO - DELETE
|
|
103567
|
-
export type PlanAnalytics = {
|
|
103568
|
-
requirements: RequirementsCategory;
|
|
103569
|
-
compactness: CompactnessCategory;
|
|
103570
|
-
// TODO - Don't show these categories yet
|
|
103571
|
-
splitting: SplittingCategory;
|
|
103572
|
-
partisan: PartisanCategory;
|
|
103573
|
-
minority: MinorityCategory;
|
|
103574
|
-
}
|
|
103575
|
-
*/
|
|
103576
|
-
// EXAMPLE
|
|
103577
|
-
/* TODO - DELETE
|
|
103578
|
-
let sampleRequirements: RequirementsCategory = {
|
|
103579
|
-
score: T.TriState.Red,
|
|
103580
|
-
metrics: {
|
|
103581
|
-
complete: T.TriState.Green,
|
|
103582
|
-
contiguous: T.TriState.Red,
|
|
103583
|
-
freeOfHoles: T.TriState.Yellow,
|
|
103584
|
-
equalPopulation: T.TriState.Red
|
|
103585
|
-
},
|
|
103586
|
-
details: {
|
|
103587
|
-
unassignedFeatures: [],
|
|
103588
|
-
emptyDistricts: [],
|
|
103589
|
-
discontiguousDistricts: [2],
|
|
103590
|
-
embeddedDistricts: [],
|
|
103591
|
-
populationDeviation: 0.6748,
|
|
103592
|
-
deviationThreshold: 0.75 / 100
|
|
103593
|
-
},
|
|
103594
|
-
datasets: {
|
|
103595
|
-
census: "2010 Census Total Population"
|
|
103596
|
-
},
|
|
103597
|
-
resources: {
|
|
103598
|
-
stateReqs: "https://www.brennancenter.org/sites/default/files/publications/2019_06_50States_FINALsinglepages_20.pdf"
|
|
103599
|
-
}
|
|
103600
|
-
}
|
|
103601
|
-
*/
|
|
103602
|
-
/* TODO - DELETE
|
|
103603
|
-
let sampleCompactness: CompactnessCategory = {
|
|
103604
|
-
score: 60,
|
|
103605
|
-
metrics: {
|
|
103606
|
-
reock: 0.3773,
|
|
103607
|
-
polsby: 0.3815
|
|
103608
|
-
},
|
|
103609
|
-
details: {},
|
|
103610
|
-
datasets: {
|
|
103611
|
-
shapes: "2010 VTD shapes"
|
|
103612
|
-
},
|
|
103613
|
-
resources: {}
|
|
103614
|
-
}
|
|
103615
|
-
*/
|
|
103616
|
-
/* TODO - DELETE
|
|
103617
|
-
let sampleSplitting: SplittingCategory = {
|
|
103618
|
-
score: 73,
|
|
103619
|
-
metrics: {
|
|
103620
|
-
sqEnt_DCreduced: 1.531,
|
|
103621
|
-
sqEnt_CDreduced: 1.760
|
|
103622
|
-
},
|
|
103623
|
-
details: {
|
|
103624
|
-
countiesSplitUnexpectedly: [
|
|
103625
|
-
"Bladen", "Buncombe", "Catawba", "Cumberland", "Durham", "Guilford", "Iredell", "Johnston", "Pitt", "Rowan", "Wilson"
|
|
103626
|
-
],
|
|
103627
|
-
unexpectedAffected: 0.3096,
|
|
103628
|
-
nSplitVTDs: 12,
|
|
103629
|
-
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"]
|
|
103630
|
-
},
|
|
103631
|
-
datasets: {},
|
|
103632
|
-
resources: {}
|
|
103633
|
-
}
|
|
103634
|
-
*/
|
|
103635
|
-
/* TODO - DELETE
|
|
103636
|
-
let samplePartisan: PartisanCategory = {
|
|
103637
|
-
score: 100,
|
|
103638
|
-
metrics: {
|
|
103639
|
-
partisanBias: 0.15,
|
|
103640
|
-
responsiveness: 2.0
|
|
103641
|
-
},
|
|
103642
|
-
details: {},
|
|
103643
|
-
datasets: {
|
|
103644
|
-
election: "2016 Presidential, US Senate, Governor, and AG election results"
|
|
103645
|
-
},
|
|
103646
|
-
resources: {
|
|
103647
|
-
planScore: "https://planscore.org/plan.html?20180219T202039.596761160Z"
|
|
103648
|
-
}
|
|
103649
|
-
}
|
|
103650
|
-
*/
|
|
103651
|
-
/* TODO - DELETE
|
|
103652
|
-
let sampleMinority: MinorityCategory = {
|
|
103653
|
-
score: null,
|
|
103654
|
-
metrics: {
|
|
103655
|
-
nBlack37to50: 1,
|
|
103656
|
-
nBlackMajority: 12,
|
|
103657
|
-
nHispanic37to50: 0,
|
|
103658
|
-
nHispanicMajority: 0,
|
|
103659
|
-
nPacific37to50: 0,
|
|
103660
|
-
nPacificMajority: 0,
|
|
103661
|
-
nAsian37to50: 0,
|
|
103662
|
-
nAsianMajority: 0,
|
|
103663
|
-
nNative37to50: 0,
|
|
103664
|
-
nNativeMajority: 0,
|
|
103665
|
-
nMinority37to50: 0,
|
|
103666
|
-
nMinorityMajority: 0,
|
|
103667
|
-
|
|
103668
|
-
averageDVoteShare: 0.90
|
|
103669
|
-
},
|
|
103670
|
-
details: {
|
|
103671
|
-
vap: true,
|
|
103672
|
-
comboCategories: true
|
|
103673
|
-
},
|
|
103674
|
-
datasets: {
|
|
103675
|
-
vap: "2010 Voting Age Population"
|
|
103676
|
-
},
|
|
103677
|
-
resources: {}
|
|
103678
|
-
}
|
|
103679
|
-
*/
|
|
103680
|
-
/* TODO - DELETE
|
|
103681
|
-
export const samplePlanAnalytics: PlanAnalytics = {
|
|
103682
|
-
requirements: sampleRequirements,
|
|
103683
|
-
compactness: sampleCompactness,
|
|
103684
|
-
// TODO - Don't show these categories yet
|
|
103685
|
-
splitting: sampleSplitting,
|
|
103686
|
-
partisan: samplePartisan,
|
|
103687
|
-
minority: sampleMinority
|
|
103688
|
-
}
|
|
103689
|
-
*/
|
|
103690
102814
|
function prepareRequirementsChecklist(s, bLog = false) {
|
|
103691
102815
|
if (!(s.bPostProcessingDone)) {
|
|
103692
102816
|
doAnalyzePostProcessing(s);
|
|
@@ -103716,14 +102840,8 @@ function prepareRequirementsChecklist(s, bLog = false) {
|
|
|
103716
102840
|
const emptyDistrictsDetail = U.deepCopy(completeTest['details']['emptyDistricts']) || [];
|
|
103717
102841
|
const discontiguousDistrictsDetail = U.deepCopy(contiguousTest['details']['discontiguousDistricts']) || [];
|
|
103718
102842
|
const embeddedDistrictsDetail = U.deepCopy(freeOfHolesTest['details']['embeddedDistricts']) || [];
|
|
103719
|
-
// TODO - SCORE: DELETE - This code is hooked correctly to use dra-score
|
|
103720
|
-
// const scorecard = s._scorecard as Score.Scorecard;
|
|
103721
|
-
// const populationDeviation = scorecard.best.populationDeviation.raw;
|
|
103722
102843
|
const populationDeviationDetail = U.deepCopy(equalPopulationTest['details']['deviation']);
|
|
103723
|
-
// console.log("Population deviations =", populationDeviationDetail, populationDeviation);
|
|
103724
|
-
// const deviationThreshold = scorecard.best.populationDeviation.notes['threshold'];
|
|
103725
102844
|
const deviationThresholdDetail = U.trim(s.populationDeviationThreshold());
|
|
103726
|
-
// console.log("Population deviation thresholds =", deviationThresholdDetail, deviationThreshold);
|
|
103727
102845
|
const xx = s.state.xx;
|
|
103728
102846
|
// TODO - JSON: Is there a better / easier way to work with the variable?
|
|
103729
102847
|
const stateReqsDict = state_reqs_json_1.default;
|
|
@@ -103806,8 +102924,8 @@ function prepareDistrictStatistics(s, bLog = false) {
|
|
|
103806
102924
|
s.districts.statistics[D.DistrictField.AsianPct][i],
|
|
103807
102925
|
s.districts.statistics[D.DistrictField.NativePct][i]
|
|
103808
102926
|
];
|
|
103809
|
-
//
|
|
103810
|
-
//
|
|
102927
|
+
// NOTE - Until we add three-state support top to bottom in Requirements,
|
|
102928
|
+
// map booleans to tri-states here.
|
|
103811
102929
|
rawRow[3 /* bEqualPop */] = U.mapBooleanToTriState(rawRow[3 /* bEqualPop */]);
|
|
103812
102930
|
rawRow[4 /* bNotEmpty */] = U.mapBooleanToTriState(rawRow[4 /* bNotEmpty */]);
|
|
103813
102931
|
rawRow[5 /* bContiguous */] = U.mapBooleanToTriState(rawRow[5 /* bContiguous */]);
|
|
@@ -103882,24 +103000,6 @@ const populationDeviationDefn = {
|
|
|
103882
103000
|
externalType: TestType.Percentage,
|
|
103883
103001
|
suites: [0 /* Legal */, 2 /* Best */] // Both so EqualPopulation can be assessed
|
|
103884
103002
|
};
|
|
103885
|
-
/* TODO - DELETE
|
|
103886
|
-
const reockDefn: T.Dict = {
|
|
103887
|
-
ID: T.Test.Reock,
|
|
103888
|
-
name: "Reock",
|
|
103889
|
-
normalize: true,
|
|
103890
|
-
externalType: TestType.Number,
|
|
103891
|
-
suites: [T.Suite.Best]
|
|
103892
|
-
};
|
|
103893
|
-
|
|
103894
|
-
const polsbyPopperDefn: T.Dict = {
|
|
103895
|
-
ID: T.Test.PolsbyPopper,
|
|
103896
|
-
name: "Polsby-Popper",
|
|
103897
|
-
normalize: true,
|
|
103898
|
-
externalType: TestType.Number,
|
|
103899
|
-
suites: [T.Suite.Best]
|
|
103900
|
-
};
|
|
103901
|
-
*/
|
|
103902
|
-
// NOTE - SPLITTING
|
|
103903
103003
|
const unexpectedCountySplitsDefn = {
|
|
103904
103004
|
ID: 5 /* UnexpectedCountySplits */,
|
|
103905
103005
|
name: "Unexpected County Splits",
|
|
@@ -103907,7 +103007,6 @@ const unexpectedCountySplitsDefn = {
|
|
|
103907
103007
|
externalType: TestType.Percentage,
|
|
103908
103008
|
suites: [2 /* Best */]
|
|
103909
103009
|
};
|
|
103910
|
-
// NOTE - SPLITTING
|
|
103911
103010
|
const VTDSplitsDefn = {
|
|
103912
103011
|
ID: 6 /* VTDSplits */,
|
|
103913
103012
|
name: "VTD Splits",
|
|
@@ -103922,87 +103021,16 @@ const testDefns = {
|
|
|
103922
103021
|
[2 /* FreeOfHoles */]: freeOfHolesDefn,
|
|
103923
103022
|
[3 /* EqualPopulation */]: equalPopulationDefn,
|
|
103924
103023
|
[4 /* PopulationDeviation */]: populationDeviationDefn,
|
|
103925
|
-
// [T.Test.Reock]: reockDefn, TODO - DELETE
|
|
103926
|
-
// [T.Test.PolsbyPopper]: polsbyPopperDefn, TODO - DELETE
|
|
103927
103024
|
[5 /* UnexpectedCountySplits */]: unexpectedCountySplitsDefn,
|
|
103928
103025
|
[6 /* VTDSplits */]: VTDSplitsDefn,
|
|
103929
103026
|
};
|
|
103930
|
-
/* TODO - DELETE
|
|
103931
|
-
// NORMALIZE RAW ANALYTICS
|
|
103932
|
-
// Raw numeric analytics, such as population deviation, compactness, etc. are
|
|
103933
|
-
// normalized as part of creating a scorecard, so the code to normalize results
|
|
103934
|
-
// is encapsulated here.
|
|
103935
|
-
|
|
103936
|
-
// Configure scale parameters for normalizing each raw test result.
|
|
103937
|
-
// Scales consist of a minimum & a maximum *raw* value. If the values get
|
|
103938
|
-
// inverted (to make bigger better), these will switch.
|
|
103939
|
-
// This process needs to be separate from the test configuration info above,
|
|
103940
|
-
// because some scales need access to the analytics session object.
|
|
103941
|
-
export function doConfigureScales(s: AnalyticsSession): void
|
|
103942
|
-
{
|
|
103943
|
-
// Scale defn for PopulationDeviation
|
|
103944
|
-
const CDLimit = 0.75 / 100; // Deviation threshold for CD's
|
|
103945
|
-
const LDLimit = 10.00 / 100; // Deviation threshold for LD's
|
|
103946
|
-
|
|
103947
|
-
const CDGoodEnough = 0.20 / 100;
|
|
103948
|
-
const LDGoodEnough = (CDGoodEnough / CDLimit) * LDLimit;
|
|
103949
|
-
const popDevScale = (s.legislativeDistricts) ? [1.0 - LDLimit, 1.0 - LDGoodEnough] : [1.0 - CDLimit, 1.0 - CDGoodEnough];
|
|
103950
|
-
// const scale = [1.0 - CDLimit, 1.0 - CDGoodEnough];
|
|
103951
|
-
|
|
103952
|
-
s.testScales[T.Test.PopulationDeviation] = { scale: popDevScale, bInvertRaw: true };
|
|
103953
|
-
|
|
103954
|
-
s.testScales[T.Test.Reock] = { scale: [0.25, 0.50] };
|
|
103955
|
-
s.testScales[T.Test.PolsbyPopper] = { scale: [0.10, 0.50] };
|
|
103956
|
-
|
|
103957
|
-
const nDistricts = s.state.nDistricts;
|
|
103958
|
-
const nCounties = s.counties.nCounties;
|
|
103959
|
-
|
|
103960
|
-
// NOTE - SPLITTING: Experiment w/ this multiplier. Only allowing the expected
|
|
103961
|
-
// number of county splits seems too stringent, empirically.
|
|
103962
|
-
const allowableCountySplitsMultiplier = 1.5;
|
|
103963
|
-
const nAllowableSplits = Math.min(allowableCountySplitsMultiplier * (nDistricts - 1));
|
|
103964
|
-
const countySplittingThreshold = ((nAllowableSplits * 1.71) + ((nCounties - nAllowableSplits) * 1.0)) / nCounties;
|
|
103965
|
-
const countySplittingScale = [1.0, countySplittingThreshold];
|
|
103966
|
-
s.testScales[T.Test.CountySplitting] = { scale: countySplittingScale, bInvertScaled: true };
|
|
103967
|
-
|
|
103968
|
-
const districtSplittingThreshold = 1.5;
|
|
103969
|
-
const districtSplittingScale = [1.0, districtSplittingThreshold];
|
|
103970
|
-
s.testScales[T.Test.DistrictSplitting] = { scale: districtSplittingScale, bInvertScaled: true };
|
|
103971
|
-
|
|
103972
|
-
// TODO - More analytics ...
|
|
103973
|
-
}
|
|
103974
|
-
*/
|
|
103975
103027
|
// Postprocess analytics - Normalize numeric results and derive secondary tests.
|
|
103976
103028
|
// Do this after analytics have been run and before preparing a test log or scorecard.
|
|
103977
103029
|
function doAnalyzePostProcessing(s, bLog = false) {
|
|
103978
|
-
// TODO - DELETE
|
|
103979
|
-
// if (s.useLegacy())
|
|
103980
|
-
// {
|
|
103981
|
-
// // Normalize the raw scores for all the numerics tests
|
|
103982
|
-
// let testResults = U.getNumericObjectKeys(testDefns);
|
|
103983
|
-
// for (let testID of testResults)
|
|
103984
|
-
// {
|
|
103985
|
-
// if (testDefns[testID]['normalize'])
|
|
103986
|
-
// {
|
|
103987
|
-
// let testResult = s.getTest(testID) as T.TestEntry;
|
|
103988
|
-
// let rawScore = testResult['score'] as number;
|
|
103989
|
-
// let normalizedScore: number;
|
|
103990
|
-
// normalizedScore = U.normalize(rawScore, s.testScales[testID]);
|
|
103991
|
-
// testResult['normalizedScore'] = normalizedScore;
|
|
103992
|
-
// // Add the scale used to normalize the raw score to the details
|
|
103993
|
-
// testResult['details']['scale'] = s.testScales[testID].scale;
|
|
103994
|
-
// }
|
|
103995
|
-
// }
|
|
103996
|
-
// }
|
|
103997
|
-
// else
|
|
103998
|
-
// {
|
|
103999
103030
|
// Just populate the normalized population deviation score in the test
|
|
104000
103031
|
const scorecard = s._scorecard;
|
|
104001
103032
|
let popDev = s.getTest(4 /* PopulationDeviation */);
|
|
104002
103033
|
popDev['normalizedScore'] = scorecard.traditionalPrinciples.populationDeviation.normalized;
|
|
104003
|
-
// TODO - DELETE
|
|
104004
|
-
// test['normalizedScore'] = scorecard.best.populationDeviation.normalized;
|
|
104005
|
-
// TODO - SCORE: Add datasets used to details by tab
|
|
104006
103034
|
const datasets = {
|
|
104007
103035
|
shapes: S.SHAPES,
|
|
104008
103036
|
census: U.deepCopy(s.config['descriptions']['CENSUS']),
|
|
@@ -104013,12 +103041,10 @@ function doAnalyzePostProcessing(s, bLog = false) {
|
|
|
104013
103041
|
scorecard.minority.details['vap'] = datasets.vap;
|
|
104014
103042
|
scorecard.traditionalPrinciples.details['shapes'] = datasets.shapes;
|
|
104015
103043
|
scorecard.traditionalPrinciples.details['census'] = datasets.census;
|
|
104016
|
-
// TODO - SCORE: Add legacy splits details
|
|
104017
103044
|
const simpleSplits = s.getTest(5 /* UnexpectedCountySplits */);
|
|
104018
103045
|
scorecard.traditionalPrinciples.details['unexpectedAffected'] = simpleSplits['score'];
|
|
104019
103046
|
scorecard.traditionalPrinciples.details['countiesSplitUnexpectedly'] = U.deepCopy(simpleSplits['details']['countiesSplitUnexpectedly']);
|
|
104020
103047
|
// NOTE - Add split precincts in dra-client directly
|
|
104021
|
-
// }
|
|
104022
103048
|
// Derive secondary tests
|
|
104023
103049
|
analyze_1.doDeriveSecondaryTests(s, bLog);
|
|
104024
103050
|
// Toggle the semaphore, so postprocessing isn't for both the testlog & scorecard
|
|
@@ -104052,6 +103078,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
104052
103078
|
const Score = __importStar(__webpack_require__(/*! @dra2020/dra-score */ "./node_modules/@dra2020/dra-score/dist/dra-score.bundle.js"));
|
|
104053
103079
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
104054
103080
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
103081
|
+
const M = __importStar(__webpack_require__(/*! ./minority */ "./src/minority.ts"));
|
|
104055
103082
|
// PROFILE A PLAN
|
|
104056
103083
|
function profilePlan(s, bLog = false) {
|
|
104057
103084
|
const state = s.state.xx;
|
|
@@ -104157,26 +103184,23 @@ function getStatewideDemographics(s, bLog = false) {
|
|
|
104157
103184
|
function scorePlan(s, p, bLog = false, overridesJSON) {
|
|
104158
103185
|
let scorer = new Score.Scorer();
|
|
104159
103186
|
const scorecard = scorer.score(p, overridesJSON);
|
|
104160
|
-
//
|
|
104161
|
-
//
|
|
104162
|
-
// calling sequence.
|
|
103187
|
+
// Before returning, create a dummy population deviation test, for
|
|
103188
|
+
// doHasEqualPopulations() to use later.This is preserving the old calling sequence.
|
|
104163
103189
|
let test = s.getTest(4 /* PopulationDeviation */);
|
|
104164
|
-
// TODO - SCORE: U.trim(popDev)???
|
|
104165
|
-
// const popDev = scorecard.best.populationDeviation.raw;
|
|
104166
103190
|
// Get the raw population deviation
|
|
104167
103191
|
const popDev = scorecard.traditionalPrinciples.populationDeviation.raw;
|
|
104168
103192
|
// Populate the test entry
|
|
104169
103193
|
test['score'] = popDev;
|
|
104170
103194
|
test['details'] = { 'maxDeviation': scorecard.traditionalPrinciples.populationDeviation.notes['maxDeviation'] };
|
|
104171
|
-
// TODO - DELETE
|
|
104172
|
-
// test['details'] = { 'maxDeviation': scorecard.best.populationDeviation.notes['maxDeviation'] };
|
|
104173
103195
|
// Populate the N+1 summary "district" in district.statistics
|
|
104174
103196
|
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
104175
103197
|
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
104176
103198
|
let summaryRow = s.districts.numberOfRows() - 1;
|
|
104177
103199
|
totalPop[summaryRow] = p.populationProfile.targetSize;
|
|
104178
103200
|
popDevPct[summaryRow] = popDev;
|
|
104179
|
-
//
|
|
103201
|
+
// Add minority notes
|
|
103202
|
+
scorecard.minority.details['majorityMinority'] = M.getMajorityMinority(s);
|
|
103203
|
+
scorecard.minority.details['vraPreclearance'] = M.getVRASection5(s);
|
|
104180
103204
|
return scorecard;
|
|
104181
103205
|
}
|
|
104182
103206
|
exports.scorePlan = scorePlan;
|
|
@@ -104254,7 +103278,6 @@ function isOutOfState(geoID) {
|
|
|
104254
103278
|
return geoID == S.OUT_OF_STATE;
|
|
104255
103279
|
}
|
|
104256
103280
|
exports.isOutOfState = isOutOfState;
|
|
104257
|
-
// NOTE - UNASSIGNED
|
|
104258
103281
|
// Get the districtID to which a geoID is assigned
|
|
104259
103282
|
function getDistrict(plan, geoID) {
|
|
104260
103283
|
// All geoIDs in a state *should be* assigned to a district (including the
|
|
@@ -104309,7 +103332,6 @@ function normalize(rawScore, testScale) {
|
|
|
104309
103332
|
let coercedValue = Math.min(Math.max(rawScore, rangeMin), rangeMax);
|
|
104310
103333
|
// Scale the bounded value w/in the range [0 - (rangeMax - rangeMin)]
|
|
104311
103334
|
let scaledValue = (coercedValue - rangeMin) / (rangeMax - rangeMin);
|
|
104312
|
-
// NOTE - SPLITTING
|
|
104313
103335
|
// Invert the scaled value if necessary to make bigger = better
|
|
104314
103336
|
if (testScale.bInvertScaled) {
|
|
104315
103337
|
scaledValue = 1.0 - scaledValue;
|
|
@@ -104508,7 +103530,7 @@ function doIsComplete(s, bLog = false) {
|
|
|
104508
103530
|
if (!bAllAssigned) {
|
|
104509
103531
|
let unassignedDistrict = s.plan.geoIDsForDistrictID(S.NOT_ASSIGNED);
|
|
104510
103532
|
unassignedFeatures = Array.from(unassignedDistrict);
|
|
104511
|
-
unassignedFeatures = unassignedFeatures.slice(0, S.NUMBER_OF_ITEMS_TO_REPORT);
|
|
103533
|
+
// unassignedFeatures = unassignedFeatures.slice(0, S.NUMBER_OF_ITEMS_TO_REPORT);
|
|
104512
103534
|
}
|
|
104513
103535
|
// Do all real districts have at least one feature assigned to them?
|
|
104514
103536
|
let emptyDistricts = [];
|
|
@@ -104712,6 +103734,17 @@ function isEmbedded(districtID, geoIDs, plan, graph) {
|
|
|
104712
103734
|
exports.isEmbedded = isEmbedded;
|
|
104713
103735
|
|
|
104714
103736
|
|
|
103737
|
+
/***/ }),
|
|
103738
|
+
|
|
103739
|
+
/***/ "./static/majority-minority.json":
|
|
103740
|
+
/*!***************************************!*\
|
|
103741
|
+
!*** ./static/majority-minority.json ***!
|
|
103742
|
+
\***************************************/
|
|
103743
|
+
/*! 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 */
|
|
103744
|
+
/***/ (function(module) {
|
|
103745
|
+
|
|
103746
|
+
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\":[]}}");
|
|
103747
|
+
|
|
104715
103748
|
/***/ }),
|
|
104716
103749
|
|
|
104717
103750
|
/***/ "./static/state-reqs.json":
|
|
@@ -104725,6 +103758,17 @@ module.exports = JSON.parse("{\"AL\":\"https://www.brennancenter.org/sites/defau
|
|
|
104725
103758
|
|
|
104726
103759
|
/***/ }),
|
|
104727
103760
|
|
|
103761
|
+
/***/ "./static/vra5-preclearance.json":
|
|
103762
|
+
/*!***************************************!*\
|
|
103763
|
+
!*** ./static/vra5-preclearance.json ***!
|
|
103764
|
+
\***************************************/
|
|
103765
|
+
/*! exports provided: AL, AK, AZ, CA, FL, GA, LA, MI, MS, NY, NC, SC, SD, TX, VA, default */
|
|
103766
|
+
/***/ (function(module) {
|
|
103767
|
+
|
|
103768
|
+
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\"}");
|
|
103769
|
+
|
|
103770
|
+
/***/ }),
|
|
103771
|
+
|
|
104728
103772
|
/***/ "./test/_cli.ts":
|
|
104729
103773
|
/*!**********************!*\
|
|
104730
103774
|
!*** ./test/_cli.ts ***!
|
|
@@ -104828,19 +103872,7 @@ let argv = yargs_1.default
|
|
|
104828
103872
|
.example('$0 equal -f foo.geojson', 'Calculate population deviation')
|
|
104829
103873
|
.demandCommand(1, 'You must specify a command to execute.')
|
|
104830
103874
|
.command('valid', 'Perform validations.')
|
|
104831
|
-
/* TODO - DELETE
|
|
104832
|
-
.command('equal', 'Calculate population deviation.')
|
|
104833
|
-
.command('compact', 'Calculate compactness.')
|
|
104834
|
-
.command('cohesive', 'Calculate cohesiveness.')
|
|
104835
|
-
.command('political', 'Assess fairness.')
|
|
104836
|
-
.command('minority', 'Count majority-minority districts.')
|
|
104837
|
-
*/
|
|
104838
103875
|
.command('analyze', 'API call to analyze a plan.')
|
|
104839
|
-
/* TODO - DELETE
|
|
104840
|
-
.command('scorecard', 'Analyze plan & generate a scorecard.')
|
|
104841
|
-
.command('testlog', 'Analyze plan & generate a testlog.')
|
|
104842
|
-
.command('report', 'API call to generate a scorecard.')
|
|
104843
|
-
*/
|
|
104844
103876
|
.option('state', {
|
|
104845
103877
|
alias: 'x',
|
|
104846
103878
|
describe: 'Specify the state.',
|
|
@@ -105057,94 +104089,15 @@ switch (command) {
|
|
|
105057
104089
|
let t1 = valid_1.doIsComplete(s);
|
|
105058
104090
|
let t2 = valid_1.doIsContiguous(s);
|
|
105059
104091
|
let t3 = valid_1.doIsFreeOfHoles(s);
|
|
105060
|
-
// let t4 = doPopulationDeviation(s); TODO - DELETE
|
|
105061
104092
|
let t5 = equal_1.doHasEqualPopulations(s);
|
|
105062
104093
|
results_1.doAnalyzePostProcessing(s);
|
|
105063
104094
|
echoTestResult("Complete:", t1);
|
|
105064
104095
|
echoTestResult("Contiguous:", t2);
|
|
105065
104096
|
echoTestResult("Free of holes:", t3);
|
|
105066
|
-
// echoTestResult("Population deviation (%):", t4); TODO - DELETE
|
|
105067
104097
|
echoTestResult("Equal populations:", t5);
|
|
105068
104098
|
break;
|
|
105069
104099
|
}
|
|
105070
|
-
|
|
105071
|
-
case 'equal': {
|
|
105072
|
-
doPreprocessData(s);
|
|
105073
|
-
doAnalyzeDistricts(s);
|
|
105074
|
-
|
|
105075
|
-
t = doPopulationDeviation(s);
|
|
105076
|
-
echoTestResult("Population deviation (%):", t);
|
|
105077
|
-
|
|
105078
|
-
doAnalyzePostProcessing(s);
|
|
105079
|
-
break;
|
|
105080
|
-
}
|
|
105081
|
-
case 'compact': {
|
|
105082
|
-
doPreprocessData(s);
|
|
105083
|
-
doAnalyzeDistricts(s);
|
|
105084
|
-
|
|
105085
|
-
let t1 = doReock(s, bLog);
|
|
105086
|
-
let t2 = doPolsbyPopper(s, bLog);
|
|
105087
|
-
|
|
105088
|
-
doAnalyzePostProcessing(s);
|
|
105089
|
-
|
|
105090
|
-
echoTestResult("Reock:", t1);
|
|
105091
|
-
echoTestResult("Polsby-Popper:", t2);
|
|
105092
|
-
|
|
105093
|
-
break;
|
|
105094
|
-
}
|
|
105095
|
-
case 'cohesive': {
|
|
105096
|
-
doPreprocessData(s);
|
|
105097
|
-
doAnalyzeDistricts(s);
|
|
105098
|
-
|
|
105099
|
-
// NOTE - SPLITTING
|
|
105100
|
-
let t1 = doFindCountiesSplitUnexpectedly(s);
|
|
105101
|
-
let t2 = doFindSplitVTDs(s);
|
|
105102
|
-
let t3 = doCountySplitting(s);
|
|
105103
|
-
let t4 = doDistrictSplitting(s);
|
|
105104
|
-
|
|
105105
|
-
doAnalyzePostProcessing(s);
|
|
105106
|
-
|
|
105107
|
-
echoTestResult("Counties split unexpectedly:", t1);
|
|
105108
|
-
echoTestResult("Split VTDs:", t2);
|
|
105109
|
-
echoTestResult("County splitting:", t3);
|
|
105110
|
-
echoTestResult("District splitting:", t4);
|
|
105111
|
-
|
|
105112
|
-
break;
|
|
105113
|
-
}
|
|
105114
|
-
case 'political': {
|
|
105115
|
-
doPreprocessData(s);
|
|
105116
|
-
doAnalyzeDistricts(s);
|
|
105117
|
-
|
|
105118
|
-
let t1 = doSeatsBias(s);
|
|
105119
|
-
let t2 = doVotesBias(s);
|
|
105120
|
-
let t3 = doResponsiveness(s);
|
|
105121
|
-
let t4 = doResponsiveDistricts(s);
|
|
105122
|
-
let t5 = doEfficiencyGap(s);
|
|
105123
|
-
|
|
105124
|
-
doAnalyzePostProcessing(s);
|
|
105125
|
-
|
|
105126
|
-
// echoTestResult("Seats Bias:", t1); TODO
|
|
105127
|
-
// echoTestResult("Votes Bias:", t2); TODO
|
|
105128
|
-
// echoTestResult("Responsiveness:", t3); TODO
|
|
105129
|
-
// echoTestResult("Responsive Districts:", t4); TODO
|
|
105130
|
-
echoTestResult("Efficiency gap (%):", t5);
|
|
105131
|
-
|
|
105132
|
-
break;
|
|
105133
|
-
}
|
|
105134
|
-
case 'minority': {
|
|
105135
|
-
doPreprocessData(s);
|
|
105136
|
-
doAnalyzeDistricts(s);
|
|
105137
|
-
|
|
105138
|
-
let t1 = doMajorityMinorityDistricts(s);
|
|
105139
|
-
|
|
105140
|
-
doAnalyzePostProcessing(s);
|
|
105141
|
-
|
|
105142
|
-
// echoTestResult("Majority-Minority Districts:", t1); TODO
|
|
105143
|
-
|
|
105144
|
-
break;
|
|
105145
|
-
}
|
|
105146
|
-
*/
|
|
105147
|
-
// TODO - SCORE: Update this w/ scoring info
|
|
104100
|
+
// TODO - Update this w/ scoring info
|
|
105148
104101
|
case 'analyze': {
|
|
105149
104102
|
s.analyzePlan(bLog);
|
|
105150
104103
|
// let planAnalytics = s.getPlanAnalytics(bLog);
|