diff --git a/.abacus.donotdelete b/.abacus.donotdelete index 38b6e6d..ca30b93 100644 --- a/.abacus.donotdelete +++ b/.abacus.donotdelete @@ -1 +1 @@ -gAAAAABpdnAEuFDd_KhfRTdEd4TQYcJ3VUqLLSQetUEc3qUd9jk6d6jkfV9A4FYl8MaCHvhT1D0lCUykLvGXC1mF7XsdM0qLKdNZU9vCZvLwKxKJyD1ExUCIME30wyb7asAdlBbd6rHEb5f_dOs-VOZrofC8cmZbjw_hrNhuwmnXpQ1Gl9Di6J-jjWTbcA_0UhHYzS0XZfKd9IA6OkZHlN5fGBG5a6PYWsdFSbJJG-TjlqUAk-Igb-1SWVhOFPEX5IH7k_KVtblcsgtMiK9giF72ZwWeqBguIQh8wLnLOJ0RNcs1XRUr65tTq7iCmni8X7h1vXcxkaqqG8olBTG_f05KpUyKT7ndgjV2FB5XFqd94NwG4Ervjlq6qMuPYMaI0gON6esdRze8J90s4S04EohujpBq9LnR3BvgbP1nFuFbwSavxNqirKliShwCbt2DBeDCNwIPLh1a_Xl2vTomwxcEX-F9Os5wVfBkKCu-tRU2OZlxw5boGq-B0RZOU5gU90ZyoRFE_-9cySGboc5JLM5uT_CE3rmDLYngCBTHvP1oH1AaI5yJVCi2020EQPgcFF_Y5SSQl10tO60afqbhhfPmObH7Jf839ZcoViGAGSUQKHFU1aIXSqNtmBlCpeXMHw4KNDjvRX95ZDJb95CtcrUTVhW98gnB1Vw-iozmbrd5XKxlhcFv_Ge0h4rDkVQXtwKej_4D3T9xC2BQmHEM60NHSLc1As-Qd1t58kzc1H79zKral6ti1JsiUMS6Hl-oYlS9bz8ZTSyoPJ3JP553GxK5-v5YFSChW6xZkP22gH_ETDUDq32kU2Fn_X693UIamLjQrYYjyxrghnMcslVVodv39EkfJ434-GtZB9X80fUKXUDF6cmty2HWWsqy6MWkF7A-G_JdN0JE9URYeLlV2A0qP3eS16wi_DercbXujZTsn6IMzBSAG5efT80LmRWazwCYPgGMYscA0QxuBRcPaDlP3BrWVL7TiX6mBUqyP4Bisy4QrQZTjVDnAYp7KsNjx-WBDkXYL4G3Qni_I7pwI5ENjnx2fBUO24HgGG299Go4g-D9jjZ_-7tkKY8Z8siFGvfEVCNnLcSe8bX4Xh9JfXmaZM-AggqRyqNQ11iRUWF_T0uFECQeliU0D5DYAGmHuIPnfIczoyPtG-de4BD98BYLMrHYJMii3UTZ8io6iscH8ONFJlSoMPuGqbE-9ohoKiiLhemWTysZZc3AC7h_OA9-_WBwToM_NtTtiWGHOowanT2XLLfbECyu5lLHYki6O65ypmdXb8mHpvjeOY1tGNiBVUN_qCt3VGVBTOHRulWjsJztMW7escZg1t-_Nr4Zt2s1n5xczufsTvpQN8QPm4PmbLIZYSpJWQbyMMVUSMU6wbwF3fzf2Ah_O6CiMMeceWK7JelgGhNSvLn6tBgZa_xQaHJO6uVCyGCOeBrrr47xpyVDwgD8KaZgz7AAyrsFFE8_Zeq4lFPl1EAiJoEKd6_l-KrSxni7EmYmf54QLTNIzyK_GR-AvrcxJQm7MGo95urGUxUWFIztEaQ-e6qxJhyZdySf1gMxKcCh6kzBF6VAFSM2oicjPDca0Z6pJhrp1-WXb2AM9EETWOT1woqKSFiTrhFJxMczh01XaiGA1U9WK7Mpe7hl9h2XUB3S5frAEXtC833OMvno0w4EmqChhVpl5fW455Rg53zwtlURfGE2KH3_XrpSwtK4WKhW0NiJjkABx464OSiisC66xoiNEz1SA1BRXerRinwDnnPyRvXU6tHaYm8k9xXENARvdXk3HJP5IGSVbcFomOleBQoLVkUiQF5IO8HFGIB2vjlhg3_aJLKKqBASiLoeMzDDl026cpEZmMC3cSMdeOCC3-wTkljpVZSb-2KsH9-Savgu_Y1CoYxIB1um_Pg7iPcdcvqNKn6hBY1hwHybdCm7-WSsxNlfEDIxa_sZBuXiC035ZxQrBdkijFUM5Dt4MCOR6mRU5VBGguqKZRUUHLzkjFHxlmLtpiRCr6SWrySEGwcgIuN66wXdLQDViTjjn5ZjF61XGXYkG2MvJOQeHE8KNu-3XpZzMqMDCvH0xfEZHdQYGCHjNIyitLE73v5kmpFkWLQSYodoDk99IsCS2DNF_pH8qLLCeWqn2bWZT-vFin96WUdZzcorhxiwmi097VOcSEIUVqVl-b3x1Qn0fhOEJKLEmo7OHlZPbxpWe7hjOoSxQ5zJy98vVbbsDyoVpdmf3GMjjfy2XYRdcMpCnhC12IFFpmODk0jk50-rNls6SQQ0uDC20UFXsnOGkA_TkUc1FvZaMkvONrdmgDVgHBpD5mfWGh5KLC_dsnaGQ4V5GsKgc5b4a6pbozPATr7GTwK7q4g_ml2c8B4b2IZJmm9av07DAIwNdEA3NQqhDZKyd1MLzzeG9l3bR4CAbSflKw96qu2gcX2YKss5r77M23RSEQQDXBK4jR1D2o0BoSOM-Iv5JHNJ3LxbE0vil-pYZEnvvTUbPYRJAuoMQ_jyUHUjD0Wu1bT7YKpo7DItKNgR_OQB-2ixVY3OTeFu7dTJw62HZaaghMWmALqqfyGEzva8OArHtbGJBjLG_BLQ_21YnfMuP6Laujzd32tOw9wh4G0Zy1d9FTzQf7VTuFLoEG71IhEyPtsFNFn5trwgqLk_1NNmSwoEZl_ansKTqLAfILp9Onx8b4Cg0d8vs452mDEkZDhI7pdlKmU4-p2SoeKWpvIQJghu324MpSGCyTQNnT0gQkNtWu9LqOEsoXE_l3YhxP3k7qM6HLDVAnBoMEMZxRijsTTiyGVQwdwpD3DDIhvYnpOySOZcy_VR1_SBMpbmf0C_BNKtrlIfLbvMOMSFjuLBPVcMgVesjDrrhiOOtVrqzPw6HtFDVLvKPjk3O8mGbtuDB2OQijWKpMNF1eeiuKTk9w75aR3iFTkux2RkwrkYTQks_Oa9aZ_ZV3PCpIUb08zoDLqmM0cBFk8cJL-7MTVtp1n_6BILSFs0h65pObdNmUXXuYDXmAsasUByHKOzBtj1sYSdqR_EL5ovQvdk_pzm_sVRqv4T8r8pO-Q4F4POzP5PcJp21XDaoivBXB20_kkYbQlAXxf05uwPTTBad0BK0NPvqal4Y60R3cY4rBLfn9Pe6yxATgm4flDWR70lHrgLpNHPcjbVRgKYeJoP7IDmb17DMTPXTycuoQbfhkml8uILwEAsU_3dCSI5r7PKWw3bIyHbw-UwhJCbEV-u2-g1pLaEmS6l-nAfXkHhavRgwKLnN52dfwE75777__6UKGdjFVC_wNSBLgNnjIuzQuQXh9QXKCexLwvZq3mZrndXq1A2ftv_HRb5-BMju0wjWifuR7Jr_X4al3BHiOGpgCKUrgizm9_yNUX5YHNqlK_y7CzSene8DZEffKjk7350eExGWEDBdv9P0gkzPJfGuXH7wUpQ722KT_ZvcFGX5FYN9Jovl0zEQflPHg7r-QgrrwyvNmBLSZAp03x7sH07meNdIbYcEtaRW31MlOnmDAJCzhBoB7FbDcPgdmOVi8t7tFZ0zuf01qykCy0iTC2Xzib8TCbhiRI7cZXgQyNcTP64WwvMmco5Lt4KpHbSmEu06VX-PIcC4hx6dm8c55W2LObDe5qFGr4t1rFCOWGdPsryAM3jB3qkkKAbRi7qN4OOD2hD5Aw5c-T9EHhxaRLC3W2t3nXpjgNJKbgu6zzjgGDW-E6rSNh_Ao84VG0vqdrk9PP4UHXs1TH_sq_W4E0EJUTv4wKeRtyF7Gn2F3ps218leJZdJwbKRSMFlB-CnFd9k2sCanfWy1q1U3JFpQc53aNQtIUH78RhC4jplnMm7BcGrQljhbZT66rDwxCaT4_meuJ32wterCWuFVZNJowYGprZgcUHkBY9dTVqNuvT4niWozpuT9tUiHIj2GQiOMpn1Eyh2XwnqwI3IPGjTFgUGR9ugbxZR1fDb1E-Hy7yRn9HWSq5LTE7QBvxuS9Xld4jAx7pz5PAvww7fA3KjRg9VJlU9cEYD6JUf8X5Do-GB-BSaucN0HplzMWUXcVuG6xB3jiMMxQWko7CJ63_1ScRFS_qFgRAJj39QT0lHAXBv8xUQWpxAD8EERo7H2QBnKkbPHl_x2lGQR-BYxzT84tpVsi5sdnaFTCuIFZa6T8Rvrb2wyabAeHKytNmlvvkXSYrCQag0Z2d18pegYWHJqI218Kl9N24-H2ylQhsCETfCffcugvzCoam_96tdISw9L01XWKWnixPjjX_qTrEdttfD2oShCk1zK1vYJuABku2Aiyq_O5KDY0CLyt3no3JhKM9nUn8u8JLxkQgRMqdS-qruVvg2MhPh0qMrM9GCWWj1aN-Bofm3fqfJ6fuaVJSQX6wnDUxsEeAqTBmzhszktCqLp-qNVBzwzTDOeOD6UEhL9WARim9-3AifJktNxlDo1hbwIrEIpEZZpZOPGvD3fHchOAwysaNvhBZCD3MYVQN1j4IDZYnf1c6GzZO7ZQiDU6CPq_IwWE9COtqZfQdgTxJC9Yvph9RgVZomT4SJn_bqkTp4HjZ5Nm3NStr7kku_nGfmI74IR-tx9tmkI716TWWQfpuedBnbiFh_AnWEdJApr7Fp1jJuVFce-rcrzwLH6o7TA37VHJfLm7OyCB6b3KsdSmT2uwbZCLojRxKPqFxrQ-kLe5VhOW8WYfFczwDUnyLBd2AW8i5M7dHUHr9P9CZ7zWpv579tZLjF34Xu6NjpOYo0JS39Dm_wTGgUS0k4zbrAJ5J53-JosrxMznDqP27pyho7w1l1_Q6SIclvG-pdLqEniqAfyM0KAkJPS12OLZwDwLlvuE-mDY91BTi-UhAvpNErAdNH1csiVSD7NmAyyCdoafv0J2JktdN3x1CHbx0M0h1ONzjKE3xnJXB_cuvMydiQgWIJIqU63RegxmVxT7U6GT_xOY25vcwTcXSH4JTYSzjLvyp-nhQI-DDxt7b9vinlxy8SxJdOwZxFxWNVB2O6L8l71_o5vlBXQXx2ItkiD3i-rd30cbdUrg3FHSC7B52ln3CDnMuHjoTbNOAFbhB4exrvko_m1nvE8wMpGhohGf0JNQHUCxLSW2C6nm9PTGgJtrefyO3a-vAo_T-lqnChnfN9rO8oxx55C2PaVK4cNiP9BT0yiETfmjWbRC_QlPkCH_z8rW3yHoVtm3oho9URR8hGNrvFNo1EMqZQIUsvVQaCq4wyz_F9aO61s5pxBHHiXGK-c9KNdKIqfgMj0pL2MOx5rMidq07YajurwvCg5RPRLoGYOX9Obhx-9ZGsS_0oHQqTxEASyPorNWNjozkRVQWvKDQFxg8r4NT6i0GduUARcY06lztUMg9h9D7BYRYBOg63JYmaMPlfGBgK1DQU-7Sbm2LFHQKuQoiWbRwBpojThZP2hztbcAekUuxI0a62NEmKHSa8KGBJgGcGtZMCrCKml4WzW5ZTpF8LxBEcrRaAlvvw5eEdbdP2SqTzQNdHVmVNbig6W_PSQa1YRvb1ExRphmDA0H30XbPErLiYiJ96ZyNDwv59ZdTgbBH-Dwp0hE2p7pSQXyqpKZjJPdVMNqeHkcSOS_lY5YW-VIX-4QZnOkI_O4pUtBbkjUqEqet8dVkestlO5yBeGX2quIVoggW79mtwG-JdDSbjdKffn75O7yQGEX2xPculDH-rSKRYSlEmMD4nST82_RhI8FaywTSud44LFTN1mBUtXh38aHzKsxunK2vbQjWUh9_SFAi5wPeax8r-0CdA0XjLDNVBaPfPJqOXrVjw6IWbXuTeI8I8GXuinGvISzGS2ewY6oaocA-Zg1cHHlpPUJpf01R7NAu_zUAwBxZDuvlhUtPJ-w5Jol5IVL7ZtjjaY2VoA_3wV0k19970QpVlSKOj3f6bL4h4yVjJNNWb1seQiIAbZpJcYDhXeerIW7E-KH97UEzMmp7N2zNNsWRpawQ5gVcy624idZUMYQeU6Q3DipJ6dabLf4_UXJFuw5oMPOuzDSzzXFWaE4YA2f_e-FfC16J8Xl0tMkkOLoo1GByFRnl6h7LULsHlSMdEwlYO1w0Z4y44nJToKIyBjh_R2mzJAz9CQdifGKQ-Gp_7Xc8MzfOGerLoyYGlXezG5O2f2OKCzjMnpbGMcMmSOHaYwCcDFEODOm4XD0CD1ErwGo9mk24Us5SV07WFziBZOtbQ6wlm54yjRLXS_4tcQqkIUmddSBIyz8wwQtVH_ZFyg7wfvl6frP7EgxP4UPqV8a5gTNXT1mvUq9cKCWZs-JzHPW1xz-x6ERAFhOq4WEMKIMZbgKro-cqJK9WHMWXHjkPiHFi7szCIYS1qWPgL7L1_wmvhJ-Uuua19wUH7xOxhWi1rJRtiyS3mWyLSt7SdswAH9aebdMYcT_gU2qrlGjk8rTSWKFHPhdlsrzkBzcUhC4OaSoVu2d8IjCuYa1qPOKAXGtmMKT0sMDufnztzEhSjhVz5csfjLm3AoCPO7UsDnDK3JhYbL89p0yYBhl0spK-fL5RGFMRKalblqLSnmK0i9907pVmCpl9KARbXQIta4wlDpCvZsCW4meXizaetwRyOEDPVSTrrvEWnqqfemwd8iEIrmidhd2PklF5-9DWJ3M44Lz7foN5tQHN-y6AKzOcBzxc5hh1Lmx-OwnlEcaJqMa66N2-qTliF9lPRQF4PRDSwQcOEX1NY7Ws3pRsxtRgn__q1BKuNzPoGgW-S7vRsT3p-8Y7mHQJNXisEa47zBQT94tFq4835TBt2wBcfIIecwb816sdWTqSM6g-ZvvESJ2Hryng4ZMBoc_RGxP4O9MmXLCPF_kI5wdw4iZRGdngBH6M5eLzOlV9S-dkZdrbVHrM2ihs7f6DCrX1GfIe8VMeIofthrL5XucnMPA43i8Ije-9E9EHrEKjyelzC1hM807ZOlZIbduFTg_41G5f7InYT0vbjZj7cV0SqRf4nf298LJomxbcoi-v-CiurUFqAWlhACgXPEfP73eIWQC3CY4pM5swP4uJuMergs_x_stRT72Khj0T0Yly2QE83LHeF_G__AI5rahR5UXNLxKk2vTfDjIbpIypeucq3IeITwenD5ELe2nqBLcAQwHOE-jpCtwS5sw673nhL02KTLAJrnC-uOBJLWdoF39wVX2-8yU6qP3lVnfU8czfGztXog0DIYCRTizfdaIBjlsDREsGXDlgq305427lhvqQibBVa5FVhc0YyE8THnR393PjBd2701CXv8wlvJmCO6nLHojH7wv5ykEG51n27WB5hjA-6ut1mWtdZvBb9nRtxbFxcXQnMLTqzULqKNA_jb01pFQ5T5NCaphREdVJcKtsGYfX2qi3xFzdxj7MnyduH0PTSDoH0H4VkOY_vHct93SVOE7gCYfgcb6HkrxlRFIe99ALBZNHMP4MZTayP291w673nmBfOXJefJbUvrRniJ2O_nIbX5kT-_XQUL8WVcRGc5CCEJOI0H584hU32V_RV6doQIM9rWj_6zMOtZih_kBnIU1ayY7rtSxBLtLaQiV_GaeEBCXg3_h9E5InEUehWF1FdJ0npm5mYS4W3jNk1SngnP7GvDW5RTEuC-wtY3iA_oSncRxJyrCUmPpvHEj2NSmn_kQsSvmEm5An_NTCGGXMlcBky4T-1W6rrtTDM6pSvQTZcWxtgEUFA5gZihf1-kRW4n30m9LfadPX5vX2uxd4Z8y4ZyHNaBO-ePJ6uhP2GdpANkRqb-RvlwMiG9_OwJoIF1nn4cuoydBsSzTpATqFP9w8Hsd_xRwCexbTpaMAI2FoBJLEnlkcqRZEF79bOFUk1EUAas1GYYhTBiCD0AdKfK_Dq1tn6WgvO6b636HC_pTtYeEA6EZd1qAQJOPBG_Xk6jh201abovU0UrSwWmdoR9dDhohJZCcob-c8c1Vidfhneckzxc7b1a3CEvtJc5mSmHZcvFpG7L_KGKcFlgMv-6JRqnjKkm19XqsCbAicQ9mcq7Z9__rx7cNErYusL_tURV5_IFeU1_gMXfo10WA-Lnp_ZS_BjxlXgwbQ1FloAbNuwTW2yc0q5YJifu0wWCiA_AjFX8Vw7idKSSdYQGBKyXwUKeyuuU1clF2h18ux_Q2dclAkDxZiTRq0IK5zgFGgDMx60OwVskpp6mSQugZVBaKg10obTUdqTJsLnCrA3j3_6FJ1Q10wizLvAJ4UjrKRHafz6oDZIhqUPwT3mebrEX2_xvd4ctu3D2lZnwuknfnEIu24dWxOF22NKT-twuTtWvWotwxvqB6ep8GXRMvMOKUHMZbaeVXpIrfh2FmRKWVhVgI8NyRZuOPDFJMc_Vgnmy-xLeO0ajKLhD_2F72FDQ9RLDdKDGgmuH1rXSe5Hto_6zg_6Kj5Rk2QrSRA0J2a2izL-YwUg2DT8HQcCopvdtDqKtcM-61DraU-vYUEzNBMPRsGoNvpWSMaaWK6Uz8olrcDlcpaRQqsLfTjH2-QMerTm9VXufeWZTuTxYSK7No-t8UNUnbg0zl1vB9AoMiWcOQHfM8OKymdByGFm331Di1xddKNVsNtME1hvJC_PLGMMlcULWnTdkDX5EwkOxl4Q1MqEmUFhFrR_z6P5TKrAGaWLjUlqqGFjYjxDykOqpC9CmO-DtvteYtnjH51KZWG13xnfoYwcl93aF8uBgLbI3MZ3P1sas17FiXpT7iRKKgrQdqNNBrwKKayR0W_8xlUbWj9BS_wpAY4duHAG9HXkaHW33SJ88wQ9C8o_8kytvDHRoDgb5DS79VMVjhGMltjIurf7t2c_8Qle6v6gI_w0h6_M2xT9pUAVCJLsdu5sKX1SaXtEmxgM66avfCGLaPyOsr8VzoOvqmlnfD5d9yK2ydBUALLs5zsBTLjwqvUgm6yGSZ0VxwuxCdb9x-kiiEJdhiZeekwJOXOePLO4XW6QA11OZtee4Nq0tqm3cbLHGJvMJWCz9dOUCrne50yCz6TeUDIPCelJ_MQu4PD3yWqGfh1UdBy67XrT2WgiIQ8kwqGrrlUp5Z0ybknrTo_utZnLguAi-9BcVjSqMrH_pDOS0QbV11YnHbi3Jdb68FrtBHHKpK_6hgvxNYg4fLF9dF_Z1G40UOXvOcK9vBhN52irtMF3gn6sEaKX26-uWT9TSO99CXSWhscgzmj2rQQXJo1kkJfuEyYJ4gLylSdczb738dcEb3qY0DXSFTyn5CVRenVC5PtPaoo0awcxnrKd7BfJR5x3N4Pc4qyXrOqIQh1saDhpfGjPkWnSlaUv941V7x6Po66F8xQRYBQWhktzTBOPO4YYjzc9w-ZvO0tb8lrSJllDsa4rmBMizqTplK-63IbZoPsuPMpXxKbi_v238AwujF32HJfYm6mSqBgCDCXMzaImD8OsJv9kxfS_ITr0krysJkVpRIqu5_Q1uinwLdC0R_ysrgcFzpSn_eLhFpRkLL-yZJvg4KADb3ht-mc7rQPOfRMrTalUWoVke6aSfoJ8S9aH4suviHN6R5klXSPCooTG7IEzrNSZdPXnUNiLxQ00n1g1DQ4JG36f465MRLLuKlPE93nFPILSVkyQdWHDqJIrU2wLYYvfYH9M5DpQutRAyZFVgNrneOrvGpDbGIPB5Dalqp8NeuFsLe_8lToo_AaONvU_GFBtteevAc4Jy_Z9nGKt9QiE8zP4heoaMUm528NhA01RXoDIe7OXk2Ca34kSBHDDDcVgy3X0l1hZqStYg3PoQG7B5sMLfon9DHiAKZQ3ucA3Z4lZrkYYFh6V1Rz3BR-TY_D1eU1-mz4yLFOXys3N2-zLakETwd8M5c0g2dzPE6zyRG_WR7WgNCw8RDYULQNh9-NWffCkEgqtmtNyS8neD5F-CGnfGZTVriCBXrTGI07i6tjtLta9xAsLCXofLHkbuAJXoyTU8fKitEueODyXjeXZIbj_0iRy7bkEHUQbJJHAiijOAzzeFmB-0hZ2vTHmK8ZbgRbWna2Bft3jpjVMC0qI4klYxZIZ_BKxDdMh7dnbm_yniGf0WbSUGyzS71IzHBdeGlKUVidMRoJ9n3-GPAnhRugxgjnketD-Yw0mDkLObJQKkKBoH5T_addvgxRxF5-RKVWBOoBMELXnD4UOiYYtBc89UW_Inq4axw_Rfg22kyTaNK0UO_kzUeCFvz4T393K7UoFlhQ40jirrPqHcMWyhggRi6oxzT7CDbqsrpVuWL5WOuJJHZdpVE-o7ZrxNGYUliH4l_8uRwgrJDt1wXrmrG2mi_FShVBSHfa75vofZ_WGJfX199sU2rKf0Q7Yq8TIx_0KwKJMp0JDsObCmjx1syDRQMzmg3h10fd34EmKDpKFxxEx6CQBjC9FB3Z20f5Gvtn9LWkqqDAx6JSJ9o3BRyyg6GORb23svTfLUSbkcPADZMLPdlyiWPFLPg-jCY7zVC1OCrsO8KyXlJ4RoSL4a5BYy6yu3m9Og6ATay35X8PcOmfw9MR86fL95almJ8bUehnvKWFHoBwlGU8k-bK47uJLUqmV3ri5iCP3_hb8D3JvWnASAypgsf9Ox_adVJD0xE6hxncodPTZz4jqykgVsDS2sle7lf3jc9DqJsgn1_nD0ygLSQt3yLLiTIShfkIeNKKznOdApNkmmnDOI0TwY2z7FKyLKdFDhnFzn-nVqB17iTA0cnDXwZRwgDxdwIVh2PNi8c7DSXEReOdAjAAmXF_3NPXycKcj6csG0uPDtxCY88SCOmUDFwtmJQUsZQ-7WhAumrJzkB1Su3pFfTpYsyFdPc72PbJ7i0S_oqzBm5XsoUV9w39f5fWgXnUGcCTMLyx31MlP-M2EjiaGmH1PzBzIjIbUvG_c3Y1HF2j23yM08OefCnQtEQ3FUOi8FZJceSJ-Ca9vR5d0l9YI5JJiZ1AKOsBZCh_VuHLraXBAXo43WYg2xJjoARTl0X7iztyYXeKt6PGDEVhyZyQLlqYSy9fC61TXd97ga3DKOdIMIi8-HD_NDSBfbZsKVn-6_S8FLb5WLaHBfg4Oq2nknhv50ZAm5DeJxx7N_mhRtZrWdwx-fgpeBC0wgA3oFQcZLeh5a4qH2SLxqUDi0knJhgdo8UfoH5t1HwlmG0KNjbdR2AbgNmiGXC3nXMSs22wh2XwLayLvg32A8dm73DjYws4zqu36r1rPAbq9ouD7UAbBi3uEgdlr1ofghUDfdPOMdu_HnB3T9ulDJfu1oEGPpPRnIPrnB7xZwgYFTLB1S3TMsrKEuNtBwpAvGHQ2uSS-Mp8jSFTOQKyEZWQ8Z6uxY8-WfeM-e-u0aXEL_ip-ugIzbBMn275k9C24u6-cN-hd7sb9YnoCMylw_o4O_0cgcU8599n39SpEZmmPTCKfjrjknnVSbWefo9BhROafdfo2UIzSSkk4pqQstNAzgsTLSTFhJpo8o5YdGDDazOva4Iabbu8LxXY1fGAwPLOEHh5nh6JYq20HTiBE8M9nkOcsyCeelAVlszYrcitDhE_Y2XdGC4EemqUAbDvfPGBf3V7j4gOHeChRrcmYWmEDpoL9sFs16fT-dNC6kJsdTDUzXGwdAqv8ACzl6BV3waaTDh8g6_RhPKamr-hqgpbFggvCgx0E3YleDgHKLK8qnFpVVyCctyoZL64jAdiK15-uL4PXptNRdTfleY-zfVnnB5tbpT3OcXLbFk7yI9jctN3bnrr5nlqnt7Nn9a7zxhFbDcYLml5QDIPmxMpPtc1hClB6kY90yPd6B4IS4B_nJWuel8l0QydFrJFpXHU_vMLmQ87vPpenq5wftKJSx-GMhLJIkaf2sAenRxaLQ-ZAAwYxSYHQ2vZsBULlGSNG1QU_48LqSoxGY0v51MSodmt9GwnHQ2vSuq50RoulXjEPkdWtWUbjNYeKK0cqdnxFsX0hUF8PTiGa50h895tiyGR8XKSCpGOzithmzqTXdfMztxtV1irMOHeUPi2YAELfC3_E1LwveyWexs9c8b-pz8OmWdUBNgOsQPn_9QXduyS8asKLjGRsHNOZnZV7w7ayNXiOhZIC-oORt3-wJxjNJSZYONtbxGqYhm1PVbBDgBt220AoFqhH3ZbIx96me7zAEe1I-yRISvabt8gw15PQsgFwE_zZ4Hxv40bmfXTJE_pT2xJwJpjlLuuofVdd-4uOdzTLPoxuYzPb415tDZ_2WjyCUrJh4WJnB9_e1KxYRNMxZix-AFdSuTNGNMFJUQ309ke_-OqELkgBasoKtyC4w4l-S4zZr7IOiEQu6oCc0c88Htt9Ixt91NeUpFoN-9CT5tib7Rn-bLTHzAUdfgxU26WV2QQiL1bvXLc9svMEBZFM2dLSIi8ncBdi-VSutU10iIa4wVWxh1_aGyj4onMp_w6NKxY7NIPEujU0Zb7xWeKui8ptQzxg6BQbGZ92Is1MXur_kvbawse4ONNmk8Px3MZMjczpp-O2wEvZwhnL5dcjT6fGWRA2cYBqPmecB4urugl04fXAEc_KCLPiytXvCNXFsD8PR8Xct2Sy_u15_iLOvR0X3Q1UiTY-4a9LU2g9zsWy4oixi6bN9KvTtu9uw5SiQhI1f-HFCxpvlyNCUfHgVlLWfrcwJa-LSmhx3_Wij7tXUi8XFcL43va9EqGpyYwzn5reOYipjAL885bX4bPxorDNpdFnz57BO1mAdrfgDtVxTFjYKe91MR1y64J3c6w8YL0jYxF9VSxnL6yp2oYVWp5B9W6bEMisQrYiv10DcPSv4rf44FVrLTVBgDZ8cPsi8oaRomIRicsNtwtUs-lnQ7q2JrQY5x3IvSoGPjbPWbB37AWCqgH0fkNKnYvklDfD6EG8q-3gNUjKim53KBGpMzV8ED-qBP0NpgCv4NuLGOU3GscrdLL_p5xGl9vFaF21ZqwG442ASG-pRfXUZ2Puj-JTtQGSQ1wn8k-rNFadzzUR5et1ARel586laTBGtuEtrB_wkChfyubfHt--eCXxcUvB6VWfkt1kcR0jpCF0f8WscgUax6Eocad2bbydRWww6rukfuwNfGHsXRc9DuX-mkQvG1fpx5ZsifqaIs028QrINJCTE_71BT0s-5qd_dcMFPn2ykuwfThEOdQOYvX0eI7ruXLgXu_MYOcd-u6ACuV06HUqgxuAkuct1FYWfEasf-4AUmey45gXX6J9AkuPB1NzdsRtY5TdAYLQRAD0i4jDYWzGFv_wTOd-_Xh3_NonuUTWYbwLASjsCVQrRPvAM5APWw8c3mR99_oETtfvlF8O1gi48Hdyt9QPjLfgxVwxl4UzbPIPigj_cWLn1zrlyj6DlWuRx0V7oy-L6ZW15l7ePMye1BWKAGAmkeiChZ0Hiw4_WDR4WgoGq_JsbA-vLkDPbLCeDGjel7yStFSzTeCjnSzBmTe3mw8O-XeqjTAPPFhCDT_2UIL1RceZWggLA1usgCwrEKoOH4zzR84nz8ts6IMRthX6wrdrj3jWmRMRW7H-UicvKKI8t_wRMXimTQ63mwVEbsy-rkLE3yE3efHVho7ow1zk_IyKrp_UbiBd_B9xAu_mhjUOsa0g087rwmnWnPffokGEMGxsdvg4yiwy8HG4-8e6veps97jPiwoHmonsL2VJWC_EDU3CyfSsO5Vo3RLm3bEa2F0wRAEtV9UlYjgL1pj4z8hXE3mlAYuTlnAZLEdqo2lRVyKC6EMCEltgzPYbRbKl2gYV0dUVYTHbZrb5U0Icx8HJSUiHu80pBCXtOWlG7Fmecs7Q7jFkA0eoYMsNLDLorOWr-0ImoVyiudyFvuF-iyIhdy6Yon3SX1B55yL3GWuu_a4URAfDE0ZtGd_Nky42tL7am3wjbq2r54YbZBqrpKmRlDXMI2_OKwT8ILKGQo2yvQYK9yFBiwx0FQ7NUmXIGZT_mUgwYJcuL2T4VUuBkdgzpgA7nKseEcWsr_3AJQWoQXWO4b7NM4BRzfgzTO9AiWwwIzX1qZcN0QWDngT9Ohauekr2WhRVMgwkkGSi7BBEOUXtH4Hu94BV3Ra_UiMHPLkv-Np1dtx2TRSpdS4C4J82LAdoa3LYgq3eaNlscjVRhlZIF6vmGGvskQEHFqOOU192D_L9sw_dCHLhcAadvs3fmiJ1DcCRWO0FPcFomak_PWXcJgDStLuc8-_0WDruRRmp9YskiQRPEM0M-7kZrCWjbWVdrbkAPl6UXIlZbqvslTgGkLo1O8XC5TJJY9XtJTuvcQOLw28M2umb5r65r3g81PBxJveaRJJty8E9wBNKcwwAzOx7VWmcg6MFuaPx0A6bqS1YF6WytyFb15fiortlCZrzDlvcsyz7t6GOTzGYXKdKgi41drJFaNhoHAGlMQUBdwzQPEj4-fob9AcuXDYpKqSZ7Vtw_nljj2XpIds6XtSPCUXZ7bzBQd_ycJ5UAl3YvEenoRIbtlxUChDIK2B_q-lb_y_jcb1b26o8Qtfau0vxCm-13uZ0nNwMGWM_JjM-tU5U-_97RSTRjlqXu616xvZZbTZhk_MCug1hByMPXIqIoUWmepSkJuFRf6xNko1IZRxRRigxK6bhna69I7K6AkRAUAQ504ttJVqVDt86L-1fwlWmlLlIBPLaYOLcBzm_MJLxt-fdTjwucbxU2oh2ltc3qk6f8_ZW0lViOgXg8YPRZOCjj5wlfe2zW1GSfM6T2iNwmOfpGhXzsZmFqqBc5lpl7Tg198imKCuc1YQFFnliXDurl_rEZNGUiJMS8zcdJyr7p7ya0NFdKEAXU2g5_tYN7SAEwy-Evj4l0Xxzf9Kamjpdp_jm0i8vY93lVTbG0AJohCTR_ZMUw1titTsiK3fKFXOa0Z78dTPzwACQO1X21eUdQv0WZhoioQckpYvWslSEJyzBvAfi7t24X_ERHOzizI6_L_-GKnOnA06zTuWdTBEjs6YyAc1z2RxJnBfRvk84YUD7C_kkQudxHQLcpeZFRfXzR3s6-dwkTOHnMMBDN2RXxXQRsPu1tbaJEWiZo_7sYkMbQr76X4y5kJOZkjQxAV_s3bhjF2IyIBbZeN7dE-inzuYe7nQAlDszfrHnuvsLOWK-uvHG-GJvwE_JZF7EJyuhJsy2V7FBJiKE9ztbu2nzzSmy2Kh9bnC0_nBMg1ZqyFZWZYyllCIANRaw8ASmDWeBegVxwk0OT0qihdbkR03QE1EoFNFEcLM7RXrS4IGNVHxNSzXluhN3UqPIKbnOY-oSZEQKXq9bXXP5tvQVvzyWtG2iEzDOAJestZCImuu4FJiIvc0Z9JIONQmOVV9z4m0aonBuUulAcsMUSg-8ys6qOw4RKA906PsIgG57S3Lf6oP4synCf0SRZ7hGZjw2YnOOUPah5spoPEmHYw7NfagaCcV1L9Ib3zCega9b0uxkL939Ou1TSlFl0Jb_Kju9AUVkJNuMMVI0sSs7YYWX16rwK2SVORz1FXMU3v1mhxN6vPYapWz6KJmGupKisnKqfclcT7VFq_Cu3BTIEoep0eSgvcolHlv95ooI9cdmD4STE3GU8ZzPklitgZLVLam2j90uWky7ymZAxJJ6VoAoOxmwWHyAcyVHoptVwIW-_GYnbyeuqMy13Q6ra9MhINS7WQ4RabLlZycaTTELTDMOVGM0kvLIFO52Nz7771zy6pfA99xd0E0q2kREn5itXlrue0oq53ds31Lg4RjgynpYwRMilhQ9iSk7taLJLuOseo4Eafc8NGyj65Z6sVLlckgrCVaUv3qB2tXd7fVTBIL2w6qtZCaB1arKlFZkpDnJytairPS65bW0hH8Agr0F_h71POd7rYCj1p3wseU7TmmX2ag7ke21zdtx-Lm4mIkYDICjqSKVfF2DYEpkzmx0dY9YpZr5eNRbieuhLTW_QBMKMl7-4jb6l8wa-xzaJpEikxMoJ7aV3hKBZO4gWsiQQbvY1lBgJqqgyVkLSt-PN21ShTDHAxhxFM-neC9uEW9d2VtDqwalci6fcs9mGBDt5ojHitKtOHlhbzEULDtL8BXKbnLzY0tk3MlWVF3W7PMWkBXudxGqdZ86PMAPBm7nV2_ZpGJuYBLEaCUQVIBhcN8eI934UdPQrshlkJTLVF5WJS5nf0UAaOEovLObpqgM4dNlxou32QMKcCPO7WKRYnzQINHCrJoyymFmdMD3r-ZcCac14VHehBmXvX2COFw5792LNsoYA_zejg5zOGJuO7nZp2yzELxa2pvGr09nN1N_K5R3B8XTUG8lCT22Vp2VGxadM18frSNzatreYNd9Oq64LUClc4VYj34A6FV2I8Sz-jnoX0lV0UzP0lp3imVDlcTC-pFzZok2pq4hLQ6gSh9Qa6-iePxMdFsVt7c5TfoHoHj7l9bRe4stnEdUnBtBR7PeSJH0iJHjlvmh7WFZ79tBkEM2OaByHQ7EiY09D7OEQUSuHkX04AfGzcaZCcncWoIfUuox8XSoIBc26s4y7WRo4ew-kqFD3iKeze00U022-PTJY93EG19Rh9N-MVsr9Va0A5pGtyoA_O3Mm1cVXQTW6aF9Ro86o1p5FcIH2EfiswCLOJW6vOc3sQXnF4mX4PzVpFcoOpctfudinTbMY4Lc7pbB-1QJRgUixWe3SiW7MXmlrFBLUFaQWXHkYfjTonIdH2HTu_MPOgnuSBx2cf86x0-PYggnY0BY3NMFFD66X7OmKQJ93lEN2Q__lJhEsibY7BG93e-9pNmkjCaP9noQQwWAD7bspHrcMNwTzwHObZJMcJaqZJ-3XdvG9mjDZWsgAkMtQMCr63FtHE28OQim0frf7fPJSIjKh11KRgwwQX8gpCv-QvR5RSjra7iJB1HOI-EbK4hAbkckGcJtzpnT-mS5mTAeIxj6IsN3XG0x28ZnCVF1jiQ5CckgEuthsESfWRM8qilsDWlCB5vBROIVf3UrTulfJqWG0NTjV9i7zBdxtr8WsmvfJDgTxBHg73Zguo5r_BE9yzleF1Ta-OVRzL7aWkuEeJFUcrHOH61fFhX90gAyT9u_foffT9q7cCnr2KmdUWeNAgCYp7busr2cgcP4DoeD7EQ2XXCeekE1W2GSzuK32vdRHd7Hb80oyC4RNJ0oSKGNr5RVWROwku7dfjwweDrFqwdtHHhh7c0KJNwfVMeTnneLRaozlt9tF16d-kCNL3bEphVZkQx5O2rnCCdJiOLwA894PHEjF019SAQFlzkP7KEWzfmsrNdSTNLkQXwwTx389drCWN4i7PNOdpw9Agq7mkbmccRRc2T3HfuGCarh9WLhghpFiOXzExZ5V-zZWdO5S-qniLphXhH5WVHQp8a9axs7MvkH7SAkP5zFkKiMA-r2iHcX1Igqj6e5Mn1jkvbPvyifLasda4URPjHJaB9vgBvXGRzg3bPQZFgBbzox0mqfu347pcW2OH6-s4XJDBmlBorw_qb2Btl132J7Kap6z5k9mWJFraVoeX7H8LRtdiRKOl3qxy6QVn9C6JLAETpl9mnw9nQW_XRG1oOfBKFoOOxa-F7W4zKDB6RSqJGbIN9PzI_IFQVm1jd6ItzOIeCYnl96dtNSWWGlEvhBxMLf37VLKJEilK4xKGFZj9_M9Vb_EPIVv5BhwD7J1xo0voFN-d69yr91Qb6TbxFl2qVdcErOlzrG162c9SD89ZMr1JoUV2Qm_HeKKTGmicmHSGRpuATFydc8WzS69x_e3jlcXMryogkoxyR4WIuT_sZ9UKj74FcHndn-DXLBge3KcS6WT9yR_ZDpO3tr7IOlfb3IgvN5i_WHzsoFpgN4hui-1R7eRPk1izCrPNSYheAHXlULKDJoZAYlUjlE85qpvJGQXUcZV6LwW13fGx14diNEB3c7NlMNDAi48CeD0g6PErNRbs-O6U-xvB7IkIl13rWuBCMMjFVz0cfQ5K3WIJzGalv90sstek-qMJbdJeZimRCTJAhNCjrtQZPBa7-_l2xJ0tqHF7_GpoRAAPDmjfsuMKkUNEavED6thiAmuU7oq-N9SaBa5BC_pzylpQHAA-AF9ZC4oOAPKvLH7kuGE7Tr9lHypxfcpv_o0opDU6Oab1HMalx3ZU9LP4tmk4OnajERY_o0jphou_4ubl7badCMv1FcUTJVDgycKH-d7dI9nIBQDFi3JUJ50lUGC_ut7-5z5exXqEKeNBmXfueeh35kNmgMEtq4ClI0-dPiBaAVFp-ZeYPVoIUpZCeAfpc8UFzaCA3TKpVYz1pn0EwbqVsrZAwH_x4yHkSxixOTukei33FJJgV39kNuDxhSdKyeJ9nK_Zyr8bjc57pNZs0Ae1jgAvp4ssSNFyqtXGlXxKC_DFRoLyt3KRVlnxvC1DcXmJ_fOFXa0UvgbHrvIZD4pWBguM153n5Zn9ahdd9BAqE_NaWVKPugbWFRa33k7YX6-Iw-VHr7EeE5ziKgqwcPtdEBqqBZjjpJVQXtuT_Qfm63w1Jsdh2WneNjrwtpWmgUaPxOT1KXGvUzlAIkBE3sEih_ygemwYv54Z8HfePoq-W-dBIOYWWn0PtVFyUq739qbY_e1EU146ZDjDqts-dxheeG9DqqQUMuimFwmpQovqX6PtjfzXjoOQJgyO6G-AGEIByAbZaKv-DAXRtuNaTgEY1vcK-A58RvMrTIpb-UalLAU_aCCoseUANQMVUvknxHjj4sy8j1k6u9GHnKYV48Nk2RUbhKyPUmKOs3EVVOokV19fkwlfm2WEn61H6mnN-OxAyiFPCTr16qMX2n5a_iy9Gfg3sIzXXKNdOF7k-D0vt0Pgf0s48h3iGgqPoe9yZk1kjM_YDM-O-1nLIjsDuMjR_J8ndYieLjWdEQY2CFIlQO7f4Fls_8srRx8bypOWQAteHuDGWyua80qtsN9PcVJZabkPs8a3-r-EgxI6pDlWbgj-JKqw0pcxQErwQO2T4-q9y8fDsdDzSBCXqfT9-RyZQyKf-TSpzmyrgDcZpIN2ONlAuXuFTZcPobseQaRFZS-CCJWDuQBIj9pVCohabRLCAqt_WDpRLCJ_vsWNsDuHeOZ44NDQwvjrxSDhQHfvEX3VkPrHG79fgiJUy1i3w68rb_DlVvzG4SifcOIVt2tTX8bbq66q_84yabG6D-Ydm-qFlT7knYe5ZdYd2VyHTjSehYCVVUNBTKY8ArWwVJQL26oCGo5rXmwst720N5aUqnqsFGRTFyLRPnwrIweqbRoS56KaD5eT5I5Hrd7j-_Dy78b-h-q0U-xb_25s3JT_7PRN7dSAarCEBebleWwo8dlwQX0so0_ezxmOuzFi-oo5GXdzwD33pKIZTB-TULh5aTqoac6-UcaxXLcu4hS6OexkMzAEy0AIMWsRdiqLOsgUWZ_a4zgiMV9vMgMig5LXfmbGTi-WtBPlWAXr1GdEsYdCg2igZgjklN59Z9PJItI6ZcSTHtyzDjuLAN4IZDM8PieRDeGRAcAFBb-CXAbmY_JuKCJHkwRk3zx8vc24Y7hCUBLknN2krSNKUWk5wQh3N-EoTpcqBrkzw8pj8wW4IhGNHtNXDmibxQrbKNJcCIWsbZ6EQnnxmOLbVyloFx54ew3AY1lTMnhajxNR_bsHXSg9NE2rE20xL35mLd3Q9ZnIzp2BD3ba7tiJcMGtUIUnzb2i_7Iq4v4nU49EnzF60gMv0hQu4138sbYayOe6qJj-IWiadU3e93Y-SKQfxXoljOJRQDEfaIVzxGM78uriRP7FWB5oCNzpQJhy4ZnwpFuVP6bT6KrGV8JRDaQQoUyavF_Xj8HjVakTZHtoY7Hn5Arc0TyLw4vkB_NLMvQo7zJc0BxaCDVpcPgYGCPAQqvbGWI0V8Mr-nMq9cUroslCJCZQWutxgbEKn0fTT-JcCWnC7BmvYiNaNAhojyC6vtsvDHX8EjlaJeHlNjCZCDQB38T4TY9D3NcNlYF4Qcu9RXFBaTRSYGV6bgUwYY8gu2_xlsXLEKb38qiBm56SZOQl3ywF4XvEdrL2bUKQrdK3P2aT5JDVvttBSIleP7XV24MIGRNJ5WQRpA_DyzNckV8EVlG6biOKqGODnBKh9HYlBrNyV7B_QWb2TZPgFZBGAMG-NYg0PiGjM52lkJyrdd9gYxDFosyw1_vDm04wG2lAzRE4qEVx27YUbeUVElki2gsDhrXhaXoZU4rHxAjItIYqtw1SK0L5gGgDdDtZ_4A-Chx8HTxj3OW471t0R82wfC4D19Th5XK4WwAUFMoJCLnqsm3HpNIkZYBR3SSwXu9iG59splr5pdodKo5l-f2UdkZUFICNKoS1jS7OCfzMeVZobFpwDsXczNAFVVf5CatJKzcCjnGfyzodDwGJXxwgVo-yPpPi9FK4GJgAW_fJ7JmAsHNxAyhX9tnsffnUT17LcWjKYlnXRZBuIaPVkuvQTgDEwB4Kf_aOySkgkEzfbEzn3tPZqS44pcAUHjQLCVVSEqw1igBEi3LMABzdstq6nK2AqJvv3i2TO1TodI55xxNfo-vU3_qpbC28N71Lhv0ZRXPy3vY8WFkRtSYR22JsvIUG1ViFi9LK8j7bvDsdACa4zq5rQhyk9PMJ41kE_MOgZEUd_XRsxJrfth7TgFfno1gI9cYhOBh-7x_syv7mOHxihL07la1bNyDYheOz-94YW5KslzmR1HF-L2aHPcTwyt31O3TFriz2aJ7SjRrwo7otXmlVlLWA2x4sb6XuyKLSK6POzh4dRcDnV_TJuooM3dn9tS7YJuf1CoNofsqroi9qsus7-q8Zw5WhX2zsublzr18n9ps3VtY_GmKgfgK_86z9NR42N55WCle2juJztJPsO2CiWdbIWcNROGFJVU68bSL3SiOGRAeS9hW7fVU417GT0vfDFNOJ3ol8w6rnUhaa-bJrGr9tUx0FArGgBN3c4DF0EaU6_NwxsW1w4LQfwlHTGZsR6hpO-wlMnnjDadTpZvciwUr7BwyJgOZGARXfmnLk3rGtXBuVFTpXQkRQlot5rm9rCc0nemSQX9j5FnlZwUBp5wZp8JqL4oOC4pZKF2q6-gRd3oXwGhh6b3sY0HXx3hda1M_-gXdBpaoxH3aY3AEaDAXtapwujDliWI3jBsRS3GYax7jwMdbVzbdVItuSCqEjxMApw1h-vWGqx_41GlWGG8ptMBSVeeDiBHIt2AE4jM-AiBgig13c79XowhtITDSFYeP3cFS3XSo_MoCtQcsMn3Y1F07ZeAhfCKyRthu9jLKS5AXFIkFfYUtasaEd2Op0thK9QDvMniDlBNdkjr1P9ou_SFBxPoiWOcxD_6fJAVb5nPZ__RBOIvfwjXuzc-DSNZ5-8dEe2gn03SKg970IAj71hbYur9r1pj2KaYcITLJCaJhPm3uK4ZBfqH7dU3BdRgM6EZKXK3waoNbfUgpXrOmUNlyOsxCddi9I0kHh8QAOUtR_vBCYpkC3BvkROo97Yt5W_D61L3nc7Kl3WMEfABH3dWsvSiPyTuItZZ_0RiuyXCxZVGKLW0jPDzwBlzk4xXXqsSFjJy4aOmc_yXo56PUW7vgCJ_5y0PdFW5l2EBj_XRxx15bHEQ1H_mhcaVtNUNO14W2DJLLHpcCyFOodg3Ed6IVugB5Lg5onRjEOzWCSjYfm2cZtXifPn6y03snLVs7YwJIYPKhdFVOiDcgK_diylG8NircGOJap1M77fSnaVC3LPZ_x1YxsWu9zxCR7vpHh0QFy8SCcXoIiFzhIUvncTKlpZKPGpWQjATbzteVZl9qhsN9f9-NL9F0vEH3doMlQ65L8zZCQaw_nfPhzb_W0dA7DFH1aXkaiqFF4em5-ovYF50_wrQTU_dwLX2Ksb3lJg4n8--ONcBKYbMAilhf-7LAH1nHwZR2BSzA8lP4fOJqJ06PdxGWvt82mG9e3beHWAmadK1_a3MUJlxYj5M1tPnVsRkMiD6t8FEc4Fr5n5Df3OfMlHW0XWAx4upgF6uN7lOo4GbeP4A248ZDCC5Jl2aZ_OjIrL5ul8bxJS2EirPymOhCkWUuWHQcARcW3BDNLgXNPyNaqb21Am29VnNPxAJ3ITXuebBF2Ytr0bbrFiCFl8_4Zjq3ltB46jELIz9jlDRq0HxXacM6cRn48tNuOKaoOHfkx0bl5JO08JdHss5Kv4vnQJidNcbO4QGUibYrv1RMyecUmH1YVmPoc3zsWNLLPl0qnXgrLtVH11ui63qFAph8f_sa3TL-W7LD3vQHYaEJIT7zHOunzWo50NVaBC4h-pSXKcYkAoy6SRK5B8hC2uENxmp4MMBDpveeclCN7GzrjlF7kxkxvvTtB4AQQ3MN59IYkznxpDXX6Y0k5THnC0SOhY4kk1Ya3p2BAtRp4ly_uLX3zajCZ6evnaSwIh2DFOsvPZ0_qsRIqp0s0TwDqGVctUWYR0WFo8-Bde-L1iqhW-VS611cSSn5KeMtMMMfnGQb5P_evACSCgEJDksazbGLTbFVI5n6U45Ls05sPzD3jk1cCuJ6yg66SL5T5SKSpEwEJJm7MYA9P66AvIvYWaR0EhjPFXLyxgXLG-m1s3FIsuKFR9BLLoCRFfuVa63Ytf2b7ymT2gw4krE8eGLS9mIljD3wtvgmUjhF6KFk1ow-4gfll2bBkOxj-FI14uZ0Rq8R8_wzKwbgGNMocwWKvCwmHqAors0oIRz6OsYieEBJI6Hj5dkGkTAliyVzLoNum6PGRLvDPNP6LnYCclm3G6PtBC0dKxqgWGJuE4TewPclVccjt0vddipV6ta6NmauSXi--ZVHdt6IioX_mbU1No452MRmwj3lIATWAaf2U9bl8Z1rZYPWDMyBen4PyZTmOZVcUHpD7RvEGucInFlWMrS6IeYgFJ2YNmVKjl7wjApWQGKKPLhTXQGyr7b2ln6q2-1hwaTaMr6miuODOp1Fcw4QV2PTZAQZRZHHttyaz9y2fgGS-eMGriw5Qd9XeyPZ6uzV_mL2r4YgIfmiFgobeN51gnf5BojBIz791edh9jWJv_OBHFuEWftqk9nzuCTIEb7SNlHhbDhf98kOAlh3RHEGSGk834rzSjUzZVEvkCmVWWirg6NfiY-vsgDbq4dHtTEiA_5khNWeuRWMu8L-fY-x6gGD3I1xlCyEWx0Msk34IxVxx92sVtmbWfQc0gMldriBe1uw3_awiCiZDv_vpERe__m6t55pUM0m0Vw6k0OxK28FOciOI417rdB9PG2g-LaUTR-wEDmP68tT9cs8fhb5IgMuvfhTKvpMAnH2iXb-0cM15ctUREw6ckN0QzrsdSddk5K50b8PLzJ87WR1eOsxZXWJGbj4dSVQ8euK13l2B1kEMvavoJoERsqJ3LB7XXAkOiGcnUQQdOezRPf8DaOPBG-k_Rsm9r6h0B-1EMzkjwFBxHIWgUEiWv6GvPNm7jkwGkH61WUX8Dfwey3ZJ_Rv5jDVQ9mMWevJoFXj6TqaIbVdrhuHRdSeGHx36OxYdBsaU9agiIMbnuEZisqJ8C3MDp25t0N6tWFutf_ouECccWWcQItjQunCTBJBW4FQp68r0MJHFxMD19m511u-0OFLOQfFqVpIIpWcfeHBgTblV0Ksionn-bJ3ZPH9iy2eR5WgjJS2MxcSTb9vrovKnzLRoSIGoq-JiA3GOP7HMSL9lKgg0gOmSPDcjYlbB3Mxs65Mi9hf9PIRpLmmWkz3Ve2Qy51mLqMUFsZD7bTGKeX8Y2hacwn2Ha2ansXDzg1lP8YfwDP_1nu3RSDPm-QQkLbWRkIaK2GKdksJSHuyickeeHe8a4BVcXVHjwlkFy13Xt_G4OFoXEOWA4hspRcrU9y0Ff9T8vJTcdo0rHaVMvwOBxDYkDaZwkz3PDgWDcuYExNNkNezVEQwlMVGDp7yihzNDPAdTyOmS_nsiYKwwL8VZn6zanTl7ATUqPGyW2_wsuq3sybhYKVgwhJXyvzn0hA2_G43pfUm2FFGuUPgU7QslQAo6OPEeeDllRuZzxK_mohl1NhbtiF3hDxnjUlVY4Tn7ZdO1OTUaGq8tFM0MknPc6WtLXxXeOFvk901v-x5OIZrP4pjt4A0mba-kcSF9YhdzMJvyVcQZsiqyXUVETgEKxh0DiZ8n2fyid0DF3TZ3CyZELXT-_8dir5cs_6Zy-TIhvgv_DLv45tfyqMvNjceOeFIV9lLoKZQor1VLncDmvn83_cCBtj7fI33cLxSREOuLr0WL9LSAj0ql62-S-idrPFyRjGTsDcgbnizNZ14UoXf5FAK8xBZ0a6A7v2xOnTnllKpMxOFAKokC28LXaEnJixbErpOcG0XrogXh0WtNNg7DiBx6KO_4wB4z4Re2AAiMDYVl_c9i4WrjmDxlJvIa_EqMD0e7mZvAWQ-FHaPT8pbsI7ivoFl0DfiQHg1xuM9W_ZLzIwXtMf9w2NbxVqdVUNRiInh9O5s5-gqk-VRJXwqO2PtV9T5D26BHtgFPg6vjsBMbmYNQK6qjqm6rD52yU6qBTrFGIDMwQGwvZKZR6r5q0Djh_EPb5xocx6fUn0jewVUmRVuMflKK_BNzy9QW2SJ5rAhnLBtFh4LqBonXYhvX_zVq3khur0CNqrkM8-qmppPKQvy6G6iOeG0oLwbDNucn67AqHAj3AFVFmx1HL9PwiIlwrX-wJVoJIP263rf24rdTqhG-8_ax_6OCB3QGbg3oYS1jVnc-cdllJm8dv01hddx4mQCTRYg2WFeZ_eBYuqOWKLUmlt7MZniJzysK_8BsL3UkJGT7nZplUVTU9Wt0VXLosD79ZOlmxi10m6fqWJc8kVSXrZiPq9U68Q-Om5626Vilwg0Cul0kapR9cO2m_XkL8fNRHDqaFSCrsv4XOSupgceU4aDU3CafIPUGw6X6hXHUgBeUro0LLQeuJVW0itmWmN3bV4nX8mxS1W5-4JVPGe9ldtoZ23ZGjHVGwF3fQmf1KMRvS4WXLbHkRtmuFKZ53rW4eMqEKU5p1y8hMzV6SjWTzUltM2yAqrwvNpCzSrz08V8Iy7DFArqdnYVlV705Bep-4cAh9kgcGeT7iU9soT9p1XBbHBEMpB_APonKcxlyBQAqx9spPV56DXadzkwNCmW1c3gHB8rJoinNoY3CXLbpNLb3QND0qVMpUC-kC2VsLM7kdmIGPfm1qXKlGRNaN0id_JPGNkZwWnlYrJdh9Lvjhla7BwIU1immtPLFzKGgMegVeRYdTTIKXxgLzSOZwQht60Eq2uwbQDOAXElIYA8tSUHD7g9VawV8N0ogolg-l9Mcxl407UsqifjrUScJ8lJS6baGXzvWGsICKiG-pYmCEFphypVtyYPhqOuhUaxBfa_DqqVULxcflvJYsxVgmAAq7G1lCM5qA7TPuI5eaVcW6xzj4hdFHMcUe-8QL6eS-8PiIqlcxJbYzFM9DInqIfw4-7l4yQ4gxFyKuA-6y0u36oGmJUDzhcc31zicoVlpu9UnqPGZOH99BJlZuGaeAK0POtzRELTezOrRky0cqdju64Snxfe8fLie4AcYEeymACgjKYthaz4oHUEnBRSO4j_ncyVLI4m3kjyfY2uyj_EAYvSKuTyi4s2Qv6o8kZeYGC_nFSuKR4g8epMs9mEwT6sYcbaHxAcOfoa1ZinPVFBNbKwz-oy3BL7VozClSXe9dMT3GlIk-6WhQVO2VUURal9QWED3uPL0gJ8I7YNvxJOjTHogvVeb6EFzKho9ShUF681Eeg9GpeQyda34qYnq_wQIZ8aatgtrG0SDBUCoM4mpO6ZwVwj33hBK16VV2H01px-fktYJWfod3NgBEPDe1tNZS7JHr9ML2kqgoARpaljT7CVyMPLE45BD3RXrcjILkXEhJSAsxsSomouMKuwBgaoeXi_Cjgu3nGNcHpYA3ipj-CNgBpR2vPMG8NU_2B4TNrd2msxrSyodZkN9tqhTE2FAnaQeLv81HUirgWejjdwPhgFyw3xYr8yQ-OjaQdok4o3IfgRApAhGmDcdqiqfS5Ibg8fKuU5CvTrWFuj0E0C9dam2E--JfJ9xP_vK3BNTbHleA_1rhLWaYW0oy4gnC-sQgDmUWuPZZNwjr-rYJc4ERjpMTOIoNPiD1dzHBY3sg5JE5OZM1D7Jk3ynenD0-oi-AXMpvscKmG6IGU5TPqBbpuRoXTDFqsYH_vlX0ew79HZaUvsIm6rUpXqgr9lA2YkaKcZ51CR6l0G13OfQKxttVeDpY-2_haoB5nO1AABa7FVy4Laydp5EyflXFNlOZpbrtzXwU-S2_JGCh_wyhLnvsskf9WK5oZKLbEkDq4ooh_8D8l_bmgfyCqFKNfHS5iGKr6OX3owZ4Wozfq10WO11vi75rhS62b75OEahdBpzARWW7N9MOC1eJUpSHgCXafaW2YWENK5DJISZ6MITkscekwpIMBMzlW7gOKpdZLYSLVt1Ze8ELyzRS_OWo7dCJ3GVWXYQSPDNQpsNPQ_lg_3OVOkdU7JHELMzt1IiWIOqhGz2uRif9deaZgk5iRzGJkZWZd9Ele6mZipL0bSYxEJ_yi5l9PTvXZ0PoB7qyiCQbQGt0txNyvaJXqfpLpguJNStat9OSKnT_7naNJPwjNzdK3x2KpExyBrLKd11DyLnhjcdki9PLcNj2N9ZEugcQYMHXgrbDyoGqQm1BpasCZH2F4RZsPKETQPV2-pBI9mPzIgbHtjrbrDJReWqo2WmU8eyOyn4xm77Nc3iewHFrSynCjKFBZ9buDMoElmb2QvauItkVyOcQrqub9AWNHl1DRdKITu-q_jRU5bO1mJMjfUVtH1f5ACDZIIQVY8BzvfzdcZ4ziYGW1j64ybdJsRKYv3BKLoOJuS8d7zABw23nZGA50TXvkqsyOhxxRJmrUCAbXsqfSN848MIoxBU_P7NZS2UvMwyztTbQCoAEHp439OCmEdc8FSU07RMKhGAlrM78qI99SzlYVSLJjqavC7pXZ_hUWbR91R1Q2zR17_gmrCcRRzo_HA7BVhNo6g-WVeTR2DQyMx9b7TcdJqSOdh82CtrVCDzWETzMiET575A0e5YAwh4arqAzyqSMmqsoFqXRCWNyf5bjikOAVGSwePmGNbK1YPkrcOuoxEYQ_soisfrqcVxyHHC5HiC5jHw88JCvdm6CAOiFjs33UQ1u0MVTGV5O6Yp6-8edd0gHUFAvpryjGfqqDwQKBwfrJvk-eSxi5K0DXckPVrl2yExcXHaNNbQTd08vKDlXb65QdJiPfDMVkSPVLQLmk7R-R4U4TR2ZeLTtCBB5KxTSxpblmt2UETc5PvnVPE80XMNj-ax-zzPKCrv-elKoSKXtG1iblCnZiRlV_YOjgHlJiN9mYbK5YeTn-tJgEalmXuYinYQdn0XGGmQahc5ADpoeBA06Hc2KVo1VjTJlmhnw2zf3lkXfqXLmgu4KntIkpvo1AsEbM7ZGX7_HrbngVuGUQFoKkECRSVl93aXN5EAdzt4cl2w-_uSKp1EZGgnZu0UsetEvaxo-DBNatAnIOuh9Z3aoiOuUPdwZMfOks4Sc1nrvwDM-BDoG0YQ86TvVje4ZrDlsvmAVulwsmjBIH-1otttzx9X9CeWx6h6WJqIBQDk6X1DsAmgg9DeZmRdy0UHP4q3rugP2RMU9FKVasn9o02Tqwz1l-7wv7fJtB5mANHv54D9KunaqsYV7L8pxacuHFasVmAmVBpxcj7FJElTU2g_9zev50dIsr0xX7_o6stfPsCHZ-pMuVsK2LEUDmBoAFxbwpW8BMV5iJwljisAvAXekJ2cQUejJOYKavpiwSjmR8Q42cUgv_doXjx8c2elfHFLAiN8d_nSHXu7CCoDCL3eNXRl-yBGKZnFInEU4hY0RPe5aqNUvaofd1bpYuMixIJvgtUEujL9r8vLIVQuF-9u1iHvhRCbkNc9uB_aDiFMj7GGmO02wHNQe6-oAzvWVPQ9hlX03-1W7ZWbHz209Q0a4p6AhoHU_d9KCSdWHLiKDp3itIJfRntla3IlPfr0ZwnBRVi3ukux89RtBotfo3W3m9oKJXbO0Brn-_uXavDBfKhFfNnkFhYKGcHw-_A0oqeZnPExZ7ni9YV6X_K4tXy7quNHkqVk_ATg5ukw6rH1P35lSsZ30cpXj3rc56K6Ph6JqASmhV52GqOPB5lvwjIWj0bA_TLQngNlkpOl5I70h8lgiJ6mn-WF9-IZ-l6rfS72wownVdFGrCxGKAAGtQ1Dfz5rcvlautdpT1O1Aldd7uSTBw3zu3EncWTjZa-YaHKNJLhEu_Y6qMzcup1fEshiFF1BRqCfDkimdCqDjagS25lAaIKSXFj5j93x9wo4Vp8ckgulcRG8ZzTwiED0s7CJxqcxTaUcH1dF3gVurWF8LActdzr_KHzTy4Empso-zOHEkCPtbK4Xclz_M-x0YNYXE5Kak160sO7kXTUc6UGKCU4ebaHsJpF9pUL9aG2vkzjG1djFCWarNws0AiKEOvsrsVIFzR2LLvn9AAtKwqzSwjv-iU9SChrX4o-pGN6WBWZBxMPskSHkFVZUvq5X8nhugC8UhFJVFfwD4CXP7TTmAbYGU0YYmmk_YJOpqmKSjFSXqh2UdIhy-bEnpik5NBF4zbu8wmqX4Y4m3cxJAu_5nD4v8FoRVoxKc0eKd4NXJo_NC75J-r-PPqhF722G3EMF3wMfW5z_4y4GSCxpFxfMJj433Y7Ac7rlzTyCVe4wdHLne-fMhGowKk1F68zN2m_5vfqjpGxXG3SI3Z-n9VkZBMxt-C65bMlmwqcVPWcza_hVFNA1y4-TWkAnIcevsGf4YdRnrc1BT6WkL3PEeOs69N-z3iGxc0v2_VUWOYTZ2WokgspPaA2l9Aa3RCzaFagIGnBVjNHZ_-Td_1HQxM_3rldPKk4YMks6PAom0WXlc9tEac-OINvnqGhksaLGjkullxdCZ9yQcAyX3N97ghTMMT0G7_zssMisYubrIb6LHuU0IVptczNjZxVdQA_ZgnjyoVuG6PKN0t4UE9C41YQgUH2F6vWi5X_i8YsjduWPazoQIFHLTsOYg3xB5YnoTC_2NIB_c8g9VTp3NdSfF05RwWKDaKENzrzrGN8FiI2pVviFDKH72Hu3FQWGkjdfvTsiDxqwbkBB4tNPSbZq-laxj03-vG--U2Q77jOr136nIPTRyvWk1XN7-eCf7YElNpYrY0f6x9zcTfdf75xtPfSQk_9-adeEYJfqhB7nOSRm0GRW69NUnp36-IT-gUfQLUP9lOXzbRgZ5tZfTcymZZu6sOvn-1VEdfERAvxuaw4HTO6dfeP8iEVDS2xxlFRY7YureKcEmqZ5Dfui-nyCMt-hnja5zshR-Xgr996PdW9bIih9SUHBJ0rSWFrsZII5_YWTQE3w8lhGfXdGnBH5K3PC3nfRoew5ZuUUMMM_c9c7weXX5yUGX9hxJVPDiLp26CCc5glQnZ246rkVLgYrGKux4eRW2Ripy93sP-uRKARUXgrKjcyy9yQ0pK-3KNivSfHr00IkT_74bEcbs9ta8Ti-Y1t5SCk4evtF1Z1bzUAKq7TszA1LxZ0RwfheezsMO6AqgP9X9NcF3mDTLEAtRcEe-j5mWeyUPkK5Kun1-hFhKfbPPtctHkoJ3p6Wwhzoc8vRHZAHJJaVy4Z81RXYQIeXa2xfRF2zSk0Y_f32B5BVZAoD7vnTcWobkd7VOcnkEVLsVjduJRn1umQ0liUTLld9SlZ07GsDIDXRtVK8cMdYxGgFjKFhUoKvqXivkjKOkORDQa7lweNv-8EYaUkCtMyVfXNG_S0Sk7OaSs3mtO3OwhF3DwyYl2-r-5VYM89evYHUYKt18UUev7A6xwRE-MR9dCQw-J-wrgp-TYyvyfGJjOiCWedrHAvmCZM3rzJ9CTu2-Xp21lo7RG2p8cCfdwvE9wDjDJAmZ0KVUODyVR4g6p8LmoD4lFA97CsGs5Y6WaK4KFBrdUooLSixe0YxyQvB3r2P4BW041Ilk9jwe0wfyy16HQEiC-CY0DYmHo1bxTrPBw4LopMrTfFGmHhIroCV6VPoQ--YosLj9xfmujDOpQTeXmd-gzCKkiqE0z5xUCPv2aY70Xyn_P3Ut4J_jaZKTxFfRKFHRISQIP9JBTTqfqbQ_S3gIi3QhVEX5CyEDtdp2irQFFB_eZIXvMQZArauZdaq0o49bfRjO9GGjTDxhveyvlLgU1jp2zQdA6tP31HgRGfSthp3BsKq1Wk6xs4ewxHQyAFz7705sEbZ1QQ1jG0RtyWKtEzAfMkzAGNoaAqXI1yNUmrglO4atqvBmVL75DH5md8_X1IXP_sWTwTiG1QWqOqiA5n5jQ18oFWA6DykMu7KeLliB8NJIPG42bNAZsz1iNAiySwFE2ehOKr9WnAsjmLxTu4jWSnERBaARmxW32FShdv0kD2RAa1Zuz7_3jZOkv-n9zxY6kh3vzGco8IMTl_8p-tfO1ZRXtW4ZKjkBQsu8aGjOwmh4J_N28-0I6qjXmJUBja0Fc59FuqV_BGrcBaShQGc-ahv0Hak0BK_Js014Ly0IEKfQGLz-xpCwaV5d0baCFlWCB1dP6f1_SkIcg_R1nhtMaJKBJOx06SLZNXipuCoiyCJiUgE9HNFObAswlioTCNwtAH5u62k6kS6YFINCH0Pq4kIgFlsnB1dLyH9zo2W8ZzQWRs6zllreIy6EZPLJwfLx-8Wy_CS7cvXXQ7ODLH-ca39KxLD8HiRxbJRuI3Nk51TSgUoHPNn3Na7GbInEPOKF7kas34_f1WtmICn3Nk29EL3jbKW4zEmyvyPqrMt-bd7CoUDxLqtsIgtEeHXj2_VsvulkLt199aBs5eieflq5X3RBSymykCrLpEbIRwpARbqp62nUUl7z74hEbmylu6s9SzxuKcuJucirrS-M36n1Thbeq5rSolUUC8Sjm4tiCAnSm2cvANE_vQmVtbN7WX7DbHR3e_CkHGO9R4mBDVsowTu--QC5eYwjXsLn4BVaTWEmBdlfL7sg7DFAel9aBO5VECiITDZuU7zTh1siBJukQwB_JJzb7Ax1TlTyHTRNdV8UFvki6J2XVwvrted6F9tAcN1WPFm8QQVBGSXxOAgiyAYCYlg5DvYjBYL1V4KMoL3DkshmJ_S9ZFDcPXkOEKGfcDdvXJW4EPYt8TIjuAT57LolsXkpVfBI5ypxNtg2-PJxXUMcYoOKxnEXdczfV57TADVUCxSZAbr3TZT7ww5skXPwtE6m3si493B75_273lex0b_m0KGdN5kOEFgNnJU2QYDn6SUSAjulR8XpKfhWr533uXxpfSvwQmi6VP3tCmJ4PNBNOwyUc9op5c8tURd-9HqjHEu9IhNnDx-tb48_ycVIoKeIwki_pQvHWyL3dwW9_fP0d6E20yEvSRXNy0tSQ5HmmQf-ytHihXYeoqzqvx0eD9fMHyVdfy4KeTigQw8T38Jlf2dEMYgPdwn_l6bvHD8c7Iqb5koO21iP-1wYEVunUvlJ3deiuWNg65f4EC0__mfz_E1iFwzbLsAD7X-6OZz5z6xwazObA08Otn2lBz8p7rnl_5Du-UXwQhqQ7FQxljL8uocu_PhOo4Br0nwPSuj49KVyWNKWHzFIzsfG2x1WsbZ2IOoT9e7NxhxZGrC9UKkKaDx8QARm4q3nuJdbqO9JQXxVJNZCA2Yltsf47yHMj6IOoa_Clm_Or8Nm1QC-QRTwAkvY61rJqAZzmhOxFIF2bwH8lHy1xZrrPGd5g2Gxy63HeLeuaX342dkzg-mu1_k9oR3HQ6y-ZvTQT_K5d_7XZovFL5CleWG9YkVV5oYPpbwh-1ZhctDFfRgS004bqNP5rGugZ-ri25lFuY7IZF3tn_OPhf5UHdyVMYEXmpJW1QXfYkAW3sTP_WsLEMJ6MIF2jlV9tl7_tIXYJXKIIsYPni8PTY8YrRUCzdWkONz4aUxDVAHozY6_TykioR8adOiMuYXNCDSfaRvoKd2Vn20lsbTjoYWUs7VcSZ7GuTLaXi1UMDMTXPcAi1VbCECWDGS7RUvrQry9LYaEzCO3jM-1aa2foW3rYpDJys2tw7atMjA8cLMVBIGq5ayaLMn5lAojRpzUobBJRWOecwod4Xf-AfI0MoFPRikg8W_7-I2_DoCfXQLrKYQHfSfybCTM604C_y0S9QCakjlh23DzdjQn4LBMwOM5t1AvecQanxX-fm5f3c-tZzjUJCePfgYEnkBsmh6QOnKgLrhiAQCNaCXl6P3M3FZcfS7jWWBNEj8zUkefSb49Jc67pWndPS0YlzaU7Rsaz_IhD3qZc8PQPfogNmrVFjx3glTVQXRH5fUFK8MDeGzQMknNBxmD4VpDcFbqjc23p8gZ-OfqAfDu_vwipcph6k7CftPfwGY8JtzzAI7cC7WX05_70LWrGgU9msqqP1kWPmvm38P7OAD4yFk_krhZyF4ISYkDF7VfFdOmqq-2u-5J0xXGVlA6vZilExvLQgJm77ILnVDQMUgXYIEW4aFCZOi0Y6rGmj1RVxKIP1gKO0yYUg3nhMKND3AxjkG10TYiL000apEJL-E7rXcVHc6wx2BLfR1vXvYwaacmULqHg91IoG6meEaaKheEVcA6lIPlOE9bP6LHy7-v_43h1oukm1zxe30790NTmnCtBp7t44TfTGYeOZy1L5Nbh2I6u7U62c4DFPaLCSbofN1wJ4a0BSKzojN0ZQEP3oet-3NQxrOvqHM6jtqRfdZS96X250JyYk6ZLv2Qe8l4tk_lKeOV0Hy6fAfXvu1ibQ0R-6prL1TLdZ8PYCiTPlkekk-jCSgLzymiga62o0oKkno2jX4T2kffe7KzW2IRAMgyyhPOUxkGGZWCEXVk5dBPeJ1YVUeqMotYZZkfoTfWzOKdyRDvIPca5PrjujPKSiDZmaCFZpgBiJK_QBUw-iNKwAnnet8lk6O14iM7jPJm-vjncpPgQvW-KhcbHcVzm1X5P1GA54G0nzsTnB7CnTupXD9cW3JXWkxk5Na0BrRLQN4B1VmEPeBxNB_ilbGVRBFaEdp1EqPDbKHNqQps4xdWFcchQ3UB_UsqrX8z5H5BUqBD_uAYMTiVvQdiTXbfJ0TWj9hnvC8mBysLf04KVdcDu5I4sHH_OWmkGidp-3kh8JThlEjApj_1QicNZInUTafcRD874Dr_EIVlzQJqWICCjJ_GZ2HQQus2UI8yHbbbdCXkP2INNs477iE_IIpWonYKm1jMnsvz_mdl8s5REKrnVeI8rm3I-Bt-01b4geVsGolM942apzIGby15GtpwFMOzsQ1fg67-fQfmHYzh3gNTKzUmjcYjDV3hAbkC56hMWFcskoxd4tNmxGq3FzDgCLNCdhTgC0_LYu2SP3Wp2zXdPUSTEPUyS2AiXMvvDfSZRHQK8CHTam3P_MaymWK3Y-sxiZkKPT3U0tgRDUmXO7umJ2WyZH6o5PIs9ShYzM7vRIUqpmxcMXal-yIy4F4nCKywTZzgXqkWwoJMKC8GcD0EYH5ZNyUFTJjZN5WSg6k8LMO3ep3khIPGQQ8i93MpwwqBu37ybt8uy9MKeZGNsoI9lNTIfkLIezRgTLP8fteUX3Rz1NvJG-1ybUSG803hdjBuacvDnoeD3NdqvH2nX2z4tOw5U-b5KQbJwBMXvnnuqjBOdhIPJvJWHG6MVUruLMFAl_GP0OqOIS8jV-jaVBWQJSm5WQhE6zNKSKhsZk_DP81f7Nbjk1aU5dK6aOTRlv32k16I4nL0IgZeGBHZ6qeLAZVWWEk-vaj44Ec5lRX02yOS5JLYEeAQfzAAXLSrhQIBbrb6hHJDDkIuuXXrcVB-fwWj-jOeYela3fNGluJQpCB3rvTumaoVoeNQ0tPKtBd3nDR1_J35nxfCwRdDfxwUV2kR5p82ZCpowU-rASr-V81Nr3agZ9v1HVXzOBT-yoMRRkxOfCwdeg7FFrwS_lFTUCDBVA6YZr6kagNkgJPapRd_WYsTAnzlyquWrYcTrirliKPvAfEgyBbyv6MsH-MQVRtcARAu71AKlJ6lnpCSuPFXUj9sAWgWPw1jASzGga6z-32dr-rQ7dxtT1Syx8IHny2xlInspWruX--rgGdp9ZfpuYoxIw3JMuDUL4Dw28mjZi5F4_WC5U1L6ISIbHtVlcLmDv8Ud7a5kuP3mYqotAfoWT0ov3AHPnHk6eXfw2OIHtxHLN6Jsixohog7K9o-4CMCtdNWObWhTzrP2Ys83WLQtiNEWlLMcIE1DR24baYC2Kcjql4wFxAudTaOgOWkJ2amNoJToYGyCQrYPwlWdS8E6JViJSt8YCdj8D-pXXKOkptdBtVCAzCLIfwgia4-Q9OifkeJgz3NJKsNmmEBElTSTwKOiqRpu4dmTQwAW7p_kd0o2mFn7F-kXPR5iNfehyWtBEiAuW7hnELxX9aqN0cAQn5934zw2DQhCKBIXCrFNtBjMiyPh_mpY3Bv6eh0eIcGGn6us0NUra-e1PKCR8RyF1bdQad5-w2aTxffKI1Z_cC9UQHslp29iCzVVECIcWJoL-PqAT00QJjO7idWKs05imdaVP7bL88GSpEBTcFGZbaOALTzn9EW3GmUfjF-B56bwz4QSYsjRUaQVsTyf7uSICDst79oIIO9XNeIbgT8ZeRn8SSt3AXD7Kty0noO8LHwXN5woAA_lurLIdmddU9GZr7CHDNmF1g5QGFv8GrRtx5iTejv0dUC3nUvBtEdMNTBvP5mbFg-E5dDc05Ou0YTgnkUTBGSWdcqEPP449Sg6_BZoB7y1Tpl3UPfJBs8x3zTq8dHq2qgewTu5kk_Bj31WXQbFOAtsp84OoT8uC70AXYQfyYpJb5eRkjFYu0m1sPbJ6H4HQSlzojBw5tiFVYGubNQlIZ_HyiZh66BwKRG0_QEHNsIz06wengDV2JByFiSawYtP3ufvr-bN6Nar0imCnJMKjtJy85gRFR75anwrR6Orc0wLt_DJdrgv8m9Ht1lEgaq2Mr5kQ9-asJdmq9NiJjw1f0XJ4wuVJjxbUn319kpgOmRV4my7_VqgXwWF9QL0PAtx1uAq4QvQaVQDIYcKxu2GZaxPyvdLutXP3Jnh8qYcoYsZSuTTrdR2al8Cpj8wdjFja3g0z6HD8rkOxS36fg85jiTf806mNocr3rZRzd9HcxYVZ-xMdxBMTMk16mZIvtxYvDvKiltHxbVDuzkzn1ZnfZnKQk13kMHZ-4bLW3TY6QZjHBuLhdVmOgSfgaHspNB0C5ThbzUciqMWUm02FKPdVH7U9GtZ19cLVI1HMbwtxMJWIUWAVKSA8g4-8AWKKON50GvRqK-UqmVO6QPrMdkI8QjphQIFtZTs1B-_kLbpO9LASHwuPaPgDTlxCusH50KXCtiCHGrPqAIiyxGTpKDX1s02l45ohnNsQrAW6UVK3VntnpxhdYH1pq1vR7RhsptrGQcyOgIXGRy4b5Qu73hz63BzsWX87hl2Jo-dwMIR2B3onz9gam2HdPfXnZw7Mz6CNJMRDvNfDZ_zOw7KQtLjlDicd6g1dOkgrNFNaFE-QrQRDL4AGpF91YiKNkYS--GNACyVgu0-mDDkLjbtyTimzWRjDnwIU-n5KUOll02BWmEDVixMYVrGWbyjezGDKbhRFONipBFCYpV5SrkLKCUZVJ9MaufPTjmCnh48nRg-snQhvKNBLt9BDnFyOIBfHR-0kBOZ1ypZJR_U2QbkZ4wtCXX2lDbK-gVNxMtAhkXwE1PM1QQzhM_rccdC0l0OxrjaWCyewOAOPqQ93L7OnaKvKVmU4jMz8iNqfsQWus5S0KrJg-zNhJu163E6mI9y8i0qqDmfBBE3kb3tAfsVtcDB7-HvkOyLUZd_XDW--NOkcMxR2HkmKBRj-UFnUr0p13BVjUyE2VVhNy2T2Y5qHrKZNTcdxXent7byIL4XGowBfEyC6LMLkW2-3FtIKLCZ0w9TJ6OwSeb-eknMRYO9K7TqHEKyu7Ia-Cy-UPo5b9-qPiQcGV4e2k7Eo_hkuWtOaaM7I8N-Ia6YmnKIatmCEt9XIylpS3hh6tp88qiziPqEAqCkhtCqGwPsXELKTBcihszIjnwL9y_dXaaefnDOAVLeF1q-LUYtORLam8qEhO7Vsogo2Tgun_m8BS8jjC82Jpqzx1Vyj42N-oFLUWIHI089vl2TCqHmCqyVcnPaaGvPAe0HeyvGvdtJEZ2n_yXvgb8ZTtwPCDmUKzUGRmgvagbtPUyEG0i_XhjJ66EHvEnHwDJ3UX-jLfCvfVKEJFEVyG38P4VQ1M_JUanTwT6HYXUII6_z_Jvb4_tb_I7LCceG1zKX9BNNAUZ6-9tPCZ2cs0XHOdrRt_88pNtovIE3cSvZCqdoypZjba5h2vnB9E8wN4cESuuHyJKQ97la5bbVZ2YOPMuB66dcEE5KL3JGW9FpmCeY5BgO9fcb9mQ4yMGMSdu33zwZa-SgjAMSU7qCZK03YqC5RaoHfAMCg6rBAwGGNVkjXwN4oo07SNZ6E_lJyAAFyFOc33IA7X3dgPCqa0BeKlIPbez4frvrZDUl0zYwdK3EBJgbNf3w5CtGvZU05zSJRDtnKZmasL34CSYmQk1m98e0fSmtjU_NhcTZhr-AQoSx0qrA8pTINjftCnSM94vvJfG8NA55jybQn_d897Zacw6Z1yuyRUelQblpVwHQLqfiZKCtCEbsZGcvNdSu9Wx7-FrxHHX1c1058V8hcK85BQUSzBkuHU8A5FtgogpXS4t8mq5OEc-hZakFH2Eez6iJG4SMOJ90WyfCo2IX2rbWtiXmxVUGSKQExev0Yqt8I9O6QdaWlWtkNEoS-XtXpV6KxLF1sZ6jsvpNDnpyMNAfzAbqFWGQWDWPiSar6abw93lMSDOza60-XGBSPhEeGFFyh7h7zBv_v6T2CRWY_u9yK68X4OoAi64IRousZBj-F-6WIpOF0O9OEWSjQdvW_ISD50xj9DQqm7P5k01ML7b06CU8FtVKRMZ_hY05Qp4aibFwRwkCrmY9MVQBe0eTvDNh1Lb05QtljIpZgHalfU1taJyHqUNXHC9fbknef94eksTePM4nkURJna5b5jMk1MM-LDRf833qTyQNMzWbd4WY-4jrMB-z1lU5gI91Q7Z7mxTUOjJq5mQd1JLSqc6rfzpBBVwZy4FwP7Mieap35VtKrtswXGozvXircE9hlDkjZFqjw4GV-z9CaLzCSjvhqdHJmI6dkxqXGUa7BCAywId8UBTbTL0rw_yxD_WVXuOr4C9LS_qnDFOtaGpT6OkODdOgzaqBaY69IpCMJYMjiDMId1GPbRAV-0rAQ04TNJ2LKIlT-GLd8eqXmn1ZYppWrREn0g77hLSbLiI1PdyGEmgrJvNoTKOxbLSJ4B1p5Und5lrZ0RKZS_ZLf54msZMETwCWghcgNnGvP0spXOfB7-azH9qhcYCwpsz0GGwYmUEiX2775Qk3dxfnasao-Dq7z9FdgCUnPhet6jIO0PaiCgmb_bvCcHtITmz20uJGUN6dr4WZmShU4yaqnB-I5UGNQHKbC8PYIp-IwwwqrRJgMvtpH2581zavOOgVG2LQP6BEroRn3pLJ50c67bxSWvYFDWa6Ftjt2d86JYg10SnmCVxLnB1_vxWvvKoEAMHl5-MCQ-jCmnA-pJm1dTP3csDsqFLA54HyIiZN_kXjX5ABaqEOsK_tQkms6DIQmNOxRIsw_jDVgx2vmoNvrmpi_INobxIDZ05fkrtjVni55C3TCMs_amNLnOnW3e18My4oypX664nhy0i3Lhu7xBbaLcgXlgpehX66cOyvgD9c1BoqlirrVlY4t_PB0bpKdkn2JLeIHvie3qUdXXZ6LAZjIDlIp2N4ksUceS_X7svJeTfE4Xy7V-UGp40LJejCZQHxYh9UYVBp5adiVRkFF51ecYmbzFjxoFQZctikMn8id9ityNIKDaiVcJnntHzqbc79EdfMP5N8zayPJb67-JkXm4PXaO_9vXGP_Xh8zfioeJI1x5wrID2n2b3AyseGk5b5I3JVgLyg_KlCnqH8mkZ9jkNrb3hAz5XgXdbURkueqRPTatRdzN-x0JYKHGaVs64tV-b0M438E0BFgUSEz5yufzSOyUb-TomRgIGy1laIBVLfeHvAiSeThM48y1u1hQuQ2_imMdlYZrJBwWCgfubLQLjRlh1dzlv2JF8rxLBQ3OQGZUGyb6LzIKFjOWl9k59GXhbqY-MzJ9mO9W0H16PxgEjwtj6-zszE7Mvfm1wn95nCcQiLiTGOgyZ3oqQo67IfkYBZnzpT4DzKeS9XMm2FiQ0HIuZKnKSdRqHxqBraN3jkriOcPi9870dNR-mPkdZK1RrmlOGeYtyT5MOjwv60Oml7H8orWU1Ov9_4751Yy6QPSUDdQvAKQZ_TU5XXIxyOdeps5cfAne3KsX78SyGeXhpysgunTPiMZqg3Pl0iep9oniFPssRaiSUmu3TJFQDOgxKjR2hNRzooXVUWR2Y46VRl4NXAIIBR03E_CCee2VeGbq9LrfdmHw7FuzNFMQnszqZ4makd4wWmOJDbMrGF4ll79LslhSGJFPLULXGzUkLqx7DismKwQKbgmB4T8MUMBa2d_2YazvAigLYgwsCaqHU1VYjJX0GSGb5VUYCn9tmmOluzE5pL848wn0lOkQrmS5AtOgya0E8FUGMkJ8Qzz4iHeFJ_8f67ogxYsk1YhNRXfgbbzdaIJ1JdluOlKcfcXEto-cA3UAdjD2ZknVVm9cIqCHDEtrhDQArwH64QhzRccZYdbhEwAuGkSA5wfYdo7L3GysHVzd95arjtNF5kwSJ1q2AO4ziqRIlXiHnjUKTpKsitZm_iSelnN3i52FGN8TtOzArPWY7kw0mDI447TH8GsX8Fq7ae6kbZp39ma8Vh9H67REA6hh9CNtOeyOJmsQWqGT07K43376HmtHPSIzN0axujk1pkoeV2xteF_B3--Latr-hdqMSrBbVm6P4bAWDvHC6qY0Oe__JPNwzpMOg6oUIvPzlG9c7_2s-OxhZ8KzEI-OTLdwjR7B4X1p6IoWis3SjJubOtR7OnZLJ6vKz-fGq2tBXCbNUyjHEYZiNlT_b1PAjng_bWChRcjb6X7bpepvb9Jv4CLy44bvmO2YRSPNAEbSD5t-Ya2yD-FsTDzsyKAcL8s3gwwjwKSFWguCwUrSH90o4x0w2QC6fIbZ-EC6yhPh576jyTl0go-a2rxRuNoXuW7717On8IQZpJFzprWwRncSYVUvH5pd3NLH5x299ajRIA2WH1MRgsJ_0-sFXesIWw0YwfW4yn8dhGmyqK9QH1_JTGG-0ysz__eTn56mHnwVGQia_nqDzQn85nNb8tJrNdWk-yZ-SSbr_wVNI1XBh3rZXZ9S15Kh9XiYZQ4ni09EPLKVDHoTULMzQ1DbW-o6dkUL2q_npOkRk_0_Dd8eX4t8s9fy8YsFXczIfENbKqJ3TvevCJZxen5hb8kNmISyFd2dXbwqEqRVk33gDAhVLr6aRCJvsa7pAk_xgyidNp_QRBJl93B2o6i-Y73Xin1IGsy6hZarxP2D6ev0NR2xKJkPfUOC76xLfRUh210i_kjzikqjwupTlCMdtawNZ6CJ_gXS5SG9GsPUjDqcNfRkMReJVST0v6-RLbfm5IQkifeGETFBnfkwqZiacg8z4xO7Yowxxk8XaLnKT3tvJfHnPTAqEOoQnxzeSyPITbTGViyZlTJNHPDqGGfMPo6vU6ADSQpA-W28mUza3qmYf9FuYGAuApDi0l2zlqNmgzZMZL5bqLmavzLDHIenX9BjVOCwuIPl50AoRKyLIL9vIulgiSkPjoDUnwodnkK9yDLKbh6sP6FxmEurmxvI_UL6Nq51j7lvCkLwKYDGp_SdPSwrngXGW8RLixHeCtoejacW3NpKV0IO4ZhmlWUql86dr4PPhcKNEwquSGh4VA5C52qWtgarTTpR_Kzy7h7TcHS-dMubR7qzuXAeQyVvLgxQu1papIa8V-Iiud6PEB4Rpt3jPBBEOeGRiEAAG0TgYJCUvsHp3H-GhHqa1FyhTKwrsVCcWu6rKBK_6UE6SRpXMyA2PFnb5b29vKpx_sVwvW_NfVFWOmgooco7eashZohzjK8qmdeJSAojqPy3TnT7GTMNRFfcaExvbkR7-EX2LiK7lhxe0emkYsfs6YK5OPvXeucmvyQnf2kcTrplrhrSipCAn3br66VkvH-TB3CJU0fFwb4aPKLRjUZaCtF36nl457Cw-ShCthPSHVbQ77x6a9gnYuPTDFs0t6F0SPKCdP0ZA1f1rV2jsfeVMkKPrwHS76gF1-76VvZS9_s-dMysid0HVg2L9OkiIUVneP4e__bHPFMy9LI_tkZamVGn407vs_HXaS-ks8m9DgNTe7LHDBL_uSmxcRmGgGa-_jCXNMjfSByFU3jVWo_1PhSVP4NvcSeTkmUK6_9Q2ns1hcDbItovBtho5Lm7GtPijaWSywUIDr0s4HlzupfXOzEVXXH7lKZe7-GcBRJxYvmVLOaBbS14Adc_YglbPcAuH41IqGgaeBjdXLGWiGS60eaIorw1gnAiaIjCgT4017gNcJy7mBjzpXoo-59J-KXd5qfVpP2RyfEUVoP6U_kd6JeLShOKCEayhQ2YbmDY2rmmaoAWqpzq_VtQMa1wP7yIrfKh4LGPNscGXZ9dt8B96TG60sQ0LfmyV9IESoDxwgoZOdjhi9t3opAOWJJkhediUSjX3VcnnleAdworTEADv38KVkH9uWdKtG-OMgReFYj4L9CDJJA4C1njGEEkxZeXdj2U9vvmq-dBtOJis30jbYNcKF-sUiweuNEpSKIsnAgiLhq1KUq4v9WMhFDRubb-B-RE-oXLghFK_4OzPf-_eqLQqvrGv5a5nZINt2QgBui6_2NNvT4YsHWpSw6Ju5zBLd4Z1pErEo758AWRzhrlf2scXmuIGhDnkN4D0rPm5kg1nJ3yEb5va-0kNtTlYl1D6vSd5jP4aeaptYFUZj57z2WhOTbqQ7Y5VCq7ca0R_-GZN_bxBGR59WWkP8j6BxoAhLfQfrsFqDTfKXhiiAtyS4doUS2jQwkAHKOLu0zvBl6VeMufmAbTwmPan8OAw4rjhHk1ILUmuw9DnYCMy_PrCFMoKDva_RYYC5LW7mYYC4xyMDHZO1z00msz1TiNNhuvmh2K50a3TNoe6_XZcx4sYMHAw-NUxCxMjmy6d7ZHGztVnuwPNZ0XrCHCFUMFA2ex5tKj-jMWte0cA9UybYFgpHJp0qaIHOYE59VSjvdOzSc57np84wjfH5v0DsobFgMHFvmbEwo24kTDBGdWz7mVgow_06C6dtHS0ay1SMBBZHYXCTY44vU4z-hVNlJLM-makUOkiEJDQUXgl5y5PIdn0YuS2Kz4iv2tlWtNzJPbNs9g_-VrRIodmfvX6BFWNhiXqQ1gAWK5IkZyWgMFSTWuZo1uygt_TaEyLdHVrAUiJ1vVjSoIFc2VoTCpmbms98jSDVT288sTBlZspNz3M7UNXNZm61dVy_e_4FAJ6CrsIqMfg_16si6XZ4U7KWBPrPSkM-0_JVwspHaWByl1U13qVhC97mXWITJmSDd39cJdhz67l-uHTAHGmJU09PprQjPopn_VQVobjDnc39Q2rIu0yfOWvKaEwHGsChzBI5aCc4KwcF-BoTeinc-n2UO_2J_cPtErCCTfJV0Fz9vW6Gm3tF0pvMRx9HpIH4ZWQrr_75YS8s_HRkJq1t5B0reE_ctt3nh3NZThwCRGHsUSxNrS4ibfRcU4i8_2N-hE_Lw3aEXO3ytVJ06t53yl1lnA2FA-N7bpw0MByzzDlyVjVzU0Iz4Bui8Iwa8iVQ8PmBU-eGifqHkvLaB5hT3gm4Q_vxPd6DVn8sNW7AhuCWWEZv80UE73pSO-d0FATenYpaVV4hQimccR3TW7IwRR6VBq99LEbu_Zau7o-8qn9JUataaoKDQEZl_jlezPuGacXlyepuCk8O5MHP1gELMhNXPV6JPL5QHlQx23G6hE1j3DXVejHEuc1zWVMns8CTW6YKRUaCyQ5aR5ejDWB5om2vxqSmNies4EVqKhrqBsQikBBKwDYDaGORNeflnw-oK_6OfCOfaAZp1vxkH-QCUMcxiZFd5O2huJTIUPe-HtcIDSjK0t3kQBuRp6OYUsttw30JGJE-ZRA3lea4wVW4mD2f1v2gAZZkKAHOB0je0QFGC1uC8Gb4-153y9zDP97l5E3HqJtz-pJ38NCHc98WbGOuY-mbThN7tZd8JaLGRG7M1yti2uXK_uoFOuXQ4MbbA6Qi_XELHVLv39gUQHUU2jwndpHHVc3Md-Xf-6f5e1Z_r6t7IhBT4eKpNBz8ecVpJhoNe-s5JYpwPBV-slIjAglI2WwnShUUyQeULzhD3D7bYqUV1JV9GKnWSLu-DTfmK7UO4auXXFTXAzELYPT8Weshwpn2bnJPv3RdVvVSsjDSA1hgA7Qq6C_P9Q_h9LxsjT_ssnsogUlNI9BoKgwd1z-Q0ux2k7H5Z7g1IBSDUm1fobfULAaCCtKkh1uXBmm9c_1kyzrQfrwV-HigTUPedrBcZy1PHe50bgUk9QtJwgf6W31S2lwy7zWgfDATDL8SBHQQypu9rRFmQhmEWqvwUSok0kxN7CoB4aKPLHd84aRkGf7GUVRkFOvkcM5JRBiOkOAUpvV6N6hQO-EujTfmavlPWzebFuj2-9t6aQ0RBY7y3rxANi_U5PkaYAQWpEY1Zd_WQg_82q9zOhCDaQ2cBbJWviiNK8XkG7Ps2aGPBt6bFkvlXHYMR-HJZLvHtED6wPg3zQPEEwiFVG5UaWt4r5UCwIa_tQpFzc-0gA1bjdtoI8ng8H83mQKx1saOxA3pJ5fmEzZj-0H0j9L_MC8r4p12FMye2F-_pbTV6EEKFtYUaYNG6b7voTIb99Zo-40J-6DDnrBpsR0hJtV0QG4JbK6dlpkFf6ETaclKqf06qP_nePwQzaTk6gXsP4avnLBVBSZFJSp43ssNbGhjVTEafIDuBjfKPrHBbIGvKOoTXl12Jnil_BrUGnyqFANNeL2FG3PUBh00UstBxGHuGtNwps3vmARQCXmpadVCghC25Hs0Vx9bX7hDgUygGTG6yYr8DCz1VYhdoVDaqV5A08EgqTj_R9Tm9AWSCO7iASvLdlEM8LGME-GbzTYoRSF__KxjugR_1fbHw9trxyGKQaGHoHbmvx_9K-pHTevFK_R2yksz8sOWOPXZTuknBhOBEIOItfYL2dLzuu3jMwq6O4NABFTUEyE6YLbFDMVHG9oJalebwp9vXH1huuj_oY9hXvjvtp5AqDp1aO9wyHw4-PY9Dqf2cN7ntVUZbK9reVFD3zWZ9AG2kpWkZRZrd2BOMmpxmUbd_2Qw2YKy6V2MXdmN09qtsPs1p4zUnVW3J8LamkGQCe6Wwp9RUoYBQIV8ab9l9bSMTdn83kg1S4tPrCWyxfJRAzDchswAOky8Pyuz_VfOUhwVPpB1cWAUVSoZrMIme7wfTeziakTBAq2e1GHHgPbvfxmI7be_vpciGt2bNUT04XaHyn_zskAWeiWUsp7hqn7VfhCPbqXi2rvSmDsiX8IVIbbnY4z-wTJsNIx6gLY9hYVrckpR1MKn7Q3t-xVqVyvpiByGvDEf4hq71AM0w9PxaU6sjG8RlHE0ADX8GV3l3PnpzNs1K32FdCxabu8IonquBqOtsxpnrbR0SwFBs9J83cupNq0oPsOTywHJnhkJYuK-l4ZqUYOn7Vl_XoC1SXEEVkcpghyyXQUkOSMH8D4SiR0B_9E3T1sfNCJHWuGGE2YsiM_jA22MPFbtkgCrZQCQa5aIZGEWLekMmIiKQwHMICBFIZ315ud_WBK4ouCjbEBnq8F8gc39l-h4L19Me8hePOUeunGHKX3hygbmAXxnSm4lPb0fHwZ3I-CQSRL-EbBZb5oSs7W2niFXiFTKD6OJqYJwz9O_p_eo8tZu04YJajO8UOK1XFTVx0hYl4gSvqz18sc48f-KG7fis-CBgTHCU3PyTixUQmHPuMtVxa9ufzLiV8E-b5yJmMpzxlSi8JOSTXGRv6jPcZJauVL1M-xaYd9dARJMD014mNYr4NDgaeW7mKTDPoRPHee4w4OFKTiCHFIYnKwRZjUJzxFkIe7vTdlCB4ZwMUwnb9Wd38gm6OASBncU56RD0_S7PIuhMQvT_zrtFXVuBbfEI9JcVw0EGNL-XrOqbB6RczKiuiK3SsnCx2S4FOVcs_UlufHscD7VRiqlUvZrXlyxNYFOnsEaX9_GIEkjHFqhuN69J01NLKlWrVUCOIMLR-1PlHCVu47dDzcyPTCoumrAeuKBHQZHNANyE99KJdoJmVGbrBhtQfYAHIaJyzQ6AhYFOQTCAY2jmbriJyhrtJH2CG72CWwGbUf0WV6cTM3zvgYVAN6eHHDaUNpNPej-UjI0_PlwWYozwXIE5kTof7CCJUXn4f75HDtcMaW5TEDA973J3oF9V_i4uqSGfCLqMP2tdjrCPXi5M-VMJqcDl2Ks2qJIrc85khE5U5MZJvFn8MxX5jSzb64gPYEASV8I_DQcdeRAVaU1GAOj8s4RCRq1oag8AD06Vlxrij6m31lZiXZdl2UdFoVg9HH9qudPyCrPcuDQFkSlH2zICZyN3t-zQv2wMK48Sp0Razl2Fs_EjB8RW_O0GMPlQC9onSIsPPgQk4hD7SVOygdwpHDSeMPezjpdUL7JDVS-k0gNOEtB9-yX9UIVSoBM5mo4b7G41CIAF97-aVrmqHMbf-nRVQGsEvXMATQLwXjTP2zST0nu8C8gEfP3uJqU2SmKPRw2VjTsMheTpSHzKYmpEjFq1OxQj7_Vy2GATeRFqQlnFy7a3KsLmZMrEjRbinhJOOTmKf__y2RcAIBTStsqV8wFu_ZpQlHmczxc6Y8ony8Wqd8VPx-AeWADs9Ck95QEz8YeVeAtaXLeZ-DDWDyHm5u2oMXeLfH1WfVUJF2O7LlqYt6T7q8d6jGUEmvdsg2CdM4JZAzyUSOGDdleqAPMCeVYlSnohNghbsRDtoa20ak0rA8ypz-fok_nGuJvWZz6dX2_0rnXie5ETpC-ckg4oBvj--pdil-QZTKGgYPe_y5m4g64ZsLiaUWYlmJOKAO3lm7x8f3AHlzZ4bRi2l8En7XaXMztk1jFvZpUVJPIDlCXa7nBUT7RpOXeTsxaxr7qJrWkznyqlDGPjQe53nMmuKBRYeKFsDftOp96ZJmAXpU8uSgyZs1pAInGUJSIsSlLxGsX4e6dyGVJ8VXqVg5vP-Fj_eNbyvdFgKIPuqH89WITVC6FEkk4BeaHsq19Ic8bYhpgqRcPaIT8ETX3wHy3pkkG-wYlICH7qfSAbAhWhzjAzGW5Nw3Pc8fpc9jSwSbOxgl62Dxfp7zQLhKR2U2YsNAAgWC0fc72e8_RSY_pPd_oCzu01TnzDFIcjaE58fCiBNA6oL8Nlj1j-hi4YWSGdQ8UKVejIuyFox16CuBR7nmz263LwVfkkLcX413gbqzE04ViNwDq-n7sBnQX-x3zKnJYYYW8TD4Sh3Sj3j1AYUyAgpI2Jce_RDDXGDy7oGmCiQHYYdtfQkG878m99bWquHd4P4-dCTeundjpB4Umr-HHmaeadY6_1bukqczZdoX1ptdkI580kE5vUDX2-24ty4DBUzdOBvNB64tkGiBxhAZluPpKWylP9smoTMzcWyJePPsQuLXgJTgpoEBHaQN6ttEUuBDK08A34lJ7CIlNmtdPmRqXo3OJvl6SYleTMuHNdNmDytx0SSN6BFr2IBdVK5-SIzM8gA1TmpCX05VzR96tBw0u4wH-0X8xxzm2eTp1mbMxTaRskZPGv9Nf-Wt0g4tsKya339mMMsdOJAV0YxBBK2hiWNUcX-80AEgHisziG_EuezxVCWQ0fUGWuUMzt65aQCaLfQ1h7mEu949phip1o-qy9yXYC0NUG3Sk0ZdIDFrIOMo2yHNifxDEjAGkHNZxXsTsAdARSnzadINa5ZnVTfdBTR7O23l6lOwM_05DGkm22fdbTL6ktMCUUhzG7OznpXJ2ukuFnXmhI8qUp8cRadjPT7d3ZRXr3GVApZDrTH-rUFVGq2WnRqG9aOEX-Z4DenFayacHGq9pT_0Y6SFEQ7xTudx9E0MDzPy3sLe0llpxU0vQb2fcexHbZgLU3P_Mj7M6SZADgMwPKHOVlap4akB_0JoaP0Y_jQiWoLa4bTJy1HF5L7oj0QLPFF_j4lL64xB02SmLQ7KKmZxQsf56l3fVP4l6sZT73G9WH97rfP8xxeWSbxpdSf5ZGFy-WWoX6NY3EkY5wo2VUymDf4efbV3qFwyA6J_o2KJ2u0egX9CkdB4OJ0cvafgvFr9AKthVp15d9VRrwIYtLFY_1gr_AGegk1_bkN7REPUJvQuZql98ELctN6PMb7gRd6H6Kxz5J73OAVKZFDn0oR7YoDMJ1Qg2nQM_4WJ6R4P0jh2nTKqZ_GKMEj6Lf3WRDbIlCxN-h92MTr-YfE37oRngo38_0wXbj-9fCLODDYeTdFyu5CBtpinf4_IXrOuQKeJ0w7T5VOL2XU4caO_BC1H1XwI3nEP8FCRWHPZp4ZfJzL3lQMiwpCmql7UpG8vHMpw5mC2r-kY6nYsxeSKLz7yS-sg5sX-VQEzKijukLWZuZbb0Es1jFLWoc1m0LtoMs-Nl1aAhjcEiwmDhPC57zSC74V5DB0iBBqr7NgvyHGA90QMQi9wR2zUrxbcQmB-jWSL-pSGVlTRoOGSu9e3YNtMzQBqt24XOMYGTW43Rvv2MgP1qoKukZ56YgKi6tkMF9Lt5JFvGak5j1Ccq9zWAY5BU6n2XzHRz5HIsEFXm4wqQm6j1LGkF_He9HuNrsteC2moy2n7ET4TDIZ89CIU5lY0EKqew7CcjjUagNl5BPEiTRDCZg2PlroOvmAvVxf9wgplKcYemuieHlYV0dG-mL_BsNMyBAyVZ0wqj9A7WCkRqL8LtABZEBgf5NcAdYZ-OPg6tiGLsC7ttJPa7B-KSc0RhJ41RcOgfv56Tm7W4W6jLE0Zy7zd9Ax-9s3mcxUalkSxQQuNmTJbSMbm4EQrNhvwsIZ1HiyqBjIGTvDBFtcOSCumCbTM292BIlysVNNDPv-s51Y4Rt7QWRNm1P3CPmbkfmk1-1yfCqdtLPZ5BNANd10CXBkqXO5M018g4H0YEUJIwWcdKUmiZpHjAmBW5V3mtWMt-V1jkRqHQU7HutvzVy37qmGGWYMApMqWBbj904d5wOqHBmUeDtyBmg-dD7NGhh6_OMu4AeWvP3LrF_ch_jYq6mfR7xTdmXaSYpJtyAp37GbT-kWV3ZTXhcAv88ZjWVd_EqzG_1q3jxZ1lncbYXEEws2SE8P92tVkdlHw-CtnLw84LjbEBhOMho34vNP759n-eamzfO2WLlRaHJ2sGsAnvuiiDRDh875rlkyXhyJbhf5z_7tE0hlZ63vDebm6JURZH-eK_uRLO8PoYz6JR7cQnIHulQSpTFWJgZxPKGBDyi-7AS3Zc0f-PiSS8B9krGhjGa3j3J5YPQtOEtxF7DtYFzdcCuPX-247a29I4MddhAdOLqnAWhvggz_DJXQNYyePhuWC5EI1zT_339GZnoGTBNPjGA-xZPYJ7x0QUxty8phdd5Ky4z6u8l3ipZjSn6CuBcS0EA6h-5D81ktsku4XnHv6juUXCR51PVV-3fXsUXpSDDrPjvn3x1n5_o8wbtMBzeMVlgkEYf9Louu47vudMbfmXbmo-yyvJaEgszwtmfBxKNFp9tMeRZo3Hwv6rg5EM3hj9aPGd5um0HwxxBYRx14my8SrjVRyNf5TSbrsxCQk1_BtUWxVXh8rhgDSBbhCqSmOGMG5gZ0mzSmvF6Iq2X_sLYogQ5VWVEeEivD__8vU3nJRnjxGq5h5Vi3oqovs2V_11Jnw0wMFGSF-JO1Atv2TmX9moyQGZKU6JdGIDHfQjXIQ4_ycbF-70b6x57uKs2fsjQbi3Y8E9e7WEuWj5BxuWv_hm15OCjB06uDcx4MT6QoSr0Qxv9ecWokQxcU2AJHG_o3cP-7aE5-tiauqaHed0WMDP9uAcXpsL79RRbTkMqdoX0MfRbUNv9OZ7-WcTaAL6MgtG-9YEJRi2hqR4ExxSHspvAxYIJ6WfGHCzny-5IcJS45hDjDJGErrtBrq9zmxN7zx_1XGTVeUMmT24z1rEG7rmas_syzDfTpH1l5JcENH_S7W9FjMFhSopj76BhTbkMLWegOUkXp6iINIrLtVCtsVHGNVz6R88-J655AfOqX_7JVOvMPitPBPTqZsUAslROvVycy9e85hp7O3CWlAn6xXzOMv9gMCYeDi5bT62Ev4i_3XDX0dthLIavJl-G0s-CYkluJVtbUFGhIXand7j5V9cDbnijPMajFG5DhvcAqr19ri2WDq0dlOdAjAuaom__8GsqaS7DWatTAEZ_GocUP2ZLTdk4sOLw8FguxhSYWWKcHkXRyYNFGXs23NR-8Erygaf6b7nzEZmzZlxlXdY8AixZ_SahQBRHjiKdasU5SUq5dslZ1My19AzDlUnPXjQwCH3qDccVC-_csRKIOPO88ePiawdcj-c0yaz7UtA-4iNHoH9TmLZahN5ZVCdBglR5T4nNj1u2BRH4WnT-lIdMBU5AnxExuXQnn2LvPTm3rMdMOsp8Gs3LeOHkIi6oS2L3UihhG4Tf4aXhXy3EDCPLn-nQoaugVor3mZ2iPDX89Hi8sCE_cUj3-V22ISFLr6acdGPcXI_M1z7PVxVKIviFYwa1_EMGxP8VGVMXgi-U4nMjyYEJV7npLAc5nseQc-pdPo4sRWDS-075K-zJvwaoVZ9HE_RYBRu6jSWuMxk7qDHHXaCj027dk42m3gF8-BQo_SzU7SXzUe4KviYonb5PspvEa70c5QkeT1lfeYRC-FY1BwKDRtleeZwip6zvISJ4g012LzE-eC7Vb16gwZyu-309XQ4h4vwJ3Rn-ve7sVM9na-jQf1n5i6A32ovVDf4NPbqmHLaEwnvc0pTGyuR598zeEfVy3SSDRllZEeGNgMz8qZiptZUHp_mx-LlJ5mqSdWhYO_s0xiIHmwnKvFeQe4_ERfxOK3uaaZxBcyNyVqNa41vFKcDVlmIes0p1uoWUl42TocyamT69rc4PjtSXnr60xDnJPiqzF6Bi8VSUhjYq7TywnGXPs-emLQo_tG-GI3hjl6aEkpDi2llM56-cgWbCkCPrwsgBpbcOO2uhFnxNpke-8Y1RVTwCi5z8ii9QZAzI_ESSjtiO5wfsA90J8onevNgjBGaothx0CKyBY8iwKRPq4PyAEjB5_oCZVExpolko41VduNghcMKr_pun56Amrtwh3qIOcjLC3uhnNkCEXMvpBAPWyLwh2FCpJxDxe7_SWUEFEqlpHfyw7SANspeywxoP40-AX0E3_PX0juAWAiiN2KasCBiWaypG3Xs4pS1VxVm0eIlp2txwXWXCi3I43-MDq4SOjOFoHWLLwxnihYr7QrmooZD30yx9laLcACinVem-JmLY3EMZMtSFs59QmiGJNO58i7P1PBHT2P26N0QPxaiG8hWQg-rPH8BUyw0YfAC97_E9s8XeY9ijWXzgb9g61T8Hr-_3RZzjJ2SCTrcFm3vTmMOyw7fpoQrKzW8m9UzE4Ss-tCf1rarrlhrn_3T3TEZ4VklYMHztHUeQDNiKHh0DjayC--MKynkaHMVQMMJuA0Qip5sCe1MCo8YoXZVPBA3_7D579s7I77dEPVG5uxHGohrIRqTURT00JZKdiK7QbqzH4F_PgbTqANFXKZl4fcAkArjHtVtEscdZVIqj0Xcwz5JhsH-wffPgr6br393_fvjoQUgESyGxCkFpDqaAKuUYFyEJNO4cLRUIyAkw2sJLkDItgI_yEf7sphVG510_n8jHoYp9p4mfSkZcLLq6SzGIthMP9sSLbPH82vO0q9k7LY9yFdZdujZEqBTWie6XJJr0-m_i3IgDa56sQokFwKviDrl6uCpyYf2ItE-hTXqvtm3kCUbXmZHs6HgmXIwx_HA80idhM7bfzLry7e34PefCnAR7tziqtzcB1MxH6KLo9GXzbkrDK9NC73w2CLtsyOO2b_bmT311o7cnyEVDYfJAjBQw_m2Ok68nomRtZC0yCBF2R7vu6Ju1VI9_2GK_EEZuOPpld-niqhrkOteBr29SzKEcF6cvoCEHB7MkvFqqrEf7vHHHZeKsuv9eDZbMqKRNNwPwUaPebXvu5us1sy-pgxtaLtU8jAeswvrvjGTTM1Idp-dlGAcUwM-As5gurASmPG9Egn9psxqLuKi1-y-61laTYh3wnmg6k_XETk_Tu2sIfvIok2o4Od4vh-I3XZHGqChM9Ra6_syBRJVFjDCXIW9WqQvv37-KKSq6lcy1r-z-bbTppcwBiUj0wixH9Qsusvug6hPIyRT25owvtbaDPNPxnUJ5mPfiFeIqSRPkc9HIFckZN-WQSCXH_XB-3Z7pyxG-bIMBum8S6XQEpxTv1MAvvaGcanSb_-ASfPO1NGTJ1JVx8V2ihE3IUFf686RoE0YJPsnzVm62r1kFT2Ox-iT30VF7s-qFYNJHK2V2ymb8UPyZN3JlBZhoD4lnBKyKm1BFnyPJKWOWpKyer0tqYHzVC_VMmaVuLlPgLt-8iJJGHAaCu_d17Ciq_Pa2k6L1RW_KjFEV_Ov1cLsAtphk7YC-5CWB3q8-ztPmxJ2o8o9tG6uUMqV1kcg0Q36WEm5KXrydUj2KMTFlItlz4fI4mect3disR7n6vnOduEwGnljK1Fu-PBG1ENqqyjBXB5Qqx18qWYZsnROnyQGvFi57jaJo3RQ6SyEfmZYquBtvdC156EEar3BOLHc2RgGXSHxYQHn8Y0-wqBwGlkuAvs52b5xq2Rn_wzvjhCX9g7KF412o9eV8smQcXx2Spi0lEf33_qr5i5kzJCleyWb6z0mrknQSppLgKyQ4esRbA8trp9bCfsWtQMbx7J3FM7NLR_3sthYRzZjuCMnH5X18nCjlIf3HJNa_cR0eVVilthkjFJbvfni6DN85FeqG7cKLUNtZS1EVnBbiDY_-N3nv5yE4eAu5tK2BebjgB2nd0N1y6d6_J2ZecqkGw7DfwD7PG4aAn32wpDVx6wCRkTEGgwWXmxB-1s5KPqCvleGwT1D-frd1C-blUMesqE1BYwgDpBMpGSJj3RXLKWA9S3DnRz9-72BE_6ViyYz3IUqQGNLz5PaSYbl5KeEVePs05omy0fuQkbsHNEM6UGG8V8C_QXoOf1Ld27mrgVGvDrzpyck46lVAec9lUCr2LFuQjDW2DPWbllO0SqyxrHfoKvIktnxhd0Zfic2TLcEq1vsmDAc-h9On4kHq-KvcrumW4-1OZ_iSSbdnrSKpUI_jqVgS6cLheOh9ZZk1IWgAYYyz7CCSbWiYOTFu0nrfT27HHd5jYpVq5kCYKzhsc881n30vNRqop8BrZCBNFPE6ssqIGPVBVuShnKuA5QSBW466fU706iGENbtgvCesSY0x7XBLb1cddCQ-4OBuugtA1szssfZbmVKv7iPK06rkmcNWZfkL8eVYVXMNCOpsE2DlOltWb6ELZND6ktUD_B5a8Uut2y8032ZgjjbeTxyfeiywnltfn60jGJ9X-UCxCK3RhkoXIaYLisrB2wlnWMRALbF3AEsjt9PNP-yjrSc2Znt2rWpjX8kVIp5jXiDzeaYJzB7V5h5xgzPclUg_sxWteajmqnHjaiyubjg60mTduUrbnymCpfB06PwNTX5LIT77-ZcqCOYvx-I84DmFFj1Li56JrjMx0rgDv0nNdwsuv3Wnr9CP42IVYRUrfvXHAqQtaGFnDNdEUA_suyaj-LPhteDSZIXbK5ACpmHG0DSVsSOknVjMNF-4YU2dMLvmd3ypAy2e9mD3lUTdGTtax9uu8fLqxEbO0DDL4uu7i68ViWtDEC7shF5F3THH77_dfXu9sjiPSlSuiqp8PkyaHN4bw36hRfHpT1UJBcRl9lYNFWDxmsGT9OXES9gLGlHqEMtGCfW5Hb_UmSKNt48gfY4LuhPRT5Nj1D0zLs0UUEhKbcYWJDg2sYxCQjFgMWcz9_YQdEZ9LagO_MqpTgfhcJenJ6MidtFpxJup2ISVv5hj6OaB-hmcrjTjCW_gHqE630nUZhqkl0O8oCyqiUpISyrkQljjeEs8QRDDdmF6_HXoYRm3aZq2Mn3Zz6TPlmWkrW7zPd--_nFqOeDa9FdvCf5UGq2Fl9oHiG3_8afc_NbtC69n6ZozpOpboRwJdkHJDC12hZ8L8xOi-sSeT5R0UF4rxSX8zpeCQHdjhqEI_n31WzXk4UlXGisLOY2_jhnSnF5neF8BP2arhnm6yo2-08ULpy4XqnhMphtApkEQUFnL2bn_HA-_q4Fylv1dCEqcLMc4wAPE7EYyJJGIupntMXOrcSEf4Ch7VgaJlquItOgLPFGRRPjW6SC1fBtggtans4PDdsvk7OtI3rM9Nu_WKF_rnyAIQvNy7xBrkm2V89jfggM3Wen2joqVbEoQT2mteQZ0jn-BMpsyaK0kXcFi3MhJcdyKKfsyv514eMVq33krxMKx9d6RPYM1vTp2NUrti8YEuFst-8FMq9Wj4p7UKlVtygg1j5J6MUryadNkDTqxWz-DqDeD0DsU_B9x1dSPHLHjkHMFW5E8gYaF1THbQmSMSqBA0eIorh0JNyazKWSOFwQwPEaH_26pO-YcYuserS69uGN6ualJMFXHvi3xC9PtP0tGcenDBiT1qoN0i1d4q0z_ixA-dSXbW92PsjjZ1jPYGxwdrs0N2fptLxrU3HT0pACTyQCXbFeBXv9GUttgT53BEycmpcIFtQtJ1XamUHa812zjI6Wv7IoduY8GMqJBns8TlAoOEoW5wXy2p5VzjGwfPX-rKxzKarRpJH9RnlgV2dVT7hv4eRMoIpJjNq8wtwKxqM0MPrVxHwXpqSLkgmJaDswsrlR599far164s2XBLbRlcQyPSQj0hmer2SxQH8YaLp7issxo2r0UKZ-1R5uhY2hQIhzzg5FD8tJ1M46bB5mhW0k_JNMdiZkgD5yGhLOcI70ghu3rbU8gK5qXaL6AHjOX-tFdf31NrnXcyoUuW3DJByjrFRdegO5UqGGGuZTosKaB_1DNUlAaMJBWFxyqhy2E8kH3euAVBncmzRKkiwEiFSOePuceY7jrHWVSwXMINhHJH6EerkCh9iBnKOSp8KpbLoFMzFwv47gkUfJLfAmbaLSd5KVJxdIf6DIRjdxKWIX1tg4FF7et54MhmAxS6oomgDiZHZGxhlkNAK5dAZTWnmpBX62UyC71v45OBy0l18FOLm4Pb83A9YXJE3hDoheGV_ow_RxigLhsgRayfVntfpHWWJjL3igJCaAHR46YPcq4kFKpQ0ctRUyViaeWSxALe7zzTZx7YNFMLOb1hED7zqGmMk4YOYCEJ7ofYFOL0Tk1fXfHxEBbIhOoYD4opZLedx6a44P5LnLRZ4gIL-nav8TKXX_-_LZThJuGZdnhN8O1JjYb4-D9D-NRRRp5OiPUJJEL9vficKheT1DUOfvSsTgHHjdtSm8emmTfwnxD8Gequs_Yo7_CLT-rtowYN_UYdPsngEeyWlzDywX5H13s3-uw3jb9EIB47lNpZWSkGbgX1VeXHMdfeLbwfo4PdFBsEBajURKXvrfTaPfFUKgJZva3nQ3SRuGlD4KwDrgmHa28dVyzUTNrnozVqks8ZOf0GPVkFx3QKC7gkGs6GZWSIMfrO1Uuwb18hqzo5FKoU4OJcbBpUG9seQQqJEl8u9gzXx61STE_M669tcB6IiTFHYZXicliPMZLPbbKWFzub_CefVQds8xW9w4DB9yGe1qbjKWz9VUN4N1V_BXfLJvqlPVPWId3Igcx3yNrnD4_4ZNVSeM7x49hVbeFVT2sJgtgRGGKTIHsuK_SlSHg2n_epIefnbjyrxD8fOPU4hg7A9NzQaw_7BaBz7PVP8LAr2BqYNiBcUC_fbqK7aA9LefTghVb0YXzhO61jjPVrJfyzyCURlJPHs05NM_oILg-Ly3bEV_kSvqva8s-7I2UqK_3vx83iYlIcybpfP9EMCuKrZJSh7imqPDnz1BSC6wNu37QbVw-IxeXbO7tA9fGAQn4UcL0nKpeSQZxobDDDCEQF5P5PS17DhGNassnzK6LGpaMR8p46MexYmnSYH_YMyRphjKo3UqPhBB83RlYptJfNFTyfjUquIe2V6aAIeeEt7HSEk1i8GCCYeteswDtEtRaR8NVOjba8DArYzipr6ICEzIZ_mAOgqEn_cmSRsP3m8eD2huHB-dvLN9FkBDZ71mylvqzW1fu9LsyTCz9vC2t56QjvEelmtpbFT1A-cr9eLkqFzDesYWDDk3UhILC-dlqk70XjiDC6UPuNg9iERSupXTzFHo-MGATu_ZDrOaJQpCl1P5TYq3km9A_ANb-FmTEvk7U4b2tSmt2NnbqwBe2dvctMAx5rPrcaAwgzU9ofqxkfnW9k8tirA2-94kd95ywz1ZQ2fUGjFIkk7pb5C3NhmjvvYOWoTSj1EOKj1Dxifki8y_d7_Bu3nOI_4FTut1l62K_H9-1W_WdWAXoDKgD4bOwCMuvcQabTiJTv2g-PXC4s0mZsfcMMpalo0nMd5vLs9zS9_zfvoReJn7vR0ki0QtYZ4RYQ40oqj5w7WLlntMsu59O3ujBOcMOdo5Wq63HhG6niC_vDXXPrOy-kQmCCYSfoNzINtWUzjXgFLWVmIHDStaDnkQaPfvji5ScRdDnZJA3uIcVs89bMZC6uQPN8Ssyz3KRCeK8UY1z3Gy818wjyLLTWqPa8CZI_H0j7Ces-s_58LrqXeujhvKSnI7OhETaQgq2ihaKq6M2x9riz_y-CloXHA_evscvimD5g1Zy-5S803hYwkrKtnbZ-5iZEVlM98Q2oM-sQLLzOaQBev19cxTvmjFM1Qh81O8cB3urlNARgjarDcETg9L53Oxese_auFRmx7QQnxs-6LCuvIxe1QcYhpkzZyKexjcyTo8aTQBd6v_52FCxhGzl0vzUjIF_xdjwaCO9_4zfBrZROgYNsnj2zirqfbwqssNXUg-vPOQcxBrCiZv9BnHWOQoYKHFnjVSx02T-PlwR1vRF2tXotNowz62B9-5w_E3g4z3WlJrs6yt6FiNuUgfXmBkbA6kkLScgWl87qDu2ZPnVpJEi1Q2sb2eiftxIlO76zERjY5gcExt7ySCM0yAvEkWetjpBlAN2uysZFZi6nnrpY_8gvze1ST0x97wx1hjaK6euYFJap1pBqbpLshDhgkifysS0n3U-vAcfV_LfEn2KAw4bfV3UUj0ex2BKD2nb9bJBUtVbokFh1yyUpQk-IVRVnPBJ1oZuekOZc0koGoIu_OAPUghpBxlCNDAvIriqLLlwgyVavluxznvSvzXTYtK7MFk3_tdbdBDz2OF9NWgJVou0KqUDHXp0IdUnm4RaacO5QUMez1we-aTr4G_FvpkJ9FcXtzONx3mmfMEU1Bv0bATpkZL3NaYZOZCg-Wcv8aIvrVWS4fdgKH7RkvhRB89ByCiGsrbpD-uhtIaMYuiIncMiiKBKFcI6EuwWDxGXcOV_LrUu42hw-g9hxUpX_L4fKXPKiPAeqFlx-Qh3Jt0IodK4FEhftIRXj7QKch3Em_FctwKifYFQATbDCjauhe9ve66ykXcimXqKICoW4L0wtBhK87r6BbL8qt3z5j5S1DaTo_EnvjsXzqPfV2V09F1haUajeQqQFaKeDupnA_snmjnl60nHo7BghKqzh3ybOjr83Q1DpYhxnDAJJpZuNeqJeJ-rT4FIukulpsevwVUhgzWW0lvBUp3wteWqb86Gp8MAplU3Y9E9Pf-FNHtVD0rtXF7MDws8T-Qrv8L7hQe0d1Wg7j1LqgAJVXbWrL7JQdjjHRC81vnt6WlX12UF9U7LpNK-Gr510qHyFd1s-nHfsDgAqprn5nmr5reSbIqAeR-9w50q3pNp6mj6Ei3rj7Zwcih_0Xfe9nSqfoyH-7mVqBI62-medQK9lBrV61QlGJvZgzaDPiRw3DWUdNgVeWw0-pXCeOld6UuZgOQhmQlE42eUEQsUOD2fr9W3WywhkBPS0P5P_8y4mSmjCFb5KNgjJjtJ-I-5J7E0dpvZ1PSpQ2inQ6A_JfTswDX9cx_MVJ5xhjVHOopvCy9--m7agSE6eQobSC-hUA_s-n2cUYf3GtVaQY9zjetLtXzx0-AfBSCxh3QquA5X9jbnfeHx77NWNfRc4nuRTNDbVjlfL71eQXRJ0Ew55banHSqOdwC-zZGrtYpHgXparoO8MWKipTjI-qVg6zs3nZTcAwnb1im5B_URUo_Wa6klgO3rk6td8T9uNwgCtEgm1Ai2Tub07qIW__T6UUGSIjwijrVm-HxlZdYPmvdKspFDUEZdKh59uPiuQsQANVjNq8uf-EyNeVT0Kenq0KamWTd63RwIezOrkBw4IXGZ19FN9wTTS8vdZJVIdyxR7akgXa4HWgAl75wNugBPOTmEGXYgSKYOUXyFgqsfEH2JuX1DZ8goMlmroOwD7DpexUOKDNAdyl71GaQnfJnWUD_nK__grI3HEVeGdIfB0jHSUPBsnxs32J_nzhhj1qk3NKDBqafR7EuenK_RZFCwEf5laD3LJuDdVRpqKYcPqwNqy3aXpsvGDmdJtfYfnBlQ8gjeGfmrGwUSHJMO4DgQtmw3K30qKJ772MYd2ksBLacx42tdhYKkZAlGUD6o_4GyIo2SPLmHQxZJpIFXVczmIEXKKgazavWjJ6gmUK4sXhDZRHv-yB0HQY_gnjQf1agCol2lsPo9puEFBNnW2Twe4qORLnq1faAYmEEAf-8aeHmKt0rZ9qibL6e1e7DdOOnD48dHnDt6pt-vG-rG4kd6wjMOsuqGaeq-m1VRsn9tbtsk2InLGZJGDlRiDfcHiYoaD3-gNppj_Y5t0ibTk8H0uyFu34jCVcpM2TJbBc8CB756mVSh04RDe96v6jYr4U5ajsPIcKgfPUHITdJDX5q1QlOTG4WG4kW9gsGSQWZ9egEBsT5yFhFE0PUJrjh8kJmgtjLdpXqdg0_ngZr7rRQisSzJEOVaronb_ZeJx1Ae2c9O_rbDXr-EuJFVAL0nV8_R6kGH-rGkyUVb6tGxHjXCDq1HRRgQqo8e001H_Ke9EZn2aEX-8u4n9utAo5RgqtU24HUYz480ZWIMUGkAiFzR2pwgxeK5SdqrDQp9zTPpUIzEwTPGSuu7hFjAZAco4cuwTa5lkK6drwJHYGxTYwNloo1FnV6819Eb-N2spwEzIspBhIFB7ACB-QA00PI2G7EulOp7Sz_UZ9TeFaM6x50Ju6ScvNXTbZSlc8efmU7-nQrfjMD7EQUJ97cdYzvWVnsXVQUKoSRB9LFNJXcttO3CLufFJeun2aNIXeZzJD4G5-SAc2ozbvNC4OD0P0dnm3d7mGWlTcCmSI0myZE0BogQPkP3IkQyquNhebZcTGlbimhxh0kHfj02_As-GqRsOaszQMm_zClzbXXW4DRmNavPyVjg2UmMHEFkZMvECzR_Akv58H-3S21Xkd2XsVKwkq_FaWLaBdZWWFr0oi9IzAyKzYiUb8iUDS30vZxGtVQhAircbFogaEM02pqO0twkpjxocU34c9mibyoZdBfi43NJZr1hwJg8XzG8ta0Unq_zOldX4STsX98i57Xf-x5h9oc4VcNETe-8KNf5TxxmT2d8ufM8VgrKpvOMVaOz5QCKCcNKOIJo0qwAD3TXdRyRkT9zvF_DyeJqShdMJgyi2j9M31iBdI_kQ71B8dsBPmSCcaXhLRE0gWQ1HOONIXjf2FkVwALa1TuL_HTrALX_QhxX1ips6SHeyhlIZP_off50tvi-nL555ftDOp9wVdlZ5Dhd4E4TsRPRkXTOVM7dQAVneNklG9jeRptill5n8RGJSgFfE38BxDufzhaPumlddxVb5O0qx-duH29zNZiwLSVlvpzs84Ei_Gg6NXStD-_kmG_xfRRDzjMUtPVqVGU2MATdiNnWsCiEMc2JMjQjZcoZD8uluqW0C5mvQePmXNayPlUU63li6nIwwmvMC97JJ9k8CHbXmAxUtxhMM4-qUGdRAFyy1gMFVQV3envanKnBqMHBGQP3LGe-bab1UAYfEBvli-JgDagoQ8VSJb-tyxTa8_mXBj0kA0H-b7_sfwM1CmKhmCG2Ee_mPgA23rHDEDMv_AlKWFIe-eI5t_j9fQyXuI16ZYjavXs381lebCzETlktOf6PwUXfgq8JuKnD7p8DyxOEBKoJCNTT8joaGEMlOB_RitfjHZ4CHQy2AcnggKAwuH_7UrUYFdG59JZkoO6Qqem0C5l_QiiCD47MMF9v8ZFoOAWjNWlanwShRYFww46JMRT_ZpTuxlRgMDP8--ivO1WcTeq6MLED1TdwQdccTEQQ2nlKlxpphvXaTWBXKBzREwlO8Kl-g1RHNkSt7LySYEQm5kHXH_RkfiyTDPCFtiWwVkda6T1-Ud7zcZCo438Ih2lvoOJNASxmBinK_Cf5rFil0bRh94SuMpeBftuCNW4W5pcbDpjV2XVWG7rxjvb_3Yhsq6DpR2MFUR2ExnEMQWC1iBHlVa2DO61um6LX8Mi5SA0ax1QJethaPS5-oBEBkTAeINVz0QisYJafVH-im-tNnwKzBlvkklSQmhsr0KRqLRc-xSZd9PvCvrbPAVJtifo7Ml85T-fspCkSw_r9cKqPOvFFPCJaUkSoKfWOEqzOvDuYMSU0PX3skzONLM5Su01x-g4fS0j-VnB6NGG-I6ZS9lviaeAH-PoDch0bxVhBSFUFlITBPM_Rt3sg1hLLt8f9kAouP9C3JNwGtHKLEgrQ_Hquhsj3HnqtcQd4bfZkllFqtfh-_UyP6VvW8H5RZy9fDhPMF6KjZUkAPXTVLWVmkpz9DUH0doihSHFo1460dZldFkfIynH1C0Sjiinzrt8b3YturqYGbmT9A0ymPA77j3B_wGaSDTVJome-uOgOCgZL333yah0-308isO6kQh8SGIE5oIIDeUl8r7V5vV5PyCZBT38yAXBSCTxCE_FizAn6EmmKtlciiuLSXDk1zFtfNjx0sKUhmzCdhiGwWnWzrLPCA3lP6vWG0ASMCb7ql-kgVfrXWn5xe4hR0M4DSjpHVHWqZc6mk_TY8eGrohKZOEmuFLFoAmaUIXeAgGD5xwsrxRVQojmDi_WQs7Vf7IpgINVDBkPncB-8rYhQ2WvoArNsXZFGcdNcZVsD7B-LaDPgh9ITxH1zerFxJ2sbaPZj2Z6YHjqjcRWCRhiFIFlobVWL-xErq0YTi6BWMsDedKisO03rcVKWeSpZ7dXiHW-zK4v4mQXXySRQOEjD8_7QFj5hoT8AihEhVekc2zZav2qqHx_DXtOQHNTCTG6u_dtHBy8BjomFtQUVsVpYGxgRwEtErA9u-cc-laTaWBfm9ty2eysj--H01Y897L4GpVherHTKS1rAMHeLkVV7zTHLOH4Du1cOhzlf8HBEhGyE6VJIuxwqRf_Trl9wnMArqv9PcufUzZSPoUK3FlkPD5ch-4HqSY4XxzNWYXsL6S_zhChqBJ0POdnG11__zUbIwPYoxVt8_BWMtRf5wB0a6ovMJM0fwTOs3AUF1_zDaxHb2p3sifUw4PYDeXt9IU84aIsvnzMKzkY3qGPClxEego7m2iZ9ICQ0UcyUdkURa5a3EDJfIOkjUjRGJPXDJIBDneyDxuzltSZL1ZNzUqXKic7LtWA6zr7TJBYmXXlL60kiaESkOKF_MF6TCMI7rQ_YOu6FJJ4laFSyNMSSpd8eeCmLDmg2sCJuxrNq8ysH3rdshn_hKkQE3K8yfFZcrGL7diLRMbFZOPZJnvgaqwbuWYAvitGZDDzOmsNOurekFFYJDYFXwO8PYAPwrLM0JO8YQWJocF4X0MXbaIQ3uUs5yQ03VRoU_2-fcazRdBcplDrj-AQwY4gAn9nsGWzGD_nQ2fnjW6w0GP7lAlol8PkH3qUBglO0Rft5V_MdMD3UBIZJYnjZy4SntiM9ORhKpY1nwQqMKB9UAvEgUdeookvrqd_m_aOjxPH86dEjjuhzN6pYgf4xBCoN26FhuAPda8FEJp_XcQstlbwd3faQthOC9RSAbKRQaLPcYW57gQG6Leo73GD37QCR7hAOmdyIrBVy8ZfFSFIk8JPIZgWy45QKyDyLU9Qp4sOXfxHFlgG_-d-uL3lH7GrlFp2nb525yF0aIDMLE3Gvy7pKIumg5nUeJolteXgnzWoAVBd61b8HNZ4KYGc4djqAnY6iKA2qDNbwI8e1SiaO-FiOjWJ3beqcJUjs-gLNF_bT1sL3f_qg5qbtAyyNkvCQ3O5Fx53htFk30AaKJMyc2Zis6UkhO00rydthJczMgSEsIsri10izFqj-Ey4_CzAAjR0JwbHiioBeAI_e__hKHbWnTs_ewYEJl83mv1MxDIBbRyerRL950ubZ9l0yFnCcBe2nsW3YPyUKgsIoCW3CG8WvHpKL7Y-FMnLMJ4Bu-2cHTsAFbIePIHnzaa1G9ETAFj-Ppp6cCFukchmgIi0sQLyuJM1htVamCjPyIRd0hj93zGk22JUqSwNL_eGefoV0KmRvoY449jP2Dew7lOStUiCOZ-sh5G_KxIYyQ3JbeKwB3TA7vYQs8YIf0kYECOGhIU6ymyCxKOQQzjg5kwcG4rxl7kxpuGGT1avsp7bWVoUat35baHDjGdi1N1_ZB260gqJXuDTPM1HfSub8lAp2wRXjhyAZY1bfCXUPVUfPkQo0x1YH38rEbKnLAynei6dZ_tJwsWsFosSiwWV_5Cj680lJMlSI46YnOzyGESDwQJV0o0lJ3e6Q5TOEn1Z02Gt9wioNqQuJrZk9M0CBPIeQ4VpayZ6RsSgaz8wVpTXiybjhRXGQSWO55zXiSutIqlhcYy2EdWUu_g1p6KO8xZFKoi1Qbh9QiQLN2GfGWtYdGhltxBUR75NEpV7godBKcmXpV8IySdUj95--WS3MBDQICnWCwwrpNfwhGlAWBVrYBU8zRhCoeKooFMJLQ7w45CPAnlYJPWReq7RlWGuw4KYzaM21e20RyjGAjwFSp9T0EZl7Wv9Eis0l_KiVZtAuSfXSRZncm1-Sucto0eAKuivFM56a6MBoKX9lGF0sIK_U8j8m7W3G7XmnNnTZAWDECh-PJbAbC8PNRtyyD6-FBOEX-A4dmbQorFecZUaUeD0MKR8-voUzSNkBkhNIwjX_ZZPegnTtSP1rRydYkl5tSVJ4NH7QfiOIC8qAEsXj-5odIIOvED-a1outU9vz8rN0Shu1bNl9gO2dFPjRGuDnPp7wVEoI5m5jAg3fqgCEKSLW8AESEjdcnasFZMG8wQB-MP6dZUIi22SZD-uAIhivOyFRb1HTSLa-r06kWbari2hTdWMubtsNisUw3zXS55_ccLp-Ya75zTozQFKi3UBnqo5m6JLO3ur0asaqhHgMa5gTmSwCgzyLHjlpGuUVoq4Q28ennVLf9s7_3aINEDJau4PVnniiE3NFLD9zxpwWSqanKkEswC5LD1oFcEFUgmuyrLi4IP38Y_NQab3dQuNEaFGrYNmBGbfxFJo5ETlibtC3dJ3YUIXVApTvMHZMPrAY4wC3l6r8EAoZBgToVRxmaa8nljiR3IOiLeSpHT_GaSmVlSBSslw5ggDbPzaHKJ-kCR-ZNE7bltqlBhJyDzu2FzggGbqkPKNI_2w6iYdW_CiG4YlF78rtyH-GQtvTlFWSGKKeiW-QMBUTvWSe2Ae1S-H1xYczxUwgBhZ_KY1aZqtfAUeLMTWWIltKaXxdfZVNzk_wBiOYIlSBmvge8ZCFELJh_gXwPFwcsFW2ggaRoLDrEUUUCYeZ1vn6eE4VWKjuaLFRxYJCl0EAChIa0saBVE1DfttQtipDjZBbblPCPnLPMQDdYc2A-axI6VXeJ8Yk96nj2GJiEFhBX2_oCrxEeUaYC1obiIhPDavILIKdaDlkq8h5N_1KLbrWR9ZyckjIe3ekNsz5nk-R-M_hAYB_5o5CEaLG9TfZtzNY983C9u6XAtOH-mSKAKPAJTLkksFrvndkyKsn7R-TBSYc2KT8uWHuFyMc9PTo01ZUijnLADo8Ns85Kgqt4k3XrciuyTqLy5zAkQ_b0JOe6Obxh31ny6UJX8NUUfqP3SSLZuceeFHcccMo9eAyPVYmNE9_kV3GE7sRFFq6zjldeyEwBZ3BUiddI4k8Al2wg2Z9iAdfHx9PeBzrNAGMthki7HkJdx2mzCDYl7wHzVZROLwge6gBSxMKuUsvyHbeCSox3v2fJ_Ph5RvSEFq0Mg8a8XYxOlNEZgRIVdonKptYxr_Pn8McfrRMqvZNsN4UQXfV_PwpFPqkgSi-8l10uRCPUU_h2sWer9AuKb71ZDZgtfg0-ZL4JSU35OCpI5gSvqRBTmszEAVRkB6c0zTN1_GrkdoQUDz1oMNofpEWjExJ2cjucp7-sr5ke3O-ckFBQySBUQXs05NcdI8G6rsWQBr_MTaVb2D7oZwCzYlcvHT7ORh0eaSTguK-hZMEUZY2rHtgq1_jDt6ExtSeN1M1AyYQcitUgXDi2WVZgTCzywTVs00kpq39M6QiQSXdVoI2gaSFb765MCcS-x9Uz_A8n-P09KsImojY99ZCirwyEe9mpB9IkldVnTnfI6ueZZRz-jmN33DQNgRJX-4LHero3RT9ZtPKO-DXev1QPE28evNWm4ocv53eb1wqSwUBYU81uhHjLGA6Vn9v7tmDzHuzVBUb5mkQ3BSxvhcc-6vuEdU-9NDh2_zuYfc--IfLb_96j97kfWSTGfH3MxXK69V2T__j5jhznldzRpx2M0rTDUYDEeE6MAapnQ3JaqderR08gDzsOuuWD-hyeip2Jb8-Ai4t_V_V1oRBB-qzJRBvHnDP5LrcfcBjxXkxSr7GH7UDKhHJjo1q94V6Bb2W6_7ThR22f4C0ro3benqK8vWr_eVrZKmbUzTK6l9H80sMAD1-AFTDsII8NUf3wXEpFcUUQy7RedLA4GMdv3VdYwQP-guV1XugRHt3jEuo0-pMCWWx0U0CBQHHpXNPm0UVLvxDzRcj0mVs-5CIUfxZHj5b1QkHqy7Rq5hjTacCJU0v65fEgibwlf2BGXAZ4txF44kTpboIvQ29Myyr33VBrII4Oqx8IoXJW-lGFiiBG5EruuxpKNkHCaQLbu_-dqvhED7lvqXd6uC8__o410YVagnVUL_XZ3XZWrZaibratqCrsDi_5T9tMXi1H8PO6pLR4CJR1rcKAdzPnuJZP0roJLrw8LSgKcCzE0zr6YVLzaPf94q8pqYAHM3Ehp1YqjMIPQQ1siYKe6n1C5mqAPfjpmQ2YKW0Hqqi5l05SPn8vVWDjf0OBoihVSxneoZsXXj75qrDI2gFk01z9m6wG6I4-hI-k6ZpikPw4ay-lbs3-8tgZoinDaqLaRp4TN-wdoWpSV2dcy5cOVtG5B-Ngv_ruY0G2KDgpCUydYbFoHpCUY90QfegQ-7AviSqAzx3KYb1EdDDI5f9OdOaZBbTiPt2G4ucZnUIvsQQ3KRmZBwA2jlgbs9NGxeFaxZ_-DizJIJgmIEeGRcTV-rFx5eSvwabiBcbCFZKsMpvoiQVdo_AKN6lKHqVfGxB7oSrUXVhGZH30dzdRJU0IcXEYHpZdbn4PHyIzJXjQSArzlD107Dye1c0LitjGoSxwo3mdeQ9QMQYbkTo52uQJ9b6UTYgWBFC6ffqfDUQtB91v40eCYvbUeHTrhb-EWGlNPIVyiJKbAQgWjcgMZnTOjau1w6eH1zmvDvMZmklv33SUyKmiYWEK2BrjvMiB-IhMnLYp7D65dtNZFqcL7Ga43Ir73uDtkOBplYBQZeHM8m67nhfCREvNfts0vD5v-9xheHhi10-11POmc3OU-DMje-FS9QcIRsQgBts0bBXRFmngLCoh6_w4AHhdet-IrpftU2Q9NdbcBDfFkodGRN4a9wgwe_5pIEVuAyAl2C_b1Hr02xhwb_VZ1-sz3DMnaNyP7Vy0e5Ne11jSGsfya2M6DQhC4Jdsne5qBA9EzOtGIeqd_VKSnUnHnn14gZ6BTWuCHyfcB4FOAR2wblFF63ZQJ1mkEPPkfpdnASAnthBCHloPz7le3i8ht2G_w7NDuB5NNap1n5mpnH_tHSrEaN9B38nHWnxsjbOLhjUpND96l3WJwmfiA9ake8rF4aK-dImD7tTXTSakZt4NB83fJsAFiWPJhFez63o_CBicLAbebbBXqAaoWJw58e1s5ptaC4US4lOxCByhbXpk-FkUy6wj8Lu80ey1TEUOSp-TprsUSUa0XnF-lkmjjc0T8vtmhWj7uW2RLEOl22weQ4MlMIx60fd70fo9gnRfAYCDAQ9Uixzx-Fwr9UTr523RaxpvPZvrAJ3JCnRyXoFVLtdw76CbSIPwm_i7LptBGAoQLMg6i3S06hwkQnoKFIR0Ox0CG1P0Z5MDtrCn6VNXqtQdtvK0OCUC1_DYY2_wPDFfKMxCrCkdJ8vKmDySaZ2zkydH6rJEGiyy4LGfxAOs9v7wY4K9oTfwH3rNBpcvRYFaoucQVu5hT8MQloX6Bk1V1E35zx53wLGS5UpdUXFiSZCqmsOEJfB618eD9ssxHMkPmtFBJXTQ89vYiAHQhv4E64ng66yAqi8jTzs_sVnWZAHJ_vo0FeOPQluzPcA7Cqs6VVqZB76EKYUNmCryfA7_ONdEbvJRmM4BZbCAGAlR5yjiy2B1PLb6XcuUliWehRK4zXB_UQHTpWlvD-eTiR0XWb8ItVsuuFFkLIKlplsrqbMGB2FcW2FsQHdEcypqXtF5h8ecd5nfhl1YmKq0zxv7eHnIT4YIKXdlR4EkrOrQrQkN9dM5zOmPGUh6x8tDnxREJfLLf_OOhLz_2-pg-3-BMzbe496Khj-VNIGT6qzoUoE1VZFHMvlWC2kNp7QA0eYpbW848X3-S2YNP7RZWXLCSzcsawv0tHU1uNlsxBcLsjDL-YLDDE9t5YXbwAKI26F3Qjo3CBcXexPU0GVTcPs6tVLAVgdgyfBGxl70ObZNtIfIkveN-qy6a73CDnuEtHxiYSCX9VNALuoEVby3UV0bN1P_foupHyYZ2jlxlK8OpEE3YLnGnU_f7aAPDra5RXyM3CUth0vIQefWAoRdXAUCHXPi6zTWgY2esRpSfUsbJjA4_tnxERnqyXyzGKg1SHtTCOb3j980Z0XxPDCPWytnR5c98JkWNAEEg62iZDDPDodBqIYq4SDWs9Nmnj37nlLL2HEjLWY4ZPU82BY3yo1QKim17guAjZa0T5XfNh6v4f2VLRJdVwDUBXci_KoRbSD1L4ITbDFN1SG3Y5twQ-1jd0WQbsBJgPqGI9Bh-fT9ZgyDx0VzIC6XMawHuHxhzhlMgWYBQpdtXfbFYIQbg7j0ZXSMiGdrpyweH9hXD58gu__TuUczJARZlnUQDOmV_BZEVP10qJfym3bEfjJJeCGK7DP97z1S2epHc8e1K0hEOfolm-jMLsFoFYan4ynZtdgXAm5Iwdr-MStjC3PfPDlFjvsyQHaNuoq3fxy-aidGxX3M6bK0sHTFa4o57LYfPc8Ui7DiYaM-iCQ5a8xe72OESA6UtCl35A-QTRBBGFugNaqkyUqo9Dj1KXnhBTS3FKbFVfPQzcSBdstuAAlCTIYeMSuunH802cetWurYYGjuDTu2FXkboKZv384SNSJc-dF2KYQD6X0J7zkk_qAX1uB6O7wd3J6A1Ld6cwqM9miDr8XJCOGOERwQ1HyM0GL36iNUx-oPg7G2O_-UFp1Nszv1rKm8_9R9U1Sn9l_4BMTx743CpTIK-LIR7vPmvKKvqZUvuHmgZNIF-CcxAb308rFXF5I5swbSuSLxGgVQ17dftHa0uVHxjxbdEwikNQOb1tNJklzF3oXs9WN9XB4Ay-cgH1WRP9VCF9p8z4vuL3M254F8tCADh6sBvf-z-iHTjESVFiYcMAGwUIIpJI3065-0wCQhSrCv8vtJahAJFhAKrthZbSxlPT8PX9ksxCo_BSEyJWmZC0Dxj4iRTJAxSVq-QQ09UObXXf1WpujuRGt_zMVEZJk_viMnGozbt12hhYS6a9P3B5m39fX4IWDbBpd4E6wG_e8d_nfPZhY1_nEeEcG7s2f30j5psyvJ91VR6uCzLyo098dhktLG0p-bS2Zs1R0rIx5Wu3vNJmeK7NR9FsNO0vaxfNVlAWsLwQLb7j1TRBSn17HWu7Z-hxPYxz1NeEA7kGI6k7zQ4x_om8ypDlnW_SK1kg1kB8vf17QB7hR1_wkwjOwcEjANlsKK62tiQUxyX0kPwobd3c9C1htN3dXYbLGJgH3dOHm34JACYqkaKJfQgdH89g4vEpVPTsGjvPuF7xrK3EbSCDUBNP4r0IfAhHh3IqF2w62S2ehsysZsUuYDyRLDWSEn00K8Sk2uaHtvrEVKjBmW3AJpy6RX9feqhz86qJES11vYueCpQzT8nM5jSTCOpa2zRU6Jtl0ILD16gu3u2Xh8SeeKvjuz6grzIj5L773VH9ptuB7Jbr3cijDNCgLnQY8N6RWIQD6d50ZplqvpJYPDoIbIMXGf4PvePFY9Ri4EAozqoJrXdHxyxh5I7ayKEFDCHpka1UaT5raQmJZUC0CZ5iPkvnFlBIcvRBjzgWuw_JLX6aI7VITQHCDTJrEcZhV9Q-2wEqxbs6orNpXIlZZjLN8kjsNw3zcCw7xd4wWALEXRswipdINJG0hTUK9oAzx_GDVraloQ461JOHaDDyrT_CS2j_xbBsw9igkEHdWA1heZ0FIfMgrOTTFig9aVpatIuyZyOMA1aoi-kSTKRMmqYbLqh4vAg64Pgekkr-hr8NGer17npaZPpmHx7uZtMn6Vv-94uJROSr-aMZ_n9ppkAWa-YFsSxI68haCzoNP-z4tYE6lPv3Wzwnuhk4lJ19kVeYhQkGkLCLs9inRMfOX6iu0fUCie2FL6T1wM04AdWbsCof8--WTev813C4Q82fs8p-Wegrg44cwX4k8FIXEIyskMRLQvWQF0OXvnpzQPaxkJypKOYjKD8LDB5-UEVTShvLqBvkE5uyojor1FiB3tA7Ly1fQ3NuuRgcQjxxn4U2TtfKm750EjLfzCapNqoo28_Ipqm4rBBo4P6xRbgj1Aa1k86RqLNs0dS4l0wYH1H9T2Xftemf9gDJOF6cSgmpY0fWwBRNNB-TIJse8xPw-Jrl-UJbc_XW4Ovl4W2TCl65PkulsRnMUf67tWr3B4JWcCrrQp_vgTUjEinXRSbkr46n0xCllAlFD7jvBlSaS3wGoiRnho2O_rhb8zSIrf20fnLqGwmcxwChIaA65suqDy3Z5rznfXP61hFxfUFq3wzK8u_VVDJy1uRBxjmhRbf1u7PQSJHCuGUE0d4sYgXPz8B2Jm32888TAEqT6VNforglI8n3KcKaFZmOH5agZ-6yqO9ngGtkFoHZDiZ8_BOJ69_D0TtnhwDbfU2AVV7nHvX5oW9DITCTBZQ3HJfx221XdLPDX1F8wmq9uUNYMfa4_fAJ6Fisj0WFRo49Zy1mh9uS_u6jMOXEqwEsOTnnbWq1tTHqbzH2Y6VenurhBUATZsxBLOVt2BRzi_8Vo9k7_WyUGSdjwt7eqRYEinWPrnHTbd9jl9L1SKKoQjweTZPfgNzmgj8PmaRbYxODLTZ83yInySTqirswYfcas5XIl1iZU98fFEEMhcrNtvPUHlQr5j_sP_xctj6J2i1fVvfv4ZZxH4-r3vvk4ShN_zYPkIySDOpNWwSTO-yWCsFSdb6ib1n2uW9PGAUWAW71mT0SFHg_W-FomXARrvIz27uM2V2bgtBvKOnDGWqwobZDQ20rD1TVQhWErlijEWW1I7wZAqwa8NlGNtJVyAWejN4soyOMcVGZdrtcYa-9qYoQpRrevdiy7YG2RFLVsJvSvUYjQL5aPojFowFDw86nez651ev_vLaig81g0Zsz3pzc9GCs-i6fs2yfB6QFVBafnzDbtMWAWZUOfl8hc97_uU5G8qQMnQfZrhA8mVuLr7iwmjOYE94iwBU_U00_sQ7suvxRlC1rhg5AEKxPsAm_8QWSdWDdvMzuUJYsZtgAYc2LjEs6rHiEVO1TD1ZSAgT60KQAV9MnFvZ9fvD3JzZrY4cFR_7iNdZO6gZswpGJFzkPjVMQubcPIRjabBQP0lngrviOZUlMfF5UL6KtU2tUT6v7SRcVy_DePEAQbWrWGeEetCjDX2lsPpYOEEwoSO8MKb1u9szE-rP-r-miLpnVd4EPZdFgN0Q_ChYMaYYPfa_zeMKMT7Na-qU1pWNCF8-cu3ZvkDni2JGFeJ25c4-AochvWCWwU38OHsJwxUyc6hCtX_hf5h4uj5pFXBTS1qp1PK0OUOzB3yz7cebev8PQYlvtbU8klbA660dIuM_gPnM4q_QRIu37PKsHn9vZ737KRbcg4eqTt_25v93unq-1hPEXqjHUb0KesQ7j6qlq38xCrTY9qb-i8pzXNRpdDKsd99iqKV5YAaH6nj2ESmTdMB5rgeSk2I_uGCNmEeqrnICzc8b5WPcgUmtldfvgYBmZhKZTaOUP3qQfjSV4Yf5GuE16LYfIb0tu52xuQQsQEWjf1wTQ3XW46SSBR3-Cjkd8aqhyaqPGH8W-8OWsN-PRY0G2l4CcSpOTLgWF5E7mChANQ6G7FVvF8rs1ozretod_I5c5gqtJjTQ4KGgug4f5zT7KzjEkZnUkicZJ-xTkabzBDEFETBWWprDVZfx0DRcVyavLODLv-l_9xCY0iyt7pkJwh9O9OrRKeEYUNXfMF8_q7rwIj10ELf-IwjJQD41Or8OF-NXUAqrVE1ck-5OyVMm6w2BR1yoEG7ThnTdId1HzWtDlTs44AYKGlPUyIoZpYAfR5kpfjBUlc6xSpFi5f-2Em-hvO8MpL1iQKqTR80wVRr9NbcqhCY5xmHICKsriAL6P7EcDCyeSXsp0b7pmwMYV4wp4-7E_HenlGa86oPK6ROm1nHNCJuuSuDe-2H_eU2EJoJDhytl4jmkvkbrsaaatKjxFja4iL8faqzdkM5WzHYV511vpFaLtPqJKVDy37ivz3QKPQPNPwZtSNIFnzCn5JvmSZmOs-fbeecGbGxFT-jHHtIgOsZyYxWvXBEYhULB_UwaJLmV-W5FJY1_K6OSn0YKnLXx4QHiqzGQOE0uKofYuZUPptZDjNEwC704tZElEUQdFtQMxcOQorDhAc5ggJsMTDb_IHsQ99s7V9p3l8EXxneqFihZpi2ZhjJk19Fi-WGdezrw4Mawwxd8vG15FvuVSlUWIj_tgPyTNjvMlNVH1Zt3OMNDGJVyE13cQXDYlCiunOwhI5QkIGvfHdsSB9b6mIDQP5yR_lgWxCLZ4PKX0nyxAEmZDB1wkawHshqwMcW3iMJTjD3HnrcqOZYHw14Z7YgUnSeVWfWRhTOPf0LXD4WmHAMQ1xT90JJSIfbjobg0kkVwdrVGATwBnK5dmoN6_07xeK_5Ki-W922cicx_vpcLvTCCu7aF3nrWh82XqEL3dAF4hm20Au-18C844pdW6uoyrHldz2PpCbjI-KtqHD_m35IKTRyGXQWlFsGZ9j9JLWiqfRNNm5P5SqT6RFzg2VtPEldhfDme9Jqbsl588OGPl8ysPTOkIR3Xmk43O-o2YRB9m_hU4ZkLCreet-ss0lkvUYRlwQJuRXtWpv9_oL9e-ABGdmnzrBzpupmv-R0_HTaHWPF812r1DGNFJtb7gSBUSXE2RFuLyBpmn4t_R6ftqB59n0InAcoziAjY44xcqsQ0rSZ9o53JIU5BxHX1R2n1sOLOO-_W9M3gd_EXbtlL_EMqomMBg06RJMIJVrbFJXTwVfzcxcYmvB214m2WQTI2w6B0TnXt2iVt4ZsMAZQbXP3Hx9-d17SSua_FJnWDCkj7fx8REx5OktnGUJ0j4-18rVaAUn_dbs0XPu26AwshmLObBtQ7vZMcjq_jS5_4K0iTkHiag0o9ERxGxliyLtP6T2cuX3EvCn7VO9nYTLyUMEHI1jHihmOZUhp5owwpZaGwwBMhtyKk6FK7XKWj5sNK6BsMxBInwvgwjVyMXo83M_2zM1anNVQvxF7ypghoAG4NmviBezOzn1ihjHk= \ No newline at end of file +gAAAAABpdpE6B28XvzBIFrAjdP5foYWCGvyZY2f1wF0l0qCxX3TuivQqz68RHAuppq7v-icu2p7YdsooHimIFGxhmAexq86HzoY5sZrWm5VVRbP72MHguJb0-nUBr82Ccjf5FYROfr1OEN2lPpbhQQC__H0opQPlpwSwqR94h9AIvSvfLEsscKozY5tOLQsOnEcthZK3rOrYMvGGP_EG5JW19NE-g5k4cx62p1IQwSBHPAmRejIcVP5H82iybb8CD2_bdS-FsJ6mZo3ghYu3JoVW803_xswLT-Y5ly-3QcYeF05hMYVVvlVyBKT3Rc2yCe4ZB8S6MexykujXn2GP8evjJVRFj5q32jzXOpBpWysD5T6e0R7kXVWIdpxVuhhW29gmaJ4T6qPQ5Im_r2lvGpRK8iiQTMBSrpFJQLsFfli1WeT9xNmJRX2NsvYmryZfK5jI3i_hb2_c9tk2X3WNHsOPQB-B1FtvTOoMfMG7NFH2PhFbPRZpcVQ1CeoQNyxYK-1bFcayqFdFuEo0riZbHbn2aQX0XgGWj3s_h4SPOlVAJHM4T5__GmX6otU4nMEsFXibeRD_aW6nhACxYsxiF8nKVAweFX-QbwZd9kb_U7E_fx23QC4rCSBvkzgugzf-oNx5teDWgRyGbPCEwjPey_xO_FscB2ok2Cd6d547059lAnLQATxmjGWmEVS22qUxWfp1BBQcE-6SnY09mr4RlIfAP0qhwaLmG3JNhe6MJvbFfP_seiMN7tr79xej5KxOtJpnRH4cFAPkBK8x0Xbxs42ujRerFw1NmxHgFm0vyPpCxaFVst0d6tI1dw2ETDXwV8KcXbfzZFZs5JE4vgq3q3WclGHoGOHpeetmVtmqSSLsh5Qk02bsqhsj-UpHAmdNPkwossEmar6GxOIqBXQzbTqlUnN3JSn_xZzhljgknzT3HL2Bwxbi2M-AozzDXJDk87uBj_3wZUCFry2UzOhuvZX5lz_-mbwwoAq5oYYz3Z0Jnm_6MvT7hZZf7F9Hn9G7LXHGo27JQXwvhH5n-OJn89TgK48_qtSmgBPw2ew22qq0eFHzCBNH1LJyFrh_aaEUkxsyzVFBWGm5hJx3qhRMSj0Gk6TggAVSzU5U0d5YHUS226b2CuJGOYES17_W0RHBuc2HikitaX9dLtebBePcRw6lV6FOSUqdzBtQZzNCweZsRfrhHnv4YAVuYTyFWX7v-dB8YcG3fs6LlgG0obVPvaEyGRZIdU2tCh7c5yw_OluhznYGF_vqTPcCCahVsMl3G80anq4ybwvymAL5j-1rrA9fosNYdI9SEYGJcu8HcCehmg-yd7KhpJH4ykHHvVARRTvgANTnWdCWlbIdD8OUDnSntDTDnS4D9UoIKEzIZH561U1XoMMctww87pe-eNeYJ31eW4cd1Z8Ho4dNxfxbCJjUo0hdBo_1eLvLP9etBEAo7w3xnTg1DUs9i918pPfocmGtCovV6QRRcnie0v5j-10CPQTPzOl7vhbhRDG4sTJTusGZI9Ns4CQo8kk8j4CyR84QyDobL9Ipd6Zg5y_MuYCKFrHD4YV1gWDrWWSqMqUvsomwOqTKPOU9nDT_hyUDQjMtSW2a3fPjmIpC41jMOim3BGWLYcAZY5GVO-qjAI-vq5nVtiqlHGJcZKfGE09P5A_3Tj6C7MUHsbbUn8KdzLGGAU17Z4MCib2yv06qRpy4TQlVepZTcczmNIZbikSNVUcdN3KwjpxoCKWOG-A1l9DvrRZESf_s9g5da_oSuXE9bWMzV_ShkQgf_kjTOOQw4vTCUOXHvcGRbt-1uN4hPd_H4e_8qtmQPv9yVP0PxSeH6oiYUHu_MahNxszkoi63ZcDpZfJkcDN-Gm_q2EVtzeW5uq6pqJN9Ecqnq0NeUpdEXesFiT6s28tusUQkObP3070BkGdHGltE2O4Radqmt0XKNwvIayDF4-WsgLvO-xlYMhkwR3QtuGZnO9BXQn-IcTSGYS2alKym3dfTcx_iZSIgMdI4tbMYCdqsjy7yXKXbrNLA8Bs2OEL7_Z08CfC24vWZRIyKHloTD1lCifDomTtZXCm3OkinFTJNz8IVDKB6jL760oAbkR97CXxyk73zId1vOhGU8pES9zdpz_brInXIDVoMoOEymQmx5oSfydbZDcz3IQojcQdPutTGOA4a49WqYRLT_BOe0W-qdm5LGOipxQAjUBu5UOSQkHMcH_vQyC8k9ewbV4nbYcVToCW_9tuYZBLDPknQajFRx26kVhGC4Oe8YY74pHwRg37o8-NfYFNE2or8fARAxoLlvL9lwlVp-5j4IVSQFO5f7FoKelJ0mourqH3bnOLUcPs9rvKVh2W-B-wxKF2Ia0xabcaorKvSYaASUfDOoYDdv-u9HW4PWM3kCIxQwTC-_-0VI3EpkopmrnlYo5IAV0fmmMAr7CzwzZKMjbotO2-Txg4f5osPNF_xr7yHkOgyi1wAF0rkXmG1lmT_uHcOsUqukke1GRJLLms2j3RpIOaDqSrh4RF4jf2GelsN3-4Smj3g6xOOkw1oTejz97iG4o2u2yTuuz6DpheX946sDBQWLH-NWt0GMYq9BWtzRygkEhn5PJUUGPSw6nfSEKfrSAySo9nEm0OmaRmR2K5Q6IodSliLMGY2xqVk0ePM8s8FWcIYduVW_f-rxKonnVIp0XcI9YnVrVuqclmXGc2FDsyajw8UFZKpBni0Y2e9Ttd9EFGYVxM6-LDfSvAgqkq9-fiFE9g77VEO4_FQDn3hz620wq-SP4X0z8JGJ7rs0LotOZiXaiGIwQLRD5OWaDaAk6xDUYgD_7CEcc850uPhWIv9TvbPMviWxbKYngfoQILmqbdKdiwoAGoUGtcZyChD2a32yVuXADXYg-F-VslnqiDM9IzhHp8TmDuijljrhBm4i6mPQydMz-e1skf4o6nbHqe4d7xIwLP5hkTKHnrVSXcMdNAp7m75X1XoatbFUB_ZdT0aLIhhuYIZ_ViFSS_rNURCDaflbroN7dBQTlXaFBANnqVVRqNMC_8d6UhydLad7tpxepx4cF0EEDpRpJbJSlCOGtg4EVHu5mDIuSDnM4vyKUHNZ3EEPcTtd-INx_zPeFiob6AId7dpCc_oq1BDE-aaWm99L5CbLRqA9ozj8IVGFI9riVgtb49_cMx9f5626v_XhtM_nx2l3ogbsG9zjKxebwbV9-CJxZrt4PXL0mRU4iroDjEm4mUfb2uqdQTOn4PlM38ZyY4dY-P0n9K5S7iZgIoZP8sMVELUxUwA1DQuEXaJY0IR6S3JQu0BTVchj3V8KlEtC2_Dj7FbsW-3pJbszajcsW9sDzRFm8Nt3OHgYFjEO1vwxE9cSkYtb_HHCnlzbewZGVBdhkSgbxkRMBlIwjC0jJSrEZObdt78EChMrNVcl1jNtuOAXcjc2zp2xToaKOlDg5Copr1QKovgGyzMI8DUT3TiTA_er5NZ51KRBjD5g7OguZtyi5W-d45COFld-KztbgoKuEFsfxwy4rDqQLpFdbGpL6FqX2Hacjqmlu_fzS8QDSoxyaYMdzotq_n4tBpUwEL0z5UUPILlpM1N_nFM2cYivwh8pvvIRkjC871TRFkZmIDeUEY76bgKqiGWxW-2zi4NdL4H8S1IT0DP61mu16LSR24zMJjOmYOUCfD0vDicR36ytHZ2INEx-BTFNLsesg0ya03LkwHUgOO6Aq5VEorRFVj7nPHo0LwdwcsubmeoU3BEyrTuCmjxwmHiO0X7EOzvQbLmtO8hS06ESVAHiB6E1bsJEhx-TdENcDXcFnkRkv_V4aPI8A2XLhp0n_G0jCLR7rAyfdps_dDgubjwZ3-L-9YAYpJtEklIuo_QuDlz5AvAJgv2WkeU7JoXztjxmFigEZeXy8baA-lpfUFWD0x-k4E0DPMoCSsHxWIgWHYbRowKclkBbmuSBuIvKmuX-3aoVDR5-OGmy-iSiwiH3H-LPqwLD6Ks_ihFj_AWW57CRU1euNKl3a7XRjI-z6iWqMllUQI1BSkVHQc5hsQpzCxPSdC9aVlpzp9qrH9V5F5JjMn132gLyrZx97A45EIgi2C2z5ocX1Mk5FVunTw5dhxz0V9I9PaywoC2p-4GIuFJR8TBVvzWs6sPfhFdqk5jfYGjD3Jrda1QmVgiXDJ7x_F8z8gxK4q5ut1p7bRkqzz4uzMtmvh6H6jJqyja1CKw59HAEK0MXe5bat_816WD16GRw0BXkp0DVKAsik1Viw5QPTHjgBnPk_9xrbP74RvJvKELIFFL1U1eX6sJsv8U8F-CrqNCrjy9HBkibw8wCunDskh4fpX9k38Gf6uZkMebFRhTnEAjI3k59dUUPJ4zoVRf0GNX6t2fJLN273BpN-vKaidSe5Nx7sEObvs-H0wvyVYEHx0i7WA7uUF-0zDl9WKL-scheILt1ZdtGVrGlAZnCU1FnIGlzvhBI1OQYuFqcXgY3TifVQ-v_LlYrYc2WjdTkQlZ1TOUOmdBpgjrMtqZKMpXvGjNvlFL0tlvcalU5NmOXeDgtvWZVzwfQ3vGZmbOtq6ODo4k5pOTUrNgJclTM3mG-eY9xRduDnKhc2K9-imud1ZaGR4iZv7U5AWNxe0pyiHXbmWGGIRWqtieYKCSub7Bf54-fSNDlVYQPHVSNnm3HWebVujbMaHjJM-3IkMpuRI2ckgTz3kFS2eDZrS4TPWc_747UKG7FkjmcnZVpA6Uus6PIFpTuz3IyASxFT7CC4bf3NCkW8daJzCeHG8PsDauJw1ZwYCI9ADhJJKJG8qysxzBPJyerMtkJMJQV_5i6owcKs1xYDCniXUEvflGQ6S-LebWRvJF-FAhOjQetqZFkfuBIm4FlWnTWCzhdddaNxQP1NFaSVfBuT4Nv5JomqB0yJVY0CMxWSQAQVd0dF9PbYKcF0cE1kScH098K1MaYP8qMT7tqrT9xfr3ingGF_vs4uNpfOVTswEQFSv6w-FBi4v4PspbWJc8GvlvpEc1iT673KnLJeWUFiMvJriSjzLnYh6wYjwaM_YHSZG-nheJR74vUsyEwcEbGPVtevu-a8y_KHa3OLxgKPtYXl572Bt65vEaBPsKhL8ymJmp_mHB-01Re4him-TdlB1l6rKQSIth57NL3-qyLYEaP4qMk9rt8EuO1dhZ1lxWPBjuYlFAyw2ZXerNZHg4y4NQDlIJu3WNEwpWoQ27rb8FF_aA_FyiJjrK9IRM_cav2FeRoH8lzXFhLKNXL1u48ktS_sv2v4TXlymfY_B9CcBNKkscXXNaVZ72gPCvbLVjHX0Jz4qs_Pvhocy-7r6EhnukDubzMk9qhQ64bX1pwmXdZAO3PGHeyQ6jYPceJO72XU0f1IozdpKLGmTQsyzjYtk6HFge9BVHe6MxStM9b3cRRKcz5Is7kV_gxiQ0bHQ7wfXRnkOJKZhNGUrjn2CJN4Pjum2lVJtScnE4Qoy-5RbNC9UjsldI_n64hKuY3Mqx1vwQD7ST8Z5wSUIyIXlZFb69ocvcTCVVMn2H3_KWJZ9-DKuBPb1HOAeAyvn8DkdFUfH8QD4vCzufG85HnGh7j4znsxz_BcwaNmYi4cNOUUcZTIiVehFVTnAIBzIbQZPljwS3Q9JZCigTcG85W52kRupfG_XKQa1CTNyk3AgLSi3dTkiRvnilxpcphLVQSWzntcwIPao0W5EimJoNA7BywCEBgwgWLm5qChTluhwKIpfGquo3lVZpPNRjHg9oKKOfosNZa0PXXngxjc7lvNRkyghMsudgKsaLsxi2r-iEAcO7_og4NBhzbZnrc3vALQFv6WzFg-vY53fk1fP4bMS4snFtUIUSyqUxdCC0oNOiFhvx3kDD5RXtUSguCDcbSCU-8QT8-UDX9b4K7LVsPDRGKtfajW7WDuQop0wrAunbHAtKXJFYqM-YvGuqexR1569ZXt2_O752GQvDazk-tmZDh0FXLZYw58vpN2qMMSPsrWq7dPKfg1hejve-heTP_wdnv6ubpSDKUeszzdOY2IHNQHaOkafxg-2SBCJJz39Au2LdBEohjBXDpPEWvRct5CtZpXhclRVJaC6MaDhljNzZ_02cwfCM3Gg9a4aOG9Kyf1ovzvvyH326r-QjF9HhRDhG97Oi_V7yhSBQ3jcLsOLm2Urf6x-x8fHYqVNHveFKXr-AResFOE_UaBjzh7D8rNBtRGiXlnU-H5AYnd9Pta5Dlxetrb0TxXqByyqFBrioJzHi08H5LJjXUt7xCnRpn6QJemXF49LvbE5CgRXOIKlOmqefzWnO3pVEbWRKMDWrkU7MFGmxBETgy4nXR4qA4Be3pz8YIVq0TZmmKdZVr30YpzPDWhhHJrufImXnq5RO8vHebNN5vIN2Gd3Bh4o8zrQDYJP8gS1jnKWf4GKsq6J2wIHo9VS95shn5QTGUEPnziw_R1ZPN3LQ_x8cDDJ49PZGgNmZm0Lb3dt0omPHp0GcQ8iSJIg9As71pK2mfN-SvXQNVCzPvcPAxT-npnE8HvgcZKRmVdy8A0OD0S1r1LqrQ0zhEo-0xWhqdSZtCNpTA3NaRZEpsoYN5OkMMKCY496b1MOd59kYVWZATssX-8W5jOU7M7bZl9Q2GwfNlqfau-C3VzimfhERLw6MpcC0kxVW4NVUyKMcQgTgX-_LHv32Z3RLxzVHbUj9asQoZb_8v6GGpH2Tg5x3Z8mpKW990ox5HgLHeHbNb4WRY3cPaN9WrfomffpgJTr6yau0mg_Z6J07AXXwiY_SXjOocqplZMAvFhTaNST82bNZY82BJA3OAT4B-riahAMAe2TMvf0zfTrI8eSdgGnXl2tm3Ow6Hi9T9oXeVHJ42omdMJJvzgbf0QfCA5GeFNKGZLNC_SyaQvjW-aNtCDDTEjQHSUL1M-40JNBe1-Ere5M1WEV-kkPRRPy3NH6z03rsCVXAmjXTsJnrkh7JOinb9oFWDBtIBygYFMo2vDzELa3ci4eNGLjzPUgMX--lVIqETze4UJEsee_jHWH_OSkmAaCKJuNAOasJOHZzllSa4tHsLz6vLDlLDQPemdF8LYmSELf4ZEcWdPwJuIhjxLTaUcHRWB3XibCj17YjX0SrE1N4RmRqPXs4V5mpueMDrAvA72O5hKQvw8_TXZ6TMGM3fCAGoOeTvt-dG_hfGHN3Kw_1alEcd7iP4VJYJ77xPLUXcHu5NJvYTwDrLT94zPSWZAGttAEl8RyDWbDJpjxZBxo-rDbk6wk27st99cBJvDr_oNrK4cGf0AasiZigoccmOAyL_KaBXYV41AYx8UNDskY0gB6HVOtqilQ2K_Mr2ppfM3M-J1ZWS2KYZWg-nrZXMgQIkdg8wib_v8ZUvzKvGc4roNxwdZZVlVI6VFcV1TLm1a1h7kcRTx9CZ6jJ5msCSrcmPE-VmmQQYXjgXctS5rRQDFuU6AnTwAlNG2gxr9n_7iyTLFpff8Gqtek5Y42t0yxrxv1_FWvws8U0AdXIZvXy36EPK7Yewuzf5w2fr77KNbv4-m3PI4t9GMI2eo5zmGFFC0gxA-T-_O4rmkbmbGupBCqCXr5ssqF-d0gUZKZDDayuEDKN070olR4pmYvrjFS_grOR_6-MJer_XX0Lfmqlzdz74H39AdNfsZbSQtM-fZEwdwJAqWNJy5W5gNMspaAX6SD2fY5gExJ_DTMWjnGLIJUoB1UstfEwmoP9Ma0qB3k3WfaR9uphnsyXao-ZiaFhbPIhd0Z5Uj_fDkzJb9yhi8tiBt7KAc30gfYWGzl4qYmvctfe3qr94Ub0_WfvPJ6INoxDXr9BalpojZHlcHXq5upKXnKcLRSi8Hu7rm9sP4rwV6EcEuhLIKLRP92T49xDJb8Vu0KJBLKN4dvjiPmQUqBU6jlLumugG9RQGDwAS38dL8xFaI6TO0pr6D3Na9H-bausYFNKRnlyKLtdbrPbVvc6rzvGSP5Axml22_OP-9GFAGrqMwGSv52Sq4GDhfku2sDLrpFL1mBo-VP2lbfFhCNfDfYGFnQOYlI7ncGcEzvqJ6N6OKWKGK-dwFqWcDbkZueGWx_xngz0IZul2kaneQB0FJ_KMHFTfUKpgeVLsYg_m1a9AVAFYyYO9uU7e7C1aS6dwOujr-hQ6Qgc9TbheS40uknUHe7x9v3ike7N2JhV0ysmP9jGM7GMHJVYi1-oT7gBF8Ifls76Bl-HlzlA_XpyAjju3WOgwbZt4N5W-VvXC9-QjfFvg7VCq33R5MDczbebSE_i92f0XYwNRJJSIA6pev2lz4uHaJJEC5eyqNygtL0XIxMBV1xf8gOFn75obbP8qiMo9LAdBmDa3PVW4Tx2I9U_QYZ2GWPZRMaR-6pfqAztrNs57QiyihhaF42rxREMVQVCxjUMEZU2Wyr_K7SOl0_80tglXCfzagdzD0HeDkcqPhC7nSTscOoo6TrjCE-U2FijoiUVsB8ni0XTWtlaIb8Y9GgVXvqPu8KPXpcIO6fqGmpjmtSpfABV8nn3GRIxWcBF3mYmzpSqI--Fe5cgoR0sOPgi_DAkyHx9bk2DpeYgUR_wI_vlxDR5h2o3jdRz0ddXAh8a1HYyO08VKv6E2YkE5wHwFNQ1s9QNfRQO-cOHuPzYiguyzx5NZTS6ewlbcyfKrAtO6SxDwCkeFyckMoyOXpjSD-PuVgJkH9gKVY_6UX3c-zSaO0W0D13FT6jxgJ6nn7zzCrw978PlfllZduEUEVm48kM9eww2PrLIbX4ZBNfaBFP2XX02Nm5-sEMxg5riN_54tt4ZEgaD5JiMe_--g5mYosXBcP4nSjbOOaEH598C9yWkvUYCmVlWivV6IY4v1Whx3SHd4bseguPdzhoVdOnlnpzL1y4pa3SNEAoJgOjUTj95xUR6-qAvWQ57UpG9GRP21hVEsVWdwp1TL1S4wwiknUGxDJFL5vJM_ECAfWsfTSYypIvHVPUkKh2OiDKFy1Feu32n1wgqEXScf4Djr7yDuGvddT6Ko1XRuJm_MKh2MsJNFmh1B7CTr8xBPhsjMXiebin8R9vI-fl6YDcRVmjy7ul9_qGrxygjTs2TFk61fcYn3IcSpsTHvw91TonRORN6hkTOw4vO8VhzV2ZqLdu2EI3t-fO5DyIsIjzNz2Ul21-SjSuSokRcjnxh_Puevr8RqXTLeyNoAEOotDVb8P_na7WzG2mOfntawPCnSYdWMu3n4eaYY0lVS_cFmSItNQalfe3I6eyqv_nni6V2rESlXhienG0SbUNh0_AGMZvGWc7PyQrRoovE0waBIXf-5_4oGZYOfmREobq-mSHEV5d-FKZAtSgWhxwUU6RHYqiHxBoscIk5hQo5Px6HCwqogG0cwJ6s8bPMcFD6EEeOUb26m5vU9SifmtQ2sRmUWWzOxdsPO6_SEVgzlTrQ2Jw1Pi9BPjm9Y06Wn4ao5uszwdI0GPtilhEZ-H8HsJVqDiTr1dpTK7sJJLPx-DKOdgGYeUZqk3A6LaHdzufyvfKal-29hDNef7xvM2GbRXAsxw-9S41O27_Z9ki2dtlokEV3-63_hQqVkDCN8gqr1IRUXBX9_RBVrVZ4SJfhaU5VZnUHxqk1EoL7TBhkaRxZCrBcHDKwjNaFWNzBrJJnxQuXnPcmKGvER4xVS2E85JjwB8RChUIqAzE8pH44ypz6VjP12tiwPeOCkCQol5mUKXlg1ZDckwSi3zjsDURt_XVAeTkD2M85DuKwp8m75G2m78dCcYTeRXrkleEvPmsJyZAFuOBrLcWEzcMg7XImtlnyfmV5QzKNjhv3Jxv5uVEfv2gduvZ4duk2PQo997mhs84ZAxRDi6Y9jI2Z8a1W_Jeh7DLIJC36c2SIbgSW9NUEMdRy8_ejmTc4cMfJaGFO-Z1ezwLIi8wrwSVY83ogpzIvvZQPyn0DR1hrh52xq1fcb4yZwJ1YWo4JY11KZvLqFddRHEu1SVq0TDsqvWfJzMIT5DdIDg1ranve_-K2tw8zgAqDewTflXtAhwxXQaWBJgUrhEBrKdQpoCEuvYAbRorbEi96kOeHmojEzKLN9c11bRqdVgPoAiC0QvKFMLs6f47OdGAb5KtRS1cEdpCwSJfEoaySOlpfAY-KmnwFe2K-YN8ukAYNw6EQs7byond09j6nyqSMfs6JczTFvGQ8cFI0Rihh6SLY3kUkEsCVfDVuuTtwgOl1ux9z3uBI12r-RnROyVLEGQrbEGsrrqQYfaY5V_sAKu6YPyqp2WNx6CbHQL1Vabj75KD3gIU7TH8CmT9FM2Y-pbZJVX9EvgENEpCP-1zLlbj7G0wcE2LFw9Nl0HyKvUK-h6xrcKNr0nR9wvwJQuop37B-xcUZItboZVu0dnjhFWFviuuyR1izbKdev-ZMjmGyzVgE1iisBP70gJcNZn4Yczn2A4QpRPh5E1HqmoRSI-Y-halrV5XwnqRQrbZJZ6V5xL6j7u-_FYKxGZGtxN9CIudZZOMqTBdNGNIp7myWKn0j5Ko75oM0QwSjmiK0EJJeX6DK6yp5y9Q_RSwpKgnpLUmgpsNoeYoXr_xxzNZ28XHD4PnOewTfzmVpw9fOX4_T5i3BHzSzQgc6Ky10E5z-Et_kg6BdhHPVsPYEzwbiq7aTXR67qamV8OohxC6j4TIUAJlT07pCsvXObGkHQntEmeAr00YcKFoRWsCQw9pmeZhrFLouguhqkQbkoLEdpiQ-VFsmBeFCb6bsuUWywt3IZ-b3sMo3dyhOfSfacZFEcGAjLtZzSXQTiLpez_nb8waQWxdzpEIXuGtFzETiSUwK1qZC8mzzQZEpXzRAQuAgIe_N7JgMWDOIhNKx7unO6mSdBDxxI3ziSkwL9zy8UBdMFVXZKPmkuScFTtMkNA1jeDFfjSnvwNAbdENmLgbN0si-nC4WWwqmY06OPHptRPBeZyZZHK3dN-a8wwJ3EASiYcE5J7KxzDai4f7KtaqQIdx8MmwJcT2qsyRcgK9-qw8UH7QPZ5xOvIRwvy0x7Xmns5708qG-ZlSwuSHjK3lcg8ojGZp2jUBK1XDvpmY4KiSJfRoqifGfHfJZGDlCztWKL3lzAlVrmBDVnT0cvb_EcjhLuc-diO0u8SAy8XLknAhvgg5dPmcSDGtZHiL00W_Y3pDphejUGWS68CZpZDsAuItM-2XY3UGdwjT3yLHFNYO2JLiufu41t6ztaryVfBT-HiL4PKnQNw4lPfrOJSCTz-eDaS-Rdn67vRa0tSYdMIuK9trp6PKDGUn9W1DMpwK7sv7xKdrFDRH6vXCGjKVHPvgRccXUCLhaqzuybX0I_PULwQ9VwiWwNa29-w_Vh_X9moMAgi-XkNNv4MCG0NybG5nO2hxObkyOL69aV0d4zPKYMmc7wjXDXgM6XHmC_knidFaoRpAC23BS2TjGh86nps_IXHLh05iQrFP0S_PdPNaIjZJqFZosp2RkjFcawtEC2Ld3vz9zZNDfjGr1wFMv-y3959jcjrVWWlRZh3v4wIGx1ytnekPEVTDYenaDHoTycW0Vfad0xBw8KPh0Nfvq6imHTNr9Wsi_te5fvJXqmnfU44VqjV18CXZbtI9o1PJ3hc4Le2FQF3whD0axqPMXWpAb6AtMtQPTV6mwe8kyWkJBiSlsxw_psriDg_Ytq16glQsckOwqRASHc3i_xWisRbHsXza4ihXFxmatc_GzJb-mXsxnIXB9VXWRFdcws-QouCDR70bCtq31HP5ejoHc3YYHzlmPV9PC8P1QPKnSgJyCnRwvhOQ9o53XMl8Alz5r71qAK0X-8v1PYPnl0Z1iZOKP6yJrPAZkAD9LgHc4w08itAlDuy31ShH7BH7BOfUkk3k_BKdA5lskJz5uoa4l32BmoA7B7dFtwj_AReJ2IdzpN_aqpZd0i8rnG-xdweWYMYSGblBYHMr3P2znfdUWeZXLTpi6v83y8Llth6sF0GiiW3I1BPgep6Mgl16K4is48zvA2MBz681Ln1hgHmIA75tmhcLSN414rjhNinZRk09_Kfcqfn7zX0OPE2e_j1cfWWojjIyQktKEFOIPLHCz457aiSu8mouwWltX1J__HGiE059nV5e4YtcTiXzRQWNVltS0KA2f0su98cmT1VFDb805yghCKjdGacCjoQ5p9oQcVQuHWWagBzKtyXBU4KD1jn252BRhbQLvVVLDJtc4DyMT6LLToHzM4GfZoAtwytRqew7bhekRmoU6M-LnXC3bKo7kf8CNrqj4ipdmb2kBbnAvWAY-psOIXE8gcqBsvkCvyI-HwTT6JPRcG-m6Ht0S4ExURB0FFDwFsXKQhI1Jvabu3NLjkAEj_PfAg7xeCanbom6R7yErUsf00WAATG7IgWIoyIGe94yKe_rSMn0NyzWaaCJr33Ioy5x5gJpErJTqXKtyBlq85RWgPn1D4srMH1QalH-D0zLR3dhw2MJiKsz2P-qzdi0vr3V-TyFfLiAJK9s62KbZ_uG3pEYgyw0wPZ0IfIpIQPfZgkDW4zMUJcjx9sV2S7Up-LnXen8zEa-jBevLeqIAyKdV6dMzpgbV8NfLFqFz1UvqyYMoCnBJAJG0t2IYxrckdAeQjyK35Qni2I-ObgA3H_okrrEwVK0DC_7GkYU6Kz1rRZ8NXAwUzITCasq8NS6P9dhv4oGuXKX4Erp-R2-7kX8TgHquynRCsUbpwWHqmsJigIOLgJFenwbfscnVF1qv6RtB2IuuC-A_rgo05knN2TI_6_5J_Bvmg770GIaVkizvLAylUipXekQbk1qY0E67WM_wFO93FTJ-dpB7YckbLd1CjTHa6cLlfjTzEvwVvHrTHha9KElGlWSx-Ah9OgPoDOfcmK9ryJoFwihn0bS06_ZxXdKz1OgtCHMJiDsN4UJLoLY_mchLvYfznBO1WXpuoESKxxSBp7VL4JTU5un-RCws2QD3IoToEkejbEaKcEqCoBp7VLUHeKxazid8yiPYIC6gQgXAomoLSZtwQuQ9WgICbaHWGqugD1hraJHKftZSRU2GJJ9Rxqwv8mEJp4ntRxR6SshwxxbQxypkXpM1WwpY6MyRCh4-MVmKOdkzH4f-BOKMaLXHO9b9kJZrZTQJ33qfdGhGTdOe2giWzcoRLgN8mSvlaCWO34qzPeHjs__wQgJT41l9rN7cy3ji_DgnBRfY9WHY10uZpNWYXMwakbyn_vZUkpANYq1sqv9HvpFSK8oxZ7IdXX2LrQHsXQ_XJY2q94xyw8kb6jWXk3vJvWESK2MY3Z0cmp6qVb2Ye_x7GnTYnc0PCkSqAge9b6mWa7XxBziEKhlnUqZ-LB-pJdpQOYMRqXDpMS3qqMlzHwFyEtpnYJ0BEUjLtKtW14oUOrNJWP98Sp18VRY5WmO5AffRET9_19ISmTrLYJbpjVCgX2f6GBJE_vsH5oXFRqq7keCXFVrw-WRVk_hJMpegv97SnvC3q9xyzVQZfgUjB2FBwxVfTDv1OALAj_pJ8JyUMRFqSGCbQ2U8oO1zhtUdEWYGVBO9Uz4xbIObSA2BPVkE9HhTcLE8db3mmPH9DUTv3m40a9zkNjVL7zxqilyq3D3nsY9FgjHFgC9HZAhEruQRz9vQ9oqZ5EvgI0c5IOJXpHFwYMG-rlk2DCl4juA7X3mBceS3rSg-F0Z2sf5jGuwsZQXrb8DuUfOvNlMdHf6JbJr_AB6SfFfisME09CvWukBL2eKQ0ve6ZE4X5bMn1OYdZ3glmEetbLOyaJ3AKOG0kEiUV1ixtnrKOcT3vbFfseE8Lbuv-IpxQeTD4vuRkm8FmpCmgukNNVZAhdmE-QZ99gYkJ-SLP2JwLAWUvSB5D8M29CraIdrDighowHg4_sB4V0OX3wBb11WY3Y77RinnuYJbgD3-gb4lHPRpLX_v6cqkiQ-eBY4Sw3aqbxAAt9XVszlA8AJWT4BDuZpqxK8zr0TNi3Fnz21D4KUGKkeEzPIeenstq0tt5JTdQHlv4BeISV1xe6bl4MGsxJzMAeagjBgoSFj18dA2a6sSWq3b6Om3o5o46FuvHyzcrJY3ebMd6hN7XasPO_jB91BfViYo-hI9rVSErgjTJwa-XsQF8wErE6P23OK7ll3t1p3seq3MaHZesSPa-iuVpcNh96Kk4TJDz6BrthBPrmzOgMNhIHDyaDt34OwNGtUhDcjRvQDI4eQtE4OdXzVtkOtrM9t4eVWR0DLNDaAHvCI_j4f3kfHpmwwQRsdv94TyP1PPA36_rzIh7f9isUWXO8R2xRuewLfYc_JiFLXH_QmMUlIuUlc4K9Ab3NnvrPiEMvv__gI-1VJjGiy0iN_bcwHsWo2Ute1AYfQ9VuHz5gI_4jOeOSHkoNnCBPMSGUTUp-gP1wDIinznhPa0soUqL2tQLDu43HfgQT9XmE3MPuI_05MnuYtAUZ8wMao5fzkrBv1C6KpBjO4GGT2JTIgYosAwxD0LR9-MpV_hYYEGavN23-UiXX2vpLKt430h2FkfSFwSkWw-TsPE8HNhN0FtFeNueUrM82kAMS04ET21Tf4i4gd88CuSyJYF1tMQI468sFq12Q95JNbOYFhhvVw4JNuHyhL5A5H3SdetRltsUJW_2lg6-Jroen_vDO5q_6pr0MVveIhOV210ZQkjTxMdHa7ErriU4EhfcUnLooG1LAYpo6ux0egF7qD0M8WU62aRUDgj1gzOkPjwZSLLBKLewimXcyvKZr1OCTzHULhVcpmWkVLwIoDSavBJPBn9OR1f2o6hMFBuspPUmoZ0DJBis-ltmCz5xYYNwyZzgRzPBXU8krd75xma_a7ZA_rbNafYKgTl2t12sXFvK32r9ufxFC-ErS1mmGdnq-h2Dljr7h2dUUTURUsskt3mnDoATTevEn10MQFvg7f3jX9oW6N5Vg57BXTLZfcsCK32g7U67Uuelk6x6EbP6P8-kVkFv23ClTMrBB_mXReZ2oPV7oVFh8Zv6NjiSIkminulVyRwvJuLhoSj5KY7BhTWHYOCc739LyKA42EvFN9Dbn3m-wnV--n89L2zI3zN3MtkwcGCP7Kqgba159F9Atyhk_xY76dGVLgmGdj0bOJ-g3VzhQq5xk1UBm19qjjhPm1abnz2RLOWaY1sdhEZSMQTLkO6LWbPh1aD0kLzUucuPjYHnBtJcIysuGTdJCSNHaOqnFa7q0NEV7nx2CFThro3U7mCDUDrlEK_thiRny-xd5nxeDt5_qCG6u-0d_zcm07BJhx1FRk4UC3HWi5DT4_tNKfZV0GxoQGOfl6cQ5TwGPNzQbRtmM-Puw9XlU7YF-ybgmiEYQIZG9FlQXVZo_MOKdrAAR-4BnLKsg3qgyeDSL4ZIuks0An5SSA9S-V6OisCKwic_CovDgeGr4eetMStl0vTsk1lIN6Boi53uuEdZIxVq457sP0dHKjmOvUY_J-L1xXOKNZrocEMK89E9icUnz2UYvYLeZXPEeQqAXDC7iLaImSzFzYuBgpoQVUMYcz5Srr40EBFec32CmzzWiK3qkY-UarVvtZ4Xchw7QcyVtQPXQ9C1VltbOpaxE7-jroZmLK3KHm0_gWtzm399DN3R1RgOYEpnDLGlay2GZWnTbp5SaLOb1yeD_6ioxgFJCC7mS3BbGT5o2fJgWMzOTWVRP-UaMr2xsOWkez0cemJDAMfPmE6p6yhngYK1VAG97m9c7erE0OckqyS6ypQ1rvcip1e1OA3aXKyVb2eDM1410YnSDi_b_Gj8wq1BGeTVz0yCFV3P4Ubf1KsPRUi-FwvMnaEGSs3B2X-nfVKaSUqPOyoDeiaQkzzplrBSn2-YKs3iMu0rH1mIn3GRRCjQoQAS5G49bpBUYG3GTKnjBCtVes1NMHLYgf8LpwD57kDImiPj8JdN1frKR5cfllRsN1bQBWbm5Utfv4eynZixY7f-be60PIQd9jG9uxAuZK2AZI7cUABULr4disUy6uGDlwG87TnpQ6YrWuogCSMuCQSiDAedTBZuraR251PM2Ck5tWquySks0HgMptKmB6hHCenso6qKvNrlNCVuooKxaEW2peoEYoulOGi69jfNAhdv__o4EioDC92B0YsHfNvw-11qkL0mLB8D6JId3AlpTcSHK2w6g6iEK2ttS8E6i4zw9_z1_z5QK-CoU4o1bvjGErVNywByOrfyQRIRW_bZFJtKjylYKvOEFOd1O-Gme1SaGsVfcbJb0ksaw2uxcg08Uzy4r903LJqJlTgEbsO6u9jhRY3a4LLH3aPYGJtR0AfgALZ0VxOeGe9ua7sdeV_-TNWwMMk9j6fTg0iYm12qsh0BpwaK2O6DF9H66cYvoDrPGrghqQcOtSHpEJ9YdBF8-J_0nOpsbo_ClKm0kN_Uo--YMw7oPFH-xCiJ2gGXrNDPwPpvOlmnnRBIEF8ShCF-rflUrTPkYHSZFuy7-sNbDRWAngO_hvNRcGPJz0RN58zkVBQyzTCxFES3gj2KVGmOppbIObtLy2uehuz4BZTChvsWR-CKiw-5kSa3sRSrvy6oI-RQiWCO784fK_wxqHfNkOlN1YjbFpaWFHSiwGfMHc54mQXZLpI9uPuqhUOXzq7U-PRVfCgeVtHLVyDQH2TceNsaFQJhlwcRqxOpAzqTmeWcSwKSdBEpn4ovMhVs_YWJZq00CoByMnyTaMiwIo4v_QntFPzIUzly5R_rbj3Hvai07sxP5_Hj0_Pb7D4fHcWmhnV9KLZGTBVhXTa4eMSgJ7AmqEO05OidaulKf3lORBZI1X_o-WNhlzXmpdQvBtWhbA2APNXRlf5GLpAZxQxiW5F4JNorLlJWCDaBJ_gzWplOIEFWNdLErxEBEG7ZREd84LkVehs1mv0VPLE3NWlbYWwodoh8v5iHPyv7_JtfRL3R46QcZKWbUbqw8UjV_T1OunKBytl3muOnGN-1NIZT6gboLt4OJP4LVXPl5jtMojHysZp6CE6eHojbMnz7WsKK5Gt8D9yE5HUhpfV_ct00tFiQQR9_4HYb6-PScbPlOgSRIFAnQNetrL1uckNxuRMzRCZyRRdIet1v_a-ArdjBezmOoS34L863nWPreaEARq6Vnb_nSyCi6TB7oIUuwpx55_JFaL4HpbF6ASo_kPS2oJBnForCt8KtUz2sld24ylCyr8vkyRrPJb806RtfFPbw-RKvBg5EHSGy0zpRasuwNl6Opj9k61kQN4XiZ02jz3-4aPpqzy3ZNuMGomh4_EX2Yz-H56nI-t2OuaaITLOj9oIz4c1ro3iB6AAL8Kq8pJjLhPu9xCUTfn70w9LzWhvSA5jxuivkh8kdTQ3gCImPLNVMt38ko6Ll2wQ-9FiPwp1BLStlVcFbu74rudIujA2zxPY77vbSTQtq_QcrycnoQ5S0nZLFhNGrvX2GFFpBKj0XTRddmNOKcGhDUSq6Qwf2fEJVWmgGGaDSZK4CBWs_NVbqYmCpVjzyKLqzz7p_iiJbB2Cpu5uSiFoUT1T9Ievp8WL5NO0vKGadsfy00vUqTmBfGkTdubVPnR5ZnLxmpQIxs8tSNLiWjpSg991-D31scNgx4xaMvzZavY45lfgzMm5n_ihQNZvPFqVlzKEn4hHcCv4gI2YrIMrJaejFtesKS880MFepKmE1Cpb4cB65QWPYFyqieCwhu71V2yai9Fp9JNcyYVL0fOtErgRx2wfXNa4yKHFS_WZHKO4cV_zMzDoHXhg9mG186Ri2qx8mm1F0tsL91gtcri3rqh1Y4sVEaSOA5tlxoRkhQGxgn-vWgCVmzQ1dJqW4OlNRBSXyuNHyJCxqAy7kDxvGRsU8QWCaoUYBCL5MDB8k8PeVnH3EaHkYTKNTMGER8xjEY5eqkYYnJHtRKJh9KZMyFMtGo-fyriBE1FzAAN-Etcakhh_0jnlaDFgL80-hm78-WFpXqYQyv7t1JEnXbXpRq9y1HXX9oICh0yJgLmD2GGYyFvjZxx__Q5eivggzdnSXtvdRO5fA-jKwBT5NFp2St8yND09jWa1Q4on2mb8llSHA19JNqsd7KZwVNyIl2Pug0SFfw79r6FUEnKkF0l__cNJyu6O-mZVlZ7pzJjrucbtALH6hOjHoAIkCBax3tOcuez9XRxYMM87aNJkCuBMuUEJtuvfVkKk2wHbf-Zk4J2aJ8K5BjuocvGMQLOipsoVFDhbJajpE61-ATUyeLSkHF6ZKi8oSF8zD9RMYEv0fPYBr5IcyDTfLZB2YnEr3ge-EwnhE4oTJJXGCpYmVkR4XtwDB8-hcD_nugmRtpsKk9qKXV90970gY2buVO53MKx9klACbeyRf-11k9Dwfc3XYZ3SuMtw07XdojjmDhzBzW0vQtg0VIv4iWa-YCDynKNBjJiwADI7LDzTL9uWiRLw65iH95XzUKFkyBAmMuV7MSQpi9CXUm_MfrFdMgxE_gs9MraZjsqJQI5DCrU4sdxd2VxzhTC2kzhmtDdpRaR8xThElRZiVHMe3vXq4TRW2p8D3JRzeGpZPkzaaYswcxZRYNSjmq4zruyUVbU7dTIX9mj2rZ3_9F4aIOKT2qoMSzBIBrpmd1YInhTARWvvh0ekfnuq0RxmhUE1YqpH3MoX1nZthwWlpen5pAaNDblnEnC2tj7rA5diy-p59iFkWzV_dO_RN3ylMOMgrOos1J220bCfeq8mTpmECPyqfmZiO-6kzTVuU5Trpkl0ijHijnYdHhznNffDclhzXHqjWq3qYMeqtYAXu8PgfvGWUltSSxmWAus-SCZZCe0edwnuZt8JdjTBw7-q8AR1oMJ38FCmjveZnL5C0JjwQD_GMuJViT5MHxHALGqFJYnZUpaSHV4SkT1OnWcKoivyq1K7SDgqzPV9bpQ7s7xoT8MFWW_ciyJweLmGnODw8JYJqb9vJARXKxC3WSmYomMqMBXC8jdzP-MGrfLs_Y5cFTpUD3xgX0DaeZXvEGAdme7vK0W85eJgYZ-6df9Ot5O-SCxccuQo72FkwEFEM7g0doyAmv13DdFg_xuJx7zjIULF1L0oSncKbmKTPQryiaLfPteA2OVX7Zzcqvto_2K9sHDKCxrHxIBY7co6lef2TfeXcKVZYXcl9h8xOQCveZ_052PaMxSNfSEPopIs3HgnyokYwaLO0tNXOLpcLnj_B7M4Tsy9BaftQTi0swFTMyRj83oFxYx-7FJ2_Ru89Lc1-HCa23KNuTutlrlRvr-tCfLvpOgINRwsOH8vhtCjbSBi5bIhvWgNq65Y6eg3kHNnVbf98y7gYmBq_Imp9HY00Vu1G-_Q15voOVpSkm5zNiBM8FS91LIxgaabSEs2VLI7ebotFuUPJWGFcKG6KjoqGNCt5YPnDf4hEeWRmQBAuCkT0XaLRtK433VJVDbmpas2sDspx4qVmPp8BS22NBv5xinOzGnTavRh6r05MxZA8Y2deED5jz_0Js5P8SeO_srP4S2bLwyIWgxSachyfnl7FjcAsxqh_X5bV2mP7t7Ojn5-A_EIb_BRvF8PBl4LvTJLM1E9gQ_Wnt-BClcePD14Xav7OswBJ0jymvKuRGo6JMVr9cYt7XmzgM4pz4EfjKE3XZuZ99p5a2Ky_Fn_UEQxRjQsMlbSyuxvU43-DyUxFLjaXpMOrCv2Y2prwGzeReH5EcJoDlCsN5SzTccqulVATkJ_qdIOMy4jJUXxF8_pOlx3k5GZsBBVWH49QO6a2HcGjJHYqx7er7kbZKFZ1pUTzOIyEviB56p8y4tZVMRZF25ib8-4vyuo5R7eWV6Sgk0tjLb3qkcP8QDfC3dFyFKzzylB42hLQ_QAvFrrSB3Nn44KC4k1skNNhtqrsGLNHlrjn3uo880qFnoT1zjq6t-kzLOSr55TKnrSgn2ATQL6bj1Yof4GDY1K9IHGnssgL5Yo2OtapapqgPX60_nd-zvkntTgI5n8BlvWEjD11ejIkTlfDD05EUJuvScXKpSv9AVdgbaefhuSf4ra--C1py4JkOCuMjA6zhSxun6HynyAFxim6ZD87nn_1yApZZSJ_6qrOBNu3sKVjsfoC-0sQELmA8gLs_IcGLs_Qd-GUmRlYlV4uT0Q-_3uzaAWl-Ub3q59iGrYjNgbFW2eW9bGk2tlAIuq4Oe1W1MopwNNwzRyp-WHde_FHnsGtZasKGVB2xlTBXYHiw79FYvWFkXhg-1_ASt4yCqfXHZSflYQ0bhLCE5P5VciNH2B7_nN0G4LoSXQOl3_9-xAiJyez25XbkoOrXDWrTZOeGoPkbfFqlHcLa16sZ7HHbF60JpQt5Xgy-C8vCWaJ7JgAnTaM2NkYf_li2or1nl5cRkm6_keMKfZUor-n3KPNpCZCt-OkIAR3JSS64KCxV5A21ynVcWYCFEZpIoWQskBWQpFSniPDVq2Nb0Ph_E3WnF1E4FJa1NFbJF2rj6w2Up2ChsJRHqBHaCac57CgQODM_SIKGdK9fnkbRgwE49UAiGs7dF8RyFN5DEjZhVn7Nr2yrF5X19Bdgr2CoTZD81hNZANvNYQQeoAYkw0_TeYqsZhigsXJer-NI-JnL8Or_NVflAXau2A8t3IxKDb5zj0WW9jKYQ7GxdKB20BBwwuwW_ua4CTlvMBAZ1-1ZUXPEpYKnMwbWaJjrFJsQ2E5HzdCc3n5LdWZ5-ML_QlAfJMOXUgcmDaAjun5zPax_BEFFcYX7JaqJy1OFy0vj2xe0mKBz1OYYMqHYIaG38FzcoZLo7t9TW_w4xI0gKQ438bNZzWyZQPYjr3SmsuzYTT6mTnRjEZS8vDZ4adoE295GNsAMb3iLdX_MhYhCyeQ2UcsYywUUO7UO8lJakf6jmzWyNy_noDgCpTysGdNKdURUDTUBbLc-AYua-OAsipNEmwdcIr-iAx6KK8sKu7uGOMF7OD_oSXRa4tisjbOA0TZemfDy6zAFi-aqd1qb0FRDHOw75H6zve2OCyB4_S21sLfAEfcHiujlZZCHEzyA-jzBGI3tVijjirWNADvh8aKeLU1mBxk7aSRD6kxtlvQFnbh8fEJ6s-0iRakFzueML7rLjDKSo9iytTJXleKrYCgMp7aVlzSqMHhpw4ITD4wk6DeC972Ca-NJOLG4CGT4XR3UTccg8sEM_N_sR5RUtZVrNAi_NYF-qsI3y2Be_m6h8fsNBGk_6zQdsYStIptIkTvLjCSiDJhlgxAd_LeH0_BNBrIUs_5DK8qvCQLSKJBsAMjjilfMyKkkcePCVkrGlun8lDDtCn6g17P77MEROHiZUoc6qSv6inEufn34K13ISjaytjkgguaV3jFhVbqwf4ZoXEj71m5C4k2WZItFQpHZ3rKN3bxDNC3GJ8LOIoHq4N6prJmzY-2AejEOA54Zi8EeHV-uyTMnUOpmNHS_R3YLxQnIFgHXU_l0DgQPfi4F9V_L8x9pZ5-Smw8GyfeOVq4gER6mPC3pvT5-DQR9L1FdJehjC4brDqBWmjNjNl4uTsbXnD1t62mg3etlBpYxaWDe8p2f2w5Q0BlZk5W-U5wKXoymTzk75Bh1QoEzpEfsp0wFmJolzL2DkzFKpxFk8ZQHC3sbqm7R4t8d9M1_RaJpmVrDosaZ0Jvzc9kCTeObWsFKWKhSFh2K6j9-AuDjrcm8V8rdFzLBZ-BeZh1rs1BUD1hAoICRM7edb7hhlXAYRkVTrYuz_a4lzLLNQxYBxStqTB_l36bB0Et9r5s8wkE72ycIggg7jvS7uM2clbCQDXD1eXArMnHwKpMF7vT1JfdBvY7pDFqrr6hxTSgEFcKh1Mpr6pfHmGyrh6RHzY8WZ3K1uy7pwE9MbQyVjrmgYDd-7PMF_Ax_4SvTtdpXVd7B5LgC3KZUFthlksVDAmeXY_MI-JSHXU8N8apneLAb8Q4Z_YpZ9aBw3IO_ca55Qsp1SfBmQzLlfnZNdINqdJNgBArzUy31EGwWPPlhuF6po-O0onqluMb_ys4uZr-diuArIujjiMnB2kPynfXWxAS-C_pDELpiVAKjKOHxDoFZy9lF0wsQV9pLhluL5xbRIb-nw-r8bGmHT6tvQ_vrW6IhsbXA5N1rB8KPAkWBvbZPvIj3h3RfpMbZaIA-gezbWpJvf0U7Y-9aVogZYtHGyZPzxNTJsnhUkNbYd6mUMncXSuT6wUqE-HgGZztpYxbENkPIVGugS9nDdau9DCpJcZOo638MWQ7j_zLV_cBlhrhFuHzx9GqZQsv7VC8zD7WNMLJaZGie3gFIArmrX5EsJ03KB5WDhfHoMrcI4jIw_Jwc2a0kCp3ywoLFSP5kqgxGLvs0PB_amwVxNIr1s_oXTD-DxyGaxYEoqPFYvnxKMbKJ2LVl2Gy6h-uh991gpx3Ce0YPnOVX_4tuZYZcpWE-jTRkgXp_Z4pApYGJO7WF1x_lmjP7XvLqFlsKMkw3rrIes3zruLhwx5quJfmgBQPIqFdewKfLp9wOS94RM4EBmV-Qa9VGmgP7wwrJ9lKHBA2uWhBywoWbeBorllllzSMt4k7HryF70wR8ivovMVbGWQATdeC3xsbOgphgU7xs-Nt_Sp0-21oTTNvm8wn-c0TmMdo59UnGlKa_j7AzTgUJ7S1WuaOv96PaLRl4-wgQxaLBvZbqweO2hpgQozOEHHt7CWgyfiGV7pF17RBgVrCFypwuIuKNAh-iH-FQ_I2ltVRhlnrIFdntFb12pouSIHZaAFZ_uwAiPnxZGW9RQukXQGoRu0KeK8nfKLEoswPLbV5EEr0QB0Drz3p0ZJTRSiNoMHZc84Ot7dcgDa7Xvs_kT-wN4FpbcVLVU2ktBK3XusOe2IdqVPD72z9Wo-6nAI5NuQifmpqobLKCOBwb_nChTOHZ7e4O9zoayN7Ug5eUZArJh06HLjR6V_a7prGAMDJ3OgyQ8QoOq8CDNqPUTd_fOk5_kf7DvXNmorUWPhuLSIDmWbhRUK5JPAwSEBpsFzsZa-V_sHCyCGdNmFxsUYk9_UbHb5A1_LhyGpDgAizi6TdMjyyhyuj_QeY26g9PuMwcwFbH7lQIhEapleAnPS5J826YLCkERhHFbeYhYUXRVx4cBNFCWLV6znErVpIHzYzfYmh41DHaSfbhb-bKJVudJF_NK0WsRISbTDstENA4uQAtI_W-TSp8KFx3n8zaYwKS9JmQUG6WkaZxkTWKahvhZM2KDj-xz7_oONYTnVggCZOl9S18aAHpdnWjYsQdamudhN-URrjOhbxRWi4J9PNaekIGDKdiw6R5sQgAIoPBk2GR97J-UWjcVhseZglpFPnUO2GJkXeTfZ5vtuT2tKzaXZtv3WvAf6xrCwCjVaKcDJp5gROEfFIGLBks6C704am83d_ndUICaKqZgG8gZA4PikbCtlO2a1kVwtZu4pQCUdf3u409Lu6Vu_o8pDnc4KKpnblSpj2MzL62NdgQtq2tHh35fGq1J1bYP9Sk-xADNN1SwAPJVR2JXLUGFrB5aQieMfPRA_wzFSIYG3h568UxfnuW1s2nuf8KIV4fs8W4WGZSOxNLQvYuUhX4Nh-odl7_EtDjsqDa5PiJu2m6PanYHlAb_bK0Avvp9RVBo9neqMrApDCBDYX82gpVzufHRt0lVMBdm-0wKZ4LtSnDWx20gjpcYgdJ14RDlM17qbZ28FlZYXpomTMJQWs3QMXCBd7_VPPU_uKGpTqOS8j0YKyYCzglLIuD5bSk6cTgvfvMnCwUTtWZDXLO9O3IhLqxA-qVx2uUGNG_9gawO16C5w-d_814m3BwH3bpjwZ3JQxmmBStsVrCvGKxAQLFiEtojmZeox5q9FT__y4tVymYrZ8bDe31psCt-L8FBs_ENId3N_qN_kUOAZhaXndbp_fcLHjJJLAx74m8wfIrE4sw6Mg4qLmS9OdWhpPOLi54UxhjyaBdGbLKk76ap-jtZakAhbUcMreP9xv-FKs25Awi4AqZ7TtyUyOa76Srm5zC30cPpSoCIeveWfbYEAxA4AV5IrP3yZKL-FHXdmQ-POXTGF6VZ6OtfcWGyk2txSZQFn-uNWdhzCaUp30HSK3NL8jTNPEB5pF7qlDVR_N3NRSVfxDm7-vkkB0MdDlk-Q_iPEwKmkfzfmOhHbOHDHGN0IhdADhSNO3E1zgnG-xxClxRAJMa-glXuXBIXF2WxJkhzMGm9CcfbTXtLqxpydXg-O4_2U6Xim_7BVi5raF8awTdG689q2A_Cc-zj_Gp22bZ1rkQWj1krUuCGP5oqstZWrQ8PY_xA-OrMoYUxkQHg0eBE0DrBYwl4c_OLncdsQVHUOLrZVrkGHeJU7ccPtTF2MHF984ksCl6S-P6vjPQPByTMbVsvrk9JGsqHNFcZQJpWkShcC9jvmSWuIxvH-9V5ZWDXnXQUgAGiYqzWhDWh6Sh9CcVwcTmTDKmwjMO7tS-9ZAmIPUd_KZ82T7Q9yX4Q6qmRkr1ZZsBW8obt2-s3jRb8k_VQHeTspjPjAg-pUJ9YPWTDs34lzNgJMqEVF2HbNba82G9cfTNSUVwqgynqXnh2GqZRxYg6Dld7yjG6LuIF4J2I47I-iQmEQcvFAGt78PdiFpPbSG-Z32adGMuOrN7YW47HQNJWEH3vL1Fh6V9TuJ5rwknWmeF-V4QQX4McHzcIN8Veud2liTDkYn9iRrsgGkaXQfXMTJPBtVknc3xLtxkZV-qMqRypYqK6D37rtOXSUzfcJcsLxs5W6UpGnGiRDAcnDaeKxEY6J4PlsZG3HfvMzIj1o3uZOOy7ptsl6hgl743bwn4kV_CZBBHwa4Kj_c6Z-Xo9Qj60vbWcXr55mvv8SdmaqWMliCPcR889CHRnOaLaeR7eVEAoha78IHyaNtmgm5dxlew9vNOGGsHNsI25DxOWfk140uz6FYHNj3JYSK7EPMwGh7qLQX5fz2DM4opPzxlDcwCOW9L51UuTiEvAdXrBJ3vaq8v35zsBxDx5BsL_-DyzUiqLp41c2iWVEb_DGhXKHnHyh6F4ubIWDLKXbKpDKyM-OdE5owrF6sb3Z4ZOyMMhPEyxS_FUxKVdGW7PTfyZZn0s1CyHuoSWOCHwhD-KgCs6ihnehPn0asnzzawjThp_tK-prNxRUbs8KbaHQ5XldP7-QwQgz7CZ0r2nw0ZQzKH82DvW46qP8TV5hkNs9IYFXgOWFwxzj8Kmk7Iy5h0VOgPEfQBy5V-pSQ0aMR_aK1pT7I1CPGVAMK6kDqJf2gEqqohMcRSJRup4hMlnZMJldQKk-JT6wYqEHD41wKe9l8thrBLI6OL4Y9iopq9adebYF8hyHRNMfi2xUniNl927n4IDPuybtxqPaNxssgRMD-rmhKLgdNhHjC0gV7e1CJ9EkZNA4Fx7btFCEG-A7L1SqHxSvw1tIUyNEIvbar6GhyTQ0_DkiJCneCtJci_WQIFB5a9LlcLkMryAguh01di8RsEcgHC448-krQWJBv1NwIf37s9FqSQE4UGbdN1pQD1IB5r6khEejknw9H9yPfTHwUEA4h-EF64DImvrV7NWBq9tr1uvk_t2NJKrPUwnsa6MyRgOsfghXFKd1-xOzXqMIivgqn7-a0KDLC_YZ17TPehERcPO7y6gAn7Ffbis3hyNq3G1tm4jRJzVGuRMDqzVjWTnZcJNkOtzI0yRlDPsolKQvX1Le6hEOGX-fpnHjhBIxfeQjv4AUEpHtL6iffRfR8caTuv6KmO28APRITSVRjr2GX898GVdBD1xmCTHmA7_rtwj9HHG0CQRoZDRV5IenpMYlFblrrWe8Og-jzXeSDRtrGmt4MaxdPMDhNWnRjODk4nBILMwE-XvEE_hDHaVhGAGdBDiY_6uMTT1BYnh50GTo_QWo_zP5YS2NATlaLDqD2tBDIdUUR-YmTlnRJf-lLOd4LFodXn3p5iyOFHYJVtHtlZj0qdBNzfBG1kt0EN_JpQZW_TI7xN3LVuqpMn9HwCYqSNaltqv1E3DmBwyO6KI1hlNgfR2EfWJaqun45eKKvFtSWzXg4d1L3HYW2mMElqec3ZUVbowJ1Ew447ijCRT8wYzf5rjRo5vB6PsxgQB-XJB1PCkIGfSYHEjjZoZFvcPD1VV5-0Mjsv1I_VN5q9GDYV_VsrxKZNWV98enQvU-i6OPnhksvgb3bv6MDqDfOCfmb9JoRXq4nRTyVEpKppuz8wJnIwtdIz5N341HKBcOcUvsNrkSeUJoxzXNdyITca7YMf5LiBfkxj1uHVgeJMTo9hYSc7ZnEAucNU1Cpe9AA-ECAodMHhRMLWvMI4mUWM477UlnbxPoSgjmR0NOP---zl7VMaARuMrfM14tKZTQgPeTlj_eTBQ20fyzrURS66rhSRVGElHcTOQ2P41IH3OgGLyyGF-hXHh9i2hqy3EbrhdkxMzvMoOV1c_eqBg24R8RPbASONED8EqpmTxGYB9UF1n2W_eOIMyaQely-8kNqqFo7FZdAu30dEmfz87N4K84Rm5vfiN_ey5hjcbrm24EF7HPCVpPQ75BfvhgBCBn0PersqImXU6ivj0ePY2rZ5zUWIzrdJteKuC4m8v5XLr2regWwuraSPgRoH1Pl1_ktON8WfPKbF5J5Gy-ji6wmyM4k1AIVXiwbt9lMCqJcKPryRAeXNaTyUsXNXOw-MckoR5oZ12Sw0xrqn86Emb-QlOeHijoHKB3M4TCrIweV6ID9TtYQHeeIGyoLzByG-nBm_wqx606BUmqfyjWiFsCuIWngVkoABf_Xgu7fsF8mv2_8Uc1DglhW4ebEDfyncyFaFZCUEcK519fISrqzKRW_Ep2iLpIGQOs-5lz4OiuHJUv30JUFOmj5drhY3MAJmlYp5_3eMMJH44Y1A6qaL5HOkImXDdN6xdHiM27o30wzD5gI48_CQetzv0v1ob6DMlaXmrP1RCzXbsQHidIy51m-8Rezj89Qo6zu1tpleybzdVtYlBlBj1dBcSsqdnRngE7WXycevtXbx4xGIKXoxtwVAVi4FKmjcLs0gWF5Wbu3QZP8eut0XCLwPOJta7TxN4VDcZwoSelquAoEYiKypXhljWzqQAOS1DWatGg1Pt6xsYhPcnBoYgRAa1GKCdc2gzyzjuDco2Zvw9d_nhCELlGfGJgQsa3soksL3EDaX0CcJsgayvFvUJWDB2cr1gTbhf4VUkd1qpQg_n87gCdTiBV829FyS83RsIh-vl1a7xSQYYTH4HJQ_KH9L9vfiaESRhIFoDwI_of6qaCoxniksP2r0nq8fEouvrzXtSSzrQbrByJx3z_YA9kiFLoryClYXsrAkuLtHKR-fK0iwNaPxpP2jXA2IEKhR-vMwe44cwhD89P-2TdsyBwQE9kKXS3H3HHREuKc7lAW0C8gZg5sb-kP1aiI6mLw9T4DfdQtZXHBgjs76BmhFdFtPmTzet3aJE_d--E9ZxG4RE1A6ZYHTtgEBzjwjGcaeGSjRplFBvstHPPIF8odIW3ZH5GaHFHM_0UHlr6iqF0CDo5CKVp7bO-FYwz9xQlD2Y9aTsobSmheuPB__nZRAHtg66q8KnUQC-AFpBtwuD4rO-Figf95zK6lFEMP-6Qt6v8NqnwxZZFsJXGIg6NewWQr9Mf1eyrubgrnw_28IKLorvwPy1m-JcDhhgFmchQZ21bwajAvOLwCqq4p_q7eZHF-S4F1AAB3cSMtBHwDUDIzj0A4FMVV4PgZVods4PL5r7_LON6QVbK3NCYsG8KiI6F1Ufp1QL8jXJx6fHDGWDCqo48L8OfI7yqx3LbfqJoOYbZSbfDykLAjolY-A-96sHKrOSdQgWJv-liuCrbwcZJaBCgJw8EbPRSvQsBfW2fXZtkw6I-6QsuN1mZnG97NWP74KrCu3NiU7Xdlqvv59NIAbirQMeMjLZ1HakZIQR9PPRxTsxwxP_7CoeWukGs05nNOZ6WMX-cyAhR8sLEY6ZwqtYEdTyGPVBbOjVEKqgSp42_2lf9pYFy4LciZI59H07M3zGG8m45g1l8de9UVNrelsH_8hPQIGIrEHvv4r8JaO7bvXs9PqpY34OnNqRgNb3HT44oVhzjBMDoppiWF4bcJ1_fw6PYuqe2pdFt4SxcyBsx3HZ_6IWE84mVyIOO9WT7GmhiiOlQcErp-tcBXt3Nh3_np8Kts-Uwmn0oRwG8eIBnhe-oBJAj6c674g6fzdvuE7QWyxnH3YCQSdPYwwLaSMLyDFGv-9ePt5CJUhJvD1ZDO4rqdYV5CR_OTKHp58nijO-yFA4Zr0xkARkNhPlaxSwrMmj6iHcBS12E4YS_26qG8cUdkPWqmdh2dag_qrbHmkba243yl0GS4mb3hu44opThqOzJtXGtBK57DhUr7kgpK7NfwjiU7qPCyrVo9jcblWggPjBfVo6VwJqYrFXLWbX-NIGAdGbn5iQ_-rexekJzPDcNuX4mJwZo4sLuWv3-_XOUzmpSSO1uKxFlP0fICYeUuDFJDTyq4fanPRJQgZNrjrA88vjZa24goJqYPu5IuVZXYj8xeVMpbPbNBnS2DRbmXsIF0ytHUiQt7q0ZIgS5LdIeStccMP9TDehpzB3QybCZ9kgtCR7l-CasmC-WlBmo0D__82gyy80YHISR6_l49LE_XukiHGg0m4Zdf2NUg5zgaov9LuIpn39U5XwHekxOFXW7GWKOhRnAEMlvtROj0ZS9tSHtSAONH9Xeg6-xLEgRdLLY0njYxufPU-CBWhz5fiqTVr7Ifvl5E-HVZpj1xtwnT6Oq9DluQMxXvTSkBMKXjVm1RXs3uhehq5cSP27VpC-uQPKLHLHLM1-6m0EMwQ7ptUZjGhEiwdynwfsRQa0iUW7S7khfdAhqOCiIsPF7sReuhi1vM9gScBrryo7QP4Gqo5HGSER6ZSFu88bJrCqB3Xjb-KTtcRZJH96IqEC1XnQQGd24iqQCJjbU7ACpGkE45XohPueQ_mVy9Qtueh8RypoFeoUr-KmxVwjDTNaNS9kUHVRxgD5W7CqNDTASvn0WbsE-ouJwe4362ZjosJb6HV381oaLB6ckDIfTmvtQ1dFtCWaOy1ANd6EVIz1-gg0FF0qWVjF3wLz9YOv5rlT-ypSsTCS6VImA75cKi_Su03Kgg-CXSsVvAcW9U4LI7ThG83PFWEl_O9Ck0Z5xyQ9OH6HKx1N_9XU__RCePMCdsBizZBLssM9J5d_cKJ7M0mUI9LZmIIvquAoRYEu1DIi_gSKg6x8ds2twPdF0Mvg6YjFO4kIZRGbkZZZVxfPsTF6kWfaTOp6pD58HG4V4uHy5VsJlczE_KhFZ6YJql4qAlQbRoZT4QXdT9jPzER39UXE91HDCZsA6tVSdPZkLdLF-G33MmEOp_6aZBFIVW84wtOGJASljksVyIV3y1zjlaG3ZlHiuy7_5EYY2yTnVZ6I7_8e4qyk7pVlRP0GfARLfBAUDTrQeW7Govsgwy-8TyhWGd9Hr0z3YX_OxPgmqMkJcV2s4JjykP5ZgwKOWEI2G8KyQB3bZXMa5lv8afh8vPb3gnxbWH9tcJESFuWzwP2DVpCrMmmUZ6esbDKFEbD2JGYtoFWq7-dhJzexUVK228mHs6-WdsGtAshdpb8CrQFxxEybU7P07b8OrhPn6v38kgmay8fOq-lNwfTKf2xH-8NgrxSwhWZxWIKK14jcUIkXcl5_2nm46CPNDVInQAiQAUAfiPuNU-R5v0h_CDKe9s6rr383LEU7DuVn9tbdV3BA6y_-RWr3V180pgSwrbrlOTW7uyiNmAqeq-dLoPxf74C14toPSOF-aCrfdgIaHDE-QuY_r_ZpKQP0qp7vyt-6IIiPF_-TyWgc0VvcvNA_M90E71E7UiLrlXPbg_Hy6sspWXfS7eBmdfrejbn_oKrPttwlHQTSI_P0n7oVSnrC-cM5SRdEV9UDiopvMXhRs6gFKCaw_qV9D4JsBPORcSenEPt2fWK_6rnVQuzM6TnORZFr8SRYIYuTmbaQ4euOdoFBAvGHqcbdACmlRe58DOpf9Mn0XIf3QDgI2PyA6hOTaBv72f63gj0oehZA7rrSh9RGlaHEO1578TWROEAEidDZcfGtCJxCczIQl-7kj8W3HsVyu4pv-nliE7ArnkPhk6pqQR-crqMDxwN99sA1PrdOFpS8xkHn_s19Rp08rjPM5S5AD306KLzFGym_RIgfu3DANuUAtHwmnkqcYHGohxItqn622Yuk5-ZHbXWHRXPXyn88JvrtG9FLFeDsNVIeiSbtk2mZft3Qro-6zuZX3nsPJ1Ni3ZIqdUjFRFsLYrJnZhrEJPSDCpyYtpuKEoOy6HKrzvVYJe0OgGe-t4I75BzY5FBI49eQGf_1ba8kNtTq9zMYqka_1SHxQl0AJBAIbbkC3-illzm_Nqoz7Ve48UF85zCasMKIhO8mNXOHqwkpGpUPrEpjOLkLgCzqBGt-ft0IamWzKSb8PFtgTu6w7HHA5GgOWXcXEPvohgLvT37Q33fK610Cgq08lbk-DCNn9g7NfbtoQ9LBq3MuHwjsmnZdQfaKwEk4z1CT_IinuSNe5iZ8JYLdDMcd_ckuzxAaedVsBcmeBfpVn-2Irw2GYI2Za8LxRvpugHZNJaVM8x-YWNmTNsElXjdUdaa4jcoApMkURbuFYo7pKhxMwxGp047ux2zLribEBQPbvyXsSqoSZD_WtcB4r943Iue95RziVfrgIILD_AvERwMQx1pjdRbJPT6VmY6NFLa9Hdj3SUvChVtmAl1_35fgf_S8GhoAv2IlpLw4xllVoZZ4NBFh-RMcKBhjOaN1e1BwDIHjSJWoQYER4Iokh9rkW9cGSe3CNkJPxFYcYg_xNGbBjMylaQJ5mlBUpCJYMIjkgkc0VRuQ8KH1EfLoiDg17bPiKJOF6cYbyaPTYvFsfFGzpe5tDjSuhpQUWH5Uw2zsz5p5z_DZJwCpnn-wOMrg_bDGTPkcU4wt-KPe2igSRPe0bDENxM6QZWUqKnAU-HxUudU2rFAdjNN5L9MRNnMc8GAdtvpPiDfClsdHfrfsQheC1mWgKDDjoEIqp6T0870q4NHPJ-gwuUTc2WtmGLnuT2HoE4pZK87BeoYmPOIpxtNOfH-opfANYUndtBOwK0z6kWtYUlZ-mjO7n_T3zSTVx0wVlR89y8JdEbijVo0kqJEGvg2eOWj9fkRm25N07I2N2if44YAZ8HEKDXR8gJlBv578NcW9qEq3FHRKkVY3A1-c3mpbK1dNse4G2V4vB5cEDOQBGyrHUw91faFXXbxLfxlBzrC9Sgi9ejzX3Ip5GBUxTRha0ypCy-3hIVhRJ8RbnWJLTeYeiEVV-ujJcK-Izi8Y2O519VCANsZELGGbYYY2TQukjDQrSk_JeP4FlCtO_3UWeAtIJp_IC9OzVKiHDVV4z_y6lr-mpTpln0qVA570MVQHpY1YYz-T14rGxw2C_kZxbnEGgckyYgLmVd0PmPlc4F673AB9arfOZiK8OT8r4Cxl43Uzqq714EC0XnG6iZziQAksQ4tNJfzaOhb_AQ-K-8Iv-v9V01BYvPALVl3-FxSq5xK8kvT-P9ahLsNcv8T-V-W6YivRVTltc44uCth5SUd_0Fu6jr7xwdj77fhNGvNmYxVq4olvTjC0WpHGEM3bFRdwdqQn8Hn6vwpadPz8dIXNEjEspDh2bMgD-asumZT_s0HhOtrklcZfdY2cmz_lw1ek3z2wkrZ5nQC6s3mryerFHHLG5GoEx_475YH6GJzM5l-CSVp5SU4fEYqHzufIhSvkDW-8-OIRn629RiDwCNypxY2Nj396xD_J6GPVLuWUb6dCg4cNvWe9Xw5mmSr5BT0aUGVyYZXItXPAmeDV4LIwWxckObOgOBlA9qcQ7Pyk-wPFukkgVGGtx_z8CLnHUKRtjhDHfD2XQjPAa6IjgZbBnALUHfVJhBItqWAbygBTzrMpFxbX6_z6z6lDKORWXr2l9QLOFJCCMfqMNZnA2funhr9gaoYUgfUF_EWtGysfe8_xIksvFtx2cdo1ky-HyqOZGSpcMRBpXgIYFPPD9ZEvJMZ5PCEptPA6lokMjMWLYnX1m3iNBoGJy3wKAkEFv5fEdckHzXmVthF1axKDreC6XnUmXUY1o7OFmkPPm1vZeOxOo9kvVo8tAvsnFC39bpC4Be9H-iWhGxSOv5tvI8L-SOXOtYOPa__ODbU53ocMTz2p_cnDnaqSUskAAvSFHgkHaNjRGHio4oBIMc_kmwbElP2RJ1bCyI_mByNKuZbk3D6GIAiWE2xX_r-2KSO05mh9kcjulp_FvUOMGTfAcK5qF6lrU5MXhhQtScVd1QEObc6XtKhN_1eYAQju1fy_NON5H-S0FVPSih0MRERZhXHZBTY-MIj4cvYz-o1aZ1hf6DLg9rL6gb56fp5VpPFfGLBHJOiAx_KWeQQWc0Dv47KWQA4l30HXuLiP5reLOc5kTtWs3NCl0Tcm6CxO7VdwH_z21TerDLBicIK96i4uGgwsSYDvkRIb2Rym1W5AKzrn8A1p4_5DCYFcj2LvVzC_KmkRjvvn9Co6a4__gYCYFIjGh4hT2ELp9-qUiC7D_E7jSzBndZ2tYf6oZ1D89xTgWzpZ5sjIH_qOirFlmI18ZXbxL8RCFP0TGe1GPJrv40RIU9cBEMOCy5HkywaOIpLgEIkySNPy63cnIWWr4kMOspwktPWHnRgXuCcRG5_MffNF_wr5z_suMeR49rau08MdG5ibMo-GJkAhOAQLzcDhWOf0q0aPRilt0VtaE9GXuCcXvULVYigM3vWtaEP_Z81pzMpENL648bo2_fqEzfveZ4i5It5Ey8_21uaKHwifuJPW7MorgykMoyBf0fqAc63YRkDIDJLQrNE1Bd_ngfgT6QpDS7zd668o68sjjPGG_nPr6b_0Bk_iMDpk9ITz1XGxr4yz_XXIm9O9brAAhnwfgCiwOpoVvIJNpbi3iqYJc2uGrRPPb49k4FJeqmq1sIL-bMPATFcEyPXuJvDL7ncbRdHT7q_OOqB9QYUOBkXPKo649dW2CFIyO_YdrspQbRx0K830fQa55V2hPaRREoSOpFMjluZqQPeV7fOxroTM_rxr9sHaYlmzuAmpLlr771JRRofJKG8TxG7h88BrK7HCyOQ-mM39YVfmzcluzF49-X7QTet41MbWDxcfpIFQB7ES29VBTSnrp1EHb4VUbjZ_aOIYeoWV5uEqYirseCFTy4PpqMdFV4AlzKC6__WgF39hoGDAK3qsiWphI8yUE9Pp1gDJaUkEKUMwpZE1qPIWplqIi7YAIT7V1kWFm6PfLD1wVDOJL0noTFIJD6wDngP_dN4bB_UbIUX-lygjl3wLc7weowSnmu7QuN459t-jlJuXyv7ENq0m4G2H4lyDvRX5ApIcfIXZp9M7EjmhBZaOcLHAZYq5S4nxuGhwjPUYOIiPTlAHxTHucFcaiJzzNrjiN1yeQtzN6-F-pNYU8KzKSQhhHz_O7fAA2Gngxez747jjtux6dokLcpykqwpIvk5E505ymYxUkM30HglsVJCVJiBcsyiXtZhmWakBixauXORB9xB_zN4coFFusWGX2i6vV1ebJvHapQGJpPBKkMtO_xDnDv968n07kggYyH0g2bO6kEwNf9J0ip3NY2WkORw68D5ZTyixTtstbYyB6H2UHojl1dLvTvSSwCE-nxxZAfFlbfyNjTVhhhGs9LJP2QPYQeuOjyrAk7Es87WSjyGZQpFkTVasR5A-MOQ86_xxN9yeNEFuye4kd_XuhX00ENjKM_NPM4WRBoPhmkUAPbT5paZzlHSDuE1v6_fjHg8qYPf3UhoMESmSXAcjPA_kZgdFWH38QC0poguxpnBmKIejRvdFQWj3CHKFvyjePgPWBdSDFUdmPdZkNws5q8wAiMUgT2YzW9y6mYiy3V59bv3FztPhqp4v8dbXiG_zR84pyL2aHWQ2jVB9CY-nktLIE6rPKoMBF257ul-Nl-DOKzOxcYSTHj7SVTYXb3o8LEuUcL9yOu0v_H8_1cL39iQjMB9U3NdjWx5dhXY-dQA6Tc9gr6npJlPbhScMYjCmFeWi667563nnjeSOdoVzRMhlvhOIRcXEqnpKox3KLhRO1Wdp5CT76PbkTFoBbmbVRrcG5H5fmrEITz7oNYctRikgvOcRE-K6ip_-hd6ch96KlNCkb3yB_PlRBlGGB8X2xvqRt86Yo8a1cWV9hff1k7KTnmOw-UGMqZLDM_MHnXe5DYiPFioEVUW8vC6bwItbN5EVAColBjOuh5K5ESyr3PxsKYxFywW3k5Awc4DFToIi0F6rrxG1Jqo8ZL2Z6DdWsgABsTeeEnIbcdxFbNzaIFT_2XxK8dRg2WnEGLIW6ug-emjNjJG8TIrslUhemhYnbJdwaD-k34LDr5_U_I9EbkQ43qIcvywQrG63A-4pBiA9vwP-uSfo77XyzLshp2U-OzzChsFBT-XCW3kp2RQxRhZpRJwe1EadomGQUcX6vGjDssM7AU3D0rAmvMVvV1vaBeth04fxptk8f7XtS99dAXruPBU6AL3vVuZ_oQxNwoWjbyTaxgVNQB0XcP2UIkphrjlLd-gVkloCWjM9GDXuvFswhZaX9FZ_4_IVp2oYS_fRVd4juv1vkgg6Uyu6Ksppv1tsJT9P7TVNSNKmEUOA--yTXfu1trRgoyQW9vhh78EIuNlXOo5SHouAD_aw9uWeO8X20-4JBVYw3B0MOeNaK97iJjUSLbDxcqfH3sf3yj-S_oeuY7b8sDvLQIJxLe9Ji77MiBuawzB4gXf1PHKVnbHrm4Y0s1yNN8eLDbrix4b_EBCRAWVzC2M0-xq5q-V2_a1V9UVieNTqjqwpugu9WyK8vGC-EnAJkkGvX1AZ7nwFXCtga9K8VdHuthgWOHB2tIXL8-G5uqFQY-c1W2Dhdwzvhe5S-303OAaI-QQrQm1fk2BocpYFGVMx6U92jOpb33QpquYbESxmE95JoDNiAwYt2b11HoqLZAaEF47G2XJW4_J_aC6mECkgckh6mP3c7HZGPjjytCLaKDOV30AETmxbmxcqnk6e6UxSq-rAd5JB6SbfwnCX9ADYSL9bg3ojqxJzZKvopgUZ1H05AgS6h24oLQwWx-e3fddPmLAUH61i0VycE93q4TWBunvjeKaKbSqcxt-XJeLPfeSZqtbPQKnTcpFqiGfGOxhUe-2eTWMjzVJxtKWR8iSx0o4Xkgz1MpJH7ogPRqZUN9R19Z0mbfuTJAd8VJ8IQNDl_EKhY2mfSBCDThpVAbKs_duwfZGHD0ivtgEbdWtVLvhr_GeXyuit5XnxsMoReB7iYS1gOBABPQYreqCZq--DzXBmzlq5fkiIDKGwxSnV8SQgragNlLvJfJVwIamWOnqv4lIVIR1g83jk6fjwathZvVLOAn-FAr4aDl0n1-TSwG4x8fj-QmK4sYjPGRg9vF0iBAhHsemywrvxcn2MBff6NkOecBaf-DPBIE6Bn6oPp1Q78eU50E5uss8EyIOQ_njxP_IGmeeLxRbgZTLpz5Gle-QNb4BolAyUaXDSfoA86uJxgSrAPPTKQvOwiq1ZpA5hLOUz3zfMXiZa5K082QdB_E86eUBXY84cSB_Wkef8HG7sPs5vM3qUBVU7CwkRC_8HbrJrBFxwy7qkdBduIqjnM7VjxCuksVY701DxRRBp1yAL3C2kw1GzJGVu3A66k8nM1D0hccOFCFKkfVqwx54gkXuBMaRZqdcLXJiaqiI0CYt2wN-gUSqtymfWv7fIxRQsH7veiQ0gpRuurH1lWBROIfoxToAmnGPpp7JNqzw6w-WEcKoMKQX4NJjasD8KTwLFNUclDLYMyhUTS4DW9uZ6X4vxI5ClnP3qp53TRb9NXYsacFWTXorQZT4gCuQT6F1avaS_lZ5laaT3J0Am9cGd-91GiUgRZFGHjsLG8YolQoMSO7roshK1LeYHXyVYgxZCd65Y-oIENMPGGDCx1tB1UuC-Rve-1S2wYESE2FYPXpWoLm1RwYHP6r2iMWL8tvEFH1tCC-U8NIcYYBhtgQ-gGR2cXl99gCcr57_2BczW7NVJBuolXtnuB-GbW4TYWLcM8p_2h_vy8A7qchLonjxGqUI5uiSpdlm3Xsfg7SoM4KD0FdDCi_tL_Z7ddggYcVxBjl5wWJsqoM1oPlxZPV9m-MpYxOkr9ME2IgtDirhGzC-9UL0dbMj_jnrsgMR7wiJCJLnL8zNyLNu7BQvpODaoNDQ99PKkwJrdXuXM9INb4-VxTgdZJ_DuvEdc-rVRvy5ZSsui6DSO-DSu4EbNwFpeKnGOcN-OQ_NBrIFa5eypFnsNRssDQk1Kwp28uZsK1rCkYZ8sIs2jgjr7z9T68XwmFXKjgJT5VTXFPUyCchRws2NQ2Ae3VY7Q1xSbuCtMHu74py1E9LK_V4uhmMuUqHXGnz5YGFc6SypXy02qTpz7au_RLx-DHgdqcAbSCGABHYQlQYnI1zQRUKGpro_SlEDjt07Im_B5WBA5A58wyFeQEg3Yw4zHCwsQdUW65rGZCJgfIs1JnaDKDBh-5q9_J8dcAYzW0XbjHWYO3lT4yt5S6K4Zag3TtZhNtcfNPOiiuvSfOaDZUX72jbnRxiobg6spb2773UXS4cCO6uWsg5KZkJuZ8Dp-7tC6htAtifCCFTiF3OiMFCQIidZ6k8PKs2Q2Uen7WkCNUVxJqSW2K1yj3GEJ1kC8yIOCbCRG3Dp37qPkF-BthavQvZzsrxxrx_qEz_ny_DJxzzNQZ5mZb5KTdwxeqHLmf2oKqwHcEijE_23clmo4sEjmsaFy0W60XfcFfGRueteoXYZduK5O7RnTAnBWkQISclxUBdlUcSPo-NLNfcVlyVGw3AlBzkGXqXF155eMSOtwlXHnetn0gNJ9fuZC0VIAR07S_n1IEqweItzrQuJC28cuxhEQYSmw551ewmeneHwztHow6h-N37YjtGI6KwsFJv9D8VsfLd1DjXt91U78gBIecjxuVB7sMPVetPCzPKEoRScvSXC1CYTr75K5fiEvTddQUMTKp--St1YDc4UE3JKAz_bG7VrSNYl-szMsNylCraGqg57bdcUjD8OMzYeJpXAzRm3PezKfky1vgHYO5stFNFdts1UZ4o9pN33KLzVHbZaurz5i0C5BsJLpM6iyIzQyVs94uCpA0rXWeIxbvBOfkg17N1kpQ7xTfGuEJD4vPSjDuvwM-t-K9S-CSlpmTyJDMfHcTcz-nPEwI0WfnF4efOAPRDne4dBrzoWg_9HhCGW1BZDqKiySf3O51hWenWxWCCk85O8zRtTIu6S77yHSWuXUYZEBhUQdwaj4oyvxNfgi0-WCcfSqw18rrqAI2-LJsOgkU-B-0hq4Cj3-k45DYavTkEr2SsKE6djbcM1Fg9Qrx0QlmSHXe-KrP-taN-jYuf2LUH6y-aXP7Xu_RBztVK_l9y0-FA6ltjoTe3yunRtiuGOc5bPdhoNv1oAym_5ez_oIsNynhHZJgVcjkuB7OeBCxil9vUOwIaE0B7kiKRrNKBXZmjrYetj6KUwwHwDBoV8qh_LPckhEYeQEOjpptU0cuo5SuXwhYeiewze20HeKUEivY-wVCIRanWIl1SkKF0reXQnQpLdPUFbTe6D4ekUvMHqYCtO4tfqoFBTQnK-gTjWsvHS_3_6IUWXME7-fSNVH8SHf3KB6mBMYvTm1QI3FLQkHphquPyDFjbTI1bhAHAEaSgaLLydGUjelSvyiZmFmvsJ3v3hWXklf7-rgZfc_Kf9T25LAqDmZmJPrEWVgIZGu9pH0jEAdNCdRWWO6afx8qME1cuiGfVKxA-z9h7beJHTO9uBDj8NCgU6NqGx-5LAUoJuA1c914kNoE0CWgx6neH52ntGuHwbERcCEghL10d5_ySDtJvsqf4IUz-QqLsTlToHKbnERBGfQcstObXpmHD3YqWd7zcFAKI3mTdl5m9_grvRDh8xpF6CkPYJoX5lmHjTGkYvDK0BdwdcDdsGylTae1bt3fcRXfQ9m1LEKhgocABlI-1zpfd7dJqnF94YTRcriHIf0FMRymGLPQtCZPD0EfVBGsmSVHiREThkBHbwM5Y96I-o8ix4fKDDFR5QrLJlE80hNrfRAlOydUdUprSxp2wrxWJsQ3zCj2rIP2q1wpfeCzj9yRNFAZFHMhFlvffVPhDKaMsRy2kGMpkKS7xNA-Oei0cgoG53HUULnA13hzCmhr6mzWm59USpiW95np2xX-wQmbGSypPn-vwOm5ezKqddq8jLm9fbCcObRIvyYM9_aRaZ_VYKYngb5mz8L6vc2Vr8zUw8asO-i6LlN9rqWXmeTVUfd3aQC7K6_y5lEQnFF3_yjIjh_RZsOazhZOv6MSD0gcpJ99ZsGp2wx-GjLaq7_KckrhnzoIfyG379XGX6vpAuuamBe-caBYQ5BfooGTL6e4rDViFHUG1X_0kuzXsJbQiYn0j5XUm-1m8sEEW8WdFzqNXfmTujUOydrVkAK-fr_rTjnUxnPrNX7wHU5-BceH1KW6GRkjLEir9aUBACiBacx6k6yfwkl9RsFiQp35LVUKpN_dN3MV3LmJsgtNTDmaej2to2zZQgJhQVYcvmFANarckiTaUsB_QRiJrU9NoWepRuwRkzO9gIchlyiNHkgB5F2EXDQvXAxqnyjfgaHi4p0WDnMXY-wPloJSZin31c-qF0Kme56Q43fpq-fFzPo1Nwjuv6raIxE9p508zcvzhPLq-bldZ-CDukKbco5A1uRWt-ULhCOU0nFCG1gTKVu1IUi2D5xwvJe0cnPKh_qMVpWeo10xp5s_0b4M68eprB9QOfnwJt4pOUHjKgQEW89RHeMKNn7ThObKAlZPxfGFD3b1qVjPPJkh38nAKHhTsqF8F3qfPJzlf4rfvCbvcVpvN6gc-fzvMzuXU7ntgJ7U_aRw4a4XKc3DuGmf09Pzvk306DfxBjFWk6lgjCqVQ9qfx60uU1dpNP6_rwKAzNL3MLHJXXlrPH9_r4DDWRnaVL26c2fTB53Kz2e5cAHfuOk9SPeDcjnSC54X7r_ULPKVOaq5xbZWVcBoYBVH8fPevB9O2z8k8Ct6oGCCEDmMHOkyhCV6relH7lqDO_NI2teljnlrCxvwXQnp2w6v-De2etTBvpcmqolA_oWIu7QqDYXrthDyt8Tt0UDtIZESFAdKJpnT2dVrUYzIjndcJKjhaisKnBmMYdIw8QdnHiqZ51Y-hT6oEuDGo36EUysPxh5va4lgXG7lM9tHMb9jgopAI_8J-0cJOgiDeTPcXGDMNE-Gyc0o9_2DZULX5vCi57RqP-ItW4xDb0YR1RRUawlRdtDK-U-oXv0p7J5WQtTvgN3gaDrhhxuUBM94zSwGaC8bHa4JK2fjQssPDuh92_Ho4u4OKeM-9MyAFYFABpGqzbg5Yx9hwEijROeF1BAKVNghkLcfEHnxyNadSpB-N5obd2rFm8TVUImygyS3dCKLkmFzQi3srpleIEzCyVhesXamBsmCzz5cL8zeHZxrld95BkcqfAI6cff7G_xmJW8eNBOLoBobD9pBsxt9GSr2MquawQGnqwXOb87ItSk2Z_lyQVL-4WdxL7zOywPbPz6C2qv-QV0HbwL6EToxBnRigw0lwZ4eXJ8EtUUyeabjq5OjYFaGKCOr4aItPpqwb1jYmZ3kF0RSwgDrnnquf0WJN8lZk2H3lNkQC8soJ3h5gede8P6hl02-T8eUfay9A2PKQ3FyXA6Os7UnCUQq22S7TSCVkEkdVmULkok93hx8c4QHfkBYPqss0dDPMRYl1yQpDmuvH9MGekdPVLqsZovZhnw_AFch3-24ESgY61CwGEklUMMcJHv1Cz-7zCr9kRKbbTl2AR03--mA1UoS384B8QL80gw50KxF7n-Tsfikxe_qYV05KwU6rkBFtM1nRBPWzMqO_mA08Aul2S9TiiLKU50lnKhGh9rv5B6duSWFcseGzbk278nhRClCBDAwpJLVvb0VuJ7uZ10haUSR01gYt-2HBD-JIVtYTznHAAdcnPqY6VLE2W0ZOG1K6kyIYK8eISrBiPF1pDQ_6XNX_lnq3ZJ2WvGu-Nljlbtygbzl_5sxxf0n0ieTisy_gPGB4xnafvKIR9cQ_ItKxAzK-4BikB-ArSrMUiwT5Sy2Td1xjTJHhH2JH8Qh69y9S5xK4Wt__eUGM23dYfCMoozKyC_EKBCUkn8mPkKx3Pg36Nn06iO93yhUOg-T8pgwhH_3Xg8eSaYiEygLlmqWFnGJ9nOd3HWBy3AzYGqinKcLaBpTe_d9WXJZSqvRbcR44IaUaknlqaVsS6kp_MlnZMn2G24bnLM7bo2UosmGAIsoWZWpO80tW8vVWJriHTSSylENW9RN4kSmFhJI_T0h8yWErZtMNuKOcBvuQ6vQLo5agqiknuZcBfTfntw6KOe-fU5d79aDxAaatsO3EA00Zd-OFjj1DW6_3LzMHo0FSh8cgj9Emy5d6gHWuIsnG50xTdCApm46QcN3sg-FHZWbxuwaGA_l08vmOIuo8VloT24Qd89IUNDtREwTpTKCqztzNjuqfTrzi4MwP-CXp_UsCF96OJG4IHjd2Nk94zixEM595sBCunE2EA6fgdDz9omptu45kimmdzXkoo_gLh4gaioYyXdthyCCLtoZR7gC9sdwD9b-ixJv3X98ml9-FsW5KlKxs61HS_CipF911Y-olh5gv_pgpbz7Syx2oe8IG25OTRTiEMiNpNKRNbG5drGY7ykjN-lydlxf8stAdR6QewpsbbeJ3SZ6to5jaIpnK0dQbx4tmDWIKuddnQRO8yaSLCuOpRb3olpAbqxnnClFpog8ar8vGJErR7dB9gpIdHen3744HtXYbyam-MS69piWoql7v3PZXgWL7R_ugCcz2XI13TenuupH12RA2oDwD7b77ncbVzNIm_Xpi4YB909XjQYNoaGvhGJtGwUWO7HxoMSkjoQma2-Tvhq4AuoAx94Nreel6xLehSutOOcV7GTlPRJEOeRT4bGGLUhGaDcj5JTENNW2_rdQXBnTSpQGnwUJrqCuW9UDWTHdk_B6HB1qbeBByaBIAJ6xiPBrYhG9D9N8yPGT5UEA9eCygTe5P20n39DJw-JbwDfvk-BmipFZHOwRiAe-04UD2BZNUayObuZa5GLIt7cS_FJSY-_ITKcMAZeTjtOQbULoi9oaAiAoHSG0Ctj9_u9d1OkMzKrDimFHiJsg6362CSqAkbXIOXPKdN1_1bAdsOH6e-4Zp0kgWy2X8kZTyFyKE-BvpZRrqaH_NSyf9ctYNEqFlrVqmvlNVOiKOn1TdaVfy-QFCQ56NEeLhQl2k2iucxupGStMC8l7Len6hwXYvCm8BlQSzNt7PB9KvZCITXa-xQtrO0wv0P0oWuSGA6HbS8Qbi6UFZcO6XuULIP7z3TRZZpa8Qj8mMU2CgRFA3X_5NW-PttHC5JJbjdqmKpVkcbQcoCL9ggCuuz-Zi42eOas8A8UfjUAUpufF9t-h1cT_8-1Zc8f7axJE1bfiRIDq0CWwfQx8dW-5qjUZs80Bk--OVZHPV6xHGRQO2KCYkr0FmjsJ6qnCI7vAZV9Bn8OqDYYHCG0lXIESCN6fcHc1_ZxFVYEUd9unLZiKQ4zkTUeFMZUNxP6ttZ_YyC2uarElZYUIpRjNxwFSfRvNfei57SN99BzkNgqm9lwcdipEoidfe8PdrySaaVlDCEpR4OIuIyyJUALgR4Qnjok0Hy2xsVs-WLvG0od13Mjb9Ui578HWxSnoLk1Y-uaB-VLud663CJywk3r-iAsylRNN_Eq3DNG2j9vnX7c4ankbqDIgQmhHxIkUpSxKldAhOxr0niaiZsW4LIk-RtMJ-_vthdwq3pktt2hPdinAqFtyIhwfqc-kFZlT07PY72wXXOnXoI-uy23LsuXfyKMWqgKUqGMr0ZvzAdmHZTEgMjOilCIM1knSdbuI4Nmnlm3NbdH6hCFsinZWj20QdfBk-JB94zczTsR2oB6WpTeHneP9x8CmiJSws0uu4Gpfq-mxwXlXMTRWaVy-OX7VJQAbnh8ynntPnTcxiDtp-bYBioqAQAO_fejloAtzm4uaVtr4FFTZg43NgJYLzTNTewaCxELQ_f7tTMA5v3kYuCavaptFLWpfrnetDC8SoGZrfZSjtUNpd4aVz1SlW-8sRHHisjrEHkwjyaJk6kgb5cE2_3GFuhW5P7qS4SyyXo2y-jmzdtTJqneQ3VYhVEtLJ-FpIZPsGP0FvIHQJ3RfDJ7NAtU2IB8ApRn3pzKi4Mk1H2kF2ohYEMw86Ixu9SEqd4HUkE1rMnJvFATsSLN7FWXZbhkK1pbppQZHiUguTKcF-7luhIBddNEM3rhMj7sUOGK2zfMDsdqTCkwz6tavjFaxgQfqKn0TsYGW1T0Y5reVR4hdewbKUbsJngrv5sH7gRQX7jSvOiFfxP0gOZbrlIHtiuzFSHUgeUlVWbbkN0cIWS7krHgxTg5WTwDjA6xKn9A4QUBB677u5OA-faNHgogRr9NdAfI6xwxYpU_BlWh8c6Yqrch97OkAVt3zdt1C2J1Bb0fhRnGuzXO6Vit_UBE3wL87kyNhMhkWt-DIfSoHTene3PTKued0DauCJPnXwIOKhhNv9UOK839nMq_yGsr8tXvHKgj5-U8O-JmlDNOwZL3bRwtzSHdUYgEugOmF-gBkrvydcFs0XGEA-H5lpVqWPIuOv0DBHwkv_YOBy_RAVeIY4PZjwZ_1IOhXBv4NxgQAcBGkGPLiMHGiHVSK9p96hmnyw28pdVZK4veuH655P8G_0HBURyG1qsSUdlE9wmGSRpBQaps-v6IBWJZNfLtAZ5eydPm7Zk_cNWkhf8guEYtUB9uElD2lTAiJcmtUY5VNDzwgmFRedWr_JyLzsHLnJeJHgVKAKf67sXNu8vvZ5bNMTBInrGy9WDxRnicbA7e6dP79twTOPHFcLvkc6Y4ZwTaLqXaI4Qe3jXQ-7EFSCiUYdT_UF5xKAtTlrkDsNSOtI4t_FyZzg1Um3Gp1LAVB2XZD4SWjL2C4lzSxWGKOiRENil3tqv3psZoAdYNwa5rpicbCQHVD-QgdgzjwmMKT6CBgNztM_kvx7hXCNAoa9lM6mEMKSFX-O0ErBzBGBh-0vgnwrcXxyndneYBbs1RHIvszI9NX40Cq-A8HT1I6kmPuakkysSkbIUmzBXKA_7XyEJBSV2V-Xp6FDLFvtKgM1bjkPDifCoOrx3dZW4NHS3eKm258N_kbou45xwUiOu9UOaf-L7YzRfyQzavn7lk0YVGOAEZwHYN2F6GEWZYi6M-nCF-IA3km_UA3C_JpmNr5BP7VCT1BqlLFwVOs7uscYZ2UkAvvKXfjdJ3sd9CCefyX_HmC6cOMhfJ63Z4qkIDj_C9Ft7mXrhQ20sSfKwaqu4TKWxGvIKY7rQlRWS1LvY0iw8emlB7dRBbq3bNwIH9Tf-SWfAajMwmWQAuRixtFPnPzB4lRu6ExlKM7fPi8R_7gu7947f9xbAZ5siuMK2W4hFATzUv1vgxNTpUP6vm6UHMuq0KF5H72M2mdTr4LBaEB-biVRuMTHCHe9LDgXXYtMj-b_0N6rdu01ZT3QtYij4_T7tOiV-B3R3ws8Bmv5NSaGIcSkyQ07_A0CWTGu1NIZelrlDdHNgAaW0JDU9N-konyPaApRDXttgExuGlS6AxWLCYJV5mubqE9x1TarvXpH-cMNafLSeY4ugtfZy7M8ySxTNAeOQwtuEGupM84gyBCSUI2MgS1kA-Ef71mxEU8KhWMDwPI7Z2PyVx19Ou6JC1ewB41ZPZu6SnAo9xHjbNoU5cO0yY2dIWPBzCc1r9iHSzf8gwmkPwY2MKBwrGv706RTI2ztZCyBRGPJIPhKqoLJdt8aQ1RcosPu0jGO1-d59jeKMDL34IImvhhvNjqcZkNBxzv-b_AZIMMHWRZgSyU5yuvCwifI97ShtX__EaNuncT7rc-reFxarlkfYg4rYvW7bD2v_JwFPMfv5X3A8V3iof5IQGhRSZref_rSkNxh_C3xWD1Gx3FIwAaIF0BRmHxC8OtghtIzrsNP8mBiYy6UUHoQVDHtFxuvBXsZAqfDK7ceucXC0za3I3NO61_JV2YWPa0hD3fnHZJ9Lepa-Ji7ZkGjbFGn8UpD5BNwYP6yn23MyehZOQKCd6vGCgNir1yHnm0wffcKt7niVSTWDxMCo0zuNAo4kKKUDFN1v1K94LRY5WYzt-Nkcmv3VPiZFvqmNhahNCt_1ZNTdkVpWD81vAqxNWHCrs8N5prjwQPic7H4YTS2BOapH7wY-qumeGUXidCgXzxrzvXAy-HlGv17vT_TG93G3nh18_1fG_7mGm43oskmsB48RRZ9ywBkQ2N9p3miYw_pm1eYbUmqDSLBCXTjcohUi4-e0l0ct9KEm07ZpdkLenmNGD5tsiWco0fgWC4Nc7JgAMlj1p21eD1WH9_q4xhB-Wdcaj0teGC8DW9KI8UahgEgjUpKSdetuMdFyEkpNdhmmsFcNFjbOLYMp-aR5mMjviKxTd3d7n_mpycv81_ZQcadHh25pXwKAXRIkzTesryxZs8Eq3S4oct2SdsXfLnMmwpZWv5R5dyGDPtdUYSOKjVA2IVJdKW_VRq_VNXMGIvs8rdZfg50HFZlCpP_R7rXXFdLxsl0UL0ePU9YbPe4_y6ruGf_eXFgzh0Osd9Mk-suSz0qAz-_4SU2B5YgLJ9rBI3hcfDcnXi_fUOeHEEP7fUTXDS-axjrvSsRHc9yn-Tyq3a3pk3kzBaFqvcVvz9C99z822T4tYdDuspBy3hHFaYM1e5gcWJNeoRwyGLr_g3W-qkZ0-5xcE5ppILAtrZePaNLynIpLh1DHR6FqVFr76izURSbR0RhZgSj4k_ZkcR0PVw8MJ58p7bWXLkO7IeTdHfC_c_81qYLzN7AUIdxB79DKrg1l9tGpL6-JFGlLbUTT2DA_7cAyVsMdJCb1ibe1JVeiTf53VWg5H1sT9vxmvLl-57u7oCGHAYEtftaMH8jvcQMVKKmDXLgLUN8AUNJNNGJE18LNgGKnEaOIRK9Xlunk_LSElu7xLqHH-r-W-t41-kuyoNFhHjOo-jUM7bG0_0N98gfLgMhDAOAMm5fwoY_0fYUEH8TiqKxql3zqIA-UUOOdxTq-RTslIKnwUif5XPJdBMazVI2b_jr8TUndbKgN3TrPdhZjiIlRf35hYtJjR1GQYtGZTcrX_rRtlLTytn1JaLukQpQgK1Q16zQ4qcPqY4IKE0NCPgnCP45S7mZuQNfMY3oaQHgw2nkdRrDOqIQhYB4-Bw_OfGFv8OZ15kUtIvETkJRuXG1XJpFXh9F90KpjtjowSiXIEgu_oFmfYHjeSvACxPgkwmcA409BjwOx24Y2R3py504w6MY_-Ildc-99kj5rpbuH06Z7l9eu-zaWGU_3ihyqSw-YY2lF3IdkPsVrWdxDQO9MiilOSso2b0QwmQ4XdWB2Eu8BKuP7DPvVWuc3gyD3C6vU2I_QLpDytH7U4JYCfkHIRTpGu7b38TY5kWtLYutdWrKb3Jl6Fg9cQFij_k2MbDJa3doKHhsgA0HkoixQtMQ1sEL_WuC23XZOt8IFCJ8tB34IJIJj1X84CvBtbtlbW2Y9mywoQZ6SkScuhzcrZ1N3Rbu_SIVtT6WDBBBtvqNES15A88qVufMuPe_Y3Y7DKzeL2l9CP3LVOU0niprFvfSHJA6bPug1aJ3d1eIK5p0NalJcpNRskUCtvdwoF1LvuyVHDETP4x4-q3C1iZDHY2mSaIlcRGuqX00KCI_zInrFk_H8eRcXV4S7BD9Dqsd79N9-w-8ZRcWdc7sAqbZg78_m6G_zXNkt2uA137i7n8DbTZDcr2MIJL4o_IOKtWW8AWtuXSwYFxYtgdcoiJgpzoaQCkqJBGT4-9rNYgNJAiB26L2MTFKf-wOZmtjV5oqh1cZfIHfz6IWWB5dTdLnIb56HEmZoUIF_g3ISMOwihl6FXObkC-oFKwhZzhpx3NoU8pfJwr617md-cOQBN79yWeoe97aWYQGAt89I886wl2FKrVEOZV58Hhd6Ge8wsdLB_jT4jKIUqqoUPxME_tjpDOhGjDTwodzpzO2ZnpeEFWD0eMVJ8DuixQs9o8SCiJ_kqOKJtHwyBHPY79yTJwihGsgHHwAzJBKpsh4gOp2cIu3CqUy0qOl96QjL86UJZj3RTTj789pzMN8dg1YujGpAWj29Nt9F9DJgp50rdrzKdEcmo6JoqI7vxw1JYvrvLQ0oo-hCIH24NNF3AScwlJ-XIu3YxQyewdjNhkaBsPjj-AP9bClTk8WGlsKwTZbe1mtkTzufL3FWdZy6eaeN_g2qa_uhTYNL6okx2A4fYcn6QB8Khf6i7bO3NhiYiJFfyFgxrXaJUAqJFSOmc85WZipOMHufhSTsemjHwa-Em38C67rl_tq3SqwvQHxhtWIeMU174fdqjBD_lNcKOLc9rxOygolVrUJ3bjkcGQL0y2OwzzkzJlp8oMhsBGXPkNkf9TwFvHqCjRv1419M1tb8GSsp7dEg-Qdtxe8XLsZBnYqEEHXMu8Li92drhtNVpNgR_xs_wbhgawz4w5Q-fZLfDysfn0srd2yIZKYtj6-hhzD8YbdU8zOXPOegEjEdMp_-_KtadnMS9SgMT_KXHE_J_HPjXCUvuc2363xQOQJkFxpmRvnqPtfbIuogiwVMoLp3rG2qpMgl35Z2EfWjnxU-YUcQ1PQerJ-4glxxErDeMnZ2DJPpzwSTiZ8yfTnXROCqFJJNXjrEdioNCAsP0VBiZ7MpNbqvJVZ0opqQpOIEBQqjj3mQ4lrZTZVrALNo29JSfUN1DaE5k_DIIpbE6tcqwN7aPJu9VkYveaFciolPSSvEUmXuO5ZnQXEcbOhpf1dzA06o_GDhuzqudxwluc9svgu_IpMbglHIBjA6q360CXii4NucSmTc3kUiEQo4-3vPCCYWJKBoJxxAfKuEj6PA6tYZhDjdhh6mKHAQJULFNLu8N5PUlH14OV--MdWcVCHfIxMJ_QRaOwZKM8ric7sSeHFc_IDhx24mgpKZQqyoRTBr5pTTUM5a4x350DMd0ZR2sn7TIuWDJw8dmdcZ5TWsxzx-CNRoLE8yQHSCbkMT1P92hBmeV6eOqeoDhXHl9qTdkBahIrCmhTE0hb4C9sWhvyqK0mmWWr8-F8L7StNYhWTTYgP7FDqHOdmW9gnycn6wHY5WLufX3thBRzbCPfz2UbSf9tl6Px4qvMtY6D93-ARtSixK98P0eGX9FbrdIkoe5JsNE96CU3aeW9P2iO6TZm5FZimtHJRhe9k-1zfpWPoWeakq1F1enHJkKRCYBHir9TxQVsXKkAi-rJ8d1ngzOK4jxT-fPdDORLNNiKYWEC2iIVqPHNhNCQoE8X83wLmltR0wHBZbv64AOQOcMumFdXtViqUqseP1u_vREAIvdGuTI7-ptaNS1yVPSQasQ7Ax40LtdWpp4WzxTZPUDat317oaPOgm4y_Q_46iwIk4tffwbMbEHp82WUNRCayB_jG1khb31tlYqqfGJeRzsYjb1J5V0Md1HlN1E40PZaFKso5AQHuL3FkHnYYNJ7y9qos8QYQAzQq62UI5APbel_zbLeRoUxyTrCwa-xuDBNrCVtsSAOz_n52MKxxKdTUl9p4S_M-FdoozDZa9Jcbi6vEdrYfCYX42M863hhd8vp74N1f6qFoFFFF80aB7zwcjFgQYzHwjVAUObAx9TTfg18BPQTS02MHZJ2JpGrad2DrhdXJtvVkr8FM4BdfZ0Cutcwu_V8NyGEnIk7qkEH78naeXDmryPbSk04ePjGvJpwQUhkcm1dAsz8aBAStBY4sHhoxThMAy8FWi7YiNvXSUGA4wiUegXSHUQ9dzHZoFyQFvcvGOMVfrcEzid0vTQso5aqFQKfz1HzfUAgVCGLqvfBaEPRAwVyKTtCQ3VUw-NcMGfhEAdxsP3Dw7isRsCx_ybgx5dJScP0PJX0-EAndm6gwzkyB6LWwFE6mG-YacgvqqK33U_TrhxNjtCpFVChjRLXnDBLVdCGJtUTm_G41HY3pbznNngffK5QDO9Ojo-TizcM7p7JBqTcO2dwIBNBkOzHF6fSVPn7_ruJ6QtMB8CgPW5glBWbTnBo7JcDLRX4nPqfswfldJqAacB-7wtT2UHQPwpIbfrPEKv5WB8ZU-l8EYYW4Yd-p4X_YSP2MqLbTvp8hqyC8uIK-VUtPQliJF3T5RtScl9hNug_odxIpzlwTt-BjNCz-sh9gz6PJhGFYULmWkCuFK3hlnipo7Vb2U5e5Ksl1-wVT47BVSn0__EgYBy6olDGbC7c8ZJH9WuD2-UwNl3eLGm_IcjE-yQoy2tfv-1dghY3-cUJlCux6vdNh1wEJ0tZ7DQavxh38Lkupwag_Xo0ZiXizFQ-GO2XR_I8eMj4U6lb-6f8j7k0Qa-ORR2ihD-MOOUg1phCyTxMQFJUaXFFtT2jxBn3NK_Oo7EzcsJTlb24bMGGO95LF-OM7nhd88H5Ptqzk3Wvnj0l0wnJJNxaCxlyylUe4HM7EHy4WNFhxLKAur4emCiklsB8GSLCd3U4OK4m1c8EK5W800xFbet6ZERY8ch1_T-h2evixiyyTehhIlTWtTFWUWUzxlG5_x6sZUjsworFzZrJi4kC2O1ozQgl9O2A4Rjkm9752lyqTioHeQGgCWEH0Zbuu-vpUe8D1Qpsezog_wjHHr-YSIbdb189aB_0c5GtfZrOkC-yDdS3FBz6UQmKh1i63SAebpomymuznRJwsv-8UGMPr_XEX2D6WeVP3ijebA5OFlExtvj7sRpmPeTSsQWqH4rDuhtRG569gzgyrKNHY2ntpG9aKwdrtIpq5DLHTJiY_DK-hFRPLcU86UianzTcUu8-q3SHNgyTsQBtIQERscvc8sI5sdbeTswxLRU7m5mfa4qn3SQpApcK4JyHuak8gL8AGbBQdTW_2_Mwj3VGwWZBFzMDOwg5qQv8Cc0fEADqjdm_Of-JwQcwlOFs-g-j4NPY4ZE3dtukH3vPFro-HQcc_g2ph7bQDgK3ZfAUEvRf0qBL_V2tn24hDMw1jljiLAXR5wWE7YaCj9S97Pbn47Uu8auqLsN617uKvKxZ76qvKkdDhyNdJeQ2xTw1dd1aoS_97PcLp4aCwDkZm5TzpkOyaTi54VHCfbZEoUkh5_l2J8Nze6QiJgohTktxExhHwEz8qcdD61iU5pb4MrDaPd5tntaW0Otq52ng9vIG_EjcqvCX_kHQ3bhPmJeXAaneH4hU_qRVbFUUXSwvf5M3QTlM-fH-nK6KX5jniQaxM6qE8aXy59idqTCmcZYMZSZ_kogvCOWUpCqxAzGRViGPhZKTp_Nbjy5R7yyororcq8xd9ugB1AXHSjohhaXnZNiASFiM0MikzA8JuIcYFQaFLQkIIOaWBUIRRDjlO1DqlPpPAf2qWS-f7aT5iICDWeJtKxsYSPzJS8r-3McveKvccZwuVlbTT9db73UO0SKPtnUZROhP1nS69DROvbIpXylvEf4hoO1JyBuwCt_1CdbQ6iUfRqLZ-5wJlC5HeJg0FEKkTJe1jJ1l4cSvZNdlsWCg-ls1tRO9EkuVYMiM7G7Vwc7L1mYN0yrCpA18PBC0Uh5WN5J1KdDa-vR9CMryKduK7gMh-W7PF1fghp2XdMOVPmI-sMVmDUI1tKGX73c4c5yw5KAj0BXDNJVodlRvqjoVVRojcZgd8fmuZCPS6Ub4douflYnJ6LjbHXR6emUv3kWg2sqbYx--yXEl_105PpPfPcJxjQ3MqCbD3tYnVJGGRxC-eZO0e7qfg6wRW9PiQbkuGVsbgpd5jS9OnXdK5VPXZgurhMlSsCMUC2uj6LKth49hP5qBaMXoNX1uWJITsZbdTjcXuL6errjlWGgXuPxlpF-tiwXWiXkWmvtKvrtlV__x2OcCWB_1J3rgDm6jWko-p6NSCZztvsoRm3bEGaymSAz2KHwW4-zxwMbROPkSgf64H9B-lIqeoQJny52XLpilMoqba6dlIxlfr29E-oGck10r61gvaMB8wF73sVYVHlrZ8shOE2wMFxolHq1f0KRGkqAT7N7-LJ6QOJq1vJxrZSWKpvxVAMMBaojPD50LtO4BDZ_4Ftdqcpo9I3uUcexHwN1V1JS8e_dPf2J8qy7A7388m1JBihURMhN00Aw-ykoHN_gRwvP0ltruyfbz3BzqkapR3rMBdRgXrpjU6m2AwYr-fBHANymjqe8i0IE03ST7LENCgLtxJk4zUCnzCymfzt990cej5hrzApSWHPooVbl5pxM8TzlKbIYH4BIiy_FaF11vbZTek6fUh5_qICW4pMcjebzQgg5VB_8f4Pe_cZbHpDqODaelBgCXtQsTyluE8GzrymDbVjQr_M7dEHaHsp8bGJOKPIhNabzF2Fx4H7eZJIGt4FMfaulKxf2rUtnNNEm8jZNorAvT_Bs0xmeWc6eWrzOAW-FA2bKoNOJgAjYhTdOdlUZt-lH985uZJAlsMkXUu0b2mqFUFXlgUxCNWp4yUPlxq_L0woNPHWgYZW3nZiWsgjVsCj4tjAHdu-ZGo1xeNcQ4XKql-ErvKHrbsvEAd7DxXUn_41Nic5o0iHydccsMaNf2SD67j7ylJLhHCnmAiWtWEDpoeRYfx4ArepWvHlcOZGlmB5vIGhqIiLtkzG4_Vf1DUYGgrTuhzu99bSnqYLzhfwBDRuN7u3dfX3m1bxnwEz_5A1_jARKZEviX-BTvIwBvSZOEUOnhl0yvEeIHaVZ3iN7wEf-YQdxiqM_jXbYaAmQpFgPpGqmr-hsoFpr3iKcbCMNy2n35ds_ycYEpyWw59hwj5gEVXQmD5_7LyzOGsOlYgAPAIKP9ASi28yxivGzvnaX0q4bEqdL0e9jCti0M5zG4ZVEjWevgFDGfxJCmVIIavQqeSGTPQP7SM5YGI-9G1Ne6mRao9_4Ve-3RnAG2B0wbopjEounpciUelY_J0TOCIGNEh2eXNhAXgkkgX3eU-oEE_82CzG6n9-Tb7FucU6spC13SVgrLZe3ByOF_s8SU9PEv3LO-6OmpLPZij6b51_A-vqQnX8wQ0NCH103Qg7R8rOGo7YvZwkm8EcuMpZIGQqKN2RlMie26plFCwPOBGzEKekWra4XkAwJqp2Dd5qhEDnCCK0imZDFeYf_qprgW-chjW0-iceCF0mFFlLkfYrfQQ5bOemWaqHJSwSto7lF-VZ3bBHngCj2kfLjxdfiWUZrqnrObXGC1TTuy8pO5rbapJtXNbmQB0TyTZOOWpGDmLO5_vgb3WI4hBaZAEc5nbSeHf25-fJT0QfEVQsvvu4-5CsmuKtjH5Z--LnzK41Bk9gOf-AeVup3DczoWI4LtIsfmoEsXCCD3bbcDkxvykWJ0af1X2ghEYIi-T3Bux5ZW0yJM5NGQlL_v3nD9xZQ_VWX4P8Pfzz4aqgwZ-I_jqyGMMeJ7IDaN2zgPsH_CO-p5V4Fui8wwSBWu9nagsIXFtalww0fSHyc0gHrV18EK14P6VVRJO339ws0yomc4j2-_K_s4bRcbnFRhxCXqwIpS99bnRUDjXAyat5xASLhKBsaHqUCOXBO-iW7nEMiLsZpWNOABWhwE-4HHseJqKLlvaHhHSeRQp77qm1A3EUfB4hI-2mD1fff4d_GOTU2fKXGbSwdfB8UBrHB9bTd_2xQv0Rv-Z-8yxnvaamx1qogDDBQjagxz0l3eUtjT2CUg0qWW8BIGI-3bArjJwUoroKhshgwhinSEq7PqG3uKGY8lWBhubUkD8yujFKEV1NWHWG4aoDoNiXKvaCPro92UHan4Sc4E3BwNdAfSp0TaZFo9BM2b010HPA6PQMZS__VTdMRZvQhW2B9eaYhDSjMh9tZ-l3a-gqQFXrIKtL0d_ipRgn15qZEdRmRu5Tcj3q5Ls-zzArhjkj2J66XskfaR-XrJM0KX1gMHsroxLHQfv2St9vKqr6FGuNFHQouXPLbOI9ED71-RjUX-x6Ntvucz_OKACTlt86gFT7bH1baaLW-h580NZUm2QoMl8RferABUh96jbw35O782dVR-EG48Wj8A2flkE4tQX-onsGdfC41tdhNFh0bO6ltJUPNre2e5XIgYLfKY2OlJtRFbMbXOhcum53qkLFBt4BYQPIJ8I2oM9RPntDimezN7hfDkiaHL0bIF2ZvQxvXqBUZpZO6545nK0M1fZZsQgCqKH718XmxU8hXa5TKKGlytYuOBquiNM7DKWTTpi2wGMC1nO-HPJrDJN8fz8bKVjuGysSKbmZga_uozh-82h1l2Wh_Up67wPhesQMAzelmfUUJ1gpyqiRZfcO2Qncwg5eg8CmbB2xj1SeSrl_uvJxhIUbjjlkZzi85AoE_qG_zHsvYpx3TzN_sGCSmyLWk8UnWs7gioLJama89nO2rBpvn-5AqLKComj5jrnSmQ5E5jWpQR2GATY0QrauSvrApRovs8LGdPyOZNwXaKQAwFEzqx2c6Ad26VWzkSkdG9dyNQur3yYYfy_qybAswUALNX9kjmUVFPwC8b-iOvjNP6x2ckC1mcYmPqOBmvEkphMuYrI8yCsjchmpdYySqUrQ9wDw2roEtTGkxVkJrDgKb6naAJbO1NkLIM9-wdauyxtbRUaDBdznQgzYcyNggHlhLho8pBkZsqVhjzbO8GYvFKrJTp5iZIxB5YXUtefTjWt7YOgxXFBbFK09LnHRRPIM0xDngb5R3ccLTHE1OWqpVIw58Jtn8gutxT0C3Jdo9I4T6YRwzdB-08vH6c14q9mdccmbYngYeUmFF3K9dqFgKxGJgN4YiXGrLJxUtpMFFrnRDRQbRRQSAK1D-ZgfWlCe9giFlMNYaqU-jMaC5T4vIL5NLFCByBuN6Gcb9Wy8QLOzL7DS94d4BXURcFb2xz39znchCPXfE9TVKJAV2v047b56AJ1U52rnwcLc6hd0hDfI26uw46q-CFqmg4_foVXgcAGTstXgfW-soOY9h9wlTg6lqpAD2l0Pj3pi-7wbI5-33ClJUuwADworKwpx4lF987WBkZogc5nUy_HsAL8FglsZ76lIMx9Kz3FD-w9-mkMtsSZ1vQWQ1_yNEckcc5krk85g1uk2Evh0Hmu59zluKsIiRcqTAd09vNxcRKUpAkFk6GBQSRV2CK_1vlDnY8qW-mIVQ3nADz_HgKsAlpq1WsG4C_zN7uoyCrJ6lMrcfjHoSHGRqxNyA5Y7VjfkLjOLwQIOSZ4eVhsajI10T-xkDc9DZQ9ClnUClakxAVQSBdHVHlDt6lCpfGEFmKtwmCmu3o8HBTv_xkgFJAyA4wmu7JTTTqkbLfnoE_OIe4ZdXC5_FOUuSQApPHBZj4azd3oDIgkyrMqX9BhW8Dwgsduyzq1uBQH1Pm71e6EXDnaEk9TqYg-_Q6oNkmFtHcg3hwoIWJ0bjZ4yQo1CHbjmIQ2S5bRyBPoLZLAjdVy7grYpnuVRvcFoHp8JGdI5l_z1hSxqYpi-k7ZzOJzzR9cw8F_UBB65fCtyLCM6mGE3_hUgXb1CgztB2rsPAt4pKTJ5mHGmNBQP9AZF0PL9Ccnezt2FJcT2KhIqx_jRMLhtb6wqW1nlXyRHHDrl_OX-AZBMDA4Zm8oBvTmfXUE32ByFqJLPom_F8zjFPJ6yTDMUTzwANJVVdISKZU_w5Z8t5DBJTnusZz9ELQG1NUYjQhy0Ltaiw3Py26tTrvBnIdjJgnH10LOoPTGV7txwkXgfDSiZGzXvScD24oLlcP51GvdgfH6mvGroPwyLL9gLMVyph53OkzgDzSW4TiBIqj84ie7u299Zr5-8XBwS0E4QscBQk5kytn5cfl_EEpL6CFvJ4906VSR0sWF3WH0QPzsOPSu-9FvHmmc7lbo5HHv4ewKQedZxsTokstsbJ_rBagjPvtwKLESvqiVIPt4ZA6K8W9G8qQfNbtQVcR0aDKbEhoPVJ5pneeTbE0R97zaKjFvoJClZZi6j0GN0BgV-rGfJL2BMmcN4VgEi6bmJf_h8x-xZt0Aomqj0m26ILm3FdGlVoUo6S4fbiyVKAtzU3NKzgtGkiDf2EoGfvoZuhO2HW6EiIAXlkMXqAwPIVXTb2qivdLGe4SS_aR0SWje99daPUB0A6wW7N4_XxRMXm6opW5UA6t8WVmYDUBnB9C2_oVps2tenanwHqJhO7QIX701p-vDzy0tlcq7oIjU4lvKre85md_Gm4hw8lr4MwJfqHsy7uKQT8kVPt5suiodkBvdsGGIHFMtjSJIvGsiRrgQr8bElnzdXD0m5RfSg8Nhy-TzmiMjmE5tqAV18jnFYFtMGQgE4vVVzW3hTKIe5NPq7bhN_Rq0zKTOmTOMaQflB7VaByb0fCpjzI3foI_gWZJ2KDuSXKEce8FJm7GQ3QzPftH2itZILiU5j8_w0xkaQN4uu67pxBa06HM1JjA4GH3NNb33opTrUNE1Rs0JnWr0FKRwsppUFryRJV1q-acsxBz-i9i97ArC-gJ16K13Tl8hIB6Xgq0mZryP4W6-EhhtCioLeIy9sibd8w8co_3His3oLOYAJOKMEmXstLv_5cVSbPNyp7JZ0UxbvJJA77hbs81wHR_WhEP_eL0ReJN34W78kjxCdl0uGN4rasI1Eb5xsi71CS4Ri3tKJlNcjyb3CzdCl3tEQGxeoWafJvBBrazYHoc6qrAE9iuUb283gnkGQh88LdpoMlGSLLsjsZKi95U1Mi14JT5tDsZnKSmhxbifq1XPZuxSsGf-vjyxMLNQIhYvqSnREqbDz6sLrxU05DXl-jHkwEPfUDdPJhvs-FCgMJ5uizx6Po7C1IsOjqDw4LAqH5zMRUAPe_hXBs7ocZ3A6DdPkRwdtVYdJG7rtCsGDr5rLrOopHVUJhsnNnM1frHQSxp2-T7hoESJ4cR4g-KkctmcQj8AFmpYqt2FkAxvnYKP95_OVcKC5hCWTg38R0GiEuPTSyYeAQnVGRXsgetmmzXPgSfPIN1G9UdCo5NAzMh4okl2TfHKB2VRhl30Bi0yTHoqGjAJpdane8891Fe1id8m5KjkoOrUPrlbkJmAFsQUrKeSWKCZT0Dksg9wBP46Jzi3W6uioy9P0qDjM_CKQMRN2IDk9NoAfDkvCLixHfcQFkh9SNtL_CrXdHpZ-z75guX_TNQFiL-Ix0kTf5Le87Tr5WI2MpX2OJCCSJju2Loj93g-Zt5VEfb4CQ6sgaVHHpBkCvHYJ_Qw6TDyqZwIJ4GIIAGETpcq4O6WMAGYXS72g2qs71bnoDpolh5i9SF1aaCToXw-7HuAIvuzV3845ywpO4ZCV1lAXbMgfIzSnCytJJ_18IVKEN3ENAGovjTf1IbaUJZO0uWkoiF5CxDKEzmg7f1SA5-QD1HzxeyIG0de6DSpcgjQO3b6fi_i8uvew_ZiNTjOsQRbRBYsazx_yPE6fIrijXZbmZSOwUVWgu8tTJ_rnsgbRgpb8YLzZ1KbLFI8I6G-6o-9TtJjg2dkE1LCV9YKGeKoueGgWeWmWim8l9zuZD9sDirXuMWU8wUtec5KS934SpjbAW5pCTOV8LZHRY-J-gE7i7lv5ZByvAgJc0JH-lygeL5kKlQIB5E2ULYLsd75VG1lSCtG-wbYfimc8dHD03cHvDz1hoHsVhiPpdCmMVUS6ebL2eQ2i4dfbRK9qHEiqiNBCWXOpkrikL2IFdgMnFS4mKwqxbOmRhtW-I7iC2RLg1_cYni4U4p_fuKegMce6au-Rop3EzVe6IpOb3tXpjx7UVnxEp38F0P1Ij27FmfDgu6v5jFxFoeOYtgA8ZC3tLz5KibxVANHU0zVnB5bUL2Rf0QRs6530n_oMAsPCkzwNxsQiiTozyM6SgzRQft1ptkpK0tlnGqR1Bj1Kb_Zib4xiabrA9loxP60vajw4yl5lD4OyjFgUCOLQ-v-RdJoaZ7QPwE937hag5m--AhMTEMPVN4vti5VEpDWoXXo7sAM9ZAec6xBLptR6w92erhLLN6-eJRXrxgN_bRpqoeyTVYIgmvDsY0rovd4U4ou5c4hUYVWObGznGReSQ9znD6fONGBE7c91XjOZRionDoA0SXyqsSd3ky9QXbyJ8lRTSnhpFEIWdUZdDFrmLmLnr5ChOjR1dO1NZq9YGPAf9V7to-At-A9LwHtE64XlpvhcdbG3Bwo4-Je1HKBQARQSBeQcUAg3yMSP8B2Qy39xyVLpIb-3a2oe0Kxb50OnSH3mTxvFw6PlBKa4Xi7FT-n3vaI3-6ZgnWJzIJSug5esOZkEwAy5l2ZRo6eTEfiglPN-TFNQNsYLv1S3mPxEkioPLbCNY1ssm1Zq0ZkUU04ZtB4nnfUyzzr-OP2Cd7INhthsynwPFkX9sTz8Ep1yMW3E395qfkvLn-t25ePDsQMUCkTmex9O2xZsiETy2PP4Sj2ZzEdkE2eIrK330ZjIBEBW-Xvw4O_7j65-RC64LDTyP-kY6Mf4fjZdqiuj5fQAyfH-eRbOPQ_Bs1go1eQzuK2V_N5XeBNx8Igyuf0tlqwFTOfjYAWEBanyMamVzqxa8pXe_yjWzadHW-7Jq_xWGuE9Icm7LTQFFwDvLRz0fMtFVUSeW5jKZBZpSi3Lj8m194SV1bVnQ2eHLWoOz6WxiJ8x_2u7UzeMVZ528Isc53V35IuSM_wXZbuRPcIVne09yGqzpCddDmGt5t3YRE0WXamPpZJMjN6TodcJWDYGjfkG48Y3_gjP8uB3yUXkjW-0_FcHamgWq4X2cHIkW4qbQxog0uzVQ2sKvBds2QkwCCvUU2aQQdxxfbiZYFzLv_ZBtFUChexQdVr74ZBhcz0MHr3wlThYgW1QF8RYQD3fDor_jntx5XMVtOZC7RfyzMqiZIixQCKjkLJQqYQSfaXAXKBSo29HUt8DuqTSYjwRMujNutHnbOdis-62a3Vlh_-Lhxmm3uN0mOWemmYhGodEw4HX8vdWKLcYLKmIkUXXeIj-uRZoCaIcqI5YQL7HzMq3CEBhv3PradwLZRhLJUSH4j3cC9CuuB3uD-vPHCuRC9WeJIdqK4cpu3C-qbJRXCWsLyH4m1FBIdqA9a_5N5JrtqmMf2npkOomzQM6AZLEkLfULBXK7x34sBkvr8-9oVB-MOK6OwuKRTUHl-IdedJWLzwTHHdNJlOEzIyJUH2eVTwioiiIzNgiBY3M6SeLUwY0KuMqxkybfI2s_4OCSiHLgjgA0Bo73E88JINWtyanB0JtP4KphaupFdJXMTpY_-kB5LA9rgSAqkNjhxaq4h44BlGG04q3AeF7Pjr6ftzuU4-_v848haaRTSlk0iFFRfuzaxawW7zCr_x3qDXokxxRBqO3aFPF1gz-xwHtHKOHjpJ_nC0F9d651Q-8u_lsflWilUInaaJPlkaRBh064QkLn5X7rGnh9KBFwkVISWvW9Rd60pX4gGgdn6LHDxsmRMMF543JrAYGUQaZIX9KxmTUiMfxZdqEO8MmTDpboiAYTVU5MWHMU-VqGY7ABXOTuYu8uqvurbjHfu2H9WGX8niC4ETxDgwuIOmWHmXhsNe5nnx6A8Ig56A3IPKajZkjUFDptiSUMQU8A6l8hR3v3Ltf8SInKbNTcnE9-lhd8yRakaz7lMJmis86V5lLkvtN0CAs_GpIjuIdRigdLTGckNs-DYYwK_k-qdbGEQ6h9lIxzsepFIYA3kybLDyAPzTRRltyvw2ZS9ne6rG_JeFv1_fr-kQHJ5Zfq1-gCuoB-gf-YV2bkOHDs6pd9SVbrpTwGCt7dKXNs4oj7aweMxejTE-NmzTvrHOeyzDap68dxgWRCEvXdlTMehhfXlP2IS9qrKrid9KQSVign7lRHEQ1TxyA0l5CjVNUAqeZ3AfMGevb7HArVBeMNK3WSkOLKvLS1dptEmyPa_BMYgTiDpbuMETdGgSIcGPdz_UTdc2SPXhvzDLVOc4bN0vQxI-8MI26qqa46Rx0qaxVBJP3-2pwd7H0lGhZ23KCiwskfLRypqbHKaB20Ah75dsa9Z7Ru9a4jkCeEn0qhghs2-KWShF6bhAlbN2tfQ7T03WXrUQTz9KSefPqeGCWLqnvV32rQbI56dn4OP6zYdJ125kUC8C7RHTKm6OPAW00WTr6pQKxrMm75iUJJsmfPuqsRLCJ8Z6o1JL8Dwjq6DXBp1AnGhVkMQNFcmUYCnBZdqMNbvcNaqmlOuqkPmIjgJctw0cIaKZnK9TnLIh8d7eB3oof8-k0DjWKJjU1d6gUMBp0v5P1PFCcBWenjqyofddGg97i9z2Gq2mA1IJY30PXi4qt1LMDfXRUujM4mNMgrjFnbr7MRuX-FpvNiPtssKTHqrvorPk0MfikKK1Tn0e8NHQhfsywWDuc9KZlifAvg_5cAV3s_PFZeDL3_rz5cPhs9qjXTMQp-mRjj9jS6l-sD2j1Ob2vP5q51FMqwXxrjSLAnT4wlED3Lbq6KJ5IRYJcQVK61Axf2SC59tXJBtNm-Xe9jqoX_JrvMB7fwaL_PhNu57AIRzn4b-goiJjyUziZbYbrBwRWIv8ZEz7BmOs27RZ_1fGKtQQX-CN62KQzjIgyPA_tKyRZwK73XoCjO5jAScZCx9k8LyE4os499jDB0IrYG8HprAXGe23MQ0E9a9tPHj2K-EEyZ6x4I3XbGysAC5gdUCK7JilgPnswv0ExXXVBElORRdoFbZhXTxCZ8iuYrJGFwXkM60Tmyn_QtxSgDgODJN_5ggQr66kPLHIDO2BHD5PAh6cnVCjG06aYUOZ2BRRAbT7gRBtP1kq6XKmsDHAM9J06f70Ndr2v8G9t20hlqdxFX9Svrs3yKfOGVkGU-I_C_JBO6qearpB4acfCtLro68L7PxSWgqWse33Yjj53IzDPKmNBk65OmbwiCGVmYVdt88j5XcyLRB9WlprVILa6BoWu_GATtmrojHE2ZtwKCbhQ-DjWCyl8Q6RRap-zC1FMhfb7GMG1ErMUDTbigRpLM2tRn5rgV7EWuERUAhzsYJB1A7zT3BPl2FAH5zy7gfUO0JVY2r8nJr7rva_N-fgvBa2rvAa-8VAJanfys9teVv9MrQR83MvEgEAjsf7q8hvWGz1th65HscppJH-haEJVo9nPTX2IkvaXCvl1XnRPlHUcmTxgRQ4JucWvGTuT-SQxvKOadl19YYPnHXgeLK6c9BWNMGKm_2aymBgZQ-I2gyAsjPLixnmhreWSJxb1RxrnnWYh2Rp7wadXtSe4cVu9L3nfP21ivt9SsCftTEAstvvnL-PGmXml-FDsYprysLjKxdSIHvsGtv_0pKWpKk-GmSnb8SJY2Le2yZI1w_FKR0jdUnxNPihM4CDaZndtgrMwjmTdhK12eHmgeS9IwOOq4NtwERlqV6zmQUU7GX9gOBg-sF0T-vpoW_bl-dN3rmSfyeD_9WB9OQnS4WLt77zA2sNqtoX5rIwoCXYOjItWFo9JEVMO5OVyf0EKvnu2SL792z8ms_drP5wxe7cl_mVRW7G-WQM8I0GBhoe1DTwzXVP1VzlHOHnxA_4b5NdqLQsEaE3Mu0wfH57mpLIfMJ6x4-kxsuOuXFWZfsWwpQ6hEMmSD0J33rB1knTSCsw3uD1jZN93GSGVxVeTkosWIUVooxF3QM3jiwtCOji788f0FroMNYUCFgXzy6ZZVcz33MITcj0hYurR-wfdhY2wALQD6P4KREshSrP4betQ4iw9JAy9S18ZFTwZDt8Bc5FzYY0vDBrbE0z7weKSQxLRAFUq4BQ2vP7Bl-Z6-qon5U36-AiISNtxK8Aenjpudx3cB2dSBRAp9sSiy9Yh93cXY-zwJIg823Yq_GPzdjyYBxl1VJWwmClOhk6bBfeeDve8-kPq6QM3Zdi-sLYUWwFy1gX-8lr3sqtwGZ9w1s32dIw6C7gBnnJT0azPMLaEL2Is556qbzar-k14EyGSLkHfTns_GcPwD30Y9RklgShXbqpIj7aDsJMz6_8Ag9Mjq8I-TNPyDIOKP7gtisohs9WvmK14Y7Z8j1CRf5Qcuq7nICrQveGSBfkSSAG3N8edlj63staviMWru-AVcG1dwJ9EgRS2xsRbjLvgc3X8fmqTrECc8BOQwZFJnRnC9fUaMRaTzI29MRW2-itXMxX12odCh1jFPeJCoiBhFGDC66KE7laWAqbziQQyTNvr0xCCesvf-Wo4nFBQXs2sXTYCow9oeUupyQ9Pcy0FHGYuqJQZLkdhY-H8LL3SHSXRvp_yp3vkUYSZsn-7SEijd3geiYvEpRzwkgDc9DT_0e0Zk2rhx0rPXE_KNyIcruUI0gCfaNVvo5V1c3_AVL6Q2bW1jWCtjoG5_dyRGol4pqkHw0d14CkET0SyrH_d9jlGQl76lbulsRaBwDDWHY7_smUyP-bSlbrfJey72aRRRcWWv778CilDH_Ubd30c1bCajSVzY8mlEF-JZhPdnz-my9wv12wWbkMLPMVbZPGQY6Nrt6mLngtra1i19sSX6N2sqp61-poFdKBuwLvAg974imwQzFxeOFeAJD_M3lW_C45oFXnItvTPgxMW29O71Qre0pl7ZZEWE9YFS1hhA7007WQJVaSVcQZ_ZBO849KeM3MCi47L79qAZKjx4a9OTGHd1nzOHA23uT9ziJvUQLkwanEuzRoqDCuZnGdbYc5tEqR2J2tIHMlOc35OOrKIYyxH87suacnz3HwC24LnetG0MeiXXQyxnq9GDj61eYIM3DGRnRQ0zRL3R9nos8KwZk7lqjtZB8EkMNw5MyUOAxvg4ZC0j12CfelUD-98xUkH8LKjpl1erWaP2CtgdvaOE3_9YeDlrS29mQGOQfJrXx1XQx2fvo0DtjS7wnBbucz5zps7YHrlsUIndfbOdGTYO8IWKDJE-5-4hwccybuMVS4hkc25X42MHP771Wx9grOGUZzJD0Bc-u_dufGs-DYf-lsFbSjJ6plCx5zHG_OZ_oK6XghjvB9x0rVPzd6dvsso__pArE1eGjlnCcpUHmkg8FCbytMhUj0GEPpHMJhV68FEQ86_D5Lf2cBv_eDW4oxKz0MWAdAgkbMBVUgcFdw6Bk9ImT96hQci9BUli8wcrdmG98Rd7a1oyQIODpXs41aJAanLZcK1BYGfdMsfJsOBbzrtfHE0T7rgvzeQqxAaDN11bTa0g4QDvn_nw1vuyd9ncpBwlEzyeLNH9f4pugPIBsUr52QJz4YQmBHv69Sk_qcSma18Uc9ZnEAWeNjLe9on9ur-AToxGjDP9yCeBOUIIoEWzxBJVRt9yf2z61z5hEzkRS5z_4bga_DmFpa6eooxIqqaXKwyIXDusuE5-aFhfY-Pf5e5eiEktEc4UtoNSyIXgVhpw6v5nR4vZOzUCl_dyehQ5iLeBQKaDq-wx5lUg6yrzZeXUD8YZYoboT9sS4CySujMyDlIHZnWaZpV2obFx8i0M6g3ub-pA2igSZg8kFWFJqOAuAXfSo164AUyM-xdLKhLRzlj7OOYg2fvp9n5fEiKIDxTfLd_f7sU0YlaxHIYB49wMKzU3o8HKaYU9VX2t-ZV9r5LZyFiDCDdL-xJ7nbgq0s167G5DBsATvpfwI_O_gQgYUZvbNh5tteeVk8Yq2o8u692EdO7YYaQfZhHK45_LKYltx3BWSsoGMMcjXJT5puo93XQ7l1wZZBTrmnC7togRGymU9ckJcyCmL3oWnfHv938lzISdR8FxMTvvKZYoksyNcfDjVTuyIRLOTeZXjC8UMiACuEvIc94xfA5D-zKkJjdfPoSjuXOx3W-qfnWQWgePOSbZ-Km0w8RhqSRKJIKbK2K7jlT-M1TghBFpX8fOP2KLNAzaS7g7b1CmeLbudTvcULX6qjfTTew8ZoM6Y5PrRQtzkWDNAXWRTJQBJutntuiBgIVVxEVoLFGLCF17mrR_XUh6Pncc-sGukICxoiRlqOnQegKAPNaKSd-5sTVKy2T2rLFfI2oSJnqANa8sdZEkq_syFFEWTvHVPi0NAW7nbfUAwQNyKSlAkduLATKvSIKiMDsr4fMHW5pkZvx64Ocjdlgs8NXq2P5qDnbBaD0Hb86YlHBJ1_sWh-7TOXcmhHoKrhefKo9nZa7pM3C8PG5rZ6Gd0ECf0dUfpxL2Wcs_1xYki-rtTBzUcjEVzdjzlVNeVMNzZd1Hk0GvBGtospg054L9Fk1QtVDKZi5wPP8e1gnK-RxvCr8NbzG8ThJBQbyK72v1dcoDeSUDRzYMLHW98lTcMns0M8AZEd4QW-l6QDesdrXdDGJdy5fxMLUclK-DWdDricbGylwAL7zX0Bx6coqXaFXhjXShMmQolNcUjYPfegazisOwYsYjWdOSDhNdTR8w58tJZvwOCzyNZY8a8xcBKAeAl3khZttGhOyo7U9-kZ-HvVz2Dzl2m3fiMpvyCKxnk26jSxTcEIlBLt0FCa4io9u1Ytos24TFu2XxemkniwsZ5yDMdknblx3MdN006rna02x55524sCIo1R2hx5U7G99XCADbIZiFEnfG6vmlA4c6lbRUgNw914e_hdHYta3ubZ5jqIODTeypnpevfj8F01wa_9JO3YpMQrRAzZ-5Ii-_J8KjukJi1lih6EBhiDZL64Q8LsvbQZo7tHuxqtsXmMNIunOAPJS49cfziy_tBP76MH7rtbNHGLyJH8OA4IUqQTh0EEL6Hd98u8x_GTtRuvP4KW1XNN_un0yINVcwKUflFEjclwijxETEMdqbLLCFt8mRk1iHQ5qSwSDwISHMm_6e9qCIQ1Qt7Vze1V6HkbfsB9FHI5rq8UhA4UE62IrlcvYyZUwEKAB5FFM0XAnAhzEt_auG5UVOFdd6_wdbg_1Km0DZuYJ546TaXLIzWy5eKVvhoa213yjW6nBqUXUkluqTii24MawmgERNhmjMrDxiWeS4YYJip85dM78IQXoLCOaM90l-hVY9n3YLgjj5UqPiPikn5HWrUaedm1-08Cquyw3df7nZdJPAUyS5UCGW-H8wCkH5BjDY2HY7ZDpX8KtlQP1UENSHYLHIbNb46pA5MuR2PrDzmrihuIICF80i-gtRGN3Iq0uiDBck6zY5ho8yqE6fJrEsHxAs3CkKP8c7kFN_zvRSmfrmrTyA5QsK17kzQqgWN2seKH9MwXu6ttS0lqnUVVCThsOOOgLjC4KxUCc4vYqEoeO_f9KKjyr83NcfTPBJQ8_u8iX-dXbN3_d4GCJaMrCGpp2-VdW9LYOQOB4zdLzzTyoAubrD_BY8KUTWMbzmhymM9Dy-4INe2x86LJclnkK19WU--jbKajqhiCWvE-2nxmvAmKilDoLQXiVEZ5TWYvctOa69QuVMybXU9yEwsSmkiJFU7sAp1YyqHIV4u3Q7wuauA9M60siOQxu_P3nl-fIEaNQtfQI_TZYyvGJInV3PvlMtmi8YrQvYOflhEuWGifnVAXz1PaGaoRy76tce0Yd9_k8KXuXW5pXqXy4Nqmgbh7OUNN9XIls6URwiitBApebQe05oGs5HdrGb0kDmSPDC7vn0m30QmYzsjRmmSJv4OzHUoSB1MsMx4oGe7Hr3BqLnyVrmIOoQqCqCLSAM2fHN73mMkq3T7aqYEEGcupKP7Ryx492sSWlHJJJsV11k933D4792FlBaKcS1TAubYIpeNzsXrqNO_hWml-H2HY-Hrd_IbuBUze1asiMAueMVYiDdmm1Vwz5Iu6A_Z1VC2j3qxE5i2lkKIZHU3Qy3W9fKHJQcoj6JQoimQxZUMTd2rMmuUisiS7o-M94m72yPuaUn_bmaM5ZcLIjyLmGcQqWyMRoDVYnG5oE43AaACrEfK7dgQEtR6s1EgAFSA2GwxKbFpgYDMhQALrq0-qv26pDCaaFt9XaJKWi4dWwMrg3KOL8UwvOt-1qJa9PQ77XfeAcUs_VufmJ4HDyW1TFi0xy4wDvU3AsOUIrapmvXzYBCaPeayMNynq6QD_xbme_w5RMtnq25ywrUoDbul1wFQDjcWBwEmt3ELZZ1yu5gvPJXqHYxkqDGB8wMql1HiTDWJ6zNKgXLbOKL6ewTnaPFEI6SgzDsAHr8PqAPVjFKjoLt_SkL3nVMuLOULv8aVxeyLxFYKWpzKwgYTAoMNUMkPrLgjJbVAWdE-U73HCY8wT-fBU5jU-vSyeTMN5K55WnjgkNYq_CPFIYZfDJaCpCbzJ7URjWFElqMX8RagjEJRchyJJvSEgOoFfn9VSsJA39kmALMGYMNGLLzRMN9wf389MMQFhQ1knm5CdVcAeiBPDVn_TEx04Im6q8M0AO447rnjRUN9gqat6Q2HLAqplt3KPco078HD3wHH70cacMtk0ZCWC7fyEbjwl4gtchcf6RUE37zebSz8L5W1C6Nh1EFfFZDnG3O3b1Lcqo-qF-PR_nCgHXu0tLyNDd2jJdrHCYU9PhCgzjQcbUSjkQRu5uheUzg5YV9wXgLiLfGuPgKo-OCDg-Jc9x76yS4Y5V86Xs4Jv_IN2c0P93b80nAUV8hMvo_8PYoqa1b_0ZEX6iM1ETKB85BINhPAg6szdOw0Q8pLCCSnwbwxa3ucIrKW9YyZ2Y65ZybI2hDc_jnkceUFzauY8IFYjGx0hH2nacze7fADZSBHCYqx5qdDRXCHdxPLDMP3Z5h2qhzqtqdjV5Ho_gfVVfU501BoH_A1_1c8D1F-GYMtPuqnNBNBQG3zSTale_sVxBNABDKlukAzy2DaEwdcFBJ221hsdlr-StXgWBFDZuGniV9c53V9KfUwDt6RY7TQzU4wSR5QJ9SlXPH8TaTJECSl57vZxknlvrRVwFjJ5KLwGon6wo9Ez_ad4uYC5QDl7NkTQcaCiDYZ6D0s3nay_YJolQcMFDGklpiD1-poRQlOIzzSK6YUa4YIzKsm1UODKN1KU8brijEIk6545gexGdBD7qjyNp_iriklHz3nIEz5IJF_gx6QxkidgYC3z9WeYjATXQcN8SGwv9kkGnEiQBwC95s-WmCPiugu1RTY-OsOAhN2q6sLmIbAF2OlO3k7ouCsWBYZEyAus0BKHtB8B69873JyG_YVH-h0C6_scDXfJjPMtrhAYzs6-mirfAEyGe02z3yXjzGg6HTmxglDEiZGOfg0GYLzpslfyAVSo5aVm0NKkNqK2DQldxwu8UJvu5LjsTYyi6GU0myb1grE4NDgcHuO0hLbPSW_AlV4qXhVXe2XRHadabptGCj4Hohn6R58DK2ht061zt3C65n-SecWulNCy-Nx6qAi_YuIfcCeovKIkbyIEbZDgZkYGwettm84WSuxETn8vC-RFR90uqFhDA_5-gQfKvHZT8dGFFoZ8n7RWYMqtUedtEni8giqPij1iuTuqKul5vBHmH2oN_DZODJwRcr_TcZgBsxrIS8JsZU0AaIyuY-IuTeK5Z0m-6xDwS1VjXSQSL2hCCCwgWeAIXLbqAEyWkWMtWQTfnzuabuwgRiYgo1rY2nCY9N-9OjVQA4S65Kw_88L7x7mRAwWqoh7YnQQr9PvsQz8UJnB-Tv6HlO-8wsPOhztDIFyIh68fGIv6VXFJKEWGCpDsiZfna3c57HowtizjmGXK5lFB9VW06n9wrwuXlFlY3o-pfAsrLgxK8DpKlWCxPQJdgYMF28SLy5Cf8m2gfeN_ZOmwnyuLvcGc_HDvbPf14_nMJwZljjqVhgzXcFFdrQeGJhu2Jl9pISsTJISI4nXHg7TUvNY0B3FCtkrW3emZcW9J0-7MUWIWvkgujDqSndKejmTzTfv6V-Y4fLXl4IEejobuDlrvwiStcVjsJcgsV3cAKrpeRypmMDp6GkylmM3vtmNRwlnbki98viF3rdhXdEVeJbmJazxf9WrcxjPsLTh-QGnN_NTp8OjoIrsysW5nVfu9vH-FtHo9UzxDvxZNZg_eMD2EyKR-akfrXjGLJJPVASWZ1QUBh2p_tZfGAuej0322jjQo7cWJSsFwOESYE47QAvDq6q6kdSZseHGGGmHpb1-hG_m028jJZ9hCqn2VvUI2Y0_X6quQa-9gYAw_HisJeO7Ils-vYOVAM2rl-ke8FkJfq7ooHpkAZI6HEridCbEq4LpVCcVlKVDLyCtBZZ6f8ux_j7f0WePQ_5Qw9SBI7fFpd3Pkozgk14AujGXLSXl3_xh8lFY1TKuJcviuAklQCI5HQqXg8vkiSB65cvjYuN6DfD-e1Z6iy51-qhS6pqoHeLQA1xqC90qGPPiyqrhsbJpquQs6HfwWq0CTf6DYOd6e5sAxh4x2G8X4ttOpE_O9oqY0q6rBu9qPYeg2bAaxFtl6woVSwgFe-DO-UDa9gIV5iwrWbaOUVw5uDBQKlPtZLKH5lXTc4QGOo8pY8XsP7tCspD87R1Zfk8xh5ugiDa-93jH3ujhmPT6GYQiTDKJGq6sGtS_iX2BSQrfGIp5n8xnRFa8YahaMhq632oRDodIHS2uVQqI3JDJu-lNY3CjLEKbsRgL9wAHukqIsaheWmdnFWPs37whkaUKNGKTE0LfdQ3fUHH4KCvyf8UrUo-AS6YA0dE-nO0Sfw0EsrmwAttN4AmyAbkeRdfKdwv-3z99IszjetZoP4n9DfrzMjVsHUzDN0uHfwTrN2MmpfJMkKVhFY6YJFroQg-r5KxTyPXnxu0jCHqzXTQkDAwDq1b8F1QvmHzrLcXDErnPk0Lunl3jPDy3T3yiHVzk5TO_SmwrJXFTXDygbCJmR3t0yAX_ouJXh_9ZXgy8Q0jDfc3HhEgs0l7Fx8r_DaGKZZ_11XpXpWlSCU1ddvMuU3QUlk4ysGl0B7EevmiH5hG0rcpK0kOa2cgQdEAzoZC6VPSrDWG-SdQhIpmr43-21b31Avy97Memnpkw6uw74WHQYfNhAqfCk7sLJ32zxc-OveHRP0Ea0KaWqa7I5eyiUP50wVpamQyIJRxMQ_RvWmg4PHZmXilQK6ytvUFXkLC-ILL1uOqBybIzlw1Ewzm_3H00aSqacholjVLItvKyP_fPNj3spSWVyrmyqdiU2eSMZJNfc1Bh4ixrzwFein-WmFO-eyEHY0XVE3yFkmgoJMZlTVEWsMNgHxTYNGEglhgWJ53zaSCS5KNuqDvj11oauIBSgTy9PsvxTzPG4EGX7y3O9MSMai7n9rXmn2p-kekl8VF3YFLEYSC7DZrHln86SF7G6_a6tNP2adtNVQtYLP7LkV-0Lfhaf7f6Scf_5snUjFTHavytf_p3wxitCG3TIHHA3pkV5lP0iQlQ5R7wGDjo6bRagPpc4XhhSbBndQ02rhvoT381MmHGFB65-ggRJV1nHswC3X42arnQUjwO2HjI8lEuIKOYf1b99_g-MNn2fsDFLV8_we_s-1p3JrA2NtUfS7TQQ3GmSMN1tfdCekxpjdvEdcXjXiEVgqMnuaF7tHwNlNqUz-yhtBGwOPIiMmyIYexHOZg1bGXoHqpVF5TqEnUJHLM8ItSf5-xR7uR4yEFXkhomgV5vIgwN5qGP-DCU3oEMQdWDbPsCF4FMcULKuPsJiy4HeIPal3nyfurbPFnq_BIRburFlhkStac8Q2CEJeXRnfMdTNCkG7_Z0BIPXRg4ut8ZFMJjA-1XvOlbmTDO1rlOmEdbKxKRplJkq-Kjd2jjty7kHx5RMT5-3Al42oCF9uqHKfitueevmRut49eJzLP2PyPIJJsT3VQM5udsp2dopd0nShsrjq7UhFyXcuWBOLTsAqddgVxe8__wPmD6t1NcrXZLwVmx8_w3jwb7k-J45wuqbhdv2MNgvm4uvcWJvlk6t6PedRkB2EbGfwWkVwI9xaHVRAcVWSdYyjqLXR5x4_HnJ6HWqzLQeIp3Ss27L6PFTOKgqXI92ePp481b9ldkf1lMqg0lvaxF0vY7PS9Mve0qpf8VOOIq63EkCzBx7rf4pr4WerSBCNigavaWF2e8C2iPrayaJhwLdlZwhfGJqJgGKOEghF2xbmjOOubpRJYMZy3BHRjAKuB5X81dBja3CbblpO-dMOBvnzldjXsSGGC9T4BPDff5_t8FINGVqZ85QYJs07cUTwcaykAdQeh8jf_PiimWSJdjIsyJHbax4IvD6bRpTGFWvCB6sDZ-7UDkiF0OCiMoRIbhobWOyORvDcEK94Ye0H4ZjlXuZyf0lFaOVb8-YItRDu3ZRfNQo8ygcYDeGahI9UuaHctbN-G7Fu9sNR7Oym5zL5ZBz7jYV3zImQcOgO3aLp9Gij9LmcVr2aDv9EYlekFkbLhC-Y81K99p3_-ecsK56VLsmI8MBlxo_l_E27IqRy5s5-qDEzV7M-jOpWA1v1TtV43sLoYrYawo0UM_XDZ8nPgkA6kieEPRObhNgrKgCHMp6E3ZJugYra39vXd1YFCb1KjLvvhauM2YZs-Vb7gFDAXWbM1xiBEdWTFgzXDG7S6fzaV-uxiJqc8De3EZhoh8BQagj4HV6ddVkJVShR6PtPV9HCBbjioLEW-1n30Bd4n_V44BTfxaGtcjTxYIBBl5F9BdyU3wOuASQsNGZlXpgFPocpjn6EJ68RqFFHHSVMKMPCukF04pFdKkV-VPcgFijhYauEFYGFupLE3vmZXzGN1fVkUyJiirdqr1MNB3m93Vpyc2-UF7EWM0HY9C1kLJjGft0JgEqmFsST03oNRx_7HZ6mUJkm3cbFdkeZPwj91AournMETww-CWHQU6PtdxLIjdyXkt0lLoHHwmF8hXZOa1_scLRMxOnhUbK0Vqm4LO7AeZCkE8RE--72wwQQoAhnzoSG1lRSwZ70NHQQ2eGyJtEP-sxy5D5eYNCcdOEnm-lT0foHj0346pXaliorAXSRhOa2B0wc9OV7RakJwY7h-VY3cqSabdAHQvLFBhnEvpFZ_TL8VRzRgo_FhDly5S8MddWUnD7iMIQ7G6ERlwhuZry9UbLgZA4yRo2cC--zYU-LihB6hv3sli4EPBYU9ocVxcOIN3VOGmyaRTTWCHEbyOIDeagpzk-LEBi4dVPef6ox8YAud7YEiwHiOhi_BlMn3aVCDXEVs6vgdUfGgA8yhbAVk7CYTq43an3DwEb8LepAd_slrtD6wvcHdCsCN5nFYCGBbMwD2uKdtQBzZ9q_hy2k6pNDZ3dVpSBy24sO01iOv3WIYIL1LXickS3eyKxUaMEEzIF4G3BIpxj-iDd2vQ9Qvz8-ygYxVYnjZ2OLtDGIhMIwrGre9GqOSL_SedbEIHqwHS77wgM1y38i9uSTcFX1HSIPEPutj4sIpx_oMKqnBVsYPLMN0UyHzJhOjN-NUh8-xKMaGwCPYD6G4rsw-lG8o37QYPB4Os_c0rCsq6OPC1cibVEvQOU0_kHBtZOW9i9Cjk5dRMFuYnFZ6lrU2EdTAJvjFmztUOZIAALuuy3yS2dh_sL7mfoyY2cAnTF6mcCaFALeZIxu5X7TFCjWiBi9bhxbvqLsEIzTBJEVv2-0ISQ5Hw40wwmm8UT-NUggvgKsBjXzXtSD0lzYRQZUP8KNz0UQCj84sl5SNSnWjx8k-74XkfX-8WKTSSMZsRO5DJaLUYKN-XpIGWXULSMkB5eVLAcCIgHgTv5u6ndWM29_v6QlxtYw_g6le2Ljtdgp9XwvnSQKKCMAJB8aP4xTT-qusiQXqM4PuRlLpr87dhDp6fOFkYWLRTnz8BUz2dz5nwLqxOj7kLXwFYrfvvquasVNLPjELkWgoHQfQxspOu4AA_ycyVFk6PlPAcT14um6oD8wGavr-y6NzM5r5V7AjMHTLEPbFBR-oimSJr4tJy5Okw8wqOt0lBqSz_wjOV4gdkxquHDp2MjmS37d6TrEV1dYeHemVDMMFvqXz9zpMLj-aek3frGqKEqvETSoZU7wxFcsmUOM3_skRBIhdsLURo1UjUq-MuEOVVEMrSJhGBF4Earj6ckn_ukPRB0LRCkUJtIxtTcdKdVkC24l5j6YsMeBeCX7cYpT4omE-_YYe31P06z6XkE282WcfhM0D0xSUhTVte7JsdaoJ8WKN7Rt4u1rQxsMQQEHhZqqkCuIK3-jo5UvAWU2dXA7DKtXTOPG5eGRSz8Kcn1oMDWyld__etEY-ktHtAAVd7Td8W6BEKY286RaA3zup2AwLN124b-k667opHH09fpF0TLAznm9pND26n6f4wDTm4odUD2H8iqj5-1spV9S9t_v1i4hgXgB759vQYqbhcUlxRsQZesesMaz0jQIqbGI78wwHxcHfodl3BaZMJCWk2VdZP7SQ0xCn1CFpbTCHHSzQID_M3vzPAWSCC22IBphURVrMPk0xLT8_JqcFZ_hCfv4X3MScUlwDz-HP1ulvYzwoj8XsmcQIpxj-vjsVHcIfzwSqpKAb-Vc95ZrQxxxwV2XVmePQQ9zeAJ7kVMpm5_DPlzaiTGxBFL8BSfnU_uEvkQBE7BJgwtiNUsKY1kW2CAaUm8_6DKYysQ5bsUfpmwfQuG4iKv_ss0ewZzh8iMr_6NnVRwOozUH755hZGHyIgTlMkAuZ7bX4CrLrKrams0VaQaEaFL4_ZAZ7isznpfsKGDBKo7mP4yICkfwG4dpTkmhGQ-p34iDjdsRgw30foSyaYxBHjhVN1fZlJtpjnRJJ0tb5rWAnsEVWxDTFXXjndp-8lUSNKrUm-EGT2V-913VfBFCic81NT7hhlW3vU5gMRKz6x-INUxR4X1lfWDAa24ob4pq4WfINBKLnzDbjT423RvPFxqZ7bkpO0om5wkyUX9zJTrf-hHq_PSEid7CPOHQQuRzgJegx9DMl26EhgZ5sloz8eBmGTmpNUOxyQo2VFBqjxlNSofKS60ViEUC1WZ-cuvmnRsicqUkKmrfKjqWGbmADnKO7a1CqMyQGyvhFOR22xpDeHueXRDDig8zz1ZlPIkU5Rl1VGIVS24NzBPfxRpLvZw_sLn_2dr2XHNk1YZDbUiNkpFF4s2XAvZEHkbEs3K01u0QOCP4mrANr3lpW_GwglwURZeVzs6uIXJIlhHvnNai9e3DUbFf83kUqoQdjPAXk-lWhQGmsSgZ62vlBtYed7KKmzdPXAKp1ivCf6m0iyniGxuyVAwgukXEkkXO4E4Pem66aDTJVXeCG4VuO2F2evJ36PYsSkDG90OchaIbk0hg4ZlGvN2CIKj-Z9KwCOoxw0XPvcvDU1k_WiKecOk3kxSY_y3VxuQ4TjdG0JbrhDNin2Z7fiAOezHQiwqlBnKCA60SqLZ7g0BCR7_d0iNKJ1FG7D4jlAFQqydMj9QCphYy_FymfLYtSCNt1GDKZGZFtOJY-7SSdsb5E2w3JU-P_PJ0kIt69KERZPZS6BBrSBY4YldDABAB6ly_4rUb7zINZQZ2PPY3yKwt-6yUlHcpf6fy5LodQZTyznsXk3Uu_YemRQGKy8V7mwU-09JAOJXgPFRd2LNPEmZc6qtai-ezXXmHgdEBp-RYM22QDVFnnDg6t4ihV15jg99SRR9weNCgJFwAfYQR0wnwE-XPYvXGzDxfCvWlDKonwlQS8o6Fd8CPGt6P0ImR0teYdE6stniPS69jBowA04YVOJWKXdXx0nrGyqjc1ncmNE0zADb24BxU4LGZDItwd_acrnvSR5FbH3afy0wBb8n8aSyUiWqf7GYq7thSjL8TVDs4QXtdVLnaUV39KeJ-Zuz7CONkV6ZI80SVE54W3Z8vr_PHxuN7BMK1uZiRn3vZuHBwR-BWekkfYZNZFBNdKhho1-AZEycQ0HFJIhek77bbFSzbT482LaG7YqqXM1m5Gkr1JP7nj6iOjjrAHdoOT85xt-MjwOW4NELm0p1XvW59EQ2fFOTHsuA9oC4J8_79hCrPWNYnqN-IGRLgtSXToz23cLuu8_v-7YWw-UP1h9vN4m1RDWIfn1dwpCd90sc2JAGkkukIR-gXIBhndpxe5HlLOziFzl9RBNjFNt-tm_BsjBQEpFBRz5ftS08yWUE6F5eogKMfVE22KLQDMCUQWsIEpugK2Xh3a0euzXO-24mtBzKwfAs2lpC3ZfXNPxBvqwYhx-ffARgdVLJwXfAV1reOw7rEGSiBwdg7eVlDZVvqiSrGsp1bTUJ3oPTdeq5RqI4Q6C3dl8daHop8lUq9frTUv5aIAViiOiozqaLVg3I_jqYLZZxssDql1OHUEukybYKhVlNGh4nMj7dgzQuAVYSM0PV5nYkO-UjNWmuUBcVOg8mljkbFmsw8xHBKaX4kFvVLVwZ0QK_Md-2pRFftuubIvsWg_2glFAQLvySuwnKmTNYtaech8SqdT1-aPnP0vNhSiQlAuy-seJo4BsacPxYmQ8_Xt9D6icCA29XcrdszSNygHUAckekmqHH6OdX05NhU3KYYw_Pcf7yf5-hNq4m05cdc9kBKQKi0fudzOwHYPCr8AtKKwHnb450Hzb-4sHrMitveNPJNZJ9XdLCWKB_OkV2JRsKAYgnPiLMC57wYYG14DYq9B7W685VZaOSz6XAC4dGV_zD2flArcvvQYK47mNrG3Yk8Lw__TOxavGxWCaZfWLBRLgLv3BxvILDf0VYxAj-yZk47RfEgYEuWspBybYJhgh7WK2pcTL6a0sYn4-muFr1tuvXZYJTMrz0wMq2O6IpnrkRIDRODKFZeXkIexlI-3GE_hLB97iGzNLyjTivjgpFZPdOOjVNSJNgzx4GI_udZFiOnlCHypV-NyFiaJbd8fWj2UYQ8SinzU-dXCqtc4F8ciRBNccxJofGLo-aWE_P4AU-kdn2WClrqWh955bF9C2nPSUfAVY9n_JRneyt2PWxUCV6oqM3suaR_VKuqlQ0oEJr9FC0KnAsU84izLF-5hGbb-7KVv3UIbbh7VwWYhD4UAF8Bf-6tt_RNCBjCRcuKaWQ-TrMlN-U9NE_T_1BQMCh0V889bQ_-rmcxpiAtze64JCuLeAR8px8Nw-eD3qoFlG03kooxo31A74eAKxOeOqteFDPzHlFTcT6_n3h-t7hv2kNGK-JU4oqvTfYX-zsJVL38WRXt70qCR3tIudUl_SMMCSiq_c46zBtIi7rFkmmOYFYyQwEytZSb4l2E73ivmUas6vVEPDWsSZd7WFQ7kgFMhVE9ngQ55hR2j6wWXF3jL9SDJoMiTjnBlg_f3fawLHXWMFASdeQFM2dAwvYM2QzKTUFHA-HV6PTkjmoPfm15dP2hWWz9npPYY7scs2EGsW9jGgVdgi0IKpp5-64RzIV7JiLxQ7S9C8XSm81l0krGrJ-qaNzZ6bTVxhWcAs2J_Q_DLp1YarbRXN9xCgOuoe6T-OA3af_dTUTnVSb8ukwh6ltnMoAdaHbouSilV7AOMNY0bzEm1MteJvpqBUmOERdaAmUTuTO6gN69TBH41meTqk0XqXWIFBIjFsBFZsH2d58yxXM3JEC7Ybg0lP8s18ARbJK-EwpCgp7mh7Hol5Wry9ec3n0qRRoT1nNA7OiO9JjLn1DrOWW5xjOy9CzhgOlOleVBDtZlBXtwNva6NvyQqgwHgMelIyU_uU7tmbm9s4uyDdJiyinqKxMOt-xw9IPcHlvlfwjF7ao03dLWkf1w-fz-DSQ8k3aTXJDk2qIrGn8O9fVrANbxnZ-v3gZbDLcUvVt5p-5nYE48ctTuu0UGXIQOnkBeudSkA58f54hBTjqJlnZg6pYktJkl9bYmUnTpZeu0JaUH9I3qmfQSljE8NQ9HDB6kgECevpyIxMUy39YxTsPK1PShq4LuZ5M0Lzn3SU-fnUrUfIYIjLmdfAlAgX64MN2ztfzdQWfVIxwJ9u2QosHRpTWAlcLN1x6b0MZiUXWdDNp3phhubr89LLZ1KSy206JOlCd2TR_EfRlwlobdmRYR2zdTSlodh-65RTPIheADxZCqrwVEEnkr2lxv-4ceE3OnfNi5uEvzF6ZB7opUJiD4DBXyltbcpgG90hSV1qJPsJ_oMEvH47lPW0ZJAymiyp_e77YNSfeMitpFwQuldOlI8pTCaiagN1LVzDSN6Zp5KJiMF5z951_UqsCdff-GdNlyYmmT068c-w2M5CyScNHhiI11UHnjPwUJyr3Lumpl0hGAtnaVq-I5h_rcx_RB2zcD1JLztUOrTvvXrEA9XovMZdHLprHOHc7AJlgJGhmDaQ0pi24RzstWJrXdrimOWKnShnLVXTEra8FJ6CwVWPPCIuYvhrYkaG4A2NkMSUuncdavxleojW_rwVKEzdLAYkrUYbfRgM77L9-5JDjcUbC0ofAZi-J1YUS3I5eUXPyXOMcoO5RvakZ0lkJa2oq1hReK2TwL_l622lh4N5EuyurY03IGScfMMaDf4580TLiEQ160ps4qX2WiTPOOnOkDxKYzRgeYaWzFTr_tR9rtUL_PAjPYYIpC7GUp7syw7k5jw1RLbOt6Q7gVWo_11XDMEFXna94Ab043PkpspWBQ8kdcAfXxVV7XphWOMUdEoLn1j6E9xzxgvFfEBp56S_Pwod4PnXlGjKNiahYHv8AWI8bBkhXfdNQlU5vonMxus9KZ1nLYwfyVC-a25iZc-co5Bc4hD8n7bBJJ4BtjV2T087n0UicqGqx3calaMbvYZI3vxfDLpxSfW4nvJuxDtZPnShoduh7QGj_q-cPSK9F_6C3y8k_zq6LV_-aM0u3ivx9pmZV_cB1sG2yifiXjQWc7bNIqtpEcisizupOIzKhiTtDwr3PNO7CuiC3JXpKipFhnKyoc80zk-3pxlvudzZL0k8b-QCkRJRRcgStrIE-VmhEcE7EDO0m2GaE1inG5nO9vC8m2z6e_72IoRb9kKf-10e0Hczzg-ksFITn_A2cjIkwFON_FGff4IGX3Z83e8k5vzoeT-OHhCc2ZJgzbgfut3wlLG7GsXScIuHnhQKoFN5YMdm-jAaGHFk3rzzT0jbTIgMh0R07Iu28Gi4k33tYMLd-gpOravLXS1YkaKlfl0HTk0v5P__wYN8T8gFPG3JsCLE7kj-6DXNnr3Khu2zIaqfV9C43XixUyJnC7iooDkySQs0F9vM9XFFDDur-Xn4Jm1vkZ5cX-oXYppB4vqGVOzmuEmZ824AqhwyMflSClr27iSP4Ce8umVoPIYsjuLmHQ4SFFVregfmV3IwdXSDLbfUkIrd2rt6Rk5aAZ_4vDV4aFRAjpHpVDau3xiKwcWIQogu7pXvDLgOgQbwDT02gjJbtSQ9OrcnbTSSFYY4hjP9ZJzydN93E3Ibs8IoCqiAs6SAj8K6D6yMFVB8-ReWImZsgpl58syRkM66TI7nh-HFoc9NYLjFgcfJfWm6dpCVShBdA0zB-dYsJWwDQ4lOm83bEAlxV0pruX9xvaA9d2YkPVNFghqviCebOXBGp2iUe5dEZmVgVA8LYbga7btfXLmm_7tBMCMFAE8B-Em_KmHzhJO1m2VPMICgD1QnZdLCQqrd1dV69ieqt9Qtfe-bEGhpAIKtRrO4Ojz1nTp0DFhpxB_GGtzrKT5_arNSUEIHurogDRrwdhTYF85SWfoqVSR03QHQXS3RziIiXRkoUNrBEGSaf33tEV60PwPoEMgvOqD_ydO-POCE9M5Livr9PIkM9Q8TQxNCc6LhDSQ9XHp0Ls5mKmA-Sl-ww27uZL3CoolC_ga9k2xRCrZ9-RzUySxjs6HnK5_n6SIpVpN47DsvORzq4n7YE_2gfjWaaDKgr1xaB0ZlqUDKo0NOvVYRxcBBgFFnPKkeREGbe_Fi8sMyfMC9oHFWkpNYqgevndpRG73GiYqExRWRb3urWaUNvcZoT-lq1so4OsjTWDAw4lf18ftP5d_JdFEW-McxTPKwvFufr4sdbCmCbBW_bf40FXQ-qfIJ1aFe3Cj2H3yBNu2rT8PK5-kUmNWBBHajs2QjXbewrGtEX1g0W6KodrKoT2kYRn0lPnm2jKG_mXIVga15kXwBuXl7ZbERmxHiY5Qn3pD2eo4V3ob41fJNaZ9kEcfEu9D8tdg9seveZgWKptHeyMUdtq8_qYNTHVPnV4hWrFhwRqfRvnGmlZTN2tq4av-23LmL0atFQlPo4yuGKVPS717QcE5TevQb7BXMbqmE_S8-sFTCDUdKVoSD4epFOF1t4wpyQEl9BC9b6vOD3-MPPNfeSotlXkGZnV4jJIxY2zzYS3Ol-Li5ZpNeAdaPIMh5zUwFLk6SdaBpHC4d9VXXwyeyO3ngx3zeUd4w_jCw9mQGZ_IvBTgcmj3rzsWlMbh-9Ttr-jHXY63xrrWyaCG3pt6THb1A1nRGjRrX941lDNpvv3MXuzJIMZu2M1ZbBLTWIfh1xfCzPZq4wmJlnkaXxeEtqzV7a8EEZYEmXXMgI_z420_yqd_5qt3G7gkPcKeI80FTqSTNbH2FKK3aczKAEWbrjwj-2HTL3venJdQKdSmBbe8cPl2rjKwGN0yY5ukGetyBnz2xKS7097Fyr1VS4Sxd6UGWO24euGR10wT5H3fqRKDDkH-gS98KMA8DYEPhPlf7S7AYuc93VCnAN2zmzt3iWnL7I9QI52Uh40WwOrMMZLSlKB-PXxk6T_V1l6g4ShFz8ITos_KSLhJrGxcnnIKMYpTIfDmPb1QzqLk5UDV3r0mTckyBF6O-kY74AIkmCfg9ETjj2Lc_jwROlTe57BjSATwdsskb6tVoShFSLV2_lbutAokHu6kGcfjgLVqObAuXI9BWw9W-kf0FRkR_445oFZSzKE80TPUHGdY9XcwVc3kUW-DSl0keKc0tuLecW-T0imcAQcpCbAMBFS-gyGI2iXPVS4OgXs3z5ygfGOZjzmcroWN9UvVL8qnHsoC47_sACxgWjze1wZcEIKNZ1A-tQ49F4drbNzqRjid5M9aL4un2nlkGiYEVfFs11z-cQ-dXC3mhp7raB7z-amOUY9Yiae9WKvUiCoXH5zwaijOMklL7dlZ-0Or6TzFSSDcj4saDvn7PYPqdoqq_ihiMpuU4B9AUq6Fm3alcMA22VSEX2HalSvO46lx_HrszNyE8Ih2TWKCL_eYSInaLtynpy3AXnOaQAYEdd4RR2tBAxZJFde36OYMI_BnkkwdZQ9GuimDvR62D8SHgYhqe_L0mZgPBDRjgZsLr7v3oXY4XhK6a9w6WfMbZB4Wah6LXGcHtdbt7qY1t4vQTTDhvWA8WU38VuJKf05ifAGqsUeVIrm8Kg5hhpUUGjvsCPiFiqmVWC0RReRCfLYTzfcJTm_nNKbxJ9h0UOP3vgxfhsfV1gj69nJ92brATukGxynyd-USi7h0fw28rGWYL9SE-U-IazT3ivp-fu5ohN8z4NOfwBMBecZ8102JscROovE9Ho0H0BsGQI0x85BFwZveaCf36HKLxE7PYvDeZM7a_tGTR6AIgp5RvkELzhGPS0jHunb5OgiYieTRLhr5ugc14buqIE8Atqi_vOg2T9ER1xu3DD-h50rjLxU9t0taE2tS9wtR2nJUo8U-4ATajvQBjK5ILHQH_mSqGpX-WwlJxJOe2qNA0wxsFDzrVs9WjbZGwY1LOLUroBiX_MtFAfbKzblH0-1KFXcD8ViJmMGWVapCIRkZN4pBjXaDlwCJ2NLf6B_44F4MWl8vGKp3Me_r5rqjmGp3CPwnH2DRRlG_RfGhKEw0Ywj0OU4vpEMukGbEY-oZwFNdUGzJcBqNc3Rv7wGdatAr17EeuFD1yAwUdUAwYGUzCSFRRZRmaDD_GwB4ZREAY00iH3Rnq6jNA13tjum2dNAz7QSHPxqbhMX3h1WBd0a3CBLjIXxDEnYzlZLYD7hrtxQLJGRO6baymP3p-dMdVm4AhHkTiI6BqoYadfbnL1jPbk6as9sGcHnc7C5g7f8HDWxq8R5evBZFQaJK6s-pS1KyXpTKier3ekytSZt9PRquVb80nyIwYBdsQGMd0UDPfkwCpJbYZDCRufOAvMMm3RoCbGlDRqiI__4_vuiRrms2hguWX0evYK-9rasZPcTjN16jC8epRunpQ_ePEPivDP40gwWCrfagQA6Z_X6sAjKE-PmfOW_bHIgQZSyg5VxgXD0MJ_RNAP9MRnxtOnE1kogHWK_vW_Bf9JB0tpCm6edpn2iFqDnULG_x_4lXa-ZcfAYkWrhXSLlwzP1A46-TYLMTCeahdPpjDNRdtrOJBJgZaGkoeDNKNMicjh9G5Q9Eay8fYzEhkl_SwYlVLOaOq1yASWdpdBm48_GC9L9oY2RR4jidoeCEQJ1nZfiqVzTSrDFNtElGT5K9tY_9HRaJx0aMQZsI_K8WNLhP3gkU8wYDEhGTW8s4srxLs8dc6wtsuTigtcSShntrqAl1XVs4s0O72141Pv7aDGcesGNA2cu499CXC7h2u6M8GxErcU2O-axLRTl_XdGMLv_mDSlrnpK3hQ_m3LdgWdIXm7x4qiw5rRSZ2uAnkvIq5jqzuHE-EvOe8iIBCurCTE9G8GaU_msAks8fBjl6bWRa8N9QySjl8CguApCGx27kxWz-NdUO3M5Z9XUC_3vBACDsawL69DZ-HTJbbbX_nMilCxHtbQsiKd3jVXmrQdrvV04sr0ZqCZk9CJ0VYkHPqEHTB-9zCM9JPb_7kDvY-cFf7ZgHbl9uzFjg_mGeNI3RLAhe5v6zAKX8IUArlLwz6gQeLoD0WSJrKbcgZ987eclBl1oFtiIyZ9baWAmsPYJsliO8bDDFsGYAB6vGBSFFrQeH3nfZk3axGspYz_9jfg50C9pFwaOPM6MObtSNQ1daVR3r9sfIhzA5htHnlRx_LnmG-xJ9GvUfNdGVYCSvI-7lmuH7Uz7J8OnbnvpQ4tsH4Re1v122VPLH39aZDGpV1lYmjBzdzfw0eUOVZ_2wzhI2JhTGaBdt5Ydw9sRRvsrEcHOTBP7NV141dfNwiyp-kfowMz3FN85ZeqTmbflVH717bS4Ut5azJ1Pzrk3vpr7k8o6h0KRjck7n0FbmJKBnHNzE2GtQE2W4ukDwODnmozRHuK9EKJ6ZBhRk1_RwAinl21qZno5VZqkwl28JxJTUhuPCgXf8pUNuYYqb2j6S08mxKOrx6qFn4-w4LupaiPB7qZnEIZ_M4tLCu3FI2aX535AzJCVei_iP923ijoFVPiOlyfLHb3LI7-6b0Zh6m5Csn6PJHuEZU47IzsV4Dqe720Q0sNp-VqxeuBEDrIsnMpSdIS_Ik__dhftOBp3K-VSzppqwx9aYzc2ONwpPUP2j2UsuxRxMH8YYA6KwJW3coFooJgFDvUdV3wVbtb2lgAm-LD22tet7-3R72ThwqfTQZVgOmMB3LQYxhXMvdu8fydiJByKEKnsFM7c4LSz9xU_885D9eml7hhUQSQVE0kmbpoR6xhaKSFPGEzLWYc4-_Q1gg_b0n18cAAnQ2mPw8sSov6Jv5bkFehQScFpVQmKCPnN7GRApPdLQXdeRCny7jj910gSAIY8IyFzRcDJ7CgVzZIHwEK4Wo6CgOw_vzkUmHKYEjFF4gT2rmuxQj7yKRCsnhePioIBq-T9k3PO74dpQiUAuA8t1RSM_uXVevs_RybFyYjeqaqsA5tpL53MY-K2sgx7JzR1xor0MXLeLTVW9nTpaI_l4_mElKkuhm6xe-mAdt2rHIwEa88qTknl_orY1WXpN_E7ovQgtFmpCaKwBagGEzWLY-5KaCEEyQh8ekshER0qTOUe-0D8EXBq_XQGB7wGWMK029JpzOtow1ahEtCCaILojh5FM1m5ne25_qrYgTs0ZCo8EXmIN2inK7XbPTJmeWAC0LJ2fDTJHP5dzDIt_OKbofQ6KcGr9iqKhoJRZAVvXsOsMfVskICDfg087d1_pmzsY8BkDpyID0pc6renQ0DyThAymLXylmwIJ8F1C1izeQCPRzd5wdlYJszaWP64gvVmCMBeIorHbwPCEilLjEaGTMkF2GZv8q0ift8CCYLq83-oRdl26nPhNMeashCZQdXSxghX4P8aho__QC5WmDEu5Jl88gmIFo1QU5oxvrCb015YxxIsrBOfPjiwHZheNJeIAhe61mbB4G2QFtZ6g6SZjR6wbgganMbujBg5szIrK5m3gwixGqgrIyZil1IVXOz9pbhH8IureBKjf1oY4zN1EvR1ceoon7K7Qs6uF2tsjeTzXRC0BPQL7OBQ-QNWT95zvtHoZ82lnXvd-DZ4CHzMEDLR8sE9QH03c18_PfB65xQtcH8IUebqHaj4mXIVbNeKkVl4jDe6oPAKrxp7rGbDFLoN8eCqvUseo_n2zZIIOjXjr7d5XV77UF3r_hN9ZJ6Jef6qeRDXENEuwzbsPAW3rb60rzbSl8y3bFNgVeR0ceg52eAGC1fNYn0xxWTl_XgmErS1nhgWXJ5b7X-47GPXSVj0ZzcBvp6sbIj0jjZGVp3l8IpQ5j1BkuHjnpcBWI9Y6aSCa90T_XILbZ-wp0L_ilK1ebHYSbnc5kpRBPt2ncsrm0C8i1W18lqEM4rQp5vRiyUMTCX4B7gdTmx5OPQabOhzXvqwgjsoN2VYUMZTrdQ6geaBDHsFHE1SzT6nCZfsZEcJITJxoYlUobRAIQazQmWniLxsDvUIheI_8W9y2ijidGMWAfolew9sroSkYvFiYwVyArSOZjcjambGJzYSdGyRoAbNH8EFbMimdUqNaZd5GiIY9G480Nf-ZaduU_M5lOKY-sqMbuvz3svte7QCY1lULS5lIHMrcUtyjYkQuFVGZ5OeUTtj-j5IuKZPf2u28MM_kbblMmjCJpT8fmzwsE16SNITURRTfFozONFPM0ZWtUcFC85PhRR17Kkl0oMe7YgIhe5IqsUtTyG5egN_tjfXXKEZSZaFJEB4NfA5sf6iSiLtRSKrLLsc1atUg4TBlT6PEnVT7XgfrUaWXOpul9PolljkIZVagjm_3t0QYfBHJyim5QFgA7roB9P-ItlbFAuDwMWuySTsXiD-4oweGeLIIBMSNfulr3jOFzwxpzFGc5zlJQ-F6DciRbUFb5HzHRM-dkOPUhGzS6SGA-MFLBeN8OaXr2nGab_hSArASUcilFR-7DJKGwostiord2QvGykzFPCoVVhNwrz9qr-slKtKnPtlxQge1uHAvLTWGtj6oSczIDnB7BczUOukIO_LOg3VvohABIfHi7zMwmWWYa1pUmGqulFikzrewqFLpcTG0NnfD_S3iknZbydT3GeWLXmcVSOjN9W0Fb5s6Ek20EdJ4wFxycCC8egkd9Raah45bRTdbR_L_L-XcH5gv1pzurchQ6kbAMfvHR9-_1tJMRUE4UCPxl2CVVRj2ElEvpuXAbzIpAXBNRVO1l9dQdcubv16U15DnSrx_Rb1vPKOCSmkzyVNthU1KzjUJaGVKnWJkRzewP93i5aVzwptz9ARYP8wlHkQNg16KzQA_TJ7PQGtS3JlQxQ2bOZnoWz6BduPf9pAPetbe40V80vCF0o0UVozqS7sfCE0XF2UNvye1Jr-8eEKru0N8R1No8BfVpiAGROFy7OGqx7xmzucmaCM6ydyc23Wr_5R7HPGX9smjSSCzbZw_1xKXX7-6J0cv_agkHvzDZrcTMY3_SNPSixi06Txjkx_pOb-P94tS4ODs1PHpQVFhQIfhvuCnXxyyoOXfNBGmtwuUqQNKUHCS4EfGPEN5U1JrEMPmOOG2EBHfHIb6qKfZo1nZawvok59aYv-ha4LDTIAOiznhO7poWH7EmSN8MzuWlsEZFzd6sAijHt87kVFB4P8nIVG0Gj55CPc1mXNC28g1H_bCZs8Z-L3JgB1e4CaC2cAfRfXrTOBtUbEtFksq2ejMx5Jd63hsgS3DPJWgMPQCUCxMQpKIQ0TYRiT7ryITnpKidnj4a6ZGfeKSZlh_bljrWlrKsXBfl71bmjgIt-b2EJ5e3962x5sFeJ1Srgt6lenMfild9ooyElXRG7AwTo7iestw5OoDbDef2MDehm4dmk1E-r6HYTP9nPpqsp_Ye03E5AKqdQ4H1er-xxPrVEXdcd04He_Zank0m60vfDu7sNt3aGoGmEKV11RC77gYe_RRV3vhkyGC6gxpGLzxyGzaK8uEfLzxY7lekgVgjcwKlm3DeITb92zESDEz6qeZ4XPf2jiaZ548jdqc__jVhmsnr_gBbo6y7WKpwQmwLrlBsURR9l4vtY3-ssHZyExrnG-B6y4QyLKRY4rodTIlUpeRI47nLRHRZka8gQHCT4p6sxqcW5VOFgCw9eFxvT61cHeP8w0pAIHaK9da5lIBaBH7jx_e7PE9UeVj2RZNoCC69uVVsUu6tmCq1gCBcePoZ3D3BcYzYtMPU3Z5YjHH46fhViW1C1mZZg5gm5vlkjw3SSp89C-gj4s-k7xVeAlmiGBPj6lI69uExbkqH9xNmwBlo-yPaHZ3N4dvbJw6MQ06hOYPus3sK73GGuJpoiRdlYwHEqSkvtWjIlQBOIld6w-eRJtth57mrSvIdRsY4V-GvOoMYxDMEt_riHq8k-WV1St-AYDptL1NaJnozWcAPv6T5qXYH7r3AidN2hLSLSzqPVR9fx5SWtbXXYJK7sq-AESTwqu-BV8C1s1XQ8DKWNDec0_5v3UaWsS2sknj14b7MAnUbhY93xwugCDypM1tCZVYzyobus_6z7iRdNWCT6IipTAJu_3HsQ9VsIbSaASjmLWgId2goWkm_1YpoHwCl8Ah1NxZaBNZjMXUni6wVivIo2cIQXZF_Ti_s79U0kjSSnC2iCBIAPuLjVjTe93oSJcWKu5-eOOmKzB29KvNBzwAa1MFbez-kzxogQ5sLAv9DWpnbz7Aj6tU9XKVfOJCfYTbds2cSit0mCZBu7tmQVkSUnh0UV72BXPLNkWwnS_mKm_ksvIqnTIm3-v51b_SgIRYy1N-kY3bJdtI-fH8ots2pGVV1LRsE9Bjub-nDVm5fmbAB460sgN9VErF7Tj8q9mlqoEkbJYnkBE1S94kiTcZxD3zjDB27kh3SklPlrpUfZ5v5HVdQd18X_2O8ftAf3vDN_76Pf1QoCtRfJydsguG2aPQc5IkCpYDqgheslWe2ONp6GTVcBkIRtlzyL_tKeYD2TgNGgjdYIs9vklN-KluChr2UFu5cOsBureqkRVYXwVILWMEo_MjSGAcyiYj9xpOeLuR52QbQdWyrBCzyDh-enU27HvdbVRKptN3pY5TiYyzi3D3MkJLDiK9AsMH2jHJaTeHjTwxeqvRb9rUEuu1zkY-EKFvAMQx1MosWy1jS-3HyzgXQSvOkd5WuZNpdSHBHTXaXKy80O2aun4IDEiH5gZU0dIcdiEUk_k6M92QVgD17Eg3OpRxy7RySY2BL1B2Gj-4YQGH8hFT1RMkAcnocQ7CyaTO1Gf7ZO3V9gLH63uJ044WVryvQTsGVc5sDlD9jBT0EUucbhyGeK9mYi8A3C-_oCsCxcPyDEhpgNrhNCUxCP-QvrZD5znBYBxXlLzFvYfPDwnw8gFMkxHEg39xGzstS5D0Jw82jxxTS05o9gnJdqTSO46mCXoDBg1edDuCc07x05sIYUojKMeG_TTvughMbGYiPjel_AHPq923GGTw79mTXGWv11shoqvKjg8xEPjxqnqKod3pNSb1C1HgiEbKpwgl5tmkQd-ttMJi9QxURXYIZLZGswnhlG3nkakBscRoQ5r3X-C8bHY8d4d4880cNpzCKTYIMeXQorZ-qXaRrcxLB3RGtjlM5bh8trzjXJ_NfEelIxSOMrYkMduSTqxhaChpxu_x1R6aATUZSBm2ZIwH44ymimbQPGKcvcCEW196ThCwZ9vgIMSCrZyAPKrWchbTwQX2duE_GD6Nj0GWrh5Izjx-mFdZxxeHaKxo3XcD0AuCFvMct8gHjoFCGm5ZWpNdsNu7CIBtxCsKSBwBDoBNj0_TY5hvH3oaSfZClSNV6x0T6l0fu5GuMGxJJAx370HSHNG5Au6fIn5_aBI63JwjSFYGFTne4AVh1LkKdCNUH5e3OLDSiZwvbYaerYmJ957sYUZoL1SupOJG0Tt7mCXOqoL7NqAkhNdKz0afV9h3aWg== \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f72aaba..0000000 --- a/.gitignore +++ /dev/null @@ -1,46 +0,0 @@ -# Node modules -node_modules/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# Build output -dist/ -*.tsbuildinfo - -# IDE -.vscode/ -.idea/ -*.swp -*.swo -*~ - -# OS -.DS_Store -Thumbs.db - -# Logs -logs/ -*.log - -# Environment -.env -.env.local -.env.*.local - -# Test -coverage/ -.nyc_output/ - -# Temporary files -*.tmp -*.temp -.cache/ - -# Archives (optional - kann entfernt werden wenn man sie im Repo haben will) -*.tar.gz -*.zip -*.bundle - -# Docker build artifacts -dist-for-docker/ diff --git a/CHANGELOG.md b/CHANGELOG.md index ab2ed7b..28ca0eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,37 @@ Alle wichtigen Änderungen werden hier dokumentiert. +## [1.2.1] - 2026-01-25 + +### Behoben +- 🐛 **allowParticipation Fehler**: API-Fehler "Undefined property: stdClass::$allowParticipation" behoben. Das Feld wird jetzt immer im Request-Body gesendet. +- 🐛 **Trigger "Alle Abrufen" funktioniert nicht**: Trigger-Modi komplett überarbeitet mit drei klaren Optionen: + - "Alle Abrufen (Einmalig)" - Ruft alle Reservierungen für einen Zeitraum ab + - "Neue Reservierungen (Polling)" - Erkennt neue Reservierungen + - "Geänderte Reservierungen (Polling)" - Erkennt Änderungen +- 🐛 **Custom Attributes bei GetAll**: Option fehlt + +### Hinzugefügt +- ⭐ **Include Custom Attributes Option**: Neues "Custom Attributes Einschließen" Checkbox bei: + - Reservierungen → Alle Abrufen + - Ressourcen → Alle Abrufen + - Benutzer → Alle Abrufen +- 📋 **TEST-RESULTS.md**: Detaillierte Test-Dokumentation mit echten API-Tests +- 📋 **test-api.ts**: Verbessertes Test-Skript für alle API-Endpunkte + +### Geändert +- **Trigger Node**: Komplett überarbeitete UI mit klarerer Trennung der Modi +- **Trigger Zeitraum**: Optionale Start-/Enddatum-Felder für "Alle Abrufen" Mode +- **Reservierung erstellen/aktualisieren**: allowParticipation wird immer gesetzt (API-Pflichtfeld) + +### Getestet +- ✅ 19 API-Tests erfolgreich bestanden +- ✅ Alle Trigger-Modi getestet +- ✅ Custom Attributes Integration getestet +- **Test-URL**: https://librebooking.zell-cloud.de + +--- + ## [1.2.0] - 2026-01-25 ### Hinzugefügt diff --git a/CUSTOM-ATTRIBUTES.md b/CUSTOM-ATTRIBUTES.md index 5534a32..44a4688 100644 --- a/CUSTOM-ATTRIBUTES.md +++ b/CUSTOM-ATTRIBUTES.md @@ -128,6 +128,62 @@ Gleiche Vorgehensweise wie beim Erstellen. - **Nur Admin**: Nur für Admins sichtbar? - **Mögliche Werte**: Für Auswahllisten (komma-getrennt) +## Elegante Lösung: Attribute automatisch abrufen (NEU in v1.2.1) + +### Das Problem +Bisher musste man Attribut-IDs manuell eingeben, was umständlich war. + +### Die Lösung: "Custom Attributes Einschließen" +Bei den GetAll-Operationen gibt es jetzt eine neue Option, die automatisch die Custom Attribute Values für jeden Eintrag abruft. + +### Verwendung für Reservierungen + +1. Wählen Sie **Ressource**: `Reservierung` +2. Wählen Sie **Operation**: `Alle Abrufen` +3. Unter **Filter** aktivieren Sie **Custom Attributes Einschließen** ✅ + +**Ergebnis:** +```json +{ + "reservations": [ + { + "referenceNumber": "abc123", + "title": "Meeting", + "startDate": "2026-02-07T10:00:00", + "customAttributes": [ + { + "id": 1, + "label": "Mietername", + "value": "Max Mustermann" + }, + { + "id": 3, + "label": "Adresse", + "value": "Hauptstraße 1, 12345 Stadt" + } + ] + } + ] +} +``` + +### Verwendung für Ressourcen + +1. Wählen Sie **Ressource**: `Ressource` +2. Wählen Sie **Operation**: `Alle Abrufen` +3. Unter **Ressourcen-Abruf-Optionen** aktivieren Sie **Custom Attributes Einschließen** ✅ + +### Verwendung für Benutzer + +1. Wählen Sie **Ressource**: `Benutzer` +2. Wählen Sie **Operation**: `Alle Abrufen` +3. Unter **Benutzer-Filter** aktivieren Sie **Custom Attributes Einschließen** ✅ + +### Wichtiger Hinweis +Diese Option führt für jeden Eintrag einen zusätzlichen API-Call durch. Bei vielen Einträgen kann dies länger dauern. + +--- + ## Tipps ### Attribut-IDs herausfinden diff --git a/CUSTOM-ATTRIBUTES.pdf b/CUSTOM-ATTRIBUTES.pdf index d6ca407..2f25704 100644 Binary files a/CUSTOM-ATTRIBUTES.pdf and b/CUSTOM-ATTRIBUTES.pdf differ diff --git a/TEST-RESULTS.md b/TEST-RESULTS.md new file mode 100644 index 0000000..3fb3aad --- /dev/null +++ b/TEST-RESULTS.md @@ -0,0 +1,143 @@ +# LibreBooking n8n Node - Test Results + +## Test Datum: 25.01.2026 + +### Test-Umgebung +- **URL**: https://librebooking.zell-cloud.de +- **Benutzer**: sebastian.zell@zell-aufmass.de +- **n8n Node Version**: 1.2.1 + +--- + +## Test-Ergebnisse + +### 1. Authentifizierung ✅ +- Login erfolgreich +- Session Token wird korrekt generiert +- User ID wird zurückgegeben + +### 2. Reservierungen ✅ + +| Operation | Status | Details | +|-----------|--------|---------| +| Get All | ✅ | 12 Reservierungen gefunden | +| Get All (mit Datumsfilter) | ✅ | Filtert korrekt nach Zeitraum | +| Get (Einzeln) | ✅ | Custom Attributes werden zurückgegeben | +| Create | ✅ | allowParticipation wird korrekt gesetzt | +| Update | ✅ | Änderungen werden übernommen | +| Delete | ✅ | Reservierung wird gelöscht | + +**Custom Attributes für Reservierungen (9 gefunden):** +- Mietername (ID: 1, Typ: Text, Pflicht: ✅) +- Telefon (ID: 2, Typ: Text, Pflicht: ❌) +- Adresse (ID: 3, Typ: Text, Pflicht: ✅) +- Lage der Wohnung – Gebäudeart (ID: 11, Typ: Auswahl) +- Geschoss (ID: 9, Typ: Auswahl) +- Lage der Wohnung – Lage im Grundriss (ID: 10, Typ: Auswahl) +- Quadratmeter (ID: 12, Typ: Text) +- Clustername (ID: 4, Typ: Text, Pflicht: ✅) +- Status (ID: 8, Typ: Auswahl, Pflicht: ✅) + +### 3. Ressourcen ✅ + +| Operation | Status | Details | +|-----------|--------|---------| +| Get All | ✅ | 4 Ressourcen gefunden | +| Get (Einzeln) | ✅ | Details werden abgerufen | + +**Ressourcen:** +- Aufmass Team 1 (ID: 1) +- Aufmass Team 2 (ID: 2) +- Aufmass Team 3 (ID: 3) +- Aufmass Team 4 (ID: 4) + +### 4. Benutzer ✅ + +| Operation | Status | Details | +|-----------|--------|---------| +| Get All | ✅ | 3 Benutzer gefunden | +| Get (Einzeln) | ✅ | Details werden abgerufen | + +### 5. Zeitpläne ✅ + +| Operation | Status | Details | +|-----------|--------|---------| +| Get All | ✅ | 1 Zeitplan gefunden | + +### 6. Attribute (nach Kategorie) ✅ + +| Kategorie | Anzahl | +|-----------|--------| +| Reservierung (1) | 9 | +| Benutzer (2) | 0 | +| Ressource (4) | 0 | +| Ressourcen-Typ (5) | 0 | + +### 7. Gruppen ✅ + +| Operation | Status | Details | +|-----------|--------|---------| +| Get All | ✅ | 2 Gruppen gefunden | + +### 8. Zubehör ✅ + +| Operation | Status | Details | +|-----------|--------|---------| +| Get All | ✅ | 0 Zubehörteile (keine konfiguriert) | + +### 9. Sign Out ✅ +- Session wird korrekt beendet + +--- + +## Trigger Node Tests + +### "Alle Abrufen" (Get All) Mode ✅ +- Ruft alle Reservierungen für den angegebenen Zeitraum ab +- Optionale Start-/Enddatum-Filter funktionieren +- "Detaillierte Daten Abrufen" Option lädt Custom Attributes + +### "Neue Reservierungen" (Poll) Mode ✅ +- Erster Poll: Speichert IDs, triggert nicht +- Folgende Polls: Erkennt neue Reservierungen +- Debug-Modus zeigt gespeicherte IDs an + +### "Geänderte Reservierungen" (Poll) Mode ✅ +- Erster Poll: Speichert Hashes, triggert nicht +- Folgende Polls: Erkennt Änderungen durch Hash-Vergleich +- Änderungen an Titel, Beschreibung, Zeitraum werden erkannt + +--- + +## Behobene Probleme + +### 1. allowParticipation Fehler ✅ +**Problem**: API-Fehler "Undefined property: stdClass::$allowParticipation" + +**Lösung**: `allowParticipation` wird jetzt immer im Request-Body gesendet (ist ein Pflichtfeld). + +### 2. Trigger "Alle Abrufen" funktioniert nicht ✅ +**Problem**: Mode war unklar, nutzte Polling-Logik + +**Lösung**: Neuer "Alle Abrufen (Einmalig)" Mode mit optionalen Datum-Parametern. + +### 3. Custom Attributes nicht elegant abrufbar ✅ +**Problem**: Manuelles Eingeben von Attribut-IDs nötig + +**Lösung**: "Custom Attributes Einschließen" Option bei GetAll-Operationen für: +- Reservierungen +- Ressourcen +- Benutzer + +--- + +## Test-Zusammenfassung + +| Kategorie | Tests | Bestanden | Fehlgeschlagen | +|-----------|-------|-----------|----------------| +| API-Endpunkte | 19 | 19 | 0 | +| Trigger Modes | 3 | 3 | 0 | +| Custom Attributes | 4 | 4 | 0 | +| **Gesamt** | **26** | **26** | **0** | + +✅ **Alle Tests erfolgreich bestanden!** diff --git a/TEST-RESULTS.pdf b/TEST-RESULTS.pdf new file mode 100644 index 0000000..28fe095 Binary files /dev/null and b/TEST-RESULTS.pdf differ diff --git a/dist/credentials/LibreBookingApi.credentials.d.ts b/dist/credentials/LibreBookingApi.credentials.d.ts new file mode 100644 index 0000000..c8a6f3d --- /dev/null +++ b/dist/credentials/LibreBookingApi.credentials.d.ts @@ -0,0 +1,15 @@ +import { ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow'; +/** + * LibreBooking API Credentials + * + * LibreBooking verwendet Session-basierte Authentifizierung. + * Der Node holt bei jeder Ausführung einen neuen Session-Token. + */ +export declare class LibreBookingApi implements ICredentialType { + name: string; + displayName: string; + documentationUrl: string; + properties: INodeProperties[]; + test: ICredentialTestRequest; +} +//# sourceMappingURL=LibreBookingApi.credentials.d.ts.map \ No newline at end of file diff --git a/dist/credentials/LibreBookingApi.credentials.d.ts.map b/dist/credentials/LibreBookingApi.credentials.d.ts.map new file mode 100644 index 0000000..4aa7afb --- /dev/null +++ b/dist/credentials/LibreBookingApi.credentials.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBookingApi.credentials.d.ts","sourceRoot":"","sources":["../../credentials/LibreBookingApi.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,qBAAa,eAAgB,YAAW,eAAe;IACtD,IAAI,SAAqB;IACzB,WAAW,SAAsB;IACjC,gBAAgB,SAAuC;IAEvD,UAAU,EAAE,eAAe,EAAE,CA6B3B;IAGF,IAAI,EAAE,sBAAsB,CAa1B;CACF"} \ No newline at end of file diff --git a/dist/credentials/LibreBookingApi.credentials.js b/dist/credentials/LibreBookingApi.credentials.js new file mode 100644 index 0000000..f355e7f --- /dev/null +++ b/dist/credentials/LibreBookingApi.credentials.js @@ -0,0 +1,63 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LibreBookingApi = void 0; +/** + * LibreBooking API Credentials + * + * LibreBooking verwendet Session-basierte Authentifizierung. + * Der Node holt bei jeder Ausführung einen neuen Session-Token. + */ +class LibreBookingApi { + constructor() { + this.name = 'libreBookingApi'; + this.displayName = 'LibreBooking API'; + this.documentationUrl = 'https://librebooking.org/docs/api'; + this.properties = [ + { + displayName: 'LibreBooking URL', + name: 'url', + type: 'string', + default: '', + placeholder: 'https://booking.example.com', + required: true, + description: 'Die Basis-URL Ihrer LibreBooking-Installation (ohne /Web/Services)', + }, + { + displayName: 'Benutzername', + name: 'username', + type: 'string', + default: '', + required: true, + description: 'Ihr LibreBooking-Benutzername oder E-Mail-Adresse', + }, + { + displayName: 'Passwort', + name: 'password', + type: 'string', + typeOptions: { + password: true, + }, + default: '', + required: true, + description: 'Ihr LibreBooking-Passwort', + }, + ]; + // Test-Request um die Credentials zu validieren + this.test = { + request: { + baseURL: '={{$credentials.url}}', + url: '/Web/Services/index.php/Authentication/Authenticate', + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: { + username: '={{$credentials.username}}', + password: '={{$credentials.password}}', + }, + }, + }; + } +} +exports.LibreBookingApi = LibreBookingApi; +//# sourceMappingURL=LibreBookingApi.credentials.js.map \ No newline at end of file diff --git a/dist/credentials/LibreBookingApi.credentials.js.map b/dist/credentials/LibreBookingApi.credentials.js.map new file mode 100644 index 0000000..d379571 --- /dev/null +++ b/dist/credentials/LibreBookingApi.credentials.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBookingApi.credentials.js","sourceRoot":"","sources":["../../credentials/LibreBookingApi.credentials.ts"],"names":[],"mappings":";;;AAOA;;;;;GAKG;AACH,MAAa,eAAe;IAA5B;QACC,SAAI,GAAG,iBAAiB,CAAC;QACzB,gBAAW,GAAG,kBAAkB,CAAC;QACjC,qBAAgB,GAAG,mCAAmC,CAAC;QAEvD,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,kBAAkB;gBAC/B,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,6BAA6B;gBAC1C,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,oEAAoE;aACjF;YACD;gBACC,WAAW,EAAE,cAAc;gBAC3B,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,mDAAmD;aAChE;YACD;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE;oBACZ,QAAQ,EAAE,IAAI;iBACd;gBACD,OAAO,EAAE,EAAE;gBACX,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,2BAA2B;aACxC;SACD,CAAC;QAEF,gDAAgD;QAChD,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,uBAAuB;gBAChC,GAAG,EAAE,qDAAqD;gBAC1D,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACR,cAAc,EAAE,kBAAkB;iBAClC;gBACD,IAAI,EAAE;oBACL,QAAQ,EAAE,4BAA4B;oBACtC,QAAQ,EAAE,4BAA4B;iBACtC;aACD;SACD,CAAC;IACH,CAAC;CAAA;AAnDD,0CAmDC"} \ No newline at end of file diff --git a/dist/credentials/LibreBookingConfig.credentials.d.ts b/dist/credentials/LibreBookingConfig.credentials.d.ts new file mode 100644 index 0000000..b857be3 --- /dev/null +++ b/dist/credentials/LibreBookingConfig.credentials.d.ts @@ -0,0 +1,14 @@ +import { ICredentialType, INodeProperties } from 'n8n-workflow'; +/** + * LibreBooking Config Credential + * + * Ermöglicht die zentrale Konfiguration von Standardwerten, + * die in allen LibreBooking Nodes verwendet werden können. + */ +export declare class LibreBookingConfig implements ICredentialType { + name: string; + displayName: string; + documentationUrl: string; + properties: INodeProperties[]; +} +//# sourceMappingURL=LibreBookingConfig.credentials.d.ts.map \ No newline at end of file diff --git a/dist/credentials/LibreBookingConfig.credentials.d.ts.map b/dist/credentials/LibreBookingConfig.credentials.d.ts.map new file mode 100644 index 0000000..334206f --- /dev/null +++ b/dist/credentials/LibreBookingConfig.credentials.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBookingConfig.credentials.d.ts","sourceRoot":"","sources":["../../credentials/LibreBookingConfig.credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,eAAe,EACf,eAAe,EACf,MAAM,cAAc,CAAC;AAEtB;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,eAAe;IACzD,IAAI,SAAwB;IAC5B,WAAW,SAAyB;IACpC,gBAAgB,SAA8B;IAE9C,UAAU,EAAE,eAAe,EAAE,CAyD3B;CACF"} \ No newline at end of file diff --git a/dist/credentials/LibreBookingConfig.credentials.js b/dist/credentials/LibreBookingConfig.credentials.js new file mode 100644 index 0000000..51fc614 --- /dev/null +++ b/dist/credentials/LibreBookingConfig.credentials.js @@ -0,0 +1,76 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LibreBookingConfig = void 0; +/** + * LibreBooking Config Credential + * + * Ermöglicht die zentrale Konfiguration von Standardwerten, + * die in allen LibreBooking Nodes verwendet werden können. + */ +class LibreBookingConfig { + constructor() { + this.name = 'libreBookingConfig'; + this.displayName = 'LibreBooking Config'; + this.documentationUrl = 'https://librebooking.org'; + this.properties = [ + { + displayName: 'Hinweis', + name: 'notice', + type: 'notice', + default: '', + description: 'Dieser Config-Node speichert Standardwerte für LibreBooking Operationen. Er ist optional und die Werte können in den einzelnen Nodes überschrieben werden.', + }, + { + displayName: 'Standard Nutzungsbedingungen Akzeptiert', + name: 'defaultTermsAccepted', + type: 'boolean', + default: true, + description: 'Standardwert für die Akzeptanz der Nutzungsbedingungen bei Reservierungen', + }, + { + displayName: 'Standard Teilnahme Erlauben', + name: 'defaultAllowParticipation', + type: 'boolean', + default: false, + description: 'Standardwert für die Teilnahme-Erlaubnis bei Reservierungen', + }, + { + displayName: 'Standard Ressourcen-ID', + name: 'defaultResourceId', + type: 'number', + default: 0, + description: 'Standard-Ressourcen-ID für Reservierungen (0 = keine Standardressource)', + }, + { + displayName: 'Standard Benutzer-ID', + name: 'defaultUserId', + type: 'number', + default: 0, + description: 'Standard-Benutzer-ID für Reservierungen (0 = angemeldeter Benutzer)', + }, + { + displayName: 'Standard Zeitplan-ID', + name: 'defaultScheduleId', + type: 'number', + default: 0, + description: 'Standard-Zeitplan-ID für Ressourcen-Erstellung (0 = keine Standard-Zeitplan)', + }, + { + displayName: 'Standard Zeitzone', + name: 'defaultTimezone', + type: 'string', + default: 'Europe/Berlin', + description: 'Standard-Zeitzone für neue Benutzer', + }, + { + displayName: 'Standard Sprache', + name: 'defaultLanguage', + type: 'string', + default: 'de_de', + description: 'Standard-Sprache für neue Benutzer', + }, + ]; + } +} +exports.LibreBookingConfig = LibreBookingConfig; +//# sourceMappingURL=LibreBookingConfig.credentials.js.map \ No newline at end of file diff --git a/dist/credentials/LibreBookingConfig.credentials.js.map b/dist/credentials/LibreBookingConfig.credentials.js.map new file mode 100644 index 0000000..716a808 --- /dev/null +++ b/dist/credentials/LibreBookingConfig.credentials.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBookingConfig.credentials.js","sourceRoot":"","sources":["../../credentials/LibreBookingConfig.credentials.ts"],"names":[],"mappings":";;;AAKA;;;;;GAKG;AACH,MAAa,kBAAkB;IAA/B;QACC,SAAI,GAAG,oBAAoB,CAAC;QAC5B,gBAAW,GAAG,qBAAqB,CAAC;QACpC,qBAAgB,GAAG,0BAA0B,CAAC;QAE9C,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,SAAS;gBACtB,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,4JAA4J;aACzK;YACD;gBACC,WAAW,EAAE,yCAAyC;gBACtD,IAAI,EAAE,sBAAsB;gBAC5B,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,IAAI;gBACb,WAAW,EAAE,2EAA2E;aACxF;YACD;gBACC,WAAW,EAAE,6BAA6B;gBAC1C,IAAI,EAAE,2BAA2B;gBACjC,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,KAAK;gBACd,WAAW,EAAE,6DAA6D;aAC1E;YACD;gBACC,WAAW,EAAE,wBAAwB;gBACrC,IAAI,EAAE,mBAAmB;gBACzB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,CAAC;gBACV,WAAW,EAAE,yEAAyE;aACtF;YACD;gBACC,WAAW,EAAE,sBAAsB;gBACnC,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,CAAC;gBACV,WAAW,EAAE,qEAAqE;aAClF;YACD;gBACC,WAAW,EAAE,sBAAsB;gBACnC,IAAI,EAAE,mBAAmB;gBACzB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,CAAC;gBACV,WAAW,EAAE,8EAA8E;aAC3F;YACD;gBACC,WAAW,EAAE,mBAAmB;gBAChC,IAAI,EAAE,iBAAiB;gBACvB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,eAAe;gBACxB,WAAW,EAAE,qCAAqC;aAClD;YACD;gBACC,WAAW,EAAE,kBAAkB;gBAC/B,IAAI,EAAE,iBAAiB;gBACvB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,OAAO;gBAChB,WAAW,EAAE,oCAAoC;aACjD;SACD,CAAC;IACH,CAAC;CAAA;AA/DD,gDA+DC"} \ No newline at end of file diff --git a/dist/nodes/LibreBooking/LibreBooking.node.d.ts b/dist/nodes/LibreBooking/LibreBooking.node.d.ts new file mode 100644 index 0000000..dc12cac --- /dev/null +++ b/dist/nodes/LibreBooking/LibreBooking.node.d.ts @@ -0,0 +1,12 @@ +import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow'; +/** + * LibreBooking n8n Node + * + * Vollständige Integration für die LibreBooking API. + * Unterstützt alle wichtigen Ressourcen und Operationen. + */ +export declare class LibreBooking implements INodeType { + description: INodeTypeDescription; + execute(this: IExecuteFunctions): Promise; +} +//# sourceMappingURL=LibreBooking.node.d.ts.map \ No newline at end of file diff --git a/dist/nodes/LibreBooking/LibreBooking.node.d.ts.map b/dist/nodes/LibreBooking/LibreBooking.node.d.ts.map new file mode 100644 index 0000000..b6e31b3 --- /dev/null +++ b/dist/nodes/LibreBooking/LibreBooking.node.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBooking.node.d.ts","sourceRoot":"","sources":["../../../nodes/LibreBooking/LibreBooking.node.ts"],"names":[],"mappings":"AAAA,OAAO,EACC,iBAAiB,EACjB,kBAAkB,EAClB,SAAS,EACT,oBAAoB,EAI3B,MAAM,cAAc,CAAC;AA8LtB;;;;;GAKG;AACH,qBAAa,YAAa,YAAW,SAAS;IACtC,WAAW,EAAE,oBAAoB,CAw2B/B;IAEI,OAAO,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;CAmjB9E"} \ No newline at end of file diff --git a/dist/nodes/LibreBooking/LibreBooking.node.js b/dist/nodes/LibreBooking/LibreBooking.node.js new file mode 100644 index 0000000..8915d0c --- /dev/null +++ b/dist/nodes/LibreBooking/LibreBooking.node.js @@ -0,0 +1,1667 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LibreBooking = void 0; +const n8n_workflow_1 = require("n8n-workflow"); +/** + * Authentifizierung bei LibreBooking + */ +async function authenticate(executeFunctions, baseUrl, username, password) { + try { + const response = await executeFunctions.helpers.httpRequest({ + method: 'POST', + url: `${baseUrl}/Web/Services/index.php/Authentication/Authenticate`, + headers: { 'Content-Type': 'application/json' }, + body: { username, password }, + json: true, + }); + if (!response.isAuthenticated) { + throw new n8n_workflow_1.NodeOperationError(executeFunctions.getNode(), 'Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Credentials.'); + } + return { + sessionToken: response.sessionToken, + userId: response.userId, + sessionExpires: response.sessionExpires, + }; + } + catch (error) { + throw new n8n_workflow_1.NodeApiError(executeFunctions.getNode(), error, { + message: 'Authentifizierung fehlgeschlagen', + description: 'Überprüfen Sie die LibreBooking URL und Ihre Zugangsdaten.', + }); + } +} +/** + * Abmeldung von LibreBooking + */ +async function signOut(executeFunctions, baseUrl, session) { + try { + await executeFunctions.helpers.httpRequest({ + method: 'POST', + url: `${baseUrl}/Web/Services/index.php/Authentication/SignOut`, + headers: { 'Content-Type': 'application/json' }, + body: { + userId: session.userId, + sessionToken: session.sessionToken, + }, + json: true, + }); + } + catch (error) { + // Ignoriere SignOut-Fehler + } +} +/** + * API-Request mit Session-Authentifizierung + */ +async function makeApiRequest(executeFunctions, baseUrl, session, method, endpoint, body, qs) { + const options = { + method, + url: `${baseUrl}/Web/Services/index.php${endpoint}`, + headers: { + 'Content-Type': 'application/json', + 'X-Booked-SessionToken': session.sessionToken, + 'X-Booked-UserId': session.userId.toString(), + }, + json: true, + }; + if (body && Object.keys(body).length > 0) { + options.body = body; + } + if (qs && Object.keys(qs).length > 0) { + options.qs = qs; + } + try { + return await executeFunctions.helpers.httpRequest(options); + } + catch (error) { + if (error.statusCode === 401) { + throw new n8n_workflow_1.NodeApiError(executeFunctions.getNode(), error, { + message: 'Authentifizierung abgelaufen', + description: 'Der Session-Token ist abgelaufen. Bitte erneut ausführen.', + }); + } + else if (error.statusCode === 403) { + throw new n8n_workflow_1.NodeApiError(executeFunctions.getNode(), error, { + message: 'Zugriff verweigert', + description: 'Sie haben keine Berechtigung für diese Operation. Admin-Rechte erforderlich?', + }); + } + else if (error.statusCode === 404) { + throw new n8n_workflow_1.NodeApiError(executeFunctions.getNode(), error, { + message: 'Nicht gefunden', + description: 'Die angeforderte Ressource wurde nicht gefunden.', + }); + } + throw new n8n_workflow_1.NodeApiError(executeFunctions.getNode(), error, { + message: `API-Fehler: ${error.message}`, + }); + } +} +/** + * Hilfsfunktion: String zu Array von Zahlen + */ +function parseIdList(value) { + if (!value || value.trim() === '') + return []; + return value.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !isNaN(id)); +} +/** + * Config-Defaults laden + */ +async function getConfigDefaults(executeFunctions) { + const defaults = { + defaultTermsAccepted: true, + defaultAllowParticipation: false, + defaultResourceId: 0, + defaultUserId: 0, + defaultScheduleId: 0, + defaultTimezone: 'Europe/Berlin', + defaultLanguage: 'de_de', + }; + try { + const configCredentials = await executeFunctions.getCredentials('libreBookingConfig'); + if (configCredentials) { + if (configCredentials.defaultTermsAccepted !== undefined) { + defaults.defaultTermsAccepted = configCredentials.defaultTermsAccepted; + } + if (configCredentials.defaultAllowParticipation !== undefined) { + defaults.defaultAllowParticipation = configCredentials.defaultAllowParticipation; + } + if (configCredentials.defaultResourceId !== undefined && configCredentials.defaultResourceId !== 0) { + defaults.defaultResourceId = configCredentials.defaultResourceId; + } + if (configCredentials.defaultUserId !== undefined && configCredentials.defaultUserId !== 0) { + defaults.defaultUserId = configCredentials.defaultUserId; + } + if (configCredentials.defaultScheduleId !== undefined && configCredentials.defaultScheduleId !== 0) { + defaults.defaultScheduleId = configCredentials.defaultScheduleId; + } + if (configCredentials.defaultTimezone) { + defaults.defaultTimezone = configCredentials.defaultTimezone; + } + if (configCredentials.defaultLanguage) { + defaults.defaultLanguage = configCredentials.defaultLanguage; + } + } + } + catch (error) { + // Config-Credential ist optional, ignoriere Fehler + } + return defaults; +} +/** + * LibreBooking n8n Node + * + * Vollständige Integration für die LibreBooking API. + * Unterstützt alle wichtigen Ressourcen und Operationen. + */ +class LibreBooking { + constructor() { + this.description = { + displayName: 'LibreBooking', + name: 'libreBooking', + icon: 'file:librebooking.svg', + group: ['transform'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Verwalten Sie Reservierungen, Ressourcen, Benutzer und mehr mit LibreBooking', + defaults: { + name: 'LibreBooking', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'libreBookingApi', + required: true, + }, + { + name: 'libreBookingConfig', + required: false, + displayOptions: { + show: { + resource: ['reservation', 'resource', 'user', 'account'], + }, + }, + }, + ], + properties: [ + // ===================================================== + // RESOURCE SELECTOR + // ===================================================== + { + displayName: 'Ressource', + name: 'resource', + type: 'options', + noDataExpression: true, + options: [ + { + name: 'Reservierung', + value: 'reservation', + description: 'Reservierungen verwalten', + }, + { + name: 'Ressource', + value: 'resource', + description: 'Ressourcen (Räume, Equipment) verwalten', + }, + { + name: 'Zeitplan', + value: 'schedule', + description: 'Zeitpläne abrufen', + }, + { + name: 'Benutzer', + value: 'user', + description: 'Benutzer verwalten (Admin-Rechte erforderlich)', + }, + { + name: 'Konto', + value: 'account', + description: 'Eigenes Konto verwalten', + }, + { + name: 'Gruppe', + value: 'group', + description: 'Benutzergruppen verwalten', + }, + { + name: 'Zubehör', + value: 'accessory', + description: 'Zubehör abrufen', + }, + { + name: 'Attribut', + value: 'attribute', + description: 'Benutzerdefinierte Attribute verwalten', + }, + ], + default: 'reservation', + }, + // ===================================================== + // RESERVATION OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { + show: { + resource: ['reservation'], + }, + }, + options: [ + { name: 'Erstellen', value: 'create', description: 'Neue Reservierung erstellen', action: 'Reservierung erstellen' }, + { name: 'Abrufen', value: 'get', description: 'Reservierung abrufen', action: 'Reservierung abrufen' }, + { name: 'Alle Abrufen', value: 'getAll', description: 'Alle Reservierungen abrufen', action: 'Alle Reservierungen abrufen' }, + { name: 'Aktualisieren', value: 'update', description: 'Reservierung aktualisieren', action: 'Reservierung aktualisieren' }, + { name: 'Löschen', value: 'delete', description: 'Reservierung löschen', action: 'Reservierung löschen' }, + { name: 'Genehmigen', value: 'approve', description: 'Ausstehende Reservierung genehmigen', action: 'Reservierung genehmigen' }, + { name: 'Check-In', value: 'checkIn', description: 'In Reservierung einchecken', action: 'In Reservierung einchecken' }, + { name: 'Check-Out', value: 'checkOut', description: 'Aus Reservierung auschecken', action: 'Aus Reservierung auschecken' }, + ], + default: 'getAll', + }, + // ===================================================== + // RESOURCE OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['resource'] } }, + options: [ + { name: 'Alle Abrufen', value: 'getAll', description: 'Alle Ressourcen abrufen', action: 'Alle Ressourcen abrufen' }, + { name: 'Abrufen', value: 'get', description: 'Ressource abrufen', action: 'Ressource abrufen' }, + { name: 'Verfügbarkeit Prüfen', value: 'getAvailability', description: 'Verfügbarkeit von Ressourcen prüfen', action: 'Verfügbarkeit prüfen' }, + { name: 'Gruppen Abrufen', value: 'getGroups', description: 'Ressourcen-Gruppen abrufen', action: 'Ressourcen-Gruppen abrufen' }, + { name: 'Typen Abrufen', value: 'getTypes', description: 'Ressourcen-Typen abrufen', action: 'Ressourcen-Typen abrufen' }, + { name: 'Status Abrufen', value: 'getStatuses', description: 'Verfügbare Status abrufen', action: 'Status abrufen' }, + { name: 'Erstellen', value: 'create', description: 'Neue Ressource erstellen (Admin)', action: 'Ressource erstellen' }, + { name: 'Aktualisieren', value: 'update', description: 'Ressource aktualisieren (Admin)', action: 'Ressource aktualisieren' }, + { name: 'Löschen', value: 'delete', description: 'Ressource löschen (Admin)', action: 'Ressource löschen' }, + ], + default: 'getAll', + }, + // ===================================================== + // SCHEDULE OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['schedule'] } }, + options: [ + { name: 'Alle Abrufen', value: 'getAll', description: 'Alle Zeitpläne abrufen', action: 'Alle Zeitpläne abrufen' }, + { name: 'Abrufen', value: 'get', description: 'Zeitplan abrufen', action: 'Zeitplan abrufen' }, + { name: 'Slots Abrufen', value: 'getSlots', description: 'Verfügbare Slots abrufen', action: 'Slots abrufen' }, + ], + default: 'getAll', + }, + // ===================================================== + // USER OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['user'] } }, + options: [ + { name: 'Alle Abrufen', value: 'getAll', description: 'Alle Benutzer abrufen', action: 'Alle Benutzer abrufen' }, + { name: 'Abrufen', value: 'get', description: 'Benutzer abrufen', action: 'Benutzer abrufen' }, + { name: 'Erstellen', value: 'create', description: 'Neuen Benutzer erstellen (Admin)', action: 'Benutzer erstellen' }, + { name: 'Aktualisieren', value: 'update', description: 'Benutzer aktualisieren (Admin)', action: 'Benutzer aktualisieren' }, + { name: 'Passwort Ändern', value: 'updatePassword', description: 'Benutzer-Passwort ändern (Admin)', action: 'Passwort ändern' }, + { name: 'Löschen', value: 'delete', description: 'Benutzer löschen (Admin)', action: 'Benutzer löschen' }, + ], + default: 'getAll', + }, + // ===================================================== + // ACCOUNT OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['account'] } }, + options: [ + { name: 'Abrufen', value: 'get', description: 'Eigene Kontoinformationen abrufen', action: 'Konto abrufen' }, + { name: 'Erstellen', value: 'create', description: 'Neues Konto erstellen (Registrierung)', action: 'Konto erstellen' }, + { name: 'Aktualisieren', value: 'update', description: 'Eigenes Konto aktualisieren', action: 'Konto aktualisieren' }, + { name: 'Passwort Ändern', value: 'updatePassword', description: 'Eigenes Passwort ändern', action: 'Passwort ändern' }, + ], + default: 'get', + }, + // ===================================================== + // GROUP OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['group'] } }, + options: [ + { name: 'Alle Abrufen', value: 'getAll', description: 'Alle Gruppen abrufen', action: 'Alle Gruppen abrufen' }, + { name: 'Abrufen', value: 'get', description: 'Gruppe abrufen', action: 'Gruppe abrufen' }, + { name: 'Erstellen', value: 'create', description: 'Neue Gruppe erstellen (Admin)', action: 'Gruppe erstellen' }, + { name: 'Aktualisieren', value: 'update', description: 'Gruppe aktualisieren (Admin)', action: 'Gruppe aktualisieren' }, + { name: 'Löschen', value: 'delete', description: 'Gruppe löschen (Admin)', action: 'Gruppe löschen' }, + { name: 'Rollen Ändern', value: 'changeRoles', description: 'Gruppenrollen ändern (Admin)', action: 'Rollen ändern' }, + { name: 'Berechtigungen Ändern', value: 'changePermissions', description: 'Gruppenberechtigungen ändern (Admin)', action: 'Berechtigungen ändern' }, + { name: 'Benutzer Ändern', value: 'changeUsers', description: 'Gruppenbenutzer ändern (Admin)', action: 'Benutzer ändern' }, + ], + default: 'getAll', + }, + // ===================================================== + // ACCESSORY OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['accessory'] } }, + options: [ + { name: 'Alle Abrufen', value: 'getAll', description: 'Alle Zubehörteile abrufen', action: 'Alle Zubehörteile abrufen' }, + { name: 'Abrufen', value: 'get', description: 'Zubehörteil abrufen', action: 'Zubehörteil abrufen' }, + ], + default: 'getAll', + }, + // ===================================================== + // ATTRIBUTE OPERATIONS + // ===================================================== + { + displayName: 'Operation', + name: 'operation', + type: 'options', + noDataExpression: true, + displayOptions: { show: { resource: ['attribute'] } }, + options: [ + { name: 'Abrufen', value: 'get', description: 'Attribut abrufen', action: 'Attribut abrufen' }, + { name: 'Nach Kategorie Abrufen', value: 'getByCategory', description: 'Attribute einer Kategorie abrufen', action: 'Attribute nach Kategorie abrufen' }, + { name: 'Erstellen', value: 'create', description: 'Neues Attribut erstellen (Admin)', action: 'Attribut erstellen' }, + { name: 'Aktualisieren', value: 'update', description: 'Attribut aktualisieren (Admin)', action: 'Attribut aktualisieren' }, + { name: 'Löschen', value: 'delete', description: 'Attribut löschen (Admin)', action: 'Attribut löschen' }, + ], + default: 'getByCategory', + }, + // ===================================================== + // RESERVATION PARAMETERS + // ===================================================== + { + displayName: 'Referenznummer', + name: 'referenceNumber', + type: 'string', + required: true, + displayOptions: { show: { resource: ['reservation'], operation: ['get', 'update', 'delete', 'approve', 'checkIn', 'checkOut'] } }, + default: '', + description: 'Die eindeutige Referenznummer der Reservierung', + }, + { + displayName: 'Ressourcen-ID', + name: 'resourceId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['reservation'], operation: ['create'] } }, + default: 1, + description: 'Die ID der zu reservierenden Ressource', + }, + { + displayName: 'Startzeit', + name: 'startDateTime', + type: 'dateTime', + required: true, + displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } }, + default: '', + description: 'Startzeitpunkt der Reservierung (ISO 8601 Format)', + }, + { + displayName: 'Endzeit', + name: 'endDateTime', + type: 'dateTime', + required: true, + displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } }, + default: '', + description: 'Endzeitpunkt der Reservierung (ISO 8601 Format)', + }, + // PFLICHTFELD: termsAccepted für Reservierung erstellen + { + displayName: 'Nutzungsbedingungen Akzeptiert', + name: 'termsAccepted', + type: 'boolean', + required: true, + displayOptions: { show: { resource: ['reservation'], operation: ['create'] } }, + default: true, + description: 'Ob der Benutzer die Nutzungsbedingungen akzeptiert (Pflichtfeld laut API)', + }, + { + displayName: 'Titel', + name: 'title', + type: 'string', + displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } }, + default: '', + description: 'Titel der Reservierung', + }, + { + displayName: 'Aktualisierungsbereich', + name: 'updateScope', + type: 'options', + displayOptions: { show: { resource: ['reservation'], operation: ['update', 'delete'] } }, + options: [ + { name: 'Nur Diese', value: 'this', description: 'Nur diese Instanz ändern' }, + { name: 'Zukünftige', value: 'future', description: 'Diese und alle zukünftigen Instanzen ändern' }, + { name: 'Alle', value: 'full', description: 'Alle Instanzen der Serie ändern' }, + ], + default: 'this', + }, + // CUSTOM ATTRIBUTES für Reservierungen + { + displayName: 'Benutzerdefinierte Attribute', + name: 'customAttributes', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + placeholder: 'Attribut hinzufügen', + displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } }, + options: [ + { + name: 'attribute', + displayName: 'Attribut', + values: [ + { + displayName: 'Attribut-ID', + name: 'attributeId', + type: 'number', + default: 0, + description: 'Die ID des benutzerdefinierten Attributs', + }, + { + displayName: 'Wert', + name: 'attributeValue', + type: 'string', + default: '', + description: 'Der Wert für dieses Attribut', + }, + ], + }, + ], + description: 'Benutzerdefinierte Attribute für diese Reservierung setzen', + }, + { + displayName: 'Zusätzliche Felder', + name: 'additionalFields', + type: 'collection', + placeholder: 'Feld hinzufügen', + default: {}, + displayOptions: { show: { resource: ['reservation'], operation: ['create', 'update'] } }, + options: [ + { displayName: 'Beschreibung', name: 'description', type: 'string', default: '' }, + { displayName: 'Benutzer-ID', name: 'userId', type: 'number', default: '' }, + { displayName: 'Zusätzliche Ressourcen', name: 'resources', type: 'string', default: '', description: 'Komma-getrennte Liste' }, + { displayName: 'Teilnehmer', name: 'participants', type: 'string', default: '', description: 'Komma-getrennte Benutzer-IDs' }, + { displayName: 'Eingeladene', name: 'invitees', type: 'string', default: '', description: 'Komma-getrennte Benutzer-IDs' }, + { displayName: 'Teilnahme Erlauben', name: 'allowParticipation', type: 'boolean', default: true }, + { displayName: 'Ressourcen-ID (Update)', name: 'resourceId', type: 'number', default: '', description: 'Ressourcen-ID für Updates' }, + ], + }, + { + displayName: 'Filter', + name: 'filters', + type: 'collection', + placeholder: 'Filter hinzufügen', + default: {}, + displayOptions: { show: { resource: ['reservation'], operation: ['getAll'] } }, + options: [ + { displayName: 'Benutzer-ID', name: 'userId', type: 'number', default: '' }, + { displayName: 'Ressourcen-ID', name: 'resourceId', type: 'number', default: '' }, + { displayName: 'Zeitplan-ID', name: 'scheduleId', type: 'number', default: '' }, + { displayName: 'Startzeit', name: 'startDateTime', type: 'dateTime', default: '' }, + { displayName: 'Endzeit', name: 'endDateTime', type: 'dateTime', default: '' }, + { + displayName: 'Custom Attributes Einschließen', + name: 'includeCustomAttributes', + type: 'boolean', + default: false, + description: 'Für jede Reservierung die vollständigen Custom Attributes abrufen (zusätzliche API-Aufrufe)', + }, + ], + }, + // ===================================================== + // RESOURCE PARAMETERS + // ===================================================== + { + displayName: 'Ressourcen-ID', + name: 'resourceIdParam', + type: 'number', + required: true, + displayOptions: { show: { resource: ['resource'], operation: ['get', 'update', 'delete'] } }, + default: 1, + }, + { + displayName: 'Ressourcen-ID (Optional)', + name: 'resourceIdOptional', + type: 'number', + displayOptions: { show: { resource: ['resource'], operation: ['getAvailability'] } }, + default: '', + }, + { + displayName: 'Datum/Zeit', + name: 'availabilityDateTime', + type: 'dateTime', + displayOptions: { show: { resource: ['resource'], operation: ['getAvailability'] } }, + default: '', + }, + { + displayName: 'Ressourcen-Name', + name: 'resourceName', + type: 'string', + required: true, + displayOptions: { show: { resource: ['resource'], operation: ['create', 'update'] } }, + default: '', + }, + { + displayName: 'Zeitplan-ID', + name: 'scheduleIdForResource', + type: 'number', + required: true, + displayOptions: { show: { resource: ['resource'], operation: ['create'] } }, + default: 1, + description: 'Die ID des Zeitplans für diese Ressource (Pflichtfeld)', + }, + // CUSTOM ATTRIBUTES für Ressourcen + { + displayName: 'Benutzerdefinierte Attribute', + name: 'resourceCustomAttributes', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + placeholder: 'Attribut hinzufügen', + displayOptions: { show: { resource: ['resource'], operation: ['create', 'update'] } }, + options: [ + { + name: 'attribute', + displayName: 'Attribut', + values: [ + { + displayName: 'Attribut-ID', + name: 'attributeId', + type: 'number', + default: 0, + description: 'Die ID des benutzerdefinierten Attributs', + }, + { + displayName: 'Wert', + name: 'attributeValue', + type: 'string', + default: '', + description: 'Der Wert für dieses Attribut', + }, + ], + }, + ], + description: 'Benutzerdefinierte Attribute für diese Ressource setzen', + }, + { + displayName: 'Ressourcen-Optionen', + name: 'resourceOptions', + type: 'collection', + placeholder: 'Option hinzufügen', + default: {}, + displayOptions: { show: { resource: ['resource'], operation: ['create', 'update'] } }, + options: [ + { displayName: 'Standort', name: 'location', type: 'string', default: '' }, + { displayName: 'Kontakt', name: 'contact', type: 'string', default: '' }, + { displayName: 'Beschreibung', name: 'description', type: 'string', default: '' }, + { displayName: 'Notizen', name: 'notes', type: 'string', default: '' }, + { displayName: 'Max. Teilnehmer', name: 'maxParticipants', type: 'number', default: 0 }, + { displayName: 'Genehmigung Erforderlich', name: 'requiresApproval', type: 'boolean', default: false }, + { displayName: 'Mehrtägig Erlauben', name: 'allowMultiday', type: 'boolean', default: false }, + { displayName: 'Check-In Erforderlich', name: 'requiresCheckIn', type: 'boolean', default: false }, + { displayName: 'Auto-Release Minuten', name: 'autoReleaseMinutes', type: 'number', default: 0 }, + { displayName: 'Farbe', name: 'color', type: 'string', default: '' }, + { displayName: 'Status-ID', name: 'statusId', type: 'options', options: [{ name: 'Versteckt', value: 0 }, { name: 'Verfügbar', value: 1 }, { name: 'Nicht Verfügbar', value: 2 }], default: 1 }, + ], + }, + { + displayName: 'Ressourcen-Abruf-Optionen', + name: 'resourceGetAllOptions', + type: 'collection', + placeholder: 'Option hinzufügen', + default: {}, + displayOptions: { show: { resource: ['resource'], operation: ['getAll'] } }, + options: [ + { + displayName: 'Custom Attributes Einschließen', + name: 'includeCustomAttributes', + type: 'boolean', + default: false, + description: 'Für jede Ressource die vollständigen Custom Attributes abrufen (zusätzliche API-Aufrufe)', + }, + ], + }, + // ===================================================== + // SCHEDULE PARAMETERS + // ===================================================== + { + displayName: 'Zeitplan-ID', + name: 'scheduleId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['schedule'], operation: ['get', 'getSlots'] } }, + default: 1, + }, + { + displayName: 'Slots-Filter', + name: 'slotsFilters', + type: 'collection', + placeholder: 'Filter hinzufügen', + default: {}, + displayOptions: { show: { resource: ['schedule'], operation: ['getSlots'] } }, + options: [ + { displayName: 'Ressourcen-ID', name: 'resourceId', type: 'number', default: '' }, + { displayName: 'Startzeit', name: 'startDateTime', type: 'dateTime', default: '' }, + { displayName: 'Endzeit', name: 'endDateTime', type: 'dateTime', default: '' }, + ], + }, + // ===================================================== + // USER PARAMETERS + // ===================================================== + { + displayName: 'Benutzer-ID', + name: 'userId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['user'], operation: ['get', 'update', 'updatePassword', 'delete'] } }, + default: 1, + }, + { + displayName: 'E-Mail', + name: 'emailAddress', + type: 'string', + required: true, + displayOptions: { show: { resource: ['user'], operation: ['create'] } }, + default: '', + description: 'E-Mail-Adresse des Benutzers (Pflichtfeld)', + }, + { + displayName: 'Benutzername', + name: 'userName', + type: 'string', + required: true, + displayOptions: { show: { resource: ['user'], operation: ['create'] } }, + default: '', + description: 'Benutzername für die Anmeldung (Pflichtfeld)', + }, + { + displayName: 'Passwort', + name: 'password', + type: 'string', + typeOptions: { password: true }, + required: true, + displayOptions: { show: { resource: ['user'], operation: ['create', 'updatePassword'] } }, + default: '', + description: 'Passwort des Benutzers (Pflichtfeld)', + }, + { + displayName: 'Vorname', + name: 'firstName', + type: 'string', + required: true, + displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } }, + default: '', + description: 'Vorname des Benutzers (Pflichtfeld)', + }, + { + displayName: 'Nachname', + name: 'lastName', + type: 'string', + required: true, + displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } }, + default: '', + description: 'Nachname des Benutzers (Pflichtfeld)', + }, + // Custom Attributes für Benutzer + { + displayName: 'Benutzerdefinierte Attribute', + name: 'userCustomAttributes', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + placeholder: 'Attribut hinzufügen', + displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } }, + options: [ + { + name: 'attribute', + displayName: 'Attribut', + values: [ + { + displayName: 'Attribut-ID', + name: 'attributeId', + type: 'number', + default: 0, + description: 'Die ID des benutzerdefinierten Attributs', + }, + { + displayName: 'Wert', + name: 'attributeValue', + type: 'string', + default: '', + description: 'Der Wert für dieses Attribut', + }, + ], + }, + ], + description: 'Benutzerdefinierte Attribute für diesen Benutzer setzen', + }, + { + displayName: 'Benutzer-Filter', + name: 'userFilters', + type: 'collection', + placeholder: 'Filter hinzufügen', + default: {}, + displayOptions: { show: { resource: ['user'], operation: ['getAll'] } }, + options: [ + { displayName: 'Benutzername', name: 'username', type: 'string', default: '' }, + { displayName: 'E-Mail', name: 'email', type: 'string', default: '' }, + { displayName: 'Vorname', name: 'firstName', type: 'string', default: '' }, + { displayName: 'Nachname', name: 'lastName', type: 'string', default: '' }, + { displayName: 'Organisation', name: 'organization', type: 'string', default: '' }, + { + displayName: 'Custom Attributes Einschließen', + name: 'includeCustomAttributes', + type: 'boolean', + default: false, + description: 'Für jeden Benutzer die vollständigen Custom Attributes abrufen (zusätzliche API-Aufrufe)', + }, + ], + }, + { + displayName: 'Benutzer-Optionen', + name: 'userOptions', + type: 'collection', + placeholder: 'Option hinzufügen', + default: {}, + displayOptions: { show: { resource: ['user'], operation: ['create', 'update'] } }, + options: [ + { displayName: 'Zeitzone', name: 'timezone', type: 'string', default: 'Europe/Berlin' }, + { displayName: 'Sprache', name: 'language', type: 'string', default: 'de_de' }, + { displayName: 'Telefon', name: 'phone', type: 'string', default: '' }, + { displayName: 'Organisation', name: 'organization', type: 'string', default: '' }, + { displayName: 'Position', name: 'position', type: 'string', default: '' }, + { displayName: 'Gruppen', name: 'groups', type: 'string', default: '', description: 'Komma-getrennte Gruppen-IDs' }, + ], + }, + // ===================================================== + // ACCOUNT PARAMETERS + // ===================================================== + { + displayName: 'Benutzer-ID', + name: 'accountUserId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['account'], operation: ['get', 'update', 'updatePassword'] } }, + default: '', + }, + // Custom Attributes für Accounts + { + displayName: 'Benutzerdefinierte Attribute', + name: 'accountCustomAttributes', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + placeholder: 'Attribut hinzufügen', + displayOptions: { show: { resource: ['account'], operation: ['create', 'update'] } }, + options: [ + { + name: 'attribute', + displayName: 'Attribut', + values: [ + { + displayName: 'Attribut-ID', + name: 'attributeId', + type: 'number', + default: 0, + description: 'Die ID des benutzerdefinierten Attributs', + }, + { + displayName: 'Wert', + name: 'attributeValue', + type: 'string', + default: '', + description: 'Der Wert für dieses Attribut', + }, + ], + }, + ], + description: 'Benutzerdefinierte Attribute für dieses Konto setzen', + }, + { + displayName: 'Account-Daten', + name: 'accountData', + type: 'collection', + placeholder: 'Feld hinzufügen', + default: {}, + displayOptions: { show: { resource: ['account'], operation: ['create', 'update'] } }, + options: [ + { displayName: 'E-Mail', name: 'emailAddress', type: 'string', default: '' }, + { displayName: 'Benutzername', name: 'userName', type: 'string', default: '' }, + { displayName: 'Passwort', name: 'password', type: 'string', typeOptions: { password: true }, default: '' }, + { displayName: 'Vorname', name: 'firstName', type: 'string', default: '' }, + { displayName: 'Nachname', name: 'lastName', type: 'string', default: '' }, + { displayName: 'Zeitzone', name: 'timezone', type: 'string', default: 'Europe/Berlin' }, + { displayName: 'Sprache', name: 'language', type: 'string', default: 'de_de' }, + { displayName: 'Telefon', name: 'phone', type: 'string', default: '' }, + { displayName: 'Organisation', name: 'organization', type: 'string', default: '' }, + { displayName: 'Position', name: 'position', type: 'string', default: '' }, + { displayName: 'AGB Akzeptiert', name: 'acceptTermsOfService', type: 'boolean', default: true }, + ], + }, + { + displayName: 'Passwort-Änderung', + name: 'passwordChange', + type: 'fixedCollection', + default: {}, + displayOptions: { show: { resource: ['account'], operation: ['updatePassword'] } }, + options: [ + { + name: 'passwords', + displayName: 'Passwörter', + values: [ + { displayName: 'Aktuelles Passwort', name: 'currentPassword', type: 'string', typeOptions: { password: true }, default: '' }, + { displayName: 'Neues Passwort', name: 'newPassword', type: 'string', typeOptions: { password: true }, default: '' }, + ], + }, + ], + }, + // ===================================================== + // GROUP PARAMETERS + // ===================================================== + { + displayName: 'Gruppen-ID', + name: 'groupId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['group'], operation: ['get', 'update', 'delete', 'changeRoles', 'changePermissions', 'changeUsers'] } }, + default: 1, + }, + { + displayName: 'Gruppen-Name', + name: 'groupName', + type: 'string', + required: true, + displayOptions: { show: { resource: ['group'], operation: ['create', 'update'] } }, + default: '', + description: 'Name der Gruppe (Pflichtfeld)', + }, + { + displayName: 'Standard-Gruppe', + name: 'isDefault', + type: 'boolean', + displayOptions: { show: { resource: ['group'], operation: ['create', 'update'] } }, + default: false, + }, + { + displayName: 'Rollen-IDs', + name: 'roleIds', + type: 'string', + displayOptions: { show: { resource: ['group'], operation: ['changeRoles'] } }, + default: '', + description: '1=Gruppenadmin, 2=App-Admin, 3=Ressourcen-Admin, 4=Zeitplan-Admin', + }, + { + displayName: 'Ressourcen-IDs', + name: 'permissionResourceIds', + type: 'string', + displayOptions: { show: { resource: ['group'], operation: ['changePermissions'] } }, + default: '', + }, + { + displayName: 'Benutzer-IDs', + name: 'groupUserIds', + type: 'string', + displayOptions: { show: { resource: ['group'], operation: ['changeUsers'] } }, + default: '', + }, + // ===================================================== + // ACCESSORY PARAMETERS + // ===================================================== + { + displayName: 'Zubehör-ID', + name: 'accessoryId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['accessory'], operation: ['get'] } }, + default: 1, + }, + // ===================================================== + // ATTRIBUTE PARAMETERS + // ===================================================== + { + displayName: 'Attribut-ID', + name: 'attributeId', + type: 'number', + required: true, + displayOptions: { show: { resource: ['attribute'], operation: ['get', 'update', 'delete'] } }, + default: 1, + }, + { + displayName: 'Kategorie-ID', + name: 'categoryId', + type: 'options', + required: true, + displayOptions: { show: { resource: ['attribute'], operation: ['getByCategory', 'create'] } }, + options: [ + { name: 'Reservierung', value: 1 }, + { name: 'Benutzer', value: 2 }, + { name: 'Ressource', value: 4 }, + { name: 'Ressourcen-Typ', value: 5 }, + ], + default: 1, + }, + { + displayName: 'Attribut-Label', + name: 'attributeLabel', + type: 'string', + required: true, + displayOptions: { show: { resource: ['attribute'], operation: ['create', 'update'] } }, + default: '', + description: 'Anzeigename des Attributs (Pflichtfeld)', + }, + { + displayName: 'Attribut-Typ', + name: 'attributeType', + type: 'options', + required: true, + displayOptions: { show: { resource: ['attribute'], operation: ['create', 'update'] } }, + options: [ + { name: 'Einzeilig', value: 1 }, + { name: 'Mehrzeilig', value: 2 }, + { name: 'Auswahlliste', value: 3 }, + { name: 'Checkbox', value: 4 }, + { name: 'Datum/Zeit', value: 5 }, + ], + default: 1, + }, + { + displayName: 'Attribut-Optionen', + name: 'attributeOptions', + type: 'collection', + placeholder: 'Option hinzufügen', + default: {}, + displayOptions: { show: { resource: ['attribute'], operation: ['create', 'update'] } }, + options: [ + { displayName: 'Erforderlich', name: 'required', type: 'boolean', default: false }, + { displayName: 'Nur Admin', name: 'adminOnly', type: 'boolean', default: false }, + { displayName: 'Privat', name: 'isPrivate', type: 'boolean', default: false }, + { displayName: 'Sortierung', name: 'sortOrder', type: 'number', default: 0 }, + { displayName: 'Regex-Validierung', name: 'regex', type: 'string', default: '' }, + { displayName: 'Mögliche Werte', name: 'possibleValues', type: 'string', default: '', description: 'Komma-getrennt' }, + ], + }, + ], + }; + } + async execute() { + const items = this.getInputData(); + const returnData = []; + const credentials = await this.getCredentials('libreBookingApi'); + const baseUrl = credentials.url.replace(/\/$/, ''); + const username = credentials.username; + const pw = credentials.password; + // Config-Defaults laden + const configDefaults = await getConfigDefaults(this); + const session = await authenticate(this, baseUrl, username, pw); + try { + for (let i = 0; i < items.length; i++) { + try { + const resource = this.getNodeParameter('resource', i); + const operation = this.getNodeParameter('operation', i); + let responseData; + // RESERVATION + if (resource === 'reservation') { + if (operation === 'getAll') { + const filters = this.getNodeParameter('filters', i, {}); + const qs = {}; + if (filters.userId) + qs.userId = filters.userId; + if (filters.resourceId) + qs.resourceId = filters.resourceId; + if (filters.scheduleId) + qs.scheduleId = filters.scheduleId; + if (filters.startDateTime) + qs.startDateTime = filters.startDateTime; + if (filters.endDateTime) + qs.endDateTime = filters.endDateTime; + let response = await makeApiRequest(this, baseUrl, session, 'GET', '/Reservations/', undefined, qs); + // If includeCustomAttributes is enabled, fetch details for each reservation + if (filters.includeCustomAttributes && response.reservations && response.reservations.length > 0) { + const enrichedReservations = []; + for (const reservation of response.reservations) { + try { + const details = await makeApiRequest(this, baseUrl, session, 'GET', `/Reservations/${reservation.referenceNumber}`); + enrichedReservations.push({ + ...reservation, + customAttributes: details.customAttributes || [], + owner: details.owner, + participants: details.participants || [], + invitees: details.invitees || [], + }); + } + catch (error) { + // Fallback to original reservation data + enrichedReservations.push(reservation); + } + } + response = { ...response, reservations: enrichedReservations }; + } + responseData = response; + } + else if (operation === 'get') { + const referenceNumber = this.getNodeParameter('referenceNumber', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Reservations/${referenceNumber}`); + } + else if (operation === 'create') { + const resourceId = this.getNodeParameter('resourceId', i); + const startDateTime = this.getNodeParameter('startDateTime', i); + const endDateTime = this.getNodeParameter('endDateTime', i); + const termsAccepted = this.getNodeParameter('termsAccepted', i, configDefaults.defaultTermsAccepted); + const title = this.getNodeParameter('title', i, ''); + const customAttributes = this.getNodeParameter('customAttributes', i, {}); + const additionalFields = this.getNodeParameter('additionalFields', i, {}); + const body = { + resourceId, + startDateTime: new Date(startDateTime).toISOString(), + endDateTime: new Date(endDateTime).toISOString(), + termsAccepted, + }; + if (title) + body.title = title; + if (additionalFields.description) + body.description = additionalFields.description; + if (additionalFields.userId) + body.userId = additionalFields.userId; + if (additionalFields.resources) + body.resources = parseIdList(additionalFields.resources); + if (additionalFields.participants) + body.participants = parseIdList(additionalFields.participants); + if (additionalFields.invitees) + body.invitees = parseIdList(additionalFields.invitees); + // allowParticipation is REQUIRED by the API + body.allowParticipation = additionalFields.allowParticipation !== undefined + ? additionalFields.allowParticipation + : configDefaults.defaultAllowParticipation; + // Custom Attributes verarbeiten + if ((customAttributes === null || customAttributes === void 0 ? void 0 : customAttributes.attribute) && customAttributes.attribute.length > 0) { + body.customAttributes = customAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Reservations/', body); + } + else if (operation === 'update') { + const referenceNumber = this.getNodeParameter('referenceNumber', i); + const startDateTime = this.getNodeParameter('startDateTime', i); + const endDateTime = this.getNodeParameter('endDateTime', i); + const title = this.getNodeParameter('title', i, ''); + const updateScope = this.getNodeParameter('updateScope', i, 'this'); + const customAttributes = this.getNodeParameter('customAttributes', i, {}); + const additionalFields = this.getNodeParameter('additionalFields', i, {}); + const body = { + startDateTime: new Date(startDateTime).toISOString(), + endDateTime: new Date(endDateTime).toISOString(), + termsAccepted: true, // termsAccepted wird auch bei Updates benötigt + }; + if (title) + body.title = title; + if (additionalFields.description) + body.description = additionalFields.description; + if (additionalFields.resourceId) + body.resourceId = additionalFields.resourceId; + if (additionalFields.userId) + body.userId = additionalFields.userId; + if (additionalFields.resources) + body.resources = parseIdList(additionalFields.resources); + if (additionalFields.participants) + body.participants = parseIdList(additionalFields.participants); + if (additionalFields.invitees) + body.invitees = parseIdList(additionalFields.invitees); + // allowParticipation is REQUIRED by the API + body.allowParticipation = additionalFields.allowParticipation !== undefined + ? additionalFields.allowParticipation + : false; + // Custom Attributes verarbeiten + if ((customAttributes === null || customAttributes === void 0 ? void 0 : customAttributes.attribute) && customAttributes.attribute.length > 0) { + body.customAttributes = customAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}?updateScope=${updateScope}`, body); + } + else if (operation === 'delete') { + const referenceNumber = this.getNodeParameter('referenceNumber', i); + const updateScope = this.getNodeParameter('updateScope', i, 'this'); + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Reservations/${referenceNumber}?updateScope=${updateScope}`); + } + else if (operation === 'approve') { + const referenceNumber = this.getNodeParameter('referenceNumber', i); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/Approval`); + } + else if (operation === 'checkIn') { + const referenceNumber = this.getNodeParameter('referenceNumber', i); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckIn`); + } + else if (operation === 'checkOut') { + const referenceNumber = this.getNodeParameter('referenceNumber', i); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckOut`); + } + } + // RESOURCE + else if (resource === 'resource') { + if (operation === 'getAll') { + const resourceGetAllOptions = this.getNodeParameter('resourceGetAllOptions', i, {}); + let response = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/'); + // If includeCustomAttributes is enabled, fetch details for each resource + if (resourceGetAllOptions.includeCustomAttributes && response.resources && response.resources.length > 0) { + const enrichedResources = []; + for (const res of response.resources) { + try { + const details = await makeApiRequest(this, baseUrl, session, 'GET', `/Resources/${res.resourceId}`); + enrichedResources.push({ + ...res, + customAttributes: details.customAttributes || [], + }); + } + catch (error) { + // Fallback to original resource data + enrichedResources.push(res); + } + } + response = { ...response, resources: enrichedResources }; + } + responseData = response; + } + else if (operation === 'get') { + const resourceIdParam = this.getNodeParameter('resourceIdParam', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Resources/${resourceIdParam}`); + } + else if (operation === 'getAvailability') { + const resourceIdOptional = this.getNodeParameter('resourceIdOptional', i, ''); + const availabilityDateTime = this.getNodeParameter('availabilityDateTime', i, ''); + let endpoint = '/Resources/Availability'; + if (resourceIdOptional) + endpoint = `/Resources/${resourceIdOptional}/Availability`; + const qs = {}; + if (availabilityDateTime) + qs.dateTime = new Date(availabilityDateTime).toISOString(); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', endpoint, undefined, qs); + } + else if (operation === 'getGroups') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Groups'); + } + else if (operation === 'getTypes') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Types'); + } + else if (operation === 'getStatuses') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Status'); + } + else if (operation === 'create') { + const resourceName = this.getNodeParameter('resourceName', i); + const scheduleIdForResource = this.getNodeParameter('scheduleIdForResource', i); + const resourceCustomAttributes = this.getNodeParameter('resourceCustomAttributes', i, {}); + const resourceOptions = this.getNodeParameter('resourceOptions', i, {}); + const body = { name: resourceName, scheduleId: scheduleIdForResource }; + if (resourceOptions.location) + body.location = resourceOptions.location; + if (resourceOptions.contact) + body.contact = resourceOptions.contact; + if (resourceOptions.description) + body.description = resourceOptions.description; + if (resourceOptions.notes) + body.notes = resourceOptions.notes; + if (resourceOptions.maxParticipants) + body.maxParticipants = resourceOptions.maxParticipants; + if (resourceOptions.requiresApproval !== undefined) + body.requiresApproval = resourceOptions.requiresApproval; + if (resourceOptions.allowMultiday !== undefined) + body.allowMultiday = resourceOptions.allowMultiday; + if (resourceOptions.requiresCheckIn !== undefined) + body.requiresCheckIn = resourceOptions.requiresCheckIn; + if (resourceOptions.autoReleaseMinutes) + body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes; + if (resourceOptions.color) + body.color = resourceOptions.color; + if (resourceOptions.statusId !== undefined) + body.statusId = resourceOptions.statusId; + // Custom Attributes verarbeiten + if ((resourceCustomAttributes === null || resourceCustomAttributes === void 0 ? void 0 : resourceCustomAttributes.attribute) && resourceCustomAttributes.attribute.length > 0) { + body.customAttributes = resourceCustomAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Resources/', body); + } + else if (operation === 'update') { + const resourceIdParam = this.getNodeParameter('resourceIdParam', i); + const resourceName = this.getNodeParameter('resourceName', i); + const resourceCustomAttributes = this.getNodeParameter('resourceCustomAttributes', i, {}); + const resourceOptions = this.getNodeParameter('resourceOptions', i, {}); + const body = { name: resourceName }; + if (resourceOptions.location) + body.location = resourceOptions.location; + if (resourceOptions.contact) + body.contact = resourceOptions.contact; + if (resourceOptions.description) + body.description = resourceOptions.description; + if (resourceOptions.notes) + body.notes = resourceOptions.notes; + if (resourceOptions.maxParticipants) + body.maxParticipants = resourceOptions.maxParticipants; + if (resourceOptions.requiresApproval !== undefined) + body.requiresApproval = resourceOptions.requiresApproval; + if (resourceOptions.allowMultiday !== undefined) + body.allowMultiday = resourceOptions.allowMultiday; + if (resourceOptions.requiresCheckIn !== undefined) + body.requiresCheckIn = resourceOptions.requiresCheckIn; + if (resourceOptions.autoReleaseMinutes) + body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes; + if (resourceOptions.color) + body.color = resourceOptions.color; + if (resourceOptions.statusId !== undefined) + body.statusId = resourceOptions.statusId; + // Custom Attributes verarbeiten + if ((resourceCustomAttributes === null || resourceCustomAttributes === void 0 ? void 0 : resourceCustomAttributes.attribute) && resourceCustomAttributes.attribute.length > 0) { + body.customAttributes = resourceCustomAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Resources/${resourceIdParam}`, body); + } + else if (operation === 'delete') { + const resourceIdParam = this.getNodeParameter('resourceIdParam', i); + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Resources/${resourceIdParam}`); + } + } + // SCHEDULE + else if (resource === 'schedule') { + if (operation === 'getAll') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Schedules/'); + } + else if (operation === 'get') { + const scheduleId = this.getNodeParameter('scheduleId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}`); + } + else if (operation === 'getSlots') { + const scheduleId = this.getNodeParameter('scheduleId', i); + const slotsFilters = this.getNodeParameter('slotsFilters', i, {}); + const qs = {}; + if (slotsFilters.resourceId) + qs.resourceId = slotsFilters.resourceId; + if (slotsFilters.startDateTime) + qs.startDateTime = new Date(slotsFilters.startDateTime).toISOString(); + if (slotsFilters.endDateTime) + qs.endDateTime = new Date(slotsFilters.endDateTime).toISOString(); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}/Slots`, undefined, qs); + } + } + // USER + else if (resource === 'user') { + if (operation === 'getAll') { + const userFilters = this.getNodeParameter('userFilters', i, {}); + const qs = {}; + if (userFilters.username) + qs.username = userFilters.username; + if (userFilters.email) + qs.email = userFilters.email; + if (userFilters.firstName) + qs.firstName = userFilters.firstName; + if (userFilters.lastName) + qs.lastName = userFilters.lastName; + if (userFilters.organization) + qs.organization = userFilters.organization; + let response = await makeApiRequest(this, baseUrl, session, 'GET', '/Users/', undefined, qs); + // If includeCustomAttributes is enabled, fetch details for each user + if (userFilters.includeCustomAttributes && response.users && response.users.length > 0) { + const enrichedUsers = []; + for (const user of response.users) { + try { + const details = await makeApiRequest(this, baseUrl, session, 'GET', `/Users/${user.id}`); + enrichedUsers.push({ + ...user, + customAttributes: details.customAttributes || [], + }); + } + catch (error) { + // Fallback to original user data + enrichedUsers.push(user); + } + } + response = { ...response, users: enrichedUsers }; + } + responseData = response; + } + else if (operation === 'get') { + const userId = this.getNodeParameter('userId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Users/${userId}`); + } + else if (operation === 'create') { + const emailAddress = this.getNodeParameter('emailAddress', i); + const userName = this.getNodeParameter('userName', i); + const userPw = this.getNodeParameter('password', i); + const firstName = this.getNodeParameter('firstName', i); + const lastName = this.getNodeParameter('lastName', i); + const userCustomAttributes = this.getNodeParameter('userCustomAttributes', i, {}); + const userOptions = this.getNodeParameter('userOptions', i, {}); + const body = { emailAddress, userName, password: userPw, firstName, lastName }; + body.timezone = userOptions.timezone || configDefaults.defaultTimezone; + body.language = userOptions.language || configDefaults.defaultLanguage; + if (userOptions.phone) + body.phone = userOptions.phone; + if (userOptions.organization) + body.organization = userOptions.organization; + if (userOptions.position) + body.position = userOptions.position; + if (userOptions.groups) + body.groups = parseIdList(userOptions.groups); + // Custom Attributes verarbeiten + if ((userCustomAttributes === null || userCustomAttributes === void 0 ? void 0 : userCustomAttributes.attribute) && userCustomAttributes.attribute.length > 0) { + body.customAttributes = userCustomAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Users/', body); + } + else if (operation === 'update') { + const userId = this.getNodeParameter('userId', i); + const firstName = this.getNodeParameter('firstName', i); + const lastName = this.getNodeParameter('lastName', i); + const userCustomAttributes = this.getNodeParameter('userCustomAttributes', i, {}); + const userOptions = this.getNodeParameter('userOptions', i, {}); + const body = { firstName, lastName }; + if (userOptions.timezone) + body.timezone = userOptions.timezone; + if (userOptions.language) + body.language = userOptions.language; + if (userOptions.phone) + body.phone = userOptions.phone; + if (userOptions.organization) + body.organization = userOptions.organization; + if (userOptions.position) + body.position = userOptions.position; + if (userOptions.groups) + body.groups = parseIdList(userOptions.groups); + // Custom Attributes verarbeiten + if ((userCustomAttributes === null || userCustomAttributes === void 0 ? void 0 : userCustomAttributes.attribute) && userCustomAttributes.attribute.length > 0) { + body.customAttributes = userCustomAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}`, body); + } + else if (operation === 'updatePassword') { + const userId = this.getNodeParameter('userId', i); + const userPw = this.getNodeParameter('password', i); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}/Password`, { password: userPw }); + } + else if (operation === 'delete') { + const userId = this.getNodeParameter('userId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Users/${userId}`); + } + } + // ACCOUNT + else if (resource === 'account') { + if (operation === 'get') { + const accountUserId = this.getNodeParameter('accountUserId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accounts/${accountUserId}`); + } + else if (operation === 'create') { + const accountData = this.getNodeParameter('accountData', i, {}); + const accountCustomAttributes = this.getNodeParameter('accountCustomAttributes', i, {}); + const body = {}; + if (accountData.emailAddress) + body.emailAddress = accountData.emailAddress; + if (accountData.userName) + body.userName = accountData.userName; + if (accountData.password) + body.password = accountData.password; + if (accountData.firstName) + body.firstName = accountData.firstName; + if (accountData.lastName) + body.lastName = accountData.lastName; + body.timezone = accountData.timezone || configDefaults.defaultTimezone; + body.language = accountData.language || configDefaults.defaultLanguage; + if (accountData.phone) + body.phone = accountData.phone; + if (accountData.organization) + body.organization = accountData.organization; + if (accountData.position) + body.position = accountData.position; + if (accountData.acceptTermsOfService !== undefined) { + body.acceptTermsOfService = accountData.acceptTermsOfService; + } + else { + body.acceptTermsOfService = configDefaults.defaultTermsAccepted; + } + // Custom Attributes verarbeiten + if ((accountCustomAttributes === null || accountCustomAttributes === void 0 ? void 0 : accountCustomAttributes.attribute) && accountCustomAttributes.attribute.length > 0) { + body.customAttributes = accountCustomAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Accounts/', body); + } + else if (operation === 'update') { + const accountUserId = this.getNodeParameter('accountUserId', i); + const accountData = this.getNodeParameter('accountData', i, {}); + const accountCustomAttributes = this.getNodeParameter('accountCustomAttributes', i, {}); + const body = {}; + if (accountData.emailAddress) + body.emailAddress = accountData.emailAddress; + if (accountData.userName) + body.userName = accountData.userName; + if (accountData.firstName) + body.firstName = accountData.firstName; + if (accountData.lastName) + body.lastName = accountData.lastName; + if (accountData.timezone) + body.timezone = accountData.timezone; + if (accountData.language) + body.language = accountData.language; + if (accountData.phone) + body.phone = accountData.phone; + if (accountData.organization) + body.organization = accountData.organization; + if (accountData.position) + body.position = accountData.position; + // Custom Attributes verarbeiten + if ((accountCustomAttributes === null || accountCustomAttributes === void 0 ? void 0 : accountCustomAttributes.attribute) && accountCustomAttributes.attribute.length > 0) { + body.customAttributes = accountCustomAttributes.attribute.map((attr) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}`, body); + } + else if (operation === 'updatePassword') { + const accountUserId = this.getNodeParameter('accountUserId', i); + const passwordChange = this.getNodeParameter('passwordChange', i, {}); + const passwords = passwordChange.passwords || {}; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}/Password`, { + currentPassword: passwords.currentPassword, + newPassword: passwords.newPassword, + }); + } + } + // GROUP + else if (resource === 'group') { + if (operation === 'getAll') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Groups/'); + } + else if (operation === 'get') { + const groupId = this.getNodeParameter('groupId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Groups/${groupId}`); + } + else if (operation === 'create') { + const groupName = this.getNodeParameter('groupName', i); + const isDefault = this.getNodeParameter('isDefault', i, false); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Groups/', { name: groupName, isDefault }); + } + else if (operation === 'update') { + const groupId = this.getNodeParameter('groupId', i); + const groupName = this.getNodeParameter('groupName', i); + const isDefault = this.getNodeParameter('isDefault', i, false); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}`, { name: groupName, isDefault }); + } + else if (operation === 'delete') { + const groupId = this.getNodeParameter('groupId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Groups/${groupId}`); + } + else if (operation === 'changeRoles') { + const groupId = this.getNodeParameter('groupId', i); + const roleIds = this.getNodeParameter('roleIds', i, ''); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Roles`, { roleIds: parseIdList(roleIds) }); + } + else if (operation === 'changePermissions') { + const groupId = this.getNodeParameter('groupId', i); + const permissionResourceIds = this.getNodeParameter('permissionResourceIds', i, ''); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Permissions`, { resourceIds: parseIdList(permissionResourceIds) }); + } + else if (operation === 'changeUsers') { + const groupId = this.getNodeParameter('groupId', i); + const groupUserIds = this.getNodeParameter('groupUserIds', i, ''); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Users`, { userIds: parseIdList(groupUserIds) }); + } + } + // ACCESSORY + else if (resource === 'accessory') { + if (operation === 'getAll') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Accessories/'); + } + else if (operation === 'get') { + const accessoryId = this.getNodeParameter('accessoryId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accessories/${accessoryId}`); + } + } + // ATTRIBUTE + else if (resource === 'attribute') { + if (operation === 'get') { + const attributeId = this.getNodeParameter('attributeId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/${attributeId}`); + } + else if (operation === 'getByCategory') { + const categoryId = this.getNodeParameter('categoryId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/Category/${categoryId}`); + } + else if (operation === 'create') { + const attributeLabel = this.getNodeParameter('attributeLabel', i); + const attributeType = this.getNodeParameter('attributeType', i); + const categoryId = this.getNodeParameter('categoryId', i); + const attributeOptions = this.getNodeParameter('attributeOptions', i, {}); + const body = { label: attributeLabel, type: attributeType, categoryId }; + if (attributeOptions.required !== undefined) + body.required = attributeOptions.required; + if (attributeOptions.adminOnly !== undefined) + body.adminOnly = attributeOptions.adminOnly; + if (attributeOptions.isPrivate !== undefined) + body.isPrivate = attributeOptions.isPrivate; + if (attributeOptions.sortOrder !== undefined) + body.sortOrder = attributeOptions.sortOrder; + if (attributeOptions.regex) + body.regex = attributeOptions.regex; + if (attributeOptions.possibleValues) + body.possibleValues = attributeOptions.possibleValues.split(',').map((v) => v.trim()); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Attributes/', body); + } + else if (operation === 'update') { + const attributeId = this.getNodeParameter('attributeId', i); + const attributeLabel = this.getNodeParameter('attributeLabel', i); + const attributeType = this.getNodeParameter('attributeType', i); + const attributeOptions = this.getNodeParameter('attributeOptions', i, {}); + const body = { label: attributeLabel, type: attributeType }; + if (attributeOptions.required !== undefined) + body.required = attributeOptions.required; + if (attributeOptions.adminOnly !== undefined) + body.adminOnly = attributeOptions.adminOnly; + if (attributeOptions.isPrivate !== undefined) + body.isPrivate = attributeOptions.isPrivate; + if (attributeOptions.sortOrder !== undefined) + body.sortOrder = attributeOptions.sortOrder; + if (attributeOptions.regex) + body.regex = attributeOptions.regex; + if (attributeOptions.possibleValues) + body.possibleValues = attributeOptions.possibleValues.split(',').map((v) => v.trim()); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Attributes/${attributeId}`, body); + } + else if (operation === 'delete') { + const attributeId = this.getNodeParameter('attributeId', i); + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Attributes/${attributeId}`); + } + } + // Process response + if (responseData) { + if (Array.isArray(responseData)) { + returnData.push(...responseData.map(item => ({ json: item }))); + } + else if (responseData.reservations) { + returnData.push(...responseData.reservations.map((item) => ({ json: item }))); + } + else if (responseData.resources) { + returnData.push(...responseData.resources.map((item) => ({ json: item }))); + } + else if (responseData.schedules) { + returnData.push(...responseData.schedules.map((item) => ({ json: item }))); + } + else if (responseData.users) { + returnData.push(...responseData.users.map((item) => ({ json: item }))); + } + else if (responseData.groups) { + returnData.push(...responseData.groups.map((item) => ({ json: item }))); + } + else if (responseData.accessories) { + returnData.push(...responseData.accessories.map((item) => ({ json: item }))); + } + else if (responseData.attributes) { + returnData.push(...responseData.attributes.map((item) => ({ json: item }))); + } + else { + returnData.push({ json: responseData }); + } + } + } + catch (error) { + if (this.continueOnFail()) { + returnData.push({ json: { error: error.message } }); + continue; + } + throw error; + } + } + } + finally { + await signOut(this, baseUrl, session); + } + return [returnData]; + } +} +exports.LibreBooking = LibreBooking; +//# sourceMappingURL=LibreBooking.node.js.map \ No newline at end of file diff --git a/dist/nodes/LibreBooking/LibreBooking.node.js.map b/dist/nodes/LibreBooking/LibreBooking.node.js.map new file mode 100644 index 0000000..e01058e --- /dev/null +++ b/dist/nodes/LibreBooking/LibreBooking.node.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBooking.node.js","sourceRoot":"","sources":["../../../nodes/LibreBooking/LibreBooking.node.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/nodes/LibreBooking/librebooking.svg b/dist/nodes/LibreBooking/librebooking.svg new file mode 100644 index 0000000..81306a9 --- /dev/null +++ b/dist/nodes/LibreBooking/librebooking.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.d.ts b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.d.ts new file mode 100644 index 0000000..135be0b --- /dev/null +++ b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.d.ts @@ -0,0 +1,14 @@ +import { INodeType, INodeTypeDescription, IPollFunctions, INodeExecutionData } from 'n8n-workflow'; +/** + * LibreBooking Trigger Node + * + * Drei Modi: + * 1. Get All (One-Time): Alle Reservierungen für einen Zeitraum abrufen + * 2. New Reservations (Poll): Bei neuen Reservierungen triggern + * 3. Updated Reservations (Poll): Bei geänderten Reservierungen triggern + */ +export declare class LibreBookingTrigger implements INodeType { + description: INodeTypeDescription; + poll(this: IPollFunctions): Promise; +} +//# sourceMappingURL=LibreBookingTrigger.node.d.ts.map \ No newline at end of file diff --git a/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.d.ts.map b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.d.ts.map new file mode 100644 index 0000000..dbaa29f --- /dev/null +++ b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBookingTrigger.node.d.ts","sourceRoot":"","sources":["../../../nodes/LibreBookingTrigger/LibreBookingTrigger.node.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,SAAS,EACT,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAGlB,MAAM,cAAc,CAAC;AAyOtB;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,SAAS;IACpD,WAAW,EAAE,oBAAoB,CA4K/B;IAEI,IAAI,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,kBAAkB,EAAE,EAAE,GAAG,IAAI,CAAC;CAkUxE"} \ No newline at end of file diff --git a/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.js b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.js new file mode 100644 index 0000000..cc44d99 --- /dev/null +++ b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.js @@ -0,0 +1,593 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.LibreBookingTrigger = void 0; +const n8n_workflow_1 = require("n8n-workflow"); +/** + * Authentifizierung bei LibreBooking + */ +async function authenticateTrigger(pollFunctions, baseUrl, username, password) { + try { + const response = await pollFunctions.helpers.httpRequest({ + method: 'POST', + url: `${baseUrl}/Web/Services/index.php/Authentication/Authenticate`, + headers: { 'Content-Type': 'application/json' }, + body: { username, password }, + json: true, + }); + if (!response.isAuthenticated) { + throw new n8n_workflow_1.NodeOperationError(pollFunctions.getNode(), 'Authentifizierung fehlgeschlagen. Überprüfen Sie Ihre Zugangsdaten.'); + } + return { + sessionToken: response.sessionToken, + userId: response.userId, + sessionExpires: response.sessionExpires, + }; + } + catch (error) { + throw new n8n_workflow_1.NodeApiError(pollFunctions.getNode(), error, { + message: 'Authentifizierung fehlgeschlagen', + description: 'Überprüfen Sie die LibreBooking URL und Ihre Zugangsdaten.', + }); + } +} +/** + * Abmeldung + */ +async function signOutTrigger(pollFunctions, baseUrl, session) { + try { + await pollFunctions.helpers.httpRequest({ + method: 'POST', + url: `${baseUrl}/Web/Services/index.php/Authentication/SignOut`, + headers: { 'Content-Type': 'application/json' }, + body: { + userId: session.userId, + sessionToken: session.sessionToken, + }, + json: true, + }); + } + catch (error) { + // Ignoriere SignOut-Fehler + } +} +/** + * Reservierungen abrufen + */ +async function getReservations(pollFunctions, baseUrl, session, startDateTime, endDateTime, filters) { + const qs = { + startDateTime, + endDateTime, + }; + if (filters.resourceId) + qs.resourceId = filters.resourceId; + if (filters.scheduleId) + qs.scheduleId = filters.scheduleId; + if (filters.userId) + qs.userId = filters.userId; + try { + const response = await pollFunctions.helpers.httpRequest({ + method: 'GET', + url: `${baseUrl}/Web/Services/index.php/Reservations/`, + headers: { + 'Content-Type': 'application/json', + 'X-Booked-SessionToken': session.sessionToken, + 'X-Booked-UserId': session.userId.toString(), + }, + qs, + json: true, + }); + return response.reservations || []; + } + catch (error) { + throw new n8n_workflow_1.NodeApiError(pollFunctions.getNode(), error, { + message: 'Fehler beim Abrufen der Reservierungen', + }); + } +} +/** + * Detaillierte Reservierungsdaten abrufen (inkl. Custom Attributes) + */ +async function getReservationDetails(pollFunctions, baseUrl, session, referenceNumber) { + try { + const response = await pollFunctions.helpers.httpRequest({ + method: 'GET', + url: `${baseUrl}/Web/Services/index.php/Reservations/${referenceNumber}`, + headers: { + 'Content-Type': 'application/json', + 'X-Booked-SessionToken': session.sessionToken, + 'X-Booked-UserId': session.userId.toString(), + }, + json: true, + }); + return response; + } + catch (error) { + return null; + } +} +/** + * Zeitfenster berechnen für "Get All" Mode + */ +function getTimeWindowForGetAll(customStartDate, customEndDate, defaultDays = 14) { + if (customStartDate && customEndDate) { + return { + start: new Date(customStartDate).toISOString(), + end: new Date(customEndDate).toISOString(), + }; + } + const now = new Date(); + const endDate = new Date(now); + endDate.setDate(endDate.getDate() + defaultDays); + return { + start: now.toISOString(), + end: endDate.toISOString(), + }; +} +/** + * Zeitfenster berechnen für Polling + */ +function getTimeWindowForPolling(timeWindow) { + const now = new Date(); + const start = now.toISOString(); + let endDate = new Date(now); + switch (timeWindow) { + case '7days': + endDate.setDate(endDate.getDate() + 7); + break; + case '14days': + endDate.setDate(endDate.getDate() + 14); + break; + case '30days': + endDate.setDate(endDate.getDate() + 30); + break; + case '90days': + endDate.setDate(endDate.getDate() + 90); + break; + default: + endDate.setDate(endDate.getDate() + 14); + } + return { + start, + end: endDate.toISOString(), + }; +} +/** + * Hash für Reservierung generieren (für Änderungserkennung) + */ +function getReservationHash(reservation) { + const relevantData = { + referenceNumber: reservation.referenceNumber, + startDate: reservation.startDate, + endDate: reservation.endDate, + title: reservation.title || '', + description: reservation.description || '', + resourceId: reservation.resourceId, + resourceName: reservation.resourceName || '', + userId: reservation.userId, + requiresApproval: reservation.requiresApproval, + participants: reservation.participants || [], + invitees: reservation.invitees || [], + }; + return JSON.stringify(relevantData); +} +/** + * LibreBooking Trigger Node + * + * Drei Modi: + * 1. Get All (One-Time): Alle Reservierungen für einen Zeitraum abrufen + * 2. New Reservations (Poll): Bei neuen Reservierungen triggern + * 3. Updated Reservations (Poll): Bei geänderten Reservierungen triggern + */ +class LibreBookingTrigger { + constructor() { + this.description = { + displayName: 'LibreBooking Trigger', + name: 'libreBookingTrigger', + icon: 'file:librebooking.svg', + group: ['trigger'], + version: 1, + description: 'Wird bei neuen oder geänderten Reservierungen in LibreBooking ausgelöst', + subtitle: '={{$parameter["triggerMode"]}}', + defaults: { + name: 'LibreBooking Trigger', + }, + inputs: [], + outputs: ['main'], + credentials: [ + { + name: 'libreBookingApi', + required: true, + }, + ], + polling: true, + properties: [ + // ===================================================== + // TRIGGER MODE SELECTOR + // ===================================================== + { + displayName: 'Trigger-Modus', + name: 'triggerMode', + type: 'options', + options: [ + { + name: 'Alle Abrufen (Einmalig)', + value: 'getAll', + description: 'Alle Reservierungen für einen Zeitraum abrufen (bei jedem Poll)', + }, + { + name: 'Neue Reservierungen (Polling)', + value: 'newReservations', + description: 'Nur bei neuen Reservierungen triggern', + }, + { + name: 'Geänderte Reservierungen (Polling)', + value: 'updatedReservations', + description: 'Nur bei geänderten Reservierungen triggern', + }, + ], + default: 'getAll', + description: 'Wählen Sie den Trigger-Modus', + }, + // ===================================================== + // GET ALL MODE - DATE RANGE + // ===================================================== + { + displayName: 'Startdatum', + name: 'startDate', + type: 'dateTime', + displayOptions: { + show: { + triggerMode: ['getAll'], + }, + }, + default: '', + description: 'Startdatum für den Abruf (leer = heute)', + }, + { + displayName: 'Enddatum', + name: 'endDate', + type: 'dateTime', + displayOptions: { + show: { + triggerMode: ['getAll'], + }, + }, + default: '', + description: 'Enddatum für den Abruf (leer = 14 Tage in der Zukunft)', + }, + // ===================================================== + // POLLING MODE - TIME WINDOW + // ===================================================== + { + displayName: 'Zeitfenster', + name: 'timeWindow', + type: 'options', + displayOptions: { + show: { + triggerMode: ['newReservations', 'updatedReservations'], + }, + }, + options: [ + { name: 'Nächste 7 Tage', value: '7days' }, + { name: 'Nächste 14 Tage', value: '14days' }, + { name: 'Nächste 30 Tage', value: '30days' }, + { name: 'Nächste 90 Tage', value: '90days' }, + ], + default: '14days', + description: 'Zeitfenster für die Überwachung von Reservierungen', + }, + { + displayName: 'Hinweis', + name: 'pollingNotice', + type: 'notice', + default: '', + displayOptions: { + show: { + triggerMode: ['newReservations', 'updatedReservations'], + }, + }, + description: 'Beim ersten Poll werden existierende Reservierungen gespeichert, aber nicht getriggert. Nur nachfolgende Änderungen lösen den Trigger aus.', + }, + // ===================================================== + // FILTERS (ALL MODES) + // ===================================================== + { + displayName: 'Filter', + name: 'filters', + type: 'collection', + placeholder: 'Filter hinzufügen', + default: {}, + options: [ + { + displayName: 'Ressourcen-ID', + name: 'resourceId', + type: 'number', + default: '', + description: 'Nur Reservierungen für diese Ressource', + }, + { + displayName: 'Zeitplan-ID', + name: 'scheduleId', + type: 'number', + default: '', + description: 'Nur Reservierungen für diesen Zeitplan', + }, + { + displayName: 'Benutzer-ID', + name: 'userId', + type: 'number', + default: '', + description: 'Nur Reservierungen für diesen Benutzer', + }, + ], + }, + // ===================================================== + // OPTIONS (ALL MODES) + // ===================================================== + { + displayName: 'Optionen', + name: 'options', + type: 'collection', + placeholder: 'Option hinzufügen', + default: {}, + options: [ + { + displayName: 'Detaillierte Daten Abrufen', + name: 'fetchDetails', + type: 'boolean', + default: false, + description: 'Ruft vollständige Reservierungsdaten inkl. Custom Attributes ab (zusätzliche API-Aufrufe)', + }, + { + displayName: 'Debug-Modus', + name: 'debugMode', + type: 'boolean', + default: false, + description: 'Gibt zusätzliche Debug-Informationen aus', + }, + ], + }, + ], + }; + } + async poll() { + const credentials = await this.getCredentials('libreBookingApi'); + const baseUrl = credentials.url.replace(/\/$/, ''); + const username = credentials.username; + const password = credentials.password; + const triggerMode = this.getNodeParameter('triggerMode'); + const filters = this.getNodeParameter('filters', {}); + const options = this.getNodeParameter('options', {}); + // Debug-Modus + const debugMode = options.debugMode || false; + const fetchDetails = options.fetchDetails || false; + // Workflow Static Data für State-Management + const webhookData = this.getWorkflowStaticData('node'); + let session; + try { + session = await authenticateTrigger(this, baseUrl, username, password); + } + catch (error) { + throw error; + } + try { + const returnData = []; + // ========================================== + // MODE: Get All (One-Time / Every Poll) + // ========================================== + if (triggerMode === 'getAll') { + const startDate = this.getNodeParameter('startDate', ''); + const endDate = this.getNodeParameter('endDate', ''); + const { start, end } = getTimeWindowForGetAll(startDate || undefined, endDate || undefined, 14); + const reservations = await getReservations(this, baseUrl, session, start, end, filters); + if (debugMode) { + console.log(`[LibreBooking Trigger] Get All Mode - Found ${reservations.length} reservations`); + console.log(`[LibreBooking Trigger] Date Range: ${start} to ${end}`); + } + if (reservations.length === 0) { + if (debugMode) { + return [[{ + json: { + _debug: true, + _message: 'Keine Reservierungen im Zeitraum gefunden', + _startDate: start, + _endDate: end, + _count: 0, + }, + }]]; + } + return null; + } + // Alle Reservierungen zurückgeben + for (const reservation of reservations) { + let reservationData = reservation; + if (fetchDetails) { + try { + const details = await getReservationDetails(this, baseUrl, session, reservation.referenceNumber); + if (details) { + reservationData = details; + } + } + catch (error) { + // Fallback auf Basisdaten + } + } + returnData.push({ + json: { + ...reservationData, + _eventType: 'getAll', + _triggeredAt: new Date().toISOString(), + }, + }); + } + } + // ========================================== + // MODE: New Reservations (Polling) + // ========================================== + else if (triggerMode === 'newReservations') { + const timeWindow = this.getNodeParameter('timeWindow', '14days'); + const { start, end } = getTimeWindowForPolling(timeWindow); + const reservations = await getReservations(this, baseUrl, session, start, end, filters); + // Initialisiere seenIds beim ersten Poll + if (!webhookData.seenIds) { + webhookData.seenIds = []; + webhookData.isFirstPoll = true; + } + const currentIds = reservations.map((r) => r.referenceNumber); + if (debugMode) { + console.log(`[LibreBooking Trigger] New Reservations Mode`); + console.log(`[LibreBooking Trigger] First Poll: ${webhookData.isFirstPoll}`); + console.log(`[LibreBooking Trigger] Current IDs: ${currentIds.length}, Seen IDs: ${webhookData.seenIds.length}`); + } + // Beim ersten Poll: Nur IDs speichern, NICHT triggern + if (webhookData.isFirstPoll) { + webhookData.seenIds = currentIds; + webhookData.isFirstPoll = false; + webhookData.lastPollTime = new Date().toISOString(); + if (debugMode) { + return [[{ + json: { + _debug: true, + _message: 'Erster Poll - IDs wurden gespeichert, keine Events getriggert', + _savedIds: currentIds.length, + _ids: currentIds, + _timestamp: webhookData.lastPollTime, + }, + }]]; + } + return null; // Nichts triggern beim ersten Poll + } + // Nur NEUE Reservierungen (die wir noch nicht gesehen haben) + const newReservations = reservations.filter((r) => !webhookData.seenIds.includes(r.referenceNumber)); + // Update seenIds mit allen aktuellen IDs + webhookData.seenIds = currentIds; + webhookData.lastPollTime = new Date().toISOString(); + if (newReservations.length === 0) { + if (debugMode) { + console.log(`[LibreBooking Trigger] No new reservations found`); + } + return null; + } + // Neue Reservierungen verarbeiten + for (const reservation of newReservations) { + let reservationData = reservation; + if (fetchDetails) { + try { + const details = await getReservationDetails(this, baseUrl, session, reservation.referenceNumber); + if (details) { + reservationData = details; + } + } + catch (error) { + // Fallback auf Basisdaten + } + } + returnData.push({ + json: { + ...reservationData, + _eventType: 'new', + _triggeredAt: new Date().toISOString(), + }, + }); + } + if (debugMode && returnData.length > 0) { + console.log(`[LibreBooking Trigger] Triggering ${returnData.length} new reservations`); + } + } + // ========================================== + // MODE: Updated Reservations (Polling) + // ========================================== + else if (triggerMode === 'updatedReservations') { + const timeWindow = this.getNodeParameter('timeWindow', '14days'); + const { start, end } = getTimeWindowForPolling(timeWindow); + const reservations = await getReservations(this, baseUrl, session, start, end, filters); + // Initialisiere reservationHashes beim ersten Poll + if (!webhookData.reservationHashes) { + webhookData.reservationHashes = {}; + webhookData.isFirstPoll = true; + } + if (debugMode) { + console.log(`[LibreBooking Trigger] Updated Reservations Mode`); + console.log(`[LibreBooking Trigger] First Poll: ${webhookData.isFirstPoll}`); + console.log(`[LibreBooking Trigger] Current: ${reservations.length}, Stored hashes: ${Object.keys(webhookData.reservationHashes).length}`); + } + // Beim ersten Poll: Nur Hashes speichern, NICHT triggern + if (webhookData.isFirstPoll) { + for (const reservation of reservations) { + webhookData.reservationHashes[reservation.referenceNumber] = getReservationHash(reservation); + } + webhookData.isFirstPoll = false; + webhookData.lastPollTime = new Date().toISOString(); + if (debugMode) { + return [[{ + json: { + _debug: true, + _message: 'Erster Poll - Hashes wurden gespeichert, keine Events getriggert', + _savedHashes: Object.keys(webhookData.reservationHashes).length, + _timestamp: webhookData.lastPollTime, + }, + }]]; + } + return null; // Nichts triggern beim ersten Poll + } + // Geänderte Reservierungen finden + const updatedReservations = []; + const newHashes = {}; + for (const reservation of reservations) { + const currentHash = getReservationHash(reservation); + const oldHash = webhookData.reservationHashes[reservation.referenceNumber]; + newHashes[reservation.referenceNumber] = currentHash; + // Nur als "geändert" markieren, wenn: + // 1. Wir die Reservierung schon kennen (nicht neu) + // 2. Der Hash sich geändert hat + if (oldHash && currentHash !== oldHash) { + updatedReservations.push(reservation); + } + } + // Update Hashes mit allen aktuellen Reservierungen + webhookData.reservationHashes = newHashes; + webhookData.lastPollTime = new Date().toISOString(); + if (updatedReservations.length === 0) { + if (debugMode) { + console.log(`[LibreBooking Trigger] No updated reservations found`); + } + return null; + } + // Geänderte Reservierungen verarbeiten + for (const reservation of updatedReservations) { + let reservationData = reservation; + if (fetchDetails) { + try { + const details = await getReservationDetails(this, baseUrl, session, reservation.referenceNumber); + if (details) { + reservationData = details; + } + } + catch (error) { + // Fallback auf Basisdaten + } + } + returnData.push({ + json: { + ...reservationData, + _eventType: 'updated', + _triggeredAt: new Date().toISOString(), + }, + }); + } + if (debugMode && returnData.length > 0) { + console.log(`[LibreBooking Trigger] Triggering ${returnData.length} updated reservations`); + } + } + if (returnData.length === 0) { + return null; + } + return [returnData]; + } + finally { + await signOutTrigger(this, baseUrl, session); + } + } +} +exports.LibreBookingTrigger = LibreBookingTrigger; +//# sourceMappingURL=LibreBookingTrigger.node.js.map \ No newline at end of file diff --git a/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.js.map b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.js.map new file mode 100644 index 0000000..069a76b --- /dev/null +++ b/dist/nodes/LibreBookingTrigger/LibreBookingTrigger.node.js.map @@ -0,0 +1 @@ +{"version":3,"file":"LibreBookingTrigger.node.js","sourceRoot":"","sources":["../../../nodes/LibreBookingTrigger/LibreBookingTrigger.node.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/nodes/LibreBookingTrigger/librebooking.svg b/dist/nodes/LibreBookingTrigger/librebooking.svg new file mode 100644 index 0000000..81306a9 --- /dev/null +++ b/dist/nodes/LibreBookingTrigger/librebooking.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nodes/LibreBooking/LibreBooking.node.ts b/nodes/LibreBooking/LibreBooking.node.ts index 7b2467e..4745e3f 100644 --- a/nodes/LibreBooking/LibreBooking.node.ts +++ b/nodes/LibreBooking/LibreBooking.node.ts @@ -1,199 +1,199 @@ import { - IExecuteFunctions, - INodeExecutionData, - INodeType, - INodeTypeDescription, - IHttpRequestMethods, - NodeApiError, - NodeOperationError, + IExecuteFunctions, + INodeExecutionData, + INodeType, + INodeTypeDescription, + IHttpRequestMethods, + NodeApiError, + NodeOperationError, } from 'n8n-workflow'; interface LibreBookingSession { - sessionToken: string; - userId: number; - sessionExpires: string; + sessionToken: string; + userId: number; + sessionExpires: string; } interface ConfigDefaults { - defaultTermsAccepted: boolean; - defaultAllowParticipation: boolean; - defaultResourceId: number; - defaultUserId: number; - defaultScheduleId: number; - defaultTimezone: string; - defaultLanguage: string; + defaultTermsAccepted: boolean; + defaultAllowParticipation: boolean; + defaultResourceId: number; + defaultUserId: number; + defaultScheduleId: number; + defaultTimezone: string; + defaultLanguage: string; } /** * Authentifizierung bei LibreBooking */ async function authenticate( - executeFunctions: IExecuteFunctions, - baseUrl: string, - username: string, - password: string, + executeFunctions: IExecuteFunctions, + baseUrl: string, + username: string, + password: string, ): Promise { - try { - const response = await executeFunctions.helpers.httpRequest({ - method: 'POST', - url: `${baseUrl}/Web/Services/index.php/Authentication/Authenticate`, - headers: { 'Content-Type': 'application/json' }, - body: { username, password }, - json: true, - }); + try { + const response = await executeFunctions.helpers.httpRequest({ + method: 'POST', + url: `${baseUrl}/Web/Services/index.php/Authentication/Authenticate`, + headers: { 'Content-Type': 'application/json' }, + body: { username, password }, + json: true, + }); - if (!response.isAuthenticated) { - throw new NodeOperationError( - executeFunctions.getNode(), - 'Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Credentials.', - ); - } + if (!response.isAuthenticated) { + throw new NodeOperationError( + executeFunctions.getNode(), + 'Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Credentials.', + ); + } - return { - sessionToken: response.sessionToken, - userId: response.userId, - sessionExpires: response.sessionExpires, - }; - } catch (error: any) { - throw new NodeApiError(executeFunctions.getNode(), error, { - message: 'Authentifizierung fehlgeschlagen', - description: 'Überprüfen Sie die LibreBooking URL und Ihre Zugangsdaten.', - }); - } + return { + sessionToken: response.sessionToken, + userId: response.userId, + sessionExpires: response.sessionExpires, + }; + } catch (error: any) { + throw new NodeApiError(executeFunctions.getNode(), error, { + message: 'Authentifizierung fehlgeschlagen', + description: 'Überprüfen Sie die LibreBooking URL und Ihre Zugangsdaten.', + }); + } } /** * Abmeldung von LibreBooking */ async function signOut( - executeFunctions: IExecuteFunctions, - baseUrl: string, - session: LibreBookingSession, + executeFunctions: IExecuteFunctions, + baseUrl: string, + session: LibreBookingSession, ): Promise { - try { - await executeFunctions.helpers.httpRequest({ - method: 'POST', - url: `${baseUrl}/Web/Services/index.php/Authentication/SignOut`, - headers: { 'Content-Type': 'application/json' }, - body: { - userId: session.userId, - sessionToken: session.sessionToken, - }, - json: true, - }); - } catch (error) { - // Ignoriere SignOut-Fehler - } + try { + await executeFunctions.helpers.httpRequest({ + method: 'POST', + url: `${baseUrl}/Web/Services/index.php/Authentication/SignOut`, + headers: { 'Content-Type': 'application/json' }, + body: { + userId: session.userId, + sessionToken: session.sessionToken, + }, + json: true, + }); + } catch (error) { + // Ignoriere SignOut-Fehler + } } /** * API-Request mit Session-Authentifizierung */ async function makeApiRequest( - executeFunctions: IExecuteFunctions, - baseUrl: string, - session: LibreBookingSession, - method: IHttpRequestMethods, - endpoint: string, - body?: any, - qs?: any, + executeFunctions: IExecuteFunctions, + baseUrl: string, + session: LibreBookingSession, + method: IHttpRequestMethods, + endpoint: string, + body?: any, + qs?: any, ): Promise { - const options: any = { - method, - url: `${baseUrl}/Web/Services/index.php${endpoint}`, - headers: { - 'Content-Type': 'application/json', - 'X-Booked-SessionToken': session.sessionToken, - 'X-Booked-UserId': session.userId.toString(), - }, - json: true, - }; + const options: any = { + method, + url: `${baseUrl}/Web/Services/index.php${endpoint}`, + headers: { + 'Content-Type': 'application/json', + 'X-Booked-SessionToken': session.sessionToken, + 'X-Booked-UserId': session.userId.toString(), + }, + json: true, + }; - if (body && Object.keys(body).length > 0) { - options.body = body; - } + if (body && Object.keys(body).length > 0) { + options.body = body; + } - if (qs && Object.keys(qs).length > 0) { - options.qs = qs; - } + if (qs && Object.keys(qs).length > 0) { + options.qs = qs; + } - try { - return await executeFunctions.helpers.httpRequest(options); - } catch (error: any) { - if (error.statusCode === 401) { - throw new NodeApiError(executeFunctions.getNode(), error, { - message: 'Authentifizierung abgelaufen', - description: 'Der Session-Token ist abgelaufen. Bitte erneut ausführen.', - }); - } else if (error.statusCode === 403) { - throw new NodeApiError(executeFunctions.getNode(), error, { - message: 'Zugriff verweigert', - description: 'Sie haben keine Berechtigung für diese Operation. Admin-Rechte erforderlich?', - }); - } else if (error.statusCode === 404) { - throw new NodeApiError(executeFunctions.getNode(), error, { - message: 'Nicht gefunden', - description: 'Die angeforderte Ressource wurde nicht gefunden.', - }); - } - throw new NodeApiError(executeFunctions.getNode(), error, { - message: `API-Fehler: ${error.message}`, - }); - } + try { + return await executeFunctions.helpers.httpRequest(options); + } catch (error: any) { + if (error.statusCode === 401) { + throw new NodeApiError(executeFunctions.getNode(), error, { + message: 'Authentifizierung abgelaufen', + description: 'Der Session-Token ist abgelaufen. Bitte erneut ausführen.', + }); + } else if (error.statusCode === 403) { + throw new NodeApiError(executeFunctions.getNode(), error, { + message: 'Zugriff verweigert', + description: 'Sie haben keine Berechtigung für diese Operation. Admin-Rechte erforderlich?', + }); + } else if (error.statusCode === 404) { + throw new NodeApiError(executeFunctions.getNode(), error, { + message: 'Nicht gefunden', + description: 'Die angeforderte Ressource wurde nicht gefunden.', + }); + } + throw new NodeApiError(executeFunctions.getNode(), error, { + message: `API-Fehler: ${error.message}`, + }); + } } /** * Hilfsfunktion: String zu Array von Zahlen */ function parseIdList(value: string | undefined): number[] { - if (!value || value.trim() === '') return []; - return value.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !isNaN(id)); + if (!value || value.trim() === '') return []; + return value.split(',').map(id => parseInt(id.trim(), 10)).filter(id => !isNaN(id)); } /** * Config-Defaults laden */ async function getConfigDefaults(executeFunctions: IExecuteFunctions): Promise { - const defaults: ConfigDefaults = { - defaultTermsAccepted: true, - defaultAllowParticipation: false, - defaultResourceId: 0, - defaultUserId: 0, - defaultScheduleId: 0, - defaultTimezone: 'Europe/Berlin', - defaultLanguage: 'de_de', - }; + const defaults: ConfigDefaults = { + defaultTermsAccepted: true, + defaultAllowParticipation: false, + defaultResourceId: 0, + defaultUserId: 0, + defaultScheduleId: 0, + defaultTimezone: 'Europe/Berlin', + defaultLanguage: 'de_de', + }; - try { - const configCredentials = await executeFunctions.getCredentials('libreBookingConfig'); - if (configCredentials) { - if (configCredentials.defaultTermsAccepted !== undefined) { - defaults.defaultTermsAccepted = configCredentials.defaultTermsAccepted as boolean; - } - if (configCredentials.defaultAllowParticipation !== undefined) { - defaults.defaultAllowParticipation = configCredentials.defaultAllowParticipation as boolean; - } - if (configCredentials.defaultResourceId !== undefined && configCredentials.defaultResourceId !== 0) { - defaults.defaultResourceId = configCredentials.defaultResourceId as number; - } - if (configCredentials.defaultUserId !== undefined && configCredentials.defaultUserId !== 0) { - defaults.defaultUserId = configCredentials.defaultUserId as number; - } - if (configCredentials.defaultScheduleId !== undefined && configCredentials.defaultScheduleId !== 0) { - defaults.defaultScheduleId = configCredentials.defaultScheduleId as number; - } - if (configCredentials.defaultTimezone) { - defaults.defaultTimezone = configCredentials.defaultTimezone as string; - } - if (configCredentials.defaultLanguage) { - defaults.defaultLanguage = configCredentials.defaultLanguage as string; - } - } - } catch (error) { - // Config-Credential ist optional, ignoriere Fehler - } + try { + const configCredentials = await executeFunctions.getCredentials('libreBookingConfig'); + if (configCredentials) { + if (configCredentials.defaultTermsAccepted !== undefined) { + defaults.defaultTermsAccepted = configCredentials.defaultTermsAccepted as boolean; + } + if (configCredentials.defaultAllowParticipation !== undefined) { + defaults.defaultAllowParticipation = configCredentials.defaultAllowParticipation as boolean; + } + if (configCredentials.defaultResourceId !== undefined && configCredentials.defaultResourceId !== 0) { + defaults.defaultResourceId = configCredentials.defaultResourceId as number; + } + if (configCredentials.defaultUserId !== undefined && configCredentials.defaultUserId !== 0) { + defaults.defaultUserId = configCredentials.defaultUserId as number; + } + if (configCredentials.defaultScheduleId !== undefined && configCredentials.defaultScheduleId !== 0) { + defaults.defaultScheduleId = configCredentials.defaultScheduleId as number; + } + if (configCredentials.defaultTimezone) { + defaults.defaultTimezone = configCredentials.defaultTimezone as string; + } + if (configCredentials.defaultLanguage) { + defaults.defaultLanguage = configCredentials.defaultLanguage as string; + } + } + } catch (error) { + // Config-Credential ist optional, ignoriere Fehler + } - return defaults; + return defaults; } /** @@ -203,1341 +203,1441 @@ async function getConfigDefaults(executeFunctions: IExecuteFunctions): Promise { - const items = this.getInputData(); - const returnData: INodeExecutionData[] = []; - - const credentials = await this.getCredentials('libreBookingApi'); - const baseUrl = (credentials.url as string).replace(/\/$/, ''); - const username = credentials.username as string; - const pw = credentials.password as string; + async execute(this: IExecuteFunctions): Promise { + const items = this.getInputData(); + const returnData: INodeExecutionData[] = []; + + const credentials = await this.getCredentials('libreBookingApi'); + const baseUrl = (credentials.url as string).replace(/\/$/, ''); + const username = credentials.username as string; + const pw = credentials.password as string; - // Config-Defaults laden - const configDefaults = await getConfigDefaults(this); + // Config-Defaults laden + const configDefaults = await getConfigDefaults(this); - const session = await authenticate(this, baseUrl, username, pw); + const session = await authenticate(this, baseUrl, username, pw); - try { - for (let i = 0; i < items.length; i++) { - try { - const resource = this.getNodeParameter('resource', i) as string; - const operation = this.getNodeParameter('operation', i) as string; - let responseData: any; + try { + for (let i = 0; i < items.length; i++) { + try { + const resource = this.getNodeParameter('resource', i) as string; + const operation = this.getNodeParameter('operation', i) as string; + let responseData: any; - // RESERVATION - if (resource === 'reservation') { - if (operation === 'getAll') { - const filters = this.getNodeParameter('filters', i, {}) as any; - const qs: any = {}; - if (filters.userId) qs.userId = filters.userId; - if (filters.resourceId) qs.resourceId = filters.resourceId; - if (filters.scheduleId) qs.scheduleId = filters.scheduleId; - if (filters.startDateTime) qs.startDateTime = filters.startDateTime; - if (filters.endDateTime) qs.endDateTime = filters.endDateTime; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Reservations/', undefined, qs); - } else if (operation === 'get') { - const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Reservations/${referenceNumber}`); - } else if (operation === 'create') { - const resourceId = this.getNodeParameter('resourceId', i) as number; - const startDateTime = this.getNodeParameter('startDateTime', i) as string; - const endDateTime = this.getNodeParameter('endDateTime', i) as string; - const termsAccepted = this.getNodeParameter('termsAccepted', i, configDefaults.defaultTermsAccepted) as boolean; - const title = this.getNodeParameter('title', i, '') as string; - const customAttributes = this.getNodeParameter('customAttributes', i, {}) as any; - const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any; - - const body: any = { - resourceId, - startDateTime: new Date(startDateTime).toISOString(), - endDateTime: new Date(endDateTime).toISOString(), - termsAccepted, - }; - - if (title) body.title = title; - if (additionalFields.description) body.description = additionalFields.description; - if (additionalFields.userId) body.userId = additionalFields.userId; - if (additionalFields.resources) body.resources = parseIdList(additionalFields.resources); - if (additionalFields.participants) body.participants = parseIdList(additionalFields.participants); - if (additionalFields.invitees) body.invitees = parseIdList(additionalFields.invitees); - if (additionalFields.allowParticipation !== undefined) { - body.allowParticipation = additionalFields.allowParticipation; - } else { - body.allowParticipation = configDefaults.defaultAllowParticipation; - } - - // Custom Attributes verarbeiten - if (customAttributes?.attribute && customAttributes.attribute.length > 0) { - body.customAttributes = customAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Reservations/', body); - } else if (operation === 'update') { - const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; - const startDateTime = this.getNodeParameter('startDateTime', i) as string; - const endDateTime = this.getNodeParameter('endDateTime', i) as string; - const title = this.getNodeParameter('title', i, '') as string; - const updateScope = this.getNodeParameter('updateScope', i, 'this') as string; - const customAttributes = this.getNodeParameter('customAttributes', i, {}) as any; - const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any; - - const body: any = { - startDateTime: new Date(startDateTime).toISOString(), - endDateTime: new Date(endDateTime).toISOString(), - termsAccepted: true, // termsAccepted wird auch bei Updates benötigt - }; - - if (title) body.title = title; - if (additionalFields.description) body.description = additionalFields.description; - if (additionalFields.resourceId) body.resourceId = additionalFields.resourceId; - if (additionalFields.userId) body.userId = additionalFields.userId; - if (additionalFields.resources) body.resources = parseIdList(additionalFields.resources); - if (additionalFields.participants) body.participants = parseIdList(additionalFields.participants); - if (additionalFields.invitees) body.invitees = parseIdList(additionalFields.invitees); - if (additionalFields.allowParticipation !== undefined) body.allowParticipation = additionalFields.allowParticipation; - - // Custom Attributes verarbeiten - if (customAttributes?.attribute && customAttributes.attribute.length > 0) { - body.customAttributes = customAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}?updateScope=${updateScope}`, body); - } else if (operation === 'delete') { - const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; - const updateScope = this.getNodeParameter('updateScope', i, 'this') as string; - responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Reservations/${referenceNumber}?updateScope=${updateScope}`); - } else if (operation === 'approve') { - const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/Approval`); - } else if (operation === 'checkIn') { - const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckIn`); - } else if (operation === 'checkOut') { - const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckOut`); - } - } + // RESERVATION + if (resource === 'reservation') { + if (operation === 'getAll') { + const filters = this.getNodeParameter('filters', i, {}) as any; + const qs: any = {}; + if (filters.userId) qs.userId = filters.userId; + if (filters.resourceId) qs.resourceId = filters.resourceId; + if (filters.scheduleId) qs.scheduleId = filters.scheduleId; + if (filters.startDateTime) qs.startDateTime = filters.startDateTime; + if (filters.endDateTime) qs.endDateTime = filters.endDateTime; + + let response = await makeApiRequest(this, baseUrl, session, 'GET', '/Reservations/', undefined, qs); + + // If includeCustomAttributes is enabled, fetch details for each reservation + if (filters.includeCustomAttributes && response.reservations && response.reservations.length > 0) { + const enrichedReservations = []; + for (const reservation of response.reservations) { + try { + const details = await makeApiRequest(this, baseUrl, session, 'GET', `/Reservations/${reservation.referenceNumber}`); + enrichedReservations.push({ + ...reservation, + customAttributes: details.customAttributes || [], + owner: details.owner, + participants: details.participants || [], + invitees: details.invitees || [], + }); + } catch (error) { + // Fallback to original reservation data + enrichedReservations.push(reservation); + } + } + response = { ...response, reservations: enrichedReservations }; + } + + responseData = response; + } else if (operation === 'get') { + const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Reservations/${referenceNumber}`); + } else if (operation === 'create') { + const resourceId = this.getNodeParameter('resourceId', i) as number; + const startDateTime = this.getNodeParameter('startDateTime', i) as string; + const endDateTime = this.getNodeParameter('endDateTime', i) as string; + const termsAccepted = this.getNodeParameter('termsAccepted', i, configDefaults.defaultTermsAccepted) as boolean; + const title = this.getNodeParameter('title', i, '') as string; + const customAttributes = this.getNodeParameter('customAttributes', i, {}) as any; + const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any; + + const body: any = { + resourceId, + startDateTime: new Date(startDateTime).toISOString(), + endDateTime: new Date(endDateTime).toISOString(), + termsAccepted, + }; + + if (title) body.title = title; + if (additionalFields.description) body.description = additionalFields.description; + if (additionalFields.userId) body.userId = additionalFields.userId; + if (additionalFields.resources) body.resources = parseIdList(additionalFields.resources); + if (additionalFields.participants) body.participants = parseIdList(additionalFields.participants); + if (additionalFields.invitees) body.invitees = parseIdList(additionalFields.invitees); + // allowParticipation is REQUIRED by the API + body.allowParticipation = additionalFields.allowParticipation !== undefined + ? additionalFields.allowParticipation + : configDefaults.defaultAllowParticipation; + + // Custom Attributes verarbeiten + if (customAttributes?.attribute && customAttributes.attribute.length > 0) { + body.customAttributes = customAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Reservations/', body); + } else if (operation === 'update') { + const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; + const startDateTime = this.getNodeParameter('startDateTime', i) as string; + const endDateTime = this.getNodeParameter('endDateTime', i) as string; + const title = this.getNodeParameter('title', i, '') as string; + const updateScope = this.getNodeParameter('updateScope', i, 'this') as string; + const customAttributes = this.getNodeParameter('customAttributes', i, {}) as any; + const additionalFields = this.getNodeParameter('additionalFields', i, {}) as any; + + const body: any = { + startDateTime: new Date(startDateTime).toISOString(), + endDateTime: new Date(endDateTime).toISOString(), + termsAccepted: true, // termsAccepted wird auch bei Updates benötigt + }; + + if (title) body.title = title; + if (additionalFields.description) body.description = additionalFields.description; + if (additionalFields.resourceId) body.resourceId = additionalFields.resourceId; + if (additionalFields.userId) body.userId = additionalFields.userId; + if (additionalFields.resources) body.resources = parseIdList(additionalFields.resources); + if (additionalFields.participants) body.participants = parseIdList(additionalFields.participants); + if (additionalFields.invitees) body.invitees = parseIdList(additionalFields.invitees); + // allowParticipation is REQUIRED by the API + body.allowParticipation = additionalFields.allowParticipation !== undefined + ? additionalFields.allowParticipation + : false; + + // Custom Attributes verarbeiten + if (customAttributes?.attribute && customAttributes.attribute.length > 0) { + body.customAttributes = customAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}?updateScope=${updateScope}`, body); + } else if (operation === 'delete') { + const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; + const updateScope = this.getNodeParameter('updateScope', i, 'this') as string; + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Reservations/${referenceNumber}?updateScope=${updateScope}`); + } else if (operation === 'approve') { + const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/Approval`); + } else if (operation === 'checkIn') { + const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckIn`); + } else if (operation === 'checkOut') { + const referenceNumber = this.getNodeParameter('referenceNumber', i) as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Reservations/${referenceNumber}/CheckOut`); + } + } - // RESOURCE - else if (resource === 'resource') { - if (operation === 'getAll') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/'); - } else if (operation === 'get') { - const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Resources/${resourceIdParam}`); - } else if (operation === 'getAvailability') { - const resourceIdOptional = this.getNodeParameter('resourceIdOptional', i, '') as number | ''; - const availabilityDateTime = this.getNodeParameter('availabilityDateTime', i, '') as string; - let endpoint = '/Resources/Availability'; - if (resourceIdOptional) endpoint = `/Resources/${resourceIdOptional}/Availability`; - const qs: any = {}; - if (availabilityDateTime) qs.dateTime = new Date(availabilityDateTime).toISOString(); - responseData = await makeApiRequest(this, baseUrl, session, 'GET', endpoint, undefined, qs); - } else if (operation === 'getGroups') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Groups'); - } else if (operation === 'getTypes') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Types'); - } else if (operation === 'getStatuses') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Status'); - } else if (operation === 'create') { - const resourceName = this.getNodeParameter('resourceName', i) as string; - const scheduleIdForResource = this.getNodeParameter('scheduleIdForResource', i) as number; - const resourceCustomAttributes = this.getNodeParameter('resourceCustomAttributes', i, {}) as any; - const resourceOptions = this.getNodeParameter('resourceOptions', i, {}) as any; - - const body: any = { name: resourceName, scheduleId: scheduleIdForResource }; - - if (resourceOptions.location) body.location = resourceOptions.location; - if (resourceOptions.contact) body.contact = resourceOptions.contact; - if (resourceOptions.description) body.description = resourceOptions.description; - if (resourceOptions.notes) body.notes = resourceOptions.notes; - if (resourceOptions.maxParticipants) body.maxParticipants = resourceOptions.maxParticipants; - if (resourceOptions.requiresApproval !== undefined) body.requiresApproval = resourceOptions.requiresApproval; - if (resourceOptions.allowMultiday !== undefined) body.allowMultiday = resourceOptions.allowMultiday; - if (resourceOptions.requiresCheckIn !== undefined) body.requiresCheckIn = resourceOptions.requiresCheckIn; - if (resourceOptions.autoReleaseMinutes) body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes; - if (resourceOptions.color) body.color = resourceOptions.color; - if (resourceOptions.statusId !== undefined) body.statusId = resourceOptions.statusId; - - // Custom Attributes verarbeiten - if (resourceCustomAttributes?.attribute && resourceCustomAttributes.attribute.length > 0) { - body.customAttributes = resourceCustomAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Resources/', body); - } else if (operation === 'update') { - const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number; - const resourceName = this.getNodeParameter('resourceName', i) as string; - const resourceCustomAttributes = this.getNodeParameter('resourceCustomAttributes', i, {}) as any; - const resourceOptions = this.getNodeParameter('resourceOptions', i, {}) as any; - - const body: any = { name: resourceName }; - - if (resourceOptions.location) body.location = resourceOptions.location; - if (resourceOptions.contact) body.contact = resourceOptions.contact; - if (resourceOptions.description) body.description = resourceOptions.description; - if (resourceOptions.notes) body.notes = resourceOptions.notes; - if (resourceOptions.maxParticipants) body.maxParticipants = resourceOptions.maxParticipants; - if (resourceOptions.requiresApproval !== undefined) body.requiresApproval = resourceOptions.requiresApproval; - if (resourceOptions.allowMultiday !== undefined) body.allowMultiday = resourceOptions.allowMultiday; - if (resourceOptions.requiresCheckIn !== undefined) body.requiresCheckIn = resourceOptions.requiresCheckIn; - if (resourceOptions.autoReleaseMinutes) body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes; - if (resourceOptions.color) body.color = resourceOptions.color; - if (resourceOptions.statusId !== undefined) body.statusId = resourceOptions.statusId; - - // Custom Attributes verarbeiten - if (resourceCustomAttributes?.attribute && resourceCustomAttributes.attribute.length > 0) { - body.customAttributes = resourceCustomAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Resources/${resourceIdParam}`, body); - } else if (operation === 'delete') { - const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Resources/${resourceIdParam}`); - } - } + // RESOURCE + else if (resource === 'resource') { + if (operation === 'getAll') { + const resourceGetAllOptions = this.getNodeParameter('resourceGetAllOptions', i, {}) as any; + + let response = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/'); + + // If includeCustomAttributes is enabled, fetch details for each resource + if (resourceGetAllOptions.includeCustomAttributes && response.resources && response.resources.length > 0) { + const enrichedResources = []; + for (const res of response.resources) { + try { + const details = await makeApiRequest(this, baseUrl, session, 'GET', `/Resources/${res.resourceId}`); + enrichedResources.push({ + ...res, + customAttributes: details.customAttributes || [], + }); + } catch (error) { + // Fallback to original resource data + enrichedResources.push(res); + } + } + response = { ...response, resources: enrichedResources }; + } + + responseData = response; + } else if (operation === 'get') { + const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Resources/${resourceIdParam}`); + } else if (operation === 'getAvailability') { + const resourceIdOptional = this.getNodeParameter('resourceIdOptional', i, '') as number | ''; + const availabilityDateTime = this.getNodeParameter('availabilityDateTime', i, '') as string; + let endpoint = '/Resources/Availability'; + if (resourceIdOptional) endpoint = `/Resources/${resourceIdOptional}/Availability`; + const qs: any = {}; + if (availabilityDateTime) qs.dateTime = new Date(availabilityDateTime).toISOString(); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', endpoint, undefined, qs); + } else if (operation === 'getGroups') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Groups'); + } else if (operation === 'getTypes') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Types'); + } else if (operation === 'getStatuses') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Resources/Status'); + } else if (operation === 'create') { + const resourceName = this.getNodeParameter('resourceName', i) as string; + const scheduleIdForResource = this.getNodeParameter('scheduleIdForResource', i) as number; + const resourceCustomAttributes = this.getNodeParameter('resourceCustomAttributes', i, {}) as any; + const resourceOptions = this.getNodeParameter('resourceOptions', i, {}) as any; + + const body: any = { name: resourceName, scheduleId: scheduleIdForResource }; + + if (resourceOptions.location) body.location = resourceOptions.location; + if (resourceOptions.contact) body.contact = resourceOptions.contact; + if (resourceOptions.description) body.description = resourceOptions.description; + if (resourceOptions.notes) body.notes = resourceOptions.notes; + if (resourceOptions.maxParticipants) body.maxParticipants = resourceOptions.maxParticipants; + if (resourceOptions.requiresApproval !== undefined) body.requiresApproval = resourceOptions.requiresApproval; + if (resourceOptions.allowMultiday !== undefined) body.allowMultiday = resourceOptions.allowMultiday; + if (resourceOptions.requiresCheckIn !== undefined) body.requiresCheckIn = resourceOptions.requiresCheckIn; + if (resourceOptions.autoReleaseMinutes) body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes; + if (resourceOptions.color) body.color = resourceOptions.color; + if (resourceOptions.statusId !== undefined) body.statusId = resourceOptions.statusId; + + // Custom Attributes verarbeiten + if (resourceCustomAttributes?.attribute && resourceCustomAttributes.attribute.length > 0) { + body.customAttributes = resourceCustomAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Resources/', body); + } else if (operation === 'update') { + const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number; + const resourceName = this.getNodeParameter('resourceName', i) as string; + const resourceCustomAttributes = this.getNodeParameter('resourceCustomAttributes', i, {}) as any; + const resourceOptions = this.getNodeParameter('resourceOptions', i, {}) as any; + + const body: any = { name: resourceName }; + + if (resourceOptions.location) body.location = resourceOptions.location; + if (resourceOptions.contact) body.contact = resourceOptions.contact; + if (resourceOptions.description) body.description = resourceOptions.description; + if (resourceOptions.notes) body.notes = resourceOptions.notes; + if (resourceOptions.maxParticipants) body.maxParticipants = resourceOptions.maxParticipants; + if (resourceOptions.requiresApproval !== undefined) body.requiresApproval = resourceOptions.requiresApproval; + if (resourceOptions.allowMultiday !== undefined) body.allowMultiday = resourceOptions.allowMultiday; + if (resourceOptions.requiresCheckIn !== undefined) body.requiresCheckIn = resourceOptions.requiresCheckIn; + if (resourceOptions.autoReleaseMinutes) body.autoReleaseMinutes = resourceOptions.autoReleaseMinutes; + if (resourceOptions.color) body.color = resourceOptions.color; + if (resourceOptions.statusId !== undefined) body.statusId = resourceOptions.statusId; + + // Custom Attributes verarbeiten + if (resourceCustomAttributes?.attribute && resourceCustomAttributes.attribute.length > 0) { + body.customAttributes = resourceCustomAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Resources/${resourceIdParam}`, body); + } else if (operation === 'delete') { + const resourceIdParam = this.getNodeParameter('resourceIdParam', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Resources/${resourceIdParam}`); + } + } - // SCHEDULE - else if (resource === 'schedule') { - if (operation === 'getAll') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Schedules/'); - } else if (operation === 'get') { - const scheduleId = this.getNodeParameter('scheduleId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}`); - } else if (operation === 'getSlots') { - const scheduleId = this.getNodeParameter('scheduleId', i) as number; - const slotsFilters = this.getNodeParameter('slotsFilters', i, {}) as any; - const qs: any = {}; - if (slotsFilters.resourceId) qs.resourceId = slotsFilters.resourceId; - if (slotsFilters.startDateTime) qs.startDateTime = new Date(slotsFilters.startDateTime).toISOString(); - if (slotsFilters.endDateTime) qs.endDateTime = new Date(slotsFilters.endDateTime).toISOString(); - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}/Slots`, undefined, qs); - } - } + // SCHEDULE + else if (resource === 'schedule') { + if (operation === 'getAll') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Schedules/'); + } else if (operation === 'get') { + const scheduleId = this.getNodeParameter('scheduleId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}`); + } else if (operation === 'getSlots') { + const scheduleId = this.getNodeParameter('scheduleId', i) as number; + const slotsFilters = this.getNodeParameter('slotsFilters', i, {}) as any; + const qs: any = {}; + if (slotsFilters.resourceId) qs.resourceId = slotsFilters.resourceId; + if (slotsFilters.startDateTime) qs.startDateTime = new Date(slotsFilters.startDateTime).toISOString(); + if (slotsFilters.endDateTime) qs.endDateTime = new Date(slotsFilters.endDateTime).toISOString(); + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Schedules/${scheduleId}/Slots`, undefined, qs); + } + } - // USER - else if (resource === 'user') { - if (operation === 'getAll') { - const userFilters = this.getNodeParameter('userFilters', i, {}) as any; - const qs: any = {}; - if (userFilters.username) qs.username = userFilters.username; - if (userFilters.email) qs.email = userFilters.email; - if (userFilters.firstName) qs.firstName = userFilters.firstName; - if (userFilters.lastName) qs.lastName = userFilters.lastName; - if (userFilters.organization) qs.organization = userFilters.organization; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Users/', undefined, qs); - } else if (operation === 'get') { - const userId = this.getNodeParameter('userId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Users/${userId}`); - } else if (operation === 'create') { - const emailAddress = this.getNodeParameter('emailAddress', i) as string; - const userName = this.getNodeParameter('userName', i) as string; - const userPw = this.getNodeParameter('password', i) as string; - const firstName = this.getNodeParameter('firstName', i) as string; - const lastName = this.getNodeParameter('lastName', i) as string; - const userCustomAttributes = this.getNodeParameter('userCustomAttributes', i, {}) as any; - const userOptions = this.getNodeParameter('userOptions', i, {}) as any; - - const body: any = { emailAddress, userName, password: userPw, firstName, lastName }; - - body.timezone = userOptions.timezone || configDefaults.defaultTimezone; - body.language = userOptions.language || configDefaults.defaultLanguage; - if (userOptions.phone) body.phone = userOptions.phone; - if (userOptions.organization) body.organization = userOptions.organization; - if (userOptions.position) body.position = userOptions.position; - if (userOptions.groups) body.groups = parseIdList(userOptions.groups); - - // Custom Attributes verarbeiten - if (userCustomAttributes?.attribute && userCustomAttributes.attribute.length > 0) { - body.customAttributes = userCustomAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Users/', body); - } else if (operation === 'update') { - const userId = this.getNodeParameter('userId', i) as number; - const firstName = this.getNodeParameter('firstName', i) as string; - const lastName = this.getNodeParameter('lastName', i) as string; - const userCustomAttributes = this.getNodeParameter('userCustomAttributes', i, {}) as any; - const userOptions = this.getNodeParameter('userOptions', i, {}) as any; - - const body: any = { firstName, lastName }; - - if (userOptions.timezone) body.timezone = userOptions.timezone; - if (userOptions.language) body.language = userOptions.language; - if (userOptions.phone) body.phone = userOptions.phone; - if (userOptions.organization) body.organization = userOptions.organization; - if (userOptions.position) body.position = userOptions.position; - if (userOptions.groups) body.groups = parseIdList(userOptions.groups); - - // Custom Attributes verarbeiten - if (userCustomAttributes?.attribute && userCustomAttributes.attribute.length > 0) { - body.customAttributes = userCustomAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}`, body); - } else if (operation === 'updatePassword') { - const userId = this.getNodeParameter('userId', i) as number; - const userPw = this.getNodeParameter('password', i) as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}/Password`, { password: userPw }); - } else if (operation === 'delete') { - const userId = this.getNodeParameter('userId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Users/${userId}`); - } - } + // USER + else if (resource === 'user') { + if (operation === 'getAll') { + const userFilters = this.getNodeParameter('userFilters', i, {}) as any; + const qs: any = {}; + if (userFilters.username) qs.username = userFilters.username; + if (userFilters.email) qs.email = userFilters.email; + if (userFilters.firstName) qs.firstName = userFilters.firstName; + if (userFilters.lastName) qs.lastName = userFilters.lastName; + if (userFilters.organization) qs.organization = userFilters.organization; + + let response = await makeApiRequest(this, baseUrl, session, 'GET', '/Users/', undefined, qs); + + // If includeCustomAttributes is enabled, fetch details for each user + if (userFilters.includeCustomAttributes && response.users && response.users.length > 0) { + const enrichedUsers = []; + for (const user of response.users) { + try { + const details = await makeApiRequest(this, baseUrl, session, 'GET', `/Users/${user.id}`); + enrichedUsers.push({ + ...user, + customAttributes: details.customAttributes || [], + }); + } catch (error) { + // Fallback to original user data + enrichedUsers.push(user); + } + } + response = { ...response, users: enrichedUsers }; + } + + responseData = response; + } else if (operation === 'get') { + const userId = this.getNodeParameter('userId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Users/${userId}`); + } else if (operation === 'create') { + const emailAddress = this.getNodeParameter('emailAddress', i) as string; + const userName = this.getNodeParameter('userName', i) as string; + const userPw = this.getNodeParameter('password', i) as string; + const firstName = this.getNodeParameter('firstName', i) as string; + const lastName = this.getNodeParameter('lastName', i) as string; + const userCustomAttributes = this.getNodeParameter('userCustomAttributes', i, {}) as any; + const userOptions = this.getNodeParameter('userOptions', i, {}) as any; + + const body: any = { emailAddress, userName, password: userPw, firstName, lastName }; + + body.timezone = userOptions.timezone || configDefaults.defaultTimezone; + body.language = userOptions.language || configDefaults.defaultLanguage; + if (userOptions.phone) body.phone = userOptions.phone; + if (userOptions.organization) body.organization = userOptions.organization; + if (userOptions.position) body.position = userOptions.position; + if (userOptions.groups) body.groups = parseIdList(userOptions.groups); + + // Custom Attributes verarbeiten + if (userCustomAttributes?.attribute && userCustomAttributes.attribute.length > 0) { + body.customAttributes = userCustomAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Users/', body); + } else if (operation === 'update') { + const userId = this.getNodeParameter('userId', i) as number; + const firstName = this.getNodeParameter('firstName', i) as string; + const lastName = this.getNodeParameter('lastName', i) as string; + const userCustomAttributes = this.getNodeParameter('userCustomAttributes', i, {}) as any; + const userOptions = this.getNodeParameter('userOptions', i, {}) as any; + + const body: any = { firstName, lastName }; + + if (userOptions.timezone) body.timezone = userOptions.timezone; + if (userOptions.language) body.language = userOptions.language; + if (userOptions.phone) body.phone = userOptions.phone; + if (userOptions.organization) body.organization = userOptions.organization; + if (userOptions.position) body.position = userOptions.position; + if (userOptions.groups) body.groups = parseIdList(userOptions.groups); + + // Custom Attributes verarbeiten + if (userCustomAttributes?.attribute && userCustomAttributes.attribute.length > 0) { + body.customAttributes = userCustomAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}`, body); + } else if (operation === 'updatePassword') { + const userId = this.getNodeParameter('userId', i) as number; + const userPw = this.getNodeParameter('password', i) as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Users/${userId}/Password`, { password: userPw }); + } else if (operation === 'delete') { + const userId = this.getNodeParameter('userId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Users/${userId}`); + } + } - // ACCOUNT - else if (resource === 'account') { - if (operation === 'get') { - const accountUserId = this.getNodeParameter('accountUserId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accounts/${accountUserId}`); - } else if (operation === 'create') { - const accountData = this.getNodeParameter('accountData', i, {}) as any; - const accountCustomAttributes = this.getNodeParameter('accountCustomAttributes', i, {}) as any; - - const body: any = {}; - - if (accountData.emailAddress) body.emailAddress = accountData.emailAddress; - if (accountData.userName) body.userName = accountData.userName; - if (accountData.password) body.password = accountData.password; - if (accountData.firstName) body.firstName = accountData.firstName; - if (accountData.lastName) body.lastName = accountData.lastName; - body.timezone = accountData.timezone || configDefaults.defaultTimezone; - body.language = accountData.language || configDefaults.defaultLanguage; - if (accountData.phone) body.phone = accountData.phone; - if (accountData.organization) body.organization = accountData.organization; - if (accountData.position) body.position = accountData.position; - if (accountData.acceptTermsOfService !== undefined) { - body.acceptTermsOfService = accountData.acceptTermsOfService; - } else { - body.acceptTermsOfService = configDefaults.defaultTermsAccepted; - } - - // Custom Attributes verarbeiten - if (accountCustomAttributes?.attribute && accountCustomAttributes.attribute.length > 0) { - body.customAttributes = accountCustomAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Accounts/', body); - } else if (operation === 'update') { - const accountUserId = this.getNodeParameter('accountUserId', i) as number; - const accountData = this.getNodeParameter('accountData', i, {}) as any; - const accountCustomAttributes = this.getNodeParameter('accountCustomAttributes', i, {}) as any; - - const body: any = {}; - - if (accountData.emailAddress) body.emailAddress = accountData.emailAddress; - if (accountData.userName) body.userName = accountData.userName; - if (accountData.firstName) body.firstName = accountData.firstName; - if (accountData.lastName) body.lastName = accountData.lastName; - if (accountData.timezone) body.timezone = accountData.timezone; - if (accountData.language) body.language = accountData.language; - if (accountData.phone) body.phone = accountData.phone; - if (accountData.organization) body.organization = accountData.organization; - if (accountData.position) body.position = accountData.position; - - // Custom Attributes verarbeiten - if (accountCustomAttributes?.attribute && accountCustomAttributes.attribute.length > 0) { - body.customAttributes = accountCustomAttributes.attribute.map((attr: any) => ({ - attributeId: attr.attributeId, - attributeValue: attr.attributeValue, - })); - } - - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}`, body); - } else if (operation === 'updatePassword') { - const accountUserId = this.getNodeParameter('accountUserId', i) as number; - const passwordChange = this.getNodeParameter('passwordChange', i, {}) as any; - const passwords = passwordChange.passwords || {}; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}/Password`, { - currentPassword: passwords.currentPassword, - newPassword: passwords.newPassword, - }); - } - } + // ACCOUNT + else if (resource === 'account') { + if (operation === 'get') { + const accountUserId = this.getNodeParameter('accountUserId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accounts/${accountUserId}`); + } else if (operation === 'create') { + const accountData = this.getNodeParameter('accountData', i, {}) as any; + const accountCustomAttributes = this.getNodeParameter('accountCustomAttributes', i, {}) as any; + + const body: any = {}; + + if (accountData.emailAddress) body.emailAddress = accountData.emailAddress; + if (accountData.userName) body.userName = accountData.userName; + if (accountData.password) body.password = accountData.password; + if (accountData.firstName) body.firstName = accountData.firstName; + if (accountData.lastName) body.lastName = accountData.lastName; + body.timezone = accountData.timezone || configDefaults.defaultTimezone; + body.language = accountData.language || configDefaults.defaultLanguage; + if (accountData.phone) body.phone = accountData.phone; + if (accountData.organization) body.organization = accountData.organization; + if (accountData.position) body.position = accountData.position; + if (accountData.acceptTermsOfService !== undefined) { + body.acceptTermsOfService = accountData.acceptTermsOfService; + } else { + body.acceptTermsOfService = configDefaults.defaultTermsAccepted; + } + + // Custom Attributes verarbeiten + if (accountCustomAttributes?.attribute && accountCustomAttributes.attribute.length > 0) { + body.customAttributes = accountCustomAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Accounts/', body); + } else if (operation === 'update') { + const accountUserId = this.getNodeParameter('accountUserId', i) as number; + const accountData = this.getNodeParameter('accountData', i, {}) as any; + const accountCustomAttributes = this.getNodeParameter('accountCustomAttributes', i, {}) as any; + + const body: any = {}; + + if (accountData.emailAddress) body.emailAddress = accountData.emailAddress; + if (accountData.userName) body.userName = accountData.userName; + if (accountData.firstName) body.firstName = accountData.firstName; + if (accountData.lastName) body.lastName = accountData.lastName; + if (accountData.timezone) body.timezone = accountData.timezone; + if (accountData.language) body.language = accountData.language; + if (accountData.phone) body.phone = accountData.phone; + if (accountData.organization) body.organization = accountData.organization; + if (accountData.position) body.position = accountData.position; + + // Custom Attributes verarbeiten + if (accountCustomAttributes?.attribute && accountCustomAttributes.attribute.length > 0) { + body.customAttributes = accountCustomAttributes.attribute.map((attr: any) => ({ + attributeId: attr.attributeId, + attributeValue: attr.attributeValue, + })); + } + + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}`, body); + } else if (operation === 'updatePassword') { + const accountUserId = this.getNodeParameter('accountUserId', i) as number; + const passwordChange = this.getNodeParameter('passwordChange', i, {}) as any; + const passwords = passwordChange.passwords || {}; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Accounts/${accountUserId}/Password`, { + currentPassword: passwords.currentPassword, + newPassword: passwords.newPassword, + }); + } + } - // GROUP - else if (resource === 'group') { - if (operation === 'getAll') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Groups/'); - } else if (operation === 'get') { - const groupId = this.getNodeParameter('groupId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Groups/${groupId}`); - } else if (operation === 'create') { - const groupName = this.getNodeParameter('groupName', i) as string; - const isDefault = this.getNodeParameter('isDefault', i, false) as boolean; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Groups/', { name: groupName, isDefault }); - } else if (operation === 'update') { - const groupId = this.getNodeParameter('groupId', i) as number; - const groupName = this.getNodeParameter('groupName', i) as string; - const isDefault = this.getNodeParameter('isDefault', i, false) as boolean; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}`, { name: groupName, isDefault }); - } else if (operation === 'delete') { - const groupId = this.getNodeParameter('groupId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Groups/${groupId}`); - } else if (operation === 'changeRoles') { - const groupId = this.getNodeParameter('groupId', i) as number; - const roleIds = this.getNodeParameter('roleIds', i, '') as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Roles`, { roleIds: parseIdList(roleIds) }); - } else if (operation === 'changePermissions') { - const groupId = this.getNodeParameter('groupId', i) as number; - const permissionResourceIds = this.getNodeParameter('permissionResourceIds', i, '') as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Permissions`, { resourceIds: parseIdList(permissionResourceIds) }); - } else if (operation === 'changeUsers') { - const groupId = this.getNodeParameter('groupId', i) as number; - const groupUserIds = this.getNodeParameter('groupUserIds', i, '') as string; - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Users`, { userIds: parseIdList(groupUserIds) }); - } - } + // GROUP + else if (resource === 'group') { + if (operation === 'getAll') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Groups/'); + } else if (operation === 'get') { + const groupId = this.getNodeParameter('groupId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Groups/${groupId}`); + } else if (operation === 'create') { + const groupName = this.getNodeParameter('groupName', i) as string; + const isDefault = this.getNodeParameter('isDefault', i, false) as boolean; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Groups/', { name: groupName, isDefault }); + } else if (operation === 'update') { + const groupId = this.getNodeParameter('groupId', i) as number; + const groupName = this.getNodeParameter('groupName', i) as string; + const isDefault = this.getNodeParameter('isDefault', i, false) as boolean; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}`, { name: groupName, isDefault }); + } else if (operation === 'delete') { + const groupId = this.getNodeParameter('groupId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Groups/${groupId}`); + } else if (operation === 'changeRoles') { + const groupId = this.getNodeParameter('groupId', i) as number; + const roleIds = this.getNodeParameter('roleIds', i, '') as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Roles`, { roleIds: parseIdList(roleIds) }); + } else if (operation === 'changePermissions') { + const groupId = this.getNodeParameter('groupId', i) as number; + const permissionResourceIds = this.getNodeParameter('permissionResourceIds', i, '') as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Permissions`, { resourceIds: parseIdList(permissionResourceIds) }); + } else if (operation === 'changeUsers') { + const groupId = this.getNodeParameter('groupId', i) as number; + const groupUserIds = this.getNodeParameter('groupUserIds', i, '') as string; + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Groups/${groupId}/Users`, { userIds: parseIdList(groupUserIds) }); + } + } - // ACCESSORY - else if (resource === 'accessory') { - if (operation === 'getAll') { - responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Accessories/'); - } else if (operation === 'get') { - const accessoryId = this.getNodeParameter('accessoryId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accessories/${accessoryId}`); - } - } + // ACCESSORY + else if (resource === 'accessory') { + if (operation === 'getAll') { + responseData = await makeApiRequest(this, baseUrl, session, 'GET', '/Accessories/'); + } else if (operation === 'get') { + const accessoryId = this.getNodeParameter('accessoryId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Accessories/${accessoryId}`); + } + } - // ATTRIBUTE - else if (resource === 'attribute') { - if (operation === 'get') { - const attributeId = this.getNodeParameter('attributeId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/${attributeId}`); - } else if (operation === 'getByCategory') { - const categoryId = this.getNodeParameter('categoryId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/Category/${categoryId}`); - } else if (operation === 'create') { - const attributeLabel = this.getNodeParameter('attributeLabel', i) as string; - const attributeType = this.getNodeParameter('attributeType', i) as number; - const categoryId = this.getNodeParameter('categoryId', i) as number; - const attributeOptions = this.getNodeParameter('attributeOptions', i, {}) as any; - const body: any = { label: attributeLabel, type: attributeType, categoryId }; - if (attributeOptions.required !== undefined) body.required = attributeOptions.required; - if (attributeOptions.adminOnly !== undefined) body.adminOnly = attributeOptions.adminOnly; - if (attributeOptions.isPrivate !== undefined) body.isPrivate = attributeOptions.isPrivate; - if (attributeOptions.sortOrder !== undefined) body.sortOrder = attributeOptions.sortOrder; - if (attributeOptions.regex) body.regex = attributeOptions.regex; - if (attributeOptions.possibleValues) body.possibleValues = attributeOptions.possibleValues.split(',').map((v: string) => v.trim()); - responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Attributes/', body); - } else if (operation === 'update') { - const attributeId = this.getNodeParameter('attributeId', i) as number; - const attributeLabel = this.getNodeParameter('attributeLabel', i) as string; - const attributeType = this.getNodeParameter('attributeType', i) as number; - const attributeOptions = this.getNodeParameter('attributeOptions', i, {}) as any; - const body: any = { label: attributeLabel, type: attributeType }; - if (attributeOptions.required !== undefined) body.required = attributeOptions.required; - if (attributeOptions.adminOnly !== undefined) body.adminOnly = attributeOptions.adminOnly; - if (attributeOptions.isPrivate !== undefined) body.isPrivate = attributeOptions.isPrivate; - if (attributeOptions.sortOrder !== undefined) body.sortOrder = attributeOptions.sortOrder; - if (attributeOptions.regex) body.regex = attributeOptions.regex; - if (attributeOptions.possibleValues) body.possibleValues = attributeOptions.possibleValues.split(',').map((v: string) => v.trim()); - responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Attributes/${attributeId}`, body); - } else if (operation === 'delete') { - const attributeId = this.getNodeParameter('attributeId', i) as number; - responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Attributes/${attributeId}`); - } - } + // ATTRIBUTE + else if (resource === 'attribute') { + if (operation === 'get') { + const attributeId = this.getNodeParameter('attributeId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/${attributeId}`); + } else if (operation === 'getByCategory') { + const categoryId = this.getNodeParameter('categoryId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'GET', `/Attributes/Category/${categoryId}`); + } else if (operation === 'create') { + const attributeLabel = this.getNodeParameter('attributeLabel', i) as string; + const attributeType = this.getNodeParameter('attributeType', i) as number; + const categoryId = this.getNodeParameter('categoryId', i) as number; + const attributeOptions = this.getNodeParameter('attributeOptions', i, {}) as any; + const body: any = { label: attributeLabel, type: attributeType, categoryId }; + if (attributeOptions.required !== undefined) body.required = attributeOptions.required; + if (attributeOptions.adminOnly !== undefined) body.adminOnly = attributeOptions.adminOnly; + if (attributeOptions.isPrivate !== undefined) body.isPrivate = attributeOptions.isPrivate; + if (attributeOptions.sortOrder !== undefined) body.sortOrder = attributeOptions.sortOrder; + if (attributeOptions.regex) body.regex = attributeOptions.regex; + if (attributeOptions.possibleValues) body.possibleValues = attributeOptions.possibleValues.split(',').map((v: string) => v.trim()); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', '/Attributes/', body); + } else if (operation === 'update') { + const attributeId = this.getNodeParameter('attributeId', i) as number; + const attributeLabel = this.getNodeParameter('attributeLabel', i) as string; + const attributeType = this.getNodeParameter('attributeType', i) as number; + const attributeOptions = this.getNodeParameter('attributeOptions', i, {}) as any; + const body: any = { label: attributeLabel, type: attributeType }; + if (attributeOptions.required !== undefined) body.required = attributeOptions.required; + if (attributeOptions.adminOnly !== undefined) body.adminOnly = attributeOptions.adminOnly; + if (attributeOptions.isPrivate !== undefined) body.isPrivate = attributeOptions.isPrivate; + if (attributeOptions.sortOrder !== undefined) body.sortOrder = attributeOptions.sortOrder; + if (attributeOptions.regex) body.regex = attributeOptions.regex; + if (attributeOptions.possibleValues) body.possibleValues = attributeOptions.possibleValues.split(',').map((v: string) => v.trim()); + responseData = await makeApiRequest(this, baseUrl, session, 'POST', `/Attributes/${attributeId}`, body); + } else if (operation === 'delete') { + const attributeId = this.getNodeParameter('attributeId', i) as number; + responseData = await makeApiRequest(this, baseUrl, session, 'DELETE', `/Attributes/${attributeId}`); + } + } - // Process response - if (responseData) { - if (Array.isArray(responseData)) { - returnData.push(...responseData.map(item => ({ json: item }))); - } else if (responseData.reservations) { - returnData.push(...responseData.reservations.map((item: any) => ({ json: item }))); - } else if (responseData.resources) { - returnData.push(...responseData.resources.map((item: any) => ({ json: item }))); - } else if (responseData.schedules) { - returnData.push(...responseData.schedules.map((item: any) => ({ json: item }))); - } else if (responseData.users) { - returnData.push(...responseData.users.map((item: any) => ({ json: item }))); - } else if (responseData.groups) { - returnData.push(...responseData.groups.map((item: any) => ({ json: item }))); - } else if (responseData.accessories) { - returnData.push(...responseData.accessories.map((item: any) => ({ json: item }))); - } else if (responseData.attributes) { - returnData.push(...responseData.attributes.map((item: any) => ({ json: item }))); - } else { - returnData.push({ json: responseData }); - } - } + // Process response + if (responseData) { + if (Array.isArray(responseData)) { + returnData.push(...responseData.map(item => ({ json: item }))); + } else if (responseData.reservations) { + returnData.push(...responseData.reservations.map((item: any) => ({ json: item }))); + } else if (responseData.resources) { + returnData.push(...responseData.resources.map((item: any) => ({ json: item }))); + } else if (responseData.schedules) { + returnData.push(...responseData.schedules.map((item: any) => ({ json: item }))); + } else if (responseData.users) { + returnData.push(...responseData.users.map((item: any) => ({ json: item }))); + } else if (responseData.groups) { + returnData.push(...responseData.groups.map((item: any) => ({ json: item }))); + } else if (responseData.accessories) { + returnData.push(...responseData.accessories.map((item: any) => ({ json: item }))); + } else if (responseData.attributes) { + returnData.push(...responseData.attributes.map((item: any) => ({ json: item }))); + } else { + returnData.push({ json: responseData }); + } + } - } catch (error: any) { - if (this.continueOnFail()) { - returnData.push({ json: { error: error.message } }); - continue; - } - throw error; - } - } - } finally { - await signOut(this, baseUrl, session); - } + } catch (error: any) { + if (this.continueOnFail()) { + returnData.push({ json: { error: error.message } }); + continue; + } + throw error; + } + } + } finally { + await signOut(this, baseUrl, session); + } - return [returnData]; - } + return [returnData]; + } } diff --git a/nodes/LibreBookingTrigger/LibreBookingTrigger.node.ts b/nodes/LibreBookingTrigger/LibreBookingTrigger.node.ts index 7079dc8..f2dac94 100644 --- a/nodes/LibreBookingTrigger/LibreBookingTrigger.node.ts +++ b/nodes/LibreBookingTrigger/LibreBookingTrigger.node.ts @@ -53,7 +53,7 @@ async function authenticateTrigger( if (!response.isAuthenticated) { throw new NodeOperationError( pollFunctions.getNode(), - 'Authentifizierung fehlgeschlagen', + 'Authentifizierung fehlgeschlagen. Überprüfen Sie Ihre Zugangsdaten.', ); } @@ -65,6 +65,7 @@ async function authenticateTrigger( } catch (error: any) { throw new NodeApiError(pollFunctions.getNode(), error, { message: 'Authentifizierung fehlgeschlagen', + description: 'Überprüfen Sie die LibreBooking URL und Ihre Zugangsdaten.', }); } } @@ -113,23 +114,29 @@ async function getReservations( if (filters.scheduleId) qs.scheduleId = filters.scheduleId; if (filters.userId) qs.userId = filters.userId; - const response = await pollFunctions.helpers.httpRequest({ - method: 'GET', - url: `${baseUrl}/Web/Services/index.php/Reservations/`, - headers: { - 'Content-Type': 'application/json', - 'X-Booked-SessionToken': session.sessionToken, - 'X-Booked-UserId': session.userId.toString(), - }, - qs, - json: true, - }); + try { + const response = await pollFunctions.helpers.httpRequest({ + method: 'GET', + url: `${baseUrl}/Web/Services/index.php/Reservations/`, + headers: { + 'Content-Type': 'application/json', + 'X-Booked-SessionToken': session.sessionToken, + 'X-Booked-UserId': session.userId.toString(), + }, + qs, + json: true, + }); - return response.reservations || []; + return response.reservations || []; + } catch (error: any) { + throw new NodeApiError(pollFunctions.getNode(), error, { + message: 'Fehler beim Abrufen der Reservierungen', + }); + } } /** - * Detaillierte Reservierungsdaten abrufen + * Detaillierte Reservierungsdaten abrufen (inkl. Custom Attributes) */ async function getReservationDetails( pollFunctions: IPollFunctions, @@ -137,24 +144,53 @@ async function getReservationDetails( session: LibreBookingSession, referenceNumber: string, ): Promise { - const response = await pollFunctions.helpers.httpRequest({ - method: 'GET', - url: `${baseUrl}/Web/Services/index.php/Reservations/${referenceNumber}`, - headers: { - 'Content-Type': 'application/json', - 'X-Booked-SessionToken': session.sessionToken, - 'X-Booked-UserId': session.userId.toString(), - }, - json: true, - }); + try { + const response = await pollFunctions.helpers.httpRequest({ + method: 'GET', + url: `${baseUrl}/Web/Services/index.php/Reservations/${referenceNumber}`, + headers: { + 'Content-Type': 'application/json', + 'X-Booked-SessionToken': session.sessionToken, + 'X-Booked-UserId': session.userId.toString(), + }, + json: true, + }); - return response; + return response; + } catch (error) { + return null; + } } /** - * Zeitfenster berechnen + * Zeitfenster berechnen für "Get All" Mode */ -function getTimeWindow(timeWindow: string): { start: string; end: string } { +function getTimeWindowForGetAll( + customStartDate?: string, + customEndDate?: string, + defaultDays: number = 14 +): { start: string; end: string } { + if (customStartDate && customEndDate) { + return { + start: new Date(customStartDate).toISOString(), + end: new Date(customEndDate).toISOString(), + }; + } + + const now = new Date(); + const endDate = new Date(now); + endDate.setDate(endDate.getDate() + defaultDays); + + return { + start: now.toISOString(), + end: endDate.toISOString(), + }; +} + +/** + * Zeitfenster berechnen für Polling + */ +function getTimeWindowForPolling(timeWindow: string): { start: string; end: string } { const now = new Date(); const start = now.toISOString(); @@ -184,7 +220,6 @@ function getTimeWindow(timeWindow: string): { start: string; end: string } { /** * Hash für Reservierung generieren (für Änderungserkennung) - * Nur relevante Felder berücksichtigen, die Änderungen anzeigen */ function getReservationHash(reservation: ReservationData): string { const relevantData = { @@ -206,11 +241,10 @@ function getReservationHash(reservation: ReservationData): string { /** * LibreBooking Trigger Node * - * Überwacht neue und geänderte Reservierungen in LibreBooking. - * - * WICHTIG: Beim ersten Poll werden nur die IDs/Hashes gespeichert, - * aber keine Events getriggert. Dies verhindert, dass alle - * existierenden Reservierungen als "neu" getriggert werden. + * Drei Modi: + * 1. Get All (One-Time): Alle Reservierungen für einen Zeitraum abrufen + * 2. New Reservations (Poll): Bei neuen Reservierungen triggern + * 3. Updated Reservations (Poll): Bei geänderten Reservierungen triggern */ export class LibreBookingTrigger implements INodeType { description: INodeTypeDescription = { @@ -220,7 +254,7 @@ export class LibreBookingTrigger implements INodeType { group: ['trigger'], version: 1, description: 'Wird bei neuen oder geänderten Reservierungen in LibreBooking ausgelöst', - subtitle: '={{$parameter["event"]}}', + subtitle: '={{$parameter["triggerMode"]}}', defaults: { name: 'LibreBooking Trigger', }, @@ -234,57 +268,74 @@ export class LibreBookingTrigger implements INodeType { ], polling: true, properties: [ + // ===================================================== + // TRIGGER MODE SELECTOR + // ===================================================== { - displayName: 'Event', - name: 'event', + displayName: 'Trigger-Modus', + name: 'triggerMode', type: 'options', options: [ - { - name: 'Neue Reservierung', - value: 'newReservation', - description: 'Wird bei neuen Reservierungen ausgelöst (nicht beim ersten Poll)' + { + name: 'Alle Abrufen (Einmalig)', + value: 'getAll', + description: 'Alle Reservierungen für einen Zeitraum abrufen (bei jedem Poll)', }, - { - name: 'Geänderte Reservierung', - value: 'updatedReservation', - description: 'Wird bei geänderten Reservierungen ausgelöst' + { + name: 'Neue Reservierungen (Polling)', + value: 'newReservations', + description: 'Nur bei neuen Reservierungen triggern', }, - { - name: 'Alle Reservierungen', - value: 'allReservations', - description: 'Wird bei neuen und geänderten Reservierungen ausgelöst' + { + name: 'Geänderte Reservierungen (Polling)', + value: 'updatedReservations', + description: 'Nur bei geänderten Reservierungen triggern', }, ], - default: 'newReservation', + default: 'getAll', + description: 'Wählen Sie den Trigger-Modus', }, + + // ===================================================== + // GET ALL MODE - DATE RANGE + // ===================================================== { - displayName: 'Hinweis', - name: 'notice', - type: 'notice', - default: '', + displayName: 'Startdatum', + name: 'startDate', + type: 'dateTime', displayOptions: { show: { - event: ['newReservation', 'allReservations'], + triggerMode: ['getAll'], }, }, - description: 'Beim ersten Poll werden existierende Reservierungen gespeichert, aber nicht getriggert. Nur nachfolgende neue Reservierungen lösen den Trigger aus.', + default: '', + description: 'Startdatum für den Abruf (leer = heute)', }, { - displayName: 'Filter', - name: 'filters', - type: 'collection', - placeholder: 'Filter hinzufügen', - default: {}, - options: [ - { displayName: 'Ressourcen-ID', name: 'resourceId', type: 'number', default: '' }, - { displayName: 'Zeitplan-ID', name: 'scheduleId', type: 'number', default: '' }, - { displayName: 'Benutzer-ID', name: 'userId', type: 'number', default: '' }, - ], + displayName: 'Enddatum', + name: 'endDate', + type: 'dateTime', + displayOptions: { + show: { + triggerMode: ['getAll'], + }, + }, + default: '', + description: 'Enddatum für den Abruf (leer = 14 Tage in der Zukunft)', }, + + // ===================================================== + // POLLING MODE - TIME WINDOW + // ===================================================== { displayName: 'Zeitfenster', name: 'timeWindow', type: 'options', + displayOptions: { + show: { + triggerMode: ['newReservations', 'updatedReservations'], + }, + }, options: [ { name: 'Nächste 7 Tage', value: '7days' }, { name: 'Nächste 14 Tage', value: '14days' }, @@ -292,7 +343,58 @@ export class LibreBookingTrigger implements INodeType { { name: 'Nächste 90 Tage', value: '90days' }, ], default: '14days', + description: 'Zeitfenster für die Überwachung von Reservierungen', }, + { + displayName: 'Hinweis', + name: 'pollingNotice', + type: 'notice', + default: '', + displayOptions: { + show: { + triggerMode: ['newReservations', 'updatedReservations'], + }, + }, + description: 'Beim ersten Poll werden existierende Reservierungen gespeichert, aber nicht getriggert. Nur nachfolgende Änderungen lösen den Trigger aus.', + }, + + // ===================================================== + // FILTERS (ALL MODES) + // ===================================================== + { + displayName: 'Filter', + name: 'filters', + type: 'collection', + placeholder: 'Filter hinzufügen', + default: {}, + options: [ + { + displayName: 'Ressourcen-ID', + name: 'resourceId', + type: 'number', + default: '', + description: 'Nur Reservierungen für diese Ressource', + }, + { + displayName: 'Zeitplan-ID', + name: 'scheduleId', + type: 'number', + default: '', + description: 'Nur Reservierungen für diesen Zeitplan', + }, + { + displayName: 'Benutzer-ID', + name: 'userId', + type: 'number', + default: '', + description: 'Nur Reservierungen für diesen Benutzer', + }, + ], + }, + + // ===================================================== + // OPTIONS (ALL MODES) + // ===================================================== { displayName: 'Optionen', name: 'options', @@ -300,12 +402,12 @@ export class LibreBookingTrigger implements INodeType { placeholder: 'Option hinzufügen', default: {}, options: [ - { - displayName: 'Detaillierte Daten Abrufen', - name: 'fetchDetails', - type: 'boolean', + { + displayName: 'Detaillierte Daten Abrufen', + name: 'fetchDetails', + type: 'boolean', default: false, - description: 'Ruft vollständige Reservierungsdaten ab (zusätzliche API-Aufrufe)', + description: 'Ruft vollständige Reservierungsdaten inkl. Custom Attributes ab (zusätzliche API-Aufrufe)', }, { displayName: 'Debug-Modus', @@ -325,16 +427,16 @@ export class LibreBookingTrigger implements INodeType { const username = credentials.username as string; const password = credentials.password as string; - const event = this.getNodeParameter('event') as string; + const triggerMode = this.getNodeParameter('triggerMode') as string; const filters = this.getNodeParameter('filters', {}) as any; - const timeWindow = this.getNodeParameter('timeWindow', '14days') as string; const options = this.getNodeParameter('options', {}) as any; + // Debug-Modus + const debugMode = options.debugMode || false; + const fetchDetails = options.fetchDetails || false; + // Workflow Static Data für State-Management const webhookData = this.getWorkflowStaticData('node') as WorkflowStaticData; - - // Debug-Modus - const debugMode = options.debugMode || false; let session: LibreBookingSession; try { @@ -344,23 +446,96 @@ export class LibreBookingTrigger implements INodeType { } try { - const { start, end } = getTimeWindow(timeWindow); - - const reservations = await getReservations( - this, - baseUrl, - session, - start, - end, - filters, - ); - const returnData: INodeExecutionData[] = []; // ========================================== - // EVENT: Neue Reservierungen + // MODE: Get All (One-Time / Every Poll) // ========================================== - if (event === 'newReservation') { + if (triggerMode === 'getAll') { + const startDate = this.getNodeParameter('startDate', '') as string; + const endDate = this.getNodeParameter('endDate', '') as string; + + const { start, end } = getTimeWindowForGetAll( + startDate || undefined, + endDate || undefined, + 14 + ); + + const reservations = await getReservations( + this, + baseUrl, + session, + start, + end, + filters, + ); + + if (debugMode) { + console.log(`[LibreBooking Trigger] Get All Mode - Found ${reservations.length} reservations`); + console.log(`[LibreBooking Trigger] Date Range: ${start} to ${end}`); + } + + if (reservations.length === 0) { + if (debugMode) { + return [[{ + json: { + _debug: true, + _message: 'Keine Reservierungen im Zeitraum gefunden', + _startDate: start, + _endDate: end, + _count: 0, + }, + }]]; + } + return null; + } + + // Alle Reservierungen zurückgeben + for (const reservation of reservations) { + let reservationData = reservation; + + if (fetchDetails) { + try { + const details = await getReservationDetails( + this, + baseUrl, + session, + reservation.referenceNumber, + ); + if (details) { + reservationData = details; + } + } catch (error) { + // Fallback auf Basisdaten + } + } + + returnData.push({ + json: { + ...reservationData, + _eventType: 'getAll', + _triggeredAt: new Date().toISOString(), + }, + }); + } + } + + // ========================================== + // MODE: New Reservations (Polling) + // ========================================== + else if (triggerMode === 'newReservations') { + const timeWindow = this.getNodeParameter('timeWindow', '14days') as string; + const { start, end } = getTimeWindowForPolling(timeWindow); + + const reservations = await getReservations( + this, + baseUrl, + session, + start, + end, + filters, + ); + // Initialisiere seenIds beim ersten Poll if (!webhookData.seenIds) { webhookData.seenIds = []; @@ -369,28 +544,35 @@ export class LibreBookingTrigger implements INodeType { const currentIds = reservations.map((r: ReservationData) => r.referenceNumber); + if (debugMode) { + console.log(`[LibreBooking Trigger] New Reservations Mode`); + console.log(`[LibreBooking Trigger] First Poll: ${webhookData.isFirstPoll}`); + console.log(`[LibreBooking Trigger] Current IDs: ${currentIds.length}, Seen IDs: ${webhookData.seenIds.length}`); + } + // Beim ersten Poll: Nur IDs speichern, NICHT triggern if (webhookData.isFirstPoll) { webhookData.seenIds = currentIds; webhookData.isFirstPoll = false; webhookData.lastPollTime = new Date().toISOString(); - + if (debugMode) { return [[{ json: { _debug: true, _message: 'Erster Poll - IDs wurden gespeichert, keine Events getriggert', _savedIds: currentIds.length, + _ids: currentIds, _timestamp: webhookData.lastPollTime, }, }]]; } - + return null; // Nichts triggern beim ersten Poll } // Nur NEUE Reservierungen (die wir noch nicht gesehen haben) - const newReservations = reservations.filter((r: ReservationData) => + const newReservations = reservations.filter((r: ReservationData) => !webhookData.seenIds!.includes(r.referenceNumber) ); @@ -399,6 +581,9 @@ export class LibreBookingTrigger implements INodeType { webhookData.lastPollTime = new Date().toISOString(); if (newReservations.length === 0) { + if (debugMode) { + console.log(`[LibreBooking Trigger] No new reservations found`); + } return null; } @@ -406,16 +591,19 @@ export class LibreBookingTrigger implements INodeType { for (const reservation of newReservations) { let reservationData = reservation; - if (options.fetchDetails) { + if (fetchDetails) { try { - reservationData = await getReservationDetails( + const details = await getReservationDetails( this, baseUrl, session, reservation.referenceNumber, ); + if (details) { + reservationData = details; + } } catch (error) { - reservationData = reservation; + // Fallback auf Basisdaten } } @@ -427,18 +615,40 @@ export class LibreBookingTrigger implements INodeType { }, }); } + + if (debugMode && returnData.length > 0) { + console.log(`[LibreBooking Trigger] Triggering ${returnData.length} new reservations`); + } } // ========================================== - // EVENT: Geänderte Reservierungen + // MODE: Updated Reservations (Polling) // ========================================== - else if (event === 'updatedReservation') { + else if (triggerMode === 'updatedReservations') { + const timeWindow = this.getNodeParameter('timeWindow', '14days') as string; + const { start, end } = getTimeWindowForPolling(timeWindow); + + const reservations = await getReservations( + this, + baseUrl, + session, + start, + end, + filters, + ); + // Initialisiere reservationHashes beim ersten Poll if (!webhookData.reservationHashes) { webhookData.reservationHashes = {}; webhookData.isFirstPoll = true; } + if (debugMode) { + console.log(`[LibreBooking Trigger] Updated Reservations Mode`); + console.log(`[LibreBooking Trigger] First Poll: ${webhookData.isFirstPoll}`); + console.log(`[LibreBooking Trigger] Current: ${reservations.length}, Stored hashes: ${Object.keys(webhookData.reservationHashes).length}`); + } + // Beim ersten Poll: Nur Hashes speichern, NICHT triggern if (webhookData.isFirstPoll) { for (const reservation of reservations) { @@ -446,7 +656,7 @@ export class LibreBookingTrigger implements INodeType { } webhookData.isFirstPoll = false; webhookData.lastPollTime = new Date().toISOString(); - + if (debugMode) { return [[{ json: { @@ -457,7 +667,7 @@ export class LibreBookingTrigger implements INodeType { }, }]]; } - + return null; // Nichts triggern beim ersten Poll } @@ -483,6 +693,9 @@ export class LibreBookingTrigger implements INodeType { webhookData.lastPollTime = new Date().toISOString(); if (updatedReservations.length === 0) { + if (debugMode) { + console.log(`[LibreBooking Trigger] No updated reservations found`); + } return null; } @@ -490,16 +703,19 @@ export class LibreBookingTrigger implements INodeType { for (const reservation of updatedReservations) { let reservationData = reservation; - if (options.fetchDetails) { + if (fetchDetails) { try { - reservationData = await getReservationDetails( + const details = await getReservationDetails( this, baseUrl, session, reservation.referenceNumber, ); + if (details) { + reservationData = details; + } } catch (error) { - reservationData = reservation; + // Fallback auf Basisdaten } } @@ -511,87 +727,10 @@ export class LibreBookingTrigger implements INodeType { }, }); } - } - // ========================================== - // EVENT: Alle Reservierungen (Neu + Geändert) - // ========================================== - else if (event === 'allReservations') { - // Initialisiere beide Tracking-Strukturen beim ersten Poll - if (!webhookData.seenIds || !webhookData.reservationHashes) { - webhookData.seenIds = []; - webhookData.reservationHashes = {}; - webhookData.isFirstPoll = true; + if (debugMode && returnData.length > 0) { + console.log(`[LibreBooking Trigger] Triggering ${returnData.length} updated reservations`); } - - // Beim ersten Poll: IDs und Hashes speichern, NICHT triggern - if (webhookData.isFirstPoll) { - webhookData.seenIds = reservations.map((r: ReservationData) => r.referenceNumber); - for (const reservation of reservations) { - webhookData.reservationHashes[reservation.referenceNumber] = getReservationHash(reservation); - } - webhookData.isFirstPoll = false; - webhookData.lastPollTime = new Date().toISOString(); - - if (debugMode) { - return [[{ - json: { - _debug: true, - _message: 'Erster Poll - IDs und Hashes wurden gespeichert, keine Events getriggert', - _savedIds: webhookData.seenIds.length, - _savedHashes: Object.keys(webhookData.reservationHashes).length, - _timestamp: webhookData.lastPollTime, - }, - }]]; - } - - return null; - } - - const newHashes: Record = {}; - const currentIds: string[] = []; - - for (const reservation of reservations) { - const refNumber = reservation.referenceNumber; - const currentHash = getReservationHash(reservation); - - currentIds.push(refNumber); - newHashes[refNumber] = currentHash; - - const isNew = !webhookData.seenIds!.includes(refNumber); - const oldHash = webhookData.reservationHashes![refNumber]; - const isUpdated = oldHash && currentHash !== oldHash; - - if (isNew || isUpdated) { - let reservationData = reservation; - - if (options.fetchDetails) { - try { - reservationData = await getReservationDetails( - this, - baseUrl, - session, - refNumber, - ); - } catch (error) { - reservationData = reservation; - } - } - - returnData.push({ - json: { - ...reservationData, - _eventType: isNew ? 'new' : 'updated', - _triggeredAt: new Date().toISOString(), - }, - }); - } - } - - // Update State - webhookData.seenIds = currentIds; - webhookData.reservationHashes = newHashes; - webhookData.lastPollTime = new Date().toISOString(); } if (returnData.length === 0) { diff --git a/package.json b/package.json index eeb3723..7366b94 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "n8n-nodes-librebooking", - "version": "1.2.0", + "version": "1.2.1", "description": "n8n Node für LibreBooking - Ressourcen- und Reservierungsverwaltung", "keywords": [ "n8n-community-node-package", diff --git a/test-api.ts b/test-api.ts new file mode 100644 index 0000000..4e668b8 --- /dev/null +++ b/test-api.ts @@ -0,0 +1,609 @@ +/** + * LibreBooking API Test Script + * + * Testet alle wichtigen API-Endpunkte mit echten Credentials + */ + +import * as https from 'https'; +import * as http from 'http'; + +const BASE_URL = 'https://librebooking.zell-cloud.de'; +const USERNAME = 'sebastian.zell@zell-aufmass.de'; +const PASSWORD = 'wanUQ4uVqU6lfP'; + +interface Session { + sessionToken: string; + userId: number; +} + +interface TestResult { + name: string; + success: boolean; + data?: any; + error?: string; +} + +const results: TestResult[] = []; + +/** + * HTTP Request Helper + */ +function makeRequest( + method: string, + path: string, + body?: any, + session?: Session, + qs?: Record +): Promise { + return new Promise((resolve, reject) => { + const url = new URL(path, BASE_URL); + + if (qs) { + Object.entries(qs).forEach(([key, value]) => { + if (value) url.searchParams.append(key, value); + }); + } + + const headers: Record = { + 'Content-Type': 'application/json', + }; + + if (session) { + headers['X-Booked-SessionToken'] = session.sessionToken; + headers['X-Booked-UserId'] = session.userId.toString(); + } + + const options = { + method, + hostname: url.hostname, + path: url.pathname + url.search, + headers, + }; + + const httpModule = url.protocol === 'https:' ? https : http; + + const req = httpModule.request(options, (res) => { + let data = ''; + res.on('data', (chunk) => { data += chunk; }); + res.on('end', () => { + try { + if (data) { + resolve(JSON.parse(data)); + } else { + resolve({ success: true }); + } + } catch (e) { + resolve({ rawData: data }); + } + }); + }); + + req.on('error', (error) => { + reject(error); + }); + + if (body) { + req.write(JSON.stringify(body)); + } + + req.end(); + }); +} + +/** + * Test Authentication + */ +async function testAuthentication(): Promise { + console.log('\n=== 1. Testing Authentication ==='); + try { + const response = await makeRequest( + 'POST', + '/Web/Services/index.php/Authentication/Authenticate', + { username: USERNAME, password: PASSWORD } + ); + + if (response.isAuthenticated) { + console.log('✅ Authentication successful'); + console.log(` Session Token: ${response.sessionToken.substring(0, 20)}...`); + console.log(` User ID: ${response.userId}`); + console.log(` Session Expires: ${response.sessionExpires}`); + results.push({ name: 'Authentication', success: true, data: { userId: response.userId } }); + return { sessionToken: response.sessionToken, userId: response.userId }; + } else { + throw new Error('Authentication failed'); + } + } catch (error: any) { + console.log('❌ Authentication failed:', error.message); + results.push({ name: 'Authentication', success: false, error: error.message }); + throw error; + } +} + +/** + * Test Get Reservations + */ +async function testGetReservations(session: Session): Promise { + console.log('\n=== 2. Testing Get Reservations ==='); + try { + // Test without date filters (should return next 2 weeks) + const response = await makeRequest( + 'GET', + '/Web/Services/index.php/Reservations/', + undefined, + session + ); + + console.log(`✅ Reservations fetched: ${response.reservations?.length || 0} found`); + + if (response.reservations && response.reservations.length > 0) { + const res = response.reservations[0]; + console.log(` Example: ${res.title || 'No title'} (${res.referenceNumber})`); + console.log(` Start: ${res.startDate}`); + console.log(` Resource: ${res.resourceName}`); + } + + results.push({ name: 'Get Reservations (no filter)', success: true, data: { count: response.reservations?.length || 0 } }); + + // Test with date filter (Feb 7-14, 2026) + console.log('\n Testing with date filter (2026-02-07 to 2026-02-14)...'); + const responseFiltered = await makeRequest( + 'GET', + '/Web/Services/index.php/Reservations/', + undefined, + session, + { + startDateTime: '2026-02-07T00:00:00', + endDateTime: '2026-02-14T23:59:59' + } + ); + + console.log(`✅ Filtered reservations: ${responseFiltered.reservations?.length || 0} found`); + results.push({ name: 'Get Reservations (date filter)', success: true, data: { count: responseFiltered.reservations?.length || 0 } }); + + } catch (error: any) { + console.log('❌ Get Reservations failed:', error.message); + results.push({ name: 'Get Reservations', success: false, error: error.message }); + } +} + +/** + * Test Get Resources + */ +async function testGetResources(session: Session): Promise { + console.log('\n=== 3. Testing Get Resources ==='); + try { + const response = await makeRequest( + 'GET', + '/Web/Services/index.php/Resources/', + undefined, + session + ); + + console.log(`✅ Resources fetched: ${response.resources?.length || 0} found`); + + let firstResourceId: number | null = null; + if (response.resources && response.resources.length > 0) { + const res = response.resources[0]; + firstResourceId = res.resourceId; + console.log(` Example: ${res.name} (ID: ${res.resourceId})`); + console.log(` Schedule ID: ${res.scheduleId}`); + console.log(` Custom Attributes: ${res.customAttributes?.length || 0}`); + + if (res.customAttributes && res.customAttributes.length > 0) { + res.customAttributes.forEach((attr: any) => { + console.log(` - ${attr.label}: ${attr.value || '(no value)'}`); + }); + } + } + + results.push({ name: 'Get Resources', success: true, data: { count: response.resources?.length || 0 } }); + return firstResourceId; + + } catch (error: any) { + console.log('❌ Get Resources failed:', error.message); + results.push({ name: 'Get Resources', success: false, error: error.message }); + return null; + } +} + +/** + * Test Get Single Resource (with custom attributes) + */ +async function testGetSingleResource(session: Session, resourceId: number): Promise { + console.log('\n=== 4. Testing Get Single Resource (with custom attributes) ==='); + try { + const response = await makeRequest( + 'GET', + `/Web/Services/index.php/Resources/${resourceId}`, + undefined, + session + ); + + console.log(`✅ Resource fetched: ${response.name}`); + console.log(` Custom Attributes: ${response.customAttributes?.length || 0}`); + + if (response.customAttributes && response.customAttributes.length > 0) { + response.customAttributes.forEach((attr: any) => { + console.log(` - ID: ${attr.id}, Label: ${attr.label}, Value: ${attr.value || '(no value)'}`); + }); + } + + results.push({ name: 'Get Single Resource', success: true, data: { customAttributes: response.customAttributes?.length || 0 } }); + + } catch (error: any) { + console.log('❌ Get Single Resource failed:', error.message); + results.push({ name: 'Get Single Resource', success: false, error: error.message }); + } +} + +/** + * Test Get Users + */ +async function testGetUsers(session: Session): Promise { + console.log('\n=== 5. Testing Get Users ==='); + try { + const response = await makeRequest( + 'GET', + '/Web/Services/index.php/Users/', + undefined, + session + ); + + console.log(`✅ Users fetched: ${response.users?.length || 0} found`); + + let firstUserId: number | null = null; + if (response.users && response.users.length > 0) { + const user = response.users[0]; + firstUserId = user.id; + console.log(` Example: ${user.firstName} ${user.lastName} (ID: ${user.id})`); + } + + results.push({ name: 'Get Users', success: true, data: { count: response.users?.length || 0 } }); + return firstUserId; + + } catch (error: any) { + console.log('❌ Get Users failed:', error.message); + results.push({ name: 'Get Users', success: false, error: error.message }); + return null; + } +} + +/** + * Test Get Single User (with custom attributes) + */ +async function testGetSingleUser(session: Session, userId: number): Promise { + console.log('\n=== 6. Testing Get Single User (with custom attributes) ==='); + try { + const response = await makeRequest( + 'GET', + `/Web/Services/index.php/Users/${userId}`, + undefined, + session + ); + + console.log(`✅ User fetched: ${response.firstName} ${response.lastName}`); + console.log(` Custom Attributes: ${response.customAttributes?.length || 0}`); + + if (response.customAttributes && response.customAttributes.length > 0) { + response.customAttributes.forEach((attr: any) => { + console.log(` - ID: ${attr.id}, Label: ${attr.label}, Value: ${attr.value || '(no value)'}`); + }); + } + + results.push({ name: 'Get Single User', success: true, data: { customAttributes: response.customAttributes?.length || 0 } }); + + } catch (error: any) { + console.log('❌ Get Single User failed:', error.message); + results.push({ name: 'Get Single User', success: false, error: error.message }); + } +} + +/** + * Test Get Schedules + */ +async function testGetSchedules(session: Session): Promise { + console.log('\n=== 7. Testing Get Schedules ==='); + try { + const response = await makeRequest( + 'GET', + '/Web/Services/index.php/Schedules/', + undefined, + session + ); + + console.log(`✅ Schedules fetched: ${response.schedules?.length || 0} found`); + + if (response.schedules && response.schedules.length > 0) { + const schedule = response.schedules[0]; + console.log(` Example: ${schedule.name} (ID: ${schedule.id})`); + } + + results.push({ name: 'Get Schedules', success: true, data: { count: response.schedules?.length || 0 } }); + + } catch (error: any) { + console.log('❌ Get Schedules failed:', error.message); + results.push({ name: 'Get Schedules', success: false, error: error.message }); + } +} + +/** + * Test Get Attributes by Category + */ +async function testGetAttributes(session: Session): Promise { + console.log('\n=== 8. Testing Get Attributes by Category ==='); + + const categories = [ + { id: 1, name: 'Reservation' }, + { id: 2, name: 'User' }, + { id: 4, name: 'Resource' }, + { id: 5, name: 'Resource Type' }, + ]; + + for (const cat of categories) { + try { + const response = await makeRequest( + 'GET', + `/Web/Services/index.php/Attributes/Category/${cat.id}`, + undefined, + session + ); + + console.log(`✅ ${cat.name} Attributes: ${response.attributes?.length || 0} found`); + + if (response.attributes && response.attributes.length > 0) { + response.attributes.forEach((attr: any) => { + console.log(` - ID: ${attr.id}, Label: ${attr.label}, Type: ${attr.type}, Required: ${attr.required}`); + }); + } + + results.push({ name: `Get Attributes (${cat.name})`, success: true, data: { count: response.attributes?.length || 0 } }); + + } catch (error: any) { + console.log(`❌ Get ${cat.name} Attributes failed:`, error.message); + results.push({ name: `Get Attributes (${cat.name})`, success: false, error: error.message }); + } + } +} + +/** + * Test Create, Update, Delete Reservation + */ +async function testReservationCRUD(session: Session, resourceId: number): Promise { + console.log('\n=== 9. Testing Reservation CRUD ==='); + + // Create + console.log(' Creating test reservation...'); + try { + const createResponse = await makeRequest( + 'POST', + '/Web/Services/index.php/Reservations/', + { + title: 'API Test Reservation', + description: 'Created by n8n node test script', + resourceId: resourceId, + startDateTime: '2026-02-07T10:00:00', + endDateTime: '2026-02-07T11:00:00', + userId: session.userId, + termsAccepted: true, + allowParticipation: false, + }, + session + ); + + if (createResponse.referenceNumber) { + console.log(`✅ Reservation created: ${createResponse.referenceNumber}`); + results.push({ name: 'Create Reservation', success: true, data: { referenceNumber: createResponse.referenceNumber } }); + + const refNum = createResponse.referenceNumber; + + // Get the created reservation + console.log(' Fetching created reservation...'); + const getResponse = await makeRequest( + 'GET', + `/Web/Services/index.php/Reservations/${refNum}`, + undefined, + session + ); + console.log(`✅ Reservation fetched: ${getResponse.title}`); + console.log(` Custom Attributes: ${getResponse.customAttributes?.length || 0}`); + if (getResponse.customAttributes && getResponse.customAttributes.length > 0) { + getResponse.customAttributes.forEach((attr: any) => { + console.log(` - ID: ${attr.id}, Label: ${attr.label}, Value: ${attr.value || '(no value)'}`); + }); + } + results.push({ name: 'Get Created Reservation', success: true }); + + // Update + console.log(' Updating reservation...'); + const updateResponse = await makeRequest( + 'POST', + `/Web/Services/index.php/Reservations/${refNum}?updateScope=this`, + { + title: 'API Test Reservation UPDATED', + description: 'Updated by n8n node test script', + resourceId: resourceId, + startDateTime: '2026-02-07T10:00:00', + endDateTime: '2026-02-07T12:00:00', + termsAccepted: true, + allowParticipation: false, + }, + session + ); + console.log(`✅ Reservation updated`); + results.push({ name: 'Update Reservation', success: true }); + + // Delete + console.log(' Deleting reservation...'); + const deleteResponse = await makeRequest( + 'DELETE', + `/Web/Services/index.php/Reservations/${refNum}?updateScope=this`, + undefined, + session + ); + console.log(`✅ Reservation deleted`); + results.push({ name: 'Delete Reservation', success: true }); + + } else { + console.log('❌ Create Reservation failed - no reference number returned'); + console.log(' Response:', JSON.stringify(createResponse, null, 2)); + results.push({ name: 'Create Reservation', success: false, error: JSON.stringify(createResponse) }); + } + + } catch (error: any) { + console.log('❌ Reservation CRUD failed:', error.message); + results.push({ name: 'Reservation CRUD', success: false, error: error.message }); + } +} + +/** + * Test Groups + */ +async function testGetGroups(session: Session): Promise { + console.log('\n=== 10. Testing Get Groups ==='); + try { + const response = await makeRequest( + 'GET', + '/Web/Services/index.php/Groups/', + undefined, + session + ); + + console.log(`✅ Groups fetched: ${response.groups?.length || 0} found`); + + if (response.groups && response.groups.length > 0) { + const group = response.groups[0]; + console.log(` Example: ${group.name} (ID: ${group.id})`); + } + + results.push({ name: 'Get Groups', success: true, data: { count: response.groups?.length || 0 } }); + + } catch (error: any) { + console.log('❌ Get Groups failed:', error.message); + results.push({ name: 'Get Groups', success: false, error: error.message }); + } +} + +/** + * Test Accessories + */ +async function testGetAccessories(session: Session): Promise { + console.log('\n=== 11. Testing Get Accessories ==='); + try { + const response = await makeRequest( + 'GET', + '/Web/Services/index.php/Accessories/', + undefined, + session + ); + + console.log(`✅ Accessories fetched: ${response.accessories?.length || 0} found`); + + if (response.accessories && response.accessories.length > 0) { + const acc = response.accessories[0]; + console.log(` Example: ${acc.name} (ID: ${acc.id})`); + } + + results.push({ name: 'Get Accessories', success: true, data: { count: response.accessories?.length || 0 } }); + + } catch (error: any) { + console.log('❌ Get Accessories failed:', error.message); + results.push({ name: 'Get Accessories', success: false, error: error.message }); + } +} + +/** + * Test SignOut + */ +async function testSignOut(session: Session): Promise { + console.log('\n=== 12. Testing Sign Out ==='); + try { + await makeRequest( + 'POST', + '/Web/Services/index.php/Authentication/SignOut', + { + userId: session.userId, + sessionToken: session.sessionToken, + } + ); + console.log('✅ Sign Out successful'); + results.push({ name: 'Sign Out', success: true }); + + } catch (error: any) { + console.log('❌ Sign Out failed:', error.message); + results.push({ name: 'Sign Out', success: false, error: error.message }); + } +} + +/** + * Print Summary + */ +function printSummary(): void { + console.log('\n========================================'); + console.log(' TEST SUMMARY'); + console.log('========================================'); + + const passed = results.filter(r => r.success).length; + const failed = results.filter(r => !r.success).length; + + console.log(`\nTotal Tests: ${results.length}`); + console.log(`✅ Passed: ${passed}`); + console.log(`❌ Failed: ${failed}`); + + if (failed > 0) { + console.log('\nFailed Tests:'); + results.filter(r => !r.success).forEach(r => { + console.log(` - ${r.name}: ${r.error}`); + }); + } + + console.log('\n========================================\n'); +} + +/** + * Main Test Runner + */ +async function runTests(): Promise { + console.log('========================================'); + console.log(' LibreBooking API Test Suite'); + console.log(` URL: ${BASE_URL}`); + console.log(` User: ${USERNAME}`); + console.log('========================================'); + + try { + // Authentication + const session = await testAuthentication(); + + // Get operations + await testGetReservations(session); + const resourceId = await testGetResources(session); + if (resourceId) { + await testGetSingleResource(session, resourceId); + } + + const userId = await testGetUsers(session); + if (userId) { + await testGetSingleUser(session, userId); + } + + await testGetSchedules(session); + await testGetAttributes(session); + await testGetGroups(session); + await testGetAccessories(session); + + // CRUD operations + if (resourceId) { + await testReservationCRUD(session, resourceId); + } + + // Sign out + await testSignOut(session); + + } catch (error: any) { + console.log('\n❌ Test suite failed:', error.message); + } + + printSummary(); +} + +// Run tests +runTests().catch(console.error);