Alone

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 or None to start with an empty database.
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 Raises:
28 ValueError: If the URL is not recognized.
29 """
30 if url == "/users":
31 if payload is None:
32 # Return all users sorted by name
33 users = sorted(self.database["users"], key=lambda x: x["name"])
34 return json.dumps({"users": users})
35 else:
36 # Return only specified users
37 data = json.loads(payload)
38 user_names = data.get("users", [])
39
40 # Edge Case: Empty user list in payload
41 if not user_names:
42 return json.dumps({"users": []})
43
44 # Filter users by name
45 filtered_users = [user for user in self.database["users"] if user["name"] in user_names]
46
47 # Edge Case: Non-existent users in payload
48 # Only return users that exist in the database
49
50 # Sort by name
51 filtered_users.sort(key=lambda x: x["name"])
52 return json.dumps({"users": filtered_users})
53 else:
54 # Edge Case: Invalid URL
55 raise ValueError(f"Invalid URL: {url}")
56
857 def post(self, url: str, payload: str | None = None) -> str:
9 pass
58 """
59 Handle POST requests to the API.
60
61 Args:
62 url: The endpoint URL.
63 payload: JSON payload.
64
65 Returns:
66 A JSON string response.
67
68 Raises:
69 ValueError: If the URL is not recognized or if there are validation errors.
70 """
71 if url == "/add":
72 if payload is None:
73 # Edge Case: Missing payload
74 raise ValueError("Payload required for /add endpoint")
75
76 data = json.loads(payload)
77 user_name = data.get("user")
78
79 # Edge Case: Missing user name in payload
80 if not user_name:
81 raise ValueError("User name is required")
82
83 # Edge Case: User already exists
84 for user in self.database["users"]:
85 if user["name"] == user_name:
86 return json.dumps(user)
87
88 # Create new user
89 new_user = {
90 "name": user_name,
91 "owes": {},
92 "owed_by": {},
93 "balance": 0.0
94 }
95
96 self.database["users"].append(new_user)
97 return json.dumps(new_user)
98
99 elif url == "/iou":
100 if payload is None:
101 # Edge Case: Missing payload
102 raise ValueError("Payload required for /iou endpoint")
103
104 data = json.loads(payload)
105 lender_name = data.get("lender")
106 borrower_name = data.get("borrower")
107 amount = data.get("amount")
108
109 # Edge Case: Missing required fields
110 if not lender_name or not borrower_name or amount is None:
111 raise ValueError("Lender, borrower, and amount are required")
112
113 # Edge Case: Lender and borrower are the same person
114 if lender_name == borrower_name:
115 raise ValueError("Lender and borrower cannot be the same person")
116
117 # Edge Case: Negative amount
118 if amount < 0:
119 raise ValueError("Amount must be non-negative")
120
121 # Find lender and borrower
122 lender = None
123 borrower = None
124
125 for user in self.database["users"]:
126 if user["name"] == lender_name:
127 lender = user
128 elif user["name"] == borrower_name:
129 borrower = user
130
131 # Edge Case: Lender or borrower does not exist
132 if lender is None:
133 raise ValueError(f"User {lender_name} does not exist")
134 if borrower is None:
135 raise ValueError(f"User {borrower_name} does not exist")
136
137 # Handle the IOU transaction with proper netting
138 # Get existing debts
139 borrower_owes_lender = borrower["owes"].get(lender_name, 0) # How much borrower owes lender
140 lender_owes_borrower = lender["owes"].get(borrower_name, 0) # How much lender owes borrower
141
142 # Calculate net change in what borrower owes lender
143 # Positive means borrower owes more to lender
144 # Negative means lender owes more to borrower
145 net_change = amount - lender_owes_borrower + borrower_owes_lender
146
147 # Update the relationships based on the net amount
148 if net_change > 0:
149 # Borrower owes lender money
150 borrower["owes"][lender_name] = net_change
151 lender["owed_by"][borrower_name] = net_change
152 # Remove reverse relationships
153 if lender_name in borrower["owed_by"]:
154 del borrower["owed_by"][lender_name]
155 if borrower_name in lender["owes"]:
156 del lender["owes"][borrower_name]
157 elif net_change < 0:
158 # Lender owes borrower money
159 lender["owes"][borrower_name] = -net_change
160 borrower["owed_by"][lender_name] = -net_change
161 # Remove reverse relationships
162 if lender_name in borrower["owes"]:
163 del borrower["owes"][lender_name]
164 if borrower_name in lender["owed_by"]:
165 del lender["owed_by"][borrower_name]
166 else:
167 # Debts cancel out exactly
168 if lender_name in borrower["owes"]:
169 del borrower["owes"][lender_name]
170 if lender_name in borrower["owed_by"]:
171 del borrower["owed_by"][lender_name]
172 if borrower_name in lender["owes"]:
173 del lender["owes"][borrower_name]
174 if borrower_name in lender["owed_by"]:
175 del lender["owed_by"][borrower_name]
176
177 # Recalculate balances for both users
178 lender_total_owed = sum(lender["owed_by"].values())
179 lender_total_owes = sum(lender["owes"].values())
180 lender["balance"] = lender_total_owed - lender_total_owes
181
182 borrower_total_owed = sum(borrower["owed_by"].values())
183 borrower_total_owes = sum(borrower["owes"].values())
184 borrower["balance"] = borrower_total_owed - borrower_total_owes
185
186 # Return updated users sorted by name
187 updated_users = [lender, borrower]
188 updated_users.sort(key=lambda x: x["name"])
189 return json.dumps({"users": updated_users})
190
191 else:
192 # Edge Case: Invalid URL
193 raise ValueError(f"Invalid URL: {url}")
194
195 # Handled Edge Cases: Invalid URL, Missing payload, Missing user name, User already exists
196 # Handled Edge Cases: Missing required fields, Lender and borrower are the same, Negative amount,
197 # Lender or borrower does not exist, Empty user list in payload, Non-existent users in payload
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.