Initial commit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Pulpit / Mapa Obiektów. Nanosi studnie jako kropki na płaszczyznę wg
|
||||
* LOKALNYCH współrzędnych geodezyjnych (seg_wells.WLL_LATITUDE/WLL_LONGITUDE -
|
||||
* siatka kopalniana w metrach, NIE WGS84). Normalizacja min-max do obszaru mapy
|
||||
* daje dokładny względny układ pola studni (bez internetu - air-gap OK).
|
||||
*
|
||||
* Kolor kropki: zielony = pompa pracuje (ON), czerwony = nie pracuje (OFF).
|
||||
*/
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/** Margines obszaru mapy (%), żeby kropki nie dotykały krawędzi. */
|
||||
private const PAD = 6;
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
$department = $request->session()->get('department');
|
||||
|
||||
$rows = DB::connection('softspm')->table('seg_wells as w')
|
||||
->join('seg_dev_resources as drw', function ($j) {
|
||||
$j->on('drw.DRS_DEV_ID', '=', 'w.WLL_ID')->where('drw.DRS_DEV_TYPE', '=', 12);
|
||||
})
|
||||
->where('drw.DRS_DEPARTMENT', $department)
|
||||
->where('drw.DRS_STATUS_DIC_ID', 3) // w eksploatacji
|
||||
->select('drw.DRS_ID as drs_id', 'w.WLL_NAME as name', 'w.WLL_LATITUDE as lat', 'w.WLL_LONGITUDE as lon')
|
||||
->get();
|
||||
|
||||
// Parsowanie współrzędnych (przecinek lub kropka dziesiętna), odrzucenie błędnych.
|
||||
$num = function ($v) {
|
||||
$s = str_replace([',', ' '], ['.', ''], (string) $v);
|
||||
return is_numeric($s) ? (float) $s : null;
|
||||
};
|
||||
$wells = $rows->map(function ($r) use ($num) {
|
||||
$r->lat = $num($r->lat);
|
||||
$r->lon = $num($r->lon);
|
||||
return $r;
|
||||
})->filter(fn ($r) => $r->lat !== null && $r->lon !== null && $r->lat > 0 && $r->lon > 0)->values();
|
||||
|
||||
// Stan ON/OFF dla naniesionych studni (DRD_RESOURCES_DETAIL=507).
|
||||
$onoff = $this->onOff($wells->pluck('drs_id')->all());
|
||||
|
||||
// Normalizacja do obszaru mapy. Zakres liczony z PERCENTYLI (2-98%), żeby
|
||||
// pojedyncze studnie ze skrajnymi współrzędnymi nie rozciągały skali i nie
|
||||
// zwijały reszty w jeden punkt. Pozycje przycięte (clamp) do obszaru.
|
||||
$minLat = $this->percentile($wells->pluck('lat')->all(), 2);
|
||||
$maxLat = $this->percentile($wells->pluck('lat')->all(), 98);
|
||||
$minLon = $this->percentile($wells->pluck('lon')->all(), 2);
|
||||
$maxLon = $this->percentile($wells->pluck('lon')->all(), 98);
|
||||
$latRange = max(1e-6, $maxLat - $minLat);
|
||||
$lonRange = max(1e-6, $maxLon - $minLon);
|
||||
$span = 100 - 2 * self::PAD;
|
||||
$clamp = fn ($v) => max(self::PAD, min(100 - self::PAD, $v));
|
||||
|
||||
$points = $wells->map(function ($r) use ($minLat, $maxLat, $minLon, $lonRange, $latRange, $span, $clamp, $onoff) {
|
||||
return (object) [
|
||||
'drs_id' => $r->drs_id,
|
||||
'name' => $r->name,
|
||||
// X = długość (wschód), Y = szerokość (północ, odwrócona - północ u góry).
|
||||
'left' => round($clamp(self::PAD + (($r->lon - $minLon) / $lonRange) * $span), 3),
|
||||
'top' => round($clamp(self::PAD + (($maxLat - $r->lat) / $latRange) * $span), 3),
|
||||
'on' => ($onoff[$r->drs_id] ?? null) === 'ON',
|
||||
];
|
||||
});
|
||||
|
||||
return view('dashboard', [
|
||||
'points' => $points,
|
||||
'onCount' => $points->where('on', true)->count(),
|
||||
'offCount' => $points->where('on', false)->count(),
|
||||
]);
|
||||
}
|
||||
|
||||
/** Percentyl p (0-100) z tablicy liczb (interpolacja liniowa). */
|
||||
private function percentile(array $values, float $p): float
|
||||
{
|
||||
if (empty($values)) {
|
||||
return 0.0;
|
||||
}
|
||||
sort($values);
|
||||
$i = ($p / 100) * (count($values) - 1);
|
||||
$lo = (int) floor($i);
|
||||
$hi = (int) ceil($i);
|
||||
|
||||
return $lo === $hi ? (float) $values[$lo] : $values[$lo] + ($values[$hi] - $values[$lo]) * ($i - $lo);
|
||||
}
|
||||
|
||||
/** Ostatni stan ON/OFF (507) dla zbioru DRS_ID - jednym zapytaniem. */
|
||||
private function onOff(array $ids): \Illuminate\Support\Collection
|
||||
{
|
||||
if (empty($ids)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return DB::connection('softspm')->table('seg_dev_resources_det as d')
|
||||
->joinSub(
|
||||
DB::connection('softspm')->table('seg_dev_resources_det')
|
||||
->select('DRD_DRS_ID', DB::raw('MAX(DRD_ID) as max_id'))
|
||||
->where('DRD_RESOURCES_DETAIL', 507)
|
||||
->whereIn('DRD_DRS_ID', $ids)
|
||||
->groupBy('DRD_DRS_ID'),
|
||||
'mx', 'mx.max_id', '=', 'd.DRD_ID'
|
||||
)
|
||||
->pluck('d.DRD_VALUE', 'd.DRD_DRS_ID');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user