@dra2020/district-analytics 1.0.7 → 1.0.8

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 (132) hide show
  1. package/README.md +5 -5
  2. package/dist/district-analytics.js +1315 -1205
  3. package/package.json +6 -3
  4. package/.prettierrc +0 -5
  5. package/dist/_api.d.ts +0 -27
  6. package/dist/_data.d.ts +0 -130
  7. package/dist/analyze.d.ts +0 -4
  8. package/dist/cli.js +0 -12091
  9. package/dist/cli.js.map +0 -1
  10. package/dist/cohesive.d.ts +0 -4
  11. package/dist/compact.d.ts +0 -5
  12. package/dist/constants.d.ts +0 -6
  13. package/dist/district-analytics.js.map +0 -1
  14. package/dist/equal.d.ts +0 -4
  15. package/dist/geofeature.d.ts +0 -3
  16. package/dist/index.d.ts +0 -2
  17. package/dist/minority.d.ts +0 -3
  18. package/dist/political.d.ts +0 -8
  19. package/dist/preprocess.d.ts +0 -2
  20. package/dist/report.d.ts +0 -15
  21. package/dist/settings.d.ts +0 -5
  22. package/dist/src/_api.d.ts +0 -27
  23. package/dist/src/_data.d.ts +0 -130
  24. package/dist/src/analyze.d.ts +0 -4
  25. package/dist/src/cohesive.d.ts +0 -4
  26. package/dist/src/compact.d.ts +0 -5
  27. package/dist/src/constants.d.ts +0 -6
  28. package/dist/src/equal.d.ts +0 -4
  29. package/dist/src/geofeature.d.ts +0 -3
  30. package/dist/src/index.d.ts +0 -2
  31. package/dist/src/minority.d.ts +0 -3
  32. package/dist/src/political.d.ts +0 -8
  33. package/dist/src/preprocess.d.ts +0 -2
  34. package/dist/src/report.d.ts +0 -15
  35. package/dist/src/settings.d.ts +0 -5
  36. package/dist/src/types.d.ts +0 -110
  37. package/dist/src/utils.d.ts +0 -28
  38. package/dist/src/valid.d.ts +0 -8
  39. package/dist/test/_cli.d.ts +0 -5
  40. package/dist/types.d.ts +0 -110
  41. package/dist/utils.d.ts +0 -28
  42. package/dist/valid.d.ts +0 -8
  43. package/jestconfig.json +0 -14
  44. package/lib/HelloWorld.d.ts +0 -3
  45. package/lib/HelloWorld.js +0 -11
  46. package/lib/_api.js +0 -91
  47. package/lib/_api.js.map +0 -1
  48. package/lib/_cli.js +0 -434
  49. package/lib/_cli.js.map +0 -1
  50. package/lib/_data.js +0 -425
  51. package/lib/_data.js.map +0 -1
  52. package/lib/analyze.d.ts +0 -3
  53. package/lib/analyze.js +0 -69
  54. package/lib/analyze.js.map +0 -1
  55. package/lib/api.d.ts +0 -34
  56. package/lib/api.js +0 -117
  57. package/lib/api.js.map +0 -1
  58. package/lib/cli.d.ts +0 -1
  59. package/lib/cli.js +0 -386
  60. package/lib/cli.js.map +0 -1
  61. package/lib/cohesive.d.ts +0 -4
  62. package/lib/cohesive.js +0 -132
  63. package/lib/cohesive.js.map +0 -1
  64. package/lib/compact.d.ts +0 -4
  65. package/lib/compact.js +0 -183
  66. package/lib/compact.js.map +0 -1
  67. package/lib/constants.js +0 -367
  68. package/lib/constants.js.map +0 -1
  69. package/lib/data.js +0 -188
  70. package/lib/data.js.map +0 -1
  71. package/lib/equal.d.ts +0 -4
  72. package/lib/equal.js +0 -59
  73. package/lib/equal.js.map +0 -1
  74. package/lib/features.js +0 -19
  75. package/lib/features.js.map +0 -1
  76. package/lib/geofeature.js +0 -112
  77. package/lib/geofeature.js.map +0 -1
  78. package/lib/index.d.ts +0 -5
  79. package/lib/index.js +0 -11
  80. package/lib/index.js.map +0 -1
  81. package/lib/minority.d.ts +0 -3
  82. package/lib/minority.js +0 -61
  83. package/lib/minority.js.map +0 -1
  84. package/lib/political.d.ts +0 -7
  85. package/lib/political.js +0 -88
  86. package/lib/political.js.map +0 -1
  87. package/lib/preprocess.d.ts +0 -4
  88. package/lib/preprocess.js +0 -101
  89. package/lib/preprocess.js.map +0 -1
  90. package/lib/report.d.ts +0 -14
  91. package/lib/report.js +0 -817
  92. package/lib/report.js.map +0 -1
  93. package/lib/sample.d.ts +0 -1
  94. package/lib/sample.js +0 -32
  95. package/lib/sample.js.map +0 -1
  96. package/lib/scorecard.d.ts +0 -4
  97. package/lib/scorecard.js +0 -237
  98. package/lib/scorecard.js.map +0 -1
  99. package/lib/settings.d.ts +0 -5
  100. package/lib/settings.js +0 -18
  101. package/lib/settings.js.map +0 -1
  102. package/lib/types.d.ts +0 -125
  103. package/lib/types.js +0 -7
  104. package/lib/types.js.map +0 -1
  105. package/lib/utils.d.ts +0 -20
  106. package/lib/utils.js +0 -223
  107. package/lib/utils.js.map +0 -1
  108. package/lib/valid.d.ts +0 -5
  109. package/lib/valid.js +0 -230
  110. package/lib/valid.js.map +0 -1
  111. package/main.js +0 -4
  112. package/src/_api.ts +0 -121
  113. package/src/_data.ts +0 -595
  114. package/src/analyze.ts +0 -92
  115. package/src/cohesive.ts +0 -156
  116. package/src/compact.ts +0 -208
  117. package/src/constants.ts +0 -371
  118. package/src/equal.ts +0 -75
  119. package/src/geofeature.ts +0 -138
  120. package/src/index.ts +0 -6
  121. package/src/minority.ts +0 -70
  122. package/src/political.ts +0 -114
  123. package/src/preprocess.ts +0 -132
  124. package/src/report.ts +0 -1022
  125. package/src/settings.ts +0 -20
  126. package/src/types.ts +0 -185
  127. package/src/utils.ts +0 -245
  128. package/src/valid.ts +0 -275
  129. package/tsconfig.json +0 -25
  130. package/tslint.json +0 -3
  131. package/types/polygon-clipping/index.d.ts +0 -1
  132. package/webpack.config.js +0 -73
package/src/report.ts DELETED
@@ -1,1022 +0,0 @@
1
- //
2
- // GENERATE REPORTS
3
- // - A test log: a simple enumeration of all analytics & validations w/ raw results
4
- // - A scorecard: a structured subset of analytics & validations w/ normalized
5
- // results, cateories, and an overall score
6
- //
7
-
8
- import * as T from './types'
9
- import * as U from './utils';
10
- import * as S from './settings';
11
-
12
- import * as D from './_data'
13
- import { AnalyticsSession } from './_api';
14
- import { doDeriveSecondaryTests } from './analyze';
15
-
16
-
17
- // TEST META-DATA
18
-
19
- enum TestType {
20
- PassFail,
21
- Percentage,
22
- Number
23
- }
24
-
25
- const completeDefn: T.Dict = {
26
- ID: T.Test.Complete,
27
- name: "Complete",
28
- normalize: false,
29
- externalType: TestType.PassFail,
30
- detailsFn: doPrepareCompleteDetails,
31
- suites: [T.Suite.Legal]
32
- };
33
-
34
- const contiguousDefn: T.Dict = {
35
- ID: T.Test.Contiguous,
36
- name: "Contiguous",
37
- normalize: false,
38
- externalType: TestType.PassFail,
39
- detailsFn: doPrepareContiguousDetails,
40
- suites: [T.Suite.Legal]
41
- };
42
-
43
- const freeOfHolesDefn: T.Dict = {
44
- ID: T.Test.FreeOfHoles,
45
- name: "Free of Holes",
46
- normalize: false,
47
- externalType: TestType.PassFail,
48
- detailsFn: doPrepareFreeOfHolesDetails,
49
- suites: [T.Suite.Legal]
50
- };
51
-
52
- const equalPopulationDefn: T.Dict = {
53
- ID: T.Test.EqualPopulation,
54
- name: "Equal Population",
55
- normalize: false,
56
- externalType: TestType.PassFail,
57
- detailsFn: doPrepareEqualPopulationDetails,
58
- suites: [T.Suite.Legal]
59
- };
60
-
61
- const populationDeviationDefn: T.Dict = {
62
- ID: T.Test.PopulationDeviation,
63
- name: "Population Deviation",
64
- normalize: true,
65
- externalType: TestType.Percentage,
66
- detailsFn: doPreparePopulationDeviationDetails,
67
- suites: [T.Suite.Legal, T.Suite.Best] // Both so EqualPopulation can be assessed
68
- };
69
-
70
- const reockDefn: T.Dict = {
71
- ID: T.Test.Reock,
72
- name: "Reock",
73
- normalize: true,
74
- externalType: TestType.Number,
75
- detailsFn: doPrepareReockDetails,
76
- suites: [T.Suite.Best]
77
- };
78
-
79
- const polsbyPopperDefn: T.Dict = {
80
- ID: T.Test.PolsbyPopper,
81
- name: "Polsby-Popper",
82
- normalize: true,
83
- externalType: TestType.Number,
84
- detailsFn: doPreparePolsbyPopperDetails,
85
- suites: [T.Suite.Best]
86
- };
87
-
88
- const countySplitsDefn: T.Dict = {
89
- ID: T.Test.CountySplits,
90
- name: "County splits",
91
- trailer: "of the population had their county split unexpectedly.",
92
- normalize: true, // TODO - Normalize this for real
93
- externalType: TestType.Percentage,
94
- detailsFn: doPrepareCountySplitDetails,
95
- suites: [T.Suite.Best]
96
- };
97
-
98
- const efficiencyGapDefn: T.Dict = {
99
- ID: T.Test.EfficiencyGap,
100
- name: "Efficiency Gap",
101
- normalize: false, // TODO - Normalize this!
102
- externalType: TestType.Percentage,
103
- detailsFn: doPrepareEfficiencyGapDetails,
104
- suites: [T.Suite.Fair]
105
- };
106
-
107
- // A structure to hold test definitions
108
- type TestDefns = {
109
- [category: number]: any;
110
- }
111
-
112
- // All the tests that have been defined (can be reported on)
113
- const testDefns = {
114
- [T.Test.Complete]: completeDefn,
115
- [T.Test.Contiguous]: contiguousDefn,
116
- [T.Test.FreeOfHoles]: freeOfHolesDefn,
117
- [T.Test.EqualPopulation]: equalPopulationDefn,
118
- [T.Test.PopulationDeviation]: populationDeviationDefn,
119
- [T.Test.Reock]: reockDefn,
120
- [T.Test.PolsbyPopper]: polsbyPopperDefn,
121
- // TODO - Flesh out county splits
122
- [T.Test.CountySplits]: countySplitsDefn,
123
- [T.Test.EfficiencyGap]: efficiencyGapDefn
124
-
125
- /* TODO - More tests ... */
126
- } as TestDefns;
127
-
128
-
129
- // SCORECARD
130
-
131
- // The notion of a scorecard is:
132
- // - A subset of analytics & validations
133
- // - Normalized, if numeric
134
- // - Organized into several dimensions/categories
135
- // - With combined category scores, and
136
- // - Those combined into an overall score
137
-
138
- // A scorecard
139
- export type Scorecard = {
140
- [category: number]: ScorecardCategoryEntry;
141
- }
142
-
143
- type ScorecardCategoryEntry = {
144
- catName: string;
145
- catScore?: number | boolean;
146
- catTests: T.TestEntries;
147
- }
148
-
149
- // A scorecard definition
150
- type ScorecardDefn = {
151
- [category: number]: any;
152
- }
153
-
154
- // Scorecard category definitions
155
-
156
- const validCategory = {
157
- catName: "Map Validations",
158
- catTests: [
159
- { testID: T.Test.Complete },
160
- { testID: T.Test.Contiguous },
161
- { testID: T.Test.FreeOfHoles },
162
- { testID: T.Test.EqualPopulation }
163
- ],
164
- catNumeric: false,
165
- catWeight: undefined,
166
- catPrepareFn: doPrepareValidSection
167
- };
168
-
169
- const fairCategory = {
170
- // TODO - Change this label
171
- catName: "Is the map fair?",
172
- catTests: [
173
- {
174
- testID: T.Test.EfficiencyGap,
175
- testWeight: 100
176
- }
177
- ],
178
- catNumeric: true,
179
- catWeight: undefined,
180
- catPrepareFn: doPrepareFairSection
181
- };
182
-
183
- // TODO - Decide on the relative weights of these tests!
184
- // NOTE: 'testWeights' are simply relative, i.e., each normalized score is
185
- // multiplied by the associated 'testWeight', and the sum of those is divided
186
- // by the total weight. Weights don't have to add to 100.
187
- const bestCategory = {
188
- catName: "Traditional Districting Principles",
189
- catTests: [
190
- {
191
- testID: T.Test.PopulationDeviation,
192
- testWeight: 10
193
- },
194
- {
195
- testID: T.Test.Reock,
196
- testWeight: 25
197
- },
198
- {
199
- testID: T.Test.PolsbyPopper,
200
- testWeight: 25
201
- }
202
- // TODO - Re-enable, when the metric is implemented
203
- // {
204
- // testID: T.Test.CountySplits,
205
- // testWeight: 50
206
- // }
207
- ],
208
- catNumeric: true,
209
- catWeight: undefined,
210
- catPrepareFn: doPrepareBestSection
211
- };
212
-
213
-
214
- // The overall scorecard definition
215
-
216
- const scorecardDefn = {
217
- [T.Suite.Legal]: validCategory,
218
- // TODO - NIY
219
- // [T.Suite.Fair]: fairCategory,
220
- [T.Suite.Best]: bestCategory
221
- } as ScorecardDefn;
222
-
223
-
224
- // NORMALIZE RAW ANALYTICS
225
- // Raw numeric analytics, such as population deviation, compactness, etc. are
226
- // normalized as part of creating a scorecard, so the code to normalize results
227
- // is encapsulated here.
228
-
229
- // Configure scale parameters for normalizing each raw test result
230
- // This needs to be separate from the scorecard configuration info above,
231
- // because some scales need access to the analytics session object.
232
- export function doConfigureScales(s: AnalyticsSession): void {
233
- // Scale defn for PopulationDeviation
234
- const CDLimit = 0.75 / 100; // Deviation threshold for CD's
235
- const LDLimit = 10.00 / 100; // Deviation threshold for LD's
236
-
237
- const CDGoodEnough = 0.20 / 100;
238
- const LDGoodEnough = (CDGoodEnough / CDLimit) * LDLimit;
239
- const scale = (s.legislativeDistricts) ? [1.0 - LDLimit, 1.0 - LDGoodEnough] : [1.0 - CDLimit, 1.0 - CDGoodEnough];
240
- // const scale = [1.0 - CDLimit, 1.0 - CDGoodEnough];
241
-
242
- s.testScales[T.Test.PopulationDeviation] = { testScale: scale, testInvertp: true };
243
-
244
- s.testScales[T.Test.Reock] = { testScale: [0.25, 0.50], testInvertp: false };
245
- s.testScales[T.Test.PolsbyPopper] = { testScale: [0.10, 0.50], testInvertp: false };
246
-
247
- const SPLITLimit = 0.1; // TODO - Just a placeholder default maximum (10%)
248
- s.testScales[T.Test.CountySplits] = { testScale: [1.0 - SPLITLimit, 1.0], testInvertp: true };
249
-
250
- // TODO - More analytics ...
251
- }
252
-
253
- // Postprocess analytics - Normalize numeric results and derive secondary tests.
254
- // Do this after analytics have been run and before preparing a test log or scorecard.
255
- export function doAnalyzePostProcessing(s: AnalyticsSession): void {
256
- // Normalize the raw scores for all the numerics tests
257
- let testResults = U.getNumericObjectKeys(testDefns);
258
-
259
- for (let testID of testResults) {
260
- if (testDefns[testID]['normalize']) {
261
- let testResult = s.getTest(testID) as T.TestEntry;
262
-
263
- let rawScore = testResult['score'] as number;
264
- let normalizedScore: number;
265
- let { testScale, testInvertp } = s.testScales[testID];
266
-
267
- normalizedScore = U.normalize(rawScore, testScale, testInvertp);
268
- testResult['normalizedScore'] = normalizedScore;
269
-
270
- // Add the scale used to normalize the raw score to the details
271
- testResult['details']['scale'] = testScale;
272
- }
273
- }
274
-
275
- // Derive secondary tests
276
- doDeriveSecondaryTests(s);
277
-
278
- // Toggle the semaphore, so postprocessing isn't for both the testlog & scorecard
279
- s.bPostProcessingDone = true;
280
- }
281
-
282
- // Prepare a structured but unformatted scorecard, from the test results
283
- function doGenerateScorecard(s: AnalyticsSession): Scorecard {
284
- if (!(s.bPostProcessingDone)) {
285
- doAnalyzePostProcessing(s);
286
- }
287
-
288
- // Create a new scorecard
289
- let scorecard = {} as Scorecard;
290
-
291
- // Filter the defined scorecard categories by the requested test suites
292
- let categories = U.getNumericObjectKeys(scorecardDefn);
293
- let suitesRequested = s.config['suites'];
294
- categories = categories.filter(x => suitesRequested.includes(x));
295
-
296
- // ... and initialize each one in the new scorecard
297
- for (let c of categories) {
298
- scorecard[c] = {} as ScorecardCategoryEntry;
299
- scorecard[c]['catName'] = scorecardDefn[c]['catName'];
300
- scorecard[c]['catTests'] = {} as T.TestEntries;
301
- // scorecard[c]['catScore'] = undefined;
302
- }
303
-
304
- // For each scorecard category
305
- for (let c of categories) {
306
- // Grab the scorecard category definition
307
- let { catName, catTests, catNumeric } = scorecardDefn[c];
308
-
309
- let numericCategoryScore = 0;
310
- let totalWeight = 0;
311
- let booleanCategoryScore = true;
312
-
313
- // Process the results for each test result in the category
314
- for (let testDefn of catTests) {
315
- // Get the config info for the test
316
- let testID = testDefn['testID'];
317
- // ... and the actual test result
318
- let testResult = s.getTest(testID) as T.TestEntry;
319
-
320
- // Create a new test entry for the scorecard
321
- let testReport = U.deepCopy(testResult);
322
- // Add the name
323
- testReport['name'] = testDefns[testID]['name'];
324
-
325
- if (catNumeric) {
326
- // Normalize raw numeric scores ... moved to FIRST PASS above
327
-
328
- // Accumulate a category score
329
- let normalizedScore = testReport['normalizedScore'];
330
- numericCategoryScore += normalizedScore * testDefn['testWeight'];
331
- totalWeight += testDefn['testWeight'];
332
- }
333
- else {
334
- // AND together pass/fail tests into a category score
335
- if (!testReport['score']) {
336
- booleanCategoryScore = false;
337
- }
338
- }
339
- scorecard[c]['catTests'][testID] = testReport;
340
- }
341
-
342
- // Set the category score
343
- if (catNumeric) {
344
- scorecard[c]['catScore'] = Math.round(numericCategoryScore / totalWeight);
345
- }
346
- else {
347
- scorecard[c]['catScore'] = booleanCategoryScore;
348
- }
349
- }
350
- // TODO - Compute an overall score from the category weights
351
-
352
- return scorecard;
353
- }
354
-
355
- // Prepare a formatted scorecard suitable for rendering
356
- export function doPrepareScorecard(s: AnalyticsSession): any {
357
- // Initialize the output format
358
- let text: any = { data: [] };
359
- let blocks: any = text.data;
360
-
361
- // If the plan as already been analyzed, prepare a scorecard
362
- if (s.bPlanAnalyzed) {
363
- // Create and cache a new, unformatted scorecard
364
- s.scorecard = doGenerateScorecard(s);
365
-
366
- // Create a scorecard header
367
- blocks.push({ variant: 'h4', text: `Analysis - NC 2019 Special Edition` });
368
- blocks.push({ variant: 'body1', text: `In response to the recent court ruling in North Carolina and the court's requirement for transparency, we are pleased to provide the general public with early access to this base set of redistricting analytics. Stay tuned for more updates!` });
369
- blocks.push({ variant: 'body1', text: `For more details, see our blog post on Medium.` });
370
-
371
- // Prepare each scorecard category
372
- blocks.push({ variant: 'beginExpansion', text: `Overall Plan` });
373
- let categories = U.getNumericObjectKeys(s.scorecard);
374
- for (let c of categories) {
375
- let sectionPrepareFn = scorecardDefn[c]['catPrepareFn'];
376
- let sectionText = sectionPrepareFn(s, c);
377
- blocks.push(...sectionText);
378
- }
379
- // blocks.push({ variant: 'body1', text: `` });
380
- // blocks.push({ variant: 'body1', text: `There is much more analysis coming of county splitting, partisan fairness, and the opportunity for minority representation! For now, you can glean a lot from the district statistics below.` });
381
- blocks.push({ variant: 'endExpansion' });
382
-
383
- // Report district statistics
384
- blocks.push({ variant: 'beginExpansion', text: `Individual Districts` });
385
- let districtStatisticsText = doPrepareDistrictStatistics(s);
386
- blocks.push(...districtStatisticsText);
387
- blocks.push({ variant: 'endExpansion' });
388
-
389
- // Report what datasets were used
390
- let c = s.config['datasets'][D.Dataset.CENSUS];
391
- let v = s.config['datasets'][D.Dataset.VAP];
392
- let e = s.config['datasets'][D.Dataset.ELECTION];
393
-
394
- blocks.push({ variant: 'beginExpansion', text: `About the Data` });
395
- blocks.push({ variant: 'body1', text: `These are the 4 datasets used in this analysis:` });
396
- // TODO - Get the shape "dataset" from dra-client
397
- blocks.push({ variant: 'body1', text: `* Shapes: 2010 VTD shapes` });
398
- blocks.push({ variant: 'body1', text: `* Census: ${D.DatasetDescriptions[c]}` });
399
- blocks.push({ variant: 'body1', text: `* VAP: ${D.DatasetDescriptions[v]}` });
400
- blocks.push({ variant: 'body1', text: `* Elections: ${D.DatasetDescriptions[e]}` });
401
- blocks.push({ variant: 'endExpansion' });
402
-
403
- blocks.push({ variant: 'body1', text: `` });
404
- blocks.push({
405
- "variant": "link",
406
- "text": "Questions or comments?",
407
- "label": "analytics@davesredistricting.org",
408
- "link": "mailto:analytics@davesredistricting.org"
409
- });
410
- }
411
- // Otherwise, return a blank scorecard
412
-
413
- return text;
414
- }
415
-
416
- function doPrepareDistrictStatistics(s: AnalyticsSession): any {
417
- let text: any = { data: [] };
418
- let blocks: any = text.data;
419
-
420
- blocks.push({ variant: 'beginTable' });
421
- blocks.push({ variant: 'row', cells: ['ID', 'Total', 'Δ%', 'OK?', '*', 'Dem', 'Rep', 'White', 'Minority', 'Black', 'Hispanic', 'Pacific', 'Asian', 'Native'] });
422
-
423
- for (let d = 0; d < s.districts.numberOfRows(); d++) {
424
- let tot = s.districts.statistics[D.DistrictField.TotalPop][d];
425
- if (tot == 0)
426
- blocks.push({ variant: 'row', cells: [String(d), '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-'] });
427
- else {
428
- tot = Math.round(tot);
429
- let dev = fractionToPercentage(s.districts.statistics[D.DistrictField.PopDevPct][d]);
430
- let bEq = s.districts.statistics[D.DistrictField.bEqualPop][d];
431
- let bC = s.districts.statistics[D.DistrictField.bContiguous][d]
432
- && s.districts.statistics[D.DistrictField.bNotEmbedded][d];
433
- let dPct = fractionToPercentage(s.districts.statistics[D.DistrictField.DemPct][d]);
434
- let rPct = fractionToPercentage(s.districts.statistics[D.DistrictField.RepPct][d]);
435
- let wPct = fractionToPercentage(s.districts.statistics[D.DistrictField.WhitePct][d]);
436
- let mPct = fractionToPercentage(s.districts.statistics[D.DistrictField.MinorityPct][d]);
437
- let bPct = fractionToPercentage(s.districts.statistics[D.DistrictField.BlackPct][d]);
438
- let hPct = fractionToPercentage(s.districts.statistics[D.DistrictField.HispanicPct][d]);
439
- let pPct = fractionToPercentage(s.districts.statistics[D.DistrictField.PacificPct][d]);
440
- let aPct = fractionToPercentage(s.districts.statistics[D.DistrictField.AsianPct][d]);
441
- let nPct = fractionToPercentage(s.districts.statistics[D.DistrictField.NativePct][d]);
442
-
443
- let id: string;
444
- if (d == 0) id = "??";
445
- else if (d == (s.districts.numberOfRows() - 1)) id = " ";
446
- else id = String(d);
447
-
448
- blocks.push({
449
- variant: 'row',
450
- cells: [
451
- `${id}`,
452
- `${formatInteger(tot)}`,
453
- `${formatPercentage(dev)}%`,
454
- `${pfBoolToString(bEq)}`,
455
- `${pfBoolToString(bC)}`,
456
- `${formatPercentage(dPct)}%`,
457
- `${formatPercentage(rPct)}%`,
458
- `${formatPercentage(wPct)}%`,
459
- `${formatPercentage(mPct)}%`,
460
- `${formatPercentage(bPct)}%`,
461
- `${formatPercentage(hPct)}%`,
462
- `${formatPercentage(pPct)}%`,
463
- `${formatPercentage(aPct)}%`,
464
- `${formatPercentage(nPct)}%`]
465
- });
466
- }
467
- }
468
- blocks.push({ variant: 'endTable' });
469
-
470
- return blocks;
471
- }
472
-
473
- // TEST LOG
474
-
475
- // Prepare formatted test results for rendering
476
- export function doPrepareTestLog(s: AnalyticsSession): any {
477
- // Initialize the output format
478
- let text: any = { data: [] };
479
- let blocks: any = text.data;
480
-
481
- // If the plan as already been analyzed, prepare a test log
482
- if (s.bPlanAnalyzed) {
483
- if (!(s.bPostProcessingDone)) {
484
- doAnalyzePostProcessing(s);
485
- }
486
-
487
- // Create a test log header
488
- blocks.push({ variant: 'h4', text: `Test Log` });
489
-
490
- let testResults = U.getNumericObjectKeys(testDefns);
491
- let suitesRequested = new Set(s.config['suites']);
492
-
493
- for (let testID of testResults) {
494
- // Filter the defined tests by the requested test suites
495
- let inSuites: number[] = testDefns[testID]['suites'];
496
- if (!(U.isArrayEmpty(inSuites.filter(x => suitesRequested.has(x))))) {
497
- // Get the test result
498
- let testResult = s.getTest(testID) as T.TestEntry;
499
- // Prepare the text for it, and append it to the output
500
- let testText = prepareTestEntry(testID, testResult);
501
- blocks.push(...testText);
502
- }
503
- }
504
- }
505
- // Otherwise, return a blank test log
506
-
507
- return text;
508
- }
509
-
510
- function prepareTestEntry(testID: number, testResult: T.TestEntry): any {
511
- let text: any = { data: [] };
512
- let blocks: any = text.data;
513
-
514
- let testName = testDefns[testID]['name'];
515
- let testNameTrailer: string = "";
516
- if (U.keyExists('trailer', testDefns[testID])) {
517
- testNameTrailer = testDefns[testID]['trailer'];
518
- }
519
- let testType = testDefns[testID]['externalType'];
520
- let bNormalize = testDefns[testID]['normalize'];
521
- let detailsFn = testDefns[testID]['detailsFn'];
522
- let detailsText = detailsFn(testResult);
523
- let score: number | boolean | undefined; // NOTE - Won't be undefined here
524
- let normalizedScore: number;
525
- let scoreText: string;
526
-
527
- // Get the score ...
528
- score = testResult['score'];
529
-
530
- // ... and format it for rendering
531
- switch (testType) {
532
- case TestType.PassFail: {
533
- scoreText = pfBoolToString(score as boolean);
534
- blocks.push({ variant: 'body1', text: `<b>${testName}</b>: ${scoreText} ${testNameTrailer}` });
535
- break;
536
- }
537
- case TestType.Percentage: {
538
- score = fractionToPercentage(score as number);
539
- if (bNormalize) {
540
- normalizedScore = testResult['normalizedScore'] as number;
541
- blocks.push({ variant: 'body1', text: `<b>${testName}</b>: ${normalizedScore} / 100 : ${formatPercentage(score)}% ${testNameTrailer}` });
542
- }
543
- else {
544
- blocks.push({ variant: 'body1', text: `<b>${testName}</b>: ${formatPercentage(score)}% ${testNameTrailer}` });
545
- }
546
- break;
547
- }
548
- case TestType.Number: {
549
- if (bNormalize) {
550
- normalizedScore = testResult['normalizedScore'] as number;
551
- blocks.push({ variant: 'body1', text: `<b>${testName}</b>: ${normalizedScore} / 100 : ${formatNumber(score as number)} ${testNameTrailer}` });
552
- }
553
- else {
554
- blocks.push({ variant: 'body1', text: `<b>${testName}</b>: ${formatNumber(score as number)} ${testNameTrailer}` });
555
- }
556
- break;
557
- }
558
- default: {
559
- // Unknown test type
560
- throw new RangeError();
561
- }
562
- }
563
-
564
- // Add the details text
565
- blocks.push(...detailsText);
566
-
567
- return blocks;
568
- }
569
-
570
-
571
- // FORMATTERS FOR TEST DETAILS
572
-
573
- function doPrepareCompleteDetails(testResult: T.TestEntry): any {
574
- let text: any = { data: [] };
575
- let blocks: any = text.data;
576
-
577
- if (!U.isObjectEmpty(testResult['details'])) {
578
- let unassignedText = "";
579
- let emptyText = "";
580
- let missingText = "";
581
-
582
- if (U.keyExists('unassignedFeatures', testResult['details'])) {
583
- let unassignedFeatures = testResult['details']['unassignedFeatures'];
584
-
585
- let unassignedList = prepareListItems(unassignedFeatures);
586
- let unassignedTextTemplates: string[] = [
587
- `GEOID ${unassignedList} is not assigned to a district.`,
588
- `GEOIDs ${unassignedList} are not assigned to districts.`,
589
- `Several GEOIDs are not assigned to districts, including ${unassignedList}.`
590
- ];
591
- unassignedText = prepareListText(unassignedFeatures, unassignedTextTemplates);
592
- }
593
-
594
- if (U.keyExists('emptyDistricts', testResult['details'])) {
595
- let emptyDistricts = testResult['details']['emptyDistricts'];
596
-
597
- let emptyList = prepareListItems(emptyDistricts);
598
- let emptyTextTemplates: string[] = [
599
- `District ${emptyList} is empty.`,
600
- `Districts ${emptyList} are empty.`,
601
- `Several districts are empty, including ${emptyList}.`
602
- ];
603
- emptyText = prepareListText(emptyDistricts, emptyTextTemplates);
604
- }
605
-
606
- if (U.keyExists('missingDistricts', testResult['details'])) {
607
- missingText = `Not enough districts have been defined. `;
608
- }
609
-
610
- let detailsText = " " + unassignedText + emptyText + missingText;
611
- blocks.push({ variant: 'body1', text: detailsText });
612
- }
613
-
614
- return blocks;
615
- }
616
-
617
- function doPrepareContiguousDetails(testResult: T.TestEntry): any {
618
- let text: any = { data: [] };
619
- let blocks: any = text.data;
620
-
621
- if (!U.isObjectEmpty(testResult['details'])) {
622
- let discontiguousDistricts = testResult['details']['discontiguousDistricts'];
623
-
624
- let discontiguousList = prepareListItems(discontiguousDistricts);
625
- let discontiguousTextTemplates: string[] = [
626
- `District ${discontiguousList} is not contiguous.`,
627
- `Districts ${discontiguousList} are not contiguous.`,
628
- `Several districts are not contiguous, including ${discontiguousList}.`
629
- ];
630
- let detailsText = prepareListText(discontiguousDistricts, discontiguousTextTemplates);
631
-
632
- blocks.push({ variant: 'body1', text: detailsText });
633
- }
634
-
635
- return blocks;
636
- }
637
-
638
- function doPrepareFreeOfHolesDetails(testResult: T.TestEntry): any {
639
- let text: any = { data: [] };
640
- let blocks: any = text.data;
641
-
642
- if (!U.isObjectEmpty(testResult['details'])) {
643
- let embeddedDistricts = testResult['details']['embeddedDistricts'];
644
-
645
- let embeddedList = prepareListItems(embeddedDistricts);
646
- let embeddedTextTemplates: string[] = [
647
- `District ${embeddedList} is fully embedded within another district.`,
648
- `Both districts ${embeddedList} are fully embedded within other districts.`,
649
- `Several districts are fully embedded within other districts, including ${embeddedList}.`
650
- ];
651
- let detailsText = prepareListText(embeddedDistricts, embeddedTextTemplates);
652
-
653
- blocks.push({ variant: 'body1', text: detailsText });
654
- }
655
-
656
- return blocks;
657
- }
658
-
659
- function doPrepareEqualPopulationDetails(testResult: T.TestEntry): any {
660
- let text: any = { data: [] };
661
- let blocks: any = text.data;
662
-
663
- if (!U.isObjectEmpty(testResult['details'])) {
664
- let popDevPct = fractionToPercentage(testResult['details']['deviation']);
665
- let thresholdPct = fractionToPercentage(1.0 - testResult['details']['thresholds'][0]);
666
-
667
- let detailsText = '';
668
- if (!(testResult['score'])) {
669
- detailsText = `The ${formatPercentage(popDevPct)}% population deviation is greater than the ${formatPercentage(thresholdPct)}% threshold tolerated by courts.`;
670
- }
671
- blocks.push({ variant: 'body1', text: detailsText });
672
- }
673
-
674
- return blocks;
675
- }
676
-
677
- function doPreparePopulationDeviationDetails(testResult: T.TestEntry): any {
678
- let text: any = { data: [] };
679
- let blocks: any = text.data;
680
-
681
- let n = Math.round(testResult['details']['maxDeviation']);
682
- let term: string = "people";
683
- if (n == 1) {
684
- term = "person";
685
- }
686
- blocks.push({ variant: 'body1', text: `The maximum population deviation between districts is ${formatInteger(n)} ${term}.` });
687
-
688
- return blocks;
689
- }
690
-
691
- function doPrepareReockDetails(testResult: T.TestEntry): any {
692
- let text: any = { data: [] };
693
- let blocks: any = text.data;
694
-
695
- // TODO - No details implemented yet
696
-
697
- return blocks;
698
- }
699
-
700
- function doPreparePolsbyPopperDetails(testResult: T.TestEntry): any {
701
- let text: any = { data: [] };
702
- let blocks: any = text.data;
703
-
704
- // TODO - No details implemented yet
705
-
706
- return blocks;
707
- }
708
-
709
- function doPrepareEfficiencyGapDetails(testResult: T.TestEntry): any {
710
- let text: any = { data: [] };
711
- let blocks: any = text.data;
712
-
713
- // TODO - Not yet implemented
714
-
715
- return blocks;
716
- }
717
-
718
- function doPrepareCountySplitDetails(testResult: T.TestEntry): any {
719
- let text: any = { data: [] };
720
- let blocks: any = text.data;
721
-
722
- let unexpectedAffected = fractionToPercentage(testResult['details']['unexpectedAffected']);
723
- let affectedText = `affecting ${formatPercentage(unexpectedAffected)}% of the total population.`;
724
-
725
- let countiesSplitUnexpectedly = testResult['details']['countiesSplitUnexpectedly'];
726
- let nCountiesSplitUnexpectedly = countiesSplitUnexpectedly.length;
727
- let nUnexpectedSplits = testResult['details']['unexpectedSplits'];
728
- let splitList = prepareListItems(countiesSplitUnexpectedly);
729
- let splitTextTemplates: string[] = [
730
- `${splitList} county is split unexpectedly, `,
731
- `${splitList} counties are split unexpectedly, `,
732
- // `These ${formatInteger(nCountiesSplitUnexpectedly)} counties are split unexpectedly--${splitList}--`
733
- `${splitList} counties are split unexpectedly ${formatInteger(nUnexpectedSplits)} times, `
734
-
735
- ];
736
- let detailsText = prepareListText(countiesSplitUnexpectedly, splitTextTemplates) + affectedText;
737
-
738
- blocks.push({ variant: 'body1', text: detailsText });
739
-
740
- return blocks;
741
- }
742
-
743
-
744
- // FORMATTERS FOR CATEGORIES
745
-
746
- // This function parses & formats the 'Valid' section of a scorecard.
747
- function doPrepareValidSection(s: AnalyticsSession, c: number): any {
748
- // Get the category meta data
749
- let { catName, catScore, catTests } = s.scorecard[c];
750
- let testReport: T.TestEntry;
751
-
752
- // Initialize the section text
753
- let text: any = { data: [] };
754
- let blocks: any = text.data;
755
- let testText: any;
756
-
757
- // Section header
758
- let stringScore = pfBoolToString(catScore as boolean);
759
- blocks.push({ variant: 'beginExpansion', text: `${catName}` });
760
- // blocks.push({ variant: 'beginExpansion', text: `${catName} ${stringScore}` });
761
-
762
- // Complete
763
- testReport = catTests[T.Test.Complete];
764
- testText = prepareTestEntry(T.Test.Complete, testReport);
765
- blocks.push(...testText);
766
-
767
- // Contiguous
768
- testReport = catTests[T.Test.Contiguous];
769
- testText = prepareTestEntry(T.Test.Contiguous, testReport);
770
- blocks.push(...testText);
771
-
772
- // Free of holes (no embedded districts)
773
- testReport = catTests[T.Test.FreeOfHoles];
774
- testText = prepareTestEntry(T.Test.FreeOfHoles, testReport);
775
- blocks.push(...testText);
776
-
777
- // Equal population (w/in the appropriate legal threshold)
778
- testReport = catTests[T.Test.EqualPopulation];
779
- testText = prepareTestEntry(T.Test.EqualPopulation, testReport);
780
- blocks.push(...testText);
781
-
782
- blocks.push({ variant: 'endExpansion' });
783
-
784
- return blocks;
785
- }
786
-
787
- // TODO - NIY
788
- // This function parses & formats the 'Fair' section of a scorecard.
789
- function doPrepareFairSection(s: AnalyticsSession, c: number): any {
790
- // Get the category meta data
791
- let { catName, catScore, catTests } = s.scorecard[c];
792
- let testReport: T.TestEntry;
793
-
794
- // Initialize the section text
795
- let text: any = { data: [] };
796
- let blocks: any = text.data;
797
- let testText: any;
798
-
799
- // Section header
800
- blocks.push({ variant: 'beginExpansion', text: `${catName} ${catScore} of 100` });
801
-
802
- // TODO - Flesh this out
803
- // There's only one test: Population Deviation.
804
- // testReport = catTests[T.Test.PopulationDeviation];
805
- // testText = prepareTestEntry(T.Test.PopulationDeviation, testReport);
806
- // blocks.push(...testText);
807
-
808
- blocks.push({ variant: 'endExpansion' });
809
-
810
- return blocks;
811
- }
812
-
813
- // This function parses & formats the 'Best' section of a scorecard.
814
- function doPrepareBestSection(s: AnalyticsSession, c: number): any {
815
- // Get the category meta data
816
- let { catName, catScore, catTests } = s.scorecard[c];
817
- let testReport: T.TestEntry;
818
-
819
- // Initialize the section text
820
- let text: any = { data: [] };
821
- let blocks: any = text.data;
822
- let testText: any;
823
-
824
- // Section header
825
- blocks.push({ variant: 'beginExpansion', text: `${catName} (${catScore} of 100)` });
826
-
827
- // Population deviation
828
- testReport = catTests[T.Test.PopulationDeviation];
829
- testText = prepareTestEntry(T.Test.PopulationDeviation, testReport);
830
- blocks.push(...testText);
831
-
832
- // Compactness
833
- testReport = catTests[T.Test.Reock];
834
- let normalizedReock = testReport['normalizedScore'] as number;
835
- let reockTestText = prepareTestEntry(T.Test.Reock, testReport);
836
-
837
- testReport = catTests[T.Test.PolsbyPopper];
838
- let normalizedPolsbyPopper = testReport['normalizedScore'] as number;
839
- let polsbyPopperTestText = prepareTestEntry(T.Test.PolsbyPopper, testReport);
840
-
841
- let compactnessScore = (normalizedReock + normalizedPolsbyPopper) / 2;
842
- blocks.push({ variant: 'body1', text: `Compactness: ${compactnessScore} / 100` });
843
-
844
- blocks.push(...reockTestText);
845
- blocks.push(...polsbyPopperTestText);
846
-
847
- // County splits
848
- // TODO - Re-enable this, when the county-splitting metric is implemented.
849
- // testReport = catTests[T.Test.CountySplits];
850
- // testText = prepareTestEntry(T.Test.CountySplits, testReport);
851
- // blocks.push(...testText);
852
-
853
- blocks.push({ variant: 'endExpansion' });
854
-
855
- return blocks;
856
- }
857
-
858
- // FORMATTING HELPERS
859
-
860
- // Convert a boolean representing Pass/Fail to a string
861
- function pfBoolToString(score: boolean): string {
862
- if (score) {
863
- return "Yes";
864
- }
865
- else {
866
- return "No";
867
- }
868
- }
869
-
870
- function fractionToPercentage(f: number): number {
871
- return f * 100;
872
- }
873
-
874
- function formatNumber(n: number): string {
875
- let p = S.PRECISION;
876
-
877
- return n.toLocaleString('en-US', { minimumFractionDigits: p, maximumFractionDigits: p });
878
- }
879
-
880
- function formatPercentage(n: number): string {
881
- let p = (S.PRECISION / 2);
882
-
883
- return n.toLocaleString('en-US', { minimumFractionDigits: p, maximumFractionDigits: p });
884
- }
885
-
886
- function formatInteger(i: number): string {
887
- return new Intl.NumberFormat().format(i);
888
- }
889
-
890
- // Prepare the items in a list for rendering
891
- function prepareListItems(list: any[]): string {
892
- let nItems = list.length;
893
- let listStr: string;
894
-
895
- switch (nItems) {
896
- case 1: {
897
- listStr = list[0];
898
- break;
899
- }
900
- case 2: {
901
- listStr = list[0] + " and " + list[1];
902
- break;
903
- }
904
- default: {
905
- let listWithCommas = list.join(', ');
906
- let lastCommaIndex = listWithCommas.length - ((list[list.length - 1].length) + 1);
907
- let beforeAnd = listWithCommas.substr(0, lastCommaIndex);
908
- let afterAnd = listWithCommas.substr(lastCommaIndex + 1);
909
- listStr = beforeAnd + " and " + afterAnd;
910
- break;
911
- }
912
- }
913
- return listStr;
914
- }
915
-
916
- // Pick the rendering text for the appropriate list length
917
- function prepareListText(list: any[], listTemplates: string[]): string {
918
- let nItems = list.length;
919
- switch (nItems) {
920
- case 1: {
921
- return listTemplates[0];
922
- break;
923
- }
924
- case 2: {
925
- return listTemplates[1];
926
- break;
927
- }
928
- default: {
929
- return listTemplates[2];
930
- break;
931
- }
932
- }
933
- }
934
-
935
-
936
- /* COMMAND-LINE TESTS
937
-
938
- node main.js scorecard -v -x NC -n 13 -p ~/src/district-analytics/data/SAMPLE-BG-map.csv -d ~/src/district-analytics/data/SAMPLE-BG-data2.json -s ~/src/district-analytics/data/SAMPLE-BG-shapes.geojson -g ~/src/district-analytics/data/SAMPLE-BG-graph.json -c ~/src/district-analytics/data/SAMPLE-COUNTY.geojson
939
- node --inspect --inspect-brk main.js scorecard -v -x NC -n 13 -p ~/src/district-analytics/data/SAMPLE-BG-map.csv -d ~/src/district-analytics/data/SAMPLE-BG-data2.json -s ~/src/district-analytics/data/SAMPLE-BG-shapes.geojson -g ~/src/district-analytics/data/SAMPLE-BG-graph.json -c ~/src/district-analytics/data/SAMPLE-COUNTY.geojson
940
-
941
- -or-
942
-
943
- ./main.js scorecard -v -x NC -n 13 -p ../data/SAMPLE-BG-map.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson
944
- ./main.js --inspect --inspect-brk scorecard -v -x NC -n 13 -p ../data/SAMPLE-BG-map.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson
945
-
946
- These calls work at the project directory, using samples in the data/ directory:
947
-
948
- ./main.js testlog -v -x NC -n 13 -p ../data/SAMPLE-BG-map.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson
949
-
950
- TODO - Fix this
951
- ./main.js testlog -v -x NC -n 13 -p ../data/SAMPLE-BG-map-missing.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson
952
- ./main.js scorecard -v -x NC-n 13 -p ../data/SAMPLE-BG-map-missing.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
953
-
954
- ./main.js testlog -v -x NC -n 13 -p ../data/SAMPLE-BG-map-unassigned.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson
955
- ./main.js scorecard -v -x NC -n 13 -p ../data/SAMPLE-BG-map-unassigned.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson
956
-
957
- TODO - HERE
958
-
959
- ./main.js -v -x NC testlog -p ../data/SAMPLE-BG-map.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson --empty
960
- ./main.js -v -x NC scorecard -p ../data/SAMPLE-BG-map.csv -d ../data/SAMPLE-BG-data2.json -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -c ../data/SAMPLE-COUNTY.geojson --empty
961
-
962
- TODO
963
-
964
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map-discontiguous.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
965
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map-discontiguous.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
966
-
967
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map-hole.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
968
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map-hole.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
969
-
970
-
971
- node --inspect --inspect-brk main.js scorecard -v -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
972
- node main.js scorecard -v -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
973
-
974
-
975
- These calls test NC block-level data stored in my ~/data/redistricting-data/2010/compact/sample directory:
976
-
977
- node --inspect --inspect-brk main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-shapes.geojson -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
978
- node --inspect --inspect-brk main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/tl_2018_37_tabblock10.json -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
979
-
980
- node main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-shapes.geojson -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
981
- node main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/tl_2018_37_tabblock10.json -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
982
-
983
-
984
-
985
- */
986
-
987
- /* TODO - DELETE
988
-
989
- These calls work at the project directory, using samples in the data/ directory:
990
-
991
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
992
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
993
-
994
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map-missing.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
995
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map-missing.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
996
-
997
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map-unassigned.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
998
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map-unassigned.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
999
-
1000
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv --empty
1001
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv --empty
1002
-
1003
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map-discontiguous.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
1004
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map-discontiguous.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
1005
-
1006
- ./main.js testlog -n 13 -p ../data/SAMPLE-BG-map-hole.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
1007
- ./main.js scorecard -n 13 -p ../data/SAMPLE-BG-map-hole.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
1008
-
1009
-
1010
- node --inspect --inspect-brk main.js scorecard -v -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
1011
- node main.js scorecard -v -n 13 -p ../data/SAMPLE-BG-map.csv -c ../data/SAMPLE-BG-census.csv -s ../data/SAMPLE-BG-shapes.geojson -g ../data/SAMPLE-BG-graph.json -e ../data/SAMPLE-BG-election.csv -f ../data/SAMPLE-FIPS-county-name-map.csv
1012
-
1013
-
1014
- These calls test NC block-level data stored in my ~/data/redistricting-data/2010/compact/sample directory:
1015
-
1016
- node --inspect --inspect-brk main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-shapes.geojson -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
1017
- node --inspect --inspect-brk main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/tl_2018_37_tabblock10.json -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
1018
-
1019
- node main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-shapes.geojson -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
1020
- node main.js scorecard -v -n 13 -p ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-map.csv -c ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-census.csv -s ~/data/redistricting-data/2010/compact/sample/tl_2018_37_tabblock10.json -g ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-graph.json -e ~/data/redistricting-data/2010/compact/sample/SAMPLE-BLOCK-election.csv -f ~/data/redistricting-data/2010/compact/sample/SAMPLE-FIPS-county-name-map.csv
1021
-
1022
- */