Jacek Kowalski
2019-06-10 6b6842c72b28c1346ef501bc656ec3016d00e1c7
commit | author | age
4673cc 1 <?php
JK 2 require_once(__DIR__.'/../vendor/autoload.php');
3 require_once(__DIR__.'/vehicle_types.php');
4
5 use transit_realtime\FeedMessage;
6
7 class Mapper {
9afb6b 8     private $ttssDate = NULL;
0c85a7 9     private $ttssTrips = [];
9afb6b 10     private $gtfsrtDate = NULL;
0c85a7 11     private $gtfsrtTrips = [];
6b6842 12     private $gtfsTrips = [];
JK 13     private $gtfsRoutes = [];
4673cc 14     private $logger = NULL;
JK 15     
16     private $specialNames = [
17         'Zjazd do zajezdni',
18         'Przejazd techniczny',
19         'Wyjazd na trasÄ™',
20     ];
21     
22     public function __construct() {
23         $this->logger = new Monolog\Logger(__CLASS__);
24     }
25     
26     public static function convertTripId($tripId) {
27         $tripId = explode('_', $tripId);
28         if($tripId[0] != 'block') return;
29         if($tripId[2] != 'trip') return;
30         return 4096 * (int)$tripId[1] + (int)$tripId[3];
31     }
32     
33     public function loadTTSS($file) {
0c85a7 34         $ttss = json_decode(file_get_contents($file));
9afb6b 35         $this->ttssDate = $ttss->lastUpdate;
0c85a7 36         foreach($ttss->vehicles as $vehicle) {
4673cc 37             if(isset($vehicle->isDeleted) && $vehicle->isDeleted) continue;
JK 38             if(!isset($vehicle->tripId) || !$vehicle->tripId) continue;
39             if(!isset($vehicle->name) || !$vehicle->name) continue;
40             if(!isset($vehicle->latitude) || !$vehicle->latitude) continue;
41             if(!isset($vehicle->longitude) || !$vehicle->longitude) continue;
42             foreach($this->specialNames as $name) {
43                 if(substr($vehicle->name, -strlen($name)) == $name) {
44                     continue;
45                 }
46             }
6b6842 47             $name = explode(' ', $vehicle->name, 2);
0c85a7 48             $this->ttssTrips[(int)$vehicle->tripId] = [
4673cc 49                 'id' => $vehicle->id,
6b6842 50                 'line' => $name[0],
JK 51                 'direction' => $name[1],
4673cc 52                 'latitude' => (float)$vehicle->latitude / 3600000.0,
JK 53                 'longitude' => (float)$vehicle->longitude / 3600000.0,
54             ];
55         }
0c85a7 56         ksort($this->ttssTrips);
4673cc 57     }
JK 58     
9afb6b 59     public function getTTSSDate() {
JK 60         return $this->ttssDate / 1000.0;
6b6842 61     }
JK 62     
63     public function loadGTFS($file) {
64         $buffer_size = 512;
65         
66         $routes = fopen('phar://'.$file.'/routes.txt', 'r');
67         $route_header = fgetcsv($routes, $buffer_size);
68         while(($route = fgetcsv($routes, $buffer_size)) !== FALSE) {
69             $this->gtfsRoutes[$route[0]] = $route[2];
70         }
71         fclose($routes);
72         
73         $trips = fopen('phar://'.$file.'/trips.txt', 'r');
74         $trip_header = fgetcsv($trips, $buffer_size);
75         var_dump($trip_header);
76         while(($trip = fgetcsv($trips, $buffer_size)) !== FALSE) {
77             $this->gtfsTrips[$trip[0]] = [
78                 'line' => $this->gtfsRoutes[$trip[1]] ?? NULL,
79                 'route' => $trip[1],
80                 'direction' => $trip[3],
81             ];
82         }
83         fclose($trips);
9afb6b 84     }
JK 85     
0c85a7 86     public function loadGTFSRT($file) {
4673cc 87         $data = file_get_contents($file);
JK 88         $feed = new FeedMessage();
89         $feed->parse($data);
9afb6b 90         $this->gtfsrtDate = $feed->header->timestamp;
4673cc 91         foreach ($feed->getEntityList() as $entity) {
JK 92             $vehiclePosition = $entity->getVehicle();
93             $position = $vehiclePosition->getPosition();
94             $vehicle = $vehiclePosition->getVehicle();
95             $trip = $vehiclePosition->getTrip();
96             $tripId = $trip->getTripId();
0c85a7 97             $this->gtfsrtTrips[self::convertTripId($tripId)] = [
4673cc 98                 'id' => $entity->getId(),
JK 99                 'num' => $vehicle->getLicensePlate(),
100                 'tripId' => $tripId,
101                 'latitude' => $position->getLatitude(),
102                 'longitude' => $position->getLongitude(),
103             ];
104         }
0c85a7 105         ksort($this->gtfsrtTrips);
4673cc 106     }
JK 107     
9afb6b 108     public function getGTFSRTDate() {
JK 109         return $this->gtfsrtDate;
110     }
111     
6b6842 112     public function mapUsingCoords() {
JK 113         $level = 0.002;
114         foreach($this->gtfsrtTrips as $gkey => $gtrip) {
115             $trip = $this->gtfsTrips[$gtrip['tripId']] ?? NULL;
116             
117             if($trip === NULL) continue;
118             
119             foreach($this->ttssTrips as $jkey => $jtrip) {
120                 echo $gtrip['latitude'].' '.$jtrip['latitude']."\n";
121                 echo $gtrip['longitude'].' '.$jtrip['longitude']."\n";
122                 echo $jtrip['line'].' '.$trip['line']."\n";
123                 echo "\n";
124                 
125                 if($jtrip['line'] != $trip['line']) continue;
126                 if(abs($gtrip['latitude'] - $jtrip['latitude']) > $level) continue;
127                 if(abs($gtrip['longitude'] - $jtrip['longitude']) < $level) continue;
128                 
129                 echo 'MATCH '.$gtrip['num'].' '.$gkey.' '.$jkey.' ('.($jkey-$gkey).')'."\n";
130             }
131         }
132     }
133     
4673cc 134     public function findOffset() {
0c85a7 135         if(count($this->ttssTrips) == 0 || count($this->gtfsrtTrips) == 0) {
4673cc 136             return NULL;
JK 137         }
138         
0c85a7 139         $ttssTripIds = array_keys($this->ttssTrips);
JK 140         $gtfsTripIds = array_keys($this->gtfsrtTrips);
4673cc 141         
JK 142         $possibleOffsets = [];
0c85a7 143         for($i = 0; $i < count($this->ttssTrips); $i++) {
JK 144             for($j = 0; $j < count($this->gtfsrtTrips); $j++) {
145                 $possibleOffsets[$ttssTripIds[$i] - $gtfsTripIds[$j]] = TRUE;
4673cc 146             }
JK 147         }
148         $possibleOffsets = array_keys($possibleOffsets);
149         
150         $bestOffset = 0;
151         $maxMatched = 0;
152         $options = 0;
153         
154         foreach($possibleOffsets as $offset) {
155             $matched = 0;
156             
157             foreach($gtfsTripIds as $tripId) {
158                 $tripId += $offset;
0c85a7 159                 if(isset($this->ttssTrips[$tripId])) {
4673cc 160                     $matched++;
JK 161                 }
162             }
163             
164             if($matched > $maxMatched) {
165                 $bestOffset = $offset;
166                 $maxMatched = $matched;
167                 $options = 1;
168             } elseif($matched == $maxMatched) {
169                 $options++;
170             }
171         }
172         
173         if($options != 1) {
174             throw new Exception('Found '.$options.' possible mappings!');
175         }
176         return $bestOffset;
177     }
178     
0c85a7 179     public function mapUsingOffset($offset) {
4673cc 180         $result = [];
0c85a7 181         foreach($this->gtfsrtTrips as $gtfsTripId => $gtfsTrip) {
JK 182             $ttssTripId = $gtfsTripId + $offset;
183             if(isset($this->ttssTrips[$ttssTripId])) {
4673cc 184                 $data = numToTypeB($gtfsTrip['id']);
JK 185                 $num = $gtfsTrip['num'];
186                 if(!is_array($data) || !isset($data['num'])) {
187                     $data = [
188                         'num' => $num,
189                         'low' => 2,
190                     ];
191                 } elseif($data['num'] != $num) {
192                     // Ignore due to incorrect depot markings in the data
193                     //$this->logger->warn('Got '.$num.', database has '.$data['num']);
194                 }
0c85a7 195                 $result[$this->ttssTrips[$ttssTripId]['id']] = $data;
4673cc 196             }
JK 197         }
198         return $result;
199     }
200 }