0👍
✅
I’ve made an array $timeLabels
this array contains timestamps from the current time till x minutes/hours ago in intervals of x minutes.
Then I loop over my rigs and compare the created_at with the values in the timeLabels. If it is in the same range (+/-10 sec) the data from the collection goes into an array with the timeLabel as key. When a timeLabel has no value, it gets 0 assigned as data. This actually works, but needs some tuning.
Full example:
<?php
namespace App\Http\Controllers\Rigs;
use Auth;
use Carbon\Carbon;
use App\MinerStatistics;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class RigController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the rigs dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
// Get the statistics from the database reported by the miner
// Group them by the rig name
$stats = MinerStatistics::where('user_id', Auth::user()->id)
->where('created_at','>=', Carbon::now()->subMinutes(60))
->orderBy('created_at', 'desc')
->take(300)
->get()
->groupBy('rigname');
// Get the rig names
$rigs = (object) [];
foreach($stats as $key => $value) {
$rigs->$key = $key;
}
// For each rig, get the last known stats between now and 10 seconds ago
$table = (object) [];
foreach($rigs as $key => $value) {
$tableData = $stats[$value]
->where('created_at','>=', Carbon::now()->subSeconds(10));
if (isset($tableData[0]) && $tableData !== []) {
$table->$key = (object) $tableData[0];
$table->$key->data = json_decode($tableData[0]['data'], true);
}
}
return view('rigs', [
'rigs' => $table,
'chart' => $this->chart($stats)
]);
}
public function chart($data)
{
$start = Carbon::now('Europe/Brussels');
$end = Carbon::now('Europe/Brussels')->subMinutes(60);
$timeLabels = $this->createTimeRange($end, $start);
$chartData = (object) [];
// Go over each returned rig
foreach($data as $key => $value) {
$arr = array(); // Create an empty array to store our results
// Go over all our timeLabels
foreach(array_reverse($timeLabels) as $t => $time) {
// Create a range to match the incomming created_at and timeLabels
// Needs finetuning!!
$start = Carbon::createFromFormat('H:i', $time)->subSeconds(30)->format('H:i:s');
$end = Carbon::createFromFormat('H:i', $time)->addSeconds(30)->format('H:i:s');
foreach ($value as $k => $v) {
// Transform created_at to the same format as $start and $end
$created = Carbon::createFromFormat('Y-m-d H:i:s', $v['created_at'])->format('H:i:s');
if($created >= $start && $created <= $end) {
if(!isset($v->data['hashrate'])){
$hashrate_ = json_decode($v->data,true)['hashrate'];
} else {
$hashrate_ = $v->data['hashrate'];
}
$arr[$time] = $hashrate_;
}
}
// If the set timeLabel has no value set to 0
// Rig is not running...
if (!isset($arr[$time])) {
$arr[$time] = '0';
}
}
$chartData->$key = $arr;
}
$datasets = [];
$n = 0;
foreach($chartData as $key => $value) {
$data = [];
foreach ($value as $k => $v) {
$data[] = $v;
}
$colors = [
"0, 188, 212",
"244, 67, 54",
"255, 152, 0"
];
$datasets[] = $this->chartData('Hashrate: ' . $key, array_reverse($data), $colors[$n++]);
}
$chart = app()->chartjs
->name('lineChartTest')
->type('line')
->size(['width' => '100%', 'height' => '20%'])
->labels($timeLabels)
->datasets($datasets)
->optionsRaw("{
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 0, // minimum will be 0, unless there is a lower value.
beginAtZero: true // minimum value will be 0.
}
}]
}
}");
return $chart;
}
public function chartData($label, $data, $color)
{
return [
"label" => $label,
'backgroundColor' => "rgba(" . $color . ", 0)",
'borderColor' => "rgba(" . $color . ", 0.7)",
"pointBorderColor" => "rgba(" . $color . ", 0, 0.7)",
"pointBackgroundColor" => "rgba(" . $color . ", 0.7)",
"pointHoverBackgroundColor" => "#fff",
"pointHoverBorderColor" => "rgba(220,220,220,1)",
'data' => $data,
];
}
private function createTimeRange($start, $end, $interval = '5 mins', $format = '24') {
$startTime = strtotime($start);
$endTime = strtotime($end);
$returnTimeFormat = ($format == '12')?'g:i A':'G:i';
$current = time();
$addTime = strtotime('+'.$interval, $current);
$diff = $addTime - $current;
$times = array();
while ($startTime < $endTime) {
$times[] = date($returnTimeFormat, $startTime);
$startTime += $diff;
}
$times[] = date($returnTimeFormat, $startTime);
return $times;
}
}
If I do it like this, I could create a dedicated class so I can reuse this logic. The data I get returned to pass to the charts is now formatted like this: (exactly what I needed)
{#3436 ▼
+"home": array:13 [▼
"17:47" => 13.44
"17:42" => 13.417
"17:37" => 13.439
"17:32" => 13.436
"17:27" => 13.438
"17:22" => "0"
"17:17" => "0"
"17:12" => "0"
"17:07" => "0"
"17:02" => "0"
"16:57" => "0"
"16:52" => "0"
"16:47" => "0"
]
+"server": array:13 [▼
"17:47" => "0"
"17:42" => 76.373
"17:37" => 76.514
"17:32" => 76.565
"17:27" => 76.486
"17:22" => "0"
"17:17" => "0"
"17:12" => "0"
"17:07" => "0"
"17:02" => "0"
"16:57" => "0"
"16:52" => "0"
"16:47" => "0"
]
}
Source:stackexchange.com