lines = $lines; $this->reference = $reference; $this->schedule = $schedule; } public function getForStop(Stop $stop): Collection { $real = $this->getRealDepartures($stop); $now = Carbon::now()->second(0); $first = $real->map(t\getter('scheduled'))->min() ?? $now; $scheduled = $this->getScheduledDepartures($stop, $first); return $this->pair($scheduled, $real)->filter(function (Departure $departure) use ($now) { return $departure->getDeparture() > $now; }); } private function getRealDepartures(Stop $stop) { try { $estimates = file_get_contents(static::ESTIMATES_URL . "?stopId=" . $stop->getId()); $estimates = json_decode($estimates, true)['delay']; } catch (\Error $e) { return collect(); } $estimates = collect($estimates); $lines = $estimates->map(function ($delay) { return $delay['routeId']; })->unique(); $lines = $this->lines->all(new IdFilter($lines))->keyBy(t\property('id')); return collect($estimates)->map(function ($delay) use ($stop, $lines) { $scheduled = (new Carbon($delay['theoreticalTime'], 'Europe/Warsaw'))->tz('UTC'); $estimated = (clone $scheduled)->addSeconds($delay['delayInSeconds']); return Departure::createFromArray([ 'key' => sprintf('%s::%s', $delay['routeId'], $scheduled->format('H:i')), 'scheduled' => $scheduled, 'estimated' => $estimated, 'stop' => $stop, 'display' => trim($delay['headsign']), 'vehicle' => $this->reference->get(Vehicle::class, $delay['vehicleCode']), 'line' => $lines->get($delay['routeId']) ?: Line::createFromArray([ 'symbol' => $delay['routeId'], 'type' => Line::TYPE_UNKNOWN, ]), ]); })->values(); } private function getScheduledDepartures(Stop $stop, Carbon $time) { return $this->schedule->getDeparturesForStop($stop, $time); } private function pair(Collection $schedule, Collection $real) { $key = function (Departure $departure) { return sprintf("%s::%s", $departure->getLine()->getSymbol(), $departure->getScheduled()->format("H:i")); }; $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 $this->merge(...$pair); })->sortBy(function (Departure $departure) { $time = $departure->getEstimated() ?? $departure->getScheduled(); return $time->getTimestamp(); }); } private function merge(?Departure $real, ?Departure $scheduled) { if (!$real) { return $scheduled; } if (!$scheduled) { return $real; } $departure = clone $real; $departure->setDisplay($scheduled->getDisplay()); $departure->setTrack($scheduled->getTrack()); $departure->setTrip($scheduled->getTrip()); return $departure; } }