電卓の成長を体験できるクソアプリ

[クソアプリ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/kuso-app) 1日目の記事です。

# 前置き
おはようございます。DE-TEIUです。
クソアプリを開発しないと年を越せない体になってしまったので今年もやっていきます。


## 過去にアドベントカレンダー用に作ったクソアプリ
- [p5.jsで作ったダメなソリティア](https://qiita.com/de_teiu_tkg/items/c938fbb52218185659e7)
- [絶対に作業できない作業用BGMサイト](https://qiita.com/de_teiu_tkg/items/6ebcef3550507258edaf)
- [社会に一石を投じるクソアプリ開発](https://qiita.com/de_teiu_tkg/items/e82870eca1f265807dbe)
- [鼻毛が生えるカメラアプリ](https://qiita.com/de_teiu_tkg/items/213aa2ade2ef840a33b5)
- [映画館のスクリーンでYouTubeが見られるクソアプリ](https://qiita.com/de_teiu_tkg/items/94259a0f90d1db861237)

# 成果物

誰しも人生の中で一度は電卓に触れる機会があったと思います。
しかし、実は皆様の知る電卓というのは、既にレベルが最大まで上がって完成されているものだったのです。
というわけで、今回は電卓が成長していく過程を体験できるWebアプリを開発しました。
適当にボタンを押したり計算したりすると経験値が溜まって電卓のレベルが上がっていきます。

[電卓育成シミュレーター](https://growing-calculator.vercel.app/)
![電卓.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173272/3d80338e-dd43-2df0-97df-3259695a4812.png)


# 電卓のレベルが
上がったと思います。最大レベルは15です。

# 解説
以下、今回使用したフレームワークとライブラリの紹介です。

- [Svelte](#svelte)
- [bignumber.js](#bignumberjs)

##Svelte
Svelteとは、ReactやVueのようなJavaScriptフレームワークの一種です。スヴェルトと読むそうです。より少ないコード量で実装できることを売りにしており、かなり直感的に書けるように設計されています。

###サンプル

例えば、2つの入力欄に設定した値を合算する機能を実装すると以下のようになります。

```js:sample.svelte
<script>
  let val1 = 0;
  let val2 = 0;
</script>

<input type="number" bind:value={val1}>
<input type="number" bind:value={val2}>

<p>{val1 + val2}</p>
```

同じものをVueで実装するとこうなります。

```vue:sample.vue
<template>
  <div>
    <input type="number" v-model.number="val1">
    <input type="number" v-model.number="val2">
    <p>{{val1 + val2}}</p>
  </div>
</template>

<script>
  export default {
    data: function() {
      return {
        val1: 0,
        val2: 0,
      };
    }
  };
</script>
```

上記の2つのコードを比較すると、Svelteでは、バインドさせたい変数の宣言が、普通のJavaScriptと同じようにletやconstで書けるようになっています。

### Svelteフレームワーク
今回のアプリでは使用していませんが、ReactにおけるNext.jsや、VueにおけるNuxt.jsのように、Svelteにも本格的なWebアプリを開発するための機能が色々と追加された、[SvelteKit](https://kit.svelte.dev/)というフレームワークが存在します。Svelteには元々[Sapper](https://sapper.svelte.dev/)というフレームワークが存在していたのですが、現在はこれの開発を中断され、SvelteKitの開発が進められています。
2021/12/01時点ではまだSvelteKitはβ版であり、まだNext.jsやNuxt.jsよりは機能やドキュメントが少なかったりするので、作りたいシステムの要件によっては採用が難しいかもしれません。ただ通常のSvelteと同様に、SvelteKitもかなりシンプルな書き方で実装できるようになっているため、個人で小規模なWebアプリを作るぐらいなら問題なく使えるかと思います。

##bignumber.js
JavaScriptでは、数値計算(特に小数を含んだもの)の際、しばしば誤差が発生します。
例：
![スクリーンショット 2021-11-28 204513.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173272/27ce6d5f-ec3b-3d42-8fbe-955ebc07ecdf.png)

JavaScriptの浮動小数点数は **IEEE754** という規格に則って実装されているため、この規格について調べると更に詳しい情報が得られるかと思います。今回の記事では割愛します。

この誤差の発生を防ぐような計算処理を自前で実装するのは大変なので、今回は[bignumber.js](https://mikemcl.github.io/bignumber.js/)というライブラリを使用しました。
なんとなくJavaのBigDecimal型っぽい使い方ができますね。

### インストール

```console
$ npm install bignumber.js
```

### 使い方例
```javascript
import { BigNumber } from "bignumber.js";

const num = new BigNumber(0.1);
// 加算
const val1 = num.plus(0.2);
// 減算
const val2 = num.minus(0.2);
// 乗算
const val3 = num.multipliedBy(0.2);
//除算
const val4 = num.dividedBy(0.2);

// 計算結果を文字列化して出力
console.log(val1.toString(), val2.toString(), val3.toString(), val4.toString());

// カンマ区切りで出力
const val5 = new BigNumber(1000000);
console.log(val5.toFormat());
```

### 出力例
```
0.3 -0.1 0.02 0.5
1,000,000
```
他にも、大小比較や、小数の丸め処理の設定ができたりします。詳しくはAPI参照。


# まとめ
普通に完成された電卓を使った方が良いですね。

# 参考
- [Svelte • Cybernetically enhanced web apps](https://svelte.dev/)
- [bignumber.js API](https://mikemcl.github.io/bignumber.js/)
- [JavaScriptで小数点の誤差が発生する件の備忘録 - Qiita](https://qiita.com/Chinats/items/e2647ca7900dfe7835a8)
- [WEB+DB PRESS Vol.122](https://gihyo.jp/magazine/wdpress/archive/2021/vol122)