sn62

Finished
1import json
2
13class RestAPI:
24 def __init__(self, database: dict | None = None):
3 pass
4
5 """
6 Initialize the REST API with an optional database.
7
8 Args:
9 database: A dictionary containing initial user data.
10 """
11 if database is None:
12 self.database = {"users": []}
13 else:
14 self.database = database
15
516 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
17 """
18 Handle GET requests to the API.
19
20 Args:
21 url: The endpoint URL.
22 payload: Optional JSON payload.
23
24 Returns:
25 A JSON string response.
26 """
27 if url == "/users":
28 if payload is None:
29 # Return all users sorted by name
30 users = [self._create_user_object(user) for user in self.database["users"]]
31 users.sort(key=lambda x: x["name"])
32 return json.dumps({"users": users})
33 else:
34 # Return specified users sorted by name
35 data = json.loads(payload)
36 user_names = data.get("users", [])
37
38 # Edge Case: Handle empty users list
39 if not user_names:
40 return json.dumps({"users": []})
41
42 # Edge Case: Handle non-existent users
43 users = []
44 for user_name in user_names:
45 user = self._find_user(user_name)
46 if user:
47 users.append(self._create_user_object(user))
48
49 users.sort(key=lambda x: x["name"])
50 return json.dumps({"users": users})
51
52 # Edge Case: Handle unknown endpoints
53 return json.dumps({"error": "Not found"})
54
855 def post(self, url: str, payload: str | None = None) -> str:
9 pass
56 """
57 Handle POST requests to the API.
58
59 Args:
60 url: The endpoint URL.
61 payload: JSON payload.
62
63 Returns:
64 A JSON string response.
65 """
66 if payload is None:
67 # Edge Case: Handle missing payload
68 return json.dumps({"error": "Payload required"})
69
70 data = json.loads(payload)
71
72 if url == "/add":
73 user_name = data.get("user")
74
75 # Edge Case: Handle missing user name
76 if not user_name:
77 return json.dumps({"error": "User name required"})
78
79 # Edge Case: Handle duplicate user
80 if self._find_user(user_name):
81 return json.dumps({"error": "User already exists"})
82
83 new_user = {
84 "name": user_name,
85 "owes": {},
86 "owed_by": {}
87 }
88 self.database["users"].append(new_user)
89 return json.dumps(self._create_user_object(new_user))
90
91 elif url == "/iou":
92 lender_name = data.get("lender")
93 borrower_name = data.get("borrower")
94 amount = data.get("amount")
95
96 # Edge Case: Handle missing fields
97 if not lender_name or not borrower_name or amount is None:
98 return json.dumps({"error": "Lender, borrower, and amount required"})
99
100 # Edge Case: Handle non-numeric amount
101 try:
102 amount = float(amount)
103 except (ValueError, TypeError):
104 return json.dumps({"error": "Amount must be a number"})
105
106 # Edge Case: Handle negative amount
107 if amount < 0:
108 return json.dumps({"error": "Amount must be positive"})
109
110 lender = self._find_user(lender_name)
111 borrower = self._find_user(borrower_name)
112
113 # Edge Case: Handle non-existent users
114 if not lender or not borrower:
115 return json.dumps({"error": "Both users must exist"})
116
117 # Edge Case: Handle same lender and borrower
118 if lender_name == borrower_name:
119 return json.dumps({"error": "Cannot create IOU between same user"})
120
121 # Update lender's owed_by
122 if borrower_name in lender["owed_by"]:
123 lender["owed_by"][borrower_name] += amount
124 else:
125 lender["owed_by"][borrower_name] = amount
126
127 # Update borrower's owes
128 if lender_name in borrower["owes"]:
129 borrower["owes"][lender_name] += amount
130 else:
131 borrower["owes"][lender_name] = amount
132
133 # Clean up zero balances
134 if lender["owed_by"].get(borrower_name, 0) == 0:
135 del lender["owed_by"][borrower_name]
136 if borrower["owes"].get(lender_name, 0) == 0:
137 del borrower["owes"][lender_name]
138
139 # Return updated user objects
140 users = [
141 self._create_user_object(lender),
142 self._create_user_object(borrower)
143 ]
144 users.sort(key=lambda x: x["name"])
145 return json.dumps({"users": users})
146
147 # Edge Case: Handle unknown endpoints
148 return json.dumps({"error": "Not found"})
149
150 def _find_user(self, name: str):
151 """
152 Find a user by name in the database.
153
154 Args:
155 name: The name of the user to find.
156
157 Returns:
158 The user dictionary if found, None otherwise.
159 """
160 for user in self.database["users"]:
161 if user["name"] == name:
162 return user
163 return None
164
165 def _create_user_object(self, user: dict):
166 """
167 Create a user object with calculated balance.
168
169 Args:
170 user: The user dictionary.
171
172 Returns:
173 A user object with name, owes, owed_by, and balance.
174 """
175 total_owed_by = sum(user["owed_by"].values())
176 total_owes = sum(user["owes"].values())
177 balance = round(total_owed_by - total_owes, 2)
178
179 # Edge Case: Handle floating point precision issues
180 if balance == -0.0:
181 balance = 0.0
182
183 return {
184 "name": user["name"],
185 "owes": user["owes"],
186 "owed_by": user["owed_by"],
187 "balance": balance
188 }
189# Handled Edge Cases: Missing payload, unknown endpoints
190# Handled Edge Cases: Empty users list, non-existent users, unknown endpoints
191# Handled Edge Cases: Missing user name, duplicate user, missing fields, non-numeric amount, negative amount, non-existent users, same lender and borrower, unknown endpoints, floating point precision issues
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.