@dra2020/district-analytics 8.0.1 → 8.1.0

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.
@@ -686,6 +686,41 @@ class Districts {
686
686
  }
687
687
  }
688
688
  exports.Districts = Districts;
689
+ // CLASSES, ETC. FOR FEATURE & COUNTY DATA
690
+ // Types of datasets by feature
691
+ /* 08-13-2020 - Moved to types.ts
692
+ export const enum Dataset
693
+ {
694
+ SHAPES = "SHAPES",
695
+ CENSUS = "CENSUS",
696
+ VAP = "VAP",
697
+ ELECTION = "ELECTION"
698
+ }
699
+ */
700
+ /* 08-13-2020 - Moved to types.ts
701
+ export type DatasetKeys = {
702
+ SHAPES: string; // A shapefile
703
+ CENSUS: string; // A total population Census dataset
704
+ VAP: string; // A voting age (or citizen voting age) dataset
705
+ ELECTION: string; // An election dataset
706
+ }
707
+ */
708
+ // Identifiers of fields for each feature in the datasets
709
+ /* 08-13-2020 - Moved to types.ts
710
+ export const enum FeatureField
711
+ {
712
+ TotalPop = "Tot",
713
+ WhitePop = "Wh",
714
+ BlackPop = "BlC",
715
+ HispanicPop = "His",
716
+ AsianPop = "AsnC",
717
+ PacificPop = "PacC",
718
+ NativePop = "NatC",
719
+ DemVotes = "D",
720
+ RepVotes = "R",
721
+ TotalVotes = "Tot"
722
+ }
723
+ */
689
724
  // Wrap data by feature, to abstract the specifics of the internal structure
690
725
  class Features {
691
726
  constructor(s, data, keys) {
@@ -2038,14 +2073,31 @@ function parseGeoID(geoID) {
2038
2073
  return parts;
2039
2074
  }
2040
2075
  exports.parseGeoID = parseGeoID;
2041
- function isWaterOnly(geoID) {
2042
- let waterOnlySignature = 'ZZZZZZ';
2076
+ // 08-13-2020 - Enhanced completeness checking.
2077
+ function isWaterOnly(geoID, s) {
2078
+ const waterOnlySignature = 'ZZZZZZ';
2043
2079
  if (geoID.indexOf(waterOnlySignature) >= 0)
2044
2080
  return true;
2081
+ if (s) {
2082
+ // If called with a session, get the feature ...
2083
+ const featureID = s.features.featureID(geoID);
2084
+ const f = s.features.featureByIndex(featureID);
2085
+ // ... and also check the 'ALAND' property
2086
+ const bNoLand = ((f.properties['ALAND10'] !== undefined) && (f.properties['ALAND10'] == 0)) ? true : false;
2087
+ return bNoLand;
2088
+ }
2045
2089
  else
2046
2090
  return false;
2047
2091
  }
2048
2092
  exports.isWaterOnly = isWaterOnly;
2093
+ function isUninhabited(geoID, s) {
2094
+ const featureID = s.features.featureID(geoID);
2095
+ const f = s.features.featureByIndex(featureID);
2096
+ const totalPop = s.features.fieldForFeature(f, "CENSUS" /* CENSUS */, "Tot" /* TotalPop */);
2097
+ const bUninhabited = (totalPop > 0) ? false : true;
2098
+ return bUninhabited;
2099
+ }
2100
+ exports.isUninhabited = isUninhabited;
2049
2101
  // NORMALIZING RESULTS
2050
2102
  function normalize(rawScore, testScale) {
2051
2103
  let rangeMin = testScale.scale[0];
@@ -2255,10 +2307,26 @@ function doIsComplete(s, bLog = false) {
2255
2307
  // Check the dummy district that holds any unassigned features.
2256
2308
  let unassignedFeatures = [];
2257
2309
  let bAllAssigned = (!bNotEmptyByDistrict[S.NOT_ASSIGNED]);
2310
+ let bAllNonWaterOnlyAssigned = bAllAssigned ? true : false;
2258
2311
  if (!bAllAssigned) {
2259
2312
  let unassignedDistrict = s.plan.geoIDsForDistrictID(S.NOT_ASSIGNED);
2260
2313
  unassignedFeatures = Array.from(unassignedDistrict);
2261
2314
  // unassignedFeatures = unassignedFeatures.slice(0, S.NUMBER_OF_ITEMS_TO_REPORT);
2315
+ // 08-13-2020 - Enhanced completeness checking.
2316
+ // Are any of the unassigned features not water-only -or- inhabited?
2317
+ // Check the official congressional maps for CT, KY, IL, and MI.
2318
+ bAllNonWaterOnlyAssigned = !unassignedFeatures.some(function (geoID) {
2319
+ if (U.isWaterOnly(geoID, s)) {
2320
+ console.log("Unassigned water-only feature ignored in completeness check: ", geoID);
2321
+ return false;
2322
+ }
2323
+ if (U.isUninhabited(geoID, s)) {
2324
+ console.log("Uninhabited feature ignored in completeness check: ", geoID);
2325
+ return false;
2326
+ }
2327
+ // Not water-only and inhabited
2328
+ return true;
2329
+ });
2262
2330
  }
2263
2331
  // Do all real districts have at least one feature assigned to them?
2264
2332
  let emptyDistricts = [];
@@ -2282,7 +2350,14 @@ function doIsComplete(s, bLog = false) {
2282
2350
  // Note, this can happen if a district is created, and then all features
2283
2351
  // are removed from it (in DRA).
2284
2352
  // Populate the test entry
2285
- test['score'] = bAllAssigned && bNoneEmpty;
2353
+ // 08-13-2020 - Revised completeness check:
2354
+ // A plan is complete if:
2355
+ // * All inhabited, not water-only districts are assigned to districts.
2356
+ // * No districts are empty, i.e., each has one or more geos assigned to them.
2357
+ // Note: We're not checking (in _data.ts) whether those geos are water-only
2358
+ // or have any population, but that's a real edge case.
2359
+ test['score'] = bAllNonWaterOnlyAssigned && bNoneEmpty;
2360
+ // test['score'] = bAllAssigned && bNoneEmpty;
2286
2361
  if (!bAllAssigned) {
2287
2362
  test['details']['unassignedFeatures'] = unassignedFeatures;
2288
2363
  }