1 | const utils = require('./utils')
|
2 | const { verifyData, PAD, maxKeyLen, EOL } = utils
|
3 | let tmp
|
4 |
|
5 | const getPadChar = (styles, values, param, gapChar) => {
|
6 | const firstVal = values[0]
|
7 | if (!values.length) return gapChar
|
8 | return param <= firstVal ? styles[0]
|
9 | : getPadChar(styles.slice(1), values.slice(1), param - firstVal, gapChar)
|
10 | }
|
11 |
|
12 | module.exports = (data, opts, isDonut = false) => {
|
13 | verifyData(data)
|
14 |
|
15 | const newOpts = Object.assign({
|
16 | radius: 4,
|
17 | left: 0,
|
18 | innerRadius: 1
|
19 | }, opts)
|
20 |
|
21 | const { radius, left, innerRadius } = newOpts
|
22 |
|
23 | let result = PAD.repeat(left)
|
24 |
|
25 | const values = data.map(item => item.value)
|
26 | const total = values.reduce((a, b) => a + b)
|
27 | const ratios = values.map(value => (value / total).toFixed(2))
|
28 | const styles = data.map(item => item.style)
|
29 | const keys = data.map(item => item.key)
|
30 | const maxKeyLength = maxKeyLen(data)
|
31 | const limit = isDonut ? innerRadius : 0
|
32 | const gapChar = styles.slice(-1)[0]
|
33 |
|
34 | for (let i = -radius; i < radius; i++) {
|
35 | for (let j = -radius; j < radius; j++) {
|
36 | if (Math.pow(i, 2) + Math.pow(j, 2) < Math.pow(radius, 2)) {
|
37 | tmp = Math.atan2(i, j) * 1 / Math.PI * 0.5 + 0.5
|
38 | result += isDonut ? (Math.abs(i) > limit || Math.abs(j) > limit)
|
39 | ? getPadChar(styles, ratios, tmp, gapChar)
|
40 | : PAD.repeat(2)
|
41 | : getPadChar(styles, ratios, tmp, gapChar)
|
42 | } else {
|
43 | result += PAD.repeat(2)
|
44 | }
|
45 | }
|
46 |
|
47 | result += EOL + PAD.repeat(left)
|
48 | }
|
49 |
|
50 | result += EOL + PAD.repeat(left)
|
51 |
|
52 | for (var i = 0; i < styles.length; i++) {
|
53 | result += styles[i] + PAD + keys[i].padStart(maxKeyLength) + ': ' +
|
54 | values[i] + PAD + '(' + (ratios[i] * 100).toFixed(0) + '%' + ')' +
|
55 | EOL + PAD.repeat(left)
|
56 | }
|
57 |
|
58 | return result
|
59 | }
|