Electronを使ったPC向け将棋アプリ開発

# はじめに

2022 年 1 月から、趣味で PC 向けの将棋アプリを開発しました。その中で取り組んだことや学んだことについて簡単にまとめます。

# 作ったもの

[ShogiHome](https://sunfish-shogi.github.io/electron-shogi/)

# 背景

最近ではスマホやタブレットでも将棋の対局や研究ができるようになりましたが、本格的に将棋の勉強や研究をするには必ずしも十分ではなく、特に将棋 AI を動す上で PC の処理能力やカスタマイズ性は有用です。

2010 年あたりからオープンソースの将棋 AI が増えましたが、その多くは GUI や通信対局機能を備えておらず GUI のアプリケーションと組み合わせて使う必要があります。AI と GUI がやりとりするための [USI](http://shogidokoro2.stars.ne.jp/usi.html) という共通仕様があり、 USI に対応しているものどうしなら任意の GUI と AI を連携させることが可能です。

USI 対応の GUI は何種類か存在しており、かなり良く作り込まれたアプリケーションを無償で利用できます。しかし、将棋所や ShogiGUI、WhaleWatcher といった特に有力なソフトウェアはどれもソースコードが非公開で、将来の開発がほぼ一人のプログラマーに依存しているものばかりです。オープンソースのプロジェクトとしては [MyShogi](https://github.com/yaneurao/MyShogi) がありますが、しばらく前に開発が止まっています。

加えて、 macOS や Linux で利用できるソフトウェアが充実していないことや、2010 年以前のレガシーな UI デザインで作られているものが多いことを考えると、新しいものを作ることにある程度の意義があると思いました。しかし、将棋所や ShogiGUI が充分な機能を提供している中で、大きな労力をかけて開発することには疑問もありました。

そのようなことを考えながら数年が経過した 2022 年の 1 月、 MyShogi の開発者（やねうら王の開発者）によって [USIプロトコルの改良のためには新たな将棋用GUIが必要](https://yaneuraou.yaneu.com/2022/01/15/new-gui-for-shogi-is-needed-to-improve-the-usi-protocol/) という記事が投稿されました。加えて同時期に [将棋丸](https://github.com/shogimaru/shogimaru) が登場したことも刺激になり、中長期的に開発に取り組むことを決めました。

# 技術スタック

## 言語とフレームワーク

今回の開発には次に示す技術スタックを採用することにしました。

- Electron
- Vue.js (Vue 3)
- TypeScript

将棋界隈だと C++ や C# をメインで使う人が多いからなのか、 GUI の開発にもそういった言語とフレームワークを使うことが多い印象です。

一方で、筆者の職場で使われているツールには Electron や Vue.js、React、TypeScript などが採用されていました。筆者自身の業務はサーバーサイドの開発がメインであるものの、こういったフレームワークを活用してアプリケーションを開発したいモチベーションがありました。

Vue.js や Electron だけでなく React や Tauri も有力な選択肢で、何を選ぶかは判断の難しい所だと思います。選定当時にこの方面の十分な経験は無かったのと、あくまで趣味の開発なので慎重な検討はせず直感的に使いたいものを選びました。結果的に Tauri ではなく Electron を使ったことは、このプロジェクトにおいては良かったと思っています。  TypeScript と Rust の両方を書いたり Chromium 以外の動作確認までしていたら、開発体制的に厳しかったでしょう。

## 開発環境

開発には VSCode を使い、 Vue や TypeScript, ESLint, Prettier に関する最も標準的な拡張機能に加えて Vim と Copilot を入れています。 `.vscode/extensions.json` を書いてあるので、ソースコードを取得して VSCode を開けばすぐに同じ環境 (Vim と Copilot は除く) を作ることが可能です。

慣れない構成での開発だったこともあり、 Copilot はかなり助けになりました。著作権の心配があるので長いコードの提案をそのまま採用することはしませんが、提案される内容は色々なことに気づくきっかけになります。

開発を始めたときは [Vue CLI](https://cli.vuejs.org/) を使っていました。この分野のノウハウがなかった私にとって、標準的な構成でプロジェクトのテンプレートを作成できたことはとても助かりました。ただ、その少しあとに Vue CLI の開発が終了してしまったため Vite へ移行したのですが、バックグラウンドとレンダラーのそれぞれをビルドしなければならないことや、 ESM と CommonJS についての自分の理解が浅いことに起因して苦労することになりました。

# 誰のためのアプリか

利用者の優先順位は次のように考えています。

1. 自分自身
1. 将棋 AI 開発者
1. プロ、アマ強豪、奨励会員

利益を得ることを目的としないので、「観る将」と呼ばれるようなユーザーは意識しないことにしています。有償のサービスと同じ感覚で利用されて身勝手な要求や批評をされることは不本意です。モチベーションを保ちながら持続的に開発するために、筆者自身が使いたい機能、あるいは筆者が関わってきた将棋 AI の分野へ貢献する機能に重点を置いています。

# 設計

## メインプロセスとレンダラープロセス

Electron はメインプロセスで Node.js が動き、子プロセス (レンダラー) で Chromium を動かすことによって Web のフロントエンドをデスクトップアプリ化します。

ファイル I/O や HTTP 以外の通信、ウィンドウの制御などはメインプロセスの Node.js で実装し、 IPC (プロセス間通信) でレンダラーと連携します。

![architecture.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/6e455b28-7868-6afa-6ce2-e18322074a07.png)

アプリケーションの主要な実装はレンダラー側に置き、 Node.js でなければ実装できない部分だけをメインプロセスで実行するようにしました。

今回作成したアプリは他の Electron ベースのアプリと同様に Web アプリとしてビルドもできます。ただし、 Local Storage に設定を記憶する程度の簡単な実装を持っているだけで、メインプロセスに依存する機能のほとんどは利用できません。

## 描画

Vue.js を使うことによって、 Model の変化に対して明示的に再描画のコードを書かずに最新の状態を画面に反映します。ただし、 AI が出力する評価値や読み筋など極めて高い頻度で更新される情報は単純に再描画すると負荷が跳ね上がってしまうため、バッファーに一定時間ため込むんでからまとめて吐き出しています。

将棋の駒や盤、駒台は一つひとつが DOM 要素になっています。 Canvas を使うことも考えましたが、格子状に要素を配置するだけなので必要性が無いように思いました。

評価値の折れ線グラフには [Chart.js](https://www.chartjs.org/) を使用しており、ここでは Canvas が使われています。グラフの描画ライブラリは他にも色々ありますが、実績が十分にあって MIT License のものとなるとあまり選択肢は無い印象です。シンプルな折れ線グラフを描きたいだけなので、できれば自作した方がデータサイズやパフォーマンスは改善すると思います。

## データ表現

将棋の局面や棋譜などを扱う基礎部分は全て自作です。

棋譜は 1 手を 1 ノードとして双方向で参照を持たせています。配列で表現する方法も考えられますが、分岐を扱うのに苦労しそうなので使いませんでした。実際の指し手ではない特殊なノードを設け、棋譜の先頭または末尾に入れることができるようにしています。棋譜の先頭は必ず「開始」を意味するノードがあります。ヘッドがこのノードを指しているときは開始局面から 1 手も指していない状態に該当します。棋譜の末尾には任意で「投了」や「中断」などの終局状況を表すノードを入れることができます。

## 設定ファイル

アプリ設定や将棋エンジン設定など各種設定のJSONファイルの配置場所を Electron の `userData` (Windows なら `%USERPROFILE%\AppData\Roaming\electron-shogi` ) の直下にしました。しかし、これはあまり良くありませんでした。 `userData` 直下には Electron によってファイルやディレクトリがたくさん作られます。独自の設定ファイルをその中に混ぜて置いたため、ごちゃごちゃしてわかりづらくなってしまいました。下手な名前の付け方をすると後々ファイル名が衝突する恐れもあります。ディレクトリを 1 つ深くして他のファイルと明確に分けるべきでした。

また、これは筆者の英語力の問題ですが、 app_setting.json や analysis_setting.json などと単数形にしてしまいましたが、英語的には settings とすべきでした。

設定ファイルの中身ですが、特にアプリ設定はかなりの数の項目がフラットに並んでいます。あまり階層を深くするのも良くありませんが、 1 階層目はカテゴリで分けるべきだったかもしれません。

一度決めた設定ファイルの配置場所や構造は後から変えにくいので、丁寧に考えるべきだなと反省しました。

# UI/UX

## UI パーツと画面構成

PC 向けの将棋アプリはどれも 90 年代から大きく変わらないメニューバーやツールバーから各種機能を呼び出すものばかりです。近年ではタッチパネルの付いた PC も普及してきましたが、昔ながらのメニューバーやツールバーはタッチパネルで扱いやすいとは言えません。
そこで、主要なアクションを画面上の大き目のボタンで操作できるように画面を構成しました。

![スクリーンショット 2024-06-15 16.32.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/d214001d-6947-4c5d-06c7-6107ea9322f0.png)

将棋盤や棋譜、タブの大きさを自由に調整できるよう [splitpanes](https://github.com/antoniandre/splitpanes) を導入しました。一方で、それ以外のほとんどの UI コンポーネントはスタイルシートや制御ロジックを自作しています。ライブラリをあまり導入しなかったのは、勉強のためという意味もありますが、このアプリに合わせたパーツを一つひとつ作ることで全体的に統一感があり無駄のないレイアウトに仕上がったと思います。筆者は業務での GUI デザイン経験が少なく、また金銭的コストをかけずに作ったため有償製品と比べれば物足りない所はあるでしょうけれども、個人開発の無償アプリとしては比較的高い水準ではないかと思います。

## アイコン

ボタンやタブなどに使用しているアイコンには Google の [マテリアルアイコン](https://developers.google.com/fonts/docs/material_icons?hl=ja#what_are_material_icons) を使用しています。似たようなアイコン集は色々ありますが、特段のこだわりがあったわけではなく、どれを使っても大きな違いは無いかもしれません。

文字が無くアイコンだけの個所も一部ありますが、基本的には文字とセットで配置するようにしています。将棋に直接結びつくようなアイコンは見つかりませんでしたが、例えば「対局」であればゲームコントローラー、「検討」であればフラスコといった具合になんとなく関連を認識できるものを選びました。

アプリアイコンは Inkscape で自作しました。

## 画像素材

将棋駒の画像は色々と出回っているものがありますが、非常に制限の少ないライセンスで提供されているものは限られます。利用に制限があるようなものをデフォルトにはしたくありませんでした。

そこで駒の画像を自作することにしました。初めは所有している駒を撮影しようと思いましたが、駒の製作者（いわゆる駒師）から悪く思われる可能性もあると考えてやめて完全に一から作ることにしました。まずベースとなる画像を作るために筆ペンで文字を書き、それをカメラで撮影して JPEG で保存した後にエッジ検出ツールでベクター画像へ変換しました。

![スクリーンショット 2024-05-11 185516.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/026e9e57-747b-8678-f23c-da533a9bf8bf.png)

学校の授業以外で毛筆の勉強をしたことが無かったので、とてもそのまま使えるクオリティではありません。また、かなり無駄な頂点が検出されているので、 Inkscape で頂点を消したり曲線の傾きを調整して形を整えました。半月以上に渡り試行錯誤した結果、ド素人が作った割にはそれほど悪くないレベルに到達しました。

![スクリーンショット 2024-05-11 190611.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/705ce93c-f06b-4f2b-b725-38a582542d60.png)

本当はもう少し頑張りたかったのですが、これ以上時間を掛けるのはやめることにしました。もう少し整った感じの素材も欲しいので IPA ゴシックの画像も作成しアプリ設定で選べるようにしています。

盤の画像も用意しました。所有している一寸盤をカメラで撮影してからマス目の線を消していますが、 Microsoft Paint で近いピクセルの色を重ねただけなので、よく見ると消した跡がわかります。初めはその画像をデフォルトにしていたのですが、解像度が低く、また木目の無い駒画像との相性が良くなかったのでデフォルト動作を単色の塗りつぶしにしました。

現在では任意の画像素材を取り込めるように拡張してあるので、ユーザーはよりリッチな駒画像を使用することが可能です。

## カラーテーマ

ダークテーマを含めたいくつものカラーテーマを選べるようにしました。各テーマごとのカラーコードは CSS カスタムプロパティを使って次の要領で書いています。

```css
:root {
  --main-color: white;
  --main-bg-color: #5f8f5f;
  --shadow-color: rgba(0, 0, 0, 0.5);
  --tab-color: white;
  /* 中略 */
}

.cherry-blossom {
  --main-color: black;
  --main-bg-color: #efc4c4;
  --shadow-color: rgba(0, 0, 0, 0.5);
  --tab-color: white;
  /* 中略 */
}

.dark {
  --main-color: white;
  --main-bg-color: black;
  --shadow-color: rgba(0, 0, 0, 0.5);
  --tab-color: white;
  /* 中略 */
}
```

トップレベルに配置した div 要素に対して、例えば `class="dark"` を与えてやることでダークテーマに切り替えることが可能です。色も一つひとつ自分で調整しました。色に関する専門知識はあまり無かったので苦労しましたが、例えば「桜」のテーマを作る際は桜色のカラーコードを調べ、それを起点に [0to255](https://0to255.com/) で明度を調整して色を決定していきました。全体的に明度の差だけで表現して、何種類もの色を使わないことを意識しました。

# 品質管理

## テスト (Jest / Vitest)

初めは自動テストに Jest を使っていましたが、現在では Vitest へ移行しています。

GUI の全ての動作テストを自動化することは困難ですが、 Model と View が分離された状態を維持し、 Model の重要な部分がテストされるように意識しています。カバレッジレポートを [Codecov](https://app.codecov.io/gh/sunfish-shogi/electron-shogi) に出していますが、カバレッジの数値はあくまでも目安と考えています。

このアプリでは将棋 AI とのプロセス間通信や通信対局機能など外部と双方向でやりとりする機能が多く、しかも状態遷移が複雑です。そのため、テストコードを書くのにだいぶ苦労している印象があります。本当はもっと注意深く設計すれば、テストが書きやすくなるのかもしれません。

## Lint と整形 (ESLint / Prettier)

ESLint と Prettier を使って、ソースコードに対する各種ルールの適用をしています。

全体的にあまり厳しめのルールは入れていませんが、途中から `import/no-cycle` を追加しています。Go 言語であれば言語仕様で import の循環が認められていませんが、 TypeScript では許されます。しかし、実際に循環を作ってしまうと予期せぬ不具合を作りこみやすくなりますし、リファクタリングや大きい改修がしづらくなります。import サイクルを完全になくしたことで変更への耐性が上がり、一部の実装をシェアして usi-csa-bridge （後述）というコマンドラインツールを作ることもできました。

## 最新版と安定版

バージョンはメジャーとマイナー、パッチの 3 つで構成されたいわゆる SemVer と同じ書き方をしています。さらに最も新しいマイナーバージョンを最新版、一つ前のマイナーバージョンを安定板と呼び、その両方をメンテナンス対象としています。

![280512530-f6cac60d-677b-4eb9-832a-ff270fe6cf92.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/7090f5c7-38ee-ca6c-43a0-225369b986b8.png)

個人開発の無償アプリでこんなメンテナンス方針を採用している事例は見たことがありません。正直なところ、安定板と最新版をメンテナンスしながら次のバージョンの開発をするのは相当に大変です。一般的な将棋ファンのために無償でこんなことをしているわけではありません。世界コンピューター将棋選手権や電竜戦などの重要な対局で採用されることを念頭に置いた対応です。リリースしてから概ね 4 か月から半年程度はメンテナンス対象となり、十分な回数のテスト対局を実施できるようにしています。

## リリース前の動作確認

既存の機能の動作はできるだけ自動テストで品質を保ちたいところですが、 GUI の振る舞いに関しては難しいところがあります。そこで、新しいマイナーバージョンをリリースする際は全体的な動作確認作業を実施しています。

v1.9.0 までは同じ機能でもメニューバーやボタン、ホットキーなど操作方法ごとに項目を書き出して動作確認シートを作っていました。

![スクリーンショット 2024-05-11 163105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/1e23e2fb-70d2-29cc-6ffb-34875a654171.png)

毎回すべての項目を消化するわけではなく、直近数回のアップデートの間にどの程度テストされているかを見ながら実施する項目を選んでいました。しかし、機能が増えるにつれて項目が多くなり、週末の半日程度で終えるには厳しくなってきました。

そこで、細かい操作ではなく機能を列挙した表を作り、具体的にどのような操作を試すかは書かないことにしました。

![スクリーンショット 2024-05-11 163134.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/d3210bea-f49e-800a-c8ec-70a0b10d3cb6.png)

実際のところ、リリース前の動作確認で気づく問題というのはそれほど多くもなく、見つかったとしてもその大半はそのバージョンで追加された新機能に関するものです。このシートに書かれた項目の消化状況はあくまでも目安であり、実際には日ごろから重要な機能を何度も触っています。

## セキュリティ

Electron を使う場合にレンダラーで読み込んだリモートコンテンツの取り扱いには注意が必要です。ただし、今回作成したアプリでは一切のリモートコンテンツを読み込まないので相対的に安全だと言えます。

Electron では読み込もうとしているコンテンツの URL をチェックすることができるので、一切のリモートへのアクセスは禁止するように実装しました。これによってレンダラー側で使用しているライブラリに悪意のあるコードが仕込まれても、できることはある程度制限されると考えられます。もちろん、 Node.js 側で使っているライブラリに関してはその限りではありません。

その他、 [Electron のセキュリティ推奨事項](https://www.electronjs.org/ja/docs/latest/tutorial/security) には概ねしたがって実装をしています。 Electron を使用したアプリケーションの中には、セキュリティ関連のコンフィグレーションが緩い状態でリモートのコンテンツにアクセスするようなものも見たことがありますが、そういったものは使うのを控えた方が良いかもしれません。

使用するライブラリは慎重に選んでいます。 NPM のレジストリでマルウェアが混入しているようなものに遭遇することはなかなか無いとは思いますが、その可能性もゼロではありませんし、その他の品質面で困ることがあるかもしれません。まず簡単に自作できるようなものは基本的に使わず、 NPM のダウンロード数やメンテナンス状況、データサイズなどを見ながら選ぶようにしています。場合によっては具体的な実装の中身を確認しています。

リリース前には VirusTotal に GitHub Release のアタッチメントの URL を入れて検査しています。これは、マルウェアが検知されることを期待しているというよりは、形式的にやっている面が強いと言えます。以前、将棋所の掲示板には、マルウェアとして検知されたという趣旨のクレームが投稿されています。そういったリテラシーの低いユーザーにからまれた場合の対策にはなると思います。

# 公開

## ライセンス

このアプリ自体のライセンスは MIT にしました。

package.json の dependencies に含まれるライブラリのライセンスは [license-checker](https://www.npmjs.com/package/license-checker) で抽出し、 [一覧表](https://sunfish-shogi.github.io/electron-shogi/third-party-licenses.html) を自動生成しています。また Electron や Chromium に関しては electron-builder でパッケージングしたときにライセンスファイルがバンドルされているようです。

## ビルドと GitHub Release

GitHub Actions を使ってテストや Lint チェック、ビルドをしています。

GitHub Release をパブリッシュすると GitHub Actions が Windows と macOS、Linux それぞれのビルドを終えるところまでは自動化されていますが、その成果物をダウンロードして GitHub Release のアタッチメントにアップロードする作業は手動でやっています。本来、 GitHub Actions から GitHub Release へ成果物をアップロードするのは簡単にできます。しかし世間ではここ数年の間に CI 関連のセキュリティインシデントが相次ぎました。そういった背景もあったので GitHub Actions へはカバレッジのアップロード以外に書き込み系の権限を与えないことにしています。

## アップデート通知

せっかく安定板をメンテナンスしても、パッチアップデートの存在に気づいてもらえなければ意味がありません。Electron の機能でデスクトップ通知を出すことは簡単です。あとは起動時に何らかの形でアップデートの情報を取得すればよいのですが、初めは GitHub Release の API を使うことを考えました。しかし、 GitHub Release 自体に最新版と安定板を区別する仕組みは無いことや、反映タイミングを Git で管理したいことから GitHub Pages で JSON ファイルを配置することにしました。実際の例としては以下のような JSON を用意しており、起動時に取得して自身のバージョンと比較します。

```
{
 "stable": {
  "version": "1.13.6",
  "tag": "v1.13.6",
  "link": "https://github.com/sunfish-shogi/electron-shogi/releases/tag/v1.13.6"
 },
 "latest": {
  "version": "1.14.0",
  "tag": "v1.14.0",
  "link": "https://github.com/sunfish-shogi/electron-shogi/releases/tag/v1.14.0"
 }
}
```

ただし、最後にチェックしてから一定時間は実行しないように抑制されます。また、前回確認したときのバージョンもローカルに記録しておき、最新版を追いかけているユーザーか安定板を好むユーザーかを区別し、どちらのアップデートを通知するか判断しています。

## リリースサイクル

開発開始から約 4 か月で v1.0.0 をリリースし、概ね 2 から 3 か月ごとに新しいマイナーバージョンを出しました。

![スクリーンショット 2024-05-11 172849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/f9ce14d2-6d09-852d-17d6-facd1151d430.png)

リリースの間隔や一回に入れる変更量について明確な決め事はありません。ただ、安定板と最新版の差分が多くなるとパッチを提供する手間も増えるので、一回の変更量はある程度おさえるようにしています。

## 問い合わせフォームと GitHub Issue

GitHub のユーザーであれば Issue で不具合報告をしてくれます。しかし、アプリを使う人には GitHub アカウントを持たない人も少なくないはずで、むしろ多いかもしれません。そうすると他の連絡手段も用意する必要がありますが、掲示板を用意するとリテラシーの低いユーザーが色々なことを書き始めます。メッセージを書く行為に適度な敷居があり、他のユーザーのやりとりを見ることはできない方が良いと考えました。そこで [formrun](https://form.run/home) を使ってフォームを作成しました。無料プランだとできることに限りがありますが、このアプリ一つであれば十分です。カテゴリ選択を設置して不具合報告か翻訳協力かを選ばせることで、機能要望や意見を書こうとするユーザーを排除しています。

GitHub Issue に関しては一定程度のリテラシーのある開発者が書くことを想定して、初めはテンプレートを用意していませんでした。しかし、その想定はあまり正しくありませんでした。私が運用している他のリポジトリだと、そのソフトウェアを使う人の技術レベルが高い傾向にあるのですが、 GUI の将棋アプリとなるとそうでもないようです。最終的にはガチガチにテンプレートを作り、運用方針に関する文書に合意するようにチェックリストも配置しました。また、 `blank_issues_enabled: false` を設定してテンプレート無しでの　Issue 作成は禁止しています。

## ドキュメント

コンセプトやビルド方法などの最も重要な情報は README へ直接書いています。

その他の文書は GitHub Wiki で作成しました。しかし、それに際して一つだけ想定外のことがありました。

それは Google にインデクスされないことです。どうやら GitHub のスターが 500 を超えるまで GitHub Wiki の情報はインデクスの対象にならないようです。余計な問い合わせが発生する原因になるのでできれば Google 検索で出てほしい所です。

ちなみに、GitHub Wiki ではドキュメントのタイトルがそのまま URL に含まれます。そのため新しいドキュメントを書くときは後で変える必要のないようなタイトルを書くよう気を付けています。英語のタイトルならば URL を見たときにわかりやすいのでしょうけれど、日本語だと URL エンコードがかかってしまえば意味を成さないので [esa.io](https://esa.io/) のように自動採番した数値の方が嬉しい気もします。

# ライブラリと CLI ツールの製作

## コアドメインのライブラリ化

将棋のルールや棋譜に関する基本的な実装は、ある程度整ったところで [NPM パッケージとして公開](https://www.npmjs.com/package/tsshogi) しました。 

NPM へ公開するのはこれが初めてでしたが、アカウントの作成や公開作業自体は簡単でした。しかし、自身のアプリではバックグラウンド側が CommonJS、レンダラー側が ESM になっており、両方で使える状態を作ることに手間取りました。最終的に `dist/cjs` と `dist/esm` という 2 つのディレクトリにそれぞれ出力し package.json へそれぞれのエントリーポイントのパスを書くことで、アプリ本体へ npm-install してビルドできるようになりました。

わざわざ NPM のアカウントを作らず、 GitHub Packages を使った方が GitHub で完結して良かったのかもしれません。ただ、検索で見つけにくいなどといったデメリットもあるので微妙なところだと思います。

## 通信対局クライアントのコマンドラインツール化

将棋 AI を通信対局に参加させることが目的の場合、必ずしも GUI が必要とは限りません。むしろコマンドラインで完結させたい場合もあるでしょう。実際に [電竜戦](https://denryu-sen.jp/) のハードウェア統一戦では GUI のツールを経由していないようです。電竜戦で使われていたものも含め、 CUI から USI と CSA プロトコルをつなぐツールは既に存在しています。しかし、積極的にメンテナンスされているとは言えない状況です。そういった観点では GUI で使われている実装と共通化されたものが望ましいと言えます。

そこで、 ShogiHome の USI や CSA プロトコルに関する実装部分を流用してコマンドラインツール [usi-csa-bridge](https://www.npmjs.com/package/usi-csa-bridge) を作りました。NPM でインストールできます。

次の図の GUI 版の構成要素のうち、赤で囲った要素を利用しています。

![usi-csa-bridge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/ef821e02-2566-cfbb-7863-fcf66d673fb4.png)

コマンドラインツールの場合は全てを Node.js の 1 つのプロセスで動かします。 Electron で Chromium を動かす場合と違って IPC は使いません。上図の IPC の周辺は実装を差し替えられるようにしてあり、コマンドラインツールのときには同一プロセス内で関数を呼び出し合う実装が注入されます。

# 使わなかったもの・やらなかったこと

## React

Vue.js と React のどちらが良かったのかは、判断の難しい所があるのと、自身の理解度が足りていない部分もあるので今も結論は出ていません。

初めは Vue.js におけるオブジェクトの変更検知の仕組みを十分に理解していなかったせいでパフォーマンスの問題を起こしたりもしましたが、十分に理解して使えばこのアプリにおいて性能面の大きな違いは生じないと思います。

現状では React の方が充実したエコシステムを活用できる環境にあるようですが、今回の開発では一般的な Web アプリで行われるような状態管理や通信が無いので、その辺りも大きな影響は無かったように思います。

## コードサイニングとアプリストア

Windows でも macOS でもアプリをインストールするときには、「不明な開発者によって作られた」という趣旨の警告が表示されます。

![スクリーンショット 2024-05-11 175607.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78005/960575b4-e192-bad7-0ed9-1621caaa8ad8.png)

この表示を出さないためには条件がいくつかあるようですが、重要なのがコードサイニング、つまり電子署名です。証明書の取得には費用がそれなりにかかる上、個人開発者では審査が通りにくいという話も聞きます。

アプリストアに出せば、コードサイニングの費用は発生しません。しかし、それも多少の手間がかかりますし、評価やコメントを付けられるのが嫌なのでアプリストアには出さないことにしています。

あくまでも自分でビルドしても良いところを無償で手間を省いてあげているので、このあたりは仕方がないかなと思っています。

## 寄付の受け取り

今後どうするかは決めていませんが、お金を出すという人が居ても受け取らないことにしています。よほど大きな収入になるなら嬉しいのですが、 ShogiGUI でさえ寄付件数が多くはない（金額は非公開なのでわからない）ことを踏まえるとまとまった金額にはならないと思います。多少大き目の額を出してくれる人はいるかもしれませんが一時的なものです。

# おわりに

全体としてあまりまとまりの無い内容ですが、継続的に開発してきた将棋の GUI について書きました。

あくまでも趣味の開発でありビジネスには当てはめられないところも多いと思いますが、逆に趣味でこれだけの時間と労力をかけて開発する人もあまり居ないと思うので、面白い部分もあるのではないかと思って記事にしています。