From e9caedae31dfff647ceaf0423d98145808e65ed7 Mon Sep 17 00:00:00 2001 From: mms37 Date: Mon, 27 Jun 2022 23:16:48 -0700 Subject: [PATCH] done --- .idea/uiDesigner.xml | 124 ++++++++ docs/OODexplained.txt | 1 + docs/crc.txt | 28 ++ docs/uml.txt | 30 ++ docs/use cases.txt | 143 +++++++++ list.json | 1 + .../Main.class | Bin 4261 -> 0 bytes .../PackageInfo.class | Bin 3067 -> 0 bytes .../TextMenu.class | Bin 7009 -> 0 bytes .../extras/RuntimeTypeAdapterFactory$1.class | Bin 0 -> 4999 bytes .../extras/RuntimeTypeAdapterFactory.class | Bin 0 -> 5907 bytes .../model/BookPackage.class | Bin 0 -> 1446 bytes .../model/ElectronicPackage.class | Bin 0 -> 1447 bytes .../model/PackageFactory$PackageType$1.class | Bin 0 -> 1324 bytes .../model/PackageFactory$PackageType$2.class | Bin 0 -> 1337 bytes .../model/PackageFactory$PackageType$3.class | Bin 0 -> 1313 bytes .../model/PackageFactory$PackageType.class | Bin 0 -> 2063 bytes .../model/PackageFactory.class | Bin 0 -> 1677 bytes .../model/PackageInfo.class | Bin 0 -> 3493 bytes .../model/PerishablePackage.class | Bin 0 -> 1716 bytes .../textui/PackageDeliveriesTracker$1.class} | Bin 1552 -> 1776 bytes .../textui/PackageDeliveriesTracker$2.class | Bin 0 -> 741 bytes .../textui/PackageDeliveriesTracker.class | Bin 0 -> 5357 bytes .../textui/TextMenu.class | Bin 0 -> 8961 bytes src/Main.java | 97 ------ src/PackageFactory.java | 24 -- src/PackageInfo.java | 57 ---- src/PerishablePackage.java | 15 - src/TextMenu.java | 181 ----------- .../extras/RuntimeTypeAdapterFactory.java | 256 ++++++++++++++++ .../model}/BookPackage.java | 10 +- .../model}/ElectronicPackage.java | 10 +- .../model/PackageFactory.java | 68 +++++ .../model/PackageInfo.java | 85 ++++++ .../model/PerishablePackage.java | 24 ++ .../textui/PackageDeliveriesTracker.java | 137 +++++++++ .../textui/TextMenu.java | 280 ++++++++++++++++++ 37 files changed, 1193 insertions(+), 378 deletions(-) create mode 100644 .idea/uiDesigner.xml create mode 100644 docs/OODexplained.txt create mode 100644 docs/crc.txt create mode 100644 docs/uml.txt create mode 100644 docs/use cases.txt create mode 100644 list.json delete mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/Main.class delete mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/PackageInfo.class delete mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/TextMenu.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/gson/extras/RuntimeTypeAdapterFactory$1.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/gson/extras/RuntimeTypeAdapterFactory.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/BookPackage.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/ElectronicPackage.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$1.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$2.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$3.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageInfo.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PerishablePackage.class rename out/production/cmpt213.assignment1.packagedeliveriestracker/{Main$1.class => cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker$1.class} (55%) create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker$2.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.class create mode 100644 out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.class delete mode 100644 src/Main.java delete mode 100644 src/PackageFactory.java delete mode 100644 src/PackageInfo.java delete mode 100644 src/PerishablePackage.java delete mode 100644 src/TextMenu.java create mode 100644 src/cmpt213/assignment2/packagedeliveriestracker/gson/extras/RuntimeTypeAdapterFactory.java rename src/{ => cmpt213/assignment2/packagedeliveriestracker/model}/BookPackage.java (57%) rename src/{ => cmpt213/assignment2/packagedeliveriestracker/model}/ElectronicPackage.java (54%) create mode 100644 src/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.java create mode 100644 src/cmpt213/assignment2/packagedeliveriestracker/model/PackageInfo.java create mode 100644 src/cmpt213/assignment2/packagedeliveriestracker/model/PerishablePackage.java create mode 100644 src/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.java create mode 100644 src/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.java diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/OODexplained.txt b/docs/OODexplained.txt new file mode 100644 index 0000000..5357500 --- /dev/null +++ b/docs/OODexplained.txt @@ -0,0 +1 @@ +use case 1: diff --git a/docs/crc.txt b/docs/crc.txt new file mode 100644 index 0000000..0d3089e --- /dev/null +++ b/docs/crc.txt @@ -0,0 +1,28 @@ +class: PackageDeliveriesTracker +responsability: starting point of the program. Handles the displaying and modifying opperations of different kinds of packages. Load and store packages to json. +collaborators: textMenu, PackageFactory + +class: textMenu +responsability: Displays operations to be performed for packages. Take user input for the operations and returns the status. +collaborators: PackageDeliveriesTracker, PackageInfo, + +class: PackageInfo +responsability: define the attributes of packages. Allow for accessing and motifying fields of package info. +collaborators: BookPackage, PerishablePackage, ElectronicPackage, PackageFactory + +class: PackageFactory +responsability: initialize and return an instance of one of the package types. +collaborators: BookPackage, PerishablePackage, ElectronicPackage + +class: BookPackage +responsability: Sub class of PackageInfo. Defines the field author name and allows modification. +collaborators: PackageFactory, PackageDeliveriesTracker + +class: PerishablePackage +responsability: Sub class of PackageInfo. Defines the field expiry date and allows modification. +collaborators: PackageFactory, PackageDeliveriesTracker + +class: ElectronicPackage +responsability: Sub class of PackageInfo. Defines the field enviremental handling fee and allows modification. +collaborators: PackageFactory, PackageDeliveriesTracker + diff --git a/docs/uml.txt b/docs/uml.txt new file mode 100644 index 0000000..f004819 --- /dev/null +++ b/docs/uml.txt @@ -0,0 +1,30 @@ +PackageDeliveriesTracker +fileName: String, packageList: ArrayList, rtaf: RuntimeTypeAdapterFactory, gson: GsonBuilder +save():void, load(): void, main(String[] args): void + +PackageInfo +name: String, notes: String, price: double, weight, double, deliver: boolean, expectedDate: LocalDateTime +compareTo(PackageInfo p): int, toString(): String + BookPackage + authorName: String + + PerishablePackage + expiryDate:LocalDateTime + + ElectronicPackage + handlingFee: double + + +TextMenu +title: String, options: String[] +display(): void, list(ArrayList packageList): void, add(ArrayList packageList): void, remove(ArrayList packageList): void, sortList(ArrayList packageList, boolean due): ArrayList, overDueList(ArrayList packageList): void, getUndelivered(List packageList): ArrayList +upcomingList(ArrayList PackageList): void, markDelivered(ArrayList PackageList): void + +PackageFactory +PackageType: enum +getInstance(packageType type, String name, String Notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, string author, LocalDateTime expiryDate, double handlingFee): PackageInfo + + +1. PackageInfo and subclass are created from PackageFactory +2. PackageDeliveriesTracker creates objects of PackageInfo +3. PackageDeliveriesTracker is dependent on TextMenu diff --git a/docs/use cases.txt b/docs/use cases.txt new file mode 100644 index 0000000..1edc724 --- /dev/null +++ b/docs/use cases.txt @@ -0,0 +1,143 @@ +* list packages +* To list packages, user enters 1 and presses enter. +* A message is shown if no packages are in the package list +* Otherwise the packages are displayed with each field associated on a new line. +* Packages are ordered to display oldest delivery date first. +* a number is assigned to each packages. +################### +# Package Tracker # +################### +Today is: 2022-06-27 +1: List of all packages +2: Add a package +3: remove a package +4: list overdue packages +5: List upcoming packages +6: mark package as delivered +7: exit +choose an option between 1 and 7: + +$1 + +No packages to show + +* Back to the main menu + +################### +# Package Tracker # +################### +Today is: 2022-06-27 +1: List of all packages +2: Add a package +3: remove a package +4: list overdue packages +5: List upcoming packages +6: mark package as delivered +7: exit + +* If all inputs are validated, the package is added to the list. + +choose an option between 1 and 7: +$1 +enter a valid package name: +$b1 +notes: +$$ my note +enter date as yyyy-mm-dd hh:mm: +$2022-09-01 11:11 +enter price: +$15 +enter weight: +$15 +enter author +$me +b1 has been added to the list! + +################### +# Package Tracker # +################### +Today is: 2022-06-27 +1: List of all packages +2: Add a package +3: remove a package +4: list overdue packages +5: List upcoming packages +6: mark package as delivered +7: exit + +* When user lists packages again, the newly added package is shown in detail. + +choose an option between 1 and 7: +$1 +Package #1 +Name: b1 +Notes: my note +Price: 15.0 +Weight: 15.0 +Expected Delivery Date: 2022-09-01 11:11 +Delivered? no +65 days remaining +Author: me + +################### +# Package Tracker # +################### +Today is: 2022-06-27 +1: List of all packages +2: Add a package +3: remove a package +4: list overdue packages +5: List upcoming packages +6: mark package as delivered +7: exit +choose an option between 1 and 7: + +* To remove a package, user enters 3 and presses enter. +* The packages are listed with an ID. + +3 +Package #1 +Name: b1 +Notes: my note +Price: 15.0 +Weight: 15.0 +Expected Delivery Date: 2022-09-01 11:11 +Delivered? no +65 days remaining +Author: me + +* user enters 0 to return to the main menu. + +enter item number you want to remove (0 to cancel): +0 +################### +# Package Tracker # +################### +Today is: 2022-06-27 +1: List of all packages +2: Add a package +3: remove a package +4: list overdue packages +5: List upcoming packages +6: mark package as delivered +7: exit +choose an option between 1 and 7: +$3 +Package #1 +Name: b1 +Notes: my note +Price: 15.0 +Weight: 15.0 +Expected Delivery Date: 2022-09-01 11:11 +Delivered? no +65 days remaining +Author: me + +* user enters corresponding ID to remove the package. + +enter item number you want to remove (0 to cancel): +$1 + +* The package is deleted from the list. + +b1 has been removed from the list. diff --git a/list.json b/list.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/list.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/Main.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/Main.class deleted file mode 100644 index bcebd1797d94f7b8abb4d95d808f9e5fe96b9ea0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4261 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 DecHj8 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/TextMenu.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/TextMenu.class deleted file mode 100644 index ca058631aa8f4c8be27482b0035bb8ad7eb8d924..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7009 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 r5o1~6F?@#sp7)Ng;9rqhMid6F|AbG$P!qa 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 mq>nY>#}eR|F2IhYmyhp|qviW+*OIj`#^T zEN<70UFAxDGVaTQ2GaOPb^_7*RiD; z!ekh1aJyy^p0W@OtdzhogD!p<>J)V}g)yWVG*76#(>B>n_Q@w#^~*Pr!X%~`63Xf1 z$uO~$>&-Py6`x5VgDk^zi#J8lu}!XCOVuFBQ`}Y_!(yK}r9R%M9DOW%qh3_uQm)Dn zEfR|iBNb_j=f|xB;qLJRi!|wgjw*Mhe-4#V)sTd;T=^ed6ezmQTS2UzX7TSFMR&2b zD^1$tZ-uNk6hkuXL{TI9_8C&*U7J`IHNSNjGJowTqIuUjc1=;1eu7gy&9UmEU>JSu zILhzx_A{XxPR$#MV^xQN+Zxt<2G<$pe*>2GiPIEelXplhb5l9)DZ__ul0w6d)2DtH z3U9vRIL+gBpV{c*@{fmpKlU+y(`EnS;D`!R=x&?PMUh+9u2iCsz#WD$rUx)+7-kQJ z*qUWj%^lkoZqcGYfbcZjXISV-wODKkvIq?XqmPE0)(FWlT%z?d zo!%o!dLWx$UdheGCbdlB3@ksB`~oeX9{P%rPr;ijw5AcIHHjhU7^hbm@^_UquP6q2 zz%|U$?n`sH9z@LI21$PWEau62AdnVFiUrb5EJ6#UCFDXcKFTD$rdba$Zqhp+|8V{c zZcem)}KF{ z-{D%cXjL0OZCK7Qyf_2P$*Cz<8Is$SKZd!cRART^JrrS!ANqt8VoLiwlx95wle!}# zhF8sh%%jGT^Mr1wNOR?q_mBS}hZEE7RL&7kLmdS~KdE>(&e~XoF{D(W1*I+33#AE; zIaHMIg!DR^Au}pz(WZ?9hP-&+6Rs9*QwP4Y3{W6XD!?}T3uy9B5mO=!;^DgHbvD?N`%`! zJ!zAP+;0zb>jCog0hpGcPG0~RW@%N$6m`H_TVFl}`y3ybqtP4yDb2^Dku6+6fo2L3 z7f0$Jki!gN#jmj5tlz6Fr53DGx|BIZ<`cmQ{4zBgn>s?)93Po7(gGG^S4CVR$#5)U z38k1-5tm6y#n=@r69uz-71xlCrR$`TiKQEa4K3d!jU1A=MR)?YQKmT=+r1MbD_Etu QKu7{Bs5lu4lG@h%Pc;E$qyPW_ literal 0 HcmV?d00001 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$2.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$2.class new file mode 100644 index 0000000000000000000000000000000000000000..69259d1e1b7c869520834978a0d0e9d19f7cab07 GIT binary patch literal 1337 zcmb_cZBG+H5Pr6_Tzf5oEg)5VuSmgoQa@G=hO@CrK@AOw#4pQrX;<&|n!7F9U*f+o z`iVpne}F&AID2g(2KxorOZH}--I;l2c6NXL{{9odQ>@uYVah_ffDEP?w!NUQYa5Rp z9>=n)0-2vP`?~0D_<&lV_h;>AWh@2oK%y~UpZg5YB(XcXB+rz$Kn0_La)Xx|e zS6lD-5qEs9y3VeSr0Uk2)jbPY2KOvMiAdbz2fi4`vthwDS>zes{U_Mz@UFW*0<{c; z(+WNAyIhMlY4wQ!9M=wmRg zdopHt)4E_Db%uOb=%$J_R~|+GazUj$dF~U7>sHT^Pg5O+L_e)~kW}qdyD?-`s0EcR z(~qP{j=9vKABF7pG(&FO-=aec`wRu~sV_V&I;JTY$`e_W4?fVnFk-ODMn=PtMZU*X z$EQYb2(q_#!$IVUhBRkd`uEN}G+gQIUntKHW3t#5qNdJW7-(MRtA7%q{vfhqa`Yi)h`80=fJVU}jI0VraQ=0YM{ zxJ)`oE@6Ib{uz195LWsD>+Sl3>QZLGDrd{~F>+rCPT{Ys`NY*BY_omr%18@XOx%}n zg(SnVge8;{RwY~|DU)E=uuRW@S-p-M$R^TFvdAUUEy6~gZ<9qHY1|<^g}bQGKb`o! Wmmn)xrGJr-6jo4mbCe#9&AC6;^lHKY literal 0 HcmV?d00001 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$3.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType$3.class new file mode 100644 index 0000000000000000000000000000000000000000..6f270ba6765f802ebde0eb4874bdb441d57781f8 GIT binary patch literal 1313 zcmb_bZBG+H5Pr6_T;C9E1zW`TiWH0|@Udzz9F0v1YG_F0+j3pn)$3lfw?+F){1-+) zk!a!%@JAVEuT9ic`~co2w=>V~%sewY^Zmz{ZvdWPHH!qM93=BdVVYsr@Ab{b`lidH zNOn|DD6`@Ax&M}TL|X*%L})1@qX`k(?S+K7FGt69?we2#D`T}a>$m&pRA}M)ri; z41FGW+=v!wHP2F;VR&&4YG>D@vdNI#rlK*-Hl-4KgWi$QEq)XbQivHGa4oGq29u^M zBZgPa|IDMtkn0H3P?6!vr|2IqT(Zdm|D(DW$fu!>L!zHlycbt(qOBNGDl~%1mg;M1 zlVcur;yWQbUBi$W_pxZx!68Flyzf&liMD-whVq%L$p;^pZm1cuWFz%(WRdG~)efkk z>w@gF`{6+QqAu;57XR#phn6e7{f_d3Fd~axLH>wGdXI+cc^DZ7_ZgmD_^~OghEhUr z2QKNz+F^mPsV=l#mF*N SXfF_wz%r^{hEkw!Ywjn*_+i)p literal 0 HcmV?d00001 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory$PackageType.class new file mode 100644 index 0000000000000000000000000000000000000000..3205581598ae144bf64bcc62a31ac73a34f85432 GIT binary patch literal 2063 zcmb_dZBNrs6n-vy>DCp&g1iX|IAsH+@}}Yj@-m1d69~g4(@&*bMxkp-*OBn2jIuyn+^bDw+8(|gW&`uoq1UjXK?DxrnpgHby2CMTvey<9enc8S~G zq;{kmhkB9ka?3pCuF1=uOCIiOC5L?4W^H>_H$2BZiPx9gCr3OAhM>LoSl#FilNa$72hlj-O3b0~VN<{Nm zw<>&Nk6|X!aC+II3Z)txInOoiVyZEN2;j#bQ1A$k8NzAPHobX zQwtQIh#(|m5CamPHa+-c1W_4r5j@%S;8PJOG7=b&scT*+7>6dh#;-@2VJnercHdBi z{zVTi(`+%cWlfu}S4unF-4=b#VBAu=WRv@sLCrdbZsm2?6j|%3gSK8G2I|eOqw)6k zO}dn5j#NYUDlXvyiDaH3R^;BAUG{X_Am5i;*xwA7$$Y9gJ+s6$pGrpe_%^L>Y5D&` zGk3X{HG9uVk+!4_t3EV(15q(r=_cR$Jf)L!PQ^9&swqm{aa~!*g)|VObrRtBPT7;N z#IShhX%%_6TQWV5@8&8yh7cA`rBv2zo4dZwh-Iun*E2&j5#99J2rl#rbqC0j1pAgW z7ijMjB1?!c`CmdK`~bQj0f;!&#nAsr1Tcqe! zWHI@5LK=d!3v`Enf)xU%2;>UEQ%Jc&=#+|g^KBwXW43;HtA2R=0)qv0IBGRTu9*iJHw_l?>hk3%a;2jox kyNG475qkGQ(#Hfcv>K-K)G=7eM9E9fLObo%Y@%lW0@K|pq5uE@ literal 0 HcmV?d00001 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.class new file mode 100644 index 0000000000000000000000000000000000000000..c54cfb7f491e24b91639430f21a45b3315b695e6 GIT binary patch literal 1677 zcmd5+T~8B16g|@qw%ry%C`$bntG0lwl*g*kv>_oWU;^QRw_zFD!FINp4ru?0zryH? zCO-HB{7)M1%r*goeSto>4|DH5GxzMwoO|cz@9#eVyu@=K2_!wF@z4mhTWd2uC4{V-XAzumFDFSv!RZnnulu)Z!S+Vyb*>}oi2)DswtJ&I_Vw= zy~__egv_|p?Qtz_JOopwE&B}hD{O!G=NgF}YC)IB@T+`vzVq6Sl)}~8P~87UO47i% zg4`bSEfBHdT_@#*(q>4j$OzIh-P6)G0BevU?}co&sSmTmh7yM~vCrU(4?Sv7Tk8zP zk#$WB{KT{)9cM^Ah%<6+t`0lYQtN{9{hjDUhhkmYGMoLoMOW-jsW-Q%lQ)Ge$G(RO z!}gU+{d|Fx);uhYowVxV+1N=}8S)!S30?2dyJrQ$%+Ajgp5)(8|Q52A6 zWYde^z`nTYX&UXc9k0`vj~8GDvlL}fz#Jhq`6H1|k}WJQEm!8#b6zo1%ohFm+*f#? z2~XgRE91D1;M?`MftzHlH;2!(^PdKp9!* vJt8b-E>T8~vL6$kz!N+r>mx-OWh`PDD-r)e&>%d!0f`Y%xAdZBFq>gpa1$qkQig)14|`Y1zxw&x6*KEfBGcvJ^-S*X)jZj%iKj zl%)+iHYzg_%l4!qJfS0nO#;!1V-_eU@`~D`W3!^hZb@@`##5v%I@+*RAQ7ODMKVvQ zFWYo%$CCoOyj`JxvY0nKYHF(@@XWHz4%-Ezq{w4@^MQ2e*y#iD<|{HuEl=s#jXeSz zr=@pcnWFa2^qQ)Y*oRIHX&o8t7ijgJUTu=F3wF6;IC6|3N_U3z6=odUva@~uvK(i6 zFpdL6G(SIoU}WS#vDh&%&|NMkk;T&*4(T|IBLcf>Hm7W-YaCs$AB(#P~r9Q_QyymaFj5NNRMIEHx8n5I>E8dl*M5jgcogS~}}r$*c85Z;=J94f_w1rE&lnZWsVOSq0a<6dAyDf_Jzg6lM#T@0 zhTF@oszqzdKvnNArk4F|l$Vp?%{c^qBZNC(2~lckKmE9o@5u=yN9{SMAp1>KMopoc z@1QCulFr+<=kk86j7V?BF1j0IcsGgn@VW^YUkq}H6sYJkN~KZLlesuP zrlX>R33fXiSvELMSkrNQ$`%t)ZO#eBIT^?20>i3SyE{bkBJX@xZ7!?3UTwzx>s{>@ zuiTEHMCLoxEvCLK)y!GG2-fkSWl5*6!~sRR8omvGdZ6#h1eBU=>>7!q*GCD72uh9C%~g_ygI2{TTcX)<93__L8W_7X{}kv5@u zkxn0@o#8h8=mYejn4XmcHMQUegJ!gQcK2MqbN%P-o4*0vz=)Js6U=BJsgerrT2)(f%k^FRloApf-)gun3F~d;S zDs!LV$U=QI1Z5m!IJi&W;_B*RuQ#`{vK$09X7P=M;|@;XB*U3BmT8c-RUB~bz6(<) zJ!%m%RMhqw*F=U4SBr2B`T8*}O=Eb@!D*bKWM*6p*K%zs04;(@#oTu{a^jBXi6l{R zv%tG5mD#+5v-pnTXux+wONAcS52YRum1rL7q!{gJqzcqCJSlK=RP7>c;%(-;(qg%-ov5l@R8uyBvzJ!R-=00C8qvLW$Lt6F+r=11ElFN>8cUcpqpRG25G=K zoTuGTi@1Inr50tT7MBzOMN*6OOHwOJN;CBXAo4D7`4EWwJ20hu$oJP0+4}$iNTt| P4oGt`FfzyjX&?Xq%4&H% delta 176 zcmeysJAsGm)W2Q(7#J9A85}oqbu$XG`6g!OsTeXcuoR^xrZ6(tO?G6Go&12AZ?YuQ zJT?v=ko0C&<~BwnP7qTsE3qt*k%8YeFF7Z_I5RKZH?<@qKZTva2516E0S|*60~?TC zoLH7RnU^(yQE+k`t0Su@11E#nzuo{j@kt!$xX&WICaW|V`F?j9B_9Bq_r+Px- z&>zqrRdqI@+z>)yEYGvw*z)+z{Q3Lv8^BkrH_^aEill`}ObL9-T`3Fa3PZ98&Pq=g zhVm%;cSGvCYqA1UU2S#T6PVcCI!iGv(96qVY=7C6Dg<5Fl5A|tp~|mSK?5@ShP-{5{#7i9n zPO`U6qa!eL%HL73^8EDA>_u(5*_FCcvWnWsZ{DlBOo!NgU0Nmo-24~k*j~8K9uI-$ zsjGZWhq{(w<2mtm>I7K0?>09sXj}ZCc}|LlUs~&hF6kt#BAR~{9>YkCi^-JbTG@lH9o-jj(3xoW8c6$ a7Do6Ui;M}D@BynMW(jMIO}>>fvi$?skkhUJ literal 0 HcmV?d00001 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.class new file mode 100644 index 0000000000000000000000000000000000000000..a167860f5d11ceb4d6b05533f0793bdbe0a36420 GIT binary patch literal 5357 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 UjC$4Lw2*Ne^2QwS@3jB(AKRe?K>z>% literal 0 HcmV?d00001 diff --git a/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.class b/out/production/cmpt213.assignment1.packagedeliveriestracker/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.class new file mode 100644 index 0000000000000000000000000000000000000000..5cd41d729db3f09e57990f0d4d7b7fb49d8e8d7e GIT binary patch literal 8961 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 packageList=new ArrayList<>(); -private static void save(){ - Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, - new TypeAdapter() { - @Override - public void write(JsonWriter jsonWriter, - LocalDateTime localDateTime) throws IOException { - jsonWriter.value(localDateTime.toString()); - } - @Override - public LocalDateTime read(JsonReader jsonReader) throws IOException { - return LocalDateTime.parse(jsonReader.nextString()); - } - }).create(); - try{ - Writer w = new FileWriter(fileName); - gson.toJson(packageList, w); - w.flush(); - w.close(); - } - catch (IOException e){ - e.printStackTrace(); - } -} - -private static void load(){ - File file = new File(fileName); -try{ - JsonElement element = JsonParser.parseReader(new FileReader(fileName)); - JsonArray array = element.getAsJsonArray(); - for (int i = 0; i < array.size(); i++){ - JsonObject pObj = array.get(i).getAsJsonObject(); - DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); - packageList.add(new PackageInfo(pObj.get("name").getAsString(), - pObj.get("note").getAsString(), - pObj.get("price").getAsDouble(), - pObj.get("weight").getAsDouble(), - pObj.get("delivered").getAsBoolean(), - LocalDateTime.parse(pObj.get("expectedDate").getAsString())) - ); - } - System.out.println("packages loaded"); -} -catch (FileNotFoundException e){ -System.out.println("no packages to load"); - } -} - - public static void main(String[] args) { -TextMenu menu=new TextMenu(); -load(); -do{ - menu.display(); - System.out.println("choose an option between 1 and 7:"); - Scanner scan = new Scanner(System.in); - int option=Integer.parseInt(scan.nextLine()); - if (option > 7 || option < 1){ - System.out.println("invalid input"); - } - else if(option == 7){ - save(); - System.out.print("packages saved"); - break; - } - else{ - switch(option){ - case 1: menu.list(packageList); - break; - case 2: menu.add(packageList); - break; - case 3: menu.remove(packageList); - break; - case 4: menu.overDueList(packageList); - break; - case 5: menu.upcomingList(packageList); - break; - case 6: menu.markDelivered(packageList); - } - } -} -while (true); - } -} - diff --git a/src/PackageFactory.java b/src/PackageFactory.java deleted file mode 100644 index 595bcb5..0000000 --- a/src/PackageFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -import java.time.LocalDateTime; - -public enum PackageFactory { - Book { - public PackageInfo getInstance(String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, String author) { - return new BookPackage(name, notes, price, weight, delivered, expectedDate, author); - } - } - - Perishable { - public PackageInfo getInstance (String name, String notes,double price, double weight, - boolean delivered, LocalDateTime expectedDate, LocalDateTime expiryDate){ - return new PerishablePackage(name, notes, price, weight, delivered, expectedDate, expiryDate); - } - } - - Electronic{ - public PackageInfo getInstance(String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, double handlingFee){ - return new ElectronicPackage(name, notes, price, weight, delivered, expectedDate, handlingFee); - } - } -} - //public static PackageInfo getInstance(PackageType type, String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, @Nullable String author, @Nullable LocalDateTime expiryDate, @Nullable double handlingFee){ - //} diff --git a/src/PackageInfo.java b/src/PackageInfo.java deleted file mode 100644 index 6b46b5e..0000000 --- a/src/PackageInfo.java +++ /dev/null @@ -1,57 +0,0 @@ -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import static java.lang.Math.abs; - -public class PackageInfo implements Comparable{ -private String name; - private String note; - private double price; - private double weight; - private boolean delivered; - private LocalDateTime expectedDate; - - public PackageInfo(String name, String note, double price, double weight, boolean delivered, LocalDateTime expectedDate) { - this.name =name; - this.note = note; - this.price = price; - this.weight =weight; - this.delivered =delivered; - this.expectedDate = expectedDate; - } - - public String getName() { - return name; - } - - public boolean getDelivered() { - return delivered; - } - - public LocalDateTime getExpectedDate() { - return expectedDate; - } - - public void setDelivered(boolean delivered) { - this.delivered = delivered; - } - - @Override - public int compareTo(PackageInfo p){ - return this.expectedDate.compareTo(p.getExpectedDate()); - } - - @Override - public String toString() { - DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); - LocalDateTime today = LocalDateTime.now(); - today.format(format); - long diff = ChronoUnit.DAYS.between(today, expectedDate); - String isDelivered = delivered ? "yes" : "no"; - return "Name: " + name + "\n" + "Notes: " + note + "\n" + "Price: " + price + "\n" + "Weight: " + weight + "\n" + "Expected Delivery Date: " + expectedDate.toString() + "\n" + "Delivered? " + isDelivered + "\n" + ((diff > 0 && !delivered) ? diff + " days remaining" : abs(diff) + " days overdue"); - } -} diff --git a/src/PerishablePackage.java b/src/PerishablePackage.java deleted file mode 100644 index a589e49..0000000 --- a/src/PerishablePackage.java +++ /dev/null @@ -1,15 +0,0 @@ -import java.time.LocalDateTime; - -public class PerishablePackage extends PackageInfo{ - LocalDateTime expiryDate; - - public PerishablePackage(String name, String note, double price, double weight, boolean delivered, LocalDateTime expectedDate, LocalDateTime expiryDate) { - super(name, note, price, weight, delivered, expectedDate); - this.expiryDate = expiryDate; - } - - @Override - public String toString() { - return super.toString()+"expiryDate=" + expiryDate; - } -} diff --git a/src/TextMenu.java b/src/TextMenu.java deleted file mode 100644 index 6b74bb3..0000000 --- a/src/TextMenu.java +++ /dev/null @@ -1,181 +0,0 @@ -import javax.swing.text.html.HTMLDocument; -import java.net.SocketOption; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.time.DateTimeException; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.format.SignStyle; -import java.util.*; - -public class TextMenu { -private final String title = "title"; -private final String[] options = new String []{ - "List of all packages", - "Add a package", -"remove a package", -"list overdue packages", -"List upcoming packages", -"mark package as delivered", -"exit"}; - -public void display(){ - int tag = title.length(); - for (int i=0; i<= tag+3; i++){ - System.out.print("#"); - } - System.out.println("\n# " + title + " #"); - for (int i=0; i<= tag+3; i++){ - System.out.print("#"); - } - DateFormat today = new SimpleDateFormat("yyy-MM-dd"); - Calendar cal=Calendar.getInstance(); - System.out.println("\nToday is: " + today.format(cal.getTime())); -for (int i = 0; i < options.length; i++){ - System.out.println((i+1) + ": " + options[i]); -} -} - -public void list(ArrayList packageList){ -if (packageList.size() == 0){ - System.out.println("No packages to show"); -} -else{ - for (int i=0; i < packageList.size(); i++){ - System.out.println("Package #" + (i+1)); - System.out.println(packageList.get(i).toString()); - } -} -} - - public void add(ArrayList packageList){ - Scanner scan = new Scanner(System.in); - String pName; - do { - System.out.println("enter a valid package name:"); - pName = scan.nextLine(); - } - while (pName.length()==0); - System.out.println("notes:"); - String pNotes = scan.nextLine(); - boolean checkDate = false; - DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); - LocalDateTime pDate=LocalDateTime.now(); - while (checkDate == false){ - try { - System.out.println("enter date as yyyy-mm-dd hh:mm:"); - pDate = LocalDateTime.parse(scan.nextLine(), format); - checkDate = true; - } - catch (DateTimeParseException e) { - System.out.println("invalid date format"); - } - } - double pPrice; - do { - System.out.println("enter price:"); - pPrice = scan.nextDouble(); - } - while (pPrice < 0); - double pWeight; - do { - System.out.println("enter weight:"); - pWeight = scan.nextDouble(); - } - while (pWeight <= 0); - - packageList.add(new PackageInfo(pName, pNotes, pPrice, pWeight, false, pDate)); - System.out.println(pName + " has been added to the list!"); - } - - public void remove(ArrayList packageList) { - this.list(packageList); - if (packageList.size() == 0){ - return; - } - Scanner scan = new Scanner(System.in); - int n; - do { - System.out.println("enter item number you want to remove (0 to cancel):"); - n = scan.nextInt(); - } - while (n < 0 || n > packageList.size()); - if (n > 0){ - System.out.println(packageList.get(n-1).getName() + " has been removed from the list."); - packageList.remove(n-1); - } - } - - //due=true returns overdue packages, else upcoming packages - public ArrayList sortList(ArrayList pList, boolean due){ - ArrayList sortedList = new ArrayList<>(); - LocalDateTime today = LocalDateTime.now(); - DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); - today.format(format); - for (int i = 0; i < pList.size(); i++) { - PackageInfo p = pList.get(i); - if (!p.getDelivered()) { - if (due && today.isAfter(p.getExpectedDate())) { - sortedList.add(p); - } - else if (!due && today.isBefore(p.getExpectedDate())){ - sortedList.add(p); - } - } - } -Collections.sort(sortedList); - return sortedList; - } - - public void overDueList(ArrayList packageList){ -ArrayList overdue = sortList(packageList, true); -if (overdue.size() == 0){ - System.out.println("no overdue packages to show"); - return; -} -this.list(overdue); - } - - public void upcomingList(ArrayList packageList){ - ArrayList upcoming = sortList(packageList, false); - if (upcoming.size() == 0){ - System.out.println("no upcoming packages to show"); - return; - } - this.list(upcoming); - } - - public ArrayList getUndelivered(List packageList){ - ArrayList undelivered = new ArrayList<>(); - for (int i = 0; i < packageList.size(); i++){ - if (packageList.get(i).getDelivered() == false){ - undelivered.add(packageList.get(i)); - } - } -return undelivered; - } - - public void markDelivered(ArrayList packageList){ - ArrayList undelivered=getUndelivered(packageList); - if (undelivered.size() == 0){ - System.out.println("No undelivered packages to show"); - return; - } - this.list(undelivered); - Scanner scan = new Scanner(System.in); - int n; - do { - System.out.println("enter item number you want to mark delivered (0 to cancel):"); - n = scan.nextInt(); - } - while (n < 0 || n > undelivered.size()); - if (n > 0){ - PackageInfo p = undelivered.get(n-1); - packageList.get(packageList.indexOf(p)).setDelivered(true); - System.out.println(p.getName() + " has been delivered."); - } - } - - -} diff --git a/src/cmpt213/assignment2/packagedeliveriestracker/gson/extras/RuntimeTypeAdapterFactory.java b/src/cmpt213/assignment2/packagedeliveriestracker/gson/extras/RuntimeTypeAdapterFactory.java new file mode 100644 index 0000000..8a4807b --- /dev/null +++ b/src/cmpt213/assignment2/packagedeliveriestracker/gson/extras/RuntimeTypeAdapterFactory.java @@ -0,0 +1,256 @@ +package cmpt213.assignment2.packagedeliveriestracker.gson.extras; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Adapts values whose runtime type may differ from their declaration type. This + * is necessary when a field's type is not the same type that GSON should create + * when deserializing that field. For example, consider these types: + *
   {@code
+ *   abstract class Shape {
+ *     int x;
+ *     int y;
+ *   }
+ *   class Circle extends Shape {
+ *     int radius;
+ *   }
+ *   class Rectangle extends Shape {
+ *     int width;
+ *     int height;
+ *   }
+ *   class Diamond extends Shape {
+ *     int width;
+ *     int height;
+ *   }
+ *   class Drawing {
+ *     Shape bottomShape;
+ *     Shape topShape;
+ *   }
+ * }
+ *

Without additional type information, the serialized JSON is ambiguous. Is + * the bottom shape in this drawing a rectangle or a diamond?

   {@code
+ *   {
+ *     "bottomShape": {
+ *       "width": 10,
+ *       "height": 5,
+ *       "x": 0,
+ *       "y": 0
+ *     },
+ *     "topShape": {
+ *       "radius": 2,
+ *       "x": 4,
+ *       "y": 1
+ *     }
+ *   }}
+ * This class addresses this problem by adding type information to the + * serialized JSON and honoring that type information when the JSON is + * deserialized:
   {@code
+ *   {
+ *     "bottomShape": {
+ *       "type": "Diamond",
+ *       "width": 10,
+ *       "height": 5,
+ *       "x": 0,
+ *       "y": 0
+ *     },
+ *     "topShape": {
+ *       "type": "Circle",
+ *       "radius": 2,
+ *       "x": 4,
+ *       "y": 1
+ *     }
+ *   }}
+ * Both the type field name ({@code "type"}) and the type labels ({@code + * "Rectangle"}) are configurable. + * + *

Registering Types

+ * Create a {@code cmpt213.assignment2.packagedeliveriestracker.gson.extras.RuntimeTypeAdapterFactory} by passing the base type and type field + * name to the {@link #of} factory method. If you don't supply an explicit type + * field name, {@code "type"} will be used.
   {@code
+ *   cmpt213.assignment2.packagedeliveriestracker.gson.extras.RuntimeTypeAdapterFactory shapeAdapterFactory
+ *       = cmpt213.assignment2.packagedeliveriestracker.gson.extras.RuntimeTypeAdapterFactory.of(Shape.class, "type");
+ * }
+ * Next register all of your subtypes. Every subtype must be explicitly + * registered. This protects your application from injection attacks. If you + * don't supply an explicit type label, the type's simple name will be used. + *
   {@code
+ *   shapeAdapterFactory.registerSubtype(Rectangle.class, "Rectangle");
+ *   shapeAdapterFactory.registerSubtype(Circle.class, "Circle");
+ *   shapeAdapterFactory.registerSubtype(Diamond.class, "Diamond");
+ * }
+ * Finally, register the type adapter factory in your application's GSON builder: + *
   {@code
+ *   Gson gson = new GsonBuilder()
+ *       .registerTypeAdapterFactory(shapeAdapterFactory)
+ *       .create();
+ * }
+ * Like {@code GsonBuilder}, this API supports chaining:
   {@code
+ *   cmpt213.assignment2.packagedeliveriestracker.gson.extras.RuntimeTypeAdapterFactory shapeAdapterFactory = cmpt213.assignment2.packagedeliveriestracker.gson.extras.RuntimeTypeAdapterFactory.of(Shape.class)
+ *       .registerSubtype(Rectangle.class)
+ *       .registerSubtype(Circle.class)
+ *       .registerSubtype(Diamond.class);
+ * }
+ * + *

Serialization and deserialization

+ * In order to serialize and deserialize a polymorphic object, + * you must specify the base type explicitly. + *
   {@code
+ *   Diamond diamond = new Diamond();
+ *   String json = gson.toJson(diamond, Shape.class);
+ * }
+ * And then: + *
   {@code
+ *   Shape shape = gson.fromJson(json, Shape.class);
+ * }
+ */ +public final class RuntimeTypeAdapterFactory implements TypeAdapterFactory { + private final Class baseType; + private final String typeFieldName; + private final Map> labelToSubtype = new LinkedHashMap<>(); + private final Map, String> subtypeToLabel = new LinkedHashMap<>(); + private final boolean maintainType; + + private RuntimeTypeAdapterFactory(Class baseType, String typeFieldName, boolean maintainType) { + if (typeFieldName == null || baseType == null) { + throw new NullPointerException(); + } + this.baseType = baseType; + this.typeFieldName = typeFieldName; + this.maintainType = maintainType; + } + + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + * {@code maintainType} flag decide if the type will be stored in pojo or not. + */ + public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName, boolean maintainType) { + return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, maintainType); + } + + /** + * Creates a new runtime type adapter using for {@code baseType} using {@code + * typeFieldName} as the type field name. Type field names are case sensitive. + */ + public static RuntimeTypeAdapterFactory of(Class baseType, String typeFieldName) { + return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName, false); + } + + /** + * Creates a new runtime type adapter for {@code baseType} using {@code "type"} as + * the type field name. + */ + public static RuntimeTypeAdapterFactory of(Class baseType) { + return new RuntimeTypeAdapterFactory<>(baseType, "type", false); + } + + /** + * Registers {@code type} identified by {@code label}. Labels are case + * sensitive. + * + * @throws IllegalArgumentException if either {@code type} or {@code label} + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory registerSubtype(Class type, String label) { + if (type == null || label == null) { + throw new NullPointerException(); + } + if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) { + throw new IllegalArgumentException("types and labels must be unique"); + } + labelToSubtype.put(label, type); + subtypeToLabel.put(type, label); + return this; + } + + /** + * Registers {@code type} identified by its {@link Class#getSimpleName simple + * name}. Labels are case sensitive. + * + * @throws IllegalArgumentException if either {@code type} or its simple name + * have already been registered on this type adapter. + */ + public RuntimeTypeAdapterFactory registerSubtype(Class type) { + return registerSubtype(type, type.getSimpleName()); + } + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() != baseType) { + return null; + } + + final TypeAdapter jsonElementAdapter = gson.getAdapter(JsonElement.class); + final Map> labelToDelegate = new LinkedHashMap<>(); + final Map, TypeAdapter> subtypeToDelegate = new LinkedHashMap<>(); + for (Map.Entry> entry : labelToSubtype.entrySet()) { + TypeAdapter delegate = gson.getDelegateAdapter(this, TypeToken.get(entry.getValue())); + labelToDelegate.put(entry.getKey(), delegate); + subtypeToDelegate.put(entry.getValue(), delegate); + } + + return new TypeAdapter() { + @Override + public R read(JsonReader in) throws IOException { + JsonElement jsonElement = jsonElementAdapter.read(in); + JsonElement labelJsonElement; + if (maintainType) { + labelJsonElement = jsonElement.getAsJsonObject().get(typeFieldName); + } else { + labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName); + } + + if (labelJsonElement == null) { + throw new JsonParseException("cannot deserialize " + baseType + + " because it does not define a field named " + typeFieldName); + } + String label = labelJsonElement.getAsString(); + @SuppressWarnings("unchecked") // registration requires that subtype extends T + TypeAdapter delegate = (TypeAdapter) labelToDelegate.get(label); + if (delegate == null) { + throw new JsonParseException("cannot deserialize " + baseType + " subtype named " + + label + "; did you forget to register a subtype?"); + } + return delegate.fromJsonTree(jsonElement); + } + + @Override + public void write(JsonWriter out, R value) throws IOException { + Class srcType = value.getClass(); + String label = subtypeToLabel.get(srcType); + @SuppressWarnings("unchecked") // registration requires that subtype extends T + TypeAdapter delegate = (TypeAdapter) subtypeToDelegate.get(srcType); + if (delegate == null) { + throw new JsonParseException("cannot serialize " + srcType.getName() + + "; did you forget to register a subtype?"); + } + JsonObject jsonObject = delegate.toJsonTree(value).getAsJsonObject(); + + if (maintainType) { + jsonElementAdapter.write(out, jsonObject); + return; + } + + JsonObject clone = new JsonObject(); + + if (jsonObject.has(typeFieldName)) { + throw new JsonParseException("cannot serialize " + srcType.getName() + + " because it already defines a field named " + typeFieldName); + } + clone.add(typeFieldName, new JsonPrimitive(label)); + + for (Map.Entry e : jsonObject.entrySet()) { + clone.add(e.getKey(), e.getValue()); + } + jsonElementAdapter.write(out, clone); + } + }.nullSafe(); + } +} \ No newline at end of file diff --git a/src/BookPackage.java b/src/cmpt213/assignment2/packagedeliveriestracker/model/BookPackage.java similarity index 57% rename from src/BookPackage.java rename to src/cmpt213/assignment2/packagedeliveriestracker/model/BookPackage.java index 16abec8..9d1447a 100644 --- a/src/BookPackage.java +++ b/src/cmpt213/assignment2/packagedeliveriestracker/model/BookPackage.java @@ -1,17 +1,23 @@ +package cmpt213.assignment2.packagedeliveriestracker.model; + import java.time.LocalDateTime; -public class BookPackage extends PackageInfo{ +/** + * It's a subclass of PackageInfo that adds an author field + */ +public class BookPackage extends PackageInfo { String author; public BookPackage(String name, String note, double price, double weight, boolean delivered, LocalDateTime expectedDate, String author) { super(name, note, price, weight, delivered, expectedDate); this.author = author; + this.setType("book"); } @Override public String toString() { - return super.toString()+"author='" + author + '\''; + return super.toString() + "\nAuthor: " + author; } } diff --git a/src/ElectronicPackage.java b/src/cmpt213/assignment2/packagedeliveriestracker/model/ElectronicPackage.java similarity index 54% rename from src/ElectronicPackage.java rename to src/cmpt213/assignment2/packagedeliveriestracker/model/ElectronicPackage.java index 13847b2..715e209 100644 --- a/src/ElectronicPackage.java +++ b/src/cmpt213/assignment2/packagedeliveriestracker/model/ElectronicPackage.java @@ -1,15 +1,21 @@ +package cmpt213.assignment2.packagedeliveriestracker.model; + import java.time.LocalDateTime; -public class ElectronicPackage extends PackageInfo{ +/** + * ElectronicPackage is a subclass of PackageInfo that adds a handlingFee attribute + */ +public class ElectronicPackage extends PackageInfo { double handlingFee; public ElectronicPackage(String name, String note, double price, double weight, boolean delivered, LocalDateTime expectedDate, double handlingFee) { super(name, note, price, weight, delivered, expectedDate); this.handlingFee = handlingFee; + this.setType("electronic"); } @Override public String toString() { - return super.toString()+"handlingFee=" + handlingFee; + return super.toString() + "\nHandling fee: " + handlingFee; } } diff --git a/src/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.java b/src/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.java new file mode 100644 index 0000000..4ffe028 --- /dev/null +++ b/src/cmpt213/assignment2/packagedeliveriestracker/model/PackageFactory.java @@ -0,0 +1,68 @@ +package cmpt213.assignment2.packagedeliveriestracker.model; + +import java.time.LocalDateTime; + +/** + * The PackageFactory class is a factory class that creates a package object based on the type of + * package that is passed in + */ +public class PackageFactory { + /** + * > This function creates a new package object based on the package type + * + * @param type The type of package. + * @param name The name of the package. + * @param notes A string of notes about the package. + * @param price The price of the package + * @param weight The weight of the package in kilograms + * @param delivered Whether or not the package has been delivered + * @param expectDate The date the package is expected to be delivered. + * @param author The author of the book. + * @param expiryDate The date the package expires. + * @param handlingFee The handling fee for the package. + * @return A new instance of the package type. + */ + + public static PackageInfo create(PackageType type, String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectDate, String author, LocalDateTime expiryDate, double handlingFee) { + return type.getInstance(name, notes, price, weight, delivered, expectDate, author, expiryDate, handlingFee); + } + + // Creating an enum called PackageType. + public enum PackageType { + Book { + public PackageInfo getInstance(String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, String author, LocalDateTime expiryDate, double handlingFee) { + return new BookPackage(name, notes, price, weight, delivered, expectedDate, author); + } + }, + + Perishable { + public PackageInfo getInstance(String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, String author, LocalDateTime expiryDate, double handlingFee) { + return new PerishablePackage(name, notes, price, weight, delivered, expectedDate, expiryDate); + } + }, + + Electronic { + public PackageInfo getInstance(String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, String author, LocalDateTime expiryDate, double handlingFee) { + return new ElectronicPackage(name, notes, price, weight, delivered, expectedDate, handlingFee); + } + }; + + /** + * It returns a PackageInfo object. + * + * @param name The name of the package. + * @param notes a string that describes the package + * @param price The price of the package + * @param weight the weight of the package in kg + * @param delivered true if the package has been delivered, false otherwise + * @param expectedDate The date the package is expected to be delivered. + * @param author The name of the author of the book. + * @param expiryDate The date when the package expires. + * @param handlingFee The handling fee for the package. + * @return A package object + */ + + public abstract PackageInfo getInstance(String name, String notes, double price, double weight, boolean delivered, LocalDateTime expectedDate, String author, LocalDateTime expiryDate, double handlingFee); + } + +} \ No newline at end of file diff --git a/src/cmpt213/assignment2/packagedeliveriestracker/model/PackageInfo.java b/src/cmpt213/assignment2/packagedeliveriestracker/model/PackageInfo.java new file mode 100644 index 0000000..e4ef20b --- /dev/null +++ b/src/cmpt213/assignment2/packagedeliveriestracker/model/PackageInfo.java @@ -0,0 +1,85 @@ +package cmpt213.assignment2.packagedeliveriestracker.model; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + +import static java.lang.Math.abs; + +/** + * PackageInfo is a class that contains information about a package + */ + +public class PackageInfo implements Comparable { + private final String name; + private final String note; + private final double price; + private final double weight; + private final LocalDateTime expectedDate; + private boolean delivered; + private String type; + + public PackageInfo(String name, String note, double price, double weight, boolean delivered, LocalDateTime expectedDate) { + this.name = name; + this.note = note; + this.price = price; + this.weight = weight; + this.delivered = delivered; + this.expectedDate = expectedDate; + } + + /** + * This function returns the name of the person. + * + * @return The name of the person. + */ + public String getName() { + return name; + } + + + public boolean getDelivered() { + return delivered; + } + + /** + * This function sets the value of the delivered variable to the value of the delivered parameter. + * + * @param delivered This is a boolean value that indicates whether the message has been delivered + * to the recipient. + */ + public void setDelivered(boolean delivered) { + this.delivered = delivered; + } + + public LocalDateTime getExpectedDate() { + return expectedDate; + } + + /** + * This function sets the type of the object to the type passed in as a parameter + * + * @param type The type of the event. + */ + public void setType(String type) { + this.type = type; + } + + // Comparing the expected date of the package to the expected date of the package passed in as a + // parameter. + @Override + public int compareTo(PackageInfo p) { + return this.expectedDate.compareTo(p.getExpectedDate()); + } + + // Overriding the toString method. + @Override + public String toString() { + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); + LocalDateTime today = LocalDateTime.now(); + today.format(format); + long diff = ChronoUnit.DAYS.between(today, expectedDate); + String isDelivered = delivered ? "yes" : "no"; + return "Name: " + name + "\n" + "Notes: " + note + "\n" + "Price: " + price + "\n" + "Weight: " + weight + "\n" + "Expected Delivery Date: " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(expectedDate) + "\n" + "Delivered? " + isDelivered + "\n" + ((diff > 0 && !delivered) ? diff + " days remaining" : abs(diff) + " days overdue"); + } +} diff --git a/src/cmpt213/assignment2/packagedeliveriestracker/model/PerishablePackage.java b/src/cmpt213/assignment2/packagedeliveriestracker/model/PerishablePackage.java new file mode 100644 index 0000000..522ec5e --- /dev/null +++ b/src/cmpt213/assignment2/packagedeliveriestracker/model/PerishablePackage.java @@ -0,0 +1,24 @@ +package cmpt213.assignment2.packagedeliveriestracker.model; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * It's a subclass of PackageInfo that adds an expiry date + */ +public class PerishablePackage extends PackageInfo { + LocalDateTime expiryDate; + + // It's a constructor that initializes the object with the given parameters. + public PerishablePackage(String name, String note, double price, double weight, boolean delivered, LocalDateTime expectedDate, LocalDateTime expiryDate) { + super(name, note, price, weight, delivered, expectedDate); + this.expiryDate = expiryDate; + this.setType("perishable"); + } + + // It's a method that returns a string representation of the object. + @Override + public String toString() { + return super.toString() + "\nExpiry date: " + DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm").format(expiryDate); + } +} diff --git a/src/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.java b/src/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.java new file mode 100644 index 0000000..405470c --- /dev/null +++ b/src/cmpt213/assignment2/packagedeliveriestracker/textui/PackageDeliveriesTracker.java @@ -0,0 +1,137 @@ +package cmpt213.assignment2.packagedeliveriestracker.textui; + +import cmpt213.assignment2.packagedeliveriestracker.gson.extras.RuntimeTypeAdapterFactory; +import cmpt213.assignment2.packagedeliveriestracker.model.BookPackage; +import cmpt213.assignment2.packagedeliveriestracker.model.ElectronicPackage; +import cmpt213.assignment2.packagedeliveriestracker.model.PackageInfo; +import cmpt213.assignment2.packagedeliveriestracker.model.PerishablePackage; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.*; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Scanner; + +/** + * It's a class that contains a main method that creates a TextMenu object, loads a list of packages + * from a file, and then loops through a menu of options until the user chooses to quit + */ +public class PackageDeliveriesTracker { + private static final String fileName = "list.json"; + private static final RuntimeTypeAdapterFactory r = RuntimeTypeAdapterFactory.of(PackageInfo.class, "type") + .registerSubtype(BookPackage.class, "book") + .registerSubtype(PerishablePackage.class, "perishable") + .registerSubtype(ElectronicPackage.class, "electronic"); + private static final Gson gson = new GsonBuilder().registerTypeAdapter(LocalDateTime.class, + new TypeAdapter() { + @Override + public void write(JsonWriter jsonWriter, + LocalDateTime localDateTime) throws IOException { + jsonWriter.value(localDateTime.toString()); + } + + @Override + public LocalDateTime read(JsonReader jsonReader) throws IOException { + return LocalDateTime.parse(jsonReader.nextString()); + } + }).registerTypeAdapterFactory(r).create(); + private static ArrayList packageList = new ArrayList<>(); + + /** + * It saves the packageList to a file. + */ + private static void save() { + try { + Writer w = new FileWriter(fileName); + gson.toJson(packageList, w); + w.flush(); + w.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * It reads the json file, converts it to a list of PackageInfo objects, and then sets the type of + * each object to the appropriate type + */ + private static void load() { + File file = new File(fileName); + try { + String json = Files.readString(Paths.get(fileName)); + Type lType = new TypeToken>() { + }.getType(); + packageList = gson.fromJson(json, lType); + for (PackageInfo p : packageList) { + if (p instanceof BookPackage) { + p.setType("book"); + } else if (p instanceof PerishablePackage) { + p.setType("perishable"); + } else if (p instanceof ElectronicPackage) { + p.setType("electronic"); + } + } + System.out.println("packages loaded"); + } catch (FileNotFoundException e) { + System.out.println("no packages to load"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * This function is the main function of the program. It creates a TextMenu object, loads the + * packages from the file, displays the menu, and then waits for the user to input a number between + * 1 and 7. If the user inputs a number outside of that range, the program will display an error + * message. If the user inputs 7, the program will save the packages to the file and exit. If the + * user inputs a number between 1 and 6, the program will call the corresponding function in the + * TextMenu class + */ + public static void main(String[] args) { + TextMenu menu = new TextMenu(); + load(); + do { + menu.display(); + System.out.println("choose an option between 1 and 7:"); + Scanner scan = new Scanner(System.in); + int option = Integer.parseInt(scan.nextLine()); + if (option > 7 || option < 1) { + System.out.println("invalid input"); + } else if (option == 7) { + save(); + System.out.print("packages saved"); + break; + } else { + switch (option) { + case 1: + menu.list(packageList); + break; + case 2: + menu.add(packageList); + break; + case 3: + menu.remove(packageList); + break; + case 4: + menu.overDueList(packageList); + break; + case 5: + menu.upcomingList(packageList); + break; + case 6: + menu.markDelivered(packageList); + } + } + } + while (true); + } +} + diff --git a/src/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.java b/src/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.java new file mode 100644 index 0000000..7613412 --- /dev/null +++ b/src/cmpt213/assignment2/packagedeliveriestracker/textui/TextMenu.java @@ -0,0 +1,280 @@ +package cmpt213.assignment2.packagedeliveriestracker.textui; + +import cmpt213.assignment2.packagedeliveriestracker.model.PackageFactory; +import cmpt213.assignment2.packagedeliveriestracker.model.PackageInfo; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.*; + +/** + * It's a class that displays a menu and allows the user to interact with the program + */ +public class TextMenu { + private final String title = "Package Tracker"; + private final String[] options = new String[]{ + "List of all packages", + "Add a package", + "remove a package", + "list overdue packages", + "List upcoming packages", + "mark package as delivered", + "exit"}; + + /** + * This function displays the title of the menu, the current date, and the options available to the + * user + */ + public void display() { + int tag = title.length(); + for (int i = 0; i <= tag + 3; i++) { + System.out.print("#"); + } + System.out.println("\n# " + title + " #"); + for (int i = 0; i <= tag + 3; i++) { + System.out.print("#"); + } + DateFormat today = new SimpleDateFormat("yyy-MM-dd"); + Calendar cal = Calendar.getInstance(); + System.out.println("\nToday is: " + today.format(cal.getTime())); + for (int i = 0; i < options.length; i++) { + System.out.println((i + 1) + ": " + options[i]); + } + } + + /** + * This function takes an ArrayList of PackageInfo objects and prints them out in reverse order + * + * @param packageList The list of packages to be displayed + */ + public void list(ArrayList packageList) { + if (packageList.size() == 0) { + System.out.println("No packages to show"); + } else { + Collections.sort(packageList); + for (int i = 0; i < packageList.size(); i++) { + System.out.println("Package #" + (i + 1)); + System.out.println(packageList.get(i) + "\n"); + } + } + } + + /** + * This function allows the user to add a package to the list of packages + * + * @param packageList the list of packages + */ + public void add(ArrayList packageList) { + Scanner scan = new Scanner(System.in); + int itemType; + do { + System.out.println("please select (1) book, (2) perishable, or (3) electronic package"); + itemType = Integer.parseInt(scan.nextLine()); + } + while (itemType < 1 || itemType > 3); + PackageFactory.PackageType pType = PackageFactory.PackageType.Book; + String author = ""; + LocalDateTime expiryDate = LocalDateTime.now(); + double handlingFee = 0.0; + String pName; + do { + System.out.println("enter a valid package name:"); + pName = scan.nextLine(); + } + while (pName.length() == 0); + System.out.println("notes:"); + String pNotes = scan.nextLine(); + boolean checkDate = false; + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); + LocalDateTime pDate = LocalDateTime.now(); + while (checkDate == false) { + try { + System.out.println("enter date as yyyy-mm-dd hh:mm:"); + pDate = LocalDateTime.parse(scan.nextLine(), format); + checkDate = true; + } catch (DateTimeParseException e) { + System.out.println("invalid date format"); + } + } + double pPrice; + do { + System.out.println("enter price:"); + pPrice = Double.parseDouble(scan.nextLine()); + } + while (pPrice < 0); + double pWeight; + do { + System.out.println("enter weight:"); + pWeight = Double.parseDouble(scan.nextLine()); + } + while (pWeight <= 0); + switch (itemType) { + case 1: + do { + System.out.println("enter author"); + author = scan.nextLine(); + } + while (author.length() == 0); + break; + case 2: + boolean checkExpDate = false; + while (checkExpDate == false) { + try { + System.out.println("enter expiry date as yyyy-mm-dd hh:mm"); + expiryDate = LocalDateTime.parse(scan.nextLine(), format); + checkExpDate = true; + } catch (DateTimeParseException e) { + System.out.println("invalid date format"); + } + } + pType = PackageFactory.PackageType.Perishable; + break; + case 3: + do { + System.out.println("enter handling fee"); + handlingFee = Double.parseDouble(scan.nextLine()); + } + while (handlingFee <= 0); + pType = PackageFactory.PackageType.Electronic; + break; + } + PackageInfo p = PackageFactory.create(pType, pName, pNotes, pPrice, pWeight, false, pDate, author, expiryDate, handlingFee); + packageList.add(p); + System.out.println(pName + " has been added to the list!"); + } + + /** + * This function takes in an ArrayList of PackageInfo objects and prints out the list of packages + * in the ArrayList. The user is then prompted to enter the number of the package they want to + * remove. If the user enters a number that is not in the list, the user is prompted to enter a + * number again. If the user enters 0, the function returns without removing anything. If the user + * enters a number that is in the list, the package is removed from the list and the user is + * notified + * + * @param packageList the list of packages to be displayed + */ + public void remove(ArrayList packageList) { + this.list(packageList); + if (packageList.size() == 0) { + return; + } + Scanner scan = new Scanner(System.in); + int n; + do { + System.out.println("enter item number you want to remove (0 to cancel):"); + n = scan.nextInt(); + } + while (n < 0 || n > packageList.size()); + if (n > 0) { + System.out.println(packageList.get(n - 1).getName() + " has been removed from the list."); + packageList.remove(n - 1); + } + } + + /** + * This function takes in a list of packages, a boolean for whether or not the user wants to see + * packages that are due, and a boolean for whether or not the user wants to see all packages. It + * then returns a list of packages that are sorted by their expected delivery date + * + * @param pList the list of packages to be sorted + * @param due true if you want to sort the list by due date, false if you want to sort the list by + * expected date + * @return An ArrayList of PackageInfo objects. + */ + //due=true returns overdue packages, else upcoming packages + public ArrayList sortList(ArrayList pList, boolean due) { + ArrayList sortedList = new ArrayList<>(); + LocalDateTime today = LocalDateTime.now(); + DateTimeFormatter format = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm"); + today.format(format); + for (int i = 0; i < pList.size(); i++) { + PackageInfo p = pList.get(i); + if (!p.getDelivered()) { + if (due && today.isAfter(p.getExpectedDate())) { + sortedList.add(p); + } else if (!due && today.isBefore(p.getExpectedDate())) { + sortedList.add(p); + } + } + } + Collections.sort(sortedList); + return sortedList; + } + + /** + * This function takes in a list of packages and returns a list of packages that are overdue + * + * @param packageList the list of packages to be sorted + */ + public void overDueList(ArrayList packageList) { + ArrayList overdue = sortList(packageList, true); + if (overdue.size() == 0) { + System.out.println("no overdue packages to show"); + return; + } + this.list(overdue); + } + + /** + * This function takes in a list of packages and prints out the packages that are upcoming + * + * @param packageList the list of packages to be sorted + */ + public void upcomingList(ArrayList packageList) { + ArrayList upcoming = sortList(packageList, false); + if (upcoming.size() == 0) { + System.out.println("no upcoming packages to show"); + return; + } + this.list(upcoming); + } + + /** + * This function takes a list of packages and returns a list of packages that have not been + * delivered + * + * @param packageList The list of packages to be filtered + * @return An ArrayList of PackageInfo objects that have not been delivered. + */ + public ArrayList getUndelivered(List packageList) { + ArrayList undelivered = new ArrayList<>(); + for (int i = 0; i < packageList.size(); i++) { + if (packageList.get(i).getDelivered() == false) { + undelivered.add(packageList.get(i)); + } + } + return undelivered; + } + + /** + * This function takes a list of packages and prints out the undelivered packages, then asks the + * user to select a package to mark as delivered + * + * @param packageList the list of packages to be marked as delivered + */ + public void markDelivered(ArrayList packageList) { + ArrayList undelivered = getUndelivered(packageList); + if (undelivered.size() == 0) { + System.out.println("No undelivered packages to show"); + return; + } + this.list(undelivered); + Scanner scan = new Scanner(System.in); + int n; + do { + System.out.println("enter item number you want to mark delivered (0 to cancel):"); + n = scan.nextInt(); + } + while (n < 0 || n > undelivered.size()); + if (n > 0) { + PackageInfo p = undelivered.get(n - 1); + packageList.get(packageList.indexOf(p)).setDelivered(true); + System.out.println(p.getName() + " has been delivered."); + } + } + + +}