-
Notifications
You must be signed in to change notification settings - Fork 0
/
extendPrecincts.mjs
63 lines (56 loc) · 2.3 KB
/
extendPrecincts.mjs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/*
Trim properties of features
HJD 2023-03-22
*/
import * as fs from 'node:fs';
import * as readline from 'node:readline';
// City of Chicago data portal
const inFile = './data/precincts.geojson';
// Chicago Board of Elections
// https://chicagoelections.gov/en/election-results.html
const inCsv = './data/dataexport.csv';
const outFile = './data/extendedPrecincts.geojson';
const inString = fs.readFileSync(inFile);
const featureCollection = JSON.parse(inString);
const features = featureCollection.features;
features.findFeature = function(ward, precinct) {
return features.find(feature => feature.properties.ward == ward && feature.properties.precinct == precinct);
};
const csvInterface = readline.createInterface({
input: fs.createReadStream(inCsv)
});
const wardPrecinctMatrix = []; // zero-based array of wards
const columnHeadings = []; // candidate names
var ward = 0;
csvInterface.on('line', (line) => {
const tokens = line.split(',');
if (tokens[0].startsWith('Ward')) {
// start a new ward
ward = parseInt(tokens[0].split(' ')[1]);
wardPrecinctMatrix[ward - 1] = []; // zero-based array of precincts
} else if (columnHeadings.length == 0 && tokens[0] == 'Votes') {
// capture candidate names
columnHeadings[0] = tokens[0]; // Votes
tokens.forEach((value, index) => {
if (index % 2 == 1 && value.length > 0) // odd?
columnHeadings[Math.trunc(index / 2) + 1] = value;
})
} else if (ward > 0 && tokens[0].length > 0 && isFinite(tokens[0])) {
// new precinct
const precinct = parseInt(tokens[0]);
const feature = features.findFeature(ward, precinct);
const properties = feature.properties;
const property = columnHeadings[0];
properties.cboe = {}; // empty object for extended properties
properties.cboe[property] = tokens[1]; // Votes
// candidates
columnHeadings.slice(1).forEach((value, index) => {
const property = value.replace(/^"(.*)"$/, '$1').replace(/""/g, '"'); // clean Chuy
properties.cboe[property] = tokens[2 * (index + 1)];
});
}; // end if
}).on('close', () => {
const outString = JSON.stringify(featureCollection);
fs.writeFileSync(outFile, outString);
console.log('Done.');
}); // end on close