Lines 100.00% 37 / 37
Methods 100.00% 2 / 2
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 __construct 100.00% 1 / 1 100.00% 1 / 1 1
 fromJson 100.00% 36 / 36 100.00% 1 / 1 3
20final readonly class TravelMap
21{
22    /** @param list<TravelMapRegion> $regions */
23    public function __construct(
24        public array $regions,
25    ) {}
26
27    /** @throws TravelMapUnavailableException */
28    public static function fromJson(string $json): self
29    {
30        $type = Type\json_decoded(Type\vec(Type\shape([
31            'regionID' => Type\positive_int(),
32            'regionName' => Type\non_empty_string(),
33            'maps' => Type\optional(Type\vec(Type\shape([
34                'mapID' => Type\positive_int(),
35                'mapName' => Type\non_empty_string(),
36                'mapTitle' => Type\non_empty_string(),
37                'description' => Type\string(),
38                'bUpgrade' => Type\bool(),
39                'minLevel' => Type\int_range(min: 0, max: 100),
40                'maxLevel' => Type\int_range(min: 0, max: 100),
41            ], allowUnknownFields: true))),
42        ], allowUnknownFields: true)));
43
44        try {
45            $regions = $type->coerce($json);
46        } catch (CoercionException $exception) {
47            throw new TravelMapUnavailableException('Unexpected travel map response.', previous: $exception);
48        }
49
50        return new self(array_map(
51            static fn(array $region): TravelMapRegion => new TravelMapRegion(
52                new RegionId($region['regionID']),
53                new RegionName($region['regionName']),
54                array_map(static function (array $map): TravelMapEntry {
55                    $description = trim($map['description']);
56
57                    return new TravelMapEntry(
58                        new MapId($map['mapID']),
59                        new RegionMap(
60                            new MapName($map['mapName']),
61                            new MapTitle($map['mapTitle']),
62                            $description === '' ? Option\none() : Option\some(new MapDescription($description)),
63                            new LevelRange($map['minLevel'], $map['maxLevel']),
64                        ),
65                        $map['bUpgrade'],
66                    );
67                }, $region['maps'] ?? []),
68            ),
69            $regions,
70        ));
71    }
72}