@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 -
|
|
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 -
|
|
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 -
|
|
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 -
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
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 -
|
|
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
|
|
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 -
|
|
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 -
|
|
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 -
|
|
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 -
|
|
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
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
]
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
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 -
|
|
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 -
|
|
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 -
|
|
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++) {
|