|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +const fs = require('fs'); |
| 4 | + |
1 | 5 | /* fp */ |
2 | | -const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x) |
3 | | -const curry = fn => (...args) => fn.bind(null, ...args) |
4 | | -const map = curry((fn, arr) => arr.map(fn)) |
5 | | -const join = curry((str, arr) => arr.join(str)) |
6 | | -const split = curry((splitOn, str) => str.split(splitOn)) |
7 | | -const sort = curry((compareFn, arr) => arr.sort(compareFn)) |
8 | | -const filter = curry((filterFn, arr) => arr.filter(filterFn)) |
9 | | -/* utility */ |
10 | | -const first = arr => arr[0] |
11 | | -const skipFirst = arr => arr.slice(1) |
12 | | -const hasValue = val => !!val |
13 | | -const toStr = val => val + '' |
14 | | -const appendCell = (row, value) => row.concat(value) |
15 | | -const cellPad = (index, str, width) => index ? str.padStart(width) : str.padEnd(width) |
| 6 | +const pipe = (...fns) => x => fns.reduce((v, f) => f(v), x); |
| 7 | +const curry = fn => (...args) => fn.bind(null, ...args); |
| 8 | +const map = curry((fn, arr) => arr.map(fn)); |
| 9 | +const join = curry((str, arr) => arr.join(str)); |
| 10 | +const split = curry((splitOn, str) => str.split(splitOn)); |
| 11 | +const sort = curry((compareFn, arr) => arr.sort(compareFn)); |
| 12 | +const filter = curry((filterFn, arr) => arr.filter(filterFn)); |
16 | 13 |
|
17 | | -const cellWidth = index => [18, 10, 8, 8, 18, 6][index] |
| 14 | +/* utility */ |
| 15 | +const first = arr => arr[0]; |
| 16 | +const skipFirst = arr => arr.slice(1); |
| 17 | +const hasValue = val => !!val; |
| 18 | +const toStr = val => val + ''; |
| 19 | +const appendCell = (row, value) => row.concat(value); |
| 20 | +const cellPad = (index, str, width) => ( |
| 21 | + index ? str.padStart(width) : str.padEnd(width) |
| 22 | +); |
| 23 | +const cellWidth = index => [18, 10, 8, 8, 18, 6][index]; |
18 | 24 |
|
19 | | -const renderCell = (cell, index) => cellPad(index, toStr(cell), cellWidth(index)) |
20 | | -const renderRow = pipe( |
21 | | - map(renderCell), |
22 | | - join('') |
23 | | -) |
24 | | -const renderTable = pipe( |
25 | | - map(renderRow), |
26 | | - join('\n') |
27 | | -) |
| 25 | +const renderCell = (cell, index) => ( |
| 26 | + cellPad(index, toStr(cell), cellWidth(index)) |
| 27 | +); |
| 28 | +const renderRow = pipe(map(renderCell), join('')); |
| 29 | +const renderTable = pipe(map(renderRow), join('\n')); |
28 | 30 |
|
29 | | -const getDensityCell = row => parseInt(row[3], 10) |
30 | | -const proportion = (max, val) => Math.round(parseInt(val, 10) * 100 / max) |
31 | | -const sortRowsByDensity = sort((row1, row2) => getDensityCell(row2) - getDensityCell(row1)) |
| 31 | +const getDensityCell = row => parseInt(row[3], 10); |
| 32 | +const proportion = (max, val) => Math.round(parseInt(val, 10) * 100 / max); |
| 33 | +const sortRowsByDensity = sort( |
| 34 | + (row1, row2) => getDensityCell(row2) - getDensityCell(row1) |
| 35 | +); |
32 | 36 |
|
33 | 37 | const calcMaxDensity = pipe( |
34 | 38 | sortRowsByDensity, |
35 | 39 | first, |
36 | 40 | getDensityCell |
37 | | -) |
| 41 | +); |
38 | 42 |
|
39 | 43 | const calcRowsProportionToMax = rows => max => rows.map(pipe( |
40 | 44 | getDensityCell, |
41 | 45 | densityCell => proportion(max, densityCell) |
42 | | -)) |
| 46 | +)); |
| 47 | + |
43 | 48 | const appendProportionCell = rows => proportions => rows.map( |
44 | 49 | (row, index) => appendCell(row, proportions[index]) |
45 | | -) |
| 50 | +); |
| 51 | + |
46 | 52 | const appendTableProportionCol = rows => pipe( |
47 | 53 | calcMaxDensity, |
48 | 54 | calcRowsProportionToMax(rows), |
49 | 55 | appendProportionCell(rows) |
50 | | -)(rows) |
| 56 | +)(rows); |
| 57 | + |
| 58 | +const parseTableLines = map(split(',')); |
51 | 59 |
|
52 | | -const parseTableLines = map(split(',')) |
53 | 60 | const toLines = pipe( |
54 | 61 | split('\n'), |
55 | 62 | skipFirst, |
56 | 63 | filter(hasValue) |
57 | | -) |
| 64 | +); |
58 | 65 |
|
59 | | -const readFile = file => fs.readFileSync(file).toString() |
| 66 | +const readFile = file => fs.readFileSync(file).toString(); |
60 | 67 |
|
61 | 68 | const getDataset = pipe( |
62 | 69 | readFile, |
63 | 70 | toLines, |
64 | 71 | parseTableLines |
65 | | -) |
| 72 | +); |
66 | 73 |
|
67 | 74 | const main = pipe( |
68 | 75 | getDataset, |
69 | 76 | sortRowsByDensity, |
70 | 77 | appendTableProportionCol, |
71 | 78 | renderTable |
72 | | -) |
| 79 | +); |
73 | 80 |
|
| 81 | +console.log(main('./cities.dat')); |
0 commit comments