+<?php
+
+namespace App\Console\Commands;
+
+use App\Beat\Encoder;
+use App\Models\AlttpSeed;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Storage;
+use Symfony\Component\Process\Process;
+
+class GenerateAlttpSeed extends Command
+{
+ /**
+ * The name and signature of the console command.
+ *
+ * @var string
+ */
+ protected $signature = 'alttp:generate {id}';
+
+ /**
+ * The console command description.
+ *
+ * @var string
+ */
+ protected $description = 'Generate ALttP seed';
+
+ /**
+ * Execute the console command.
+ *
+ * @return int
+ */
+ public function handle()
+ {
+ $seed = AlttpSeed::findOrFail($this->argument('id'));
+ $seed->status = 'generating';
+ $seed->error_detail = null;
+ $seed->save();
+
+ $temp_dir = sys_get_temp_dir();
+ $rom_file = $temp_dir.'/DR_'.$seed->hash.'.sfc';
+ $settings_file = $temp_dir.'/'.$seed->hash.'.json';
+ $spoiler_file = $temp_dir.'/DR_'.$seed->hash.'_Spoiler.txt';
+
+ $stage = 'initial';
+ try {
+
+ $stage = 'settings';
+ $settings = array_merge([
+ 'calc_playthrough' => true,
+ 'create_rom' => true,
+ 'create_spoiler' => true,
+ 'count' => 1,
+ 'enemizercli' => base_path().'/vendor/z3/enemizer_linux/EnemizerCLI.Core',
+ 'multi' => 1,
+ 'names' => '',
+ 'outputpath' => $temp_dir,
+ 'outputname' => $seed->hash,
+ 'race' => $seed->race,
+ 'rom' => config('alttp.base_rom'),
+ 'seed' => $seed->seed,
+ ], $seed->settings);
+ file_put_contents($settings_file, json_encode($settings));
+
+ $stage = 'generate';
+ $proc = new Process([config('alttp.doors_cli'), '--settingsfile', $settings_file]);
+ $proc->setWorkingDirectory(dirname(config('alttp.doors_cli')));
+ $proc->mustRun();
+
+ $stage = 'calculating patch';
+ $encoder = new Encoder(file_get_contents(config('alttp.base_rom')));
+ $patch = $encoder->createPatch(file_get_contents($rom_file));
+ $spoiler = file_get_contents($spoiler_file);
+ Storage::disk('alttp-seeds')->put($seed->hash.'.bps', $patch);
+ Storage::disk('alttp-spoilers')->put($seed->hash.'.txt', $spoiler);
+
+ $stage = 'done';
+ $seed->status = 'generated';
+ $seed->save();
+ } catch (\Throwable $e) {
+ $this->error($e->getMessage());
+ $seed->status = 'error';
+ $seed->error_detail = [
+ 'stage' => $stage,
+ 'type' => get_class($e),
+ 'message' => $e->getMessage(),
+ ];
+ $seed->save();
+ return 1;
+ }
+
+ if (file_exists($rom_file)) unlink($rom_file);
+ if (file_exists($settings_file)) unlink($settings_file);
+ if (file_exists($spoiler_file)) unlink($spoiler_file);
+
+ return 0;
+ }
+}