Skip to content

Commit 370d04b

Browse files
committed
winrate colors are working hooray
1 parent 2909acf commit 370d04b

File tree

3 files changed

+41
-259
lines changed

3 files changed

+41
-259
lines changed

app/assets/javascripts/crossfilter.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,7 @@ function crossfilter() {
885885
orderNatural: orderNatural,
886886
size: size,
887887
dispose: dispose,
888+
clone: clone,
888889
remove: dispose // for backwards-compatibility
889890
};
890891

@@ -1226,6 +1227,10 @@ function crossfilter() {
12261227
return group;
12271228
}
12281229

1230+
function clone() {
1231+
return dimension.group(key);
1232+
}
1233+
12291234
return reduceCount().orderNatural();
12301235
}
12311236

app/assets/javascripts/scout.js

Lines changed: 33 additions & 253 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
var formatNumber = d3.format(",d"),
2-
formatChange = d3.format("+,d"),
3-
formatDate = d3.time.format("%B %d, %Y"),
4-
formatTime = d3.time.format("%I:%M %p");
2+
winInterp = d3.interpolateHsl(d3.hsl(0, 0.44, 0.49), d3.hsl(122, 0.44, 0.49));
3+
4+
function logistic(x) {
5+
return 1.0 / (1 + Math.exp(-x));
6+
}
57

68
// we will keep a list of filter objects
79
// each filter object will have:
@@ -103,236 +105,6 @@ function matchList(elem) {
103105
});
104106
}
105107

106-
function barChart() {
107-
if (!barChart.id) barChart.id = 0;
108-
109-
var margin = {top: 10, right: 10, bottom: 20, left: 10},
110-
x,
111-
y = d3.scale.linear().range([100, 0]),
112-
id = barChart.id++,
113-
axis = d3.svg.axis().orient("bottom").ticks(4),
114-
// vaxis = d3.svg.axis().orient("left").ticks(4).scale(y),
115-
brush = d3.svg.brush(),
116-
brushDirty,
117-
dimension,
118-
group,
119-
round;
120-
121-
function chart(div) {
122-
var width = x.range()[1],
123-
height = y.range()[0];
124-
125-
var topValue = group.top(1)[0].value;
126-
if (_.has(topValue, "wins")) {
127-
y.domain([0, 100]);
128-
} else {
129-
y.domain([0, topValue.value]);
130-
}
131-
132-
div.each(function() {
133-
var div = d3.select(this),
134-
g = div.select("g");
135-
136-
// Create the skeletal chart.
137-
if (g.empty()) {
138-
// RESET link, hidden at first
139-
div.select(".title").append("a")
140-
.attr("href", "javascript:reset(" + id + ")")
141-
.attr("class", "reset")
142-
.attr("class", "filtered")
143-
.text("reset")
144-
.style("display", "none");
145-
146-
limits = div.select(".title").append("div")
147-
.attr("class", "filtered")
148-
.style("display", "none")
149-
.text("from ");
150-
151-
lower_limit = limits.append("span")
152-
.text("-")
153-
.attr("class", "lower");
154-
155-
limits.append("span").text(" to ");
156-
157-
upper_limit = limits.append("span")
158-
.text("-")
159-
.attr("class", "upper");
160-
161-
g = div.append("svg")
162-
.attr("width", width + margin.left + margin.right)
163-
.attr("height", height + margin.top + margin.bottom)
164-
.append("g")
165-
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
166-
167-
/** WHY IS THIS HERE
168-
g.append("clipPath")
169-
.attr("id", "clip-" + id)
170-
.append("rect")
171-
.attr("width", width)
172-
.attr("height", height);
173-
*/
174-
175-
g.selectAll(".bar")
176-
.data(["background", "foreground"])
177-
.enter().append("path")
178-
.attr("class", function(d) { return d + " bar"; })
179-
.datum(group.all());
180-
181-
g.selectAll(".foreground.bar")
182-
.attr("clip-path", "url(#clip-" + id + ")");
183-
184-
g.append("g")
185-
.attr("class", "axis")
186-
.attr("transform", "translate(0," + height + ")")
187-
.call(axis);
188-
189-
/** Y AXIS WAS DISTRACTING AS IT CHANGED CONSTANTLY
190-
g.append("g")
191-
.attr("class", "axis")
192-
.attr("class", "vaxis")
193-
.attr("transform", "translate(" + width + ", 0)");
194-
*/
195-
196-
// Initialize the brush component with pretty resize handles.
197-
var gBrush = g.append("g").attr("class", "brush").call(brush);
198-
gBrush.selectAll("rect").attr("height", height);
199-
gBrush.selectAll(".resize").append("path").attr("d", resizePath);
200-
}
201-
202-
// Only redraw the brush if set externally.
203-
if (brushDirty) {
204-
brushDirty = false;
205-
g.selectAll(".brush").call(brush);
206-
div.selectAll(".title .filtered").style("display", brush.empty() ? "none" : null);
207-
if (brush.empty()) {
208-
g.selectAll("#clip-" + id + " rect")
209-
.attr("x", 0)
210-
.attr("width", width);
211-
} else {
212-
var extent = brush.extent();
213-
g.selectAll("#clip-" + id + " rect")
214-
.attr("x", x(extent[0]))
215-
.attr("width", x(extent[1]) - x(extent[0]));
216-
}
217-
}
218-
219-
g.selectAll(".bar").attr("d", barPath);
220-
// g.selectAll(".vaxis").call(vaxis);
221-
});
222-
223-
function barPath(groups) {
224-
var path = [],
225-
i = -1,
226-
n = groups.length,
227-
barwidth = Math.floor(width / n) + 1,
228-
d;
229-
while (++i < n) {
230-
d = groups[i];
231-
path.push("M", x(d.key), ",", height, "V", y(d.value.value), "h", barwidth, "V", height);
232-
}
233-
return path.join("");
234-
}
235-
236-
function resizePath(d) {
237-
var e = +(d == "e"),
238-
x = e ? 1 : -1,
239-
y = height / 3;
240-
return "M" + (.5 * x) + "," + y
241-
+ "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6)
242-
+ "V" + (2 * y - 6)
243-
+ "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y)
244-
+ "Z"
245-
+ "M" + (2.5 * x) + "," + (y + 8)
246-
+ "V" + (2 * y - 8)
247-
+ "M" + (4.5 * x) + "," + (y + 8)
248-
+ "V" + (2 * y - 8);
249-
}
250-
}
251-
252-
brush.on("brushstart.chart", function() {
253-
var div = d3.select(this.parentNode.parentNode.parentNode);
254-
div.selectAll(".title .filtered").style("display", null);
255-
});
256-
257-
brush.on("brush.chart", function() {
258-
var g = d3.select(this.parentNode),
259-
extent = brush.extent();
260-
if (round) g.select(".brush")
261-
.call(brush.extent(extent = extent.map(round)))
262-
.selectAll(".resize")
263-
.style("display", null);
264-
g.select("#clip-" + id + " rect")
265-
.attr("x", x(extent[0]))
266-
.attr("width", x(extent[1]) - x(extent[0]));
267-
dimension.filterRange(extent);
268-
var div = d3.select(this.parentNode.parentNode.parentNode);
269-
div.select(".lower").text(Math.floor(extent[0]));
270-
div.select(".upper").text(Math.floor(extent[1]));
271-
});
272-
273-
brush.on("brushend.chart", function() {
274-
if (brush.empty()) {
275-
var div = d3.select(this.parentNode.parentNode.parentNode);
276-
div.selectAll(".title .filtered").style("display", "none");
277-
div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%");
278-
dimension.filterAll();
279-
}
280-
});
281-
282-
chart.margin = function(_) {
283-
if (!arguments.length) return margin;
284-
margin = _;
285-
return chart;
286-
};
287-
288-
chart.x = function(_) {
289-
if (!arguments.length) return x;
290-
x = _;
291-
axis.scale(x);
292-
brush.x(x);
293-
return chart;
294-
};
295-
296-
chart.y = function(_) {
297-
if (!arguments.length) return y;
298-
y = _;
299-
vaxis.scale(y);
300-
return chart;
301-
};
302-
303-
chart.dimension = function(_) {
304-
if (!arguments.length) return dimension;
305-
dimension = _;
306-
return chart;
307-
};
308-
309-
chart.filter = function(_) {
310-
if (_) {
311-
brush.extent(_);
312-
dimension.filterRange(_);
313-
} else {
314-
brush.clear();
315-
dimension.filterAll();
316-
}
317-
brushDirty = true;
318-
return chart;
319-
};
320-
321-
chart.group = function(_) {
322-
if (!arguments.length) return group;
323-
group = _;
324-
return chart;
325-
};
326-
327-
chart.round = function(_) {
328-
if (!arguments.length) return round;
329-
round = _;
330-
return chart;
331-
};
332-
333-
return d3.rebind(chart, brush, "on");
334-
};
335-
336108
function data_host() {
337109
return "http://localhost:3000";
338110
}
@@ -355,18 +127,24 @@ function entities_url() {
355127
return data_host() + "/ents" + debug_suffix() + ".csv";
356128
}
357129

358-
function filter_chart(element, dimension, group, domain) {
130+
function filter_chart(element, dimension, group, colorgroup, domain) {
359131
element.group = group;
132+
element.colorgroup = colorgroup;
360133
element.dimension = dimension;
361134
element.djchart = $(element).parents('.djchart');
362135
var dateAxis = (domain[0] > Date.UTC(2010, 1, 1));
363136

364137
element.render = function () {
365138
var grp = this.group.all();
366-
if (typeof grp !== 'undefined') {
367-
var xyValues = _.map(grp, function (g) { return [g.key, g.value.value]; })
368-
this.chart.series[0].setData(xyValues);
369-
}
139+
var colorGrp = this.colorgroup.all();
140+
141+
var xycolor = _.map(_.zip(grp, colorGrp), function (gs) {
142+
var winpct = gs[1].value.value;
143+
var color = winInterp(logistic((winpct - 50) / 10.0));
144+
return {x:gs[0].key, y:gs[0].value.value, color:color, winpct:winpct};
145+
});
146+
147+
this.chart.series[0].setData(xycolor);
370148
}
371149

372150
element.reset = function () {
@@ -399,10 +177,15 @@ function filter_chart(element, dimension, group, domain) {
399177
renderAll();
400178

401179
// TODO if not too hard, make selection area draggable
180+
// TODO get rid of remaining uses of d3, make page lighter
402181

403182
event.preventDefault();
404183
};
405184

185+
element.tooltip = function () {
186+
return this.x + ': ' + this.y + ' games, ' + this.point.winpct + '% win.';
187+
};
188+
406189
var options = {
407190
chart: {
408191
type: "column",
@@ -437,24 +220,19 @@ function filter_chart(element, dimension, group, domain) {
437220
title: '',
438221
endOnTick: false
439222
},
440-
credits: {enabled:false},
223+
credits: { enabled: false },
224+
tooltip: { formatter: element.tooltip },
441225
plotOptions: {
442226
column:{
443227
animation:false,
444-
color:'steelblue',
228+
cursor: 'pointer',
229+
color:'rgba(0,0,0,0)',
445230
groupPadding: 0,
446231
pointPadding: 0,
447232
borderWidth: 0,
448233
pointPlacement: 'on',
449-
marker: {
450-
enabled:true,
451-
radius:4,
452-
symbol: "circle",
453-
lineColor: "#111",
454-
lineWidth:1,
455-
fillColor:"#222",
456-
states: {hover:{enabled:true}}
457-
},
234+
states: { hover: { enabled: false } },
235+
marker: { enabled:false },
458236
shadow:false,
459237
threshold:0
460238
}
@@ -493,7 +271,9 @@ function add_filterchart(element, dimension, group, title, domain) {
493271
var thechart = $(document.createElement('div')).addClass('filterchart');
494272
chartContainer.append(thechart);
495273

496-
filter_chart(thechart[0], dimension, group, domain);
274+
var colorgroup = groupWinPct(group.clone());
275+
276+
filter_chart(thechart[0], dimension, group, colorgroup, domain);
497277

498278
element.append(chartContainer);
499279
}
@@ -557,7 +337,7 @@ function scout_init() {
557337
winGrp = groupDJ(winDim.group());
558338

559339
durDim = gr_cf.dimension(function(gr) { return Math.min(40, gr.match.duration_minutes) });
560-
durGrp = groupWinPct(durDim.group(function(d) { return d }));
340+
durGrp = groupDJ(durDim.group(function(d) { return d }));
561341

562342
dateDim = gr_cf.dimension(function(gr) {
563343
return gr.match.play_date.getTime();
@@ -594,7 +374,7 @@ function scout_init() {
594374
.data([matchList]);
595375

596376
d3.selectAll("#total")
597-
.text(formatNumber(gr_cf.size()));
377+
.text(formatNumber(gr_cf.size() / 2));
598378

599379
$("#player_id").each( function(index, playerIdInput) {
600380
$(playerIdInput).change( function() {
@@ -616,7 +396,7 @@ function scout_init() {
616396
add_filterchart($('#filtercharts'), mb2Dim, mb2Grp, 'Player\'s 2nd Mining Base Timing', [0, 15]);
617397
add_filterchart($('#filtercharts'), omb2Dim, omb2Grp, 'Opponent\'s 2nd Mining Base Timing', [0, 15]);
618398
add_filterchart($('#filtercharts'), durDim, durGrp, 'Game Length, minutes', [0, 40]);
619-
add_filterchart($('#filtercharts'), dateDim, dateGrp, 'Game Date', [Date.UTC(2014, 7, 1), Date.UTC(2014, 8, 3)]);
399+
add_filterchart($('#filtercharts'), dateDim, dateGrp, 'Game Date', [Date.UTC(2014, 6, 25), Date.UTC(2014, 8, 15)]);
620400

621401
renderAll();
622402

0 commit comments

Comments
 (0)