はじめに
飲み会や旅行で使える、ブラウザベースの割り勘計算ツールを作りました。
かんたん割り勘計算
最初は「合計金額を人数で割ればいいだけ」と思っていたのですが、実際に作ってみると意外と考えることがありました。
特に、
- 特定メンバーの金額固定
- 支払額に傾斜をつける
- 100円・500円・1,000円単位への丸め
- 丸めた後の差額調整
- 合計金額との整合性
- 計算結果の共有
あたりです。
今回はソースコードの公開ではなく、アプリの構成と実装時に考えたことを簡単に紹介します。
技術構成
今回のアプリは、ざっくり以下のような構成にしています。
Browser
│
│ HTTPS
▼
Frontend
│
├─ メンバー管理
├─ 金額入力
├─ 割り勘条件設定
└─ 計算結果表示
│
▼
Application Logic
│
├─ 固定金額処理
├─ 配分計算
├─ 丸め処理
└─ 差額調整
│
▼
Backend
│
├─ データ保存
└─ 共有URL管理
│
▼
Database
特別に巨大なシステムではありません。
むしろ今回意識したのは、
「小さなWebツールなので、できるだけシンプルな構成にする」
という点です。
処理の流れ
割り勘計算そのものは、概念的には以下の流れになります。
合計金額を入力
↓
メンバーを登録
↓
固定金額を設定
↓
固定金額を合計から除外
↓
残額を計算
↓
対象メンバーへ配分
↓
指定単位で丸める
↓
発生した差額を調整
↓
最終結果を確定
こうやって書くと単純なのですが、実際には最後の
「丸め」と「差額調整」
が少し厄介でした。
単純な割り算だけでは終わらない
例えば20,000円を6人で割ると、
20,000 ÷ 6
= 3,333.333...
になります。
当然0.333円は支払えないので、どこかで丸める必要があります。
さらに、
100円単位
500円単位
1,000円単位
などに丸められるようにすると、
各メンバーの支払額の合計
≠
実際の会計金額
となるケースが出てきます。
例えば単純に全員を3,300円にすると、
3,300 × 6 = 19,800円
200円足りません。
逆に3,400円なら、
3,400 × 6 = 20,400円
400円多くなります。
この差額をどう扱うかを考える必要があります。
固定金額という条件が入るとさらに面倒
例えば、
合計金額:20,000円
Aさん:5,000円(固定)
Bさん:4,000円(固定)
Cさん:自動
Dさん:自動
Eさん:自動
とします。
まず、
20,000
- 5,000
- 4,000
---------
= 11,000円
なので、残り11,000円をC〜Eさんに配分します。
ここまでは簡単です。
しかし、ここに
・傾斜をつける
・100円単位にする
・固定金額は変更しない
・最終合計は20,000円に合わせる
という条件が同時に入ってくると、単純な割り算だけでは処理できなくなります。
傾斜配分
もう一つ実装したかったのが、完全な均等割りではない割り勘です。
例えば会社の飲み会なら、
上司 多め
先輩 やや多め
若手 少なめ
というケースがあります。
内部的には各メンバーの条件をもとに配分額を決定しています。
概念としては、
残額
↓
各メンバーの条件を評価
↓
基準となる配分額を算出
↓
丸め
↓
差額計算
↓
再調整
という流れです。
このあたりは今回作ったアプリの肝でもあるので、具体的な配分アルゴリズムについては非公開にします。
一番悩んだのは「丸め後の差額」
個人的に一番面白かったのがここです。
例えば、
計算上の金額
A:3,428円
B:3,428円
C:3,429円
だったとして、100円単位に丸めるとします。
単純に、
Math.round()
的な処理をして終わり……
とはできません。
丸めた結果、
合計金額が変わる
可能性があるからです。
そのため、
① 元の配分を計算
② 指定単位に丸める
③ 丸め後の合計を計算
④ 本来の合計との差額を取得
⑤ 条件を崩さないよう差額を再配分
という考え方が必要になります。
実際にはもう少し条件がありますが、差額をどのメンバーにどう再配分するかについても今回の核心部分なので割愛します。
共有URLも作った
計算だけならブラウザ上で完結させることもできます。
ただ、実際の利用シーンを考えると、
幹事が計算
↓
参加者に送る
↓
各自が自分の支払額を確認
という流れになります。
そこで、計算した内容をURLで共有できるようにしました。
さらに、
編集用URL
閲覧用URL
を分けています。
幹事側では編集できるけれど、参加者には閲覧だけ許可する、という考え方です。
このあたりは単なる「割り勘計算機」ではなく、実際に使う場面を考えて追加しました。
作ってみて分かったこと
割り勘アプリというと、
金額 ÷ 人数
くらいで作れるように見えます。
自分も最初はそう思っていました。
ところが実際には、
入力
↓
固定金額
↓
傾斜配分
↓
丸め
↓
差額調整
↓
整合性チェック
↓
保存
↓
共有
まで考える必要がありました。
特に面白かったのは、
「人間ならなんとなく調整している処理を、どうやってロジックに落とすか」
というところです。
例えば人間なら、
200円余ったから、この人を200円増やそう
と簡単に判断できます。
しかしプログラムでは、
なぜその人なのか?
固定金額ではないか?
傾斜条件を壊さないか?
丸め単位に違反しないか?
合計金額は一致するか?
などを考えなければいけません。
小さなWebアプリですが、こういう部分は作っていて結構面白かったです。
まとめ
今回作ったのはこちらです。
かんたん割り勘計算
登録不要でブラウザから利用できます。
今回の記事では全体構成と考え方だけ紹介しました。
配分・丸め・差額調整などの具体的なアルゴリズムについては公開していませんが、
「単純そうな処理ほど、実際のユースケースを考えると意外と奥が深い」
というのが、作ってみて一番感じたところでした。