Skip to content

Instantly share code, notes, and snippets.

@gordonwoodhull
Created April 17, 2020 16:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gordonwoodhull/5d12886460c82132d8660537dc56641d to your computer and use it in GitHub Desktop.
Save gordonwoodhull/5d12886460c82132d8660537dc56641d to your computer and use it in GitHub Desktop.
dashboard1
license: mit
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Test-Dashboard</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dc/3.0.9/dc.min.css">
<!-- <link rel="stylesheet" href="d3.slider.css"> -->
<!-- Dashboard Dependecies -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/keen/dashboards@gh-pages/assets/css/keen-dashboards.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.min.js"></script>
<!-- <script type='text/javascript' src='https://rawgit.com/crossfilter/reductio/master/reductio.min.js'></script> -->
<style>
html, body {
height: 100%;
width: 100%;
}
.svg-container {
width: 100%;
}
.irs--big.irs-with-grid {
height: 70px;
width: 500px;
margin-left: 5%;
}
g.stack._0.rect {
pointer-events: none;
}
/*thead {
display: table;
table-layout:fixed;
width: 100%;
}
tbody {
display: block;
height: 19em;
overflow-y: scroll;
}
tbody tr {
display: table;
table-layout:fixed;
width: 100%;
}
th, td {
width: auto;
}*/
table {
display: table;
width: 100%;
}
table thead,
table tbody {
width: 100%;
}
table thead {
overflow-y: scroll;
display: table;
table-layout: fixed;
width: calc(100% - 16px); assuming scrollbar width as 16px
}
table tbody {
overflow: auto;
height: 150px;
display: block;
}
table tr {
width: 100%;
text-align: left;
display: table;
table-layout: fixed;
}
/* .chart-wrapper {
display: none;
}*/
#focus .axis.x .tick text {
text-anchor: end;
transform: rotate(-60deg) translate(-10px,-12px);
}
#range.dc-chart .axis {
display: none;
}
#range svg {
display: block; /* default inline causes padding? */
}
</style>
</head>
<body class="keen-dashboard">
<!-- Navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<span>
<a class="navbar-brand" title="Click to view data source" target="_blank" href="https://github.com/square/crossfilter/wiki/API-Reference">
Dc.js Simple Dashboard
</a>
</span>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="table-responsive col-md-12">
<h4>Filtered Records</h4>
<table class='table table-hover table-striped table-bordered' id='dc-table-graph'>
<thead>
<tr class='table-header'>
<!-- Programmatically insert table headers here -->
</tr>
</thead>
</table>
<!-- <div class="col-sm-12" id="paging">
Showing <span id="begin"></span>-<span id="end"></span> of <span id="size"></span>
<input id="Prev" class="btn btn-secondary" role="button" type="button" value="Prev" onclick="javascript:prevPage()" />
<input id="Next" class="btn btn-secondary" role="button" type="button" value="Next" onclick="javascript:nextPage()"/>
</div> -->
</div>
</div>
<div id="vertical-whitespace" style="padding: 10px"></div>
</div>
<div class="col-lg-6 col-md-6">
<div class="row">
<div class="col-lg-12 col-md-12">
<div class="chart-wrapper">
<div class="chart-stage">
<div id="bar-chart" class="svg-container">
<div class="chart-title">
<span>
<strong>Bar Types</strong>
</span>
<span>
<a id="reset-focus" href="#" class="reset">reset</a>&emsp;&emsp;
<a id="reset-all" href="javascript:dc.filterAll(); dc.redrawAll();" class="reset">reset all</a>
</span>
<!-- <div id="range"></div> -->
<div id="focus"></div>
<div id="first-letters"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-6 col-md-6">
<div class="row">
<div class="col-lg-12 col-md-12">
<div class="chart-wrapper">
<div class="chart-stage">
<div id="pie-chart" class="svg-container">
<div class="chart-title">
<span>
<strong>Pie Types</strong>
</span>
<span>
<a href="javascript:pieChart.filterAll(); dc.redrawAll();" style="display:none;" class="reset">reset</a>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script data-require="underscore.js@1.5.2" data-semver="1.5.2" src="//cdn.jsdelivr.net/underscorejs/1.5.2/underscore-min.js"></script>
<!-- <script data-require="coffee-script@1.4.0" data-semver="1.4.0" src="//cdnjs.cloudflare.com/ajax/libs/coffee-script/1.4.0/coffee-script.min.js"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.7/crossfilter.js"></script>
<!-- <script src="d3.slider.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.15.1/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.2.1/dc.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reductio/1.0.0/reductio.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<script lang="babel" type="text/babel" src="index.js"></script>
<!--Plugin CSS file with desired skin-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css"/>
<!--jQuery-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!--Plugin JavaScript file-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
</html>
const log = console.log;
var dataTable = dc.dataTable("#dc-table-graph");
var pieChart = dc.pieChart("#pie-chart");
// const barChart = dc.barChart("#bar-chart");
// var focus = dc.barChart('#focus');
const chart_11 = dc.compositeChart("#focus");
var range = dc.barChart('#range');
// var composite = dc.compositeChart("#pie-chart");
var dim = {}, // Stores all crossfilter dimensions
groups = {}, // Stores all crossfilter groups
cf;
// index a group key -> i and i -> key
function ordinal_to_linear_group(group, sort) {
var _ord2int, _int2ord;
return {
all: function() {
var ret = group.all();
if(sort) // NEW
ret = ret.slice().sort(sort);
_ord2int = {};
_int2ord = [];
ret.forEach(function(d, i) {
_ord2int[d.key] = i;
_int2ord[i] = d.key;
});
return ret;
},
ord2int: function(o) {
if(!_ord2int)
this.all();
return _ord2int[o];
},
int2ord: function(i) {
if(!_int2ord)
this.all();
return _int2ord[i];
}
};
}
d3.csv("info.csv").then(function(data) {
// console.log("data:",data);
data.forEach(d => {
// var parts = d.Created.split('/');
d.date = new Date(d.date);
});
draw_charts(data);
});
function draw_charts(data)
{
// Programmatically insert header labels for table
var tableHeader = d3.select(".table-header")
.selectAll("th");
// Bind data to tableHeader selection.
console.log(data);
// 'Project_id', 'change_request', 'Created', 'predicted_class', 'predicted_probability'
tableHeader = tableHeader.data(
[
{label: "pid", field_name: "pid", sort_state: "ascending"},
{label: "cid", field_name: "cid", sort_state: "ascending"},
{label: "date", field_name: "date", sort_state: "ascending"},
{label: "types", field_name: "types", sort_state: "ascending"},
{label: "probability", field_name: "probability", sort_state: "descending"} // Note Max Conf row starts off as descending
]
);
// enter() into virtual selection and create new <th> header elements for each table column
tableHeader = tableHeader.enter()
.append("th")
.text(function (d) { return d.label; }) // Accessor function for header titles
.on("click", tableHeaderCallback);
function tableHeaderCallback(d) {
// Highlight column header being sorted and show bootstrap glyphicon
var activeClass = "info";
d3.selectAll("#dc-table-graph th") // Disable all highlighting and icons
.classed(activeClass, false)
.selectAll("span")
.style("visibility", "hidden") // Hide glyphicon
var activeSpan = d3.select(this) // Enable active highlight and icon for active column for sorting
.classed(activeClass, true) // Set bootstrap "info" class on active header for highlight
.select("span")
.style("visibility", "visible");
// Toggle sort order state to user desired state
d.sort_state = d.sort_state === "ascending" ? "descending" : "ascending";
var isAscendingOrder = d.sort_state === "ascending";
dataTable
.order(isAscendingOrder ? d3.ascending : d3.descending)
.sortBy(function(datum) { return datum[d.field_name]; });
// Reset glyph icon for all other headers and update this headers icon
activeSpan.node().className = ''; // Remove all glyphicon classes
// Toggle glyphicon based on ascending/descending sort_state
activeSpan.classed(
isAscendingOrder ? "glyphicon glyphicon-sort-by-attributes" :
"glyphicon glyphicon-sort-by-attributes-alt", true);
updateTable();
dataTable.redraw();
}
// Initialize sort state and sort icon on one of the header columns
// Highlight "Max Conf" cell on page load
// This can be done programmatically for user specified column
tableHeader.filter(function(d) {
console.log("==============>", d.label);
return d.label === "pid"; })
.classed("info", true);
var tableSpans = tableHeader
.append("span") // For Sort glyphicon on active table headers
.classed("glyphicon glyphicon-sort-by-attributes-alt", true)
.style("visibility", "hidden")
.filter(function(d) { return d.label === "pid"; })
.style("visibility", "visible");
cf = crossfilter(data); // Main crossfilter objects
let barTypeDimension = cf.dimension(function(d) { return d.cid});
let barTypeGroup = barTypeDimension.group();
var reducer_time_est_max = reductio().max(function(d) {
return parseFloat(d.probability)
});
let pieTypeDimension = cf.dimension(function(d) { return d.pid});
let pieTypeGroup = pieTypeDimension.group();
var reducer_prob = reductio().max(function(d) {
return parseFloat(d.probability)
});
var pred_prob_max_pie = reducer_prob(pieTypeGroup);
pieChart
.height(400)
.dimension(pieTypeDimension)
.group(pred_prob_max_pie )
.valueAccessor(function(p) {
return parseFloat(p.value.max) || 0;
})
.ordering(d => -(d.value.max || 0))
.othersGrouper(null)
.slicesCap(10)
.innerRadius(100)
.externalLabels(30)
.externalRadiusPadding(50)
.drawPaths(true)
.legend(dc.legend());
dc.override(pieChart, 'legendables', function() {
var legendables = this._legendables();
return legendables.filter(function(l) {
return l.data.max > 0;
});
});
// example of formatting the legend via svg
// http://stackoverflow.com/questions/38430632/how-can-we-add-legends-value-beside-of-legend-with-proper-alignment
pieChart.on('pretransition', function(chart) {
chart.selectAll('.dc-legend-item text')
.text('')
.append('tspan')
.text(function(d) { return d.name; })
.append('tspan')
.attr('x', 100)
.attr('text-anchor', 'end')
.text(function(d) {
return d.data.max; });
});
function static_copy_group(group) {
var all = group.all().map(kv => ({key: kv.key, value: kv.value}));
return {
all: function() {
return all;
}
}
}
function any_filters() {
return [chart_11]
.some(chart => chart.filters().length);
}
function hide_second_chart(chart) {
chart.select('.sub._1')
.attr('visibility', any_filters() ? 'visible' : 'hidden')
}
[chart_11].forEach(function(chart) {
chart.on('pretransition', hide_second_chart)
})
var chart_11_grp_copy = static_copy_group(reducer_time_est_max(barTypeGroup));
var group1 = ordinal_to_linear_group(chart_11_grp_copy, (a,b) => d3.descending(a.value.max, b.value.max));
var group = ordinal_to_linear_group(reducer_time_est_max(barTypeGroup), (a,b) => d3.descending(a.value.max, b.value.max));
var c1 = dc.barChart(chart_11)
.group(chart_11_grp_copy)
.colors('gray')
// .xUnits(dc.units.integers)
.keyAccessor(kv => group.ord2int(kv.key))
.valueAccessor(function(p) {
return parseFloat(p.value.max) || 0;
})
.controlsUseVisibility(true);
var c2 = dc.barChart(chart_11)
.group(barTypeGroup)
.colors('red')
// .xUnits(dc.units.integers)
.keyAccessor(kv => group.ord2int(kv.key))
.valueAccessor(function(p) {
return parseFloat(p.value.max) || 0;
})
.controlsUseVisibility(true)
.brushOn(false);
var linear_domain = [-0.5, 100 - 0.5];
chart_11
.width(850).height(350)
.margins({left: 60, top: 20, right: 10, bottom: 100})
.x(d3.scaleLinear().domain(linear_domain))
.xUnits(dc.units.integers)
// .x(d3.scaleOrdinal())
// .xUnits(dc.units.ordinal)
// .keyAccessor(kv => group.ord2int(kv.key))
// .valueAccessor(function(p) {
// return parseFloat(p.value.max) || 0;
// })
// .centerBar(true)
.yAxisLabel('counts')
.elasticY(true)
.brushOn(false)
.dimension(barTypeDimension)
// .mouseZoomable(true)
.zoomScale([4,8])
// .group(barTypeGroup_mod)
.title(kv => kv.key)
// .elasticX(true)
.transitionDuration(0)
.compose([ c1,c2 ]);
chart_11.xAxis()
.tickFormat(function(d) { return group.int2ord(d); });
// equivalent of javascript: link, don't know why those didn't work
d3.select('#reset-focus').on('click', () => {
focus.filterAll();
dc.redrawAll();
})
d3.select('#reset-all').on('click', () => {
dc.filterAll();
dc.redrawAll();
})
var chart_11Filter = [];
chart_11.filterHandler(function() {}); // disable built-in filtering
chart_11.applyFilter = function() { // non-standard method
if(chart_11Filter.length)
this.dimension().filterFunction(function(k) {
return chart_11Filter.includes(k);
});
else this.dimension().filter(null);
};
chart_11.filterAll = function() {
chart_11Filter = [];
this.applyFilter();
};
chart_11.fadeDeselectedArea = function (brushSelection) {
var _chart = this;
var bars = _chart.chartBodyG().selectAll('rect.bar');
if (chart_11Filter.length) {
bars.classed(dc.constants.SELECTED_CLASS, function (d) {
return chart_11Filter.includes(d.data.key);
});
bars.classed(dc.constants.DESELECTED_CLASS, function (d) {
return !chart_11Filter.includes(d.data.key);
});
} else {
bars.classed(dc.constants.SELECTED_CLASS, false);
bars.classed(dc.constants.DESELECTED_CLASS, false);
}
};
chart_11.on('pretransition', function(chart) {
chart.selectAll('rect.bar').on('click.ordinal-select', function(d) {
var i = chart_11Filter.indexOf(d.data.key);
if(i >= 0)
chart_11Filter.splice(i, 1);
else
chart_11Filter.push(d.data.key);
chart.applyFilter();
chart.redrawGroup();
});
});
chart_11.on('preRedraw', function(chart) {
var domain = chart.x().domain(),
min = Math.ceil(domain[0]), max = Math.floor(domain[1]);
chart.xAxis().tickValues(d3.range(min, max+1));
});
// Setup different dimensions for plots
dim.tableMaxConfidence = cf.dimension(function (d) {
return d.pid;
});
// ##############################
// Generate the dc.js dataTable
// ##############################
// Create generating functions for each columns
var columnFunctions = [
function(d) { return d.pid; },
function(d) { return d.cid; },
function(d) { return d.date; },
function(d) { return d.types; },
function(d) { return d.probability; },
];
// extra dimensions for filtering
const cidDimension = cf.dimension(d => d.cid),
dateDimension = cf.dimension(d => d.date);
var color = d3.scaleSequential() //d3.scaleLinear()
.domain([0, 0.9])
.interpolator(d3.interpolateBlues);
// Pagination implementation inspired by:
// https://github.com/dc-js/dc.js/blob/master/web/examples/table-pagination.html
dataTable.width(960).height(800)
.dimension(dim.tableMaxConfidence)
.group(function(d) { return "Dummy"}) // Must pass in. Ignored since .showGroups(false)
.size(Infinity)
.columns(columnFunctions)
.showGroups(false)
.sortBy(function(d){ return d.pid; }) // Initially sort by max_conf column
.order(d3.descending)
.on('pretransition', function (table) {
table.selectAll('td.dc-table-column._0')
.on('click',function(d){
table.filter(d.pid)
dc.redrawAll();
})
table.selectAll('td.dc-table-column._1')
.on('click',function(d){
cidDimension.filter(d.cid)
dc.redrawAll();
})
table.selectAll('td.dc-table-column._2')
.on('click',function(d){
dateDimension.filter(d.date)
dc.redrawAll();
})
table.selectAll('td.dc-table-column._4')
.style("background-color", function(d){
return color(d.probability)});
});
updateTable();
dc.renderAll();
dataTable.redraw();
}
var tableOffset = 0, tablePageSize = 10;
function updateTable() {
// Ensure Prev/Next bounds are correct, especially after filters applied to dc charts
var totFilteredRecs = cf.groupAll().value();
// // Adjust values of start and end record numbers for edge cases
var end = tableOffset + tablePageSize > totFilteredRecs ? totFilteredRecs : tableOffset + tablePageSize;
tableOffset = tableOffset >= totFilteredRecs ? Math.floor((totFilteredRecs - 1) / tablePageSize) * tablePageSize : tableOffset;
tableOffset = tableOffset < 0 ? 0 : tableOffset; // In case of zero entries
dataTable.redraw();
}
cid pid date types probability
ID17426 8894 2018-01-09 06:00:00 1 0.7
ID17487 3602 2018-05-19 06:00:00 1 0.6
ID17501 4763 2018-09-22 06:00:00 1 0.59
ID17488 3794 2018-05-26 06:00:00 1 0.57
ID17514 0506 2018-03-26 22:06:00 1 0.57
ID16288 4953 2018-02-26 22:26:00 1 0.56
ID18536 3606 2018-10-11 05:00:00 1 0.56
ID18660 7520 2018-09-15 06:00:00 1 0.52
ID18487 8894 2018-11-08 06:00:00 1 0.52
ID17295 7942 2018-03-26 22:06:00 1 0.5
ID16895 8866 2018-02-26 22:25:00 0 0.49
ID19026 8081 2019-02-16 05:01:00 0 0.49
ID16479 7414 2018-02-26 22:23:00 0 0.48
ID17607 7202 2018-09-22 06:00:00 0 0.48
ID19123 0612 2018-11-17 05:01:00 0 0.48
ID17752 9658 2018-12-05 06:00:00 0 0.47
ID16694 6140 2018-02-26 22:26:00 0 0.47
ID19280 6715 2019-09-02 05:01:00 0 0.47
ID16906 6001 2018-03-26 22:06:00 0 0.47
ID17799 2893 2018-10-13 06:00:00 0 0.46
ID18804 1922 2019-02-16 05:01:00 0 0.45
ID17420 5105 2018-07-07 06:00:00 0 0.45
ID16399 6651 2018-02-26 22:25:00 0 0.44
ID18563 2532 2018-09-22 06:00:00 0 0.44
ID17507 7533 2018-03-26 22:06:00 0 0.44
ID16567 1229 2018-02-26 22:29:00 0 0.44
ID16137 0146 2018-02-26 22:25:00 0 0.43
ID16009 5867 2018-03-26 22:06:00 0 0.43
ID18414 5074 2018-09-15 06:00:00 0 0.42
ID15516 4232 2018-02-28 13:45:00 0 0.42
ID15587 8669 2018-02-28 13:46:00 0 0.42
ID16085 9501 2018-02-26 22:25:00 0 0.41
ID16726 8891 2018-03-26 22:06:00 0 0.41
ID16927 8380 2018-02-26 22:26:00 0 0.41
ID16398 5178 2018-02-26 22:25:00 0 0.4
ID16965 0709 2018-02-26 22:26:00 0 0.4
ID17483 6176 2018-07-04 06:01:00 0 0.4
ID18318 9447 2018-10-13 06:00:00 0 0.39
ID18503 2764 2018-01-09 06:00:00 0 0.39
ID16911 6062 2018-02-26 22:26:00 0 0.38
ID16789 6329 2018-03-26 22:06:00 0 0.38
ID18569 6939 2018-10-11 05:00:00 0 0.38
ID17224 1056 2018-03-26 22:06:00 0 0.37
ID17477 6200 2018-09-06 06:01:00 0 0.37
ID17433 2617 2018-10-11 05:00:00 0 0.37
ID16664 2572 2018-02-26 22:26:00 0 0.36
ID17491 3562 2018-06-23 06:00:00 0 0.36
ID16565 1644 2018-03-26 22:06:00 0 0.36
ID16994 6989 2018-03-26 22:06:00 0 0.36
ID17233 6067 2018-03-26 22:06:00 0 0.35
ID17949 2556 2018-05-19 06:00:00 0 0.34
ID16695 6257 2018-02-26 22:28:00 0 0.34
ID17424 9501 2018-11-08 06:00:00 0 0.34
ID18064 1056 2018-05-26 06:00:00 0 0.34
ID16940 0174 2018-02-26 22:26:00 0 0.33
ID18985 0832 2018-10-11 05:00:00 0 0.32
ID17874 4439 2018-05-05 06:00:00 0 0.32
ID18436 8794 2018-07-21 06:00:00 0 0.32
ID16956 1644 2018-02-26 22:26:00 0 0.31
ID19142 3562 2019-02-26 06:00:00 0 0.31
ID19495 3895 2019-09-02 05:01:00 0 0.31
ID18738 1922 2018-10-13 06:00:00 0 0.31
ID18249 8072 2018-11-08 06:00:00 0 0.31
ID18450 8891 2018-10-11 05:00:00 0 0.31
ID18490 9763 2018-07-28 06:00:00 0 0.31
ID17378 3243 2018-03-26 22:06:00 0 0.3
ID17464 2260 2018-03-26 22:06:00 0 0.3
ID17322 6257 2018-03-26 22:06:00 0 0.3
ID19281 7098 2019-02-26 06:00:00 0 0.3
ID17030 7029 2018-03-26 22:06:00 0 0.3
ID17962 7601 2018-06-16 06:00:00 0 0.3
ID16397 4439 2018-02-26 22:25:00 0 0.3
ID17169 8507 2018-04-21 06:01:00 0 0.3
ID17879 3546 2018-04-26 00:27:00 0 0.3
ID16809 8009 2018-03-26 22:06:00 0 0.3
ID17690 8220 2018-03-26 22:06:00 0 0.3
ID17763 0906 2018-05-26 06:00:00 0 0.3
ID16605 1851 2018-02-26 22:23:00 0 0.29
ID19053 6532 2019-09-02 05:01:00 0 0.29
ID17083 8808 2018-03-26 22:06:00 0 0.29
ID19169 0217 2019-09-02 05:01:00 0 0.28
ID18308 8369 2018-07-07 06:00:00 0 0.28
ID16916 8316 2018-03-26 22:06:00 0 0.28
ID17569 1922 2018-03-26 22:06:00 0 0.28
ID17272 5787 2018-03-27 07:00:00 0 0.28
ID16469 0453 2018-03-26 22:06:00 0 0.28
ID16824 7575 2018-02-28 14:08:00 0 0.27
ID17693 8670 2018-03-26 22:06:00 0 0.27
ID19471 0612 2019-02-26 06:00:00 0 0.27
ID16894 3393 2018-03-26 22:06:00 0 0.27
ID18824 3546 2019-02-23 05:01:00 0 0.27
ID18575 3330 2018-10-13 06:00:00 0 0.27
ID18446 3147 2018-04-08 06:00:00 0 0.27
ID17672 3552 2018-03-26 22:06:00 0 0.27
ID19305 4963 2019-02-26 12:57:00 0 0.27
ID18063 1557 2018-09-06 06:01:00 0 0.26
ID17163 3243 2018-03-26 22:06:00 0 0.26
ID18883 7219 2018-03-11 06:01:00 0 0.26
ID18198 9225 2018-09-06 06:01:00 0 0.26
ID19474 2303 2019-02-26 05:03:00 0 0.26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment