98 lines
3.4 KiB
PHP
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'
|
|
);
|
|
}
|
|
}
|