package domain
import java.time.temporal.ChronoUnit
import java.time.{DayOfWeek, LocalDate, LocalDateTime}
import enumeratum._
sealed trait Age extends Ordered[Age] {
def breachEncapsulationOfValue(today: LocalDate): Int
override def compare(that: Age): Int = {
val now = LocalDate.now()
breachEncapsulationOfValue(now) compareTo that.breachEncapsulationOfValue(now)
}
}
object Age {
def fromBirthDay(birthDay: LocalDate): Age =
DynamicAge(birthDay)
def apply(value: Int): Age = StaticAge(value)
}
case class StaticAge(value: Int) extends Age {
override def breachEncapsulationOfValue(today: LocalDate): Int = value
}
case class DynamicAge(birthDay: LocalDate) extends Age {
private def calculateAge(birthDay: LocalDate, today: LocalDate): Int =
ChronoUnit.YEARS.between(birthDay, today).toInt
def breachEncapsulationOfValue(today: LocalDate): Int = calculateAge(birthDay, today)
}
sealed trait CustomerType extends EnumEntry
object CustomerType extends Enum[CustomerType] {
override def values: IndexedSeq[CustomerType] = findValues
case object General extends CustomerType
case object UniversityStudent extends CustomerType // 大学生(専門含む)
case object HighSchoolStudent extends CustomerType // 中高校生
case object ElementarySchoolStudent extends CustomerType // 小学生
case object Under5YearsOld extends CustomerType // 五歳以下
}
sealed trait Gender extends EnumEntry
object Gender extends Enum[Gender] {
override def values: IndexedSeq[Gender] = findValues
case object Male extends Gender
case object Female extends Gender
}
case class Customer(birthDay: LocalDate, gender: Gender, customerType: CustomerType) { // Genderはまだ未使用
def age(today: LocalDate): Age = Age.fromBirthDay(today)
}
sealed trait MoviePrice extends Ordered[MoviePrice] {
def breachEncapsulationOfValue: Int
override def compare(that: MoviePrice): Int ={
breachEncapsulationOfValue compareTo that.breachEncapsulationOfValue
}
}
class MoviePriceWeekday(customer: Customer, today: LocalDateTime) extends MoviePrice {
import CustomerType._
override def breachEncapsulationOfValue: Int = {
(customer.customerType, customer.age(today.toLocalDate)) match {
case (General, age) if age >= Age(70) => 1100
case (General, _) => 1800
case (UniversityStudent, _) => 1500
case (HighSchoolStudent, _) => 1000
case (ElementarySchoolStudent, _) => 1000
case (Under5YearsOld, _) => 1000
}
}
}
class MoviePriceWeekdayLate(customer: Customer, today: LocalDateTime) extends MoviePrice {
import CustomerType._
override def breachEncapsulationOfValue: Int = {
(customer.customerType, customer.age(today.toLocalDate)) match {
case (General, age) if age >= Age(70) => 1100
case (General, _) => 1300
case (UniversityStudent, _) => 1300
case (HighSchoolStudent, _) => 1000
case (ElementarySchoolStudent, _) => 1000
case (Under5YearsOld, _) => 1000
}
}
}
class MoviePriceWeekend(customer: Customer, today: LocalDateTime) extends MoviePrice {
import CustomerType._
override def breachEncapsulationOfValue: Int = {
(customer.customerType, customer.age(today.toLocalDate)) match {
case (General, age) if age >= Age(70) => 1100
case (General, _) => 1800
case (UniversityStudent, _) => 1500
case (HighSchoolStudent, _) => 1000
case (ElementarySchoolStudent, _) => 1000
case (Under5YearsOld, _) => 1000
}
}
}
class MoviePriceWeekendLate(customer: Customer, today: LocalDateTime) extends MoviePrice {
import CustomerType._
def breachEncapsulationOfValue: Int = {
(customer.customerType, customer.age(today.toLocalDate)) match {
case (General, age) if age >= Age(70) => 1100
case (General, _) => 1300
case (UniversityStudent, _) => 1300
case (HighSchoolStudent, _) => 1000
case (ElementarySchoolStudent, _) => 1000
case (Under5YearsOld, _) => 1000
}
}
}
// Domain Service
object MoviePriceCalculator {
private def isWeekday(dateTime: LocalDateTime): Boolean =
!(dateTime.getDayOfWeek == DayOfWeek.SATURDAY || dateTime.getDayOfWeek == DayOfWeek.SUNDAY)
private def isLate(dateTime: LocalDateTime): Boolean = dateTime.getHour >= 20
def moviePrice(customer: Customer, today: LocalDateTime): MoviePrice = {
(isWeekday(today), isLate(today)) match {
case (true, false) => new MoviePriceWeekday(customer, today)
case (true, true) => new MoviePriceWeekdayLate(customer, today)
case (false, false) => new MoviePriceWeekend(customer, today)
case (false, true) => new MoviePriceWeekendLate(customer, today)
}
}
}
Last active
July 15, 2019 05:05
-
-
Save j5ik2o/72f5281260376e7394c12cbcea17e5f1 to your computer and use it in GitHub Desktop.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment