@dra2020/district-analytics 1.0.6 → 1.0.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.
Files changed (75) hide show
  1. package/dist/cli.js +102 -52
  2. package/dist/cli.js.map +1 -1
  3. package/dist/district-analytics.js +102 -52
  4. package/dist/district-analytics.js.map +1 -1
  5. package/lib/HelloWorld.d.ts +3 -0
  6. package/lib/HelloWorld.js +11 -0
  7. package/lib/_api.js +91 -0
  8. package/lib/_api.js.map +1 -0
  9. package/lib/_cli.js +434 -0
  10. package/lib/_cli.js.map +1 -0
  11. package/lib/_data.js +425 -0
  12. package/lib/_data.js.map +1 -0
  13. package/lib/analyze.d.ts +3 -0
  14. package/lib/analyze.js +69 -0
  15. package/lib/analyze.js.map +1 -0
  16. package/lib/api.d.ts +34 -0
  17. package/lib/api.js +117 -0
  18. package/lib/api.js.map +1 -0
  19. package/lib/cli.d.ts +1 -0
  20. package/lib/cli.js +386 -0
  21. package/lib/cli.js.map +1 -0
  22. package/lib/cohesive.d.ts +4 -0
  23. package/lib/cohesive.js +132 -0
  24. package/lib/cohesive.js.map +1 -0
  25. package/lib/compact.d.ts +4 -0
  26. package/lib/compact.js +183 -0
  27. package/lib/compact.js.map +1 -0
  28. package/lib/constants.js +367 -0
  29. package/lib/constants.js.map +1 -0
  30. package/lib/data.js +188 -0
  31. package/lib/data.js.map +1 -0
  32. package/lib/equal.d.ts +4 -0
  33. package/lib/equal.js +59 -0
  34. package/lib/equal.js.map +1 -0
  35. package/lib/features.js +19 -0
  36. package/lib/features.js.map +1 -0
  37. package/lib/geofeature.js +112 -0
  38. package/lib/geofeature.js.map +1 -0
  39. package/lib/index.d.ts +5 -0
  40. package/lib/index.js +11 -0
  41. package/lib/index.js.map +1 -0
  42. package/lib/minority.d.ts +3 -0
  43. package/lib/minority.js +61 -0
  44. package/lib/minority.js.map +1 -0
  45. package/lib/political.d.ts +7 -0
  46. package/lib/political.js +88 -0
  47. package/lib/political.js.map +1 -0
  48. package/lib/preprocess.d.ts +4 -0
  49. package/lib/preprocess.js +101 -0
  50. package/lib/preprocess.js.map +1 -0
  51. package/lib/report.d.ts +14 -0
  52. package/lib/report.js +817 -0
  53. package/lib/report.js.map +1 -0
  54. package/lib/sample.d.ts +1 -0
  55. package/lib/sample.js +32 -0
  56. package/lib/sample.js.map +1 -0
  57. package/lib/scorecard.d.ts +4 -0
  58. package/lib/scorecard.js +237 -0
  59. package/lib/scorecard.js.map +1 -0
  60. package/lib/settings.d.ts +5 -0
  61. package/lib/settings.js +18 -0
  62. package/lib/settings.js.map +1 -0
  63. package/lib/types.d.ts +125 -0
  64. package/lib/types.js +7 -0
  65. package/lib/types.js.map +1 -0
  66. package/lib/utils.d.ts +20 -0
  67. package/lib/utils.js +223 -0
  68. package/lib/utils.js.map +1 -0
  69. package/lib/valid.d.ts +5 -0
  70. package/lib/valid.js +230 -0
  71. package/lib/valid.js.map +1 -0
  72. package/package.json +2 -2
  73. package/src/_api.ts +1 -0
  74. package/src/_data.ts +42 -19
  75. package/src/report.ts +59 -34
package/lib/api.js ADDED
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ //
3
+ // THE NODE PACKAGE API
4
+ //
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const U = require("./utils");
7
+ const preprocess_1 = require("./preprocess");
8
+ const analyze_1 = require("./analyze");
9
+ const report_1 = require("./report");
10
+ class AnalyticsSession {
11
+ constructor(SessionRequest) {
12
+ this._config = {};
13
+ this._testScales = {};
14
+ this._tests = {};
15
+ this._scorecard = {};
16
+ // Grab the session parameters & pointers to data
17
+ this._title = SessionRequest['title'];
18
+ this._xx = SessionRequest['stateXX'];
19
+ this._legislativeDistricts = SessionRequest['legislativeDistricts'];
20
+ this._nDistricts = SessionRequest['nDistricts'];
21
+ this._planByGeoID = SessionRequest['plan'];
22
+ this._data = SessionRequest['data'];
23
+ this._featureIDs = {};
24
+ // TODO - INTEGRATION: data2.json
25
+ this._census = SessionRequest['census'];
26
+ this._election = SessionRequest['election'];
27
+ this._districtShapes = SessionRequest['districtShapes'];
28
+ this._districtProperties = {};
29
+ this._graph = SessionRequest['graph'];
30
+ this._countyNameLookup = {};
31
+ this._countyFeatures = SessionRequest['countyFeatures'];
32
+ this._stateTotal = 0;
33
+ this._nCounties = 0;
34
+ this._tooBigFIPS = [];
35
+ this._tooBigName = [];
36
+ this._expectedSplits = 0;
37
+ this._expectedAffected = 0;
38
+ // TODO - INTEGRATION: DELETE
39
+ // Process the config request
40
+ // let configRequest: T.Dict = {};
41
+ let defaultSuites = [0 /* Legal */, 1 /* Fair */, 2 /* Best */];
42
+ let defaultConfig = { 'suites': defaultSuites };
43
+ // TODO - INTEGRATION data2.json
44
+ // NOTE - Session settings are required:
45
+ // - Analytics suites can be defaulted to all with [], but
46
+ // - Dataset must be explicitly specified
47
+ this._config = SessionRequest['config'];
48
+ // If a config was passed in w/ empty suites = [], use the default suites
49
+ if (U.isArrayEmpty(this._config['suites'])) {
50
+ this._config['suites'] = defaultSuites;
51
+ }
52
+ // TODO - INTEGRATION: DELETE
53
+ // // If no config was passed in or it's empty, use the default config
54
+ // if ((SessionRequest['config'] == undefined) || (!(U.keyExists('config', SessionRequest)))) {
55
+ // this._config = defaultConfig;
56
+ // }
57
+ // else {
58
+ // // If a config was passed in w/o suites, use the default suites
59
+ // if (!(U.keyExists('suites', SessionRequest['config']))) {
60
+ // this._config['suites'] = defaultSuites;
61
+ // }
62
+ // // Otherwise use the config (and suites) as passed in
63
+ // else {
64
+ // this._config = SessionRequest['config'];
65
+ // }
66
+ // }
67
+ this._planByDistrictID = {};
68
+ this._countyIndex = {};
69
+ this._bOneTimeProcessingDone = false;
70
+ this._bPlanAnalyzed = false;
71
+ this._bPostProcessingDone = false;
72
+ // NOTE: I've pulled these out of the individual analytics to here. Eventually,
73
+ // we could want them to passed into an analytics session as data, along with
74
+ // everything else. For now, this keeps branching out of the main code.
75
+ report_1.doConfigureScales(this);
76
+ }
77
+ // Using the the data in the analytics session, calculate all the
78
+ // analytics & validations, saving/updating the individual test results.
79
+ analyzePlan(bLog = false) {
80
+ try {
81
+ preprocess_1.doPreprocessData(this);
82
+ analyze_1.doAnalyzePlan(this, bLog);
83
+ }
84
+ catch (_a) {
85
+ return false;
86
+ }
87
+ return true;
88
+ }
89
+ // TODO - Terry/Dave: Do I need a guard here?
90
+ // Get an individual test, so you can drive UI with the results.
91
+ getTest(testID) {
92
+ // Get the existing test entries
93
+ // T.Test is a numeric enum, so convert the string keys to numbers
94
+ let testValues = U.getNumericObjectKeys(this._tests);
95
+ // If there's no entry for this test, create & initialize one
96
+ if (!(testValues.includes(testID))) {
97
+ this._tests[testID] = {};
98
+ this._tests[testID]['score'] = undefined;
99
+ this._tests[testID]['details'] = {};
100
+ this._tests[testID]['districtWIP'] = {};
101
+ }
102
+ // Return a pointer to the the test entry for this test
103
+ return this._tests[testID];
104
+ }
105
+ // Prepare a scorecard for rendering
106
+ // NOTE - This assumes that analyzePlan() has been run!
107
+ prepareScorecard() {
108
+ return report_1.doPrepareScorecard(this);
109
+ }
110
+ // Prepare test results for rendering
111
+ // NOTE - This assumes that analyzePlan() has been run!
112
+ prepareTestLog() {
113
+ return report_1.doPrepareTestLog(this);
114
+ }
115
+ }
116
+ exports.AnalyticsSession = AnalyticsSession;
117
+ //# sourceMappingURL=api.js.map
package/lib/api.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/lib/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export {};
package/lib/cli.js ADDED
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ //
3
+ // A SIMPLE COMMAND-LINE INTERFACE FOR EXERCISING THE ANALYTICS & VALIDATIONS
4
+ //
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const yargs = require("yargs");
7
+ // TODO - DELETE
8
+ // import * as fs from 'fs';
9
+ // import * as path from 'path';
10
+ // import * as parse from 'csv-parse/lib/sync';
11
+ const PC = require("polygon-clipping");
12
+ const Poly = require("@dra2020/poly");
13
+ const api_1 = require("./api");
14
+ const preprocess_1 = require("./preprocess");
15
+ const valid_1 = require("./valid");
16
+ const equal_1 = require("./equal");
17
+ const compact_1 = require("./compact");
18
+ const cohesive_1 = require("./cohesive");
19
+ const political_1 = require("./political");
20
+ const minority_1 = require("./minority");
21
+ const U = require("./utils");
22
+ const D = require("./data");
23
+ // Simulate DRA unioning district shapes in the background
24
+ function addToPoly(poly, polys) {
25
+ return PC.union(poly, ...polys);
26
+ }
27
+ console.log("Starting command @ ", new Date());
28
+ // COMMAND LINE
29
+ let argv = yargs
30
+ .usage('Usage: $0 command [options]')
31
+ .example('$0 equal -f foo.geojson', 'Calculate population deviation')
32
+ .demandCommand(1, 'You must specify a command to execute.')
33
+ .command('valid', 'Perform validations.')
34
+ .command('equal', 'Calculate population deviation.')
35
+ .command('compact', 'Calculate compactness.')
36
+ .command('cohesive', 'Calculate cohesiveness.')
37
+ .command('political', 'Assess fairness.')
38
+ .command('minority', 'Count majority-minority districts.')
39
+ .command('analyze', 'API call to analyze a plan.')
40
+ .command('report', 'API call to generate a scorecard.')
41
+ .option('state', {
42
+ alias: 'xx',
43
+ describe: 'Specify the state.',
44
+ type: 'string'
45
+ })
46
+ .option('number', {
47
+ alias: 'n',
48
+ describe: 'Specify the number of districts.',
49
+ type: 'number'
50
+ })
51
+ .option('legislative', {
52
+ alias: 'l',
53
+ describe: 'Specify that districts are legislative.',
54
+ type: 'boolean',
55
+ default: false
56
+ })
57
+ .option('plan', {
58
+ alias: 'p',
59
+ describe: 'Specify the plan to evaluate.',
60
+ type: 'string'
61
+ })
62
+ .option('census', {
63
+ alias: 'c',
64
+ describe: 'Specify the Census data to use.',
65
+ type: 'string'
66
+ })
67
+ .option('shapes', {
68
+ alias: 's',
69
+ describe: 'Specify the shapes to use.',
70
+ type: 'string'
71
+ })
72
+ .option('graph', {
73
+ alias: 'g',
74
+ describe: 'Specify the contiguity graph to use.',
75
+ type: 'string'
76
+ })
77
+ .option('election', {
78
+ alias: 'e',
79
+ describe: 'Specify the election data to use.',
80
+ type: 'string'
81
+ })
82
+ .option('counties', {
83
+ alias: 'f',
84
+ describe: 'Specify the FIPS-to-county-name map to use.',
85
+ type: 'string'
86
+ })
87
+ .option('empty', {
88
+ describe: 'Specify whether a district should be empty.',
89
+ type: 'boolean',
90
+ default: false
91
+ })
92
+ .option('suites', {
93
+ describe: 'Specify the test suites to run.',
94
+ type: 'array',
95
+ default: []
96
+ })
97
+ .option('verbose', {
98
+ alias: 'v',
99
+ describe: 'Specify whether code should log to STDOUT.',
100
+ type: 'boolean',
101
+ default: false
102
+ })
103
+ .demandOption(['number', 'plan', 'census', 'shapes', 'election', 'counties'], 'Please specify all the args.')
104
+ .help()
105
+ .argv;
106
+ // PROCESS COMMAND LINE ARGS
107
+ let command = argv._[0];
108
+ let xx = argv.state;
109
+ let bLegislativeDistricts = argv.legislative;
110
+ let nDistricts = argv.n;
111
+ let planByGeoID = D.readPlanCSV(argv.plan);
112
+ // Don't load other datasets, if just calculating compactness
113
+ let graph = {};
114
+ let census = {};
115
+ // TODO - INTEGRATION: data2.json
116
+ let data = {};
117
+ // TODO - DELETE
118
+ let election = {};
119
+ let counties = {};
120
+ if (command != 'compact') {
121
+ graph = D.readJSON(argv.graph);
122
+ // TODO - INTEGRATION: data2.json
123
+ data = D.readJSON("../data/SAMPLE-BG-data2.json");
124
+ // TODO - DELETE
125
+ census = D.readCensusCSV(argv.census);
126
+ election = D.readElectionCSV(argv.election);
127
+ counties = D.readJSON(argv.counties);
128
+ }
129
+ let shapes = D.readJSON(argv.shapes);
130
+ let bEmpty = argv.empty;
131
+ // TODO - INTEGRATION:
132
+ // - Expand 'suites' to 'settings'
133
+ // - Allow 'datasets' to be passed in from the command line too
134
+ // - Update configs
135
+ let suites = argv.suites;
136
+ // TODO - INTEGRATION: Delete
137
+ // Keys for the datasets to use for analytics & display
138
+ // export type DSKeys = {
139
+ // CENSUS: string; // A total population Census dataset
140
+ // VAP: string; // A voting age (or citizen voting age) dataset
141
+ // ELECTION: string; // An election dataset
142
+ // }
143
+ let datasets = {
144
+ CENSUS: "D16F",
145
+ VAP: "D16T",
146
+ ELECTION: "E16GPR"
147
+ };
148
+ // } as D.DSKeys;
149
+ // Session settings are required:
150
+ // - Analytics suites can be defaulted to all with [], but
151
+ // - Dataset must be explicitly specified
152
+ let sessionSettings = {
153
+ 'suites': suites,
154
+ 'datasets': datasets
155
+ };
156
+ let bLog = argv.verbose;
157
+ // TODO - INTEGRATION: Does DRA have this to pass?
158
+ // Invert the plan, so you can create the district shapes for the SessionRequest.
159
+ let planByDistrictID = preprocess_1.invertPlan(planByGeoID);
160
+ // SIMULATE THE HOST
161
+ // 1 - Create district shapes & extract properties (area, diameter, perimeter)
162
+ const polyOptions = {
163
+ noLatitudeCorrection: false
164
+ };
165
+ // Index the shapes by geoID
166
+ let shapesByGeoID = {};
167
+ let idStr = "GEOID";
168
+ // TODO - Terry: But sometimes "GEOID10" hasn't been set to "GEOID"
169
+ let firstFeature = shapes.features[0];
170
+ if (!(firstFeature.properties == null)) {
171
+ if (U.keyExists("GEOID10", firstFeature.properties))
172
+ idStr = "GEOID10";
173
+ }
174
+ for (let f of shapes.features) {
175
+ if (!(f.properties == null)) {
176
+ // let idStr = "GEOID";
177
+ // TODO - Terry: Sometimes "GEOID10" hasn't been => to "GEOID!"
178
+ // if (U.keyExists("GEOID10", f.properties)) idStr = "GEOID10";
179
+ let geoID = f.properties[idStr];
180
+ shapesByGeoID[geoID] = f;
181
+ }
182
+ }
183
+ // Find the smallest Feature
184
+ // COPIED from dra-client/geodistrict.ts, and lightly modified
185
+ let geo = shapes;
186
+ let minFeatureArea = Poly.polyArea(geo.features[0], polyOptions);
187
+ for (let i = 1; i < geo.features.length; i++) {
188
+ let a = Poly.polyArea(geo.features[i], polyOptions);
189
+ if (a < minFeatureArea)
190
+ minFeatureArea = a;
191
+ }
192
+ // Eliminate anomalous holes
193
+ // COPIED from dra-client/geodistrict.ts, and lightly modified
194
+ // This is a bit of a hack in the sense that it is still an open question as to whether this is a problem
195
+ // with either the underlying shape data or a problem in our simplification of that shape data.
196
+ // But in any case, what this does is eliminate any holes that are smaller than the smallest feature. Such
197
+ // a hole must be an anomaly. CA/2010_VT in particular seems to have many such issues.
198
+ function eliminateAnomalousHoles(mp) {
199
+ // Normalize to multipolygon
200
+ if (U.depthof(mp) == 4)
201
+ mp = [mp];
202
+ for (let i = 0; i < mp.length; i++) {
203
+ let p = mp[i];
204
+ let cleanp = [p[0]];
205
+ for (let j = 1; j < p.length; j++) {
206
+ let a = Poly.polyArea(p[j], polyOptions);
207
+ if (a >= minFeatureArea)
208
+ cleanp.push(p[j]);
209
+ }
210
+ if (cleanp.length < p.length)
211
+ mp[i] = cleanp;
212
+ }
213
+ }
214
+ // Create district shapes
215
+ let districtShapes = {};
216
+ districtShapes['type'] = "FeatureCollection";
217
+ districtShapes['features'] = [];
218
+ for (let districtID = 1; districtID <= nDistricts; districtID++) {
219
+ let districtFeatures = [];
220
+ // Collect Features by district
221
+ planByDistrictID[districtID].forEach(function (geoID) {
222
+ districtFeatures.push(shapesByGeoID[geoID]);
223
+ });
224
+ // Union them together
225
+ let poly1Coordinates = Poly.polyNormalize(districtFeatures[0], polyOptions);
226
+ let polyNCoordinates = districtFeatures.slice(1).map((i) => Poly.polyNormalize(i, polyOptions));
227
+ let poly = addToPoly(poly1Coordinates, polyNCoordinates);
228
+ // Convert the result to a Feature
229
+ let bPolygon = U.depthof(poly) == 4;
230
+ if (!bPolygon && poly.length == 1) {
231
+ bPolygon = true;
232
+ poly = poly[0];
233
+ }
234
+ eliminateAnomalousHoles(poly);
235
+ let f = {
236
+ type: 'Feature',
237
+ properties: { districtID: `${districtID}` },
238
+ geometry: {
239
+ type: bPolygon ? 'Polygon' : 'MultiPolygon',
240
+ coordinates: poly
241
+ }
242
+ };
243
+ districtShapes.features.push(f);
244
+ }
245
+ // CONSTRUCT A SESSION REQUEST
246
+ let SessionRequest = {};
247
+ SessionRequest['title'] = "CLI Test";
248
+ SessionRequest['stateXX'] = xx;
249
+ SessionRequest['nDistricts'] = nDistricts;
250
+ SessionRequest['legislativeDistricts'] = bLegislativeDistricts;
251
+ SessionRequest['plan'] = planByGeoID;
252
+ SessionRequest['data'] = data;
253
+ // TODO - INTEGRATION: data2.json
254
+ SessionRequest['census'] = census;
255
+ SessionRequest['election'] = election;
256
+ SessionRequest['districtShapes'] = districtShapes;
257
+ SessionRequest['graph'] = graph;
258
+ SessionRequest['countyFeatures'] = counties;
259
+ // TODO - INTEGRATION: DELETE
260
+ // if (!(U.isArrayEmpty(suites))) {
261
+ // sessionSettings['suites'] = suites;
262
+ // }
263
+ SessionRequest['config'] = sessionSettings;
264
+ // CREATE AND INITIALIZE AN ANALYTICS SESSION
265
+ let s = new api_1.AnalyticsSession(SessionRequest);
266
+ // DISPATCH TO REQUESTED COMMAND W/ NEEDED SCAFFOLDING
267
+ let t;
268
+ let text;
269
+ function echoTestResult(test, t) {
270
+ console.log("");
271
+ console.log("Test:", test);
272
+ console.log("Score:", t['score']);
273
+ let keys = U.getObjectKeys(t['details']);
274
+ if (keys.length > 0) {
275
+ console.log("Details:");
276
+ for (let i in keys) {
277
+ let key = keys[i];
278
+ console.log("-", key, "=", t['details'][key]);
279
+ }
280
+ }
281
+ console.log("___");
282
+ }
283
+ if (bEmpty) {
284
+ // Make a district empty
285
+ let randomDistrict = Math.floor(Math.random() * s._nDistricts) + 1;
286
+ // TODO - Terry, why does this constructor not need a <T> type specification?
287
+ s._planByDistrictID[randomDistrict] = new Set();
288
+ }
289
+ switch (command) {
290
+ case 'valid': {
291
+ preprocess_1.doPreprocessData(s);
292
+ t = valid_1.doIsComplete(s);
293
+ echoTestResult("Complete:", t);
294
+ t = valid_1.doIsContiguous(s);
295
+ echoTestResult("Contiguous:", t);
296
+ t = valid_1.doIsFreeOfHoles(s);
297
+ echoTestResult("Free of holes:", t);
298
+ t = equal_1.doPopulationDeviation(s);
299
+ echoTestResult("Population deviation (%):", t);
300
+ t = equal_1.doHasEqualPopulations(s);
301
+ echoTestResult("Equal populations:", t);
302
+ break;
303
+ }
304
+ case 'equal': {
305
+ preprocess_1.doPreprocessData(s);
306
+ t = equal_1.doPopulationDeviation(s);
307
+ echoTestResult("Population deviation (%):", t);
308
+ break;
309
+ }
310
+ case 'compact': {
311
+ preprocess_1.doPreprocessData(s);
312
+ t = compact_1.doReock(s, bLog);
313
+ echoTestResult("Reock:", t);
314
+ t = compact_1.doPolsbyPopper(s, bLog);
315
+ echoTestResult("Polsby-Popper:", t);
316
+ break;
317
+ }
318
+ case 'cohesive': {
319
+ preprocess_1.doPreprocessData(s);
320
+ t = cohesive_1.doCountySplits(s);
321
+ echoTestResult("County splits:", t);
322
+ cohesive_1.doPlanComplexity(s);
323
+ break;
324
+ }
325
+ case 'political': {
326
+ preprocess_1.doPreprocessData(s);
327
+ political_1.doSeatsBias(s);
328
+ political_1.doVotesBias(s);
329
+ political_1.doResponsiveness(s);
330
+ political_1.doResponsiveDistricts(s);
331
+ t = political_1.doEfficiencyGap(s);
332
+ echoTestResult("Efficiency gap (%):", t);
333
+ break;
334
+ }
335
+ case 'minority': {
336
+ preprocess_1.doPreprocessData(s);
337
+ minority_1.doMajorityMinorityDistricts(s);
338
+ break;
339
+ }
340
+ case 'analyze': {
341
+ console.log("");
342
+ console.log("Analyzing a plan ...");
343
+ console.log("");
344
+ s.analyzePlan(bLog);
345
+ break;
346
+ }
347
+ case 'scorecard': {
348
+ s.analyzePlan(bLog);
349
+ text = s.prepareScorecard();
350
+ console.log("");
351
+ for (let line of text.data) {
352
+ console.log(line['variant'], line['text']);
353
+ }
354
+ console.log("");
355
+ break;
356
+ }
357
+ case 'testlog': {
358
+ s.analyzePlan(bLog);
359
+ text = s.prepareTestLog();
360
+ console.log("");
361
+ for (let line of text.data) {
362
+ console.log(line['variant'], line['text']);
363
+ }
364
+ console.log("");
365
+ break;
366
+ }
367
+ case 'limit': {
368
+ s.analyzePlan(bLog);
369
+ text = s.prepareScorecard();
370
+ console.log("");
371
+ for (let line of text.data) {
372
+ console.log(line['variant'], line['text']);
373
+ }
374
+ console.log("");
375
+ text = s.prepareTestLog();
376
+ console.log("");
377
+ for (let line of text.data) {
378
+ console.log(line['variant'], line['text']);
379
+ }
380
+ console.log("");
381
+ break;
382
+ }
383
+ }
384
+ console.log("Ending command @ ", new Date());
385
+ // FIN
386
+ //# sourceMappingURL=cli.js.map
package/lib/cli.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import * as T from './types';
2
+ import { AnalyticsSession } from './api';
3
+ export declare function doCountySplits(s: AnalyticsSession): T.TestEntry;
4
+ export declare function doPlanComplexity(s: AnalyticsSession): T.TestEntry;
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ //
3
+ // "COHESIVE" - We're naming this category which is about county splitting.
4
+ //
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const U = require("./utils");
7
+ const D = require("./_data");
8
+ function doCountySplits(s) {
9
+ let test = s.getTest(7 /* CountySplits */);
10
+ // THE THREE VALUES TO DETERMINE FOR A PLAN
11
+ let unexpectedSplits = 0;
12
+ let unexpectedAffected = 0;
13
+ let countiesSplitUnexpectedly = [];
14
+ // FIRST, ANALYZE THE COUNTY SPLITING FOR THE PLAN
15
+ // Pivot census totals into county-district "splits"
16
+ let countiesByDistrict = s.districts.statistics[D.DistrictField.CountySplits];
17
+ // countiesByDistrict = countiesByDistrict.slice(1, -1);
18
+ // Find the single-county districts, i.e., districts NOT split across counties.
19
+ // Ignore the dummy unassigned 0 and N+1 summary "districts."
20
+ let singleCountyDistricts = [];
21
+ for (let d = 1; d <= s.state.nDistricts; d++) {
22
+ // See if there's only one county partition
23
+ let nCountiesInDistrict = 0;
24
+ for (let c = 0; c < s.counties.nCounties; c++) {
25
+ if (countiesByDistrict[d][c] > 0) {
26
+ nCountiesInDistrict += 1;
27
+ if (nCountiesInDistrict > 1) {
28
+ break;
29
+ }
30
+ }
31
+ }
32
+ // If so, save the district
33
+ if (nCountiesInDistrict == 1) {
34
+ singleCountyDistricts.push(d);
35
+ }
36
+ }
37
+ // Process the splits/partitions in the plan:
38
+ // - Count the total # of partitions,
39
+ // - Find the counties split across districts, and
40
+ // - Accumulate the number people affected (except when single-county districts)
41
+ let nPartitionsOverall = 0;
42
+ let splitCounties = new Set(); // The counties that are split across districts
43
+ let totalAffected = 0; // The total population affected by those splits
44
+ for (let c = 0; c < s.counties.nCounties; c++) {
45
+ let nCountyParts = 0;
46
+ let subtotal = 0;
47
+ for (let d = 1; d <= s.state.nDistricts; d++) {
48
+ if (countiesByDistrict[d][c] > 0) {
49
+ nPartitionsOverall += 1;
50
+ nCountyParts += 1;
51
+ if (!(U.arrayContains(singleCountyDistricts, d))) {
52
+ subtotal += countiesByDistrict[d][c];
53
+ }
54
+ }
55
+ }
56
+ if (nCountyParts > 1) {
57
+ splitCounties.add(c);
58
+ totalAffected += subtotal;
59
+ }
60
+ }
61
+ // Convert county ordinals to FIPS codes
62
+ let splitCountiesFIPS = U.getSelectObjectKeys(s.counties.index, [...splitCounties]);
63
+ // THEN TAKE ACCOUNT OF THE COUNTY SPLITTING THAT IS EXPECTED (REQUIRED)
64
+ // Compute the total number of splits this way, in case any counties are split
65
+ // more than once. I.e., it's not just len(all_counties_split).
66
+ let nSplits = nPartitionsOverall - s.counties.nCounties;
67
+ // Determine the number of *unexpected* splits. NOTE: Prevent negative numbers,
68
+ // in case you have a plan the *doesn't* split counties that would have to be
69
+ // split due to their size.
70
+ unexpectedSplits = Math.max(0, nSplits - s.state.expectedSplits);
71
+ // Subtract off the total population that *has* to be affected by splits,
72
+ // because their counties are too big. NOTE: Again, prevent negative numbers,
73
+ // in case you have a plan the *doesn't* split counties that would have to be
74
+ // split due to their size.
75
+ unexpectedAffected = U.trim(Math.max(0, totalAffected - s.state.expectedAffected) / s.state.totalPop);
76
+ // Find the counties that are split *unexpectedly*. From all the counties that
77
+ // are split, remove those that *have* to be split, because they are bigger than
78
+ // a district.
79
+ let countiesSplitUnexpectedlyFIPS = [];
80
+ for (let fips of splitCountiesFIPS) {
81
+ if (!(U.arrayContains(s.state.tooBigFIPS, fips))) {
82
+ countiesSplitUnexpectedlyFIPS.push(fips);
83
+ }
84
+ }
85
+ // ... and convert the FIPS codes to county names.
86
+ for (let fips of countiesSplitUnexpectedlyFIPS) {
87
+ countiesSplitUnexpectedly.push(s.counties.nameFromFIPS(fips));
88
+ }
89
+ countiesSplitUnexpectedly = countiesSplitUnexpectedly.sort();
90
+ // Cache the results in the test
91
+ test['score'] = unexpectedAffected; // TODO - Use Moon's complexity metric here
92
+ test['details'] = {
93
+ 'unexpectedSplits': unexpectedSplits,
94
+ 'unexpectedAffected': unexpectedAffected,
95
+ 'countiesSplitUnexpectedly': countiesSplitUnexpectedly
96
+ };
97
+ return test;
98
+ }
99
+ exports.doCountySplits = doCountySplits;
100
+ // 2 - THE COMPLEXITY ANALYTIC NEEDS THE FOLLOWING DATA:
101
+ //
102
+ // If a map is already in simplified (mixed) form, the complexity analytic needs
103
+ // two pieces of data:
104
+ // - The counts of features by summary level--i.e., the numbers of counties, tracts,
105
+ // block groups, and blocks in a state; and
106
+ // - The map -- So it can count the features by summary level in the map,
107
+ // as well as the number of BG’s that are split.
108
+ //
109
+ // TODO - Where would the state counts come from? Preprocessed and passed in, or
110
+ // done in a one-time initialization call (which would require a full set of
111
+ // block geo_id's for the state).
112
+ //
113
+ // However, if a map is not yet (fully) simplified, then determining the
114
+ // complexity of a map also requires a preprocessed summary level hierarchy, so
115
+ // you can get the child features (e.g., tracts) of a parent feature (e.g.,
116
+ // a county).
117
+ //
118
+ // NOTE - I have script for producing this hierarchy which we could repurpose.
119
+ //
120
+ // TODO - For mixed map processing--specfically to find the neighbors of a feature
121
+ // that are actually in the map (as opposed to just neighbors at the same
122
+ // summary level in the static graph)--you need a special hierarchy that
123
+ // distinguishes between the 'interior' and 'edge children of a feature.
124
+ //
125
+ // NOTE - The script noted above does this.
126
+ function doPlanComplexity(s) {
127
+ let test = s.getTest(8 /* Complexity */);
128
+ console.log("TODO - Calculating plan complexity ...");
129
+ return test;
130
+ }
131
+ exports.doPlanComplexity = doPlanComplexity;
132
+ //# sourceMappingURL=cohesive.js.map