From 3cc665ee1dd6ca02a3f74daf200031ea9e6cc5ce Mon Sep 17 00:00:00 2001
From: Mimmi <mimcr147@student.liu.se>
Date: Mon, 9 Mar 2020 14:21:58 +0100
Subject: [PATCH] hej

---
 README.md        |  54 ++++++++++++
 architecture.png | Bin 0 -> 24045 bytes
 nginx.conf       |  27 ++++++
 schema.sql       |  15 ++++
 todo.go          | 214 +++++++++++++++++++++++++++++++++++++++++++++++
 todo_test.go     | 149 +++++++++++++++++++++++++++++++++
 6 files changed, 459 insertions(+)
 create mode 100644 README.md
 create mode 100644 architecture.png
 create mode 100644 nginx.conf
 create mode 100644 schema.sql
 create mode 100644 todo.go
 create mode 100644 todo_test.go

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5bc4d3f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,54 @@
+# To-Do API
+
+This is a backend for managing a simple task management application.
+The backend consists of three different parts:
+
+- Go application
+- SQLite (default)
+- PostgreSQL (optional)
+- NGINX (optional)
+
+An overview of the system can be seen here (dotted boxes indicates optional parts):
+
+![](architecture.png)
+
+## Go application
+
+In order to run the application, you need one dependency: "github.com/lib/pq","github.com/mattn/go-sqlite3".
+This can be retrieved by running `go get`.
+
+If you are using SQLite you may want to change the database file. 
+Update the following line in todo.go:
+sql.Open("sqlite3", "./foo.db")
+
+If you are using PostgreSQL you may want to update the database information to match your system.
+Update the following constants in todo.go:
+
+- databaseUser
+- databaseHost
+- databaseName
+
+## SQLite database 
+
+If SQLite is used to store all the list and todo information.
+In order to setup the database schema, run `sqlite3  foo.db < schema.sql`.
+
+## PostgreSQL database
+
+If PostgreSQL is used to store all the list and todo information.
+In order to setup the database schema, run `psql -f schema.sql db_name`.
+
+## NGINX (Optional)
+
+There is a configuration ready for using NGINX as a reverse proxy (in `nginx.conf`).
+However, the url to the application may need to be updated.
+
+## Run
+
+To build to application, simply use `go build` in the project directory.
+You can also use `go run todo.go` to run the server directly.
+
+## Test
+
+Test the system to make sure everything works.
+This is done by running `go test` in the application folder.
diff --git a/architecture.png b/architecture.png
new file mode 100644
index 0000000000000000000000000000000000000000..c77c5f8b3bb08e16b1174479156483cb34bfaa5c
GIT binary patch
literal 24045
zcmeAS@N?(olHy`uVBq!ia0y~yU|z?-z^KW=#=yWZS*PBbfq^kG)7d#7+u7YYKPSH^
zxF9h()g`mIASbahz?gwSV`6ebLXfA9#)-tlgoG1kwKchl%7Z#OdV&(_PaNQD*~62>
z!_|56C~F@hqn(2)kAakE&F*6dI2P%@ZaQP7YP!{PYuthBNy|Q5?OyLP+u-VAhILb}
zJW5gc%ia+@nY+tNLP8?AA?N9*NlXH}nNNsmGFfq*n8%#7-1&yI!y6Tj-y9LX9utfw
z)H0t4^El_hGV9<E<`dUEorL_|lbqkOGUiP`^QdXg5wBK;WTthh%u|+xO=-w@{-^2G
zqBCE5gjn4ZG?r>rJX3xBQbR&gVwSN%!y%bPzls$sbR>_SQ#dl~y|KZKcmMzY|DV?~
z<9Z!iTd%|17;C{KDKQ?NraL@5>SbaoVyaE8Ga6@T>h?B1yj;Y_cF%*2?IE{=?Zu;+
z$J`Ps-Q?8S*sfLo|6d=LoRBd8%z+Q(hyMTHFaG!c|8m2C&$4W7%#{qHimC5Rk6--F
zz`(?v84^(v;p=0SoS&<gn3A8As#lR)zyJa^6;>6w1-Ypui3%0DIeEoa6}C!X6;^r0
zRv=-0B?YjOl5AV02;Tq&=lr5n1yel}Jp&~>E(HYzo1&C7s~{IQsP>|iG+U*Nl9B=|
zef{$Ca=mh6z5JqdeM3u2OML?)eIp~?qLeh<;>x^|#0uTKVr7USFmqf|i<65o3raHc
z^AtelCMM;Vme?vOfh<yh0f;+GGSd(?<rPD{m7Jfe50cS0)HBeBn+-A^Bx)6uTAZI#
z3Nk)4FSEqX$Ofz!T^M1T4Oo|Rer`cgYH@L9ex98nR12~gx_bYj%+$P+M36Ob^~hrA
z>H{+JOY(D5ONug+J@ZOZiwcTTp}JuX#H|8qmW@6rxR8Pm5;tJcAQv|~E*pJtEP`Ux
zj*H(_Ycd0a1B0iFV@L(#+q>+0f?aPN|Hv-j$P##juZfpC;=tC0o7Ua9)^>=iW5t3s
zygCPx4%f!U9&O^So-XRx)g^ndt2Xq=Jy#aN5Qjj4fCqa%%a<ihntf+>_0Fd%KhHjI
z_Vk<k*><O)f7-K|Q4_V@92po{1RM~A!ZN0<$x-^NS{ax)6dDjjgSbM$(_SP2kd#0+
zBh&SW`*K?CARa=};lZhDgppvD!ZjwAbsP8DhVY@<*KlC!cT~*{4r^FBVv=jCSID3`
zfuT|RJ*sAg#t3eK9mjrs3$R4-1Op>e_&sJ6_cJhU6jLbZ{rYxc5t=y5x;^a3A;7@M
zlBDbKK<f2v=cj1m95I#r$brJZ#Bn65;ehG2?d_)&5#9%}1a^FqLkd<<7<6o9Xv|)d
z&p*`}#6w6b6g;&BX+bi1G+;*q7I%tW?TD0I95!<P`S<(%x0~tnr|x)jH9Y?Awp&@N
zg-+kBQ{}YNmR<Gu?*ikiYop7ba{gR@wJYWzBO(hmCJD{3t={%_`~5mqy~@eHW*a>x
zt4)nK_f6aLL*&bVtMA({E_T1&E?<}N|KIoh-h0HmOBoxpH{PpUCyg+KktIpfpyo$G
z^}|+ipZ+ORnR*JJ&P8$`D05SmoEK=Z9P5|Q4_@xKw#&KLhecoo6XPV~P)4nG7kEbM
z*zWND-rlv&?R?AJxtI!tBQ~XUW}ces)+=>%ZI)@6{IkNfhE;w&AjiPnHbrDb{Qi9}
z<)891?&A8Nc+eQN3~7|$64-I<!?FNXG;w<tj+p-&9!R2=P7XY*5|5=0&vu%MC^S}u
zEhv6|?%E>P?p3y&?(PhYUcw5i3zh~JDWDjcaFz8~k7V-teZN-mN}J_e<quPEU$DBM
z@s5WcGjc$4IVXI4baY$7!KOnyW_a!5V!H0t^u&MzsoZE_U<y@sco1c}PDT`2r+~wP
zNh};O+MJUPqpIcz>1AllzPh6*1n#0n3GN<w`+Lj$=1M)53NmF8@DNj2U9gGmydb>D
z>T+68{{G&zh0g4km025iaOy;EI#T!lZ+Z5W6@hnFg(ZJYl)Emq`1uhOr#W~w{`&fQ
z_P@Y?0t;4ukQcK-D+W6jGBjrM<a32O!DAI{;ScAA17G>M=b;s_M*<oQ*BS274B>=(
zbU_xYRr$Ld-KZ@qZcQ#IVG&qi!nlbmTuPN4VWdV{W9sQ?H+v+FHwj%?9e&>IUPbci
z(A8nraw8^2KG^^N@A}#=7v0Tjf0bn4*|9Nq+s(9Xzu)b??IxW&rLvvJ`}z6#`T2Xl
zPV=2<baa+kZr1L1yH;<_yL&4vTDLlS-lpGmzu#{EmtmD&dUv;B^06DM*YC?Z+{Syl
zK=tTOjo-0ae*EjC;Lc@e<l?OPeAay1QL*SLyVe^W)r#2lVo~>-3C?_)rMFi_?aa8S
z^!s7E{2Iq*wr&4@y$-*csr7V6zx}@*fA9bQ8-L8Q{HwFWe7o8=kGl1@srk-IvAw_f
zyj}M4xn;9zzuin%-4>bLYq}<QxnJ4qwcCF+SkyLezh8Iz+nr+n{XeG1*KKU$m0p$~
zq`F>QKQ4z`OlQTU<may)Ib%M5Jr|gdNDVi*-fTF`w`_sN6jAN48*grIu6;c>>JOjo
zmw?@0E_uKG^Z7jg?2y}!llyJc+~sSx$d=tm{PtpTf7tEH)745>ePee`*N@M8du!|G
zuc6$lo8DcIt3IpdGb6$LZpq}@9}nBVeYxyEJ;Snh(Fwi%e~NxTxBvgLf8n)v-`?K-
zJ?+-}eZS9b&sfD;_T|OJeX8FUw##jLyZ!#YJy%nHX9+13tX0eKYldg(02`*q$9gx1
zt&N(xBcW9F-SzeJH7i2A6R)p}%{{HVU1wwLM*V>9#ZB3)Yn$2mw|VRBT*7kl$;ruY
z4>0p@5s#}lxNg@gE$i=hii5WWdgtEoKe&3&<<n<o8ozze%)gD_?#BW4EwB2{+<0EH
zv|^9i>H?d0%v-_f6HI6@HTs(0z2ep@mHK+^_IbLoyRNAD&I(}(kNxLe^SIai&Gq<t
z)6%tJ46|1L`FXzHk7c#6x}VQYm&ZZt_x;M+|E5hk?}WsbtkloX&c1y*J${@0-<SUX
zYPbqCKZ-0kYC7+GYZM~+hb%ns<KyGCsi&u1+m?G<%f|bebM~AiOsb`&f1gbD_saS5
z`Mmw?W2sp+Pq$=V&Y7LN?PF}Jb=jL2%sYjwcd$zBul)b_`)%>~n#5Pr_B?EpzV+|-
z`+Rnpf`+T>_HJ7H>Tdb{udz8-ZNr|vUcdiavh~+J(cAO3owIuVVx>OUs`&c9rT6EC
zt({=~ZpUK#X}cWke>`a3w>$6rJX_&pJNG`BOeyB7N1f_XcXyT6DyeSmcy&j8eoc|Z
zn)UP7y*+Dw|4Xvh_nYbRx2xap&3(J|x?j#>^;iE^FS2@Bar4x}cKN*TcZ&OK|Ns5I
zY~4Y{%1f={aT!@#b1yIJ{rdK{`R#XgJ15z$^!`})`)&HJzWP6p<(Iu)a>VDr-2^VA
zve;Gi!s_t#FW&8bzwS!*zgMf*D}4{W|Nr-w%l_WB+qj+nmNB#Q`P_UrH9W2}Cj9D=
z!b2awyf_x`rq|(fGfw}G#my6}Ig;OR=5D{MBp&dqwvA7AR-v@)?b4~fGS_>L_LkkN
zd@gi**PGoJZ){8!ejU?x|A^f?cZU6Y&pnOO75=@e!D8dt((AF}J6pUuOCR2nGR+d%
z8Fv0iS(Q@zhI_q^zLDYAxUcWEDAL_p_y7N&=k}?&^CINe-DF+YnR@aoM_=dE&>u%w
z?@s*9xR~qwg!=Ynt2g}aUVv0)2gEXY@hlN@pSpJYJ*&bf-}*}no!RdTt-5C4+x+*(
z<Nmje>~bG;55M34f8X0pr}gT*W^9<e=^dY>(UI*nT7eU{g};7X`~B|o-3POzB)2N8
z%CLDMTYe`|eQwF5`n6#pd#~;HHM@C4|M$z~^K<%bzkLWk_9DhBW{Ft%)=lrWUXQ!B
z*q#4=)+_UKALOrwKK3##?K!qWYv-g>`~UyVw|>25a}D>ax#jm>9-p$x_1lzSzm2Wj
z;<p^xWm8_s$#g|6xq4~MrM=bV_m$Q>@yzPgTb&`ZaoNVeo8|XwPv5fHXqWT4uEaxU
z^-A?uN^hBd&9bVsIX}C8qnW82qCQXveen6beSeJjjT5Eqy)hrecIs`O_?k<4<=29D
zcXsak>a{i^t2cOMr&zeSkE{OPFF{Y3obF4#*tO!<ua$P|s`Hmz3lukWS;xJue(lqR
z8S&TGURz(@7!x5gxA2%`-Arx<;nRnNuV1~szW8z0VWs~sc8UCcs<*n}RMFlYZ#JF&
zV|DeY@9fE&;z|n|x5lrpO3Nw??SA!g`Fy#|+W}XE-Wut+?}{@|4TzXi!J~UnZ-bxC
zWnpta(~G-Se||atb=8~bdH%Lvue_M(F4q}zVfLo}xE*>o>Y}f@uG=|ncK*Jb@1IY~
zQY~A#QtY}5YsDmi1xK&`Weq^IB|b$v=+4Mm8m#?j+wHv9#$UH(Ts&k_>vegVZ|>Ty
z*FIgoEK`1`@M_UQP>r;9_q$!4^-`->zAQAE7hGC;H}7oe+^@-jp^Com7hMZHyLJ`N
z&crooE7m;Iku}SiQNJ=QKvg~{aFe=duQc!JKTO}{#cO^QZsNE9vqAp9<h1GER=Bun
ziN_Q)uJ``5ZB_HM>0whmBfnnRwlJeFq}ROEv20PQ`I^g*8yJ~=g0E(HN%!vNb^Y%5
zxNv^uGs$9mlOJL!z4t>;f7ac8=h5@{t6x{QUS~a(xV@!WC}F9!n%SujDrYihznhU5
zEOxbl;pEILhPlB?@K##Lx`t&_0|S<(xZUg$dUvPp_uHFc;jfBHGky7IiJV!<o%{OQ
z+P`-eo#bq|A{*{{a*^4Mgyx>oi{H3Dh(xUP-Y~EH<)x!jI!<i0`2Din#D2{rqqjSs
z&)c^;w{nvI&S@`QE{N|syDZ#gW=(1AI!T?{sr75u?SFZFtwV6?y*-u7@(#`Hs*AZ$
zy7$MU?y@%<k1xwvv?S!$a--T`CGt<SPh7QGZ?(*bQG4RlU7FgGQzqrDJTueyxc~Ct
z<$kjNcdhx~^8H*`bZ+RiWoy<mGBRD4a(F%k(IlFxz2L!<H=ECYOI9<Mjf~7Tbqms+
zr6pCpQtaj`ty5xiGUcx4JP&@bGAQiAlCNAJw(M=PWX*iP=X2lOvRj$o?i8QDIm0md
zkG-t-<FKoT))=nyon>-yQBZf2lV~KX`hJC%_N&+L+hsqE>6lMyx9&ELjTR|>WwC|c
zYrNwZyg9H`G<N;J%s+4P_y0}PGn_jAn_J|fse%!X`4Z-Pa&8)3wpn}2Zo1H`l|DzN
z{NNPWaqRuP0A)m*pomN3#Vo7RtYdqxFj*uW;qc~Lb?3*qp4->19GcMK9(-y_m{XBb
zX)RysY2EE#J|8?c-~PV+uEH(*Zm(^MHcz{HCnCT;Jo8hDdE)&i$4#%tT;3lddqvgU
zXYu4cy-kj)1*gKU>^0xp@_E<B_1o^2-Cnxhukx+Y?_bwvIk|t{k;QjC=ir{EjMCND
zzG`ipEZzT#Ih^&)r-@UeQm?x1T(d|lrSxi8r}KkV@(NSdXqWKoul{#*!@L7qCEgib
z?|?NHL{>CB`+Y@bj@0*+3$%jG!%9^{#cx?mzu+Yi_1EZX=)shXnP;!eS{)Xe`rxWP
zYtkvNHS3PNYJ0P6qvuS2)5{;t@7EN|ui3>CR#$h^$8p)SrmMelRD-w2^jgj{O6{88
z9hMwgths9QY^CGr7U#rvv_01Ny^-nqlZ`9&DksMl9u+M+YkK|1wTxa(KRvFjsj-og
zGfVH5-z}X!-#YBzhG%VSUoJ8{2x^hN%sTSwk4k#i)wc_b5D8}|$BI%P$C<NlU-AFD
zs5ZtdPX0iPn4RwL*YW>f9dCG5Ij37l^Xl5@>+JroKFwaaqcZ*P6+^FIB28Ysu2*N=
zxDX}rEtp|F1E^tGH}Ui)nXuH_D-w6^mfyd-Uf!;z;@I0MA}jZ}UVgEnN6J*|@w!=j
z?v1<O%|7;Sm4-y<MN{n#?X@l0;g41aoU{ENbAM^%$$96j-|rDhF1nf<xptP<i>I4(
zW^W6>m^`CRU8ei^3=Wk~+@D#H+PpKkcf8p-arWaY{?U*2`TfoeGcoO2wvY4Z)(yYD
z>Inut*>%3{Xz0Hcneid&e~XJ7r~R(Un-{!){p(9IJ6qf|fA9Zrh<l=U!jtQ}-!1Me
zt^NJ&>uHm%z0#j&Myyj`7iw7KI3xbOkhto#ogWv}MgIQw7F44DT=j3=Q<I{`*oZgF
zrxvcAUN?8yl8a{Rs>_o0O1r<BUi;x7duQsylb4oyD_>vr^7`(dF~Y$@nR}P5E{tsb
zYxP~(<%VjJ?&*o#DStmX^I57Cbxsy~eQ5Ii`v0~?jw|mUWBnWWYv<iP+v?`NsybtM
z++`hi$&IV?ucs=1yZkz1@4uZ7EK{ZAb7O)pKfF_X-uB|h<MQ)Y==(2PF-_o3?;@nC
zUBH{MbmG;Bqu%;^ulV;b^4ewTSgW+Gk(qtgGFwl*Q+=!7tvqG3`?8<4>iSieo=c^#
zUUN`OuRu4vNbT+C$Nl!d#FDluTw5Q1Up@ZPk5KUmH$R`Ze}8=LE`@VbIy}~H);iVl
znknG-yWQ_=raf%tvpP}z=fh$CZ&!l-f4<v%O2?-1QwsOvj8dDeA*)x+UNgzCSK9oX
z{dJ?QR;y;O_4@qmZ0+lHyMCS88o$4;?#<FoKVDTiH)+Rik9&RN)T}vipx#IQ@7wo%
z9;aX3B^6b+_0HL?*;4VVt=bIN-HQMI{y{VUx7Y($S#O?Ae!bi>>&AwK`}Nj_&%MGM
zv39xFj;V21Tz?%A_Wz=L)vC?N`1Ktr{x#WNd7WWqX{sMCeRRHP5uBP47U*4Gb?nK8
z*orF_uhY)XYMm}x7t+1`_r^n;w$_CIIPi0i@<nT;W?-R60QaN4-|x-NFfF;iQ~A2C
zSrKE-lVks<Mx}18n-&(+Ahh$r>Mg#f_U45~$CNs4RpOJgu_y|@s}jXsdN=E0$>)7(
zYbHlY_1k>%xbL+p_prVA9rrw$^kZS^=B<8DgfvyZT{N839hDKgKw@WtdC|eBC%e?#
z^L8oT4|>@YS<koiMO#o*clM2Ateq22x4ely=`8zog;<IC_S_pfPXl$=>wW0CvS`+x
z{&~9_Op6W{JZU;TrS?+%j(5i=N<Ws_DR1E=<NRKIdaqSb_WHh;bsswJSUf(WI4L^j
z^7;8Mw{qVT{=M#$a8!)<tBa3b-76G96wN<4G-j{){U|Ryu5#(w8HR_$&#<~Z+co9Z
z{r~^U?@R4mwe{`Y-P=oFTsZhe;`*YMi7^ImqBX8+MTG?(QmoW`{r=bM_3xvdP4h}a
zyP|fRvYDnBUaJVU4X?ejDth9gCw^HIuWg+2(sFus^p=c?+XJ{azpl!eowsY{d9yjE
zP3%vWUYQZTRc!Utu(c<%WW!!>?W;e;ss3YU!u*OyoWZ9{eW$5<Pn+>uQ2C-)+~m^E
z(>sGNXCGY}b_FrWvET)ZNWtBz*K6&Bb2z$0B6y@sPTY}jmCq3o?rQS?dwQ$Jf|#o-
zWAb)9WV<gLeK%Y5Mz+@+fi0`#*0J6xzsq}aVbR*?Pi3z*Mc?~-b!x=*ZL6*?Uw3w4
zb#c+$lA2QUy1!qq3*VhF`Fi;G;!@G;_NU~TSk~1?eBgl>PYc*so}HPQd_BH?@7;>W
zy>&cGRxQxky^eeNPQ4AOecEdpwZz|OnzjWWT<Oi13hIf=n@j73B?rWsr~MC_S;f7v
zW#jhNirk-dzAWp0*0Ha&hb71f%b8xWRe!x2{@c>zs%enx<=q+@MUUk^e_8cu_pMh}
ze?J`NpM6^Ijj(T~mh{$NS^HxC248<@SNrQqMfj~hVavXW3Mv$=?U4G7C@w-G9A>7s
z^T}o@yZ4#&mWOEH7j&0-82#B~z1q@eELT#)l5M7*{kHG-yUpeIYp<J>g+(?`efWLL
zWxvle`?J@z&Dj~j>Txb)P5Hdn@b>kpNQcMlre{wn_uC}trLXYsy1ci#-1`5Y&u7n?
zN3Gpj`DWwsKN0S}{Z5VyjXyvG@Bifjonc8&VLj`Ww<RYgD1w?MKVL^A_nOwQh4&_g
zmPK$eaV+7|2%Pe4f~;9i#H%i)I@j=rO8b7sSiyoPAe2dpd*!rH^XIETBP;XWF3+1&
zbV{=>O4@vRTIk$akCi5TXPTvT;%w-g@7DuoiaR`rnmJ2`8y0UGMT}={Ewip@>;^T{
zW9B}(k<iTh=8W<AE&FPJFY{R&^duz4j)`N6bHjnHG7&jlux5b5gvbZi<LkHXe!uVb
zx;>w~W?L37yYInS%f=^@F-v%grKa)jjUtRJMZyXNXU}%7MKs2ZIR1RO>|gfztoiM&
z*W<E_pP&00y(RPVF*aVQ6x*sV8?J^uex1f<CZ^cnV9EMJMN?g3wlcg$JLBw3<Kyam
zJ6|rF{bqW6-A9$(@AvJVTYS#)+R9*c`=h>d=7NShb)&a!*_M0z*v?s3co|v#sXK%v
z-s3_v0xY?GW}BT|x9?Zh?$_&f=e)eMv~GW&to1L=+;4Zw@6YKEzAXLi-QC+(B`*@H
zmM93AH-fU>v2OFMD;jyBt2h3-@F*(z%Nz+<2%eB{{C>awet-Pl|NnmH{`~YbY<F3%
z^`{fcxgQ=J-1hmL_4D(s0l_Sv92}AlNs7;_TFem>Y+HetB$}Y|;a2wgo1)<{iT!rJ
zR=5VHl)k>Ub)IeYt;*+f)1&kEmR_1><I2FuvdXXFz}8nemPW9spRk?D-~R8G`Inyk
zd_MpC^$QCenXMnT2)}u=`TVwLXJ<cuTN+r%B5=Z=k?H!MJ^5GQ!)Gf>8bJe6hxzSu
zrpHyS-23<2?SDVA*YDj1Y93$PUtgbnYfI+R`IDJJU5T9>0y~~9I${P3KL<u`4bC$s
zCMwr*zfPZD`)qy5VP5ks#^-G=|N8bedIDz>bR1FR!R}K_6$2ueQbhIE{62XVp8YJj
z|NMHrzU=wj@>>@cI=`KrzwhJk+<iZvnH4;6u>N>Ncx~L?DogopUO|TipIBgnyYq`y
zed?Qa-+j?h)BW$|x4OgnwWoAHJnpx@b=LfT&h^;xxo78EUw?mpnXj}x`|FGD^0}q2
zu4sNYyvfMOqU8@806t}%z$nvsU@JqO(sX#jdZJ`d{Vhj+&Ap=2y5COg@Bb0|?M5=c
z{06zY9}mM;hpmm_I}8c|hppTKJHo6j)#1bEtHKj*ZOPnc{lWJ8on-IndSBJ=*Z=?f
zcZym4&(ra%wj0giWn>Xp(ZJA{&3fSmD?H7xgVW6UgH}~vGNSj@?7X@z_V$!186O@T
zytXcOcg+r#SD*%W1!yvk10M2?oEj@nKb;<**Khl6#{NyaN?+gFcwFvvbVT&ltk8t;
z=#8f<pG<ULQ~mwjwN0s~r!cQzje1;v`7~&tZc4D9XM9f1{z)wJr}9nxS~tTmxy>~D
z+L|N3*Uk{15V~W=d%Np>(7es6YLIzJ#eV5oZv8zE)~|MKX1liBUtZcILm<BC^1Cma
zQcu76eBRzaI;-y0d>_Wchg!LFpPiYRbALtPvF}25+V`b;wJt8N`}=F#t*kA^ZT417
z*A)&b!_#a#lXlpe4efGOC)#)<lY*D~eGT7m&g%7z%;j^_(&v^=GtIqa!oR*t3zX?s
zGPQhIDYpkc1pUeB!S?%gn<px}|I#}+zxLbA^`G6ObDuO{4feOax?Sek(bfP@76AtZ
zc1EV_G81mV+s+-`2Nt<@zd2|9e#`20yH4%<`Aj-~?OF5tcgoq{-QB(Y>gsTPz0jp{
z910B%OF0F0gdq=mukw3vT)uvbbpD=;ZM@QHpP!xmtbVKR_uIcRYrKp?mix_JWo_vW
zst2+n8V+o2%V$^)Pn=%DKfc}0f4l4Ty3NsfJC9Cba9>*c`&-$&ozHJAY?sU0nsrqx
zxBMDtbdpuk;X#zZ_KDr#5m5(*MknDPpHA!NzPPZ^tma2S^sbVX`}Z*OSsd`s+<e~d
zx5%xhMYbT<t_0<-sqItYN#rZnp6~an?H*pbu`wA|7QMc+bMxH#e?LJ(p0C#Oq=P08
zl9U`CNKKY@G=&z-3wE%^RX!D!-(dIe$78vquUEsjC-+$%E9cC+x+=8raluy(g@7+i
zC8B!2wlgq5Z3~#p<Zt_RN^IH9)NhZv^?zlp+4*c1D5?BDZvQXw>@3sOCs!5bf#Smq
zG=aTSGz1nQU9Jg7yF|Y|Xy(5)LDBim-12)Lr|&&y^*UmI-CuCsQ+hpidxXXgKagg1
zMyBg?X58R_<(-Jq#`|@@&${(UB!<Tnw$}dp`TSplbncdkU*F%q?`QipB>TpOhpXnd
zD1%BIRt<*-Q4Qu(y`gESv4T@4YRied{eR1L|9Z7L_u87seMQkZ8(Vp$OiomNeU<w4
z)z$9s)|I?W90~%)j7-;O+!a^_8z^s8HmLtsv-{&Q>9@aLuiswz`PonI+llS6HHVh2
zi`^YH*Q%83dD2cH76FF^T&!JM1%H1&pAX6!sut4bd2<YZGTvUl<WTxj=R5cKRqvh9
zIZ@qcS^P|8-;HN~j}|a;gfulAtIXT+ux)C=l2`Uew%@PIz8+KDd$;U%?zV!5PVtSl
z-|t*zU(+sEmGL#a!x&UHSLy|XG-m()_O|xHta%IHFKFib6kC4j{nPCAd()WNcs$@a
z-t=po#>ZnRj&a;NaeHo<oXg$)cH8OKuNQpc2w8T(UA{KuRnqMRj?JfRa;D0??$+P8
zVWD&Ttq%_m`#z2g{qn!_^EvDDRwXY2mOg*>0F>+$xkawptXmts-OTsdT6fS0vVeLc
zE4SE<WwZ0Ls+K4;9Pnz~dOhy;GXME`RXx>}-|v?Hm01ItVt9Ibdi2{{Ti1F|*DL$?
z^Z9K*>$f7`Uj^HPBKjMX>(xh6zjr&bLZ{0V*0X>TrTx;gll|>pzTW%m)#~3V-p}V0
z_vLQA8dh1V8zRQYBG9qf;jKk@-!8?51M*D!|9tAsoKyvJQiH=;Zl4(j2fy8`&cB_#
zey@+?>si_BUM}A<(=2z^-OA^4S=O4?cduY%;t-kP5V&=RmZ#I_XJ@(Jh!t5LRr+w&
z{QeJpS1D~*@G6fLb&REqbq^ZZ-)uUqXI#n~mU(GO=hxTQ&!4k+%oA*+39;`ghe+sy
zst1kiVZBQ3pc-4ifuXTUG+@%w>i2uEuiNp6EBKS@)L!#@H`EJkem<GJHt}#9YxUb0
z2~c7aZ(PI`^SH^+7Mdd!{xQuu_Uzm3{O`v68CB9#b+_NS#KtT2<oL!c8*Ok!vY?8E
zBWCsSnVUfg9TY9|IL^$szrSw(zpC92+oXNYhnC$bbhl@J9q2BbTKekB$;sLaXMxl`
z<Pg{)c5d$zFQ`=sqAY1=XQiHMFT9<*{pZi*(iNbj=AT*o;UN3^LlbX;=R*@hSvg|D
zLnr(dT%p#u^;*>Ff4{Ep54(KR0+dw(BtWJ5hvHS!%1r0i|JxZ``E+WX%<5yCSH1Wg
zR=hzg+W_L?XRKXWR&zl8a-+>b0w>%Xea&tj+0ODL`R+<%CJu!FVWwGbpgA++ROWLb
z_bQ*uzP`72ckbr1W_4V%Q%_He+@5zg=hc;!bzRa;*L<>cKqXn0+kzEL;b$9nCLC;<
zHSyURSmCsmX>ZlnPmC{S7$ygu`+dn<f99@#+j4JT+mg5SYS?DG+Fv)8&#%i`?A{M*
z^=PJ6$ALrf${vS6)^(=meR-i_v%reQr1Y#azwHzM(w|SKM~k?AJ0k4=W8HpPtC9_z
z!fHP<bJ%z!65?yWPQ6=rT-GkRp!7;_G1#mr@ePLSo|-4~L)-Zs8xMdc8JpSp{jPlY
z`~CiQPz|)qfBw7arkR(HfKrn6-!GSa&ufCc@KIc$p!dJ+qBby(Lt(<=17~I$|J`x*
zOW|6ssHxfxx@*+u*KAt5^Vuv*xrt}N&V8id5dP5O4(qE12R<e*qeX?cz}?%%Gfdvo
z^|tE8?z(YjXR&b}Xw8BA4xue+PZAYDNiQ3e^i0j8KR-L0T<g3-hUq5D6v5r~|Nq?#
z+bqM#BA`*lSo*j2^I7xFRxzblLnE(mWC9h&3ip^?MR&+mJZN0D(*WXV4uyaSrt<r>
z+x<6$+zR!bV{!3b-S4-T%o1fm^}mA;XrBMFwDVT5YXuw>${S0s$6f~&<@^7BoBj9S
z@AsX@pFEFRZn)v?t*xj39?0ngwMhiHL2IS%uxT}dcnu6ptCcRS3|=03b8aoTq)5^W
z2#IY?uG3#32eJmL2$a&<7@4l~Xy`a8^f5`z|9gG^KhwU@#eUEb1vUOcR)XT2nVruh
zHEpTFgnp)3^#L<C!aM^~Au=1JVit4p!6w$DW&Jzjps@+5sTJ0<dYlt^e0#Z1$Ems%
zn+~!`M??xQtN;J^JE+W#PM=%)Xa6NV-{ZBQiA+$OFY}!pb$Xg^?)BL6tzWOl+rQ4U
z|Mz3@%lN%jUwzirFZ}cAwEnll{PsVlTlu}cwe-K-r?1!JZ-07vI(Koe*(TF#5y~>l
zjy&!X)qXSC-)<vlZOO9QS*F>~UhljfR~`BH*H`bH{h+z;ce~&J`SkT#^m!@MtdOMH
zPgp?-)HU$Qa*s)jtc^(m7w+F<m#=y7|KI+<-=giee@&a6oAzt>s_5-`y+SXFJ?B^d
zin;LIc}|yI^cTs=e{Krd6-$|9BuMA&NSw3kwLN#JeeE*yoErvVrHi4Xt05i-Y76ye
zZMs`_+w~oH^u3t(%jefg?VSDUzii<V!PINJtG~aiyUne?$Kdrg^E(C3Pxd9K_DT1x
zcNgbz15I;2X*$yLJHF(iYn{FLgJo;>Kkl;@I$j(b8GJ3ZYU9Ua(!bx%ul;t@XZ2!L
z?`c1(b{sG+yz``LmwwVk)#))pI~8nG>%~Ld^>%#yUGn0BVo_uMsb5dTlaKX$ynS_L
zuzFEr;U}$m$^ptu_J6+wKRIR?esgF2zn{-nxcAFV<lbcTFV-~wp3SBE?=LO&UcH8I
zsqBrvAH>$~`}JyH-n--5Gd?~#x->WL?dv|PR~qr#tKaQZFMRjGvgm|jyUMiC=aVZx
zKXZM@zQg1F+%K1wdW*;32Te}CT>a@)>EmO)%C*~qA*o$sZ{`_S?kN=<Hh(@GHp{!S
zgDd<PYxA|$;rgI#pL=eO<+iWaqHlAm&q>gmu(kg0>-e%8iS0iv-{<XqYj*#WQSz}K
zuDP$9xb-$<US1ZO5&w3H;fd<^d$+HYd)K`hG+_zqxq%xecZ$z{U4M1cn$H=pn9rUR
zKXog6eQx=^%H{PxA9d@i&1?VqFmUbRzrVhI)<19gT;~2InQI?A92B`~zTHgUb~|tP
z%@u)*b8c=*y|%Bm+WPmK&42G-UEtW9^ZV`g?|ZF5g`I8nH<PbrE8Yn`yT2xM^|bdl
zKVER=4=oq{^sYuczGmaft$&uy&O5bxS8yUEubk3$2!Hsg>*|AVT-&V5-emaBGSMv8
zjmd7b{rBVXzV5dtCMvHjetu51@8i$s^M5m3+xq1eBfCt(`+dLHy%&o~IvgYh?lE5S
zRKIC_-X{1|*v#;ivp4UHX@A!(tnRlZcl+IKM~+4P+rIzr*_iINfB(L(H^07U!i{GK
znEAgv-~ad9?Z4umo%wCIxJ*BM+0XiHdG5W!<FaSB`l)~G{ViO2vhL~B@HY#Z`MRn@
zSH}0STsazAAHFX1+_sx((wFa_Up6~$R?uPX^?NSGyk00<ey8vs`zA5ns2dj+ItOoC
z`AQr#`C#A5lzG+N-f5@Uqg8fqwPfShaqTeeQOtXK#`wI+_2A>6ah)BZy}!WKf<k~|
z<D#s>P`9w_vg@1zO!r=XxBGowR;JDCHJeYxPMscCb&`Fp)c$4qYiBlv$(F2MyY17#
z1;?B<E9M#`I_*4nbycXge2De}9^Ls*Ee~u+JX~{Ol~~L5xN6<x3#%S$T7;gS*ws|9
zQ)T+<_4{u1w_X)5-D;pNzBS7J!vW@JyHsxN{eJJY{N(G$f9{N0eD#-);{qEd=Qf^?
zj<5Nw-z4bo|5Mbtz*J^+^!7Z^5Y6xD+wWDae*aP6TIkos|L)oUdZB#()9?EK-|Opa
z{&VZ^Nr<oenHoC3YHHtlhIrj8zu#;=uO+)&t1Rri=vCkO%fYn|BMX<~f)!CQq92}Q
z2WGqME_?fD{qL++jkQ<Ler@pIdFEg<`|s;{JZpAtoUi%%QoP2?NlekKrQh$@@Be?)
zu6B0L`l(x7o?HF<@%XL${~ztLH6IQ>JGMFP_8oOME^X12xYDbk|DOJQK7anCKbkp{
z|E!o6QmYu;q{_Ou_V+j6HDM3l9$R>G-|u(X{B}PU*nT>pyf1p=E{^uMS1zs6|0Ke~
z73pxY@5<Y_r}zK=+YXxhT^hHJNp@?67U%4$j1|k>sz6!BC-&q0y5G6-cR=lj?JrhE
z*SmWESor!za{pJy)lpnu7f-SKE>f|4`p?hLZ{OIMe73iK%i?~!TXugwI9I>h`5e?@
zvAa1-=<Lh)_Q8jifJV&t4KF;OVpl#T*Dj{}+vW5nQOk-oxz^0D`;{5YFgvp^b?tnc
z%1xl*ygL%f|C?voiGRP5+~3n4Zl1@>9jIWReNCr0`NQAzg?8^J+3!~Oo%N(WMPui@
zE}^$CkF))?sC?9^{wp<6+VX|_(J!B#&Cb8|dj0-)XQ%w|{~q}KM$u{A%jRF*E-&~0
z{@?yWwa4`(@-AQFF7VHLwQ%vf=g=ry71EHn@1v-P-?=A7jc%Y(BL8g<cl~tr+A=B5
zsYva5(!_|bACJrbuDvr`qbUBB&}r}LNBhpWuDf0EWZ#M<IbmT%YS&fI=D%;ss`oQz
zGfn;fK}jXO=x*oXMJH-^e*3NQF=(A<WZL<8Z(qOM<)qd(`OlLc<8vR5mmI8kvdpn7
z=6llrTcz*2?}#6H;`{m0&g_X@cf?=qS)n~uXMe-LcUsn#lexqGR^MY4pJ?Y?q`5Bj
z{{PssbFIx&i&d?QV=I)!Wqu~VGFJT=Ki{raY5GyK)cG-SFE*d~dqZSr&XbAU*Z%0O
z+um-!?X=FEkNH=5lRvzUoglhXewotrmo`iFR!tYO*(s-{x=LWuzMW!sU5vIrc^z=b
z?7MPQ=igJa=bY?4?XNQ1%WmJi-49HQ4r>LSd)RbfMe6Bks_T^Byl%5l5jxj;#5*yz
zVoI_`;_NR^e0I6(?KoQ@cQ^XFt4-m&0-f4vuVsvi?Q^ExxZdmC_a$z1ms8QQRRK?D
zfEp}yTq2?2iQnz-?a}jEw&}8;^-Ll4x#jmNEn~ZP{aKY^CHr=^cc6A#U1_+slWSL0
z#g$hpr}=H|dJ^Ph3#xU}=e$z8Y<OkXqN=pnhn{~rt^Zw@H*4pG8wsU?*G#0PgjY}F
z;bLml6Zp68ic;7$lhA`sd-cAQPrYZgdRjy+n`YtUNwYHdY>l#5zxP|z{ZlK$g17Qa
z+n$lL_Sp8-sRmyz+{oYm_s{*UzY9;zt9aD8rak0)rTBuM*AD%DxBGm#d06+-sGO@=
zYp(h7#-0e7GQscqqIVZTv+no(POjYIW9xQ@zjbEW>CBnOUTCQ|Mg^oUHT<9TFvL6~
z_A#h`H~DdEb7q&)*F}M=mqq1WO?HW0e!u#??f!nDu-2-q`Jf@57_;)plTS@_mwOqn
z-5DF{dOX~Fo85C$8|Uu<u_q4iy;>Wlw8zKQS^r9F^z%UNO;M|_9=%ih_oL^(D@@+t
zew@RCQ!Jm1@9FhLE#JQ5)vDO(+cLIZ4eS2Gz5Vs7sZ0}B9u3_;Z@0PslCWbwu4@fu
z{ZqQV|4D68ZsAqCtlSHgSDR+tE1JCW=+)ZJFSmE=`<`6xV^dyiowj!IX`MMY^!}b)
zy?)=T=%Ntuzs2#JE}Ng6eSOQ0XJ^;03UFP$=xAvD_p1A^ixq-3-@f;H?G(u0bK%k}
zro$U7KCU>w%HV9@X|_2L^G;6=IR0hY!3)Vw^LbyYZrSnb)}4rRLTjgI$(D8A{<C$t
z|9#P@n7jRzs#Q~8*c@)>|Nc93_mlJMVxnVAOS?}Oyz7717QH0gwhA=eU{%|;o9BJq
z-{}0kPp9w9c`q3~<1Rl_-QLr3bBb)HH=NWD&!6*U(#oS(|4w+Zy*#$Lc6HS+yS$9n
z`1P5cG3L*Yyt?pc)wJB{3#~TV*xXF&*8NkbC&1UO^>(7zb+5%w96+h{9`}VuulD_X
z5`57@<*(AadzH_2J)5~~r{>z0Cu&))Cqt%eI8`fo@|XYPO<F-yc7~sHEb`R|4YM_U
zXBKViEgijl&5@J3?$vL%hP&#ii~Zh_w?y*z#iNUgLX@U4rT&e5`Cjq%{i#vf&Vk&s
zxl{iB_P-pkRJ?Z~Pv_w;Gbd#ie$JXb+x=#Lwy(cb`5D9GKMt=b4Vrmuv#9y<&F?)Y
z?upZ#l4V$WaEtu^l^f^0Jj!}ZvU+O9o7HydQ;$aL&VQ<__u*@D`qZs4m8_S#qn4Vo
z&OCNIJIhG)E^}((HH-f~dmX3v_#Ne~{LnA@w?FE5=#@ol!oGf4RK4N<zu&(N56oP4
z<Dx`LZ>Fz)?C!F!-B+0Wpy_KBOP5xGtVO|s`RZF%8LWQ2!%Jt$6UA3-FQOd1ZF4U#
z^Zi@p+c|ON3h(v1)-C;idP{EQw3pqBckx|YAAkQ!>-sf3M^mo`2Qw_aZullRYVVZR
zNY9y07pDhZ-z5|G?CRpW8V&z|fLljbaxdODMf)V*(nn0M%Hk%joUc`P?9*Gxe{P%p
z{?%R>_3M7<vX|Sg<c2QYvZO%KGVq4k^jU411y`m<+8^2}cJ9c2P|uTn+AFu!2?oJ|
z<=3AqaXoqa#jPp5v8usyuY_7ebG|luJ3V*)hC5G1KlppUHd}kX;OxS+55kuE&Nj1~
z!Sj1Z;fj6Q>+Z#S9b5kH{M5ihUqimwwf$Ol{b;ZHw{8<zDR6I}p>dUv#;OCMj|;=T
zioag9OYo`Xy1KdH0V@o%f3?OXPuVo}+S=&fq3f!{kNNspJ{6h2H|Vj$;r$a<8a?KF
z8nGfwVyn)IIW?b7?qfZ?|HOy+n_jKdU$?OCp<#;B*#e9GFD|;ve|;SJ)THiDg?(uM
zz8$SPr*D4Ke)3c?;VQqp`kaEMOdiFhkC=Yl4(6U3rT19kz_hRBPj{`I_G9;@8y~(b
zvYZ!cv~^o+?qRFcKUeo}>U#a?{pKav)_-fYF8KWa{`GqN@536x8>(h5nZ9Y6Irrl)
z#=U!e=ASnEd1L9@>3d?AJzqF=_nzY2tG<Tr<lc6_uDbZ{l(+u%zb1cub@g<A``RAO
z+%L>=KmNz>2%q^%{#tAGygj}}@25U_YU2)`x>#TZN+)aiF1)g8SDP9hZp^AQ>z_ma
z%&xkV;TNZim7YGmH09T%>8I;vZVQ~gWp4Ssn<l#M+gjvr>0i0r>#4i>cd>>4GX1c`
zyL&1>*KAmGJu5SO)3gh|e*LpfEu7(1bwFxgjQC{7(74q?qDKuIc<aNxRxDoPymN|A
zeK^;WkSn!j(VU05zBo@@7OuH^g=k>?@>l0p%Li@x8~mPkZ~XlFe?NuVLxPrH@>;R}
z+{8Gq+uOJNz0^PX->s(#AG)t>wYt9O_2n-yzb-obUaj8SRO$P9@%eWbgl50~Xq3DB
zp6R9#&g;`NcNfT;nlv_nJL3*>SU6%HmzbZ56hE7PV^ga4{YR@l2F~n?iurPSZ<kTj
zvmg`wtW?q7>p|rXXZ0&i>uyisl`!4r72kK2X~j>D(^^@z7iHGo>@uoa#p;|KV_LuT
zRN-;i=ew<5aqo#T^7{Q~*4rIFx6NtTTJ=8S4pT&_@zwkDcCGJ|v)$#xv$bi}a;K_7
z&*ndi{Ox|K)P_DPjaYuo>noS$>J~ZSSLfFMO8ve4yxs2~&aH1J_pdgby7aGX`#iOo
z$BNs2smbfx=;!X=;JfYkg`~(^{0+OrQl+o`h!ZW94QqI{?2Xa%6(|4wJYWAy{`R)p
zdDiv+uf$e`b{nl~7khPSo$Z>_Cf{GLy0&oHx9c@~PszmIig-C|mGpD)z~G74h6ASM
zt8e74jK5&|wWq6YA%AeZN_fcr4e|AVzy6zE_P6Q1QJva)y^k^bKV)~coYIjJU#g#}
zxG-dy;j&q`o;7jneOMmqAa|@Yb#;5wLm$rYEqj;ky*Ryu_3W#pIe%2Ge6AYj-ZHr_
zH2dw3pZjdCH-w%{{v!7<{wU9;ziW@EHiUjysN$ma>-VLQsHLL3wkN(=E^^7%;@WY?
z=CmaLLc`fwiMM;C|K>j|F@NhlW0~9IbKcrs97`6RU-w1tMAiKE!c8xa2bkyisxLmz
zI6cy$w)C3(36pDPEI+H?Y;^DZdn)R}x>)P|oqZEuZuZ;jKV^?!@Uxa_39PHNel1iC
zE?Sl|zqD?7(I53Y(tqt0gD>8=^+0ml*)6emrfG66SSEd`e_a)S_AR;I;4tlN#~ibH
z)(PcJ{if`GXI&?x2Q@`Rp+GltQn>e&D@)4X-}}cMv~A<MU!RudhJ5MX$8^|d|AT%R
z%S-hyuk5<8bj>D%FH0lWvS*zP_<q30RagI(n=ZfCs!u;2_fNm!qw6HKc-6+8Gxt4s
z$=&nJBIM$pmY4Anrt5Tj9`648?e=LOsnA7CraK(&{x<QO-Q-Zoa^<qqW8M9~UTFuj
zz4PJRIVHq>ugI73SufvvC0{W;7vwnon49(iPFGtAy?sBDW}9SA`af~SnwG*_{+$Q6
z%>Q@pbk@zwHfytVLj+d1<iB*i{{72k|K&Pi`P^SO1iZYtdAa7r;HtoWURKMKu6L`q
z&Sy%wsvR8m;K^HK+v`8C99n%|iTAO`JEJxG6R(D!zS0~0I5O19NryH5r0ea>4p)wx
z%bQPV|D5Z!?fjJ|$uD=ln`|Va9XW54o_fD@SitiC{wqQ+`Q|6*SuOl>H~DAOfByh}
zsoHDWyEkrnr_H_X-~WX*ybE7%zV|zI@Aah0#t<&h7~cba#_#s)7HPiou75Hq_{rI?
zS$Qty%m3Jm`=qVi{(F+>PO;NRw!P~P?9AP|-+RiG8JDkYz2^4&-R}G)l?<lt^IsRe
z`CcCBq5PfIq-ek2@9QVy-f^#tpJu23NVfdW!|A&Vx2v9;z30K!>v7(5;;%oQbW>&h
zxAUg#Ni*sLZfC4>HMcXpG^g+P+wJjBCN=*k-WhhsqgZ~I{>_Q=+KZk{bpQ2rUH6vx
z-%WM=>q_Eh{Jqm}weR!_sgwHhUEVsPI}010u3Gi`k@U_ZW`Q%(4fo7Hv^ZN->-xtV
z7NH7f7E9V3Ui?oi#$f8MLdo^3lH{%zc!{6*xqp6uz4!^YS<|nuuAcb1Yxa!tE2=X;
zeRj^aHcvBu^G-gNJM&4@x<B`)pDvKy$)IcXa>-<+>$3OtFWaoovv4?NH#6?V<`bon
zUw=Q@w72i#+Gz9rd$S!sxAT17ku@)4@Aj{j59$_tzP`9J{;<s|y@1Xb?P4!e6Z_Tc
z{BOU$_%}jq=gOl>=70Sb#m%z*vh(>o@0<G9D`U1^KGG?ye0J)p$FDbEWexjRe1>&a
z-AuVs-i0xRM@8#){yu0>baSTibZG^vUoRH_-FNF+Z=tWu>8&~Kca^R)y_>$f@aROl
z&oSDWNwGg<eCNxD7w2T_eJFVQ&YiPf|7+xmRK1SAJ2PG!Dg2^x=CM`Ql@(K-K5Wgl
z{q}p;9`3}zrMAzE`d7bZ75Mv9zy4$C1=EyY<#$W3hepk{5C9FfI-KQrAs+7K!&<}}
z6Iy${SMQ_!YoEsK9WK)!9I4;Q8Nce#{|BZI_b?s)pn5)a`<LUZ&m0IXEm*s%vnq`%
z#@RN1-_K_m%jcGP)g0vdTEgk9bX`bbr<l_Il}s%HJ9b@@sL!d@3=W8nnwa}TXr+F~
z&j2l<9c`~qi5(Ey!M3o=b{YFRQO=0NGgliGT(uN2*maN1?m*xI;eX4%tVlSjYS{h7
zF0k;ii8sr-sCDPrSp$DP)PA%6Jm23LPmg71O*ZPze*5|NF1<e!>sFjvy5rjBBR@;#
z3GCQ4?d*wC>pnjFKLzr8+N?Bh6vp-#{|k_03ZE`;^1s5fsAA#cVRJ=J?4GBnx+-+u
zfl%w$62A%qj`MuIw0N2-``TM!_RDroJLIxq^;?mi-G5jnO3#*j+1?(I|5m;$yYVaI
zx_9%N;_gll*u=Un>isUc-_^^i#a}I}EzOTzU1j0&$nag`YOPmMJ&V7+y{*1ZJtn;3
z3cv7Vb^mYII=LTnf`dGc^GZ<eU3TlGCs^)Gzu{seQkosS-Bh)(Gx}o1t_dN|kEe!Q
zKlSdI%=YYaVe-AdLxomvI`%*9cKm5mwSprZg8ODKFq)YqGcWtBR<8K9sY(mpy_I_Y
ziYctvR_e^(AHk=tEnR;pMD^9Fb;nofy?XWg+wJ_{dduFiD;2M8dTO<F*H5jV6aLvb
zGc7EVO%OG|b|bWR?)B%6Cz{?gB?Koao{f#Z^}J=%(^aR}?GoNCCu`Te^Vql5-CHKz
z4E^?e!M|rFc@eQuQ+J$X?TB0-_uaLA`YR=!@Y0EVuGe<i>H5oUm%kSNB(U_7NTO7>
zwsC4pUv%Nx=gSN)R_UyMk-t3ocwZggot)cRj#G~b?RGG`7;1fcn+~`|)iIr+F?-KD
z_N|Tzs~u8V);)Zn*l;ys8=tII%Tb$Y!3RnYn_SN=o62;p;M6Ogn8TKzzZwQVnDu(=
z683dF-yJVARSuYUAk_5AkCf|K?~ZS8lhR(_T(@S&|9`)01!ShZW{+0=e<|YGrDtDx
zZ+`}@%uoo}%*3+J^!53hf+r#u7%^X;<A18{s+z-tS=OeF+3&)B?n|v?4v$?gl>Cz2
za%;)ztG{-?-}m|Q+Lg^Sjq0=o7a9q)F9~~fbn)A(T&r2yPC5C2yAK`n9sc}cJ$k-F
zN>PBDajVGABf1+`a8CtIH9XRKFsbb4%V|@5Z}rxHb6ovu6~k3kh0n!Z+2;z*My^>X
z#FcmVM|kncV?M!~cdFFaMQ#0}bFOf2+$+#RBav><1m~_N%Ag@)dsCN<cM{eKGqQYg
zZV<bE=l$em-!6*S>Itu#zuNM<?b(=VMVG(WCm-usn7Y=cz;sKlYgCMLsHs`mwKb7-
zJXI0XUIqp;X3k64dL*kZ@o7WA#s1b=eV)1-^|A|fjx(h1lA8uv(a@?D5Yo6>D8EP6
z`kML!jVscpN);O%>bL}UJbPZd_*$s;2Cc?y*Q{lEN4=t!E0|Tr-R(8Ibs~nXO8&^U
z?Ca~4+SBAggU5}bA`4c3&|=yITc0Y@)?nnjJ9FKeUh{hf=1V8;eEGD-ETdF+-?LfS
zInU>oo0*qyJb&iA$qFt81}PQLSpasqx3(PGk+BXmXLUlDk?Fe4&cG01P~`?%Q|0e)
zSv<DnqN`m)Y4QDAFPG1Mw>;p|78lTt4NdLc%MKNN?z_!z|0keU^sx`9%R7-vV29Yt
z-shVHL9rs>pkUs3x9s*=(4?z<TG^o%&TE^~{q5D?gSIb%mRLVt%WwN7!2W69u>i<C
zfL46Nfvul>EtQx;l@?TT%&&U2Qp?he9o#C^h+g0~*Q)G-Bm2z`LFGRt){EVGH#zfJ
z9!b}!d(^4E#=T!|*_vas<iqA)pJhB7+_ny|WOAK4C-c#f&TYr#s(<)2PCa})P+)}}
z<FmrGcCTky2%nsp<uteWSnPsblZ`{KB)_|})9&ZuNmeUG%|uu?&MI=B*?Bb!GB~ng
z2WX~CG(E|mB`dDsz}9E)9Ye1*9N4N=YFW0A>xuV+S#MUqoOMNLwL;kZ+Y2*%)-Xl<
z&Az%SG~x_+b&o?IQ;Fy~!LGBA=?({m#!W0{w{wi8Z7Mc^H-@I35|K7YXpm?A{d9W#
zt)t@cInnuhw}O_(nC09sm~EWy7ulX{3o79b{Ab~asnmuHmxDIuDlD*!2krKoZCSj`
z_VXFzYrD(yv+wNKIA8hOn$71nrJbF1vyojc<NLkp^_u;R;NGXgZid*_&9^tOHAZk=
z2(<{?zW9>1bNE9q^`{N23KRNcTTds&Z%XL|PeEvZoa}Fx37UeupW17BZNp)H`#a^T
zVN5G_mA;-<s&Q?7Q^PUU`tNtkR~N99xh|+;G1*^od71C(=P8Ev+>P01@&&FsD{!2d
zWqSI5QT<ud>n*M}ViOn|vl;LD=q<g(!ev<Cd+aA@U)Y@;g?1gaACHRbb}8-O<vCgH
z+ScrF`6F5DZbWU(Qhk5yvzNexmAi7agH2c)cW~*%@4I97_siuY>CQ2)BV)g6tvXQp
z;6NiN6W=#ozN^8KpNT_ZLN`NWww_l`a1K+e+zz$-=kxddRGWC^<=*f2yw_x1T+}*0
z&E0cu)b_l&5$7g{3P;p_y_);*P%C(^x9E?*-|w$=Y-U^L-W3_hy6)EjdFwJA`9FI;
z3pyy2ffnuTRt?c$V>&9bL#?>}!$J0aqG2~X)6dM97_s$npY^Y>8;kqxX30Mk))K9D
zdJtu3{%utpBh&Se{7J@3t3H4mkf7e~ioiy*+*>zNr^lvUUhcpB<Ye{Rp6YW`UfKP5
zxBLCAo9Xj&K?|YZ?tZ_o?0RhZ%w5u;oYI&ipirROw)>1JXr&7%>)qqbkV$LjlYO)8
zcHZWjo6~QD7BITYmQK04KK}l^`hS(LFE8)U-SM#P+EQ=v>K6;!b6#FrT3Oy30$Qqh
zBDCRvX}IP#(2@ag0?qPph>f-`ef6Z>MpOEo?e{y$zu#`3uN%GX4EtKHxT&=v2iG*+
z64eg765wm83tF3C%EYoR^zo@c!4)NpXFq<w66_!PtI$#blwKX`I8CyyfY%TC+yC7%
zUpegNv+{eD>6araOXb7NlS<X)Ofn|y{d~^)XKCRT(4v(SN&z7!XR7(l$*6v_v3>2<
zYf+IF5j_qytTT?A?)$#XD9f#A*{Ogh60K?hYfjG8s**R&JqB8HS@uYO{~x2m8E?1U
zKBr##>f++|tvNT1Htv}*f5M!VGv3$zi?KdAGw6M2AnUr7)AxP4+Q7)1bEt(=H7vIJ
z?bc<S2QG8pUN3SmeW`QlK6#Te&&RXue!W=yWxMKnZU@l%NV}(h&2HxeGlU;jRS2+T
znqTv&Q#WeMiT}AF=LEZ-Ypmb@Z`a-O`?dSBKl0oEd7vMYoOXMAe!gw>w=c=5*JI1?
zK4SFT9mI6qL?G^1P{RS!uiHdwA6R8y)A{}L`TXF}JFC;q&YHRF(Gu}(@tRHNz1m;Z
z*{2ly*U$fCWzV|r|G(<l=J|1TVe_Jt16Y~3)?ACP|EpzD^id`#IRP}s5uGGo`9$!)
zbHloQd3SgHW3M{PU;X1@`)#T0HGwu7@4Pr;x?hz&e|uDD$Fh677V*afTOwB3iY#l0
zT0eDW#NAF)yD-PKUWeOwK~s+VtP79#$*%RAYt_m*p(K=Lou`CN?^=e&>{n|Q3w*ym
z5Cz39Xb2<V1Jf%zo3t|$@<&!h7iygHxwE&rT>i+rO{et|3lG`~?GU@8t9yc5sla#d
zT9$RlYZkk_96IN?^-4W$j!>=ON(D{lF|OGqoWJwww8TP38=)OyM{;$3bSo72?mdd8
zGc4iM6ivGZS=*{DXXn{kKiu$o-R@rs+oHGU)$O}+q|2t(>A|e!=Ic(Z@_jI?>M&;v
z^0H!)y$3+61a79!|LXYW$H&LQojRufO8@`;{@w8nXtn$C<Ij}E8nf;0ZGE)bxH0>c
ztvZT-8yqGbn563c1~ka#_$JujHWgGl#@}Ax$o%@s%E|mm{1y)w=C8EK+#X@C3OO6*
zzpz4qZ>_e#j%7$$-$9}Kz@ML=b0G!a&!^Kt1z+mrWxi{(udlP~xEiyuP@iR8;eO{U
z{!A?ER=#Iux*ozG2Wmh-7HK?DFi1Yu;}W!--|mOP#^a!63bs{WJ~)EPfY}jp%hg%d
z74DM0qB@(QF?$tHWA-Zc_2AqMCQfO7xL5uDXV{J3@AuzNJ2z+MjorDox7jt={(7-E
z_i?YepU(Q1>MZL_YuPR8^+48pp+<nfiUke3`1b#J)NR*M`=F8i&2jnqFYc>icW-;U
z`MjN7$J<LwyG`@%>}X0~G3PEvjP~(~i$g$(XO%vhL$n+nJm<`-c*H4x<W->OypUJd
z*XOs(RjuGp;<x*e5G)XRxAnl*T}LhBU0FC{g0G@25Dz%X#4V<?fnC1l0{ce&Js+Af
zcgao#Ew2NuN02{K_Ts|9tgEX+Po|%%v0%D>Mo*^~)E0jAR{<?XMY(EzzumrU;|68-
zzAY<*m#dw-vZu26a>NbLN>9*QgCn1O{6+rg#qYagRrY2^X6ek+95JU=lA0wr1a>UD
z$AT6$A(Iarm#=@rd?RqN+s*L!+Nl=Vv(0jA7*@YIGCOZqW>RHE(VvgUe~ZPO)!uzQ
zuDbQ8rM=LOXFf;UOf?)H%<A%gFzeMpZBQEz+!Sk+5~%okHM~~9y6jEFZ0quM>l=6R
zX&Z!Uuh}JHo_Xnrn0{Q2bk2sxzn@O)Z@U(i4O$71y!*{2@10pO8jY)W#bn#v^|$|f
zCB67s%`V;OZC}zho!VOS{cicUW77FIcE8{Ex?W?#^J~%hxn8TLuGNX!a$?K;Z5J(z
zH9;$*A~&b~EIfO5mg(u#>5J~Q9Wed+O&B#9FJNQ+l3IIdiKksh?URY_Z?4DJf883m
zp%T<odp0{i?|N)`?4q{UYc}`U{{QoN+v7fKwP{noE)ih5E~xBwLv?yg()`+Qk)5Y=
zudJ8|S~sY-;{j9lg$0hCUlR|`Fig(5u)t9>SfaJm>e$BPa^Q8Jphd|#em1Yz+w$)2
z`pI(<v~ne>GSgo~=KZ$YdDnK8W_!>39p1U;O6#7yySuiXRGU4etYcA>`-53kyHSe*
z1p(nk&~EY{A0O8WtezIyn|(IqT6DhcY@5nWpoO3_!=^_}d*Apvcl+J6<#UR<_OILf
z{oZXpn-31b*{|nV7S{;qb5DJDclYm)NB+59suvN^OaN_tj^A}NZ8m71Ab8x{cfQ?S
z&|=N%=X1+Ji%05aE;GxzxXAUA;2ACBg0o^5md)9~5f4g7C1~mBNPxrLp!fTJ=YblE
znfq>h*#uhdW0|u3MpE~eP}R8S#Sg5CpZNqYSgG)DT6CT#%Z8KUD;ETHuDdcdLU*%m
z^*5imTq)(6_j|vCR^YxlCY^t#f@f<-)-I*F{;`{{Zd$$W=E4w_g1P4T^L%F*988~l
zZHmW2fgNm}SKOJdhxEUZy&k;%F}$E}U|=#;Tkyd1Zj&+V+Er6_&C)vkp-0j<YfazP
z!bjrqH5b{}dPRvw#a=#tduw+1>$|(R$J-P>Ix^*ImS?EJ>P4Den`E6iH^o)IHN9^d
zZ7&s5`E;u0@s%gKLF?SuFP?PFcI`WCcU05iLDZb@b611bjf0D-Pks);FQ$a;`}Zpw
zRKEJ(3At7FbI-fO{Pth2f<}bB_x33F+gwtQ3Nl*qr0AUG^B)i5AGfB4MqR83?wuUE
z^V_ZL+;4AgF3pX5w(I@=|M&9tehs^SHbPo^@|HOJFBhEa?*IJ!{P*>!Wz{p|?p3|k
zwSV?)$K$@upjAf8GAB;ciJY`gay@rQ!@5JPRmnSbVA*oP1QwAKE4ts@%3lBWcy!j8
zrT;V+=YA^Q`f6(Er=6<{UMyOjUGsA3^i!s?6QcY;%eu}lZVCJSW^;di+^za47M}02
zF7EsH>-F0&m;JxbZm%-QyK_Tp)*Mg9?CE;3M)Uq%beG?Hn9usm`rv|9hC5$fn-e!>
zjra9QnYWgF$^HD+G`2PP{f(@Z`jwzQEVMJ=@P}nejR#}UCyUcRu5Nmjz2*JB-?!YP
zbDu=pi&lJlb@jAW`MWpG7cLobtWKL{=I(m4dg>L;>5CNNZ)-6Z-mstkx9H}w*xhAi
z$7RcZOuMe=+&1HwCV1J|^(Q(PrPlxcaG3u#XeEqzT*bokUTai>y!4hDZY~ON(%c!q
z72dG!P-}JmP9u2uB(PkIDL%W1KdRJN^nm^MJH^*lg=*Vh`?_xTJ8;L%-+S?z1I%nZ
zA1-rdp1bnp(@FLDKU}lsh9oVE>5hsC)v_)K&90npS1S}d&9p6Y{a5`h3+%pL3AW3)
zTlf3z-<Zu@mrReZG19dE`D8Na015dY_X-a4?u_HR{d6TmWA?mz7OQ$e%@fc<MTLMl
zOt*73_tyUTc)V_v!dADeJ*$_kn`xBVCEvYjfnRLK)ve((Tb%>T<3&|>Y58+L&OH3@
z>CN)c?N@C!X^F?z6dwDT(#|LQ>iYfS^S1X6?0;a-s_78^uxZcQ7!g=AsKG&z`^vi5
z+kF;~IR5+3oMsx^yNN-&`-8B*&BNnM=2bqMxo_&1WwY}>iDW$t`T1;i{-5M^|7V)z
z&bnW+dhNDTrPIA`zx(_B{`cdTzJgX@OZKlWJU{DjnC_vq(c91M;N|`t-*CY6|9i!7
zu!q1zz!9dcSyw;ZO~2Y2mK-Op7n1?%Ru^x*SM&MoH_(!=f1jrB|B-uS$$`+$dXsCW
z(}i|PWOvPZrNb?z^MP^Yxs^F5QbkjB)e3aIHS4bn?|Alp@8V~W#sw%zxvDHETrKr~
zWzpTz>yg`dPVq{cZFzXO{r2YbcG<J|+&jCS9;{LbzuSIQYqi+zO{X3m?e;C+zbd5s
z!K%WuT<b(rvgK~N^-4{Rx_e<!%qzDwXQCOIuJ74f8Uk833mG9;FoWgQ)z#_x`~Pgx
zT>LK3T{g8{zOLfh>F|bCDZX4Whi`z6yNUSz?(W-vzu#}yUbjOj`N67Oc0QRG#^17X
zUW0l~#m~=~s`|aUu`&7D=g^~FSHq&uUa|eTxZiFQXivx_W8UziKP}SsfR>`Z|Ly!1
zT%te-4-U|Z^?yItZofBcQibNmga7Ac+<84af8Wb^RsY)Jld98aEZb4}_v`iAPs_gi
z-BS1E#YMXpR~JWFg-&6~-23&K_x(Mm;@@w*9`{d%Yn!oXX>!=I)KtZDQ#>s%+v%Lf
z*jeVVfP?jl)T(LWXX96WT;t_6C2pEdWRm*4ibeUEq1zumnHH2PeQk=Rme)O#j0+2<
zH24=U{`UI%`LuI$GEYUUN%(NS{@>=g1&26aE?>Fj`q$UjzaPJ3v-f1=gsmT%xb+Oy
zhVMPrD?Po)FEt3%EzSiUGx0O`>7q}M`|YEyuZ#V=AG8KW^Y;g(de#?ObM}Aln+4iM
z1c_{snFsQAzfIeIziu~wlzWdvV)F66ua2{sg0?QvdN9W%bJE{GpU*EdTr}&oiBG!l
ziYtH1ANQJni)~uJ>y_61Pq)^^S_fyZ6Ee??n)~F^p2}kTt3Jz8{H*--bT`gqdQ;FR
zrW^HR<C<63);wRe{@90AOCz3#t<L}d?{BTbDyw&UKA&6W;&a~SbI*Riv&O5}onM#{
zlgCkHeltbb`rnVohqdHBM>HHT?a!AB1rKI|6OM*m<KsT-bN%0Cj8ZymKOA7*_tiAg
zQFjX0wJTPj$tm^qUN+(0OPdbV|NA`u+qLNYpX(04vXkjzIsw`{2s)|ef2NlVYcp5H
z<nCQ6**tGnO*z&peY@BEUdArD-i@Ij)?B+D5ORHP*{zeHwdb>~O0yPmm&~;)eRCtZ
z-?TJe@BN)E4{z8!>vz!op4R<o`K~J>;FcPgXbcq&IK5<9&&A|@;#(`UR`3+B&03Sb
zI&5vu+O5}4{k$Z?SM%|xxLx&zsLawHP-oR7d`;6OP)o)#Y3ke^xwp4j%5T>)3o*}7
z&AzlZSi88Hjd#@}lZ_V3Hfg^8^~J+bx!`FmIRAr*fDoouksV>jdqI2U@?VBbOY-{4
zDX?Q%6nZo504qlf_a8R#6Hf(qEW78iiEBA>XM_Rdc7-%1mUV`^6+_rTJg^X$Pyme(
zTx|}ABo|QG0A?8qD-`tJ<Xvb5<{^lcpbi7l-ZV&l>zK*Vn0+RX<0^PO7aWgZ!b23T
zH4ZMd9nP?D#3YwFui%3hun_T8pzaKER|af)lA6N<sm;<(rC=U{2x3L+F@VENz!+`&
z64dPzv>Z^I-r!(poB=wk<V{<EEUaz=2MR-D2xveDxl0BPnIk?82Taq<TV8>A2x18r
zTK^Ah3e|#q_0oM$keh0)x*vYO-yc2OEO!m44_~`5CN_@SB{1dmG~Ls$vsausCA=eS
znc8va<}XGTfsVZg?(8gn`}_U={#x6W3QVup@3-UlFTCQZ(oYUvRG%}lJkmNKaec=<
zN$?mt!jB3MSUF-Um5~HM;XQhq>F6=B4WsApDhLd%gN=XGpNXFk+-<(E4s>w1r>mdK
II;Vst0H?(_)Bpeg

literal 0
HcmV?d00001

diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..40a47a2
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,27 @@
+user nginx;
+
+error_log  /var/log/nginx/error.log warn;
+pid        /var/run/nginx.pid;
+
+events{}
+
+http {
+    include       /etc/nginx/mime.types;
+    default_type  application/octet-stream;
+    keepalive_timeout  65;
+
+    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
+                      '$status $body_bytes_sent "$http_referer" '
+                      '"$http_user_agent" "$http_x_forwarded_for"';
+    access_log  /var/log/nginx/access.log  main;
+
+    server {
+        listen 80;
+        proxy_pass_header Server;
+
+        location / {
+            # TODO: Update the url
+            proxy_pass http://app:8080;
+        }
+    }
+}
diff --git a/schema.sql b/schema.sql
new file mode 100644
index 0000000..aaab4e1
--- /dev/null
+++ b/schema.sql
@@ -0,0 +1,15 @@
+-- A table that stores all the lists in the system.
+drop table if exists list;
+create table list(
+    id  integer primary key autoincrement,
+    name text not null
+);
+
+-- A table that stores all the tasks in the system.
+drop table if exists task;
+create table task(
+    id integer primary key autoincrement,
+    name text not null,
+    done boolean default false,
+    list int references list(id)
+);
diff --git a/todo.go b/todo.go
new file mode 100644
index 0000000..501f3ff
--- /dev/null
+++ b/todo.go
@@ -0,0 +1,214 @@
+package main
+
+import (
+	"database/sql"
+	"encoding/json"
+	"fmt"
+	_ "github.com/lib/pq"
+	_ "github.com/mattn/go-sqlite3"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+const (
+	databaseUser = "postgres"
+	databaseHost = "db"
+	databaseName = "postgres"
+)
+
+type Task struct {
+	Id     int
+	Name   string
+	Done   bool
+	ListId int
+}
+
+type CreateTaskRequest struct {
+	Name   string `json:"name"`
+	ListId int    `json:"list_id"`
+}
+
+type List struct {
+	Id   int
+	Name string
+}
+
+type ListCreateRequest struct {
+	Name string
+}
+
+type ListCreateResponse struct {
+	Id int
+}
+
+func CheckFatal(err error, w http.ResponseWriter) {
+	if err != nil {
+		w.WriteHeader(http.StatusInternalServerError)
+	}
+}
+
+type Database struct {
+	Db *sql.DB
+}
+
+// getURLParameter takes out the first URL parameter from the path
+// path should be formated as /type/param.
+// It returns a parameter representing a string.
+func getURLParameter(path string) *string {
+	// TODO: Handle multiple parameters
+	param := strings.Split(path, "/")
+	if len(param) == 3 {
+		return &param[2]
+	} else {
+		return nil
+	}
+}
+
+// getLists retrieves all the lists from the database.
+// It returns a slice of List structs.
+func getLists(db *sql.DB, w http.ResponseWriter) []List {
+	rows, err := db.Query("select * from list")
+	CheckFatal(err, w)
+
+	// Retrieve all lists from the query
+	res := make([]List, 0)
+	for rows.Next() {
+		list := List{}
+		err := rows.Scan(&list.Id, &list.Name)
+		CheckFatal(err, w)
+		res = append(res, list)
+	}
+
+	return res
+}
+
+// getTass retrieves all the tasks from the database.
+// It returns a slice of Task structs.
+func getTasks(db *sql.DB, listId int, w http.ResponseWriter) []Task {
+	// Query the database for all tasks that references the specified list
+	rows, err := db.Query("select * from task where list=$1", listId)
+	CheckFatal(err, w)
+
+	// Retrieve all tasks from the query
+	res := make([]Task, 0)
+	for rows.Next() {
+		var name string
+		var id, list int
+		var done bool
+		err := rows.Scan(&id, &name, &done, &list)
+		CheckFatal(err, w)
+		res = append(res, Task{Id: id, Name: name, Done: done, ListId: list})
+	}
+
+	return res
+}
+
+// insertList adds a list to the database with listName as its name.
+// It returns the Id of the list.
+func insertList(db *sql.DB, listName string, w http.ResponseWriter) int {
+	var listId int
+	//err := db.QueryRow("insert into list (name) values ($1) returning id", listName).Scan(&listId)
+	_, err := db.Exec("insert into list (name) values ($1) ", listName)
+	 db.QueryRow("select last_insert_rowid()").Scan(&listId) // SQLite specific 
+	CheckFatal(err, w)
+	return 0
+}
+
+// insertTask adds a task to the database.
+// taskName specifies the name of the task, and listId the list that it belongs to.
+func insertTask(db *sql.DB, taskName string, listId int, w http.ResponseWriter) {
+	_, err := db.Exec("insert into task (name, list) values ($1, $2)", taskName, listId)
+	// Handle non-existing list id
+	CheckFatal(err, w)
+}
+
+// listHandler manages requests with regards to the lists.
+// A GET request to /list will retrieve all the lists.
+// A GET request to /list/<id> will retrieve all the tasks of the list with id <id>.
+func (db *Database) listHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method == "GET" {
+		// Handle GET Request
+		param := getURLParameter(r.URL.Path)
+
+		// If no parameter exists, retrieve all lists
+		if param == nil || *param == "" {
+			// Retrieve lists
+			list := getLists(db.Db, w)
+			json.NewEncoder(w).Encode(&list)
+		} else {
+			// Get the list id from the parameter
+			listId, err := strconv.Atoi(*param)
+			CheckFatal(err, w)
+
+			// Retrieve tasks and send them back
+			tasks := getTasks(db.Db, listId, w)
+			json.NewEncoder(w).Encode(&tasks)
+		}
+	} else if r.Method == "POST" {
+		// Parse the request and create a new list
+		body, err := ioutil.ReadAll(r.Body)
+		CheckFatal(err, w)
+		listRequest := ListCreateRequest{}
+		err = json.Unmarshal(body, &listRequest)
+		CheckFatal(err, w)
+		listResponse := ListCreateResponse{}
+		listResponse.Id = insertList(db.Db, listRequest.Name, w)
+
+		json.NewEncoder(w).Encode(&listResponse)
+	}
+}
+
+// taskHandler manages requests with regards to the tasks.
+// A POST request to /task will create a new task with the name and list provided
+// in the Post Body. The Body should be in the format
+// {"name": "taskName", "list_id": 123}
+func (db *Database) taskHandler(w http.ResponseWriter, r *http.Request) {
+	if r.Method == "POST" {
+		body, err := ioutil.ReadAll(r.Body)
+		CheckFatal(err, w)
+		taskRequest := CreateTaskRequest{}
+		err = json.Unmarshal(body, &taskRequest)
+		CheckFatal(err, w)
+
+		insertTask(db.Db, taskRequest.Name, taskRequest.ListId, w)
+
+		fmt.Fprintf(w, "OK")
+	}
+}
+
+// ConnextDB connects to a postgres database.
+// it returns a database handle.
+func ConnectDb() *sql.DB {
+	// TODO: Refactor the database config
+	//for postgres database
+	//db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s@%s/%s?sslmode=disable", databaseUser, databaseHost, databaseName))
+	//for sqlite3 database
+	db, err := sql.Open("sqlite3", "./foo.db")
+	if err != nil {
+		log.Fatal(err)
+}
+
+
+	return db
+}
+
+// Handlers retrieves all handlers for the server.
+func Handlers() *http.ServeMux {
+	db := Database{Db: ConnectDb()}
+	mux := http.NewServeMux()
+	mux.Handle("/list", http.HandlerFunc(db.listHandler))
+	mux.Handle("/list/", http.HandlerFunc(db.listHandler))
+	mux.Handle("/task", http.HandlerFunc(db.taskHandler))
+	return mux
+}
+
+func main() {
+	// Listen on port 5050
+	err := http.ListenAndServe(":8080", Handlers())
+	if err != nil {
+		log.Fatal(err)
+	}
+}
diff --git a/todo_test.go b/todo_test.go
new file mode 100644
index 0000000..6993991
--- /dev/null
+++ b/todo_test.go
@@ -0,0 +1,149 @@
+package main
+
+import (
+    "io/ioutil"
+    "net/http"
+    "net/http/httptest"
+    "testing"
+    "strings"
+    "strconv"
+    "encoding/json"
+    "bytes"
+)
+
+// checkFail fails the tests if err is an error (not nil)
+func checkFail(t *testing.T, err error) {
+    if err != nil {
+        t.Fatal(err)
+    }
+}
+
+// setup recreates the database according to schema.sql.
+// This is so that all tests occurs from a clean slate
+func setup(t *testing.T) {
+    db := ConnectDb()
+    defer db.Close()
+
+    sqlData, err := ioutil.ReadFile("schema.sql")
+    checkFail(t, err)
+
+    sqlStmts := string(sqlData)
+    for _, stmt := range strings.Split(sqlStmts, ";") {
+        _, err := db.Exec(stmt)
+        checkFail(t, err)
+    }
+
+}
+
+// TestTask tests all functionality with regards to tasks
+func TestTask(test *testing.T) {
+    // Setup the database and create a test server
+    setup(test)
+    testServer := httptest.NewServer(Handlers())
+    defer testServer.Close()
+    // Create a new list for the different tasks
+    b, err := json.Marshal(ListCreateRequest{Name: "Work"})
+    checkFail(test, err)
+    res, err := http.Post(testServer.URL + "/list", "application/json", bytes.NewReader(b))
+    checkFail(test, err)
+    // Read the response and retrieve the id for the newly created list
+    listResp := ListCreateResponse{}
+    body, err := ioutil.ReadAll(res.Body)
+    defer res.Body.Close()
+    err = json.Unmarshal(body, &listResp)
+
+    // Get all the tasks from the new list
+    res, err = http.Get(testServer.URL + "/list/" + strconv.Itoa(listResp.Id))
+    checkFail(test, err)
+    if res.StatusCode != 200 {
+        test.Errorf("Expected 200 got %d", res.StatusCode)
+    }
+
+    body, err = ioutil.ReadAll(res.Body)
+    defer res.Body.Close()
+    var tasks []Task
+    err = json.Unmarshal(body, &tasks)
+    checkFail(test, err)
+
+    // There shouldn't be any tasks in the list yet
+    if len(tasks) != 0 {
+        test.Errorf("Expected len(tasks) == 0 got %d", len(tasks))
+    }
+
+    // Test the creation of a task in the list
+    b, err = json.Marshal(CreateTaskRequest{Name: "Work", ListId: listResp.Id})
+    checkFail(test, err)
+    res, err = http.Post(testServer.URL + "/task", "application/json", bytes.NewReader(b))
+    checkFail(test, err)
+    if res.StatusCode != 200 {
+        test.Errorf("Expected 200, got %d",res.StatusCode)
+    }
+
+    // Test the if the task got stored in the list
+    res, err = http.Get(testServer.URL + "/list/" + strconv.Itoa(listResp.Id))
+    checkFail(test, err)
+    if res.StatusCode != 200 {
+        test.Errorf("Expected 200 got %d", res.StatusCode)
+    }
+
+    // Check so that the list contains 1 task
+    body, err = ioutil.ReadAll(res.Body)
+    defer res.Body.Close()
+    err = json.Unmarshal(body, &tasks)
+    checkFail(test, err)
+    if len(tasks) != 1 {
+        test.Errorf("Expected len(tasks) == 1 got %d", len(tasks))
+    }
+}
+
+// TestList manages the testing of lists
+func TestList(test *testing.T) {
+    // Setup a clean database and a new test server
+    setup(test)
+    testServer := httptest.NewServer(Handlers())
+    defer testServer.Close()
+
+    // Retrieve the lists
+    res, err := http.Get(testServer.URL + "/list")
+    checkFail(test, err)
+    body, err := ioutil.ReadAll(res.Body)
+    res.Body.Close()
+    if res.StatusCode != 200 {
+        test.Errorf("Expected status code 200 got %d", res.StatusCode)
+    }
+
+    // Check that it didn't contain any lists
+    var lists []List
+    err = json.Unmarshal(body, &lists)
+    checkFail(test, err)
+
+    if len(lists) != 0 {
+        test.Errorf("Expected [] got %d", len(lists))
+    }
+
+    // Test creation of a list
+    b, err := json.Marshal(ListCreateRequest{Name: "Work"})
+    checkFail(test, err)
+    res, err = http.Post(testServer.URL + "/list", "application/json", bytes.NewReader(b))
+    checkFail(test, err)
+
+    if res.StatusCode != 200 {
+        test.Errorf("Expected status code 200 got %d", res.StatusCode)
+    }
+
+    // Make sure that the list is stored
+    res, err = http.Get(testServer.URL + "/list")
+    checkFail(test, err)
+    body, err = ioutil.ReadAll(res.Body)
+    res.Body.Close()
+
+    if res.StatusCode != 200 {
+        test.Errorf("Expected status code 200 got %d", res.StatusCode)
+    }
+
+    err = json.Unmarshal(body, &lists)
+    checkFail(test, err)
+    if len(lists) != 1 {
+        test.Errorf("Expected [] got len(%d)", len(lists))
+    }
+}
-- 
GitLab