package models class ConversionException(from: Unit, to: Unit) extends RuntimeException(s"Cannot convert from $from to $to.", null) sealed trait Unit { def productPrefix: String protected def conversion: Float def name: String = this.productPrefix.split("\\.").last protected def abreviation: String def measure: Measure def convertToPrimary(v: Float): Float = v/conversion def convertFromPrimary(v: Float): Float = v*conversion def convertTo(v: Float, other: Unit) = { if (measure == other.measure) other.convertFromPrimary(convertToPrimary(v)) else throw new ConversionException(this, other) } } case object Gram extends Unit { protected val conversion: Float = 1f val measure: Measure = Mass val abreviation: String = "g" } case object Kilogram extends Unit { protected val conversion: Float = 0.001f val measure: Measure = Mass val abreviation: String = "kg" } case object Ounce extends Unit { protected val conversion: Float = 0.03527396f val measure: Measure = Mass val abreviation: String = "oz" } case object Pound extends Unit { protected val conversion: Float = 0.00220462249993f val measure: Measure = Mass val abreviation: String = "lb" } case object Mililiter extends Unit { protected val conversion: Float = 1000f val measure: Measure = Volume val abreviation: String = "mL" } case object Liter extends Unit { protected val conversion: Float = 1f val measure: Measure = Volume val abreviation: String = "L" } case object Teaspoon extends Unit { protected val conversion: Float = 202.8842218965f val measure: Measure = Volume val abreviation: String = "tsp" } case object Tablespoon extends Unit { protected val conversion: Float = 67.627891024f val measure: Measure = Volume val abreviation: String = "Tbsp" } case object Cup extends Unit { protected val conversion: Float = 4.166666f val measure: Measure = Volume val abreviation: String = "cups" } case object Gallon extends Unit { protected val conversion: Float = 0.26417290088f val measure: Measure = Volume val abreviation: String = "gallons" } case object Count extends Unit { protected val conversion: Float = 1f val measure: Measure = Number val abreviation: String = "" }