Skip to content

Instantly share code, notes, and snippets.

@smitsgit
Created January 14, 2019 12:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smitsgit/0ce6e9fa793cb00e85be0e8a4810f032 to your computer and use it in GitHub Desktop.
Save smitsgit/0ce6e9fa793cb00e85be0e8a4810f032 to your computer and use it in GitHub Desktop.
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