Hello, if you have any need, please feel free to consult us, this is my wechat: wx91due
COMP1117B Computer Programming
Assignment 3
Due date: Apr 14, 2025 23:59
You are reminded that the VPL system on HKU Moodle evaluates your program with full marks under the condition that your program output is the EXACT MATCH of the expected output. In other words, any additional or missing space character, newline character, etc., will be treated as errors and lead to 0 marks. Also, you are suggested to make more test cases on your own for testing your program.
Question 1 [50%]:
Task
Design a Python program to process Starbucks coffee orders and generate a comprehensive sales report.
Input Format
Example Input
Below is a complete input example. The input is divided into two phases: drink definitions and order records.
3
latte,4.50
cappuccino,3.99
espresso,2.80
2
Explanation of Input Structure
The first line is an integer m (number of drink types).
The next m lines define each drink’s name and price in the format:
<drink_name>,<price>
<drink_name>: Name of the drink (case-insensitive; e.g., Latte and LATTE are treated as the same).
<price>: Price of the drink as a float (e.g., 4.50).
The next line is an integer n (number of orders).
The next n lines define customer orders in the format:
<username>,<email>,<membership>,<drink1>,<drink2>,...
<username>: Customer’s full name (e.g., John Doe).
<membership>: Membership tier (gold, silver, none; case-insensitive).
<drink1>,<drink2>,...: List of drink names (case-insensitive). Each occurrence of a drink name represents one unit purchased (e.g., latte,latte,cappuccino means 2 lattes and 1 cappuccino).
Output Format
The report must match the following structure:
==== Starbucks Sales Report ====
Total Sales: $23.94
Average Order Value: $11.97
Top 2 Drinks by Quantity:
1. espresso 3 sold
2. latte 3 sold
Top 2 Users by Spending:
Membership Tier Sales:
- Gold: $11.69 (48.8%)
- Silver: $12.25 (51.2%)
- None: $0.00 (0.0%)
Required Metrics:
Total Sales: Sum of all valid orders.
Average Order Value: Total Sales / Number of Orders.
Top 2 Drinks by Quantity: Sorted by quantity sold (descending), then alphabetically.
Top 2 Users by Spending: Sorted by total spending (descending), then by email.
Membership Tier Sales: Total sales and percentage contribution for gold, silver, and none tiers.
Formatting Rules:
Drink and user names are left-aligned in a 15-character-wide column.
Monetary values and percentages are displayed with exactly 2 decimal places.
Capitalization: Membership tiers are capitalized (e.g., gold → Gold).
Requirements
Your program is required to include these custom functions:
1. read_drinks(m: int) -> dict
Purpose: Read m drink entries and return a dictionary mapping drink names (lowercase) to prices.
2. parse_order(order_str: str, drinks: dict) -> tuple
Purpose: Parse and validate an order string.
Return:
(email, membership, item_counts) if valid, where:
item_counts: Dictionary {drink_name: quantity} (e.g., {"latte": 2, "cappuccino": 1}).
3. calculate_total(items: dict, drinks: dict, membership: str) -> float
Purpose: Compute the total cost of an order after applying membership discounts.
Discount Rules:
gold: 10% discount
silver: 5% discount
none: 0% discount
Rounding: Use round to round up to the nearest cent (e.g., $4.561 → $4.56).
4. generate_report(orders: list, drinks: dict) -> str
Purpose: Generate a formatted sales report string.
Sample 1 Input/Output
Input:
3
latte,4.50
cappuccino,3.99
espresso,2.80
2
Output:
==== Starbucks Sales Report ====
Total Sales: $23.94
Average Order Value: $11.97
Top 2 Drinks by Quantity:
1. espresso 3 sold
2. latte 3 sold
Top 2 Users by Spending:
Membership Tier Sales:
- Gold: $11.69 (48.8%)
- Silver: $12.25 (51.2%)
- None: $0.00 (0.0%)
Sample 2 Input/Output
Input:
4
latte,4.50
cappuccino,3.99
espresso,2.80
mocha,5.20
5
Output:
==== Starbucks Sales Report ====
Total Sales: $50.51
Average Order Value: $10.10
Top 2 Drinks by Quantity:
1. latte 4 sold
2. cappuccino 3 sold
3/7Top 2 Users by Spending:
Membership Tier Sales:
- Gold: $22.92 (45.4%)
- Silver: $17.19 (34.0%)
- None: $10.40 (20.6%)
Hints
You might use these function in your code.
Use fixed-width formatting (e.g., str.ljust(15)) to align drink names, emails, and monetary values.
Format all amounts to 2 decimal places (e.g., f"{value:.2f}").
Use sorted(dict.items(), key=lambda x: x[1]) to sort the dictionary by the value of each element. The sorted() function sorts elements in increasing order by default. Setting reverse=True will sort the elements in descending order.
Question 2 [50%]
Task
Starbucks manages a global coffee bean supply chain with a multi-level hierarchy (e.g., "Global Supplier → Regional Warehouse → Store").
Each node in this hierarchy holds a certain amount of coffee beans. Your task is to calculate the total beans for any queried node, including all its sub-nodes, using recursion. You need to write a Python program that
Reads a hierarchical structure of nodes (supply chain entities).
Accepts multiple queries for nodes and outputs the total coffee beans for each queried node (sum of its own beans and all subnodes recursively).
Uses recursion to traverse the hierarchy when calculating the total beans.
Input Format
-
The first line is Integer N (number of nodes).
-
Next N lines: Each line has the format name,parent_name,beans:
-
name: Unique node name (string).
-
parent_name: Parent node name (empty if root).
-
beans: Non-negative integer beans stored at this node.
-
Next line: An integer M (number of queries).
-
Next M lines: Each line is a node name to query.
Output Format
For each query, output a single integer:
Total beans of the queried node and all its descendants.
If the node does not exist or total is 0, output 0.
Requirements
Your program is required to include these custom function:
1. build_tree() -> dict
Purpose: Read input from standard input and construct a tree (hierarchical) data structure.
Returns:
A dictionary, representing a tree storing the hierarchy, where each key is a node's name and each value is a dictionary with the following keys:
"parent": The name of the parent node (an empty string if no parent exists).
"beans": An integer representing the bean count for the node.
"children": A list of child node names.
2. compute_total(name, tree) -> int
Purpose: Calculate the total bean count for a given node by summing its own beans and the beans of all its descendant nodes in the tree.
Behavior:
If the given name is not present in the tree, the function should return 0.
Otherwise, retrieve the bean count of the current node (tree[name]["beans"]) and recursively add the bean counts from all children nodes (i.e., each child in tree[name ["children"]).
Assumptions:
The tree structure does not contain cycles (i.e., it is acyclic).
Sample 1 Input/Output
Input:
6
Root,,1000
Asia,Root,500
Europe,Root,700
China,Asia,200
Japan,Asia,300
Berlin,Europe,400
1
Root
Output:
3100
Explanation: The root has 1000 beans and two children: Asia and Europe.
Asia has 500 beans and two children: China with 200 beans and Japan with 300 beans.
Europe has 700 beans and only one child: Berlin with 400 beans.
So, the total value is 1000 (root) + (500 + 200 + 300 for Asia) + (700 + 400 for Europe) = 3100.
Sample 2 Input/Output
Input:
3
A,,100
B,A,200
C,A,300
2
D
B
Output:
5/70
200
Sample 3 Input/Output
Input:
2
Child,Parent,100
GrandChild,Child,50
1
Parent
Output:
150
Sample 4 Input/Output
Input:
8
Root,,100
A,Root,50
B,Root,60
C,A,10
D,A,20
E,B,30
F,B,40
G,E,5
2
A
E
Output:
80
35
Hints
Implement the custom function build_tree() to get inputs and build a tree represented by a dictionary where each key is a node name, and its value is a dictionary with keys: parent, beans, children_list.
Implement the custom function compute_total(name, tree) to sum the node’s beans and recursively add all sub-node totals.
A overview of your main program might be: