0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「割り勘」は奥が深い——5パターンの計算ロジックを持つ割り勘サイトを作った話

0
Posted at

はじめに

飲み会の幹事をやると必ずぶつかる問題がある。

▎ 「均等に割ると新人に重い」「上司が定額で出してくれる」「子供はタダにしたい」「幹事は少なくていいよ」

こういった"ちょっとイレギュラーな割り勘"を、その場でサクッと計算できるツールがほしくて https://warikan.keydrop.net を作った。

この記事では、割り勘の計算パターンを整理した思考プロセスと、静的サイトとして実装した技術的な判断を書く。


割り勘の5パターン

まず「世の中の割り勘シーン」を洗い出すところから始めた。

  1. 均等割り(基本)

1人あたり = 端数処理(合計 ÷ 人数)
差額 = 回収額 - 合計

一番シンプル。ただし端数処理の選択肢が意外と重要で、「切り上げ/切り捨て/四捨五入」×「100円単位/10円単位/1円単位」の組み合わせを用意した。

現実では「10円単位で切り上げ、端数は幹事が預かる」が多数派なので、デフォルトは 切り上げ・10円単位。

  1. 傾斜割り勘(グループ別倍率)

役職・年齢で支払い比率を変えるパターン。

基準単価 = 合計 ÷ Σ(グループ人数 × 倍率)
グループXの1人あたり = 端数処理(基準単価 × 倍率X)

ポイントは「基準単価」の導出。単純に均等割りした額に倍率をかけると合計が合わなくなるため、加重平均の逆算で基準単価を求める。

倍率の相場は「役職者1.3〜1.5倍、若手0.7〜0.8倍、新入社員0.5倍」あたりが現実的。

  1. 無料枠(N人タダ)

子供や特別ゲストを無料にするパターン。

支払い人数 = 総人数 - 無料人数
1人あたり = 端数処理(合計 ÷ 支払い人数)

シンプルだが、UI上で「総人数」と「無料人数」を別々に管理することが重要。「8人で来て子供2人タダ」を直感的に入力できるようにした。

  1. 幹事設定(無料 or 追加負担)

幹事の扱いには2パターンある。

  • 幹事は無料(予約・集金の労働に対する報酬)
  • 幹事が多めに払う(余裕がある場合の気遣い)

// 幹事無料の場合
残り合計 = 合計金額 - 0
他メンバー1人あたり = 端数処理(残り合計 ÷ (人数 - 1))

// 幹事が追加負担する場合
残り合計 = 合計金額 - 幹事追加額
他メンバー1人あたり = 端数処理(残り合計 ÷ (人数 - 1))

「幹事が多く払うのがマナー?」という疑問を持つ人もいるが、決まりはない。予約・集金・連絡の手間を考えると、むしろ少なめが自然という場面も多い。

  1. 固定額メンバー(上司N人が定額)

「上司3人が各8,000円出す、残りを若手で割る」という現実によくあるパターン。

固定額合計 = 固定人数 × 1人あたり固定額
残り合計 = 合計金額 - 固定額合計
残り人数 = 総人数 - 固定人数
残りメンバー1人あたり = 端数処理(残り合計 ÷ 残り人数)

バリデーションとして「固定額合計 ≥ 合計金額」はエラーにする必要がある。上司が全額以上払う場合は計算が破綻する。


実装の技術的判断

フレームワークを使わなかった理由

React/Vueを使う選択肢もあったが、割り勘計算という「状態が少なく、画面遷移がない」用途にはオーバーキル。

  • HTML + CSS + Vanilla JS のみ
  • ビルドステップなし
  • 依存パッケージなし

ホスティングはS3 + CloudFrontの静的配信で、デプロイは aws s3 sync + CloudFrontキャッシュ無効化のシェルスクリプト1本。

JSのモジュール設計(Revealing Module Pattern)

  // calc.js — 計算ロジックのみ。DOMに一切触れない
  const Calc = (() => {
    function equal(total, people, rounding, unit) { ... }
    function weighted(total, groups, rounding, unit) { ... }
    // ...
    return { equal, weighted, withFree, withOrganizer, withFixed };
  })();

calc.js(計算)→ ui.js(DOM操作)→ app.js(イベント配線)の3層に分離。計算ロジックはDOMを知らないため、テストしやすく、ロジックの変更がUIに波及しない。

端数処理の設計

端数処理は計算エンジンの中核。applyRounding(value, method, unit) として独立させた。

function applyRounding(value, method, unit) {
  switch (method) {
    case "ceil":  return Math.ceil(value / unit) * unit;
    case "floor": return Math.floor(value / unit) * unit;
    case "round": return Math.round(value / unit) * unit;
  }
}

value / unit で単位に変換してから処理し、* unit で戻す。これで「100円単位で切り上げ」が Math.ceil(value / 100) * 100 と自然に書ける。

差額(端数の行き先)の可視化

端数処理後の「回収額 - 合計」を必ず計算して表示する。

例:30,000円を7人で10円切り上げ → 1人4,290円 × 7人 = 30,030円 → +30円が余る

この差額を表示することで「誰かが30円少なく払える」「幹事が30円受け取る」という調整ができる。現実の割り勘で一番モヤモヤする部分を明示した。


SEO対策

AdSenseで収益化を目指すため、SEOも意識した。

  • JSON-LD構造化データ:WebApplication + FAQPage の2種類を設置。FAQリッチリザルトを狙う
  • FAQ内容:「割り勘 端数」「割り勘 傾斜 相場」などの検索クエリに自然に答える内容を用意
  • パフォーマンス:静的HTMLのため初回表示が速く、Core Web Vitalsに有利

まとめ

「割り勘を計算する」という単純に見えるタスクでも、現実のシーンを丁寧に分解すると5パターンが出てきた。

  • 均等割り(基本)
  • 傾斜割り(加重平均の逆算)
  • 無料枠(除外計算)
  • 幹事設定(固定差引)
  • 固定額メンバー(差引+均等)

計算ロジックをDOMから完全に分離したことで、各パターンが独立してテストできる構造になっている。

https://warikan.keydrop.net

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?