最近の雑記

色々と長い期間を掛けてやりたいことがたくさんでてきて記事を書かなかった。今日も夜ご飯を食べることができなかったし、多分ちゃんと疲れているのだと思う。


壺で2:40を取得した。もう数秒を詰めるだけで大変だな、という気持ちの他、例えばfunitureあたりはかなりマシな動きができるようになったので、つまり僕の進化はまだ止まらない。

Glitchless in 2m 40s 852ms by naari3 - Getting Over It With Bennett Foddy - speedrun.com

www.youtube.com


「極味や」というお店でハンバーグを食べた。本当においしかった。並び始めが11時15分くらい、店が始まったのが11時30分、中に入れたのは12時過ぎあたりだった。

形を整えられただけの赤いハンバーグが目の前に出され、これを熱くなっている鉄板の上で焼く形式。店員さんに触ってもよい、と指示されたタイミングではまだ表面のみが熱された状態なので、自分たちで切り分けて鉄板で赤みがなくなるまで追加で熱して食べる。肉の味が凄くしっかりしていて、岩塩と白米が一番合うタイプのハンバーグだった。

とんかつの話にも通じるが、これも家庭のハンバーグとはレギュレーションが全く違うもので、これこそ外食でないと食べられない味なのだろうと思った。調理過程が本当に知りたい。できれば家で食べたい。


Minecraftをやった。葉月味というヤロウがSkyblockをやりたいと言い出したのでサーバーを立てた。進捗は以下のツイートのツリーをどうぞ。

こんなにも狭い土地は、現在はある程度の広さまで拡充されており、複数のTTが立っていたり、目覚ましい発展を遂げたと言える。最初に50個の目標が用意されるのだが、未達成のものはあとひとつとなった。絶賛苦労中なので、もし全てが埋まったらこれについての別の記事が書きたい。

初期に参加してくれた方々が皆Minecraftに対して深い理解を示していたのもあってかなり勢いの良いスタートダッシュを成功させた形に思える。現状までに特段荒れたようなこともなく、参加者の民度が良くて本当にうれしい。


↑のサーバーの話。

今回はOracle Cloud Infrastructureの異常に強力なAlways free枠を使って建てた。身内で遊ぶ分には充分すぎるスペックを無料で提供してくれて、ありがとう。

コンポーネントの準備について。普通にたてるのはつまらないし、何よりメンテナビリティを大きく損なうので、ある程度気軽に、だがそれなりに便利な docker-compose.yml を作った。→skyblock-minnna。以下これを説明する。

まず、今Minecraftサーバーを建てるのであれば確実にコンテナとして立ち上げたくなるだろう、ということで itzg/minecraft-server をつかう。これは、itzgさん*1の作った異常に便利なコンテナイメージで、環境変数を与えることで無限の機能が働く。例えば、ワールドデータのダウンロードだとか、各種プロパティの設定、果てにはPaperやFabricのサーバーまで驚くほど簡単に建てることができる。docker-compose.yml を見てもらえばなんとなくわかると思う。

バックアップは次のコマンドで、リストアはその逆を行えば良い。愚直で嬉しい。やはりコンテナは便利。

docker run --rm -v skyblock-minnna_mcbig:/data -v $(pwd)/backup:/backup alpine tar cvf /backup/backup-$(TZ=JST+15 date '+%Y%m%d%H%M').tar /data

次に、Discord用のbotを作成した。今回はDiscordのサーバー上に人を集めてから運用する前提のため、運用を手助けするためのbotが必要になった。まずは許可された人だけがDiscordからコマンドを実行できる機能を実装した。ゲーム上で自分にopを渡す、でもよかったが、これを行うとスポーンチャンクあたりが保護されてしまう。これはたいへん煩わしい機能な上、初期状態があまりにも狭いこのSkyblockでは最悪何もできなくなる可能性があったため、なんとしても避ける必要があった。また、コマンドをサーバーのメンバーに見える範囲で実行することである種の透明性を持たせたかった。

あとはホワイトリストに人間を追加するために「メッセージに記載されたminecraft nameに :heart: のリアクションを付けることでホワイトリストに追加する機能」を実装した。これは言わずもがな便利でしょう。

docker-compose.yml に記載のあるように、Minecraftがrconを受け付けること、DiscordのBot用tokenを渡すことの2つができれば起動することができるはず。今後も使い倒してどんどん便利な機能をつけていくぞ。

実装の詳細はまた今度書きたい。Rustが楽しかった話とか。


仕事でJenkinsをお膳立てするための環境を作っていた↓どこかでちゃんと記事を書きたい。

Configuration as Code というプラグインによって、Jenkinsのコード管理を実現している。ただ、本当はコード管理が大前提のBetter Jenkinsを求めている。誰か助けてください。


いつもmineoを使っていたんだけど、昼間の回線が常に重いという問題を抱えていたので、試しにpovoに乗り換えてみた。ちょっと前までは「どうせ全く外に出ないのだし、今真面目に考えてもなあ」とか思っていたんだけど、

  • 結局急な外出時に毎回↑の問題に当たってストレスを抱えてしまうこと
  • povoは基本料金が0円であること
  • 知り合いがデュアルSIMの2本目として契約した話を聞いたこと

が重なって、ついに乗り換えてしまった。povoと自分の所有しているiPhone 12 Pro MAXはどちらもeSIMに対応している。eSIMは物理のカードのやりとりをすることなく通信が可能な形態で、契約後に発行されるコードをiPhoneの設定で入力するだけで通信可能な状態となる。これがかなり良い体験だった。物理カードのやりとりをしなくてもよい、というのはお互いにとって大きなメリットだと思う。全てがRDB上のレコードで解決される雰囲気があり、スピード感がかなり良かった。実際、最初に必要な会員登録のメールが届いてから、利用開始連絡のメールが届くまでに15分も掛かっていなかった。たったこれだけの時間でmineoからのMNP転入→実際の通信開始までたどり着くことができた。過去に何らかの通信キャリアとの契約体験をしたことのある人間にとっては驚くべきスピード感だと思う。

契約時、知り合いの紹介コードを入力したので今日は一日通信し放題とのことだった。なのでWi-Fiを切ってずっと4Gで通信させているが、通信速度は一日を通して概ね良好に見えた。明日以降はクーポンという形式で配布されているデータ容量を購入することで高速な通信が可能になるらしい。通話についても、相手に掛けるより先に「n分間通話し放題」のクーポンを買わなければ割高になってしまうらしい。とはいえ、上述の通り基本的には家から出るないのでその時に気をつけることができればきっと問題ない。

もしpovoも遅かったらどうしよう、とか思っていたけど、最近はMNP転出に料金が掛からない上に、途中解約金のような概念も存在しないことが多い。povoはどちらも満たしているので、その気になればいつでもahamoに乗り換えることができるのだ。より純粋にサービスの質で戦うことができてるっぽいし、いい時代になったと思う。

ちな僕のコード→ L32JV087

*1:おそらくhypixelで働いている

雑記 生活むずい/M3などでのリリース報告

最近ブログを書いていない。リングフィットアドベンチャーをやっているので体力がなくなっている、というのもあると思う。体力を付けて一日の活動時間を伸ばそう、という目的があったが、現状本末転倒な感じ。ある一定の体力を超えるまではこの差が産まれ続けるということだと思うので、もうちょっと頑張りたい。

締め切りに追われてDTMをやる必要があった時が一番色々あったなあ、とふと思い出した。多分なんだけど、単にやらなければならないことの逃避先として様々なことを探していたのではないか、と思っている。その結果の一例として壺の記録は2分46秒になったわけで、これはこれで嬉しかったが締め切りに追われる気持ち悪さとはずっと戦っていたので、まあどっこいどっこいでした。

現状見える僕のブログの更新数ピークはだいたい1月とか2月とかで、僕がよく見ていたブログが最も頻繁に更新されていた時期とも被っていて、そのモチベーションが一旦落ち着いた形となる。書きたいことはそれなりにあったんだけれど、最近単純に余裕がなくて細かなことに手が回っていない。例えば、いまご飯を食べるのがめんどくさく、それをサボってブログを書いている。美味しさのためのものではなく、普段の生活に必要な食事を取る、というのが結構な苦痛になってきている。というか食事についてだけじゃなくて寝ること以外ほぼ全ての「生活を回すために必要なこと」が全部面倒になっていて、ヤバい気がしている。なんだろう、仕事が忙しくなっているのだろうか?

ただ、外に出て遊ぶ、みたいなのはちゃんとできている。M3には行ったし、昨日と今日とお昼にイタリアンの店でピザを食べた。全部楽しかったので、単に普段の生活習慣が離れてきているんじゃないか?という気もしている。

こんな感じで体力を使うと、寝る時間がアホみたいに早くなる。最近のリズム的には20時くらいにはもう本就寝に入れるような眠さが襲ってくる。さっきの活動時間というのはこの寝るまでの時間を伸ばしたい、という意味合いが強い。なんか、頑張って起きていないといけないというのが自分の気合を大きく削いでいる気がしていて、これを早くどうにかしたい。外に出たら確実に睡眠バランスが崩れるのは本当に良くないので。もっとみんなと遊びたいぜ。


2022春M3について書いておく。本当にありがたいことに、poniyamaさんが新設されたレーベル Liminal Warp の「Anime sampling × Leftfield Bass Music」がテーマの新譜コンピ Nocturnal Edge に参加させていただいた。僕は not seeming!!((これはつまりシュールという意味です))) というトラックで参加した。スネアが大きめでベースが多少グニュっとしているトラックです。sine compress。実は一番最初、僕が企画の趣旨を勘違いし、ドナルドのサンプルで構成していた。その後軌道修正をし、とても良い形に仕上げて提出することができた。ドナルドの版は今度VIPバージョンとして上げたいですね。

soundcloud.com

liminalwarp.bandcamp.com

M3と同時タイミングでリリースされた荷鞍Recordsの3rdアルバム「# PARTY ALL-NIGHT」にも参加した。前回まではテーマがあった気がするけど今回はなかった。ただ、前回参加した時からずっとテーマを無視していたので、今回も同じく特に考えること無く自由に制作した。こちらでは caramell11111 という、ウッーウッーウマウマ(゚∀゚)をさらに早くして、hyperflip、dariacoreっぽくしたものを出した。人のdariacoreをかなり参考にしていて、トラックの展開の作り方をたくさん真似た。いつもの僕のトラックよりも手数が多いように感じられると思います。あとはキックスネアが「ドンドンタッッ」で構成されているのが凄く好きで、それをたくさん混ぜ込めたのが嬉しかった。

soundcloud.com

nigurarecords.bandcamp.com

両方とも本当にすごいコンピアルバムとなっているので是非どちらも聞いてください。お願いします。

まともにクラッシュダンプを読んだらAbleton Liveのクラッシュを止めることができた

ずっとSoundtoysのプラグインが原因だと思っていたAbleton Liveのクラッシュが、ちゃんと追ってみると実はそうではなかったという話。

割と前からTwitterで騒いでいたようにずっと困っていたんだけど、今回M3や荷鞍のための制作に対してちゃんと支障をきたしていたので真面目に調べてみた。

まず、Soundtoysがわるいという先入観を捨て、クラッシュ時に生成されるメモリダンプを確認する。

こんなファイル↓

見つけたらこれをWinDbg Previewに突っ込む。

ここにdmpファイルを入れる

そしたら 0:000> の横にある空欄に !analyze -v を入れてEnterを叩く。

すると、以下のような結果が得られる

このうち注目すべきは赤線を引いた箇所で、ここを見るとどういった例外がどこで起きているのかが分かる。今回の場合は MeldaProductionAudioPluginKernelV1164 って書いてありますね…………………アクセス違反を起こしている……freeした後に触っちゃったのだろうか………………

もしかすると、Soundtoysのプラグインが大きく目立っていたのはプラグインホストであるAbleton Liveが落ちたからであって、Ableton Liveを落とすと同時に大きく目立っていたわけではなかったのかもしれない。ずっと疑っててごめん。

で、実際にAbleton Liveがクラッシュしないようにする必要があるわけだけれど、まず最初に問題となっているプラグインのアップデートを試してみる。こういった問題がアップデートによって解決されることはけっこうある。MeldaProductionAudioPluginKernelV1164 というのはMeldaProductionのバンドルに入っているプラグインから共通で参照されるdllらしい。ということでバンドル自体をアップデートしたら、無事クラッシュが再現しなくなった。ずっと起動し続けていても落ちなくなった。めでたし。

詳細な再現手順を作成することはできなかったので、なにかの相性問題なのか、またはプラグイン自体にそういったバグがあるのか、詳細はわからなかった。が、定期的な更新がある限り、古いプラグインを使い続けていること自体が何らかの原因になることは確かにあるので、いつか必ずやってくる嫌な事象に当たりたくなければアップデートし続ける必要があるのだと思う。

その上で、やはり推測ではなく計測が大事だということもよくわかった。特に思い込みは怖いので、一度冷静になる必要があるのだろう。

秋葉原の「丸五」というとんかつ屋で特ロースカツをいただいた

僕は自分の作るとんかつが世界で一番好きで、それは下味の塩コショウが結構しっかりつけられているだけのふつうのとんかつなんだけど、たったそれだけの違いだけでそれ単体(ソースなし)でご飯がよく進む味になってくれる*1。これは実家から教えてもらったとんかつで、多分おふくろの味でもある。

そんな中、とある人々は「丸五のとんかつが一番うまい」と主張をし続けている。どちらもを真と捉えることはできず、どちらかが偽となってしまう。ならば、直接僕が出向いて決着をつけようじゃないか、ということで、4/3の昼食に丸五の特ロースカツを食べてきた。

あまり長い事書かないが、この試合はノーコンテストだと思う。両者のインターフェイスが全く違うため、試合の形式にならないのだ。

とんかつと聞いてあれを想像するのは難しいだろう。分厚いが柔らかく、脂分も甘い。用意されているソースは酸味が強いためおそらく肉自体の中和のために用意されているのだろうし、そんなとんかつに一番合う調味料は岩塩だった。とんかつ単体であんなに味を出してくれることがあるのだろうか?正直ステーキを食べているような気分にもなった。衣もいい感じにサクサクなのだ。セットのご飯/野菜/赤だし/漬物のバランスもかなりよかった。

正直、旨さ基準で言えば丸五に軍配が上がるのだが、それはとんかつの勝負ではない。レギュレーションが違うのだと解釈した。適当なとんかつ屋で食べたことのあるとんかつともまた全然違うので、恐らく丸五が特殊なのではないかと思っている。もし世間一般のとんかつ屋がこれなのであれば是非ともおしえてください。そしたら僕の作っているとんかつがフェイクであることが確定します。

f:id:naari_3:20220404053214j:plain
特ロースカツ + セット

f:id:naari_3:20220404053222j:plain
遠近法で太いように見えるが、実際に太いのだ

追加コンテンツ

了解!

*1:かなり大きく好みの問題だとは思う

Getting Over Itで3分切りを達成した

ついに昨日3分を切った。正直ここ最近で一番達成感のある瞬間だった。

youtu.be

長いところ大きな指標として「3分切り」を掲げていたのでそれが遂に達成された形になる。この指標については、srcのリーダーボード中1ページに収まる1000位以内、かつキリのいい数字が3分だったというのが大きい。3分切りをしてようやく750位なのだが、それを達成したのだ。僕のキリのいい記録は1ページ目に乗る。

以下ページが自分の記録になる。僕のルールへの解釈に勘違いがなければそのまま登録されるはずだ。

Glitchless in 2m 59s 963ms by naari3 - Getting Over It With Bennett Foddy - speedrun.com


6分切りまでは2018年か19年に達成していて、その後期間を空けて2022年初頭から急に壺のやる気を出し始めた形になる。知り合いがやる気を出しているのを見たら自分もやる気が出てきた、という構図で、タイムが似たような知り合いがちらほら居たのが最初の起爆剤になった。その後、知り合いと競争する事によるデメリットが結構大きいこと*1を知って、それ以降は地道に自分の可能性を探っていく作業を繰り返していた。このためにはモチベーションの設定がかなり重要になっていたのだと思うが、幸いなことにこのゲームは他のゲームと比べて格段に設定がしやすいものとなっている。あなたが初めて壺で1時間を切った時、おそらく「多分30分切りならいけるだろうな」と思うことが予想されるが、その具合は少なくとも5分切りまでは続く。これは「操作の極端な特殊さ」と「ステージ理解」の両方がそれぞれの軸で埋められていくからだと思っている。最初あまりにも難しかった部分、特に前者は本当にやるだけで慣れていくのだ。技術上昇中に特定の記録を達成するのだから、「大きなミスがあってこのタイムなら、N分切りは達成できる」という考えに至るだろうし、このロジックは結構長いこと続いていく。僕の場合は3:30切りのタイミングまで続いていた。

これ以降については自分の動きを見直す必要が出てきた。例えば細かいテクニック習得や安定のためのルート実現などを目指すなど。アイデアは自分から生んだものはあまり無く、基本的には人の走りを参考にした。暗中模索より、既に作られた道を進むのが容易である。ただ、あまりにも早い人の走りは全くと言っていいほど参考にならなかった。ゲームの性質上、壺の位置/その時の慣性の方向/ハンマーの振り方の3つが揃わないと敵わない動きがたくさんあるのだが、上位勢たちはこれを高度な動きの固定化によって実現しており、それによって現段階の自分では実質的に不可能なことが多い。そのため、あまり力量の離れていない方のプレイを見て勉強する必要がある。これは現在1位のBlastboltさんも同じことを言っていて、以下の動画に詳しい。この件以外にも良いことをたくさん言っているので、好タイムを目指す方は一度くらいは見てもいいかもしれない。

www.youtube.com

f:id:naari_3:20220404040648p:plain
具体的にどの走りを参考にすべきか?の指標 https://imgur.com/NQ2dUvF


上述の通り、モチベ維持というのはとても大きな問題になってくるのだが、その大きな助けになってくれる存在として統計があると思っている。具体的にはRTAでよく使われるsplit timerのことを指している。

f:id:naari_3:20220404042225p:plain

この機能はゲーム内をある程度の区間ごとに区切っておき、そこに達するまでの秒数や区間ごとの経過時間を記録しておいてくれるものになる。これによって細かい変化が分かるようになるのが本当に嬉しい。「この区間は駄目だったが、この区間はすごぶるよかったぞ」「この区間は過去最高の記録だったぞ」等が視覚化されるのだ。僕はこういった細かい変化に一喜一憂することはモチベーションに対してとても有効だと思っている。これが無い状態と比較すると明らかで、主観的でぼんやりとした「このあたりは前よりもちょっと早くなったような気がするな~」では自分自身も納得させられないのだ。これについては「ウメハラも言っていた」と id:kaikityou さんが言っていたので間違い無いと思う*2


といった具合で、僕は自分との戦いを続けており、その過程として3分切りを達成することができた。この後はBlastboltが言うように少しずつ目指す点を変えていきたいと思っている。最終目標は2分切りかなあ、これができたらもう良くなる気がする。


ちなみに昨日紹介したBINITはrejectされてた。めでたし。

Glitchless in 1m 00s 000ms by c7v2c7v2 - Getting Over It With Bennett Foddy - speedrun.com

*1:心象が良くなくなる

*2:ウメハラが実際になんて言っていたのかは知らんが

なんかいろいろあった Reactライブラリ作成/年ぶりの音MAD投稿/おつくるる/壺の陰謀

マックカフェというタイプのマクドナルドがあることは知っていたのだが、マックカフェで頼む普通のドリンクの氷もマックカフェ仕様になっていた。いつもの小さな箱型ではなく、大きめかつ透明で薄い氷だった。これによるメリットは溶けにくいので長い間美味しい状態でドリンクが楽しめる、ということだと思う。友人宅で雑にウーバーイーツ(マック)を頼んだらこれだったのでうれしかった。うちの近くもそうなってほしい。

<追記>

f:id:naari_3:20220403012223p:plain

神情報ありがとうございます。神。

</追記>


Reactで日本語のクロスワードを扱うことができる @naari3/react-crossword-ja を作成した/「最強無敵スーパーウルトラ神神神合作」のクロスワードのWeb実装をつくった - 名有りさんの日記 という記事を書いた。微熱さんとは全く関わりがなかった(ないよね?)のにnoteの記事内に名前を出していただいた。何故か僕が知らない所でそういう話で通っているということなので、これは凄いことだと思っている。でもWeb系といってもフロントをやっているわけではなく、今はSREという職種を全うしている最中である。最近っぽいフロントについての深めの知識はないので実は今回の対応はちょっと大変だった。でもやれることはやったるので何かあったらお声掛けください。なにかしますよ!


で、そういえば音MAD作者とかをやっていたなぁとか思っていたらすごく簡単な音声のみの音MADを作りたくなってきたので作った。尻の妖精と好きな曲をあわせたものになる。

これはむかーし作ってたプロジェクトファイルを掘り起こしたもので、メインみたいな声の部分だけ完成していたので昨日でそれ以外を埋めた感じ。まず既にかなり完成されている音声にサンプルを乗っける作業になるのだが、これはやはりかなり楽しかった。どれだけやってもベースが凄いので、ずっと凄いままなのだ。楽しくないわけがない。まあこういった楽しさはセリフ合わせだとかコンテキストをメインにする音MADでないから難しい部分がない、というのはあったかもしれないが。むしろ今回にいたっては凄い曲の構成を真面目に掘り下げていく必要があるタイプの音MADなので、楽しみながら勉強することができた。色々と得した気分になった。僕もMonophobeになるぞ……。

みなさん過去作ろうとして途中で力尽きたものっていくらでもあると思うんだけれど、まずはそれを掘り返すあたりからやってみようかなと思っている。まちカドまぞく2期も来てしまう……急がなきゃ……


くるる幼稚園の12周年記念特番を見た。

くるる幼稚園10&11&12周年記念特番☆*。 - 2022/04/02(土) 22:00開始 - ニコニコ生放送

くるる幼稚園10&11&12周年記念特番☆*。

おかげさまでくるる幼稚園は12周年を迎えることができました! 10,11周年はお祝することができなかったのでまとめて祝っちゃいます!!! 本当にありがとう!!!!

出演者(敬称略)

・くるる

【出演ゲスト】 ・かなた ・日南 ・さとうきび ・TEN ・バトラ ・もこう ・みかりん*

【衣装提供】 ・まこと

すごい。涙が出る。僕がむかーし見てた生主が、僕がむかーーーーし見てた生主とコラボし続けている…………………冗談抜きで涙が出る……………………僕はバトラのリスナーをよくやっていて、その次いでにてんてーを見ていたという感じなのだが、この枠だとこの2人の区間が一番面白かった。彼女ら彼らの輝きをまた見ることができてよかった。

こういう趣味全般って各人が勝手に昔の思い出としてしまう節がある。彼らは実は全然生きていて、勝手にこちらが愛想を尽かせただけなのだ。大人になるにつれて体力の減少だとか時間がなくなっていくだとか、どんどん情熱を捨てる言い訳が増えていく。ふと振り返った時、趣味から離れていて、「自分の中のこれに対する情熱ってこんなもんだったんだ」とがっかりするタイミングが来てしまう。ただそんなもんだったとしても別に良いと思っていて、そういう体験はきっと別のところで活きると思っている。と思うと、上述の「彼女ら彼らの輝きをまた見ることができた」というのは自分の体力が戻ってきたのか、この枠になにかの縁を感じたために一瞬でも戻ってくることができたというのは素晴らしいことだと思う。この枠に特別な何かを感じるのは過去のそういう体験から来るものなのだから、やはり意味はあった。とても嬉しい。おつくるる!


なんか、speedrun.com 上のGetting Over Itのリーダーボードの様子がやばい

f:id:naari_3:20220403002251p:plain
1位、1分ジャスト

2022/04/03時点魚拓

えっ!?!?blastboltじゃないの!?!?とか思ってたら、なんか様子がおかしい。

www.youtube.com

これがその走りとして登録されている動画なのだが、全然壺じゃない。なんだこれは。概要欄も相まって超怖いんだが。

どうやら向こうの国ではまだ4/1らしく?、エイプリルフール的なものなのかとは思っているんだが、にしてはこの投稿者はちょっと様子がおかしい。以下にフォーラムへのpost一覧を貼るのだが、陰謀的な話をし続けている。

曰く、壺の作者であるBennett Foddyは既に居らず、そのアカウントの秘匿情報はmodpack製作者で有名なanjo2、obama(これよく見るけどなんなんだ???)、goiの speedrun.com でのmodチームに共有されているということらしい。ある地点より以降は何年も前にBennettによって作成された機能を少しずつリリースしているだけ。また、TwitchやYouTubeで壺系の配信を主に精力的に活動するCodyummは実質的には存在せず (曰く "not real") 、というのもBennettを偽るチームによって話す言葉やメッセージなど全てが指示されているとのこと。このチームのことを binit と呼ぶ、とのこと。

なんだこれはたまげたなあという感想が出るのだが、もしエイプリルフールネタであるのならもう削除して然るべきだし、Verifyした人がBlastboltというのも何か変なものを感じる。もしかしてホンモノのリークなのか…?いやまあそんなことはないと思うのだけれど。ちょっと普通に怖い出来事なので文章で消費。


生活がやばくて、11時に起きたが19時に寝て、22時に起きた。明日は昼から秋葉原の丸五という店でとんかつをいただく予定。壊れつつあるのでどうにかしたいですね~

Reactで日本語のクロスワードを扱うことができる @naari3/react-crossword-ja を作成した/「最強無敵スーパーウルトラ神神神合作」のクロスワードのWeb実装をつくった

きっかけ

先日、最強無敵スーパーウルトラ神神神合作という音MAD合作が投稿された。

笑いや勢いが強いパートの多い音MAD合作で、個人的にとても好きなものだった。主催の微熱さんによってこの合作の制作進行についての記事が挙げられている。

note.com

こちらにも書いてあるが、この合作は告知としてクロスワードが使用された。先にTwitterに投稿されたものは一箇所ミスがあったようなので、今から解きたい人は上のnoteを参照してください。それで、記事内クロスワードの項目最後にこんなことが書かれていた。

15x21マスのクロスワードをWeb上で遊べるようなサイトや仕組みが見つからなかったのですが、Webプログラミングできる人なら簡単に作れそう。なありさーーーん?

そりゃもうやるしかないよね、ということで制作に着手した。完成品は以下からどうぞ。スマホ未対応です。

@jaredreisinger/react-crossword について

この時、一番最初にやったのはクロスワードのためのライブラリ探しだった。仕組みをイチから作るのはあまりにも非効率的なので、使い回せるものは使いまわしたい。それですぐに以下のライブラリを発見できた。

@jaredreisinger/react-crossword はReactの上に動くクロスワード用のライブラリ。以下のように答えのデータからクロスワードの盤面を自動生成してくれる。答えを入れてみると分かるが、文字を入力すると現在フォーカスをあてているカギの方向に応じて自動で次のマスに移動してくれたり、矢印キーでの移動やBackspaceキーでの文字削除などもできるのでなかなか体験が良い。実装としては、単一かつ見えないinput要素、svgで表現された盤面が存在する。盤面上のマスをクリックするとその位置にinput要素が移動し、文字を入力するとsvg側のtext要素に文字を埋めていくようなhooksが組まれている。

日本語の非対応ぶり

最初はこのライブラリで充分なんじゃないか?と思ったんだけど、しかし想像通りかつとても残念なことに、日本語入力に全く対応できていない状態だった。IMEのことを何も考えてられていない実装で、具体的には「りんご」という単語を入力する時、「RりりNりんGりんご」という入力に化けてしまう。これはIMEの「入力中かつ確定していない」ような状態の取り扱いを考えず、文字として認識できるタイミングで即時で扱うためにこうなってしまう。

@naari3/react-crossword-ja について

そのため、このライブラリをフォークして自分で色々用意することにした。

日本語入力を扱う

まず、ライブラリ名のsuffixとしてjaが付いていることが示すように、日本語の、しかもひらがなにのみ対応するようにした。上に挙げたIMEの件の他に、日本語圏のクロスワードは「っ」と「つ」を同一視するようなものがよく見当たるが、このようなルールを外から注入できるような仕組みを作るより別ライブラリに切り出したほうが嬉しそうだなと考えたため。スコープは狭いほうが良い。

その上で日本語特有っぽい文字入力の挙動について色々考えることにした。実装に至っては様々な罠を踏み抜いてしまい、本業がフロントエンドではない自分にはゼロベースで対応することになったため結構な苦労を要した。例えば、日本語入力中、未確定の状態だと文字キーとしてPROCESSが振ってくるだとか、compositionという状態の概念だとか、さらにブラウザ間の実装の差異による振る舞いの違いだったり、結構大変だった。最初はWordleの漢字バージョン「漢字ル」を作った - 詩と創作・思索のひろばmotemenさんがやっているように onsubmit で拾うような実装も考えたが、今回はひらがなのみが対象であり、英語版に見られるような入力が即時で反映されるような仕組みを生きたままにしたかったため、未変換状態の文字列をそのまま使うように対応した。

具体的には、input要素に入った文字列をstateとして保存した後、カーソル number 相当の添字を用意しておき、 文字列[カーソル] が指す文字がひらがなであったらその文字を入力確定として扱い、添字を +1 させる。これで入力中のアルファベットが拾われる問題に対処できた。inputの onComposionEnd という、日本語変換が完了した時に発火されるイベントにフックして上記の各stateをリセットさせるくらいのことしかやっていない。

inputを常に空にするとonCompositionEndが発火しない問題

最初はinput要素を隠すために以下のように実装していたのだが、これだと onCompositionEnd は発火しない。

<input value="" onCompositionEnd={() => console.log("fire!")} />

未確定/入力中の文字列は onChange などによって拾われるが、onCompositionEnd はinput要素内に未確定な文字列がある状態からでないと発火しない様子だった。

これがバグなのかはちょっとわからないが、対応としては入力中の文字列はきちんとvalueに格納するようにした上でstyleで文字列の透明度を100%にした。見えなければなんでもよい。

スマホ対応について

今回はパソコンのChromeから確認を行った。スマホ対応は時間が足りず行うことができなかったが、問題だけは把握している。スマホでの日本語入力のシナリオで「りんご」と入力することを考える時、「り」「ん」「こ」「Backspace」「ご」というキー入力が飛んでくる。このライブラリでのBackspaceの扱いが「現在のマスを削除しながら一つ前のマスに戻る」という挙動をするため、クロスワードのマスの終端にあたる場合に馬が合わなくなってしまう。スマホであれば以下から試せるが、「さが」のようになる。

対応としては今の入力方式がスマホの日本語入力であるか否かを判断し、そうであればBackspaceの挙動を変更したいのだけれど、どうすればそれが取れるかわからない。もし判断方法が見つからず、かつスマホも対応させたい場合はBackspaceの機能を落とすことでも解決できるとは思う。

おわり

といった具合でとりあえずパソコンから動く日本語対応のクロスワードライブラリを作成することができた。スマホ対応さえできればもうちょっとおもしろいサービスを展開できそうな気もするが、それはまた別の話ということで。