]> git.localhorst.tv Git - alttp.git/commitdiff
aos seed generation
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 10 May 2022 17:10:37 +0000 (19:10 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Tue, 10 May 2022 17:10:37 +0000 (19:10 +0200)
12 files changed:
.env.example
app/DiscordAppCommands/AosrPresetCommand.php
app/Jobs/GenerateAosSeed.php [new file with mode: 0644]
app/Models/AosSeed.php
composer.json
composer.lock
config/aos.php
database/migrations/2022_05_10_144912_aos_seed_generation.php [new file with mode: 0644]
resources/js/components/aos/Seed.js
resources/js/components/pages/AosSeed.js
resources/js/i18n/de.js
resources/js/i18n/en.js

index 9fa47a0ab8d9af784640edd7ebf710c84223e27f..c1b602fa2bd93b919c2c44b4337cf367cc0dbb7a 100644 (file)
@@ -61,5 +61,6 @@ DISCORD_BOT_TOKEN=
 DISCORD_BOT_CREATE_COMMANDS=
 DISCORD_BOT_ENABLE_COMMANDS=
 
+AOS_BASE_ROM=
 AOS_HOSTNAME=aos.localhorst.tv
 AOS_URL=https://aos.localhorst.tv
index 8ec3eb4bf1d4c4bd43d9ac1dd2e0de5f38e150e4..a023fcbd45752ff704f223cf1a789260bbb33960 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace App\DiscordAppCommands;
 
+use App\Models\AosSeed;
 use Discord\Builders\MessageBuilder;
 use Discord\Discord;
 use Discord\Parts\Embed\Embed;
@@ -22,15 +23,15 @@ class AosrPresetCommand {
                $cmd = $discord->application->commands->create([
                        'name' => 'aosr',
                        'type' => 1,
-                       'description' => '(testing) Generate an AoSRando seed.',
+                       'description' => 'Generate an AoSRando seed.',
                        'description_localizations' => [
-                               'de' => '(test) Generiert einen AoSRando Seed.',
+                               'de' => 'Generiert einen AoSRando Seed.',
                        ],
                        'options' => [[
                                'name' => 'preset',
-                               'description' => '(testing) Generate an AoSRando seed from preset.',
+                               'description' => 'Generate an AoSRando seed from preset.',
                                'description_localizations' => [
-                                       'de' => '(test) Generiert einen AoSRando Seed anhand eines Presets.',
+                                       'de' => 'Generiert einen AoSRando Seed anhand eines Presets.',
                                ],
                                'type' => 1,
                                'options' => [[
@@ -50,36 +51,40 @@ class AosrPresetCommand {
 
        public static function listen(Discord $discord) {
                $discord->listenCommand(['aosr', 'preset'], function(Interaction $interaction) use ($discord) {
-                       $presetName = $interaction->data->options['preset']->options['preset']->value;
-                       $message = MessageBuilder::new();
-                       if (isset(static::$presets[$presetName])) {
-                               $preset = static::$presets[$presetName];
-                               $seed = strval(random_int(-2147483648, 2147483647));
-                               $params = array_merge(['seed' => $seed], $preset['settings']);
-                               $url = 'https://aosrando.surge.sh/?'.http_build_query($params, '', '&');
-                               $embed = new Embed($discord, [
-                                       'fields' => [
-                                               new Field($discord, [ 'name' => 'Preset', 'value' => $preset['name'], 'inline' => true ]),
-                                               new Field($discord, [ 'name' => 'Seed', 'value' => $seed, 'inline' => true ]),
-                                               new Field($discord, [ 'name' => 'Logic', 'value' => $preset['settings']['logic'], 'inline' => true ]),
-                                               new Field($discord, [ 'name' => 'Area', 'value' => $preset['settings']['area'], 'inline' => true ]),
-                                               new Field($discord, [ 'name' => 'Boss', 'value' => $preset['settings']['boss'], 'inline' => true ]),
-                                               new Field($discord, [ 'name' => 'Enemy', 'value' => $preset['settings']['enemy'], 'inline' => true ]),
-                                               new Field($discord, [ 'name' => 'Link', 'value' => $url ]),
-                                       ],
-                                       'footer' => new Footer($discord, [
-                                               'text' => 'Grün',
-                                       ]),
-                                       'timestamp' => now(),
-                                       'title' => 'AoSRando Seed',
-                                       'type' => 'rich',
-                                       'url' => $url,
-                               ]);
-                               $message->addEmbed($embed);
-                       } else {
-                               $message->setContent('unknown preset '.$presetName);
-                       }
-                       $interaction->respondWithMessage($message);
+                       $interaction
+                               ->acknowledgeWithResponse()
+                               ->done(function() use($discord, $interaction) {
+                               $presetName = $interaction->data->options['preset']->options['preset']->value;
+                               $message = MessageBuilder::new();
+                               if (isset(static::$presets[$presetName])) {
+                                       $preset = static::$presets[$presetName];
+                                       $seed = AosSeed::generateSurge($presetName, $preset['settings']);
+
+                                       $embed = new Embed($discord, [
+                                               'fields' => [
+                                                       new Field($discord, [ 'name' => 'Generator', 'value' => 'This seed has been generated with fusecv\'s randomizer on aosrando.surge.sh.' ]),
+                                                       new Field($discord, [ 'name' => 'Preset', 'value' => $preset['name'], 'inline' => true ]),
+                                                       new Field($discord, [ 'name' => 'Seed', 'value' => $seed->seed, 'inline' => true ]),
+                                                       new Field($discord, [ 'name' => 'Logic', 'value' => $preset['settings']['logic'], 'inline' => true ]),
+                                                       new Field($discord, [ 'name' => 'Area', 'value' => $preset['settings']['area'], 'inline' => true ]),
+                                                       new Field($discord, [ 'name' => 'Boss', 'value' => $preset['settings']['boss'], 'inline' => true ]),
+                                                       new Field($discord, [ 'name' => 'Enemy', 'value' => $preset['settings']['enemy'], 'inline' => true ]),
+                                                       new Field($discord, [ 'name' => 'Permalink', 'value' => $seed->permalink ]),
+                                               ],
+                                               'footer' => new Footer($discord, [
+                                                       'text' => 'Grün',
+                                               ]),
+                                               'timestamp' => now(),
+                                               'title' => 'AoSRando Seed',
+                                               'type' => 'rich',
+                                               'url' => $seed->permalink,
+                                       ]);
+                                       $message->addEmbed($embed);
+                               } else {
+                                       $message->setContent('unknown preset '.$presetName);
+                               }
+                               $interaction->updateOriginalResponse($message);
+                       });
                        return true;
                });
        }
diff --git a/app/Jobs/GenerateAosSeed.php b/app/Jobs/GenerateAosSeed.php
new file mode 100644 (file)
index 0000000..b8c7e9e
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Beat\Encoder;
+use App\Models\AosSeed;
+use HeadlessChromium\BrowserFactory;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldBeUnique;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Support\Facades\Storage;
+
+class GenerateAosSeed implements ShouldQueue
+{
+       use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+       /**
+        * Create a new job instance.
+        *
+        * @return void
+        */
+       public function __construct(AosSeed $seed)
+       {
+               $this->seed = $seed;
+       }
+
+       /**
+        * Execute the job.
+        *
+        * @return void
+        */
+       public function handle()
+       {
+               try {
+                       $temp_dir = sys_get_temp_dir();
+
+                       $seed = $this->seed;
+                       $params = array_merge(['seed' => $seed->seed], $seed->settings);
+                       $url = 'https://aosrando.surge.sh/?'.http_build_query($params, '', '&');
+
+                       $fac = new BrowserFactory('chromium');
+                       $browser = $fac->createBrowser();
+
+                       $page = $browser->createPage();
+                       $page->setDownloadPath($temp_dir);
+                       $page->navigate($url)->waitForNavigation();
+
+                       $fileInput = $page->dom()->querySelector('input[type=file]');
+                       $fileInput->sendFile(config('aos.base_rom'));
+                       $page->waitUntilContainsElement('select');
+
+                       $page->mouse()->find('button', 2)->click();
+                       $page->waitUntilContainsElement('a[download]');
+
+                       $page->dom()->querySelector('a[download]')->setAttributeValue('download', $seed->hash.'.gba');
+                       $page->mouse()->find('a[download]')->click();
+
+                       sleep(2);
+
+                       $encoder = new Encoder(file_get_contents(config('aos.base_rom')));
+                       $patch = $encoder->createPatch(file_get_contents($temp_dir.'/'.$seed->hash.'.gba'));
+                       Storage::disk('aos-seeds')->put($seed->hash.'.bps', $patch);
+                       unlink($temp_dir.'/'.$seed->hash.'.gba');
+
+                       $seed->status = 'generated';
+                       $seed->save();
+
+                       $browser->close();
+               } catch (\Throwable) {
+                       $seed->status = 'error';
+                       $seed->save();
+               }
+       }
+
+       protected $seed;
+
+}
index d44cfccbe242380631392a7316371e05deff0653..18633b7a471ce65a0be0d1e02f28bea0d20e4629 100644 (file)
@@ -2,13 +2,34 @@
 
 namespace App\Models;
 
+use App\Jobs\GenerateAosSeed;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Str;
 
 class AosSeed extends Model
 {
        use HasFactory;
 
+       public static function generateSurge($preset, $settings, $race = false, $mystery = false) {
+               $seed = new static();
+               $seed->hash = Str::random(16);
+               $seed->generator = 'surge';
+               $seed->preset = $preset;
+               $seed->race = $race;
+               $seed->mystery = $mystery;
+               $seed->seed = strval(random_int(-2147483648, 2147483647));
+               $seed->settings = $settings;
+               $seed->status = 'pending';
+               $seed->save();
+               GenerateAosSeed::dispatch($seed)->onConnection('database');
+               return $seed;
+       }
+
+       public function getPermalinkAttribute() {
+               return config('aos.url').'/h/'.rawurlencode($this->hash);
+       }
+
        protected $casts = [
                'mystery' => 'boolean',
                'race' => 'boolean',
index 490fb47c80a1d9500bc944a02dd2804052b5caaa..06e61869e993665e1a1d93be74ff56f350b003cb 100644 (file)
@@ -7,6 +7,7 @@
     "require": {
         "php": "^8.0.2",
         "beyondcode/laravel-websockets": "^1.13",
+        "chrome-php/chrome": "^1.6",
         "doctrine/dbal": "^3.3",
         "guzzlehttp/guzzle": "^7.2",
         "jakyeru/larascord": "^3.0",
index 560b19033249236d9655345bebd959a21f049836..3c72e9031f6c050f7d0128f5a348045a9dee7aa8 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "7ae17dd5730b055eb0b260e5b8ee41d5",
+    "content-hash": "ac83dea6ac9ea66e7899d97abf35b4fb",
     "packages": [
         {
             "name": "beyondcode/laravel-websockets",
             },
             "time": "2021-12-14T00:20:41+00:00"
         },
+        {
+            "name": "chrome-php/chrome",
+            "version": "v1.6.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/chrome-php/chrome.git",
+                "reference": "e8264cb33a02053caf8877c1566e54f09c60d10c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/chrome-php/chrome/zipball/e8264cb33a02053caf8877c1566e54f09c60d10c",
+                "reference": "e8264cb33a02053caf8877c1566e54f09c60d10c",
+                "shasum": ""
+            },
+            "require": {
+                "chrome-php/wrench": "^1.2",
+                "evenement/evenement": "^3.0.1",
+                "monolog/monolog": "^1.26 || ^2.2",
+                "php": "^7.3 || ^8.0",
+                "psr/log": "^1.1 || ^2.0 || ^3.0",
+                "symfony/filesystem": "^4.4 || ^5.0 || ^6.0",
+                "symfony/polyfill-mbstring": "^1.23",
+                "symfony/process": "^4.4 || ^5.0 || ^6.0"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.4.1",
+                "phpunit/phpunit": "^9.5.10",
+                "symfony/var-dumper": "^4.4 || ^5.0 || ^6.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "HeadlessChromium\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
+                {
+                    "name": "Enrico Dias",
+                    "email": "enricodias@gmail.com",
+                    "homepage": "https://github.com/enricodias"
+                }
+            ],
+            "description": "Instrument headless chrome/chromium instances from PHP",
+            "keywords": [
+                "browser",
+                "chrome",
+                "chromium",
+                "crawl",
+                "headless",
+                "pdf",
+                "puppeteer",
+                "screenshot"
+            ],
+            "support": {
+                "issues": "https://github.com/chrome-php/chrome/issues",
+                "source": "https://github.com/chrome-php/chrome/tree/v1.6.0"
+            },
+            "time": "2022-03-30T09:50:16+00:00"
+        },
+        {
+            "name": "chrome-php/wrench",
+            "version": "v1.2.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/chrome-php/wrench.git",
+                "reference": "e8a34b54df8c9cd4f6d166bdb9df475988e17ce4"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/chrome-php/wrench/zipball/e8a34b54df8c9cd4f6d166bdb9df475988e17ce4",
+                "reference": "e8a34b54df8c9cd4f6d166bdb9df475988e17ce4",
+                "shasum": ""
+            },
+            "require": {
+                "ext-sockets": "*",
+                "php": "^7.3 || ^8.0",
+                "psr/log": "^1.1 || ^2.0 || ^3.0",
+                "symfony/polyfill-php80": "^1.22"
+            },
+            "conflict": {
+                "wrench/wrench": "*"
+            },
+            "require-dev": {
+                "bamarni/composer-bin-plugin": "^1.4.1",
+                "phpunit/phpunit": "^9.5.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Wrench\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                }
+            ],
+            "description": "A simple PHP WebSocket implementation",
+            "keywords": [
+                "WebSockets",
+                "hybi",
+                "websocket"
+            ],
+            "support": {
+                "issues": "https://github.com/chrome-php/wrench/issues",
+                "source": "https://github.com/chrome-php/wrench/tree/v1.2.0"
+            },
+            "time": "2022-03-30T09:35:45+00:00"
+        },
         {
             "name": "dflydev/dot-access-data",
             "version": "v3.0.1",
             ],
             "time": "2022-01-02T09:55:41+00:00"
         },
+        {
+            "name": "symfony/filesystem",
+            "version": "v6.0.7",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/filesystem.git",
+                "reference": "6c9e4c41f2c51dfde3db298594ed9cba55dbf5ff"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/filesystem/zipball/6c9e4c41f2c51dfde3db298594ed9cba55dbf5ff",
+                "reference": "6c9e4c41f2c51dfde3db298594ed9cba55dbf5ff",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.0.2",
+                "symfony/polyfill-ctype": "~1.8",
+                "symfony/polyfill-mbstring": "~1.8"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Filesystem\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides basic utilities for the filesystem",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/filesystem/tree/v6.0.7"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2022-04-01T12:54:51+00:00"
+        },
         {
             "name": "symfony/finder",
             "version": "v6.0.8",
index d09377507ea510237dd3f5fe9f960a4adaa87f7d..7f98a904a642d77c2668e1035f7d6f976f7f7d19 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
 return [
+       'base_rom' => env('AOS_BASE_ROM', ''),
        'hostname' => env('AOS_HOSTNAME', 'aos.localhorst.tv'),
+       'url' => env('AOS_URL', 'https://aos.localhorst.tv'),
 ];
diff --git a/database/migrations/2022_05_10_144912_aos_seed_generation.php b/database/migrations/2022_05_10_144912_aos_seed_generation.php
new file mode 100644 (file)
index 0000000..31debf7
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+       /**
+        * Run the migrations.
+        *
+        * @return void
+        */
+       public function up()
+       {
+               Schema::table('aos_seeds', function(Blueprint $table) {
+                       $table->string('status')->default('pending');
+                       $table->unique('hash');
+               });
+       }
+
+       /**
+        * Reverse the migrations.
+        *
+        * @return void
+        */
+       public function down()
+       {
+               Schema::table('aos_seeds', function(Blueprint $table) {
+                       $table->dropColumn('status');
+                       $table->dropIndex('aos_seeds_hash_unique');
+               });
+       }
+};
index 289e00e7bca78a9763f39e67291c1425bba669c6..efc113015eb2990217126043d395191305162e82 100644 (file)
@@ -31,7 +31,7 @@ const Seed = ({ patch, seed }) => {
                        <Col md={{ order: 2 }}>
                                {rom ?
                                        <Button
-                                               disabled={!patch}
+                                               disabled={!seed || seed.status !== 'generated' || !patch}
                                                onClick={() => applyPatch(
                                                        rom,
                                                        patch,
@@ -54,8 +54,34 @@ const Seed = ({ patch, seed }) => {
                                        {' '}
                                        <strong>{i18n.t(`aosSeeds.presets.${seed.preset}`)}</strong>
                                </p>
-                               <p>{i18n.t(seed.race ? 'aosSeeds.race' : 'aosSeeds.noRace')}</p>
-                               <p>{i18n.t(seed.mystery ? 'aosSeeds.mystery' : 'aosSeeds.noMystery')}</p>
+                               {seed.seed ?
+                                       <p>
+                                               {i18n.t('aosSeeds.seed')}:
+                                               {' '}
+                                               <strong>{seed.seed}</strong>
+                                       </p>
+                               : null}
+                               {seed.race ?
+                                       <p>{i18n.t('aosSeeds.race')}</p>
+                               : null}
+                               {seed.mystery ?
+                                       <p>{i18n.t('aosSeeds.mystery')}</p>
+                               : null}
+                               {seed.status === 'generated' ?
+                                       <p>
+                                               {i18n.t('aosSeeds.generated')}:
+                                               {' '}
+                                               <strong>
+                                                       {i18n.t('aosSeeds.date', { date: new Date(seed.updated_at) })}
+                                               </strong>
+                                       </p>
+                               :
+                                       <p>
+                                               {i18n.t('aosSeeds.status')}:
+                                               {' '}
+                                               <strong>{i18n.t(`aosSeeds.statuses.${seed.status}`)}</strong>
+                                       </p>
+                               }
                        </Col>
                </Row>
                <h2 className="mt-5">{i18n.t('aosSeeds.generator')}</h2>
@@ -71,6 +97,9 @@ Seed.propTypes = {
                mystery: PropTypes.bool,
                preset: PropTypes.string,
                race: PropTypes.bool,
+               seed: PropTypes.string,
+               status: PropTypes.string,
+               updated_at: PropTypes.string,
        }),
 };
 
index 6cea156640001c3228ac93c911db88c82a3eb11f..e3cfda8f93b6a8f3e6b754b6007691d1e0254eb3 100644 (file)
@@ -1,5 +1,5 @@
 import axios from 'axios';
-import React, { useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
 import { useParams } from 'react-router-dom';
 
 import NotFound from './NotFound';
@@ -17,9 +17,7 @@ const AosSeed = () => {
        const [patch, setPatch] = useState(null);
        const [seed, setSeed] = useState(null);
 
-       useEffect(() => {
-               setLoading(true);
-               const ctrl = new AbortController();
+       const loadSeed = useCallback((hash, ctrl) => {
                axios
                        .get(`/api/aos-seed/${hash}`, { signal: ctrl.signal })
                        .then(response => {
@@ -33,13 +31,36 @@ const AosSeed = () => {
                                setLoading(false);
                                setSeed(null);
                        });
+       }, []);
+
+       useEffect(() => {
+               setLoading(true);
+               const ctrl = new AbortController();
+               loadSeed(hash, ctrl);
                return () => {
                        ctrl.abort();
                };
        }, [hash]);
 
+       useEffect(() => {
+               if (!seed || seed.status !== 'pending') {
+                       return;
+               }
+               const ctrl = new AbortController();
+               const timer = setTimeout(() => {
+                       loadSeed(seed.hash, ctrl);
+               }, 2000);
+               return () => {
+                       clearTimeout(timer);
+                       ctrl.abort();
+               };
+       }, [seed]);
+
        useEffect(() => {
                setPatch(null);
+               if (!seed || seed.status !== 'generated') {
+                       return;
+               }
                const ctrl = new AbortController();
                axios
                        .get(`/aos-seeds/${hash}.bps`, {
@@ -55,7 +76,7 @@ const AosSeed = () => {
                return () => {
                        ctrl.abort();
                };
-       }, [hash]);
+       }, [hash, seed]);
 
        if (loading) {
                return <Loading />;
index 391e176cf3130aedeec88c714fde86533641cc72..7d2aab09c24e95b8b69d6b8451d8ef065b54898e 100644 (file)
@@ -8,9 +8,11 @@ export default {
                        setBaseRom: 'Base ROM auswählen',
                },
                aosSeeds: {
+                       date: '{{ date, L LT }}',
                        fetchingPatch: 'Lade Patch',
                        filename: 'aosr - {{preset}} - {{hash}}',
                        heading: 'Aria of Sorrow Randomizer Seed',
+                       generated: 'Generiert',
                        generator: 'Generator',
                        generators: {
                                surge: 'Dieser Seed wurde mit dem Randomizer von fusecv auf aosrando.surge.sh generiert',
@@ -40,6 +42,13 @@ export default {
                                Tournament2022: 'Turnier 2022',
                        },
                        race: 'Race',
+                       seed: 'Seed',
+                       status: 'Status',
+                       statuses: {
+                               error: 'Fehler',
+                               generated: 'generiert',
+                               pending: 'ausstehend',
+                       },
                },
                applications: {
                        accept: 'Annehmen',
index 190aceae3e4ea0644ab6864de352a053abedc959..4f0bcc6697730fa398a2da7fae6361d2bbcb7cf4 100644 (file)
@@ -8,9 +8,11 @@ export default {
                        setBaseRom: 'Set base ROM',
                },
                aosSeeds: {
+                       date: '{{ date, L LT }}',
                        fetchingPatch: 'Fetching patch',
                        filename: 'aosr - {{preset}} - {{hash}}',
                        heading: 'Aria of Sorrow Randomizer Seed',
+                       generated: 'Generated',
                        generator: 'Generator',
                        generators: {
                                surge: 'This seed has been generated with fusecv\'s randomizer on aosrando.surge.sh.',
@@ -40,6 +42,13 @@ export default {
                                Tournament2022: 'Tournament 2022',
                        },
                        race: 'Race',
+                       seed: 'Seed',
+                       status: 'Status',
+                       statuses: {
+                               error: 'error',
+                               generated: 'generated',
+                               pending: 'pending',
+                       },
                },
                applications: {
                        accept: 'Accept',