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