@dra2020/district-analytics 16.0.0 → 16.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/district-analytics.js +131 -101
- package/dist/district-analytics.js.map +1 -1
- package/package.json +1 -1
|
@@ -459,74 +459,76 @@ class Districts {
|
|
|
459
459
|
bNotEmpty = true;
|
|
460
460
|
// ... loop over the geoIDs creating district-by-district statistics
|
|
461
461
|
geoIDs.forEach(function (geoID) {
|
|
462
|
-
//
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
462
|
+
// 01-04-22 -- Removed water-only guard
|
|
463
|
+
// // Skip water-only features
|
|
464
|
+
// if (!(U.isWaterOnly(geoID)))
|
|
465
|
+
// {
|
|
466
|
+
// Map from geoID to feature index
|
|
467
|
+
let featureID = outerThis._session.features.featureID(geoID);
|
|
468
|
+
let f = outerThis._session.features.featureByIndex(featureID);
|
|
469
|
+
if (f == undefined) {
|
|
470
|
+
if (bLog)
|
|
471
|
+
console.log("Statistics: Skipping undefined feature in district statistics: GEOID =", geoID, "Feature ID =", featureID);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
// ACCUMULATE VALUES
|
|
475
|
+
// Total population of each feature
|
|
476
|
+
// NOTE - This result is used more than once
|
|
477
|
+
// 03-27-21
|
|
478
|
+
const dkCENSUS = outerThis._session.features._keys["CENSUS" /* CENSUS */];
|
|
479
|
+
featurePop = fieldForFeature(f, dkCENSUS, 0 /* TotalPop */);
|
|
480
|
+
// featurePop = outerThis._session.features.fieldForFeature(f, T.Dataset.CENSUS, T.FeatureField.TotalPop);
|
|
481
|
+
// Total district population
|
|
482
|
+
totalPop += featurePop;
|
|
483
|
+
// Ignore features when the county is unrecognized
|
|
484
|
+
const countyFIPS = U.parseGeoID(geoID)['county'];
|
|
485
|
+
if (U.keyExists(countyFIPS, outerThis._session.counties.index)) {
|
|
486
|
+
// Total population by counties w/in a district,
|
|
487
|
+
// except the dummy unassigned district 0
|
|
488
|
+
if (i > 0)
|
|
489
|
+
countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
|
|
470
490
|
}
|
|
471
491
|
else {
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
// NOTE - This result is used more than once
|
|
475
|
-
// 03-27-21
|
|
476
|
-
const dkCENSUS = outerThis._session.features._keys["CENSUS" /* CENSUS */];
|
|
477
|
-
featurePop = fieldForFeature(f, dkCENSUS, 0 /* TotalPop */);
|
|
478
|
-
// featurePop = outerThis._session.features.fieldForFeature(f, T.Dataset.CENSUS, T.FeatureField.TotalPop);
|
|
479
|
-
// Total district population
|
|
480
|
-
totalPop += featurePop;
|
|
481
|
-
// Ignore features when the county is unrecognized
|
|
482
|
-
const countyFIPS = U.parseGeoID(geoID)['county'];
|
|
483
|
-
if (U.keyExists(countyFIPS, outerThis._session.counties.index)) {
|
|
484
|
-
// Total population by counties w/in a district,
|
|
485
|
-
// except the dummy unassigned district 0
|
|
486
|
-
if (i > 0)
|
|
487
|
-
countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
if (bLog)
|
|
491
|
-
console.log("Statistics: County not recognized:", geoID);
|
|
492
|
-
}
|
|
493
|
-
// Democratic and Republican vote totals
|
|
494
|
-
// 10-22-2020 - Added Other votes
|
|
495
|
-
// 10-24-2020 - Added guard against inconsistent election data
|
|
496
|
-
// 03-27-2021
|
|
497
|
-
const dkELECTION = outerThis._session.features._keys["ELECTION" /* ELECTION */];
|
|
498
|
-
const featureDem = fieldForFeature(f, dkELECTION, 7 /* DemVotes */);
|
|
499
|
-
// const featureDem = outerThis._session.features.fieldForFeature(f, T.Dataset.ELECTION, T.FeatureField.DemVotes);
|
|
500
|
-
const featureRep = fieldForFeature(f, dkELECTION, 8 /* RepVotes */);
|
|
501
|
-
const featureTot = fieldForFeature(f, dkELECTION, 9 /* TotalVotes */);
|
|
502
|
-
demVotes += featureDem;
|
|
503
|
-
repVotes += featureRep;
|
|
504
|
-
totVotes += featureTot;
|
|
505
|
-
// NOTE: Unless you grab the values above before accumulating them,
|
|
506
|
-
// you can't accumulate othVotes for districts. You must calculate
|
|
507
|
-
// them by implication later.
|
|
508
|
-
if (bLog) {
|
|
509
|
-
const bBadElection = (featureDem + featureRep > featureTot) ? true : false;
|
|
510
|
-
if (bBadElection)
|
|
511
|
-
console.log("Statistics: Inconsistent election data for precinct:", geoID, featureDem, featureRep, featureTot);
|
|
512
|
-
}
|
|
513
|
-
// Voting-age demographic breakdowns (or citizen voting-age)
|
|
514
|
-
// 03-27-21
|
|
515
|
-
const dkVAP = outerThis._session.features._keys["VAP" /* VAP */];
|
|
516
|
-
totalVAP += fieldForFeature(f, dkVAP, 0 /* TotalPop */);
|
|
517
|
-
// totalVAP += outerThis._session.features.fieldForFeature(f, T.Dataset.VAP, T.FeatureField.TotalPop);
|
|
518
|
-
whitePop += fieldForFeature(f, dkVAP, 1 /* WhitePop */);
|
|
519
|
-
blackPop += fieldForFeature(f, dkVAP, 2 /* BlackPop */);
|
|
520
|
-
hispanicPop += fieldForFeature(f, dkVAP, 3 /* HispanicPop */);
|
|
521
|
-
pacificPop += fieldForFeature(f, dkVAP, 5 /* PacificPop */);
|
|
522
|
-
asianPop += fieldForFeature(f, dkVAP, 4 /* AsianPop */);
|
|
523
|
-
nativePop += fieldForFeature(f, dkVAP, 6 /* NativePop */);
|
|
492
|
+
if (bLog)
|
|
493
|
+
console.log("Statistics: County not recognized:", geoID);
|
|
524
494
|
}
|
|
495
|
+
// Democratic and Republican vote totals
|
|
496
|
+
// 10-22-2020 - Added Other votes
|
|
497
|
+
// 10-24-2020 - Added guard against inconsistent election data
|
|
498
|
+
// 03-27-2021
|
|
499
|
+
const dkELECTION = outerThis._session.features._keys["ELECTION" /* ELECTION */];
|
|
500
|
+
const featureDem = fieldForFeature(f, dkELECTION, 7 /* DemVotes */);
|
|
501
|
+
// const featureDem = outerThis._session.features.fieldForFeature(f, T.Dataset.ELECTION, T.FeatureField.DemVotes);
|
|
502
|
+
const featureRep = fieldForFeature(f, dkELECTION, 8 /* RepVotes */);
|
|
503
|
+
const featureTot = fieldForFeature(f, dkELECTION, 9 /* TotalVotes */);
|
|
504
|
+
demVotes += featureDem;
|
|
505
|
+
repVotes += featureRep;
|
|
506
|
+
totVotes += featureTot;
|
|
507
|
+
// NOTE: Unless you grab the values above before accumulating them,
|
|
508
|
+
// you can't accumulate othVotes for districts. You must calculate
|
|
509
|
+
// them by implication later.
|
|
510
|
+
if (bLog) {
|
|
511
|
+
const bBadElection = (featureDem + featureRep > featureTot) ? true : false;
|
|
512
|
+
if (bBadElection)
|
|
513
|
+
console.log("Statistics: Inconsistent election data for precinct:", geoID, featureDem, featureRep, featureTot);
|
|
514
|
+
}
|
|
515
|
+
// Voting-age demographic breakdowns (or citizen voting-age)
|
|
516
|
+
// 03-27-21
|
|
517
|
+
const dkVAP = outerThis._session.features._keys["VAP" /* VAP */];
|
|
518
|
+
totalVAP += fieldForFeature(f, dkVAP, 0 /* TotalPop */);
|
|
519
|
+
// totalVAP += outerThis._session.features.fieldForFeature(f, T.Dataset.VAP, T.FeatureField.TotalPop);
|
|
520
|
+
whitePop += fieldForFeature(f, dkVAP, 1 /* WhitePop */);
|
|
521
|
+
blackPop += fieldForFeature(f, dkVAP, 2 /* BlackPop */);
|
|
522
|
+
hispanicPop += fieldForFeature(f, dkVAP, 3 /* HispanicPop */);
|
|
523
|
+
pacificPop += fieldForFeature(f, dkVAP, 5 /* PacificPop */);
|
|
524
|
+
asianPop += fieldForFeature(f, dkVAP, 4 /* AsianPop */);
|
|
525
|
+
nativePop += fieldForFeature(f, dkVAP, 6 /* NativePop */);
|
|
525
526
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
527
|
+
// }
|
|
528
|
+
// else
|
|
529
|
+
// {
|
|
530
|
+
// if (bLog) console.log("Statistics: Skipping water-only feature in district statistics:", geoID);
|
|
531
|
+
// }
|
|
530
532
|
});
|
|
531
533
|
// COMPUTE DERIVED VALUES
|
|
532
534
|
// MMD - Generalized the per-district population deviations's for MMD's with variable #'s of reps per district.
|
|
@@ -1022,47 +1024,75 @@ exports.fieldForFeature = fieldForFeature;
|
|
|
1022
1024
|
// f is a direct GeoJSON feature
|
|
1023
1025
|
// p is a geoID
|
|
1024
1026
|
function _getFeatures(f, datasetKey, p) {
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1027
|
+
if (!f.properties || !f.properties.datasets)
|
|
1028
|
+
return 0;
|
|
1029
|
+
if (datasetKey && !f.properties.datasets[datasetKey])
|
|
1030
|
+
return 0;
|
|
1031
|
+
let n = datasetKey ? f.properties.datasets[datasetKey][p] : f.properties[p];
|
|
1032
|
+
return !n || isNaN(n) ? 0 : n;
|
|
1033
|
+
}
|
|
1034
|
+
/* 01-04-22 -- Replaced with the above
|
|
1035
|
+
function _getFeatures(f: any, datasetKey: string, p: string): any
|
|
1036
|
+
{
|
|
1037
|
+
// Shim to load sample data2.json from disk for command-line scaffolding
|
|
1038
|
+
if (f.properties && f.properties['datasets'])
|
|
1039
|
+
{
|
|
1040
|
+
if (!f.properties['datasets'][datasetKey])
|
|
1041
|
+
{
|
|
1042
|
+
// Feature is missing the dataset
|
|
1043
|
+
nMissingDataset += 1;
|
|
1044
|
+
// console.log(`${nMissingDataset}: Data ${datasetKey} missing for feature ${f} Returning zero.`);
|
|
1045
|
+
|
|
1046
|
+
return 0;
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
return f.properties['datasets'][datasetKey][p];
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// NOTE - The fGetW() code from dra-client below here ...
|
|
1053
|
+
|
|
1054
|
+
// Direct property?
|
|
1055
|
+
if (f.properties && f.properties[p] !== undefined)
|
|
1056
|
+
{
|
|
1057
|
+
return f.properties[p];
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
// Joined property?
|
|
1061
|
+
let a: any[] = _fGetJoined(f);
|
|
1062
|
+
if (a)
|
|
1063
|
+
{
|
|
1064
|
+
for (let i: number = 0; i < a.length; i++)
|
|
1065
|
+
{
|
|
1066
|
+
let o: any = a[i];
|
|
1067
|
+
if (!datasetKey)
|
|
1068
|
+
{
|
|
1069
|
+
if (o[p] !== undefined)
|
|
1070
|
+
{
|
|
1071
|
+
return o[p];
|
|
1032
1072
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
for (let i = 0; i < a.length; i++) {
|
|
1044
|
-
let o = a[i];
|
|
1045
|
-
if (!datasetKey) {
|
|
1046
|
-
if (o[p] !== undefined) {
|
|
1047
|
-
return o[p];
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
else {
|
|
1051
|
-
if (o['datasets'] && o['datasets'][datasetKey]) {
|
|
1052
|
-
let v = (o['datasets'][datasetKey][p]);
|
|
1053
|
-
if ((!(v == null)) && (!(v == undefined))) {
|
|
1054
|
-
return o['datasets'][datasetKey][p];
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1073
|
+
}
|
|
1074
|
+
else
|
|
1075
|
+
{
|
|
1076
|
+
if (o['datasets'] && o['datasets'][datasetKey])
|
|
1077
|
+
{
|
|
1078
|
+
let v = (o['datasets'][datasetKey][p]);
|
|
1079
|
+
if ((!(v == null)) && (!(v == undefined)))
|
|
1080
|
+
{
|
|
1081
|
+
return o['datasets'][datasetKey][p];
|
|
1082
|
+
}
|
|
1058
1083
|
}
|
|
1084
|
+
}
|
|
1059
1085
|
}
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// Feature is missing the property
|
|
1089
|
+
nMissingProperty += 1;
|
|
1090
|
+
// console.log(`${nMissingProperty}: ${p} value undefined for ${f.properties['GEOID10']}. Returning zero.`);
|
|
1091
|
+
|
|
1092
|
+
return 0;
|
|
1093
|
+
// return undefined;
|
|
1065
1094
|
}
|
|
1095
|
+
*/
|
|
1066
1096
|
function _fGetJoined(f) {
|
|
1067
1097
|
return (f.properties && f.properties.joined) ? f.properties.joined : undefined;
|
|
1068
1098
|
}
|