-
Notifications
You must be signed in to change notification settings - Fork 132
/
DecisionMatrixRaw.js
173 lines (164 loc) · 4.3 KB
/
DecisionMatrixRaw.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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import * as React from "react"
import { scaleLinear } from "d3-scale"
import { extent } from "d3-array"
import { forceSimulation, forceX, forceY, forceCollide } from "d3-force"
import { Mark } from "semiotic-mark"
import { MATRIX_DATA } from "../sampledata/matrixData"
import { XYFrame } from "../../components"
import ProcessViz from "./ProcessViz"
const speedLabels = ["6 Weeks", "3 Months", "6 Months", "1 Year", "2 Years"]
const expenseLabels = ["$1K", "$10K", "$100K", "$1M", "$10M"]
const MIN_RADIUS = 10
const MAX_RADIUS = 35
//Define dpilicate axes, visible on non-integer values, hidden (with labels) on integer values
const axes = [
{
key: "yAxis",
orient: "left",
className: "showingTickLine",
label: {
name: "← Expense →",
position: {
anchor: "middle"
},
locationDistance: 70
},
tickValues: [0.5, 1.5, 2.5, 3.5, 4.5, 5.5],
tickFormat: () => {
return ""
}
},
{
key: "xAxis",
orient: "bottom",
className: "showingTickLine",
label: {
name: "← Delivery Speed →",
position: {
anchor: "middle"
},
locationDistance: 60
},
tickValues: [0.5, 1.5, 2.5, 3.5, 4.5, 5.5],
tickFormat: () => {
return ""
}
},
{
key: "yAxis_labs",
orient: "left",
className: "hiddenTickLine",
tickValues: [1, 2, 3, 4, 5],
tickFormat: d => {
return expenseLabels[d - 1]
}
},
{
key: "xAxis_labs",
orient: "bottom",
className: "hiddenTickLine",
tickValues: [1, 2, 3, 4, 5],
tickFormat: d => {
return speedLabels[d - 1]
}
}
]
function processData(data, sizeBy) {
//Augment data with radius size, subject to scale
const scale = scaleLinear()
.domain(
extent(
data.map(d => {
return +d[sizeBy]
})
)
)
.range([MIN_RADIUS, MAX_RADIUS])
data = data.map(d => {
d.radius = sizeBy === "None" ? 10 : scale(+d[sizeBy])
return d
})
//Jitter the points so they dont collide with one another when xy values are similar
//Copied From: https://bl.ocks.org/mbostock/6526445e2b44303eebf21da3b6627320
const simulation = forceSimulation(data)
.force(
"x",
forceX(d => {
return +d.Timeline
}).strength(1)
)
.force(
"y",
forceY(d => {
return +d.Cost
}).strength(1)
)
.force(
"collide",
forceCollide(d => {
return d.radius / 100
})
)
.stop()
for (let i = 0; i < 120; ++i) simulation.tick()
return data
}
function fetchTooltipContent(d) {
return [
<div key={"title"} id="tooltip_title">{`Vendor: ${d.Vendor}`}</div>,
<div key={"metrics"} id="tooltip_metrics">
<div>
<b>Previous Contracts: </b>
<span>{d["Previous Contracts"]}</span>
</div>
<div>
<b>Number Of Employees: </b>
<span>{d["Number of Employees"]}</span>
</div>
</div>
]
}
export default function DecisionMatrixRaw(sizeBy) {
const decisionMatrixChart = {
size: [750, 550],
margin: { top: 10, right: 80, bottom: 80, left: 100 },
name: "Decision Matrix",
className: "decisionMatrix",
points: processData(MATRIX_DATA, sizeBy),
pointStyle: () => {
return { fill: "white", stroke: "black", strokeWidth: "3px" }
},
customPointMark: ({ d }) => {
return <Mark markType="circle" r={d.radius} />
},
renderKey: d => {
return d.Index
},
axes: axes,
xAccessor: d => d.x,
yAccessor: d => d.y,
xExtent: [0.5, 5.5],
yExtent: [0.5, 5.5],
backgroundGraphics: (
<rect fill={"url(#gradient)"} x={100} y={10} width={570} height={460} />
),
additionalDefs: (
//Linear Gradient gives stoplight color zones to encode desirability
<linearGradient id="gradient" x1="0%" y1="100%" x2="100%" y2="0%">
<stop offset="10%" stopColor="green" stopOpacity={0.3} />
<stop offset="50%" stopColor="gold" stopOpacity={0.3} />
<stop offset="90%" stopColor="red" stopOpacity={0.3} />
</linearGradient>
),
hoverAnnotation: true,
tooltipContent: d => {
return fetchTooltipContent(d)
}
}
return (
<div className="matrixWrapper">
<ProcessViz frameSettings={decisionMatrixChart} frameType="XYFrame" />
<XYFrame {...decisionMatrixChart} />
</div>
)
}