Micro SaaS Academy

Unit Conversion Lib

Let me guide you through how to implement the additional units in your system based on the ticket.

1. Understanding the Ticket

The goal is to extend the existing system by adding new measurement units for:
Length
Temperature
Pressure
Time
Power
Volume
Each unit type is associated with a specific SI Unit (the universal standard unit). Other units are defined relative to this SI Unit.

2. Approach to Implementation

Step 1: Define Base Unit Interfaces

For each type (e.g., Length, Time), you need to define an interface for the unit. This ensures consistency and type safety.
Example for Length:
interface LengthUnit : Unit

Step 2: Implement Each Unit

For each new unit, define how to convert to and from the SI Unit.

Example: Length Units

// Meter is the SI Unit for Length
object Meter : LengthUnit {
override fun convertToStandardUnit(value: Double): Double = value
override fun convertToUnit(value: Double): Double = value
}
// Kilometer
object Kilometer : LengthUnit {
override fun convertToStandardUnit(value: Double): Double = value * 1000
override fun convertToUnit(value: Double): Double = value / 1000
}
// Mile
object Mile : LengthUnit {
override fun convertToStandardUnit(value: Double): Double = value * 1609.34
override fun convertToUnit(value: Double): Double = value / 1609.34
}

Example: Temperature Units

// Kelvin is the SI Unit for Temperature
object Kelvin : TemperatureUnit {
override fun convertToStandardUnit(value: Double): Double = value
override fun convertToUnit(value: Double): Double = value
}
// Celsius
object Celsius : TemperatureUnit {
override fun convertToStandardUnit(value: Double): Double = value + 273.15
override fun convertToUnit(value: Double): Double = value - 273.15
}
// Fahrenheit
object Fahrenheit : TemperatureUnit {
override fun convertToStandardUnit(value: Double): Double = (value - 32) * 5 / 9 + 273.15
override fun convertToUnit(value: Double): Double = (value - 273.15) * 9 / 5 + 32
}

Example: Pressure Units

// Pascal is the SI Unit for Pressure
object Pascal : PressureUnit {
override fun convertToStandardUnit(value: Double): Double = value
override fun convertToUnit(value: Double): Double = value
}
// PSI
object PSI : PressureUnit {
override fun convertToStandardUnit(value: Double): Double = value * 6894.76
override fun convertToUnit(value: Double): Double = value / 6894.76
}
// Bar
object Bar : PressureUnit {
override fun convertToStandardUnit(value: Double): Double = value * 100000
override fun convertToUnit(value: Double): Double = value / 100000
}

Step 3: Integrate Units with Measurement Class

Use a generic Measurement class that works with all types of units.
Example:
class Measurement<T : Unit>(private val value: Double, private val unit: T) {
private val standardValue = unit.convertToStandardUnit(value)
fun convert(toUnit: T): Double = toUnit.convertToUnit(standardValue)
}

Step 4: Add Derived Units (if needed)

If you have combinations like Power or Volume, define derived units similarly.

Example: Power Units

// Watt is the SI Unit for Power
object Watt : PowerUnit {
override fun convertToStandardUnit(value: Double): Double = value
override fun convertToUnit(value: Double): Double = value
}
// Kilowatt
object Kilowatt : PowerUnit {
override fun convertToStandardUnit(value: Double): Double = value * 1000
override fun convertToUnit(value: Double): Double = value / 1000
}

Example: Volume Units

// Liter is the SI Unit for Volume
object Liter : VolumeUnit {
override fun convertToStandardUnit(value: Double): Double = value
override fun convertToUnit(value: Double): Double = value
}
// Gallon
object Gallon : VolumeUnit {
override fun convertToStandardUnit(value: Double): Double = value * 3.78541
override fun convertToUnit(value: Double): Double = value / 3.78541
}

Step 5: Testing

Ensure each unit and conversion is tested. Create test cases for:
1. Conversions to SI Units.
2. Conversions from SI Units to other units.
3. End-to-end integration.
Example Test:
fun testLengthConversion() {
val kilometers = Measurement(1.0, Kilometer)
assert(kilometers.convert(Meter) == 1000.0)
val miles = Measurement(1.0, Mile)
assert(miles.convert(Kilometer) == 1.60934)
}

3. Considerations

• Ensure proper unit type checking (e.g., don’t allow Length to be converted to Temperature).
• Use extensions for better developer experience:
val Number.kilometers get() = Measurement(this.toDouble(), Kilometer)
val Number.miles get() = Measurement(this.toDouble(), Mile)
• Integrate the new units with your frontend logic to display values in the user’s preferred units.

4. Final Flow

1. Define units (e.g., Kilometer, Fahrenheit).
2. Add conversion logic for each unit.
3. Integrate units into your shared Units Conversion Library.
4. Test conversions thoroughly.
5. Update your app’s logic to utilize these new units.
Would you like me to help you implement any specific part?
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.