| 1 |  |  | <?php declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | use Smr\Exceptions\UserError; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | use Smr\HardwareType; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | use Smr\Path; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | use Smr\PlotGroup; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use Smr\TradeGood; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use Smr\TransactionType; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | class Plotter { | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 11 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 12 |  |  | 	public static function getX(PlotGroup $xType, int|string $X, int $gameID, AbstractSmrPlayer $player = null): mixed { | 
            
                                                                        
                            
            
                                    
            
            
                | 13 |  |  | 		// Special case for Location categories (i.e. Bar, HQ, SafeFed) | 
            
                                                                        
                            
            
                                    
            
            
                | 14 |  |  | 		if (!is_numeric($X)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 15 |  |  | 			if ($xType != PlotGroup::Locations) { | 
            
                                                                        
                            
            
                                    
            
            
                | 16 |  |  | 				throw new Exception('Non-numeric X only exists for Locations'); | 
            
                                                                        
                            
            
                                    
            
            
                | 17 |  |  | 			} | 
            
                                                                        
                            
            
                                    
            
            
                | 18 |  |  | 			return $X; | 
            
                                                                        
                            
            
                                    
            
            
                | 19 |  |  | 		} | 
            
                                                                        
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 21 |  |  | 		// In all other cases, X is either an int or a numeric string | 
            
                                                                        
                            
            
                                    
            
            
                | 22 |  |  | 		if (is_string($X)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 23 |  |  | 			$X = str2int($X); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                        
                            
            
                                    
            
            
                | 24 |  |  | 		} | 
            
                                                                        
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 26 |  |  | 		// Helper function for plots to trade goods | 
            
                                                                        
                            
            
                                    
            
            
                | 27 |  |  | 		$getGoodWithTransaction = function(int $goodID) use ($xType, $player) { | 
            
                                                                        
                            
            
                                    
            
            
                | 28 |  |  | 			$good = TradeGood::get($goodID); | 
            
                                                                        
                            
            
                                    
            
            
                | 29 |  |  | 			if (isset($player) && !$player->meetsAlignmentRestriction($good->alignRestriction)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 30 |  |  | 				throw new Exception('Player trying to access alignment-restricted good!'); | 
            
                                                                        
                            
            
                                    
            
            
                | 31 |  |  | 			} | 
            
                                                                        
                            
            
                                    
            
            
                | 32 |  |  | 			return [ | 
            
                                                                        
                            
            
                                    
            
            
                | 33 |  |  | 				'Type' => 'Good', | 
            
                                                                        
                            
            
                                    
            
            
                | 34 |  |  | 				'GoodID' => $goodID, | 
            
                                                                        
                            
            
                                    
            
            
                | 35 |  |  | 				'TransactionType' => TransactionType::from(explode(' ', $xType->value)[0]), | 
            
                                                                        
                            
            
                                    
            
            
                | 36 |  |  | 			]; | 
            
                                                                        
                            
            
                                    
            
            
                | 37 |  |  | 		}; | 
            
                                                                        
                            
            
                                    
            
            
                | 38 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 39 |  |  | 		return match ($xType) { | 
            
                                                                        
                            
            
                                    
            
            
                | 40 |  |  | 			PlotGroup::Technology => HardwareType::get($X), | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  | 			PlotGroup::Ships => SmrShipType::get($X), | 
            
                                                                        
                            
            
                                    
            
            
                | 42 |  |  | 			PlotGroup::Weapons => SmrWeaponType::getWeaponType($X), | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  | 			PlotGroup::Locations => SmrLocation::getLocation($gameID, $X), | 
            
                                                                        
                            
            
                                    
            
            
                | 44 |  |  | 			PlotGroup::SellGoods, PlotGroup::BuyGoods => $getGoodWithTransaction($X), | 
            
                                                                        
                            
            
                                    
            
            
                | 45 |  |  | 			PlotGroup::Galaxies => SmrGalaxy::getGalaxy($gameID, $X), // $X is the galaxyID | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  | 		}; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | 	 * Returns the shortest path from $sector to $x as a Distance object. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  | 	 * The path is guaranteed reversible ($x -> $sector == $sector -> $x), which | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | 	 * is not true for findDistanceToX. If $x is not a SmrSector, then this | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  | 	 * function does 2x the work. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  | 	public static function findReversiblePathToX(mixed $x, SmrSector $sector, AbstractSmrPlayer $needsToHaveBeenExploredBy = null, AbstractSmrPlayer $player = null): Path { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  | 		if ($x instanceof SmrSector) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  | 			// To ensure reversibility, always plot lowest to highest. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  | 			$reverse = $sector->getSectorID() > $x->getSectorID(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  | 			if ($reverse) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  | 				$start = $x; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  | 				$end = $sector; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  | 			} else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  | 				$start = $sector; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  | 				$end = $x; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  | 			$path = self::findDistanceToX($end, $start, true, $needsToHaveBeenExploredBy, $player); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  | 			if ($path === false) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  | 				throw new UserError('Unable to plot from ' . $sector->getSectorID() . ' to ' . $x->getSectorID() . '.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  | 			// Reverse if we plotted $x -> $sector (since we want $sector -> $x) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  | 			if ($reverse) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  | 				$path->reversePath(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  | 		} else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  | 			// At this point we don't know what sector $x will be at | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  | 			$path = self::findDistanceToX($x, $sector, true, $needsToHaveBeenExploredBy, $player); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  | 			if ($path === false) { | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  | 				throw new UserError('Unable to find what you\'re looking for, it either hasn\'t been added to this game or you haven\'t explored it yet.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  | 			// Now that we know where $x is, make sure path is reversible | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  | 			// (i.e. start sector < end sector) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  | 			if ($path->getEndSectorID() < $sector->getSectorID()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  | 				$endSector = SmrSector::getSector($sector->getGameID(), $path->getEndSectorID()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  | 				$path = self::findDistanceToX($sector, $endSector, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  | 				if ($path === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  | 					throw new Exception('Unable to find reverse path'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  | 				$path->reversePath(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  | 		return $path; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  | 	 * Returns the shortest path from $sector to $x as a Path object. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  | 	 * The resulting path prefers neighbors in their order in SmrSector->links, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  | 	 * (i.e. up, down, left, right). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  | 	 * @param mixed $x If the string 'Distance', then distances to all visited sectors will | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  | 	 *                 be returned. Otherwise, must be a type implemented by SmrSector::hasX, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  | 	 *                 and will only return distances to sectors for which hasX returns true. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  | 	 * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  | 	 * @return ($useFirst is true ? Smr\Path|false : array<int, Smr\Path>) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  | 	public static function findDistanceToX(mixed $x, SmrSector $sector, bool $useFirst, AbstractSmrPlayer $needsToHaveBeenExploredBy = null, AbstractSmrPlayer $player = null, int $distanceLimit = 10000, int $lowLimit = 0, int $highLimit = 100000): array|Path|false { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  | 		$warpAddIndex = TURNS_WARP_SECTOR_EQUIVALENCE - 1; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  | 		$checkSector = $sector; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  | 		$gameID = $sector->getGameID(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  | 		$distances = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  | 		$sectorsTravelled = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  | 		$visitedSectors = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  | 		$visitedSectors[$checkSector->getSectorID()] = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  | 		$distanceQ = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  | 		for ($i = 0; $i <= TURNS_WARP_SECTOR_EQUIVALENCE; $i++) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  | 			$distanceQ[] = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  | 		//Warps first as a slight optimisation due to how visitedSectors is set. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  | 		if ($checkSector->hasWarp() === true) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  | 			$d = new Path($checkSector->getSectorID()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  | 			$d->addWarp($checkSector->getWarp()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  | 			$distanceQ[$warpAddIndex][] = $d; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  | 		foreach ($checkSector->getLinks() as $nextSector) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  | 			$visitedSectors[$nextSector] = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  | 			$d = new Path($checkSector->getSectorID()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  | 			$d->addLink($nextSector); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  | 			$distanceQ[0][] = $d; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  | 		$maybeWarps = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  | 		while ($maybeWarps <= TURNS_WARP_SECTOR_EQUIVALENCE) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  | 			$sectorsTravelled++; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  | 			if ($sectorsTravelled > $distanceLimit) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  | 				break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  | 			$distanceQ[] = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  | 			$q = array_shift($distanceQ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  | 			if (count($q) === 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  | 				$maybeWarps++; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  | 				continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  | 			$maybeWarps = 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  | 			while (($distance = array_shift($q)) !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  | 				$checkSectorID = $distance->getEndSectorID(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  | 				$visitedSectors[$checkSectorID] = true; // This is here for warps, because they are delayed visits if we set this before the actual visit we'll get sectors marked as visited long before they are actually visited - causes problems when it's quicker to walk to the warp exit than to warp there. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  | 																// We still need to mark walked sectors as visited before we go to each one otherwise we get a huge number of paths being checked twice (up then left, left then up are essentially the same but if we set up-left as visited only when we actually check it then it gets queued up twice - nasty) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  | 				if ($checkSectorID >= $lowLimit && $checkSectorID <= $highLimit) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  | 					$checkSector = SmrSector::getSector($gameID, $checkSectorID); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  | 					// Does this sector satisfy our criteria? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  | 					if ($x == 'Distance' || (($needsToHaveBeenExploredBy === null || $needsToHaveBeenExploredBy->hasVisitedSector($checkSector->getSectorID())) === true | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  | 							&& $checkSector->hasX($x, $player) === true)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  | 						if ($useFirst === true) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  | 							return $distance; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  | 						} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  | 						$distances[$checkSector->getSectorID()] = $distance; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  | 					} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  | 					//Warps first as a slight optimisation due to how visitedSectors is set. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  | 					if ($checkSector->hasWarp() === true) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  | 						if (!isset($visitedSectors[$checkSector->getWarp()])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  | 							$cloneDistance = clone($distance); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  | 							$cloneDistance->addWarp($checkSector->getWarp()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  | 							$distanceQ[$warpAddIndex][] = $cloneDistance; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  | 						} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  | 					} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  | 					foreach ($checkSector->getLinks() as $nextSector) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  | 						if (!isset($visitedSectors[$nextSector])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  | 							$visitedSectors[$nextSector] = true; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  | 							$cloneDistance = clone($distance); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  | 							$cloneDistance->addLink($nextSector); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  | 							$distanceQ[0][] = $cloneDistance; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  | 						} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  | 					} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  | 				} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  | 		if ($useFirst === true) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  | 			return false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  | 		return $distances; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  | 	 * @param array<int, \SmrPort> $ports | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  | 	 * @param array<int, bool> $races | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  | 	 * @return array<int, array<int, Smr\Path>> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  | 	public static function calculatePortToPortDistances(array $ports, array $races, int $distanceLimit = 10000, int $lowLimit = 0, int $highLimit = 100000): array { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  | 		$distances = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  | 		foreach ($ports as $port) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  | 			$sectorID = $port->getSectorID(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  | 			if ($races[$port->getRaceID()] && $sectorID >= $lowLimit && $sectorID <= $highLimit) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  | 				$distances[$sectorID] = self::findDistanceToOtherPorts($port->getSector(), $distanceLimit, $lowLimit, $highLimit); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  | 			} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  | 		} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  | 		return $distances; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  | 	/** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  | 	 * @return array<int, Smr\Path> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  | 	 */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  | 	public static function findDistanceToOtherPorts(SmrSector $sector, int $distanceLimit = 10000, int $lowLimit = 0, int $highLimit = 100000): array { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  | 		return self::findDistanceToX('Port', $sector, false, null, null, $distanceLimit, $lowLimit, $highLimit); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  | 	} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |  | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 211 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 212 |  |  |  |