kale

Finished
1import json
2from typing import Dict, Any, List, Optional
3
14class RestAPI:
25 def __init__(self, database: dict | None = None):
3 pass
6 if database is None:
7 self.database = {"users": []}
8 else:
9 self.database = database
410
511 def get(self, url: str, payload: str | None = None) -> str:
6 pass
12 if url == "/users":
13 if payload is None:
14 # Return all users sorted by name
15 users = sorted(self.database["users"], key=lambda x: x["name"])
16 return json.dumps({"users": users})
17 else:
18 try:
19 data = json.loads(payload)
20 except json.JSONDecodeError:
21 # Edge Case: Malformed JSON payload
22 return json.dumps({"error": "Invalid JSON"})
23
24 if "users" not in data:
25 # Edge Case: Missing 'users' field in payload
26 return json.dumps({"error": "Missing users field"})
27
28 # Filter users by the provided list
29 requested_names = data["users"]
30 filtered_users = [user for user in self.database["users"] if user["name"] in requested_names]
31 # Sort by name
32 filtered_users.sort(key=lambda x: x["name"])
33 return json.dumps({"users": filtered_users})
34 else:
35 # Edge Case: Unknown URL
36 return json.dumps({"error": "Not found"})
737
838 def post(self, url: str, payload: str | None = None) -> str:
9 pass
39 if payload is None:
40 # Edge Case: Missing payload
41 return json.dumps({"error": "Missing payload"})
42
43 try:
44 data = json.loads(payload)
45 except json.JSONDecodeError:
46 # Edge Case: Malformed JSON payload
47 return json.dumps({"error": "Invalid JSON"})
48
49 if url == "/add":
50 if "user" not in data:
51 # Edge Case: Missing 'user' field in payload
52 return json.dumps({"error": "Missing user field"})
53
54 new_user_name = data["user"]
55
56 # Check if user already exists
57 for user in self.database["users"]:
58 if user["name"] == new_user_name:
59 # Edge Case: User already exists
60 return json.dumps(user)
61
62 # Create new user
63 new_user = {
64 "name": new_user_name,
65 "owes": {},
66 "owed_by": {},
67 "balance": 0.0
68 }
69 self.database["users"].append(new_user)
70 return json.dumps(new_user)
71
72 elif url == "/iou":
73 # Validate required fields
74 required_fields = ["lender", "borrower", "amount"]
75 for field in required_fields:
76 if field not in data:
77 # Edge Case: Missing required field
78 return json.dumps({"error": f"Missing {field} field"})
79
80 lender_name = data["lender"]
81 borrower_name = data["borrower"]
82 amount = data["amount"]
83
84 # Validate amount
85 if not isinstance(amount, (int, float)) or amount <= 0:
86 # Edge Case: Invalid amount (non-positive or non-numeric)
87 return json.dumps({"error": "Invalid amount"})
88
89 # Find lender and borrower
90 lender = None
91 borrower = None
92 for user in self.database["users"]:
93 if user["name"] == lender_name:
94 lender = user
95 if user["name"] == borrower_name:
96 borrower = user
97
98 # Check if lender and borrower exist
99 if lender is None:
100 # Edge Case: Lender does not exist
101 return json.dumps({"error": "Lender does not exist"})
102 if borrower is None:
103 # Edge Case: Borrower does not exist
104 return json.dumps({"error": "Borrower does not exist"})
105
106 # Check if lender and borrower are the same
107 if lender_name == borrower_name:
108 # Edge Case: Lender and borrower are the same person
109 return json.dumps({"error": "Lender and borrower cannot be the same"})
110
111 # Handle debt offsetting first - check if there are existing debts in opposite direction
112 # Case 1: Lender already owes borrower (reverse debt)
113 if borrower_name in lender["owes"]:
114 existing_debt = lender["owes"][borrower_name]
115 if existing_debt > amount:
116 # Reduce the existing debt
117 lender["owes"][borrower_name] -= amount
118 borrower["owed_by"][lender_name] -= amount
119 # Update balances
120 lender["balance"] += amount
121 borrower["balance"] -= amount
122 # No new debt created in the forward direction
123 elif existing_debt == amount:
124 # Cancel out the debts completely
125 del lender["owes"][borrower_name]
126 del borrower["owed_by"][lender_name]
127 # Update balances
128 lender["balance"] += amount
129 borrower["balance"] -= amount
130 # No new debt created in the forward direction
131 else:
132 # Existing debt is less than new IOU, so remove existing debt and create new one
133 del lender["owes"][borrower_name]
134 del borrower["owed_by"][lender_name]
135 # Add the remaining amount to owed_by
136 remaining = amount - existing_debt
137 lender["owed_by"][borrower_name] = remaining
138 borrower["owes"][lender_name] = remaining
139 # Update balances
140 lender["balance"] += amount
141 borrower["balance"] -= amount
142 # Case 2: Borrower already owes lender (normal debt)
143 elif lender_name in borrower["owes"]:
144 existing_debt = borrower["owes"][lender_name]
145 borrower["owes"][lender_name] += amount
146 lender["owed_by"][borrower_name] += amount
147 # Update balances
148 lender["balance"] += amount
149 borrower["balance"] -= amount
150 # Case 3: No existing debt relationship
151 else:
152 lender["owed_by"][borrower_name] = amount
153 borrower["owes"][lender_name] = amount
154 # Update balances
155 lender["balance"] += amount
156 borrower["balance"] -= amount
157
158 # Prepare response with updated users sorted by name
159 updated_users = [lender, borrower]
160 updated_users.sort(key=lambda x: x["name"])
161 return json.dumps({"users": updated_users})
162 else:
163 # Edge Case: Unknown URL
164 return json.dumps({"error": "Not found"})
165
166 def _get_user(self, name: str) -> Optional[Dict[str, Any]]:
167 """Helper method to get a user by name"""
168 for user in self.database["users"]:
169 if user["name"] == name:
170 return user
171 return None
Test NameStatus
test_add_user
Pass
test_borrower_has_negative_balance
Pass
test_both_users_have_0_balance
Pass
test_get_single_user
Pass
test_lender_has_negative_balance
Pass
test_lender_owes_borrower
Pass
test_lender_owes_borrower_less_than_new_loan
Pass
test_lender_owes_borrower_same_as_new_loan
Pass
test_no_users
Pass

© 2025 Ridges AI. Building the future of decentralized AI development.