@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 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\":25},\"marginal\":{\"range\":[0,0.85],\"weight\":75},\"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]}}");
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
- this.testScales = {};
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 - SCORE: Toggle
101350
- if (this.useLegacy()) {
101351
- console.log("Using legacy district-analytics.");
101352
- // NOTE: I've pulled these out of the individual analytics to here. Eventually,
101353
- // we could want them to passed into an analytics session as data, along with
101354
- // everything else. For now, this keeps branching out of the main code.
101355
- results_1.doConfigureScales(this);
101356
- }
101357
- else {
101358
- console.log("Using dra-score analytics.");
101359
- // TODO - SCORE: Temporary HACK. Query dra-score for threshold.
101360
- results_1.doConfigureScales(this);
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
- // TODO - SCORE: Toggle = Invert this logic
101375
- useLegacy() {
101376
- // TODO - SCORE: Opt-out
101377
- return (U.keyExists('useScore', this.config) && (this.config['useScore'] != null) && (!(this.config['useScore']))) ? true : false;
101378
- // TODO - SCORE: Opt-in
101379
- // return (U.keyExists('useScore', this.config) && (this.config['useScore'])) ? false : true;
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 - SCORE: Toggle
101513
- if (this.useLegacy()) {
101514
- return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
101515
- }
101516
- else {
101517
- // NOTE - This assumes the plan has been profiled
101518
- const scorer = new Score.Scorer();
101519
- const popdev = scorer.populationDeviationThreshold(this.legislativeDistricts);
101520
- return popdev;
101521
- // TODO - SCORE: Temporary HACK. Query dra-score for threshold.
101522
- // NOTE - The plan may not have been scored yet, i.e., no scorecard yet.
101523
- // return 1 - this.testScales[T.Test.PopulationDeviation]['scale'][0];
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
- const compact_1 = __webpack_require__(/*! ./compact */ "./src/compact.ts");
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
- const political_1 = __webpack_require__(/*! ./political */ "./src/political.ts");
102136
- const minority_1 = __webpack_require__(/*! ./minority */ "./src/minority.ts");
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 - SCORE: Toggle
102149
- if (s.useLegacy()) {
102150
- // Disable most legacy analytics
102151
- // Get the requested suites, and only execute those tests
102152
- let requestedSuites = s.config['suites'];
102153
- // Tests in the "Legal" suite, i.e., pass/ fail constraints
102154
- if (requestedSuites.includes(0 /* Legal */)) {
102155
- s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
102156
- s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
102157
- s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
102158
- s.tests[4 /* PopulationDeviation */] = equal_1.doPopulationDeviation(s, bLog);
102159
- // NOTE - I can't check whether a population deviation is legal or not, until
102160
- // the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
102161
- // the given type of district (CD vs. LD). The EqualPopulation test is derived
102162
- // from PopulationDeviation, as part of scorecard or test log preparation.
102163
- // Create an empty test entry here though ...
102164
- s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
102165
- }
102166
- // Tests in the "Fair" suite
102167
- if (requestedSuites.includes(1 /* Fair */)) {
102168
- s.tests[11 /* SeatsBias */] = political_1.doSeatsBias(s, bLog);
102169
- s.tests[12 /* VotesBias */] = political_1.doVotesBias(s, bLog);
102170
- s.tests[13 /* Responsiveness */] = political_1.doResponsiveness(s, bLog);
102171
- s.tests[14 /* ResponsiveDistricts */] = political_1.doResponsiveDistricts(s, bLog);
102172
- s.tests[15 /* EfficiencyGap */] = political_1.doEfficiencyGap(s, bLog);
102173
- s.tests[16 /* MajorityMinorityDistricts */] = minority_1.doMajorityMinorityDistricts(s, bLog);
102174
- }
102175
- // Tests in the "Best" suite, i.e., criteria for better/worse
102176
- if (requestedSuites.includes(2 /* Best */)) {
102177
- s.tests[5 /* Reock */] = compact_1.doReock(s, bLog);
102178
- s.tests[6 /* PolsbyPopper */] = compact_1.doPolsbyPopper(s, bLog);
102179
- s.tests[7 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
102180
- s.tests[10 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
102181
- s.tests[8 /* CountySplitting */] = cohesive_1.doCountySplitting(s, bLog);
102182
- s.tests[9 /* DistrictSplitting */] = cohesive_1.doDistrictSplitting(s, bLog);
102183
- }
102184
- }
102185
- else {
102186
- // TODO - SCORE: Except these. Continue to do these here vs. dra-score.
102187
- s.tests[0 /* Complete */] = valid_1.doIsComplete(s, bLog);
102188
- s.tests[1 /* Contiguous */] = valid_1.doIsContiguous(s, bLog);
102189
- s.tests[2 /* FreeOfHoles */] = valid_1.doIsFreeOfHoles(s, bLog);
102190
- s.tests[4 /* PopulationDeviation */] = equal_1.doPopulationDeviation(s, bLog);
102191
- // NOTE - I can't check whether a population deviation is legal or not, until
102192
- // the raw % is normalized. A zero (0) would mean "too much" / "not legal," for
102193
- // the given type of district (CD vs. LD). The EqualPopulation test is derived
102194
- // from PopulationDeviation, as part of scorecard or test log preparation.
102195
- // Create an empty test entry here though ...
102196
- s.tests[3 /* EqualPopulation */] = s.getTest(3 /* EqualPopulation */);
102197
- s.tests[7 /* UnexpectedCountySplits */] = cohesive_1.doFindCountiesSplitUnexpectedly(s, bLog);
102198
- s.tests[10 /* VTDSplits */] = cohesive_1.doFindSplitVTDs(s, bLog);
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
- function doCountySplitting(s, bLog = false) {
102244
- let test = s.getTest(8 /* CountySplitting */);
102245
- let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
102246
- let countyTotals = s.counties.totalPopulation;
102247
- let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
102248
- let f = calcCountyFractions(CxD, countyTotals);
102249
- let w = calcCountyWeights(countyTotals);
102250
- let SqEnt_DC = countySplitting(f, w, bLog);
102251
- let CxDreducedC = U.deepCopy(CxD);
102252
- reduceCSplits(CxDreducedC, districtTotals);
102253
- let fReduced = calcCountyFractions(CxDreducedC, countyTotals);
102254
- let wReduced = calcCountyWeights(countyTotals);
102255
- let SqEnt_DCreduced = countySplitting(fReduced, wReduced, bLog);
102256
- test['score'] = SqEnt_DCreduced;
102257
- test['details']['SqEnt_DC'] = SqEnt_DC;
102258
- return test;
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
- exports.doCountySplitting = doCountySplitting;
102261
- function doDistrictSplitting(s, bLog = false) {
102262
- let test = s.getTest(9 /* DistrictSplitting */);
102263
- let CxD = s.districts.statistics[D.DistrictField.CountySplits].slice(0, -1);
102264
- let countyTotals = s.counties.totalPopulation;
102265
- let districtTotals = s.districts.statistics[D.DistrictField.TotalPop].slice(0, -1);
102266
- let g = calcDistrictFractions(CxD, districtTotals);
102267
- let x = calcDistrictWeights(districtTotals);
102268
- let SqEnt_CD = districtSplitting(g, x, bLog);
102269
- let CxDreducedD = U.deepCopy(CxD);
102270
- reduceDSplits(CxDreducedD, countyTotals);
102271
- let gReduced = calcDistrictFractions(CxDreducedD, districtTotals);
102272
- let xReduced = calcDistrictWeights(districtTotals);
102273
- let SqEnt_CDreduced = districtSplitting(gReduced, xReduced, bLog);
102274
- test['score'] = SqEnt_CDreduced;
102275
- test['details']['SqEnt_CD'] = SqEnt_CD;
102276
- return test;
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
- exports.doDistrictSplitting = doDistrictSplitting;
102330
+
102331
+
102279
102332
  // HELPERS
102280
- // Loop over all the county-district combos, skipping the virtual district 0
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
- let nD = CxDreducedC.length;
102291
- let nC = CxDreducedC[0].length;
102292
- for (let j = 1; j < nC; j++) {
102293
- for (let i = 1; i < nD; i++) {
102294
- let split_total = CxDreducedC[i][j];
102295
- if (split_total > 0) {
102296
- if (areRoughlyEqual(split_total, districtTotals[i])) {
102297
- CxDreducedC[0][j] += split_total;
102298
- CxDreducedC[i][j] = 0;
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
- let nD = CxDreducedD.length;
102308
- let nC = CxDreducedD[0].length;
102309
- for (let i = 1; i < nD; i++) {
102310
- for (let j = 1; j < nC; j++) {
102311
- let split_total = CxDreducedD[i][j];
102312
- if (split_total > 0) {
102313
- if (areRoughlyEqual(split_total, countyTotals[j])) {
102314
- CxDreducedD[i][0] += split_total;
102315
- CxDreducedD[i][j] = 0;
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
- function calcCountyWeights(countyTotals) {
102322
- let nC = countyTotals.length;
102323
- let cTotal = U.sumArray(countyTotals);
102324
- let w = U.initArray(nC, 0.0);
102325
- for (let j = 0; j < nC; j++) {
102326
- w[j] = countyTotals[j] / cTotal;
102327
- }
102328
- return w;
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
- function calcDistrictWeights(districtTotals) {
102331
- let nD = districtTotals.length;
102332
- let dTotal = U.sumArray(districtTotals);
102333
- let x = U.initArray(nD, 0.0);
102334
- for (let i = 0; i < nD; i++) {
102335
- x[i] = districtTotals[i] / dTotal;
102336
- }
102337
- return x;
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
- function calcCountyFractions(CxDreducedD, countyTotals) {
102340
- let nD = CxDreducedD.length;
102341
- let nC = CxDreducedD[0].length;
102342
- let f = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
102343
- for (let j = 0; j < nC; j++) {
102344
- for (let i = 0; i < nD; i++) {
102345
- if (countyTotals[j] > 0) {
102346
- f[i][j] = CxDreducedD[i][j] / countyTotals[j];
102347
- }
102348
- else {
102349
- f[i][j] = 0.0;
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
- return f;
102442
+ }
102443
+
102444
+ return f;
102354
102445
  }
102355
- function calcDistrictFractions(CxDreducedC, districtTotals) {
102356
- let nD = CxDreducedC.length;
102357
- let nC = CxDreducedC[0].length;
102358
- let g = new Array(nD).fill(0.0).map(() => new Array(nC).fill(0.0));
102359
- for (let j = 0; j < nC; j++) {
102360
- for (let i = 0; i < nD; i++) {
102361
- if (districtTotals[i] > 0) {
102362
- g[i][j] = CxDreducedC[i][j] / districtTotals[i];
102363
- }
102364
- else {
102365
- g[i][j] = 0.0;
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
- return g;
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
- let delta = Math.abs(x - y);
102374
- let result = (delta < S.EQUAL_TOLERANCE) ? true : false;
102375
- return result;
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
- let e = 0.0;
102380
- for (let i = 0; i < numD; i++) {
102381
- e += Math.sqrt(f[i][j]);
102382
- }
102383
- return e;
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
- let numC = f[0].length;
102388
- let numD = f.length;
102389
- let e = 0.0;
102390
- for (let j = 0; j < numC; j++) {
102391
- let splitScore = countySplitScore(j, f, numD, bLog);
102392
- e += w[j] * splitScore;
102393
- if (bLog)
102394
- console.log("County splitting =", j, w[j], splitScore, e);
102395
- }
102396
- return U.trim(e, 3);
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
- let e = 0.0;
102401
- for (let j = 0; j < numC; j++) {
102402
- e += Math.sqrt(g[i][j]);
102403
- }
102404
- return e;
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
- let numC = g[0].length;
102409
- let numD = g.length;
102410
- let e = 0.0;
102411
- for (let i = 0; i < numD; i++) {
102412
- let splitScore = districtSplitScore(i, g, numC, bLog);
102413
- e += x[i] * splitScore;
102414
- if (bLog)
102415
- console.log("District split score =", i, x[i], splitScore, e);
102416
- }
102417
- return U.trim(e, 3);
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(7 /* UnexpectedCountySplits */);
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(10 /* VTDSplits */);
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
- const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
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
- let test = s.getTest(5 /* Reock */);
102666
- // Calculate Reock scores by district
102667
- let scores = [];
102668
- for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
102669
- let districtProps = s.districts.getGeoProperties(districtID);
102670
- // Guard against no shape and no properties
102671
- if (districtProps) {
102672
- let a = districtProps[0 /* Area */];
102673
- let d = districtProps[1 /* Diameter */];
102674
- let reock = (4 * a) / (Math.PI * Math.pow(d, 2));
102675
- // Save each district score
102676
- scores.push(reock);
102677
- // Echo the results by district
102678
- if (bLog)
102679
- console.log("Reock for district", districtID, "=", reock);
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
- // Populate the test entry ... for the shapes that exist!
102683
- let averageReock = U.avgArray(scores);
102684
- test['score'] = U.trim(averageReock);
102685
- test['details'] = {}; // TODO - Any details?
102686
- return test;
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
- exports.doReock = doReock;
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
- let test = s.getTest(6 /* PolsbyPopper */);
102694
- // Calculate Polsby-Popper scores by district
102695
- let scores = [];
102696
- for (let districtID = 1; districtID <= s.state.nDistricts; districtID++) {
102697
- let districtProps = s.districts.getGeoProperties(districtID);
102698
- // Guard against no shape and no properties
102699
- if (districtProps) {
102700
- let a = districtProps[0 /* Area */];
102701
- let p = districtProps[2 /* Perimeter */];
102702
- let polsbyPopper = (4 * Math.PI) * (a / Math.pow(p, 2));
102703
- // Save each district score
102704
- scores.push(polsbyPopper);
102705
- // Echo the results by district
102706
- if (bLog)
102707
- console.log("Polsby-Popper for district", districtID, "=", polsbyPopper);
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
- // Populate the test entry ... for the shapes that exist!
102711
- let averagePolsbyPopper = U.avgArray(scores);
102712
- test['score'] = U.trim(averagePolsbyPopper);
102713
- test['details'] = {}; // TODO - Any details?
102714
- return test;
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
- exports.doPolsbyPopper = doPolsbyPopper;
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
- // TODO - SCORE: Delete
102797
- function doPopulationDeviation(s, bLog = false) {
102798
- let test = s.getTest(4 /* PopulationDeviation */);
102799
- let targetSize = s.state.totalPop / s.state.nDistricts;
102800
- // Compute the min & max district populations
102801
- // ... excluding the dummy the 'unassigned' 0 and N+1 summary "districts"
102802
- let totPopByDistrict = s.districts.statistics[D.DistrictField.TotalPop];
102803
- totPopByDistrict = totPopByDistrict.slice(1, -1);
102804
- // Remove empty districts
102805
- totPopByDistrict = totPopByDistrict.filter(x => x > 0);
102806
- let min = 0;
102807
- let max = 0;
102808
- // If there's more than 1 non-empty district, calculate a non-zero deviation
102809
- if (totPopByDistrict.length > 1) {
102810
- min = U.minArray(totPopByDistrict);
102811
- max = U.maxArray(totPopByDistrict);
102812
- }
102813
- // Calculate the raw population deviation
102814
- let popDev = (max - min) / targetSize;
102815
- // Round the raw value to the desired level of precision
102816
- popDev = U.trim(popDev);
102817
- // Populate the test entry
102818
- test['score'] = popDev;
102819
- test['details'] = { 'maxDeviation': max - min };
102820
- // Populate the N+1 summary "district" in district.statistics
102821
- let totalPop = s.districts.statistics[D.DistrictField.TotalPop];
102822
- let popDevPct = s.districts.statistics[D.DistrictField.PopDevPct];
102823
- let summaryRow = s.districts.numberOfRows() - 1;
102824
- totalPop[summaryRow] = targetSize;
102825
- popDevPct[summaryRow] = popDev;
102826
- return test;
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
- exports.doPopulationDeviation = doPopulationDeviation;
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
- const U = __importStar(__webpack_require__(/*! ./utils */ "./src/utils.ts"));
103046
- const D = __importStar(__webpack_require__(/*! ./_data */ "./src/_data.ts"));
103047
- // TODO - SCORE: Remove legacy code
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
- function doSeatsBias(s, bLog = false) {
103068
- let test = s.getTest(11 /* SeatsBias */);
103069
- if (bLog)
103070
- console.log("TODO - Calculating seats bias ...");
103071
- return test;
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
- exports.doSeatsBias = doSeatsBias;
103074
- function doVotesBias(s, bLog = false) {
103075
- let test = s.getTest(12 /* VotesBias */);
103076
- if (bLog)
103077
- console.log("TODO - Calculating votes bias ...");
103078
- return test;
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
- exports.doVotesBias = doVotesBias;
103081
- function doResponsiveness(s, bLog = false) {
103082
- let test = s.getTest(13 /* Responsiveness */);
103083
- if (bLog)
103084
- console.log("TODO - Calculating responsiveness ...");
103085
- return test;
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
- exports.doResponsiveness = doResponsiveness;
103088
- function doResponsiveDistricts(s, bLog = false) {
103089
- let test = s.getTest(14 /* ResponsiveDistricts */);
103090
- if (bLog)
103091
- console.log("TODO - Calculating # of responsive districts ...");
103092
- return test;
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
- exports.doResponsiveDistricts = doResponsiveDistricts;
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
- if (bLog)
103100
- console.log("TODO - Calculating the efficiency gap ...");
103101
- let test = s.getTest(15 /* EfficiencyGap */);
103102
- // Get partisan statistics by districts.
103103
- // Use Democratic votes, seats, and shares by convention.
103104
- let DVotes = s.districts.statistics[D.DistrictField.DemVotes];
103105
- let DSeats = s.districts.statistics[D.DistrictField.DemSeat];
103106
- let TPVotes = s.districts.statistics[D.DistrictField.TwoPartyVote];
103107
- // Exclude the dummy unassigned '0' and N+1 summary "districts"
103108
- DVotes = DVotes.slice(1, -1);
103109
- DSeats = DSeats.slice(1, -1);
103110
- TPVotes = TPVotes.slice(1, -1);
103111
- // Calculate D vote share & D seat share
103112
- let DVoteShare = U.sumArray(DVotes) / U.sumArray(TPVotes);
103113
- let DSeatShare = U.sumArray(DSeats) / s.state.nDistricts;
103114
- // Finally, calculate the Efficiency Gap
103115
- let efficiencyGap = (DSeatShare - 0.5) - (2.0 * (DVoteShare - 0.5));
103116
- // Round the raw value to the desired level of precision
103117
- efficiencyGap = U.trim(efficiencyGap);
103118
- // Populate the test entry
103119
- test['score'] = efficiencyGap;
103120
- // test['normalizedScore'] = 0; /* TODO - Normalize the raw score */
103121
- test['details'] = {}; /* TODO - Add details, if any */
103122
- return test;
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
- exports.doEfficiencyGap = doEfficiencyGap;
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
- // TODO - SCORE: Comment these out ...
103732
- const reockDefn = {
103733
- ID: 5 /* Reock */,
103734
- name: "Reock",
103735
- normalize: true,
103736
- externalType: TestType.Number,
103737
- suites: [2 /* Best */]
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
- const polsbyPopperDefn = {
103740
- ID: 6 /* PolsbyPopper */,
103741
- name: "Polsby-Popper",
103742
- normalize: true,
103743
- externalType: TestType.Number,
103744
- suites: [2 /* Best */]
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: 7 /* UnexpectedCountySplits */,
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: 10 /* VTDSplits */,
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
- [5 /* Reock */]: reockDefn,
103793
- [6 /* PolsbyPopper */]: polsbyPopperDefn,
103794
- // NOTE - SPLITTING
103795
- [7 /* UnexpectedCountySplits */]: unexpectedCountySplitsDefn,
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
- // Scale defn for PopulationDeviation
103813
- const CDLimit = 0.75 / 100; // Deviation threshold for CD's
103814
- const LDLimit = 10.00 / 100; // Deviation threshold for LD's
103815
- const CDGoodEnough = 0.20 / 100;
103816
- const LDGoodEnough = (CDGoodEnough / CDLimit) * LDLimit;
103817
- const popDevScale = (s.legislativeDistricts) ? [1.0 - LDLimit, 1.0 - LDGoodEnough] : [1.0 - CDLimit, 1.0 - CDGoodEnough];
103818
- // const scale = [1.0 - CDLimit, 1.0 - CDGoodEnough];
103819
- s.testScales[4 /* PopulationDeviation */] = { scale: popDevScale, bInvertRaw: true };
103820
- s.testScales[5 /* Reock */] = { scale: [0.25, 0.50] };
103821
- s.testScales[6 /* PolsbyPopper */] = { scale: [0.10, 0.50] };
103822
- const nDistricts = s.state.nDistricts;
103823
- const nCounties = s.counties.nCounties;
103824
- // NOTE - SPLITTING: Experiment w/ this multiplier. Only allowing the expected
103825
- // number of county splits seems too stringent, empirically.
103826
- const allowableCountySplitsMultiplier = 1.5;
103827
- const nAllowableSplits = Math.min(allowableCountySplitsMultiplier * (nDistricts - 1));
103828
- const countySplittingThreshold = ((nAllowableSplits * 1.71) + ((nCounties - nAllowableSplits) * 1.0)) / nCounties;
103829
- const countySplittingScale = [1.0, countySplittingThreshold];
103830
- s.testScales[8 /* CountySplitting */] = { scale: countySplittingScale, bInvertScaled: true };
103831
- const districtSplittingThreshold = 1.5;
103832
- const districtSplittingScale = [1.0, districtSplittingThreshold];
103833
- s.testScales[9 /* DistrictSplitting */] = { scale: districtSplittingScale, bInvertScaled: true };
103834
- // TODO - More analytics ...
103835
- }
103836
- exports.doConfigureScales = doConfigureScales;
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 - SCORE: Toggle
103841
- if (s.useLegacy()) {
103842
- // Normalize the raw scores for all the numerics tests
103843
- let testResults = U.getNumericObjectKeys(testDefns);
103844
- for (let testID of testResults) {
103845
- if (testDefns[testID]['normalize']) {
103846
- let testResult = s.getTest(testID);
103847
- let rawScore = testResult['score'];
103848
- let normalizedScore;
103849
- normalizedScore = U.normalize(rawScore, s.testScales[testID]);
103850
- testResult['normalizedScore'] = normalizedScore;
103851
- // Add the scale used to normalize the raw score to the details
103852
- testResult['details']['scale'] = s.testScales[testID].scale;
103853
- }
103854
- }
103855
- }
103856
- else {
103857
- // Just populate the normalized population deviation score in the test
103858
- const scorecard = s._scorecard;
103859
- let popDev = s.getTest(4 /* PopulationDeviation */);
103860
- popDev['normalizedScore'] = scorecard.traditionalPrinciples.populationDeviation.normalized;
103861
- // TODO - DELETE
103862
- // test['normalizedScore'] = scorecard.best.populationDeviation.normalized;
103863
- // TODO - SCORE: Add datasets used to details by tab
103864
- const datasets = {
103865
- shapes: S.SHAPES,
103866
- census: U.deepCopy(s.config['descriptions']['CENSUS']),
103867
- vap: U.deepCopy(s.config['descriptions']['VAP']),
103868
- election: U.deepCopy(s.config['descriptions']['ELECTION'])
103869
- };
103870
- scorecard.partisan.details['election'] = datasets.election;
103871
- scorecard.minority.details['vap'] = datasets.vap;
103872
- scorecard.traditionalPrinciples.details['shapes'] = datasets.shapes;
103873
- scorecard.traditionalPrinciples.details['census'] = datasets.census;
103874
- // TODO - SCORE: Add legacy splits details
103875
- const simpleSplits = s.getTest(7 /* UnexpectedCountySplits */);
103876
- scorecard.traditionalPrinciples.details['unexpectedAffected'] = simpleSplits['score'];
103877
- scorecard.traditionalPrinciples.details['countiesSplitUnexpectedly'] = U.deepCopy(simpleSplits['details']['countiesSplitUnexpectedly']);
103878
- // NOTE - Add split precincts in dra-client directly
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
- // 1 - Create district shapes & extract properties (area, diameter, perimeter)
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 = equal_1.doPopulationDeviation(s);
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
- preprocess_1.doPreprocessData(s);
104934
- analyze_1.doAnalyzeDistricts(s);
104935
- t = equal_1.doPopulationDeviation(s);
104936
- echoTestResult("Population deviation (%):", t);
104937
- results_1.doAnalyzePostProcessing(s);
104938
- break;
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
- preprocess_1.doPreprocessData(s);
104942
- analyze_1.doAnalyzeDistricts(s);
104943
- let t1 = compact_1.doReock(s, bLog);
104944
- let t2 = compact_1.doPolsbyPopper(s, bLog);
104945
- results_1.doAnalyzePostProcessing(s);
104946
- echoTestResult("Reock:", t1);
104947
- echoTestResult("Polsby-Popper:", t2);
104948
- break;
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
- preprocess_1.doPreprocessData(s);
104952
- analyze_1.doAnalyzeDistricts(s);
104953
- // NOTE - SPLITTING
104954
- let t1 = cohesive_1.doFindCountiesSplitUnexpectedly(s);
104955
- let t2 = cohesive_1.doFindSplitVTDs(s);
104956
- let t3 = cohesive_1.doCountySplitting(s);
104957
- let t4 = cohesive_1.doDistrictSplitting(s);
104958
- results_1.doAnalyzePostProcessing(s);
104959
- echoTestResult("Counties split unexpectedly:", t1);
104960
- echoTestResult("Split VTDs:", t2);
104961
- echoTestResult("County splitting:", t3);
104962
- echoTestResult("District splitting:", t4);
104963
- break;
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
- preprocess_1.doPreprocessData(s);
104967
- analyze_1.doAnalyzeDistricts(s);
104968
- let t1 = political_1.doSeatsBias(s);
104969
- let t2 = political_1.doVotesBias(s);
104970
- let t3 = political_1.doResponsiveness(s);
104971
- let t4 = political_1.doResponsiveDistricts(s);
104972
- let t5 = political_1.doEfficiencyGap(s);
104973
- results_1.doAnalyzePostProcessing(s);
104974
- // echoTestResult("Seats Bias:", t1); TODO
104975
- // echoTestResult("Votes Bias:", t2); TODO
104976
- // echoTestResult("Responsiveness:", t3); TODO
104977
- // echoTestResult("Responsive Districts:", t4); TODO
104978
- echoTestResult("Efficiency gap (%):", t5);
104979
- break;
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
- preprocess_1.doPreprocessData(s);
104983
- analyze_1.doAnalyzeDistricts(s);
104984
- let t1 = minority_1.doMajorityMinorityDistricts(s);
104985
- results_1.doAnalyzePostProcessing(s);
104986
- // echoTestResult("Majority-Minority Districts:", t1); TODO
104987
- break;
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);