Created
January 14, 2019 12:02
-
-
Save smitsgit/0ce6e9fa793cb00e85be0e8a4810f032 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: Promotion? = null) { | |
fun total(): Double = cart.asSequence().sumByDouble { it.total() } | |
fun finalPrice(): Double { | |
val discount = promo?.discount(this) ?: 0f.toDouble() | |
return total() - discount | |
} | |
} | |
interface Promotion { | |
fun discount(order: Order): Double | |
} | |
class FidelityPromo:Promotion { | |
/** | |
* 5% discount for customers with 1000 or more fidelity points | |
*/ | |
override fun discount(order: Order): Double { | |
return if (order.customer.fidelityScore > 1000){ | |
order.total() * 0.5 | |
}else { | |
0f.toDouble() | |
} | |
} | |
} | |
class BulkPromo:Promotion { | |
/** | |
* 10% discount for each LineItem with 20 or more units | |
*/ | |
override fun discount(order: Order): Double { | |
var discount:Double = 0f.toDouble() | |
for(item in order.cart) { | |
if(item.qtyInKg >= 20) { | |
discount += item.total() * 0.1 | |
} | |
} | |
return discount | |
} | |
} | |
class LargeOrderPromo:Promotion { | |
/** | |
* 7% discount for orders with 10 or more distinct items | |
*/ | |
override fun discount(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<Promotion>): Sequence<Pair<String, Double>>? { | |
return promos.asSequence().map { Pair(it.toString(), it.discount(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, LargeOrderPromo()) | |
orderDetails(joeLarge) | |
promoInfo(joeLarge) | |
val annBulk = Order(joe, bulkOrderCart, BulkPromo()) | |
orderDetails(annBulk) | |
promoInfo(annBulk) | |
} | |
fun promoInfo(joeOrder: Order) { | |
val promos = listOf(FidelityPromo(), BulkPromo(), LargeOrderPromo()) | |
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