From 5e25912247223f1f3cd6c4aae71d52745598cf12 Mon Sep 17 00:00:00 2001 From: illenko Date: Sun, 18 Aug 2024 14:17:37 +0300 Subject: [PATCH] Implement general components. --- .github/workflows/go.yml | 34 ++++++++ README.md | 9 ++ common/amqpmodel/model.go | 27 ++++++ common/connection/connection.go | 18 ++++ common/consumer/order_action.go | 36 ++++++++ common/go.mod | 8 ++ common/mapper/order_action_result.go | 14 ++++ common/publisher/order_result.go | 31 +++++++ environment/docker-compose.yaml | 11 +++ img.png | Bin 0 -> 115403 bytes order-service/expired_actions_consumer.go | 25 ++++++ order-service/go.mod | 11 +++ order-service/go.sum | 6 ++ order-service/http_model.go | 27 ++++++ order-service/main.go | 68 +++++++++++++++ order-service/publisher.go | 31 +++++++ order-service/rabbitmq.go | 96 ++++++++++++++++++++++ order-service/results_consumer.go | 64 +++++++++++++++ payment-service/consumer_payment.go | 25 ++++++ payment-service/go.mod | 12 +++ payment-service/main.go | 19 +++++ product-service/consumer_cancellation.go | 17 ++++ product-service/consumer_reservation.go | 24 ++++++ product-service/go.mod | 12 +++ product-service/main.go | 21 +++++ 25 files changed, 646 insertions(+) create mode 100644 .github/workflows/go.yml create mode 100644 README.md create mode 100644 common/amqpmodel/model.go create mode 100644 common/connection/connection.go create mode 100644 common/consumer/order_action.go create mode 100644 common/go.mod create mode 100644 common/mapper/order_action_result.go create mode 100644 common/publisher/order_result.go create mode 100644 environment/docker-compose.yaml create mode 100644 img.png create mode 100644 order-service/expired_actions_consumer.go create mode 100644 order-service/go.mod create mode 100644 order-service/go.sum create mode 100644 order-service/http_model.go create mode 100644 order-service/main.go create mode 100644 order-service/publisher.go create mode 100644 order-service/rabbitmq.go create mode 100644 order-service/results_consumer.go create mode 100644 payment-service/consumer_payment.go create mode 100644 payment-service/go.mod create mode 100644 payment-service/main.go create mode 100644 product-service/consumer_cancellation.go create mode 100644 product-service/consumer_reservation.go create mode 100644 product-service/go.mod create mode 100644 product-service/main.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..38e3e5b --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,34 @@ +# .github/workflows/go.yml +name: Go CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.22.3' + + - name: Install dependencies + run: go mod tidy + + - name: Install golangci-lint + run: | + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.1 + + - name: Run goimports + run: goimports -d . + + - name: Run golangci-lint + run: golangci-lint run \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..2e03b9f --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# Messaging driven architecture with RabbitMQ + +### Stack +- Go 1.22.3 +- RabbitMQ 3.13.6 +- amqp091-go v1.10.0 + +### Architecture +![img.png](img.png) \ No newline at end of file diff --git a/common/amqpmodel/model.go b/common/amqpmodel/model.go new file mode 100644 index 0000000..e05f3f1 --- /dev/null +++ b/common/amqpmodel/model.go @@ -0,0 +1,27 @@ +package amqpmodel + +import "github.com/google/uuid" + +type OrderAction struct { + ID uuid.UUID `json:"id"` + CustomerID uuid.UUID `json:"customerId"` + CardID uuid.UUID `json:"cardId"` + ItemID uuid.UUID `json:"itemId"` + Price int `json:"price"` +} + +type OrderActionResultStatus string + +const ( + OrderActionResultStatusSuccess OrderActionResultStatus = "success" + OrderActionResultStatusFailed OrderActionResultStatus = "failed" +) + +type OrderActionResult struct { + ID uuid.UUID `json:"id"` + CustomerID uuid.UUID `json:"customerId"` + CardID uuid.UUID `json:"cardId"` + ItemID uuid.UUID `json:"itemId"` + Price int `json:"price"` + Status OrderActionResultStatus `json:"status"` +} diff --git a/common/connection/connection.go b/common/connection/connection.go new file mode 100644 index 0000000..68e60ea --- /dev/null +++ b/common/connection/connection.go @@ -0,0 +1,18 @@ +package connection + +import amqp "github.com/rabbitmq/amqp091-go" + +func ConnectToRabbitMQ() (*amqp.Connection, *amqp.Channel, error) { + conn, err := amqp.Dial("amqp://user:password@localhost:5672/") + if err != nil { + return nil, nil, err + } + + ch, err := conn.Channel() + if err != nil { + conn.Close() + return nil, nil, err + } + + return conn, ch, nil +} diff --git a/common/consumer/order_action.go b/common/consumer/order_action.go new file mode 100644 index 0000000..ea050cf --- /dev/null +++ b/common/consumer/order_action.go @@ -0,0 +1,36 @@ +package consumer + +import ( + "encoding/json" + "log" + + "github.com/illenko/common/amqpmodel" + amqp "github.com/rabbitmq/amqp091-go" +) + +func ConsumeOrderAction(ch *amqp.Channel, queueName string, processFunc func(*amqp.Channel, amqpmodel.OrderAction)) { + msgs, err := ch.Consume( + queueName, + "", + true, + false, + false, + false, + nil, + ) + if err != nil { + log.Fatalf("Failed to register a consumer: %v", err) + } + + for msg := range msgs { + var orderAction amqpmodel.OrderAction + err := json.Unmarshal(msg.Body, &orderAction) + if err != nil { + log.Printf("Failed to unmarshal message: %v", err) + continue + } + + log.Printf("Received a message from %v: %v", queueName, orderAction) + processFunc(ch, orderAction) + } +} diff --git a/common/go.mod b/common/go.mod new file mode 100644 index 0000000..443e8a7 --- /dev/null +++ b/common/go.mod @@ -0,0 +1,8 @@ +module github.com/illenko/common + +go 1.22.3 + +require ( + github.com/google/uuid v1.6.0 + github.com/rabbitmq/amqp091-go v1.10.0 +) diff --git a/common/mapper/order_action_result.go b/common/mapper/order_action_result.go new file mode 100644 index 0000000..c0bdf44 --- /dev/null +++ b/common/mapper/order_action_result.go @@ -0,0 +1,14 @@ +package mapper + +import "github.com/illenko/common/amqpmodel" + +func ToOrderActionResult(orderAction amqpmodel.OrderAction, status amqpmodel.OrderActionResultStatus) amqpmodel.OrderActionResult { + return amqpmodel.OrderActionResult{ + ID: orderAction.ID, + CustomerID: orderAction.CustomerID, + CardID: orderAction.CardID, + ItemID: orderAction.ItemID, + Price: orderAction.Price, + Status: status, + } +} diff --git a/common/publisher/order_result.go b/common/publisher/order_result.go new file mode 100644 index 0000000..13ab3ad --- /dev/null +++ b/common/publisher/order_result.go @@ -0,0 +1,31 @@ +package publisher + +import ( + "encoding/json" + "log" + + "github.com/illenko/common/amqpmodel" + amqp "github.com/rabbitmq/amqp091-go" +) + +func PublishOrderResult(ch *amqp.Channel, exchangeName, routingKey string, orderResult amqpmodel.OrderActionResult) error { + body, err := json.Marshal(orderResult) + if err != nil { + return err + } + + err = ch.Publish( + exchangeName, + routingKey, + false, + false, + amqp.Publishing{ + ContentType: "application/json", + Body: body, + }) + + if err == nil { + log.Printf("Order result published: %v in %v with %v rk", orderResult, exchangeName, routingKey) + } + return err +} diff --git a/environment/docker-compose.yaml b/environment/docker-compose.yaml new file mode 100644 index 0000000..bdc14ee --- /dev/null +++ b/environment/docker-compose.yaml @@ -0,0 +1,11 @@ +version: '3.8' + +services: + rabbitmq: + image: rabbitmq:3-management + ports: + - "5672:5672" # RabbitMQ default port + - "15672:15672" # RabbitMQ management plugin port + environment: + RABBITMQ_DEFAULT_USER: user + RABBITMQ_DEFAULT_PASS: password \ No newline at end of file diff --git a/img.png b/img.png new file mode 100644 index 0000000000000000000000000000000000000000..9d61d3aa6c0fd2c970eb2cc58ccbfb640730cf8f GIT binary patch literal 115403 zcmeEu1zc6x_P-!XC(4br6`-Q7r+bayCH(jh4wk|NzAh=`yd-Jsxq zUj&EId2inP{bqju=gj*Ii9uN&xJL}89E-n%h8ScwuU;o z)<-vgz0=0r+{DJv;@6GZ=4NKP+DCJF)T5@AmAU<|FVizOIeNXLYb?N<|EhObgWL}? zg|#Xf>ev8ffN2vu)6rYN+C_8?^$m`n%*c8uBqjz^&Et!Y-o)BKQ^(x?>-~pKC#U7B zAdkgqWo{1oJ27h~Paj`o>cFpS0@KK2IUYR+D9*os?>A{!eFMb*raNgtBStTG3hYo?iNzfIZMQ&}Lv`YI1ZMK;MMl+{FB=-ZSfH>ay!;gG;P!tjvvdPn==ZX4loy zJH+%6u55IV)b%%naM<+EXX2On5Y`1?wz0Yg=H#eHTGk^e9;rW+@#xt87hPh6bpRWR z!3jM&zEAT=ef7U}4ZHGRnPPCwk%s*9;lr%ucZ&3zv&Z~(kSAvEpG+9AGymp<>FMb) zY5(Sg>9A_CLRtThCXDfTf{rGPnc>F?V`KS^34&hszOg=xakI6wz~9@5xY zk1X;(nYd$6odnu{-n2n~m^KS5a~)f4o4>N5S+2{0DC$T#Ls6ckC@pBQ)!`j z&lCXZ?=*v~%uGM;3?A8%6Epags%UE401{5C>!59*X$FWR6RQc#ZfaS9Z~Cxrlsbl1 zfQABY5A)O3zmOTg{w!e3#X{3c)5JvA#2glhfEz4ytqcKaIOOZUIw$?hiQhD_zv4a) zy2sQRMwPzfLb{APP+d0A{sR}{U}a<0{J(Oo%xu4g_-}Hd<7-Zu=wq|}pW|7NDE*znX1;N?Q|~|C;Tuq3S>S7ZwTr z7{Y#!a<*fvoJ9H0VYV58PlmbW6Z&y%x3x9Rv_UrI?`gQ9KQZKgOiLVd?IY0tW!>-h ze2VQjggOb#pTzzCn5sAi=1D^JcbiexW3&1b&ghR>j2|elu9*%mEJF{=GMQ*vTN}dC ze<#A4UsGgV2SXd>qhv4ay9)Tu03u9gKG=}}Ea3_xzJ~`eLV9>$2C}iRo4y^KxC?gf zm)j1Hj_>|LAf3URj zqp$wXOP^4UWBi|tosQeAbYZ^D?kMkmH2B{NsQ!7f_~dY41CcfdOJu;K9;LgPkIfBC zkU%2L>__bX_(@;Ib#xcZ75{!F`*$AsjjkR)^819|SIPem9?1+A>_7_r8zcJXk~zBi zFq8g!SN>}Wcg7#nNdH?1{SV>rKY`x=2MB$ocmG`YU$yDK82S}#|H2shF_HIQ4E-}V z^fkEqFNRKfogcsdhU@zaV~G7LWKKlQe@_e@rw@LY%N=sxzZ!;qSm6Hixg5*)^zrBA zazCyZ{BJSzbB04la`<~di2b_-5*FxDRQ%_KLmbDcyrXc4 zE&LyV=v%Gsktg~Kf#}E@{2AHpU!out5cYf{cmJU1;CPkwI6Q*g^Lqsje_%+&cw|j} z-xI+e`d7oy{{fr(9z#DANBq2w=#Q^dILdDSJ6Jf(J{;y0{yp6Nkr+Cnwg1J?VfoJ= z9}&?W*E1daq2mg7Soc8UKkgbwBPv%8^hKHx~7Sy{gePX2fZF@3i}1pPi2 z_|v)}<{z`$IwlS$c6~7XcXu9`?C*--j!QR>E$NXae$&ho1*VM0*PN^{Jq|{WE%1N9 zFBSaM30fUZYlCk;dhthclcV+1-!-gXVf3?GR_Jl<$T3qmE=@kx(?8y_vL0uIj~{t# zX^$WI^IF!QI$ir`A?jbPW%+9W>f7SOk#_&ED*nd<>f64w<468=sLGG2TNqXOtxZpV z_5H_;--UF{$5!(s@i;c#|KY^r$6Vs!to}`Ql7Byw-&S6J!kPTzGg`;RX5Z4lD!=4+ z|KLKIKg;1A2Ux#PArFD@vs1_)cD{e_e*Som$NHTy{I&!1=ckZ=UViIufvCUa@;}R; zk0|Ev5cLCX{dt43KXG5quUAkGS7H7YA4SIiWjWe|{nfiMaWEh6$^KRc3frv>BlO2> zJ12hV>aguk^Il(*DZlHy{t_jh%*ScDqtJ=%ICXdINd9==^=+%c@gu(n_s@&8KW+EU zF$TV(<)8nU!LM-fj}|+B52}A)LXr7zRWQK#9iV>jBY!-gj;lS7@boPkatz`BAUqxZ z`oTZ=)#~HlQTXKt!cPVUhi8v}lKkt5qZ?p9=Ki(L#Bv%A`P8W^r$hyKZLIVBJRh34P{8ud6xP6>1^Fn?pnd?%NVo>JVicj-!3@(LLdyzO^;gZYQwtfbQyU# zf@N&;RF@_0xF2v?!+ls+DP8F_Rabb5gm7L7kWvk=oDVyN{L7#FH0&AzrveiRcr4?f z%H^u{1g+qu@}RSkCoZc%hYNtxmB!l$;vi5Cf6z)aAZx)(I`MkoRV@g>H6hwP(ZQl% zY>eA#_IKs-`X*xfG)@WvhlHo7^*(E4!3WP%EqH1sn8E4FP0YU%tO)!gZa3Zv3r#ns zsaH?UceWNepZTC_E3MzHzvs(oPeh^;fv~gqRDGdJktY&7f`9{ug&jQmEcYo#%ST$l zckKe~BEAjY-5Rp9w~7BusAsOHqCK1>*}`Mt5@#N!ESdPFtSS4Yn|yC=bXN}gTtDv_ zJGkv%q@VQkABfSIy!hx*>oz_UDx2BsrUk0~Cq@&ubh_hE>aR+9&y^^p+~cI*`1qQ@ zrJ8M8PpYZ-w){1%M>IaMvzOoFMgzWrJ7gi zx_u2xM>_}qq*S9|mJx0z^uxct*q3KKA*C0n%t?ghPw3#M|in(&Ez+f9cvKPs~jEsrk7fKP*O1icYFw1JC%tFn4+&$Q$Rs z>5J$$wQDd$j%!XZHLjJ(Tlqp_a`ybgkU49`sjd5{9b3d{dYT6j!8>a+=Q?6KLovK= zL>Z8TLtSnpY6kS62n6CG^Y4}M&Y%bqheJ>M_B1?lOK+Lqtd`&Cj4I*^W87a}iLX9; z;quKE-%uh(gNh3f@*ppj*ZUTWt%N~|HJ9Gg-)+j?4;;K?7<_xPt>p!q#Y#Ia`S1qe z4eWIs^M)2}n$M3lxbE%27e!WU&R1MEc%4=J?Tvt_li*x1fT#=iQ_D_>+5{%*wR=r6 zly0ofUk=oeNhM#Mmwy|)Z6Ni4!~TpJ_Bf-dvy?#SMckozC#{arrS@=IFNm>~j(BL2 zS^}kv-j=6rg{vJc+U1*pw}YLM?aE}cWF8~~`m<7CNF zLtE;~(VQ70jAPU<3#br{Cn+;raYW~UmLzb*ehNjqAZRGVyG*yK|YHq9hTJahW9 zxD-MtuVj%BW~Zt*z}?FE4}suyTo!Ti$$!C~J}J6%7hYtr(ye^OG95bAst_PAQl+h+ z3hQO!oS}~ysm2L|g;~uB`NlOJAmE(R^q0hlzZus!iNb@irx`>EV5Y0mDlfAs_wUx>eE?&Gx|C z%A_irVYjSn=iV-)NfitZ!o_ql_5?PBBCZk%SvqeDw-*QK)ZQ5VZSh~sXSYy;c^96X zPFFtX1?f@~@xg2vyvR12wnfehebxii^00|NQ*!pj?k;cu}U;=RNfhMkBZ&7r}3yT#cb zE@K!|56^o$Z4*te6jX9gVew{(-A|>a77i3D5<1tR>V<%?{z_Z~6ri-rJU+9GW z7=R$<=>_XgB9Gd?Nw4b4_IhuiK(DvD&?u6?elv${MZl+&%DDwE+nCf=KfPtY79pnd za;j0kUxPL^*0rZ>kN46buWyd~YHH6SPz@8j;v|CN*$K}_i86FMVc40)1>n%%{S*N8 z67Cl0fqPwHe-HC*Tj2et%dgXVlBp=?Vi3t`${SZ}&xJw7@g(DbxkF&aA%;^2#@gZ1 zKNzk=UU*hq{Q7VXU%eHx{F)9jgQkEI0kD)xdYL8ZAwBvD?AcJoL73z~vE> zLH-E>U8A`#^keV09wLgNcRVDG{AO7Gv8m+QMt~V}>ng%XK9`Jo1QT)!7Eeoe%NUjt|&1 zRh#_@PoIl16KJ)mCl${aoR!eFR1bh&Oq=F`Jn;ka418i4HVn*zf#ida;otlo_|otN z`1UEoD{!U&hkY?@N+n_7@^g)rmrf9XQ^=$4pcS9z9Tu6!S%6f%1}&vFU@xcHw^ZX# zunG4=3l!#F4tvy##9S2-fR+1i*n@s`jR_BEMZIE$0%7n1-7;$w-N0z!aO^8Izd|!%}J^Q6A@rG zy)od^^qw{J9FScRI)U%6BJJzI1jq*bZ;pLAqBFtT&QIFl?uVk{QrM7W3N`WwiLB% zYn`*E-}F9N+>G`iil=*Dk{6co&h&3d?g=Se zT5b9m26-k0+yo|&>nGau(-+Yh#;n7%g3tJR^NTc~04e6Vx2251_z0nKfdD))xkhR1 zV3?IAH-v!%HlA_YJ(E({5R>lxh7!6HB41i09}1!5fFgfL0!lJrPE7d3{p+xk-^NBk5Dcl_cs59f+f&u+BE<_LvbVmLLo)<(K4Cu4% z1fFM$0#gR~zU#R;_cI7VTLkIK+Kt3h=#VEc@=o){GRqE}HfT$r3Fi@k4GfyDIvR=) z1hWhn_7893FLH8_7Wvq-K zy<9-JRg-+zHQ?Y5UtQTkgxwn<4`vEb90+mTg)m(Qx;^yRwUZ5pt34OE5dTf3Y9#9MUD&tG9acKO-j7I0O1tY?zi_ z1nBMyfhv)Bguw=8BvSc=2>DVt5GCo-br)8co}l*J_zi2(5CViBVI&;&AOXP!78Nc% z4MS7rX*hiKiv$ofVmKO@L4v>RYXk$kU0x*w**gk0F#eAF`yvf~K$Mp(N9IZn)z@KG z^fwHz9U0I>dCt^#gJj80K)5#b_iY;BfiS?U7rhCyKtfiA8DZ=dc6m;CAq?X>mrp+C zlXavfqYPt>sCth96}ukIb?dZ`4{VagtsqxC8h|{e=73%wO8nAl)PTM)5b3nYo+@WE zLJ-NYM0_>;9Xq1t{%n2>I#D{+@oIQOS1CNLTU#G4k=ybvsBxWE>Ca?!+Do)wnqKj@ z&Qg5cwNMmtd1ZCr>NVv`Wat;_6bb(wC)dx_ZrHLE;tS{l54tXUz+S}H`( z3pFRi2ademnm|-$Fhs9&Lo}+~mQLkW+TJ@T*Zfr1q+DvmOd_;{8aQIYyEpipQCIl_ zc09B3^V_QRwioP|x%oz)Xijl8WAamUJ{!D8vog1iGnlQ4ayKb|^;Kd0n}wEKgGqg| zrEw>}1Z;7wh7WV>m8Qh6>pr=sVCrcvKIk)=a0_|xEY9%U6X!h(k(|L~%bRgG^f|Oz z{CpHqb5c!;K3nAWp^TWl7K|ZSOwW@qVrhxH}Gc||I(*Ow(R zsO2f&QB6v}WVBjyuE6f}XGr1Kwy6&>>Z}wW>CNKjHc`1D`jXAzv%~_I4TR%BB-AV) zKbfZ>k5abmjNKx)Pv@MhX47ZOteMxC=W1)iC|wEiCW;X!5T%+Ioi0eTsG~^`j7z$> z%-2L$e0meEMT;TprgtllV|tI&uJZ%;emeoTHDiPArM78Vd4P zoRaFpsP92ovNv&ByOh%fa50RRxExYVYF$jcZf`G}e(EjQM#6@YlH4CHYj=7AQJgPZ z^s=sw(d?R4yTs{&!Af^2)Fi%tuf%>i1(Q-a8&@_{#FK7mGkOO?FOFPls(M=C1$L9g za;3xO9_?0MLP&Vzd(Bs`n^x9r+AB?a7iwlktED?!dj&3A%&YRR(B#{*Sx&ER&OieCri8c zkj?#wvN4UvJxEy3V+s2PE;i1%DZX8QPv0(Gas5WZkRp}r>9+2Mz}P~C9OZhMfvAe1 zdh2uPQV-$tozC-r^cm{S)Gm2+%T?oJKv-0^0qTrg&O86Ux^0n-rCuyct(GUbTrr;w z@PHqM2odnZ3lRe!K*=e|O*MRNiWp?FdSR?On8zCTBT_|OoABtP)3Ftw?AFFE?`HlME63oKQoPkpxKB5ZN628|XYmmGe`rg`OnT1904j%?O=PBl%R_D(uSMXCAYy}gmbNpx1r z?o%xZ&_w$*?fO3IVxie}+@bfGe9v5shd&#bA3ShNHmTimu)P<0JJ+;lDvsTFPU`Br z&Jc3Hi%=$`@`VC{AS_YLRQ~nr1_N1D0RffHi!t?#5Xtq0&$q~jA57Lt2#$*w52kRt z?vvL*3Ybe9(53Ti)6nf@R_5^;<)(;dl%YA?v#@aG-R~6&A_|+jcg%48v@a&#_jCwK`IV68HU~ zvZ0TSUTPUkWL4qOm+1*OhhJxJ$$9$h{T<&y+X)DE#5MhU>O~nT!rV7*)Cva2Ggu=x z)5WWk=rmJA649_NNcY{`CgNHR&fD#KeY)+|Cro3<3y*@js?jt?0t}5@=iIjX6%>SL z*M{zhB$2@--E_-dFc~rShG^m06S(tLmh1{`h@cF62}=!iDUb~B(Dv3CzISCYn7r`t z_OOD?^@!Ito2`WDop)pe7vu}231SN;1Y)$xJh6;p@?Hi+zNgzAe#2osg~EiBn@y5% zHuTZsdH8q|7g$!-u<6QE4$*U%6fD4#VtuG0i4o<(7gdk6d-v|%c;y%L`)i+ZHFSb$ z7s5rZi6@+J7$NA!>30)uq;gK5!w7J ztJC^e`NNQ1E1lJ=!`|oc756piTTBJr!?8#)h{>p%&6$Vt!sQ?F-7C)CV-p`XYnhnF zSMc_oY{$zMEYX+|x|VbU!5`8rBLj_of#u=UWaJl}a_OwSxmPQcCTov|NzrInBq0n5 zw_53z+@>;$f?3D~B5vxU)^}|IxJ?SgZ-WGLa-)bbR0O0k@Lio#ViKUPq{iu23J3kd zcdb8%!;#j!*Xm!;H8L5}Qw!&Cp;oxDv-!$itdzY@7ft}{c9mVOn0bUB9!7P#NU;Fw zKIO3A4kk0djGJdH7E8B6xkuHiC<^Y=MGp7@oIKfVZCQSi`N0PhmGa1f87!0-ohV9% z1;bGvu28XDv(-yqv6>8*JB?*5aB1z8=WV4e(eB39Gnj*t8stXhinh+wF?1$uPS^Hr zVU$mt!;%2`l85`SRxnmm?B3nUWx_I~<(yzn1-RYGNb+KX8dAjPh*WC?;TN396cp#X z<8O*sdaHHog~pse3~th9=HA{WI|WE9Rqq)%;L4Y{o#CJ2Es2SQD-P4viw$952sZl! zIw@ssT=7qSS!9B8)A@6{cNodNl21bBajd=ac{@+l-4v*}BACcANCns5OK+OdeRev% zPH|p(f_zWFJA44=K;cWwhv-e~wj7dj2qS4YO}_wp#LZ8`J6BwCuyW!Gv0h_q3YhU; zw_Xi^80*yb+m2=Xq3j2LY}jgb?6kT-ltuU?@xaBQFg;&WAIE) z;AnCCEAf}~wi*HrVU>>+=+#wszq}nXmNy*3=G-D&-Q*_;g)|2*zK}9&VuH%$L}&M| zY%fpB)bS!JTvJKFLXAnR97lO4Po)jnCCgS)Ldz5CxPh(ULP({k`l>cFhl6wrY1!7g z^@{%Rc@WbG-%9#4N0FC29L;6aZig7|o)y$qt%GFP;sxljcyzAy zbdxwKSA{kxjmAS4f#1q`Q#iTo?%Cp19J#krne`Fz0rZGRa6} zVgeG;T6WTS6givtzJa-jvKXVDzkI|!LG(yJ;_P#zl6Sq+gg1#=$kcI&#Zpb0FN-&= zc->Z#ts~Rz(D8kK!D$Q=qUibw7Nx7+T#$knB0-N*CJiT2VM=cu>#AN|-h5>+SxQm$ z)YKamJxT5Q7z`y-3*AZz9V!vZ(NA^SPGPs(^9-OP7^sijd&4sZSSh2gtiU9RkUeqk8JI;Nm4x#;FRf3S-7 zCn}HE=80uG`P6Ue4f8ddd|C#lxT4(YWYW!F*YZzL>&mBReqM@2BBXjlza>Vz<9~Mo zo!m-bGtUGB4KRLvZB9;8xzMgXfiakRd>Pt}SXr#s{23cR93&@gOOiXOBvVai6!~@= zc=}x*uhe0U)5}n@`D~eZNj<7-$QPnfP?ziv<$A>;PgMbFr0TJqVzzya;=K3yj4gGn zXRN;Qrs_52Y^vLXxv4kN!}TAmnBT6}au;Svw#94>Oxx1yWhaWhP8*BfUWY8_^osNo zU3l)=tt-$2GKl^AwQSxcCymdK>E84rmng90vF!5bb(Wr~Bg#Q2@A25bc9?-^6{#PZ z%VkCf#+i8m-V`auohA_4c%A4O8b#6UiccjmL8BR&1|cj-a$7hsO|+p587wAzPI^!8 zhh7i(a)4jns|>af)1<=wFtPyo=Fi=g!RANt11T>WEU9zkn(;(GMPI;`*nIYGGJ=VQjh3QI25n}1EjJNP*r7*`h|Izn z^pZv$q8oYouY5#4>#J&ibprzf(`S#x6oI}&h8&1uiou(#{L6pKzrBMlKx zyrT43vt7O8jVn464SnoTn||TN;(b|($z@-X;=1%xh^0$$2ZW5auf=R|*%cSloGq?A zz1p!DXcd`SyAaM5l33{tdAp|91E2j6XS_~oV;+z4%W2`B$oIl~Qeb9tSIUhpCe?x6lF3_pof^?w0q(Ga#)jxzffbn@#4ccDHj>gy$U0x(snrpfD91}E<6@Z4-_yGk@xe1T6rbis7^<(Ngot* z%%j4SGsAyyy(Tl@EH0;M_;Ro>go`vgAJDIvag;3XI?3!p2raYef!O)EKA|BE=EuAb zue;%zzphg%*A+{YeSBKHv~xc)QQq6={#nB4c5R549^KtQO-z05j}UY6v;L?0pEz=m zKk&=im|f)5p;x#tav@)^xEc8hM)GQLl=n8e6g1Qi8ljlTq@rbeTBi;rcy-|!8a5OY z#9Yzvgq(Ud3uA6rz=tdFfec|}7J;bvR-)azr+SjzOqBg57IKSS#&Ur z$sSgT)Gbg`%U6i)b5b$Tho|mqPfNG)^uO64sd@egB_NJ{BERfh{g1hsIG@Sl) zTW3S1+Lwuo9Ok=c2hB&Ww!6e8IC-pwuDmMr2!MJlmdyEdy1TLl!!mzqBa^+QcM1WC z{9yb3yxvphKxpppVsi+&8iQtlt{@s}d9=;QeWZ5r`L^?cVdUD>IBNj~pwJ+W{|#8h zzr9m5!m#$*aKq`qz{O2xM&(V}sk!{Y5 z&IRTi#3PaRqY-ikj?dto-4S+bb4^n)$`e=;akSuZGx>yVd~i)gX-GAaLd!3mZkM*> z5eO$$>+D_-UBrkKkdI(_+pHw)qA&W3^maV9Ur5_L5$l{GqdiL ztCI=)beFy7k;fX258zZ}GveKW0>cPpz*0$+8io@h7gwbTzi*xWJo=%W9^`h-2vJ9< zfTO)W!JZbsn5We>F6fpfnW=f{)dC@&eTuSnskNbvo03#l$XJsr@4{%GOrajGe6IY1 zXTg0J&g`>cd8n+9P^ZjpzS?fz|8y=-ozOu?@=G_Z^T%Ql$L`od^&*Y8SKQdP7dadV zKs51Y_r6*VU9dp9fTSE!;>BCd!xM-KI?v}-(y+8E`=tA`CBmT>9^H_`xZY3AI`8eh zI-Lxdeh&LS;P&z^xc*mER=3e?o07nKVE+RFmT(F~UXYR6x;pH~E=_6AI_U=yg^Ng_ zgg{BZ(ArLJ5pm?t=d`?NE^KJACe8x!OF|*xp!c29Rl6{cAl^~E6MIC`- zil?AdWXuJt^1^I)YZ9u(|L# z0BUv5T~+If~uHpQnjCg$11nuyrrimnS8F}qYdU-8Lu-graKE8$Sxv*Zo1 zML&#g^=H2P3(9@cO5TY9X6>DR_}YX>j>hcpvdwI6s~PNWb9if+UxF6#;c<+~77f=^ z{l)SqXgc*fxdXbG5K0Lh=&fV%9ye$1Zk<>u$su~93Jk;{R~(_ButLXrT8FbdeyRN_`)1ci zMWH~)Xty!8Y?W!Y;*9N;=Q%)4;r(~|YXV~fw!#va@8`0#Je&j^|JBLy+*!7d z8;Y@b?lNk#gY;#xS!T`W9x>HA#}{T>B8}?VRMvWJfZr0zAzRA6pv-c?(PUsaP_K7U z;G0;A9tgW>i-MIiuKIY?Um0`sCVj#U_TERPa(IKq3a@&t-PzV=x;=Sa#z9)vB=)ll za6IHsqi=CA0{q>o;b2*GgH0);O4erd;~V&7Z_XpUBe$KZmt?f*G-)SN$)I?o;fqXo z7K7w-fc{fEcCYMGkHe+Cf{BV;62p#YYIkm?Oy1r3%N3v|M2ur^+Wt-R>xPyD5e$+n z{P^_ei^A4z7o?wJiQ+{K8i=kt$!>C0zRZ^FnG(Ya-ynL_=W+!qLbfI-8%V|^lpr7_ zGU)fY&-LTdX@zY;GqNa~ly{;KYF_>RH)dg})g%QXFII&e$EcQ7zAmgezSfYE?CyzS1mQzf}$v6JDDo$P8v&p`rdMjEGR^{EK3Su z7|MIDUgJ-lMI{-)CN^%J9<{?_@G`GGM%gAdHe6$BoxUYV(1dgne&zm(W_R>~Q` zExcPRGr}P*ei5g_mBgY*sGzhv9_l4#y0^OZm`L+EQJ4J^muw&P8fS}nwdJSFuKP1M z&4HK$lOuwi;Wh;RVi*|h=1$uOr|;G|dhJ+h?|!PnLI}a*h!CqpDe#|&$RT?cHJe z8Osf$TuUJIZ4Y8ReU=NFpBm2@AE~6uyi}9BH4dnSH=JUr>DcsWrn47UbX9XX-lcT>oOTFHZF)w#Jnv(^=R^u?!hQXf{0ewj zu%(ud=ni`ek0Iwm9#**Hp;pthy}NKnE)W;j!HUYDD8r_&rr@-961%ti#y7r# zUR9_@-JY8tI5Z#!)OVBxL0!hhm$(w;9cRIE-PE)Ogdq{+flIr0lqA2{PI;&{Jfz!UY1+&myc!+JDKcn^mr!B{FmrU7UuV;TP(9 zHUfOKPPg>JnDzNcA$w+a!YV2FJ&GsRJu=a2@3>kq=laQ%y2op`k)AWf#8!K+%)G$y zM#emw!tX1KaiQM(^v&_}%6Z{;k^->XQwnnQNa2i;L^_5dpm+K}$Y7jN^m6n~!IJCt zk{86};u96P7Hro+I_%ZX+1q3b%I2_X6C%W7VWA^7= zxDr!jCQuG)UX^a1D%KazOcjsRqx9uwdfd7-A-r<1kLX;rJDD$T0$Z7B^oLTQeY)^a zF*O)#I(9JYfty}0ISEkUaaO#1ZP=P-%{?Ke2^p=fOsPkGPQ5zk@q6h+#z7jIGuSG( zxq*?{!f;Xy>hUhgS2T(ltU9BJ+AXl%#)gaH3j&G4wWnF{7AJ33H9k^afA{j7EvdJ_ z@OfPBbC~+H`_H8-HA%F`CTXo3-lTo5OBa$-MaWN3Y_=XLC#9cK$*b78s~x;?XlcG+Nb)PflIl*gb)0`F`gjaA!?| ze!Zv=q$D1Z7Q6w8*UT~5j;xX&mE=={2e0(Yr75RnPNe1+zzT0@7Er$i+Grh3+KkwP*i@dUG=4qqJaN{0;reswHb!CN{`>@lmaf!UWpe zry{9@<2Em;yqrY$oz`zg<<5F+zG#(wV);^zr%lzPA#c}MfqHrdGna4SR<@X_biEzN zV1XhE5w|Pfec5}AdV@^qQv2#10K=C&cr1Dv-7np6U4ySZEAecW5OHeg6``$B)G#VF zn8ugXc=IGMJJc>zRfP}Is`G5iUg@H5wKWPA8{g{cNIvm{U(gT}jK~#yypldr5&wZ% z3nbCV6sW|DZjaVlB~0P96N*KVhg7T$thro-nIHA_gUfOOxmr@2_;>tOS~Z2#g^rw@Lg7u&z$GJWGDP)E@VGH_e%9 zxMCD8gYy=w5@5g_0~HG%h@z9YCsy9tV0W1lwx~ofA1o}Dlua2+dbNk9h=PB9QUPNs z-wBP1H^ZQgfc-GHm~LTl!~mf2L6LV-!P=ECTv}$@a(njt$IYCW#+n&?kh*%xZ#&O@ zHZ7A*dNL4`=Iq6LPALWl1TpyLE8)a0qFfH|g5*%3#V)Z@_0R4{J_;`r(eqlSn0QL= zQLS|O&2CdQr5tk-ZD!d^RV$}EYw5^?&Ly*j{ApFPEbQ;{K`o^~zz+V|t%FHlTxT?& z2SiR)XdYoV5xv$N-tF8ID_va}Mc;QSwJ>4_#M;rx;K4aq{eWlUd;pyx`EWZ?bp2<@ zWfkU3#&e|VvR%(M<@7~GBk(UrPy~cZBNu}=7vCGqd6dr9;&*u_Q=Yt%X>0c3r=6WS zX0XDUN@6J?Sr8k25h|AcXgESX*EjSLvF=*)&Svb&Fs|83UrbH9Sb8w?(36)>cHmN5 zB>e=a9pcxhmSW*+c+t&L+JYX@uP_JBOkuF&7aD z=k*zp@Ea-11kPx;y(7JBZZ$-_*WjU>tZ`9CW^I$YD_>?p9Zml>N(U6R&6M|2;!ptE zd7o`0T6KUg?`73`SdI*{p*-7Qp~CPrXJ=99Ii;|NZlJ!4jak1K3TLe@`!L@pIGv~K zlGPdVkJtjE7B!8n!|$82)?Ic#V<)~}Qxe$;&U^ z7p=F9Kn>(*>EbEHPNF6AOOL!}rFGPmh&7h18QAMb%tnKg_G`nb_{D68o<8QzY|Pi5 z+ol>;77LjcX@W z*qAAW_+8nDqE9qYq9#IoQm)#SV^R96p2wlf8;gAC6yj4sC#jJbH zoDI>;bv~G=MA}g=T_*%3mi6OjZOQ@Mn_BJgd0$F0(ucI=V&3 z?yqNxIQ6V=hFcPpctLeI6bliqxuE$pPo9e{$Q{gjWq+BnFGHv31~IPQ$W1Kcg@D+| z$Ob83f>xwIc)Hg%<1Np-)h zu8X4#cHT4YOW!;dy)-yd!olZzpe{*o%$h3t(L*GXnySiiFjH9@RV2g~7j%Gj7E!xz ztxK$w>NZ1ljy@*atF*U#dxSA8DwBKvAjzg6>+`NZI$Yt~T zS{PHqSt&FY#dDCLGdcIN#&B-q5Y{=*W79o&ODoNK6XNrzJ06H*qQZE<5vM1qRv_=4 znS+ffjaEw#U^Oe54^Mf!m-RG;$$nnjq;W)DX?=(LB3ff0LohfDt;~=cR0Os>e=c%G z8R&qgU^7}bPs6a5a~B7KK&olGMzR$h1rHv4E79-v9s z$)iLKriMpl#z^KQ>qSHCh@nQ$oF8zxVV6*BqguG$L|pWI7OwF3Z(X|8vwG zvmiZlY48={nKeDAe#MXr(8Ay_P;jFH<{|EW;6p+|FoNKn)s2_p%|RGL6m+ZPLll=d z{JW7x=V9jA!BYEe4|l&IpF5Rwf(Gk2Nr;%o{Gj%E#exYB0EfOTvwPK+J#o3$YlNLr zHR?=&n1$joKL)$!CwYOj1!ntTh-r?JotM(1VLt*Y&q_JvL9oq4aFpE-;TjCES~dh( z-gKc`7KeLcS{-7R>`pusI|}IStv8E)@rU%KkQu4%$lwxTMTVF`51L;ifSM^-K?}8QRTfJi zDE@!dA`eE{*dhAxfjbwdj8kj!p_0Dknq^~@q(~+Gn7XVH*xA0365If+&I06oe70p` z>!bt+XKhYbWTFtTZ(y*}?=I5lG>1XD(&^AHObOS~R0`9vzTn>3+OL*00<+(Nd?EZ?oK7efrRbz&WIhwh`!8~j zZ;(sH^b)6EEF6V@RGC|38*KmN<2uJBSXmq|{Oucv`Hie5ohI0Z1HfK6+8Y~n$s1h* zwQd+z@DK*rK9mxRqLMVEIMQK)8&+pwbhD675@ri2DAvgpz?PNf=SW~2MlbMKB|NN( zProCX9c4N*4|YX?jWo3+B_M`@X@5C3IZYX_*Vv47_3dm8`@o(?4U8hMbCBM*90s)I z#v{u)l!?|jg__dl_VSc+y>F=i`h!AFi#CwJe9*I2-rJZA!g(04W)IXy9rkbQLYX7! zvlCKg`ECjD7k8-YCF~)*mU4kPR-4g#410v36ksOaM@Ci zD(FYEr#C$x&IOnV5+-NmB{*OJ${Wh97SXVEBf0K4M&m`3$=oQ(e5|a^%7k_WE*DmG zi9&>EEO>=XtE>E>?;Az3SVfB6JHGVUXpP;1gc3Y2Vh5Su7buetf=OufZ4r!pDu^<; z8i}*2-&jR0nG&kc?2WbNF-s{x*zN!HR6BTCUN^70|XJo)t z%FTL$y*4uR*$_jyavj$a3)SnJC^%9sLc=6uuhX?-!WZ&5;fK?CYTdrT)$ecRuI=u1 zIf*2(cns`(0d*eDw`P5&op7!Qu7wS~NKu|eR3IH5{KKF+OrPRQ)&9Z zQz^3R`(>mnW0FWL2*9(#)@}4CIl{SMD`^f=>OQEnckbIG#Z=cqr7sCpX)AKFm z<(|@l6-g{g$*0d50#zd5$;%A(E<6kw=U~z@_)>oBxzQM)C^d%^<+9eN9fI?~`q(hS z-{wX%^*29wiwX>*&1%hj&ayIN+8GY67Q8$C?^VgrZvgYy$gFkY>J_l~YW-%#P#}Z= z19xD52_dE*0hG8qVKOMeTvDxlbKLqJ@K~AT2+u2Xw}R&tEpA)fo4`u}X?RMd9QT1S z5m>Rl3IChvHYu?u@ldyXh{s8MNP}TJbUFgHC6kQ4%V0>H5O$l5 zJc#K#`>1rGndiIKV+<{LoMxvoDLhUAHJd8xJ>x;tf=A`Nvo+x)fj=pSvo#%Jk_5e=0kUR(^iu{m<$f`gx15bM3K5L<8Bv|SSjPsaD)P|Nik4;Qja%a0LUTe z^~+cYAg#XUKM6J!KCx;<^1eXSO|_7Q0d^pS5TmP#MR9=_b>8=UqWSE4>*|;Kc~D%i zy7@}U_Z0@Zw^E@xv1*0I&f>`AXO}xS%l5bS6V*&zSJ%#v2>E3VKNVh2gokR3$_FK| z6M?N@!oVar$9^2vzkx=`6aVbQjV9@3lf%J%}1 zbb+I2=ff&=?TFFeA^dsx2o zCJ&SYDu+J0A@t?4m#fuFvSA5a=F`FWuB0 zD(^i7)b%|vgI+%$aOSo35!xN8>)qOyXo=x)zz%@c7Pe9Bai_fvDlzO^zEk{&^Au6z z*cAhakX}x>JDEJDqs5maGeU*qdNsq?lw2jY;2nmL z^7^(InMBy7)wj(}xom|Dmd#j$hPMf)g(X@`^reOpRG9VUw#;sqsR=%J2>uY7J5rb` zeemqVfa$4J;lKj#IApn2t=Dfk{4luA&JUR+JLgWMUpJem^zUzZ0rs@w)_u}4#^{QI zw?%x#XgQ`;#kSXfacKoX1+G|TCTJ;J?9iuh)()|KH2Im-_84-` z1XdFd+2{bx*BdRAaZkgzPs!@f7AEMTlZ(lhnkdKFa9*e}l?>nKj?nxRK>9p{v z-gM>nXHZ$!m*$h+_`t|uQ;Gws!`#<>zqAz8a`q zu)DMG6p2dZ8PXtsh;|>$tK7=J>A1Dv&tllG(VNUG5=|X_cOqqi?9B$?Anf}WabGpa zW!}AWmKP=VMUKgY#RzZ=%+{7CVXBAUaSx1G=-lr6>X zXKSE!oGJ)~tk_JT*mwYstm%cQH7HcbaPQ>Y=?$5YX^4g)%M~x&l+(!j; z6kg=AJEb_2zvULcY+XC5S7_W)*GhJ1{nSx7UhQ1gidwAo#>Z=(SKEf)VGPpMIO=LQ zxyt!+_lNDhtM$ylBl1~t8W}{OOohd28MJYK*lufwWlb1o!n@CCl7;W&XTAJrTTca= zN~Vi7s|;eoP|3?k$M72gY50V7tB^q|$XU4(l78i*ZWUknS%&Y+F$!K|`S;!ovd>qW zOVQRZ$0?q>-oDE#5_L6SZd5A_eyI591m(sD_LsuqTK+au=$}fI@k zUot!lxZ_D>lfr;A7cE~r#v*c;J+q*CUcJrZKBMoEgM2(#S~v&Fw+->n_EGE6`W&8zHNLr}Os@@X$w*3l3(RKS1f2){}r0eB- z!%&}B-|cEu;C`q;j>+MTks&W3G5RVlOCtM?HM&~6&i;y&LNQ5v@iTzV`=rH@Xh-Q4 z{_MD%&WgaXVp^w)ogRBmu040wm!vX(EMMXi!a6r-vJsSwA>N}WktvLarH?-1P}}Bz zbnCCfp7@GkEvbkTBJk*DG?bNWHJUn+<9IksX*%>5#)_+~I4x~2(SCTaA*{hv1;{6P+4i96Qo`vAkS#Dnx)ey zFxwqYE>$l}U2d^y%2JISrbeP8l3TW91Zl6;OE6#HGobbAMDh=NH zqd!&o=1*8SM7tbVMcyczv{zDij23x$9T{QmHRYV7Xa4z0>h9Yl=@iG2Gfunx5<;(5@i<@56$ z#ShBXYFIO7tl!<4*=p=43LB3F%VAGiE4z5PB?(t7TK2NCRBlYu29X69w_6psf`k1s>Q?gHk*^E-aj#{W1p4;Fu zPDeQ@|7|y#2f=*vyb3+7{Zny<{U2@OHt$!YzE`^UW!}!u{T!4GGC8257u`Ep`W~oI z&B3(_vCCugX6~t7uSihFHUqZvIRZpZkh;gnOMg>M`ze|qz3F81Cum8J^|N`X95jzZ&ZK^|g4dai4OV zhohgHN`+&&Z9edb%s}m6l?Hrs&&!jt%`6lSuT!npB2(kEd)B)*%(tM`nAGgWYcAIP z(<8l_B=eiP^qRW4p;RsQmfQCaO=HDcFfiEPn>5;O2(%Qq*16FI|GCHP`?iAaUiMO!iX*nrbdgduqC%><=@CNdyK%v1;TT z!vntGEZt+BcAeFupP)Q`br33Tu0G92qpWrZO^G4UNWn8Mas7G`dz{H4%a`7X6>s=! zODy#(v>JgScWOU1 zXdg{_yL;mkXBqX4wVtsWlHX9G%7gVKvER6Qem(`6RHaG)IujLFmz~B^f!E{9XvrV9 zlNqYH8E#79J}|M{)wS~cfVxAnIIwl zp4OBh*egfSJHlcrAKHsAp%6*H>k?(LZdd)eXf1jLi^F^vq9OZ>6CIbyP}|V!87J)_ zy7CdnB>Ggogcex@d$Zl+TxDh$K6RD-A1!GD6z?2$~lRC-AUKhd;` ztBW3(hLFOK9QHdg34J!?qSEj)SE24I#b*4UB{OU^9PWn|Zq`*TxSjje57rBKhLc8# z(dM)ACl2dg^W~G>nw$?iA4F~b+3Qg-0^-6riZANSCp7aF`XVqjtdjV>7r<0D`VZ;g zH$1k5f#?ZEmI`@~tK4X_C~OX(IGFRS1StI||3V>31p?yEcBNP_qc1T)5BGh5K8y*I zx|iD%T}~kiLuCwUNiNq)?f4@}=bRz_Tl$2kS(Q(gYdmD6S+*J_4B zA%lJL-~4Y0$;}AY1RLOtT}5hA^@qFJp5?asAtd1j{@*W=KnY$zq%~yF^6&I}CGvFM zm-^KfEXqG;KOiQBOeWF>)gckZn9)IJY=Q+p;uJQGelCq*rPHr7 z;zzu?icIuyI$O!SH0$ia?+vnz|~F!-RK1SKu(2UUS--Mc*yOHBXEY$SzI zwx&$2B<4kU()j-x7t>!+OLgj~u$T>Pu+TuF$ELA4+6Ria&Cpi;arE*5tUIU66Nmn) zxnK28ewR$h*4&e;;a&e(qG&qJ@bmkB&{Wm^l71Zc#!e_3(z&#@^%mFffQ%CI{X)4U z{VdA~dd64qqtC@HB!%-W%GJxhdR%N7^+(~FRm#=&Gw2`7LxhkjgZwH<Ya4snjGtg=`mnQ8G0Zlsj0V zhj)LjkRrWHf%qK5GNNfKw$j9+^1)uyIb^Zu3?yrz@-^cV87xO=vv?*~8IU-uqB*EQ z+@e@R&5mVqC4X|>>V?zrZ&EFiWs;4vi}&{gKQ(P2vYk*Iu}&f?lf<`?3AmNvI1O6e8U{6y$lhxGi$cJ3o09S2_Bbb@)2gb7 z2yJd{)%#2dK>u^c4{%NVZ;OSSpRo9PMPveGQz;2l&BKioZ+44IF^15VOqt}U7Hf8i zuZejHL)}IjO}Phv_!}q7U(-1H6VR!)J>YNMo-BjT*i>dfk`nLB(P2j*c%Y6b9$Fu7 z$G`E>sN@IHVQE$y3VdG$06QR4g&~+kgr{@%Ko}6|^U~i3fD@-K=$1Hl10E@WN3+3D zi{bi0^zZp5`&GN{vz@~~77I^n%0>Z1tWj+6Le*nf%gK3XNL|`$Nli6H@^^8=&=c6yzQ!klA_JFHG4rly@ zbwNi0BhV7vomXI9(={NMXp#AUs4FLv)?$cwH9Mwg5c*dW=1<;>$8tTA$_(&g*3S`W zHcR#Q>oA;HJl!G`x#*xyx%^P^VsTz;^W+RKyr23Q!QsX8wmuQ+SZZTnIY*wJ1$x+b zG@8GzQY{z4n8$d9A1J!;2$!FfzSLu1br`B$Z0%Y{;jb+k$~hQ9Zb;;|#8T259w(CU3*$tzv*v(3Q+|a^F&s$+=YVOpJE6H3-CNdh=E)l7lKpP*9L= zx>zzA?~i@#U_5#28-o^M2q6%7(xYaC4guC}@Actt(7?f)j;2jfIX`?0GLHU7N}@Ty zK>#Kw+}4Gc`uH0JW?YXmR@Fekz{FHh`;F_GZsFi?7gpt2+? zP>q515{NvXPDsBhZ1+dsKqjOl2>%NggCnJJL&)v|3pO6$5*vKFlOSOcdJ+VC=m&v) zw=WVMz2ST6!w@-maR;gR((!c*g`W?8tYB!g$|&uOXTzCyt^LE4>#F{Q%(2G*eWnh0=5!bb5_8Ozki(uj;R2PHT@-SI;vq0`YBGPGl3OPH z)x0>~;E{zBg7j|qVMT=WUxJc3mbIz-&KVl2joaB;B@}*{Wsf9;7a$oWCtCM~m#yb2 z$}~T=dDK#Ag3|k6@>mJ^`ROW*c-XnMzZ-Z{4;x1)-#dxJs|#;*_&!H`Ey^$g#0^ax z*LMjUq5rp!D^$V!9FzuC25l1YtvR-}JPDWW5?GfBlyb%5ne~>x|Aeq0Qoil{x1aE9 zi+5$;SVFLd0g`>WSA=5Y2UHrw?hm~qzh{8j3^+*8RinN#t6)x3idxusisM1G^Cd^Yh;&O0%;b zw~C(m+S^S6dmu810gB?;vX=zebUcn#I1zj$1K+N$8@C#KQuy)OGc`#=rY>ihG3PPA zUG!v~vq=)YM%QsI!M|W82rq2w-k0xM)pWo1R+^pZhKs-4U#@8X`?3GY)&}tC;@QFK zlLQ6fgTsdKShSI8^xhyCTDhbAS6=ErKZ*cWiBuUMd}+;z<6*D{{0#AC9IrFR>SOa+ zmkhf-7wmp4!+bll%fG-V9@qoMAN|Z6Wwo?rDm+d*%J~Xgz2V;==_*MANI*^9yns#V zTC6iqR{mXYspfLB#If*ldjM(ykvb1G95-=5uALvN&Ikt0{xX+V&ETRcC^WpD{Z2OP zK2Qig??}J=br3PO|BoS33}HGsYVE$AgaM_7nk3g8l$vU#96=lwW2kqCctMKafL23e zIrIE*1b8AId58qPLy>bjmwexjTcAU9h9Cqsv5=8yY#qQ7b8ak;fEN|2;Yexg( z-93~?wzl8sp!oxwh2qBKRNY{*fJyEVE41ttBTMhs@iYib6pvUta>w%n9gP7hi6234 zPsjehox1?n`1ODSw1&@cO<%Rilg6`n3i54;1iT9KZ6Yw~&HOy@D$aNMyln)X5JD#e zgcCfbPz0=?0FI^^nA{vh2_@+B@^znieRD1ldoZ1pNOn*9tM-)d6&Ge7p4=dw>F8Xg zo(h;lOU_e_qt$F6qe_c481`LcaZnBX^EF$BZ*HDR`c2eRto!fm}6_)@k+cnw6?$N(t*aWvY~+ zt$WADV||p1gyUiF;($&WaH=y@BeD;PKuC(i(F6&=M$Ch(1c(N=H8K8{t0k%3Wu?UmGbwKpZG6eti7 z*stSAdhLb7CrbZ&6DHM8Hvp9}sOxCnUZuu`4Twka43_5AlsRqgVIV^k2YwOOaRgHs zBjyBVknI~Q3U{SUh)_FFYoqI{RIu>)988iXf!3-2mdC=#;60)z&?ray;*C_ilj=Tts-yON7|Ah@)F zM*Nq**ytsLICP@as|cpU4*~yw>mFov)B3B@L9yP#=0#(D?n5z-#w7hlpyvOkdqBb#DGZ@mIi+!JIAnR$F@G&j~fR+Y6T0 z+=K`S$O~cOIqr+Z4#OJbK|ocla0Fd)2@n;gFqiE!8H#}*N*BeTy+nT#Sip7Q%4yn& z1hnbI^C&6sH`fX*Ea%(U(gKDYefNtO$)}P1T%soquxK97j~CgJ@fz$_c_|md9JZrQ z{uW6scy0;OVZc49zB8}SNrPt0D_bK#t#CHP-|`}U1x&s0l@{2H(R;k<#2!s$L%ki;PP3eG66rOY9%6=tzEq^ zS~J=>TC=b@h7Ejz=Rm$As28gM$i=Bl`lD3JRKT^U-`Hdo-K0CBV8WXlSK^s3qTnx) zHdxP{@`}~=hse9~&4NB`GG7AW-^^#}13=w+J+Yqm@?9CJGj;pb#+s?t#x*wm+2?< zTFKi#pbeI-;qf@njrdWf+fd%~v*vkW)uB2aIWMqD;`gTH^qWZ7FOM&TYmu*D>OmDi zn$7~K=2*P52pVuTb1;{Iuuzf1EzixV7Pp$C8c4V};d7`R$%c@Ikvz=?)$%K_jp68^ z^K;(*6R&7r5!725!60(}&^8eTyZ1kR3zY&M(YeUt}FV7J*irT~@pY){N z4T8G2 zE0)JqPyz}k1xM=+oPT$f&-WJqOpHOe7S4xH{@c+kJpe2I7mo=BZGTGUvV@nN*#W}E zx}y0(Stc=vDus=!ROYa6qlg1{jIfvQX#V%sMY&KYoie$n3|0UEE%nUXw{qEmybkor z=(KZCQD%qJMgP;VN7T#2kpxgJ%m2&!MbZOJbI+u8=XtyL9s6US5%L-Mcp%+A#oHs; zw8sQGFzGIP!s2Tw*4P=vfL89D@`LRhoz0r>8~QzD^fgf)F1tIyh$sR&B6?y5WA&8;)N7<^l{x$rfs*%6S_wIt!p(58iNLjWUi_ zu8PtLxV4@>c0Idi~X*^p%Phv^ETwP|i zE*#8-gD{~r)O{H!U#Bg({xjJ+kKSHfh(zJA%rL_XfIoSy2`rtK|I6O{Q~oI3c`cVK zbM#g^lNYz8zS_PKeco5c_Zc{`tXuJCD~9j%t^ahCYa*{^GirbSW?t#TrwngHh^n0|M}S=tro>V z{{3X3FinVpS*_#?=59uduyD2*-RjFsqbvCWV(nxw?G-_qzbWkKjefYCmYvCBei>cu z;dwk8jVgENG?zrJc0t1D4aNE>fBwhZ6otd;y&u|%ZL@{z7CV+=M4S{$aUO|T-Np(| z2Qr$%7dSt(%{ppKBerC9_C;YW|NFK)p;=V)ItjmIS(X?;spOyOS1*h^YXY z%87I$nT^kBcl4cLq3q3&QR|EhNtqbk`b(kW!-~5VwQ{o|7sF**m|3({IaKh`Q}Vff zo2LHBs(QGfC$ahvs{^&JBuSZ%@ z4}G~GBNmNZrhAT38%{?}GC_KCIm=h7o|iN{u!oc`Y(-VWMgbAS)WO~8*DT9Yv04KY zD8;kAVfRt}`%|^3&y`>)3R6`DIn>S~jH_w6F&@KQsU3$*1u1hTK$sAiGXZf)zrqvA z0Z;zB{2jxb#jMki`7uyD)!%xZc8)100^8KY#~NP~SYG!@>})o5B#A7^y8Z?UfQJrF1GhQyWhKw(fh z+^w0YTU*4Wy5E&C@HiMtM&Sr)oo42H5UYF8HU}V~fTsb2r2?VWuovnJHCa39$~;zPcJfE>uWW^r~s-A_E`% z6#rtj1$OHizgOSC_xG0f@(G+DXN?it??0k9;S&q_U=gv$+(IUDZZUKGjmu#8vZ5^q zuG&?^)SclRvG-e~9te6TJwH*>ZAr6foI{~8oWjwATvaKs;)!0c;aWq)Wi5fdKWuM#QBz3+&nmwIOXbgP9?|XYoJB0B!65bRuahg-axJGYpvs)`7_R zqPte`)#C-BcMdP|6iaRg`3}oF?B^LrVWD?t#*HO@PAxKSdRW#8(Q$l}7y&yG9KhF& z?P>9#U5`yAy}?$p5Wx#%uF1G>nB|vdQlnlw%#&# z3M-e+h{oz@*L`7e+8sxT?0}r?&Lw0Y+BjeS3uK_f4bI!lzRX2_vaVNsfMc=78>m) znjdB(F+f`o@ly4%IgEB2W_xKDp_{7p;`{rsdh47Pf?u2@kl zWF!Y&U)jqzc$H^nFp`wHeZSJ)#Ag2>ry-lm67qSqb%kAtZvTw16Z^9M zhlbWw+JK-2l@unHbaDXtFmiriwg+FOBg)QTS@FpAY!f|;+ZoP)Z!q@bi98Y#LKb&amwgr}~(?RTrljX}{iSa#Ote;mkB_ zG@X@dxoP29#aw5Y{Z}-3rb?q}t?Atu;ggJiAD%BA*vn{WU;#@BvwHh@u|1HMcc7a7 zcz0%U{goWYZc3e!Do&Wq>64Pn(dX!K1MeR90Q#5vePRav4!B5uvtO&9BTxiwLSlNJ z`M5UuZ5jF(`117o%5elrx#Y(lVMz-#o}FlPS{PciuLs~iDv=JyX;j3C=}CKAhQ0ltpO`Lp#$wa$1P`Vg zNq_7Q!ex@0h=``f&f8?Q-KsuimcvJKl#`X^`SQ9QhjH32eLCOxg@>oY+cQW$r%Z%* znVa|1R}97_bajIWFH=~SP<1FY{;dyCp0ySU0s5ha-y`*^sE!^-T9O z$CEt)a14kBrB6w*VwFvG;BaG-?{%lBp`j2sEWp-Jjlm_;zuxjyMnT%6N?zC&N>b55 zY_1}mrN=04sXwk{d)b{huOwMO^I=?garzbR4Q&JRut{CgQJe20ktbb4Zvk7Ya+7d} zX(nE4=hyp7lBZssnKDBeN>Sw>(Z7EoX;)1Bl1Ls*l8hk;mx#pL1o&}x0hQZO5-mCd z14CSy6LWGT2lkoY*KEUg{GLy5#;lXOoB7UaR|X*8`mTj>zbeCWo7v*!mUYCVn3vjU zw__MOo0EJpp?Qz5(R(qX6dXFbi(qav-J+OajCdpUb#QVjQNqt!>u;{jz3kuf7Xx`5 zjBx6S96{6^Y&zZd=1PPEu=vhUP{H|jfyGUp&+tzBLy?5P0?t3~!~~X{g<*%g+ZhC^ zY!7$e=5o9^?ukH*oK}h~5a5Nkw|-^uJSGXs@%D$lGJ~%z_Az(X)~m;U&-!_o;l=h@ zRtU%SLtvSaK#;_mc)T&-ui}NpiKKR*3(LEWqsyhON^^kun8bi?toU1;wwMqst#7B+ zU86B{3d3^HG-YI$aA!w|=1!*(yQ_3jO$qL)uXdd$mn;Tj5LxhLq@IXrHV4Jr-|FQE znAmLNo3H7ApYab^JQBD|qwxvu7!Nwm(Y0GWW1EaU4IE(UlIer{>ZtoX_PD(nd&;9* zg(tq%il8?sHU@^C;jMJM!XlVOVoc2~Jr?WeZ*4c4mkXF6=n%Ru+z0?@pZt#9o<^-KOlNMgb zcP?_jwH4zmh*!S__5(rKpJxJJ(;elY?#J&5n%s_v-e+?8M?NcK(58J1 zd&joV+?S6jGMLFn{qE)vVp~&T>zd2R;^XM0eu#pc!3Bumoow^bwClYqB|flRdZ&mU z62|;!_N|g7_b2Y&eMSGg{rU$-Z6R&F-gaFTGwsP+pETZi7+kgkK=5jIKhiP`!XTtT zZ;iDgJJi&nX|$(8!!svch&@mY?+y-KIb7(*RMPK-bE3xYZ*-Wtz7O3!`uWRe2=B|& z6K?zHlF^TE4gK9)x0R)VifpXmJSYXD>1_Gmj7*y3iK$+&nm>Tji3gzq9_>dN$SkCf zjNzS(Ewr+3d>B4je~Oe~6ixy!QGhiU1X@IeTJrf^JS+9t{*kV?CwzX#n{LYbZ|b@ zuYd2^rUb-0N8Z#DYkvRBeEW_`yo0}aOa9^-kiNTzu{{G5`F7E=#+??rLJx>+Cmg0d z%Xh?6?IzZv>HHA3-bj&$_WR}c2P_Lj)>yoG7I{w#cuuhB=APTXwo5D)o0!_nqp@F4 z>zvSu1bkxn?ua9w%iS8_fi~fRxN$NqwQ9BB-%-)y@`>`n#g@4@7kYgAVry0}_>S%p zBLCiAXOAj~uH`!K^L)TUty2e1<~Xzofk5w?-Aw-5m6BM=Y<->`PbhZHP!M~Zr|1ev z$m;^jY}oe3VEGwLEXs6IQn5svpo`mDkHn-8u_B~0>h_PJGZM?@h!ilWv3{q1oIit}WhYugfuo(%MGEha=|Jv(%V>*<9Xtw9W zva|+Q#YSbE{F>vr+DObD>eCvyJ-WU2Ez@GP=Ii-wI@ieCdjyProKT%}mv2l#>AJ4? zzt#uH%>-E|TN|O_@@Rb11-;*TUE}5^+~g{1SE%61-niC#UYUW`nSAdL=S?)lNw!HO zN8V#BLVQS@1&zpgqwpODm!VpyI+}*fzWS931}SLl)GSJEfbM_U%y);jdPbJQ;EIDBJ0 zZO=Z(m>q0Ks9VtCNW3$ejkx{t+SPn^4%g(tJdpX_h}-iNUe}$NVUMlJUQ0gnhR2sh(n^K{?lE;~|y zo>;Am?T3yP9x|x(g2oBLSLd;TwXp-MTM zC+tirOj1gQDAq3<>MjR8G3}c;f{Pj+xF<_~P$yo9q5Gq?rGM>duj?|Y(h`-6!_hue zBfVoB4Ff!Lo__k)RwIrE<;h&oGygmENh}Dt6x;r6AE{c$*&Jh6*@<8E``S%Bi<`?A zilv{vuojJ>ZVP?6BM)!F3cZn-4{Mz`jfP=V8hUQn>#wgVbRnpT`^J~j)<&rnLeKrK zao@iRR!P~2s?Q*++f5<5abl6}ScQZV|I6s_(R=zZW*eTi4&J(6K|#}LoA-yy9KYIw z9&#Oy0#eMjpph1x-Olj%eIHae+pU6Jk#{O4A%4c%N|bE{U)(;!7%_X|7Clol!fSH% z*1W9t$;I*@K%T$!P!lX2(}$bOn?Xf#BNl8eM z+BTBGB1S3?waHYZ3;2AIPn$l;)S4=m!6YqKX3AVJRxW4l zthv|Au}qZtSZpbc_;VOq&QZ~P&+n4hAecDAkoVk97Q{4#mOD^V{Jz(3LVIpM&F($t zGc~k2-k_DwRgib58BYWXQdbitR<(;u&!tQzlAT4#SFmuLA;_@>rrq=VJ>Yn|*`RrT zdC2_P7mpAdq%6KWcSGO3x8j*_MoO!vjAgBUY4N=}(ck~gdqQ3ed@eijqq)jit~jjg zw$FK}@?H~YDXP9v{tbM+$;%S(Wv9qwJUHx>bJ|EbWNVyL_@Z>hnkIdI{kIi)A862o z4-^QJq3ft}-BaDRq8GQ#nR`1inN^iNEI?m;bBby@`MW1@U_!YqhDC4{9-GH_5VFvB zjLzfl4sOd*3^oyMV#u9T_Ap}~J{OwC!K5S%FB-e_XztIil^HWV!@1u`^gib+4hR+~ zSDSsVw_SvFUApf7wyme~L)&PRQ@f@G6^mC%IObRtI=24kF$;_$JU%&czB{pCe~?DsxQ^J( zVXmNwzDrubdIn?KX(QBpH&^)m$$AZr%irho3$`Dr*6%J&$=oiQ6YhQ&K~9BFnlijl z&0TYyrO{w}EoY`_i|JqOk71I(#A(giob7fSDqxsD@}@Nll4CVRW6LQ0w|NsmAnM%& z_Gr`N{0zTci&J&{)`^xKIoI7h?|l6uF-6>2GK?spYMid-|=%$H#V)4|PPT8}66slN{lv zq!d+y-MNF0*OxbZ#!&=|Kk{XRSw(X#=YQ0m8x~?CUQY)YVoa`yKQ_s?<+dNc6qJ0h z{7qIYKn z^8*g`_&!+K5sNf-o)wXgl6H=wQR~|RZd|Fh7_-En$?eM!q4DXCff#dscGha(SF2Hx z(t~xZNR9}!?T1UWG(PvLCd3HQ?7@*>yRT$Qm~>uVUR#}dQ6B?_dS0*3wvl;jTAyIvAJI*b_8J(1wGAi-syL!x{r3d81LCnDxBojuog#P|DMVy>p(O^?77LU zh!>FXdAQGGa8kw1Q?vr^TSP(-#!G= zsSYN!prP!XwQL1xK$qW|`bA3k@QMVzh!N{WU&h48jtEG+_P0rdE`yOKw_h>yS1ZEB zl*>I(xxJZsntiPMI;SM#8Z87I;|k8{oGPjE0{AUTqlhNu2;^auT);_m>l+`sWeI!_ z5z~%^Y2=KXjFt^AiWRA};|@eO6|VbZUc8@v41Ugc;E4Tpkh(Y9Wa76OkET}1A9zpt|WJMg~8YF4}vbtk9OyqHs^n;&}XG9Lb^XS2X|Lh1H5lzEGJZ&@M38A5%!i zB%|B4_ieK1kg;>S>s=n~9T_qK-GHLOoAyct=?Yv9+w5~+tEn2de0>Y1+CDs|^%A!o z9Wi@-5ClgILtTjtr=LONBF(tYsA|)tpY{e_89Cs*z}$#$1um7GtJM4r=JlVg4hUo= zuV2ejy2fK8a*xK{W`hXv-Jvgy=7aoB7R=5WXR#IOY~g24@Ya+U#?1rlB9R^52FIb{ zsaQMVx|PYzD9YtOS(VQD?hl*e#P8yagAw|}=*^k*#k}SCSR{|kZi46kbnoJS@X4+| zpJXt|4?~f*s1PJCCiBbIXYr1n@in;l7Q-W@?X$Ye$LuhL3hx5pQ1Y<=|uv`Y(Q^D-9NueR$rSI1j8& z{e@1$Fl|*@F_;;VSR=WqCK1=Nv_eh3s-OvxzQ&_j-goXV#Ba^b&4EWp0(P7=FGP@X z!kLSUYvsW}tcb^&MuvIy;QG(5GX{e?hI3m=o(Q@RL-tve9#>VwBsHB2I+|z7B%+ME zG=|O(tMAesazt!9MWRKT?UMQ9EtR1`!X~SA?I@gs_(ewOKKiXrDq$S#*{;YY`YjHU zUnGe*laNFCb$D@SL>dWrUSTD??zeE|5s$VH6GQVA?qxML(QBZ2oc6GWVpADoV%kVD zX&fCzuW~0Wqo_C{BG0Lp^QO$*(X5FCnnD+|UtsljsS~hA_IQ?^)6)>(ble~rjIko2 z=w#I^hQYK;XIY+CEtkra2l!g61DzIw=~UFuT+AwD50VAILH289g`m&xzQ8!~K!}7E zOCg*?fma7^GeAGIERLR&&~7V|V<&^Z&$SkXnPvcC*NYU}V%S?ac%>rH?YKuP*a+W6FxeXx167ji}D4 z7fbcdo#%A<+TJ?dTMNdBedF#dcEP02EpUq0A<0NtJK2iH(Kf!<>GBn2*Y=0p`a?ch zqIIUBhF*Nj&97-VwR?*r^DH0$4F}GI0*SIexVwiYN!Cpdvl6kAxe`5Gcnp6g;({Pw znRysay;WBt`YFAzkt+f(U^wtYfCp4X2zS0{bAsPWN78iexItS0Vx}1I1S|iE`-|QSqHb=y%hKm?xu*i_%b)1$BV^6kdMc%XfL_h&|jbnHk@yRoG^(tDP z?S)vM>ZQHW_ztgj+s_Z(VyXEKB9z&bL{KMY^3gp7uap$62vd0q#x@XlNJ9~rh`x^HFxV~j|cFf~M`tjwfqrA`a zA85l4j~KL~VG^;Boz?og-4XLIUtW>!;V~lE-mQ|{Y`hp?(5U0^IQ5Qk6-Q79_u*+M zt2+_{PYaNyv#GCqziwUb^z)0tMr?lS>&(#4Ud~l@O36U8riniWXGPSm4dAYKNQ8@j zi9XVdC7&x)N>wB{rO6|K`+)Hvw#nPL}7a~{UHKrnA4JS42EYP9-7EOW%|($Dvq6P%w*s|pI&RE zQGlqhjC@5NKjX6$5B%~$W8OkA+Dih$U30tj#ls0-{RxjgMF#~kDQY!O)F%xzXQB1N{$zr~T4X6ch7O^_*53$s|S zZ(|e46G_Bi6fZ0CxC)cRJvz0ZMRZ2U6 zQ%`nyBE??_bj8p*rQ67>vl}Aw#oo;tfT5Yo=v1fy9UKTnc$v)Fb+w!~m?`BtA3!&f zT!p+|^O;z)aybB-c|C&ovYtALP6vwbgjj~j9B~)Fz{lF)oCsA=+#At{n7Yv%1se@+ zFfge*ktk=8Q5+rIq>_6%^e06_UVGVmZ`k&VTz*DVz1_>AZ3aZjg(7}?3PWY%RioP~ zvbRE>-qVptypYGbCzN&p?Civ3m#t~_wy5B?1jGl6Ol2#0^PFHS{Fy}w51~Cnq^yn= z5=sYM7o9P-4h>qkHpZO%n$)#%7{B#kkLpx=#5gTQJ}B0Uik|KkwiX@O)oWW=r@l?eTJ>G^T-U3o@29dn-SX>-QJRB!05C zj%=`=-vVmvtsl6u+*$NmObuZi`0m8Nk10Is#o=nS$!kLct1S3@9_nFzh7+k{dn?r1 zdB9n~;>mOx;sf-W6)212Ly;jrG6$F$=D=;aJT8)ck_%<0ONxp^TS;h&>+tZ=7id#i zF%%(UPx=UuvNO@#Nqcqbz3AMiN(LRr;wao;Z;oK(spZxbg+CFdQ3f{o0_ikN-?ny# z2-A^FDHPwkJ7BJHv0^)W_GZxSj=&DAr&p2u2f&lO)cU_MT9F_+kjkCr7pN`j0(EQQ|M2|bQ(4Ej9TydKh3 zCyC&-jj6mOrvr*>%_PymgLkn26ljXdZVxX}01ml5 z(lFL96>?ff7I4uY4X`_Ja=0l*v8KT#-<2k@r%rF*k&##v%b)@L^jFr{_zbxJrxrLk zPfB8Fjy&4FO11CC%;`uq1syYH>*3gD|r*r z@!Hw&?d+rzDuKl}HPa)gng!-z%O#~Q7OU?A`EuN zU^!*`G;m;xDrDg_=DI)0&Yec5B5r{~`u)&1wos1|X+v(8T*Px1bu$acSvE@eVyLNR zr{0^tG8JMOT!caB8Ek|W;W9({!NL282Ih)u96O&ygL_eBd-0cDd23$|9!~j?iNag@ z;IWl?i4ovvcN!J$q4Da^=zH<#Ft(Kp#p``9oZFwG5#VH+ojO6q(=HB$qRkfRh(}nxu};mIY)BD$x%N zT&A12EbXh?KX2oevkiF%Zy|r&+k5we?B%$hPV}3>_x5F5@Zf-TzVtRm^kw8jh&Pup zML`eOXd!L%w8V&*KT>Z$FTSSWW@-D?yC1xIH;oUGV0_EYx{yxlQ zdF_uMXppL~>cC^DoF@vc-$CHR$cd>D!SN>tH#V0BCP}io;T$gbfo;K1uq|85i`KY`p%ozAWOvs#!|F&Sp??9KejWgL@Knvj zeKHORJ~6V5gRMxD$5grDdPKe3{LEb_)8VAIA3MIFlPdq5fDu#M?7HlVqlEW$KOy;H zK0>C1t`d5g5x)-`e)B{BgA1>3w)0XCYWsg`eM`mC@ewbrXFhwL%i6$Be8kRBjsT z;DnsgjllBpWB*@}@*#x?L=h(67GzH-CTE@a-|Nl{_`ehnI+GQNATjNwB{{{#SByU3YJUrcVU=Nc-|6gRiWmr~SxHT&9&>-C*~)$z_aCtxa0l}*q`;81-?AUSpzd{VrZrzdirCE#LkH1W|+ zGc952|M2t88o4M?lK6n5H*hyk!fOIL_!BQ`YY2!#2_>9!JYmV>|!)0Qig_kA=^Jq(S^sq z#)|;_NBx^O)>dTdCI5+tP)^Bp>ONs4uoF(ZxA*M)#X=suw*<=$1<*E^CsuHDOy(PayAS#Q(${q&(BNxEpkr>V5 zg#~ym^$E4#XrrdlE~KvygCip&2jscz=W1y9^X|EM92POz2A6 zii5Lme{*%b!q#RZ_l1=O{7hnqH%GkqoMU*9BkWIpbG~C$ODAjEss|8Y=v6EaYXC2= z8%Ry(SPD$n8X)6#MM|N-;((3PQ+61IOp5|&V;NuHmQdQKD(sq!Rl2IE?6tV&h3~C9 zRZ%M4rqQih!FOL6VLbo+v?y=vvRHNr3T2k;Xlp6t%c40n1<#Vm7t_#48ju%fYnLs| zThTnjwbiQBg(~C-kpU2od>yhkz!%DtGlA;Z_7=bASz)uS;{Fz30j>|z0Nz$A?}uXc ze}@ZA1ArrKu3%Lw#VP+Yggt-|_KaMOhzQ3RRu(5L;x@pi2+fJl2P*f4Il&bUI<4{! zY@if+l+tlM?p^^p7>B2|n3xzhv_h^AtN|@y3l3eb z8f*l)nkL^{_dbYglt}lxhgJ45ls+j%ZlU_k=VN8WHG4U41G)xs|2@$@>o_5c~xsmc#O4)99(Y@qqPZTA`_ z?_h_H0`Fc*bu|woNdz%V9;V}cL!gL+KC%1;bh%(2bkE5+;{tnN2re=X0nr1+9Rvqm z0}W*`0HUSOdiL(MVOz6`rh2Qkjt-@OfB+qaVv$_3+Mh!6*l|X2xxC@xUvV0p$h!;mhekM!pg zEkcWl>$TxX`P~%4xBzjE;Kv=~I}Jno?;fZ5Nd9~vNxN2-97c)_B(z^9d@7VJuvV{P zbB6ul_te+*5liMApr}@`n=~i4fp14IE-q%!Z)W%L^@TbBr)?BWEbo6%RaIqrUsJ=r z`}eQiBL2sh1E$e@doC*qBD}DJyoHQBR86L^t zfJW+7%Uy2!h8Pe^M(6*$EpKm$oRRpaml*JRoz-!|xs!6}T8b=&Q+B7n;sAhao`#nC zeN3KNWEs#}El@jbiFZYAyF0j-IEJUa%8*Pc_L%Py|p zZvY4Y=F}zk+*ae+cm$ISdMOS+m<2eQl38=@2^N*|A*?HYApj!>9Mr+>;&*rD4IaVx zNK%8p`25rRV22n~ME*UA0JD81yXB@J;tSDmmeI`lxX6VQClruHiRI*a+FScD3^lE2 z4I<{u2EYbp%4bY!*&L$(<2`&UWm%*wQxy4(yeU_dosumWrQ~F~7RO}_@)ow)dW?dp%5i00ku=mN$>&jc~*PIRbEe@a4ce0mRYt5il1@$IPe zGB*)d8S8Y|*;Eu6KYqIxtx@I&lrV`yxn9-cR5wE^>iJMXc=Yd=tF%f69T?ujtsov~ zeFrqM}MF zP7mHP&+Km2ofS4@eqsdR_?XY5RP%ZH`1`69P5c!fICk8g( z1UXz3=uD~0u9x9vr^|%`FI@Dtg^Mm18@5cSu&jsSCj(4?00#JdPZ+L zwk?SK7O-9VvFUSTe4W<09rfFMP#0jK{+_aG%^x)@C{KeVk^qAT)iM3gH#_=Zv9)m{ za0IG$uFlWJL4OR_Ax9&SnjqWwq2q6%8|mf?ywq-^erw90r7h=uxGZYFdxa(zF9ol)8nY5e2O1b zxj3AM5o|5nLCdvyKFk(55QmaO$n-Z1Dai*+9*Hz}j;;a9N!jpRc~f*rt~eg_r9KHU zML_1BzIuCmd)u|LLXmW*fwOfNYt($Yik{v67*(w*4CSDS&4UC)?M>y29F1HzX|wJY z-O>Lf2W}kppfdoD!*y3h<7@tXvNgbI1913cA@Vb&8mMG2)nJ$p9Ylm!0Yu(11!h}BEYp~X@&CzmcF z^c%aV(rT@{pFzoU;x*eS;CDz4sOJdzPDfncUjC)J-vh3;RIjN@w|{-?<8zi_tF7Mp z=NTK!&drV6KAy#|6~q_+mxN#o$vRNGU~!}w4`;#w7OypD`Utt^QbD8}azNKisW&r{ zy2dWEMO~7lLXBgmAw>D?gJEDk9tD2?M=q%~d>V$N6Je|QsOU`mhjj*mh=`g8}Np$%Whd2sC|KPV9`}<`o z-c^}zVZKH}+nys1fcfi$Bv6Uup?k^`ttwpGCb8~ ziGK%ADKKq>)c#thL9-%nvx8<*LP7$`F+GNi-xfk`@JigwVWq=>dgJs}tMn_)NGJjV z0?-zL0|hYh`Z~Zw@i^N=e&e`|CMeiWqb0!3jtRnWoJ;WAA;8HOfUI1$aRVg+3piK~ zL;Z~Zd9y<4PgPs!^X_P(<=dsxZ}Dw4A`9qQ<-R@y>Y?3UD~!Iia3VKZV4 zB1Uni%A*6?OT;EJH#WLW4lKa?7_>G>^=*o}#)_2T+nsF=!bRx$oNq^CzOT}6`3&rK zczMIqJBDp1P!s5ie6FO-eY5-0_jvO07%Rz93WUA=;dTI3-U&(l2Y?%@Y$FwGn+x9csAT!0QuP*6~3PY(p_5dn`dt%l6NSM6HU5oz2VnLH(0 z`IPBOda?X^-~{tgyDk6EtLQ_zVzYw}o#^#r7GG)kdNS6kP-D#C5>ExS{;sk8T}HF!3_tpOct2El z(mWp)02p8iXvt=BzS)0&&6b&d5TjEn`$p^tyqRDCygck0K@I#G<>NpCZ$aNSwPYiWot>R^0YxmeNi=f3exyRa+U;jsr^@a*(ZdFu zL?5W7vU{GHlj&I==DduA{`nCi0Qda8BDORll&JqhpYyCM9{=BmCPGHMq9q5hC0Do2 zOX6>2B`fmU3TUQ5iiw&>C!fMhoaS#DxY+Kk6(oGP*n$&H!lR_B=i#(O6_*PL5TjNS zhMpnA?klVF8OngW@?(*;mHi>>QT=3Z3Dw8z3EN1h18%ZV^pES_$=xj5J%UPuy<$UC zb`hTXXzmw$coz%NqJ$QeCR3Qr@njvQgLl(1|5M{ldw~-dDl+}gXs-2)C|fv+1fNM+ z4_u!|saO8L?04tBzhJJQ>k|1Pgm9tt_!$=8_FBgb_POAeBjhisF3zN_+A^oE7 zJu!i!kZ7P>@Py=#is{jJb3))tr25dow#Nl_UY;L2Z`tG8?rS9$ywNg&J;U;FJ%7C{ z;2ji!?w{vXKn{wTY!{OyU#gwkbeX3af}=?|0yM-|*OT?EZLOn!%Uk7V<$1O9si{?* zo}OYYb9aZJcLRJlZGDG>gTq|C6$Z%dY0Pj)^7$dAJ?ZW_9cHp8fZd!;6kYaZ(lbEH zJ>}#_TAb5|%|$Z6!y{_UDtjf3FPN1^7YXI7PZGeQd-WQYe^yX(3|12Ck*Mr^Z=W?! z0GG**YMz%@#c~J2@rr*?{{e@bVpuS7QH?V-UEDsB{lZ5=Uj!vdP*l}mHj;aPu8dr} z4FpQNGPXgdhAO}bV3&Ts5tigHzUPi6hGNgUYL%*p{@T{hL8g&?B~{^U@PSwoWm9a4 zu{Y7a2d_}^)!DkQfY%j*8H=s#f(m>EsO!UM>n8(m(}JXel$3L>NODoo#WgAfLpm(fZjO zzj2)pD8BqN8x!(&I383Uxuev8|B`YYF1NVVwK1j)^G5>%**$+{d^2nLZ?9{r-)7+C=) zaYYPIj>z!3bcUM0O`k*8U>?O-a={>#L{5K?G(=LuLo?bz=d!q0&e!8yFijn3n+wBWk-zly#U4xGkT6 zOe(eY7HP|NzgV<>YBM(QzjBx-+BFDvZw^F(gWWAs?!e4vtPR0FPv98^!W5FQCceJD zw3a3Fbl{b+*OW=#*iWE%L*+xI)d@fkZd&pk)kB>&b$qZf*Ryr||2$AH*Ya8^sQWDw zAqiC0#Sb|2@GvG2#KtMW0xhB5sh#Q?zm^Z2-mn^!Gag=ED0v|c>gfWWE_LrGH4u|> zish0SQ{TK#FAmvsPJIC?@~5GI+ec<(oJ|hi8s+)I1;;zX@d8^gUBa!!F*OATz_QvjWS6rH{@)o`6&(z?6kh4iNvUGu; zGBz8@_8{(MxDT(|s{)FL3GGfGS0;tIs!)x|m}vl&7Q2)PbPI5z;hrA}*t%<&xUe6e zt~66)51uO$RLV!0;cA#-ithaOsOGWh8rP*KNogVxSZ_Z(reoT_sdg6sn{t_4C$3r> z;^2`F>9QC~B5~qB`ClvmmY8BVcA2beMbfF<8(W}G3kqZG_H*pC-m8`hBA$TJ%rLIR z^xQSU8}5~1{CayVA(AL#7 z%@bQeWCw}RohX3#_fWUZka5dSN~-q8&JKMLv7VmZTYmbd2&WcwHFe1$W$`?HAX;ck z9Pr%&v=g_LylB7r?H;Cqt^J{1pp!W?Nj?iZZO4<$J5tKE_=BATV&1^pP#S6xJe zBp*ete~A+cIUp%fbi}!eqtB-997dFk=a|M6WQ0h+dvL;q{nqDAyJ*)NAe$vqYO+^v{+DsdA@2s@jBp|!*B0_#OW15fZfjW#(oRK^t9H~w~W`cGY5j0 zpZCVpojk@lo@Kj%^s>b0{7ZoHxE(D zYWYkj^=_`iL`WA}onh_|AjDc)T9nhx&COw?&{h>N2b!`g2e94|KuBniiajnm3}8zI zTd1i?H=ws6876E6{ty&Xg$}~VZI5C3eY|U1SezGRQ#gpIPNy31bAygd8k?2^TLV6$8ZUmWEwkusuVEZBfS%wrt^ z^MJT9e_lc;FoaJX8YLR&75!LKA1mn}r~P5=%+q`WP03;=I9rhe*#sdE2-mlvq@)WaM~VGXs_v<)jv z3#<&K9Wv4!7YG(XcRdJR%GfFJ`t8E8R3{x>hV(%gT%OX57qlegLSvdVq^t&Y14g0L zwcGEN_$enhN7B?irZg(FRhQ^&E1rNXUM>(mNrl>_^!059q;{_Scjw0eq?50sQ$P^7 zgan#g1*GX{y;+lqTHXrg_Y--Q$N~i4H-LB=k}eV2F>QA0-@VV<(R#*lmn!xv?Re5L zp=Q^es&9!sA%A(QKsceZ`+k`qYh;1a`-+rs&YztsCfF=5hk%vzdr0|gHBw%o>)<5e zgyRVXtgMCx?tW7R{P&*)Dh0YMBd1Ov4BHA4spE5^&D`eeTKE`$l3Sa>j_ch-4hiR% zhx5T&tw(TNX%9yZ)Fo*k1|wR!gW?la9#yWZ)TlAGUM zPPsohJ^0=1!`t$dhja*5PK?zE;@`1#f_^OsI3qDL20|VdFiHvx{rm=j`U)}e1T(p?D%^V?9wtSChe|3>%x`+6(+$3q%i z*e!Eml7GTkBD*v2AP%_sGJy9SEHJ{%-oVV&J>+8A0~LhDA(%JqSj{`(&0B+geNtsp zszaENj0=9Ar^`?{v1xyOt$J)o0(|VqNJ-(`Hx(tzZa>PycOO;LAfT5tJ$N zi>mho)OJ*7Z6Z+5HpiHH(gVN8Jo+wcy8`ZLwa9?8Fnpv&?!CByN_BZ`fwQbWlsY z!j7dEqQ1^}em4>LXZcBLJmkpyUZjaa{B8S>)3mX|o7)=JS4{<5NFBjEe?y`3 z-dnGE?9DZpvsBmE~z%H5CPt(jld_V+tj~zx4$J&k$ zjGEC5Dd-mAxBzoS+5PGW+yK>mo-3q4Zh5M7&aJ(8RPD|qBqW4NdUW@f^M}~4zQ*Jr zbTs?kA!ycU~jZD`I5aT9r| zEWP!M~|t=EGb^WM9)3$@_iCrFhS&6D9MYKsa{&2S;t0%!OQY)98oP*VZ$|l-r|c5_fON zobQ%dz(@>6sR|-9$5697<;YXBNT^~oacA+d2#AH4gfiC6W1Ehb^CM-OByM&Fv*>j& zfHRuEXcC2c=yFQu3kyy+|Fzi%c0?w)GxCe$#Pk61hV+#vf}mhj&N}jx5(`Ja^IJ~y z32{>`cllmFi-X*I?*16E?wQJ8%h~#=pOTPd3@dcLcOkAJir01u%g8O7+MoWf^3P6= zBWaN_dn8m%8@@5%zk3IK6z;rSxWo5LXm3PsxoXop!FcP`E}s-uZLEzJ(QK$jMaYHd z7%4A@#b@dmN%G*s6F({|#k)6ID)q7!aY(hOSRPfdd)I#NI`mVZr*px8yRv~iv)0<(dhNEd%L^r9`v84sV4R&n$mzh6naimRM zfD*(-Z^~iD>R}^cFbZx+u%=c62YZNQlVNxS6mM87#%wZ=8Zr0;tJ$<3)7mG6r6&S9 z+@p<41$7+}!FuHO+qVXa4#-SCGsb&zE0DuNQl8rCqm*!H5@xE)eI^orpg!-1$imSi z$54S!N?G9&rlzBFg9T29w|LA>=UDpR|8WJ1qKYeIyrous+?-F!bUFSb-mo`MN)TJ! zyH)N!S3t+h-ogSR(FCfR_p_9#7leVFMG>ZXcM!scQUbG_D)6YB;`a-U>*+@TQ7C6i zHb+P&0s&pB?GGm>k7PbikLX3i?_?~M_iaFa;MMF>4feWF0EVYpv*yq$0?Zqww~gYY zRGB8)`a&e+P&1GxX2?OrWghg@^;f6F`L_g14#8#&dD z9j8h3{Q@3y5SmUNCcWGNlN~i`V1zJCtL9gEN1QgVb2*>s5^3T1%sJ2Wa-?I*(+~)4 zU8TRHU3_fFp9ZL1H0gZ3SxDfAD1g^iyKLMGV47u%?2xh7X|$&0v>HpO0m2;=j49<8 zh*N1Fio^8^N+$%`cUZ+hg!yYCH%2B`z-LwFXOU*8B0D%w8IQ1IX$dgBys}a}pHlnS!b{DysJSP5K_i0^VmbL41li?JrQbM|&Da z|Ed&PJL58FLnwsWaI&Fn*}}nz-7=)YE|_?XTHXJnas>BT$KL$NS~y8P@*U@f;Hen?O;wL+wn7ZQ3gRx2d?{1-V2Xa@(uI0hSx4&Ld)hp6(#@E zOk4tbVhJ{_PVwI!8;r+=L&YSvP$Bw^i;D|(uSukM>Hfx*R~%7w_c-PaQHrgo901tZq)p<38M(vX{j9Sj_pGy2 zPB6a8Zuu%CHY)0iF4BaNKfPa(d{~ygFXCUNt?J?RnXvgOKurI0YYWqyJ{b_k( z?Rsc~XQeZqB@_^lLZ{te$_4m>Ot(h0l#t*^eCdKR$%zG9hCiPFJQ2wT)F7sLEuD{`l$V^R^ixI%v z?_s9ywc>JF-i5buQzQHfGn@N_RS&`=o{E!jrN(L|Q}nHp+WPu#fWC-h(R;JUjG)&A zS;v|P)82S94AW2Dh1pDfyL`LAQ=PAv$oST2|IKHRdwt5`p&AqJ0iC%(=k8l7t!$sv zx1*ZVWRpK4ua(dAIiMAxH3Jz8Y88b}s`Pml>5)8Vo5O59=@SK7!StyABWQGpg2xh4 zUlL;$6wM3!SxmJ_R6WikiC@|90O@7W6O}uufUk6$McaqJ#8Jdr_>GXt(^xYCWbyA! z2qqt_X|9e?`Zj9=G5wALFte@OuChi=-v1)sIck$GR!HmpQE9Y?Sn$#^{LgzJmUf6i z1G@CmBXG}`>NDgl#XcAy-H=f^Eru|q8+h9`0=t?-idHo|tZ9)aBq1iD|JFca4ek!T z?q3o>V2qHvN^z}^vFv;6e#zbFc(SUOlhD@-ea<@=0s_}cdOj}pM&R~j5`lQyJRZUV znRNMwUKqUts#e6fZOSOT6^3wwjU(OTzsX>Sx4vhknBp={;YJMh`zt8P zCR6orV~al2LUfL#DBk&;UXu#i7(|h>)bDF}*hNWZ*=##M&#zV!cv8L(1m~8#ulxhLfQLrSu9^yFS1)&o2j1D(7pXO9>ERYT>lUghQZ)eJ{u8+xS@{wtNqsLfe}x zQG7k+p-)CFLaB0@{#)YrJ}tZVE&Fsi4i8p+jG|WFp1y&Rbl$Cg8uBhm0LqfG?Qadg z$NTV8^|l(@2cAITA;#@9_swARO`NO#%O7&M418%sl)iNBlX0()deY3 z5TQ056?3Q8Z*hHT=oj!Ae#_0K+6WG4ash6keQjTx8CS#M1iY_(NMtK+-Np8${6!7v zr^oI0&YNA-l+7wFA0Hx+ELwffbpa*13OD)|i*{ed=Mm&nxg}pP zNKdbS!I8dP2-M8@7uh;})c0GyRJT3`$t>bMfv>|%F^od%RTr8!zdf?x>$5FD+gCsD zsNv@7Ob#`YJj&WprZ5|iQDo38_Q`kK8B0_?97ph;DJA2;cy6PjV9SgEd1p~8f#!H} z=w*3P?ni-!s{guqK)3Jn_hYKnCR0?oWCpaq9a$z0mZf&;njS(lGaBqORTPyd$_XUT zeA}v{Qn>fnc8&JJui9+Vd8%mJY=A5)>ukDO-5OoUJMHa7()NC-Cx^+t_2c7Mpl3!2 zfWIW8RvGG)&j$7jYo=)R7|U9d7r*VSBQrMoO0yesBwSI)R zYEzj1zwiO}H@%b!?W}RKXIkyBFBiDg2@nDNssO>QikkMptPE=>E7;Ub{FVo9t|aP@KJXg9k~i<(;<%CHm6b@}?EeyWnsG!6IF4Xx_T8bh zzjX`wNPz<~M)|XImC%6aS^?v~*B@d3P|dXYT;gw(c&rbco~ItZB_&&csuLdmLHB0& z%EyVxX^Q~Bz}JgHMI?(IzIs8z!9hW}00R8_{ma;K$R-uI_aQG63J@;4fP!SOmO@`t z+G;%~;cwd+Jme6^rDhbZ<6V_3g7NHJWi9H(`xU$b*K)NGKuXja8(S5bL$3)-BMg44 z+O?wIPi?$Z@2fzlai8|X=M=3t|8n6&&KqjA8|MtT^MX2$BDD%caUO&Z z^2Z1Die;nMsqP2ecHjOA0o-bgBa_AwVOXsjWaU?kG>;=!`XO~&jC8h5`b4Ua)k|fkM<~hH3r8#WQN+E(~kP)pk2#U!pzZ_ z?Wb6e1Frl5ZGIp2_fkT<@21BQ5q-oF?WP2v@iXV$@0LTf)Lz=js`s??@VIj->u_zg zJ;G1o;K92yqML~#7#<(ke}D3u%HqsyNzFe@FVoA*t^2gy3a#!NS-^rysj&&raFRFt zYA{^%(pIC~BCaKwFPtIZPpvD40K%4de$VL-y3z*_XetcUsKhZ zOp}@!?4mv=Co*P!q8&&N9)2@eSK`J(BBNTcVe#pV#_QiT8GZMZ>1>q&if|f5H_n3% zqekf`KmyUxKR}yvLr#^LDLp}%Ki&V0x;c=hm4ecH;d6fi!&7Ax?`xt#t6b*ZtEj-^ z7({Kh&0JGI_1L5pAAjt0eyds7C?AOSGOa`B_Ot-e<9b!dWqT}=Mz%vgyzDPfceQKt zc?868%STHTgN+&J%inK@h<%Y=1i(-XHDrbKM$#-l$BXXdrAAj&AfG?3GS-Xy^XW*k zIBMn5KjSS=a>ZZ*FG-c*_o#%JA~cuGZzQ}0(qDiuczHmZVVi0s!rb=_Of{M(7o0Cp zp?t{xVEaPp-$!bz-+sN0)jKSIUiB(gW$KtWMpq`usLp6_lw^BPN{9^BZBHg=aAs^D zwTG%rYA_n9O}TOV87v}Pj^9pW`Z`L;#uo|T&?`x(s9-iat~k7=3nAYWA~-(L!QBZ{zp z6hg+gi(k*$p(O9twkt`Ry`NaI>0~}Rchj3zKG}{K0T8O;53vFS#fkG+p*o*^u{lpP za^4p^-DBM?5vaG9CqXNH(9}2HD4bR!XvZAtDz*9++>XZ~Mt@to+HK^|$vd#Lo;o0M zQ)-Rxs3dg?_Hcey>rulL4W;`Rvwg|8++1ZPoIZ9B%+oShI$U4>%&1vrygQMHkg=eR z6aM%-lO|=>m4HE|Q+pUplVV4K86qw))*LHLf)4SbN{PYJ82i9Bz5@e4D=0X5&Ba!Z z9%vWkz70{ik1bly6vE>(XN4BfixpOc>moqkk7;<^dF06jmtA)k@Pl9>w9!DNJgN|9xCy=YJnJNPPMrC6f*ma)&aqBk%_8R1O$*aImlfz|0p@ zAXsnxyDV9Bmi@v!Usw@DD!*#Yq{Wp-Z)7@m!5&7%%(bDa%%px1)}n{OW@mxXV+_DH zCwWsII5WB+o91$OtEo|`2Sb0Al?=OeaHBH)9vF9>dZ#qDm?I&0=R?m>hxbK6Y3wcu z0u|7|TBbAid)MBp46iLfjXT0zHgV8C6AZ~U5y|<1`3+4j3X4eS9Dg*vNM+{QS{=5? zW@X0kfA;CWPoW)52lK?t_DAr}Qc76K(uv`lqRtOI9We*r} zRqJ!(LL1VbDkDM-b}2fH`3`=FcvwhSN*RnG;el<`fTbPSWKJiN->DSaI@7H2T0$8y zWQXH#I`}dn{rgrZw#w&<8@AoJwwUkMYXY1Z zbap8ejtJbiccpbwBQ5sxoM$zYFu@Mw;^A3qw{qt1PHW8uG#)1j_&es|3h z`V=v0$?tE*QlX5TRGeDzRU)EJYRcyP?~F`mX5IGX-=?}vo2eN=LgBI!+4MAjHoKm* z7-Fd0@=IFcYsM`Av5amjUKk!m1=y~4a@tXWkadMmb#!9`%y!@-EV2j+Xu({otWTB6 zBFJi$e61T+{c3eqqad_c)6PRexF8Q&A?E3yPJ0?~Dc<#(kr=Hw&3;3!*XY=lKR+DL zDJh3`|6MqNPBFs2?{?q@;gXE%ZYnC9ofPz20N6qiRG_cJ`8!&oPlF(=-@A&)#d- z>T`S(xwE@i9yl_B6>CnV+? z`uONi6V6c5t)%6W_JY|iHiM#1eu|7|gIy5tcJY+H#ERV`j~|DK>nUL1*x_K*htn6Z z{uLD>3%cuAPEEV8T1^`C)7VL1{w~uDY^JpZioJBvdw0DOHYv?zdP%~klrZx2B06S! z^re)3L&QwN#tyMy!W?!@FE&H1qw2m!_c!9&W5S^S#R6PCxkGFYe%y;ZT@RW)cPV-6 zwj|m-P8)86fYPuD1EByn^cag>l;#z zTc8H#Fys?UipbaIFy=3tgNX&+C5C@;Ij{Mtx}{{Yg_b(ZSGA|iBEZ_VnTJoWqn{XT z#_IFd=b9}@IXUX8Pq8QZXVvv>4z%RLBBhGW1ZDsD3?uG)vVW=PIi;SaCOO)8K4%_{ zWDClqr2zJ7|CYIG3;PyGM8Bf|tQ-Tdpx@bO)gDg_8h#!;-`8}d zNTVhx*uFSuKHKQ$qKr)zS&3zfb~yi3*bCLMSXK87zL0Aq8(+`^I7I}{WYF%ThI+^BDlq@fE5)6>9wz{#!P_=imB z={rPB4Yz&q><(x)%%R^?ygS@+KRnF%;V(l&NJ7R83sv`_*5q) zTVfKV4WfY;$?71YV+eU6pNsne_Z?nXQL>25XU7Qa*F(gLCI2~T1B=n$Cktwm`ae9i zmM=8EslATuEQqYYBGGGhq684Q!kR&V*bu#9yqyAbw~)bTG|mB^%pgdT40uj>iD_pl zgB{xQ#BA`Ki09{gBz=byMf*j>h7V$v^88i#(~>_i@m-({^1O8S~PM=GRHS>VUQV;McVwP{`ok})}STOD3wkV z5`Bq*EKB-z<||6CE>$MPa4}fT-Mk-FY0fWkfiG22Q5C2hy_c67L$YnThj3IHFo=M!;r-p%dP=NgDOR3!k?;uU&a=^UJa`lCX zhwRV&|4Fvyc)E|4{DUgs{~9lzkngUPU-B4n6;<4vtWjgrX}D3pQ*68W`1e(=>DEqdxDMo_e@O+q9BQ!dt8q zHo`zU^z!l&uH*{jb|?7Wa-Qy;u!8hP?88|e`-O1q;B#unDto?Yp6%RPAylVFwYT_6 zk0jwP_n%R{XY-7gGdWm2A7;o%d7bec(DgB!{~_tRk$m!c+hmtN&e&ZlWo!Yf&iu+Obyp2_GGb4Sn=;Oo!%4%yNY$f7G!L8 zLSScz&}iu+#6(g=9+HsYX#KhHY-;)dD4t-(jV}C-Q3taA|TO0Zr z?QwR%%WBvWQ&$v`@m^0ZvLE+Vej?QGQM8UnQE{h^P`Hj>twhcwLPeo2BoFvLx5xXN zldG$gE;_(%C*E*(b{1{-x|{&Tyy)XIcyF@AC@ar>8)8R5(BL=Vuu_1y}1*2vJkb(aE zQ?mx+`RI%!T0zNJe?_mK zOwNp9-|WLbwg<_cTcC#uG-oJO#*3)vULHn+#5dQ48pG9L3Gy_e69f9kgAbk!PMZCK zb9M;XLjK{F=yt|k6NWPBG_@lkHy<`}_1j#?z_jdSZ^bWtFF6L&qxs#;CJ!vm9?~_3 zy6l|XC8Yd5$=3@zUEaRu{;EX=_r0lGJ11CM*q;hecWE}V>RrjGR{TYV`@V5l8uRo- z60ps9{CFajXmXfQczIUQu|q>h!cTt6d%fTtV?NgaFdGZLNc<1mJ-56dE64IeKkuu8 z>tEHT5$?m-3s2}pS?~Ncb&}qQl!5<5-PA6;iAy(b@bZTz&gPS0!>y4*_IFq|qaRY` zbRRhynxq?w+*K_`m%L*O3$dbu=%e<-TcJ$Ww_3yN9S$-&)Nh16PK+}JJh8zH;qc_( zUF8oKyQSV*XLp^>d<7(V+!TcNd4VxqFLXk=WA4^Fc`k2 zc-)^S=XWFP(O5}t_USaTJl$lRdLhW)T%Zx&wJU7PcqHt@Y%$u&F?Diss(!6R%(#K| zbk|!xn|k3+vB_*eacRJqZ%~hr`u4+X(#aChr>gfVO`6ILAIoE_4i^jK!f!`(TFD=z z72{7M6q08IL)P~56g_VCq5A0`dl$n45N~iBG zuWSB@+8=x$5kIB>hpw*xs&f0@7DT0`1f;t`>6QlRkUCNlhfYbAl#YXRcOxL(jdV&# zNw-oG((&Kt#!v6e_suX4bFZHFynC;`_FB(+*0VZi9u21xx1N%PhqDqJYA=S1T*+re zaj%$itDa2cdKib1F6bS#D&SuPWI|zW@F|oziplt(a{3{z9{??*UhDE9lb#cOwyHgbLBryHiknp*8(6^~?@T=DAm!RPXY7mQc$3lP=g| z*B*W={j?)-Xd>&dD~+_lrt`tU%UNcEqu|A6$IrvB#Qb&#;^!u&L4-vYneHc1&J1c4 zyc{|5)SPafj1ctNy*Xc($%O+ZU=|eVLCBSf?3ESODJi=+$5C~ ziEH;)&O_rlFA-cc-$L~`S*(J14u zHW=M(@d>{>P}7TpZn+^1s78A@xJ(f}UR7%?F&}r-E>8D7*~3^?Z{+?&y5OffQz?pv zYx26-KXLVb|A>@AMV{fe7PY-Xnx*#|$xl5msQUIV&5BBKP05SH=#|q4tdm|t<+S&B z#aO9$1B%Z<@N3OC2Zlg{4wn5u2DvyEM)`CwkN(iZ?;*-Gjt{vBZ2Ib&z7+fQ4cV~2 zNP9DV=})%9Yz=k@cOkC6h*!{Qq}{>IJTZ+z4AKEEP3NX^`p@sH57yW;$*R9$)&>dF z%ck6UJf0&OscWGE9JQYAtMXa{?E7y*lik(RHkY5M%iX$6a}*-c8P#Z_h52@N)F?|lEOX?|=x=AgS~yo#NXMLU z6+iur5bl?>`)B@#V5(kk@ABG}iws`ece;&-_~+4(?W zw$gLH3}!g*MQNiioNaUCxZ^RcMO$=d)`bo#_?AtUP$5xk5o|C4+efC9Nq+VhH~hFw zL|Hpq?;z2FGWd`N+6r?&bR1fcQbWTvCXo%RoMsuWUKWMu(wQ$}*Ii9&^fOb&XN9`1 z2ar}YDF_)qaF$pcW;NE;8YCypPgskjT&c(LMC*&9Q#}%L+ClHW3wZuCpcq@> zi9rjC{}AYc8?AFN=H39FVik;vt7ydldAbzhXg`tFgGd@#9B{SDF2gQ@7VU#XIu=3# zwA^DPK5w>BP*1jTPr(Z1W1_<1&Ig_q>-;+uk(>V^XxqQp51DZ z(YX1=VZv^lSb2Cq%ELnPzMoz@({ziG0HOG9LvKVf2}(1Lm8DGTCr?2tif*<2yu4z3@R#aR#SygHB zW!I{ebktX-7kP9uDU5RE`^l7B z&=|{C$fez)zx3{H*e^#46OEFMd56;pFUvlt~-u@znQ2R+WWPOE>FJKON#m?{!HK2E{ zItn@*?np7}^RQjXoETV)I+tBFL~wHwlyv3r4`9{3joV?T=735*AsW@9^-whnBcH>y z@hW<9SsS##8=8k6zwc!El`vK3_O|wvNhK?Dr@~pMeApEcu!Td7zIsYb-~8G-Iu+?n z6%HNzfmM-f8LhN6U+&Mc86xW$Bph5<%bHF{OgH7UPX|?vQ+S*sI^FEaCU>i@Zc03) zU4>u!!7e(Hb#Wl6MC=m!W}>hy*6r#zk%d4$g%2C^rcvbtVzKC&L(;gt#O^#o6zNZ$ zGx-s+8o?UsJNVH;w>D|cRpCGYpYi9=rWBV#xW#+|pTAzcVU?TYXM@of(k2wp!3d=g ze#&N}OA=(&gvV8GJ@u*l z2|3Q=S5(<~FK*d6ipSN;vqFghNL`*_uOiGYdsXZA8 zFy3}4%35u>U90TTBu%3}rt%95k}#PLYI(9UnVCo08eSY^S1Ri zqLAuh8;?1Gfb;?uRf`&&F9z$^=A4o@{fYdB#v};by-Bg0JsEF7&)9b5oy{ly13TD{ z$gyQ;wI0rtN(;@;UehH5A)%iHKc))&qPSo7bCf?`z5fwpMTpqq&%5+?ypEz6pC?ki z0XIb_vs_QsGb&=nJZC*CEm&MMp>eTWCx&`jc78u`Qs=>el>qf^g=MB26II9xV5po~_MoI7-6X~+u%SvOZfI$4r&Ur!%$TA|;1IDE+v z)2^|8oWyGvj)L1VH{2D7WF6~0)K7E{yV*=%cXptf=P~T?I}{-UB6^`f&TDzm>()O# zog9=t=(}KN(Y$v0I@c))9*Y2G7eT!L_qh~BWXB1Tom3#_yaScPkG(DVb-gRUs7&Yi zyycMt`O1Bo(K|dpa6LH@Wus}t=mMPx4sDlNdlE)_c8ci z4vtZJA7d)km>NLPGx|z1=5Aq{Yh+|l-6d9ig<0G-@|&p11-5Q}^;I(AH*|~Gyf{)G zooDYJl2IG%?GVWiA~iBk*->iMuv8Sw@5q`=1zA6&B$b?u_!u8pr+#Fw~1ij!avp8ocmGb$8w2@1<>3!4SrNkNcA(J~WZgnkUTy}4ArL7bnT*E_*k z|LY*;frEIgnk{X(GhO~XnTJ)tY0Ep3T1Nc13ft=ut*ZF!M5%#+=QAGLxdMFNtXde; zDjlT4q~_wBeWnG3%K=Gf0POqgY^I<{(pz=1Di6oX71_y!9OaOJy~e_#)hgn>pP`(O zZwi%!7;9gFN+l3}e)_8Ij-S7OA90o>Iq|4l0*KM55R&7$SH3uI45B!2&z)|#00dBN z7LQ5&xg2pMgqm!0TsqdK(zpk+x@wshXZ4yHe4J2CN+SH)20zENSgFOMu1ewb2)S^K zbq)mv^h|(5=>{0y*XWO)!#KQ>B$)_sk3=H1Ry72Kb*U+OE^TAMw2H-_m$eI;e*k4ln&&{#*dsH=FVVfl}P2@wi$VTn8W2Ayx zvfQ7y#UZOqb{GKOO%) zhW)f)4dyBhO}eSUFCsdWMtgJhzMvtzTObiQ;0owKKwmWdb}NG!1p*p;y;j9gDw%U& zXL*!4u;}O)VVt{*tp=>NVBEsJgCS`ydVJ$^a~Tj!2`agV{<9~8VxT5LGEtvbkD@ZU z<%$UQKAug_{>KC(=yj)?>|1E@U?#?_wHUuI{O)AJ4nE)guSac)ou8dOx1jzMhdU-c z9=q_Z#>O{2Jw1jOG^T5X5(6C zN78f4RD+2lEwcOT0Nb@CZ<*&5)Z&r_U)v`9^;&K3!8&SxF=SWwg+GZjcS|{%NrMUC zowQ2PLDnf?-n!@sOG}H| zbk6fg@qB*1AS4za@G96!vV;bdHl2?a#b<+F)7zwjX7-{kSe>36t*vB#I;%(wca8hS zoZ#Q9H3l|>;o6TdogHpIsXu_tn4FJ;(bOu1YPogFKb5bwv`USDZiB!`yAMr< z6R5;U3sI`#)8;6G|Cn19Y$dS_v{VbahQKMCSdn)3t*j2L=$=$cxddfm3Iv=o8t_lz zoL+`~RRL?TqNH}5k4;bsxH2?*zOBTgIY5_lKnI8b<(%rKc>h&I=3%7(8Yx zplG1uc$MdAK&?TmCo3>8yG1h4%+A}J0r;a&n{S#tBs@9DW3S(|NFz#vLu|}dRj%ChsvVKh#;+KAOnUJ(9q^fR474}Ew@a|v zNa_`E3;k8HoV)wC6;uPyR6ZHK-eLsz0rQ&@RX%l2-*Gfc^-JdOkS-h^9Qf2h;U!Sb zQ+X>=d;6eREZ|vJ#XK*LWl@O_WZZGV`81i^x)gFhQ(?6Q6UDRfd54FGFO+O*4#2H1 zG2$=#mvjD?$#M4n5!@NN7a$-Yn9nybf=*ZbT-*^&khh}V_`Is?|t zNTe0eOC*k`NZ5^#JTG^7qe*HCm>5(t?$9YDyo&l&hm1lP4Iae)z1v|AI3VC~Y$E_d zZ#tCZkV1Jf1z_hA{NFB=*oo9wK^kI={xK!`AOD69lE?0+B>bUJ;0c1Sn_KQShu=eGg$w1uDlGS4)kTOZAtdabi&X52r?_TbQ#3}+p#>Nq(+VT-lEubApM<3mw zWJ^anK(nN@h6_bFAfSPqR~`Iy)MxeO#yxTtYyq@?Aq*X0t5 z%<}5kwW{Kd8{^oO;!w&L*s#W3!d44@UeKAP|Xj+$plhgdF3JqFYRDIoUuIgXT?SPxfbQakG)W}J* zKM{|w0b6VzmipHgnZY}~G+dF_1lF?AbNA7;MdzdWEP{NTG`Pg^-h88UGmkFHr3w0^ zEZEb&PljyJ6%Q@g2#vmqzAh?J4K(15`(`#tD?3f2qe3}1@TgW(q?COR}p93 zAB|vwS58V=`XdOYyR8R-YfW(C=l$2x;a9DQCy7lWu=Ez;+8AfZ)wq9qGy29fP~5|Xvz8QS*sl)>J)@@*RyMchF&?X6V$sO^{oQMg97!! zsIXFSazer)#Uk5I!Ivst;&iw=b6~XT`20Dy%3`jrywCL!2}v;sBe~=?m|`g$$5SllZWan0{eserC&o_3T~ zgttC;%yCD4ar;U)1EmcJS?F>>X!6E$fc8^AZmnFf2=K9*p~)cF_<J*UdS z)ir*syS=@g#i!-nsS>M=%g!`qF6;~__7QEmfom=-?Czg$^Std95-76)!U51gV7FTk z@+~pm36|VX0<>Lk!tca|}Ku*?2Tm-z4 zaWO656O=9BI;8FV`qM;pGwDGfR}{fR^{snu*@f;rG17#M0M5HCdz1oL#M!ys|bi=80;lt zn^;g42x+6?Zh+|7`2(Zd<#F?iqDnkoXG_heTQ5_>{&OmyFX7L+;%)?3GZimT(hjApnDoM>@!Z|~_3HO8Km zdxNArQ-J;YuN8n_Lg`f+tAkRU#4#0U%!e-YOq+t*$72PzSa)>qfpxnF{pxpU?X>H8bMi!YR@l7cvb5g%_PV(Q#-0Xt1jn5`R{3%}8h zUn!QC06j}tkeb%xj^%;5g3>yZgkb&3v_9K;4b`D^WcMh4eas7$d&E7P#>f7jO=5tF zp8Z1Ri?a(a*>+dSEY4OOAS!=z!1)1-2V5rrA*~n-4?WOk2PcX7neGc4o4){%pl3Yd zvoQ>+9ZT}WI+KzZXX;zD&fSVpoq*MtXWu?|e~|#t%Klh21X^tK>Eb7zjC$z4x7N3c z+BFG~Y{W7Uv7wXjVF7ZL1Q17xb)p$ARz{;z#W(TT2pM|4>=p#EGXDIVU>}peFHPGG~GKox><+|y0 zdmRW|5#w?Jp)Ur=8p?enc-HZyWMi;+R!%?+B1vr|A+!<2t!li8Z!bEZqMhUSF$wou zu98I%>+AnGZk(sYKF0LJ*-Zoche>7Jng?49c=DLn*1#?X=aA0x%I)oLwC_Jb z;ooUW8wnEAg!u=aq3uk^OS(}uyX{17CI+AoSm6pgdmQ-i--O|{?Hl8m2p-^MqZhw` zP~Iskiw1)0e0Rj4DQe0a&BAf%rv-#=ed9-%05{WCl`&a*hToChZe;`sA9Ht>u=QpcDN)z#7^Zy-!B*lPMn}XzeEPS>~8^5~XF!v{y--5!3 zfn%*&;57KJ-5KM!owBLvj|;yw*E$dFo+dM$beEU;n*9PfxfoJObds!o1{B@5M`E9#BcA8r46OLS9zsh=XG zQHntxZ{ohii3RbyBO$kCOcN;+14FM{U}vID9JpJD$ePc2Tfn#>#=ij(_y~^f3>FA@ ziu%tzEO35;jn2QW(AC7eI7-K({?i?l@gOo!+V<4RqB;C%V=7_m1DV|o?w1yicby-| z$pP>(d4j#{IS6?1-GdL>)+qvcI>2d!=3cd&_n{X?w~xUZka zV*eyLf4_?~HI~CBf?SMMc(r_!N=bzafj2;5+(~{Dx}^m8Sb``a)zLBxl07SxsjdfQqWYY=vZKM&{t-IuCZdeAx& zy6ojV`Ib6{n?1Y1c{|RUOUPwMyUKi2+$zsK5(y3fd>#qRLI$9$tcBy&7fMDO5Rp)? zR+>U^f88Myaz_;zO_&zJG8@*98<>*a zF7VtA(#!AbA9;A9hyU?LqWnl7zwU;0V-$gwEK>(e&`lv|LM){oM0RZ{@h7UY{F+QnBpUP zK8qD70#YD65v~D)R45%*I^mi+cc! zGc1Brt|tn8K@VP+O$MeNIiKT$BHs>`25rn3hKR>~Q8Z(Q_?YYue0cX4R-L9v{rnb0 zIX4j*41_8L(EEuTQ;?^^IDHB*0#0{C!Xx#MC~Q@Uc*>|PHJ=b~o)_Ev<u$rr{SUxC;?)zXrby31hLkKBrZX$C7i zXGwHAI>gcW`_1QpK;Bt!PJHeUSuPl|AXuO zok|h(nUW9RZfu^&Ug`wcFthC z6h;xbdn%c~L>$p?>T1Y%VXje05wf8q12KMirK_lgSgtoOJo(NihNro)8U)#W(Feq_ zAxFDGm)hIpH0z3IFl0s>$w|eo*COBF;*rSwu|BUTk-#ng)NM@x>>ds%yG=4%{)IW~ z)?w-E>#I%k@e$VatR>J=GHB2|I5br*)v+hZJ)sTSC7{ok& z`T6+^(HKX!cXeA>pFB;Gvjy>A9eFHrs}p5r9Z) z*!C<)Jhn3>Y_T7A)s$Fmqv#aHZU1zl_@bgQEun|>l$I%S_&nO3ptUNy$z?aGiP91b z1F?4;FSU^Q{7Y0TvbYD(j zXke+kKqkMmww800BTTn1K7wz3p1~>V|L_=69$z87Y}Wa+1?P**WB~=4$Q!XZY5&DK z>e36_xiX@2OEFQdd|Y0Xpc|e)ZmDX*A+0|X83ifPxhST$e6}xzXO`sECJ8aWU!5N< z!|zr_Fp0q_DWO7|-Ws110Lw<_h9^hiu^9>sL z!2oRSFlF~;uwvOLAS|GS!b0*!iZ#FeTo(Hw&8%CSY&&F#>FA zFzY^u`6nD^T*^Q@&U=70l;)HrHor>6<4J4&HqB#B>e{-$)CV3T)|<*4+Mv#)ga3fk zZ0+fvhH8Uyd~L-6v>f55b<*W|%3^kLFeeA>E_}2QF($9Y7!t^E^Se*8TSOta^t$+` z98g#nY2xmEYZgd0717(h5EdA!u$NSvbUkmOMPu2ox$_$DyWlQHg_3^FRdXqP@q?c; z@K5x~T^Xp$&TnzQiem8s%E11kcfhsvU>5+{xn&h4)e~Cls9H*%YcQx_CdO?yfP&F(u4RFNHVL=q!wB?`%Ya$gAqt-&(1f~t6v6HNHZ(oU*dol zBum}BXUha$Q1IQ20EA4V)rB_E;`3{=>t~Meyg)J7zlk4yCxB;ac@F;+=zSM zYWJVM2FjxzadL*7IbIKvjckjD7Q*XFhwD&Uu`}^`9}Qfa6w~rQ`JEJKllu6}^BU&u zzx3PDw~T5A3rT*IA?AxkL=*zDHmy~o7;YkL$T1pd$MA5kdDO&j0t>O9Uf(ACz8(r( zYYqUan$m3Ac~@+o`1u!c+EP(37Rl!VpZ;{^V@lHR@QEe44RjOPvuuXn@(hdCbL268 z1B8Vkv+ntMQZSl{V}Py(VA@=phMzRx%~xsL-HG1(P#Dv6TWTP1njkLBsVaO~uAXw* zj=+wK%&VWFV4YeQ(T8Wmuhy^iyIxS+FF^mkqYVS@ihByt1EhV-^OsDI zf^fPH2Z(be(}`81hXQ}UmUUuVXQ4cH)i!dCU4p3^=-kQsObV)r{;(}$YNCfSr=aGy zCp1_NOoG3_Q85*n0btA+pkGRMfrysFCcw=l0#pOvBMI!ne2wVK90qKi3)OAn4*}B0 z(xnKLFoXW^lhz^Ly^^2Q8>yAZb%PPlUne>3gMPR!7)XCJ!03;P<+AMTY+c~9XW{a$ znxAx0`iaKV0t>aWi`lsyKIL;Fa(E0Xcg%)UKso2yA;C$ipD21|!w69QKZ3cc79%&S9OKf+_adP$D&ImpY6i-Q zkcHgNkUR}8zoqcMgP49pezU5Z%Qf>G)ArWDAv`ncskQ#930&u~BR1IA0#P=P+TjBt zm zO>d6wgL>I?i-%wwxqE0DD^ubVhELY;N}F`oKpzHZQZRv8juCssYXmDnSm{YT*AeCy+LQkH!pNpI_$AdO*ZmY+IuUObFitj9AIdz#a;~ zrIn+Rf^8)ya#^T_kqHwmAIQ&y71w)g3n--{i>2OIRD27vVVRXln0?qOX@GCt)yu?h4;gvhLK^EWBg#hRr?&wWd zv3|Rxrw@I?g{7$>6*NB+zbpzNxa-AMbXT1LGDhgH?J0S&BM?5@;g>=x=};%gOgJm( z&RT~EIjf$$#|%t7#d!^7b{n#H@(tIbdHMG z-5bmqDQG8F-%UdP#QIpr=OMXBMv}aq8z%9GF30?pjbB!0-?j&;4+ut5+YLMfjrPVA zw`_z>^mSeuM z_acyj2BL0r-<&$hn{UNI3-(%yKJ~@w?D|vnkD9n%uoR?AuJ0zgRK^<%so&fP&M}v@ zI+nPd5e^Ahs5Z$?Pt$v2Xo=PGV?EGee#rIO3igJRj>_}uETP`K84uTH-qI-M)Ova*UrhOfDIvdM9-iRt{Pt4k zI=x!2LOK`frOSg?%RhGQ2UFoYDE8szbD7aH3!`!8oVc}<%@pB_jbhQ%09*5y`6O!J zX0nZIZ?HPdhpP_w-X2hjE0anzE?QuFV4pFVJJlIeBZD4h$TJ#sHI|MbvZ%T{c3 zg|>C(sBl&0OD>Grly$-T8}DcKwGlS$rV|m9zPP*Vp=MIsnDeTQVz`6J&#(cI)Ps7f zm%t5Wp?ilBjhJujsvJf#f!oSs<1;M$U}b1q%YM)}Fn8P6-tCqxXosjh)3Q*gKr@?+ zsIk_6AKflTe&2gEdZV+Byj;cu)Q&y29ExR8w0(q@=J`-(Ol2Ye=N3ZgyG z*gpnRHz*aFoiXLUPMC7ER^oO|;wzo9_Vg=sAFon~^FIm8be3$pog6cgc(M65y4uP@ z^yxkw|H}oS&KV$YzMtu2_(0(&gdtaMzMu9>#WlJ4TyaSZw|G=ckvi#(ReXD;j9~Qy zHb<^x-&nzp?gN-rT>EguKyQ+8{FT&4ET+%RdDI$~f{a#5`fozk7}bnMhDo=+j_M6# z1JRJ)=u6lAUJtY3I8yo#q;dPK2WX<-D`M^WcZA0BXv-k^#`5l73WLPQ3IP>9?fbo ziDrSkJ|EG1@=L1ZzM|3GhhD_7O@I~!lJz9Tcysp=A?$(V4U~8$G!MMmnj3j|8I{>i zSbYG#`WFU;{BIm3ss20S27T!-%t|`DSsSsN-qiF>g93Ly_2c&38G{TM_oaHoz@AYD>r!b!lu7U%qZJ~ienhU=x0_#|tAeS^okuMAHGA0 zSNlwXgtBXJBzM5LJ%#bi?zY};1NSn_LS*Qh%jCIrr)WP>^G}B|MilMjV%2g%&%^g1 z$ZvI!kxTBz_?U>pJQWhq=3n-+G*`_hD9pW-E%r5wzIW5_)C_3WD5arD6w0x}fmb}{ zsHv@Oi$(zE*5sgHE`S>+HvDe7q;>%ek@|-jfb~V|Mncw zQj3Ky`HU@9pa@p7HS(FP`Atn%>u$fSxQ5!F6B5saWqN z%`RsAuC5fPO3LS`!|LRFT5hg0%}fdpK7xiG+|85qpy zl#NvUiGRZrZnidJQXOW9;LUwv|<|E*?Gu`2uV zVw1e-ERgF~l_SoN@>dLwx9Sq5Seu4`%4!sZ_xtz^h${})`sGajFi|{24NKQfJD635 zPX1yTN9(6(fM&=k)jELI%*ZHHz)4a25+nljAS>T;fY#>G%5K*#(-=0b$5h79?QU+4 z7t+0ilzIWM)R0Our3{ViALdhq1aIG9_Vhd?Us7kdtKaPIGrCX-H6Q{-%Aym!1Nle= z!l%|kvraoc*Nt~a3pFIHXFP}=?#&0QPVS)2g@`o^n^=p-NqXRq9JQw{?Vg#Pyv~t> z25Q2J2AEqksG#+?N_e;5Lo*;P_Hii^CL3^C1O9Mt>sv~#1;iidM6tz>k4AK37*nvX z1H&Y;O>LIAn_36ii1^&a!!A|1nJ0IT6Cv5myy2X85v=05nR1?0YW67*pXOBq0s266 zi$T$3d1)C6H`m@NwL;MthB$*%hiFRSk)U+K|AjrDu?Trgd4>(pduD0%0}{V@SE@`B zVws}9m~ZtmNR=|Svn!3`0=(LDLqAFrn0Ys|t@+#IpU*g;!vQGc`2ESrC%dSk4?jGq zP%#NoclbmtAHs8wG@h3)cqcmdD1Wv0{N14ot&NG|jkwfk^P&o)-&bI^Gx#!T=kRT?90aC%ybL2=AV)J(j`d}Wx4}DjoS|(v>*cVMBZtd%6x9 z4}d!kTg%26Q0}HtOww*dIm7>*eYwj}n7bk;-QL6lDzszXamXs5vo=xB)H~+0IKC`5 z^2g%>u1XLHvSDq%4~XDKGgXcgw(Mk;ql%X1`lcZal-5k@KbRx25FJ1BJQhWbKtjRk zWl6a_rFv>OOO=`tL>zCsfE?fKu(MNj*_GeB_2%*f*5J#s$?^GRFi>4FR9**o1UOS_^bR*4)#xKtvxkfsAeFY4ls0kE`$AqPct@sg#^E30 z8%jebeb0?jKyjiIg}{J^9ziFDn`uGEb?0;MK}%V!GC-U9Z`C?dWZJ8ZDd5oPna8f3 zh=Hm}yHA}cKvCf?7bg2d1f4i;rj^Rg z%RYtV3uh+qr!|CR(2-DAgW3nwW}r2&-i9~FXNiM#*oW}y3{lVFy&)vFVwbTioJ9%* zW*U`(8CB-FN3|egEHm}Eb3-Qh0HjrtE0V!@Xnqyar`gzvoF7?;M&qSp_)%n|`HyPX zxf~#31`yo%>a$PZL18)}jbCdb@(w7C+S@I(d}erJ;HIp@1nOTmq)s&bhIv%>Ovh18 zsB6lK2wvjGB!)gK)!g?wqGP(>1-1Lq>Jq{feW zdKDwu9wNM1 zZgcZT?Cek&Rk)9sIbgQZxyYf#*>*lJeN*sqM%Hw8tuI!CxY%6=0qL374NER;$6=M6 zCK;zlE_bCTG~XLJmH-h7I~?}Iehlx9IC$)M59cYZk0ZgS_VOk{%zfRkbW*g$*A}T$ zS;fI*^FR^Yq!2!9?JI-}%r+fQtgN}q2%0URiTgmtaHD?4WCCcSe7IiCS0-HNen{Oj z@)=9{VWLGeP{0|wdmdnfEaY_~Cr5m+*|t1>NMx@{2M5)S&hP6+CHBeAY z*^cyfK&j)}33*%1l%-sY->ui{UHM}2ihKi%ikfIPhtmdWVdg~E{Q!-MsZwmkhr+%m zI!ciOBQ$@wH~R}Yj7a36Powx#>x>6Nvvrmt33f~YZJ@Mb&^Z)9;kOv1Vm7DFavE)9 z#HB?6GE%A$=OH+8H02o7;tAv0wor~7jyw6!N>faxgJD9%Pz-oIgVEv!(71uo0bxLx z!n2F-j8=p1=S|=!6*@P;SUjkn&Y|orc+?w2f96Q!c~xb0LckprGVmO z>9DHZ5K(XD7xWaF`|Ithmzk$_*~Qr@!i7|QQyUjrHOWp-bCT(8{8!O`#Q1Q zaGIalD2;NOE~`c7V)EZC+|^P=h_QROZo4R0G^Ypk07HQgtsgt8q7yIqh&OS(bWK1d zgp0*YUOeb4PCov=18~}!iF^QmB9Kc4{3Fved{4HG0ZC5N8uVVX9MCE2M010w)T+Gb znz8&EpLAy!($Vzja*Id(lh(t4eWz4boIhu@I=)2?`=w8j3`z%+YNoR^%5mzqvi!af zls|wt5Z-X)C>u}Kg*Ed*VdW@}p0t2Upt@4{lny6|*k|D`{c=~RR)UDJ_S}7@H5;7> zZZNGY4#KrElFVy20pS9R{GylfN(7V@yGVn@?q(IUGbkyUDgf{%AoCsQ(g$zb3azyk zo%@EX?zk;&g>Ta zJ$>_+j(uXEM^Yt9WmSNxIlPz4*>bupGX}_|PiY?Wt4=apxE*7H!j_$1N}D=ZXmt6D zrAW>Slmk$!TGLqkWu?WngP1a8jkM4b8gp#}0IPCpAU$|rcaG_oRr5#F(7rEdz_%wc zY*r$HZyska7Z!<>MgMc{JK7t?)8angH4K%w3+?P;kX3-r48OX0*|`lG8d%+YA3QCT z=cAoB&M6*EC6!4^07ulpyHuZ?0$#TqWaYGx!y7V7@#iaoz~MQ`liGuCSV5edY+jFe z*$VW#glh2#QNj7neEynDo(ecM+59eTS-=S_5yX(#2>Z@%sID9;ZOmE$pN^X<^`hKJ ziqRYpcugG4Kq%lKgP-pW>JNUQPmzKCpAP&e(b>k?**rV?}_3D!z)T<*4bY-h?BZ*_P z0zC_?mF7z6&sguldUN{HMOwSk(EbADHGTf(%re583J#RTObo+__CujoHL`}|jaH7U zPx>DXiZ4whmH}$ejStWmVo&11$yH;+cYHwz0KjKFx)Xz7uLj-k=%yh#QP`jVP~?lV z3eOm-RIPDhCpA@>!~&=m7;~nvxTRj8Ldj_UvdTP@rA$D2+^XN!$+^_~>|o_P-`zmQ z*fuarjotC9XXhm-Ihp0&@2h(*3g?_UrTZJxKk4=4S?1mA9V>w6OSTT5OkV$m(J2OB z^B_^WeqsTjcQJ%Sfh@EJ4crm(A^Q+`!=~ zSsM9Nm%X{dmeIb^(NU&hvFc#MmcTDS8e=+l1*25cx$I6_vs;$m(6T|HRk@NQU`+>XvKo^ z4Wk9`Eio|#9p$fAw@u;Z zPWRIw-s9vdcgKwLUAw@Qa0d0osjcyXcU?o@pBGUDV|fG*9HD`rFFpYciaf`<(_wJy zK~9&C79~NsQY&EjM|b zN;+-~F3$XNB*a?kJuhrt;`dmd)GPAcup&-4K`dt(s4(L361+eLw&PEN^qB$y14$_G z0!(`e)E2PI`C6{_zIdk9tF^(f%p8w}=)P8wY2)>y5&d_5&|5u8Tr-)IPv!5uRwYZ5 zoW=6Ld^8oq8%hPXfI2)uR|CSwV&jDhtrMlS;-@c@*fqUh^;|I0FDw69EGN z^snMSd39B-C77wwoGon-hz2O|AQEQy&P9lZBB}gpJKSSy>>Y^`sctaWNnr_QbiE0@ z!^{L9b_VZkaQ^&iG(O-VmirFfNlJq+(K>1eWr+Sg|VsnlV7>+ zQMF=_aTJ{ceGn16sjJ+8hqL!VIGdau5f$~yDow8@xlQkAK3bv=7tM=wKl)L|a zBE%T4I7NLKY#W}ZDEi0-O4Hk4_ruqdjaL#D%+*^zY8*bTF6Q^Vs%w}i1W<(9*hG=m z2-D1u#=^U1d#{{T2;~R{d~oh@P(z|5FO>QY=%{{f%)d*)Z1e@%SmqnLcL1iSS*idr z&XQQ-xPbGSKcutEw7$8-q;B3Y9IJv>a9P^lVs`6>J2Iz;e%Zr1>-(LqwtK@08LjYc zC||irgSJfgSB*hJm(Gx=jeH)<0mk?3o0aj$@$XyG`Z_kV3Rf4wnS$VCzo zy7~X42&wC)pl_l5|0qJBtKrO|92wYKzerwa{3qkJvp0ONxzs@jY&*Q@&Tu;sMx1#Y zr}y(47ER?JIbx|l@Y@|d?f7!Q$B91-H~fa=L(5$I>hO4-uiVRDV}B|EC{vst{ZPvX zUsYaq9LTp6ZCDf!NqL_6$@8W!Ev!ztUEXAu$1OL##d)5@fWVQb7=AS~PT|mTHaaW~ z$)-2K?SMR2_l5veW6CXlnE>JJF}_d+6HVh@B8T~! z-YovN#{~kRaN;!T3_CbGN8sPFKk@qXi57edRx!q{>T`LXeud;8v8jOlVN3n%iRzcQ z$07JgfI;`Z`bG>a5wb&Lg4~>XsoKlXQ3HMU_+nYT433kF%Z~ErbIA+_tq+-91@iT-V(EB>|8 z!tkKn$>O0PwSkAULifQq!PEIl0{oKMAO(vT%iAWwFp}5a<*Jhj71rpp_mTRwZtu-h zn}H+a_cU1WnwS`E_ei5ZxN>#M0?)qi+AVx6 zi&RS9OC_?%SFE$&Q9x$b4xL+?^JjiW%ImuKOf>hf%SoL{rskM@=nG((%rvl?PkB5Y zwly$n_%Yvni&Z}Us6F<&D1yS)+HGIJdna*x`KUMj@w51a&-AO)g^mgQKa@?_UXsqw za&zTAeIZ*Delw%?e zga?x&9ntwCqa%)}aZ03F>6d1wV(6qIxL%5ccOJ)HIG)jjC0-D$bcXnBI5THDjb1Tm zR`U<*HN6kX4c*#wH@N(eBDudD9ldcdx~^eG zkP?(`5Dp;S-QA_Mv~-Ddmk5I7p*uwS2-02B-6ka#0((x`-*86UFEN)Bf!SXpQgHvHGP9^@k;PaO~ zwcDdb<_11VjOb|EHeZx~o!e;l_k*S@&C=R~#ET?hINcrN)p|#IScOt{$r9dpFoQyMirUhCwgR!dc@R(^L2j7{E9_)#dm$ zU3NynjRzj6eZq2NtjbN=#s1f$Ul-(t-sSoeU+Alf$^o9IRaHSb|JHBjpa3=-qaP`}g9|(JV zbCN3sTtpCabDDeIZDu_Bdo#Oi2EhLZ=O`kb@V5J)S22}p2ENMf4P5lF1pP;Ih_cfQ zO`a25kt*!(I**84K^IT6n_aud>GJacREXTCc>{!mB6u5{{^!<7Ljy@=RTKFh z(1omPH2?RK2ur`7|9SI{C?WQkU$!T5ZR#isNSQc_c@Mvi=c#Or6SCP5{|v#%ZT&F7 zdboHUEfXf;c}lPqR*7#q(r!vP+njOFVUR1W4NDQmUM3ifEc<&Ks?ishZE{Az?z3u_ zz(HkOYS95BCmkx98D#J*YJTaf9ADWoEIg7l z@xa&*B(z5Ry%3crm$|OE;D0IiH;E+|tRN(vg5hRi$D0FRCDPkQa>&EoSX=?&TqDFO zq4cKxmf8|%0q&nf)2Ai2xziBm$ZW(~E%k~heh8wn1s2)au@*r4E3iq89`tu(z;fP; z^8@w=WN;+8t8Jx-(*hQjnOVsF&r^QJ>IquQ>C<`ZIDx5~MVt_ofcE-`wqn;`J~DYH z8^f?w+P}X4<1A&aS$S&4fmtMd9aHHXwU$>w77YKXMkFf5%NK@_*Iq$1CE zB9-CWC%q!7t5YSYB2{W;#&Z6$V}y8^TFhZM>^QaZ8AOdGLK}?Mpjs8M2 zX`BUXd$<32A!2Na;_~a5W?{&UOJ}+I*4fBc*~pJv^l?{V4u?5wy@nM$!-x7`%#3`) z+z*#1#W%4D7i&4c-Q+1u3}1RL5#sh{;Pt3vNiOKHJFfgGQtc;xFjYg2&KSQQNMKi1 zaM=+?fQp8%PdHBg@MYbPxJrhl)Vdf1xW)pUa+<49i>2-M+wPZ&Zu1AL-{RCSs1O$K z2_q*gSxpb(TPPc%=UQ&*b^rbugJcJp43P`H7xXJSrho( z+J7akTWL0AQFTH1HG{k2lgIeV!QsC2adV|i1Cv?0Y^g|VwbXt3@>iGr8V?Vf@O$0e z(kCu<-4CuF9r~T2s3W(6PuA$r~K0q~x7JOoc&em$-%HVg(S{xys5zbG_UzsPH zKIBLk;Fm6BFLKVjUpn80L637l58T}m zh)ig}zW4JhD0k~~!XWOn8q;DHW z3(^L?H|)Bc?tKEJd|u<0$RoekEMtnSxXA`~IDaZ$AnZ7)wnUA(s0@ zz!U1>6jrB@n)~ej&#Zo9^g4FE)9({*@Jjsga&plLgF&069#0kB1eDh~-jqhe7>phW zs1*pGizd<$8vET}TwOl=s<&5h!`;13IT(k&FH4`B$dwBuZHN)HtZ_jh;eqi#NO0O< zvtd2H+H%|!npzplqc6VISdfAWzS3BRx9*q`G2p6wzj&fcn9gP*u|?Y52*|1d6(P?9 z>A^Bj{;EWY=5$lqAwcYUaqz@<%6&WbO43EtZ>|9m0b*-r8R=q=I~b>V5j<$nfT?}{ zeH`<7&#%BwF}K*vt(TYw$CU@T^4dSJdG5JYk_Nlwjc|SaY>|izpm&TX26MU)Qwb^# z9#+z_8y&R!Nkl+rRRf=Cjcb-0uRb!6V#*NY;Gm9`{`95u5b67MtsAzH(?kmj9X?_Nz%<&~bh5OwWCXJY&w( zYZpZ`=ZkVRj*Jbdny}9R@piuTo84Dj-|r^8{rRQNrh*+tc!$6Uz76XZL=?(t>)$0%6GipyYwq_%!B1@X;b^ zs$vv@?%$IE77_FyxWPC&!B&Rt(H=`~gy=>=Q30r_wBuAEdx@2h$nZHC}&|L+>Q5W6SEaS;ICrT=>h~OSZM=*eDS&B98Y@Ygp614tVF0teZlp zIItn6VyLTK=W_;Yd^!Tc0D^!C>aQ>7U$>YI(rFD^3G}ZSs8|1LYs3QLY@X2Bdg zDLPqda8^Z)7=I|%Sjz%i!3aR$4p+mqR_W9UWO;QWxS9KlCTp*D~ z->AYUQ@3O>=^r#t<}fAVuv7|OoeMnot(~Lwr&T~W0HN{P0ou{67(n4racKv9|4i?D z|C#cqvKZ3K`hDG> z)tqYnx>ZZ}o9Yd>$QcivUYkiQ^@;>I)mc6b<$eVIF|?O^u%n@7tbY~QNDc0mld#&rH(4g021hLG=wDBm+`Q2O6+{Q zCkQR(L;ckc+3$uhlLcB{6>D4`Msj5|c)yz~W@fN+G9NL1LZt*nl*np>u35U?S|277 zUGhxu=J;omsOU8NrA6^G>s4!RC^f$|heCEgyBocpuFDY<8lMJetet`1Uusod)6BQ^ zRO7!*Ex>*k*-vx2%+M2wGlAE0@+=4*`N~lehA5(5CUQG{xEYolZSdr#R=v(sB{k$s z%rO}-WU$+rrdu1o^dLmlfr>#nhK@{&J|>cMv^Zag(!M)>9@9zCWCjKPZGRX-4Q!49{;K%0wvcDg^bbaPMQnp!_-Ianmt0t*Cv z8)!!hFU7Gxz?;(*7_Tc!qyaq23Ww+L?m2~UZtm-zs4PvORam{)R1Se6e*s@+vmHy~ zLtg0ULadh?AC6jufhA{~ZN%s8rTmMX4Lzm|zbCv8zGmeN9Axe|p-FrU{ZmoVC|IJm zGJLW=RNU)Bw#c<3-P&QRje>hGG9FI1ohig24%9A8&!X@+y113Bo#eE(?$E6wdUqCEy=jWXj!_p6v;@Z$=v=bx;MR6K%nY-Zt;DU9s$sy0pWO@H>ku)b!pMr7P zv83a{6qH=d81R--UiX=3OYKSb5=Uq!*2>&xcm-Mx;xcTrk;cnUSIsDuiVBT@V~+wO&vX}m;ozb zwqkEnF}0%Ghuhh*b9|Gra#K>svJm)A1~PyV?#vEUxjnu9-JvWwY^F7PB3+;*JYOApRD& zo%aO4p{ACauU41<3ljNx10(kLbO2K8D2z= zIexWWc$MQ}2+2P-RC30LY05kQ>9r1zn@-+5)8JaQUVu8ogh2;%{~1D z*t4>c(nX08l~O07(6K?(xJg_m%zxf_)$q6sTaG;3EEi5hn9HRJ)T5;mCnz>hTl5nr z8E;Zjul#56{r8!lJB?S-%v-B}6T{pGE+b4(urCB0!mY&AO=J;TRb&<`cSxe1%VEDa_e4;*Ti8jo`X7NMkmvj*+IVDmHAljS;*L+Kqu@sorh8Gn@qH z%r;>nul@H=-`lCRoCHL$@}V2P@+)xT!ArB`j{qv9?>8%c34-t9pB5dPiw&RZOfo2x z@me#2@?ho8XZvZ5mFAH#P3{j+7V<=49z#>17Z5MpT7*rMc)er2^CQ(rv4q7=oIkOgbmEZex=rx|sFOb^dlx;Aj_(@}wLUOmG_R{GK(atTun_j`Xj* z5ZSNtygEs6o5y919jI&P-~dC?f!rR2C?Pq`$JbAuM#IRnyZT%I{dI5*M9s~oSWn&i@{OSVH>9@$_MkhB&26?lF_1|rqdWYql2o5Yd3%LaE*_paZ=zl+ zLzFZD9(4fvYqc#pQp|qY6{XAHE-dJm#oF$A*kZS&8B}t75_S?4#gE4lvuJVD?;Bec#NnrA#p=`P}4giw`o_)QkNtHCvbB##Qm_!ChtvkMQnt!T+VRarX zn08>%iLB>{ub4vA_|c}t|H>qcX1mpo@?Ga%_#CfpJRlA^0Um`8lJebKb1YsJrKBG0 zctCLaC=s4T6Bq+tP*i@&rFJARx%!V%WG`RTIi1mZon;l4)h4izTv0eTMZnDk`Kpbn zOCi9GA2N5jXgcwP{i`g-88trw-cG2!XIqaH%Zs%w$22mT(c91SHx?WqU;SW9dnm0dT zQ8ucQ3Nnye2Lfe&>N|$O?Hw?I4YBOTao`!*JsOdwkFy{%e}j!d^d z<~YJegh8-X=Ks0Lf@#9n<3y`KK@=Zjic|7tGoCv~Ir-w%<5u{Zk^1kNxq69=nN^y> zqr9Uz>dRAl&FhqiOwx%6CIcmcq89P7J7B)nn$DO^+8zX=nWN{H$ubsHuA{_HKu*UlDT3Xgu5gB{Io3WK?BHGn9GPuFIWDra)p}UNCIy@%#p@EQyKvtAR(y3 z!w~5dJFIVmbps-4x_`Bbepvtd+Q59m^ClLk#fqPrI^sQc?<4MG<+_;tfY`688q+*{ zHHs3y_vM&W5ZSwS_=7+MIzibr)3ZcgMR@|{eVe>=zoGHZ2LdM?F({yuO1~ zIOAXl@u@pf30q{~^}M^r`}sNAIKhSM`2$3aN}Xftdla5OhU~r2vHj{$Zm|Qphfp(dT2h!C9EQ+y9c1R4=9tyBSbot zeuC31M0iwDfLo&_&*^^f@9F^7vVk+nLCs$C{m4%|>FM$VO8HZq=Fe#?mw5GwTIRh2MAgR}Zk;{6zVL zPJ-#_ywQ^^5AhYS-DJ%Smsjsu>zjC0s8&NY&-I}Dw@9t|nT=*i__3iWTl)lhUtIoC z-#+LDdUz+)Pw;wW?84n{xf)}8{9BL1ej}yt{6lx=dXp!*<=R}OWua~!=38$2a9`vL zP)GjJN;fK5>>r>b?>T@E~f0Iz{3It>gubuLC*=tyKZj%7AI7_`?-jSZB7%p zEUZv6#+uBDTvgtM24D4h1%n3H)3zkkmd?PAn=x-=)n=pi+u+e=b=J;^-wXcrzr7J{ z4)51`^;Ki>WdnCXiT4OabBUR8ABeoNnvK<{Ek4Jdzd7?|CZV)Hc} zFuVFbIQf2;e~7^Bmg8)>a24Bh9V#ayNy1%K0#$J?K^!j}BPiRg>i^q63*`W1av+KI zb++02Z}+s!Z@I0*haT)Y*SB%XUC-R`9wqF?%YHGVAFc93_erXKd4fL@cwJ3QY1*Ll zN4SvSV4?YYg~h})M&U0Qt(V&s4!!!fpJfKWa=bR)TFrgKXc<1mYq_LCOPzLzdJ6u` zX3|Q;vu~JWS+vZklG28|G{kD`Yp!k({-xz-UK!QX&fjFO9M5lwxa@QZ;$&3XHyD$~ z=5n7{D5rh~eSmYEqm9ZdX4_(spytN~5gEZA&SO4Y|HzLniax-0LbeM?Cg5+Gv@*Sw}8^DECj;#E3z; z{gx<$x5{B_;VOeR6lOK^Rk&p+9`8xWSr;#T>+5z7vvsj&6r70rdah!{Wv$}1qJEN# z#AjnQp5DTok_{1bhINSDO60+J$QSQAPQHhdGYeGU^?vf=CiyyfVb11uLMP;Ri}JUC z8S~WnZ~1d_VMj#o^8=Z5g1*r|weg`Z*qKi790KO26v1eG5f?DMDV2-~?o_v6lH5S+ zs*20k$w?P)_>3nCh&^4!9Iqho^UukZFzq=!RDNbb{o`F^twNd(`&Yn#$V@M_KI4Tj zb}Ip0t06*^Fi(X?o#D%iSwwe4o45;^N&B}?dfYO!a;UT$(u+oCOdnx)KfEy?+SL3N z!zAxCsKD2RvM+<4Ie48zC1`r-^`3Q_P^ZcX0+ zN`RiAfe4N5ZL~O3iT!YME==ZJY*a#u-5E_*c=+qLWIVT9A%`;;Hkc`hW>7g0z=K5ga|&ui%4L#5 zno}N{Re|zXR>^x&g`vTqa)9CKLQ6#lASWRT{6Zv(g`KDLf|`)SZ;jiO zYMOO%@2@ZxPF@RZNiN@6>dYG`M7weL`wM0p7tqjK@8RZN@>w0vzgQWx6>E6OIiaX(3m+8wS?mR~SXh;v{E<2T?fQ#)#`z2YuV(rMZ zeVQ+I?1wZyS0<^=%N9~WThfn;-A!-Ilp?0kXF#Z2#P)7MZC~FDxT5xFNg2_eLjk+h z;B^sAQYg!By$UOOrBo4e#?7)RQFj-rFj$JffMRgUgYEumq+AAra!h8>b6=fA&gaBq z6uO)iVuzW^uUk`)wOG%k@=uFIybghm)fzccu7?UK52u8w|NiKHRyXuXRT~B{K~a;+ zH)a56Q$9nIFFdJn*#91TRcXnpG5hQ|Jq%94vHcvPB_HVtH|hw$zI2FIR{ew;6n#*R z3XZ+>a_14ugjb*4(?^B5#`|JLW_XiD{P35WJa=WMpOFabT;%mG5!K_f8ij&a7<9%m z%6;Z!ITBREJij|aF65Cds5PE1U%(-={&S{JU1B{r!my8KD;R@ddSs;5?pMToWQoaP zqNGTM$hdeMoyj{OKzIf^B};XNLRXr7(fuAO(FLmZVdJ^JNj0;zXQEde=9|7|w{IVZ^`gP2J@!yK$lAH&dRA75%Cn zZRES-{C65-o$mDeiGG#O;~Ec#p9@9k+|e^-hQHTS;(F76>+SzU-JYtlhrkS55nku| zM1ce+N2~hH5vd?SW%G6RyLzg_MZe7jO$IBK^p?VpG6L3bs1&GzVTZ^tzR-<^}qg2^Ej@KQqx-iwgWU|^nivCCPcrLukMdEWD7N|D`s zPpS9g%CNA&O67=1$EaVXpIO91?DYXIR*Lh*l7U%Ymf;$7kOS+H@?r~-HTqk>w4jNfTA2McNn)e+( z#|x*Folf`C8j{h}EDe3pm(H5OBAO`7=Z|^R1_bfPmKT0thd3l#N^UexjDiY#e4ubm zofi9qf>rJ@?L-!I9Ru4w891c7lr%g&BMhye8OV9~A(AX&S=^t>I8$0U8{0&a>1dc+ z{mWt||BfL>!VB-3QgqlzprjU+LWI ze$_5XuPXZ%fPbdF;e7pHsI$8VpgTvX<-~yif!RsRrIHEF9?v(vx6@LD!cE6!liMEl z%eQmL&|At@qQv+Q*zIeQ+=}G3LL;_%RT3FQHG2+x8(rwjOmTb5Ib{Uo)~{RScXU0M#Yk&5D zx5{qeY3<>HL`px+hy8BuNbY@JYj*2NF3_Y4=?s)`%OU=mtlEC*mk$nB*t(Ehp_7^t zlRKFm2_w(6i9eKU%ig~3V#kUX{e`HR0{7Goy4TVI9+(I1^Id5!q>64Ed?#cJmURbn z&veFr8Jr+z_COUxL;XqCtcF5)uyAjpwpwJ!W?u|j6Bfro@wmNJ0- z`7EvGpsOYW8Dx7xaoZF3%X%&8jxA&dz+LGx1E(wmZmRo+n@}+To^XE9Nof0Ktq7=F zptK7|;9@J0eii3gfPh^PLB!imfk0w8^E=l=OoZ6gQ@V=P`Lhza6U{dU$v5S@%Zy1_ z^l!dhB+mAuOeK^&>?Et7n9;jz+kYr47|GljUjkhTcl4r3lNN5qTM5oaZdu0?%1a2x zO#NIC|J(=Ngc5TXM;TwWe#B|*eWpuA%KH9RERVrbzsW~DFUqC0*FCRMrXfberBA{F z%Xpc9Ijq)UX>~e7uUDNbZR9e+M>Y{Jyf>C+^bLWfJ}}Xi9{!o)DjRjkXgB*qE|Hqj zUTeSpzg&P81yUoVNPova5taKc&-;l5HPh;e|7k%|+(sw@luw&+p_h+waAJhfsQ^wU zga1MiPWe21cd!oMxh$S14DsLp#Ak3(tO?q+u|3NYQESXy zYPxdJj$FH5{o8xVVua6>#*6#=id915G#O-^C={(q2>&v#Za)fwJE{v37;zy81gL-2 z#OB6;HUKS~%f0Xxpq2iK{N3ETyTMoK?7@Py{XpsXVd$OVaFj_S81tp*_bN z-SKYIUcZ&nRO`a=@Lp2L>sDhK8y_@?il;v&!yhKLa(+vxm{mb*c6(`$jluw+@@(w2 ztwjldA~DZ;7N(&p{ez@AStx?CO_4f{tFx3)Cfw@hqpTP_>zfV8*PPFNdsp1vh}tTR zK=Ja!#-Qs$qa#vYG0o-6EZ_$MGy=$Vz88-7PpbGi78L)}R}#4DdLF8%@7|tdtfc+Ae-&d%4;NhWUeVI~6X#sdruyjy!j42Csy*nG=d@QRds62Z~^Lw%>x;*Q~)e1?`0^v-t1jqddx zGA^tBPx=d<9c5C8TBM(17z$PgF}Kn{r?jqV${P->I5_GfpR-2}dfP2#J=#2c`NMaH z@^pt6%l%MzbgXck<^%^5eku}1wZ*3loHDDOJf-tAIOz*|ZvPjb&ePWwWIp94b6V7) z5BFA4lG8pZZ0y4sqCre4mHc^rG>o{?yB7Ou4N|(ki*CWh=H;$Km_El>1S<8dSPmye zSagtXyUk=EHPILDelG)pC<|CBhG{;m++-}}L>6_>;D?r={dk@{0K$kS3aHuPigz|d zU|J$nZq{Xi$6fDiHkqt7TpyKuj5GHR(PrL`)#GsX%W=mm+XK*WH9&TG86?e`@pm~w zA<;x1;j!Y>?hLRCt@C@o^pzhT@$0vG8Z7Hf&X~UZUm(J@OdijW|MYPYPC-l09KCI2gp%~d(SnGCo6YkYac{0w&ph&woo>Xj zgWXC>6n9V?Wr(EuC+M)PR;#Ogx_9#GO}<>7sqz%#j6~&A=4#sltDMzB{T7C9W%9_` z^0jQ;JN)Y_g^iMIw`#9YJkCV4uO%~OmvWF2;at){CtqoLTm6yrSM#8(7ume)kh%vt zsHrnN-Fb=tAlwP0&dSa2(=2H<%*BnAXyo!BGqgkyxv}oYl`x9d@>83&MpVFN)jmU> zEHzX$@4pJ)QY+LD*}D)aM%egs458C3xLHRHWB_ z;OSN(4kOQaP@{K#cgQbw&s5>I1~RlK8GZ){%cg24WZOq6Z06}v61vB$DDk@`3jbNk zOWwkJp6KrmKI#$*dgAhwUdq-tdEPvw=b*jMhVlEJ@k52he#n&7Og(qhzJPt7EEJ+v%F1XSxtsD=${P+o zy5A|s37bb+D|Crrh#8MnL<$fCqeP$ms=h>;?~lK}LjjH$TGU55cU&!htA3%xud|?k zdf1yL5KSogWG~q4>OKfUZr9~OaOP4u9Fu0nb8pzjiy!QHj@C$fcU`TtKLKzM4gj1b zs;?7#4&2u^U14u)5zcIQe98c~(b3|L8zT5CNrFuz-~6peg% zw9kV;b2Ve5j{$6TCo;G}_W+4aAHb-0PHk(dS2G zgwcUf+#)ACnzPJ;BU@gr%k%CNcU=F*vFvptAL2`Ig>5uSBU3ePY>C#%!I3|0-lf%e zFYHWq;h-;GWOLYRKVVZ&Oi%Hjlz0|?z>^i*1(MSLlcufUBRnS;kpZYP+mdY#S{f)Q z)zM&Dk~37$DqFAJj_(XEc(7ulgtmp@&6(ipLT;>gxOcW=RgcK#E!F_4S;!5kvz>wFkjdn&aq zP-U|b{+@mswxqL__{?~yfbbX`biXT2(BNq?9ZnF}<3K#yCP3o`1Rg-+2Bmi#seN84 zpn*z=cq|wgfMquHuwQU2c0fubl9E6sn@y_rZD8Z?h^TA{t-WX;J(tK!G9D^VzxP*0 z$WaL_QDXIFsqx$grXz9taM60EE3d&c_)m;PPk8tO*>N7mRsIM6SR)czeL#-}o{f3$ zvQ?;8Krwjsj_ZD+dJQE$DA1+FZnnv=2fEa0$E8L9D^mM z{)UUqeZmN{yFfgo1IyM@29o>Y1ard!>Z83mbUYqOnPI65mB`WRApUb=5HkHO`aO3* zwZZ~eHvhXkQzBO2FoRVn_GA?~NIC$b*8X#|iuLt09|nzs6ha_iDB#d3-NrP6HCWe( zAhg{7Pkx&Fy78P``eHazt?{k3WC5@;{By!qr$)7csk>I0WdTD5ybzpkgL^^wuI$jZ%h z2{q_&K2*aT_X?oWKkE_7v%3AS-N*ycHe}nUYqwD1y$4iv*9`B47X9FRtG2Vc1wah@ zE7+~#u#>s$!xYk}kemSCbn-3iSpq6hT=%yd>r1t1R?ybnSo@f+pu~rhqot97`r`!w z*j?_pjSpf&tIubAF;6|Oy6vMdEASua?*LqN1a7y??q zBn3RK3ly^&Af8j5$d*?1h(x{iBYxoHL)ZvG?tCiigxG&44T@v_7=(fFK1#DCOZh{I zz(z37bOoRC$DDVW+kBJHm4cxC7lOWx8ql|BAtV#I5h`ZYpBi&ea2y#7QG4$r$K=B$ zn;r35zn|E2GVt{*kZDEw+Su1sfFuDDN(MX{A+fEzZ9=y^jQqAKE+FsfV1YStBuDNiUYq;~orQM`65g@9W&)3EBtdIzf&eHb<20TB6IXt= zsR5PGFG;+-bdN3jz*JPabXj;ro{5$25v8Xx%Vwv4iQ~PYcns(kTdzTss=`bdCJevT z+~NF@*oy8`8Z!i*mu&9sZvlrQiMHNt-b^WrL!%-ehKdJkDr!glq%pnF`0(N^?LrDp z9WjqU{wio98tHFF8pv@eX*Pc3g1GYw<&svNE6&0=;|IMhOkL699VXbaHVfnSbHBmL z?;v82XsOtM|1A(AylMUDHZK*8f0CEiG6A;Vv5q#i44IeI6|`076PGGc5H%G>Zin^o zM_|&=_<;XX33){KHCQb$BU42)IbG8*4h~cjtUA}5%oc8&>Dws=yLq0ngDMbDrH91w za$p6n07m@0>KX;u|CCPIQs^|mqnGH!b9Wab=a!2A5NCI07MtkJw9eNErJo^)=Le#t z4v`I~hpuFi#cDMlLh03}KM_(o7)v0uL%A~=z29vYGdIZ1&Vls;0hM7?3I?1{gIIK? zcwrUYI%mdQ(;)RRy(8A6k^~T0JX9XQE?><_H0P=1)5QesD}2*TF~)=Em7#~IDHbfZ4f#`~B(q8KQU!X1<$l%QzXT-*7*y}IQ-fX5D^${*Z1uz zsvGs=mMA-SvD-B!YTLb+poMx?e$bSdFqM z$SVOTZ67;7SJ2AUU7CcyIAXP(f8as1Pt}yH_-1r%_NVxc3tzmS3!Xs!w_u8mLJ88& z7YOS!2Jj`to$iT-S{K{)JJ(WUo>b70d{K~FV(QB>@{UJ;s+h^@XC|4pT9|JAIfVvn z>alvynN$K=7x#q9qHy`3^o=!BNa8j~mk?vY)4mixHl<#H_Y+k?===4F1+IA57-)QVnsiDo)Ltp3^Gp z;#63g0CI3|JP%%rN+O>bFWPEtvpbnsmkgQX+UQ&T+Y4g1ebF!d=HW=kEa!K1l0d)V zN(iT+^r&X80vgH-ApJZjC_gl9ACzx{Hx<(VlJ*(;2%Ic0{^w+of7yu$x{2oewCL?k zxh_5|B_nQf2U@BalVSZTfre_^KTfYJT(|tZ<2-m+3S(ae@ZBp8=69q^X|MWZ|e(4$1_Lv|`f);krAV0D|nAX>AFA4N6TV@hYsV_t@SGNb|@HuA_c#|4kapH{o`%zsc&1J%~5*#^~s)BzXN*?ftX;EA)3g z5mAm41grgLX?*_M4AbwIaxPK@nqC1#TJD8PIvaUYh-db!JO7==fbGGXyJ4WRtu{4X z2w)+e89lB%y4+TuEY?A5t+o9GdNzv-xUBnmKPQvDiVbF~aDVj)od7?Wk-O_(;phH6 z-J5zMEhUO597~o$7=N7~<`+%-C})DQ?04H#m$p9xE;5r_6CWbUgSvlL%3-}OQhGgP zvSzf#_OC>=LjHeCM9Hf5MNrae_N6ynibh-YNPuZF@vn1I3DFUH9Rb%+zpboAWOkQZ zr7Y(s{UfN+er!t(Jb89`_5gt?6bk~viS}Dv6Di$^CTF9FjG9Lf zZ+EGk_`cC9Q-=fwdlF6A|0Adrg6o$5l~n!_`M|_;Ux~b=NNb&drePKF^~(9B(Xhko zCL44-BFzEcXe|TemCgM|!s%UtyL6Xt`b&-2SU*3@ejHpbS-{HqUjk6Iu`%0T#MA#< za{2nK=kPU9fKGnbf6Bb0DU+_lek(-T{8?3|_C6O(Jvknn?lw6R{eKjqqjeTYckdUT zb+I|3r=Md{kc{&AQ~#E*t~A9 zCKPex2~kdt)Z~)hW#Y7Y4$fM{03!s)xtVI)uM^T|^3qOQ*; zyGt$Qzwb9gVMKcdF;;)-?Qt`UDRbsJC#CG*Rp13^%Gk*i+Ll4k5UW0GzRI|A46;0)0=>pwaZrNR^qTZ(#`19PAB@|BN z-^iLP2ia`IG@IF{FW2MtwOnHZ%YDg@gEVXn4wmMGF)&oR*0?2fj58m3wqKiOvgM`F zqs<{bJWl?KJlQdXxwD6n6z1mXZ~{2u_K6mLUVIzyj%&LC>*P}7e{HoIaQE$}&DYAE z8KyXFPU**Hk#d3U!hTv$f$mf$v*PUd`h+EcNBFbS=s^swJkIuIbT2W{@s+?xw15_M ztJMX$2r3ooG!O`mbC(DM&OM2JLJdp3FA?OHs{)nRNBaC_2JqoE$ZuJpn zF{sBZ%Mm{9xsz4y8upd_@nKv{w1QSI>@9=uIyMnCM5;$6L%j%+`K@l9zV{F5^wf8n=g1G?Kb4H&rAF(QAMV| zX~We>>0eP^0u83_g!7Tdo~Y9s^T>!NeShF%#_JTZ9|{8s384^=OHfAw>f2Q1U**>A z9(gQV6#SlA7puK|aeEn#5$H(Nwq}F!4X*3ho|7}qUnq1TKZ}eHU>_oo7QK(u+&knh zzT9q=wM0bQH$LB@Pf>z7x1^=M-{9v5YJD~2Afo;GE1eJ;2Z}>a-XyHrN z=eU3z6hh7ELH#bn@FK{eaPKX=@fD<|g-uLq? z{aGQSi=T*E(@lPVWsrg+r24Q|19J;ZCgZQ_Dje{De4SlP7qZBuY;*T1zuMoctdz2)4fZ{Pxrm8VHL313mSBP^MZ&U5fr>UQoW(^vBRlj>YJuVbwoO%?h*Y| zebVP!z3<7lSBNgX^{T8jFm`zkrBVd;KbWlv0ZdN@Ddj`#oiLKW&BrZP!$SB1oin{A z+(}6?29#25?59!)HSi#-F_zPW7a(_z&W}BORzMbl7=5o@KE@BorINZ4W=e&e@Wvb||-HMv#IJe)K@*9=TCn#(W6G1gO?r8>m z%%3T^O`6dgs<&?Wi$*Yw>|btu@O_e?|MQJZwbXR4m3E60#?j%!A#p74TN>3^6rzdz z&O(t4HXumTu$}IDML|?_{oU2qpqp{4^jC#?usYNSbOz}pO5mm#7_stC0uj0vR<|U= zIeffYQ#nm9z{};x>Yqt22afwd#I9&)00#W!>P-tZ)BiJ_;myG5W0X|3BnBfKJL=kk zo?$4C&rxP2DK<#H{2+X{_TAdk_p*(zY$zw$J*!xU>n_iA*1ybEgSlEcUS>y;J2 zBy-MeyVnm|v6LoQE>Ro*(-pl42~rOCI`E#HJJkhj^_EXc0f^}`Z6Icy3VB#Mpw5*K zY{n!LjhrH>&6Np`6&UZ>?Lag$vpI-$y{wnV(1U!1mAhW02%!?fN%oZeZ7=Plz(VOtZl5G?J`j zI9xgI$AepG^TNd_E@uD>44__x!et1<35JkH2^nsW-es5<|l#SctAgCm16<|bTv=1ZKS&6i3KhEU;cB1{9prPf=-ZBL)cq(_>Kg^$Ju@JG+A~Zn@&tt6{~3@U5b#SutqlISfO4>*{oim! z@9;l}Kumx-_=*n+;_&YOn-S1;YT6QqRe^~eXn8{5%t;G@7D()};pv-eTEhlR5Rd?2 z04^M41=<4Jriirg+dA7P%A(DeX`w^ITskMTKRgYG85me(JY5_^MqZ**%C4B$Aj`RA z<*ws>na1hBt~6{ZPFpT$NNw4bXMVuZzdK)(zW`$nj-CNGg(biHWmxqYIKE&Qe>O)F zc+#%!>2pg!%?KFc0ZrB`v?fSw1Lc+3L9?v`f!82j@4twA71j*U?BUMW$6uUv2db_y z-JA-%w{4q_^<*1CD8*-eiopS#LC;Kw&jh0t%GM;js&5?C5v6CI4*K`+|8sOlF{} lXLFNrEHF|rQL^xl`UP_>rdM8FJDmXtJYD@<);T3K0RXNkkx~Ev literal 0 HcmV?d00001 diff --git a/order-service/expired_actions_consumer.go b/order-service/expired_actions_consumer.go new file mode 100644 index 0000000..1d7b79c --- /dev/null +++ b/order-service/expired_actions_consumer.go @@ -0,0 +1,25 @@ +package main + +import ( + "log" + + "github.com/illenko/common/amqpmodel" + "github.com/illenko/common/consumer" + amqp "github.com/rabbitmq/amqp091-go" +) + +func consumeExpiredProductReservation(ch *amqp.Channel) { + consumer.ConsumeOrderAction(ch, "dlx-product-reservation-action-queue", processExpiredProductReservation) +} + +func processExpiredProductReservation(_ *amqp.Channel, orderAction amqpmodel.OrderAction) { + log.Printf("Processing expired product reservation: %v and other work will be done...", orderAction) +} + +func consumeExpiredPayment(ch *amqp.Channel) { + consumer.ConsumeOrderAction(ch, "dlx-payment-action-queue", processExpiredPayment) +} + +func processExpiredPayment(_ *amqp.Channel, orderAction amqpmodel.OrderAction) { + log.Printf("Processing expired payment: %v and other work will be done...", orderAction) +} diff --git a/order-service/go.mod b/order-service/go.mod new file mode 100644 index 0000000..221028b --- /dev/null +++ b/order-service/go.mod @@ -0,0 +1,11 @@ +module github.com/illenko/order-service + +go 1.22.3 + +require ( + github.com/google/uuid v1.6.0 + github.com/illenko/common v0.0.0-00010101000000-000000000000 + github.com/rabbitmq/amqp091-go v1.10.0 +) + +replace github.com/illenko/common => ../common diff --git a/order-service/go.sum b/order-service/go.sum new file mode 100644 index 0000000..d5587c9 --- /dev/null +++ b/order-service/go.sum @@ -0,0 +1,6 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw= +github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= diff --git a/order-service/http_model.go b/order-service/http_model.go new file mode 100644 index 0000000..2987bf8 --- /dev/null +++ b/order-service/http_model.go @@ -0,0 +1,27 @@ +package main + +import "github.com/google/uuid" + +type OrderStatus string + +const ( + Pending OrderStatus = "pending" + Completed OrderStatus = "completed" + Cancelled OrderStatus = "cancelled" +) + +type OrderRequest struct { + CustomerID uuid.UUID `json:"customerId"` + CardID uuid.UUID `json:"cardId"` + ItemID uuid.UUID `json:"itemId"` + Price int `json:"price"` +} + +type OrderResponse struct { + ID uuid.UUID `json:"id"` + CustomerID uuid.UUID `json:"customerId"` + CardID uuid.UUID `json:"cardId"` + ItemID uuid.UUID `json:"itemId"` + Price int `json:"price"` + Status OrderStatus `json:"status"` +} diff --git a/order-service/main.go b/order-service/main.go new file mode 100644 index 0000000..0f80a04 --- /dev/null +++ b/order-service/main.go @@ -0,0 +1,68 @@ +package main + +import ( + "log" + + "github.com/google/uuid" + "github.com/illenko/common/amqpmodel" + "github.com/illenko/common/connection" +) + +func main() { + conn, ch, err := connection.ConnectToRabbitMQ() + if err != nil { + log.Fatalf("Failed to connect to RabbitMQ: %v", err) + } + defer conn.Close() + defer ch.Close() + + err = declareDLXExchange(ch) + if err != nil { + log.Fatalf("Failed to declare DLX exchange: %v", err) + } + + err = setupDLXQueues(ch, []QueueConfig{ + {Name: "dlx-product-reservation-action-queue"}, + {Name: "dlx-payment-action-queue"}, + }) + if err != nil { + log.Fatalf("Failed to setup DLX queues: %v", err) + } + + err = setupExchangeAndQueues(ch, "order-action-exchange", []QueueConfig{ + {Name: "product-reservation-action-queue", TTL: 15000, DLX: "dlx-exchange"}, + {Name: "product-cancellation-action-queue"}, + {Name: "payment-action-queue", TTL: 60000, DLX: "dlx-exchange"}, + }) + if err != nil { + log.Fatalf("Failed to setup order-action-exchange: %v", err) + } + + err = setupExchangeAndQueues(ch, "order-result-exchange", []QueueConfig{ + {Name: "product-reservation-result-queue"}, + {Name: "payment-result-queue"}, + }) + if err != nil { + log.Fatalf("Failed to setup order-result-exchange: %v", err) + } + + orderAction := amqpmodel.OrderAction{ + ID: uuid.New(), + CustomerID: uuid.New(), + CardID: uuid.New(), + ItemID: uuid.New(), + Price: 100, + } + + err = publishOrderAction(ch, "order-action-exchange", "product-reservation-action-queue", orderAction) + if err != nil { + log.Fatalf("Failed to publish order: %v", err) + } + + go consumeExpiredPayment(ch) + go consumeExpiredProductReservation(ch) + go consumeProductReservationMessages(ch) + go consumePaymentMessages(ch) + + select {} +} diff --git a/order-service/publisher.go b/order-service/publisher.go new file mode 100644 index 0000000..b765330 --- /dev/null +++ b/order-service/publisher.go @@ -0,0 +1,31 @@ +package main + +import ( + "encoding/json" + "log" + + "github.com/illenko/common/amqpmodel" + amqp "github.com/rabbitmq/amqp091-go" +) + +func publishOrderAction(ch *amqp.Channel, exchangeName, routingKey string, order amqpmodel.OrderAction) error { + body, err := json.Marshal(order) + if err != nil { + return err + } + + err = ch.Publish( + exchangeName, + routingKey, + false, + false, + amqp.Publishing{ + ContentType: "application/json", + Body: body, + }) + + if err == nil { + log.Printf("Order action published: %v in %v with %v rk", order, exchangeName, routingKey) + } + return err +} diff --git a/order-service/rabbitmq.go b/order-service/rabbitmq.go new file mode 100644 index 0000000..f0bd0d8 --- /dev/null +++ b/order-service/rabbitmq.go @@ -0,0 +1,96 @@ +package main + +import amqp "github.com/rabbitmq/amqp091-go" + +func declareExchange(ch *amqp.Channel, exchangeName, exchangeType string) error { + return ch.ExchangeDeclare( + exchangeName, + exchangeType, + true, + false, + false, + false, + nil, + ) +} + +func declareDLXExchange(ch *amqp.Channel) error { + return declareExchange(ch, "dlx-exchange", "direct") +} + +func setupDLXQueues(ch *amqp.Channel, queues []QueueConfig) error { + for _, queueConfig := range queues { + _, err := ch.QueueDeclare( + queueConfig.Name, + true, + false, + false, + false, + nil, + ) + if err != nil { + return err + } + + err = ch.QueueBind( + queueConfig.Name, + queueConfig.Name, + "dlx-exchange", + false, + nil, + ) + if err != nil { + return err + } + } + return nil +} + +func setupExchangeAndQueues(ch *amqp.Channel, exchangeName string, queues []QueueConfig) error { + err := declareExchange(ch, exchangeName, "direct") + if err != nil { + return err + } + + for _, queueConfig := range queues { + args := amqp.Table{} + if queueConfig.TTL > 0 { + args["x-message-ttl"] = int32(queueConfig.TTL) + } + if queueConfig.DLX != "" { + args["x-dead-letter-exchange"] = queueConfig.DLX + args["x-dead-letter-routing-key"] = "dlx-" + queueConfig.Name + } + + _, err = ch.QueueDeclare( + queueConfig.Name, + true, + false, + false, + false, + args, + ) + if err != nil { + return err + } + + err = ch.QueueBind( + queueConfig.Name, + queueConfig.Name, + exchangeName, + false, + nil, + ) + if err != nil { + return err + } + } + + return nil +} + +type QueueConfig struct { + Name string + TTL int + DLX string +} diff --git a/order-service/results_consumer.go b/order-service/results_consumer.go new file mode 100644 index 0000000..45635d6 --- /dev/null +++ b/order-service/results_consumer.go @@ -0,0 +1,64 @@ +package main + +import ( + "encoding/json" + "log" + + "github.com/google/uuid" + "github.com/illenko/common/amqpmodel" + amqp "github.com/rabbitmq/amqp091-go" +) + +func consumeOrderResult(ch *amqp.Channel, queueName string, processFunc func(*amqp.Channel, amqpmodel.OrderActionResult)) { + msgs, err := ch.Consume( + queueName, + "", + true, + false, + false, + false, + nil, + ) + if err != nil { + log.Fatalf("Failed to register a consumer: %v", err) + } + + for msg := range msgs { + var orderAction amqpmodel.OrderActionResult + err := json.Unmarshal(msg.Body, &orderAction) + if err != nil { + log.Printf("Failed to unmarshal message: %v", err) + continue + } + + log.Printf("Received a message from %v: %v", queueName, orderAction) + processFunc(ch, orderAction) + } +} + +func consumeProductReservationMessages(ch *amqp.Channel) { + consumeOrderResult(ch, "product-reservation-result-queue", processProductReservationResult) +} + +func processProductReservationResult(ch *amqp.Channel, orderResult amqpmodel.OrderActionResult) { + log.Printf("Processing product reservation result: %v and other work will be done...", orderResult) + err := publishOrderAction(ch, "order-action-exchange", "payment-action-queue", amqpmodel.OrderAction{ + ID: orderResult.ID, + CustomerID: uuid.New(), + CardID: uuid.New(), + ItemID: uuid.New(), + Price: 100, + }) + if err != nil { + log.Fatalf("Failed to publish order action: %v", err) + return + } +} + +func consumePaymentMessages(ch *amqp.Channel) { + consumeOrderResult(ch, "payment-result-queue", processPaymentResult) +} + +func processPaymentResult(_ *amqp.Channel, orderResult amqpmodel.OrderActionResult) { + log.Printf("Processing payment result: %v and other work will be done...", orderResult) +} diff --git a/payment-service/consumer_payment.go b/payment-service/consumer_payment.go new file mode 100644 index 0000000..7d15da6 --- /dev/null +++ b/payment-service/consumer_payment.go @@ -0,0 +1,25 @@ +package main + +import ( + "log" + + "github.com/illenko/common/mapper" + + "github.com/illenko/common/amqpmodel" + "github.com/illenko/common/consumer" + "github.com/illenko/common/publisher" + amqp "github.com/rabbitmq/amqp091-go" +) + +func consumePaymentMessages(ch *amqp.Channel) { + consumer.ConsumeOrderAction(ch, "payment-action-queue", processPayment) +} + +func processPayment(ch *amqp.Channel, orderAction amqpmodel.OrderAction) { + orderResult := mapper.ToOrderActionResult(orderAction, amqpmodel.OrderActionResultStatusSuccess) + + err := publisher.PublishOrderResult(ch, "order-result-exchange", "payment-result-queue", orderResult) + if err != nil { + log.Printf("Failed to publish order result: %v", err) + } +} diff --git a/payment-service/go.mod b/payment-service/go.mod new file mode 100644 index 0000000..6ed39b5 --- /dev/null +++ b/payment-service/go.mod @@ -0,0 +1,12 @@ +module github.com/illenko/payment-service + +go 1.22.3 + +require ( + github.com/illenko/common v0.0.0 + github.com/rabbitmq/amqp091-go v1.10.0 +) + +require github.com/google/uuid v1.6.0 // indirect + +replace github.com/illenko/common => ../common diff --git a/payment-service/main.go b/payment-service/main.go new file mode 100644 index 0000000..38ac953 --- /dev/null +++ b/payment-service/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "log" + + "github.com/illenko/common/connection" +) + +func main() { + conn, ch, err := connection.ConnectToRabbitMQ() + if err != nil { + log.Fatalf("Failed to connect to RabbitMQ: %v", err) + } + defer conn.Close() + defer ch.Close() + + go consumePaymentMessages(ch) + select {} +} diff --git a/product-service/consumer_cancellation.go b/product-service/consumer_cancellation.go new file mode 100644 index 0000000..2214def --- /dev/null +++ b/product-service/consumer_cancellation.go @@ -0,0 +1,17 @@ +package main + +import ( + "log" + + "github.com/illenko/common/amqpmodel" + "github.com/illenko/common/consumer" + amqp "github.com/rabbitmq/amqp091-go" +) + +func consumeProductCancellationMessages(ch *amqp.Channel) { + consumer.ConsumeOrderAction(ch, "product-cancellation-action-queue", processProductCancellation) +} + +func processProductCancellation(_ *amqp.Channel, orderAction amqpmodel.OrderAction) { + log.Printf("Processing product cancellation: %v and other work will be done...", orderAction) +} diff --git a/product-service/consumer_reservation.go b/product-service/consumer_reservation.go new file mode 100644 index 0000000..d92b148 --- /dev/null +++ b/product-service/consumer_reservation.go @@ -0,0 +1,24 @@ +package main + +import ( + "github.com/illenko/common/mapper" + "log" + + "github.com/illenko/common/amqpmodel" + "github.com/illenko/common/consumer" + "github.com/illenko/common/publisher" + amqp "github.com/rabbitmq/amqp091-go" +) + +func consumeProductReservationMessages(ch *amqp.Channel) { + consumer.ConsumeOrderAction(ch, "product-reservation-action-queue", processProductReservation) +} + +func processProductReservation(ch *amqp.Channel, orderAction amqpmodel.OrderAction) { + orderResult := mapper.ToOrderActionResult(orderAction, amqpmodel.OrderActionResultStatusSuccess) + + err := publisher.PublishOrderResult(ch, "order-result-exchange", "product-reservation-result-queue", orderResult) + if err != nil { + log.Printf("Failed to publish order result: %v", err) + } +} diff --git a/product-service/go.mod b/product-service/go.mod new file mode 100644 index 0000000..46082fd --- /dev/null +++ b/product-service/go.mod @@ -0,0 +1,12 @@ +module github.com/illenko/product-service + +go 1.22.3 + +require ( + github.com/illenko/common v0.0.0 + github.com/rabbitmq/amqp091-go v1.10.0 +) + +require github.com/google/uuid v1.6.0 // indirect + +replace github.com/illenko/common => ../common diff --git a/product-service/main.go b/product-service/main.go new file mode 100644 index 0000000..b85a5c9 --- /dev/null +++ b/product-service/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "log" + + "github.com/illenko/common/connection" +) + +func main() { + conn, ch, err := connection.ConnectToRabbitMQ() + if err != nil { + log.Fatalf("Failed to connect to RabbitMQ: %v", err) + } + defer conn.Close() + defer ch.Close() + + go consumeProductReservationMessages(ch) + go consumeProductCancellationMessages(ch) + + select {} +}