@dra2020/district-analytics 4.2.0 → 4.3.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/dist/cli.js +729 -577
- package/dist/cli.js.map +1 -1
- package/dist/district-analytics.js +649 -519
- package/dist/district-analytics.js.map +1 -1
- package/dist/src/_api.d.ts +0 -2
- package/dist/src/cohesive.d.ts +0 -2
- package/dist/src/compact.d.ts +0 -3
- package/dist/src/equal.d.ts +0 -1
- package/dist/src/minority.d.ts +0 -3
- package/dist/src/political.d.ts +0 -7
- package/dist/src/results.d.ts +0 -1
- package/dist/src/types.d.ts +2 -15
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -89793,7 +89793,7 @@ exports.scorePolsbyPopper = scorePolsbyPopper;
|
|
|
89793
89793
|
/*! exports provided: partisan, minority, traditionalPrinciples, default */
|
|
89794
89794
|
/***/ (function(module) {
|
|
89795
89795
|
|
|
89796
|
-
module.exports = JSON.parse("{\"partisan\":{\"bias\":{\"range\":[0,0.2],\"weight\":[50,80]},\"impact\":{\"weight\":[50,0],\"threshold\":4},\"competitiveness\":{\"overall\":{\"range\":[0,0.67],\"weight\":
|
|
89796
|
+
module.exports = JSON.parse("{\"partisan\":{\"bias\":{\"range\":[0,0.2],\"weight\":[50,80]},\"impact\":{\"weight\":[50,0],\"threshold\":4},\"competitiveness\":{\"overall\":{\"range\":[0,0.67],\"weight\":100},\"marginal\":{\"range\":[0,0.85],\"weight\":0},\"range\":[0.45,0.55],\"distribution\":[0.25,0.75],\"weight\":[0,20]},\"bonus\":2,\"weight\":[100,80]},\"minority\":{\"range\":[0.37,0.5],\"distribution\":[0.25,0.75],\"shift\":0.15,\"bonus\":20},\"traditionalPrinciples\":{\"compactness\":{\"reock\":{\"range\":[0.25,0.5],\"weight\":50},\"polsby\":{\"range\":[0.1,0.5],\"weight\":50},\"weight\":[0,50]},\"splitting\":{\"county\":{\"range\":[1,1.71],\"allowableSplitsMultiplier\":1.5,\"weight\":50},\"district\":{\"range\":[1,1.5],\"weight\":50},\"weight\":[0,50]},\"popdev\":{\"range\":[[0.0075,0.002],[0.1,-1]],\"weight\":[0,0]},\"weight\":[0,20]}}");
|
|
89797
89797
|
|
|
89798
89798
|
/***/ }),
|
|
89799
89799
|
|
|
@@ -90063,6 +90063,7 @@ function scorePopulationDeviation(rawValue, bLegislative) {
|
|
|
90063
90063
|
const _normalizer = new normalize_1.Normalizer(rawValue);
|
|
90064
90064
|
// Raw range in not inverted (i.e., smaller is better)
|
|
90065
90065
|
const range = C.popdevRange(bLegislative);
|
|
90066
|
+
_normalizer.clip(0.0, 1.0); // Handle deviations bigger than a whole district
|
|
90066
90067
|
_normalizer.invert();
|
|
90067
90068
|
_normalizer.clip(1.0 - range[C.BEG], 1.0 - range[C.END]);
|
|
90068
90069
|
_normalizer.unitize(1.0 - range[C.BEG], 1.0 - range[C.END]);
|
|
@@ -90223,6 +90224,11 @@ function calcProportionalDistricts(proportion, nDistricts) {
|
|
|
90223
90224
|
return integral;
|
|
90224
90225
|
}
|
|
90225
90226
|
exports.calcProportionalDistricts = calcProportionalDistricts;
|
|
90227
|
+
// TODO - 2020: Revise the second, when the update comes out (in September?).
|
|
90228
|
+
/* Sources for majority-minority info:
|
|
90229
|
+
- https://en.wikipedia.org/wiki/List_of_majority-minority_United_States_congressional_districts
|
|
90230
|
+
- http://www.ncsl.org/Portals/1/Documents/Redistricting/Redistricting_2010.pdf
|
|
90231
|
+
*/
|
|
90226
90232
|
|
|
90227
90233
|
|
|
90228
90234
|
/***/ }),
|
|
@@ -101325,6 +101331,7 @@ const preprocess_1 = __webpack_require__(/*! ./preprocess */ "./src/preprocess.t
|
|
|
101325
101331
|
const analyze_1 = __webpack_require__(/*! ./analyze */ "./src/analyze.ts");
|
|
101326
101332
|
const score_1 = __webpack_require__(/*! ./score */ "./src/score.ts");
|
|
101327
101333
|
const results_1 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
101334
|
+
// import { doConfigureScales, doAnalyzePostProcessing, RequirementsChecklist} from './results' // TODO - DELETE
|
|
101328
101335
|
const results_2 = __webpack_require__(/*! ./results */ "./src/results.ts");
|
|
101329
101336
|
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
101330
101337
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
@@ -101335,7 +101342,7 @@ class AnalyticsSession {
|
|
|
101335
101342
|
this.bOneTimeProcessingDone = false;
|
|
101336
101343
|
this.bPlanAnalyzed = false;
|
|
101337
101344
|
this.bPostProcessingDone = false;
|
|
101338
|
-
|
|
101345
|
+
// testScales = {} as T.TestScales; TODO - DELETE
|
|
101339
101346
|
this.tests = {};
|
|
101340
101347
|
this.title = SessionRequest['title'];
|
|
101341
101348
|
this.legislativeDistricts = SessionRequest['legislativeDistricts'];
|
|
@@ -101346,19 +101353,21 @@ class AnalyticsSession {
|
|
|
101346
101353
|
this.features = new D.Features(this, SessionRequest['data'], this.config['datasets']);
|
|
101347
101354
|
this.plan = new D.Plan(this, SessionRequest['plan']);
|
|
101348
101355
|
this.districts = new D.Districts(this, SessionRequest['districtShapes']);
|
|
101349
|
-
// TODO -
|
|
101350
|
-
if (this.useLegacy())
|
|
101351
|
-
|
|
101352
|
-
|
|
101353
|
-
|
|
101354
|
-
|
|
101355
|
-
|
|
101356
|
-
|
|
101357
|
-
|
|
101358
|
-
|
|
101359
|
-
|
|
101360
|
-
|
|
101361
|
-
|
|
101356
|
+
// TODO - DELETE
|
|
101357
|
+
// if (this.useLegacy())
|
|
101358
|
+
// {
|
|
101359
|
+
// console.log("Using legacy district-analytics.")
|
|
101360
|
+
// // NOTE: I've pulled these out of the individual analytics to here. Eventually,
|
|
101361
|
+
// // we could want them to passed into an analytics session as data, along with
|
|
101362
|
+
// // everything else. For now, this keeps branching out of the main code.
|
|
101363
|
+
// doConfigureScales(this);
|
|
101364
|
+
// }
|
|
101365
|
+
// else
|
|
101366
|
+
// {
|
|
101367
|
+
// console.log("Using dra-score analytics.")
|
|
101368
|
+
// // TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
101369
|
+
// doConfigureScales(this);
|
|
101370
|
+
// }
|
|
101362
101371
|
}
|
|
101363
101372
|
processConfig(config) {
|
|
101364
101373
|
// NOTE - Session settings are required:
|
|
@@ -101371,13 +101380,15 @@ class AnalyticsSession {
|
|
|
101371
101380
|
config['cycle'] = 2010;
|
|
101372
101381
|
return config;
|
|
101373
101382
|
}
|
|
101374
|
-
|
|
101375
|
-
useLegacy()
|
|
101376
|
-
|
|
101377
|
-
|
|
101378
|
-
|
|
101379
|
-
|
|
101383
|
+
/* TODO - DELETE
|
|
101384
|
+
useLegacy(): boolean
|
|
101385
|
+
{
|
|
101386
|
+
// TODO - SCORE: Opt-out
|
|
101387
|
+
return (U.keyExists('useScore', this.config) && (this.config['useScore'] != null) && (!(this.config['useScore']))) ? true : false;
|
|
101388
|
+
// TODO - SCORE: Opt-in
|
|
101389
|
+
// return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
|
|
101380
101390
|
}
|
|
101391
|
+
*/
|
|
101381
101392
|
// Using the the data in the analytics session, calculate all the
|
|
101382
101393
|
// analytics & validations, saving/updating the individual test results.
|
|
101383
101394
|
analyzePlan(bLog = false, overridesJSON) {
|
|
@@ -101509,19 +101520,21 @@ class AnalyticsSession {
|
|
|
101509
101520
|
}
|
|
101510
101521
|
// NOTE - Not sure why this has to be up here ...
|
|
101511
101522
|
populationDeviationThreshold() {
|
|
101512
|
-
// TODO -
|
|
101513
|
-
if (this.useLegacy())
|
|
101514
|
-
|
|
101515
|
-
|
|
101516
|
-
|
|
101517
|
-
|
|
101518
|
-
|
|
101519
|
-
|
|
101520
|
-
|
|
101521
|
-
|
|
101522
|
-
|
|
101523
|
-
|
|
101524
|
-
|
|
101523
|
+
// TODO - DELETE
|
|
101524
|
+
// if (this.useLegacy())
|
|
101525
|
+
// {
|
|
101526
|
+
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
101527
|
+
// }
|
|
101528
|
+
// else
|
|
101529
|
+
// {
|
|
101530
|
+
// NOTE - This assumes the plan has been profiled
|
|
101531
|
+
const scorer = new Score.Scorer();
|
|
101532
|
+
const popdev = scorer.populationDeviationThreshold(this.legislativeDistricts);
|
|
101533
|
+
return popdev;
|
|
101534
|
+
// TODO - SCORE: Temporary HACK. Query dra-score for threshold.
|
|
101535
|
+
// NOTE - The plan may not have been scored yet, i.e., no scorecard yet.
|
|
101536
|
+
// return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
|
|
101537
|
+
// }
|
|
101525
101538
|
}
|
|
101526
101539
|
}
|
|
101527
101540
|
exports.AnalyticsSession = AnalyticsSession;
|
|
@@ -102130,10 +102143,22 @@ exports.Graph = Graph;
|
|
|
102130
102143
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102131
102144
|
const valid_1 = __webpack_require__(/*! ./valid */ "./src/valid.ts");
|
|
102132
102145
|
const equal_1 = __webpack_require__(/*! ./equal */ "./src/equal.ts");
|
|
102133
|
-
|
|
102146
|
+
// import { doPopulationDeviation, doHasEqualPopulations } from './equal'; TODO - DELETE
|
|
102147
|
+
// import { doReock, doPolsbyPopper } from './compact'; TODO - DELETE
|
|
102134
102148
|
const cohesive_1 = __webpack_require__(/*! ./cohesive */ "./src/cohesive.ts");
|
|
102135
|
-
|
|
102136
|
-
|
|
102149
|
+
/* TODO - DELETE
|
|
102150
|
+
import
|
|
102151
|
+
{
|
|
102152
|
+
doFindCountiesSplitUnexpectedly, doFindSplitVTDs,
|
|
102153
|
+
doCountySplitting, doDistrictSplitting
|
|
102154
|
+
} from './cohesive';
|
|
102155
|
+
import
|
|
102156
|
+
{
|
|
102157
|
+
doSeatsBias, doVotesBias,
|
|
102158
|
+
doResponsiveness, doResponsiveDistricts, doEfficiencyGap
|
|
102159
|
+
} from './political';
|
|
102160
|
+
import { doMajorityMinorityDistricts } from './minority'
|
|
102161
|
+
*/
|
|
102137
102162
|
// Compile district-level info for plan/map-level analytics
|
|
102138
102163
|
function doAnalyzeDistricts(s, bLog = false) {
|
|
102139
102164
|
s.districts.recalcStatistics(bLog);
|
|
@@ -102145,58 +102170,65 @@ exports.doAnalyzeDistricts = doAnalyzeDistricts;
|
|
|
102145
102170
|
// NOTE - I could make this table-driven, but I'm thinking that the explicit
|
|
102146
102171
|
// calls might make chunking for aync easier.
|
|
102147
102172
|
function doAnalyzePlan(s, bLog = false) {
|
|
102148
|
-
// TODO -
|
|
102149
|
-
if (s.useLegacy())
|
|
102150
|
-
|
|
102151
|
-
|
|
102152
|
-
|
|
102153
|
-
|
|
102154
|
-
|
|
102155
|
-
|
|
102156
|
-
|
|
102157
|
-
|
|
102158
|
-
|
|
102159
|
-
|
|
102160
|
-
|
|
102161
|
-
|
|
102162
|
-
|
|
102163
|
-
|
|
102164
|
-
|
|
102165
|
-
|
|
102166
|
-
|
|
102167
|
-
|
|
102168
|
-
|
|
102169
|
-
|
|
102170
|
-
|
|
102171
|
-
|
|
102172
|
-
|
|
102173
|
-
|
|
102174
|
-
|
|
102175
|
-
|
|
102176
|
-
|
|
102177
|
-
|
|
102178
|
-
|
|
102179
|
-
|
|
102180
|
-
|
|
102181
|
-
|
|
102182
|
-
|
|
102183
|
-
|
|
102184
|
-
|
|
102185
|
-
|
|
102186
|
-
|
|
102187
|
-
|
|
102188
|
-
|
|
102189
|
-
|
|
102190
|
-
|
|
102191
|
-
|
|
102192
|
-
|
|
102193
|
-
|
|
102194
|
-
|
|
102195
|
-
|
|
102196
|
-
|
|
102197
|
-
|
|
102198
|
-
|
|
102199
|
-
|
|
102173
|
+
// TODO - DELETE
|
|
102174
|
+
// if (s.useLegacy())
|
|
102175
|
+
// {
|
|
102176
|
+
// // Disable most legacy analytics
|
|
102177
|
+
// // Get the requested suites, and only execute those tests
|
|
102178
|
+
// let requestedSuites = s.config['suites'];
|
|
102179
|
+
// // Tests in the "Legal" suite, i.e., pass/ fail constraints
|
|
102180
|
+
// if (requestedSuites.includes(T.Suite.Legal))
|
|
102181
|
+
// {
|
|
102182
|
+
// s.tests[T.Test.Complete] = doIsComplete(s, bLog);
|
|
102183
|
+
// s.tests[T.Test.Contiguous] = doIsContiguous(s, bLog);
|
|
102184
|
+
// s.tests[T.Test.FreeOfHoles] = doIsFreeOfHoles(s, bLog);
|
|
102185
|
+
// // s.tests[T.Test.PopulationDeviation] = doPopulationDeviation(s, bLog); TODO - DELETE
|
|
102186
|
+
// // NOTE - I can't check whether a population deviation is legal or not, until
|
|
102187
|
+
// // the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
102188
|
+
// // the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
102189
|
+
// // from PopulationDeviation, as part of scorecard or test log preparation.
|
|
102190
|
+
// // Create an empty test entry here though ...
|
|
102191
|
+
// s.tests[T.Test.EqualPopulation] = s.getTest(T.Test.EqualPopulation) as T.TestEntry;
|
|
102192
|
+
// }
|
|
102193
|
+
// // Tests in the "Fair" suite
|
|
102194
|
+
// if (requestedSuites.includes(T.Suite.Fair))
|
|
102195
|
+
// {
|
|
102196
|
+
// /* TODO - DELETE
|
|
102197
|
+
// s.tests[T.Test.SeatsBias] = doSeatsBias(s, bLog);
|
|
102198
|
+
// s.tests[T.Test.VotesBias] = doVotesBias(s, bLog);
|
|
102199
|
+
// s.tests[T.Test.Responsiveness] = doResponsiveness(s, bLog);
|
|
102200
|
+
// s.tests[T.Test.ResponsiveDistricts] = doResponsiveDistricts(s, bLog);
|
|
102201
|
+
// s.tests[T.Test.EfficiencyGap] = doEfficiencyGap(s, bLog);
|
|
102202
|
+
// s.tests[T.Test.MajorityMinorityDistricts] = doMajorityMinorityDistricts(s, bLog);
|
|
102203
|
+
// */
|
|
102204
|
+
// }
|
|
102205
|
+
// // Tests in the "Best" suite, i.e., criteria for better/worse
|
|
102206
|
+
// if (requestedSuites.includes(T.Suite.Best))
|
|
102207
|
+
// {
|
|
102208
|
+
// // s.tests[T.Test.Reock] = doReock(s, bLog); TODO - DELETE
|
|
102209
|
+
// // s.tests[T.Test.PolsbyPopper] = doPolsbyPopper(s, bLog); TODO - DELETE
|
|
102210
|
+
// s.tests[T.Test.UnexpectedCountySplits] = doFindCountiesSplitUnexpectedly(s, bLog);
|
|
102211
|
+
// s.tests[T.Test.VTDSplits] = doFindSplitVTDs(s, bLog);
|
|
102212
|
+
// // s.tests[T.Test.CountySplitting] = doCountySplitting(s, bLog); TODO - DELETE
|
|
102213
|
+
// // s.tests[T.Test.DistrictSplitting] = doDistrictSplitting(s, bLog); TODO - DELETE
|
|
102214
|
+
// }
|
|
102215
|
+
// }
|
|
102216
|
+
// else
|
|
102217
|
+
// {
|
|
102218
|
+
// TODO - SCORE: Except these. Continue to do these here vs. dra-score.
|
|
102219
|
+
s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
|
|
102220
|
+
s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
|
|
102221
|
+
s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
|
|
102222
|
+
// s.tests[T.Test.PopulationDeviation] = doPopulationDeviation(s, bLog); TODO - DELETE
|
|
102223
|
+
// NOTE - I can't check whether a population deviation is legal or not, until
|
|
102224
|
+
// the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
|
|
102225
|
+
// the given type of district (CD vs. LD). The EqualPopulation test is derived
|
|
102226
|
+
// from PopulationDeviation, as part of scorecard or test log preparation.
|
|
102227
|
+
// Create an empty test entry here though ...
|
|
102228
|
+
s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
|
|
102229
|
+
s.tests[5 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
|
|
102230
|
+
s.tests[6 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
|
|
102231
|
+
// }
|
|
102200
102232
|
// Enable a Test Log and Scorecard to be generated
|
|
102201
102233
|
s.bPlanAnalyzed = true;
|
|
102202
102234
|
s.bPostProcessingDone = false;
|
|
@@ -102237,185 +102269,279 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
102237
102269
|
};
|
|
102238
102270
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102239
102271
|
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
102240
|
-
const S = __importStar(__webpack_require__(/*! ./settings */ "./src/settings.ts"));
|
|
102241
102272
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
102273
|
+
// NOTE - The active code is below the long multi-line section to be deleted.
|
|
102274
|
+
/* TODO - DELETE
|
|
102242
102275
|
// CALCULATE ENHANCED SQRT ENTROPY METRIC
|
|
102243
|
-
|
|
102244
|
-
|
|
102245
|
-
|
|
102246
|
-
|
|
102247
|
-
|
|
102248
|
-
|
|
102249
|
-
|
|
102250
|
-
|
|
102251
|
-
|
|
102252
|
-
|
|
102253
|
-
|
|
102254
|
-
|
|
102255
|
-
|
|
102256
|
-
|
|
102257
|
-
|
|
102258
|
-
|
|
102276
|
+
|
|
102277
|
+
export function doCountySplitting(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102278
|
+
{
|
|
102279
|
+
let test = s.getTest(T.Test.CountySplitting) as T.TestEntry;
|
|
102280
|
+
|
|
102281
|
+
let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
|
|
102282
|
+
let countyTotals = s.counties.totalPopulation;
|
|
102283
|
+
let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
|
|
102284
|
+
|
|
102285
|
+
let f = calcCountyFractions(CxD, countyTotals);
|
|
102286
|
+
let w = calcCountyWeights(countyTotals);
|
|
102287
|
+
|
|
102288
|
+
let SqEnt_DC = countySplitting(f, w, bLog);
|
|
102289
|
+
|
|
102290
|
+
let CxDreducedC = U.deepCopy(CxD);
|
|
102291
|
+
reduceCSplits(CxDreducedC, districtTotals);
|
|
102292
|
+
|
|
102293
|
+
let fReduced = calcCountyFractions(CxDreducedC, countyTotals);
|
|
102294
|
+
let wReduced = calcCountyWeights(countyTotals);
|
|
102295
|
+
|
|
102296
|
+
let SqEnt_DCreduced = countySplitting(fReduced, wReduced, bLog);
|
|
102297
|
+
|
|
102298
|
+
test['score'] = SqEnt_DCreduced;
|
|
102299
|
+
test['details']['SqEnt_DC'] = SqEnt_DC;
|
|
102300
|
+
|
|
102301
|
+
return test;
|
|
102259
102302
|
}
|
|
102260
|
-
|
|
102261
|
-
function doDistrictSplitting(s, bLog = false)
|
|
102262
|
-
|
|
102263
|
-
|
|
102264
|
-
|
|
102265
|
-
|
|
102266
|
-
|
|
102267
|
-
|
|
102268
|
-
|
|
102269
|
-
|
|
102270
|
-
|
|
102271
|
-
|
|
102272
|
-
|
|
102273
|
-
|
|
102274
|
-
|
|
102275
|
-
|
|
102276
|
-
|
|
102303
|
+
|
|
102304
|
+
export function doDistrictSplitting(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102305
|
+
{
|
|
102306
|
+
let test = s.getTest(T.Test.DistrictSplitting) as T.TestEntry;
|
|
102307
|
+
|
|
102308
|
+
let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
|
|
102309
|
+
let countyTotals = s.counties.totalPopulation;
|
|
102310
|
+
let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
|
|
102311
|
+
|
|
102312
|
+
let g = calcDistrictFractions(CxD, districtTotals);
|
|
102313
|
+
let x = calcDistrictWeights(districtTotals);
|
|
102314
|
+
|
|
102315
|
+
let SqEnt_CD = districtSplitting(g, x, bLog);
|
|
102316
|
+
|
|
102317
|
+
let CxDreducedD = U.deepCopy(CxD);
|
|
102318
|
+
reduceDSplits(CxDreducedD, countyTotals);
|
|
102319
|
+
|
|
102320
|
+
let gReduced = calcDistrictFractions(CxDreducedD, districtTotals);
|
|
102321
|
+
let xReduced = calcDistrictWeights(districtTotals);
|
|
102322
|
+
|
|
102323
|
+
let SqEnt_CDreduced = districtSplitting(gReduced, xReduced, bLog);
|
|
102324
|
+
|
|
102325
|
+
test['score'] = SqEnt_CDreduced;
|
|
102326
|
+
test['details']['SqEnt_CD'] = SqEnt_CD;
|
|
102327
|
+
|
|
102328
|
+
return test;
|
|
102277
102329
|
}
|
|
102278
|
-
|
|
102330
|
+
|
|
102331
|
+
|
|
102279
102332
|
// HELPERS
|
|
102280
|
-
|
|
102333
|
+
|
|
102334
|
+
// Loop over all the county-district combos, skipping the virtual district 0
|
|
102281
102335
|
// and virtual county 0.
|
|
102282
102336
|
//
|
|
102283
102337
|
// NOTE - The county-district splits and the county & district totals may all,
|
|
102284
102338
|
// in general, be fractional/decimal numbers as opposed to integers, due to
|
|
102285
102339
|
// dissaggregation & re-aggregation. Hence, comparisons need to approximate
|
|
102286
102340
|
// equality.
|
|
102341
|
+
|
|
102287
102342
|
// Consolidate districts (rows) consisting of just one county (column)
|
|
102288
102343
|
// UP into the dummy district (0).
|
|
102289
|
-
function reduceCSplits(CxDreducedC, districtTotals)
|
|
102290
|
-
|
|
102291
|
-
|
|
102292
|
-
|
|
102293
|
-
|
|
102294
|
-
|
|
102295
|
-
|
|
102296
|
-
|
|
102297
|
-
|
|
102298
|
-
|
|
102299
|
-
|
|
102300
|
-
|
|
102344
|
+
function reduceCSplits(CxDreducedC: number[][], districtTotals: number[]): void
|
|
102345
|
+
{
|
|
102346
|
+
let nD = CxDreducedC.length;
|
|
102347
|
+
let nC = CxDreducedC[0].length;
|
|
102348
|
+
|
|
102349
|
+
for (let j = 1; j < nC; j++)
|
|
102350
|
+
{
|
|
102351
|
+
for (let i = 1; i < nD; i++)
|
|
102352
|
+
{
|
|
102353
|
+
let split_total = CxDreducedC[i][j];
|
|
102354
|
+
|
|
102355
|
+
if (split_total > 0)
|
|
102356
|
+
{
|
|
102357
|
+
if (areRoughlyEqual(split_total, districtTotals[i]))
|
|
102358
|
+
{
|
|
102359
|
+
CxDreducedC[0][j] += split_total;
|
|
102360
|
+
CxDreducedC[i][j] = 0;
|
|
102301
102361
|
}
|
|
102362
|
+
}
|
|
102302
102363
|
}
|
|
102364
|
+
}
|
|
102303
102365
|
}
|
|
102366
|
+
|
|
102304
102367
|
// Consolidate whole counties (columns) in a district (row) LEFT into the
|
|
102305
102368
|
// dummy county (0).
|
|
102306
|
-
function reduceDSplits(CxDreducedD, countyTotals)
|
|
102307
|
-
|
|
102308
|
-
|
|
102309
|
-
|
|
102310
|
-
|
|
102311
|
-
|
|
102312
|
-
|
|
102313
|
-
|
|
102314
|
-
|
|
102315
|
-
|
|
102316
|
-
|
|
102317
|
-
|
|
102369
|
+
function reduceDSplits(CxDreducedD: number[][], countyTotals: number[]): void
|
|
102370
|
+
{
|
|
102371
|
+
let nD = CxDreducedD.length;
|
|
102372
|
+
let nC = CxDreducedD[0].length;
|
|
102373
|
+
|
|
102374
|
+
for (let i = 1; i < nD; i++)
|
|
102375
|
+
{
|
|
102376
|
+
for (let j = 1; j < nC; j++)
|
|
102377
|
+
{
|
|
102378
|
+
let split_total = CxDreducedD[i][j];
|
|
102379
|
+
|
|
102380
|
+
if (split_total > 0)
|
|
102381
|
+
{
|
|
102382
|
+
if (areRoughlyEqual(split_total, countyTotals[j]))
|
|
102383
|
+
{
|
|
102384
|
+
CxDreducedD[i][0] += split_total;
|
|
102385
|
+
CxDreducedD[i][j] = 0;
|
|
102318
102386
|
}
|
|
102387
|
+
}
|
|
102319
102388
|
}
|
|
102389
|
+
}
|
|
102320
102390
|
}
|
|
102321
|
-
|
|
102322
|
-
|
|
102323
|
-
|
|
102324
|
-
|
|
102325
|
-
|
|
102326
|
-
|
|
102327
|
-
|
|
102328
|
-
|
|
102391
|
+
|
|
102392
|
+
function calcCountyWeights(countyTotals: number[]): number[]
|
|
102393
|
+
{
|
|
102394
|
+
let nC: number = countyTotals.length;
|
|
102395
|
+
let cTotal: number = U.sumArray(countyTotals);
|
|
102396
|
+
|
|
102397
|
+
let w: number[] = U.initArray(nC, 0.0);
|
|
102398
|
+
|
|
102399
|
+
for (let j = 0; j < nC; j++)
|
|
102400
|
+
{
|
|
102401
|
+
w[j] = countyTotals[j] / cTotal;
|
|
102402
|
+
}
|
|
102403
|
+
|
|
102404
|
+
return w;
|
|
102329
102405
|
}
|
|
102330
|
-
|
|
102331
|
-
|
|
102332
|
-
|
|
102333
|
-
|
|
102334
|
-
|
|
102335
|
-
|
|
102336
|
-
|
|
102337
|
-
|
|
102406
|
+
|
|
102407
|
+
function calcDistrictWeights(districtTotals: number[]): number[]
|
|
102408
|
+
{
|
|
102409
|
+
let nD = districtTotals.length;
|
|
102410
|
+
let dTotal: number = U.sumArray(districtTotals);
|
|
102411
|
+
|
|
102412
|
+
let x: number[] = U.initArray(nD, 0.0);
|
|
102413
|
+
|
|
102414
|
+
for (let i = 0; i < nD; i++)
|
|
102415
|
+
{
|
|
102416
|
+
x[i] = districtTotals[i] / dTotal;
|
|
102417
|
+
}
|
|
102418
|
+
|
|
102419
|
+
return x;
|
|
102338
102420
|
}
|
|
102339
|
-
|
|
102340
|
-
|
|
102341
|
-
|
|
102342
|
-
|
|
102343
|
-
|
|
102344
|
-
|
|
102345
|
-
|
|
102346
|
-
|
|
102347
|
-
|
|
102348
|
-
|
|
102349
|
-
|
|
102350
|
-
|
|
102351
|
-
|
|
102421
|
+
|
|
102422
|
+
function calcCountyFractions(CxDreducedD: number[][], countyTotals: number[]): number[][]
|
|
102423
|
+
{
|
|
102424
|
+
let nD = CxDreducedD.length;
|
|
102425
|
+
let nC = CxDreducedD[0].length;
|
|
102426
|
+
|
|
102427
|
+
let f: number[][] = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
|
|
102428
|
+
|
|
102429
|
+
for (let j = 0; j < nC; j++)
|
|
102430
|
+
{
|
|
102431
|
+
for (let i = 0; i < nD; i++)
|
|
102432
|
+
{
|
|
102433
|
+
if (countyTotals[j] > 0)
|
|
102434
|
+
{
|
|
102435
|
+
f[i][j] = CxDreducedD[i][j] / countyTotals[j];
|
|
102436
|
+
}
|
|
102437
|
+
else
|
|
102438
|
+
{
|
|
102439
|
+
f[i][j] = 0.0;
|
|
102440
|
+
}
|
|
102352
102441
|
}
|
|
102353
|
-
|
|
102442
|
+
}
|
|
102443
|
+
|
|
102444
|
+
return f;
|
|
102354
102445
|
}
|
|
102355
|
-
|
|
102356
|
-
|
|
102357
|
-
|
|
102358
|
-
|
|
102359
|
-
|
|
102360
|
-
|
|
102361
|
-
|
|
102362
|
-
|
|
102363
|
-
|
|
102364
|
-
|
|
102365
|
-
|
|
102366
|
-
|
|
102367
|
-
|
|
102446
|
+
|
|
102447
|
+
function calcDistrictFractions(CxDreducedC: number[][], districtTotals: number[]): number[][]
|
|
102448
|
+
{
|
|
102449
|
+
let nD = CxDreducedC.length;
|
|
102450
|
+
let nC = CxDreducedC[0].length;
|
|
102451
|
+
|
|
102452
|
+
let g: number[][] = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
|
|
102453
|
+
|
|
102454
|
+
for (let j = 0; j < nC; j++)
|
|
102455
|
+
{
|
|
102456
|
+
for (let i = 0; i < nD; i++)
|
|
102457
|
+
{
|
|
102458
|
+
if (districtTotals[i] > 0)
|
|
102459
|
+
{
|
|
102460
|
+
g[i][j] = CxDreducedC[i][j] / districtTotals[i];
|
|
102461
|
+
}
|
|
102462
|
+
else
|
|
102463
|
+
{
|
|
102464
|
+
g[i][j] = 0.0;
|
|
102465
|
+
}
|
|
102368
102466
|
}
|
|
102369
|
-
|
|
102467
|
+
}
|
|
102468
|
+
|
|
102469
|
+
return g;
|
|
102370
102470
|
}
|
|
102471
|
+
|
|
102371
102472
|
// Deal with decimal census "counts" due to disagg/re-agg
|
|
102372
|
-
function areRoughlyEqual(x, y)
|
|
102373
|
-
|
|
102374
|
-
|
|
102375
|
-
|
|
102473
|
+
function areRoughlyEqual(x: number, y: number): boolean
|
|
102474
|
+
{
|
|
102475
|
+
let delta = Math.abs(x - y);
|
|
102476
|
+
let result = (delta < S.EQUAL_TOLERANCE) ? true : false;
|
|
102477
|
+
|
|
102478
|
+
return result;
|
|
102376
102479
|
}
|
|
102480
|
+
|
|
102377
102481
|
// For all districts in a county, sum the split score.
|
|
102378
|
-
function countySplitScore(j, f, numD, bLog = false)
|
|
102379
|
-
|
|
102380
|
-
|
|
102381
|
-
|
|
102382
|
-
|
|
102383
|
-
|
|
102482
|
+
function countySplitScore(j: number, f: number[][], numD: number, bLog: boolean = false): number
|
|
102483
|
+
{
|
|
102484
|
+
let e = 0.0;
|
|
102485
|
+
|
|
102486
|
+
for (let i = 0; i < numD; i++)
|
|
102487
|
+
{
|
|
102488
|
+
e += Math.sqrt(f[i][j]);
|
|
102489
|
+
}
|
|
102490
|
+
|
|
102491
|
+
return e;
|
|
102384
102492
|
}
|
|
102493
|
+
|
|
102385
102494
|
// For all counties, sum the weighted county splits.
|
|
102386
|
-
function countySplitting(f, w, bLog = false)
|
|
102387
|
-
|
|
102388
|
-
|
|
102389
|
-
|
|
102390
|
-
|
|
102391
|
-
|
|
102392
|
-
|
|
102393
|
-
|
|
102394
|
-
|
|
102395
|
-
|
|
102396
|
-
|
|
102495
|
+
function countySplitting(f: number[][], w: number[], bLog: boolean = false): number
|
|
102496
|
+
{
|
|
102497
|
+
let numC = f[0].length;
|
|
102498
|
+
let numD = f.length;
|
|
102499
|
+
|
|
102500
|
+
let e = 0.0;
|
|
102501
|
+
|
|
102502
|
+
for (let j = 0; j < numC; j++)
|
|
102503
|
+
{
|
|
102504
|
+
let splitScore = countySplitScore(j, f, numD, bLog);
|
|
102505
|
+
e += w[j] * splitScore;
|
|
102506
|
+
|
|
102507
|
+
if (bLog) console.log("County splitting =", j, w[j], splitScore, e);
|
|
102508
|
+
}
|
|
102509
|
+
|
|
102510
|
+
return U.trim(e, 3);
|
|
102397
102511
|
}
|
|
102512
|
+
|
|
102398
102513
|
// For all counties in a district, sum the split score.
|
|
102399
|
-
function districtSplitScore(i, g, numC, bLog = false)
|
|
102400
|
-
|
|
102401
|
-
|
|
102402
|
-
|
|
102403
|
-
|
|
102404
|
-
|
|
102514
|
+
function districtSplitScore(i: number, g: number[][], numC: number, bLog: boolean = false): number
|
|
102515
|
+
{
|
|
102516
|
+
let e = 0.0;
|
|
102517
|
+
|
|
102518
|
+
for (let j = 0; j < numC; j++)
|
|
102519
|
+
{
|
|
102520
|
+
e += Math.sqrt(g[i][j]);
|
|
102521
|
+
}
|
|
102522
|
+
|
|
102523
|
+
return e;
|
|
102405
102524
|
}
|
|
102525
|
+
|
|
102406
102526
|
// For all districts, sum the weighted district splits.
|
|
102407
|
-
function districtSplitting(g, x, bLog = false)
|
|
102408
|
-
|
|
102409
|
-
|
|
102410
|
-
|
|
102411
|
-
|
|
102412
|
-
|
|
102413
|
-
|
|
102414
|
-
|
|
102415
|
-
|
|
102416
|
-
|
|
102417
|
-
|
|
102527
|
+
function districtSplitting(g: number[][], x: number[], bLog: boolean = false): number
|
|
102528
|
+
{
|
|
102529
|
+
let numC = g[0].length;
|
|
102530
|
+
let numD = g.length;
|
|
102531
|
+
|
|
102532
|
+
let e = 0.0;
|
|
102533
|
+
|
|
102534
|
+
for (let i = 0; i < numD; i++)
|
|
102535
|
+
{
|
|
102536
|
+
let splitScore = districtSplitScore(i, g, numC, bLog);
|
|
102537
|
+
e += x[i] * splitScore;
|
|
102538
|
+
|
|
102539
|
+
if (bLog) console.log("District split score =", i, x[i], splitScore, e);
|
|
102540
|
+
}
|
|
102541
|
+
|
|
102542
|
+
return U.trim(e, 3);
|
|
102418
102543
|
}
|
|
102544
|
+
*/
|
|
102419
102545
|
// ANALYZE SIMPLE COUNTY & VTD SPLITTING
|
|
102420
102546
|
/*
|
|
102421
102547
|
|
|
@@ -102450,7 +102576,7 @@ These counties are split unexpectedly:
|
|
|
102450
102576
|
|
|
102451
102577
|
*/
|
|
102452
102578
|
function doFindCountiesSplitUnexpectedly(s, bLog = false) {
|
|
102453
|
-
let test = s.getTest(
|
|
102579
|
+
let test = s.getTest(5 /* UnexpectedCountySplits */);
|
|
102454
102580
|
// THE THREE VALUES TO DETERMINE FOR A PLAN
|
|
102455
102581
|
let unexpectedSplits = 0;
|
|
102456
102582
|
let unexpectedAffected = 0;
|
|
@@ -102543,10 +102669,10 @@ function doFindCountiesSplitUnexpectedly(s, bLog = false) {
|
|
|
102543
102669
|
return test;
|
|
102544
102670
|
}
|
|
102545
102671
|
exports.doFindCountiesSplitUnexpectedly = doFindCountiesSplitUnexpectedly;
|
|
102672
|
+
// NOTE - This function just creates an empty container that dra-client fills in when generating the UI
|
|
102546
102673
|
function doFindSplitVTDs(s, bLog = false) {
|
|
102547
|
-
let test = s.getTest(
|
|
102674
|
+
let test = s.getTest(6 /* VTDSplits */);
|
|
102548
102675
|
let splitVTDs = [];
|
|
102549
|
-
// TODO - SPLITTING: Flesh this out, using virtual VTD's ...
|
|
102550
102676
|
test['score'] = splitVTDs.length;
|
|
102551
102677
|
test['details']['splitVTDs'] = splitVTDs;
|
|
102552
102678
|
return test;
|
|
@@ -102576,10 +102702,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
102576
102702
|
return result;
|
|
102577
102703
|
};
|
|
102578
102704
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102705
|
+
// NOTE - This file will NOT be empty, when legacy code is deleted.
|
|
102579
102706
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "./node_modules/@dra2020/poly/dist/poly.js"));
|
|
102580
102707
|
const geofeature_1 = __webpack_require__(/*! ./geofeature */ "./src/geofeature.ts");
|
|
102581
|
-
|
|
102582
|
-
// TODO - SCORE: Remove legacy code
|
|
102708
|
+
// TODO - DELETE
|
|
102583
102709
|
// Measures of compactness compare district shapes to various ideally compact
|
|
102584
102710
|
// benchmarks, such as circles. All else equal, more compact districts are better.
|
|
102585
102711
|
//
|
|
@@ -102658,62 +102784,83 @@ const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
|
102658
102784
|
// For each measure, the compactness of a set of Congressional districts is the
|
|
102659
102785
|
// average of that measure for all the districts.
|
|
102660
102786
|
//
|
|
102787
|
+
/* TODO - DELETE
|
|
102661
102788
|
// Calculate Reock compactness:
|
|
102662
102789
|
// reock = (4 * a) / (math.pi * d**2)
|
|
102663
102790
|
// NOTE - Depends on extractDistrictProperties running first
|
|
102664
|
-
function doReock(s, bLog = false)
|
|
102665
|
-
|
|
102666
|
-
|
|
102667
|
-
|
|
102668
|
-
|
|
102669
|
-
|
|
102670
|
-
|
|
102671
|
-
|
|
102672
|
-
|
|
102673
|
-
|
|
102674
|
-
|
|
102675
|
-
|
|
102676
|
-
|
|
102677
|
-
|
|
102678
|
-
|
|
102679
|
-
|
|
102680
|
-
|
|
102791
|
+
export function doReock(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102792
|
+
{
|
|
102793
|
+
let test = s.getTest(T.Test.Reock) as T.TestEntry;
|
|
102794
|
+
|
|
102795
|
+
// Calculate Reock scores by district
|
|
102796
|
+
let scores: number[] = [];
|
|
102797
|
+
|
|
102798
|
+
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++)
|
|
102799
|
+
{
|
|
102800
|
+
let districtProps = s.districts.getGeoProperties(districtID);
|
|
102801
|
+
// Guard against no shape and no properties
|
|
102802
|
+
if (districtProps)
|
|
102803
|
+
{
|
|
102804
|
+
let a = districtProps[T.DistrictShapeProperty.Area];
|
|
102805
|
+
let d = districtProps[T.DistrictShapeProperty.Diameter];
|
|
102806
|
+
|
|
102807
|
+
let reock = (4 * a) / (Math.PI * d ** 2);
|
|
102808
|
+
|
|
102809
|
+
// Save each district score
|
|
102810
|
+
scores.push(reock);
|
|
102811
|
+
|
|
102812
|
+
// Echo the results by district
|
|
102813
|
+
if (bLog) console.log("Reock for district", districtID, "=", reock);
|
|
102681
102814
|
}
|
|
102682
|
-
|
|
102683
|
-
|
|
102684
|
-
|
|
102685
|
-
|
|
102686
|
-
|
|
102815
|
+
}
|
|
102816
|
+
|
|
102817
|
+
// Populate the test entry ... for the shapes that exist!
|
|
102818
|
+
let averageReock = U.avgArray(scores);
|
|
102819
|
+
|
|
102820
|
+
test['score'] = U.trim(averageReock);
|
|
102821
|
+
test['details'] = {}; // TODO - Any details?
|
|
102822
|
+
|
|
102823
|
+
return test;
|
|
102687
102824
|
}
|
|
102688
|
-
|
|
102825
|
+
|
|
102689
102826
|
// Calculate Polsby-Popper compactness measures:
|
|
102690
102827
|
// polsby_popper = (4 * math.pi) * (a / p**2)
|
|
102691
102828
|
// NOTE - Depends on extractDistrictProperties running first
|
|
102692
|
-
function doPolsbyPopper(s, bLog = false)
|
|
102693
|
-
|
|
102694
|
-
|
|
102695
|
-
|
|
102696
|
-
|
|
102697
|
-
|
|
102698
|
-
|
|
102699
|
-
|
|
102700
|
-
|
|
102701
|
-
|
|
102702
|
-
|
|
102703
|
-
|
|
102704
|
-
|
|
102705
|
-
|
|
102706
|
-
|
|
102707
|
-
|
|
102708
|
-
|
|
102829
|
+
export function doPolsbyPopper(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102830
|
+
{
|
|
102831
|
+
let test = s.getTest(T.Test.PolsbyPopper) as T.TestEntry;
|
|
102832
|
+
|
|
102833
|
+
// Calculate Polsby-Popper scores by district
|
|
102834
|
+
let scores: number[] = [];
|
|
102835
|
+
|
|
102836
|
+
for (let districtID = 1; districtID <= s.state.nDistricts; districtID++)
|
|
102837
|
+
{
|
|
102838
|
+
let districtProps = s.districts.getGeoProperties(districtID);
|
|
102839
|
+
// Guard against no shape and no properties
|
|
102840
|
+
if (districtProps)
|
|
102841
|
+
{
|
|
102842
|
+
let a = districtProps[T.DistrictShapeProperty.Area];
|
|
102843
|
+
let p = districtProps[T.DistrictShapeProperty.Perimeter];
|
|
102844
|
+
|
|
102845
|
+
let polsbyPopper = (4 * Math.PI) * (a / p ** 2);
|
|
102846
|
+
|
|
102847
|
+
// Save each district score
|
|
102848
|
+
scores.push(polsbyPopper);
|
|
102849
|
+
|
|
102850
|
+
// Echo the results by district
|
|
102851
|
+
if (bLog) console.log("Polsby-Popper for district", districtID, "=", polsbyPopper);
|
|
102709
102852
|
}
|
|
102710
|
-
|
|
102711
|
-
|
|
102712
|
-
|
|
102713
|
-
|
|
102714
|
-
|
|
102853
|
+
}
|
|
102854
|
+
|
|
102855
|
+
// Populate the test entry ... for the shapes that exist!
|
|
102856
|
+
let averagePolsbyPopper = U.avgArray(scores);
|
|
102857
|
+
|
|
102858
|
+
test['score'] = U.trim(averagePolsbyPopper);
|
|
102859
|
+
test['details'] = {}; // TODO - Any details?
|
|
102860
|
+
|
|
102861
|
+
return test;
|
|
102715
102862
|
}
|
|
102716
|
-
|
|
102863
|
+
*/
|
|
102717
102864
|
// HELPER TO EXTRACT PROPERTIES OF DISTRICT SHAPES
|
|
102718
102865
|
// TODO - SCORE: Create an array, as opposed to a dict
|
|
102719
102866
|
function extractDistrictProperties(s, bLog = false) {
|
|
@@ -102791,41 +102938,53 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
102791
102938
|
return result;
|
|
102792
102939
|
};
|
|
102793
102940
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102794
|
-
const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
|
|
102795
102941
|
const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
102796
|
-
|
|
102797
|
-
function doPopulationDeviation(s, bLog = false)
|
|
102798
|
-
|
|
102799
|
-
|
|
102800
|
-
|
|
102801
|
-
|
|
102802
|
-
|
|
102803
|
-
|
|
102804
|
-
|
|
102805
|
-
|
|
102806
|
-
|
|
102807
|
-
|
|
102808
|
-
|
|
102809
|
-
|
|
102810
|
-
|
|
102811
|
-
|
|
102812
|
-
|
|
102813
|
-
|
|
102814
|
-
|
|
102815
|
-
|
|
102816
|
-
|
|
102817
|
-
|
|
102818
|
-
|
|
102819
|
-
|
|
102820
|
-
|
|
102821
|
-
|
|
102822
|
-
|
|
102823
|
-
|
|
102824
|
-
|
|
102825
|
-
|
|
102826
|
-
|
|
102942
|
+
/* TODO - DELETE
|
|
102943
|
+
export function doPopulationDeviation(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
102944
|
+
{
|
|
102945
|
+
let test = s.getTest(T.Test.PopulationDeviation) as T.TestEntry;
|
|
102946
|
+
|
|
102947
|
+
let targetSize = s.state.totalPop / s.state.nDistricts;
|
|
102948
|
+
|
|
102949
|
+
// Compute the min & max district populations
|
|
102950
|
+
// ... excluding the dummy the 'unassigned' 0 and N+1 summary "districts"
|
|
102951
|
+
let totPopByDistrict = s.districts.statistics[D.DistrictField.TotalPop];
|
|
102952
|
+
totPopByDistrict = totPopByDistrict.slice(1, -1);
|
|
102953
|
+
|
|
102954
|
+
// Remove empty districts
|
|
102955
|
+
totPopByDistrict = totPopByDistrict.filter(x => x > 0);
|
|
102956
|
+
|
|
102957
|
+
let min = 0;
|
|
102958
|
+
let max = 0;
|
|
102959
|
+
|
|
102960
|
+
// If there's more than 1 non-empty district, calculate a non-zero deviation
|
|
102961
|
+
if (totPopByDistrict.length > 1)
|
|
102962
|
+
{
|
|
102963
|
+
min = U.minArray(totPopByDistrict);
|
|
102964
|
+
max = U.maxArray(totPopByDistrict);
|
|
102965
|
+
}
|
|
102966
|
+
|
|
102967
|
+
// Calculate the raw population deviation
|
|
102968
|
+
let popDev = (max - min) / targetSize;
|
|
102969
|
+
|
|
102970
|
+
// Round the raw value to the desired level of precision
|
|
102971
|
+
popDev = U.trim(popDev);
|
|
102972
|
+
|
|
102973
|
+
// Populate the test entry
|
|
102974
|
+
test['score'] = popDev;
|
|
102975
|
+
test['details'] = { 'maxDeviation': max - min };
|
|
102976
|
+
|
|
102977
|
+
// Populate the N+1 summary "district" in district.statistics
|
|
102978
|
+
let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
|
|
102979
|
+
let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
|
|
102980
|
+
let summaryRow = s.districts.numberOfRows() - 1;
|
|
102981
|
+
|
|
102982
|
+
totalPop[summaryRow] = targetSize;
|
|
102983
|
+
popDevPct[summaryRow] = popDev;
|
|
102984
|
+
|
|
102985
|
+
return test;
|
|
102827
102986
|
}
|
|
102828
|
-
|
|
102987
|
+
*/
|
|
102829
102988
|
// NOTE - This validity check is *derived* and depends on population deviation %
|
|
102830
102989
|
// being computed (above) and normalized in test log & scorecard generation.
|
|
102831
102990
|
function doHasEqualPopulations(s, bLog = false) {
|
|
@@ -102875,7 +103034,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
102875
103034
|
};
|
|
102876
103035
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
102877
103036
|
const Poly = __importStar(__webpack_require__(/*! @dra2020/poly */ "./node_modules/@dra2020/poly/dist/poly.js"));
|
|
102878
|
-
// TODO - SCORE: Remove legacy code
|
|
102879
103037
|
// HELPER
|
|
102880
103038
|
function polyParts(poly) {
|
|
102881
103039
|
let parts = { type: 'FeatureCollection', features: [] };
|
|
@@ -102990,35 +103148,6 @@ function gfDiameter(poly) {
|
|
|
102990
103148
|
exports.gfDiameter = gfDiameter;
|
|
102991
103149
|
|
|
102992
103150
|
|
|
102993
|
-
/***/ }),
|
|
102994
|
-
|
|
102995
|
-
/***/ "./src/minority.ts":
|
|
102996
|
-
/*!*************************!*\
|
|
102997
|
-
!*** ./src/minority.ts ***!
|
|
102998
|
-
\*************************/
|
|
102999
|
-
/*! no static exports found */
|
|
103000
|
-
/***/ (function(module, exports, __webpack_require__) {
|
|
103001
|
-
|
|
103002
|
-
"use strict";
|
|
103003
|
-
|
|
103004
|
-
//
|
|
103005
|
-
// PROTECTS MINORITIES
|
|
103006
|
-
//
|
|
103007
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
103008
|
-
// TODO - SCORE: Remove legacy code
|
|
103009
|
-
function doMajorityMinorityDistricts(s, bLog = false) {
|
|
103010
|
-
let test = s.getTest(16 /* MajorityMinorityDistricts */);
|
|
103011
|
-
if (bLog)
|
|
103012
|
-
console.log("TODO - Calculating # of majority-minority districts ...");
|
|
103013
|
-
return test;
|
|
103014
|
-
}
|
|
103015
|
-
exports.doMajorityMinorityDistricts = doMajorityMinorityDistricts;
|
|
103016
|
-
// Sources for majority-minority info:
|
|
103017
|
-
// - https://en.wikipedia.org/wiki/List_of_majority-minority_United_States_congressional_districts
|
|
103018
|
-
// TODO - 2020: Update/revise this, when the update comes out in September:
|
|
103019
|
-
// - http://www.ncsl.org/Portals/1/Documents/Redistricting/Redistricting_2010.pdf
|
|
103020
|
-
|
|
103021
|
-
|
|
103022
103151
|
/***/ }),
|
|
103023
103152
|
|
|
103024
103153
|
/***/ "./src/political.ts":
|
|
@@ -103033,18 +103162,14 @@ exports.doMajorityMinorityDistricts = doMajorityMinorityDistricts;
|
|
|
103033
103162
|
//
|
|
103034
103163
|
// FAIR/PROPORTIONAL
|
|
103035
103164
|
//
|
|
103036
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
103037
|
-
if (mod && mod.__esModule) return mod;
|
|
103038
|
-
var result = {};
|
|
103039
|
-
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
|
103040
|
-
result["default"] = mod;
|
|
103041
|
-
return result;
|
|
103042
|
-
};
|
|
103043
103165
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
103166
|
+
// NOTE - This file will NOT be empty, when legacy code is deleted.
|
|
103044
103167
|
const assert_1 = __webpack_require__(/*! assert */ "assert");
|
|
103045
|
-
|
|
103046
|
-
|
|
103047
|
-
|
|
103168
|
+
/* TODO - DELETE
|
|
103169
|
+
import * as D from './_data'
|
|
103170
|
+
import { AnalyticsSession } from './_api';
|
|
103171
|
+
|
|
103172
|
+
|
|
103048
103173
|
// Partisan analytics need the following data:
|
|
103049
103174
|
//
|
|
103050
103175
|
// An "election model" by geo_id, where each item has 4 pieces of data:
|
|
@@ -103063,66 +103188,89 @@ const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
|
|
|
103063
103188
|
//
|
|
103064
103189
|
// I'm labelling this general concept a "Voter Preference Index (VPI)," a
|
|
103065
103190
|
// conscious +1 letter play on Cook's "PVI" acronymn.
|
|
103191
|
+
|
|
103192
|
+
|
|
103066
103193
|
// MEASURING BIAS & RESPONSIVENESS (NAGLE'S METHOD)
|
|
103067
|
-
|
|
103068
|
-
|
|
103069
|
-
|
|
103070
|
-
|
|
103071
|
-
|
|
103194
|
+
|
|
103195
|
+
export function doSeatsBias(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103196
|
+
{
|
|
103197
|
+
let test = s.getTest(T.Test.SeatsBias) as T.TestEntry;
|
|
103198
|
+
|
|
103199
|
+
if (bLog) console.log("TODO - Calculating seats bias ...");
|
|
103200
|
+
|
|
103201
|
+
return test;
|
|
103072
103202
|
}
|
|
103073
|
-
|
|
103074
|
-
function doVotesBias(s, bLog = false)
|
|
103075
|
-
|
|
103076
|
-
|
|
103077
|
-
|
|
103078
|
-
|
|
103203
|
+
|
|
103204
|
+
export function doVotesBias(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103205
|
+
{
|
|
103206
|
+
let test = s.getTest(T.Test.VotesBias) as T.TestEntry;
|
|
103207
|
+
|
|
103208
|
+
if (bLog) console.log("TODO - Calculating votes bias ...");
|
|
103209
|
+
|
|
103210
|
+
return test;
|
|
103079
103211
|
}
|
|
103080
|
-
|
|
103081
|
-
function doResponsiveness(s, bLog = false)
|
|
103082
|
-
|
|
103083
|
-
|
|
103084
|
-
|
|
103085
|
-
|
|
103212
|
+
|
|
103213
|
+
export function doResponsiveness(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103214
|
+
{
|
|
103215
|
+
let test = s.getTest(T.Test.Responsiveness) as T.TestEntry;
|
|
103216
|
+
|
|
103217
|
+
if (bLog) console.log("TODO - Calculating responsiveness ...");
|
|
103218
|
+
|
|
103219
|
+
return test;
|
|
103086
103220
|
}
|
|
103087
|
-
|
|
103088
|
-
function doResponsiveDistricts(s, bLog = false)
|
|
103089
|
-
|
|
103090
|
-
|
|
103091
|
-
|
|
103092
|
-
|
|
103221
|
+
|
|
103222
|
+
export function doResponsiveDistricts(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103223
|
+
{
|
|
103224
|
+
let test = s.getTest(T.Test.ResponsiveDistricts) as T.TestEntry;
|
|
103225
|
+
|
|
103226
|
+
if (bLog) console.log("TODO - Calculating # of responsive districts ...");
|
|
103227
|
+
|
|
103228
|
+
return test;
|
|
103093
103229
|
}
|
|
103094
|
-
|
|
103230
|
+
|
|
103231
|
+
|
|
103095
103232
|
// OTHER MEASURES OF PARTISAN BIAS
|
|
103233
|
+
|
|
103096
103234
|
// TODO - PARTISAN: This formula might need to be inverted for D vs. R +/-
|
|
103097
103235
|
// TODO - Normalize the results.
|
|
103098
|
-
function doEfficiencyGap(s, bLog = false)
|
|
103099
|
-
|
|
103100
|
-
|
|
103101
|
-
|
|
103102
|
-
|
|
103103
|
-
|
|
103104
|
-
|
|
103105
|
-
|
|
103106
|
-
|
|
103107
|
-
|
|
103108
|
-
|
|
103109
|
-
|
|
103110
|
-
|
|
103111
|
-
|
|
103112
|
-
|
|
103113
|
-
|
|
103114
|
-
|
|
103115
|
-
|
|
103116
|
-
|
|
103117
|
-
|
|
103118
|
-
|
|
103119
|
-
|
|
103120
|
-
|
|
103121
|
-
|
|
103122
|
-
|
|
103236
|
+
export function doEfficiencyGap(s: AnalyticsSession, bLog: boolean = false): T.TestEntry
|
|
103237
|
+
{
|
|
103238
|
+
if (bLog) console.log("TODO - Calculating the efficiency gap ...");
|
|
103239
|
+
|
|
103240
|
+
let test = s.getTest(T.Test.EfficiencyGap) as T.TestEntry;
|
|
103241
|
+
|
|
103242
|
+
// Get partisan statistics by districts.
|
|
103243
|
+
// Use Democratic votes, seats, and shares by convention.
|
|
103244
|
+
let DVotes = s.districts.statistics[D.DistrictField.DemVotes];
|
|
103245
|
+
let DSeats = s.districts.statistics[D.DistrictField.DemSeat];
|
|
103246
|
+
let TPVotes = s.districts.statistics[D.DistrictField.TwoPartyVote];
|
|
103247
|
+
|
|
103248
|
+
// Exclude the dummy unassigned '0' and N+1 summary "districts"
|
|
103249
|
+
DVotes = DVotes.slice(1, -1);
|
|
103250
|
+
DSeats = DSeats.slice(1, -1);
|
|
103251
|
+
TPVotes = TPVotes.slice(1, -1);
|
|
103252
|
+
|
|
103253
|
+
// Calculate D vote share & D seat share
|
|
103254
|
+
let DVoteShare = U.sumArray(DVotes) / U.sumArray(TPVotes);
|
|
103255
|
+
let DSeatShare = U.sumArray(DSeats) / s.state.nDistricts;
|
|
103256
|
+
|
|
103257
|
+
// Finally, calculate the Efficiency Gap
|
|
103258
|
+
let efficiencyGap = (DSeatShare - 0.5) - (2.0 * (DVoteShare - 0.5));
|
|
103259
|
+
|
|
103260
|
+
// Round the raw value to the desired level of precision
|
|
103261
|
+
efficiencyGap = U.trim(efficiencyGap);
|
|
103262
|
+
|
|
103263
|
+
// Populate the test entry
|
|
103264
|
+
test['score'] = efficiencyGap;
|
|
103265
|
+
// test['normalizedScore'] = 0; // TODO - Normalize the raw score
|
|
103266
|
+
test['details'] = {}; // TODO - Add details, if any
|
|
103267
|
+
|
|
103268
|
+
return test;
|
|
103123
103269
|
}
|
|
103124
|
-
|
|
103270
|
+
|
|
103271
|
+
|
|
103125
103272
|
// HELPERS
|
|
103273
|
+
*/
|
|
103126
103274
|
function fptpWin(demPct) {
|
|
103127
103275
|
// Vote shares should be fractions in the range [0.0 – 1.0]
|
|
103128
103276
|
assert_1.strict((demPct <= 1.0) && (demPct >= 0.));
|
|
@@ -103728,24 +103876,26 @@ const populationDeviationDefn = {
|
|
|
103728
103876
|
externalType: TestType.Percentage,
|
|
103729
103877
|
suites: [0 /* Legal */, 2 /* Best */] // Both so EqualPopulation can be assessed
|
|
103730
103878
|
};
|
|
103731
|
-
|
|
103732
|
-
const reockDefn = {
|
|
103733
|
-
|
|
103734
|
-
|
|
103735
|
-
|
|
103736
|
-
|
|
103737
|
-
|
|
103879
|
+
/* TODO - DELETE
|
|
103880
|
+
const reockDefn: T.Dict = {
|
|
103881
|
+
ID: T.Test.Reock,
|
|
103882
|
+
name: "Reock",
|
|
103883
|
+
normalize: true,
|
|
103884
|
+
externalType: TestType.Number,
|
|
103885
|
+
suites: [T.Suite.Best]
|
|
103738
103886
|
};
|
|
103739
|
-
|
|
103740
|
-
|
|
103741
|
-
|
|
103742
|
-
|
|
103743
|
-
|
|
103744
|
-
|
|
103887
|
+
|
|
103888
|
+
const polsbyPopperDefn: T.Dict = {
|
|
103889
|
+
ID: T.Test.PolsbyPopper,
|
|
103890
|
+
name: "Polsby-Popper",
|
|
103891
|
+
normalize: true,
|
|
103892
|
+
externalType: TestType.Number,
|
|
103893
|
+
suites: [T.Suite.Best]
|
|
103745
103894
|
};
|
|
103895
|
+
*/
|
|
103746
103896
|
// NOTE - SPLITTING
|
|
103747
103897
|
const unexpectedCountySplitsDefn = {
|
|
103748
|
-
ID:
|
|
103898
|
+
ID: 5 /* UnexpectedCountySplits */,
|
|
103749
103899
|
name: "Unexpected County Splits",
|
|
103750
103900
|
normalize: false,
|
|
103751
103901
|
externalType: TestType.Percentage,
|
|
@@ -103753,35 +103903,12 @@ const unexpectedCountySplitsDefn = {
|
|
|
103753
103903
|
};
|
|
103754
103904
|
// NOTE - SPLITTING
|
|
103755
103905
|
const VTDSplitsDefn = {
|
|
103756
|
-
ID:
|
|
103906
|
+
ID: 6 /* VTDSplits */,
|
|
103757
103907
|
name: "VTD Splits",
|
|
103758
103908
|
normalize: false,
|
|
103759
103909
|
externalType: TestType.Number,
|
|
103760
103910
|
suites: [2 /* Best */]
|
|
103761
103911
|
};
|
|
103762
|
-
// NOTE - SPLITTING
|
|
103763
|
-
const countySplittingDefn = {
|
|
103764
|
-
ID: 8 /* CountySplitting */,
|
|
103765
|
-
name: "County Splitting",
|
|
103766
|
-
normalize: true,
|
|
103767
|
-
externalType: TestType.Number,
|
|
103768
|
-
suites: [2 /* Best */]
|
|
103769
|
-
};
|
|
103770
|
-
// NOTE - SPLITTING
|
|
103771
|
-
const districtSplittingDefn = {
|
|
103772
|
-
ID: 9 /* DistrictSplitting */,
|
|
103773
|
-
name: "District Splitting",
|
|
103774
|
-
normalize: true,
|
|
103775
|
-
externalType: TestType.Number,
|
|
103776
|
-
suites: [2 /* Best */]
|
|
103777
|
-
};
|
|
103778
|
-
const efficiencyGapDefn = {
|
|
103779
|
-
ID: 15 /* EfficiencyGap */,
|
|
103780
|
-
name: "Efficiency Gap",
|
|
103781
|
-
normalize: false,
|
|
103782
|
-
externalType: TestType.Percentage,
|
|
103783
|
-
suites: [1 /* Fair */]
|
|
103784
|
-
};
|
|
103785
103912
|
// All the tests that have been defined (can be reported on)
|
|
103786
103913
|
const testDefns = {
|
|
103787
103914
|
[0 /* Complete */]: completeDefn,
|
|
@@ -103789,94 +103916,103 @@ const testDefns = {
|
|
|
103789
103916
|
[2 /* FreeOfHoles */]: freeOfHolesDefn,
|
|
103790
103917
|
[3 /* EqualPopulation */]: equalPopulationDefn,
|
|
103791
103918
|
[4 /* PopulationDeviation */]: populationDeviationDefn,
|
|
103792
|
-
[
|
|
103793
|
-
[
|
|
103794
|
-
|
|
103795
|
-
[
|
|
103796
|
-
[10 /* VTDSplits */]: VTDSplitsDefn,
|
|
103797
|
-
[8 /* CountySplitting */]: countySplittingDefn,
|
|
103798
|
-
[9 /* DistrictSplitting */]: districtSplittingDefn,
|
|
103799
|
-
// TODO - More tests ...
|
|
103800
|
-
[15 /* EfficiencyGap */]: efficiencyGapDefn
|
|
103919
|
+
// [T.Test.Reock]: reockDefn, TODO - DELETE
|
|
103920
|
+
// [T.Test.PolsbyPopper]: polsbyPopperDefn, TODO - DELETE
|
|
103921
|
+
[5 /* UnexpectedCountySplits */]: unexpectedCountySplitsDefn,
|
|
103922
|
+
[6 /* VTDSplits */]: VTDSplitsDefn,
|
|
103801
103923
|
};
|
|
103924
|
+
/* TODO - DELETE
|
|
103802
103925
|
// NORMALIZE RAW ANALYTICS
|
|
103803
103926
|
// Raw numeric analytics, such as population deviation, compactness, etc. are
|
|
103804
103927
|
// normalized as part of creating a scorecard, so the code to normalize results
|
|
103805
103928
|
// is encapsulated here.
|
|
103929
|
+
|
|
103806
103930
|
// Configure scale parameters for normalizing each raw test result.
|
|
103807
103931
|
// Scales consist of a minimum & a maximum *raw* value. If the values get
|
|
103808
103932
|
// inverted (to make bigger better), these will switch.
|
|
103809
103933
|
// This process needs to be separate from the test configuration info above,
|
|
103810
103934
|
// because some scales need access to the analytics session object.
|
|
103811
|
-
function doConfigureScales(s)
|
|
103812
|
-
|
|
103813
|
-
|
|
103814
|
-
|
|
103815
|
-
|
|
103816
|
-
|
|
103817
|
-
|
|
103818
|
-
|
|
103819
|
-
|
|
103820
|
-
|
|
103821
|
-
|
|
103822
|
-
|
|
103823
|
-
|
|
103824
|
-
|
|
103825
|
-
|
|
103826
|
-
|
|
103827
|
-
|
|
103828
|
-
|
|
103829
|
-
|
|
103830
|
-
|
|
103831
|
-
|
|
103832
|
-
|
|
103833
|
-
|
|
103834
|
-
|
|
103835
|
-
|
|
103836
|
-
|
|
103935
|
+
export function doConfigureScales(s: AnalyticsSession): void
|
|
103936
|
+
{
|
|
103937
|
+
// Scale defn for PopulationDeviation
|
|
103938
|
+
const CDLimit = 0.75 / 100; // Deviation threshold for CD's
|
|
103939
|
+
const LDLimit = 10.00 / 100; // Deviation threshold for LD's
|
|
103940
|
+
|
|
103941
|
+
const CDGoodEnough = 0.20 / 100;
|
|
103942
|
+
const LDGoodEnough = (CDGoodEnough / CDLimit) * LDLimit;
|
|
103943
|
+
const popDevScale = (s.legislativeDistricts) ? [1.0 - LDLimit, 1.0 - LDGoodEnough] : [1.0 - CDLimit, 1.0 - CDGoodEnough];
|
|
103944
|
+
// const scale = [1.0 - CDLimit, 1.0 - CDGoodEnough];
|
|
103945
|
+
|
|
103946
|
+
s.testScales[T.Test.PopulationDeviation] = { scale: popDevScale, bInvertRaw: true };
|
|
103947
|
+
|
|
103948
|
+
s.testScales[T.Test.Reock] = { scale: [0.25, 0.50] };
|
|
103949
|
+
s.testScales[T.Test.PolsbyPopper] = { scale: [0.10, 0.50] };
|
|
103950
|
+
|
|
103951
|
+
const nDistricts = s.state.nDistricts;
|
|
103952
|
+
const nCounties = s.counties.nCounties;
|
|
103953
|
+
|
|
103954
|
+
// NOTE - SPLITTING: Experiment w/ this multiplier. Only allowing the expected
|
|
103955
|
+
// number of county splits seems too stringent, empirically.
|
|
103956
|
+
const allowableCountySplitsMultiplier = 1.5;
|
|
103957
|
+
const nAllowableSplits = Math.min(allowableCountySplitsMultiplier * (nDistricts - 1));
|
|
103958
|
+
const countySplittingThreshold = ((nAllowableSplits * 1.71) + ((nCounties - nAllowableSplits) * 1.0)) / nCounties;
|
|
103959
|
+
const countySplittingScale = [1.0, countySplittingThreshold];
|
|
103960
|
+
s.testScales[T.Test.CountySplitting] = { scale: countySplittingScale, bInvertScaled: true };
|
|
103961
|
+
|
|
103962
|
+
const districtSplittingThreshold = 1.5;
|
|
103963
|
+
const districtSplittingScale = [1.0, districtSplittingThreshold];
|
|
103964
|
+
s.testScales[T.Test.DistrictSplitting] = { scale: districtSplittingScale, bInvertScaled: true };
|
|
103965
|
+
|
|
103966
|
+
// TODO - More analytics ...
|
|
103967
|
+
}
|
|
103968
|
+
*/
|
|
103837
103969
|
// Postprocess analytics - Normalize numeric results and derive secondary tests.
|
|
103838
103970
|
// Do this after analytics have been run and before preparing a test log or scorecard.
|
|
103839
103971
|
function doAnalyzePostProcessing(s, bLog = false) {
|
|
103840
|
-
// TODO -
|
|
103841
|
-
if (s.useLegacy())
|
|
103842
|
-
|
|
103843
|
-
|
|
103844
|
-
|
|
103845
|
-
|
|
103846
|
-
|
|
103847
|
-
|
|
103848
|
-
|
|
103849
|
-
|
|
103850
|
-
|
|
103851
|
-
|
|
103852
|
-
|
|
103853
|
-
|
|
103854
|
-
|
|
103855
|
-
|
|
103856
|
-
|
|
103857
|
-
|
|
103858
|
-
|
|
103859
|
-
|
|
103860
|
-
|
|
103861
|
-
|
|
103862
|
-
|
|
103863
|
-
|
|
103864
|
-
|
|
103865
|
-
|
|
103866
|
-
|
|
103867
|
-
|
|
103868
|
-
|
|
103869
|
-
|
|
103870
|
-
|
|
103871
|
-
|
|
103872
|
-
|
|
103873
|
-
|
|
103874
|
-
|
|
103875
|
-
|
|
103876
|
-
|
|
103877
|
-
|
|
103878
|
-
|
|
103879
|
-
|
|
103972
|
+
// TODO - DELETE
|
|
103973
|
+
// if (s.useLegacy())
|
|
103974
|
+
// {
|
|
103975
|
+
// // Normalize the raw scores for all the numerics tests
|
|
103976
|
+
// let testResults = U.getNumericObjectKeys(testDefns);
|
|
103977
|
+
// for (let testID of testResults)
|
|
103978
|
+
// {
|
|
103979
|
+
// if (testDefns[testID]['normalize'])
|
|
103980
|
+
// {
|
|
103981
|
+
// let testResult = s.getTest(testID) as T.TestEntry;
|
|
103982
|
+
// let rawScore = testResult['score'] as number;
|
|
103983
|
+
// let normalizedScore: number;
|
|
103984
|
+
// normalizedScore = U.normalize(rawScore, s.testScales[testID]);
|
|
103985
|
+
// testResult['normalizedScore'] = normalizedScore;
|
|
103986
|
+
// // Add the scale used to normalize the raw score to the details
|
|
103987
|
+
// testResult['details']['scale'] = s.testScales[testID].scale;
|
|
103988
|
+
// }
|
|
103989
|
+
// }
|
|
103990
|
+
// }
|
|
103991
|
+
// else
|
|
103992
|
+
// {
|
|
103993
|
+
// Just populate the normalized population deviation score in the test
|
|
103994
|
+
const scorecard = s._scorecard;
|
|
103995
|
+
let popDev = s.getTest(4 /* PopulationDeviation */);
|
|
103996
|
+
popDev['normalizedScore'] = scorecard.traditionalPrinciples.populationDeviation.normalized;
|
|
103997
|
+
// TODO - DELETE
|
|
103998
|
+
// test['normalizedScore'] = scorecard.best.populationDeviation.normalized;
|
|
103999
|
+
// TODO - SCORE: Add datasets used to details by tab
|
|
104000
|
+
const datasets = {
|
|
104001
|
+
shapes: S.SHAPES,
|
|
104002
|
+
census: U.deepCopy(s.config['descriptions']['CENSUS']),
|
|
104003
|
+
vap: U.deepCopy(s.config['descriptions']['VAP']),
|
|
104004
|
+
election: U.deepCopy(s.config['descriptions']['ELECTION'])
|
|
104005
|
+
};
|
|
104006
|
+
scorecard.partisan.details['election'] = datasets.election;
|
|
104007
|
+
scorecard.minority.details['vap'] = datasets.vap;
|
|
104008
|
+
scorecard.traditionalPrinciples.details['shapes'] = datasets.shapes;
|
|
104009
|
+
scorecard.traditionalPrinciples.details['census'] = datasets.census;
|
|
104010
|
+
// TODO - SCORE: Add legacy splits details
|
|
104011
|
+
const simpleSplits = s.getTest(5 /* UnexpectedCountySplits */);
|
|
104012
|
+
scorecard.traditionalPrinciples.details['unexpectedAffected'] = simpleSplits['score'];
|
|
104013
|
+
scorecard.traditionalPrinciples.details['countiesSplitUnexpectedly'] = U.deepCopy(simpleSplits['details']['countiesSplitUnexpectedly']);
|
|
104014
|
+
// NOTE - Add split precincts in dra-client directly
|
|
104015
|
+
// }
|
|
103880
104016
|
// Derive secondary tests
|
|
103881
104017
|
analyze_1.doDeriveSecondaryTests(s, bLog);
|
|
103882
104018
|
// Toggle the semaphore, so postprocessing isn't for both the testlog & scorecard
|
|
@@ -104616,11 +104752,6 @@ w/in VS Code:
|
|
|
104616
104752
|
* api-analyze (analyze) - Analyzes a plan and logs the results.
|
|
104617
104753
|
|
|
104618
104754
|
* unit-valid (valid) - Exercises the validations.
|
|
104619
|
-
* unit-equal (equal) - Exercises the population deviation analytic.
|
|
104620
|
-
* unit-compact (compact) - Exercises the compactness analytics.
|
|
104621
|
-
* unit-cohesive (cohesive) - Exercises the splitting analytics.
|
|
104622
|
-
* unit-political (political) - Exercises the partisan analytics.
|
|
104623
|
-
* unit-minority (minority) - Exercises the minority analytics.
|
|
104624
104755
|
|
|
104625
104756
|
* invalid-unassigned (valid) - Tests a plan w/ unassigned features.
|
|
104626
104757
|
* invalid-missing (valid) - Tests a plan w/ a missing district.
|
|
@@ -104671,13 +104802,10 @@ const analyze_1 = __webpack_require__(/*! ../src/analyze */ "./src/analyze.ts");
|
|
|
104671
104802
|
const results_1 = __webpack_require__(/*! ../src/results */ "./src/results.ts");
|
|
104672
104803
|
const valid_1 = __webpack_require__(/*! ../src/valid */ "./src/valid.ts");
|
|
104673
104804
|
const equal_1 = __webpack_require__(/*! ../src/equal */ "./src/equal.ts");
|
|
104674
|
-
const compact_1 = __webpack_require__(/*! ../src/compact */ "./src/compact.ts");
|
|
104675
|
-
const cohesive_1 = __webpack_require__(/*! ../src/cohesive */ "./src/cohesive.ts");
|
|
104676
|
-
const political_1 = __webpack_require__(/*! ../src/political */ "./src/political.ts");
|
|
104677
|
-
const minority_1 = __webpack_require__(/*! ../src/minority */ "./src/minority.ts");
|
|
104678
104805
|
const U = __importStar(__webpack_require__(/*! ../src/utils */ "./src/utils.ts"));
|
|
104679
104806
|
const S = __importStar(__webpack_require__(/*! ../src/settings */ "./src/settings.ts"));
|
|
104680
104807
|
const D = __importStar(__webpack_require__(/*! ../src/_data */ "./src/_data.ts"));
|
|
104808
|
+
// import { DistrictRow } from '../src/results'; TODO - DELETE
|
|
104681
104809
|
// Simulate DRA unioning district shapes in the background
|
|
104682
104810
|
function addToPoly(poly, polys) {
|
|
104683
104811
|
// TODO - POLY: Fix 'poly' import, so I don't have to do this workaround.
|
|
@@ -104694,15 +104822,19 @@ let argv = yargs_1.default
|
|
|
104694
104822
|
.example('$0 equal -f foo.geojson', 'Calculate population deviation')
|
|
104695
104823
|
.demandCommand(1, 'You must specify a command to execute.')
|
|
104696
104824
|
.command('valid', 'Perform validations.')
|
|
104825
|
+
/* TODO - DELETE
|
|
104697
104826
|
.command('equal', 'Calculate population deviation.')
|
|
104698
104827
|
.command('compact', 'Calculate compactness.')
|
|
104699
104828
|
.command('cohesive', 'Calculate cohesiveness.')
|
|
104700
104829
|
.command('political', 'Assess fairness.')
|
|
104701
104830
|
.command('minority', 'Count majority-minority districts.')
|
|
104831
|
+
*/
|
|
104702
104832
|
.command('analyze', 'API call to analyze a plan.')
|
|
104833
|
+
/* TODO - DELETE
|
|
104703
104834
|
.command('scorecard', 'Analyze plan & generate a scorecard.')
|
|
104704
104835
|
.command('testlog', 'Analyze plan & generate a testlog.')
|
|
104705
104836
|
.command('report', 'API call to generate a scorecard.')
|
|
104837
|
+
*/
|
|
104706
104838
|
.option('state', {
|
|
104707
104839
|
alias: 'x',
|
|
104708
104840
|
describe: 'Specify the state.',
|
|
@@ -104801,7 +104933,7 @@ let bLog = argv.verbose;
|
|
|
104801
104933
|
// NOTE - The plan here is complete (all features assigned).
|
|
104802
104934
|
let planByDistrictID = D.invertPlan(planByGeoID);
|
|
104803
104935
|
// SIMULATE THE HOST
|
|
104804
|
-
//
|
|
104936
|
+
// Create district shapes & extract properties (area, diameter, perimeter)
|
|
104805
104937
|
const polyOptions = {
|
|
104806
104938
|
noLatitudeCorrection: false
|
|
104807
104939
|
};
|
|
@@ -104919,73 +105051,93 @@ switch (command) {
|
|
|
104919
105051
|
let t1 = valid_1.doIsComplete(s);
|
|
104920
105052
|
let t2 = valid_1.doIsContiguous(s);
|
|
104921
105053
|
let t3 = valid_1.doIsFreeOfHoles(s);
|
|
104922
|
-
let t4 =
|
|
105054
|
+
// let t4 = doPopulationDeviation(s); TODO - DELETE
|
|
104923
105055
|
let t5 = equal_1.doHasEqualPopulations(s);
|
|
104924
105056
|
results_1.doAnalyzePostProcessing(s);
|
|
104925
105057
|
echoTestResult("Complete:", t1);
|
|
104926
105058
|
echoTestResult("Contiguous:", t2);
|
|
104927
105059
|
echoTestResult("Free of holes:", t3);
|
|
104928
|
-
echoTestResult("Population deviation (%):", t4);
|
|
105060
|
+
// echoTestResult("Population deviation (%):", t4); TODO - DELETE
|
|
104929
105061
|
echoTestResult("Equal populations:", t5);
|
|
104930
105062
|
break;
|
|
104931
105063
|
}
|
|
105064
|
+
/* TODO - DELETE: Code moved to dra-score
|
|
104932
105065
|
case 'equal': {
|
|
104933
|
-
|
|
104934
|
-
|
|
104935
|
-
|
|
104936
|
-
|
|
104937
|
-
|
|
104938
|
-
|
|
105066
|
+
doPreprocessData(s);
|
|
105067
|
+
doAnalyzeDistricts(s);
|
|
105068
|
+
|
|
105069
|
+
t = doPopulationDeviation(s);
|
|
105070
|
+
echoTestResult("Population deviation (%):", t);
|
|
105071
|
+
|
|
105072
|
+
doAnalyzePostProcessing(s);
|
|
105073
|
+
break;
|
|
104939
105074
|
}
|
|
104940
105075
|
case 'compact': {
|
|
104941
|
-
|
|
104942
|
-
|
|
104943
|
-
|
|
104944
|
-
|
|
104945
|
-
|
|
104946
|
-
|
|
104947
|
-
|
|
104948
|
-
|
|
105076
|
+
doPreprocessData(s);
|
|
105077
|
+
doAnalyzeDistricts(s);
|
|
105078
|
+
|
|
105079
|
+
let t1 = doReock(s, bLog);
|
|
105080
|
+
let t2 = doPolsbyPopper(s, bLog);
|
|
105081
|
+
|
|
105082
|
+
doAnalyzePostProcessing(s);
|
|
105083
|
+
|
|
105084
|
+
echoTestResult("Reock:", t1);
|
|
105085
|
+
echoTestResult("Polsby-Popper:", t2);
|
|
105086
|
+
|
|
105087
|
+
break;
|
|
104949
105088
|
}
|
|
104950
105089
|
case 'cohesive': {
|
|
104951
|
-
|
|
104952
|
-
|
|
104953
|
-
|
|
104954
|
-
|
|
104955
|
-
|
|
104956
|
-
|
|
104957
|
-
|
|
104958
|
-
|
|
104959
|
-
|
|
104960
|
-
|
|
104961
|
-
|
|
104962
|
-
|
|
104963
|
-
|
|
105090
|
+
doPreprocessData(s);
|
|
105091
|
+
doAnalyzeDistricts(s);
|
|
105092
|
+
|
|
105093
|
+
// NOTE - SPLITTING
|
|
105094
|
+
let t1 = doFindCountiesSplitUnexpectedly(s);
|
|
105095
|
+
let t2 = doFindSplitVTDs(s);
|
|
105096
|
+
let t3 = doCountySplitting(s);
|
|
105097
|
+
let t4 = doDistrictSplitting(s);
|
|
105098
|
+
|
|
105099
|
+
doAnalyzePostProcessing(s);
|
|
105100
|
+
|
|
105101
|
+
echoTestResult("Counties split unexpectedly:", t1);
|
|
105102
|
+
echoTestResult("Split VTDs:", t2);
|
|
105103
|
+
echoTestResult("County splitting:", t3);
|
|
105104
|
+
echoTestResult("District splitting:", t4);
|
|
105105
|
+
|
|
105106
|
+
break;
|
|
104964
105107
|
}
|
|
104965
105108
|
case 'political': {
|
|
104966
|
-
|
|
104967
|
-
|
|
104968
|
-
|
|
104969
|
-
|
|
104970
|
-
|
|
104971
|
-
|
|
104972
|
-
|
|
104973
|
-
|
|
104974
|
-
|
|
104975
|
-
|
|
104976
|
-
|
|
104977
|
-
|
|
104978
|
-
|
|
104979
|
-
|
|
105109
|
+
doPreprocessData(s);
|
|
105110
|
+
doAnalyzeDistricts(s);
|
|
105111
|
+
|
|
105112
|
+
let t1 = doSeatsBias(s);
|
|
105113
|
+
let t2 = doVotesBias(s);
|
|
105114
|
+
let t3 = doResponsiveness(s);
|
|
105115
|
+
let t4 = doResponsiveDistricts(s);
|
|
105116
|
+
let t5 = doEfficiencyGap(s);
|
|
105117
|
+
|
|
105118
|
+
doAnalyzePostProcessing(s);
|
|
105119
|
+
|
|
105120
|
+
// echoTestResult("Seats Bias:", t1); TODO
|
|
105121
|
+
// echoTestResult("Votes Bias:", t2); TODO
|
|
105122
|
+
// echoTestResult("Responsiveness:", t3); TODO
|
|
105123
|
+
// echoTestResult("Responsive Districts:", t4); TODO
|
|
105124
|
+
echoTestResult("Efficiency gap (%):", t5);
|
|
105125
|
+
|
|
105126
|
+
break;
|
|
104980
105127
|
}
|
|
104981
105128
|
case 'minority': {
|
|
104982
|
-
|
|
104983
|
-
|
|
104984
|
-
|
|
104985
|
-
|
|
104986
|
-
|
|
104987
|
-
|
|
105129
|
+
doPreprocessData(s);
|
|
105130
|
+
doAnalyzeDistricts(s);
|
|
105131
|
+
|
|
105132
|
+
let t1 = doMajorityMinorityDistricts(s);
|
|
105133
|
+
|
|
105134
|
+
doAnalyzePostProcessing(s);
|
|
105135
|
+
|
|
105136
|
+
// echoTestResult("Majority-Minority Districts:", t1); TODO
|
|
105137
|
+
|
|
105138
|
+
break;
|
|
104988
105139
|
}
|
|
105140
|
+
*/
|
|
104989
105141
|
// TODO - SCORE: Update this w/ scoring info
|
|
104990
105142
|
case 'analyze': {
|
|
104991
105143
|
s.analyzePlan(bLog);
|