jackson

Finished
1import json
2
13class RestAPI:
24 def __init__(self, database: dict | None = None):
3 pass
4
5 # Edge Case: Handle None database by initializing empty structure
6 if database is None:
7 self.database = {"users": []}
8 else:
9 self.database = database
10
511 def get(self, url: str, payload: str | None = None) -> str:
6 pass
7
12 # Edge Case: Handle invalid URL
13 if url != "/users":
14 return json.dumps({"error": "Invalid URL"})
15
16 # Edge Case: Handle invalid payload format
17 if payload is not None:
18 try:
19 payload_data = json.loads(payload)
20 except json.JSONDecodeError:
21 return json.dumps({"error": "Invalid payload format"})
22
23 # Edge Case: Handle missing 'users' key in payload
24 if "users" not in payload_data:
25 return json.dumps({"error": "Missing 'users' key in payload"})
26
27 # Edge Case: Handle non-list 'users' value in payload
28 if not isinstance(payload_data["users"], list):
29 return json.dumps({"error": "'users' must be a list"})
30
31 # Filter users based on payload
32 users_list = []
33 for user_name in payload_data["users"]:
34 user = self._get_user_by_name(user_name)
35 # Edge Case: Handle user not found
36 if user is not None:
37 users_list.append(user)
38
39 # Sort users by name
40 users_list.sort(key=lambda x: x["name"])
41 return json.dumps({"users": users_list})
42 else:
43 # Return all users sorted by name
44 users_list = self.database["users"].copy()
45 users_list.sort(key=lambda x: x["name"])
46 return json.dumps({"users": users_list})
47
848 def post(self, url: str, payload: str | None = None) -> str:
9 pass
49 # Edge Case: Handle invalid URL
50 if url not in ["/add", "/iou"]:
51 return json.dumps({"error": "Invalid URL"})
52
53 # Edge Case: Handle missing payload
54 if payload is None:
55 return json.dumps({"error": "Missing payload"})
56
57 # Edge Case: Handle invalid payload format
58 try:
59 payload_data = json.loads(payload)
60 except json.JSONDecodeError:
61 return json.dumps({"error": "Invalid payload format"})
62
63 if url == "/add":
64 # Edge Case: Handle missing 'user' key in payload
65 if "user" not in payload_data:
66 return json.dumps({"error": "Missing 'user' key in payload"})
67
68 user_name = payload_data["user"]
69
70 # Edge Case: Handle non-string user name
71 if not isinstance(user_name, str):
72 return json.dumps({"error": "User name must be a string"})
73
74 # Edge Case: Handle duplicate user
75 if self._get_user_by_name(user_name) is not None:
76 return json.dumps({"error": "User already exists"})
77
78 # Create new user
79 new_user = {
80 "name": user_name,
81 "owes": {},
82 "owed_by": {},
83 "balance": 0.0
84 }
85 self.database["users"].append(new_user)
86 return json.dumps(new_user)
87
88 elif url == "/iou":
89 # Edge Case: Handle missing required keys in payload
90 required_keys = ["lender", "borrower", "amount"]
91 for key in required_keys:
92 if key not in payload_data:
93 return json.dumps({"error": f"Missing '{key}' key in payload"})
94
95 lender_name = payload_data["lender"]
96 borrower_name = payload_data["borrower"]
97 amount = payload_data["amount"]
98
99 # Edge Case: Handle non-string lender or borrower
100 if not isinstance(lender_name, str) or not isinstance(borrower_name, str):
101 return json.dumps({"error": "Lender and borrower must be strings"})
102
103 # Edge Case: Handle non-numeric amount
104 if not isinstance(amount, (int, float)):
105 return json.dumps({"error": "Amount must be a number"})
106
107 # Edge Case: Handle negative amount
108 if amount < 0:
109 return json.dumps({"error": "Amount must be positive"})
110
111 # Edge Case: Handle same lender and borrower
112 if lender_name == borrower_name:
113 return json.dumps({"error": "Lender and borrower cannot be the same"})
114
115 lender = self._get_user_by_name(lender_name)
116 borrower = self._get_user_by_name(borrower_name)
117
118 # Edge Case: Handle lender or borrower not found
119 if lender is None:
120 return json.dumps({"error": "Lender not found"})
121 if borrower is None:
122 return json.dumps({"error": "Borrower not found"})
123
124 # Edge Case: Handle zero amount - no IOU should be recorded
125 if amount == 0:
126 # Return users without any changes
127 users_list = [lender, borrower]
128 users_list.sort(key=lambda x: x["name"])
129 return json.dumps({"users": users_list})
130
131 # Update IOUs
132 # Update lender's owed_by
133 if borrower_name in lender["owed_by"]:
134 lender["owed_by"][borrower_name] += amount
135 else:
136 lender["owed_by"][borrower_name] = amount
137
138 # Update borrower's owes
139 if lender_name in borrower["owes"]:
140 borrower["owes"][lender_name] += amount
141 else:
142 borrower["owes"][lender_name] = amount
143
144 # Recalculate balances
145 self._recalculate_balance(lender)
146 self._recalculate_balance(borrower)
147
148 # Return updated users sorted by name
149 users_list = [lender, borrower]
150 users_list.sort(key=lambda x: x["name"])
151 return json.dumps({"users": users_list})
152
153 def _get_user_by_name(self, name: str):
154 for user in self.database["users"]:
155 if user["name"] == name:
156 return user
157 return None
158
159 def _recalculate_balance(self, user):
160 total_owed_by = sum(user["owed_by"].values())
161 total_owes = sum(user["owes"].values())
162 user["balance"] = round(total_owed_by - total_owes, 2)
163
164# Handled Edge Cases: None database, invalid URL, invalid payload format, missing 'users' key, non-list 'users' value, user not found, missing payload, missing 'user' key, non-string user name, duplicate user, missing required keys, non-string lender/borrower, non-numeric amount, negative amount, same lender/borrower, lender/borrower not found
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.