Files
FloatBackOfffice/TEST/test_gps_partition.php
dev-chiefworks f76abffdcd first commit
2022-05-31 16:21:53 -04:00

156 lines
6.3 KiB
PHP

<?php
require '../backend.php';
// We will not limit the SQL we will exhaust the allowed memory
// we will process data in ${hard_limit} batches and hopefully catch up
$hard_limit = 500000;
//PostgreSQL
$gps_db_host = $savvyext->cfgReadChar('gpsdatabase.host');
$gps_db_port = $savvyext->cfgReadLong('gpsdatabase.port');
$gps_db_name = $savvyext->cfgReadChar('gpsdatabase.name');
$gps_db_user = $savvyext->cfgReadChar('gpsdatabase.user');
$gps_db_pass = $savvyext->cfgReadChar('gpsdatabase.pass');
$conn_string_gps = "host=${gps_db_host} port=${gps_db_port} dbname=${gps_db_name} user=${gps_db_user} password=${gps_db_pass}";
$pgconn_gps = pg_connect($conn_string_gps);
$q = "select member_id,count(*) from members_tracking group by member_id";
$r = pg_query($pgconn_gps, $q);
if ($r && pg_num_rows($r)) {
while ($f=pg_fetch_row($r)) {
echo "[".date("Y-m-d H:i:s")."] Processing member_id=".$f[0]." (total member records: ".$f[1].")\n";
//if ($f[0]==22) continue; // Crash!
$p = processMemberGPSDataPartition($f[0]);
}
}
pg_close($pgconn_gps);
function processMemberGPSDataPartition($member_id) {
global $pgconn_gps, $hard_limit;
$min_id = 0;
$max_id = 0;
// Min id (the biggest id we have stopped processing last time)
$q = "SELECT max(last_id) FROM members_tracking_index WHERE member_id=${member_id}";
$r = pg_query($pgconn_gps, $q);
if ($f=pg_fetch_row($r)) {
$min_id = (int)$f[0];
}
// Max id (we will limit the processing pool to get consistent results)
$q = "SELECT max(id) FROM members_tracking WHERE member_id=${member_id}";
$r = pg_query($pgconn_gps, $q);
if ($f=pg_fetch_row($r)) {
$max_id = $f[0];
}
echo "[".date("Y-m-d H:i:s")."] Process from ${min_id} to ${max_id} (member_id=${member_id})\n";
// Select id's for processing, we will have a separate threads for each device id
$pids = [];
$q = "select id,device_id,ttime from members_tracking ";
$q.= "where member_id=${member_id} and id>${min_id} and id<${max_id} ";
$q.= "order by device_id,ttime limit ${hard_limit}";
$r = pg_query($pgconn_gps, $q);
$pid = 0;
$total = 0;
while ($f=pg_fetch_row($r)) {
if ($f[1]==NULL || $f[1]<1) {
$f[1] = "NULL";
}
if (!array_key_exists($f[1],$pids)) {
$pids[$f[1]] = [];
// Try to get the pid
$ttime = $f[2];
$q1 = "SELECT id FROM members_tracking WHERE member_id=${member_id} AND ";
$q1.= ($f[1]==NULL ? " device_id IS NULL" : " device_id=".$f[1]);
$q1.= " AND ttime<'${ttime}'::timestamp ORDER BY ttime DESC LIMIT 1";
$r1 =pg_query($pgconn_gps, $q1);
if ($r1 && pg_num_rows($r1) && $f1=pg_fetch_row($r1)) {
$pid = $f1[0];
}
pg_free_result($r1);
}
if ($pid>0) {
$pids[$f[1]][] = [$pid,$f[0]];
}
$pid = $f[0];
$total++;
}
pg_free_result($r);
$processed = 0;
foreach ($pids as $device_id=>$ids) {
echo "[".date("Y-m-d H:i:s")."] Processing device_id=${device_id} (member_id=${member_id})\n";
$last_id = 0;
foreach ($ids as list($pid,$nid)) { // prev,next
echo ".";
$q = "SELECT a.id AS nid, b.id AS pid, ";
$q.= "ST_Distance(a.gps,b.gps) AS distance, EXTRACT(epoch FROM a.ttime-b.ttime) AS duration ";
$q.= "FROM members_tracking a LEFT JOIN members_tracking b ON (b.id=${pid}) WHERE a.id=${nid}";
$r = pg_query($pgconn_gps, $q);
$f = pg_fetch_assoc($r);
pg_free_result($r);
$q = "UPDATE members_tracking SET previous_id=".$f["pid"].",distance=".((int)$f["distance"]).",duration=".((int)(1000*$f["duration"]));
$q.= "WHERE id=".$f["nid"]." RETURNING *";
$r = pg_query($pgconn_gps, $q);
pg_free_result($r);
$last_id = $f["nid"];
}
echo "\n";
echo "[".date("Y-m-d H:i:s")."] last_id=${last_id} (member_id=${member_id},device_id=${device_id})\n";
if ($last_id>0) {
$plast_id = 0;
$q = "SELECT last_id FROM members_tracking_index WHERE member_id=${member_id} AND device_id=${device_id}";
$r = pg_query($pgconn_gps, $q);
if ($r && pg_num_rows($r) && $f=pg_fetch_row($r)) {
$plast_id = $f[0];
}
pg_free_result($r);
if ($plast_id>0 && $plast_id<$last_id) {
$q = "UPDATE members_tracking_index SET last_id=${last_id} ";
$q.= "WHERE member_id=${member_id} AND device_id=${device_id} ";
$q.= "RETURNING *";
$r = pg_query($pgconn_gps, $q);
} else {
$q = "INSERT INTO members_tracking_index (member_id,device_id,last_id) ";
$q.= "VALUES(${member_id},${device_id},${last_id}) ";
$q.= "RETURNING *";
$r = pg_query($pgconn_gps, $q);
}
if ($r && pg_num_rows($r) && $f=pg_fetch_assoc($r)) {
echo "[".date("Y-m-d H:i:s")."] New last_id=${last_id} (member_id=${member_id},device_id=${device_id})\n";
} else {
echo "[".date("Y-m-d H:i:s")."] ERROR: ".pg_last_error($pgconn_gps)."\n";
echo "$q\n";
}
pg_free_result($r);
} else {
echo "[".date("Y-m-d H:i:s")."] Invalid last_id=${last_id} (member_id=${member_id},device_id=${device_id})\n";
}
$processed++;
}
echo "[".date("Y-m-d H:i:s")."] Processed: ${processed} (member_id=${member_id})\n";
unset($pids);
return $processed;
}
function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit) {
//error_log("public function distanceBetweenTwoGpsCoordinates($lat1,$lon1,$lat2,$lon2,$unit)");
if (($lat1 == $lat2) && ($lon1 == $lon2)) {
return 0;
}
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
}
if ($unit == "N") {
($miles * 0.8684);
}
return $miles;
}