@dra2020/district-analytics 2.0.0 → 2.0.3

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.
@@ -190,19 +190,14 @@ class AnalyticsSession {
190
190
  // Convert them into a (possibly empty) list of features
191
191
  let discontiguousDistrictFeatures = { type: 'FeatureCollection', features: [] };
192
192
  if (!(U.isArrayEmpty(discontiguousDistrictIDs))) {
193
- for (let i = 0; i < discontiguousDistrictIDs.length; i++) {
194
- let poly = this.districts.getShape(i);
195
- discontiguousDistrictFeatures.features.push(poly);
193
+ for (let id of discontiguousDistrictIDs) {
194
+ let poly = this.districts.getDistrictShapeByID(id);
195
+ if (poly)
196
+ discontiguousDistrictFeatures.features.push(poly);
196
197
  }
197
198
  }
198
199
  return discontiguousDistrictFeatures;
199
200
  }
200
- // TODO - DASHBOARD: Delete, when cut over to the new analytics UI.
201
- // Prepare a scorecard for rendering
202
- // NOTE - This assumes that analyzePlan() has been run!
203
- // prepareScorecard(): any {
204
- // return doPrepareScorecard(this);
205
- // }
206
201
  // HELPERS USED INTERNALLY
207
202
  // Get an individual test, so you can drive UI with the results.
208
203
  getTest(testID) {
@@ -218,12 +213,6 @@ class AnalyticsSession {
218
213
  // Return a pointer to the the test entry for this test
219
214
  return this.tests[testID];
220
215
  }
221
- // TODO - DASHBOARD: Delete, when cut over to the new analytics UI.
222
- // Prepare test results for rendering
223
- // NOTE - This assumes that analyzePlan() has been run!
224
- // prepareTestLog(): any {
225
- // return doPrepareTestLog(this);
226
- // }
227
216
  // NOTE - Not sure why this has to be up here.
228
217
  populationDeviationThreshold() {
229
218
  return 1 - this.testScales[4 /* PopulationDeviation */]['scale'][0];
@@ -301,7 +290,16 @@ class Districts {
301
290
  this._shapes = ds;
302
291
  this.statistics = this.initStatistics();
303
292
  }
304
- getShape(i) { return this._shapes.features[i]; }
293
+ getDistrictShapeByID(id) {
294
+ // NOTE - Find the district shape by ID (not index)
295
+ // return this._shapes.features[id];
296
+ for (let f of this._shapes.features) {
297
+ if (f.properties && (f.properties.id == id)) {
298
+ return f;
299
+ }
300
+ }
301
+ return undefined;
302
+ }
305
303
  getGeoProperties(i) {
306
304
  // Make sure the district shape exists & has geo properties
307
305
  if (i in this._geoProperties)
@@ -431,8 +429,8 @@ class Districts {
431
429
  });
432
430
  // COMPUTE DERIVED VALUES
433
431
  // Population deviation % and equal population (boolean) by district.
434
- // Don't set the values for the dummy unassigned district.
435
- let popDevPct = null;
432
+ // Default the value for the dummy unassigned district to 0%.
433
+ let popDevPct = 0 / targetSize;
436
434
  if (i > 0) {
437
435
  popDevPct = (totalPop - targetSize) / targetSize;
438
436
  bEqualPop = (popDevPct <= deviationThreshold);
@@ -772,7 +770,12 @@ class Graph {
772
770
  // Ignore the lengths of the shared borders (the values), for now
773
771
  // Protect against getting a GEOID that's not in the graph
774
772
  if (U.keyExists(node, this._graph)) {
775
- return U.getObjectKeys(this._graph[node]);
773
+ // NOTE - CONTIGUITY GRAPHS
774
+ // Handle both unweighted & weighted neighbors
775
+ let n = this._graph[node];
776
+ let l = (n instanceof Array) ? n : U.getObjectKeys(n);
777
+ return l;
778
+ // return U.getObjectKeys(this._graph[node]);
776
779
  }
777
780
  else
778
781
  return [];
@@ -1366,9 +1369,9 @@ function doPolsbyPopper(s, bLog = false) {
1366
1369
  exports.doPolsbyPopper = doPolsbyPopper;
1367
1370
  // HELPER TO EXTRACT PROPERTIES OF DISTRICT SHAPES
1368
1371
  function extractDistrictProperties(s, bLog = false) {
1372
+ // NOTE - I am assuming that district IDs are integers 1–N
1369
1373
  for (let i = 1; i <= s.state.nDistricts; i++) {
1370
- let j = i - 1; // TODO - TERRY: How do you get away w/o this?!?
1371
- let poly = s.districts.getShape(j);
1374
+ let poly = s.districts.getDistrictShapeByID(i);
1372
1375
  // Guard against no shape for empty districts AND null shapes
1373
1376
  let polyOptions = { noLatitudeCorrection: true };
1374
1377
  let bNull = (!Poly.polyNormalize(poly, polyOptions));
@@ -2452,8 +2455,10 @@ const testDefns = {
2452
2455
  // Raw numeric analytics, such as population deviation, compactness, etc. are
2453
2456
  // normalized as part of creating a scorecard, so the code to normalize results
2454
2457
  // is encapsulated here.
2455
- // Configure scale parameters for normalizing each raw test result
2456
- // This needs to be separate from the scorecard configuration info above,
2458
+ // Configure scale parameters for normalizing each raw test result.
2459
+ // Scales consist of a minimum & a maximum *raw* value. If the values get
2460
+ // inverted (to make bigger better), these will switch.
2461
+ // This process needs to be separate from the test configuration info above,
2457
2462
  // because some scales need access to the analytics session object.
2458
2463
  function doConfigureScales(s) {
2459
2464
  // Scale defn for PopulationDeviation
@@ -2925,7 +2930,6 @@ function doIsContiguous(s, bLog = false) {
2925
2930
  exports.doIsContiguous = doIsContiguous;
2926
2931
  // Are the features in a district fully connected?
2927
2932
  function isConnected(districtGeos, graph) {
2928
- // export function isConnected(districtGeos: Set<string>, graph: T.ContiguityGraph): boolean {
2929
2933
  // TODO - TERRY, why does this constructor need a <T> type specification?
2930
2934
  let visited = new Set();
2931
2935
  let toProcess = [];