繁体   English   中英

php / laravel:创建chartdata,如果没有数据提交到数据库,则返回0

[英]php/laravel: Creating chartdata, return 0 if no data is being submitted to database

我试图从数据库返回的数据创建图表。 数据存储在数据库中,此表中可以有多个图表。 由唯一值标识。 (原名)

array:102 [▼
    0 => array:6 [▼
      "id" => 2002
      "user_id" => "1"
      "rigname" => "home"
      "data" => "{"hashrate":12.364,"pool":"eu1.ethermine.org:4444","shares":{"valid":"2","invalid":"0"},"gpus":[{"temperature":"56","fanSpeed":"56","hashrates":12.364}]}"
      "created_at" => "2018-02-23 10:24:50"
      "updated_at" => "2018-02-23 10:24:50"
    ],
1 => array:6 [▼
      "id" => 2019
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.612,"pool":"eu1.ethermine.org:4444","shares":{"valid":"736","invalid":"2"},"gpus":[{"temperature":"65","fanSpeed":"67","hashrates":19.804},{"temp ▶"
      "created_at" => "2018-02-23 10:25:56"
      "updated_at" => "2018-02-23 10:25:56"
    ]

如您所见,根据钻机名称,有两个可能的图表。 我想在图表上显示两个装备的哈希率值。 此方法有效,但是,当一个装备停止时,没有数据从该装备提交到数据库。 该图表未显示该装备的0值,正在使用最新的已知数据。 (du)

我通过修改查询来解决此问题:

$res[$value] = json_decode(MinerStatistics::where('rigname', $value)
            ->where('created_at','>=', \Carbon\Carbon::now()->subMinutes(20))
            ->orderBy('created_at', 'desc')
            ->get()
            ->toJson(), true
       );

现在,当钻机停止运行并查询数据库时,我仅获得过去x分钟的数据。 这是在foreach中完成的,该foreach使用按钻机名称排序的数据构建新的多维数组。

当我重新启动装备并开始向数据库报告时,这会引起一个新问题。 图表上的值不在当前时间戳上继续,而是在钻机停止的地方继续。 通常,我会将上次报告的数据和先前报告的数据的时间戳与仍在运行的装备的数据进行比较,并在每次运行的装备报告时返回0,但它们报告的时间戳不同(彼此之间的时间间隔均为8秒)

我该如何修改返回的mysql数据,最终得到的结果是这样的:

array:2 [▼
  "home" => array:150 [
      0 => array:6 [▼
        "id" => 2300
        "user_id" => "1"
        "rigname" => "home"
        "data" => "{"hashrate":12.359,"pool":"eu1.ethermine.org:4444","shares":{"valid":"5","invalid":"0"},"gpus":[{"temperature":"57","fanSpeed":"57","hashrates":12.359}]}"
        "created_at" => "2018-02-23 10:44:42"
        "updated_at" => "2018-02-23 10:44:42"
        ]
    1 => array:6 [▼
      "id" => 2298
      "user_id" => "1"
      "rigname" => "home"
      "data" => "{"hashrate":12.367,"pool":"eu1.ethermine.org:4444","shares":{"valid":"5","invalid":"0"},"gpus":[{"temperature":"57","fanSpeed":"57","hashrates":12.367}]}"
      "created_at" => "2018-02-23 10:44:34"
      "updated_at" => "2018-02-23 10:44:34"
    ]
    2 => array:6 [▼
      "id" => 2296
      "user_id" => "1"
      "rigname" => "home"
      "data" => "{"hashrate":12.367,"pool":"eu1.ethermine.org:4444","shares":{"valid":"5","invalid":"0"},"gpus":[{"temperature":"57","fanSpeed":"57","hashrates":12.367}]}"
      "created_at" => "2018-02-23 10:44:26"
      "updated_at" => "2018-02-23 10:44:26"
    ]

    ...
    Server stops, no data, should continue like this

    3 => [false] ,
    4 => [false] ,
    5 => [false] 
    ...
    rig reports again to the database

    36 => array:6 [▼
      "id" => 2296
      "user_id" => "1"
      "rigname" => "home"
      "data" => "{"hashrate":12.367,"pool":"eu1.ethermine.org:4444","shares":{"valid":"5","invalid":"0"},"gpus":[{"temperature":"57","fanSpeed":"57","hashrates":12.367}]}"
      "created_at" => "2018-02-23 10:44:26"
      "updated_at" => "2018-02-23 10:44:26"
    ],
  ],
  "server" => array:150 [▼ // This keeps running, or visa versa
    0 => array:6 [▼
      "id" => 2301
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.62,"pool":"eu1.ethermine.org:4444","shares":{"valid":"749","invalid":"2"},"gpus":[{"temperature":"64","fanSpeed":"67","hashrates":19.778},{"tempe ▶"
      "created_at" => "2018-02-23 10:44:44"
      "updated_at" => "2018-02-23 10:44:44"
    ]
    1 => array:6 [▼
      "id" => 2299
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.68,"pool":"eu1.ethermine.org:4444","shares":{"valid":"749","invalid":"2"},"gpus":[{"temperature":"64","fanSpeed":"65","hashrates":19.815},{"tempe ▶"
      "created_at" => "2018-02-23 10:44:36"
      "updated_at" => "2018-02-23 10:44:36"
    ]
    2 => array:6 [▼
      "id" => 2297
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.644,"pool":"eu1.ethermine.org:4444","shares":{"valid":"749","invalid":"2"},"gpus":[{"temperature":"64","fanSpeed":"65","hashrates":19.793},{"temp ▶"
      "created_at" => "2018-02-23 10:44:28"
      "updated_at" => "2018-02-23 10:44:28"
    ]
    3 => array:6 [▼
      "id" => 2295
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.105,"pool":"eu1.ethermine.org:4444","shares":{"valid":"749","invalid":"2"},"gpus":[{"temperature":"64","fanSpeed":"65","hashrates":19.793},{"temp ▶"
      "created_at" => "2018-02-23 10:44:20"
      "updated_at" => "2018-02-23 10:44:20"
    ]
    4 => array:6 [▼
      "id" => 2293
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.557,"pool":"eu1.ethermine.org:4444","shares":{"valid":"749","invalid":"2"},"gpus":[{"temperature":"64","fanSpeed":"65","hashrates":19.78},{"tempe ▶"
      "created_at" => "2018-02-23 10:44:12"
      "updated_at" => "2018-02-23 10:44:12"
    ]
    5 => array:6 [▼
      "id" => 2291
      "user_id" => "1"
      "rigname" => "server"
      "data" => "{"hashrate":76.562,"pool":"eu1.ethermine.org:4444","shares":{"valid":"749","invalid":"2"},"gpus":[{"temperature":"64","fanSpeed":"65","hashrates":19.794},{"temp ▶"
      "created_at" => "2018-02-23 10:44:04"
      "updated_at" => "2018-02-23 10:44:04"
    ]
  ]
]

我写的当前代码:

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(20))
        ->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) 
    {
        $p = [];
        foreach($data as $key => $value) {
            $x = [];
            $time = [];
            foreach($value as $k => $v) {
                $time[] = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $v['created_at'])->format('H:i:s');
                $x[] = json_decode($v['data'], true);
            }

            $hashrate = [];
            foreach($x as $k => $v){
                $hashrate[] = $v['hashrate'];
            }
            $p[$key] = [ 'time' => $time, 'hashrate' => $hashrate ];
        }

        $datasets = [];
        $n = 0;
        foreach($p as $key => $value) {
            $colors = [
                "0, 188, 212",
                "244, 67, 54",
                "255, 152, 0"
            ];

            $datasets[] = $this->chartData('Hashrate: ' . $key, array_reverse($value['hashrate']), $colors[$n++]);
        }
        dd($time);
        $chart = app()->chartjs
            ->name('lineChartTest')
            ->type('line')
            ->size(['width' => '100%', 'height' => '20%'])
            ->labels(array_reverse($time))
            ->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,
        ];
    }

编辑:我找到了答案,请检查下面。

我已经创建了一个数组$timeLabels该数组包含从当前时间到x分钟/小时之前的时间戳,间隔为x分钟。

然后,遍历我的装备,并将created_at与timeLabels中的值进行比较。 如果在相同范围内(+/- 10秒),则来自集合的数据将以timeLabel作为键进入数组。 如果timeLabel没有值,则将其分配为0。 这实际上有效,但是需要一些调整。

完整示例:

<?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; 
    }
}

如果这样做,我可以创建一个专用的类,这样我就可以重用此逻辑。 现在,我返回传递给图表的数据的格式如下:(正是我所需要的)

{#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"
  ]
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM