Design a subscription billing model with three plan tiers: Free, Pro, and Enterprise. Every plan belongs to a customer and can produce a monthly cost and invoice line, but each tier calculates its price differently.
The provided Subscriptions class supports these operations:
Subscriptions() creates a billing service with no plans.int addFree(String customer) adds a Free plan and returns the index it was stored at.int addPro(String customer, int seats) adds a Pro plan and returns the index it was stored at.int addEnterprise(String customer, int seats, double discountPercent) adds an Enterprise plan and returns the index it was stored at.double monthlyCost(int index) returns the monthly cost of the plan at index. Free costs 0, Pro costs 12 per seat, and Enterprise costs 20 per seat before applying discountPercent.String invoiceLine(int index) returns "<customer> (<tier>): $<cost>", where the tier is Free, Pro, or Enterprise and the cost displays exactly two decimal places.double totalMonthly() returns the sum of every plan's full-precision monthly cost.int planCount() returns how many plans are being billed.Indices are assigned in insertion order starting at 0. Adding another tier later must not require changing the existing invoiceLine or totalMonthly logic.
Your task is to implement the abstract Plan base class and the concrete FreePlan, ProPlan, and EnterprisePlan subclasses. Do not modify the provided Subscriptions class. Keep shared invoice behavior on the base class and tier-specific pricing inside the corresponding subclass.
Input:
Output:
Explanation: Acme's Free plan is stored at index 0 and costs nothing. Globex's 10-seat Pro plan is stored at index 1 and costs 10 × 12 = 120. The total monthly charge is therefore 120.0.
Input:
Output:
Explanation: The Enterprise base price is 50 × 20 = 1000. Applying a 10% discount leaves a monthly cost of 900.0.
1 <= customer.length <= 400 <= seats <= 100000 <= discountPercent <= 100index always refers to a plan that has been added.100 calls will be made across all methods.Full marks when a base plan type holds the customer and declares the monthly cost calculation, with free, pro and enterprise subtypes supplying their own pricing. Lose points heavily when Subscriptions branches on a stored tier flag or an if/switch over plan kind instead of delegating to the plan.
Full marks when the invoice line is built once on the base type and every tier reuses it. Lose points when it is duplicated per tier, assembled inside Subscriptions, or when adding a fourth tier would require editing existing invoice logic.
Full marks for a Subscriptions class that stores plan objects rather than parallel arrays of customers, seats and tiers, with per-seat prices named rather than repeated as bare numbers. Lose points for printing to stdout or for a total tracked in a separate field that can drift from the stored plans.
Passing every test is not enough on its own. A submission is accepted only when the design also clears the bar.
| Call | Returns |
|---|---|
| new Subscriptions() | null |
| addFree("Acme") | 0 |
| addPro("Globex", 10) | 1 |
| invoiceLine(0) | "Acme (Free): $0.00" |
| invoiceLine(1) | "Globex (Pro): $120.00" |
| totalMonthly() | 120 |
Free costs nothing. Pro is 12 per seat, so 10 seats is 120. The account total is the sum of both.
Run checks these cases. Submit also runs a larger hidden set.

