couple

Finished
1import json
2from typing import Dict, List, Optional, Any
3
14class RestAPI:
25 def __init__(self, database: dict | None = None):
3 pass
4
6 """
7 Initialize the REST API with a database of users.
8
9 Args:
10 database: A dictionary containing user data with user names as keys
11 """
12 self.database = database or {"users": []}
13 # Ensure all users have the required fields
14 for user in self.database["users"]:
15 if "owes" not in user:
16 user["owes"] = {}
17 if "owed_by" not in user:
18 user["owed_by"] = {}
19 if "balance" not in user:
20 user["balance"] = 0.0
21
22 def _calculate_balance(self, user: Dict[str, Any]) -> float:
23 """
24 Calculate the balance for a user based on what they owe and are owed.
25
26 Args:
27 user: User dictionary with owes and owed_by fields
28
29 Returns:
30 Calculated balance as float
31 """
32 total_owed_by_others = sum(user.get("owed_by", {}).values())
33 total_owed_to_others = sum(user.get("owes", {}).values())
34 return round(total_owed_by_others - total_owed_to_others, 2)
35
36 def _get_user(self, name: str) -> Optional[Dict[str, Any]]:
37 """
38 Find a user by name in the database.
39
40 Args:
41 name: Name of the user to find
42
43 Returns:
44 User dictionary if found, None otherwise
45 """
46 for user in self.database["users"]:
47 if user["name"] == name:
48 return user
49 return None
50
51 def _update_user_balance(self, user: Dict[str, Any]) -> None:
52 """
53 Update a user's balance based on their owes and owed_by.
54
55 Args:
56 user: User dictionary to update
57 """
58 user["balance"] = self._calculate_balance(user)
59
560 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
61 """
62 Handle GET requests to the API.
63
64 Args:
65 url: The endpoint URL
66 payload: Optional JSON payload
67
68 Returns:
69 JSON response as string
70 """
71 if url == "/users":
72 # Edge Case: Handle request with no payload (list all users)
73 if payload is None:
74 # Return all users with updated balances
75 for user in self.database["users"]:
76 self._update_user_balance(user)
77 return json.dumps(self.database)
78
79 # Edge Case: Handle request with payload (list specific users)
80 try:
81 data = json.loads(payload)
82 if "users" not in data:
83 return json.dumps({"error": "Invalid payload"})
84
85 # Filter users by name and sort by name
86 filtered_users = [
87 user for user in self.database["users"]
88 if user["name"] in data["users"]
89 ]
90
91 # Update balances for filtered users
92 for user in filtered_users:
93 self._update_user_balance(user)
94
95 # Sort by name
96 filtered_users.sort(key=lambda x: x["name"])
97
98 return json.dumps({"users": filtered_users})
99 except json.JSONDecodeError:
100 return json.dumps({"error": "Invalid JSON payload"})
101
102 return json.dumps({"error": "Invalid URL"})
103 # Handled Edge Cases: Request with no payload, request with valid payload, request with invalid payload, invalid JSON payload, invalid URL
104
8105 def post(self, url: str, payload: str | None = None) -> str:
9 pass
106 """
107 Handle POST requests to the API.
108
109 Args:
110 url: The endpoint URL
111 payload: JSON payload
112
113 Returns:
114 JSON response as string
115 """
116 # Edge Case: Handle missing payload
117 if payload is None:
118 return json.dumps({"error": "Payload required"})
119
120 try:
121 data = json.loads(payload)
122 except json.JSONDecodeError:
123 return json.dumps({"error": "Invalid JSON payload"})
124
125 if url == "/add":
126 # Edge Case: Handle adding a new user
127 if "user" not in data:
128 return json.dumps({"error": "Missing user field"})
129
130 user_name = data["user"]
131
132 # Edge Case: Handle duplicate user
133 if self._get_user(user_name) is not None:
134 return json.dumps({"error": "User already exists"})
135
136 # Create new user
137 new_user = {
138 "name": user_name,
139 "owes": {},
140 "owed_by": {},
141 "balance": 0.0
142 }
143 self.database["users"] .append(new_user)
144
145 return json.dumps(new_user)
146 # Handled Edge Cases: Missing user field, duplicate user, valid new user
147
148 elif url == "/iou":
149 # Edge Case: Handle creating an IOU
150 required_fields = ["lender", "borrower", "amount"]
151 for field in required_fields:
152 if field not in data:
153 return json.dumps({"error": f"Missing {field} field"})
154
155 lender_name = data["lender"]
156 borrower_name = data["borrower"]
157 amount = data["amount"]
158
159 # Edge Case: Handle invalid amount
160 if not isinstance(amount, (int, float)) or amount < 0:
161 return json.dumps({"error": "Invalid amount"})
162
163 # Edge Case: Handle same lender and borrower
164 if lender_name == borrower_name:
165 return json.dumps({"error": "Lender and borrower cannot be the same"})
166
167 # Edge Case: Handle non-existent lender or borrower
168 lender = self._get_user(lender_name)
169 borrower = self._get_user(borrower_name)
170
171 if lender is None or borrower is None:
172 return json.dumps({"error": "User not found"})
173
174 # Update lender's owed_by
175 if borrower_name in lender["owed_by"]:
176 lender["owed_by"][borrower_name] += amount
177 else:
178 lender["owed_by"][borrower_name] = amount
179
180 # Update borrower's owes
181 if lender_name in borrower["owes"]:
182 borrower["owes"][lender_name] += amount
183 else:
184 borrower["owes"][lender_name] = amount
185
186 # Update balances
187 self._update_user_balance(lender)
188 self._update_user_balance(borrower)
189
190 # Return updated users sorted by name
191 updated_users = [lender, borrower]
192 updated_users.sort(key=lambda x: x["name"])
193
194 return json.dumps({"users": updated_users})
195 # Handled Edge Cases: Missing fields, invalid amount, same lender and borrower, non-existent users, valid IOU
196
197 return json.dumps({"error": "Invalid URL"})
198 # Handled Edge Cases: Missing payload, invalid JSON payload, invalid URL
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.