Last active
January 14, 2019 13:50
-
-
Save smitsgit/a89c77490de7b03cb018054a82fe8c81 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data class Customer(val name: String, val fidelityScore: Int) | |
data class LineItem(val productName: String, val qtyInKg: Int, val pricePerKg: Double) { | |
fun total(): Double { | |
return qtyInKg * pricePerKg | |
} | |
} | |
class Order(val customer: Customer, val cart: List<LineItem>, val promo: ((Order) -> Double)? = null) { | |
fun total(): Double = cart.asSequence().sumByDouble { it.total() } | |
fun finalPrice(): Double { | |
val discount = promo?.invoke(this) ?: 0f.toDouble() | |
return total() - discount | |
} | |
} | |
/** | |
* 5% discount for customers with 1000 or more fidelity points | |
*/ | |
fun fidelityPromo(order: Order): Double { | |
return if (order.customer.fidelityScore > 1000){ | |
order.total() * 0.5 | |
}else { | |
0f.toDouble() | |
} | |
} | |
/** | |
* 10% discount for each LineItem with 20 or more units | |
*/ | |
fun bulkPromo(order: Order): Double { | |
var discount:Double = 0f.toDouble() | |
for(item in order.cart) { | |
if(item.qtyInKg >= 20) { | |
discount += item.total() * 0.1 | |
} | |
} | |
return discount | |
} | |
/** | |
* 7% discount for orders with 10 or more distinct items | |
*/ | |
fun largePromo(order: Order): Double { | |
val uniqueItems = order.cart.toSet().size | |
return if (uniqueItems >= 10) { | |
order.total() * 0.07 | |
}else { | |
0f.toDouble() | |
} | |
} | |
fun findBestPromo(order: Order, promos: List<(Order)->Double>): Sequence<Pair<String, Double>>? { | |
return promos.asSequence().map { Pair(it.toString(), it.invoke(order)) }.sortedBy { it.second } | |
} | |
fun main(args: Array<String>) { | |
val joe = Customer("John Doe", 900) | |
val ann = Customer("Ann Smith", 1100) | |
val fidelityCheckerCart = listOf(LineItem("banana", 20, 10.0), | |
LineItem("apple", 10, 20.0), | |
LineItem("watermellon", 5, 30.0)) | |
val bulkOrderCart = listOf(LineItem("banana", 30, 10.0), | |
LineItem("apple", 10, 20.0)) | |
val largeOrderCart = mutableListOf<LineItem>() | |
1.rangeTo(30).map { largeOrderCart.add(LineItem(it.toString(), 10, 10.0)) } | |
val joeOrder = Order(joe, fidelityCheckerCart, promo = ::fidelityPromo) | |
orderDetails(joeOrder) | |
promoInfo(joeOrder) | |
val annOrder = Order(ann, fidelityCheckerCart, promo = ::fidelityPromo) | |
orderDetails(annOrder) | |
promoInfo(annOrder) | |
val joeLarge = Order(joe, largeOrderCart, promo = ::largePromo) | |
orderDetails(joeLarge) | |
promoInfo(joeLarge) | |
val annBulk = Order(joe, bulkOrderCart, promo = ::bulkPromo) | |
orderDetails(annBulk) | |
promoInfo(annBulk) | |
} | |
fun promoInfo(joeOrder: Order) { | |
val promos = listOf(::fidelityPromo, ::bulkPromo, ::largePromo) | |
val data = findBestPromo(joeOrder, promos) | |
println() | |
for (item in data!!) { | |
println("[ Algorithm: ] ${item.first}, [ Discount: ] ${item.second}") | |
} | |
} | |
fun orderDetails(order: Order) { | |
println("########################################") | |
println() | |
println("Order Details ") | |
println("Customer Name: ${order.customer.name}") | |
println("Calculated with: ${order.promo}") | |
for (item in order.cart) { | |
println("Product: ${item.productName} [ ${item.qtyInKg} ]") | |
} | |
println("Actual Price: ${order.total()}") | |
println("Discounted Price: ${order.finalPrice()}") | |
println() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment