From ce2238d23110661c924e86feb97c54a6af7046be Mon Sep 17 00:00:00 2001 From: Jean Paul Ordonez Date: Thu, 3 Oct 2024 23:42:15 -0500 Subject: [PATCH] Parcial_JeanO --- app/domain/models.py | 9 ++-- app/services/usecases.py | 2 +- poetry.lock | 86 +++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 + test/__init__.py | 0 test/fotoParcialSoft2.png | Bin 0 -> 57858 bytes test/test_app.py | 81 +++++++++++++++++++++++++++++++++++ 7 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 test/__init__.py create mode 100644 test/fotoParcialSoft2.png create mode 100644 test/test_app.py diff --git a/app/domain/models.py b/app/domain/models.py index 141efb5..60535d5 100644 --- a/app/domain/models.py +++ b/app/domain/models.py @@ -1,8 +1,8 @@ from typing import cast - import shortuuid from langchain_core.messages import human, ai -from pydantic import v1 as pd1 +from pydantic import v1 as pd1 # Utilizando pydantic v1 de manera consistente +from langchain_core.messages.ai import AIMessage def generate_uuid() -> str: @@ -10,11 +10,12 @@ def generate_uuid() -> str: # Entities - - class Conversation(pd1.BaseModel): history: list[ai.AIMessage | human.HumanMessage] = pd1.Field(default_factory=list) + class Config: + arbitrary_types_allowed = True # Permitir tipos personalizados + # Aggregates class Chat(pd1.BaseModel): diff --git a/app/services/usecases.py b/app/services/usecases.py index fbf613f..cdc9867 100644 --- a/app/services/usecases.py +++ b/app/services/usecases.py @@ -42,7 +42,7 @@ def continue_conversation( return self._agent.get_last_response() def _update_chat(self, chat: models.Chat) -> None: - chat = models.Chat(id=chat.id) + # Aquí utilizamos el objeto `chat` que recibimos como argumento en lugar de crear uno nuevo chat.update_conversation(self._agent.get_conversation_history()) self._db.save_chat(chat) diff --git a/poetry.lock b/poetry.lock index 4cdd109..9413173 100644 --- a/poetry.lock +++ b/poetry.lock @@ -414,6 +414,90 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "coverage" +version = "7.6.1" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, + {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, + {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, + {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, + {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, + {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, + {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, + {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, + {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, + {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, + {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, + {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, + {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, + {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, +] + +[package.extras] +toml = ["tomli"] + [[package]] name = "dataclasses-json" version = "0.6.7" @@ -2103,4 +2187,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "2444438026f1b76defa5644ca632725b91000ec28af9954c3fe93c80eda564c4" +content-hash = "b4e071cdda25ded1a1e84a148922aa0fc4e2b0a44e8cf3ced2dd4b62400d8a08" diff --git a/pyproject.toml b/pyproject.toml index beab032..6654144 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,8 @@ python-multipart = "^0.0.11" shortuuid = "^1.0.13" boto3 = "^1.35.29" langfuse = "^2.51.2" +coverage = "^7.6.1" +pytest = "^8.3.3" [tool.poetry.group.dev.dependencies] black = "^24.8.0" diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fotoParcialSoft2.png b/test/fotoParcialSoft2.png new file mode 100644 index 0000000000000000000000000000000000000000..dde775d47eb1cd68de216e7aca7bfa1cd33f2445 GIT binary patch literal 57858 zcmce;cTiK&*ET9$1w=%;fP&I{N4iv{N$*8^FCsk<5$OUdy#^6MX#wdiL3;1Kg&ul< z2q7dS7k}^jet+Hh=H8j_-ZOLN%-Pwq&)Ms&wfB0~vsU6?>uONmWx9Lo)-B4HnyLo3 zZV~R>oZ#D}H!Yl_cTqPN0)GRI7q_ZLAMM@T5W6VrDBrqOlR}PtLvnL}$5+$b|JJPs z@BWw zy203&VcTM-=M33u0Ck5u>o@AU9DU41$F{ho39M~DK)VmA5t&vy)NxDt*X2(J8kYHv zbd%7QscdE)IVfCV0Hf%qGB0%}i_;{>=a8q;;xg#1t-LYxMLNTC8A8AtF&oE{ zPtb-OCA(aU+C9@PBnxX$_>_>%%QL}KRCxBr(~ZUnSIvuvg((+SQlo6-)qXH6V_O7v zL%7}xNR`oY-t~sPm&d^3BT6q2$_^`lbN4o$rl3ac+|XQARn>R)l%IMHUhgr^(_Gpq z5mQWT=LeClhG6ou0>W5DfQs~jTmUpmmW;_Vlynt+)U^YqdXtUsFNh4<7;L>geh!Zf zBW(cqBhlUdf#(aqOG1LtAmFwJEcwkGS_dmN4hLJMO1(V7h1W_D@Yqa-miIq$r zj$iOqpYIUp%WDSblhX@YHTkZKvM25h(zFcY7sx}$3khQ>70sXfE|Bz!8h!dNG%DVAW~)6W4~KJ5uLh1exlJcYJ9tc_+Np8VI# zbUJ;cpGxQQjwj|~qacp(M|1#c#jTngyF@D@(P@#Gpo47)eBcKsc#Q1?YXiKF2K6+$ zmUozAR@=m?gAQUM>FeMx36bDEf=gLwv)FO{5UJ$51QZJ$LF=3Ak+FWd%OFx4GYL%( z`Tu_2_D4aEaaV7rA|c0 zpO}@Twq1mF!O(W1pt68FgG>|Oy}y%b;9fwxyGaDXN?M#o{5Au>FCwM zsZX~oQTAG;Ou>!7#M?vf3=@2MyDU+KT=!YhGDp{-A6`+}Tz>cKD3r6I;uUOSv?RQG ze&kQ1{b$2CNhInP2V%t6&g*$!=>Rv3wUkV4U=l9j8Y7IXp2&I@1lq990gjx8OfZZwy)!-Oo{4rTCRxq3~kFC%@>iEdh0iHl95B^r6SjCG_6#CnR{JsW*7T54~54-!p< zQQ%4r5;=zX<-4u@qCtc^lgUYq_Nl?Q7!>q&(t{EH>AuOdHTXrFya0s~ zH@=vkH7q{Y#(>G5%=J<7>F0Yeyv`CFB87kaB7E&P2$txhO$YmO6jXRN7y97e$FMF5 zw~7JkUt88IG$iWSumR$S#h+jnLitGVegfN82d}NdelGB?E{HuQT<-S>!l{Gyp4E(1 zT1_j-)Qqr5tOp>;SiPrU9GE{sk`!^dZ_nF_WG@c-YT#dn*blbPd~+cY2n6aL;C}F% zwRNCST!{4rt+(fr*cy7(sYcAU|4)#6?pqUz&9Kf|r+!?wkeuryVQ!a(g+k}W+X%hC z63wd4w-%rdYpdmy*Re?|nQ7 z!g`HVxW7HOb-w%H*uMZ^lF{ERH9R=UF_eJy251#GudPPXZy^hMBY$ur;GNO`S$aPW z+P9n$^G^_Xo)S2Q4mo}KMYY zNALDVrllc9rL~9q^>vca6{>wg87MMj;Mzr~=#jP3xz-hAtH)@k!()>m3xp6@T3pzr zU}p@e^TMlNfhswBp?N9DZJ2WM!te$#rwC;V@#VS5VeKL_3;mYy5F~4e&lN;&%B}*! z=n*(wdF>OrmJgvv4lh<;9D%v-XMN?uv-Voz9yVV)ORa|6DrCK{Eh1sJulAQ{3*5*6 zN6-WX+jcXT;cwiyp0mB!;P0pR0RA?Ot3Y{CX{2fsBeY2^tsdfCfq|Bv%#uhs43%JN zF75qDBT)R3QVNO5D23R>SKcu$9tjZijcmjZ)rEzD56S9zxZWf2e!p;!Xs3)V#Nj=3?=P0YrXXydPO#}TZTpYaI<&CYrayy9Jx+uA*SwzUiGFI1e` zrU4XvWoi$4eXml?FLG71Iq0CvOh1A|FgJu+a4@y+{LX6VRPlo4y^Ay;nXEGnJpR3& z!=t7wNAy# zt6|7V;+KrWTBvK+A@kffOjxR#;9Ue;ucW}yiRIN6%6CB~yolXbDuSIiEYWljUbH`D z7N4D%@$IbF>C*X)Oo2T2+lnT_AWr6=uWqE!<*jNtY>Ty(7tQ=rGoU^4E4&Q1lSg}0 zWM5)HB6V7sj7R9##oKkw=R5Vx8P6rcDn+$vxr&Tr5)%(CPEY7hdtUy^0I%OWlHbev zAPWo;qO;|9CuD;}j-Uj)(((Kse*13+dS;=6Ggl{loR{IE-pz-G=$W~_Sfz|hp37df4K%E^=1ARvt0+Gh0A7ybX^Oix|L5uq$C2*j$_woi^uZIW zu>%yABS2I}&SuD6I;PV1iDKKJ(Ye-_fXgSi!pb{g)G0yzdQ?F!=8-;TM=ie~u}Fo*xf6{%GGh+v8PT^zppP#bNM;66k` zB8`89UgK6+F0C9e(DFk<`!}UORUKuovc2pB1e@4Ad8?HMZS4$4({EU1O9AB*g6iS= zLJ<`(^?|xv8ft24%9Z{L5#YB62R7qN(PP)M?ZN9VjN*L~3Wjk z2>&Dj?66#Xbg0&}L5;)^Bj@;4BO6wvEvJ<_{e`;Da=z^G008JfI%jLY(*Af=LwBRh z?@(xRU?xNtz*KNF%kKZsDg-#0FoXp?Jh)zj9d>N0CL*V=HtrM`RgSlh%LD-em5lCJK^W*jRq0!Gj^hZ^|iZ=kQh{mUz45$!l{7mvV zbE3nX`=_VsS|hVB9NLFxbtKq}wbqdnQ%Rch&+gF=xzobDW(acm; zp9RVh(71phoru1ZXybXF+zCY>byd?DJN0eUHw^m3ieF!-Me_S5cq8(5T)Cu|=H<*w z^g(_B>{xj-$z9Dtp_|LXG$rwMTkoYun&Io32=X$V%oBe4h!6OS1KR9Fy0G!!*3-Cc zq0r;^rTj1ZxswBs2q*9D!rcsk`PYn@ee_l_xpRkq3Usou(z@<_xjr&@t7w4(KKl=A z9|kGs-)em^ag$kY)7{dX?q$1{YN;m_VWYw-;E+Z*{;!sp`$7sf*{}7Prg#@W`Fby_mvn>#g^yABG&;@Fy>r5b(Bzt*66l5R{%3@&wS1kU#C0ZrR+3jj+@H z`d+k$mYaN#IAH2N-pOKX(N^%?HDHxU8S$Fy@GX&*4vmN5o zuWImSIH_=Z6#Px2gx=|l8p-xz($QrG9gEsd4x+il?WDN_mvCsr!56+SwvfAH$MO{D#4{O}{KQ1gA#;On$Ptj58CZAQG}LHATt0M$ zeR*O&sp~hRB%EKHda0|=#}1hSiC>V#mvFtRrcTFOB^xiTj$d?LLh?O$PwUmJLq%np zL?V*grPzAX(M}ufXJYkH9nJK*U!d4z2nyDbxGGz{TNc23dcqJ2IbUBhhN*4?1J_Qt zHrjOQFg$}%*!XL2ne;VN9}y7q^%v1C+XynrhJ7^6bsLpmFrwD19qVzqn4;~Xp%=xi zr)U=IEm6O29s=L+2LX!4t~SH<5f#90-cgPLNhmP@j^-{}}zjEZHswqUMwAI6dU09y{8_M&K`M=HVUogt@|9MoZwMVf*O6Q+m`Cq!Wva35t01n7hEg8R=K(-x+p#4RIX!YWVzd z3K!Aen3$L+Bye~^m|%%+e!`TlEF}p2NzO@pk(8A5q!D^eNp|m1$9h-n%;NA#8!L2O zn(AgE3-(5YNCW^bnO^F**|jqs6N@O?e`^R&=s z@}j|*Qs5Prz~wFiF-J(v6fXLiRWYKC&IrFw1?-pR-U?x1?F(c5H}ip?e?>A^Op6WW zxihy;2R73>`||HB6!At$HM5ZVET|Nahv;rKe}Quw%7ME!gU5(&W+lm(-XXUft!DGO z@571Ty&nh3o_Ep&%F^=xS4WSZ@W`7lo$G6o!O!J0Q>!KsHsCLohFiZG|@KJYhVFm;(%`g=LyvohsDwUzS3*~)Y0~+U{?32FLapBHoss{)CMo>ymHZWyEiaL2trnE_H4)mgvXbWrCHfLp~Iih z2iqerKKi$XZ}I{xpK<)tx1oVK`w0G9_y$h#9svRHu25L{tJh}IK`qHDrsYlqvTu7epzfkDX zy$+7ilw$m`K8H69a2G)XlCX!yDP4`$KTMYZfEmiTd&qRUO#%?49SMyfVx8wkS?fW= zkxT%@!D*O>-h7p|sdbUfC>;zdHJn5I7lC1`SbZn=q zgWBS?D!0iv95P+^b5KN`$Vldd6Pa9>QY}$Bah~S=XcoBn-iFKbULqhva@h5@@7DQ~ z6WMl93*M_^hr4gT*WJum^uUYKtbI7L%>n#f?O^O!V{GEIKVMw`2Ls<|$1^_DwIy5Z zt^6@WXBE9|7n%LaG@nT!XUPLcjdLK55XP6CAa+GnWPR@AgEv$h?U!f1G|a_ek0QQY z5Vg@A3`nw!P^F z1b&mO!l`zrlFk*9l6qdzrqf*Y1A$U^?jIXR)KV)BMwhCc~o|_dd)A zsK}VOUN4kaZ{?bP+y6!y0!4vv>8+S(XX;^1Mh%t&-!uvYu= z)fi_u5hoq&3c)RBNgO15{1J&?t^(r1gEo49BQ{L)*&MLN23A0SE3He_Q!M(qRgg!1 z!*z=#G-U+S?NT7g(t|hsLH(q~niwR#)px|3e=y3de*r{vgCk16I>!HU8I+}9TZ>ZM zAB#OS)Ms3D?AHikZG3beu5a|)xm=dpbhPIkH4P9Oi;qRD{sMtomZ0Qt0YPj^0pVPP z8ZoLUVGXL1P8On2buD;obzsV4G?(j#u%BypYSQ`lIVLEAO1g1O2}MRosectxFC< z1b(u*aMhZdV}Y-Q?hW(>AI+T$j|L!*W9EEM3{Tg@8SAtXMNmWRMVLaCf+Z;`L$=)m zeK{TCA8haJkx{2&M{S8CRP`H$!Q%Df^8+s~FD1l#ih=Y8wy8XkVxxD-P7xcM(0IjW zL%;T##G!9Q(!QGVqrBI*+bdY_&8RePVmus>rz`cCdjEi4nbdPyAK>HBhG6g9Xb+)D zQ@7Ro=pt4Krl!IyKk3&TW2AJU8~$owFHqcdq?i0sCh2=quI9DCfEGM!0;nJkoPU$ab`j{X-4v-s2EVPzmI{ zn66gMhzi+h?4!beC&0xTHswKROYy-Z6idyn z!=IdUW9k({Ir18(H-U>(8=GP!ou~Qk6>flAiAbXl{HKb*$;CR6kls^@=MCROk2Ztt z(2Z~CBgJqRf;I;yT~L)|df`y|T;N+4NEilOeUP%@kG!kjf+diH%#LRQ$2giMLOAvt z>o(W=T=4jsKHApnSR&47tR>U~Rx=%(* zPw6X-Bd{TcZ7=a2BWzl4Nh$2puVWXuv7>jd=bRJ|=Ne>iQ$aMxH)u~olF?;GujW6R zYVS$9vt%(oMZRTaaCh!ey z7EJ1(PdY^y=T|d?^%CN1PkZ=gx{7DN9|6z31a;?k&}IM+5zfT>Cra?w5pUdiOM2gB z-~ZDNm!N)_Fc`i4DBO59_`v~4F%EZ{s(+&7;96BDW=ALwfrJxTfv3<}kjqTPxI zh-4(Hw4Ri&{I+fC&#e6$VPz=As5$Um4qM;SLwoTD%6hXMwFJ(7k`S)eK*IzKivh z;{^Jr&q_6$cw=JggYCRH3e0G|@PDCPif{_;Acewq$d1dY;wans7LoIkRkTD>iU;x= zaJiW^04g4nvv(!w&bpf1t6>^{w1+__Vp!NUkNP~ILlDr{BfzdMcE9Jw`g)B3mIpL= z=~=ng<#4cciUr7Tfl}j#-pK}mz+*-HZ(F+&-jFs4v-;UsV_R0XrSxrE?+zmTUf1Sg z!+Bc-R`$2;Woxh(Mo?g&5m={wkP1#`shL*zd+QN<76SO)+GwnpQ|{~?mjY{$!p^G0 za>nu;*P7TNeC%93S%>0PGrX2)1ue#5bd! z15k>R->>!93h@;KSr)tF7p*5n16kPU(_Q?KtlxDHrOj+>O4|}pvSe}lbhPKMU%nYW zRkBh-ZbOgE_qFF17Wj3EZVzG;SBt-5!ok;<^h=%1WP;ZUFR{Nu7pN0A*{K`wCPtsV z<40?8$0bXCnD4E18OVXfh(WIfk?XdIN0(lFovBYsYX4bV&6=1!<2YM#9vki?b`e%u z5c&!uOLv2+U=z62AXxY!>|J_V+L{m$ofxXVuuE=xNtlzHJ5&4jr0pK`TOQfX5T2qX zE>8cTBl{rT|4kl)+z=%N#hMuCiwXfZ^MF6cn0`sHP3+w3{{@<`Q+o9C{N#~T?U{8LZd%*-tKhW0qS-12+1 zzB$?*Nkrzm=vL~s^oHEy;xqh30ZoYamdxP8v4a!oRix4l^3hRuYUvgV-_tVt?Rcj* ziMez(@5<35L`8)NhlMMaOYF&_mi(4nE0mNLT~SuHR;yxA8qyZ0h-D(H_P;m-|?L;>tCFdTL0nyi01!X zipTFr|7Vh37V+iNhX0n9u*+2JQ>*Co+>AB$bN&ft*QOmox$gzp%{@fYoc$WPb#M*f z!HaF73-=VmoDgz33EN&a>-1phq^;7jY#6F==c{6;Fj>8h3<;zVWxf>3j3ht#hf5hs3ANE`CjMi!pIvjlQ^5#SQ z-u42joSBGM26)q~2H*XOjkd^)DK{C&c)oBIM9FlKNUMR9`%u~4<>)K|kt2`>_)1>@ zI3eQH(xK9Y1#Gc(C=X7;+)WEHl)@+5M5M_2SNqel<1*tiwWaYK^suvHa)Ma!FT+Yr ze@hY7h4{J(XI~tdkZjTNAf1uE_jiH0v9&!ID~Vv6QQLEA>eu!I(Z8c57oWGI=%I9= z=LEJ8{!sBSpgv>RFr;*yp3Q$kk?Mk{(u`*Ad0tlO*jiPVc-X1$6f?UD^ppJ*#f-ea zi)Z=og$Ubvv#k`*Z<2NV2Yc`Rxk~4Q@9ym^7~}czdLhr8%7GS6x(#WGc+eJ0Lca_{ z#qf>0Ld=kr`b+ax+TVr~?PY`Knrj8!VnH@h9(9&yrt6dBu{@7i-0;3tw`GzyPC(Ph zP5Z89n&gcXAtsgjC$GYw7xq4#eS5SYZ&PCdT6rL;f`kKw8q}CHKTb8ONxXqp1^l=D z)F_IM0&J^Bmxn4?GB`^qN9!Z4z;G4^J0JB#lBnMTcsnf zc#pmI!EY^D9}aHF3o)b?dr*wUgtpY!lmY ze!EST?EW5{?|h0;V6qXr7nfT3G*_*0TAlLsB4?nm zQ+bsG6Ub@xC@Igh>&b_g_?^E|WyF276y4jYR_r0)GoNH=Q>=kd^jGFLa|CSM0X=NpN~ZT z@=X=!{WnJ@e^O7W}uu1@`>4pc-GZz`pEVO>2b1c`W*y50tNGgis%!Z1>Kh? zt#NIfNnurQ63`^ab@v>f7_N&8Ual)8ncE5c${6+6l3G`<&_}p+Fw=A*77`WNsDYg! zv`;QH>aB9`J;zMFX`X4y=rlr5qovH~>6D?*u07;F%|D(JAJ!$z5yqMO&=ZhreTe8a6JwAM|4oV(F?kolw%i{NpH6LW9 zvk2Ulp!(#ZJ9`oQc`PS>L(9>Noe8VHr|dL2YZDR?!>~Mv=OZn@J@oc_0IfOA5((!s zbJqG}RzHCSNULggR9V}=wxu-xki%rF!!O6rF8f%kzxlg(`d-r1cSFm=Ly(GVTQ?Kx zahwm^Ve8Gt*rP5k3_@Qs)415pV}yC@As<7P7!=EuJz+1dXI-@wHD^N4)Keq=Ot#qd zKbEhea!G6HQCJs_U`g%8A~%U{O*yQ;@B)Q5OjXNl&vI+ZXNL)5aeYoFZ5MA!YdPhH{K!2vqj zxLlAd2XzzdCz+{;asu5$1|ou5?}sl3Q@#Xpy}0N~qRgtdV|P+K*jxaMyDCHXTON+8 z(B95&z`3Jyi+?P6S|+essm~n6b0`|SXNeBZ6Prr!I2qwAg=aWd%3vL6DQ z{}Ev{QQdr-cnF9h!jaEKI!nvo&4lGHMP((Ya*jEAf@s2boPF?pVCKf0AG$zYIQ$Vt zfGIB|uXuwcwzDsma) zvbSPc84k3%sL9+#_nsFM`pD~Td~kVbB0kfwZJqD$#OMFJ)rHa7do z#Igk-_DhwJs2w$ZgD+qD1zYQF3d+V;QsHo`%Wbbk-&<~za05VG#5cXBXr>@);c)PM ze`S5d7wgyT^di)0Y!j{YS&fC|sI2AA8KOY7gNz4W*Rvm#Q;!LqJJYj`5HBSQd9%A; z#q4{hW<0S`CF9W$719~|!K?9GP0>J7_5QCQiOHy*ONF*Kcbp7mVKoA^S0OF8wb2$=;4uEpIr;lI}&$vE_H>X&TLtfftrJ3VORx>CDJs=5LjIzU{P?7POOh;=! zQGQv!5D*To`b?JW&Db&z;kxpNrD|U(siS+ERwTV?6qBF?1ib2r2 z0ui4ht+(H(sO$_6QX3xjTD_lcs54RNiYRXDsf2Qgj2l<}T3_nkKaNzd_wHL}5q8?m zE!daesQ=hX$!G`{VR0iaE-}d9;2CH(+SV*DW*pV3D@v=N*oSvC*(kz#UpY3}(;hEX z(m9wWH@$t7F}|O_7JR|S$f#K^XzNC7Ch~xnA<9!LUFP(M#9z0J#KYqv-dDd!)p7@_ z4|hZIyrX-xmr>(Jq3H(gU)e9zO>T?rT@)D)iv55IkWcZY{2E;JeZ@7_i4l);Okb4V zGa|krW>)%1cKj;aYe<>r8QQPGLGW7;$H}wY(KOe^XuIkRdNt4!yU(|jNa`kTx!s;B z`;}4fu~6V!*vD14RiM_yg}`#O%l&neUmFh*FApP9J6BDx`Zw?e3{Bf1F=CQ?ti$dk z^WZCqS5&*uo$E&oDFghkbxk73zB^ODNh~?{L{3L&ec@m`-&ej#ge2yp6 z#sMFB=Dp(WOLf`Dk7}M2m}G06SuauQ^#-pcV?E@TTSJo@E!~&KdkZriha1em$WPx{vO#YS9YGmQ3sE19X2I ztX#hdyUMUiHPB?c{+n@c|FLC`5N*2Zsj!o9H~^FWc;%Kl@$^}r#V0iXSd!n#&MC1< zw$bO!XMD0(RErD{kOgaELKJuEUck%*Fs}a+|9-X83(Gp_)r)$TxvjZMpve+fVu(%$ zWsYZBrE!G6|5;|$j}Ph&;(P9Dpdgju@iLr^5>$%E)6T7^N9d8Ulzx5nJcM&dcNsSj zZi1nAvwB%Nd}s0FtzM7l#f(QwpWUKkilP1N*Zx3ughHGeB2D_<8LoWJbrTd z$;NZUhomn&=DyoE1AOFAL{B_EvJavMf$t5R5ptByCfeBjO-#N`@w6H5@t#?yfiYD# z;Zb>+Z$HoGbj<-ho4mOyVD+P#U@?y~KF+1dH@lrH^oayw_I|T;4#ln*tHZFuuWNB1 z7Nd~Im=)%+Zw;Wgynp_*m_8NKScD8hR-8lVaaNmd@dK&zbMhOhjk7~ryngKi;T~msM zK6y)Mh*xCDXsft!{{asoN@6!;1QqLbnBky z*|Mnc)K-0J_{7=Ue@N~hn)*-5Xx{$NZQaaZ-boj7&2qfEsNc1c;oGv1YBBVeFR3wy z=ooL@_)2Z>sj|7 zK~somA?tr)1{2)q;jMvG#{Y^SB#8$8cW~wZTm<2Uj`}}dYI2f2kjh2%vrk3RZ$tGw zF3#2S`P;3y&>K05i+hUvpD1(5dm7nHB$49NS%Lu@j{W0qjl^zP^k7^FmABDY%9tG1 za|jt6I3srs_!;9Ns~W`|-C;$tkozF>T=AVNPgSd}0+eb(csb?{-5MA{HhoiRQ#28@ zxd@Nt`i$)zJ2^yB-~^weDAu~DPGUkM0D_$hE(8c-%W32{rmCa+l->^s{b?PcSmCPX zot&)gD-6~mp#uY)!KqtaJj+XjZY06>z%yp&_dU#s<)Mj8v0aIOb0-oiLSoz9ce(aHRKcjLo~20q6Tq&DWT9g{D3xphhpD2E zyrMe&7JgYG}MRkP1g==!QD*f zfZf@`vjf{c+MwihlZACbsNq;IV^Iro*5|)x^5e}Gk^d4gwIiNZLu@zQUKWm2+U1UE zJ^d@sCeef7NC-!x7R<^SY;}hHF%Du@JHvnT(kSyA^c2p{t0>S z@}I7fO>aKQmDb1k0g_2pk^woR@8i?Er(kCmG)U zK)4ul`6E4)yy_5dC8kBJv$&Xb(}BLD(MD8 zVGKws1I&r;a%e3=1Hjr1BC3^ph>%w?RgJCeS2+{gRmS@!T66u6H z&i|FX;9Kxu=y%%XwbT$e>*)60mh7H-Q_pgwP(BB)4ex?1wDQdZ2fPz`XDPyX$rBYs zod)vQEyW#zJexL7nNIKQ$yiRm_uq=DJ)3veRpn5JDk)nnLz2NjYyK+9Lq&dBpIvK4 z$${AyA^NG{@D*Rba2xBm`t!F7PhW`pMKT|@FZP(WnUZR+qj0DQt4p7;4HwvFa4gv} zfmowlN_N<}IG^nmgA4Y6>ZI0~y}ISjW%I>qx+~^{Vz_0`h5h05z-EXI$;&Hvf_PSR z>ugL|LV2WrmQeB=&Wp0}&zR6}(t^z_m9laDu_^V5kj3P-pXD95HrQDgE+W^D_KWIc z653@ku!26S6aQ;}Rh-?v#7V_hG;8A+p6-Z@Hg@hzUL=+d@kFdZAnoiX(^Y>XKak#MDhyVciz-p|1%Vg;S=mP4r4?=RH8Px_9Gj1y`YX=s5yc2-B%V$er}~$T6c= zW24*{Jr%*m6kUiJyq+dEf(LK=b+SJwL8LRXnbmQVttu`%sYjYf>qTR_lPw)W^d7eD z9!lW8hw5uqR{ortDOF)sH}n2K^p!5|Uar-+k~?a>zNhw3`SKYX!|Kw9 z#!phD-O*?=JnxI*ri>v53*Tpii&~DpY+idago(AIbWeVHujXmhDT$Y`f%g~h%lFb@ zT|<6vGB6zh`sE)+zAPruBc2i^Za%Rc>-9gycz(XGSuzhxgIkkm_O9t2_y}DbJh(|Y z%R@<>ME+EYCNd8hmFGQ4I&6K&)^soS-RQYb;D&JxkbX2R5;QMG{c!Lt^QzR;?@KeM zr>=8@;5Tb7FM2fMSrR{AVW{uz!z-@{ob%K7y|qG@7+H7VUL$YieRNR9X_@eDg*?9j zKuzgB#_bZPDTT|O2Y!JjonedpA$4!r+pduF;zg79r}nE{ouns!aJAzzNymZ`q<%*> z=U6*|WdkKMc9rzn)vm!lb?O$=o0j7&ig|p5=eGhGKfJ9B8&>Rw2&HR!gfLi+#Jhgn zCHVEtc%uKQQkRa?MklA>S3FCYxz=sRkyU1IWg7bP{zc!p51OBUT6oxAg$%2iQ6+T4 z6`UzPI$$FEhzXe%o|gpununTNLv$Kb8Kyajo4?XMP8|FLjb8d0oBN!V+NztFlh^y{P?Rq(69jYQOV*cvwsQ1Omy6oaUN1GNdFBJAxEFeso=}Px_7e{v7a%A zG```K6TK}(>gDV-(O-*4I;(9ZFVs&jLCf(Q$NU6IP|H=Yt)MPHt@dhJ@X7xW=5i>zOW za|+~#es*$oGk)-auGYkW*3KPt-eys!Fk#y_*HxKO)~ZyOZd&T2i1Sa1{C4-VYITTd z@X}a$#H4LX!(_G(mtd2@7){9ljq);WndJa-Orv#`f?0xGQ@naQnkZwwS$-T0T!*uL#R21)xTz9|8m;;&?4Shzy*tP1jrBG(aWQMUvwy3X`&7B3 zD*j?iz@w6_y3JSp%08FGb>IWPysJo+9snHNcvqMsT(H3Zqof%8!yV3e$3#T512*B*KET5lQyW9NDAKzv@RhqHP?Fvb~u`FN}`!#0f zLFMb>=KMF`6!@|ow|OJjX4+7;b)$*z=;IpzrT&nwX`rVdaO20=IjXO=>j+FCTG#oe z?u9Km5)^?&ho8dpgnr2Pi^aJ8x0MiI?`T{$Khl;6D7m}()%x(k-k*4pOHm+rRd3n1 zbxF1CvG|jwDZ#pRld((ODCbv_<u zx1c1=0z}IRio@X8h@PW8Kqmao5+j{^o;tQ;q}maaGajI-$khQ5(6eu~{()T4Hb9I0 zI1B&$TgnQpFq>p&r*Jv8&sFy`7t1g~15Pj%5IeO#M_%VRq0}Nq71N9VTg_>9d+U3T zDF<5E8S3re<)U$|a%T!MQ=L?TUs5J-Ls*yiI$fzBGdk;kp*Pnn=2QFnSbV^fp{DX| zJ-n6EIgq3o_ys;-0W%=2AJi$xvK5|*nt5pbBu0sxG6%8xsQ)mY5mQkC_LET}L+k$f3Gs54KvBMy*JBoV#vR#fN zHeaM%82gwRE}pf4H-b5Syi6jGXCW&hyS%XtelI1jI-%yYeu?cvf+c{MCXZObC$q)&$pLibIoO$Oeut@8fyVlews(7sAguS!ERM0w z`*h!+db)c-JwA>H-@l;4oK8%5N`(^lJVKLZ-OH`*Qc1q?SbRq2R73Um6=BMUcBcTEIRD{KKSzj z=MOSmVd{)*0|-1S+z+B-58)*o1OeNr*|O4tIYt?cc6Si zIeyQ}B}>kPF*7r0{SfvMse4qOH!Iu*cDK?T9+v%}p!ND)N9lweOsBTW=eb`2`{vUv z%+|Yaihbq#Gs3m_%!sOIqBy8XFvPHk8Xx)OCaY7QQ&IS)IKO{ZC*1q+@^SKRx4|a4 zJrlDlxB9yit{eV3|FH#qvE$SUb-vQ#N@MpP4UhkSD1Keu-vOfDSDG_aG7-lCMeCe> zq70a-SU9J~vd@$8@oGMD>Iq>xQ#z)XZ>v|V7b%{-d27)!|4TSt_qOpJ@mFZ_?`hQk zV0PF0$Q#C-Md*KnaTWf9#?u0NH|F!--1)DJ^xeyUPx!~L)7jbS{sZf2BnF-pY)O&~e^b%>J~0!k_>8^Mx3l%CS3^9kHFAFD?n` z=D}6Q;IuCPC>FZY9I>_p`+uq0MHPmS2IKmMUp;;0!J_pFDhlyG0=$|-qeTM-Gi7Hi z^2ZarK6|r16$;v}-XZ+9`u>7{oSE=#rG4e{#oKuSg3CNlLA{uNFX}`a@&_zPxX8vo zZLxfp%~PX)$I-W-@L!&`v={sM7xdH2N&>TlGR8crKfkPx|Nfo~AsSzPLb&~OawzK0 zU_SjHn~tv@QwB?K1(ba5+vxL{**GfOmD5lRr8?L}6ls^KtK?oj5O1xwu-~cp8S$Gk zUr4Gezt}`e_1z#fJ>r3%Je8+_`u0sI*x^}1Pc&P@*WyZmgF!w`pq3`FevDG-YfD-x$)*kLFhv|(-%H{l3%=8i}jE93rq;YOYg4b2mEZ$u{N6&Atmyc zwHn(es5PvVc~U{Q^)pt*A=;@eR8v)4J#DO+fsXq5yI!ldq4jJ&OBjDs@IA{9UGC(n z1s^Z|u-z*XulJ=h@3v*WyTG5_VA#GqBSWs=wp?D2ttCY@$r~j4e=+x#0Z}dL{;<;0 zAs~$)f~0hJNrUvzBHi5}(jXz--7s`_cf&A9gLHSte_-!@&pzk&d%wKjnZ?YkwProP zeA3Zsb8&-Tw8+A&v0)7H4-0X|Grozh?c6_nX&bU!tW+fH%j;l0f(cuZjabl%*k6@p zc})A-GY3YQ(XSP%D9uc?G6|QGjO*OEwpmyl8R%;32>)w#Q`n8l)h+qVvk8Fv(!+0u ze-EbSrs{5R__qU@7Om6vM!Wn#%FGBEfe?{d7Tt05RQ%omW>YENLa(j-$5J?z>Vq}C zZdezbH9{Rb9t?$xqSK7ZN*HnCXrRZqwKt{-^o37AlG_{yTvQ> z498-k?Cw;1{i^V5t}E?r*j!F|Rt+G8q$t*l!o3syRysDe6eA6J{mEs9wj-YWuCcM& z!NjOf)xg4M)@3_YiY7o=siDn^z(KYc#mCxMmCk)L(Ye7LnC5x^>0$b4na{6SOkv7- zT-vmt9r&-Wz^XyUgmr06utvi!&=c0``Y8mHj99=jA_T}?AN$?5L+!(^Xo3u-Z zg1ecTtaBk~FONMR+9K)|5QYX7ZhzZyoZO&aX<;SSu(p$I1sIrqC?qNL)5;0HD#lK2 zupMgSyGjzdN!ce$9}#^J!l0VwR3h`SpFFhbeB_F7D^T`8e8<+!Qld9W0h@#Hu9W4vUY@Is|2IOY%oJ7)`AC_F7B;ulB9meW#CZhBdCSrzIlJv&FsLoy;0oj-dBQBZpkr2 zomkkC4~KSQF-J{7F&fQ%7Wz?t-;@YL0h54coVMh)Ms&QD z>D?9=Rp&6X%?P1~Ojo%j%fh;dP+Q&`GO+4e)fu*9tsO*4T^0i^5U{F5@6@An8vU{=kWIH$hRDc_ zrA?Lr4UWdCf}mKD;0SMfnCAOKHPINqqD7R!)ch9mL-K(LND>X7?RIQ_*1x94T9EPB zbFAuCcv1ncPvhe;)V+&{*mkq=4rY7KFkgj_K1jU(!Ug$C9SF8tlxsA_d@rU=Z+#91p@v47~$h#pO zBb2_y{h1Upz$pA~C0*``S8ors);;)kjrIy%WS_ z#43qoDVhh%0ua+Q-yCS=+qD^OC>yRcoGr1w(6_FS!$)gi&k{VD1DsY{QxBwBpkzEba@N-Senn z2;E|pbj8j{Pf8J!ta0?Xiz~0%hpLOG86qf3jU9dCXwh*kca7g*tXnr+h+gICB9UipGHM zuA~0+Ir4i4;bBF}`Qd8ow(y2X>I;S^R$USr+Ri8V+#;Xa8Ljoc8{hm^04O~cKDzm% zSLb$0kvZclE> zfR!Qz&QzJ#)8wSU^(MYIs@2vZiAcgf6Y(wKb=&tKqoO=RsNQ-syhwh+2zz4Zf|F_Lq zA8CE~DP@!Mi6KXYjFzqB;$ivX`tbke!-Tl>{=W{45J~8dnGz)naK*(vUO)#tqE#-+ z$sw)^K5yYVPkx>WA$NnG;;vl>&QV5L8G6e%*oz`F5Y770yl#MK(*|;B=9{Mxnrb(? z)Iu3(VS0Q_ohl6+jgb3dqNP!yogtlavMyV#LRs~NAUg@Ze^86FxLzQiJ)IZn%>SEa zks3{HGoho@3qH!E!6?0_;a6Q$`=}`7+XXyQHBM~@{2WFFCtfloRX|=fmTVG&{a3zz z1G5*gnWk`?!q%p7+|9-Ii!WH50tGmO&Q5g8Y&S*AaLd+atEOr+k;VvoRh1B9an;dh zc3?VB*51UUd236Zt$e*Mp`Tm|iAg0bOG83$ z`J6P!7t@$y+O}CD>0GU=6E=>81aC{pO6^@=U4?I{Lo=(bLb~CbTO^5Fwc9y|nH*ept-u4?l4eOW z#MTI2fLue7T5xC2&d5k=8fhXJK6e%4N_~0wbWNr4>)Xb(al^>;{?Yu7d@0Rr+*?c2 z>^`n~6dn6C9m~)?VKpun2Y2L6`i=eRH>rm#jH9`hQ&?us~B9|HrQox$x9>>YtcefC6YQI7A#((Oqn7{(-U%=jRm0q@RB_%JV1&M1 zw!++YstF-w#Jxrm9n-|c{U*7cyY$=t(Sh{xGbQy@;Tt>Cl@{^6&9BR2G<36`HBI>6 z_jlYrvdiT#Vs3lvn#pr5d~bO?H``t}BAMW8ghMeK{Qcc-1v2q^kzQW5pJ@V@r1>ttR?^eW@J!}fL1 zx2DoYypmcFS0-auqZ5J!+hVH>&A zti0ncexQEMO;awE4Xkg*L@LqBJ9n$0E0#nypO7W-Ey^MA$iq!v3pjpTNmR{m-4RQU zxY#MRtl1(oH;O%&qGqcDFZ9YI7G;~H0g(c%VgmWjxkHMUk=>ufahFg&~ z`iph8m>%Cl3>TiqqI=58rMZ&k+6{W#Cbu)N9H9au*HU=l7fNcYxU_nx7**PKuJTb% zwx6T3e7DQ{==D7GBo}pe_MS94O6#uUiK@MkH1t4Lx zk@r0u8rkD-@U{GKeI|47Gq_PcI8z6ZjY8_6z`r%s46;@}!_(Isg~>8yp~t(4T317b zG6KCl?TMn_P9<;{g|)n2Rbx*)I4PnWn6u=eNFwZ2|Jf=HL>he8oQJ2is()&v+EpVW zXWK!4E70^nxWm@>k(Iix-!JSccIcOZ#N?oUkz0clO$0Lp*O)2@ZwsC3`=7Zb9_8kz z_X*V9+mzyv?smnIk~-RJ($lNut4QzzMXrU*d-2_kNl=4Yx5G%$Zg!VhiAN6%VZNGK zjyOwCfwv;pK|$|N`c%z$dLU@SLW}UXFGk6`>>RWO8P?Tef*_B@sf_AHjlAv0&}#na zl2Gl@)+uL7Q6+!FwcwN4mxn6V!N$muijCJ$Y#hp$)gyCz0^;}Slg**L+DbU!EFwpx zfKy2r1#ckX3$E9Bw)M;piFwHB2A#?GY!1o5@fY09Ja3BU`%Cg=E!vE-0}2stz>Wfs z($zAt3U*n{S9T3p$~3&jGkcRa;(geyqlo0#NRA+x;Fh@2OOrQYI*lB!}WzRP0756x?;^$+s z_%+;q^=c2VmhQdU`yLBQ3GEc)S1#|G z{()`Ob8y>@K*CuT71aWr9KL~qd=9`iAs>-&wc%tKI&b} zfIJZOQ}DC7Hsdm0gJSi(OB`-5q3Y0=JxcoQIQW8r6jwUS#vYI5OU`->v?1UikFjSa z4t5T+F0YoO*>+n=ii|NQX(tYr*JBsYjPlLuQmo!hG&I5OXA6@mPWi@bJZDQfA7LeA zYudn)rGt(Vplj<6)=C!|6fgGK?nKG!*H0Uhy!W9_BJ}&Vti1_WkloL;%`fqK z>0mcveDoNDeFVaN){(ZI4mdq=hU%KQ3>zfW;ZzuC1!RTrjxut@MK+=kD;0<#+06Dy8=A=ihMW*mVM$^d%Z9d~fu$8eYzUOZ}yC<4%Ra zgR$G_vuV~87nGwc&Dj9@QzGRtZfxgrOQRPazl*7wTk%jV%ZbYAE~AEL%HF{TRJ}|T z+s}6y3lK?zY_l~fo&Ra6$^BpXUe@2CG zq2d>bS?+r=mEI41Bm0`Dot0afq~vSMnxl6sm!ekQ9^SS@ONM|whcTCEBg^0jED_pd zG*O7c z#AAbbO6}&NP&*R7%xHtU8Nx%&1$mwX6!P74n zZAuc$Nah8fG)R&NG2O)JE^r>J7r=rByBVrFDt+cb%*p8`!}*Qv%n<9Yw15&$7;(s` zvFtuBr*C0U5)}huT&=e)IZT+&J*8k%2F(LmZA4yf2uAF}eY@Q*(!1yL76MdCQGLYY@?OZ}+Ipxevo&k6>G28X zhJJWLo`K(jCO7p`kq30lL{NMnABPOHqV5l{X}qT!^4};4BI>$oa9*;>916UUS3>@! zr+65lLU<4A$X{S{Cg!;Y`u|kEnX?EX^&>CBzp z^rc%ChE(6UzeL(o1sAFgtkk!ohBy!7X^TQ|6c)yKU*Ty%EDK4bR+5>=%5=?9B+q_) zE`TKK`ZbtK0`G&)oN1p_`Bjg0fz)9mCDfjZKE8fEO#mw{!Z}=(k@q5cgc-J(!2^B3 z0_L~T{*9Bb&j&?NsI5ifTA3{U_5KX0g}IjK+|LgXqM@h9J1fk_ftTDHDR^yxtH0#4 z;{F*JRm;dhf`}KPg8OoR<<7l~=xvf6GVJEI=jGaE9sY%Ov#6#<%|);+?m_D6zd+My z@VY1tObu6i84oAihHyIgy<94iZ)J=6p4D>&PNHJc;ws}5Qj{s|8z101hz;h>lG7Ww zN|st!ZC(J48?x)HtC~~S6yTyzFC}(TU&gfjV^%F_wd0Et#6jrSkSF@_6%u_a`5fg3 z3o>I`44bdIMQ`~H9xSofM^u>DsJTo$FRLu6-(oZowDwl>VYG!5C+>~|da7-yXjn7J z4yv~4)~Z!2k)*hKbagEQcGWSQSsUNdW9WZ}XdV&e<#DPa_L+f5?lyX}xa;#xGi?<- z461i?A?a@sDDdgm?dWkp2`{+x2lDczM`D02`bC*hH;s8tisOK`^+^PVJ6D z*%D>^PT+y;6e#H1JdV)qq&W@AUwAbzQWeH12jBpSa>fKQ^w4s6&6Z4Oo9(S*V}vr< z2gT7MNsB zOgt{nEU8!ceg_R5mt-k!^*j8Q zx$YK0)8_{JwkkN2jDMh2Y=!lt4FQmOb#SDvHssQs=n0xPgy-6+)>yguCKh)8Nv7tA zOHcR{%;%=ck4kLn7dS6l>RN8~MFC6A07}GKxU*OX3o)GXc?jL%+ZAH7Fx&ynXV7}y zXD)q5pU3o{L0LxRj{hBywV-ZRn}z$Oy30y`rENSp8R9;3P$JOs38PY*Ht3psJLkxx`q$IF*ncH3yeWYBLLYcVP;u-2Gr7AEU4;uXKU?HQsi2BPSEOLaaxAXmDZ@R z%xe{DvywAJt~LSbz#|5oVOy^?Ef}tr!w6e&JajGG^+x6s|w-5Y3 zYe$61K2oXBnLCUKO$~;$4EK{zFy^2YgJuUpeQ-Zm%tm`c@bLAmJj1O>(Rt>WUgq9< zX6^%bj={-7RJ%(yTD@8@jkoWCK&Gbuzo|ICL(yJ(#zo=#LCU78`RN15OVPZSSTjsC zuAx~*HC)>v)Ni?{ogW@Dt#EHNyr{}&X@`+eT^955A_ zUTc=egKJAdJIhz>h&R%u>yo1;x)`m#B;MF}8QUy)CW9{c7;d%#*cEc|U!HjvN3e|9-fS`dw#w|5Jna4)y=RV)s&y#L8?~Jlv2AyxaOLjk1v7Z|d8$~Bw+`g00j&h46zQf5yTp#tm z@bw4x#f+4}`OC&LkF!fs`$QB}m$2CW%7UBYL0cw%#<9{=)o+9f-?`atrtmWrllaDH z%fqWKBlc#fTRzx8Pkw@12bG09UO;L5S}@9QYP=Mzx$GJFL^g$O>h$(vpYOa;k8sJU z6vr>q(0Hgdo^!Ce9BpO#>_u4M(1z2m|4PdO_S9<2R&?%^3YAx4(um9^&e4=F&pH5F zjpjP2m5RP%nB<{#fF?p)CXwV%I| zJY*Ef+gijx&Tma+9b$_B39aaQe$Xoszta=+S*n`Sbz$t}+7Q56Ugj4rCt}-1lJ1J# z^HCr`6Rq`1yYKFUq7}&96=s3pM=v1E0EHJlEp`LJ7Q@#|k7TFRAycwN=b%%Ij?75p zBlQJ4{`=g4qL1akWcuQ|Ce67xh_Kd{RS|1Zo>i5O+tN5?)aT(Y2AgSz;=MHipiN5& z;ZvwAp?1tXajfTGohhYjS4OK2;i+wRQLIXHyIxpD;ulmps3{5DZ~|dQYc3h*1I4$u z*RR#T!>*iuxUlJFv#F{_jb6ybOw5m`qvj_=b6iL#NgB$dSZYFq94h~Hzk06D5Atxl z0pIyv?ytlex~;NGuSM{iNm^$@rEt1b(BFgF_>}LkvC%GxJ+Q|M=m|;v^0X#{mKBqT z^vz*DZR^YPnX{>6s%!F?hafAy9dudk9ZTvdVxxFNgdI7Kj^OPAaum~|T-NSE)O zVG0mKm1ko|^sZNh5uq8os&Oqm&e~0OR zz>Sq~m1Az`>fIPE3A6}GUGvq7?F6R@FTmmDiovqik6~0EcI;JTZ?Bhwco%Z8`|xrY z^{S~hwTwN7B0S}=7GGn(#zUy(KL9~}O+nj#S)TRV*2cTMu~Uvl;X!_{9FAl*KzP-v zfxOS>fy+6xx3UrMr8?&bUU>Y)@>drFbazoD(kcD^Ms`x_R{~4Bboq0@(x~rpa8>$) zypLZz{N&F=@c zL3R(3=7Ly|&D(P*956 z`rd0uq^2np^1ze;1)0TMmC97mA#N%=uY@BTNIK3P!6F-cKCeb~+T~c!xm}3Dj_uq1 zGJdl*=w0!%#hOyhCB6kDPiGLC z=#N^w)gvBrbbqHWaQ2&g5@&+&M_M|u>DRaj{5tUMvRetZ1w&AiyZWI~d@A~P-eb4< z?1eAEL!$UU-<6U{*PM@2u72toKl8}uM|0EA2|pgU^9-X9S1Lr!Fe(CIkmp}MMpf@0 z_HDYRwYCWJ=5BJ0bCxC3KdcS=^j@U}X{LgF_LZ;`93HD-dEdJ9cKhu!ux4enAdYPB zbPM`^*IF%pzjObISgwj}XJMLRATYm)4p|jlginY1LPBMc#}s>9LKcpX@&0pY$Z@aa z*KZLK{?PbXU6-e!>S{rF!B|5MknXI-Z-B{uDd2aU1Pa3)_9OBtsCwl)g zCxPAmc}oD^ao=2M@FiY;{M9Yx2Mwg#|DKar08lK8d@^d=`y`2Q1wVf2*tj@4XZ{NW z{G2ee-x0Y=k?%GTF3|V=t{ywzBUAkxgP+)Ai@%WA^4!$v3vFEVmJ_UDT!wBW!g6Ec zD)m$UsC^;+zY!NJTK^y}4lSOE3yJsTr4{`c@y%N?3o)TgGFEJ5$HuMGu;fk^>Mu-t z6OKKGM014v1E>2>tERy)Qoz-C18A3A{-dal3EODt;c+oJhChi5or`DULL|`#BBgu$ z(po#?S?j&*1go8scwMmsrsl1kqTldg3l=+wt?KHn3?*N=sGps2{uVki@#vC?6^Ao( zJM=zmq2_4iM3Op)auT!EE6r!6GZU+z;47D&VeF(1&%?E{R4nR%sMl%!gVZlKKP%W^ zr*#OXK|ZH`F9Q4qs#+`Q10m9vw2V>4_XT`yhR^DV3=t10_H38Xz9t2 zWlBBW-!+a+c$nVv6gk%2=PskI)%amo>gpFPnHm?9sg9hcSO5j0{AR!*|3YPv1dsp@ zcdPZ_V%)8K!HBT-b-XI7zbF^vqxR5|J@8@d;oLu(iiUMp&=-jYp=@!Fg^5|nkY5nJ z_Bz?i4;-{IE8qe%;*UEB+%Za|h23qJuNOS`RfXNVlX9`~koUtMd_faetkT)r2Snn4~vm}MAT+#~dbArwj>>~x3&H}n>Pk?8jQ zu(5T>exOBtnt6{u1t&)~${35O_^=Nj%nfbX(hYKAn*DCt{Wtg)m0GsG4`t`XN(mQf z#FIkK2qA@30AS)y8co}rgRbZ^xgN1>46JhXP#w_kdhaZS-l<&I@ggg;i3 z_0sY@6|~D6&n*EnU3#OetA#p>l(J=xH5at&wd8ar&7s29mNzoKb3S)0ZSd0e2Fm%M z{OFjV7h37)Q{V`gpzX&OX@?=Fj3`qwinIAkX z8qz+-klfd}P{nK$kqzwc3r>2`3L11EQwim6v+_A}cbP>6%a=5Ku6mpb!X~&wxEm(> zE)OA|fOwl{U%)%m_QaEuT{Bwnn?#mXgj)fkFe77EP+Q~ zcaABy4Hac5(bHUBiZ;Y<{x~3bD`?sQbn5n*QeAdH>3K4 zE?Ug^9xZ*LhS$Ps4_who-zk=yv5CN4ed650tkal7Xe zGSk^Mue)$wDSs71Vcq@s4V^+)JLN@`sXQ5ciS6@W#6wnK8Ar!}-B#4M{SW(@*2n{M zd;eq+zv#-c4BW`pwzrJEoU0?fLsQM{`6^EZp=wfYDx8m=Y^fOIGwnDK=MRK+`Y$$R zwUt2(JRCNePa#Ce59M7LA!jCWC{glXRLuVmJfuf){6T@nT~jw)D^&%QkxkCrSV<$R zldv^7Cql%OZyEG`#~ySUso4wjqGM00f%)_m`9?yKCoa^I92XphOM<6|1qdw~MK(5a zyuop9=ldIn!X7ph=^kPX?tZdm?em0B70$*Y#<(_HK;zjHU2Y*ZN-mF{qUNUj5c~T5 zeD>@?t*M~t>UC-q2?yC2ewz>mQf=gYpEN-iv9H&~^xyNx@|#%b((>pJPgZ>^-o@R7 zML4s5lhtR-KcHev?q9<|wB?U$6v zrdSAS;KGQQgL6SMfsj9osI{%)caPft0T;9TuCHhSH1i~H;nCt?CqS+ z{%$ori0sWr{q`;-kg()yOS;3O@*)9$Od4NX6^vhUvjL9k@04qQlvB(D773YEGI-=X zP24b=#_|lc6r_s8-Lr-Rn>62b+=f*Xo<{gH{)(Y+)?sc4Ur*Q7MkzKWN*KIps?dJ1 z>r04yo%;eK6u)^+(!3Vw@W2BhsB9i@vQ)LTOwrVwj^w=q(=u)QPk4yimgiw{ct&p) zKyMuL=9-9Z>&F=#1MS&c-SVv2cO2jvEYn^<>|oW8alVb+Ww#vM_`lILM3fI~oKBxmH7_|U5hb5+ zo7TSxtAilTmuZdEDf2Jv735IdfePt!!N%I32JXKl7!Nf zCQh4ejim9i3fdA__R6!CP$Gn2R#B;_%T(E!(YVBwdz%k@dD?Oxn~_T>lg4LrCqi;8 zB0Q?Ke}6ypW8-b^3)nwETnl;4xZ52W&;OZkK!q*6o;9(g(t(?&mTPJ^_`)DCX_>!5 z*0K|KVKYvH{1%>c^#nEJ0DURHcp0?@*T%iG)YxiME=6|{?dmM5nt!U?~;3>O~zh9i( zGaPj%Q(S#SrlUfu&RR4-Qj>mEY7RFgb-zun?T{(2zPsAe%HOjdFuDJdds3;FNn6;g zU$oAnZdRYYt_B1rGa=L3i}JWDaF8Rb zl&{RVG1cJ_J~P_imZ1u$x;J-Wg_#3g>RP5s>c5+~od&1dH^6#4?t&)5%2rgneO9QY9Xt0dXeaV{ka_M{f!p_=wI0fap6D-q4mtGj9fxx_i>QHm=ol zdA1UFI441`JCLcdsZjezLfXCOE0^tz>z%wEGaRQKcYEg-XtZA&^p|=WDnjakzl5IG zz!ht62rQO^&+S)dT*Jb|53+-1H$LAq2@gI#u`3ogZs=UYZ~;SL1KUxhCAa$4Q!MEF z9T(U>jGPkvEIHuYOa%3xaoDDK(F8`?5)yYh$yR!1)=cJf{Fbh`)EM>yv05H6B_;Am z@|XL>QrM|e!1YDplZGS?bnb~u&1Oob&d6eSh@(M?u(K4_TI8#vC2<}F6SMg}yU zH649>WFh|4ys}SWH>!Exd$Cd;c}DK6d6DE`Dy)W#N0hqtX8R)C1}<4s{2x4LoUI!Xk(ImYf+bH z+LqRA3q#Kog4IRQAN)M>Tc?AluRZJ0oT>wpF}#5@OU97*U)n+2H_HEAJaqGX7PENf zLk(Md*vVXn2EiBYphLG&^7VYHNH@ys<=8`{zDLPho3G&y39OGR*m}(Jj2cR6U7m*x z8JeR6Hs(?-F4%>{rsIn#!3HA7oFbWGBIw1bOp2&>`?t2GsA z;Jbo%S5W*P)(QtDt8DY(FMmQDKO`6$O6_+L+XIe`*Wue(Rpuw>L%9%4a;Q~N9zK5q z>cER#>13>>{guBtA3$%(KsG9C42ruQOcIACVsTe9cfYX9>8hfV%La)tOZfvDP*w!w zap%{B#D`jtDhDHT<9byt?c-EPjiP&eL944%ejB~W+m|dWG75q}y{&J5Ytso#2Qhdf z3-qq9Lg|Bp(o{0^7BwlHEs=aJ|qm)O^uT(R~wK)+dFggsW5G}o5oO=p%!UA03VrLh8L%jrFr97_cT zcUMdMz=Kr-zqwdishQrflbj;QAei|8O)P&gIFkP-I zu9)&w;c|N+MAZka zHR+V^4kPQz?sE)Trc~QGwVF8s<;$eZ9Kyl3KZoLt*T)-yQhP=DBDBc0c!5pzN^6P5 z)-F?!OLeV#e#VLivMqGc!MdlZCoM+q!#qhEcAOr@qgkQ;A${o01B$CS&G9WEN)^b= zX71xd1=XP^1^cRZy+Z>0u-sH;rafG7UdWq`f1@tW{-7?1|1;_WrjY|j1Z?G`2cEX1 zE91q0BZ9dpxG~EuB@v(Me2cf%^!~r4E##hP3y(vizi11%YqZcOSMN9k&#NeDnuwPm zlqVJ%Wn9@(CWCkHof{uABfAEx#cn_1Dg9bQ7}7o)V00Es$Ym#(ajw$w)%mjUwerPO z81wJj_z=l%@zrpL6CUB(S3Wr^HbbkEJ_!$Pa)|$Gx=>ow_DMV!v{;f0jP?;&NArp& zyf;^P8O1KV=!GS7aviv#jOKo++M!b|m${zQ9~2l>Jl~2~>SgnhX>%-blVMD3F+(q8`!?!t6A z%&qQ*l$U3rm6>M`hAeg6j$JkLa%}pYk%WX3aK`x6SsQ{RP#!olRvvJ}at-IBo^8-N zMFg@0=rgWpg-manIP(7!BBG4XSJtWRJR8l@WsgR+^LCy&A00chrOnQo|4j)WvYoaG zd9x@jZ>=DW9I?%!L5TCOLb$4ZWBJ?Fj-7MjA?z6c7S(&|vYISMI|42p**nh1mMo)= z@`{&yF{MRdt6t_9*uHI~<@(+oeQF`+IlqkqzBOq(U4Or4n#OobtSS7up>cQIp49i) z#c@bOEqJ1IW5oj_&?RbkVQKEidh1En5*u0$Q?sy$WizkwO*loqbUaA7kEOW>-YUS^ z;xono2$^7?-{DI)96yv-Wgw}NxwyGm4`=gCbpv9G?MMBle;7eTB62-0+_`PT&(qh- zv8|_jhF{w?T}-uAXAreN%x^t}ng!g(s?f>vLYyFy;Bb%KL&4uKk%A@HABKe6Iqwm! zn$=c{g@?w`jI=F^J7*UJ&(u$c`W;@-dHZ*t;LFlw62DxRD0UQ8xjBXlETc!u&ADC0&D8J;Jd*a(kv zA&k$-!ZmA{`Jc@r;DVU1)O@8?^+AvoWhr}=lzk?%$$i82uEnC3EQ2JaC*X|i;QK)c z1!in4*3`{o=GXY{b#(gs2k|f}oKtGC?ikV8Z-%HhkX1*SzuW)LE!=-XrTC)#;h9>% zc_tq)h$tZeP+@uPLqDS&f)>ibh;Y(G;y;2GTznAcy?^?lJ;5FlQCTQb$D=icsWjYk z0KtGP1m5c@iGUGG^uOsV>SUrB>U zAJytl$!3t$Y%Kt$8YNe#5c)uQX|qj*@=Yuy#PkDMsraoap8MIsVQ8kl4{}r!+CR!c zc-K?)&!K`=T2a|Wy*^(Ad?^t^yuXDIzF|G(SO+OX06Gv$LxH%S4MpU1(B!ZW%YfFx zBy~D2whi4k+$ER&+aY>dpD((pzMeDzwX%@vp#a>NZoh4v=-n>Z`St&$j@e%L?~ z1;L2>KKz6tCZ;P>2TU{aeTMy2F;7WWg^7O{Hz4_g&9xS2g-u$KW7|?!L;3}tPet?n z-}vSewW*-4jxMiFa0c3cK(1s|a3zHCbnGmcMu%*WD)6)ViINdkJs!&)oOSsd)PS%> zqx7ifqS}$CY-oErlR}~OY|#*=kauj11P(!x1(^_whQanaB$G&tFDGx=K9s=?WXincW>qHqoB?hVv z?edAtu03Q2|25MZ_EZ=KA7~&=P!`vUc3v^~4InP8ALYG4)~0H_WyIS9iK;;I0!NoF zf5lKaL57WZV*ftOs-QB$88(^w6bHqUy{Z!Q7%zcUF>XddE%#&6`on1O$~zYY%K#0H z^?a#-wwb3ddmgW4^p@9HE4s+g?f5O};wZ@*CicJEH(2xj#s!2et5z5OgA1tU{s$Mp zyl2Aq7yPfGi)EX<{|WIK4nMDNs^V_S|KPB#=-&-`LsZ+7yKinL`n1kTnfYc)-`153 z;_hJCi-1-EZ8k0Y+^Pgf=G}mt*gBi#flP&GnKDgzzlOChMOcDkxvb0CJf+iy-!>@~ z2^z@mbHc9&fE)$|KG+DPT$A!ib~n1E^+{kP{{;u5o6w(Rb{fv@4Z((Wdc%hgnRRLc;2=LP?N-5mS0}MdC);&jM-$=m~nZ!nt&jQBLErT*^ zV4o6a?OL96IfkFHn?kXv`nJ6>GJaDT2B??Hic~uCV z{;Q(`4)2XUKN_9jI-I^M75Gxa!Dsy6CW}f!3w_eNUX%4^I}As*5)^rEF61RNU|7L zC~rL!&UMU#`CSeZJDAR(kAEx>)_@)(6;dhprb4ce`PUkb|0CLOiU%)gg>f?-HC-C` zZ>Y-dcqk52Xk5d~{Q{4uc!)tie<&href~2#>OZrOf4QR65604il-Jooa?P!5*u>`P zvU_!q&Bb8bx@skboK|ChGubeNPog&{wlcZf6z8ehBshUc-x;Z7>d=R9ybl;e({EiP zU#Lt|TUA24X;MA3hL#1-{&rLt++%!o!`Sb)KN{O%T8FM&Y$XhmRw%1o@F{FeoIs9H z*7eMXjfpEo*YQ>Zg{DxY;h+gi95W{%zpN`$n&_=tRIXpcmSx&@^jyCNn3sqdl z%60H*$W4!prmk>>_ ze;AxPG8iRH`W@kbP2&E7atoqjPv3)a&U|fkHK@K{#3hc)>%eZ>pRbY%wU_v&Yd&el zr%&;OhxsSirB822i@fBH+3Qh|j}y=^HuRi8G*$|A*0t2y5In`I&ZkOwxw}pFo@dNk zi#ut|Rsinj`-caKf$85ZSG5N5o_#(7lT&Hhlk8=4eiYqO@|V#h-Vw0Zb~N(0B9%Mj zo;){WUP`?4JEFaFnJ3l~L5roHj(CXggI=^0eQ->Ne;z>U{*lc^WdFBpuF$X+>()(( zBqjqGvC^hdnT^xE0=L;#I!hsUdy)u-ni`cPh##Wket~lq^UZsOxMKnKNE`67(`y!T z!#BG~cvDK;v-39rmhQB^Om!-eIQ-`wYe|2uG1jq8>Bvs zFi7stjPE!*q>K!Dnjw(C_xnt(hE7(3l3%1$q`g7;P}_R#&Vn%66VMS13;gajhWUys z1_E^2rvA;}^BOqmhCfaRZy?)9Sp5n(gF2PuL z$>a$xK|i9Y@Cd+Y(7annXL4iyC8I- zyzpM}1y6hUTW`qHn7a^^Ses+!pI;Lf`(8QO(Ghx?39VzZ0=)Kp+tVVG>5n}r%{e`` zJb=(dR{r0T?IQT+P?K`dyn!^!#VDh2`r`W=;>*d2K70yqw`Q==-3+}g95Ku@gb{w3 z_py!)tnPNL=Y`l4F%f-S1ia{##xQp(?Nna3RPd0Wi(+o&QTk3z7k<{B=2G$4ln*An zNlE^~c(a(?^1|II@Sa`eJIp?zG_GJ{eo@oNGfWdv*Xx3$`WhRFW#EP0q#5-#`Q=dE zLzeg~xuP}Mwzx7k534=U@ZVUR%2Q8rn*#=&CcWOhs$iBWJ#L?Ss||6ZpNN{qB>V$t zKpf}$f9aacaO!5*D9ooXGg^#B*@a9=B5P+ zH_oeNz^)gZAL@j-rJ}ak7Pwjo(%(RPI?H^wHCc#7J=<6#-JIEV{wesJD^}@C+{VNb z&0~^gtFsy=~vB^T!`u(!MVcF)Xr@k?sbwtITWym2gl&049j z1omy*Q%9-pN=||>RKGT+&78!e7YED-Ym$UPG#dq_j#B7nfq3L6QA~R-TKhD`(jwTPPJhf zb8x4ckHxCQ-$RJR)yajtwS^ONV7K|G*uL}fE8Yo)$fQ1`*Xn8VH}7b>^WAPw@(#B) zT&&vqHX?NzVOIrDm+Dql?E2MfBJV#$9phX5tL;zr28h7{{(rD;wUg<}ZnZ0D=jmqx zWBi!=sbZDI(OL!P8GX>UmC!yP>#v;h|E3o=>@X?hYJESl+BU=kn%xF z#a-sLC^Y~$wn&vqG0(kT5eS0Z^>C0O=fqYO)r=l}2gP_4s`)J`n0k7^g5jSWI@=D#(e*~aU2rx=k4ll6ww@o)(BCkR{+kb1%0tu2>`w`p;?Mo z+Vow(#1xEvJ67P3sSTqYOGc>{+TZp;`@qx#R9BZr?AIMLHdik5H1S3^HsmP_EEPaG z8xfh78sf&JX&$YhD4ky#OUX_!|?j0dkR9I1zEgTq924i`1rB5^SqdNjSG}mY*bAu&P#|Lqg@pQuJlG;@DMm5aNwL)IZc=8a@M z)|~pY3A~CTH4^`y5l6*BDi?=Q5Wq-6`7GpPBoCkc8Ps)HA=WJBK9CxNbywZ`p$ZZp zAM2rxcF#et!~q9Y5-Pja;tm5*R$Jl7xC*AO$9}1QCr2BYZZWPC2&#JNRx2Z7r}wrI zk&q#_vFemG#a6YY2Bt=ydm44(i(JD$tDLgt1V;rO@K)mJ@z1|*Ac?Q5?+9#vCCb`= zF7HQbxq9q@z?DPET*z^s?97eG`3@{BkW!ybLBP6Y0sc{a5vDfXjA~__HL26*e*rI< z(X%9{S(}rZueH=OAb1Uh-@=qNglNPUsRadVJ;jj~mSCG%r)|R*i_bz{r^?J58(`%l zY@Q*FJE+y*5+PAf6F#Eevg9)@T5no|O9Hief9L(yE(5)eB}m{#n3^ooZ)>HmcqHj{l)wO`qe}2LDE>b6iMQOnoC7CoDz&|Kskh zqoVBFE>Kh?L_kGAT0y#`8x#ekJ0u1H0qGdJ21G$XK&87ohOS{iq@=sMa~NuX0cPfm zKF|BTvA+24th3Hvzjd#vduHy~*WUZuSD2W3J6o!H*9iQZJCYIXKXP*9%K5ux8~lCe z)Ra0xg)AT88>1}~hSBT*abX8}rTt3AUi;R1L%7!dl1Eo6Nzw+Kd38#@=(M7(&J_h7 ze0Xo*IS9SLokA| zu=WSO^DDo5-Om%TG0*>#!~99ijG(mLr-E`?feKPI%eMe)2tgt6TdM|ciu+Mk-dD#< zDaQ*_%G+yN*2WdwVk-dC;87c~ZP@U6W!}q&9mXY38tTJkrvj5dA%BU@Mp1mrx3LzH zPW~D_%HR|@m)qBUdrCKJIg>_too!>4+2F}lQv~dxF&$_eo3?TyEN;QaPP)2rX9 zEe)>#e>>L;Bo`M`=eGj}@3-xuT#%?b0&Thtg9QURMQdo;jgkbhub%tvD1$oW2+&Q^ zl~q-TJ<#1qd{}~qAu2^aV32HY!cLRv!)$rlWy|fTH`umrvs%v17TUu#G4JLe>7!iA zg;|#{OZ|FmjFH0>!v;=iiIOmze97H^S1R*0Sd zQ=Gm3GL7|P94(bOeB%}8d8Jn+_RsF$BTTp-cQ(e!%vpGG4D8w*`~dq_lbIqM`{Y?+xs?tVImlW zn04Q4*;NilZpM+UW1XRNMqtuUE2e$lwb>jg;N(K;OLW=G@Japdst9;A{$LNIX^C8m z{OERE_-?lJ1)Sr>gzyph>^$L?js;p-Z(SYV2S5a`wBJBvo(jtBcA!aoe-&=TG*4J= zPf-j?Xd;WSMd51um9Vu?9mbr#6x!7s!;SS?ccqDliRLvGQnq~C22m|8eVtyiBfjDk zrJp7__v7^OoXT9ka*gI(_E*%IjOyIj`eV*|i4M9rmKF5)g)UKRfAuKq0u!wm2Dtip z(?|@*tx#>kwZIgg_*2Jg0Qf(uzo4b9b@{B$`3UkUnqb$S=dr|XXE_IPnO>o$G-3!RU)f7v$^}Vmi_&nq78W5GG%e|@2_MU7hZPV zHF)(4n``idEx`ja;{W=3ppQ~cK+hRuY^W*sb>ZdLl<3A5~96BPMpdrm_Wu1O-7Gm$EKOLOeTLvEde@Wj%tTMP6No)n8R~c~vDJEE(^Tt37#o^Q7aMor!V+#pA6Z(sO1Wg`F?Pnn~M%o+XBs z=74ls^ZTzf_N}$FxwDIz%%?ttH~2s7EA#k9!^ooJ-~3-C?e@>VOWJ};t!&(>+KA=R z4^$`euJ;OmLDDbQ>_;yPnKyyL_pYuKs@WNQk4E^8tbd9n7JvgijS>t}BB+SkCqy+j zdB_zW?#fmxVAJNXeVk?;w}3OeO~^1qo!G%Zgxh@(?e^dO*Ew9+{_CffC1$4AbNnh! z(gcD8@N>%L;tj<6S^rp)|NqS^H3C6shd5tp6J%$EkCGnQ=kkQ`U})lxxNq-y`qR_-9D ze>kEqIeuFw%3BMc9=Vngn#ksI7^Pp-Q$kl-n9Y*%)%genr&r_#5JVb&mc-5APhSNl z!pPlyGO2edG3%dO=WJ_G>c;anXKiO~oWY<8soY*ZVzJ=6m$6Z_F(&Gz6>&R5s&ueW z6(KbIMGR_;athDlV(HeBzpirtkODi!lyOjtXP>;55GjVWPpgw)oA;lU%Q6j6#A$k` ztfEA6)(HQ__54kKUGgu#rW96*lX#2zZ~^4{?B69l6jQ9>s`$N}E1s(1dU9IvX#Gd) z=*|1&5o{346m0*6jn94DM#H8NPoEn~KV`&Z*cp&rlgsrf8m%ug)_e zRspIvzV`K-%{ZX&HEZhx&N~}_4<0TVFem^h=kFx(9ML}pnR&&NlKq~;%ehOM5c`vS z$x}uReL5|<=UohdbAm3D7$u`~486*) z1v#2!WB>FzZ|Hbf_$**sR1l2V`X!R;kIrbKW@24wfvl!41?+s-yTM!M)I#FjjinU` z5$#QGx9Y&A#0e_!v#i>HbOLAD_n@C~(;R6wKI~}LE$o#T7LOgKTkL=>$n>9Fy~7_t zd|8~NYE~~L>o&iCV_IN<*x7Dpeam}gZX|xD16e$=sHK5B*DxL|&Ex?Nw6lA@hi?jP zq#{1p-f{vxxjs3OZb*Nx@IIA157D*uhIlAuZe*4=ZMV=~_tvb(t7r>^59wz3k1Dus ztEkI9UBoHtr)JmCoS587G|cy{3Uy1{o?5Z}t+FYjw9^%2%dcTlb{7Id#`YlhFsj9sZU zIrO}K@s`tb=Fe0ADlN9>*ZPV4ZZLOzMrg{f3J$yKLEe&@{leg#Q0x#(@kC@ivI|q# z5&l}amBGFKGwKX~*r_MdH#yAtOi`9E@` zlHBPDkOUTS>O|^T*l~Q7ToVs8(!B6`g_DRC7$Jtk*`v38I$Tsf(|7+BXFpu9hbPK`-oAjf2$zKBTm3)uNy~u2f9jKD%&gxgrCz6F zEWm4We+qZ%7m~1x5zyWtxojD?|SeOxg9%f+%f<0vA{G1xzgptt+>3aH`x zZ_Z@oQ9>v8UsGxRe?SvZ-~UY$5G9)(b(*Gieu4<`L>f#tS#?cwPytpAS=pHgEd{gu z(l2fOL)IvjkKuq*$ShW`EQ`TfWpB$uZ@}JUir}srb{ZzN_L);nW$ym>>Ra@*@_G5eZ+|UHKMyBw1 zti~_B_w@N((p=P~bJ7FvubeHul|h~jH>+u&g480e<^8aGoj5HyrzZ#N!ka&&8|D@qITvKIr>xGF}}{HmSe6$?bkyx!tq98`Y{lg=oyLrQ+5H>8 zV8kk(vcS#@z#cZSjmKh?5xXilX?!m%#3X^1CE(kXLt+SUi(#L~_Gdjp;o`l?;?9Z? zPS#qrht$EI0##aMj_$l}*=o2aYDQS+Ms=Cr|G^sE#>P1h^GrT}tG^r3Ec{jFBhf&g zcF4`Aw-m)Hc*djnriCsWp5ors}}Ls+~E$JpfuBbIP@a?)BO5!12jU(zPz ze(d<)*=nDAP5)dy>*loax41O-xQdiaUP@{HO&V}$mOWtDEptU! z@2a6*=@|dNb*tZ)3mjVsu4f`p;gCf#)`ow6&$jMx_>23%XTJ|j@!~7*EJ(Kq7&7*G zqs_nJLioN{71i{s`L{D=f!eq`N5Kd-DPgffP2(-UD$J>Y-9p@g`p;Vc-MohC>U(Kb z8Bl_m=%+jC=~`Yt3Ys~sN@GtTspF4e7A+(#`aVH6Bsv3nC2V?*uTbdK zt8Qi7xYqB%)kn^I%9!XPC+A-F{g(9Kd1PK|FQ4OLQZ0Mt|J6J_kqU5p zxo1V$%Tk0(?e42KS-jbi=j0&Y-doi$dC)(4CG7E-ZSogbrC7L~EOaE>lXla5gH zB%NbNNSg;w-0~SIoB4WNK%u08_ zto;INYJYB(hrEQ+ZZ=H(R$jlsez_5QChYRI{1=@|2278A*t(vlUh;5?Q8*RJsmdW& zJ4ab9<-NG@?LbK{b}`<|ujQkw;A`oRpU!2pLX1YP-}zBdWcWl95leirG|2@P6why; zJm{M&KlE+C8aewwdSH}e&222747y+Mlzhj_^Z{HVsY~nL{m2JUn$RAv&?Z@I@$OQLbxt^n%mTW0@)PiMi@s0Vf$SQWXGD9YsAheZpen^CXR=+ZWdvspD1|S?#xV? z*cUACUgXr}*oR!?S}eS8;VqnGuHre#Y-2ul<#*nWqi~SfI6B*0mp=za5u6@G_rdFL zq~y?+(3CLkl-3KqMeySvM?uRO`h;cvwmfs(u5eVw_vzkfcNsf66J*%DPJ7D1qu!u# zP!aY;!=}DA6Doq=xK$#kYYAS&0M;f!bRz+5Y3wAH!P#Rk2$6F%RPqX zT`?KtCuCbepWFkicZDz{Fk(&tZojJ7&UZ3J`%iKdlE$~_oWY3^Sc7#9OeC!80oGyN z&7V-XyaS(tn}3FxRN-JV;vAUSMCk}TyjHYJK37FwV0P*R@i-@u8YY4@%Wq4+5kJ|v zTbL(mYxsPQ@g>uDduQstV2WD2dfRDVf40E}kQcVI`Hx+9f<~x1qJhGct3X($ltgjOJ-(NU0(niPXkQvV1e$PzH!zb3ZR(RDng!%4JbF3O-;<3z=Yuq7?0J-QY`C~ z6-m|?|4N4RbGKjZ(|m-katH0`@6IJ*>rXGr8sS$)fuvTY0;QvXV9ul{`m7JZBiWY1;qtU{2M*SuV0p z8v8#-E8uqhR>ebpO)eWW(j9!#JGJNP_>Lb`Wm=bQRi~oQHCpsawncQ1-X(SOT|{GQ z5MykGe`D)hC)&_AXCu$tpQhLu*`O@3glZ2ngT5y28{8Z?YYgQ~?E3GM7>s)vm`z zK68-;>w-_#Uj3-~_fWde8eNYMrKKN$xG2Rnp4_bZ>^#h-<8Kkd7W<+`#*u(JZ^6-x z;Q{F6SWc9Vvq6TZtdQ~7!INJD-8WwnRh$?hvjH;^YFm-62E91CpqV=vh>AMir(s` z2oV6W>SlT+|N1;tpULq?gU7)*$kjrF2X^o?rD|GL6#wK@$Y%W|xf0KPOeL*tx46YH z*9B;z%wb7fRpun9^}Rw^1RZ(yP4YNNHj!sD(tnw`oyv(5ig*O}46(@-i84#WW^(Ic zCOSHoO(|5d+InGB!$t8ORBs-D2DDP}-$0e{2vI?uKQpfzIub@I$tAl$=il!J3UPXV zlWS2RejUXb(PfIZ)JXrgF7!X~*}_PHhD~?gW(Gkh`I4KCyw1Nx*!^(CM%dk4Sd(8n zcznt78KLfxJ+buy#_y|g7!V~l$mQ7CY+BsX{>@TC$#OXM8Rh%exSK9P@n0Vq#O1ij zmlvwI{h+bAp(?0O^W~q^$*uK=Ivuba1IGzF$ci*z4{b-}BP&+H?PhkRJn+5{{9){o zAZMF9Y#TX_R7e`1%^}!4e`jgdFqV=kn!ge2?bZo?fCzY~ zAB2qpfAbM&9V^fA;Vfm}Fv9n*C~)jdKRhP-#J+%$e|WSRe-P6BgL1h=@`rNyF+qu` zyE~RbdXxC)73y|_t+!P2S$LUhUAuP){*ZlnB;B(a%2$v{(iwZ37xhXMM_8NoLz2?t ztsVauPHY?>ZiG}oz0F$+FsS0a4gu7v4s>~(Iyq$W-}tx1Ml;0BD_&&Uh}}SPjE3^4ta46z+XP{ut4loJ$>zs&iYtvQ0;aQW4;OD@hh@~f$(Z`e%DtDF9#TGSyL`EhS-5+8`i=W=hPL!H+8SKCEj+>XKj4FIu zskQNvz(4y#oB$7Q#!f)k#{IP<%D4z(A+}ayKgURYr%2P9o3+6@w(m-OjpJTdScK@V zZxleifGLK|+t|-~1~Yv{2+)b5$}aq?mA1$FU-JKkrnkJm@7CLO@!v{Vvfa<(?0*x9 zrGIL}*dU$vGT-y7^4?_CR~ETc<9)7p!Meq|!L;;9G%T<@AXGZ;yQOSUUGWh))ryfB z#u15Wg*rVQAh>{p`C%1ZGlSOmwc=7p+K@{8dH7?#*q&Yi_C0NtJ6KF`cx@ z&SqXBmsvy8De%cEf{mkz>0P&nsff=D1&^_M;<#-mjx z{%Uf_>!q9$E!E`so0DB5i3sb*Vln64kxL_bvwP6mZkjE?s!}|hCe(e_aqCjY5+3kk zl;PkzCV}d zAJe?NK4OK$31<1C`*UZ)1FPE?g@sBn*=JHUnvofU94F>d-9|V#&tr{Gs;e%nzdc(y z+0SKB2NgyTy9j|?pw!r-=>2zf7rY7yvam2aq>=vi+Rm4JAZ1>hsuH^3qj`O7My+|# zIjNG3bE$d{h)#DZ_AVPdGonOp)1KED~f5Nk5_{S48BUv&X$3 zZYI3eW~~BLjQ2Jq9~kncHPnk1^+<3=NL2>Jg*{|x@wOhhVAv8``Z}f4LnU1LwYut& z;z{!ry;`AJfLgV-cJJ&8u@!0n4;!UTG-ZQxGq~{t#7&3;Bh#PzXzJKo_=D>{3UodNj60W=T)nqikWeT8S zo5mgu9P4e48S9KAtgT}a#H`45PT>yry5{vwNie@t3JdWbfQsa?JIPzC91YOau69ts zu3MxEJnNI41~^58ifpRY;D`l>-IY#xvW5tO?mdpsVMLNpmuhgk{cOh;YHDZTd8?gT zjCS?qu*V+d?kfJ;Zonbc*lTCY_+OkSFHh2a-P<$BTe}9so<)WLF>lqU4CbRkkQ~-4 zM}yDaS^Fj9ZTki{ozr~b#m8Be2M%;6GWdD4$`7sAnyaSNNsVVk@s^H+Dx{A&*D_2b z(~KRo_H3J*r-<*PV2#D98Z@X9jwilF=jXAg_3NZJmRq?(DGNZinqoegvTv=su300! zg_t=jh`<|@FG)Wv;nut?pSz^{x3~E`>zlAG zo|C9Z^)s~ixl)3MjLa?~mDP|4%vuy_$78!W-O#mws;b^}pI+Vubk{*-a)8}<2$k1t z^{zwFHkUDYLQZ?`(4R58pjnWUyKgmS(J^YrGc;r5HImGD=U8eHe6SUQI#~g$^GI5+ z#;01T%}LPez(G_(#0li#5dPQYNDUd0Xk^+suAF<^%jwJhJa-cnAZrv)?9Tqxn}LNY zc?Z&mb2A#L36N{#!VKG(QnyCgu-KzEwwZ@vd0cw7HMOY1!o@o)Y5xApY`}-uaN`ym$k6 zt!2KTc53UZ95D+C`!J<%44q4!_>rrQgX8!f7q~2sn3g8Scs&mW(@jPp&PsWM1vzfu zGz8u652BeU;A1}6)8Ma^ZCtyWKtK((m2O~9X*sWBRva9h3cq0s672d4r;Qf7e8%}8 zhF$L6zy)HL$2ZG=Va=Z<`jA%aR$!ke`r7+^>bULAo8OxRZ`p|c^|=I_*sbTd_xf-A ze(-VPE$rs~=g;u53uEA0?1uz$7OL-P7r6C8RNim%)ld7_zb3QtZdx)?ApG;G<%unB zN@4bf+}zws))ux`wi%E-?UzgT+WqtK99*)$pY+&OoK&S@QP@+lni8DPOUK3vOcEX5 zact9CI7JL1^z={7@yCtuCiYAURwK0nc=k;C1~>A$8s6Au_}0&wzsb{fOVEFb-KSUK z3oGX}N-@4h&Ghy0(3oCUt&b;n(x{U~^K^dV(iy3pxjrp1up?c$elS0e7zA?`w6I62 zCS@AS`CDp~EE02yuy#_DEkem6`D}O!%*NQJ7pS$*UMqDR?_z(4!0l%eaF1%4A^Mr@ z@|TV?Sv(GW5&_J!C1=On$|&~Q&SREWw?C+vDqX1_hS%o560jn4JocGNI2Z|;LD|lX zGPg2Fyn7r8bw zQN%u>0XT0Px96K)@R8A}#qBps2)VVw{3C4I^;*b@E|XQ0)~#dNKeDN3XqEAufMmJd zlqX?UU{6#Lg~N>0e)*@8`n$Wup2EYFK4V5IfpC!^Nwc5VLxr)mT;R6>OMy|zlXKH= zd$}8w%!v=8l^;g$@Mqk>aeTdK2ERr=2d7Ixf?+UaJAPA1NfHn(Smf0Y)8#JG6x7_e z8vTGsJ8UjQgpa-xm9Y|3VCckI7Fl$wGu=za-Q1}6f0hw_mWQX z06WYzqCEWNf-S~4;s9mX%CeBnEH(ljhvvu4ESi*F=uJt}`TME_)AruR8r}-rcXc3x z@LH&UXG5UU;zy`diO}TePmQ2HIVg6*-ENU*8vbnDFZJE$k@UV7<;u@Yp~6{ReK6hf zmm5B=)Q>VIugeB(F^==xkf08kl8auvGH3l8%T{p}64#-5Zpv?)Ic2@c&XTQamPn|a z`~6tAlemeGAExNu;;~|u^`ApDLOVHg+&!eEuq-AjBnH0HL*TQ-Dss7?P!lY zu;;b099TmJWjRj?C;F~^-7oU$m#|;l)_LE@UQQJW=II=3#2hMr<^Zy= zAc-#e9KNwCb2i?N#{E(!b%0R0o8$}N?u13k@MpHS3UXtoim@)K*&XiWLNdmMoyU!& z&vHoWpT18B!7NHT+7J7EzVX(jz1#ZTYS2>qChsw#KGEr<*(!=mnCP;=L8CZTgHk$- zG$Lzp!W0iN3Hc6;U#gv*7cNMhx|K2EUCp@p{3E2U?OH|NsfDjt#bePpX{-k6I}V6a zy}~Mfi{8r>J`A>6?Fuo}_4QDpvS@wbqBUOAk!9JhYBq-(0QXX-;rUn$?V5IewqVzQ zz$2ka0i?Nnb%t;;qEFvF*Si7pbu>tdWgNZ6=aj;4eH>n^5VO07%nPMW21Ncl7M$s4XE{ zJf1FNgYHffg~d{_1Gv&XBMSXKWfe$;sPnWN=Q{2MY6Fs_Pq5)rp4G%`` z;sgRy;^{^w12GHNp`JQ>5dxjs9JFbrxF(KiZ zqLd-hKLFog9GLKy2My8z{)V+fB<~Mo6Vu3N@2363mBWpo)3$m3ji? z>AhiN*se;7i&t8@kXMHoy*_=EMf>CX^a;<^*7Gyo{f-hUy{Y)oD#lpTrj*)6V)&xg zag!2Ho6D-azh#916j&c8<>X9rA*oMU^fn;H6ECiz4mBN_1!$nv4J8h&oH(X-VZ{@2 zl`KHUIqaf)*i~~w$Irb|WWMA9Lgn3O*H=0=?IZ{VF}wnKkt7zUOcKSM`4brku!5qr zr}$}XG>~D=0sX~sZr7AI)_Sdrr1j`sjnvF0q9KD`W;-5x|IAF@PK&dYE>M(+7dz$W z0mXW$wJ*(-gZCG~Bc7`L&>YpGg3!}TJAV!}#nKH!m7CC+fxT6QgCSY(F5zNmAHZoW zDl)%F(9P`mU=T8Fw{ez7qs`6;aa3!>1AF#lTWvI-Y9~v@!9dFSiF?SUNRE?qh%2$6156{k*9p&y+Hs;2sb2Hb zq|8l|A)S8eUFX*r<-40E?c&IH)tmB=8fe1N#_z+2F%iGfl)fw-h%rT#pnXvip4|Pl z=+4?>)9qsCmFD9TJ>KKwW8DD7Q>_nTt-tr&xrku1(44UCy3(Io4KUsvsmMIl8S9&4 zG}oHoB61UZ>d=o|1wEPfl8$6|F%A75M&3)e1m=;&evu#FNB)MsQvVBbT@F`48$*3+ zuYP0Q2EVPL3{Ma@LuwrMEW)DYkSgr*?60t7tEzJne$7ud*O85uSMM0{tee5V&kGT6Jr zw3V1uhS_7szLlDnNqsy~ej9A1ULx2y6}PddxItEw@-+3zePdiCuaccCwxkez*LDJ8 zwy~LOVDS^;nLXk+y5&kO9Qk3PjL$MU_Z1g73R?>_)Lm-ZMr;UqckG`oWIu*K^9sN(iW&jI~+JbYu~%OQB7Ys**Daov(UnGHZUb-~mk6H^J$l z{|>!F;sTiBBjkr=^_`hz)lFUyP`>JZ>}V{a#? zLMb15huE|UG}EQ?3}Ka@KN@bwml|zN5{D=K@+p2Q=wZ7ZFt|B~hlWO_@itDNUC}U2K&IjA2D{oY z9Pc!Jm%B|M#j#t)KN-6Bi0>a#HXOBM`JSgRM7VIdnW!?fd4&Rb614bEBDMF7zd$I7 zm!z*DX+j?_K?{B}^62}s=x0;RiJp=YrIlgr`Y7ePe@DtcVWTY~tSW)6y{5J%S8k^; zKH|mY&|f&2Jnp9LksKnWW1QM>(2AD|OH>x9?ukNYJOPP?&?ds6GDg1hz=U+T0P-|*)G5QQK5ew8evH~re8-Xdb+Pp`lPZ7K zCF#ORlKZCT9^bTBo-qt{P;;s7!vv?;0R8VABA^(gw&{Az| z6RzniCJbA0l=a>UYTxxQR3v6lwVhu)o2-!r%;ZM3`pE?oy%5i9OYohjY`CISO_jnx2R3<%?0sgU)$O>QaZqC9u(DIddx{pZffI{ab`MKQ%_+jaOT}_ zIc}c-ZKOxt3J@De1F#h|lDpJON#FA^EEuvE%DM=WA4of!iu0BMlZWMsU#VJTGTMVR zu73oIizo?T3ZR$BIXJv*X*Fq}20ryZZ6Vz=)- z_W7oBFbx(z{`5Nf(V5OPGoLKAYI+{hK)XAdh!j_sq@`6qP^Z`S_|jwX!rwy+pyIG} z*KIe^KNc3dYCNL+P!Dd;y5yQ%W8m~(mBBgnJj<;azheU}8kLAtCh-;Ya+Jiug~<82 zkcF?Mui;iK4@1H`&L8Q*Hny!E2lSJ&Pv^ulbFL&F$_SLk(_Q5$44_)}mcZ+$GM*wu zJJ6X=&PMK1UF8Yt#SpQQZ@lpFA8+cNgJ2_SMU~e`xIiDqPALqSvx^=BSk9Z5!N!Nx zea3||G@X3wm2JUq~{>}bhC{gEA59!Y(!;B2N`(mKdq`W zOzuUC?3g=4pzeuu$x^I`8A*E1%e5?+%R)Sc&vpl1;MrDzUG9^Cr$PlKx<6kll4X%&=j3R|$LzxPA6+ka~) z=`BF|V4fbTG7}uG)^dIIC~5|yl8B0yI$fR)At8ItJ1}4fr#OR|^#%xJw(uL2E;i2T zTsF5kET0&gpARCJ55F_gA(l59<5vd;}jEL{_)=_Rp^IyNEbS6*jxqL@h>&ObTE#t^Aqefhi8U)gbz_7;7MTZm zv$t?~z|9OUS${yw>iBm_Wi)ewS06M4bpLi|v)>0T~NF* zi>bO7<4Nd#mv*AZlzy_MK+CpD#DvddS_zD2s>X@h{HTUTDW+Z5$_Te;0UAN6ZXo=D z9gDd@1MieNBvGo^26_-hbs8e|kevQnc>>asN|OFewdgzEC{OK@MK8ZZQ5%`#eJmv7 zzXz?Z>faKy=~f8^bZtaG7_zyLm_x)ZTnSw|sx|$i&Otfec+5Qbn~EONAf`@gq@dlxY^{-3PRkz*Ezc_OWNRG!IIZp~jw-Pb_vm1tVc69^ z2PGmS#Np^ulW|P7!4O)GX2`A(=-;^2E$Hy`QufwP53en%Y;->?c+&(Ai{Pah$@@BxAZKm(%UY ze!6a^FEAt++6>PV8cx%?+VZqrP7F(mbeKi$lP7+lwSA3UhfAP9;zFyO1ZUnOeUypvq%XWI5;C&oj+jT8+&MSaM6k|^t5kfbIYOV9m z2}tc5;y?99-?01LO_pn^U9_A0VkJ|@nyqg(@W_na}0 z!-pc3Zg~2%nL2rHf@U;^?utPv)cy;7%0wz%?O6a)V28=IyM&%nn z^q9Z-Y*o+8_UHq<3$u3*Wal zWbtV&{0UjIDq%l8XXKGtd{xV-QJwLcZ9uMq!=CCPh}B_L9D5iXyP6F4K7gz5ZMPE+ zWTcH(j(Iav%S;YB&79;vok&N9b&glf(cUJzMI41t=Vd+myIUEPA*@2 zi1t{0Ydey4$XdwTT#sRvXEy{}p;-r0V|D^(TP;}yPuWp>_~gDICGFN~@Y_$TDKWMH zChPDWtvX+YXwIT{X8xQCxb*XtI%u-S+nb@YW;MpfaEiJ%UPN&2XrN1MFq>vrqjf& z%QKq}5~(+H`B9;D>@Id@{jTz;r2w^dmR!IWA$FujXybyhAz8S8;>d`_fuprmTw2Ve z{o>}*;z)7Vb&Wi_*zQTJ(Zm#)^E(4=Yt_$AFr8lRDuM7TQmfdj4%|`v{Y$49mEqH_ zI{0E)kcd60ldQv;Fa*u(DEP!%eyzI;s-XO4038!ny%&RqSuN~2NfjJXX0V62?rF4= zOe>ap+-+(!or7`E?3r|i0f?LVi{?A!g_uze(_VeKc&$<^BJVhi$NT$+Y}Qp&%IMH% zf=eEnGyTr5U)OC4o~>u{pAb4h#Oe97=FehV`80f}`-^|L9VySU+38)sm=S^=m;b7 z4{P0fE=;G1C(6IMkkdp3RV1&Yu5tW>UZ!$*cW5mf9O{0`8)MtAZhPVVy8<<6A=qpP zpiZfQ1zB}s-1V52_KGhEL0F|^<6{;V_C22C{=cctSleNzH~1?Rs3r9+F-$D4xp)ST zpV=F-4jfl9`*sB+=Nyz96&eJ;iO(2EbDL0~!8P--Gzv6xT-;ZIDMe4Y zcnLFS2zhyH2(IS}^)5H+N2qVbVG7vuFv|634CioHZKJt-2T+x2(K{^~c+}NKQRyf* z`)#G3&n0U;^zKsMbZ%vv1BrEISa` zH;OzB^vT%Pm=mv$DSy&Zpg>9?>)lvuRe%Pa7Oy!{MwJ>-KU97?fo#p2@XRpsAd7(S zPP7zwur(Il>uq5TA8mFKukUGI-aYX)j)n8szdS2DljjhU-sd)D>j0XJcinjJ0~@{b`O3T+bmRal%?qI z*Di^PTQNJRi*tazQ#Xxx*hrlz}2xg?Udx`$c(!~s$;a%G2J&>wH~9N+)3rZkV}wiS%7q{giA6Qo+>*8r6v9%pxLPqpj0 z`e)4CYg4ZLK?X4%iEX}2;%UGaI}~L3*R2|42sPVL2S9s=;9UU}i}T#Jy{y|%VZKbI zvPHO)oByV}-y#s~W_PuvYB3_{Y$%&g`1Bd9xTHxwUp9(kg zclo00^T$!aPx3%wSutQlV;)Z69$4G|OrwqvXC~*?uFMKWXz$)?8MfZ9#VR1xFQg0l zX~wMBDPs2F6DT{FskbV+G-Ktaa$V})!e@E)Atb1LCVw$wT5U9k+DAC=qlB%q&3EeQ zYSklkAoapr$rq#W-ExO#aAjnu(47RPptVE~d8fm=;%a2c+~h=#3280+{nQ355q6*@ zbKHG6`-JP3kne!GEjoNANhHyvJxP<;&jHdTV^}#13{~nu*PKbEY6ORUs|L-Ll)pT{ z<7zuD_uPTI*&Q0_A-(ID$C_QWu~Q_nxJJ7fxKWZaJ!tFZF7t!wOsf`G9aa!5Iy~`0 z5gfKp(EbRB^Fw#CC~5$05ESChPTcq;LdwG+BJQ>K)EKH-+-Yd@t-tt|>d!f3Eg&*A z&SN3wFkxt;qwO%W!Q&dCDHA)#@7ozWb8@Q8LyQ;{DG8QhcW9h){~F*JQP(O6CI>_} z67Ccv7~DKZ>?H9f`G_Tqw2iUD7OC~oUiEbtSgE-ud{_Y0$v`Ko*%9m=;~^=LixtpN zE?Wn#$FLf_bGJk=(^lmZRovEf?sGX)+LD9xJ`$i9l~;KfA04_aY87|`r#$9ecS-At;bC!<&NJjEr_2h?^jzrPHi(n}EPw%pPB0R|%1M%eV-H<*D!51o@*<2!L zE{Bueo$1NUkAoLo@P+4I0_OCuZ-n1No-2$)ES^)*^q)73UB?=EElTI9=dDlbnH_kw z&JwlC)^2;;z)`|&6?pkBx`vIMA69VkDyS(oxViEzpWW{O(1wC+Jz}6eQVw zWPBnmzkIVP#QnI(Y5+P>R^I4H=U<~(9cowu1pD5jcvaUeiJXFVYDi~{U7Scvj8>VL z$k6H!MuNi2FjYVco`N1ig$Dgi-p>7$A_*Rn#Dx=L;Y!(y_!X>f}>H2fds$ z(OooFhGk{FjJu35v#jzSpj0D&5Ar{RY7%pWI@jP56HiE#SG*dB+&MvtSr&{^U&ud> zomyM+EQXI*3HkAteS@cHI3^Gi?`*+0$U$$1i8g?661%S&^c>kzn{?E)G#XhM-6e_G7ZV5tcVE&SGV*n*F?c)Fl(%YaM5OTn+Pp`MIT}xJVZCpU+O9LXa`^zfBg# z7WZL%yy@EGPuIc;@!PlN4W5GaK{v zbnPnQam@wK(#+J>pmXl+aqF&#MVT(f?vUZtsb(uh8fsnW}lCVNy>0dFx;?;z*7`bEJ>FX$Qe)&h`1b9+*! ze_&ehIfzr-xM{6=x={lf3W!W6oIljmOVXEjOaA*k_I#UOVfPFt9s8qEVAsdJ|EE{w ze`WFiHmnn*oQ+EW+us{I+3b9*iRCm|m!Y3o$z*C+V(ON971iMq@ zw{&`C`hJKg4(@iP?Tg6!bm#jNgdDDq8q(GAQYpLC?aX#BC{^29GI5>pfh#WGMxh6! zd{z=6=H7ctxy#Dskj1%>>EJeXW6PxY_(oj?F}63 z8$G*ZbPiMPvlz%oD{w4mF{P^)2E0IM7mTnsm-o=UCl1F@=uZ z8zK4FR$0HOyVx8|bKps|>sS6D|A6bXlxGD6Ht|$}x@T1zuyzZcIRcu1!Hu=TG;FPI z1+XmckRM6Ktnwa`zU)!>cwC@^@y74=S0Jg@VFMzbeJ31*T z^V#<-cw^5vLLEG>Zsq&g2eS;nK7zBBUFHmXmgM{Nm7?gc()hLSPCeNz1`2^}BEGzgr*4CWS5lt6kDfZ2C@0=zFMs_QIyqU&|BVSuv^9_D zdoWdO0I&`)q2}XNT$mHeNqQc5f+YTUo8{WCt)x8wqp>QIpww2`ldzkCG-FuRqt4S3 zz6kB?({7_@@tqcPHgc9tg)z^}6@U}q#?XztAq!G}ys4vcS@l>W(9%?G)?vfC%^-_RmJ2>3gXlJy(grvM)3baYbTjRab{c%2tS-4r!a!B{x zUZqUw`X}HSsP@ z0}Gh-<<{?+mAsM6ZB}F3Korjc_comoc%;AR!s@Ntv$;;DIS>3Z>f9WuSro=wIR(fq z_9C#-I(;aNz=>s#yNB%TuCrS=$qVO=U8j0<02bB;gIal4ED(-goh@cVN zRwFU0>ZVPiWFUPdyp&n)kk0+Es88wRd*P_vT!}JzXU2ed1-Nv^B;2^G4zTJ(k2$1> zPSrG3Sqzvb?m)g$z80UA`7_syqRhYGeoIh%J00fdQkB=MvNk`mIFKfw`uG3Rj?V&o z=AihkvGZH-U?F<5V>#Ywnmn4Hy3I;h(ID zj9s|6Wi$~23H~ev-9XAmw;i1y^4P+l_}EyP=Z8EZsDRviFCg(tcvE3@ZAZPKU&ZKO zjt3~_n1T`}D{wU1;&9Ds!#jJ((4b04LFbLxpI(~}Z*pbU&dhaPUX3qA<}=Z0q8{9M zouN&~74DGdE8BaEJ9R%=zOR{++K3#JnsMY@BcDdXKU^Deo2%F__H(3F!Un#~^iH%C ze%N7vpQgSn;jwY5_3J0xZtj=oVNXj%J=VYM%Ff|N zH5@rV5vyatd(S`}Hr!p98N@HEtGPOn5)IDF#J8G|Qy3mc{JI%VGuvwhB`3$4SRsF3 z)DjzmwZYw#l8hCUlMlrS9Hw&fy%D*ifvTz%jt8_k)*rQrXjs|pr4;tU4O;bk=B7m( zB!gjVI9}S9U|LOjUj?!RoJv0gb%DOL&pm@4@XPZ#CNx&TAas3Cc0>J1>)`M>&fwFh z3ijCT6V3A*qg zi~?Zv!jk~euJagE63GWNZW{kx1R5ae?&5NF4N0$oF1eYsEl*vrUHw`MG=`y;e{O&0 zQ~gW;Xfqj7-~)>5qbjR|j;<+z_WO8f+`GCViA9;A6J3zJu88c~WsJI{0d)iuDvOCtxByu!%rtmGUfaRIs=!W4co%CLU7_>&Ri-#cV@e zr9rLHJ$T=W?g0L~_NT>{8L>NannkN>M^nl0_|UXa7h9$2Y2ZH1z~;pAlRH)~;1(S? zh9{&R$P53_G!{eL>G1NAC{uHI-(3QyLLvs5vgvkP7^#OUomGHoo!^sOh>FBh%Th_m zqcNBia1M^}b!><)1l~Y}xMu)kJ;bwI+^Rm1yrm}z^tlU%5!81{wL4ThDOX08v$5s; z6Ezf!AKCRK&NlATYznx8Z68+Y(Z$|!Og9ntFEAHLX^I@a(iupUe{BnK5NHihhG<6!^ivp>!N(x|0m`@`v5# zLlqge&WJnVuhj>El+?K(QljRTD!!=fHqYoz_u!D!_#HeMl_ty+roWP3PouW;m>G69 zf67-E;ser{1}nes7yY10UG;S57S2HfJ-wC$6w^15dN6UOhH&>?G$`H~tosCuf2h2# zS(52_r9QF0sE$BL?z7jw)Os8loRo)R*(*5 zJQkN?G+x#B$PEFyYF7-(Me4zhF;odY8E>DL8+t`b>IaFM8RG&OcjNBLG6i?)ek@CbAYKeV zZcvZ3oKmzO20DfL8vmF(C_;TL*xLZ~ME-tWjBE|8DI6nY;aE@=KJV=<~~h?#mN z8k|y!P(Yy|tH`OGA(0u&Zj?&VWLZTPm<{#RJdk$kIPR{jTFj$#4CP-JPa3qk*wFUF zjT`!+yU1$)MK{%rrwB|Iv(W`tZb-ykk zg1Tpx)jZR$<<%dm7g3J=V(SWTZ7_iCfnLG4ybJV^W_u}O8{x{ znbV_T%Qvq2r9)>Y=Dj+0I~U>eg)7M*CF}>U_&A>$>>n|wCNEkn`krgFXN(oB*ZJ=S z18DSoxX1PS#O$}S^R=yNciGSIa)FLR7x9){KvT!_p!=+291xe*{G>syDTx!wynAp^ z+3hx2Et(ZTjZDgL^&qQ;v({7TU3#JZuKzmkGrZ&>*OKK6Gy2IwC8dD&E2%<Ee4w&)p|*c(7G z5y{kU`>Gz7`l7_7hm7F}(jt6|61m%BlI{$aH o%>S?YA5fzI`s0L-+}txIUwgrY%{>kjsZH#rx%D5VSK;yh08VGvga7~l literal 0 HcmV?d00001 diff --git a/test/test_app.py b/test/test_app.py new file mode 100644 index 0000000..a917c09 --- /dev/null +++ b/test/test_app.py @@ -0,0 +1,81 @@ +import pytest +from app.domain import ports, models +from app.services.usecases import ChatService +from unittest.mock import MagicMock + + +@pytest.fixture +def mock_agent(): + return MagicMock(spec=ports.AgentPort) + + +@pytest.fixture +def mock_db(): + return MagicMock(spec=ports.ChatRepository) + + +@pytest.fixture +def mock_transcriber(): + return MagicMock(spec=ports.TranscriptionPort) + + +@pytest.fixture +def chat_service(mock_agent, mock_db, mock_transcriber): + return ChatService(agent=mock_agent, db=mock_db, transcriber=mock_transcriber) + + + +def test_deberia_iniciar_chat_al_llamar_iniciar_chat(chat_service, mock_db): + # Arrange + expected_chat_model = models.Chat(id="mock_chat_id") + mock_db.save_chat.return_value = None + mock_db.save_chat.side_effect = lambda chat: setattr(chat, 'id', expected_chat_model.id) + + # Act + chat_id = chat_service.start_conversation() + + # Assert + mock_db.save_chat.assert_called_once() + assert chat_id == expected_chat_model.id + + +def test_deberia_continuar_conversacion_con_consulta_al_llamar_continuar_conversacion(chat_service, mock_db, mock_agent): + + conversation_id = "mock_chat_id" + query = "¿Por qué Java nunca se siente solo?" + + chat_model = MagicMock(spec=models.Chat) + chat_model.id = conversation_id + chat_model.get_conversation_history.return_value = [] + + mock_db.get_chat.return_value = chat_model + mock_agent.get_last_response.return_value = "¡Porque siempre tiene un montón de classes!" + + + response = chat_service.continue_conversation(conversation_id, query=query) + + + mock_db.get_chat.assert_called_once_with(conversation_id) + mock_agent.set_memory_variables.assert_called_once_with([]) + mock_agent.assert_called_once_with(query=query) + assert response == "¡Porque siempre tiene un montón de classes!" + + +def test_debería_actualizar_chat_al_llamar_a_actualizar_chat(chat_service, mock_db, mock_agent): + + chat_id = "mock_chat_id" + + chat_model = MagicMock(spec=models.Chat) + chat_model.id = chat_id + mock_db.get_chat.return_value = chat_model + + mock_agent.get_conversation_history.return_value = ["Hi there!", "I'm doing great, thanks!"] + + + + chat_service._update_chat(chat_model) + + + mock_agent.get_conversation_history.assert_called_once() + mock_agent.get_conversation_history.return_value = ["Hi there!", "I'm doing great, thanks!"] + mock_db.save_chat.assert_called_once_with(chat_model)