前回に続き, 電卓アプリ(昭和な電卓のシミュレータ)を対象として, ウェブアプリ開発を漸進的に実施してみよう.
今回は,加算式電卓(前回の宿題)を元に, 逐次四則演算機能を追加実装し, 基本的な実務電卓(business calculator)として完成させよう.
$ cd ap/calc
$ firefox 〇〇.html &
$ gedit 〇〇 &
calc.htmlおよびreg.htmlからacc.htmlへの統合・改変の例: (あくまでも例.他の書き方もあり得る.)
... <h1>加算式電卓</h1> ... // HTMLコンテンツについてはcalc.htmlを元にして適切に変更... <script id="VIEW"> // VIEW部には変更なし ... </script> <script id="REGISTER"> // reg.htmlからREGISTER部をすべて流用 class REGISTER { ... } </script> <script id="MODEL"> let stts = 'res'; let buf = '0'; const dat = new Register('データレジスタ', 4); // データレジスタの準備 const acc = new Register('アキュムレータ', 6); // アキュムレータの準備 function show(reg) { // 引数としてレジスタを追加 if (reg.err) { // そのレジスタがエラーなら電卓全体もエラー状態に stts = 'err'; disp('Error'); } else if (stts == 'err') { // 電卓全体がエラー状態の場合 disp('Error'); } else { disp(reg.str()); // レジスタ内容を表示 } } function set(k) { buf = k; // バッファに書込 dat.read(buf); // データレジスタにバッファを書込 } function upd(k) { buf += k; // バッファに追加 dat.read(buf); // データレジスタにバッファを追加 } function exec(k) { acc.add(dat); // アキュムレータにデータレジスタの数値を加算 // acc.load(acc.val() + dat.val()); // or これでも同じ,むしろ他の演算への拡張性が出現 } function start() { stts = 'res'; // 開始時は結果表示中になるので... ... show(acc); // ...アキュムレータを表示 } </script> <script id="CONTROLLER"> function entNum(k) { // 数字入力中には... ... show(dat); // ...データレジスタを表示 } function entExe(k) { // 計算したら結果表示中になるので... ... show(acc); // ...アキュムレータを表示 } start(); </script> ...
以上の変更で加算式電卓として, 一般ピープル向けの通常の利用方法に対する動作は完全となった. 数字入力→「=」キーの反復によって,加算を正しく重ねてゆける.
しかし,通常とは異なる利用方法... 数字入力せず「=」キー連打した場合の挙動 (状態遷移res→resのアクション)について, これで良いのだろうか?
計算関数exec() の設計思想として, 次の3通りの考え方があるだろう:
妥当性・利便性について各自で熟考し, 計算関数exec() の定義内容を変更しよう. そして,今後の開発過程でも同じ考え方を貫くこと!! (あるいは,動作モードの切替機能を追加実装しても良いだろう.)
どちらにせよ,柔軟性を考慮すれば, 関数exec() の定義を次のように変更しておくべきだろう:
function exec(k, reg) { acc.add(reg); // アキュムレータにレジスタdatまたはaccの数値を加算 // acc.load(acc.val() + reg.val()); // or これでも同じ,むしろ... }
加算式電卓acc.html を元に, 四則演算(二項演算子+−×÷の入力・計算)機能を追加実装し, 昭和な逐次演算式の実務電卓bc.html へ改変せよ.
const K = { gen(c, f, s, l) { return { 'class': c, 'func': f, 'str': s, 'label': l }; } ..., B(s, l) { return this.gen('symbol', 'entOp2', s, l); } // 二項演算子キー生成メソッド }; const keybd = [ [ K.N('7', '7'), ... , K.B('/', '÷') ], // 「÷」キー追加 ... // 他の演算子キーも同様に... ];
let op2 = '='; // 二項演算子 // 初期値は'='でも'+'でもOK // '='の場合:'123=' → = 123 = ... accに123を代入 // '+'の場合:'123=' → 0 + 123 = ... 初期値ゼロのaccに123を加算
function exec(k, reg) { switch (op2) { // 直近の演算op2で切替,現在の入力kではない // '1+2='→op2='+',k='=' case '=': acc.load(reg.val()); break; // '=123=' case '+': acc.load(acc.val() + reg.val()); break; // '+123=' case '-': ... case '*': ... case '/': ... } op2 = k; // 現在の入力kを次回exec()時の演算op2に利用 }
function entOp2(k) { switch (stts) { case 'err': break; case 'tmp': op2 = k; stts = 'tmp'; break; case 'res': op2 = k; stts = 'tmp'; break; case 'num': exec(k, dat); stts = 'tmp'; break; } show(acc); }
余裕があれば,bc.html に市販の電卓によくある便利機能を追加せよ.
開発した実務電卓アプリを提出せよ.
担当教員へレポートを送信せよ: