Jacek Kowalski
2019-02-19 33182e945b9b5ee3528f34a483ba84771e5de1fb
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 {
8     private $jsonTrips = [];
9     private $gtfsTrips = [];
10     private $logger = NULL;
11     
12     private $specialNames = [
13         'Zjazd do zajezdni',
14         'Przejazd techniczny',
15         'Wyjazd na trasÄ™',
16     ];
17     
18     public function __construct() {
19         $this->logger = new Monolog\Logger(__CLASS__);
20     }
21     
22     public static function convertTripId($tripId) {
23         $tripId = explode('_', $tripId);
24         if($tripId[0] != 'block') return;
25         if($tripId[2] != 'trip') return;
26         return 4096 * (int)$tripId[1] + (int)$tripId[3];
27     }
28     
29     public function loadTTSS($file) {
30         $json = json_decode(file_get_contents($file));
31         foreach($json->vehicles as $vehicle) {
32             if(isset($vehicle->isDeleted) && $vehicle->isDeleted) continue;
33             if(!isset($vehicle->tripId) || !$vehicle->tripId) continue;
34             if(!isset($vehicle->name) || !$vehicle->name) continue;
35             if(!isset($vehicle->latitude) || !$vehicle->latitude) continue;
36             if(!isset($vehicle->longitude) || !$vehicle->longitude) continue;
37             foreach($this->specialNames as $name) {
38                 if(substr($vehicle->name, -strlen($name)) == $name) {
39                     continue;
40                 }
41             }
42             $this->jsonTrips[(int)$vehicle->tripId] = [
43                 'id' => $vehicle->id,
44                 'latitude' => (float)$vehicle->latitude / 3600000.0,
45                 'longitude' => (float)$vehicle->longitude / 3600000.0,
46             ];
47         }
48         ksort($this->jsonTrips);
49     }
50     
51     public function loadGTFS($file) {
52         $data = file_get_contents($file);
53         $feed = new FeedMessage();
54         $feed->parse($data);
55         foreach ($feed->getEntityList() as $entity) {
56             $vehiclePosition = $entity->getVehicle();
57             $position = $vehiclePosition->getPosition();
58             $vehicle = $vehiclePosition->getVehicle();
59             $trip = $vehiclePosition->getTrip();
60             $tripId = $trip->getTripId();
61             $this->gtfsTrips[self::convertTripId($tripId)] = [
62                 'id' => $entity->getId(),
63                 'num' => $vehicle->getLicensePlate(),
64                 'tripId' => $tripId,
65                 'latitude' => $position->getLatitude(),
66                 'longitude' => $position->getLongitude(),
67             ];
68         }
69         ksort($this->gtfsTrips);
70     }
71     
72     public function findOffset() {
73         if(count($this->jsonTrips) == 0 || count($this->gtfsTrips) == 0) {
74             return NULL;
75         }
76         
77         $jsonTripIds = array_keys($this->jsonTrips);
78         $gtfsTripIds = array_keys($this->gtfsTrips);
79         
80         $possibleOffsets = [];
81         for($i = 0; $i < count($this->jsonTrips); $i++) {
82             for($j = 0; $j < count($this->gtfsTrips); $j++) {
83                 $possibleOffsets[$jsonTripIds[$i] - $gtfsTripIds[$j]] = TRUE;
84             }
85         }
86         $possibleOffsets = array_keys($possibleOffsets);
87         
88         $bestOffset = 0;
89         $maxMatched = 0;
90         $options = 0;
91         
92         foreach($possibleOffsets as $offset) {
93             $matched = 0;
94             
95             foreach($gtfsTripIds as $tripId) {
96                 $tripId += $offset;
97                 if(isset($this->jsonTrips[$tripId])) {
98                     $matched++;
99                 }
100             }
101             
102             if($matched > $maxMatched) {
103                 $bestOffset = $offset;
104                 $maxMatched = $matched;
105                 $options = 1;
106             } elseif($matched == $maxMatched) {
107                 $options++;
108             }
109         }
110         
111         if($options != 1) {
112             throw new Exception('Found '.$options.' possible mappings!');
113         }
114         return $bestOffset;
115     }
116     
117     public function getMapping($offset) {
118         $result = [];
119         foreach($this->gtfsTrips as $gtfsTripId => $gtfsTrip) {
120             $jsonTripId = $gtfsTripId + $offset;
121             if(isset($this->jsonTrips[$jsonTripId])) {
122                 $data = numToTypeB($gtfsTrip['id']);
123                 $num = $gtfsTrip['num'];
124                 if(!is_array($data) || !isset($data['num'])) {
125                     $data = [
126                         'num' => $num,
127                         'low' => 2,
128                     ];
129                 } elseif($data['num'] != $num) {
130                     // Ignore due to incorrect depot markings in the data
131                     //$this->logger->warn('Got '.$num.', database has '.$data['num']);
132                 }
133                 $result[$this->jsonTrips[$jsonTripId]['id']] = $data;
134             }
135         }
136         return $result;
137     }
138 }