Skip to content

Instantly share code, notes, and snippets.

@rirakkumya
Created February 2, 2013 13:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rirakkumya/4697304 to your computer and use it in GitHub Desktop.
Save rirakkumya/4697304 to your computer and use it in GitHub Desktop.
型クラスを使って契約種別に従い計算を行うビジネスロジックを実装してみた
/*
概要:入力されたCSVの契約種別コードに従って計算を行い、結果を出力する
仕様:
CSV入力パターン: [名前],[契約種別コード(A or B or C)],[基本料金],[使用量1段階],[使用量2段階]
※文字列はクォート無し
sample: "foo,A,3000,,","bar,B,1000,200,","foobar,C,1000,200,300"
契約種別コード別料金計算仕様:
A: 基本料金
B: 基本料金 + 使用量1段階 * 0.1
C: 基本料金 + 使用量1段階 * 0.02 + 使用量2段階 * 0.3
出力パターン:
[名前]:[料金] (料金の小数部は切り捨て)
sample: "foo:3000"
※契約種別が対象外及び計算に失敗した場合等の異常が発生した場合は"error"を表示
【入力データ】
"foo,A,5000,,"
"bar,B,980,1000,"
"foobar,C,980,500,500"
"xxx,C,980,500,A,,"
"yyy,D,980,500,500,,,,,"
【出力結果】
foo:5000
bar:1080
foobar:1490
error
error
*/
object PriceCalc {
trait 契約種別
case class 料金A(basePrice: BigDecimal) extends 契約種別
case class 料金B(basePrice: BigDecimal, packet: BigDecimal) extends 契約種別
case class 料金C(basePrice: BigDecimal, packet1: BigDecimal, packet2: BigDecimal) extends 契約種別
trait PriceCalc[A] {
def calc(x: A): Option[BigDecimal]
}
def priceCalc[A: PriceCalc](x: A) = implicitly[PriceCalc[A]].calc(x)
}
object PriceCalcOps {
import PriceCalc._
implicit val priceA = new PriceCalc[料金A] {
def calc(x: 料金A) = Some(x.basePrice)
}
implicit val priceB = new PriceCalc[料金B] {
def calc(x: 料金B) = Some(x.basePrice + x.packet * 0.1)
}
implicit val priceC = new PriceCalc[料金C] {
def calc(x: 料金C) = Some(x.basePrice + x.packet1 * 0.02 + x.packet2 + 0.3)
}
}
object Convert {
import PriceCalc._
import PriceCalcOps._
import scala.util.control.Exception._
sealed case class Price(name: String, price: BigDecimal)
private def spritCsv = (_: String).split(",").toList
implicit def str2bd = BigDecimal((_: String))
private def contractMatcher = (x: List[String]) =>
catching(classOf[NumberFormatException]) opt {
x match {
case List(n, "A", b) => priceCalc(料金A(b)) map (Price(n, _))
case List(n, "B", b, p) => priceCalc(料金B(b, p)) map (Price(n, _))
case List(n, "C", b, p1, p2) => priceCalc(料金C(b, p1, p2)) map (Price(n, _))
case _ => None
}
} flatten
private def price2Str = (_: Option[Price]) map (x => f"${x.name}:${x.price}%.0f") getOrElse "error"
private def mkResult = price2Str compose contractMatcher compose spritCsv
def exec = (_: Seq[String]) map mkResult
}
object Execute extends App {
import Convert._
val inputData = Seq(
"foo,A,5000,,",
"bar,B,980,1000,",
"foobar,C,980,500,500",
"xxx,C,980,500,A,,",
"yyy,D,980,500,500,,,,,"
)
exec(inputData) foreach println
}
@rirakkumya
Copy link
Author

target version 2.10.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment