From b547fa89e6f265a1281cad06526536af55ab8ad5 Mon Sep 17 00:00:00 2001 From: INAHIDC <136551905+INAHIDC@users.noreply.github.com> Date: Sat, 28 Sep 2024 01:04:14 -0400 Subject: [PATCH] a little more code (a lil less embarrassed) --- README.md | 78 +++++ book_manager.c | 165 +++++++++ book_manager.exe | Bin 0 -> 61226 bytes books.csv | 38 ++ librarian.c | 195 +++++++++++ librarian.exe | Bin 0 -> 61925 bytes nginx.conf | 22 ++ package-lock.json | 781 ++++++++++++++++++++++++++++++++++++++++++ package.json | 18 + public/.env | 5 + public/Caddyfile | 7 + public/Dockerfile | 12 + public/index.html | 76 ++++ public/librarian.html | 168 +++++++++ public/member.html | 106 ++++++ server.js | 90 +++++ 16 files changed, 1761 insertions(+) create mode 100644 README.md create mode 100644 book_manager.c create mode 100644 book_manager.exe create mode 100644 books.csv create mode 100644 librarian.c create mode 100644 librarian.exe create mode 100644 nginx.conf create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/.env create mode 100644 public/Caddyfile create mode 100644 public/Dockerfile create mode 100644 public/index.html create mode 100644 public/librarian.html create mode 100644 public/member.html create mode 100644 server.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..cdecb62 --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ + +# Library Management System in C + + +## whatiss it ? + +- **Search & Sort**: search for books by title, author, or year, and sort results by title or year. - i used bubble sort +- **Librarian Actions**: Librarians can add and delete books, with 'maybe' plans for modifying book records. +- **Retro ui**: I like the retro look a lot so why not? + +--- + +## Tech Stack + +### Backend: +- **C**: Core logic for searching, sorting, and managing books. +- **Node.js**: talks with ui and the C file. +- **Express.js**: RESTful routes. + +### Frontend: +- **HTML/CSS** +- **NES.css** +- **JavaScript** + +### Database (Future Plan): +- **CSV (Current)**: Csv for now haha +- **SQL (Future)**: probably **SQLite** or **MySQL** + +--- + +## you can try it ! + +1. Clone the repository: + ```bash + git clone https://github.com/INAHIDC/DR.BOOKMAN.git + cd Book Keeper + ``` + +2. Compile the **C files** + + +3. Run the librarian program + +4. Set up the front-end server (You need to have Node.js) + ```bash + node server.js + ``` + +### Members: +- `/member` lets you search and sort books. +- type a title, author, or year, and click "Search." and then sort results by title or year after searching. + +### Librarians: +- `/librarian`, log in with the password `knowledge`, and manage the library. + +## Files Treeee + +``` +/dr-bookman + ├── book_manager.c # main logic + ├── librarian.c # Librarian functions + ├── books.csv # Book storage + ├── server.js # Node.js for front end + ├── public + │ ├── index.html # Ni stands for Intuitive Introverts (a carl yungs theory) + │ ├── member.html # search page + │ ├── librarian.html # Librarian page + └── README.md +``` + +## Maybe Plans (maybe ill maybe not) + +1. **Move to SQL**: maybe move from the CSV file to a relational db like **SQL** +2. **More Librarian Functions**: features like modifying book details, borrowing/returning functionality +3. **Gamification**: because im a gamer i think will add grammar challenges or quizzes, turning it into a small game with points and leaderboards? + +--- + diff --git a/book_manager.c b/book_manager.c new file mode 100644 index 0000000..ed9c061 --- /dev/null +++ b/book_manager.c @@ -0,0 +1,165 @@ +#include +#include +#include + +#define MAX_TITLE 100 +#define MAX_AUTHOR 50 +#define CSV_FILE "books.csv" + +typedef struct Book +{ + char title[MAX_TITLE]; + char author[MAX_AUTHOR]; + int year; +} Book; + +void add_book(const char *title, const char *author, int year); +void delete_book(const char *title); +void list_books(); +void save_book_to_csv(const Book *book); +void load_books_from_csv(); +void rewrite_csv_without(const char *title); + +int main(int argc, char *argv[]) +{ + if (argc < 2) + { + printf("Usage: ./book_manager [arguments]\n"); + return 1; + } + + char *command = argv[1]; + + if (strcmp(command, "add") == 0) + { + if (argc < 5) + { + printf("Usage: ./book_manager add <author> <year>\n"); + return 1; + } + char *title = argv[2]; + char *author = argv[3]; + int year = atoi(argv[4]); + add_book(title, author, year); + printf("Book added: %s by %s (%d)\n", title, author, year); + } + else if (strcmp(command, "list") == 0) + { + list_books(); + } + else if (strcmp(command, "delete") == 0) + { + if (argc < 3) + { + printf("Usage: ./book_manager delete <title>\n"); + return 1; + } + delete_book(argv[2]); + printf("Book deleted: %s\n", argv[2]); + } + else + { + printf("Unknown command.\n"); + } + + return 0; +} + +// CSV +void add_book(const char *title, const char *author, int year) +{ + Book book; + strncpy(book.title, title, MAX_TITLE); + strncpy(book.author, author, MAX_AUTHOR); + book.year = year; + + save_book_to_csv(&book); +} + +void delete_book(const char *title) +{ + rewrite_csv_without(title); +} + +void list_books() +{ + load_books_from_csv(); +} + +void save_book_to_csv(const Book *book) +{ + FILE *file = fopen(CSV_FILE, "a"); + if (!file) + { + printf("Error opening file for writing.\n"); + return; + } + + fprintf(file, "%s,%s,%d\n", book->title, book->author, book->year); + fclose(file); +} + +void load_books_from_csv() +{ + FILE *file = fopen(CSV_FILE, "r"); + if (!file) + { + printf("No books available.\n"); + return; + } + + char line[256]; + while (fgets(line, sizeof(line), file)) + { + char *title = strtok(line, ","); + char *author = strtok(NULL, ","); + int year = atoi(strtok(NULL, ",")); + + printf("Title: %s\nAuthor: %s\nYear: %d\n\n", title, author, year); + } + fclose(file); +} + +void rewrite_csv_without(const char *title) +{ + FILE *file = fopen(CSV_FILE, "r"); + if (!file) + { + printf("No books to delete.\n"); + return; + } + + FILE *temp_file = fopen("temp.csv", "w"); + if (!temp_file) + { + printf("Error creating temporary file.\n"); + fclose(file); + return; + } + + char line[256]; + int found = 0; + while (fgets(line, sizeof(line), file)) + { + char *book_title = strtok(line, ","); + if (strcmp(book_title, title) != 0) + { + fputs(line, temp_file); + } + else + { + found = 1; + } + } + + fclose(file); + fclose(temp_file); + + remove(CSV_FILE); + rename("temp.csv", CSV_FILE); + + if (!found) + { + printf("Book not found.\n"); + } +} diff --git a/book_manager.exe b/book_manager.exe new file mode 100644 index 0000000000000000000000000000000000000000..7d930eb1589f1ad62bf2212c12a3607d29b4c47a GIT binary patch literal 61226 zcmeIb3w&Hvy)V8dk2ZZ~pe=+)Wq=e?q#<dOHbsgvNv55^BpLE(3l?{#nMpEsk{RaF zrihr5MmrACT#tHsj-J0kDYxfdJl1niibp*uMO*L{I9#oQS`iOZi^uBmV8loM-`{%d zJ$rT@Z7zq;^<MTTJ8P}q`mNu4J!j9J#=AyXK4Yu^_v9pFN0HLy<o{>>H-PG;SABUY zdu+kCuRdz?e*5aSo>1HojYYa+{$59?zppQnaO?~^V#z*7sLxT~-0J9!1cK#DmMkol zq<wD20w1`DeRTMDU95|-#q$_D$F5_G^75`{4j|Rz&I4>2Qaf&lW~2X<2b|=ltB?wG zRiG9$PCROZUL7bnI9RqtUJy|URZ57!8vuhvBFq2#7<)>R=H(-d9n7lE&5pSkE6W9< z>==Y-*>rMn$`ir<1YkW^;U5X)zzsdJuMWmK$^-s{A3(be|0-}3&FgSyT~5Zv%3}i2 zJ|7hTup-<!f&uI-j|x1lBXs2kCAwLclkoZlUJdc<z)gm)!ku+F32$dSPM`sjFG@M< zH9+!(1U+tR0N7&OHMp}bC*jq#v=OL-{*B-!{uC2gmy_@kVb0f1@KM}^w;6ZV<>Yn= zh9jNQheuFJc%CdIWSxxF-XwMNQPmi3!n+N3*5xF;%8eZIqhciExJdvn2kHNugtxAe zmp@PcPva(fJ8)-RPR_TQLmsC8=Wr9=yQyGYPQt6+zyU&Z7@P1qI7t8JB)kn3y!=`E zPeDU?J2^=I=OnxuA>Rb~%^~puIttGao*D91=`Y;^$Gf`9i?7<x)hNEo$vlIvmU+^J zA4e2cK7E2wG@$qi6!pU2WEU2r(6z6o@vdaCr_*<f$2PvNhQ{<n7n;2jm8m6%G{(|w zXe?3p1O;E_*_HTLihrK;ia!A(eR0a3SuD!mR^{gxaK?9|8xGdk628hY&)`#K$48zZ zi83Ds_St_Xd5a(Sm2~ZUeUUBUrX(+UVDKnuv$XgF@12~SOpi>UQ2F%GbHyJ&b|wT! z@l^wWfcKJzz$^12`m3Z}d{sS|^(WBO3B>yJK!&$<4~<dd8v*MYfqiPASrTo%!-d~N z&-4th_&!gToI;XjslrF8m@d2sIQ8iw&v4-<36QEUb!0ww8AdT^Qgd9&;c9E&wzU;h z9iH^c2(+!740_T9tEks{(rZ3<4<*r}vzIElH-4jde>aTqL?$0I_W$yvCeC?^zp&0T zG?x6CCtZCDCy|~vIAJT^zZH1tc@Tg97m+(rxD0ZT{baQl`Ju_;{XwLVw{jgN43rX! z-IZfsCTCSXJvp8!!PpFY`9XSe#WF6@ipL0fc*$4)G&$)><z))5ge}=ZkY4%R-HZ*t z*XHS*^c;I7-;?@%#)-<I7og4OQPq%os`$g3iR0j}iYfv1u4I`XUryAbHc#r;nTvtl zkUH0pD!9^<Zd(b%9rFwxFUmY~1#mY0B>8Qx?G?`nn%0;%wQ2`QW<H1#6c||xP`c0s zP<qMj_z!KoDg0ltp0NC2nqG1#vZ=xq_&@Y?@&2!qHC9YwARc-y5r<<O?|Qd(w`&L7 zBl-kPdIn_w1#P9-hW^K&CnukvX*x4mq5~fT5R85VT$t(`NHRZ#QbUs`=8+wXhdv1e z1lkAl&-^#!x)lA)Ah6PfLy#bgyU`~>^Y20I#5@uJlpiF@A4Hoo8;Hz^Cw1b?zay7A zmZ`j$#}@CuU&m-JI&9`|;i3_WxiToF`u8DT50Wf%ucbco%B3XDgzd61-fSf6g3r-2 z*_r2gS8}rBS#^|c_oRM~Xm+L=?VeP7N#@l;^r`pRZSTJf{oo^S2VF?ojb3n+6gty@ z|DLqF#FKUwc~b5P<R{RfJ}MEv1_L8}htj|Wl>$y>udKXUr;=|_0ay1qNwEa^49^da zIViHh`b9KKxnE8<zU)c2Q{_2V>LgY0NXUjh-H;mhq@IM>H%o@T6_EI&5JgJ4Ny1CG zl*##-#gOA{Le`eb+Sg%Bbj~KopZEStK<+YG;YTxWg|nNbkaj8LA;F`>GdLzdB*lE$ z?3v|YQVc+m1YAaR(1HTUdG~Sdfqk!z5kPvOKIMk~?RL-bPzU_xIvU`W$1=Og(dqUQ zSpj|l*HJ_mH`Se}OuHTA7155&v<a0Xo_$Y^A(gyn>>@^KH;jKQ^B9ak;pQ-^Gau%y zvSCi%WVo>H24Y6~d3o+wW-ZA?Ob6dL!IBrD#wlwmP;=Hve9|KaL6LIaVQ0XT=G-Sz zZKaOJ)UgIQba=(vWuvppIN}6}cH$Bt8n@EESDh3#!;h8@5Ut_Dd|i}ds{sK1e+RxN zHAKes41Sf{xOnKV1@`wP&L@F$=5Y>lkAm;NO8B*+?Gb_fRStdf36xl-NK_pbRiDYO z`Xxe)I9Ef})X>AgNDtG0Px|8=Jv~GOT`40tcS(N#gx(J<F6*#+6v6vt8taMJDI!YU z=uSA_lNR~_eiU%>CE0<Tm1B|A@VJoh7iC0;d~}%Sj%7Z~#pJTUFeDO7E=T>JW&H<G zf9CDnyb?yOUz4@ek6_lrM1An9l(6Krs6Q?1Jyb6=CGjsJVm}7biJ`9$F0Qk!9_R>b z2W68lqEmq6DC%GYE_Yg#K%gI$nABD%BT`d<pQVnpP!NTv)Q~hG%GuWYTOy4PJe(!c z{RB%34L~VE#o@vaU5^CC?Iizj;d^<J6#tW~*n*0|uW}`l=!}I+rS#j--f)CzM3w8Y zb_y9WH($foDU;(Ktgi?<>?;zZ=ZXp{@^t_W_LySo8RKgUtmsx;OQS_PZ*T%rMPlR7 z(+NlF<lq^bXZXq|J*&}S5>HOhdTMf+XYg#1XXAe){}V&~{S+`D_O5rI`PuJj?S!?G zpj$uew55*SHh9aEm}1A0=gxjkz|)04Z0FXVhuH@FPZWLwWis!Xdq8ZYa?CtqkbZ-& z=O-@3{JV^ghJ4B~=Erv}l%phvk0^Z#*P*u#*5oDTo#0!V!PoN=%LZS!C7N_1?|S!f z%#Xt>?@5xCs^3G&#vdns!sYU$^J$@z2RmYM0eJG4riS|b{KA4P{zTH4o5^0e`f&OB zi&rN~oyDu~EA`bEudXlc7~D9o_=Deu5z;XDibp9NItw1aVtMkkTGtJ)9Kkl;lfI|u zH}%DKm*Y3Z_Pr(ecaL4Hntyf?W2m{PzO<qt_3MVzsoxY|bYE#1;tiQZsRMM&KsWP; zrHG~CGVre)D=y;_ltBVmuOHHrJr;n^*-sdJ@1*hvjPh!f&&1&@z8@G~nWA#1QNDx9 ztrQu<D?dy5E#z2vz3?-$f4MzsJj3;++dZjoa#cJSr?-2t9PaR@yrn&~FfPj!Kt0z{ zEb-Wvd0!k}@)?kBKyO-$8c#Y=S|;r9f*r-w51}^}iJ8A!0+mOAF(Ty`i)o*yv-(S| zh{M;wwD`l9(nyppJPe4t@@dR+C3<{$u|(W>Jhse}_7$aDiW+R=C>B5PAqe6cJZ1xK znQP;(lczkXA7tzZMFb6&T*dqU4G19F4wC3XU-BILS-!^xtbWG{)Ig|f7s1=x7Q2pC z5a#e=%#VfFb8O5~o|LzwWOBtTK~AuE|NDTGt}m@0_Kgj`^e>5`Vc#DIU;0Dx;=#gS zwV?OFc|NR5Y5g`hk>@(<1p3heqMP=XI_it-$FNc^t?}fq{5sGZQa|vdZpU(})jql6 zKCr-$@TJKWwZv?A$?;W~S)R-Uux8}(``VeS$(8BC51}dQccDJLt;n0MFDc2~3M{}j z00x_9ZbEUy)B#w#YnyAUtKHQm4Day_hfAI5P1PVaG?~Ec9V~+6t{twsUGH{jcOO4d zcnN6)*)uNmEYCsDaKQlXuNRX#gQw4BJ_N&g(`yFd{u712yaQmWNw0hW0MF{DD3mHZ zslpdf<4t8et50F2I{*Gp;QylZvf_^nf_6HeX1jZ^@J`niP_~P*twk6giibXhJo@}% z@5ZymgFB$RH@#{z#oE6h|9;$)XYV%pxU2X}>-YV13?ex9zgC<oq{jQcgQL<(&+2b@ zZQmJsI(eyQ-=A@E%8EbIL~%Cw=Yiq}>yh(fGt-O3wd=roo!>C<(zh3-^Xnm5@t2<U z+D;F??(n9Inun_##rv;Av*HhCfHe4eQDSiLb$jv9X~0~?k4q`Kh9Cv)|40gmp-XW& zq+kPZ>VqfIoJ4|5#UJ@+6d(u*kU9NFD7*1&mn*ft_<`L}0r8Yx@nIia^<43X?;u~N zt8d5Qn0Gk%$I2JvI9YfP5D?q-X@;F}VhMVRy)pGuPuf#7`Mtpt2+reW@7Ux4(tXdJ zSqvh)9ViZ+BW3FfQco^wEh-*L5PgVo=H1BX{crGfXYtUVfY^{;FLV*sPIh^QUhDUJ zQhaDz@^{xV)`<T8xj#tyuCz4B&}(~dZy+tnCzIX<Kh`Z$?A`e1`@eRSz@ClYc>iPM zj~}5u)IYOJ$w|PI05$-)l_Zp2O+0z_yL|kU<>LLHLhYF^sCEjkc>kZ_;xl#y=TS8e zAaA<*9E48C3!rpSeY$hPYkRFe|2o>@ZUaLg)~BwE{p8HO#C3Q{`WkeJ@4U|QTPXh| z^0aSzbvruee>TAfLzsJ)|7&6uW`+Hw1JD@5r^7Q$|1hMM6|Zh9t-xeZU+SD3rxo~i zn*UNuo<Q3(AHyD=hG==za8WuBBV+2=zMsN6j(xwctJ{L``!r~7`UK89_w3n}MzZ_r zLd*m29GqCNrw#K<6k_GhTbl}jSG@m!q2=y(Y$`$_v3k==B+07E=boT3D)W1EXxdE{ z@Bbc(H0xf*D<;Q<Z)nqfd=om>K;qw_>J38G#3~HAP{Q#p&*W*NKfYF5fIhqpQlC90 z=3kDZ@7KW;La@w!ooPxkeVA8Fj-O5Ob`o!g#7n-&=N-{_3xH=d@aP%=Jrr1`O5!C} zLxJM`ZK&iGljCRBBQF|rbr(|OYjhZI{TgPDGfQ<Cm+&RPGT)v+@cbttK+T`Vd60K_ zmDWg|_otI9?$=<r^vau1_6)s{SdX)mPjb+vFcQ)yy@<|&zA^cI4E9UWbrK6a={n2- zzov!ayX<I{d=aF$vG@sxXL6MjZRO!py6^=YS`Uq-zUxVSFS(GPh|y8V@h_J^dvWL% zQq$k@#5zwZii54{uc1+@hPbSFK^%HL2nfoa)XE2Vt`2h$or|4)bnxWl*}s?Tw{&4x zu={3msW^SZ+C+>u!_^@{Vsga+PIAdcDr3QVedTj!7xDS`nZy;C|I@aOr#xwwJ$crH z#pByNsakvH+cc+;I03ZHq6}c+uWyGKKQc{UPR9EK7LUdI{}GDrsQ@J$A$<p^<mRsd zcB1erC}G4En{^RxS>soJ@|ASq-|+^CA7yTVFVB9@h}U%C1H3BPl`iZ@4*ekcI9wS( zo?Ka?)?Em8_$jlP6o9jSg(0DXa849fBcba=;X0X{ToJq*0To6-Wzw%rPO6nF`cdYe zG4`DOD_uU2xeTo)SI~LbnF_Q}ktR~PzZkj-IQ9{Y7vlW4U6e<#UhmqsQJn7Hfz#b* z_if~-yG8KU00~9)drKDO6@P3DAScEL7toH?7eDTrhkJP!<_t{PwvxnJ*RTfz-QtvY z*n6@}t*`6TPRztldQ-<@Mfn~q#Gi>RqD7Z?<H_XDu((!-qp9y?o|p%73{Dj7c`vpz zAA1{kztFYsX2^D@r?b{Lc~0KewXYu%C2Mguj7{kddkHf0y5QN`;aW&gfc3_G$IH$x z;qqek@@)J=;(FIn>Xn|<Z)l~r6|B&aUh<@{y5MJmy1p-%VCa=A7LX_~1BqhyLKG|_ zUGfxMw^Nr(2=yyW<<8}v)z3Bz*Rv8g3iHTBi7MBy53())D6BJHX2g%M&oOW6N!SNF zy^YVt9?iB72F%n-@PB&BL-+-$lX4#@ZSt$)$361|a6h?^&PyAp{TKw~r}zyx#rN8t z+;_9t&t3cOC7YguV{75qTIJZhlEjTlbkA_xI2=1bbYF8`@4y&@Zu?aaZ8PCg&&Kg& z1}@F&frz(s;nP=w|8u(h9*Q3sW(z#2aWO84DDxE8<4kV+xM3gIKSk}&+x{@QXCCYi zKln(AryGXb>?MisyM|pnHemlJP4=%ve8T=?uzxM=e=N4xGx%g#!^UTMe5Pwle>Z+C zbCrq@Z+hkLui)DZ81x+!5sjU7w=~*LsfbwWCG+c_xv01}<4O;Vz-|bIA45dnJSE?A zLcXWnh}~wyZqsm^S-#sK-^s?*$=HH=2<Y87hRqBF^lp4E`4V<J#188`ukF;?g|vU* zzF3a1DnQsJ=cj#((J{V1^z{3GUZ3_XZnXV?8W>~59X`({`b?9S86~mHJp0b@(%=H- zS;KR@cF!xG)yF&lZof0DEm6UEQp2UFFLm$()n_W7&fJ8LF3_)PfXnxX*fk_*Blt}| z(a>V1hxUh2+8_4Q60j!oGS&xtF$iMV{NgwYbY3Cg;8Pyj*vbq1K#lJ$@lSB%+sw+R zY3m274*FM<`Jb|_-ck_AjnAz4I2|aB)~CLW3DTQ7?n!+&a}Fd1|77Dr5B^{>Glp{J zllX@Zf#zramKe~X^SsP9=-W7i6K9n26AN7F#if~Lfa%jLed2&2yB;fj{qrENh2Mc3 ze%p!P+ZDgH2ESh+o6GOBfK9<qtOrxy%v^!`p)r2OiC%VGPIJ^hpTLp%Kn+V2&{@Zs zvzQ69dN6M<H};u#(!OMPML*UIF7nZ_OfM~N(}nXu;)zLwH_b6d@FO0l^%q|vnq5Yd zFu6N>1d;RA7r}DUp1B_^Fw_4Iw#~dp<bOu_ts?(j<Us&uV|xFS?USPYtpe|HYIB3g zf0pt%SR=Y0QSDW<jf_mLdTAT2taDQ}zfG?CsH~qkHSqH!{u`Sb^e=`nNZz@om&^9& zn_k254gUAyJdpUS^e$dD>aUUY)1|*?6YW*{q%5oSGrVljdqCF5WV%zP^jrzaQ7hB6 zGQCEo7t1tHroX}A&B(}^KfG*OLSaG0uZo-Gb4iF4x)fZL{?Gm2F^k-!N4E4BB}`Xt zea8)EI}GHM$8*Zjdjx*JOb2ch<uRGs-!95dSssyPhfGgZi24_0dRnHmULS}u_FGv# zCsSX28}qfcF^8nbRBF=d|D8g6+}|C%*-?Je&PZgJ*6Z&>G3L0XGt!HE;8w@G{ITw2 zZ?G>Bznl330X8*0Y8<yDLWywjR>v*=WTGb$LuPN#AG?*+g0KS!!NARqRdL78z4X6q zRbcf(77oP|ED#I_6G3J1sp$(G#X^u2FivzKYwz3D7unP2kaCwZKO=?W<(=`}oU}U@ zi^Lp}Xs|ET*X`&Eg@cYR0QST}2>{C3s`!oc7g)$*tSRE)jUE2o{!rMzGaM{On24*5 zlq5wKy11G=dnXh{Ca`d!(KZor2noyC9+n99MujLsj?P%nPkbFz5sCR@d$~yELNj`5 zvMZA83zRc<<Z=<;%08BKRMZ#AG#nM>nvq%BNkT5^UPmC(>&G*iL2jqA`sPMgL(^)e zSH~f3GVF)B_BzU18@8a1U(LINv954rk0a*q>kg{s&0F0qo4w83Rx_VJmI(R7j&LL% zcSO1z@lbbPs4IkLLpy_xGM~4(wUtw9izKGSYSXb8YwN+|q``PHoN(Y#(?lfVi1+%# zVdVIOrokvG5v{?1qpZEDUP+<CgKNj-MyMxxP%K-`qY|30ikGeGzR|I&d$q$+77HeJ z`@@@1z@bOU4<;wSb!u`lfcsV4f5g2Quosaw!Y+H(>{(w$54k2ny$CDBOfnX{84Yo{ z0s%-AcdUv!di-%mU&ImWMHgEW4|XO(kv`^dYz@T{Nq_i`WRRi&jUhXQ=BfbtN+K9{ z_!HE9Bo$5+|MYggSR?^js^y+gq6fVo5Oh@Zuj(f}rF%3UOa>w_9-e<h@J0IQLES{8 zGZJ>dhj9X|3X}_}XKuGMlz<=a4QAt$v;bR~KzisNNhZkqJV<VIBrvE1dHk=6-sspH z3Wfu`Gr+g7dJ=@AN|1^lPfq6EKl+h?ZATsD{~5Qki}HeqW9rZ5t3u8L3hK-)=gf!p zE#`idTOM_p>p|B^bC0?X<k0u*H`hCd%;kZcddy)adObPiKu)<Mr;KNCP3^~W%Fdj! zC#Q^OZcXj&Ipva^a#>C}8a20fRG7<0a_Y}rZLarSkyFmW-%?k1v!krPX1%t)YE3i} z5A~yK^{j~ncURo#s7;12PGH7CFWs_j4HX0Y`Skao$E<c#t}9<#UZFho|7eQ6y$v_( zz~jM4%kf!i0rC|{_u^iR`~cGNWsEIHp3-09E=B$v(k09BkR$STq@}n6$X6h}1$P*E zCsG&gDDpm}&#l0-p~zEu>m{I#Jf(Nzeh_&|@4<Z#c}gd6Ka4!33$aN%f;^>vg&pNr zkRL_*L)<5kKaKP@JQ_ESyboyv_lw9!k;ZYKMt%V4=W)M`JmywbiNl&#k#{1k!##mK zVvc!msPsq5BW=aK+z%5WrNgQc<j0Y&#lc@G@=m0mz8ZQXKZ^9nxIM_9M*1plAM%K6 zcHmmfU&xOjWu<uh8+l42xWmXtk^UNYKf&>l>u+%Hr#wELT#EZa<n2h`hWlg4JCJ&D ze+qdY(owpRr*zZxup9DDq+_^`AW!M<a6g7TeHS2(`zZ1QNWX;pD};lz0W<O#@;;=O z+<@;tAdhuDyC3&S!lxAXIPzG}v%I&%&d6h}&X(bR8F{SF*@tjvkjI*xy^ebVd0I%l z4R_H_;2^EWZAadTG=_UQ@&ib}i2F+9$B@2;yA*l0hOzayZ$uvZEmn=Yir{ZubGCpD zEo}uhR!}Qb*weOf9$UC}UPWO?K{Vf&H?~05N3k9y{O8f{U%^c=O=)iZZvmT+zE1U& z>hy^h-9`C@MX`c>n-BR#1%-=jC5%cOzE;8sCp)k3?FB>j{32T!1Aca1=`b&!&8y9; zuysgY#BaK~OBS$84$Ncr{zA5>r-03SDXSgP*(uBO3)uXR=2zr(*rK)-3*9U7?GG%j zSk$pFx?pVnc;V^%bC892d`9xbQv!u+Z56q8v=N=Pl1{dq3SY^oQf05~b_$l8QXBFe z(S1P5O|S=~OgTQa$fjf<x+<^QD|u83oVTw3J1lT+z|doH3S;sh=B|AP%mG+GVB51` zc&45m04$mXyAQBYzz$@=9s}$sU`MiGrvN(**jN^feF$R(V5hQRJ%APM$M@k7zv?;) z*g?QfX2D(sYyz-}ESMvW>1{~0GN(QX?~&<%Oh;t;s7#-d=}R*Gg-j=8y6^*Lx|ipa zuaV`oIq+Ip_U6F1%5s-XqcZK!!FwR5{0Uk9haC7(S^kDhpO@)NGJRF1^FAo_c$-YC zWLhiJ+hiJ+>4P#oDAU6-eMY9w$@GUZRaSagmS2<UyaS?UxlGGtdYeq!WV%D90hxwn zx?84-{{6CiK&Bs+>8E7+h)fm!5n2A4Our@5Q#p8V#fz}mTk#_7Fk8G_W~=AtnRRrq z*y#_q%5$DgHaAYCV!2?J$lDT3c>VE&n-1O>yEng~4=w#+oUh~}e=pw~^zXKSS){Nv zm}u|o!GSFfkKFy8!6=>YY{up{7-R1*Yz+s4QTCa_ws0KGw$cd;d$v%XJIV7S#{N}7 z_(>F=3}XI7Bt)wRO^a$;uy1!Lh65{>C(3&iz{6s}-pKAC_6^AO`FoKoVOl(x(E5UV zH2T6fyNtmU{Cl^Tv#wYW7*{Ylwu^LPHwSt^PR4^Vc_xP)0bq4nJR0nzvqDX12J7?} z^agu7qkHN5-drjTCrO|&&nWH2np2kcpmI06lxdy8{!oHJ3avBJ*A?o<@toG@hr#zy zd$hPbyJk-)5R~w@0Uk?e{)Bc<GSs<C6LhXpP+nZc1b98uLb~e|d1)j%K&P)aXJc?S zruvPd9!~3JZec-xG^!=`MuY5jQ4aOtfGiZyqJDhC9>?Y}!#3NQe`h3?V0SVhWjCX< zR)1J{&`)}VB0IINWM8N9A)S_!dsx1(SeGajpcGF8LJ^n?2z}b_u4pXOm*`?e)|x%C ziv1Pq>clB8sQnG=!tq|5eTsF_fjj#&>xw2({(II%=k37wN5%o{vn-y7b@oOXJ50GS zklFvFTps}+6*;*32;~xyUD#_tf`ET-IMm$(i!MTm4qfk!^nvPPD%~q0@D_$F!ix9W z0sKFY`*wFrliRy)ZFwLJt6?vSHvVX6O>cb7o>1Q!Sa1#E2ZyDJHQ~xNm1`;_Vj1x0 z&cV&{tr`Co;L@FgPajIe_r~#&fEk_nfSY~iwCf4_qox)CD{bmoCY*lY(49jI&fM)! z1Wl;yLE!!G-Z^~aF|C=;DEOT3okNd@Yc{pVKr8pQv_VjJXE$P4TcTa|ozsSbEvE$< z{a<k5yw7QyLJyn?P6=0^OW{0i%K9lty#;#90&iL1|1=9Y#H&|4pNC)-{11b$Z?t1H zIyx|VV02{k;OOY+;n5?bM@Pp-PmYd{o*vDNPK>gLfbYclGm_DV#vVHP(D*~A9y<3h zJ7hoPI8<@SdB}ID<52X_z@d>tqlb<h8ap(8==7m;hu9<bM;wn-JmP%B_ejSh(MJXz z8F^&%kt2`LyIt&{RW#}ttr>NWBKy|$CRpG`@W|tQiuiwrd_HIGG`#V#2k^`AU*J!J z_7?ar!~&&|vk)ipBrc!-O#x5?=wDOKz!!=I-g1=YZ)s|G)KzYfAD}wc^d^#h!A+f! zSa2;0{#a+vranAa(C2ro=~jQus8V-VUt|q7S$zq|nl4{M9scj6k7oI5EVQ$`vl9@Y z#1sC`U2Etm1#F_RIbKPkJcWA)?mXMP&K`e^<rU2jNAM&K|Cj8eJx?%zw~ZxGQ)tw1 zK;HZ~o=i$O%xDFLys|)Gi~M{uioJkS3Ph547znJ3^lB+XfvPGfz|%1P1S=|94|6Wa zD-hD@_(G0CAqN%mL-gS_84#PpK&UeqXTOAcSKIQJ!tUEq*Vf+T)>`X4?)rAGI~(S6 zwX`+3yjqKUi&pRUx$(S9Q{A1+mes1&txbcKH$B#7pH|o0ghzPVTC?fqPv2rH^a2CD z-rd@!ZFYGf4dm1|H@9e8ymhS5z-UEPtIyleM#{9Zc}9&Af3w%Mg=^Z{=JI;kd;_Dg zdFysolvQ>&Hn-fVH8!+1y4vbInrN`VK-k<4Zgq`5&DB(|)wZ~rfV6HcTR1bu`YN_) zW{lQm60(&o&Ovi|+p}1)B}TQYuCBeY-Ro*|Yt8L#Tbdi1wrH*vkXUNq_*$C1&0E^t zT6-&1Lt8g1Hmcpe21~Wws3ujtZWr2IWB`5btsbqBn~7a)fQh~r0fSn$%mCLnx7RB0 zas#Zen|*AB0aeI=USdFfu6nK2)7*k6Xm6@(YiMp_mzrx^+->bGO|7iN0B>$?Z_#dR zho8I+jSX$=GNTHXZrkQ+fvhd=&2BiEEK}=la&K;^LyusW8>rqopNxPj3}A~J0yQ?* zH*CI>U1@;HSPe~e_3k>h(ttKJwYj&rTeSMkXyN7#Xk~9R>YIISnrlltyUGB$wl+7^ zlihi&yXxy(@J=<OFXPELtpR?=zs7ZI$rI@BQ&-opYm6E}7U){D51~u_sE)_OwFZuK zOKV#TYyvNo8dcm_E!yo(&D)yLm3*X1Yb~tP+*-?48F=V9E-xPObCZp>qGNJeuywPh zqOFx(XW*0BT3w#a?0Pe-&f8Yc%FHl4ZN1un2!+feLv3RNyCDmu{<e0E9_>x&2441d zqoNt3V#8)WQo(7hP3%UaP8w=6#zQw-W5C_pebnb&wXLk&fRg;42JYO=4KUeF=Bn1L zstR+}=FKf`w~tjCQ1|vWt)^mK%?1(-BTrLXD_d(+Z$XT<h#|XG6N6p@)LLg?5U{;T z+27lYKt+HxG$N|2ro(~<(H9h2wHeLls=FPYlyO0p(lOVYG28C+xxMaI2uAc;*#>hp z$x@-!-l_SvH@C1FqmnvE3xvk#P4UvIwKZ#7(T6t9fU>!zxsfB?JSCEtP+Boiw6b>? z7-EVrb%3nNirr#hl20K66w$IVHcg44rZ0A@QQb<N)Ys~1-(1VyX@Es!Rn^{!A)ESB z!*&?TY19+nEv_~X46>G{u2$wUSGLx<+Q?k8w$@xLn^uXYb>>RdRMys;YeiG$HbZ3_ zw%Gs+6)M-(Y;JUEbsjwD+sd}&R<EsIpH=P2t*)+In^oOlRBv5dzZqjoeLElJ#rWK! zc`yX}>e+1uo@?uNu$V5=Z=V6t9PC~TX4W#I(NqbI^~i5B)sQ5r_cWVopl9~F#Am9c zW_*C8KGEQ=LnPc`K@j2^7%e6YqMt*e)q;>qqRqgN)9to~Hjf4yvv#A(<=y7GvlYuO ztO+%&gs{e`*}%3M2x3U3(cSBAV%v<0R!_s`wo10$fZXM#v449TmYAC0)l|>!H0m)m zG&ZA0$WfH$Hg=a$z1f8kT=W+9E(4r33v1h28rs}!hf&F`(paf&ZE$HAZtgZ}nwn`k z@VOdVTv(T|cN;Zotw;-EvFg*ZDy58f@ZlV<2G%EBLwd3L^cz)DAu=D^X@EtHd7I^W ztd(^dbu<EOuk&oFWdSn~8db2M0V6%c5JgiD>oRIY50%3gRwGp1ZB)x8D-2rSAi5dW zKNx9x3>2XxcRLFiV5R9D4MNlR7*%d8v9zt^=yspa-NJSmRbIG{h2>6#c6X+o%GYfl zQacq_3s%y!B9XfkS@w}R<hCRmR8xzs6nTLIw^RIzJq9n=wr+FznAk;d02c%AdA7}y zn>?}ivKMNQCxPD0^6c|fUf<)fyu1Q!GwsPL*R#BWe0-!84F~%j2CPVjiLG0nT?eRL zokNG1_JMXqnRpvGk~Dw|>C-kXn!q;o20Oi(x?nx_(Ji<aF^J8lCvO8fhsJK&LOX0t ztEVYT!YT;Hn|uhF#eai+p^eR><{w*dFa9sc?~q@cn%9Nm$0g7wfk2=2vR%aNmtJJM zxHy056-!qwT~>$|c(^XV=*mUdW0$f;i*8+%kJEwt0$YC3tyj-qbag?)vYW5Ay`ymB z)$?q4(67K|Ygk5^!YZ`7`RcrPEZTVWMGec|dD$&^9Cuz7+XD1_LSNXhEDula&cDdE zs%Y7w{Hw0G%6=)1k&3~ifu15<!LCP(g_jVSMWDi=i>`)1i?3!4%Wi@|Z(VP+1-64= zA<pv3k=kswKP+8B37rJtM&>GhIH;kVhkS9~hpC4D!{LTHE6V>Zvt4sd_nj5V+q=6f zHhHhPCeMb(^}r?Cw@{m@Xy;!GCJ*2~gqzbZc$V0{K*g6R_wV!%&ELBIi!4CrdGsAl z_^aQscz)5Sv^Jd!)1_Rj&VyY`?GNO+mX-|U_bs)Lxt10^De&I<|Cecjx|?s}XRonH zBym$b)_D_7U)P8)#@rO<XR$YlXJ&2+t*cqTqjPUJ9)&1xWpy|2(A(|k7hk`rT(`C& z>pM6}dSD`!&~{f=^6%q_20IJ}svW*Px2BiAN4IY64#AVr3A3x!v9^5O#=lIv{-sF$ zU+l*V3on)xUbBX!h?KSEo&VLbXwu>QLR|=--Irv$tWcNT3)0V~>WnDpPT4&a->Ie# zP{=IQVat11_s;Md`uHS{yiuv*vz(qfLZJ~iy~VKGhF%-&52C&4^2?HqIj~4KRq2I& z$kAuG9EU?6#Q!5$QsyJg=N~c|O~t2<_@)o)#%96!5pc$5!6^i3-z+$^-WZ()rw%xa z!EYYPjGHlft>XZSGieb3PRA@b_W=hBq8aHN2F~a#bjE-~n+e0t-$v=k46X1eT9h=w z@>}X9o_oano(<tXr_XjlO6vY|P%bb*eg#N$23|mB3*p=W;29ELN$#Gdl?yobS#Y|6 zLmyTe65a!da~7)}1kT7Tl)na?bF<L-H{f*4fJ0xQ$5+RBFEAu5MBr4+!u<;1IA+1A z1deYOoGrj{&Vq9{aK>?ycc2ii2uja$2wAo~jHi7Ad)O;FgmCtvbdE!)6>#wJY%K9x z9Y?gn{tn>+*MkloB;?QC+Bt-`lD~39^av;4R*E_o74=K~!Vv*Tx~WDR^(#Y!17(4u z)~f^&m-@vbD#2yI3FH4lD(aW|^&<jMl;_*p@E>1I&AARhONu(WbH_1-`cdFGX24M+ zEq!<`N7}vJwCte=OLqpl6`fCkPKB}<8EJ~^3&3$I9HxFdO0*&g@r7M(U!&=TShWJp zgjJ39DyOVUwiH$+o0u<URkEe9sv36;JY|gpK*Ac?FCY=K5A`N$;ZvGUVGX<)L8F$> zK^P;RPr^R8LIndt(S5fG@)JPrF+nK0Crpq6a9#)n1s!E)ArINP4qUewN+I`#*;)R6 z7ZHb8;Pq*X_R1GzL*WauxcO4PAb$y85RNs%OHerm-36~YGZB=OzYZWT{DoBpIVfkL za4qPJE|3<pNQ{{y>kIe1cXLkFXmwh(;*c$X*rAk=hhoeiM(s4bz=NX0hYoFcIe=Dr z^y>XW$U`>#E?Um#^wmGBzs$S{PmMM@WgFP!T*?<G0T;fYm^WX_7h?bu1&n_954E!{ zW#<vVgq{2R2|m&qhE{PH<+>A{ECMpC^s=KYMp4qsd?~%00K@g5v)GJ)l9J~j@<N_H zcv7d+9}CP)9tY?Md8V+T{Ovd&aD+U_<XlRgM*tV{;9-4Q%oyVEZ%PnI*a!2@RQ8cG zkzqrMH1nlwNPZVGo9n5hY&fIL^0)I&17F0(6uQgb;d>c4R4aU8mPzUU52zQq(>HAR zFDiBd#4i;a1LqMN7pB(~GRwWg^WZGx!H@98lX%mS6h<adG!^nVri@iWdp~fFnELXE z0Xc`8Y>+$WiV>hcp!qQZpq^rzzQY2@z4)%G4nc+;0u3k5j?H7ZVV~o`A+H$Mh4{S# z%|xu)4FWQ!#)Owqo^4Dx2OJ0rO-u1VXH39vAmSGj>Yb?Jn&#}J0A}<%iNL9=nF&YE zDWm8Q!m1u%=jhJq)ZeAsP&^t)Ec8q8s>i1@+4AVsJR{|~i#QlEPl@BIm<b0VReIN5 zcM%P;iim_9I`X$42|6u~jMW!`BVx6`PkjB!h*s5id^}o+mzfWhE+jUhz!$MWo;6>p zFTV<~kf)QrJ!aZ@ztQpxfR~WREDM!{zv}L?BR{jh>Rg0BGfu-@WwYbBN@l{5{`w<u zgnfGPN+-it05kOtFX6A5$9co26KHAvDCt6cI)K*G+EA_8Fg%I=<wOMKtT*IbKzhwK zCM-v5F(%NwOcaev#m^$(2>YPpYF*LF3d2Sy(%aAyJ~Zc}A8>OoiNbUoebpo&)C<g< ziNYIZF=-9bR9It*o+4*P$9Y&|nQje!o~-o*!%@83tend%XZ#LsjsN}LJpiJ!_3j&W zdBls+a1M^|yc!<*0@M}qIHnwJNbWJ<j7tv+PkaxMk16g9ud&1TXFKBubqKY32{_KB zYStsj9|0Lb%4H@1n-7yaaEn-_9u0BjMKdg2HK?zc0Y{BdhE?AQ?CV5h`Ts(qMVFAj zl*&YgsoykqLSP~Dy9|L9FBwrKsDU7`YK55yN@^WW-hokoQ;PpNbFLhJZUK(yUs+#J zHXO);U^0sB_H_M=n7@~BkQ$ax0diWk(tDhsL-KfmEqsj(zb?dvqi7)_lYDBv)SASj z+XtbQb1D1ybo<aqO%#nwjX(9eefksqiK*A3=eVY%m(gD3E<~>*Xe9I^ubD3;Pn#|e zPF2*GqqF=q3d;+5W}Yt$nGb^E+~<oih&h`tNM?uy`%K|4wPu6LBIapk#X>pjQvT`z z9TCsu)13H`@k}@(p0Q|3^ki@2IK{^y$OxXspm?6jUxf615*Bp0UcA-M0XdDF0r?NY zSuXnp$Dxzmj0xvjK%yp`IwF9>3ErFZej(%``|QN9bPcDb{#{7?oJJ!qq0OV3>#6D& zJD?YdKGV370FJOTjV<Q>qv9|M9No^nh{dcJRAVN?JMDlrrJb#MO%d~Qzw87Np_i_X zo>B4)>hjQ;thOhHHw&nlQJm7E372Q;enAAcfyoGrBjS)^m82IJ%@^|Z2+XeN@G3fE zi_Xx>Y7M+jkMFkyW%{qI;Y6M|O%<7HCqAP!<m~Vu1Q%YmgPQqLz3E}#2ro}R`lWTN z5{(DR3Hqh<a-4^kooIFbdJ(4iQeJ*YmnVvaUuSmE@dl%iP{=dAm;VVkK9dKZ1Z30% z`92^{JiI0PDUtpyAY&%TVp{mZbOz2<fDD)*Hvuwcf_MS(;W04t2w>RoH3VPIOdaqi z{9xt8J(~?_MuVVJ$B&GSPXR~7#*M%<Un(}f0vr(=VIbgjky)4W#pA#cBS4pbS1=1f zX8XuKxcFFYqfwnCGhg>goFxF~+b~p4aUGC2SnL6ZK3yQ`jZ2S1yzLSq0Y^Q{lZEpJ z*^nrHOv*!_LFC)$D|^=KVTnWYsu*dlG5t>xhk9tf?Xy-QfP78j;NeH$(5P;vqkQqS z?u#it0ayD1-9A=U7c%}BG3Kxm0)+fd-WGoUB1E6s@8oUa_fJkqhipjmkFcQwIr6Ug zqS&B_5V1k_kp{~`BY%;Xgunb2BFcvJWS)p;vA2>h>oM=GF35({&uBDzPTNoAO6DiJ zJoKQE{*D?hk9uKE2bX8+u}<|1fkW{_^Nv}4<#!)y#Mn|~#gVh{j55oy<s`_9v4!ZE zFEzH5fsq(nc!ZdclrMg1)?K`UN3Jl``*`qX4l#<FRpRuN?gD3;z9Ywk4zze9bRXAs zC%w#<(!J_DbpL}{cll}}p}cxe(fE1jE^tV98V}7zQhtx3=8e$(MP2vl{q8&u-SJ{h z*$3%4cN`b?Wq<C$*f-Ia^*H1vegTkvaOb^AUs2mJWs$~HuA`*i2Xx(O1STsOms)G- zyr$Z%%YIs`%S`=rr#~K~*GfhGirOzAp^(Qh<tH_S_b1>uxXi%e4Hv<XBRWLG`=9uu z23N|M=Qx)G$6<n$0dg80aJm&NHERTp)6{A^AOku?y;f>Whfu37!kK}x{x&N7*qX5- zdH}6Xp*875GU2_}fV_y*fIJMyX%plzKz?h2JO#)(9in=-;pOW<?i$n^mx}NafH*H( zKXNqR7?<+$fQlaqnVd`Qn_fnp7}<O|7{+;v7mTJ|HOYPMI1q$)F1FH<Gqsc3knofi zc5vrf=%2^wGPCj!1$5~KJ0?nm5w#MK>M{syf>cd_hzYX(2rMfhlDlV4+?QLp)2W(? z7rsA{16lty3wPg~xR+SC)486Rdy$3vw=CSZ&xt#ImBhrW+G*i#w{SmYaF-*A58jz> zMcpG_`^F3pb|rd}eY>#MGI*(#p3-8fc$TA|9#K=_$QfUcv8ixGjIBM1h~v8R)jLJD zamhHeMqPGfO5OL(pu6ht9dDjqRVB(_Q=M7K{^e1YpB`s}L&b*eD#I``XVL3|`uiyy zl9{7!0%MB_QgzbO-|sh~PDV?Qvg!qKf6>C7hDS5^aSQhY7VgnGaX)S0US#2Z%EJAl z7ViCX;{LLQyWPV5w1xYpEZhg?#64r-USi>%v2cIH;4XXIM}RZiXk)~W8f~&-OvcZM z(qgJn;td{c9z)NWZL~3DR`Xz%%u@GX%%HpKm2aY6Rp*qyrXNYF9m>no<7{|U#fI(b zX-6AfuM6t$4=T#~>f)efwCPb=D4g{#!&!1nkkN8bMau<oAF*&BwQ!GGxW8uMJ~}7v zAG2^jY~kK-;XcpkaZ>lgbK-u`!u^Pa`+$Y}atrq(bK?Ff3-_ZI?guQ~%PriG&WZb| zh5ML=`-p}6Z5HlhbK?H6h5Jbh_k$MhZ5Hk)=fwT6g*)vXWN#8Hkg8D&_Z=4Q<8$Kv zsD=9}3-`ko?g0z;Q*+`@Ps*7ztv+qxe#F8(Y~g--PTU`}aL-t{AGL7bZE%;f%mi>| zn_-PHQ_Zkh<Ek7t&M7V4gc)}9JZ4x!W;MfR$t-n$AJ)&)>8@tjH&L&uG3Br6XU}SS z8k0xe^f()is@SkOU@7xu(d&ZdxKc$~&7RdoN*)ENI)w-@^^5gKaquM}GFm27v|JGP zG7ERRh5Km>_itFZGaNEgm|ob~#f=v3B^K@(3-{+O+>7SKy~4uXVc~wx!u=%+cl(^U zS6R51S-4MFxW8)QUNR@{H5Tp_7Vb>-9TkV`=ON_GQRkQw_ggI7Yb@N0EZpB_;a)Z; z?oJDLr-i%S!oAAEy<$$>>n+?p7Vae$?zL|acaMd;&%)hd;eMNid(E75_gc7bw{S1B za1UF!(=QWV_-Ny^aPP2iudr}`(8Ap_C+=+)?mZUnH5Tp%E!=%`;=bL&J!;|Zv~WLc z;l6!N+;>>G_glDoEZm>5aPOEC_YMp90SkAZh5K`F5chzE`vD90?H2AoG`P!^ReFY% zl{zIh)(L7=S!D2%>x8JXA$6df%ksIyR5%xKO8g+`LlJx)N1ysneM)S|tX7p-GE3e6 z`wY6P)z_P-S5=4d*YqpK>Jer6>2WsnsMxSwlj8||x|Hj$3tHDr;9(+ec{O)e)3-oP zkg74u>f#fY)kVLGmJ8zkM+^4}3wL^Ez$DN5e=xX9zkhKCzpI!xv`{ghrKz;xfYM^B zcz%P=D(Uma*<#+1S;c&o%u@GfX3$;5#+#^D)wuH4^zmHH&Lig8dBnV~*9Ar0^OmSP zZHc-gN(<F5)<0m0x>GY)UPYZjM@3y0FBx?sZ(`I1&Lip!nN`$f$t<HT4<4Lt|NbWG zRdrPPYlf)HC@)Wsv*DDAjTt_V)AhQbsC!sZRuNTwRLP?tRR@$73bKBy5p^<J4ytIm zAnu1P+{Y~3M=adCEZj%u#QjkVcX~sCX;iN|XyG2Ua6ddJ?nf-#$1U7PE!_JJ?lR`> zGsL{=?}i6ef6wx=^xzSt1$gFOZ}iHFo<^B%mN8^j{XI)&sr!vH=&oj&H&L&u!^&UN z_vLCDpM~x?dd<0{rW+npu`xq`*Y&!f9+yy*RbQ?iRq`lERa9xAAnR+5sFTrhR7J}L zaqqWqKWyRNZ{hAWxJ$p^JcHj=%o|#$n9tHwYB8p?coSm&mh*^tLuM88Su#uAx6Yuu ziupHDuc`s%uNh+gi1PCEI2-O$v0+=4(<_YKgs#^GMP0q3tm3))fRaZ+s<taF6lDE1 zM%2k@IjN%Mg1CDu+(#_jJ1pGS8r-Gd=`AYLt!-4y8(OHC&(c(CF|M?D6JoyXJYwFE zS;c&o%u@HgGw7~j{!P@Ysz>>2`gpEBsJuKq&IYfF4cm3o#=NfA1x4MJin5C5>V74U zf>e2w77DWda!b^Ga0bh(s59uOsLSFdqwe&Z7<F`7Gu!IIkXc1tmdrBhUYJ356?Jc- zUR6HjujwPIdO&%3dYlao6&o|0+vs{-P}CJE$||C&dz3s1QdOh0P>}Ttji{5+l2Ore zLEH;0+&e7XD=ge6)Duejnbo;Dai=f9nf4CV+b!J7EZl!#;XW}Z?te5s$CuA}`YhZX z7Va-uxHCNP2{d+LpM*|WxO*(zODx=<vT!e&6ZhX*xH~P}?H2BjTDaTi#QmIwdyR#A zk%c>bV^>CtjQNr|aevjqy~4ts9BPWp^#c~}jyZA9Sh$y2xKF6jSnuyW7Vc$p;{LLQ zyTihrzJFoX-Dhx@<NTQ!#(6cz8FbVfm&HqZutI48d*@zn^bVTnbG>HxY{HOP&2d>W zOWl7rgYIgMdlU7la;jLJe*UVCDlbouvth9sjcw*{&yd~J_w^Pa62yucZ@5<P{KPv} z35Txd5nn=g$JF1+dK3Ll@=$Lxd;#J4NKG}y^%`*K`+8KHKgAmn39}HkISL%O9yr$T zGZM~n;CS?S2GJZ|c&l3{z17W*8ma|3Tvwx&9bpLvNr)2=Cx5obAtAQ|BA)70kN_a+ z6IDSc3W)NcfIJ9@+7}4OrvaghN&@l^fNYmC3&>XiIcdWA79i>~4uSIrqGM`xDbDzh zz<`Dp8vz-UQ72k$2IMddNPSR1wgI9(`x6lQd~DprJqZY1#8Tkw2ZY|iVetAaAU?hZ za7dgd0XZmJ<k9=|!kS-v%h<5|cYvd25JC9`K-BXI0`g}-4DV>2;>&qOCSDign;#wM zgOig=!W#e~Hye;TK-4!x1m$}O2Nx8PGJlXm99gX%0)(Q{pz~EgDgZIG_%0w0-OgN7 z^hT!%=PYp4r~j}9UYJ7fMJ5`CRqY6B`gVh`s)n!m(HD_?rZ~I~IBJzEv{*;2Og^m# zq{PI1D<Fpfp%$W5Hz0-<UERS%9ChN^U5CWk1Dw;kJg8<L2c*LU`5Yj02`zeqy`9m$ zh*gt!jsl1DGNSGqfQ;(#6HRjFOgurVxPKow6((MP0%Q!lgui<IVZ8qedg;7k!QRO3 zAbNog(db2Hjcr_0L-$KCxJFHsZvaHCpM`za12SQ<YMmUCjcB=pTIqf#D}(_tVwE5t z0YrU2PEh{;h>j^TzXZq;6R+n1Q7a<R>J>of3}3_sQT_uUK2s|PzM9{I8biXH0Xb=s z&<#k1sZ|FcwAwN3lK@10b|bid29Pn`s>J>CfQ*`KcoL8f)EL}<3W(Yh2|DKhDFcoX z3D@GC1y0a0AQgc4fJ1#lw5lZ>lNNUa66NwJoERYIbb0(c@zcy`zuhGBUjfIV<Di;- z6_63hNAP+U5QDp>;f=8PK`pwB5#Xo5F+*MhL_7<sqL;qJ{3=E+L$69e)OuC$+6;&j zgs3DSoq%La-suBm#H7W2)XEeIX+X}Ql@S}C1Vo(-2+EHD5&$0|Pb?_D;wa9;mCVlp z$7ACDV?fNY`ddKgq{5JSF<$m?%G9caUjLx$-YNU(L6a5@z!}4cZOGgTh|d%W8XzZi znUP^>KqgF)a1aoq$F+uo!6@)1OtJAL;2hB{M&B5xcZ(685vwPN4&*WPdLEF|CcS<N zh|@IZ{tA$zCVBGlRbwA08-BkDkfVSYl<VZzkqw-?0T}>yArEGd5Uo<Erx?8;1RNMY zi_Shk%;Wrj17zG3;r|GTI-?em@Na;On&y;W1466~Ulil5U20DxTHOFhSfD`y`q4Z; ziXA4ORs(0mMA;39M{k7;+W`n&La%rt*4Nn^Wl>YBKHwO3<~W#C`b{|RBOH^ae+S3` zlfV84Adi8UVdqnTsB<=<*L)PmOmxZ!0hj3S;GT%=f_F^Z-vJ!;9Fd?C2BgHq{eGfj zisv*S<ECgi2*`-Z@{a>@1PzI*p!_XB)c1}B<VS!|r7<F%14QlL1&$qWK2zUS6p)pG zoHY6C?SNF6Ah!YHFhTAH#BPfDJ%9}8ns!B^!9Iv1zIWr0GCu&EQ9upLe;yF(7bJ_2 z=WBp~OqLe^3Wx&`Bj#TM<bZ6E$GSShk$4cj$>fXQP%D#F8Qw4D&?V&SG4v*iLqS=i zrI#Gl0hIDAL93&BD}vt$h{r^^2@s}_5{L~7Ue;lfX9sY$>lWjE*`M1_-$Rs5cHRq! z&%|p85OuP|*Uz1_ex}Q?&))*)w5in>0HJZhh>d56vZ>XJfT+*)gfEujZCfBCTWMW1 zK8iRrM#w9Hv)#n29FP$cq!y3?lU}WWRG4}}0FVw-%qIbX8M9(z5ReiRor8do-iGdf z56Gy=Uta;lX@YzQ5HFUdMjYm2z#KKnYzO4939=H9b0(jb0n(x4@QCU}k2A@$2{?8@ zjP?9&fH+Lt-wVh9tN~Io>P7(R(J2GWJ_|^PNsE61WXuGi_nZZQYk21efH(j#`q$3^ zQQx2uUS5uOp^YMX4emDr;xTEu0T7yn4V)%G)F=ChL;03?iYSBoeZX<*{_5Hj!|P<Q zDlk$00C3bd$Avr}17yGy37-Yzph?pw0HMo>=VvXDmjH3_xAZ8h{t6H$S{V`+qW+*s zo{Ir7Ru06Y6cCck;N=8_E(5Y1kP(x8b^+3(%j{1?Leyehw+5By-AE^O9D+OuNR0_{ z2#^lckOaa${|Jb~WS?Vz*mcSnf5J5Q_L%fK1stEL)hmFM>8(JX{Rbe-q(uqdf1}Pb z1^045YV=lJa+5Z0;&nT<GHKBR$b%qm^titU#BAp$02u&|q3JV#jGO3u50DCz7C#4M z)YR(FfS5<NrFf6dVUvW{0WxN4RSgI;^oj)$si3SwsN@3908$75DO*q~4+M86yET8z z-`5?Ct753HE28rLojYT}-KrE0^#xVFD~4^nD!^$fOE~!DqZs`F3H@XtUc<E89}We4 z;L;mR1Y;h5UmzTeF}!+P>*OzKlJ6}pEsq7e@KeC$M$1qloQMZvk%ZP2iFJY<e+kaC zh<p3a3oo9GOotch^>+s~{thN>I&OF|sFv6p4YFQ;AFu-`TTsPhlPj)Vq+75X8=AIk z)9^F%Z7#1@t9RG7Z{fd8?QUtY;L5kk3G+b`ddrmsNsecX|1OH~XO86p5%n`Aa8!bR zDh8(tt@MLcNvk#*eqtrGo7~FlH5^gwvhd7B0y4(S9)Dcxq+i#w;s@X^Ix->+G}=(@ z^iM&yyDy2?rgjFSiBP0Zy|36xOvG9w8~|=qf3L9>FVq{=^jCvftNBT4uG{E*)jtI; z?PsjGA>eKc^)=?0RQ?>;9z>1V*8KM*>Rc}Q3j+<vX&QbzNQ(u#LveH%O>{K@3<Pt) zfnXTDivPqDe!VcB;JG-9`{6JCi&2S))*0W;@B`oChoIu17wP4&SddR@l-Krz5<QWm z9!mG#doRQYM6~X3WT!u@1?UG7O%VQ*iB|oyf3llA8$##5HyEI%(%(cXt2ku<%Ofs? zW*GX)7O`LyCm<Sr<^TkG{jpv2T6Z26q=tVdey6e5-`^@=5H=d5UwG7F$-YFWHwb$o zZZVa`*d7EWvBgg<S^U@1-qhC6=+=C#?)Lg-{0h9cxla7txVxzy>+1_>pg~I!moa|` zZ*@~$H=byZ2V;%?M2|aWjFb2sf~+^FGi~a?mlW}0YSK&F72GRaQyxXvgg#mIopGkB zHHr+>Y4~|fArcXwp9WJH=7wTa$;B5(k(MS}o40k^?yFIU<EPse!||@jtFqtyzlKD` z%L=uvG;3f8X`msw7H`F4+U8JSz~`0@&MDUJZK4TDS$s<{A@MdxVy-{{zw<!hE8JmJ z)<qB;Ih5S}L9hpo&z;4)A>I_}Q*qYNSC@?8yeYvEbh^R5WG^X9QHuAd#{99p7!`Xj zbZXV7(5dI=tjSi43>4Nl(8KQz^A{eXtMjrdYB&ei(6zDHp=l3M2!R2kfe60>MP}KP zUGyikdy=8fUDLQtm=K$(WH_jW;&hnEG=FcrTj0aS7-9Cvmuyb$bn%8jk`JSU7Vz&4 zhq`+bOaZ93-isF&8UX&8K|H5ikyEZ@=Als&(++(yST1KSCf>$p6!}kQ7)9|ju<NU< z*HyzR+Vo=qb!}a44HIJ^gkhG>;QH{QRi!;98brT1x78>j(EIRzS1{HW46j?O`O(ir z(DJ^ZVQRt)D?_nJA19yiiy0TA4uq+1Yi<z(5f!O{ZYTVV2L^YYzCRiwCm<d)dhsh< zu^atJ3s-8DS_NjO)?lK&uZJ(g0&X?6ZVrVp*I;;?Z4D-PQ-{X~6{4V#<YLK_1;Dzp zTVaS#eMk+O@wqqnSgM%iEHK2{0mFL&7UIiC4da_wKk91$X@q-$#n4;5{&)i8DW6-o zIb}Fu_JJt^L1o%rbXy2QhKchjLCOOdor`z&fKew*fng}r8Rxc-6OBk0$&GG7ZpMm* zyfB@~`Fx}7tvh+jo}-zG)9=y5Fm)64UjKU{F)g0l8Q+U_K(DqN@1v(h5Dy3PEIxfy zrWD4g=Zk?l%!VO2NFOM9w9H~n!|~ZO_|^~>g#Pdy$zW_RB+|o_e7hR}9$+}wHH%>y z4it(wo-)`>WeuZNaMFh`J!+&77z6w0Lpi;Hnp<_iES*<ypJKhJB9aThXQ#Gs9N~rO zC`r=`!NHx*$TSV#V9ixstJC7qU}vZ+)R`5jGe{$r70R}HM^Ryct{u$|IboQb0Y{Fu zf{3Xv==Lxz_&JfR{(*TQ7TJ^2LxhP4%e)B_T)JqFDW&d=^mT>0li1MljwWM+n3(61 z={pR$PamN44wE$=>Uzj2T;GJLIbF(W?CoUe`mlS%ijd7bM#^EA#s*ysrJb0qRIHQt zvDD(7kTmoLvC_8oxGAC_SA`jZZ~BSH94*;Xts$W3Y1}XvKO%9{z(Ly|>7eOGFN8OC z?z$bMJKTL36fKI*v~?BH!OvLu;DcSM#t&f)OJL}rot5l#`l?@q4i24W_L?bbl)HGJ z#gr_!23SRQ_i?|{uqo#m4D_`6!Ir=u=aVfl6sJMc$7t?6s=}1UCam0Pi__q0lgIEg z3vQYpq~P)~gPB(yx~bF-pOzt5Cn%S5J;X_+rezQ0vZvCFs=Hxk8Tr7Y<}hVk^SaTz z>@b!!z^0K=2_=obyR$QlnaMD^m>D`Hp01kg;g$|Py=UkFIypxwft7QNm5D(=XR(2G z%r2?l)G<yD#?B+y4=g{;yP?QVtt;6_i<=x;7#nctp}Jyc)>vWkh9QgE6qB~bA&Bsn z{6KPMH|2EJS$YgcYOEr%#yCR~^Kh>prRA)Yuo8lL(~TTzt8MWD#U)=QYJ0L~2gpum zy+T|0=!-7Ubo*aH%CuvV!JWM#r;yOheV-aOh&>0iu#9ACW~Wa^xu|>ewKzFPoMXV> z)|rw*!aUK<#zu@$=I)cTY8NxSGNiPT`q>5)#o{n$a2Gy|@?Xl7O<)^H4^>d6;mJIE z$tTa00dtlW=6%de+XhKMzGXglvqGaz)`U%t5Dzs>GkFRZqm}7EL|-ZMktutjEC!N< zq1%j>ono|rZH#3$%@ZVnb={W}7Bs1uB@}||`!YS2)xobItbT+6%etx7P0ESUD0xnI zBRY_o4A&aN4ZYWY`Yt)u%0?d?NnZJYnGj7rLnFE>daByL<u0bgK28nr(+vl?qmAUN zn?>v=)cT5qnQFg5R>0DuS6V`TV4kz?qj6MxMu0=htfTGeL^F3U-5}Eq$5xj@_N<Qz zrnf&2R@IFapB$Ai4)P~Pbi<hU(z$bv==y?x_MVWAc<Hz}?C%!)R%~W>#S^=57y#Sl z%v5sLGes4~F?~-A-=Yy>aoR1YsLK^Y*MU1%2B+v3Qw#&*8BIBQSjSOOp`RtGy%|4` z&+0vLQ06m>!Jj{Gl-)`6s+kt8(`=#1V{!_Z;xK{hXY}T5d1juyb0<ug{CwB``f;Be sRQNM1x{BhNaA{ba?pY21)tIUJaL&+g+EHembkQ`frf@M(=>z-!4>=C{GXMYp literal 0 HcmV?d00001 diff --git a/books.csv b/books.csv new file mode 100644 index 0000000..1cb6579 --- /dev/null +++ b/books.csv @@ -0,0 +1,38 @@ +Pride and Prejudice, Jane Austen, 1813 +1984, George Orwell, 1949 +Pather Panchali, Bibhutibhushan Bandopadhyay, 1929 +Gitanjali, Rabindranath Tagore, 1910 +Gora, Rabindranath Tagore, 1910 +The Great Gatsby, F. Scott Fitzgerald, 1925 +Slaughterhouse-Five, Kurt Vonnegut, 1969 +The Hobbit, J.R.R. Tolkien, 1937 +Fahrenheit 451, Ray Bradbury, 1953 +The Handmaid's Tale, Margaret Atwood, 1985 +Crime and Punishment, Fyodor Dostoevsky, 1866 +The Brothers Karamazov, Fyodor Dostoevsky, 1880 +War and Peace, Leo Tolstoy, 1869 +Anna Karenina, Leo Tolstoy, 1877 +The Count of Monte Cristo, Alexandre Dumas, 1844 +Don Quixote, Miguel de Cervantes, 1605/1615 +Ulysses, James Joyce, 1922 +A Tale of Two Cities, Charles Dickens, 1859 +The Picture of Dorian Gray, Oscar Wilde, 1890 +Lolita, Vladimir Nabokov, 1955 +Catch-22, Joseph Heller, 1961 +The Master and Margarita, Mikhail Bulgakov, 1967 +Invisible Man, Ralph Ellison, 1952 +The Sound and the Fury, William Faulkner, 1929 +Beloved, Toni Morrison, 1987 +One Hundred Years of Solitude, Gabriel Garcia Marquez, 1967 +Midnight's Children, Salman Rushdie, 1981 +Heart of Darkness, Joseph Conrad, 1899 +Things Fall Apart, Chinua Achebe, 1958 +The Sun Also Rises, Ernest Hemingway, 1926 +The Brief Wondrous Life of Oscar Wao, Junot Díaz, 2007 +The Amazing Adventures of Kavalier & Clay, Michael Chabon, 2000 +The Goldfinch, Donna Tartt, 2013 +The Kite Runner, Khaled Hosseini, 2003 +Never Let Me Go, Kazuo Ishiguro, 2005 +Persepolis, Marjane Satrapi, 2000 +The Hunger Games, Suzanne Collins, 2008 +Shantaram, Gregory David Roberts, 2003 diff --git a/librarian.c b/librarian.c new file mode 100644 index 0000000..3ca8a0e --- /dev/null +++ b/librarian.c @@ -0,0 +1,195 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define MAX_TITLE 100 +#define MAX_AUTHOR 50 +#define CSV_FILE "books.csv" + +typedef struct Book { + char title[MAX_TITLE]; + char author[MAX_AUTHOR]; + int year; +} Book; + + +void to_lowercase(char *str) { + for (int i = 0; str[i]; i++) { + str[i] = tolower(str[i]); + } +} + +int is_numeric(const char *str) { + for (int i = 0; str[i] != '\0'; i++) { + if (!isdigit(str[i])) { + return 0; + } + } + return 1; +} + +void search_books(const char *query) { + FILE *file = fopen(CSV_FILE, "r"); + if (!file) { + printf("Error: Could not open file '%s'.\n", CSV_FILE); + return; + } + + char line[256]; + int found = 0; + char query_lower[100]; + strncpy(query_lower, query, 100); + to_lowercase(query_lower); + + + if (is_numeric(query_lower)) { + int search_year = atoi(query_lower); + while (fgets(line, sizeof(line), file)) { + Book book; + strncpy(book.title, strtok(line, ","), MAX_TITLE); + strncpy(book.author, strtok(NULL, ","), MAX_AUTHOR); + book.year = atoi(strtok(NULL, ",")); + + if (book.year == search_year) { + printf("Title: %s\nAuthor: %s\nYear: %d\n\n", book.title, book.author, book.year); + found = 1; + } + } + } + + else { + while (fgets(line, sizeof(line), file)) { + Book book; + strncpy(book.title, strtok(line, ","), MAX_TITLE); + strncpy(book.author, strtok(NULL, ","), MAX_AUTHOR); + book.year = atoi(strtok(NULL, ",")); + + char title_lower[MAX_TITLE], author_lower[MAX_AUTHOR]; + strncpy(title_lower, book.title, MAX_TITLE); + strncpy(author_lower, book.author, MAX_AUTHOR); + to_lowercase(title_lower); + to_lowercase(author_lower); + + // Search if query matches title or author + if (strstr(title_lower, query_lower) || strstr(author_lower, query_lower)) { + printf("Title: %s\nAuthor: %s\nYear: %d\n\n", book.title, book.author, book.year); + found = 1; + } + } + } + + if (!found) { + printf("No matching books found. Maybe you should add it!\n"); + } + + fclose(file); +} + + +void sort_books_by_title() { + Book books[100]; + int count = 0; + + FILE *file = fopen(CSV_FILE, "r"); + if (!file) { + printf("Error: Could not open file '%s'.\n", CSV_FILE); + return; + } + + char line[256]; + while (fgets(line, sizeof(line), file)) { + Book book; + strncpy(book.title, strtok(line, ","), MAX_TITLE); + strncpy(book.author, strtok(NULL, ","), MAX_AUTHOR); + book.year = atoi(strtok(NULL, ",")); + books[count++] = book; + } + fclose(file); + + // Bubble sort + for (int i = 0; i < count - 1; i++) { + for (int j = i + 1; j < count; j++) { + if (strcmp(books[i].title, books[j].title) > 0) { + Book temp = books[i]; + books[i] = books[j]; + books[j] = temp; + } + } + } + + for (int i = 0; i < count; i++) { + printf("Title: %s\nAuthor: %s\nYear: %d\n\n", books[i].title, books[i].author, books[i].year); + } +} + +// Sort books by year in ascending order +void sort_books_by_year() { + Book books[100]; + int count = 0; + + FILE *file = fopen(CSV_FILE, "r"); + if (!file) { + printf("Error: Could not open file '%s'.\n", CSV_FILE); + return; + } + + char line[256]; + while (fgets(line, sizeof(line), file)) { + Book book; + strncpy(book.title, strtok(line, ","), MAX_TITLE); + strncpy(book.author, strtok(NULL, ","), MAX_AUTHOR); + book.year = atoi(strtok(NULL, ",")); + books[count++] = book; + } + fclose(file); + + // Bubble sort by year + for (int i = 0; i < count - 1; i++) { + for (int j = i + 1; j < count; j++) { + if (books[i].year > books[j].year) { + Book temp = books[i]; + books[i] = books[j]; + books[j] = temp; + } + } + } + + for (int i = 0; i < count; i++) { + printf("Title: %s\nAuthor: %s\nYear: %d\n\n", books[i].title, books[i].author, books[i].year); + } +} + + +int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: ./librarian <command> [arguments]\n"); + return 1; + } + + char *command = argv[1]; + + if (strcmp(command, "search") == 0) { + if (argc < 3) { + printf("Usage: ./librarian search <query>\n"); + return 1; + } + search_books(argv[2]); + } else if (strcmp(command, "sort") == 0) { + if (argc < 3) { + printf("Usage: ./librarian sort <title|year>\n"); + return 1; + } + if (strcmp(argv[2], "title") == 0) { + sort_books_by_title(); + } else if (strcmp(argv[2], "year") == 0) { + sort_books_by_year(); + } else { + printf("Unknown sort option. Use 'title' or 'year'.\n"); + } + } else { + printf("Unknown command. Available commands are 'search' and 'sort'.\n"); + } + + return 0; +} diff --git a/librarian.exe b/librarian.exe new file mode 100644 index 0000000000000000000000000000000000000000..fb327956b933db4ea7be9bbe775d2526d94702d3 GIT binary patch literal 61925 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 literal 0 HcmV?d00001 diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..1b3d9fa --- /dev/null +++ b/nginx.conf @@ -0,0 +1,22 @@ +server { + listen 80; + server_name idkyet.com/i-guess; + + location / { + proxy_pass http://localhost:3000; # Proxy to server.js file + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + } + + location /librarian { + proxy_pass http://localhost:4000; # If you need a separate backend server for C programs + } + + error_page 404 /404.html; + location = /404.html { + internal; + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..24a2d7f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,781 @@ +{ + "name": "jp", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "jp", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.3", + "child_process": "^1.0.2", + "express": "^4.21.0" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/child_process": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", + "integrity": "sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==", + "license": "ISC" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz", + "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "license": "MIT" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..c6c14b9 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "jp", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "body-parser": "^1.20.3", + "child_process": "^1.0.2", + "express": "^4.21.0" + }, + "description": "" +} diff --git a/public/.env b/public/.env new file mode 100644 index 0000000..f4dca03 --- /dev/null +++ b/public/.env @@ -0,0 +1,5 @@ +PORT=3000 +NODE_ENV=production +DB_HOST=localhost +DB_USER=usersaidHI +DB_PASS=holdupwaitaminuteWHAAA? diff --git a/public/Caddyfile b/public/Caddyfile new file mode 100644 index 0000000..79e7240 --- /dev/null +++ b/public/Caddyfile @@ -0,0 +1,7 @@ +idkyet.com { + reverse_proxy localhost:3000 +} + +file_server { + root ./public +} diff --git a/public/Dockerfile b/public/Dockerfile new file mode 100644 index 0000000..312fba6 --- /dev/null +++ b/public/Dockerfile @@ -0,0 +1,12 @@ +# Base +FROM node:14-alpine + +WORKDIR /app + +COPY package.json . +RUN npm install + + +COPY . . +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..5fe2760 --- /dev/null +++ b/public/index.html @@ -0,0 +1,76 @@ +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>The Library of the Ni Society of London + + + + + +
+ +
+

The Library of the Ni Society of London

+ +
+ + + diff --git a/public/librarian.html b/public/librarian.html new file mode 100644 index 0000000..f948491 --- /dev/null +++ b/public/librarian.html @@ -0,0 +1,168 @@ + + + + Book Manager + + + + + +
+

Use Key to Access

+
+ +
+
+ +
+
+ + +
+

Response

+

+    
+ + + + + + \ No newline at end of file diff --git a/public/member.html b/public/member.html new file mode 100644 index 0000000..5d05663 --- /dev/null +++ b/public/member.html @@ -0,0 +1,106 @@ + + + + Member - Book Manager + + + + + +
+ +
+

look for a Book

+
+ +
+
+
+ +
+
+ +
+

Sort

+
+ + +
+
+ + +
+

List of Books

+

+        
+
+ + + + + diff --git a/server.js b/server.js new file mode 100644 index 0000000..ff40457 --- /dev/null +++ b/server.js @@ -0,0 +1,90 @@ +const express = require('express'); +const bodyParser = require('body-parser'); +const { spawn } = require('child_process'); +const app = express(); +app.use(bodyParser.json()); +app.use(express.static('public')); + + +app.get('/member', (req, res) => { + res.sendFile(__dirname + '/public/member.html'); +}); + +app.get('/member/search', (req, res) => { + const query = req.query.q; + + const searchBooks = spawn('./librarian', ['search', query]); + + searchBooks.stdout.on('data', (data) => { + res.send(data.toString()); + }); + + searchBooks.stderr.on('data', (data) => { + res.status(500).send(`Error: ${data.toString()}`); + }); +}); + +app.get('/member/sort', (req, res) => { + const sortBy = req.query.sortBy; + + const sortBooks = spawn('./librarian', ['sort', sortBy]); + + sortBooks.stdout.on('data', (data) => { + res.send(data.toString()); + }); + + sortBooks.stderr.on('data', (data) => { + res.status(500).send(`Error: ${data.toString()}`); + }); +}); + + +app.get('/member/list', (req, res) => { + const listBooks = spawn('./book_manager', ['list']); + + listBooks.stdout.on('data', (data) => { + res.send(data.toString()); + }); + + listBooks.stderr.on('data', (data) => { + res.status(500).send(`Error: ${data.toString()}`); + }); +}); + +// librarian +app.get('/librarian', (req, res) => { + res.sendFile(__dirname + '/public/librarian.html'); +}); + +app.post('/librarian/add', (req, res) => { + const { title, author, year } = req.body; + + const addBook = spawn('./book_manager', ['add', title, author, year]); + + addBook.stdout.on('data', (data) => { + res.send(data.toString()); + }); + + addBook.stderr.on('data', (data) => { + res.status(500).send(`Error: ${data.toString()}`); + }); +}); + +app.post('/librarian/delete', (req, res) => { + const { title } = req.body; + + const deleteBook = spawn('./book_manager', ['delete', title]); + + deleteBook.stdout.on('data', (data) => { + res.send(data.toString()); + }); + + deleteBook.stderr.on('data', (data) => { + res.status(500).send(`Error: ${data.toString()}`); + }); +}); + +// Start +app.listen(3000, () => { + console.log('Server running on http://localhost:3000'); +});