@dra2020/district-analytics 9.4.1 → 9.4.4

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.
@@ -351,7 +351,7 @@ var DistrictField;
351
351
  DistrictField[DistrictField["bContiguous"] = 4] = "bContiguous";
352
352
  DistrictField[DistrictField["bNotEmbedded"] = 5] = "bNotEmbedded";
353
353
  DistrictField[DistrictField["CountySplits"] = 6] = "CountySplits";
354
- // 10-22-2020 - Add OtherVotes
354
+ // 10-22-2020 - Added Other votes
355
355
  DistrictField[DistrictField["DemVotes"] = 7] = "DemVotes";
356
356
  DistrictField[DistrictField["RepVotes"] = 8] = "RepVotes";
357
357
  DistrictField[DistrictField["OtherVotes"] = 9] = "OtherVotes";
@@ -435,7 +435,7 @@ class Districts {
435
435
  // Add an extra 0th virtual county bucket for county-district splitting analysis
436
436
  let nCountyBuckets = this._session.counties.nCounties + 1;
437
437
  // INITIALIZE STATE VALUES THAT WILL BE ACCUMULATED
438
- // 10-22-2020 - Add OtherVotes
438
+ // 10-22-2020 - Added Other votes
439
439
  let stateDemVote = 0;
440
440
  let stateRepVote = 0;
441
441
  let stateOthVote = 0;
@@ -460,7 +460,7 @@ class Districts {
460
460
  let featurePop;
461
461
  let totalPop = 0;
462
462
  let countySplits = U.initArray(nCountyBuckets, 0);
463
- // 10-22-2020 - Add OtherVotes
463
+ // 10-22-2020 - Added Other votes
464
464
  let demVotes = 0;
465
465
  let repVotes = 0;
466
466
  let othVotes = 0;
@@ -477,7 +477,6 @@ class Districts {
477
477
  let bContiguous = true;
478
478
  let bNotEmbedded = true;
479
479
  let bEqualPop = true;
480
- // 3 - MORE ...
481
480
  // HACK - Because "this" gets ghosted inside the forEach loop below
482
481
  let outerThis = this;
483
482
  // Default the pop dev % for the dummy Unassigned district to 0%.
@@ -519,13 +518,25 @@ class Districts {
519
518
  console.log("County not recognized:", geoID);
520
519
  }
521
520
  // Democratic and Republican vote totals
522
- // 10-22-2020 - Add OtherVotes
523
- demVotes += outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "D" /* DemVotes */);
524
- repVotes += outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "R" /* RepVotes */);
525
- totVotes += outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "Tot" /* TotalVotes */);
521
+ // 10-22-2020 - Added Other votes
522
+ // 10-24-2020 - Added guard against inconsistent election data
523
+ const featureDem = outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "D" /* DemVotes */);
524
+ const featureRep = outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "R" /* RepVotes */);
525
+ const featureTot = outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "Tot" /* TotalVotes */);
526
+ demVotes += featureDem;
527
+ repVotes += featureRep;
528
+ totVotes += featureTot;
529
+ // demVotes += outerThis._session.features.fieldForFeature(f, T.Dataset.ELECTION, T.FeatureField.DemVotes);
530
+ // repVotes += outerThis._session.features.fieldForFeature(f, T.Dataset.ELECTION, T.FeatureField.RepVotes);
531
+ // totVotes += outerThis._session.features.fieldForFeature(f, T.Dataset.ELECTION, T.FeatureField.TotalVotes);
526
532
  // NOTE: Unless you grab the values above before accumulating them,
527
533
  // you can't accumulate othVotes for districts. You must calculate
528
534
  // them by implication later.
535
+ if (bLog) {
536
+ const bBadElection = (featureDem + featureRep > featureTot) ? true : false;
537
+ if (bBadElection)
538
+ console.log("Inconsistent election data for precinct:", geoID, featureDem, featureRep, featureTot);
539
+ }
529
540
  // Voting-age demographic breakdowns (or citizen voting-age)
530
541
  totalVAP += outerThis._session.features.fieldForFeature(f, "VAP" /* VAP */, "Tot" /* TotalPop */);
531
542
  whitePop += outerThis._session.features.fieldForFeature(f, "VAP" /* VAP */, "Wh" /* WhitePop */);
@@ -549,14 +560,20 @@ class Districts {
549
560
  bEqualPop = (Math.abs(popDevPct) <= deviationThreshold);
550
561
  }
551
562
  }
552
- // 10-22-2020 - Add OtherVotes. Revised from two-party to include Other.
563
+ // 10-22-2020 - Added Other votes. Revised from two-party to include Other.
553
564
  // let totVotes: number; <<< Now being accumulated by district
554
565
  let demPct = 0;
555
566
  let repPct = 0;
556
567
  let othPct = 0;
557
568
  let DemSeat = 0;
558
- // totVotes = demVotes + repVotes; <<< Now being accumulated by district
569
+ // totVotes now being accumulated by district
559
570
  if (totVotes > 0) {
571
+ // 10-24-2020 - Added guard against inconsistent election data.
572
+ const bBadElection = (demVotes + repVotes > totVotes) ? true : false;
573
+ if (bBadElection && bLog)
574
+ console.log("Inconsistent election data for district:", i, demVotes, repVotes, totVotes);
575
+ if (bBadElection)
576
+ totVotes = demVotes + repVotes; // HACK to guard against bad election data!
560
577
  othVotes = totVotes - demVotes - repVotes;
561
578
  demPct = demVotes / totVotes;
562
579
  repPct = repVotes / totVotes;
@@ -605,7 +622,7 @@ class Districts {
605
622
  // this.statistics[DistrictField.TotalPop][i] = totalPop;
606
623
  // this.statistics[DistrictField.bEqualPop][i] = bEqualPop;
607
624
  this.statistics[DistrictField.PopDevPct][i] = popDevPct;
608
- // 10-22-2020 - Add OtherVotes
625
+ // 10-22-2020 - Added Other votes
609
626
  this.statistics[DistrictField.DemVotes][i] = demVotes;
610
627
  this.statistics[DistrictField.RepVotes][i] = repVotes;
611
628
  this.statistics[DistrictField.OtherVotes][i] = othVotes;
@@ -631,7 +648,7 @@ class Districts {
631
648
  this.statistics[DistrictField.NativePct][i] = nativePct;
632
649
  }
633
650
  { // ACCUMULATE STATE STATISTICS FROM DISTRICT TOTALS
634
- // 10-22-2020 - Add OtherVotes
651
+ // 10-22-2020 - Added Other votes
635
652
  stateTotVote += totVotes;
636
653
  // stateTPVote += totVotes;
637
654
  stateDemVote += demVotes;
@@ -649,7 +666,7 @@ class Districts {
649
666
  }
650
667
  else { // If a district is empty, zero these results (vs. null)
651
668
  this.statistics[DistrictField.PopDevPct][i] = popDevPct;
652
- // 10-22-2020 - Add OtherVotes
669
+ // 10-22-2020 - Added Other votes
653
670
  this.statistics[DistrictField.DemVotes][i] = 0;
654
671
  this.statistics[DistrictField.RepVotes][i] = 0;
655
672
  this.statistics[DistrictField.OtherVotes][i] = 0;
@@ -685,7 +702,7 @@ class Districts {
685
702
  }
686
703
  // UPDATE STATE STATISTICS
687
704
  let summaryRow = this.numberOfRows() - 1;
688
- // 10-22-2020 - Add OtherVotes
705
+ // 10-22-2020 - Added Other votes
689
706
  if (stateTotVote > 0) {
690
707
  this.statistics[DistrictField.DemVotes][summaryRow] = stateDemVote;
691
708
  this.statistics[DistrictField.RepVotes][summaryRow] = stateRepVote;
@@ -1245,8 +1262,7 @@ function extractDistrictProperties(s, bLog = false) {
1245
1262
  props[1 /* Diameter */] = diameter;
1246
1263
  props[2 /* Perimeter */] = perimeter;
1247
1264
  s.districts.setGeoProperties(i, props);
1248
- if (bLog)
1249
- console.log("District", i, "A =", area, "P =", perimeter, "D =", diameter);
1265
+ // if (bLog) console.log("District", i, "A =", area, "P =", perimeter, "D =", diameter);
1250
1266
  }
1251
1267
  }
1252
1268
  }
@@ -1281,8 +1297,7 @@ function scoreKIWYSICompactness(s, bLog = false) {
1281
1297
  }
1282
1298
  }
1283
1299
  const scores = Compactness.scoreShapes(goodShapes);
1284
- // 10-21-2020
1285
- // - Return all by-district scores instead of just the average.
1300
+ // 10-21-2020 - Returned all by-district scores instead of just the average.
1286
1301
  // - Round & invert the scores here at the source vs. later on, higher up.
1287
1302
  return scores.map(n => 100 - Math.round(n));
1288
1303
  // const avgKIWYSIScore: number = U.avgArray(scores);
@@ -1456,7 +1471,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
1456
1471
  const assert_1 = __webpack_require__(/*! assert */ "assert");
1457
1472
  function fptpWin(demPct) {
1458
1473
  // Vote shares should be fractions in the range [0.0 – 1.0]
1459
- assert_1.strict((demPct <= 1.0) && (demPct >= 0.));
1474
+ assert_1.strict((demPct <= 1.0) && (demPct >= 0.0));
1460
1475
  return ((demPct > 0.5) ? 1 : 0);
1461
1476
  }
1462
1477
  exports.fptpWin = fptpWin;
@@ -1721,32 +1736,34 @@ function prepareRequirementsChecklist(s, bLog = false) {
1721
1736
  return paRequirements;
1722
1737
  }
1723
1738
  exports.prepareRequirementsChecklist = prepareRequirementsChecklist;
1724
- // Example
1725
- exports.sampleDistrictStatistics = {
1726
- table: [
1727
- // District 0 is the dummy unassigned district
1728
- // HACK - Total VAP #'s at the end are just so the same matches the type
1729
- [0, 0, 0, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1730
- [1, 653133, -0.0950, 0 /* Green */, 2 /* Red */, 0 /* Green */, 0 /* Green */, 0.4177, 0.5823, 0.8631, 0.1369, 0.0734, 0.0360, 0.0009, 0.0235, 0.0064, 50000],
1731
- [2, 620961, -0.1396, 0 /* Green */, 2 /* Red */, 2 /* Red */, 0 /* Green */, 0.8820, 0.1180, 0.3129, 0.6871, 0.6169, 0.0391, 0.0013, 0.0310, 0.0099, 50000],
1732
- [3, 971777, 0.3465, 0 /* Green */, 2 /* Red */, 0 /* Green */, 0 /* Green */, 0.7261, 0.2739, 0.5174, 0.4826, 0.1745, 0.1572, 0.0020, 0.1531, 0.0090, 50000],
1733
- [4, 863420, 0.1964, 0 /* Green */, 2 /* Red */, 0 /* Green */, 0 /* Green */, 0.8957, 0.1043, 0.1734, 0.8266, 0.6489, 0.1348, 0.0020, 0.0496, 0.0127, 50000],
1734
- [5, 805029, 0.1155, 0 /* Green */, 2 /* Red */, 0 /* Green */, 1 /* Yellow */, 0.5743, 0.4257, 0.6587, 0.3413, 0.2494, 0.0363, 0.0012, 0.0536, 0.0081, 50000],
1735
- [6, 824741, 0.1428, 0 /* Green */, 2 /* Red */, 0 /* Green */, 2 /* Red */, 0.5341, 0.4659, 0.7045, 0.2955, 0.1619, 0.0526, 0.0018, 0.0782, 0.0090, 50000],
1736
- [7, 549714, -0.2383, 0 /* Green */, 0 /* Green */, 0 /* Green */, 0 /* Green */, 0.5025, 0.4975, 0.6906, 0.3094, 0.2468, 0.0319, 0.0013, 0.0258, 0.0111, 50000],
1737
- [8, 484777, -0.3283, 0 /* Green */, 0 /* Green */, 0 /* Green */, 0 /* Green */, 0.4105, 0.5895, 0.8370, 0.1630, 0.1074, 0.0316, 0.0013, 0.0197, 0.0077, 50000],
1738
- // District N+1 is the dummy state-summary district
1739
- [9, 721694, 0.6748, 0 /* Green */, 2 /* Red */, 2 /* Red */, 2 /* Red */, 0.6293, 0.3707, 0.5722, 0.4278, 0.2925, 0.0729, 0.0015, 0.0618, 0.0093, 400000]
1740
- ],
1741
- details: {},
1742
- datasets: {
1743
- shapes: "2010 VTD shapes",
1744
- census: "2010 Census Total Population",
1745
- vap: "2010 Voting Age Population",
1746
- election: "2016 Presidential, US Senate, Governor, and AG election results"
1747
- },
1748
- resources: {}
1749
- };
1739
+ /* 10-23-2020 - Removed the district statistics sample.
1740
+
1741
+ export const sampleDistrictStatistics: DistrictStatistics = {
1742
+ table: [
1743
+ // District 0 is the dummy unassigned district
1744
+ // HACK - Total VAP #'s at the end are just so the same matches the type
1745
+ [0, 0, 0, null, null, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
1746
+ [1, 653133, -0.0950, T.TriState.Green, T.TriState.Red, T.TriState.Green, T.TriState.Green, 0.4177, 0.5823, 0.8631, 0.1369, 0.0734, 0.0360, 0.0009, 0.0235, 0.0064, 50000],
1747
+ [2, 620961, -0.1396, T.TriState.Green, T.TriState.Red, T.TriState.Red, T.TriState.Green, 0.8820, 0.1180, 0.3129, 0.6871, 0.6169, 0.0391, 0.0013, 0.0310, 0.0099, 50000],
1748
+ [3, 971777, 0.3465, T.TriState.Green, T.TriState.Red, T.TriState.Green, T.TriState.Green, 0.7261, 0.2739, 0.5174, 0.4826, 0.1745, 0.1572, 0.0020, 0.1531, 0.0090, 50000],
1749
+ [4, 863420, 0.1964, T.TriState.Green, T.TriState.Red, T.TriState.Green, T.TriState.Green, 0.8957, 0.1043, 0.1734, 0.8266, 0.6489, 0.1348, 0.0020, 0.0496, 0.0127, 50000],
1750
+ [5, 805029, 0.1155, T.TriState.Green, T.TriState.Red, T.TriState.Green, T.TriState.Yellow, 0.5743, 0.4257, 0.6587, 0.3413, 0.2494, 0.0363, 0.0012, 0.0536, 0.0081, 50000],
1751
+ [6, 824741, 0.1428, T.TriState.Green, T.TriState.Red, T.TriState.Green, T.TriState.Red, 0.5341, 0.4659, 0.7045, 0.2955, 0.1619, 0.0526, 0.0018, 0.0782, 0.0090, 50000],
1752
+ [7, 549714, -0.2383, T.TriState.Green, T.TriState.Green, T.TriState.Green, T.TriState.Green, 0.5025, 0.4975, 0.6906, 0.3094, 0.2468, 0.0319, 0.0013, 0.0258, 0.0111, 50000],
1753
+ [8, 484777, -0.3283, T.TriState.Green, T.TriState.Green, T.TriState.Green, T.TriState.Green, 0.4105, 0.5895, 0.8370, 0.1630, 0.1074, 0.0316, 0.0013, 0.0197, 0.0077, 50000],
1754
+ // District N+1 is the dummy state-summary district
1755
+ [9, 721694, 0.6748, T.TriState.Green, T.TriState.Red, T.TriState.Red, T.TriState.Red, 0.6293, 0.3707, 0.5722, 0.4278, 0.2925, 0.0729, 0.0015, 0.0618, 0.0093, 400000]
1756
+ ],
1757
+ details: {},
1758
+ datasets: {
1759
+ shapes: "2010 VTD shapes",
1760
+ census: "2010 Census Total Population",
1761
+ vap: "2010 Voting Age Population",
1762
+ election: "2016 Presidential, US Senate, Governor, and AG election results"
1763
+ },
1764
+ resources: {}
1765
+ }
1766
+ */
1750
1767
  // Create a DistrictStatistics instance, deep copying the underlying values.
1751
1768
  function prepareDistrictStatistics(s, bLog = false) {
1752
1769
  if (!(s.bPostProcessingDone)) {
@@ -1771,7 +1788,9 @@ function prepareDistrictStatistics(s, bLog = false) {
1771
1788
  s.districts.statistics[D.DistrictField.PacificPct][i],
1772
1789
  s.districts.statistics[D.DistrictField.AsianPct][i],
1773
1790
  s.districts.statistics[D.DistrictField.NativePct][i],
1774
- s.districts.statistics[D.DistrictField.TotalVAP][i]
1791
+ s.districts.statistics[D.DistrictField.TotalVAP][i],
1792
+ // 10-23-2020 - Added Other vote percentage
1793
+ s.districts.statistics[D.DistrictField.OtherPct][i],
1775
1794
  ];
1776
1795
  // NOTE - Until we add three-state support top to bottom in Requirements,
1777
1796
  // map booleans to tri-states here.
@@ -1942,7 +1961,7 @@ function profilePlan(s, bLog = false) {
1942
1961
  const geoPropsByDistrict = makeArrayOfGeoProps(s, bLog);
1943
1962
  const splits = makeNakedCxD(s);
1944
1963
  const summaryRow = s.districts.numberOfRows() - 1;
1945
- // 10-22-2020 - TODO: Convert Dem + Rep + Other = Total to two-party vote shares for analytics.
1964
+ // 10-22-2020 - Converted Dem + Rep + Other = Total to two-party vote shares for analytics.
1946
1965
  const demVote = s.districts.statistics[D.DistrictField.DemVotes][summaryRow];
1947
1966
  const repVote = s.districts.statistics[D.DistrictField.RepVotes][summaryRow];
1948
1967
  const statewideVf = U.trim(demVote / (demVote + repVote), KEEP_DECIMALS);
@@ -2072,10 +2091,10 @@ function scorePlan(s, p, bLog = false, overridesJSON) {
2072
2091
  try {
2073
2092
  // Add KIWYSI compactness score
2074
2093
  const kiwysiScores = C.scoreKIWYSICompactness(s, bLog);
2075
- // 10-21-2020 - Compute the average score here
2094
+ // 10-21-2020 - Computing the average score here
2076
2095
  const avgKIWYSIScore = Math.round(U.avgArray(kiwysiScores));
2077
2096
  scorecard.compactness.details['kiwysi'] = avgKIWYSIScore;
2078
- // 10-21-2020 - Add KIWYSI scores to the by-district details
2097
+ // 10-21-2020 - Added KIWYSI scores to the by-district details
2079
2098
  let byDistrict = scorecard.compactness.details['byDistrict'];
2080
2099
  const nDistricts = byDistrict.length;
2081
2100
  for (let districtID = 1; districtID <= nDistricts; districtID++) {