-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathindex.js
97 lines (88 loc) · 2.98 KB
/
index.js
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
Converts the YAML data into a CSV
*/
const fs = require('fs');
const yaml = require('js-yaml');
const dateToString = date => date.toISOString().split('T')[0];
const args = process.argv.slice(1);
// Load data
const baseFolder = __dirname + '/';
const rawData = fs.readFileSync(baseFolder + '../data.yml', { encoding: 'utf8' });
const data = yaml.load(rawData);
// Check year input
const DEFAULT_ELECTION_YEAR = 2026;
const year = /\d{4}/.test(args[1]) ? args[1] : DEFAULT_ELECTION_YEAR;
if (!data[year])
throw `There is no data recorded for a ${year} election.`;
// Prepare output data
const PARTIES = ['ACT', 'GRN', 'INM', 'INT', 'LAB', 'MNA', 'MRI', 'NAT', 'NCP', 'NZF', 'TOP', 'UNF'];
const partyData = { date: [], org: [], n: [] };
for (const party of PARTIES)
partyData[party] = [];
// Parse data
let count = 0;
let electionDate;
for (const poll of data[year]) {
// Load election date
if (poll.date.length < 2) {
electionDate = poll.date[0] ?? new Date(`${year}-12-31`);
continue;
}
// Add data
for (const key in poll) {
if (poll[key]?.[0] instanceof Date) {
poll[key] = poll[key].map(dateToString);
}
partyData[key].push(poll[key] || 0);
}
// Pad data if party not listed in poll
count++;
for (const key in partyData) {
if (partyData[key].length === count)
continue;
partyData[key].push(NaN);
}
}
// Fix crash when trying to plot future parties
for (const party of PARTIES) {
if (partyData[party].length === 0)
partyData[party] = [0];
}
// Collate parties into blocs
const BLOCS = {
'leftBloc': ['LAB', 'GRN', 'MRI'],
'rightBloc': ['NAT', 'ACT', 'NZF'],
};
BLOCS['otherBloc'] = PARTIES.filter(party => !BLOCS['leftBloc'].includes(party) && !BLOCS['rightBloc'].includes(party));
for (const bloc of ['leftBloc', 'rightBloc', 'otherBloc']) {
partyData[bloc] = new Array(partyData.date.length).fill();
for (let i in partyData[bloc]) {
for (const party of BLOCS[bloc]) {
if (partyData[party][i]) {
partyData[bloc][i] ??= 0;
partyData[bloc][i] += partyData[party][i];
}
}
}
}
// Create CSV
let csvData = '';
const headerData = ['startDate', 'endDate', 'org', 'sampleSize', ...Object.keys(partyData).filter(key => !['date','org','n'].includes(key))]
csvData += headerData.join(',') + '\n';
csvData += ',' + dateToString(electionDate) + '\n';
for (let i = 0; i < count; i++) {
csvData += partyData.date[i].join(',') + ',';
csvData += partyData.org[i] + ',';
csvData += partyData.n[i] + ',';
const pollData = [];
for (const party of PARTIES)
pollData.push(partyData[party][i] || 0);
for (const bloc in BLOCS) {
pollData.push(partyData[bloc][i] || 0);
}
csvData += pollData.join(',') + '\n';
}
csvData = csvData.replace(/NaN/g, '');
const outFileName = baseFolder + 'local-data.csv';
try { fs.rmSync(outFileName); } catch { }
fs.writeFileSync(outFileName, csvData);