diff --git a/src/Controller/Api/v1/DeparturesController.php b/src/Controller/Api/v1/DeparturesController.php index 0bb5e56..109f556 100644 --- a/src/Controller/Api/v1/DeparturesController.php +++ b/src/Controller/Api/v1/DeparturesController.php @@ -64,9 +64,7 @@ class DeparturesController extends Controller $stops = $stops ->getManyById($request->query->get('stop')) ->flatMap([ $departures, 'getForStop' ]) - ->sortBy(function (Departure $departure) { - return $departure->getEstimated(); - }); + ; return $this->json($stops->values()->slice(0, (int)$request->query->get('limit', 8))); } diff --git a/src/Entity/TripStopEntity.php b/src/Entity/TripStopEntity.php index f85a152..f90df10 100644 --- a/src/Entity/TripStopEntity.php +++ b/src/Entity/TripStopEntity.php @@ -99,7 +99,7 @@ class TripStopEntity implements Fillable public function getDeparture(): Carbon { - return Carbon::instance($this->departure); + return Carbon::instance($this->departure)->tz('UTC'); } public function setDeparture(Carbon $departure): void diff --git a/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php b/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php index 10be76c..a9661b9 100644 --- a/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php +++ b/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php @@ -39,6 +39,14 @@ class ZtmGdanskDepartureRepository implements DepartureRepository } public function getForStop(Stop $stop): Collection + { + $real = $this->getRealDepartures($stop); + $scheduled = $this->getScheduledDepartures($stop, $real->isNotEmpty()); + + return $this->pair($scheduled, $real); + } + + private function getRealDepartures(Stop $stop) { $estimates = json_decode(file_get_contents(static::ESTIMATES_URL . "?stopId=" . $stop->getId()), true)['delay']; $estimates = collect($estimates); @@ -49,7 +57,7 @@ class ZtmGdanskDepartureRepository implements DepartureRepository $lines = $this->lines->getManyById($lines)->keyBy(t\property('id')); return collect($estimates)->map(function ($delay) use ($stop, $lines) { - $scheduled = new Carbon($delay['theoreticalTime']); + $scheduled = (new Carbon($delay['theoreticalTime'], 'Europe/Warsaw'))->tz('UTC'); $estimated = (clone $scheduled)->addSeconds($delay['delayInSeconds']); return Departure::createFromArray([ @@ -65,4 +73,40 @@ class ZtmGdanskDepartureRepository implements DepartureRepository ]); })->values(); } + + private function getScheduledDepartures(Stop $stop, bool $hasRealData = true) + { + $now = Carbon::now(); + + // If we have real data we skip 5 minutes, because sometimes trams or buses get out too quickly. + return $this->schedule->getDeparturesForStop($stop, $hasRealData ? $now->addMinutes(5) : $now); + } + + private function pair(Collection $schedule, Collection $real) + { + $key = function (Departure $departure) { + return sprintf("%s::%s", $departure->getScheduled()->format("H:i"), $departure->getLine()->getSymbol()); + }; + + $schedule = $schedule->keyBy($key)->all(); + $real = $real->keyBy($key); + + return $real->map(function (Departure $real, $key) use (&$schedule) { + $scheduled = null; + + if (array_key_exists($key, $schedule)) { + $scheduled = $schedule[$key]; + unset($schedule[$key]); + } + + return [ $real, $scheduled ]; + })->merge(collect($schedule)->map(function (Departure $scheduled) { + return [ null, $scheduled ]; + }))->map(function ($pair) { + return $pair[0] ?? $pair[1]; + })->sortBy(function (Departure $departure) { + $time = $departure->getEstimated() ?? $departure->getScheduled(); + return $time->getTimestamp(); + }); + } }