/**
  * Generate a new galaxy.
  *
  * @return \Illuminate\Http\RedirectResponse
  */
 public function generate()
 {
     // Start with a clean slate.
     DB::table('stars')->delete();
     DB::table('star_links')->delete();
     // Create new stars.
     $starCount = 200;
     /**
      * @var Star[] $unvisitedStars
      * @var Star[] $visitedStars
      * @var Star[] $allStars
      */
     $unvisitedStars = [];
     $visitedStars = [];
     $allStars = [];
     for ($i = 0; $i < $starCount; $i++) {
         $star = new Star(['name' => $this->generateName()]);
         $star->save();
         $unvisitedStars[$star->getKey()] = true;
         $allStars[$star->getKey()] = $star;
     }
     // Create links between stars.
     $totalLinks = 0;
     $starId = array_rand($allStars);
     $visitedStars[$starId] = $allStars[$starId];
     unset($unvisitedStars[$starId]);
     // Random walk to generate a uniform spanning tree.
     while (!empty($unvisitedStars)) {
         $star = $visitedStars[$starId];
         $otherStarId = array_rand($allStars);
         $otherStar = $allStars[$otherStarId];
         if (!isset($visitedStars[$otherStarId])) {
             $star->exits()->attach($otherStar);
             $otherStar->exits()->attach($star);
             $visitedStars[$otherStarId] = $allStars[$otherStarId];
             unset($unvisitedStars[$otherStarId]);
             $totalLinks++;
         }
         $starId = $otherStarId;
     }
     // Add some extra links to create cycles.
     for ($i = 0; $i < $totalLinks / 10; $i++) {
         $star = $allStars[array_rand($allStars)];
         $otherStar = $allStars[array_rand($allStars)];
         if ($star != $otherStar) {
             $star->exits()->attach($otherStar);
             $otherStar->exits()->attach($star);
             $totalLinks++;
         }
     }
     return redirect()->back()->with('status', 'Generated ' . $starCount . ' stars and ' . $totalLinks . ' star links.');
 }