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