Open4

Scalaでjr-pricingの実装

あぷしあぷし

はじめに

scalaで https://github.com/masuda220/jr-pricing を実装する

Scalaインストール

ランタイム系

appseed246@appseed246mbp src % sdk version

SDKMAN!
script: 5.18.2
native: 0.4.2

appseed246@appseed246mbp src % java --version
openjdk 21 2023-09-19 LTS
OpenJDK Runtime Environment Corretto-21.0.0.35.1 (build 21+35-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.0.35.1 (build 21+35-LTS, mixed mode, sharing)

Intellij

  • Intellij IDEA Community Editionをインストール
  • PluginからScalaプラグインをインストールし再起動
  • プロジェクト作成
    • Scala: v2.13.12

参考資料

あぷしあぷし

文法

数値の型変換

opaque type

  • 既存の型に別名をつけられる。
  • IntのOpaque Typeを作成しても、四則演算はextensionとして定義する必要がある
package models

import scala.annotation.targetName

object Prices {

  opaque type Price = Int

  object Price {
    // 10円以下切り捨て
    def apply(value: Int): Price = (value / 10) * 10
  }

  extension (x: Price)
    def value: Int = x
    @targetName("append")
    def +(y: Price): Price = Price(x.intValue + y.intValue)
    @targetName("subtract")
    def -(y: Price): Price = Price(x.intValue - y.intValue)
    @targetName("multiple")
    def *(y: Double): Price = Price((x.intValue * y).toInt)
}

日時

javaのjoda-timeを利用する

libraryDependencies += "joda-time" % "joda-time" % "2.12.5"

参考

あぷしあぷし

実装のための整理

料金体系

  • 料金 = 運賃(basic fare) + 特急料金(super express surcharge)

片道の料金計算に必要な要素

  • 出発地(東京固定)
  • 目的地
  • 指定席/自由席
  • 大人/子供
  • 特急種別

往復の運賃計算に必要な要素

  • 片道の営業キロ
  • 利用人数
  • 日時

料金計算に影響のあるデータ

  • (0) のぞみ割増
    • 特急料金に対して、目的地ごとに設定された固定額を加算する
  • (1) 自由席割引
    • 特急料金から530円減算
  • (2) 子供割引
    • 運賃特急料金から5額引
  • (3) 往復割引
    • 往復601km以上で、片道の運賃を1割引
  • (4) 団体割引(全員大人として扱う)
    • 8人以上の割引
      • 1人あたりの運賃特急料金を一定額割引
        • 12/21 ~ 1/10: 10%
        • 上記期間以外: 15%
    • 31人以上の割引
      • 31~50人: 1人分の運賃特急料金が無料
      • 51人以上: 50人増えるごとに1人ずつ運賃特急料金が無料
  • (5) 季節による変動
    • 指定席特急料金が増減。自由席は変動なし
      • 繁忙期(12/25 ~ 1/10): 指定席特急料金から +200円
      • 閑散期(1/16 ~ 1/30): 指定特急料金から -200円

料金ルールの適用順番

(0) -> (1) -> (5) -> (2) -> (3) -> (4)

あぷしあぷし

ハマりどころ

if-then- else

Scala3ではif ... then ... else(if)スタイルで記述する

def compare(a: Int, b: Int): Int =
  if a < b then
    -1
  else if a == b then
    0
  else
    1

参考