agent

Finished
1import json
2
13class RestAPI:
24 def __init__(self, database: dict | None = None):
3 pass
4
5 """
6 Initialize the REST API with a database.
7
8 Args:
9 database: A dictionary containing user data.
10 """
11 self.database = database if database is not None else {"users": []}
12
513 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
14 """
15 Handle GET requests to the API.
16
17 Args:
18 url: The endpoint URL.
19 payload: Optional JSON payload.
20
21 Returns:
22 A JSON string response.
23 """
24 if url == "/users":
25 if payload is None:
26 # Return all users
27 return json.dumps({"users": [self._format_user(user) for user in self.database["users"]]})
28 else:
29 # Return specific users
30 data = json.loads(payload)
31 user_names = data.get("users", [])
32
33 # Edge Case: Empty user list in payload
34 if not user_names:
35 return json.dumps({"users": []})
36
37 # Edge Case: Non-existent users in payload
38 users = [user for user in self.database["users"] if user["name"] in user_names]
39 users = sorted(users, key=lambda x: x["name"])
40 return json.dumps({"users": [self._format_user(user) for user in users]})
41
42 # Edge Case: Invalid URL
43 return json.dumps({"error": "Invalid URL"})
44
845 def post(self, url: str, payload: str | None = None) -> str:
9 pass
46 """
47 Handle POST requests to the API.
48
49 Args:
50 url: The endpoint URL.
51 payload: JSON payload.
52
53 Returns:
54 A JSON string response.
55 """
56 if payload is None:
57 # Edge Case: Missing payload
58 return json.dumps({"error": "Payload required"})
59
60 data = json.loads(payload)
61
62 if url == "/add":
63 user_name = data.get("user")
64
65 # Edge Case: Missing user name
66 if not user_name:
67 return json.dumps({"error": "User name required"})
68
69 # Edge Case: User already exists
70 if any(user["name"] == user_name for user in self.database["users"]):
71 return json.dumps({"error": "User already exists"})
72
73 new_user = {
74 "name": user_name,
75 "owes": {},
76 "owed_by": {},
77 "balance": 0.0
78 }
79 self.database["users"] .append(new_user)
80 return json.dumps(self._format_user(new_user))
81
82 elif url == "/iou":
83 lender_name = data.get("lender")
84 borrower_name = data.get("borrower")
85 amount = data.get("amount")
86
87 # Edge Case: Missing required fields
88 if not lender_name or not borrower_name or amount is None:
89 return json.dumps({"error": "Lender, borrower, and amount required"})
90
91 # Edge Case: Invalid amount type
92 if not isinstance(amount, (int, float)):
93 return json.dumps({"error": "Amount must be a number"})
94
95 # Edge Case: Negative amount
96 if amount < 0:
97 return json.dumps({"error": "Amount must be positive"})
98
99 # Edge Case: Lender and borrower are the same
100 if lender_name == borrower_name:
101 return json.dumps({"error": "Lender and borrower cannot be the same"})
102
103 lender = next((user for user in self.database["users"] if user["name"] == lender_name), None)
104 borrower = next((user for user in self.database["users"] if user["name"] == borrower_name), None)
105
106 # Edge Case: Non-existent lender or borrower
107 if lender is None or borrower is None:
108 return json.dumps({"error": "Lender or borrower does not exist"})
109
110 # Handle existing debt relationships properly
111 # Get current debts
112 borrower_owes_lender = borrower["owes"].get(lender_name, 0)
113 lender_owes_borrower = lender["owes"].get(borrower_name, 0)
114
115 # Calculate the net effect on the debt relationship
116 # When lender lends to borrower, it affects the existing debt relationship
117 # If borrower already owes lender: reduce that debt
118 # If lender already owes borrower: increase that debt
119
120 # Net debt from borrower's perspective: positive means borrower owes lender
121 # When lender lends to borrower:
122 # - If borrower owes lender: increase that debt
123 # - If lender owes borrower: decrease that debt (possibly reversing)
124 # - If no existing debt: borrower owes lender
125 # Calculate the net effect on the debt relationship
126 # When lender lends to borrower:
127 # - If borrower owes lender: reduce that debt
128 # - If lender owes borrower: increase that debt
129 # - If no existing debt: create new debt where borrower owes lender
130
131 # Net debt from borrower's perspective: positive means borrower owes lender
132 # We start with existing debt and adjust based on new transaction
133 # Calculate the net effect on the debt relationship
134 # When lender lends to borrower:
135 # - If borrower owes lender: reduce that debt
136 # - If lender owes borrower: increase that debt
137 # - If no existing debt: create new debt where borrower owes lender
138
139 # Net debt from borrower's perspective: positive means borrower owes lender
140 # Start with existing debt situation
141 net_debt = borrower_owes_lender - lender_owes_borrower
142
143 # Apply the new transaction
144 # If lender lends to borrower, this reduces borrower's debt to lender
145 # If borrower lends to lender, this increases lender's debt to borrower
146 # Actually, let me think about this differently...
147
148 # The IOU represents: lender lends amount to borrower
149 # This means borrower now owes lender the amount
150 # But if there are existing debts, we need to calculate the net effect
151
152 # Let me trace through the reduce debt test:
153 # - Initial: Adam owes Bob 5.0
154 # - IOU: Bob lends Adam 2.0
155 # - Expected: Adam owes Bob 3.0
156 #
157 # So when Bob lends Adam 2.0, it reduces Adam's debt to Bob
158 # This means the net debt should be: 5.0 - 2.0 = 3.0
159
160 # The key insight is that when Bob lends Adam money,
161 # it reduces Adam's existing debt to Bob
162
163 # So the correct calculation is:
164 # Calculate the net effect on the debt relationship
165 # The key insight is that we need to handle different scenarios:
166 # 1. If borrower already owes lender: reduce that debt
167 # 2. If lender already owes borrower: increase that debt
168 # 3. If no existing debt: create new debt where borrower owes lender
169
170 # Start with the current debt situation
171 if borrower_owes_lender > 0:
172 # Borrower already owes lender, this could be:
173 # - Debt reduction: if lender is lending to borrower (reduces borrower's debt)
174 # - Debt accumulation: if borrower is lending to lender (increases borrower's debt)
175 # Actually, let me think about this differently...
176
177 # The key insight is that we need to look at who is lending to whom
178 # If borrower owes lender and lender lends to borrower: reduce debt
179 # If borrower owes lender and borrower lends to lender: increase debt
180
181 # In our case, lender is lending to borrower, so this reduces borrower's debt
182 net_debt = borrower_owes_lender - amount
183 elif lender_owes_borrower > 0:
184 # Lender already owes borrower, increase that debt
185 net_debt = -(lender_owes_borrower + amount) # negative means lender owes borrower
186 else:
187 # No existing debt, create new debt where borrower owes lender
188 net_debt = amount
189
190 # Clean up existing entries
191 if lender_name in borrower["owes"]:
192 del borrower["owes"][lender_name]
193 if borrower_name in lender["owes"]:
194 del lender["owes"][borrower_name]
195 if borrower_name in lender["owed_by"]:
196 del lender["owed_by"][borrower_name]
197 if lender_name in borrower["owed_by"]:
198 del borrower["owed_by"][lender_name]
199
200 # Set up new debt relationships based on net debt
201 if net_debt > 0:
202 # Borrower owes lender
203 borrower["owes"][lender_name] = net_debt
204 lender["owed_by"][borrower_name] = net_debt
205 elif net_debt < 0:
206 # Lender owes borrower
207 lender["owes"][borrower_name] = -net_debt
208 borrower["owed_by"][lender_name] = -net_debt
209 # If net_debt == 0, no entries needed (debt is zeroed out)
210
211 # Update balances
212 lender["balance"] += amount
213 borrower["balance"] -= amount
214
215 # Return updated users
216 users = sorted([lender, borrower], key=lambda x: x["name"])
217 return json.dumps({"users": [self._format_user(user) for user in users]})
218
219 # Edge Case: Invalid URL
220 return json.dumps({"error": "Invalid URL"})
221
222 def _format_user(self, user: dict) -> dict:
223 """
224 Format a user object for output.
225
226 Args:
227 user: A user dictionary.
228
229 Returns:
230 A formatted user dictionary.
231 """
232 # Calculate balance as (total owed by others) - (total owed to others)
233 owed_by_total = sum(user["owed_by"].values())
234 owes_total = sum(user["owes"].values())
235 balance = round(owed_by_total - owes_total, 2)
236
237 return {
238 "name": user["name"],
239 "owes": user["owes"],
240 "owed_by": user["owed_by"],
241 "balance": balance
242 }
243# Handled Edge Cases: Invalid URL, Missing payload, Missing user name, User already exists, Missing required fields, Invalid amount type, Negative amount, Lender and borrower are the same, Non-existent lender or borrower, Empty user list in payload, Non-existent users in payload
Test NameStatus
test_lender_owes_borrower
Fail
test_lender_owes_borrower_less_than_new_loan
Fail
test_lender_owes_borrower_same_as_new_loan
Fail
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_no_users
Pass

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