B1, B2, B3, ... in creation order."itemName|unitPrice|quantity"
itemName is a non-empty string without the | character.unitPrice is an integer representing price per unit (in dollars).quantity is an integer.unitPrice * quantity.P10: 10% off subtotal.P20: 20% off subtotal.FLAT100: Flat 100 off, applicable only if subtotal >= 500.REDEEM: Redeem customer points for additional discount (see rules below).P10 and P20 are applied, only the highest percentage is used.FLAT100 can be applied at most once and only if subtotal >= 500.REDEEM can be applied at most once.subtotal.FLAT100 (if applicable).REDEEM (if applied).percentDiscount = (subtotal * percent) / 100.0.floor(payableAmount / 100).REDEEM is applied, the bill can use customer’s currently available points for discount at the rate 1 point = 1 dollar.20% of the current payable amount (after percentage and flat discounts):redeemCap = floor(currentPayable * 20 / 100)min(customerPoints, redeemCap).BRONZE: 0 - 99 pointsSILVER: 100 - 499 pointsGOLD: 500 - 1999 pointsPLATINUM: 2000+ pointsString createBill(String customerId, List<String> cartItems)
customerId is a non-empty string.cartItems contains 1 or more strings, each in format "itemName|unitPrice|quantity".unitPrice >= 0 and quantity > 0 for every item."B1", "B2", ...)."ERROR".long applyDiscount(String billId, String discountCode)
billId must refer to an existing, open bill.discountCode must be one of: P10, P20, FLAT100, REDEEM.billId is invalid or bill is already paid, return -1.discountCode is unknown, ignore it and return the current payable amount (no change).String payBill(String billId, long amountPaid)
billId must refer to an existing, open bill.amountPaid must be exactly equal to the current payable amount.REDEEM was applied), then new points are earned, and level is updated."PAID|final=<finalAmount>|pointsEarned=<x>|totalPoints=<y>|level=<LEVEL>"billId is invalid, bill is already paid, or amountPaid mismatches, return "ERROR".1 <= cartItems.size() <= 10^50 <= unitPrice <= 10^91 <= quantity <= 10^6long).createBill(customerId = "C1", cartItems = List.of("book|200|1", "pen|10|5")) returns "B1"200*1 + 10*5 = 250; bill ID starts from B1.applyDiscount(billId = "B1", discountCode = "P10") returns 22525; payable becomes 250 - 25 = 225.applyDiscount(billId = "B1", discountCode = "FLAT100") returns 225FLAT100 requires subtotal >= 500; subtotal is 250 so it is not applicable.payBill(billId = "B1", amountPaid = 225) returns "PAID|final=225|pointsEarned=2|totalPoints=2|level=BRONZE"floor(225/100)=2; total points become 2; level stays BRONZE.createBill(customerId = "C1", cartItems = List.of("shoes|600|1", "tshirt|200|2")) returns "B2"600 + 200*2 = 1000.applyDiscount(billId = "B2", discountCode = "P20") returns 800200; payable becomes 1000 - 200 = 800.applyDiscount(billId = "B2", discountCode = "FLAT100") returns 700800 - 100 = 700.applyDiscount(billId = "B2", discountCode = "REDEEM") returns 698C1 currently has 2 points from Example 1. Redeem cap = floor(700*20/100)=140. Redeem amount = min(2,140)=2. Payable becomes 700 - 2 = 698.payBill(billId = "B2", amountPaid = 698) returns "PAID|final=698|pointsEarned=6|totalPoints=6|level=BRONZE"floor(698/100)=6. Total points become 6; level remains BRONZE.createBill(customerId = "C2", cartItems = List.of("mouse|499|1")) returns "B3"applyDiscount(billId = "B3", discountCode = "P10") returns 450floor(499*10/100)=49; payable becomes 499 - 49 = 450.payBill(billId = "B3", amountPaid = 449) returns "ERROR"