From 4136546b927f78a475cb36b442c051ecaadb605e Mon Sep 17 00:00:00 2001 From: Jacek Kowalski <Jacek@jacekk.info> Date: Mon, 27 Jan 2020 23:39:17 +0000 Subject: [PATCH] Show when the vehicles were last seen in TTSS --- regenerate.php | 6 + parse.php | 12 ++-- config.php | 7 +- lib/Database.php | 42 ++++++++++---- lib/Mapper.php | 24 +++++-- lib/Output.php | 29 ++++++++- composer.json | 3 templates/vehicles.html | 22 +++++++ 8 files changed, 109 insertions(+), 36 deletions(-) diff --git a/composer.json b/composer.json index 21ddca9..85d257d 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "require": { "google/gtfs-realtime-bindings": "^0.0.2", "monolog/monolog": "^1.24", - "twig/twig": "^2.0" + "twig/twig": "^2.0", + "twig/extensions": "^1.5" } } diff --git a/config.php b/config.php index 3bb0f3a..3b1ce68 100644 --- a/config.php +++ b/config.php @@ -1,5 +1,4 @@ <?php -$tramTypes = new TramTypes(); $sources = [ 'bus' => [ 'gtfsrt' => 'ftp://zdmk.krakow.pl/VehiclePositions_A.pb', @@ -9,18 +8,18 @@ 'database' => 'mapping_A.sqlite3', 'result' => 'mapping_A.json', 'result_vehicles' => 'vehicles_A.html', - 'mapper' => new BusTypes(), + 'vehicle_types' => new BusTypes(), 'prefix' => 'b', ], 'tram' => [ - 'gtfsrt' => 'ftp://zdmk.krakow.pl/VehiclePositions_T.pb', + 'gtfsrt' => 'http://gtfs.ztp.krakow.pl/VehiclePositions_T.pb', 'gtfsrt_file' => 'VehiclePositions_T.pb', 'ttss' => 'http://www.ttss.krakow.pl/internetservice/geoserviceDispatcher/services/vehicleinfo/vehicles?positionType=CORRECTED', 'ttss_file' => 'vehicles_T.json', 'database' => 'mapping_T.sqlite3', 'result' => 'mapping_T.json', 'result_vehicles' => 'vehicles_T.html', - 'mapper' => $tramTypes, + 'vehicle_types' => new TramTypes(), 'prefix' => 't', ], ]; diff --git a/lib/Database.php b/lib/Database.php index 22cc51c..e83f4ab 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -10,13 +10,23 @@ $this->pdo = new PDO('sqlite:'.$file); $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - $this->pdo->query('CREATE TABLE IF NOT EXISTS vehicles ( + $this->pdo->query('CREATE TABLE IF NOT EXISTS vehicles2 ( id INT PRIMARY KEY, num INT UNIQUE, - weight INT + weight INT, + line VARCHAR, + date INT )'); + try { + $this->beginTransaction(); + $this->pdo->query('INSERT INTO vehicles2 SELECT id, num, weight, \'?\', \''.time().'\' FROM vehicles'); + $this->commit(); + $this->pdo->query('DROP TABLE vehicles'); + } catch(PDOException $e) { + $this->rollback(); + } - $this->addStatement = $this->pdo->prepare('INSERT OR REPLACE INTO vehicles (id, num, weight) VALUES (:id, :num, :weight)'); + $this->addStatement = $this->pdo->prepare('INSERT OR REPLACE INTO vehicles2 (id, num, weight, line, date) VALUES (:id, :num, :weight, :line, :date)'); $this->_cacheClear(); } @@ -35,7 +45,7 @@ protected function _cachePopulate() { if($this->cacheId === NULL) { - $st = $this->pdo->prepare('SELECT * FROM vehicles'); + $st = $this->pdo->prepare('SELECT * FROM vehicles2'); $st->execute(); $result = $st->fetchAll(PDO::FETCH_ASSOC); @@ -58,9 +68,14 @@ $this->cacheNum = NULL; } - public function getAll() { + public function getAllById() { $this->_cachePopulate(); return $this->cacheId; + } + + public function getAllByNum() { + $this->_cachePopulate(); + return $this->cacheNum; } public function getById($id) { @@ -74,25 +89,28 @@ } public function clear() { - $this->pdo->query('DELETE FROM vehicles'); + $this->pdo->query('DELETE FROM vehicles2'); $this->_cacheClear(); } - public function add($id, $num, $weight) { + public function add($id, $num, $weight, $line = NULL, $date = NULL) { $vehicle = [ 'id' => (string)$id, 'num' => (string)$num, - 'weight' => (string)$weight + 'weight' => (string)$weight, + 'line' => (string)($line ?? ''), + 'date' => (string)($date ?? time()), ]; $this->addStatement->execute($vehicle); $this->_cacheAdd($vehicle); } - public function addMapping($mapping) { + public function addMapping($vehiclesMapping, Mapper $mapper) { $this->beginTransaction(); - $weight = count($mapping); - foreach($mapping as $id => $num) { - $this->add($id, $num, $weight); + $weight = count($vehiclesMapping); + foreach($vehiclesMapping as $id => $num) { + $trip = $mapper->getTTSSVehicleTrip($id); + $this->add($id, $num, $weight, ($trip['line'] ?? '?') . ' ' . ($trip['direction'] ?? '?')); } $this->commit(); } diff --git a/lib/Mapper.php b/lib/Mapper.php index a36b4ef..7f0e701 100644 --- a/lib/Mapper.php +++ b/lib/Mapper.php @@ -4,6 +4,7 @@ class Mapper { private $ttssDate = NULL; private $ttssTrips = []; + private $ttssVehicleToTrip = []; private $gtfsrtDate = NULL; private $gtfsrtTrips = []; private $logger = NULL; @@ -35,18 +36,15 @@ if(!isset($vehicle->latitude) || !$vehicle->latitude) continue; if(!isset($vehicle->longitude) || !$vehicle->longitude) continue; list($line, $direction) = explode(' ', $vehicle->name, 2); - foreach($this->specialNames as $specialName) { - if(substr($vehicle->name, -strlen($specialName)) == $specialName) { - continue; - } - } - $this->ttssTrips[(string)$vehicle->tripId] = [ + $trip = [ 'id' => (string)$vehicle->id, 'line' => $line, 'direction' => $direction, 'latitude' => (float)$vehicle->latitude / 3600000.0, 'longitude' => (float)$vehicle->longitude / 3600000.0, ]; + $this->ttssTrips[(string)$vehicle->tripId] = $trip; + $this->ttssVehicleToTrip[(string)$vehicle->id] = $trip; } ksort($this->ttssTrips); } @@ -57,6 +55,18 @@ public function getTTSSTrips() { return $this->ttssTrips; + } + + public function getTTSSVehicleToTrip() { + return $this->ttssVehicleToTrip; + } + + public function getTTSSTrip($id) { + return $this->ttssTrips[$id] ?? NULL; + } + + public function getTTSSVehicleTrip($id) { + return $this->ttssVehicleToTrip[$id] ?? NULL; } public function loadGTFSRT($file) { @@ -130,7 +140,7 @@ return $bestOffset; } - public function mapUsingOffset($offset) { + public function mapVehicleIdsUsingOffset($offset) { $result = []; foreach($this->gtfsrtTrips as $gtfsTripId => $gtfsTrip) { $ttssTripId = $gtfsTripId + $offset; diff --git a/lib/Output.php b/lib/Output.php index 2944625..0fda9ab 100644 --- a/lib/Output.php +++ b/lib/Output.php @@ -1,9 +1,19 @@ <?php class Output { - static function createMapping($db, VehicleTypes $vehicleTypes, $saveConfig = FALSE) { + private $db; + private $mapper; + private $vehicleTypes; + + function __construct(Database $db, Mapper $mapper, VehicleTypes $vehicleTypes) { + $this->db = $db; + $this->mapper = $mapper; + $this->vehicleTypes = $vehicleTypes; + } + + function createMapping($saveConfig = FALSE) { $mapping = []; - foreach($db->getAll() as $vehicle) { - $mapping[$vehicle['id']] = $vehicleTypes->getByNumber($vehicle['num']); + foreach($this->db->getAllById() as $vehicle) { + $mapping[$vehicle['id']] = $this->vehicleTypes->getByNumber($vehicle['num']); } if($saveConfig) { @@ -17,11 +27,13 @@ return $mapping; } - function createVehiclesList($trips, $mapping, $saveConfig = FALSE) { + function createVehiclesList($fullMapping, $saveConfig = FALSE) { + $trips = $this->mapper->getTTSSTrips(); + $lines = []; $vehicles = []; foreach($trips as $trip) { - $vehicle = $mapping[$trip['id']] ?? []; + $vehicle = $fullMapping[$trip['id']] ?? []; $vehicle += ['trip' => $trip['id']]; $lines[$trip['line']][] = [ 'trip' => $trip, @@ -29,6 +41,7 @@ ]; $vehicles[$vehicle['type'] ?? '?'][] = $vehicle; } + foreach($lines as &$line) { usort($line, function($a, $b) { return (substr($a['vehicle']['num'] ?? '', 2) <=> substr($b['vehicle']['num'] ?? '', 2)); @@ -36,6 +49,7 @@ } unset($line); ksort($lines); + foreach($vehicles as &$vehicle) { usort($vehicle, function($a, $b) { return (substr($a['num'] ?? '', 2) <=> substr($b['num'] ?? '', 2)); @@ -44,14 +58,19 @@ unset($vehicle); ksort($vehicles); + $dbMapping = $this->db->getAllByNum(); + ksort($dbMapping); + if($saveConfig) { $twigLoader = new \Twig\Loader\FilesystemLoader(__DIR__.'/../templates'); $twig = new \Twig\Environment($twigLoader); + $twig->addExtension(new Twig_Extensions_Extension_Date()); $vehiclesHtml = $twig->render('vehicles.html', [ 'lines' => $lines, 'vehicles' => $vehicles, 'prefix' => $saveConfig['prefix'], + 'mapping' => $dbMapping, ]); if(!file_put_contents($saveConfig['result_vehicles_temp'], $vehiclesHtml)) { throw new Exception('Vehicles save failed'); diff --git a/parse.php b/parse.php index 3252150..c54f19d 100644 --- a/parse.php +++ b/parse.php @@ -39,7 +39,7 @@ } $logger->info('Got offset '.$offset.', creating mapping...'); - $mapping = $mapper->mapUsingOffset($offset); + $mapping = $mapper->mapVehicleIdsUsingOffset($offset); $logger->info('Checking the data for correctness...'); $weight = count($mapping); @@ -72,17 +72,17 @@ throw new Exception('Ignoring result due to better data already present'); } + $output = new Output($db, $mapper, $source['vehicle_types']); - $logger->info('Creating mapping...'); + $logger->info('Saving mapping...'); - $db->addMapping($mapping); + $db->addMapping($mapping, $mapper); - $finalMapping = Output::createMapping($db, $source['mapper'], $source); - + $fullMapping = $output->createMapping($source); $logger->info('Creating vehicle list...'); - Output::createVehiclesList($mapper->getTTSSTrips(), $finalMapping, $source); + $output->createVehiclesList($fullMapping, $source); $logger->info('Finished'); } catch(Throwable $e) { diff --git a/regenerate.php b/regenerate.php index aaa821f..643a9f0 100644 --- a/regenerate.php +++ b/regenerate.php @@ -7,7 +7,11 @@ try { $logger->info('Regenerating '.$name.'...'); $db = new Database($source['database']); - Output::createMapping($db, $source['mapper'], $source); + $mapper = new Mapper(); + $mapper->loadTTSS($source['ttss_file']); + $output = new Output($db, $mapper, $source['vehicle_types']); + $fullMapping = $output->createMapping($source); + $output->createVehiclesList($fullMapping, $source); $logger->info('Finished'); } catch(Throwable $e) { $logger->error($e->getMessage(), ['exception' => $e, 'exception_string' => (string)$e]); diff --git a/templates/vehicles.html b/templates/vehicles.html index 9c9d4e7..2302e8a 100644 --- a/templates/vehicles.html +++ b/templates/vehicles.html @@ -80,6 +80,28 @@ {% endfor %} </table> +<table> +<caption>Vehicles in TTSS</caption> +<thead> +<tr> +<th>Vehicle</th> <th>Line</th> <th>Last seen</th> +</tr> +</thead> +{% for map in mapping %} +<tr> +<td> +{{ map.num | e }} +</td> +<td> +{{ map.line | default('?') | e }} +</td> +<td> +{{ map.date | time_diff | default('now') }} +</td> +</tr> +{% endfor %} +</table> + Generated at {{ "now" | date("Y-m-d H:i:s P") }} </table> -- Gitblit v1.9.1