hlydecker commited on
Commit
39a23e4
·
verified ·
1 Parent(s): 280b1e8

patch: o1 fixes

Browse files
Files changed (1) hide show
  1. app.py +220 -206
app.py CHANGED
@@ -1,206 +1,220 @@
1
- import gradio as gr
2
- import pandas as pd
3
- import numpy as np
4
-
5
- # Global variables
6
- expenses = []
7
- participants_set = set()
8
-
9
- def add_participant(participant):
10
- global participants_set
11
- if not participant or not participant.strip():
12
- raise gr.Error("Participant name cannot be empty")
13
-
14
- clean_name = participant.strip()
15
- participants_set.add(clean_name)
16
- participants_list = sorted(list(participants_set)) # Sort for consistent display
17
- participants_text = "\n".join(participants_list)
18
-
19
- # Return updated participant list for dropdowns
20
- return participants_text, participants_list, participants_list
21
-
22
- def remove_participant(participant):
23
- global participants_set
24
- if participant in participants_set:
25
- participants_set.remove(participant)
26
- participants_list = sorted(list(participants_set)) # Sort for consistent display
27
- participants_text = "\n".join(participants_list)
28
-
29
- # Return updated participant list for dropdowns
30
- return participants_text, participants_list, participants_list
31
-
32
- # Add expenses
33
- def add_expense(description, amount, payer, participants_list):
34
- global expenses
35
-
36
- # Validate inputs
37
- if not description or not description.strip():
38
- raise gr.Error("Description cannot be empty")
39
-
40
- if amount <= 0:
41
- raise gr.Error("Amount must be a positive number")
42
-
43
- if not payer:
44
- raise gr.Error("Payer cannot be empty")
45
-
46
- if not participants_list:
47
- raise gr.Error("Participants cannot be empty")
48
-
49
- # Ensure all are unique
50
- unique_participants = list(set(participants_list + [payer]))
51
-
52
- amount = float(amount)
53
- expense = {
54
- "Description": description,
55
- "Amount": amount,
56
- "Payer": payer,
57
- "Participants": ", ".join(unique_participants),
58
- "Split Amount": round(amount / len(unique_participants), 2),
59
- }
60
- expenses.append(expense)
61
- return pd.DataFrame(expenses)
62
-
63
- # Optimize Balances (same as previous implementation)
64
- def optimize_balances():
65
- global expenses
66
-
67
- # Create a comprehensive balance sheet
68
- balances = {}
69
-
70
- for expense in expenses:
71
- payer = expense["Payer"]
72
- participants_list = expense["Participants"].split(", ")
73
- total_amount = expense["Amount"]
74
- split_amount = total_amount / len(participants_list)
75
-
76
- # Payer gets credit for the entire amount
77
- balances[payer] = balances.get(payer, 0) + total_amount
78
-
79
- # Participants owe their share
80
- for participant in participants_list:
81
- if participant != payer:
82
- balances[participant] = balances.get(participant, 0) - split_amount
83
-
84
- # Simplify debts
85
- def simplify_debts(balances):
86
- # Round balances to avoid floating-point errors
87
- rounded_balances = {k: round(v, 2) for k, v in balances.items()}
88
-
89
- # Separate creditors and debtors
90
- debtors = {k: v for k, v in rounded_balances.items() if v < -0.01}
91
- creditors = {k: v for k, v in rounded_balances.items() if v > 0.01}
92
-
93
- transactions = []
94
-
95
- # Continue until all debts are settled
96
- while debtors and creditors:
97
- # Find the most negative debtor and the largest creditor
98
- debtor = min(debtors, key=debtors.get)
99
- creditor = max(creditors, key=creditors.get)
100
-
101
- # Amount to settle is the minimum of absolute debt and credit
102
- settle_amount = min(abs(debtors[debtor]), creditors[creditor])
103
-
104
- # Round to 2 decimal places
105
- settle_amount = round(settle_amount, 2)
106
-
107
- # Add transaction
108
- transactions.append(f"{debtor} pays {creditor} ${settle_amount:.2f}")
109
-
110
- # Update balances
111
- debtors[debtor] += settle_amount
112
- creditors[creditor] -= settle_amount
113
-
114
- # Remove if balance is effectively zero
115
- if abs(debtors[debtor]) < 0.01:
116
- del debtors[debtor]
117
- if abs(creditors[creditor]) < 0.01:
118
- del creditors[creditor]
119
-
120
- return transactions if transactions else ["No transactions needed"]
121
-
122
- return simplify_debts(balances)
123
-
124
- # Reset App
125
- def reset():
126
- global expenses
127
- expenses = []
128
- return pd.DataFrame(expenses), []
129
-
130
- # Gradio Interface
131
- with gr.Blocks(theme='soft') as app:
132
- gr.Markdown("# Expense Splitter App")
133
-
134
- # Participant Management
135
- with gr.Row():
136
- with gr.Column():
137
- participant_input = gr.Textbox(label="Participant Name", placeholder="Enter a participant name")
138
- with gr.Row():
139
- add_participant_btn = gr.Button("Add Participant")
140
- remove_participant_btn = gr.Button("Remove Participant")
141
-
142
- participants_display = gr.Textbox(
143
- label="Current Participants",
144
- lines=10,
145
- interactive=False,
146
- placeholder="Participants will appear here..."
147
- )
148
-
149
- # Expense Adding
150
- with gr.Row():
151
- with gr.Column():
152
- description = gr.Textbox(label="Description", placeholder="e.g., Dinner")
153
- amount = gr.Number(label="Amount", value=0, precision=2)
154
-
155
- payer = gr.Dropdown(
156
- label="Payer",
157
- choices=[],
158
- interactive=True
159
- )
160
-
161
- participants = gr.Dropdown(
162
- label="Participants",
163
- multiselect=True,
164
- choices=[],
165
- interactive=True
166
- )
167
-
168
- add_btn = gr.Button("Add Expense")
169
-
170
- with gr.Column():
171
- expense_table = gr.Dataframe(
172
- headers=["Description", "Amount", "Payer", "Participants", "Split Amount"],
173
- datatype=["str", "number", "str", "str", "number"],
174
- type="pandas"
175
- )
176
-
177
- # Button Interactions
178
- add_participant_btn.click(
179
- add_participant,
180
- inputs=participant_input,
181
- outputs=[participants_display, payer, participants]
182
- )
183
-
184
- remove_participant_btn.click(
185
- remove_participant,
186
- inputs=participant_input,
187
- outputs=[participants_display, payer, participants]
188
- )
189
-
190
- add_btn.click(
191
- add_expense,
192
- inputs=[description, amount, payer, participants],
193
- outputs=expense_table
194
- )
195
-
196
- with gr.Row():
197
- optimize_btn = gr.Button("Optimize Balances")
198
- result = gr.Textbox(label="Transactions", lines=5)
199
- reset_btn = gr.Button("Reset")
200
-
201
- optimize_btn.click(optimize_balances, inputs=[], outputs=result)
202
- reset_btn.click(reset, inputs=[], outputs=[expense_table, result])
203
-
204
- # Launch the app
205
- if __name__ == "__main__":
206
- app.launch(share=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+
5
+ # Global variables
6
+ expenses = []
7
+ participants_set = set()
8
+
9
+ def add_participant(participant):
10
+ global participants_set
11
+ if not participant or not participant.strip():
12
+ raise gr.Error("Participant name cannot be empty")
13
+
14
+ clean_name = participant.strip()
15
+ participants_set.add(clean_name)
16
+ participants_list = sorted(list(participants_set)) # Sort for consistent display
17
+ participants_text = "\n".join(participants_list)
18
+
19
+ # Return updated participant list for dropdowns
20
+ return participants_text, \
21
+ gr.Dropdown.update(choices=participants_list), \
22
+ gr.Dropdown.update(choices=participants_list)
23
+
24
+ def remove_participant(participant):
25
+ global participants_set
26
+ participant = participant.strip()
27
+ if participant in participants_set:
28
+ participants_set.remove(participant)
29
+ participants_list = sorted(list(participants_set)) # Sort for consistent display
30
+ participants_text = "\n".join(participants_list)
31
+
32
+ # Return updated participant list for dropdowns
33
+ return participants_text, \
34
+ gr.Dropdown.update(choices=participants_list), \
35
+ gr.Dropdown.update(choices=participants_list)
36
+
37
+ # Add expenses
38
+ def add_expense(description, amount, payer, participants_list):
39
+ global expenses
40
+
41
+ # Validate inputs
42
+ if not description or not description.strip():
43
+ raise gr.Error("Description cannot be empty")
44
+
45
+ if amount <= 0:
46
+ raise gr.Error("Amount must be a positive number")
47
+
48
+ if not payer:
49
+ raise gr.Error("Payer cannot be empty")
50
+
51
+ if not participants_list:
52
+ raise gr.Error("Participants cannot be empty")
53
+
54
+ # Ensure all are unique
55
+ unique_participants = list(set(participants_list + [payer]))
56
+
57
+ amount = float(amount)
58
+ expense = {
59
+ "Description": description,
60
+ "Amount": amount,
61
+ "Payer": payer,
62
+ "Participants": ", ".join(unique_participants),
63
+ "Split Amount": round(amount / len(unique_participants), 2),
64
+ }
65
+ expenses.append(expense)
66
+ return pd.DataFrame(expenses)
67
+
68
+ # Optimize Balances (same as previous implementation)
69
+ def optimize_balances():
70
+ global expenses
71
+
72
+ # Create a comprehensive balance sheet
73
+ balances = {}
74
+
75
+ for expense in expenses:
76
+ payer = expense["Payer"]
77
+ participants_list = expense["Participants"].split(", ")
78
+ total_amount = expense["Amount"]
79
+ split_amount = total_amount / len(participants_list)
80
+
81
+ # Payer gets credit for the entire amount
82
+ balances[payer] = balances.get(payer, 0) + total_amount
83
+
84
+ # Participants owe their share
85
+ for participant in participants_list:
86
+ if participant != payer:
87
+ balances[participant] = balances.get(participant, 0) - split_amount
88
+
89
+ # Simplify debts
90
+ def simplify_debts(balances):
91
+ # Round balances to avoid floating-point errors
92
+ rounded_balances = {k: round(v, 2) for k, v in balances.items()}
93
+
94
+ # Separate creditors and debtors
95
+ debtors = {k: v for k, v in rounded_balances.items() if v < -0.01}
96
+ creditors = {k: v for k, v in rounded_balances.items() if v > 0.01}
97
+
98
+ transactions = []
99
+
100
+ # Continue until all debts are settled
101
+ while debtors and creditors:
102
+ # Find the most negative debtor and the largest creditor
103
+ debtor = min(debtors, key=debtors.get)
104
+ creditor = max(creditors, key=creditors.get)
105
+
106
+ # Amount to settle is the minimum of absolute debt and credit
107
+ settle_amount = min(abs(debtors[debtor]), creditors[creditor])
108
+
109
+ # Round to 2 decimal places
110
+ settle_amount = round(settle_amount, 2)
111
+
112
+ # Add transaction
113
+ transactions.append(f"{debtor} pays {creditor} ${settle_amount:.2f}")
114
+
115
+ # Update balances
116
+ debtors[debtor] += settle_amount
117
+ creditors[creditor] -= settle_amount
118
+
119
+ # Remove if balance is effectively zero
120
+ if abs(debtors[debtor]) < 0.01:
121
+ del debtors[debtor]
122
+ if abs(creditors[creditor]) < 0.01:
123
+ del creditors[creditor]
124
+
125
+ return transactions if transactions else ["No transactions needed"]
126
+
127
+ return simplify_debts(balances)
128
+
129
+ # Reset App
130
+ def reset():
131
+ global expenses, participants_set
132
+ expenses = []
133
+ participants_set = set()
134
+ participants_list = []
135
+ participants_text = ""
136
+ return pd.DataFrame(expenses), [], participants_text, \
137
+ gr.Dropdown.update(choices=participants_list, value=None), \
138
+ gr.Dropdown.update(choices=participants_list, value=None)
139
+
140
+ # Gradio Interface
141
+ with gr.Blocks(theme='soft') as app:
142
+ gr.Markdown("# Expense Splitter App")
143
+
144
+ # Participant Management
145
+ with gr.Row():
146
+ with gr.Column():
147
+ participant_input = gr.Textbox(label="Participant Name", placeholder="Enter a participant name")
148
+ with gr.Row():
149
+ add_participant_btn = gr.Button("Add Participant")
150
+ remove_participant_btn = gr.Button("Remove Participant")
151
+
152
+ participants_display = gr.Textbox(
153
+ label="Current Participants",
154
+ lines=10,
155
+ interactive=False,
156
+ placeholder="Participants will appear here..."
157
+ )
158
+
159
+ # Expense Adding
160
+ with gr.Row():
161
+ with gr.Column():
162
+ description = gr.Textbox(label="Description", placeholder="e.g., Dinner")
163
+ amount = gr.Number(label="Amount", value=0, precision=2)
164
+
165
+ payer = gr.Dropdown(
166
+ label="Payer",
167
+ choices=[],
168
+ interactive=True
169
+ )
170
+
171
+ participants = gr.Dropdown(
172
+ label="Participants",
173
+ multiselect=True,
174
+ choices=[],
175
+ interactive=True
176
+ )
177
+
178
+ add_btn = gr.Button("Add Expense")
179
+
180
+ with gr.Column():
181
+ expense_table = gr.Dataframe(
182
+ headers=["Description", "Amount", "Payer", "Participants", "Split Amount"],
183
+ datatype=["str", "number", "str", "str", "number"],
184
+ type="pandas"
185
+ )
186
+
187
+ # Button Interactions
188
+ add_participant_btn.click(
189
+ add_participant,
190
+ inputs=participant_input,
191
+ outputs=[participants_display, payer, participants]
192
+ )
193
+
194
+ remove_participant_btn.click(
195
+ remove_participant,
196
+ inputs=participant_input,
197
+ outputs=[participants_display, payer, participants]
198
+ )
199
+
200
+ add_btn.click(
201
+ add_expense,
202
+ inputs=[description, amount, payer, participants],
203
+ outputs=expense_table
204
+ )
205
+
206
+ with gr.Row():
207
+ optimize_btn = gr.Button("Optimize Balances")
208
+ result = gr.Textbox(label="Transactions", lines=5)
209
+ reset_btn = gr.Button("Reset")
210
+
211
+ optimize_btn.click(optimize_balances, inputs=[], outputs=result)
212
+ reset_btn.click(
213
+ reset,
214
+ inputs=[],
215
+ outputs=[expense_table, result, participants_display, payer, participants]
216
+ )
217
+
218
+ # Launch the app
219
+ if __name__ == "__main__":
220
+ app.launch(share=True)