AHC の Web 版ビジュアライザはとても便利ですが、毎度出力を入力欄にコピペする必要があるのが難点です。そこでこの記事では、Web 版ビジュアライザを手元で動かし、seed 値の入力欄を変更すると即座に直近の手元での実行結果が表示されるようにしたときの手順をつらつらと書きます。
【追記】ssaattoo さんが公開しているユーザースクリプトの方が万倍便利なのでこの記事は読まずにそちらを使いましょう。
動作イメージは下のような感じです。
今回は Web 版ビジュアライザを手元に持ってきてシード変えたら即座に直近実行したときの解(と出力したログ)が表示されるようにするのはやった。かなり捗るのでオススメです #AHC019 pic.twitter.com/03TZAqOoE2
— iwashi31 (@iwashi31) 2023年4月2日
ローカルサーバを立てる
手元でサーバを立てるため Vite で適当に最低限構成のプロジェクトを作成します。
$ npm create vite@4.2.0 local_visualizer -- --template vanilla Scaffolding project in /Users/iwashi/procon/ahc019/local_visualizer... Done. Now run: cd local_visualizer npm install npm run dev
Now run:
に続く 3 つのコマンドをそのまま実行してブラウザで http://localhost:5173/ にアクセスし Hello Vite! と表示されれば OK です。
諸々をダウンロード
Web 版ビジュアライザを Chrome で開き、適当なところを右クリックして「別名で保存」を選択すると、こういうものがダウンロードできます。(これは保存時のファイル名に Visualizer を指定した場合です)
先ほど作成した local_visualizer ディレクトリ配下にある index.html
の中身をこのダウンロードしてきた Visualizer.html
で置き換えます。
$ pwd /Users/iwashi/procon/ahc019/local_visualizer $ mv ~/Downloads/Visualizer.html index.html
Visualizer_files
の方はディレクトリごと public
配下に持ってきます。
$ pwd /Users/iwashi/procon/ahc019/local_visualizer $ mv ~/Downloads/Visualizer_files public/
さてページの方はどうかな?
./b36525d8.js がないぞと怒られていますね。 b36525d8.js
をダウンロードしてきて local_visualizer
配下( index.html
と同じ階層)に設置しましょう。
さてどうかな?
three が import できないと怒られていますね。本来なら importmap のあたりで解決されてるような気がするのですが、よく分からないので npm で three をインストールしてしまいましょう。
$ npm install three
さてどうかな?
コンパイルエラーは出なくなりましたが、seed 値を入れても input が自動入力されません。
ブラウザの開発者ツールのコンソールを見ると b36525d8_bg.wasm
の取得に失敗したよと言われています。なるほど wasm ってそういう感じなんですね。 b36525d8_bg.wasm
をダウンロードしてきて public
配下に設置します。
さてどうかな?
コンソールのエラーは消え、入力も自動生成されるようになりました。ただ肝心のビジュアライズ部分が真っ白ですね。
よく見たらすごい下の方にありました。
むむむ、なぜか canvas 要素が 4 つもありますね。
よく分からないですが index.html
に初めから記述されている canvas 要素を消すとなんかちゃんと動いてそうな感じがします。まぁこれで良しとしましょう。
追記:冷静に考えたらこの canvas は js で動的に追加されるもので、動的に追加された後の html をダウンロードしてきたからダブってたんですね。なので index.html 内の canvas を消すは結果的に正しい対応でした。
出力結果の読み込み
僕は普段手元での実行結果を {project_root}/tools/versions/latest/out/0000.txt
みたいなところに保存しています。ビジュアライザでこれを読み込んで seed 値を変えた時に自動で表示するようにします。
index.html
内の script タグ内の先頭にこういうのを書きます。
import output_0 from "../tools/versions/latest/out/0000.txt?raw"; import output_1 from "../tools/versions/latest/out/0001.txt?raw"; import output_2 from "../tools/versions/latest/out/0002.txt?raw"; import output_3 from "../tools/versions/latest/out/0003.txt?raw"; ...
すると、それぞれの txt ファイル内のテキストが output_**
という変数に格納されます。これを表示したい seed 分列挙します。えっ!?... 本来なら出力ファイルを public
配下に置いて Ajax で都度取ってくるべきなんでしょうが、1 分でも多く解法考えることに時間を使いたかったので今回はコレでいきました。vim のマクロなりを使えば 1000 シード分くらいでも一瞬で書けますね。
さて、index.html 内の js を読むと seed の値を変えた時には generate
という関数が実行されるようです。ここに先ほど import した出力をフィールドに差し込む処理を追加します。
function generate() {
const seed = document.getElementById("seed").value;
var D = 0;
if (document.getElementById("fix_D").checked) {
document.getElementById("D").disabled = false;
D = document.getElementById("D").value;
} else {
document.getElementById("D").disabled = true;
}
const input = gen(seed, D);
document.getElementById("input").value = input;
+ document.getElementById("output").value = eval("output_" + seed);
updateOutput();
}
さてどうかな?
ハイ、動きました。おつかれさま!