関数電卓 RINPn(りんぷん) オンライン版の内部構造を解説

前回の記事 でお知らせした通り、フリーの高機能関数電卓ソフト「RINPn(りんぷん)」に、Web上でいつでもどこでも使える「オンライン版」が登場しました。

このRINPn オンライン版は、従来のダウンロード版と同様、オープンソースのソフトウェアです。なので、商用・非商用問わず、誰でも自由にソースコードを改造・流用できます(ライセンスはMITライセンスです)。

という事で今回は、前回の記事の続編として、RINPn オンライン版の基本構造(アーキテクチャ)と、ソースコードをちょろっと軽めに解説しておきましょう!

- 目次 -

まず起動してみる

RINPn オンライン版は本当にすぐに起動できるので、中身の説明に入る前に、まずは一旦起動して現物を見てみましょう。

それには以下の RINPn 公式サイトにアクセスし:

ページの以下の所にある「オンライン版を起動」ボタンを押すと起動します:

RINPn 公式サイトのスクリーンショット

画面デザインは以下のような具合で、「INPUT」欄に計算式を入力して「=」ボタンを押すと、計算が実行されます:

RINPnオンライン版の画面

どうでしょう? 無事動いたでしょうか?

ものすごく古いブラウザとかだと、動かなかったりレイアウトが崩れるかもしれません。 また、スマートフォンも機種・世代などによっては同様です。 今この場では、なるべく新しめのPCでお試しください。

RINPn オンライン版の基本構造

それでは、RINPn オンライン版の内部の話に入っていきましょう。

以下のGitHubリポジトリ上でソースコードを読めるので、適時併せてご参照ください。本文中でも所々でリンクを張ります。

全体の基本構造

まずはじめに、RINPn オンライン版の基本構造はめちゃくちゃシンプルです。

ダウンロード版(デスクトップ版)の方の RINPn は結構大がかりなんですが、オンライン版の方は、前回記事でも述べた通り、機能がかなり削減されています。

ダウンロード版と同等の機能量が必要な場面では、普通にダウンロード版を使えばいいわけなので、オンライン版はむしろ逆に、「今すぐちょっとした計算をしたい」といった即席利用時の手軽さに的を絞っている感じです。

なので基本構造は、

の合計3枚のみです。なお、TypeScriptのコード2枚は、ビルドされて1枚のJavaScriptコード「rinpn-online-bundled.js」になります。

以上の基本構造を図にすると、以下のようなイメージですかね?

それでは、ソースコードの3枚(ビルドで生成されるJavaScriptコードを除く)を、それぞれを詳しく見ていきましょう。

画面役のHTMLファイル: index.html

まずは一番表側、画面用のHTMLファイルです:

» コード全体を見る

わりかし何の変哲もないHTML+CSSのコードで、ボタンが大量に並んでいるだけです。

一応は表示機器の画面サイズに応じて、電卓のサイズも変化するようになっています。1枚のHTMLファイルだけでPCもスマホもカバーするためで、いわゆるレスポンシブデザインというやつですね。

具体的には、CSSのメディアクエリ( @media (...) {...} の所 )を使って body 領域のサイズを変えて、それにフィットするように、ボタンを載せたパネル類も伸縮するような構造になっています。

ただ、スマホって画面サイズのパターンが多種多様で、OSやブラウザやバージョンも多種多様なので、モノによっては普通に崩れたり使い辛いレイアウトになったりは(まだ)すると思います。フリーで即席仕立てなので、そのあたりは現状ではもう仕方ないと割り切っています。運用しながら熟成させます。

式の計算処理を担うTypeScriptライブラリ: exevalator.ts

今度は逆に、最も深い層である「式の計算処理」です。これは「exevalator.ts」というTypeScriptコードのファイルが担っています:

» コード全体を見る

この「exevalator.ts」は、RINPn同様にうちで作って公開している、フリーの式計算ライブラリ「Exevalator」のTypeScript実装版です。

うちでは言語処理系の類を色々と作っているのですが、その中でもExevalatorは、式の計算のみに焦点を絞ったコンパクトなライブラリです。 コンパクトなので多言語移植が可能で、現時点で Java / Rust / C++ / C# / VB.NET / TypeScript の6言語に対応しています。その TypeScript 版を今回使っているわけですね。

» 詳しくは Exevalator の公式サイトへ

Exevalatorの使い方はかなり簡単です。ちょうどすぐ後で解説する、今回の rinpn-online.ts の処理が、Exevalator の使い方のいい例にもなると思います。

なお、今回の本筋からは外れるため割愛しますが、Exevalator もオープンソースで、その内部構造や処理フローの解説記事もあります。興味をお持ちの方は、下記記事をどうぞ:

ただ、上記記事の内容は若干マニアックです。軽めの内容ですが、ある程度は言語処理系の話とかに興味がないと、読むのはきつい記事かもしれません(いま振り返って読んでみると)。

中心役のTypeScriptコード: rinpn-online.ts

さて、最後に中心役となる rinpn-online.ts です:

» コード全体を見る

このコードが行っている主要な処理は、以下の3つです:

これだけです。中心役といっても、実質やっている事は「 画面と Exevalator との仲介」みたいなもので、地味ですね。

一応参考までに、計算実行時の処理フローだけ、詳しく追っておきましょう:

1. まずユーザーが「=」ボタンを押す
2. 「=」ボタンのイベントハンドラ(300行目付近)が発動する:

calculationButton.addEventListener("click", () => {
    calculate();
});
3. 上記処理によって calculate() 関数が実行される
4. その中で Exevalator がインスタンス化され、変数・関数登録などの設定が行われる:

function calculate() {
    ...

    // Exevalator をインスタンス化
    let exevalator: Exevalator = new Exevalator();

    // 式の中で使う関数を登録: sin(x), cos(x), tan(x), etc.
    exevalator.connectFunction("sin", new SinFunction());
    exevalator.connectFunction("cos", new CosFunction());
    ...

    // 式の中で使う変数を登録: PI
    exevalator.declareVariable("PI");
    exevalator.writeVariable("PI", Math.PI);
5. Exevalator の eval メソッドに式が渡され、計算が実行される:

    ...
    const result: number = exevalator.eval(expression);
6. 結果がフォーマットされ、OUTPUT欄に表示される:

    const formattedResult = formatResult(result);
    outputField.value = formattedResult;

このような具合です。

ソースコードをビルド・実行してみる

さてさて。

アーキテクチャ解説はこのあたりで完了ですが、せっかく内部構造が把握できた所で、実際にソースコードを入手してビルド・実行してみませんか?

git と Node.js さえ入っていればすぐできます。という事でやってみましょう!

1. ソースコードリポジトリをクローンする

cd 適当な場所
git clone https://github.com/RINEARN/rinpn-online.git
cd rinpn-online/Japanese      # 日本語版の実装ディレクトリ

2. 必要な環境を揃える

npm init      # ※リポジトリには "package.json" は含まれていない
npm install --save-dev typescript
npm install --save-dev @types/node
npm install --save-dev esbuild

3. TypeScriptコードをビルドして、1枚化したJavaScriptコードを生成

npx esbuild rinpn-online.ts --bundle --outfile=rinpn-online-bundled.js

これで「 rinpn-online-bundled.js 」が生成されるんですが、リポジトリ内にも元々含まれています。一旦消して、きちんと生成できる事を確認した方がいいかもしれません。

4. 起動する

起動するには、index.html をブラウザで開きます(普通にダブルクリックなどで)。するとブラウザ上に電卓画面が表示され、上記の「 rinpn-online-bundled.js 」が読み込まれて動作します。

改造する場合は...

改造する場合は、JavaScriptファイル(拡張子 .js)ではなく、TypeScriptファイル(拡張子 .ts)の方を編集してください。 編集後、上記手順「3.」のビルドを再び行えば、電卓の動作が更新されます。

今回の内容は以上です。
ぜひ気軽に改造・流用して、みなさんのオリジナル電卓を作ったりして遊んでみてくださいね!

RINPn に関する更新情報は、今後もこのコーナーにて随時お知らせしていきます。お楽しみに!