diff --git a/app/DataProviders/Bahn.php b/app/DataProviders/Bahn.php index 067f33f63..ecdb8d9ac 100644 --- a/app/DataProviders/Bahn.php +++ b/app/DataProviders/Bahn.php @@ -4,6 +4,7 @@ use App\Dto\Internal\BahnTrip; use App\Dto\Internal\Departure; +use App\Enum\HafasTravelType; use App\Enum\ReiseloesungCategory; use App\Enum\TravelType; use App\Enum\TripSource; @@ -20,6 +21,7 @@ use Carbon\Carbon; use Exception; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; use JsonException; @@ -172,25 +174,56 @@ public function getDepartures( CacheKey::increment(HCK::DEPARTURES_SUCCESS); foreach ($entries as $rawDeparture) { //trip + $journeyId = $rawDeparture['journeyId']; + $departureStopId = $rawDeparture['bahnhofsId']; $tripLineName = $rawDeparture['verkehrmittel']['mittelText'] ?? ''; - $tripNumber = preg_replace('/\s/', '-', strtolower($tripLineName)) ?? ''; - $tripJourneyNumber = preg_replace('/\D/', '', $rawDeparture['verkehrmittel']['name']); $category = isset($rawDeparture['verkehrmittel']['produktGattung']) ? ReiseloesungCategory::tryFrom($rawDeparture['verkehrmittel']['produktGattung']) : ReiseloesungCategory::UNKNOWN; $category = $category ?? ReiseloesungCategory::UNKNOWN; + $hafasTravelType = $category->getHTT()->value; + + $platformPlanned = $rawDeparture['gleis'] ?? ''; + $platformReal = $rawDeparture['ezGleis'] ?? $platformPlanned; + try { + $departureStation = Station::where('ibnr', [$departureStopId])->first(); + if ($departureStation === null) { + // if station does not exist, request it from API + $stationsFromApi = $this->getStations($departureStopId, 1); + $departureStation = $stationsFromApi->first(); + } + } catch (Exception $exception) { + Log::error($exception->getMessage()); + $departureStation = $station; + } + + // Cache data used for trip creation since another endpoints do not provide them + Cache::add($journeyId, [ + 'category' => $hafasTravelType, + 'lineName' => $tripLineName + ], now()->addMinutes(30)); - $departures->push(new Departure( - station: $station, - plannedDeparture: Carbon::parse($rawDeparture['zeit'], $timezone), - realDeparture: isset($rawDeparture['ezZeit']) ? Carbon::parse($rawDeparture['ezZeit'], $timezone) : null, - trip: new BahnTrip( - tripId: $rawDeparture['journeyId'], - direction: $rawDeparture['terminus'], - lineName: $tripLineName, - number: $tripNumber, - category: $category->getHTT()->value, - journeyNumber: $tripJourneyNumber, - ), - )); + preg_match('/#ZE#(\d+)/', $journeyId, $matches); + $journeyNumber = 0; + if (count($matches) > 1) { + $journeyNumber = $matches[1]; + } + + $departure = new Departure( + station: $departureStation, + plannedDeparture: Carbon::parse($rawDeparture['zeit'], $timezone), + realDeparture: isset($rawDeparture['ezZeit']) ? Carbon::parse($rawDeparture['ezZeit'], $timezone) : null, + trip: new BahnTrip( + tripId: $journeyId, + direction: $rawDeparture['terminus'] ?? '', + lineName: $tripLineName, + number: $journeyNumber, + category: $hafasTravelType, + journeyNumber: $journeyNumber, + ), + plannedPlatform: $platformPlanned, + realPlatform: $platformReal, + ); + + $departures->push($departure); } return DepartureHydrator::map($departures); @@ -259,6 +292,8 @@ public function fetchHafasTrip(string $tripID, string $lineName): Trip { // sorry throw new HafasException(__('messages.exception.generalHafas')); } + // get cached data from departure board + $cachedData = Cache::get($tripID); $stopoverCacheFromDB = Station::whereIn('ibnr', collect($rawJourney['halte'])->pluck('extId'))->get(); $originStation = $stopoverCacheFromDB->where('ibnr', $rawJourney['halte'][0]['extId'])->first() ?? self::getStationFromHalt($rawJourney['halte'][0]); @@ -273,20 +308,26 @@ public function fetchHafasTrip(string $tripID, string $lineName): Trip { } } if (empty($category)) { - $category = ReiseloesungCategory::UNKNOWN; + // get cached category since Bahn API does not reveal that on the journey endpoint?! + $category = $cachedData['category'] ?? HafasTravelType::REGIONAL->value; + } else { + $category = $category->getHTT()->value; } - $tripLineName = $rawJourney['zugName'] ?? ''; - $tripNumber = preg_replace('/\s/', '-', strtolower($tripLineName)) ?? ''; - $tripJourneyNumber = preg_replace('/\D/', '', $tripLineName); + $tripLineName = $cachedData['lineName'] ?? ''; + preg_match('/#ZE#(\d+)/', $tripID, $matches); + $tripNumber = 0; + if (count($matches) > 1) { + $tripNumber = $matches[1]; + } $journey = Trip::create([ 'trip_id' => $tripID, - 'category' => $category->getHTT(), + 'category' => $category, 'number' => $tripNumber, 'linename' => $tripLineName, - 'journey_number' => !empty($tripJourneyNumber) ? $tripJourneyNumber : 0, + 'journey_number' => $tripNumber, 'operator_id' => null, //TODO 'origin_id' => $originStation->id, 'destination_id' => $destinationStation->id, @@ -305,13 +346,20 @@ public function fetchHafasTrip(string $tripID, string $lineName): Trip { $departureReal = isset($rawHalt['ezAbfahrtsZeitpunkt']) ? Carbon::parse($rawHalt['ezAbfahrtsZeitpunkt'], $timezone) : null; $arrivalPlanned = isset($rawHalt['ankunftsZeitpunkt']) ? Carbon::parse($rawHalt['ankunftsZeitpunkt'], $timezone) : null; $arrivalReal = isset($rawHalt['ezAnkunftsZeitpunkt']) ? Carbon::parse($rawHalt['ezAnkunftsZeitpunkt'], $timezone) : null; + // new API does not differ between departure and arrival platform + $platformPlanned = $rawHalt['gleis'] ?? null; + $platformReal = $rawHalt['ezGleis'] ?? $platformPlanned; $stopover = new Stopover([ - 'train_station_id' => $station->id, - 'arrival_planned' => $arrivalPlanned ?? $departurePlanned, - 'arrival_real' => $arrivalReal ?? $departureReal ?? null, - 'departure_planned' => $departurePlanned ?? $arrivalPlanned, - 'departure_real' => $departureReal ?? $arrivalReal ?? null, + 'train_station_id' => $station->id, + 'arrival_planned' => $arrivalPlanned ?? $departurePlanned, + 'arrival_real' => $arrivalReal ?? $departureReal ?? null, + 'departure_planned' => $departurePlanned ?? $arrivalPlanned, + 'departure_real' => $departureReal ?? $arrivalReal ?? null, + 'arrival_platform_planned' => $platformPlanned, + 'departure_platform_planned' => $platformPlanned, + 'arrival_platform_real' => $platformReal, + 'departure_platform_real' => $platformReal, ]); $stopovers->push($stopover); } diff --git a/app/Dto/Internal/Departure.php b/app/Dto/Internal/Departure.php index a38f946f2..4095fb288 100644 --- a/app/Dto/Internal/Departure.php +++ b/app/Dto/Internal/Departure.php @@ -13,12 +13,16 @@ public Carbon $plannedDeparture; public Carbon|null $realDeparture; public BahnTrip $trip; + public string|null $plannedPlatform; + public string|null $realPlatform; - public function __construct(Station $station, Carbon $plannedDeparture, Carbon|null $realDeparture, BahnTrip $trip) { + public function __construct(Station $station, Carbon $plannedDeparture, Carbon|null $realDeparture, BahnTrip $trip, string|null $plannedPlatform, string|null $realPlatform) { $this->station = $station; $this->plannedDeparture = $plannedDeparture; $this->realDeparture = $realDeparture; $this->trip = $trip; + $this->plannedPlatform = $plannedPlatform; + $this->realPlatform = $realPlatform; } public function getDelay(): ?int { diff --git a/app/Hydrators/DepartureHydrator.php b/app/Hydrators/DepartureHydrator.php index eb9d0b460..cd472870d 100644 --- a/app/Hydrators/DepartureHydrator.php +++ b/app/Hydrators/DepartureHydrator.php @@ -44,8 +44,8 @@ public static function mapSingle(Departure $request) { "when" => $request->realDeparture?->toIso8601String(), "plannedWhen" => $request->plannedDeparture->toIso8601String(), "delay" => $request->getDelay(), //TODO: make it deprecated - "platform" => null, - "plannedPlatform" => null, + "platform" => $request->realPlatform, + "plannedPlatform" => $request->plannedPlatform, "direction" => $request->trip->direction, "provenance" => null, "line" => [