flights(); // Resolve internal_name → id once, used throughout $continents = Continent::pluck('id', 'internal_name'); $arrivalContinentIds = $flights->pluck('arrivalAirport.region.continent_id')->unique(); $has = fn(string $name) => $arrivalContinentIds->contains($continents[$name]); // --- Simple "fly to X continent" achievements --- $this->awardIf( $flights->contains(fn(UserFlight $f) => $f->departureAirport->region->continent_id !== $f->arrivalAirport->region->continent_id ), 'countries_continents.intercontinental' ); $this->awardIf($has('africa'), 'countries_continents.fly_to_africa'); $this->awardIf($has('asia'), 'countries_continents.fly_to_asia'); $this->awardIf($has('oceania'), 'countries_continents.fly_to_oceania'); $this->awardIf($has('antarctica'), 'countries_continents.fly_to_antarctica'); $this->awardIf($has('europe'), 'countries_continents.fly_to_europe'); $this->awardIf($has('south_america'), 'countries_continents.fly_to_south_america'); $this->awardIf($has('north_america'), 'countries_continents.fly_to_north_america'); // --- All inhabited continents --- $inhabitedIds = collect(self::INHABITED_CONTINENTS)->map(fn($name) => $continents[$name]); $visitedInhabited = $arrivalContinentIds ->intersect($inhabitedIds) ->unique() ->count(); $this->awardProgress($visitedInhabited, 'countries_continents.all_inhabited_continents'); // --- All continents including Antarctica --- $this->awardProgress( $arrivalContinentIds->unique()->count(), 'countries_continents.all_continents' ); // --- Continent route pairs --- $this->checkContinentPairs($flights); } /** * @param Collection $flights * @return void */ private function checkContinentPairs(Collection $flights): void { $oneWayRoutes = collect(); $directedRoutes = collect(); foreach ($flights as $flight) { $dep = $flight->departureAirport->region->continent->internal_name; $arr = $flight->arrivalAirport->region->continent->internal_name; // Directed route key e.g. "europe→asia" $directedRoutes->push("{$dep}→{$arr}"); // Undirected — sort alphabetically so "europe→asia" and "asia→europe" are the same $undirected = implode('→', collect([$dep, $arr])->sort()->values()->all()); $oneWayRoutes->push($undirected); } $this->awardProgress( $oneWayRoutes->unique()->count(), 'countries_continents.all_continent_pairs_one_way' ); $this->awardProgress( $directedRoutes->unique()->count(), 'countries_continents.all_continent_pairs_both_ways' ); } }