@dra2020/district-analytics 8.2.4 → 8.2.7

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.
@@ -503,10 +503,17 @@ class Districts {
503
503
  featurePop = outerThis._session.features.fieldForFeature(f, "CENSUS" /* CENSUS */, "Tot" /* TotalPop */);
504
504
  // Total district population
505
505
  totalPop += featurePop;
506
- // Total population by counties w/in a district,
507
- // except the dummy unassigned district 0
508
- if (i > 0)
509
- countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
506
+ // Ignore features when the county is unrecognized
507
+ const countyFIPS = U.parseGeoID(geoID)['county'];
508
+ if (U.keyExists(countyFIPS, outerThis._session.counties.index)) {
509
+ // Total population by counties w/in a district,
510
+ // except the dummy unassigned district 0
511
+ if (i > 0)
512
+ countySplits[outerThis.getCountyIndex(geoID)] += featurePop;
513
+ }
514
+ else {
515
+ console.log("County not recognized:", geoID);
516
+ }
510
517
  // Democratic and Republican vote totals
511
518
  demVotes += outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "D" /* DemVotes */);
512
519
  repVotes += outerThis._session.features.fieldForFeature(f, "ELECTION" /* ELECTION */, "R" /* RepVotes */);
@@ -1216,10 +1223,11 @@ function extractDistrictProperties(s, bLog = false) {
1216
1223
  }
1217
1224
  exports.extractDistrictProperties = extractDistrictProperties;
1218
1225
  function isAShape(poly) {
1219
- const bPolyUndefined = (poly === undefined) ? true : false;
1220
- const bNull = (bPolyUndefined) ? true : Poly.polyNull(poly); // TODO
1221
- const bNoCoordinates = U.isArrayEmpty((poly.geometry.coordinates)) ? true : false;
1222
- return (!bPolyUndefined && !bNull && !bNoCoordinates);
1226
+ if (poly == null)
1227
+ return false;
1228
+ if (Poly.polyNull(poly))
1229
+ return false;
1230
+ return poly.geometry && poly.geometry.coordinates && !U.isArrayEmpty(poly.geometry.coordinates);
1223
1231
  }
1224
1232
  // SCORE KIWYSI COMPACTNESS
1225
1233
  function scoreKIWYSICompactness(s, bLog = false) {
@@ -1309,8 +1317,12 @@ function doHasEqualPopulations(s, bLog = false) {
1309
1317
  let popDevTest = s.getTest(4 /* PopulationDeviation */);
1310
1318
  const popDevPct = popDevTest['score'];
1311
1319
  const popDevNormalized = popDevTest['normalizedScore'];
1320
+ // 09-19-2020 - Added to catch edge case of only one non-empty district
1321
+ const p = s._profile;
1322
+ const totPopByDistrict = p.populationProfile.totalPopByDistrict.filter(x => x > 0);
1323
+ const bTwoOrMoreDistricts = (totPopByDistrict.length > 1) ? true : false;
1312
1324
  // Populate the test entry
1313
- if (popDevNormalized > 0) {
1325
+ if (bTwoOrMoreDistricts && (popDevNormalized > 0)) {
1314
1326
  test['score'] = true;
1315
1327
  }
1316
1328
  else {
@@ -1457,12 +1469,25 @@ function doPreprocessData(s, bLog = false) {
1457
1469
  exports.doPreprocessData = doPreprocessData;
1458
1470
  // CREATE A FIPS CODE TO COUNTY NAME LOOKUP
1459
1471
  function doPreprocessCountyFeatures(s, bLog = false) {
1472
+ let fipsCodes = [];
1473
+ // CREATE A MAP OF FIPS CODES TO NAMES
1460
1474
  for (let i = 0; i < s.counties.nCounties; i++) {
1461
1475
  let county = s.counties.countyByIndex(i);
1462
1476
  let fips = s.counties.propertyForCounty(county, 'COUNTYFP');
1477
+ fipsCodes.push(fips);
1463
1478
  let name = s.counties.propertyForCounty(county, 'NAME');
1464
1479
  s.counties.mapFIPSToName(fips, name);
1465
1480
  }
1481
+ // CREATE A FIPS CODE-ORDINAL MAP
1482
+ // Sort the FIPS codes in the county shapes
1483
+ fipsCodes = fipsCodes.sort();
1484
+ // Add a dummy county, for county-district splitting analysis.
1485
+ fipsCodes.unshift('000');
1486
+ // NOTE - This was added for the legacy SPLITTING implementation.
1487
+ // Create the ID-ordinal map
1488
+ for (let i in fipsCodes) {
1489
+ s.counties.index[fipsCodes[i]] = Number(i);
1490
+ }
1466
1491
  }
1467
1492
  // ANALYZE THE CENSUS BY COUNTY
1468
1493
  function doPreprocessCensus(s, bLog = false) {
@@ -1482,12 +1507,18 @@ function doPreprocessCensus(s, bLog = false) {
1482
1507
  s.state.totalPop += value;
1483
1508
  // Get the county FIPS code for the feature
1484
1509
  let countyFIPS = U.parseGeoID(geoID)['county'];
1485
- // If a subtotal for the county doesn't exist, initialize one
1486
- if (!(U.keyExists(countyFIPS, totalByCounty))) {
1487
- totalByCounty[countyFIPS] = 0;
1510
+ // Ignore features when the county is unrecognized
1511
+ if (U.keyExists(countyFIPS, s.counties.index)) {
1512
+ // If a subtotal for the county doesn't exist, initialize one
1513
+ if (!(U.keyExists(countyFIPS, totalByCounty))) {
1514
+ totalByCounty[countyFIPS] = 0;
1515
+ }
1516
+ // Sum total population by county
1517
+ totalByCounty[countyFIPS] += value;
1518
+ }
1519
+ else {
1520
+ console.log("County not recognized:", geoID);
1488
1521
  }
1489
- // Sum total population by county
1490
- totalByCounty[countyFIPS] += value;
1491
1522
  }
1492
1523
  else {
1493
1524
  if (bLog)
@@ -1495,18 +1526,24 @@ function doPreprocessCensus(s, bLog = false) {
1495
1526
  }
1496
1527
  }
1497
1528
  // NOTE - The above could be replaced, if I got totals on county.geojson.
1529
+ /* Moved this to doPreprocessCountyFeatures() - 09-14-2020 to fix VA county mismatch bug
1498
1530
  // CREATE A FIPS CODE-ORDINAL MAP
1531
+
1499
1532
  // Get the county FIPS codes
1500
1533
  let fipsCodes = U.getObjectKeys(totalByCounty);
1501
1534
  // Sort the results
1502
1535
  fipsCodes = fipsCodes.sort();
1536
+
1503
1537
  // NOTE - This was added for the legacy SPLITTING implementation.
1504
1538
  // Add a dummy county, for county-district splitting analysis.
1505
1539
  fipsCodes.unshift('000');
1540
+
1506
1541
  // Create the ID-ordinal map
1507
- for (let i in fipsCodes) {
1508
- s.counties.index[fipsCodes[i]] = Number(i);
1542
+ for (let i in fipsCodes)
1543
+ {
1544
+ s.counties.index[fipsCodes[i]] = Number(i);
1509
1545
  }
1546
+ */
1510
1547
  // MAKE AN ARRAY OF TOTAL POPULATIONS BY COUNTY INDEX
1511
1548
  // Add an extra 0th virtual county bucket for county-district splitting analysis
1512
1549
  let nCountyBuckets = s.counties.nCounties + 1;
@@ -1528,6 +1565,8 @@ function doPreprocessCensus(s, bLog = false) {
1528
1565
  let tooBigName = [];
1529
1566
  let expectedSplits = 0;
1530
1567
  let expectedAffected = 0;
1568
+ // Get the county FIPS codes
1569
+ let fipsCodes = U.getObjectKeys(s.counties.index);
1531
1570
  // Loop over the counties
1532
1571
  for (let county in fipsCodes) {
1533
1572
  let fipsCode = fipsCodes[county];