Files
FlightsAPI/app/Services/Achievements/Checkers/CountriesAndContinentsChecker.php
2026-04-26 20:00:11 +10:00

98 lines
3.4 KiB
PHP

<?php
namespace App\Services\Achievements\Checkers;
use App\Models\Continent;
use App\Models\User;
use App\Models\UserFlight;
use Illuminate\Support\Collection;
class CountriesAndContinentsChecker extends BaseChecker
{
private const INHABITED_CONTINENTS = [
'africa', 'asia', 'europe', 'north_america', 'oceania', 'south_america',
];
public function check(): void
{
$flights = $this->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<int, UserFlight> $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'
);
}
}