@dra2020/district-analytics 4.3.0 → 4.3.3

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