engine()->computeMatrix($points); foreach ([0, 1, 2] as $i) { self::assertSame(0, $matrix[$i][$i], 'Diagonale nulle (distance d\'un point a lui-meme).'); foreach ([0, 1, 2] as $j) { self::assertSame($matrix[$i][$j], $matrix[$j][$i], 'Matrice symetrique.'); } } // 0,1° de latitude ≈ 11,1 km : on tolere ±300 m sur le modele Haversine. self::assertEqualsWithDelta(11_100, $matrix[0][1], 300, 'Distance a-b ≈ 11,1 km.'); } public function testOptimizeOrderFromStartIsNearestNeighbour(): void { $start = new RoutePoint('start', 47.0, -1.0); // Fournis en desordre : b(47.3) le plus loin, c(47.2), a(47.1) le plus proche. $points = [ new RoutePoint('b', 47.3, -1.0), new RoutePoint('c', 47.2, -1.0), new RoutePoint('a', 47.1, -1.0), ]; $ordered = $this->engine()->optimizeOrder($start, $points); self::assertSame(['a', 'c', 'b'], array_map(static fn (RoutePoint $p) => $p->ref, $ordered)); } public function testOptimizeOrderWithoutStartKeepsFirstPointAsDeparture(): void { // Sans depart explicite : le 1er point fourni est le depart (reste en tete). $points = [ new RoutePoint('depart', 47.0, -1.0), new RoutePoint('b', 47.3, -1.0), new RoutePoint('c', 47.2, -1.0), new RoutePoint('a', 47.1, -1.0), ]; $ordered = $this->engine()->optimizeOrder(null, $points); self::assertSame(['depart', 'a', 'c', 'b'], array_map(static fn (RoutePoint $p) => $p->ref, $ordered)); } public function testLegDurationsUseAverageSpeed(): void { $start = new RoutePoint('start', 47.0, -1.0); $points = [ new RoutePoint('a', 47.1, -1.0), // ~11,1 km du depart new RoutePoint('b', 47.2, -1.0), // ~11,1 km de a ]; $legs = $this->engine()->estimateLegDurations($start, $points); self::assertCount(2, $legs); // 11,1 km a 60 km/h = 0,185 h ≈ 666 s. Tolerance large (modele Haversine). self::assertEqualsWithDelta(666, $legs[0]->durationSeconds, 30); self::assertEqualsWithDelta(11_100, $legs[0]->distanceMeters, 300); } public function testLegDurationsWithoutStartFirstLegIsZero(): void { // Sans depart, le 1er point EST le depart -> 1er segment nul. $points = [ new RoutePoint('depart', 47.0, -1.0), new RoutePoint('a', 47.1, -1.0), ]; $legs = $this->engine()->estimateLegDurations(null, $points); self::assertCount(2, $legs); self::assertSame(0, $legs[0]->distanceMeters, 'Aucun trajet pour atteindre le point de depart.'); self::assertSame(0, $legs[0]->durationSeconds); self::assertEqualsWithDelta(11_100, $legs[1]->distanceMeters, 300); } }