From 891dfa8834554ce35e4720c8686c728070212243 Mon Sep 17 00:00:00 2001 From: dognutss Date: Wed, 28 Jan 2026 14:46:02 -0800 Subject: [PATCH 1/4] Refactored expense to use id --- .../datasource/IDataSource.java | 8 ++++++++ .../ucsd/spendingtracker/model/Expense.java | 13 +++++++++++++ .../datasource/IDataSource.class | Bin 0 -> 330 bytes .../ucsd/spendingtracker/model/Expense.class | Bin 879 -> 1199 bytes 4 files changed, 21 insertions(+) create mode 100644 src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java create mode 100644 target/classes/edu/ucsd/spendingtracker/datasource/IDataSource.class diff --git a/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java b/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java new file mode 100644 index 0000000..d3da38d --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java @@ -0,0 +1,8 @@ +package edu.ucsd.spendingtracker.datasource; + +import java.util.List; + + +public class IDataSource { + +} diff --git a/src/main/java/edu/ucsd/spendingtracker/model/Expense.java b/src/main/java/edu/ucsd/spendingtracker/model/Expense.java index 3b73dca..aea1c9b 100644 --- a/src/main/java/edu/ucsd/spendingtracker/model/Expense.java +++ b/src/main/java/edu/ucsd/spendingtracker/model/Expense.java @@ -4,11 +4,20 @@ public class Expense { private String name; private Category category; private double amount; + private int id; public Expense(String name, Category category, double amount) { this.name = name; this.category = category; this.amount = amount; + this.id = -1; + } + + public Expense(String name, Category category, double amount, int id) { + this.name = name; + this.category = category; + this.amount = amount; + this.id = id; } public String getName() { @@ -22,6 +31,10 @@ public Category getCategory() { public double getAmount() { return amount; } + + public int getId() { + return id; + } } diff --git a/target/classes/edu/ucsd/spendingtracker/datasource/IDataSource.class b/target/classes/edu/ucsd/spendingtracker/datasource/IDataSource.class new file mode 100644 index 0000000000000000000000000000000000000000..2bad1a69e1eb85baddeb62032939adf926b7572a GIT binary patch literal 330 zcmb7fDWXGBcgMC`m*61B;lG%W82A7_3h|sW zu(F(Y@3Ul`_x1hp3E&20j)WkL?nSRUExH%uv~}y?rFt@6Xc=VJ_Ffq=zvH|da*mWx zZsn^KjdW|VsJBK1!uZNM8?FhX)3X&Jy=}EAFv9)>8ODTZWu1BGpKIeEW!)IUan&l> ztfaTG|1Q(8u^r)}`lr?LlObn354jPJmfgc5Pj=>HHk~pe9*)cD72K=Mfk!E1XL|Zk)m>FmAm7tg4@JFj*Z~P4?+SY zA|wv{0DctW?bf7H8mX0#CGX7ayqPy|_V=HkzX0sRDZmiem4n1h{OQ1*zLVh~2#0ax z`DZe6$CH5^xvxGjJe37x1uCcBd(Rzt;n024Kb3wgkPW@D6sUGDu8!k~Rh|m0_+BiB zljx&>-MymCL7GZf-WyMnkhR63fDsI6bQpaWghBjV;6?j#uWMI7w0q=yz{yI;VBN$j zssfp|-77+%ZX$=gvTm9vU`1I?6GfDiWtk|$6j7X`{s zgW33PFcoND#Vr+>gTMT*$vSGZ!cfLXdL#9=eOV`gG86u3EwIO=>o2BA?0&i%O2+Nv z80m09^thtZ@g#|S`8rUVnCV=P)x*F&>X+fG%fe6+(=wF6`lP)2q_{lu%v{9{{@3Uw zMCEw4oFAw-do$FWM>8}Wdxj0in4$GeLvQhK>9R$(C~;$DmM~FcsV1#W-aEWuA>76t zp2|{0gtinFLtBbWMpL+(Qust)5w@05Xyle~sIb#IIaJxX#;?v^4b9<+9>$t;u;v^r zEr;S@srRPEvebKHhQO8&N8~)1N`)~8;@1miJ{Yx~Mmh@Q1s&2~ufmkeb+=7NX%V@jvjMR-Yx^J3C z^i_NLPK}a0isXVsz<}?-0fF1Rqbc@`B(k*fbDp0YeyHoa7(G&HsR(9{SUnQ1V sOSYMNhby(P@;2;qPynava9Ri-awPaN{Cc9S|LE>~ExKPwALm;qe^~w@YXATM From 486e45db75d753cfefa63204e5987c386d91b6d8 Mon Sep 17 00:00:00 2001 From: dognutss Date: Wed, 28 Jan 2026 14:58:42 -0800 Subject: [PATCH 2/4] Refactored ExpenseRepository to use IDataSource interface --- .../datasource/IDataSource.java | 9 ++++-- .../datasource/InMemoryDataSource.java | 30 ++++++++++-------- .../edu/ucsd/spendingtracker/model/Model.java | 4 +++ .../repository/ExpenseRepository.java | 12 +++++-- .../edu/ucsd/spendingtracker/App.class | Bin 2399 -> 717 bytes .../datasource/IDataSource.class | Bin 330 -> 363 bytes .../datasource/InMemoryDataSource.class | Bin 1847 -> 2026 bytes .../ucsd/spendingtracker/model/Model.class | Bin 1031 -> 1152 bytes .../repository/ExpenseRepository.class | Bin 1408 -> 1523 bytes 9 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java b/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java index d3da38d..271cbc8 100644 --- a/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java +++ b/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java @@ -2,7 +2,12 @@ import java.util.List; +import edu.ucsd.spendingtracker.model.Expense; -public class IDataSource { - +public interface IDataSource { + List getExpenses(); + + void addExpense(Expense expense); + + void deleteExpense(int id); } diff --git a/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java b/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java index c71abcd..908f914 100644 --- a/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java +++ b/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java @@ -6,29 +6,31 @@ import edu.ucsd.spendingtracker.model.Category; import edu.ucsd.spendingtracker.model.Expense; -public class InMemoryDataSource { +public class InMemoryDataSource implements IDataSource{ private List expenses = new ArrayList<>(); - public InMemoryDataSource() { - } - + @Override public List getExpenses() { return List.copyOf(expenses); } - + @Override public void addExpense(Expense expense) { expenses.add(expense); } - public final static List DEFAULT_EXPENSES = List.of( - new Expense("Groceries", Category.FOOD, 150.75), - new Expense("Utilities", Category.UTILITIES, 80.50), - new Expense("Gas", Category.TRANSPORT, 60.00)); - - public static InMemoryDataSource getDefaultDataSource() { - InMemoryDataSource dataSource = new InMemoryDataSource(); - dataSource.expenses.addAll(DEFAULT_EXPENSES); - return dataSource; + public void deleteExpense(int expenseID) { + expenses.removeIf(expense -> expense.getId() == expenseID); } + + // public final static List DEFAULT_EXPENSES = List.of( + // new Expense("Groceries", Category.FOOD, 150.75), + // new Expense("Utilities", Category.UTILITIES, 80.50), + // new Expense("Gas", Category.TRANSPORT, 60.00)); + + // public static InMemoryDataSource getDefaultDataSource() { + // InMemoryDataSource dataSource = new InMemoryDataSource(); + // dataSource.expenses.addAll(DEFAULT_EXPENSES); + // return dataSource; + // } } diff --git a/src/main/java/edu/ucsd/spendingtracker/model/Model.java b/src/main/java/edu/ucsd/spendingtracker/model/Model.java index 97e5c80..41ddd0b 100644 --- a/src/main/java/edu/ucsd/spendingtracker/model/Model.java +++ b/src/main/java/edu/ucsd/spendingtracker/model/Model.java @@ -14,6 +14,10 @@ public void addExpense(Expense e) { repository.addExpense(e); } + public void deleteExpense(int id) { + repository.deleteExpense(id); + } + public List getExpenses() { return repository.getExpenses(); } diff --git a/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java b/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java index 91f5f8e..8694683 100644 --- a/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java +++ b/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java @@ -1,13 +1,14 @@ package edu.ucsd.spendingtracker.repository; import java.util.List; -import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; + +import edu.ucsd.spendingtracker.datasource.IDataSource; import edu.ucsd.spendingtracker.model.Expense; public class ExpenseRepository { - private final InMemoryDataSource dataSource; + private IDataSource dataSource; - public ExpenseRepository(InMemoryDataSource dataSource) { + public ExpenseRepository(IDataSource dataSource) { this.dataSource = dataSource; } @@ -19,6 +20,11 @@ public List getExpenses() { return dataSource.getExpenses(); } + public void deleteExpense(int expenseID) + { + dataSource.deleteExpense(expenseID); + } + public double getTotal() { double total = 0; for (Expense expense : dataSource.getExpenses()) { diff --git a/target/classes/edu/ucsd/spendingtracker/App.class b/target/classes/edu/ucsd/spendingtracker/App.class index ad685f9990d31c62c723e7896a3b6d2a489bd416..8b94c2efd477e7e21386beef45825c3ad1407a01 100644 GIT binary patch delta 322 zcmYL^y-or_6ot>M;>xgwe*{6DSb>EUTG^RkVPRt8Ph#f?1FYGd!C@ew(f9~tA4Z~y z_9i}qZ(_XK*nH=ln{#h+zY3qJ+{gFJ8-ODSA09&^d1AGBYw_qK&yc;7Q`wHB9<-0G zHFgz6hWkrx)!0N+)e~J4kHSd0&}cET<~CCCq2TF@p%SrjL(>xjp6Z91uJnx+j#k`kq{N9nRk5kt*?*sNtbHx>*^-HixMW~jU^CQGRr=Cvw%v-dcAcVXG~Ks5T-xs~B{74`0y8z` z@2ErBuKUA1fm|jVj&P*iyn#7^jZjdoYBfFECl>4R8(xN|o*%E6m_MptGoTJ{7nds?&0nryQSoJ@EEyuwr5fSsm%Jz>5))o**Y5&c~^UdL*n0 ztdD~&2_?BYhn$FIPMBu7!aC12s($}+Dzge z?z7UX>X6mHtC^P--8)#~zn)pSy=u1V(y6hOT{fZ-B#*ew@wDFKnM?>ITdu8Bs@F(Z z|7W!q0aMp_&?p4%hv&iQRzN$$!V$O^ZfAJxbXQMrbh!4YTV~$%L7cF)F_x|O?_R)Y1WC>A zJdTB9kNsL;RFQ_X9f8@*%hPGBpCp03B)&(1uVr1foyrkaq+4S#TslL8*%4&e6I(x* zaXz|=E{0u|^9bC&rx=5EhxRHx?vB;lWxmXuV(VZ zSO>Rr@h;YQX(*e=IHxm z7MEBvGH?cGrspM=loq8jGT2}!u<@BFAgPp_pOTuR4>icz4ycPOF(n1cXJpXU0I5<( zRizom$iNHKmRgbuSIDB_sTnr$x`G)SBLgD?Gtiw349qNy46F=nKt4N=$Hc$^b~w delta 192 zcmaFObc%`V)W2Q(7#J8F83ZPB`3A7rWaed-*fBCNYiNcsGO#%3r=)T*Ff(xSFt9SP zF*5M`Wag#%mF6a;7KJ1x<)kt)2>IkEC+37D7G;9?P(hZGjLc$221B2T0{V>BlSLU7 zf*BMUfTjX%VgS;NAk%;(JCLUj<})y`YHerW*a#G0V&DRjAZZZE4J3KMY*rx63*<2} K@Bv9C27UnEh#u+y diff --git a/target/classes/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.class b/target/classes/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.class index 6c7de2fbd3ca23b7d428524b4e0df2d3b2162f2e..c4574a3f65608cbddaa9ae67f57a5d3cb8efb501 100644 GIT binary patch literal 2026 zcmbVN+j7%L5Iti%QKBfe<3PCW0$~H#2_Wt_X9L86Mc@#?AryI=Sd$=&!*E&H9kbI6Z8K~O z&vv{O8Sv(+2uzzx9{Qc2DNM_o6)itlpCMBtGHJ*$6kqT)Zo1rCG3S;!`0`VYsG^=*^2d|SBY?HIW_ML@li zj_1fJhHSaAz>uqvhmI@?1_oeg7-AUiX1^5#d|gq{QAD9140{Y{=wm3<9Zx*yw3b9L z&zD@HRjT_Jg_2UQUC#!%9S6gCzr`h#-C`(0Di|2 z4Tl->-MUrD299Es8rJmN>vPKt<#H->&39e8YsdGhTM*K@Z6}-=Cd%6v|NZ?`78IG| z22S84T@ZmV>`k(!1XisqGH8ihh}Ul683suWLW&J)xw2JRDA6FCHgEoy$HN1+$fMV!=WW861z8CS?~@26&Av4~j)!}2^4)Lb6YX4LSA;rOQZZq+0W4Ti%z zyV7jO9mOco%+jZaJ{h&&=-E$Wk%1oBXfu*!kSx=YA5a{BkNo(5C_a0S(!Usf6M65Y z?>u>cqH`2mpyvp^sc4G9KJ2F_!vP#5>^Q@r2=_c$l~3RJTMU1|Z?EZh1`4k?vgcDc zeH%E(@CThLUNhvKp{JqZCq7~q7&p~j-Jq8YZqh$^+}*omvrxwa%#lUO?jasy9tXYwRo4fn literal 1847 zcmb7Ee^V1z6g@9uvI#371}Iq3cC03#uD^FBWV35@8=a=nc_G_P ztKITkv+-QIM$`1nj?;A;(kQm?%1y`J%F|W#T`>#@j65@6nucw*TSjH$nQV9hntVl= zj_mNX^JT& znVxL1JUYfO&cw@=N?suSEkPfyWul84@7WR{fg_mGaU4GiM6;oqo2j5uex0kH%NAu0 z44qHcHB3|1I@@4*p{!Fneo{>1>$PI3SSuE)(Z$*+pMr*8Silw2mw#4A%8#q9<;vC7 z%33YDSoXs(h;z6Q!+C+BPur}+z(s+G^F-kGUh2V!WcG;Z>q&n$8<{u+F6)RRDllBK z+Opi;+>ma~+^{)Hqa~+d+I7>ll$-x+|3mofl%(EU)-;*1jll)CB1M=2{fA8r$ZpS&-opLuZn(4#}YVR(T4M4tHL6u!Xo>N zw&d707twOsnJ*+yn9XL$Phd9HU+AYBm#(YCw{;ZpJBNcH0%KojZTgWwEPMdS>!9!g zN!BedpO{_S>pd}iB3P@wtM~O@B-qzE#rmF(HSl?el6B6u1t$BIi{ujuG1V5H7 zHDVL{pTG-hrnpC}2v;J)KTZ*?m~UyARO7nGJ`9ZuK1h$wh$b!dxw?xZ4@ZZ$aWsjE z9ZdS>iEW%r;^z1~`zB2DuRX8**c*Sr_O6@HI1C-4J?nQa+1gOTdYKIzsD)zpCzec%*PoI zVnZCo?+!{tisLTIA!3m+D)YoH1VvWvDCBKidW%(J&-4fef={p&(}X|yk*G%bwNUUn Ifg-5?4_cwa1ONa4 diff --git a/target/classes/edu/ucsd/spendingtracker/model/Model.class b/target/classes/edu/ucsd/spendingtracker/model/Model.class index dee4092281371b88864c4c2b3e5b9026e279b406..ddc397342eab5872a87dba52d1686e78d042482c 100644 GIT binary patch delta 330 zcmXYryGjF55Qe`w@v<8>xJF4~)Od-y8*h-xR!}6hVjtKg1VR+u!cIFMU@Kq2Mgx+< z!UwR^=kOVVbIztYbN=}+^FMn}e)v84`~prnn#Tyuyeo~-@sC86Bpsw#dj4>m4)0T8 zChEl3WooPk)L9iwKM|ypPvkD%4cKH$2zzOEb(3`mm+DIT!=6xz;xlV&1?&^$FXlvM z^I!A&DERKM!RYi`A5`jN)0;Y% z51x%3v-9pan>weA&C35u%NKh@3T=5cc1_lO41`T!wCPoI8$%%~e8}%7U{l~>kYdegjyJA4sx+#f2CI ofNUO!8U{fIAs~;DL6JcTNJ8{8LF6F%mDf)eVNqpQ1Dm1_0IDt)<^TWy diff --git a/target/classes/edu/ucsd/spendingtracker/repository/ExpenseRepository.class b/target/classes/edu/ucsd/spendingtracker/repository/ExpenseRepository.class index a94d74d9522144a922c5f119320d3e4b8e0a39dc..0676bcfa4117addfb8b94ce78ee36121dce90b52 100644 GIT binary patch delta 685 zcmZ{i&uSA<6vn@EXObbENljyunxsufYty8)PGS@PG_^LiLIdKaP;lX5s6&a=MAC`4 zYhPi!D>s5Gw?;%57vj1reE^sG0`ApwrvVX>fjgY@o%=iAIoxCOhnYJ0`Qamg7B&qC zLL(UFf=Y{Ol0-f@v8J|M-`(jA`g>lJ5MS$bJN`PM{#+DT4ZeOcO=NM-z!bp=hV$|p zy=|(LZJ~f^Lh_+^;Q8L2XHUHDp-0fm?aHnyxM<-#E)Wvlsnp&gP+PtdXQvl&$-oj} z{E_?Abq0Rtz`5Hw^ersovivMcb`@6))ClQ61#RE!yMC{4VFh)W)olGLp~Tb3mz1=} z(7<&IH&Et=`<~x=+#7U#6IC=Vtl_3S)*d7TVu5k>Nl+$}>ZOL(CH1 zM5^M(Spz1Sc?9;N0@Xr6NiC00h4{-`A;jFj-g0~~{~vGjC^3kzfbt0Vf=7=rcx8Nh z4&%TzZLVf(zr?jruFxxN|R_4ozHEah^EN|nn;&PpNg(XSq2Vu7zIaIjm zvdXRawSM19Gs38RA0yTb&$2OauyEt5QQoMdNr6@Q#Mok=sSk3|n2^;@fC*AeN+EAf zh@2rUH<83|jM--^C@Dw{4EkJnFXt2eXwuIlTK9xA)G97AFC9y`FD1^1?91a@Lx&?S zDXPX>rgFv+WyM##JH@3w%gwDp=Z50d@vq`L5$QAsNwbN=w9K7hjvNcJd-8h*sq;b- l_u*ts`fIGq>^V$fo)fexcpB}P42Fr)1*jl=MNJTmjeqp3Ya9Ro From 16b96c2db40f6158b9c19e5057a29f21c6ca0f7f Mon Sep 17 00:00:00 2001 From: dognutss Date: Wed, 28 Jan 2026 15:37:50 -0800 Subject: [PATCH 3/4] Added SQLLite database as a new datasource and switched the app to use it instead of the in memory data source --- spending.db | Bin 0 -> 12288 bytes .../java/edu/ucsd/spendingtracker/App.java | 5 +- .../datasource/SqlDataSource.java | 65 ++++++++++++++++++ .../ucsd/spendingtracker/model/Expense.java | 2 +- .../edu/ucsd/spendingtracker/App.class | Bin 717 -> 2297 bytes .../datasource/InMemoryDataSource.class | Bin 2026 -> 2046 bytes .../datasource/SqlDataSource.class | Bin 0 -> 4190 bytes .../ucsd/spendingtracker/model/Category.class | Bin 1430 -> 1513 bytes .../ucsd/spendingtracker/model/Expense.class | Bin 1199 -> 1199 bytes .../ucsd/spendingtracker/model/Model.class | Bin 1152 -> 1152 bytes .../presenter/AbstractPresenter.class | Bin 1173 -> 1173 bytes .../presenter/PresenterManager.class | Bin 2512 -> 2581 bytes .../presenter/PresenterSwitcher.class | Bin 1539 -> 1539 bytes .../presenter/SpendingPresenter.class | Bin 3055 -> 3053 bytes .../presenter/SummaryPresenter.class | Bin 2351 -> 2355 bytes .../repository/ExpenseRepository.class | Bin 1523 -> 1516 bytes .../spendingtracker/view/SpendingView.class | Bin 3769 -> 3769 bytes .../spendingtracker/view/SummaryView.class | Bin 2151 -> 2151 bytes target/classes/module-info.class | Bin 277 -> 306 bytes .../compile/default-compile/createdFiles.lst | 16 +++++ .../compile/default-compile/inputFiles.lst | 29 ++++---- .../repository/ExpenseRepositoryTest.class | Bin 582 -> 0 bytes 22 files changed, 102 insertions(+), 15 deletions(-) create mode 100644 spending.db create mode 100644 src/main/java/edu/ucsd/spendingtracker/datasource/SqlDataSource.java create mode 100644 target/classes/edu/ucsd/spendingtracker/datasource/SqlDataSource.class delete mode 100644 target/test-classes/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.class diff --git a/spending.db b/spending.db new file mode 100644 index 0000000000000000000000000000000000000000..3588d06ba86c6bfc9bc3c5b0a20c5abfbc08c5fe GIT binary patch literal 12288 zcmeI#ze~eF6u|MjRCJQMbt=5ECB?;mz$k|l(^%68W|CM>DKx2VQqjSoqyM!RX$HHv zO8Gvx+`VwW^2zijx8ba^^1N8(StV!cL}{(gMU+z7wU%p5)cHY^xW3N+3aw7xzK-22 zukEY$r+W|xAb=H_g7n#wrqOu*DlRl>CK*G7$xS)#4?VD zqaaS@+N2WPB{##!tr?jp8AyGKB<9`?r&(oR7ORhKn&pdiQHi@^*sp7ISM(DIAb getExpenses() { + List list = new ArrayList<>(); + try (Connection conn = DriverManager.getConnection(url); + ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM expenses")) { + while (rs.next()) { + list.add(new Expense(rs.getInt("id"), rs.getString("name"), + Category.valueOf(rs.getString("category")), rs.getDouble("amount"))); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return list; + } + + + @Override + public void addExpense(Expense e) { + try (Connection conn = DriverManager.getConnection(url); + PreparedStatement ps = conn + .prepareStatement("INSERT INTO expenses(name, category, amount) VALUES(?,?,?)")) { + ps.setString(1, e.getName()); + ps.setString(2, e.getCategory().name()); + ps.setDouble(3, e.getAmount()); + ps.executeUpdate(); + } catch (SQLException err) { + err.printStackTrace(); + } + } + + + @Override + public void deleteExpense(int id) { + try (Connection conn = DriverManager.getConnection(url); + PreparedStatement ps = conn.prepareStatement("DELETE FROM expenses WHERE id = ?")) { + ps.setInt(1, id); + ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/edu/ucsd/spendingtracker/model/Expense.java b/src/main/java/edu/ucsd/spendingtracker/model/Expense.java index aea1c9b..a8dea45 100644 --- a/src/main/java/edu/ucsd/spendingtracker/model/Expense.java +++ b/src/main/java/edu/ucsd/spendingtracker/model/Expense.java @@ -13,7 +13,7 @@ public Expense(String name, Category category, double amount) { this.id = -1; } - public Expense(String name, Category category, double amount, int id) { + public Expense(int id, String name, Category category, double amount) { this.name = name; this.category = category; this.amount = amount; diff --git a/target/classes/edu/ucsd/spendingtracker/App.class b/target/classes/edu/ucsd/spendingtracker/App.class index 8b94c2efd477e7e21386beef45825c3ad1407a01..dd6d8f7dc1245237056e2ca1e5051bf8f55646af 100644 GIT binary patch literal 2297 zcmb_eYje{^6g`{RmLr^oJV@#!Bmn|AFT^WQWD2D`15QYrkeN)&hs9PBQCoH;nZp0* zAK?q`)HD15epIJtB|9=CGXB7Lywa}r-h1xZd#?29zkfdhxQAbK^r2rvB7-DS0yD4W z8@cz^khNObE=u37I>x=|ULbYbc5MHSK!0vwM?+fRidCu`^`ciYyqe{dY-ithW$_Qo zHA>Q#UbXHPEo1A?@&nGcf|(9Y#XKRf8f)uXwW??PRrj6o@Gbp%)~|;vI&=&wz~2d6 z&lO^Qbi`kaqUROvlLGUxc9m+$DjVx+)G>q+6>3z#>=LRQ+#uj7fyLN>Z*1!?W2?p9 z4ktRs6hq$&EPTbNUa3g;U1&3*Y^KObtWC|eJj?NUHtlGe?G+u9IIS|B5qQxh(++a- z@zfv5C?H`@;94)(!lXK&&El+rc1~dX8$pYB3y_`f4cQ^2b?L}`%hfTD{xos|C)zKkt3=7Tk(ES-HWxD-up^MTPZbFa6`1};z4FR( zx8uvqnZJdZc`ToAEB9ZAbeV-JI|aq-&Leo+EG}-cP6em}a}>sswR=S?53b5xJPm&+>0Ot=9zaFa8EA8?B!jYX1N8<;k=CT7(n)xa4u-NZb%TrdZ+14|YV)<1uEji8=hvY!&dm5L^p5VRBcV(9?K<+xU^G z4x@lOxJyo^@H2km7e|5~Z}I*{xeS3u@P|koMRt0{|Am(q>lgq literal 717 zcmaJ;O>Yx15Pi;fOrUK_KY-G@oDvS~0ZtSlRTLzoz$GOT;^gi+8^f->c)b<vW=W_ljkXe@KP? zRGuY@VK}j&OlH#QGG7*3exY+(H~F8UBZhYFrSl9sqsdYk6=D@kOFSCSy4awdWh+Re ziG%0PS=YlR!^bzqsoW;#DiWbhGo4hg5t*|jBYiA*|8${5s{F!6B3AxH&1I4J6Y1sD z7A{nyvCz3FOr+-Yrbx`K6P`x=MW)0{^Gc=GU0hw~9P8LBZP;ems`b{Qrrwd&q?Y_j zr8W%Pqj%MN{_1lu+#cW#cFE{O7A9QKh;%VowfT<;23|{jp-ZQG^ivN?FK|diP5O8c zl8NXLb}0)eGK%f{m*{<_Lj#nXt zX8wRXHZCMV5loD0{S7YM`WH-yXWB*xaWQw!z4yJ(ea|`fcjzEg`hKwg6`1C}iH65O zxA5Xqgjb8NirGqWZ6&+3ylOwKDtwdWwQ_Yz;Yp?*82A;@y69!KT**$auNU9s%Ntb_ z15bb!EQ3~yAfa08c&*mc(?WzcgQ&#`+7-dWv+gk`rHu@`k`9Yb;&Mr`R8q7j^T&-$ zqzY|fx!d9-r<|B)z#rkX#Tm{z3!ZG)t4(p9z1EiG~YtuS1L+0{l%t!`3C)AK|i$ zE@)OxxtCh$9n8!gF^z}E4Yf&GqIF)Zp>6V9gQIMY2}*H=@g_3YL`Ga>_dZ>)N6&w_ zF~W2l;YR*(BV1(yC2vA{(Znt`vBAtI&UL-R(6`V%?@1wbJxn}y1Q@JiBs(d`C}YmH Vk!Zic3^!SlHB-QMxXV4_e*sjicozTw delta 795 zcmZvZ&r;J+6vn@sq)i$wN!m(jp+%4)O$!zkL8Zz_t4^Sb?g(e!(kFf!ya8kt>gWy#Ln!=N=P zPd2NS^c=%X#u05fquU!gE@4Tk3;=AGO&FMS>$?1r-uxC$k9X000)@+4>#tI<_+5AhL5>n%;N%>rF)z2VT(Pi uk^6*;BX6K8Z!xLJ@2Fhv8#vZCu;IBA-_-PwgEDSoowVMK-oahmL*g%{7GwMX diff --git a/target/classes/edu/ucsd/spendingtracker/datasource/SqlDataSource.class b/target/classes/edu/ucsd/spendingtracker/datasource/SqlDataSource.class new file mode 100644 index 0000000000000000000000000000000000000000..11f3c5ef00fcb01824ac9920fb0408e919fdaa4f GIT binary patch literal 4190 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 delta 502 zcmZvX!Ab&A6o&tEXGR?xYt+=7ii$vVGF-ONEUJa8cC~6TrG!$7psk}fkW0&Y1qm90 z7Ck^g`(7qG_oCLK&HVp8bN=s~Gq%UJ`~Lm<24Ek46oOEYeJW(5FbQraxCts(LHDw9 zeBNnY3`V_`(f!UQArf5ohTQ>y4hf>&WYgekwcTwGb_w;Oe4xFWdC+UN;xLeOkU)xH z6iX*I2#XFZM3l=qh$5!kk^>uYaT!GuCl3x!z0l)S&>mUL@+SMK&iKa~m^ z!54l2Ka@Coxu!leDfnjC*`4|A%ztNp{QUMEz%I5-q>#=dVZ0$)u`ShWS+6;gi=R(;vhQdi{Q}dk9eoj@dwVR=LAyw$!10! zNv?47G9BWVY!Qe-bE^AOG(t+coU>0bx^n0_DhfEi{f`{&%dS6rh8-@Ud?r^nnK^#c zt{(*hu_tw(W?bu*7949luPL5%?p{wUud=+(;x5}NdwYDU&&|eHP^0+;`A_VnI1l{X zX|@J3FxeJykG-WyH11=aJn`11TBlU07-~vj&;fyKHzy>xM zLwd|E!mW(4_&2V?xWyT`2dKq39!kEt%9n4)K2Xrrjd9~6?@jv6@rmwG_i4rJLQ+^g jj%n~-6RT{i>~C|Hj!!r%AL5ubwiC|s1suY|IO@?afT#M+ literal 1152 zcmbVKe{0iF6g{`=+9plgt<$NSzc**v>H-51Y#9u7FsKvk=>KW+sBdP;$Pdv^rGi%Q z4?ln(O1$qi>xQl>OUUEBmvhfO_uTvA=eO?wcCcAQj<7Dg)Jcc2=fuY%@MJJbB6s*k zM9xv@3Ez34)*|wRg+uqP>-cUka$XJ&#V{e5kvI-xnS{}M!sG5ts#BQr{2ix>#j9yx zn^5S;KqlLSC-wz78ht|kDN8jmhq8qtEW(`K=o=tZEzF}psC8u^_S2(*hz{I=F9`K+ zICTBK8%cG}F7wH2851^UOF82Vt2bTG%c>%@{!+mtEQ7WieG|*LTErE?qYF7_VF{NA z#D)BKRzijQDH1VNoVWKTQf^vU#dShXdQ7@UD33&v!Pt+w-RSBGNE7KhT^T1_yU~-Q zz)jMKHFW*}bpB=Gi5J^#<;8}DJGje(#(59I#PxgGMCw*PQ;?>G7HmT41j6?B!ZaF+ zU8x#s>T%svI+=^(c+y$A>Ob%1d0#|{SA$Qx$ngu9&9D5mzM%4nPdU_ht?Ebvd64(qz|EqxD^l*%#geboO{-39)mDpmDbdSA)}67Iw1 b8|B;$7cXlR02?-`k)!`z$*}L)vxO1i+cOK zd~nigoOT4fTg`T}vn`%oAyy9Ah}5cA%yK-mR?ckS`_>d%t+5! z=T)Tqe#{w|$AbN4+V@fWbKj%wUY<3a5Ah;O_E*k17Cz@jsW};S!}(USUCpGa!ip+1 z8AYVY1PCk=D@bvtq00;Aq{*4wdc3D{n${4)Dh}YYN&^I~CqxcQF-*lUJw#%F}PDIUNdNUYyZ@aFwBy4vi2mdsm)w z;swXf)_&PPsMK!eYEP3r1Y@Uk9C($>bDyB@x=Uh_EIqPZ3QCm~QKk(lh*O#>awq2! zw6(KCKMEB+CSpkNN;c;jAoQAOLqwuJ6FS;;4Aj1IPCrKFV45(P-IN}VuAPemKk%Jx z@7xb6OY7^c{V@|AFvT;yi#x>?MKvS7m4&Kiv7*ZFQlZHMj5I0Ftif18lxtoLdE!f* z%(XgQh%9eu%w2V_*7%n z3|Hxv2qrMe70ZQYC`8hZf+@x+&ayXwEN6*yHmLCb=U}sQLLLd`2?b1Zlm=HhOPx0R j5!O9}mWfD6_926!^b$_|U6+^s8F@*;OcYq7 zJ31I9^IIi7%9fnN-&e%V{EZfpgW%s9i=A5qKyOUyF_%`;EQHES}TfEBke z%Q1{OfoWWz=&Fhq1ST;>(Gtfs6m47=xPfK)mVVj?>syjR6obGo&u@B_ieIs@D!<#V zahsuE{;>O{8xgf(x)-$!Fm*FzPf|2So{=}*eXuE4$Wp|R!zfu* z{DzuYhXDC~%QJUpu{}G^` zDv%@@sgTqOV=HVy2P8oeFlt73anx*4HKQ}`)-jYN(=<>l6w^vVVu&K%)RSXDDO8Jx k?dj#?B1IZ5VTQb-UZlOtxI$k8%@bM)D;RF#7VaSZ8KRcH3fWEh12=_DeomQBjmq1W^$`Nqk)G#t>mOE!7u|ssDi7 zX#5)uNl9vAeD=vdV4_d{3*+4FiVr(?=FFTkv**L`_k{iJPyY*m8a6pX3>9f>S^1Nh z*1F?4&)g=5wwIcSF=+J{4c9^#rhpD(zZ#A+gM&KNfD^MU*hr}M@ZQ_$Xi^}B;|$?u z+hgd+n6V@CENPy=2uEhXo0MNQTNgNqQQ2WL=9uD)GrX4_-IMuH(##^qF*&%bk`XwK zQ3kW+?rwNX&eP{=-0VLY^x~WQW&i<3t3zgxCDd2YQJnayYA+e z`Q`g>=<(q3yWCdsL9_(jt;70SqlE67Bz6qhGBu>hQN8u5wJ=?fUOJ6<1%5l z31ARwp652}+fJ+Hwm9xHYdiXzAbj!?yL6j6$b{E5U2dP|>SKQ5LI5TDn}X)UeyaSZ4ot@3go zr>KZxg7O~D1WV+vNM=jPUmZx$8YNF+DAK3amr%wzI!I+xnD*~4VFt6bb_nCBpbFi# zlu^M!vox*dtwIkMiWCmFb dK$0e|6Sjgi-1M_sxPuMc_1O&f@BojH{tJw*X3zit diff --git a/target/classes/edu/ucsd/spendingtracker/presenter/PresenterSwitcher.class b/target/classes/edu/ucsd/spendingtracker/presenter/PresenterSwitcher.class index 25a5a41d0dc2371892fc1d2d3076769208244024..b73c27a776a2f2c205f8be3d169258cadb2d3717 100644 GIT binary patch delta 533 zcmZ9J%}x|S5XXN#GrO}p^fK%UD6l#Ux*yD<<7DEb7NA+*_34f9x)(`Qj&4~8`% zBkB976j0%e&!}dMaY?&jeyBKqPBX!znRHfbRnGfd&_vV}6${;bm+bUA-Hqg_Rg*gP zLWLR4MJ|~majG;lOAdru;n8r{X>j HSZ3lc{`O6# delta 535 zcmZ9JO-~b16o#KW({?)3Yd=s5#gDd9C`{22+6{<^#>kR|iN<9$SZD|=+NcY`1;3!V zOZP5~B(x@7_ygGR3tad|jOR{WnMvMx&%Ni|=bU@b^qJ0I{u%!Sp0MNLC|YLKogW+) ziXI6?zT1A^jt<*LooM$>ckgX~a8e$8E&Gbp=E2cHf6Ht;&02uVHH}YJ;Vvz|^pQ$U zl9Y8*8jrN;Io~n?bKLT{Il;7&n%mqlz6w(nO_jT5UA?N*SoBzsI?I0dG3xc(oxSLV zRZX2G^Ia{Z=Lj_oR?II6YTVaEJTQS%&(&DdG;J%1-v03iQ*}?%0UK<3JTzmsF3>8E z%y0KgHkV>O&9-E!jfyg#65Y=-fLw+npL8EP={^1{nJlVM(F}|15&%-7to45LKRyiC}*aoL6+}1=gv9b{myspz1R9j zYwY$vH+}>#iO&p3kTv)?6sQa%;)L8LGLo@XXf)JuyJ$NT4AWcJQ(}t6LpuB#42}T! zUT(XvS;`k;NPETGtWggl!VyJ-xW&fQCXQyb2wgG*kDyIMjH4al%5F7|cnNHXZt7s^(#YE|8DDUN=m8I(dPXXP1^ z!qj5oD^(R`S&bMN#E^zzjtm}S=plAJ;*_s<-{Ux-VT9ueJjoDRH{UWd8;+gNWbLXW zzVIavj$%y1L5@QhXK2_69uA+L~Eiur4?r&(i^nVuIrtJS*<{I@y%C?;AKU ziRU<`F+<6#ma||MEQY33f7XM`o5j`4qEoSptA`Al!%>b|%!wIgB9z6vh6Rr2-O@fH z9T(pydX&LeBn&^YIKgoei{iEt*C+7;$1+ZdKb0m@{Uwgmcv%G1G^kN>0_OnB{rPSu5qL5xgUQ*JFvWg7*v>()%25 zq7p$Rtm2Y^5AdOek2o&lWAU5TD-8XPX!EZh)9E4tj8+;qc?$UoOj=hcT7yhKpd&pn z_ybsa2ii>pYY3-rpb@B{HC@A_*C|87S@Da%bu&kP=Ytwpc!MIUcCQN|x?TXQl*DaA#0WW0Gu*`FLS2XU z%Zv@xaG3r_YB=Va%^e&kyHvxAU*EswHY0l!ItbitU!nsObmSPiaG2~2MYAORf3hX0 zr929rfOB<{5{{yX645LZ28Z-F!c4>HUl@x>?vU#ZER)T;nnj6U*U#Xt*~KdidptrO qa*)`B5JC8V!bTqo8zlx+_cXB+NH)KXcX1I{2-cvztM~+;qU~RNqT8AP delta 1320 zcmYLJ-&0#f6#n++=5DxbAc_2tBm~+@fB=mkRVx%}3vGjdwNPy9&kNkbg^r>j=eQ#bXXV!{CU*=&UiS|LP54kN zz(J7l-J4sNk`abFfqH}(^bN;;pCNwhN}OovB1I8e>78fi|>Dq4mcY_6r=qGYsZ>VbOB!Igi=b)jcPF^*i!AE$w6Il{Z+F z=p*u+(RaQE3~2#B464CeaGiXPK`hy>dOPd5S(~Aut9x?A+OX1DE4P%Maf?oFX()g} zhQRn{!OoTJlA?KDpc^R@FXAPR!}6ilNx2PSSQ@^L_y|ThUZ$!&qIK8FrYD_}D@fO4 z@}w`>K86z<;|!5KK*qI;mYXjMoWv=4$Jee;FeE*7c8p-cLyX62cwS9sX#y!$t^OXa$jX(>UTpY zs{CI_3RTdAK1`(_D&vK19ATKggZ{p49A|id%v4pB*fqv_%Xo#p=`zkJa}TeRd83SX z2))4Y&Er2*Ej~}G1aVXS3CgGqaZ+di`*4KpDD5+p#GY;w)zmbc!V>j_{vs$v2P^b; zl}IAc9xLfNm}=e_&==BFqpM}ikyUbrDb<6&K`65gnzXw(w3|+y*P$RiuS1AhqM}#i i4L^}LOfgHuwJLwCO*US^HGGE838yCOI=;Y{X!##CZ{|S& diff --git a/target/classes/edu/ucsd/spendingtracker/presenter/SummaryPresenter.class b/target/classes/edu/ucsd/spendingtracker/presenter/SummaryPresenter.class index d3d99c768d08593b6eb4d72fb081b1a7e719b09a..0e808ca0c8112a44f629dd2196d266d4fc7d5ab6 100644 GIT binary patch delta 911 zcmYk4OHUI~6vzK}rZZEfx9w01(n=8#Y9C<5BKW}a5H`jqV133g&<0A%l(bVH3)78X zpt)bby$dyHjU+x+E?CLZgLbeEqi(p(h%l2hF)Pxed48*(mUWrAIEX@*I)EEqXCYS7!)CS)X)*d zDGf1>I1&tlj$B6e)EJDlyuDPi&En!#-pUoMH3m5rpL4W_IYw}r!Ch&mFt}oK@vIwX z7_`Oe=B8PG?!j54HH>kb!#G1=!+c_{>ooO;uMb zxl~0&SZ{qVEw-g~maP9sif3}Pn?W^K?Lvu4^y*g5wDZ|Q{;8O7MZFBXXl}0L%t4EG zDy{+X*_9SuN?H7I4F!$aQpv8^WpnF#-d-=|Dh6(f*J^mcui&;$<5}RC!@Plczlu9L zvbd|^9>;w=5U-RWv8((NKh=$zo9+)_WNDbRQfRGUg6w&UmLbyzgcHf(k6?-S(7wUj zfIqQ=BR~U3-_c(Q7s&dWnL1Q(gkazz?e({+aS4+Y5y!bCVmm7jE<>tOkiisLM=nDs zryVts{D8;-+IeIkK?T7kw!4+}AFE=Tq!@iO7;m$tN!k$#w3{Y(qJg0Xl83o92i!x? zF4P3`R!JMoFpDc~+z5FGCkIk*$+eEGHn$>&O669mAvwcumuAU3GM&^y(|G1*CiiZdgc(Lw#eH z*fb{wMfQPqF4`M#)9Rtq3VEeJ9E*>9fEjxS?`Qa{Xo(%*7*IvW8}cgXqqVsfX%a=w zz(POW_13d7fI&JDNA{7}a_7TwD7$osAli^i5=tSb9*e(6>_6J9-L_D1!5X%$9`z5a zV}xWGeWMs_uu>!~g#wMD$t0>cS;d*7++8WxPXAD-2IlpY2AE+A(+%7xS&35vGq1_i zpDZxkl*Q7L-L1jD;hVp} zM>X-1`e1zaclawzyv*5d3ymp>FK5rpnfc~B-<;X+zrTD1uz}4GeDJGKGz8E?=sz-E z7<$F1mh~qGN22Huda`EKbk+&}M6wV>FM=vU8p6;BE231_>qWby+b5!0GOK0BGK$ZI zrCZ{pW}8mUdZ|A;lzlHnM8wYpUlgvESU6d7i_VR~+>ostP7iar(n8U`>( z(El@^>l>w#M~je7bSH3JD~U?$2AO0*RvyxD88Je*EF2HSCJZK$c~`u;V^;LMX*({> zs~X}MCPWxVIHFxtN#rEjHH@kl(=d(+LbNlV&}%xvGFU`HtOGvh`MJatuB*7AVHz_` z;tZh`LQoG4dsm!tE4hQuWJW?m5-EaGb=^ZP>~nq3sJKa(>8fmpFd?KduR+HGA;_w1 z9M|gAX1y)K@&)>KX>hW@{F^R=Q;DHxV1ZO^GVhbDJn zwR{IMPTgW!*_Mj!2axSfrW0sgLV5LbtQh6E_pIZ7 z%`qy3fYbaEA4T>Y9e7`EZNZDEz#Jp>SRh5iGM6Yer)Qx7p%67nOO-dGs(hJp! zeaOSQ>&C3HkH?T#iPS-Dq=75{Qj0US;V#rN$TAS&9u_>nSFBEeftR8?ZE_8a5O(Jp zm?XSLoHw(CZ%D5xvvK7U=88LS{`{DI%UOO`=a`Ey$`=~rSsuq6CK!Lx4C24Ll;`1J`%qWx literal 1523 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 diff --git a/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class b/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class index b9367867da5b64701688b10be29a4d563db900a9..c8a5ba901d3e14432d8c7406bc1adf70556960dd 100644 GIT binary patch delta 917 zcmY*XOHW*e1sB^QW~HEVa396=Z3jU zS1#P6BL#7ArwjjuEB=JTcv3p!I7#mLZti!^cg{WM%y;H1|8;)y9l#J?dmuoRA*pb| zz28?g;O<*Vuh{(zVq;TGhQbg^8r#Owj+RN7X;VvBX?xR3X_Ll+nesq}SO70n8HFl} zP`qE*vOm}2mT`%pl2^Mb!wO0me8Wa!HEdhqv7L1@oiQ^W_)zAE2KXQgDPB~l2qLuq zrnRmBmr*67T15@Q3?+H_Wz$+S?af_n%F6J!td4wYRn#HE4_J4N7mX^K5M}UWOj}OG2IIMVkr@0S3k4*t;oHK?g(8jAa|CuuhpRl9y9dnS!f4CbUx_ zZ3?dQcR~m0-B8hsoBW5+!*20&A>bXrpo}3E!x-TqF~Ud0+Cl|mq+8$Cxg_Hb|1FkP zPvEYMdnzVzpKih_M@t#$Wo^{jT1c6^REktT#FUI_6_23*N73y~%819L3HPju80Pp# zX)GusuHuPPh)jjdm^(Hpj#!H(H${v8kv4(~k_ff<@m4jEms5o;Cj!; z-N`*KH6Qc|PUmunT0m9=bH;(zr?mS?*x@CkM_|!!kmE-vIE06wFYfmrq4W^t(a)&N z;!3m>^;tAT{moglI#hrA5jrQE{asmfN58=1zvh4}dfcZ7_r=9#JuW%_^|*^nx&9UX z0_HyDl9}hza@XE7!hwqf@Ek8_*Nb+%q=Xqg2BP^iXPsH3)2f`zsC0_kak1eT delta 919 zcmY*XOH&g;5dLO2$u40CA-s_QLU<$*mWL=JDhMbj@-RG%ikiR@6GOsdMYzaGZyr)} zw8|=v9;{MJ62t;;9z0m(Kk&xUKcJSqAypPNyVKp%-Cut_J%`Rir}Nw2y#oLPc%ndJ z@QN=MudKk5DtD(|`$QXSZDO$XMH5luB7@xGon^2LCKq)(WE61Z!LFc?p(^#Gw0tZS z*5h_KP>=@(7l#!#1tqEPb*wD)t5hvUg_%()IIHqAoZwKP=E03x1vL!CvCu|nX;X{n z$z|PG+tMbJ>l}4BDW0+hm7#&dgGTX&b=MM84j%}_zOEaAmC!;o5g}$RL*7{xt>O=B z&=@q1c2qK`W{j~F*Hv^fIHr?EC|(y>(G!c5W%8|1(JdyVcAEp5iXQPy>Y#eP9Ouy| z4x}D8^tYAP?$Q~=lAcjPrTrXZ&lKm>ih)rW#=aPbP2B(>; z#Y2gRHW7~L3x*w&xT#?3m}@BcI2_kG0+<%BWKYd3ZYh{M77{Slh%!eIx5ZC+)OMF+ z9`}T18Fo4FfFoqKt5Cbs`lca%TUJ#&Vu&kvB%WKFiR3(%#aru3UT8y9#R`MuVPeD< z+os{tJCJD6(6SoMhNMiBq#@IuPu5rRN+e^x47l$z9Kj5nJ18QxIOr#V7yan81nx(h+s9|&5^^FYu_qAKtS zmn6)+&ypDyQ%cwN71GO&2;eG4$m*pDj}l=<>l*wynltpU%y!(_GS@BpxDk|_cQFyz z#mpY=0BPLM0aKVg3t53`RN{XLcdi7%AdCfqUZf9tu7*aEQF4~+J5nSJ({54$A(=S* eC?JO;V<{UI!9$WN`4aReu}YSCziTkCfy#eO0i^Q) diff --git a/target/classes/module-info.class b/target/classes/module-info.class index 02f23fd04b813cd97092ede3a59a1f143b089a2a..f7e553dc6ba48b332c9dbd459411ba21c4991f93 100644 GIT binary patch delta 171 zcmbQrw26u9)W2Q(7#J8F8AK;?MI;u1 wiVJf@7(^znurcIdU}4~FU|`^8-~rmr$G{IJ1%V_t10#blkY<3=K&wC;0BM3B$N&HU delta 142 zcmdnQG?j_#)W2Q(7#J8F8H6TsMYstwa56IRXC;;;rd8-A=jW9a<>wR&GjKC9a6<*t zDspp#8F(2PI6wk=#f3l~KO+Mtn3t4ToGQW~IPs{BAp-*o0|(Gx1_mxL$pa?&8bA~y Mg8-NZp&2160N(8yqyPW_ diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index e69de29..a8ce4f0 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,16 @@ +edu/ucsd/spendingtracker/view/SummaryView.class +edu/ucsd/spendingtracker/presenter/SpendingPresenter.class +edu/ucsd/spendingtracker/model/Model.class +edu/ucsd/spendingtracker/presenter/SummaryPresenter.class +edu/ucsd/spendingtracker/App.class +module-info.class +edu/ucsd/spendingtracker/repository/ExpenseRepository.class +edu/ucsd/spendingtracker/datasource/IDataSource.class +edu/ucsd/spendingtracker/datasource/InMemoryDataSource.class +edu/ucsd/spendingtracker/model/Expense.class +edu/ucsd/spendingtracker/datasource/SqlDataSource.class +edu/ucsd/spendingtracker/model/Category.class +edu/ucsd/spendingtracker/presenter/AbstractPresenter.class +edu/ucsd/spendingtracker/presenter/PresenterSwitcher.class +edu/ucsd/spendingtracker/presenter/PresenterManager.class +edu/ucsd/spendingtracker/view/SpendingView.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index c5ac4cb..3b467f5 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1,13 +1,16 @@ -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\App.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\model\CategoryModel.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\model\ExpenseModel.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\view\SummaryView.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\presenter\PresenterManager.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\module-info.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\repository\ExpenseRepository.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\presenter\AbstractPresenter.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\InMemoryDataSource\InMemoryDataSource.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\view\SpendingView.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\presenter\SpendingPresenter.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\presenter\SummaryPresenter.java -c:\Users\tonyn\Desktop\Lab3_Starter1\src\main\java\edu\ucsd\spendingtracker\presenter\PresenterSwitcher.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/App.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/datasource/SqlDataSource.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/model/Category.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/model/Expense.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/model/Model.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/presenter/AbstractPresenter.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/presenter/PresenterManager.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/presenter/PresenterSwitcher.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/presenter/SpendingPresenter.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/module-info.java diff --git a/target/test-classes/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.class b/target/test-classes/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.class deleted file mode 100644 index 02f56bb1be28311196c767b03748f7bc37ced3ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 582 zcmbVJyG{c!5F96$930`9@Cc%SE>Pft3I!oW2&xDqh*HowcUIzXu}`)S!Dmr{DEI(A z3b7YnO)8ol@6LL5J%0aqeFM-zGen8uSSC5oW0!E3Nu4M?^j5@o(sC;^IWO|!C8#ByZPgoe@149)9Ydo_`L~>{S#246B$P_q>K|X!pgxj=ANc>M6sZOWh_vv reKim+QU)v$TO#hOYlW~7I{Fa`Ua Date: Thu, 29 Jan 2026 22:34:09 -0800 Subject: [PATCH 4/4] Refactored to use persistant storage in the form of an SQLite database run locally. --- spending.db | Bin 12288 -> 12288 bytes .../presenter/SpendingPresenter.java | 25 ++++- .../spendingtracker/view/SpendingView.java | 95 +++++++++++++++++- .../repository/ExpenseRepositoryTest.java | 89 ++++++++-------- .../presenter/SpendingPresenter.class | Bin 3053 -> 4515 bytes .../spendingtracker/view/SpendingView.class | Bin 3769 -> 8105 bytes 6 files changed, 153 insertions(+), 56 deletions(-) diff --git a/spending.db b/spending.db index 3588d06ba86c6bfc9bc3c5b0a20c5abfbc08c5fe..f67a8ced0d1f415217db7a538d601b7f45961d9a 100644 GIT binary patch delta 181 zcmZojXh@hK&B!}Z#+i|KW5No4F8(PnxLHu3iN9Wgjg>)EohdK1+|<=C#5E|y(bLZt z$YT7$z`zhBD$WR$G4T)aa1AmB3OI_&GXn*TLqj}$JVQKPgBcD#2MTM6ih|S`x%vCM uqyqU;5EBhiO!V8%3zTBy|HJ@9FtAxl;66Ve4{ + model.deleteExpense(id); + updateView(); + }); + + this.view.getOpenModalButton().setOnAction(e -> { + view.showAddExpenseModal(newExpense -> { + model.addExpense(newExpense); + updateView(); + }); + }); + updateView(); } @@ -25,12 +37,17 @@ public void setOnShowSummary(Runnable action) { public String getViewTitle() { return "Expenses"; } - + @Override public void updateView() { - int i = 1; + view.clearList(); + for (Expense e : model.getExpenses()) { - view.addExpenseRow(i++, e.getName(), e.getCategory().name(), - e.getCategory().color, e.getAmount()); + view.addExpenseRow( + e.getId(), + e.getName(), + e.getCategory().name(), + e.getCategory().color, + e.getAmount()); } } } diff --git a/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java b/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java index b9dab5f..02ed959 100644 --- a/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java +++ b/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java @@ -1,36 +1,60 @@ package edu.ucsd.spendingtracker.view; import javafx.geometry.*; +import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.scene.text.*; +import javafx.stage.Modality; +import javafx.stage.Stage; +import java.util.function.Consumer; +import edu.ucsd.spendingtracker.model.Expense; +import edu.ucsd.spendingtracker.model.Category; + public class SpendingView extends BorderPane { private VBox listContainer; private Button summaryButton; + private Button openAddModalBtn; + private Consumer onDeleteHandler; public SpendingView() { - VBox headerBox = new VBox(10); + VBox headerBox = new VBox(15); headerBox.setAlignment(Pos.CENTER); headerBox.setPadding(new Insets(20)); + Text title = new Text("Spending Tracker"); - title.setStyle("-fx-font-weight: bold; -fx-font-size: 24;"); + title.setStyle("-fx-font-weight: bold; -fx-font-size: 26;"); + + + HBox navBox = new HBox(10); + navBox.setAlignment(Pos.CENTER); + + summaryButton = new Button("View Summary"); - headerBox.getChildren().addAll(title, summaryButton); + openAddModalBtn = new Button("Add New Expense +"); + openAddModalBtn.setStyle("-fx-background-color: #2E7D32; -fx-text-fill: white; -fx-font-weight: bold;"); + + + navBox.getChildren().addAll(openAddModalBtn, summaryButton); + headerBox.getChildren().addAll(title, navBox); + listContainer = new VBox(5); ScrollPane scroller = new ScrollPane(listContainer); scroller.setFitToWidth(true); scroller.setStyle("-fx-background-color: transparent; -fx-background: #FFFFFF;"); + this.setTop(headerBox); this.setCenter(scroller); this.setPadding(new Insets(0, 25, 20, 25)); this.setStyle("-fx-background-color: #FFFFFF;"); } - public void addExpenseRow(int idx, String name, String catName, String color, double amount) { + + public void addExpenseRow(int id, String name, String catName, String color, double amount) { HBox row = new HBox(10); row.setPrefSize(450, 40); row.setPadding(new Insets(5, 10, 5, 10)); @@ -39,6 +63,7 @@ public void addExpenseRow(int idx, String name, String catName, String color, do "-fx-border-width: 0 0 1 0; -fx-font-weight: bold; " + "-fx-border-radius: 5px; -fx-background-radius: 5px;"); + Label nameL = new Label(name); nameL.setPrefWidth(200); Label catL = new Label("[" + catName + "]"); @@ -47,12 +72,72 @@ public void addExpenseRow(int idx, String name, String catName, String color, do Label amtL = new Label("$" + String.format("%.2f", amount)); amtL.setPrefWidth(80); amtL.setAlignment(Pos.CENTER_RIGHT); + Button deleteBtn = new Button("X"); + deleteBtn.setStyle("-fx-background-color: #ff6961; -fx-text-fill: white;"); + deleteBtn.setOnAction(e -> { + if (onDeleteHandler != null) + onDeleteHandler.accept(id); + }); + - row.getChildren().addAll(new Label(idx + "."), nameL, catL, amtL); + row.getChildren().addAll(nameL, catL, amtL, deleteBtn); listContainer.getChildren().add(row); } + + public void showAddExpenseModal(Consumer onSave) { + Stage modal = new Stage(); + modal.initModality(Modality.APPLICATION_MODAL); // Blocks the main window + modal.setTitle("Add New Expense"); + + + VBox layout = new VBox(15); + layout.setPadding(new Insets(20)); + layout.setAlignment(Pos.CENTER); + + + TextField nameField = new TextField(); + nameField.setPromptText("Expense Name"); + TextField amountField = new TextField(); + amountField.setPromptText("Amount"); + ComboBox categoryBox = new ComboBox<>(); + categoryBox.getItems().setAll(Category.values()); + + + Button saveBtn = new Button("Save Expense"); + saveBtn.setOnAction(e -> { + try { + double amount = Double.parseDouble(amountField.getText()); + onSave.accept(new Expense(nameField.getText(), categoryBox.getValue(), amount)); + modal.close(); + } catch (NumberFormatException ex) { + amountField.setStyle("-fx-border-color: red;"); + } + }); + + + layout.getChildren().addAll(new Label("Expense Details"), nameField, amountField, categoryBox, saveBtn); + modal.setScene(new Scene(layout, 300, 250)); + modal.showAndWait(); + } + + public Button getSummaryButton() { return summaryButton; } + + public void clearList() { + listContainer.getChildren().clear(); + } + + + public void setOnDelete(Consumer handler) { + this.onDeleteHandler = handler; + } + + + public Button getOpenModalButton() { + return openAddModalBtn; + } + } diff --git a/src/test/java/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.java b/src/test/java/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.java index b9f7718..9c4ceb1 100644 --- a/src/test/java/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.java +++ b/src/test/java/edu/ucsd/spendingtracker/repository/ExpenseRepositoryTest.java @@ -2,8 +2,8 @@ import edu.ucsd.spendingtracker.model.Category; import edu.ucsd.spendingtracker.model.Expense; -// import edu.ucsd.spendingtracker.datasource.IDataSource; -// import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; +import edu.ucsd.spendingtracker.datasource.IDataSource; +import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.DisplayName; @@ -14,55 +14,50 @@ public class ExpenseRepositoryTest { - @Test - void placeholderTest() { - assertTrue(true); - } - - // private ExpenseRepository repo; - // private IDataSource dataSource; - - // @BeforeEach - // void setUp() { - // dataSource = new InMemoryDataSource(); - // repo = new ExpenseRepository(dataSource); - // } + private ExpenseRepository repo; + private IDataSource dataSource; - // @Test - // @DisplayName("Should start with an empty list") - // void testInitialEmpty() { - // assertEquals(0, repo.getExpenses().size(), "Repository should be empty initially."); - // } + @BeforeEach + void setUp() { + dataSource = new InMemoryDataSource(); + repo = new ExpenseRepository(dataSource); + } - // @Test - // @DisplayName("Adding an expense should increase the list size") - // void testAddExpense() { - // Expense coffee = new Expense("Coffee", Category.FOOD, 5.50); - // repo.addExpense(coffee); + @Test + @DisplayName("Should start with an empty list") + void testInitialEmpty() { + assertEquals(0, repo.getExpenses().size(), "Repository should be empty initially."); + } - // List expenses = repo.getExpenses(); - // assertEquals(1, expenses.size()); - // assertEquals("Coffee", expenses.get(0).getName()); - // assertEquals(5.50, expenses.get(0).getAmount()); - // } + @Test + @DisplayName("Adding an expense should increase the list size") + void testAddExpense() { + Expense coffee = new Expense("Coffee", Category.FOOD, 5.50); + repo.addExpense(coffee); + + List expenses = repo.getExpenses(); + assertEquals(1, expenses.size()); + assertEquals("Coffee", expenses.get(0).getName()); + assertEquals(5.50, expenses.get(0).getAmount()); + } - // @Test - // @DisplayName("Deleting an expense should remove it from the list") - // void testDeleteExpense() { - // repo.addExpense(new Expense("Rent", Category.OTHER, 1200.00)); - // Expense toDelete = repo.getExpenses().get(0); - // int id = toDelete.getId(); - // repo.deleteExpense(id); - // assertEquals(0, repo.getExpenses().size(), "List should be empty after deletion."); - // } + @Test + @DisplayName("Deleting an expense should remove it from the list") + void testDeleteExpense() { + repo.addExpense(new Expense("Rent", Category.OTHER, 1200.00)); + Expense toDelete = repo.getExpenses().get(0); + int id = toDelete.getId(); + repo.deleteExpense(id); + assertEquals(0, repo.getExpenses().size(), "List should be empty after deletion."); + } - // @Test - // @DisplayName("Should handle multiple expenses correctly") - // void testMultipleExpenses() { - // repo.addExpense(new Expense("Gas", Category.TRANSPORT, 40.00)); - // repo.addExpense(new Expense("Movie", Category.ENTERTAINMENT, 15.00)); - // repo.addExpense(new Expense("Apples", Category.FOOD, 4.00)); + @Test + @DisplayName("Should handle multiple expenses correctly") + void testMultipleExpenses() { + repo.addExpense(new Expense("Gas", Category.TRANSPORT, 40.00)); + repo.addExpense(new Expense("Movie", Category.ENTERTAINMENT, 15.00)); + repo.addExpense(new Expense("Apples", Category.FOOD, 4.00)); - // assertEquals(3, repo.getExpenses().size()); - // } + assertEquals(3, repo.getExpenses().size()); + } } \ No newline at end of file diff --git a/target/classes/edu/ucsd/spendingtracker/presenter/SpendingPresenter.class b/target/classes/edu/ucsd/spendingtracker/presenter/SpendingPresenter.class index 92159908eb50e2f5ac34fcf18e937eb242309d82..238d4aa8bdd472103d75235856d57b0060a8f8ef 100644 GIT binary patch literal 4515 zcmb_f33nS;75<*LvByub;-pTKv}qdL)Rvu0LPDS@q&Rj;L~SRrQc+sAu{5zKk!FN6 z{}^21yYq5Xv0_Vl-Ztv?T7 z3V+ejg>DT!620gXIB6Ap!_QX>Mzw4?1>0HjDrWwgRWZsHt7M%SwY$SDoXFjs%htJ25PfT(Z2ZUn-fEwX?qG zxsJeHW8=r%<#6vYT+$V7=}|3@{y=vQ`)vX$49HGxACFT-dZ$&6LBJQ8~_MAB*Fcus9S zEOD=j<}jmqfl0*tG>c)lhFKfqDq1Olr~dB<+j1-Y->|{j*&sYR3ujW|2#yNqez{cZ4wVo^h0qM&TvyUl%y3A#4G-B%=*uuK?vx2Sj@ZpyYMSFcK3Ly_49I_^vhA$Qs8-gE14?;S!c*;ISCus}6&nazfy&YqiR)Np zNi~cs3b$e~@{^oEr#jYQn^f&iqBU5(3UO|qMF7XL)zY?#&dLIn%e}1 zW^Kos_e+ab<+5rRDzI+eEauFLt=^->9&g#M3Y_X}WwR+KFxh!yyL%kV!8B{>ZhN9Z z&_WW!5=^jg>PhCDYL%C5PXQ79-;%s~d>N;#$5YarS&ksfqFGujn4^w$eU#nS-9%M8 zgwAlA8ex2b3a3Cgyn`b^fNNh+0`ZV&{w&b!-3ft9n|Rk^v168mQgu2MuR4*(S=(&y zxWMV{+H0$l09u#LM!2h~#G?}80BSaLOyJI!oMf6=P)-hH?Ip+b{0f6z=*)T}JKIja zr#tUzkLwwFsApZjlD8hPRg#Ugo#~D$$V}n0uIs5oc6rY7mfb=%iKhjkERKU(kM>Y6 zey9fjk0ic{Zza{=PX%sk&iQEkjOQr(b0zzX#8>gPBz~!e;09aFa(Ixfj?TL7HNPBYdw4vF21b+9EgLVdm91v+?SBkSZoW4s2 zRQ_cg$Er*h%_`4J8vZD7Pa7v2!PD?(9;!DNWv>dkz}<{P7k@|yUU`_~Q$L@3@ey7> z%C{%b!@&m3q$VbxgGk+gb_Ine;?YRgk>DNZ9zO95H;3-_aS=Ei zD3QT)ccet9<8ie01!#fW3o!w&;M1#WIDHdm1!gC1;=I6LZizFv&xXk~D z`TwRG-llFhVDVO$HLNfkbQ|fv@8mfdTf# z$Uu&Fm0~*?N8?3Eb-Ri83p4^2qDU|`b|8tNI3U~<8`&8!BcKA(4Ur_7-{xZ%zJu=u s_wV5;-WAE~6!<=VfFB1>Kf%vvDqQb%7 delta 1047 zcmYk5$#WA|5XOH`%ZxO7vLrSaP?mRW%XZ9;&EiA>JGNt-1cE{civ=FQU`qx|##umF zSQ5zXopQ)2hg>*7AWF<3#fhr$Ur?NK$RXEMvGj};NKH+z(_eRg@6AuGf7d&YpFj8m z$nyPNXH%fVAwpWyNRz@T&rRh^Zf@GWqzHC)<)V^o(X`TLUIe?EHz*=Qi*s&a-ktYS zotiE(ituc4%AHYcFc+fh%$=Z4I`q(M^Mt>TPmMj12zga_-! z*>5wUd5>X5hhK2iN=3%`Ky!eDrffB~WjUnD@sT2W#w}%Mi{(Pe-*KNqoR2j}_{98f zO~hjyyWkc| zeM6qy)s;(x`NAXivgQI8lUz(#eChBNU)y}6xyrSB2lYx7`c~0yp6L2jBl*JAj62^p zUM!w3&)M8mq`ic>9dD=z{c>PoglO_2Pl|VzpgfSybocy*%G}3(NW4lS^MI95r9M-o z;jVlU;FQP}gha-$(5xjzgG8nz(zJ|%%W3fh&pT1+;aM@xNVTd+v*}vfK?wvTX=S>9 zrTI0y<40G^fNOl%HOpVUg0(m&O9+jeXSjyd>-!K~(SAoDm*=!320LcApKgTV`YG5_KGnq?x_3>|MAu$E6p(LGdNZoGQbE0iZbS$ zfM^2GNGO~Be;G&yyvtBqASc=*G9}|RKSFzIiKB|wbJY33aVBl*NRs#;v8h+YreuQo oTDKr7DXf$PHb9vLUteO;A4E|RyifU@D_oa|BSkm(j$5pK3B;DD9smFU diff --git a/target/classes/edu/ucsd/spendingtracker/view/SpendingView.class b/target/classes/edu/ucsd/spendingtracker/view/SpendingView.class index 9274657d0840f9ff2e6f57bd84338b07ed040890..d85bda3022c785f43c3fb8f409583ba5a28e9c5e 100644 GIT binary patch literal 8105 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 aCpao2Qu(`;Sl=rBjVN1l=QA^Lv+otCBm delta 1671 zcmZWp>30)V6#u;}Gs$#lXqr%l(iT~2Nl8<>uvH~cS|~y(B!I&rhIUHJ2`MIFX@wKq zMO2n2?jRynaX~;jp{=0ejvET%@sV@b?ywM+Kq$}YVGMT@-P=+8S_-kMOkE{H+EgsZ3ck;wu_*6%gqJTyr9$AVRoo-4 zO4M<*XR9!+QL$E-++=Dr5@{nTg=go=Q7{%8M6&xBol!&*6FgkF-uF*k}$`)c=Z#BcgtFr2Z8x3l~uXeejDeW_w}BYod$e z4E~Cisn+Cj`6B6LcVbh6Sc?-X`tb&jxk`C7|1kG>c026d9Xt7c&qDrJehI(sspo$e z)bpE#wKjaoYkfzi;%f%`TDIPWZy0QonG4_1$*MdOeo$})Kg#$?z3%c^Hdz zayDnNq&4U;u`K9~m{=L0>#G7m6FP;D)$@H==fgOXS=?(P7VvH~(Q(GA>n)PaC;&20 zshCkTh6*-SXLwF$77snb0ee+?E{=6Vudz9gotgt zL7kgKy3o#(CN}Q|1~Eh%sp47&!}t&~rRBJQi*QlmUHFJJH>GXG$D}C)`3WxNCPw8j zD}__6=V?N-L2Q%QZeW&GmzoP0smqQ}t*FoNIi2IEg73-yg(bflZylE{`7N$dfXMbU Je!*|h{spR)Uc3MR