From 94b1eea2eb989cb7fca8ed00efbf82ec72c33772 Mon Sep 17 00:00:00 2001 From: Saidev Dhal Date: Sat, 21 Dec 2024 18:12:12 +0530 Subject: [PATCH] peerlist hacks --- .github/FUNDING.yml | 1 + app/(routes)/chat/[slug]/page.tsx | 136 +++++-------- app/(routes)/chat/page.tsx | 66 ++++--- app/(routes)/page.tsx | 33 ++-- app/api/ai/history/route.ts | 17 ++ app/api/ai/stream/route.ts | 10 +- app/api/auth/user/route.ts | 5 +- app/api/vectors/route.ts | 18 +- bun.lockb | Bin 343184 -> 362544 bytes components/custom/auth/auth.btns.tsx | 28 +-- components/custom/auth/auth.dialog.tsx | 76 +++++--- components/custom/chat/comp.tsx | 150 ++++++++------- components/custom/hero/dragable.cards.tsx | 10 +- components/custom/lib.selector.tsx | 38 ++-- components/custom/loading.screen.tsx | 15 ++ components/custom/mdx.comp.tsx | 57 ++++++ components/custom/msgs/msgs.tsx | 84 ++++++-- components/custom/msgs/msgs.wrapper.tsx | 4 +- components/custom/sidebar/sidebar.tsx | 39 ++-- components/ui/aurora-background.tsx | 4 +- components/ui/command.tsx | 64 +++---- components/ui/dialog.tsx | 54 +++--- components/ui/popover.tsx | 22 +-- components/ui/tooltip.tsx | 22 +-- context/user.context.tsx | 14 +- db/defaults.ts | 19 +- lib/rag.ts | 8 +- lib/redis.ts | 3 + lib/use.local.ts | 12 +- package.json | 5 + tailwind.config.ts | 222 +++++++++++----------- 31 files changed, 703 insertions(+), 533 deletions(-) create mode 100644 .github/FUNDING.yml create mode 100644 app/api/ai/history/route.ts create mode 100644 components/custom/loading.screen.tsx create mode 100644 components/custom/mdx.comp.tsx create mode 100644 lib/redis.ts diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..26909c8 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [SkidGod4444] \ No newline at end of file diff --git a/app/(routes)/chat/[slug]/page.tsx b/app/(routes)/chat/[slug]/page.tsx index 23369a1..bad3184 100644 --- a/app/(routes)/chat/[slug]/page.tsx +++ b/app/(routes)/chat/[slug]/page.tsx @@ -1,44 +1,59 @@ "use client"; -import { useState } from 'react'; -import { ChevronLeft, ChevronRight, PaperclipIcon, ArrowUpIcon } from 'lucide-react'; -import { ScrollArea } from "@/components/ui/scroll-area"; -import { Button } from "@/components/ui/button"; -import { CustomTextArea } from "@/components/custom/text.area"; +import { useEffect, useState } from "react"; import { SideBar } from "@/components/custom/sidebar/sidebar"; import useLocalStorage from "@/lib/use.local"; -import { LibSelector } from '@/components/custom/lib.selector'; +import { Message } from "ai/react"; +import { ChatComp } from "@/components/custom/chat/comp"; +import LoadingScreen from "@/components/custom/loading.screen"; -export default function Component() { - const [isCodeCollapsed, setIsCodeCollapsed] = useState(false); - const [isSidebarExpanded, setIsSidebarExpanded] = useLocalStorage("acter-isCollapsed", false); - - const toggleCodePanel = () => { - setIsCodeCollapsed(!isCodeCollapsed); +interface PageProps { + params: { + slug: string; }; +} - const messages = [ - { id: 1, text: "Hello! How can I help you today?" }, - { id: 2, text: "Can you explain how to use React hooks?" }, - { id: 3, text: "React hooks are functions that let you use state and other React features in functional components..." }, - ]; +export default function ChatPage({ params }: PageProps) { + const [loading, setLoading] = useState(true); + const [isSidebarExpanded, setIsSidebarExpanded] = useLocalStorage( + "acter-isCollapsed", + false, + ); + const [history, setHistory] = useState([]); - const codeExample = ` -import React, { useState } from 'react'; + const chatID = params.slug.replace(/^\//, ""); -function Counter() { - const [count, setCount] = useState(0); + useEffect(() => { + async function handleSlug() { + setLoading(true); + try { + const response = await fetch("/api/ai/history", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ chatID }), + }); - return ( -
-

You clicked {count} times

- -
- ); -} - `.trim(); + if (response.ok) { + const chatHistory = await response.json(); + setHistory(chatHistory); + } else { + console.error("Failed to fetch chat history"); + } + } catch (error) { + console.error("Error fetching chat history:", error); + } finally { + setLoading(false); + } + } + + handleSlug(); + }, [params.slug, chatID]); + + if (loading) { + return ; + } return (
@@ -49,64 +64,9 @@ function Counter() { /> {/* Left Panel */} -
- - - {messages.map((message) => ( -
- {message.text} -
- ))} -
- +
{/* Input Area */} -
- -
-
- - -
- -
- -
- - {/* Right Panel - Code Viewer */} -
- {!isCodeCollapsed && ( -
-

Code

- -
-                {codeExample}
-              
-
-
- )} +
); diff --git a/app/(routes)/chat/page.tsx b/app/(routes)/chat/page.tsx index 66f20cd..5b8a36a 100644 --- a/app/(routes)/chat/page.tsx +++ b/app/(routes)/chat/page.tsx @@ -1,43 +1,48 @@ "use client"; import { Badge } from "@/components/ui/badge"; -import { MoveUpRight } from "lucide-react"; import useLocalStorage from "@/lib/use.local"; import { useUser } from "@/context/user.context"; -import { OfcLinks } from "@/db/defaults"; import { SideBar } from "@/components/custom/sidebar/sidebar"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import { ChatComp } from "@/components/custom/chat/comp"; +import LoadingScreen from "@/components/custom/loading.screen"; +import { useRouter } from "next/navigation"; export default function ChatPage() { const { user } = useUser(); - const [chatID, setChatID] = useState("null"); + const router = useRouter(); + const [chatID, setChatID] = useState(null); const [isMsg, setMsg] = useState(false); + const chatInitialized = useRef(false); + const [isSidebarExpanded, setIsSidebarExpanded] = useLocalStorage( + "acter-isCollapsed", + false, + ); + + // Generate chat ID once the user is available useEffect(() => { - const fetchChatID = async () => { + if (user && !chatInitialized.current) { const id = Math.floor(Math.random() * 900000) + 100000; setChatID(id.toString()); - }; - - if (user) { - fetchChatID(); + chatInitialized.current = true; } - }, [user, chatID]); + }, [user]); + // Navigate to chat page when ready useEffect(() => { if (chatID && isMsg) { - window.location.href = `/chat/${chatID}`; + window.history.replaceState(null, "", `/chat/${chatID}`); } - }, [chatID, isMsg]); + }, [chatID, isMsg, router]); - const [isSidebarExpanded, setIsSidebarExpanded] = useLocalStorage( - "acter-isCollapsed", - false - ); + if (!chatID) { + return ; + } return ( -
+
{/* Background */}
@@ -45,31 +50,24 @@ export default function ChatPage() {
{/* Sidebar */} setIsSidebarExpanded(expanded)} - /> + isSidebarExpanded={isSidebarExpanded} + setIsSidebarExpanded={(expanded) => setIsSidebarExpanded(expanded)} + /> {/* Main Content */}
- {/* Header at the top */} + {/* Header */}
Public Beta
-

- Need awesome components to ship? -

-

- Am the one who supports Acternity UI, Magic UI and more libraries. Ask questions, modify component. -

- {/* Input area */} -
+
-
+ {/*
Generate a SaaS pricing calculator @@ -82,11 +80,11 @@ export default function ChatPage() { Write code to implement a min heap -
+
*/}
- {/* Footer at the bottom */} - */}
diff --git a/app/(routes)/page.tsx b/app/(routes)/page.tsx index 66c5f08..7ad6a8b 100644 --- a/app/(routes)/page.tsx +++ b/app/(routes)/page.tsx @@ -2,11 +2,7 @@ import { useState } from "react"; import { Button } from "@/components/ui/button"; -import { - PaperclipIcon, - ArrowUpIcon, - MoveUpRight, -} from "lucide-react"; +import { PaperclipIcon, ArrowUpIcon, MoveUpRight } from "lucide-react"; import { CustomTextArea } from "@/components/custom/text.area"; import { Badge } from "@/components/ui/badge"; import { OsBtn } from "@/components/custom/os.button"; @@ -18,14 +14,13 @@ import { LibSelector } from "@/components/custom/lib.selector"; export default function HomePage() { const [isOpen, setIsOpen] = useState(false); - const handleFormSubmit = async(event: React.FormEvent) => { + const handleFormSubmit = async (event: React.FormEvent) => { event.preventDefault(); setIsOpen(!isOpen); - } + }; return (
- {/* Background */}
@@ -36,7 +31,7 @@ export default function HomePage() { {/* Header at the top */}
{/* Public Beta */} - +
@@ -47,23 +42,27 @@ export default function HomePage() { Need awesome components to ship?

- Am the one who supports Acternity UI, Magic UI and more libraries. Ask questions, modify component. + Am the one who supports Acternity UI, Magic UI and more libraries. + Ask questions, modify component.

{/* Input area */}
-
+
-
- - -
+
+ + +
diff --git a/app/api/ai/history/route.ts b/app/api/ai/history/route.ts new file mode 100644 index 0000000..70e8de4 --- /dev/null +++ b/app/api/ai/history/route.ts @@ -0,0 +1,17 @@ +import { ragChat } from "@/lib/rag"; +import { NextRequest, NextResponse } from "next/server"; + +export const POST = async (req: NextRequest) => { + try { + const { chatID } = await req.json(); + const chatHistory = await ragChat.history.getMessages({ + amount: 100, + sessionId: chatID, + }); + + return NextResponse.json(chatHistory); + } catch (error) { + console.error("Error fetching chat history:", error); + return new NextResponse("Failed to fetch chat history", { status: 500 }); + } +}; diff --git a/app/api/ai/stream/route.ts b/app/api/ai/stream/route.ts index 577e608..ddf0463 100644 --- a/app/api/ai/stream/route.ts +++ b/app/api/ai/stream/route.ts @@ -3,16 +3,18 @@ import { aiUseChatAdapter } from "@upstash/rag-chat/nextjs"; import { ragChat } from "@/lib/rag"; export const POST = async (req: NextRequest) => { - const { messages } = await req.json(); - + const { messages, namespace, chatId } = await req.json(); + const disableRAG = !namespace; const lastMsg = messages[messages.length - 1].content; const res = await ragChat.chat(lastMsg, { - namespace: "acter-db", + namespace: namespace, streaming: true, + sessionId: chatId, historyLength: 100, historyTTL: 604_800, similarityThreshold: 0.7, + disableRAG: disableRAG, }); return aiUseChatAdapter(res); -}; \ No newline at end of file +}; diff --git a/app/api/auth/user/route.ts b/app/api/auth/user/route.ts index 89e4548..f1fc78f 100644 --- a/app/api/auth/user/route.ts +++ b/app/api/auth/user/route.ts @@ -11,6 +11,9 @@ export async function GET() { } } catch (error) { console.error("Error in fetching session:", error); - return NextResponse.json({ error: "Internal Server Error" }, { status: 500 }); + return NextResponse.json( + { error: "Internal Server Error" }, + { status: 500 }, + ); } } diff --git a/app/api/vectors/route.ts b/app/api/vectors/route.ts index 9768394..f5f904a 100644 --- a/app/api/vectors/route.ts +++ b/app/api/vectors/route.ts @@ -1,5 +1,5 @@ -import { ragChat } from '@/lib/rag'; -import { NextRequest, NextResponse } from 'next/server'; +import { ragChat } from "@/lib/rag"; +import { NextRequest, NextResponse } from "next/server"; export async function POST(req: NextRequest) { try { @@ -9,12 +9,20 @@ export async function POST(req: NextRequest) { type: "html", source: source, config: { chunkOverlap: 50, chunkSize: 200 }, - options: { namespace: namespace, metadata: { title: metadata.title, description: metadata.description } }, + options: { + namespace: namespace, + metadata: { title: metadata.title, description: metadata.description }, + }, }); - return NextResponse.json({ message: "Content added successfully to ragChat context!" }); + return NextResponse.json({ + message: "Content added successfully to ragChat context!", + }); } catch (error) { console.error("Error adding content to ragChat context:", error); - return NextResponse.json({ error: "Internal Server Error" }, { status: 500 }); + return NextResponse.json( + { error: "Internal Server Error" }, + { status: 500 }, + ); } } diff --git a/bun.lockb b/bun.lockb index 7b3bebab7c506db9f28a23ca37a32b79019f2e7c..3fa119c8a8a8bd30d9bcde0bacf77010f104e62f 100644 GIT binary patch delta 82131 zcmeFacT^S0zdd?R!%$(^GbDqd7?>wo%MZ*#7Hcg5!qWYsqJpCO84Rh=S*|!x2F3-3h0^eG;B0j` zkmV!7qoQ$-!O`Aez`vwg(D5&6NZ^q0kp2ckh+Zx-C@MU3SWu#25$-C30%<@NoD5_| z!GTfX!-p6Q*9vJB`RMr(Ap_#ra5ZptyN6z3dmuaDr(;Nz+rZH9zJ}{Xw0gau<6lyr zqFQ~GRi0=_dJKU*>Khr@FDS}j=!1;ud;~JzS+BtAf&Adq!-66Q2GuqgtPOvG zRrJV!z^LeCxC@2qTo~ghJL}}gG2fUMh=Jy8WuDpI!a(1 zXn>1@a$G9iJsyM44o8GU21disun}~F!Qk(tbv!yaXb9VBr1LgFj=&(?2OlJ<-az>( zKWg?(2GU_kimy$n#G(i>csl7WkatA{MhCkM4vKTuORXra_cmlmNJL;%RB`C+eIUk; z_iYB!*!;TQuB_HdBOvSZa?#2c1k$_rbi9guM0;Y=@N!zG^p@ac(FeoHC1nx2P4;@A@1V#>2aXMxQdlnTO zGMELrRMB`oAPu|-A<# z2D&P{nl@k~hKEG=3pN-QR5ut9qe(5@w2Es3+0Z2Dh@qrmKn6yCz1*+?A)!I2Z&3}c zzL!8QAb~&z=HZ&!{o8uB=P}Wfm~sxBB~LzNwGTi0kYwF$|w^e2Bql8 zJir3Lj(YPJ-JB{wn%A#ic+8M!gJC%Q$h#wh0{ej)uGQ1-^E7J%GaH-(6cHH`6*ef! zuopW0GuA`1#@hWzaJVBeDG&(;b_*cQe(I??x)V5W+>8pS|I<&g(LqD75*fbM*9@{6 z`p*Hi8WI{lJTzoraCCxh@PNRW&}c-AVL*6fSRlGG5gCQhP&kkcFSckieF%EY9yRjG z)w4i@;TSl}|I$$Npa+lxSPIAisi5 zfebxYpaZaojvpIq4c!5jgnkCd2BU%lBO?q3!=x4lLpkt4z_P$rz%oELAm)8iAst^f z*COd6FcA|yX*&|c1wh7nGLQ`q1u`~z0NJ3Qjx~Xds2_C93#1{hnrV1L$5TKKZGrZh zr=p`mL;Awd1JLP-sGzXKVL_1wL%;CQaDbsf2Q8SAfgFMyAPXKuPZ^vmbeykaDv+^Z z4MyiqTKOr^W$4yztZz(I-|#qtVR~n+oY|OEtB%en_2(_?}3NWZZDgPA`dKr0%yC4M|&F#SUZ!t_0fW6DYy%G zy+AFPOyFEqCIcBG5kRgg-GGddw-`{C_XVdXs{vWD15mxMzoriZmViDTe&f:n> z-vbHu)EXSq254jd3YKDlNO}NNT^|}1%N`X#kJ)fw2${iP3uJ>ggSGOffegAeKs1mP z4&?nW_52axXb{)DCM@6IkhDiHmj}3-;2WsMcskUC)MV{aXrTxpBa9z(GJpM66!V7lanq#pgi!X*4FDZ0Lz2 zF9eRv-Vs^_CE~RnSqrX#&V1`gH3MfwZ&8jtc{frE9qXB5H8>so!w6-0{?dsBn9Ap0F1 zS+^b?9|+F+?vGaenV57O3EJNt8N^0FI-u%Ut)VbDh*xds9I5-zSQ9+^o zgCc{1R4YS+;@Sw!L!nr;S^t?|5#a1m|M0Mw=#bE;LbJ63Mj#v5j{?MPKzbqr$knU@ z8X&)!rg@})P~Vt=s1RWg6d4k3xSg)`G-gQukba1XQ{eQlYKXhRum-#gI1KPnT{<5E z$M)V_?Z!WV9LotAT2E4tPeU*n-G&DTMwgnW<)_Y5Mi;Di9(^3DY{Ycw}5X0U2 zX#3DV_ZREFatsxfL`7>>YK{~@#%!XF)_rIYIQN^*K$ah}TI<*eAbY$WNDo@K8Fk-d z4F7ZE>wq3{c{8okcG5R%wTkNNJ+*Fh)(vj_rWF^~~) z6_`lZ$8Xjw{9%jcN-R^VOJ{(yfIa7$VnnEWb;u{)}FIH6W{fv{Q@p0?4NsAHW$A zPI`Ve?q|2A@6jUZC6EI!ZLeltD6kxO`+eG}v?DkoE-|Uper=8p!wrro5TN6asL&Z) z0;;ipKkwU-QripZV`EDem- z(Gke@x&v9w(kq%n{`vMHHAidCx(YW$dG@n9ko}N>g@Mm7SMmY5PeljyH$;YnMFtK) z6V{g_SN_lnp87-aFZNSn)O9WLKU~ygyBnH4pP?5(J)6Oa%Yf{5lbhNU4jDKkJTl0j zRvQ=^Wq76QK~Z>KfIj$^RxWVRFgOHl+}8a34m$0^y*Dt(( z&?7A)DI3VSzYjpBh7BS-E+er3@n6dUC?f~$C?9M1KFQ1Kn|EEkOAPT^XR~cz`mh)ZCC^XBl!6R zZPkwha>P$R!=nw*4p;`b1;}zoo@y0W1}_W#7@TXtIUw`T<9%G$=dnOP=mbCMYrVk8{=ugiM0cU7z0CGf1>xh>JZa9Pl|EZTh zhWePl2JHB=F-K z_+OpPu!O;K9>|7{0D0pRlTp=Ezf=N zwlf>Z*hm7hgM(ke|Gc3WddLQA=QFAq9d!Nyocdj0ap3IyMm37xztnnULAhekrxY-% z^*jR7z|Qs>e-32B9SR!N4m8sdo{S2L#!K|XD7Ub{2!kO91!?gCAbYkRNEcVr8wiXI za_fhc$Qhij%mZY(z);OIlZ$8#JOMIhZUX7ivp{-iQ&Fwn&*!z^%POXMEZnbU z?L7>n$5-nJ+f~PKVlm|O?@BfdbZlWtT=moHGllBZm^9=5j9X~l)v>lW8= z`*B>a+0*wn^R2z2{HC2H=C+Mb9&cK-C)mxeiHF0LpVOUV0;lc^f46Jpx%PJFdp_zA z(D`1y-;SI}e9&&&yp2v5I)~J~JpKCHb4@E&Th{OH+n7a*h7TXvJ!b0LydCep&CIy8 zr*5TNp9_7ddOOK#hbv1$>HX4%ESJAbiJ5hN z8Cme+v7X0MK9<_jx8pBQF8{J+-JQ|DA1bgWrrf+8S0=slD{gbC+Jrq*@2m=YvhwWo zey;+5{%~>Gi2|up)=hRO-*NT^$8JFY*l!kl3%u6XdNGXuh;Ir{zX3BTw1*4|DjZP&h78zB()5%>^UN0S*eL0>Em8wpC8xHt@0@TbuGqJC9STH@vd^Eu8*mFUW37+I7c-w=2iUNEz$xN zOgA7mQ3A3W80{3NdKRg-o#J25V*E`>tLGzMvNITJBGzn`%nlw#S#dI3WOq!K>dMH?ty(G5+iod5t3MinYds^gqn2NkRkCN$WHr`eo>-$KR>=pm|7E>^mmj;US ziU!J+`abeKFh3M5q-54NOPvcU{$3V&KPJ!swQaUm1=G2Kl416e`WI518d&6I5NM2~ zn)V2+ky<#gu34^*#ixPwRw=l!;^b|SXG3fc5q|JA%MZY4n~j3nLB|Y98#8yo)P24J~qyRVOAUqVUuwaC6$K54m0LC1}W zien=m<5{J9BOjA3R^)ohHH=FAl1fe^i#!=ZLliZt!;zzOZ|ozLEv2M4M!=L(avEEV zixtNvKJqoJQZz_y%~TufS4+j&+e;ehz(Vpy2p-6W=gelQn4{wFXE9D!()@gkH&s2P78~1qvF`oM}Ds7Fk~eYU5Ef{su1NBfo*hM(tFO)u><%Jo<02&R_!AQZPn` z8c6aRuqI#zb+UL?)Y_4iTMf=Z;?Te5A~{1M3vL zbQ{c5WgPGyTn&bHU>KYX4_lCqyv4K=sm@GEWvVJUoh1rj64sux?=L9Fj|* z*PT_yWi$kg3lUaW+_w#^4Vb;^>7g|=Gmz(QHmwC~#3fcPR1;t9qm->W?nA*iE7UH@ z*TLA97E1MMX;FY0(5+aow$_rS!(doM>w1|a^tBh~hiM^F@ElUFttq)_9jo;&D?DsL z+N%X5^u4Z$ zbf{fTnNi!$WWtiwMD4|Vq|o)YUZyWd`Kzg}Fu1i6(9FxU2&tA_HBFz9YQU82fo3@I zjY?n-4_lBXs=Oa5Z3@%VCB3xHU_EFAmw<7M5l)TGrtM(0)vfXgQr(n{(Oz;B+{(_Q zQY?tG!C(zL-^?tZ0b|!BCD7e$pU?Y09dcGXRCtzb2N4GH_764KL;Dd>e4$|fHeikM z*805zDw;+wo+3s68q`Vbf>lK86O5MzT9lk9i?r3EI7M6Jygmj4?9{w1wenHY11!=k zA0;QiV!DhxALUwrSCze3E#gtig!W3}W4%%v;+I>XAJ|&Be%OX7Ta<=Ajsiv64ZB=d7x72N<5Vfe~C-gu|jrf*2j1*SizFzVVh(tOT zZ6nmWgK?!psMRscll44xCQBFFD^9@{IUn4^BDP9kW3$w}gOU#MSBP-G9zS=%w80AW zHB03?D*hoBX;4QcJ;Wj}>8QmI1`;QPTOAdrL6#~Z7yzzW#jJ6nV;AVfp+B-;zkE^N zDm`YNbF_n`)t!k2@;Mlm25o?(3Y`_F!3YaX9R{;{xG>EDYsiI3y4qREL3SHN0yj-; zX6V4$E{cDsMZO0SA;!(5lUc5Udg$V4XI1lkMJ^7Yu(hUu&TKc!tUr1pmLb)d0t*O~aVYP+!2q`S9NY(e} z;2|ZCM@qBlRtK}R&tJ)ju*eJ>E;Cq4uqE^atH;99%pOYmP>b|;4$KL?M z${pq||SBBzB|4GyepHr)loX}PJFRAZ3hA8(N(23cd-CBQ7L9;D>N zTcl5e6sM6Esp??GA24vRk`BlktmKTe$ae=@Tg9nNsvfHNCs<55p`6P+wUiC}b|A*4 z6AVUAYX{<$U|N8?U_pEa#$dt}@iR-VLzJ9fEb`zX-va%HhaCtb3ukg1+f zDj$vwNy+f>l6r(IPDzM*Rp9WQL`qv7xbGE>&>F?If^mok<1B|O!4812B+e;V(ceTU z>7y)?-%uq7kTg_r8f}pe4b^N=4@#0TQb`|eG4+pBW2T{(v^`RB8e=iNfKZdMBe_K> z=@3>$se?Dh%Ty#9?JF5bbwaAXnwpAKQ>Nr|NYzujh^5FR$8e^x>;Rhw@tS%fXtcj1%V>7~=|dV+<=zP@HC2q&^cAe?aC0 zC4Cn5;biT-h+0H$_l*VO88cR(Fzlj@yyV8S4C?6};Sp^%4FjvC1Yi$Zij=2zH!QjdMvG8ak_X;;<)q=g zM5^MHZjt7uD*k{6sY-gfMRxsFYZPOGtt$YmA#PKj(M?yuJe7=AUUG4vRgNcElv>+s`n zWoif3mF=6BP*<+GW1~UJB8;u1Iy|RKuIWnpJe*+CwZYNm%nL9Eiu!zKGS9)0M{%y> zC5Ix_9=i5EVkcPLZ|pCy0V-oS{XAFe1^j@)o(0CZ)t=wqfU$P@rXDh4zM^JDBDRwlEJ&4-y2>Wxb@<8|V3&od`p$x(Q@_>Xg?Z z#i@l-*q5(?v4*^y@Ajn@Xomt@177hfE=|?P7yCO<$}T3<0m@vIdE z#(J=7p$DtXWklpI{6))?E~nPiMumTYfW ztXqTj@jgdu-@XCV2$Zpf`ppmWN~nwjtiE;4_MgE5!3v=ae0->y(!P-_Eiou_-h0c- zmRMh=2JXfx1J(>hG4xSpxzSQ>G1gcDn0D538Dy?fJxgn%7%I(u{qumXB-M7PvR*ID zf{wXL|65^`w9H`W$*CasLWI2qC)%POBGFds0i!;Q?+k870lWfoKSHR{0w?ae`|&o?_hf%RpBQovdz z$K7JeT&o^@8+w^auS54$TZSNoZ5iEMi4@KcZN238NVP>ZumC%3)AirZx0r32VA^a8 zY-ToH1;bGq?y9jtcbq&9Db9FUjN{uEu$D^3jRtlbtv;gfQoy{`r|(lp;Z@LRFKOy# z#ecO$uDu11=(yj8E2QZXSYy6Uk({Wc00E>HtRX zn{&dz0>Cf=6Y;VWteeWX+SWg4oj7#rBrwgXcwCjAf_-zp$$W?r%{NSGNHLzUlTE=O zfiZ^R#-?W3^RTu)!3j9Dq#RcKw_BvEhm~}I;}InXFzATlw8J8=J7V1*Zl%GFqgtqI z!_z{{+iaFgWLule zoM)EbgLPC(@~N@qDeH`*S7(E1UIjDV0nqAO^9_ z8Et6bW?!=$4%Sd@fX&?lYos-Y*LqdXYNvgaY-N@vo>lz!TTJI5;@t(ttJv?>Ku5O= zbOlpG8>_3b;81m*9ptGHX+FN0YG}6q3#DfJOTK zoZ^1~N2l{zrP$6on&sYLbQ?CP8D`TQu(s-(g|-(J|AQ9!!X^Ci7pqqfjLj}<@7FXo z7mS9W*#NUFU$I7-3np^cD@ytyi+liL2NY4~rd&MdTjwr#DLoH2kmo~T>o}rd4Y>+d zTdnXG#@zm@Hs$aRnMWJ2_F7|LOTf5>Xs^59gRvI)6b~YG|Iqpemf>LsQdiC5-aikl zCK$eS8?I)t4y`k_u4(I#c6bQ~^FSV=5_T=snfeqh-vDEkVD-$VV%NFeI0xW_%M^6D zV~g4J3m6u69C&sjr9}fL>JK-*xv7r_e-(>an2&h&*{?J8{3lB{wXo65YXeqaEy?LH z0gNW7kLmIbFdA#G1a2@(pKmHTCoPismg1Cck)v;E_o*eNqqmfFh!t;RFUAep0dEu- zJ&Q3w?4AW{3Z|~Ka;ZPHhVVFs4W$*B`aVD&gA_}_xOfjc5QZRb!3?s$qxDIBew5qj z3?9d~Mhn0iprraPK>h=aeL{cH`;vFH0l@wWH+2SMN%ib1&A6*LowdjxAacYoDt>0! z_nzi&&F-OK+6@Rs(<(Cc9Pkh+HUdjW<6Fl2T5PC|NZs!<#!b^8;+q}};ZdaMN%RCk zW_X~_KDA%>hrLMhx6=Fy026!8Yl6>I+Qy zF_;$p*rnxak2I&M2V*%Lj8$sQEd?6{1~Y@rQv73nn=bEqZ1p=|>DoWhT&0C`7qE7? z0RxU*;5V=qV2BBvoS%Ye+h-u&HI;v=I9;~Lkx#XWj>jP^>JiVhtxIFCzyff)#@atO zsIS#Ewg}AcTiye(hF~xP16<{=+;t{^(IoA@lVIQOGZlHkQ{Oc_`h+9pk5XzdnQUIF zN1pHo#+Qo!Rg1LfrILQtVmk3k{R#(Lt?z5a=?{z4?49EO2fliJXAM%${rg~aJ z;a4FVddW3EYP+_&K*-5pt+l%F^7T9zUcR>VGFAA*&frdYCQ_V^+E_gUYpOC@-TAY& z#%hbr6)-$c;_HQCU##u6K?-|4>PbbarFtg<$aF(3fwHpWSF6RWu`8Hn4=2$gFghO7 z1MC49&mx-TmcOkGev)T_>Gz?Qn_!yF{N}2G!KmAed1D$4rXIpgCy}zK2e^Djqk582 zUxL{5H5!$xcf3s-q2iS$&afYm@=#B}wI$sBtrsJ~>M0qGy=>M?M&*Zl-f}7Yh8^>< z2w?e*0mIiM*n$rs)d)Jai$-RfytXKP-&<~NYgCs7&40;YcpHxq{sXDzYAsx|D&Uvx zv_NG~`-5==a4v!$mxJNmBK-UQTPb+XJY8?2PJ8szpHOZ;aL~0i&hrK45wVhA%GBgVwUuqb&6sm{uRg z!}J#zVmjT+re!{((&LG@ya>O=NAKXQ)ZQ%T!SC{sp-ya=&B5BM3{MU63b3|XUULsA zzfqa<)Z50p00s;=k2u0&hhNdtdkjwu0Mnjc{zgi(m66s1zwy@qHEDem-x%}GfpG`Z z^77)(0{+9iz&dI6;0!zs>|0El?ttOlI^MbbRM=`KBXA^`C+@*UbrlOM7=4X5J;?h2 zrq#gywZpFk(kiUZcr%%*Gdzr7RNjE;^B!YY1HU-fP>tSjq_jE7drpGsBaCx%xnhd{ zD~o&+za_|tgf$r_)cW|H9f;BR4MWza?kA?zV2E+N47-OEmwGK?97<@t$6*Fz*BT7( zmoUOJkm91RZPQ1=`l|Qv`JpO)nb2K*!0cU8ae9lF`uJ_cZ$`=czCySrY%1=E*ivU>C{xx}<%3|1o1%;&DGz?f z=YvJ^aZ>z0)K9EsP~Rf+S2tM(Ghcl!z|a4R)X|bb!UsN8um2CQquO9Iy~6(vX#j#$ z{l2;vkcRZZhgTowHBFnGWIWZ4D zTk)|`zI-m@%Zxqzfs4qy_v*M0$cxCn9mI$Ehw$M=v{3@SR8C|r9(~oe@YJea{~M$& z=kTG87w}>27xCeh8<~F@AGUK<$Lm0rzky$o2dIf}$c&r#uz`E{ym@D&NJ z{|;s3f5wO9ap+Kyt+IX`1yqASBk2)u^`{i{0Z%A`0==uMKj8Ipj z?q4L-2CM2f{2MZ>nx3B<*^ryA6Pf%;=edzm4P7U)L$!_QKeame!HV30T*o{q>c}Mj z*pC;HH+t)w$oqVN^oSp@B(R5`|39MDrTeJw_Mn=~b zJ%1OFd>@b=IS4EUyrk<_bv==PIZxL-&@-L@@z3xSKX~I`KyEVcf!sX))^!P1GT#KG zLHU8qFA8MCC3SQH@*=Xlv#z^ndZIy3sK^^DA_Hw0Drp5&B(Dr!6zB=$47cd{xsm03 zbe%}vQ0KXk1~-Ln%SECk5-igiKMDf*A5kIi$shkfRv4h`MDkub_6D+tef4}Ill^s0 zq~RetC)zOnLUrNakQIg_pBBgH<%rZ{fixfvNY5qc{1+h0kJa^LU7rZ#MPza^eyH)! z1S_1TXUx!XCXf~jAg|oWhG#?PeRK5ue?#s?zv=lz-nUriz(oFPnqixsv0cX;D2W{{=-I$zSR`H&TD4>qL6C;(H{R z@c}p*7>`<;0r#_ZD~g0N*w0bIa7dSPBkMU1ogP06WOcvm<%mpPzz@bK|J!rCawE&< zKqp?+^NCDe#}C&3rwu}d1@7nth|G8hr2Ys<1E1*mxseV31)W*1@Pp-F>*a_{zSB98 z^?cCrldgZ_ROOAIAutB>vethf^X;G$Wgsic4`k6oIxhlbeo-BZF%uV&v({1PM0T(= zkmbuH>KSEnA&o1i^W4Z;R}DJzf70`FBP*<->qHJ+Js_p}x=y4)4S_75=&L6h0rAh! z6hGKN3lbg4TZ6O0PC#aL#Sd1{4M>mpQ`C{Xr_PCm!9(?OLv)=8Pb3Nje`5q~*yvpQQ5{K(6rffV_yTCsW7YfUIu`kgi{$>#J2A{4<#GgZUmnR#ac-__b)Y=N27(b-fXg7ZFVvngZFec0m4T2@OF= z&}G3uUb&GC4AS*~L*|DfpB{+=vgj{5jsbGWCIVS*GLQyL*LjKwB19x~?G*{|rs>g9fw*vVo33CtxU$!50OjA<;U<0P)Wduk(>4xDuIQ z1Ic>EL?GvD8W8^s^YMc{%+mR4AT8evq=DOjyohXgudW{e(y&87md^&#pi@9zIu1}1 zG$02Vm6*d?c;!M?B;^ zwI%g@BJV4uql2y!=_ePR6L}y1_LLV;+v_UmLT+S*6?L6RL#qI(y8=1#ZhHQ|A>II3sv6jwrBRyi)bt3Qc)XUe`_5TgBelNYeSE62#w=NJ_z@np%jt%vE zBJ+KLG@!B0o9OvOu8Zw-y}gbd^n4=k?+E1miJkR~+{g-gLuZeJfQ;2J{f2P8JdqVe z=z1iOLoy7=SsoAMko^K=Id+to1ms050@;v)1T9g3KLPgvS;1i-Z#V+vMI=9}=V$AB zZe;!`T_>`hb3k_F3Xu6ZI$j0xtYx^a3paqgi0sLqKvwWT&wr@nBOMqP36bWUV@m4WJOkt%uykr}Q)Hc$;n1AYRsg4()XSJ%zD?xk}JkoWuOypfK6IyTp_ z6%hXno$TO$Hq-@-4Ri;x0)OV}NWB+04GGlC1?lAm0O{&bAh((kK)N^)2yYw41G$dQ z1hSrAfoyL!kk@QG`d>}_2WdbW3J}wEoTK0HZ^(-0>*W>zxpl1vvZ0MSZU%BC+yi92 zdx1R0oTH_zfPY%g>)((!T-Ni6^u$#l^*@00z->LB$co`|pwEn&ZO*-M@cHgDB~P%IIN^rwjGI6%2lw#dvET(h zyoj9EuSjtHcgU6F`?oaOPV@a+n(yDzsNdG`LG}B$G~d6aX^2&n3+(rAX}*6;b4kJ` z!Cm$Hw>00sr9l|r`u;7=_it&we@pZITbl3R(tQ7xhHo@+*#r5Wq9Bkb$A9~FhUKX9 zF!B9cn(yDzeE*i_`?oaTzoq&A?YA^l|M%b0Z1JyVtW&>X{e{E6zWg++S?c||$BquU zGut*~ar4`GFDGof5}OrWewwk$hSeL+HF7$0zrwx=XAf2ww<^3yg`|ONe=NLqSdY%1 zT$gXj4l zf4Sf9tbOl=@6R_(&yKgbshlcz@w ziB3}Y-_QPSQ=;nZ9-TkuTwh;Uwv8y0bbji|Fr&CW5WfR4d*Q5nVGSzCZofZ)Y0Bxt@Er zh`-QowQrr(IH2vdxW}J1`?cz^ZbU_!T>6`Enc#q-|u_>JS@PDamd{xT$D+nzNI z4>@`tcesAB$kMyrx3?Zr>-K_xi7Nw)r_Rki6Dy_$!+pucYRCG%Na%iaQ0szQ-5>tk z%=2dKqI!n)4V~AX?RwbPBPf1R*ZCQBIxSAzar?l8B7fL7elYEqNlWr<@vdp}BCJQ_ zT;^@aZCrisb7IE>lgLRbnJO{ z#meGm4rkmBKhw%M*h?9Z&y?TPv}x1V!aD@!H5oWK`Phs`Z-)(9GGoQCwRH<-*bQ#E zr0k)HCy(0*PDBFd+Pn@8LhK=H(T1TrRaO&%jsO^ZOUz4 zp#o2A+U9Q@U~;ZEq(-}&tJ>eWy)L+OLdX=`2mK6#ovZg;Su{_hyN?|ko@jixO^>r} z#LrTiT>FI2iOr3jGEc+}`&m4td1J~S+y1vXG|DyeP`8E4%iL{$d%(M~3kI2L9NS`w z>T#vZ&R(ZioW4@kYyYXnGmboH_0w+GPUrLaXSZ=Z-h2I~4NpZb^S0zRZ*HCXL*B*D znlz?kCEH2QI*Pxy`~CUa_L$F=uf@MORT+A+|MbQm=7pyxMx1K5vTx#+nGLdDEL=8g z?4uG5_oX=ZpM3hyTov;Veyo@6ikBU`Tx+%Dk6Veq-swA}N_g_GmIl#PEA+a4(9bsK z!m{=KODq_0@9ot^1vbrb&1&%b*})mRGncjK*F5s?39+X(?!})=eyey#?uwsT zmaJ~~XnB));}3XWwJjf=T(VC1z8h%JSAD4c6^B;uuH5z3 zI<#`}j}4BLkzdEJNNL}@uXnAgiKFV>J2!6D(2OHvZh}?scWt-#h0QIJ;$`Q5gf;&TF6E!rguC@le}dPi}@K4_uq8;yt-5u2$yF zfm6%BJZc#^xYzTU*(+NX``G34Z%+QZZ~m||H6>vAr!qd}SD*bQKK}CajF7Ws^1dG4 za7~`ktob{To?N{7`Dms>aVYMWH`{=;JXZtTu8>BgnEw-ZYxOtifA zJ@okI!NFdUcN6!Q*|4kXhjKj~hK9`@hkiDjfJPbL@auS)0YvRy_6I zzsY^`{^+;&do_FO=(jX!<(^)bY_68HKm0@Jn7M9?qn8ieFlETR6u;LVRr4)MUbX6K zRELWzGd}UlF>A#Ka~s^CR++*9(U-%v?2MZ}cIWgVqZ$>u*}vxC-A=cAUAa*+G4>bJ z+UhluoCZc+dHq|UCE;bp66enwmOdyld+gN9d572krEIQ>4;jRWamJse!v^s?(0D|Q z3Nm&z9u>C+0FDXIfq>&8g>XVVB%Bn!!GLU$MmQy25KfC0A%HU?lWgb@A^`v}*B;}F1gF_dsa93$Km zF5!S%B93rdoF)7zTq6K?#3;gDafNVC)EWx7FD4Qmh+Bk*!ZQ-^NTd)Ri-&|K!Z!-= zRHPA}i5Gn^vBo>0*Xb9O9z6i%S2wN#6#6kF59HS6C27=oN{OA6RMloW9@n_*M z7Rog$Hbzl39?DTFQ{$nSj3S3h>^LaiBcbFqib*4(R2dKDDHYi$>L)=x+o^P$0>ya@y8MF(8AGQ`g^*3bSvZcRQz#^i zg-}KuqYyj|g4;LU;&D+RY15PU@33<$w#5Ux@16|N}|9MU07O@Yu@T%mB3g7-`aeq!QG2(fb@ zJf+Y~cq$O8%!QDlKxiQzQn*Z^%`6D5MA|F}$r%v7P-r7sq(bnR2Vqqzgm&Tsg$EP@ zeudCMEc+G0?D-Jv@gJ)+b`sqMgyst%?4r;`$g?55rw}$9LRYbkLRKaO=QIf2MMxTi zZVMq~Q|KWa(;?U`f{>67AwV3Xu$6+_90fDj}mWehgeprRWXyvQA|6t>Orgzu2!lo1dT6aq3K3>C{VAn?k&BTnxc(HH3u45E8^O3R@|-ErF0I;+8-NUIXD8g;BzF zDFlbL5T-7LFh*RVaFl{~7KCwPVitthbr7CXm>@itL8!7GLdG%(6U9RcmnpPa4q>uL zTMi+41B5RWrivCTAb4zquxbT_>EZ*02NVKULP!zIRzjG)34;A92#V;w3PSVE5Oz^W z74m8b?h9JZ?3RznqIIn?_CPLOg=(ZI?HibFDaV-S9Z4eUHLdX!uC~T$RwhqF4 z5w{LP@OB8-C}axP^$;9(K$yB7!Xj~n!chv|8z3we6E{GJ-3j3-g{8uCBZMluAY^QW zuuMFpaG64zO%PUyv`r9_cSHC>VU=jH8G^?i2&*AW z3Soojz7<0AeGqn0*d*j_5Z+S=+Xi8a*hV31KLqFP5Vnbs?GU;hfRIgLhj82h!R{c0 zgdGreiDMMDQgGV|VULL02_g6pgliP`3D;c^91cU6x(mVqafQNB3f{XR91;_ELx?>B z;VFe9!gCLVDn}t??16AhJfv`$LYuu1PKdO<5R#8U_(CCDwAcs1<2Zy>`yiYaA1FMa z5U?M@S+Q(CgxMz`*dKs!PINy2q4`M&yC_@`@<9miDTEz_a7k>Vkd+O=`4EIFBIFQ+ zZl@q*Q@AP|4@0m!4I$w$glpm$g{>6aju>0Dxq%as^|Gy3=C#k_-6@0p-`j?~nKZD< zUtcC3^W1c+^8UeX7QC)}?D|y87u$wk&QBg+$*)tti*dz^PM#x{d9FeyA##p`c}D^|82vV{5|E;JC^>qZO`hoAMTnu zE^N8rz-7Ozrv5Xx1ckq8+C9-JaMqL5TxYghxvd+PUOrE;P`h*S?Xs0Q+v+_iIR5qi zclDY#UO&=%{=2M06@oe!jRuRJ+3xx+|5DDp3mu4)h$oW&DDOcyyx|%WHqUz=-Rg#SbGU7wl8v z*38h0r(D`M>)z#Pnd#XpdXIN(B%N@Q+^craezkZ^uLI9weqP=ua#Z=!2TzDyG*2`i z`69V{sd5=TN3}_)xa@e{RRwEJ*f;Tu8t!?i*w!htq z3XUVcq~$p{q3h1}yQjB1(elFC3p;v57Vta2`=r;@@Q~s2rhU%$#;IH8{FB{|-t7F? z?LyJ%r;;6aWj4uW-u>L>9oSwz>d2xz%ilI>{G>S<#5#rVB&2WO zQ2%LqdeLHzeQzIlkySrHyteCdV0F>u2llM$airAaMg9eZ^EsFo{J7@0PLulnwRyR=O%)O3H-as)#8QbRXkKfijMdO2T5>6hR9?bCO}P7HtQIC)#X%}Z~TZL+}qVAt-c zOPc30?{RMPe(n5t$XJI1Deqekzhxe0&T{>IVCQL-S5+DR*Cl^g|j`==4@|T%&q6Ax8u`-Cgn1Z z|9t`LW!uGmis|9G6otV>_&B71_2z@nuCWJJw279wzx5^uIk}?!(A+Um|~8(sb35w6qi_$4-S-Z>+u5 z_r%1g{dLY=f4+9-`^3qCcl_!-6W3^7smFQGCXAT=aa{GiWx|e5YFDD|{$>qZC43BD zTdMV&J$CzGSQ6yI{I zVT-@!Rp0S`#*Yi!+wIH}Q!g4Fgna|4mGlaaDGek%xLm>pFb*349^%d(!H)2rg8NYj z@5HF15V9^qxJ%)KsC5iNw<{1*k3sk(Zc(tyf#7!>!WWTp9Ku!#Zz%jNd{00Kz6xRS z2|W53CGqkE9(^4CfYRk86dOq_JPG9}6;n18lO#H3Ly5fxWfPUWl8{b8sd61k&?zXg zB-T^8Or^wWDETGP_cWB`8&D2Wv6n>AGf+HkLWwy8rH~}{Q+Yt8;#nv~BoTQQ%IsTE zE>I~ZiE_U~X?`2ZxZk0aki_p)-cxZu2c?uGMxTR{^(U0OR2(Hy`#h9xcc7%6hw_6Y zZd0+l3&rmO6lY1yyZ~h@l{Zw%NTSh2D8cujEWQZE1^%Jpa34ySOHj(gKbN2!rDD1a zr6T-u8A|K}D4VEMhJUU=sqzp?&=n}I@DG*CR7&JPsRsY#KuLZCluW*6g)+(8xXoZhmd*$f|s~O!R{{zem5a_i5d1`kKOw}vg0P7~Ghw^~p~`CrL3bdu5bG#hrcmN8gjOQ( zE`;Pa5DrmjBZ}OE;PDnh%smM0#6AiSC{(-;p@SHDAHwW+5H3*YBwQXqX#O6;xCaor zh_e*lQ*eI>p{p465I?d$K)6exyQuXDLbs0)QXfI+A#PEy`vk%7F@yk-@)*Ka3U4U% z7QRm)1b>FG_z8qS@q&WG7YJRRLg*(lpF%iF!SoD5km&FXLhM%vn2UMCH{giSOorM?3$V^!5!pbqR0yr@GwG%c>y6@?4$4iLSmy@Pg^W^N_*rq zE9AJn_n`$7V?UjbIOdu4W@b~<@26&-zFfcJgv`Q6|9DfgSe>!Yd@DH~8gA(7`g(On z-{*si-kxmCwa5+SuW9I)?fbiFzJEC!uUfxvqaJ@mz9_ik{*m8)?N)F9IrnxWi$`^A z<1=r$&9Sc;j^^U!uHCHW{k&S`Y47HZKUb^J=K<{|ADlmXhnOl!4vC%nm+5z_QB=66 zRATl1dbJu?EIf4b3jdw~u4CU1Sy}B`gUZ9_7P{Mi-j0k_x350m7P5G%#Wvkowtv-` z6CYI=f3bn~9~RQyoJQp~Z`Pho2`AQdA9KFR0iOjww<_$pvDfYFOW}pRd#7$4+;Z`~ zX^xjFz7Ck|*vIYugwDHuYW(QPxw`4YyO+4If0EL0z}%xL!rMl25EWm-oiSqQOStpB z4g7n7!f@g83PP4GgmJGR#EG*Mx|txjzlIPmM!kk$mj}XK3JIdt8wgt|q`rZWC~i>* z&I`fsErd}b56ohd33L&cygmGUXq=~Z>x)p}t{x^g07H>P@``8eA0Fen#+2kz$14Pz=Hw3X6oV1mP%!#S(_2**T+LJ%%f*hJxkFcyZ8>;fUEFobNej)F%y2qlU@ zI4uH;KzKmm5QVd%NKpv0%R`7M3gMjCN1=HI2o;M#xFCiWgYcfh1qzphOK}KU6(Ni( z4&jP8OQBmO2<{~yTot2AK(MO};Vy-1qE<-=TPdWLgm6RLq7YmKf?p{Jw?s-Q2oA0g z-ca~c_&Pv1N@1}BguCJeh1jYPx;R3(FESk=RH+8Rq5GKEbP9t-0S5R$7y z2>JoSQ?ZVMhZ}?vKSFpe0)K??fWjdPFGLY%2(y2J5aSHtmDoq2c?}2^OG9`ghL(o# zp27tR?}SSk2w62Dj4K1-gE&i}TP+CgWg&bLqsl_Cs}12Ug)gF(3xur{Qe7bYEpAZ= zt^>iZ9FB=b8!@vSj)@L+p}e7DVsN}a1QY9$KW+*|GpxE1p^;A4Opp>W#rI3y2TN%m&Du<{Pu@Ob9 zK$-0cC8i3LVm4wwmFD%KRCI+>!bU{8LU~W+0+muWqFhxdSzb`aRfXbcBYvmStpODG zYEXW#5u>X?vGay4Xgog z5Nq0q?ZjH}MIGs9V{H*qN9u}`**-#D;aC^oE`}27iDLw_aB&BCh&Y0$I7_H6TF7vbVIxXyTug%L1p-PNJ}n)Z8=>e`cAFoc|97TQS8) zN;3W?>>EmzO)c;@?)kSA=_Q3rqHHs10dKGsts6@_O>2I@f1-qU`S31#7iaZ9g_2Ya zSXjG5=~KH3^W;Gx(IGr+{JF*0Oxj{2U8^Uyx0LE_L5)93ERioFG9)T25Pv@JBfhqj zhMDXd>6NP{*$)Yd<$prf&=!B|ZO_W1B>SkKuwg-w2E(!Tx^~*A8uEWD8!oY-x;AP< zvw~6DU`YBJzU5gLX}{5QZkWMPV#|vz(j4{nd@(U0{n^yV1ktOzlq1bg+EU*iLoa!! z(6paei}=4eym8 zYBZJ@yT%%O?_G>F_TFN7pJ#WLd!?9s|L@OFp6u?KGiT16Idi7$-eFIBLu*66A4Q=K zhDZ8E8*+ymk_-lixf@a=3|&nuZINEF)P^@*4CifVxhCRxcSEpE^|MqKrTHnPZKxD$ zxSYGdF8p2Kc=%8f53VHL03uCAKlokJ@<>KAXj4GLqb{$cq30?` zqO$!RK%JatxyI%g@cC}{O1%|-GR z1C1vr^Pj7v6~}!8+3p1;tpsRgB+X6Iyg=hwU;O8;&|v?Pc(@^nX31CzwA+&AA!(&S zyNr9bVIfKL#{DVW^Iu^}D}(#}lIAICWkK5}&0j>)d_dczojX`m5`9733lp+!ibq2WTaU)g@zH(0&8>uZE=6!~I%?g0oB{tv;TA2dI24N&6P}>jD1z1~iIp0BGL` z){%Tk4MF@>YF$?n8-cb=(s(X8EXO}%qMIZYtS@OzK$`;^YxJ$8HO2j(0F`ebY0YrI z8=z7RC9OH`@%^8RqE#bFoJYy{ce#~lRMJ>f#5x&sio3od;mTIp8$?|9O8}xCxDZ{Dd04~VeTw&4&Z@)U4d=@ zPx)&CaL8*0H0POj9P3&Et${W`Tc8~f4s--K?nMHffX+Y{fG4`~l()^m7GNu|4fq4t z4)9n)o(jjK=$Zp9fH0sX&{4zN9d{D2GK z3KRs~fx>_%@EC1iU2%E(H_VR9CJCwa!lnIx)I=U zxjgl_6i^!Q2Fh^cE{huT47ezZFSm1C9eHfRg~WhYK0qlNfgy zW*Jr)i5NC{MqL@8EWqR9$^$&Ltp>nz_`HB>0FQ#J1n}%TPOEpJhw}WsKp+SR1-5{` z1Xv0z1AIaA06c-=9OJ(S@hd!-03HE#1Gov?0`35R1NVRjz(e2>@ECXsJOiEsJd0jdJu0=|F`Fde=<8~6#B1B?T23NRiR2@C?Ng1!#mv6*#%x^3<1MXfTQ3r;Co;MFcKII97QKO4!pzt zP2euD7ti~E0{~Ao=JabHz$q7J&zyd9s?Z_`pZD^Bz~8i)ahv0G5OH3s402MS)Rl{}F&4 z9ym?12Y57GHy|2_0lEV{04I!T1%TeT{|-n15`jKIU!Wh*9~c0%2XcTnC-4FHTqfxO z18@q@r-3s-(pmhEKQ7|=b@_pL;GGXF1Qr3!p%71E9Dw_HU_WpWm<9X<%!fZLfS(M8 z74G5w9-8hx-~mhWY+fFr%wvy7pM<#UN;F!_y8pUFMuDVmjd`_7CeALKw-cWC<5GNr@e<- z+y@>2kAWw^CEzk}1*iq=0C=utF<>M&q9&=6<@Gy$3d&4A`W3!o*y2`o>L;vWln0VQ4muOUYF1~+ekcfdcuQ{Wm< z6}9B=g!2LpfFqC};F*_|QM>oJrU4^yzZuv9`~lnm?Iv&wn1bi20B6da8LtC4^W{u; z5b!G}Pn^y2XAwLXo;w#0fkyy04mhjjiTMkFQNU=R6ObGHIf1VLJHP-Kfe#SMA1#kT zp<{t@z&_Ca0G=Y>6F>m=;Qa*JbeeGnFcVk;aLLUjHkZ`XfvP|t7;i(+6W~u^FE9v& zq<}sYhy-e*5+#tI2ak_I(;dV8Nq|SB-vM}5I~S-2K|2f_z`X%TdWDA_KzD$P%Y6VB zlm~!=z#)K(NiH6b0mlI@8o5a1ns5a0127(N2Y5>B0w~lK*BGENZ~)Idgqmj|IHDXL zrCkWut31T?Jhb3?j%&5eKv5tM@D9SB1AhVhM(aHA2f(?_-w^l^cm(h_j%3*JBmLL5k6i0}}@*SAb5+nIC6>oC&f? zI1ugI@Kq_}kH#ccd?&z4?Etm|j2q}MFzMn+yazSIGZ07rqtz#;ien)a+z0MB|p7jeA+oaZob4mW234&|qTQ-GCB<#r!vEc7`*e`2h91ke{B z0QZ4=0R8hWa0j>z+yZU_H-Nu@>p&WC4Y&$iLHWvfqm4NvGBFJxGcz%>Ha^AS{sqtr zcnL6?a@=|ku=YiPB7i5L)2nfc@rp4j2Ve`>0E}C#S&~vc{LcgenLZ&OO~<800e~wB zt|(}_{J3(Nkq>YH@&b7P21N$8T!1EzSFM?-Ae(?nl17k*(K$(p9oCsRJaf3#GSfjh zbZb1;bWceqjeJ_6oU!qlvo|k*Qv=E<3vl+v@rY%V;<^14QW9W%;UJY&LB%9JV?iv0 z1yC5}kdJea{~|+CI0>AZP-`Js319&XXj!F^rpd9sr_7A}G<_iG0YDO$kDRV+nfOcw z?V0!fGMx^lrSU!(^dPIetdXW5m0=oVQhT5Z&>Cn3GzV$|mG#(yu7R6MKy{!Zz=7{; zK{K^0Icyo;5*#+0}_FxKKNf>fWoT*r$-pFFDliS0 z4$K4$C}=LOKLN9V*}xoNKA=@XtJp%&QuN-cDe58P3J{h9O99QS)S4MtvkmApr|{-5 z$oN$y3L$95UjXK(1(FPz;6Kat_RiuzXNOKmG_&0O#pee$mdG9R;1l&*D83}2kZs@1a<=3fIom8 zz;<8{up8I~(2dEb(RkJFnMOY5KL{KE*fwVY=Fw!F#Qh2OyJNUH4jcuJ0EYq6G(o)A zglmPL2JIBU>lxr8a2_}ZSo4xjnpWrq+>>?{VBRZi6o%CMxZVJs0FQxNKpLR+6{h_K zTnBCfj{v5V{s3V9yTEOEC7tPa0PFjEc>WupET$##f6Qpjq}@NXqVt}@wSuSs3)Xlk z*jmmrJa-1311|wqBrp2Kd)(XNnj5g^7J&gbdf*ch-U0srAAq+2eS`lv5WU9p8-VxZ zQ&TKy%$JeI!nFL_^`oRwp--Pgp7KW9B=YH~gZ!tJ$4Bz9ysXl5B2NxLs}%VtpS(7J z2`~Z~+ldu-1Sy)qqYpslOtPS9Z^t{|B(`t~9 z8BhaFfF_(mGFn9|OlwY8m_M5)_gBZEg_UO)e6kcGTbAn0E7UIfd&AVz4d|O zKwZEK2nOl^-?05_;YKsB8w%nZ2QH$&1}G>H2mnd~o&W_E2CVb2kYYd)fILj&f{1k9 z6TH{bs04Qv{^6hDW}-hHG-fKmXAVSM5c%Pr(RnEDeQ?jr_>{eNMWa`NvbYZ>9q9`ial?rK!g@VQkYSt=`dzQ}%lmloXzD*&&())3xG04L-YdIR7 zv~tjsLUk{+A`AiGYHF!@2nQm<@@_h@aO)4#h^3!X_0_c$3%+qR2 z8t-Y1MgRq{0BgENv(97PY}QWRROZ*3E6JLX0%%eeq}51k`<9?Fy#+w$W^KsJ_UBHc z#;nXDPK!nJ}agoTnX0$1zw4tS;v@=!r;C|N7n7SEX# zh5a=mP1+tzER5#XG}cV5)u8y~o>^MA^XaCon%eu|1&8wMQ6G*dZLaht^4s=ec*i_mqkCQNM z0>+740(dyP<2@&2ec1kHAO{}40&IbPccG{3OESt z0?0oQ*SWwdU^_4Z_z9Q^`~hqLHUder@IQZO%mvAM+^++M0lx#k0?|lYfop4A{eb1T zUkWS%eg+l*i-9RXRiux`bto_jScvD5xU!ObSu_|J1TdWnLa8LBuw*<82Rb9e_qcL7 zFb3Djz*yi1U>qlR0egW;NZf<#Zh+0hHswE>jjQB8apmI48Q70|){sqi3}ADd1Zesbz!Bg$ zz`XPqmU9#!J&6g20VXnm!dV~{hy*B5W2R+zZvtJTF%NlIAmxzGwzif_MN1-2ae(E7 z;mR-1@LgV#j-RFZ0zN=pF!Iy2K49>~wG^)W8jxQOvfcPq;RjsL0~GWYxB&1A!~(!w z+}{BBl_I}hT*Y%9{u#C0c({UxTfjBoGQfg!fo=!K@|kqDKNY8GHDyTGWKvNh zc-VCLaHVCbBzZ2e{V7z-NJq==o?dP(R8xRXN~dHR@2z=gA%0_vuBPMXvUE~2pz$PW zCS(n$X(1$P3TZU*P+R(imXW+vfL%&+MD`@>Uc??$1o#9#%AyQfxF~3B2FOZE@55Sc zD5My`K1wr{!Ift721)}TL1VXLyV7xs<4VUXg=QSK8o>6c z3b2hB5g9V8;Cc$odjU2HLnuSD76~gOoo!hOC)s#sSIt zIf-Ux`_dd#q8>m6>H<{26X0k?1sIB1cpY3BidpzKKrMhu)C6h(R75kgbzxdrv!S%ytI1Wn3XdI2Q>?jbY>YJ;u`%IL5ZO69e5)>12obWX_{;5u(G{)d0wF&w_o z#Fg3whIZJ{w!YC`@8XUf*t{-x#(jUR@Ee0ZJk&SPHxT2PII-X8Wp=&@v_w4XCNlfH^4UpW4l-b2K=b*5c&9) zG7tEkb#FA;bM%cJ;0y5$^!N4Gy%nFp5Rw-PVHiIgj-REUS_Fg5Stqs1Kr!=`71oX4)IORlXUZlLEiur7S~zi zXk_fBj}yHbp=SL+bp`cT-<8Mn2KkLu^$+z8&?Q92^oW7&J+{R@D$}CY_lgpM0jTo? zDQRVt$n#{w>+EH8!0r+$oBgqhBdIe=cKPvIRFkE z;vZxZ;Z2MU^oe3;S(B64-o$9*9$|y&6u1XGU3dOc)vZGfdVk*_wt#M*xQ2poX5yp~ zc;`1E+-M^ln;OgFC%9Fc8qbC1f(2MiK-EPh27jN=4GIJyClqj!DgDhc$FGkGe})u# zK2kjFM1y8VS93{l(17=Q?wQs4PSZo+2=?`7-w3c1$>0dBC^_7hC0$#2XPr)Rz{KAm zB^UC}8MUS6(hqrlMoK91!ZJ`ajIwx2K`bI)7%(jaLy&>G&cqsob1HO=CI#VQMiS% zp#i$awScY#5eFCw%A8pkf1<~4>*4>J}t zL^z6zVUTlQtZ9wVgkFpHjOfagQ~CLhH3uC+q9Lc8>YhtQyOyZ;J20^6y#4CFf78y1 z4OC85>!Fwc2J;6fO~Y(2JL_V_FxUEuCV}h$-`I&gEn$k1cH#}L`aeXOR>p=Q4`qgN zU8bzrdhx(DgC1sNd+L%9y6hopbdJ(<8ZP{8i6Sb14t7ZV+R8Z00Ezys(Q3j)ZM9l? zS1(B%e;hq^sPvk4cA`sb^!Xy_$oU|uOUn9|F_-5&f+&^(Ybv!bD2*VlwKm#(!3pXY zoYuzZYKSZ-+}fZf-3y9FZD7GcVpba%w1%4~)E3DN-NbRSwRIEs+8_WebW`i0rh6BE zint0=axT1~qb+y1m9X8?F(OS-Du`8gGK*M9GJAl74m;AJeQfLq{cP0&{%EOEW-$*O zh{Ap^j0H@n$T)GTEga6#L*#4+ooXGrha=MF1z6P^zXL?T8r zJhs{X$Y%D{hoz)x;0)`*l3-+4ENMTzq9q_SN&^-6* zCI*rKcGpWHS9>_aN6GN!-Js}Qt*0zD=lHdbZHxQ zrP7XCvf{|w4=Jq0ie3S~$3E&j2Pra4L=+R@9gME-tBR@8PqhB!c)b^MZ^0$y$U9d| z>VWugNi4^O3egTYCia@uqk9%bS3qmQ=68foI4oNM^BP*|`o|+HO9khi4h>}Bh_De3 zBaF_bz+jA~>G9WnAA&Vij;Pl;SJ5BBE-ET3=2W?g1p5XA>z-lC#4#_qeo@bd+mh;n zs{$f3jAB zSW?1D3C~El^}m)9dKNO+^}VjY&-=mqFARp>I`v=nd8PEw>^U4DgsxsJ=DKa}w|1c% zu#|C6C-aKn2&0=J%3CyvKpQ4V_S9$H0(O=jVGm=_L(u;F#ZM7vL-q3S)xp^d_rY(@ z-e#I*vbUXTe`ogevm##?V?i-0(&%O`RaTwh_3JmdO`q|vazIBJ*s7EjTWRcO;BZ8x zbKURQd{AZk>q^5bwdhh-JOM{YUvRMZG~P7lcegVwV!**+5hab4(mS-c9lB`Wp}Q98 z^F-xN#vpT`kLoXNd+3V?1`dy~Fx2-EDV^XiQg0hbv-J}@NOJTO7ds(*mi7~QI>VJ} z`Kf)SVBV?W_T9(&Su|{f6bv}YkE(_o=x?(w5-G9;BK<`B&KN{gTevR-BSXT7unEyG zbCli%M%nRI1{|4ur88PgKFP}_Q3i%|-wWO7^lQCboKt3XUV+TA{-5!Ep4mMDosqeA zzPYn=(TCkrkxN>>zqk&uIF02WtIHhW7X^c5@7U5%Nl>O2773h%6!=*5o9(Mkr9yN$ zwHFRSiak=AUR$5*T%Kp_p8@{9=(@TekV4-c(r@l znf{9(om5f+Fly_R-`ICg(5Q{;J*GlAHQ(K(WAmOpYm2B_8WaaeT8}H^?TS-Pa-ME~uPO3K zEAK!GtNX)UPq$j_UvO-amdv1F5;Q~@RTQjOUKQ79(3nv+3%5rrDkx6d94Qp%(I;~J z&R(y#SyCdA!dXD|z~#l(ZFN?MQzcJ4QrJm+%p=36PuNk%lBYgAoY8Dw^71oD)7LDf zcS^&KKqfAcCZ0doZi2_tl9rT*n4_>Ue7>nw-t|JunU<97)wV;(z^1E*9BoV`22*cuTIr2 z0clzwp{%|L4E1k$qwlajiQezVvV34YD$7W@jA=XQg*_?G@iM5}BUaB;7cj zYaiEl>SRQ>xQcj`h^SSgs_IA0Zv5P1N~cvVRgNHxfH*4Rwrs}XQwl%7W+2j}s4j0(I!pfR89SkWGup|Tp6-<^g zG+73j!zrsA!oQo*wRma`HD<+ODaal)$hG3Tn9(h|I_R~O8#P2MIL!~i$sRFo-_=I_ zSETtlu}6e*{`b0um0>Ym*)ed1YyO6Db8CZBFa2&l+}jE@Vl0 zS5w%>K%;!MR1cl_Wa;7BeGeD2aFnhks(~Z4Iyl(FRwX6fb^Pk_bPGpYq;QT=ca*Mv z*(I%iw4@}~5~(q0;?!DV<##aDoLb^CWCg574tB}l^^2#a6?TYsN}o4mZjM9X4G@hF z7@ZA=YKcnSjbDfEuA}zB=(mHDO;y)146qMkQgak33>|4Zoj;B^AAQrrwXQN(zg9=A z=#Gj$2M0&dVaE(5n}2T@V&TY9SEPX>)V;1cXWR9r?3-2lA1<(P_{)^uKUdi}e9-;5 zmXvSm3f~^c+YTHw^t*A@iw!+BqmPB-JEYKemu-o-w{UpZzLu0Rb;V%hHO~VF&G@+W zm8p5^uXC|*Y_2O-gTrvPt}yom=QD6}XP~jk-J@r&U6C+2svivZ$y-l+B&Sb3aWod3 z-_}z%cWSQx=gNt#a}z9_-Rp@4;4qA>Cz7qNlKzF9Qno>s^#yIDz6MQy`zE4EPq>4e zeH$t@6?0IZ(9E-NEq0G-styu4oH{xU`n$#|8G+E{FE$kqD9fX{@QgEh8%i}74dRTR zT(Wa}!JOriU0DuIXdxEF8M_)B!-VG(aC(HPU9Fm5SkJWFKR!Vja+OdzOjPLw{X)UP zwp%@9*lz!urw1sJiSDM$GBzl4RT&%1xzY8QcW%B*NpHsH`32DfyKbDSFANhqdKtTh zrhtPHXywx9qnpiKa{v=@Y@uQQO_z0;KvrGvR-%1xqigr9!vvy4mSIAjd}R?PWO-SH z37LX0aTVo-W)UVNM`?6ZSJdLdKd<-NJ-jgzo+eYO*AivX`OSk`sR5+h_&%pnCPgP( zINH_{5eyFq7X!b`94+7As#x+ur=a2O#o>6Pck5Jea59lGTv6xRQS=6f)Uc@1PjqF#&g!3AR`|xY;N|aBc7~bi9mO9M*cu#c^vNZr ztv^$*dMk@SX$C{@j>5h#ILkswGdSzCyRI8~Xw(!7=eUld8ab9g7S{U73l??hy?0B0 zN0oyn-QQ6p_BDp5SNPve);dBs^vi6r3?}@NL8Sg)&|59T)essfeEa_&Xy+>3Bx6In z8vd&;fg+;6vFv|0(-$iDs*@No@PDXOMx`@8r&mJM?r*GJSaaoUT2gEuVsy;`-^4dv zUBuxX@Q$us)a6OJZ86GMsJ%1;Pg;pft_*-mjcU+ z!NzbK=P10@qHqtxgecK>h_RModX(5Y#Mr=YI+8-cn%Y%34mH-YncX#$6sy^-VMbXze}{*4@Y_3ZXEStd{Iu>5EHP*=oKyelMp=zf`iN7_2rMZn$h14+a=^E zhiZHe z3}VDE?B2)+bN1S6*|Sk9*q~KU)zsS%7$as6M>)>1;`nf53v*;v~+U3-=?|1>x_^kak_CR3)Z|8`-{a(iAQ1v5!bvc|`X zROB_xj1_6vz$=Vtz!EUCZOm_ybN#-3#V|0-1=+e-aT(0!Kf&P)4qewj_B@>U-DPlK zn~(*m`+%iKwq`EvjY9>fz6Rp^;=AZBR#PGDC~r;^0W+?a^C& zMBWUIP*8k33cK4|z7xr#G9@a$or3L)r zg?TjkbM1J%?N$17ajicm^o#EcZ`IA1H0I)%X$k7vMP&l~xl6c;^`nht?TRF*t=v9A zJQ)M6x+RE|A8_rTAUyGG{sHM+63loK7Pji?P3&G^#o!wNKlv#^v>1bTlv>WG31TaA z7!uWugT-FgqV@Gxx3=WaIOX*}aEA2}t$%<)HLWs8Fg)ucBE~`627SfVvFMNXV~uX1 zGo>@^N@{ey*R?I-ia#l%c9!#AWfiTdRJ@;Rjsp2_Hz+lx?oQ+_=NrgZ-rf6&i6|m; zBsj2jo_xE>Kx4zO85>lNV7$Xzf)s|1>Q2jJ+*Y+5B+G@VqDD4J5228zSTYvxa6xSf>Yr8n}n95`(}gvUSx9W5xO)8I|@Jhn*1(Bp^5 zlstP*Zrb;(g$y@b(oGsD8jUx47h4PtZW&}AGPRV)V%B)smY`n<@4@V3*e3mct1IuGHPz~L{@M@6wV*=`02c@vC zPd@(M`tMJt58?054OS^?xc(*?0Eeco zv`OgyzYh~mlZ_3`@4(3}w#fVHxIXnt^UbVWjvgE?22X~pJHu5sYP0nIzFPAS_cQ1( zfkOLvj}WUTqegc|s6OCus#M{g#am%6t!>DU8Yw=a6vKg$qQQ@-!TFJ*>yLQzI(w8_ z1E>B&-HXpl!}j1%t_{#<62;mdjSaJC@H?Ze8@xcFVBITF=--Ey#SV6Ly@B}+91Et@ zD(RZZISu+LW7L9+xQYk!q0oXcV$KwpA#*2QE;-!?3frlug4*B(nuX{N$P}-e`m-n9 z!_PSBH-X{+P0r!!jO+7+zo)H=`g;mi-_mU!Af*IS^5$OIEaK#}u1G=DFAr1a`$24- z3N!ovpbk-w3p<)77a!MB;RwRksDIrb#1n9YhJ&L3WK3#(=B43wt92HRM5M40U!|Ta zeedY(mzI=KKZq*Rkar0<@`K}X!}e9X#qaH4;n<9nB1oz7p+er8vu7PwQ_5pk;nEKx z1$oWSWZqLF=D-IkJpo4mybU$887p>By31I#{LAmWLPEZ}-47fLfe1yVkwRCU9+Rus zkfHf;$bh%(mgUBZJOX(efP=N#b?Cc4H#N8whP>s~R_ufn>U_xGv22IxF3y&`ea4FR z$ZH-YrB?_EpFB5zue(aQ{K`l-WvrM8j-&-r#5^0hZOE=nbNj2 z>2qOVl12Irq_7o}yP1kM9~8FFNq-U)2Dvx5QrAWH&z+t>Sm&ciQzAy5acW8#k7X`4 zBkK1?N+5P^ZP2TWj}v95L)prb5iTBj(0XXQsH}{@P^u27Sni0_=ME8E2@Sg$cjwx!7uU#>)ec0{;EmSjN z!(3MgDU8gg_T4e|_^IDarB)Rf|9n!!Q0A=-4w|#NV??F-W%CRN2O|u^b33H4zPrK~ ztvc+p$pa}cCP#)|DdI5lnv=mn-95rPyDjmreoc`M*9y?hN|`nj!dHUkzxGNAs&YEh(>4L?h&N-+@7ey{2c<$4}qXoq5_xZ$Dl&#A7jR zCf?P35VLSGn?bdsq<+b@zN%o~O;JMmc*SeHI8H4>!NH2yp6Ki!Vf^jA!V$~~QhlV* zJlhVhtDSR3?RIKjZrQaNFAB{<-k#uK)Be)JrLUX4=Rtm51>xvCBavc{lp1aOyj=XT z-fzeoh!-U=?WFM{7J1FTfP=m3>C3Xej55uC>!hD0%iB0!%$tP;r|m#-dlok9_k+&5 z){EWqY{S@PwVbeO3sCkHFCvAFKXp;9UERO#oI_1P>*(%{7nNosM!p>{TF%ChfkAmJ zuZC3d2e0<2;u)^p&8ez==9PPO|AEc6Sf!525Lg~5)UV`%xe<$Om-TVddx1hdYU9ej z-SNVJkGs4km$I}@8>GSo#yn@0BVp|77fH9*!Ke zQ_jjmx=lWClXl`HDiA;8NEP98j59-p64n?&3Ay5BuN^OTICy1`| zP`dvFF>{`=L1+c!plq)`UvDq9EGU$%g^x+mS~ZbE%ci|(KdJJMp^lb1hD{LW`H&Gc zK{Uabm(&lOxxhJfqQiGR<0>&GqQkPz8K+qe`r+Ws3*L+=_-03r#~CMp2K`~=$%8x> zaiwSP|4_BUC-d8~800ze<4b>S_?5FMQD^~H8PC8^y^PIr{7~*)Qd>EVfWK!yh5Il; z#4Ru;YtymN%p;+<9B)R+aqdXvQFr@$^+p)dQkGzhT!@~Sc_h?0GLL{-iW~vWQ^u-w z{aL_Azl^Comf68&TC2!^!py`1a&}fMo1EQCp2cd`0=5xk=Y%e`M&1+!N zq3X|qEV9vm3oXSI`HQ_X798xI^Oiz(zX@V9pJmr@%G~p8CkwY_i0PSAv_6^9PUuO& z%J(3;-IGP{Whh0?W=+9zLEtL3E;Bk-(N-MUuOG5sd&t#^L0he;YmsDg;VG(%R{V2~ zbIQd_K~P4{^+TtK%fFy`S4E5P+J3sH@Ca;Egs&(aNOKAO(g#cS;wb|X)Ewf zuAvYgA9(ce;46(&!^P{%S02(3n3@v@l!IudczSfZIxJVW|>aMWdC*U_;sr zF=8bef6`3V^;%yH>ChnTjVBbsfWd&Pm7!(}G|ZhTJXfg-e!U8nT{Tn0@%iXXF^127 z%@kW#VKD-JrOcwMQKpq5&^}O%1<`zYw%Q>Mtg5oPON&Y@lOshCK5?8acC5xb|I8ec zK{xs*bwGWayXZRSYV)vS@As3iU4z%1E^|bwHPGYpA{B$#h^1>#XH~O6!_+y#@i){x z5-;)D7-#cTh;wxQ7GEHhlL7hiY!Lwt`5wY4sXV5HQS;P^RB-iI6&f58QP3Kn*3(i0 zkirl+_VqVT#&cyx%M>)~Sfp^G=hMI4%*U_&cPJ^!T5=Im@I_?uD8KcarkyxG+@Qxh zLjIsYcMvHI7ZW-^k8Jt&EZ4_{k>r4+gOlF5Z0OW%r~~F>ND}kU8J)kvhwq{M zI51A=w-^g1WvLX_MHt}btJVI~epR2MbGBSS0oZG0iZ@a?$~`zgbi={I*&PD4_G6QQmM^43mWU~g$639U=XMBw7acCfclzM@D^s5rHE4fjBd)S=we#-%$wF)ito_kGXXOzGHzU-PRqj9kjpc2Q>$}gHA2o)tm&G z4DDNAFMd1VVjH{?ks(qiR){o|YFM>GyxWLZ_g|`^+T5y4)nMsXMD~N5uuqZEx|tgH zKNJwRQXEAK;nN)s&W6n^g?S4!JhW0YvA$aCkuLS$yM@%~3r54I8J=7JlPRoyC*2e; zSBocG(T@MFiq=DI)~KI24Gim=V^YU_DVEmB&=bF)wDhxo_t5{rRGNO-M-Y64bM+6j z4Zhc@#K`gg7E#REe~W}KjO_Oq!>jzeTaLpA99%)~ndSfIo8dY6c{8`)FiBKD^$5)F zV-QTG)z3w=&pJHK6YyCFrw4^*Tu$r1#rbc`#9{hxqS4N*KNrEL%d-(J`Qeokf3*mp zI>~>C9X3iO)pyoM)+#^YPX6ys^uIUKe+&2j-Z<$Vl~q(!V}|sk{~WRY#ab=@#HO3w zI(687HKm8`iTXJH{6Q-A z@pKK>iL^h#8L>_rzXZ+%a25dP%^7~*B)6Q1FYY;~$9zcl!#d&c037qc!ALqYdG4iZ zZOi{o4&^u3x{d3^le3U@e4QA)7o2y&$z_0{Uw~uWwOmzIPR4P=da)WD2J?DxaIew3 zN`>`m#LsL$Ev2|Yoic~a+h1bXnLN!L^o@|m4C&q1i;roLHE6v^qkcy~=VZpLAAh~Z zu+{j925PD-OQbbIuYiLqfQz*@ojI9$8|y5*B2ea?Pi0E4>ZcQfdYy4m@+#9on+@V9 zEja|*vy+WEcp~2h(Hl#IAS^~X(n$Ll+&2jG{{NqKLTh*)V4XIId4J zXZB_67H?3$-d|o*tUiTgmEGI0c!TndetNnTlQEmtP63<5*#qdxij9?CXQ;4Vm=9uk zEZsr0JZN;Z)7n5fI-jgZ6bS@wU z95FW4WV>hcg$6u+g7|a<-}j)wnw-J=@Qe+3Z>vZ62 zATC;GQYB_z^5+^V@d>v1uQigru3%_~?dl}u;h;)??el(y?-Uhdqwn{XDVGoTt<-tq zt~*MK5;Z4m7lTh_QPi{T;@~N488zD>l20S7#O_eP9QrVQ?aAHq$6^A@7i0|OsXIjA zY4icfX=t)j%sg$$DQ=&JKfCM_hBF{)w$}Vi>$wMaixKd<^f)^RagO^YLq5dj`)yZ_ zb}SD2swnR49@V49&mY;P|KWybEiqe04N?EP(J@pLoY|eUl&k`_@JBF94<~3AWpK(~ z88j>hCARuj3@ll=yYzM~q?q~lAvokzYcjm9F?VxJB$eQgHj=@vxTatBnrlXsZe{J8 ziX&HAC*Grzn!Wa_Z~oR!nKEUM(T3Z>98kcF3I z5l!=k7?}Caa^10G_J1`l#4T0K6FG`$C5G)2^)LQUVI#XTHHlh4l64jh zF5zoNt=ngA3@s(&Oy=o6)pK{nck*AqwEJRp{N*=?C`fS@<9?BL4Mx?*V{NpPvl2$c z!JIF+?iZ`mP{n_Dhzv6f@!+!6p!m7BSlaf=e&GN$MBEjt@Rm)3nfo75YjvaCjqnK@ zz22*?#19BG^Nl?q?5{#=)XwXwm8)bUG1CYl<(Q58)tOeE-Y4=67@fl1=OFb*;!I+VhLB)S>RPz`Zkki(%&g&gwHg>(Hl!l3dznmy!9t=MpG_z07pi3tALFY-i33JM5 zZ`gNO?7(wq_EEnTEW_wjJkP5ElLu``QyfZ}V#CTx7theOMcZ4-Z-%g0;*^79rWSzH z<4g8yf(%}5ZgWKKiHC+2Z`CWMX>NKNhGNLX9IWhZ)h`q!dK?iEcn-~e%`gblbZ1m# zaf6elMz^k_iTQmrLX|G*h**id|6w&T^@w;+&g@rRD~<^NJ6ZIdJx4^7$DnI#tt&@F zIMzpue~0f_%>^>YUM(VKHH2rm=E@WsGTJIbzZNIE86C}ED(3T$gYi8Hpj)Yd;il|n8B$GtB#A*`*4+=$5rQw zKb835%#1Dg3S5~mz#~o}g+Bjvtxx?ME&C%tbvsVTGMX}j?`w-~gW9~7Dc=7@v&uzp z#-UW10{#!A6E^-L31=Lm2cipyY-bGPKYa0$j$?N-Ili^9*Im zsBQ^o8O^Eon*UQXIy5|~zN0nNc)RLI&1WgXJjCc`%h$01p&~gEe}JaKvgh(=+w*wp6@3&-!Jee3!^KlUYks z*3Z^&mK@UGO)9TtaDc!AL@x7vScHpj?fgFn{m@hDr>^QxkntntFwx?PF))iC8snS+ zWq&LCpAo;7hY&ohAWdT% z3OLtJ=Ws?;d5WJCd!12-S4Vxl%P%%`<2eu#GsV3sxua_Y2(qz?5W{=PUK35}o}E9L4wPjZA^xL(Gw@VDxZj+E9^&gm)` zn*9lMzaVQaXzZ6aXQ#rG*4|TuE8B+a&WfQg7#zXDk00aSR(R8}doy=%1gl>J9zhEI zz-ipYzrqgxi8;SAiGpI6&WgjxYrY2#ej4WNux87^331cG0oioGw`Zrlgz#*RZNp^Y zt8;2s2#j6({NS$F}%b^sj*rVDxF&pKY+aNDr@l|frdw|EtU6sHA+3XsL=frVpHW?iJ-1+N(Z(Fzx zyS74+p_IQGDg4sDrCZ$-g`ciPODX+L)vVAfY}`FM&v%L2KN;O@K;@}wuTbWa3+f8Xqtzze^0%n#x&}euvX8R$dp?-eG(El5~oK`zL*MW#sDRV3*Z- zeO(NG2f?}i64Ty6@c5gm;K*G?{;V^-;7dgXC4No2DL#@@yB@wJT>nA!&fXFY{sH~k zEzuRvp?}{}y{P}Dm*s4}uE(-y^H7}hjTAdnZ|#Ak$u+vI;9D8~HV5s6yhkYmGVfAm z>|J4gkLP}OMd*9{k|XwS*=3eg*>QVhCmdL!Y@ot0&}I%e%~|}oM}C{*aZj9l51IMy z3)>ISuQXz*1GI>K{QKi(!HK0I3-OVY(F#b(kCa@$H}-I!5!*-6oUu(OcVW#9z`+J` z&Qq^#=jd}^gM(irhTx?8`(gp4n==MT%U6R@_r;SB*uDC2UsU-BeQ^Fl{6{=%QEA^p zaTtB<3my2>Ly_kb9H<(41H7yPn6?{-$7U$J(4l7vdM(!8kKit!XCVGRkOl(MfM|(;hSp#A*^X3DP1`9gWwV zC<95t*0AL(4SAm`22x_6tbW$|7ZAT1OgXGi+Z0C)rm}_uPsMwK$ZbV zgRryfPh|@jj_|-v_9jG7+vjQ&d|16*>yXAy6_CQg58cw^xrjBI0u4)I#XQO=15Wzd z-?m5ZyW}6tFUA-IAS3$&0joS0k08U`6nQx{Y;kE|sWRsBU6u0r;{sjyb5Y4;N+012 zJ)Vo+cs36~4h{-~7B;RQx$>}fgjNv#5W;h@$YjDK5FGrhuEdLJrI8`@h1%i9?H`)! z+>xvQDC%KS6rxLhA?$6yF&!KX=TDLkHSzX(J5yEwBG z!Z!!#r;+YyaxNT7u9BYdt4FQ&F$pX)oRRXH4#|56Ml^ShT~S`IX&-78fG*OB{Y z{Ly;Z4XFdH==n;#cLQhXSK=dclzSz57lPK+k%KdUZwAzuxn<`!Se3(87)AqhjbDkh z{NQK{4!Q?^Ia9`W?qke|l+P4H@V8xFiR7HH+7NK$14nFT3r^}I3{kKH>b31c3Vb$Vp zh8r)%6AH}WnOZi@xwgDj`}dO#V$K8T z9%mbPy)0PRIijI8IvQBBpe9ap5Vf@f(^(-x(?E(c+8XsDUw)H|A%i0tBazUN30lO{ z%0v5VLZmlksHWm*nkrhmX}O^-w3}^)akSd(EopMGgb2THV!BWwlo;!Mh9osuBaNx%RNWch4KJMXv=Z)yXX$ ztr=a$7_q*9l`fXXGdz+(KVvOFr(3sodKNj_rdPwNDbzX?C=`S`tKG6h!y@zcRK1*E z(O8K!(6EXt3@^tf{&LmsmGCVBlGZ$sXqBp|sI|9rPvKeCWYT&=xj;L;G6Vz|f7^Mt z<0ua3SX1$HhHPd=u*EGqz35QTRd=mgE)f@Km|(!D`bB4fYEx-F;Y(u+E7rhrV@ zv#NvUVFqoO&8FhYF*ce{$w^0sP;Zd4h4gNtMIx=Q$O(cm#a=HOn@uj}?1x{i#%MRC z!$=Xvd&qhMSuLG6dwl~k^#Q4%u|;mZnC}4vvY#7CS2q3z*2iEimrZYg*X+)%R|a$6 z=|xK4t6r4T3=ZaKoQud@xe!`HowEdbWIy&i2J7}hXmdG;izkIl!5($;=#_=yyo22w z9&R>uglH}yA-ZWEy{KN;%12-+PUgNe%4nXRrQ3wUZIp?4t9E+xma7}Sm(@U!7?)4g zBJt$reP(+vH>m}xj$Rq=Y3W0SK{^3uPEYbZnKr&tHT`x)j54o)hAY5qP6G$mjtcBuW&)d*XQe>`C~wT}jxA0P|I+hO|9loB=St9v=hUkCY@xgL5G=6b8q z&y8A){g+1gR3yC-3Yda)8QsguhMx~T&V^yt>?c)PA4tn5?iMvQ(7KywRLtZSy3SGc zpq4+cn^?hi>UxXm_q|kSX=R#in%l%{U_F_FY9-_sbBdW<%ViU3Fby4&U$2}2U{|T~ zuvPkr%apvz7buKD4~wCmw$FuaacHCNAv)Vsz|k!CMO<-Hpt|@AO5d}Q3n-775XwQJ zlGoAzhZ+;-ONB7qVbm&70*$sbzi3^;7fWE}m(irw zVM(<0N*_90)8`D<9NO5a1z{t@-S#r*%-LIFWdTvPBs?$sRq5UWBBCU8Q&*PC-p)!q zXR*S(T0pNX;^bzQ`4OIJkk?B)H5hTBu)26s*1+1D6NXV{+GSjN|Jc6yfJd?&(6QbZ z5M4^aQnoH)VkwiSIlqfu+0R(8^REG3r&8H7xb1~E!)0B>VQ|{j1V<^9_OGkcFBv(b z3AHgmopNiQDxtqW*mwm~}gaPe;`I{VBpJ1$PNZ>C>oc7MbJ3b%tGWmq{ zxRmY+Uv#mIwNK9_ZtgHTBv7|)A~|P4?j82KVZfH z*{DXVqw%{cO!!Bpm;b85f(6UJ@wGLo>8r2w%U`{g`vGS>)4^hkPAo8VXOChF_~*SG zK@g*NEZ)B+;AjY*3*h;elaJ>7+R=N*w?=W%$5chXQxxh`kM9-l7aJMZ&8K^0-^hf{@iDy<@l~YBC3m%+UHbcUPw8G;$ScHpr0j3$QijXX_Z1^$I zv@|Fwvn)R!DJgT34|Y=d>(0b(1FLn4>=YI27vCo?F{Wo!x+=ci@kf=UTHOoxIrenuW*!Cn%5q}DeN$}|s)j6hTWGwEYqxwf$o+4v=M@Po>=@}It(>XG>b95xD z7Zsl_#6p4MsD51MD4&?PzL3;KskzwO!Q_d`XGnuGU&tvQH#e0Kmphp9i>Vz<#l(~5 zrs8~bH2C?5VI53PM$}IfDQ7BD847={A|z*`!5ln!Nv)~E-YF^(^%2+GnanPh+N*hG z(eJOCe}x7sf4K5 zC^(at|IB0-!Qm!<)H^`z>}x6_#)O;7>O;ipx~5{el@stGQn?C!1=#LGJCoh#LgHna zS;&uvCj_cu=PiYA{uX5_BaV976c4~^D8%?skwaHfGY-7r!4-^60 zvh%?TqWaIKq6OsNa)1!+&pOaSML;7{QP1=agwDiLwEl!gA0E6f)|@aE$*r8%k7VVl zSTnzR96xEwx%@tuREwt-O+_pc)h=l*RH2B-Y9=pnb*?FgSUbuzgZGQNir?$SjBqVKVx6JmPBCHQoTOo-|1 zlMt2Ir*}F>ytSylF;V?QWF?b1$dc|yB2?xD&KD$uTtec2*eIW#y}I-Z>g>}aYCv41 zNE>DHa8G~i8HG$%PdJ4~8#0gKEBKFD;tC<_W*A~4#n!Mbtv$0i>$P2QRXSgrgke$zBglu|(qL4P}$cBgA zQ_TOzRIIE;oZsjD4q`qh_=GAxtwhE0+08VNE4w64C_+T4LDc6RR z`%MMQl(L=(rHkPVLG32$qzFu6*fdko+_(V~^I#lTq}KV&e4o#?z?xz91*7sKNX93% z;nOE(Vp1~`{{Bb?DjOr6C6QhO3pPzL71?nAx#@guacPywUPM&1X`gG1oD0qyZ6g|& PH1aRt>cpLjHp~7$37W-L delta 70637 zcmeFadz?+xAOC;O9*5a3xs)&xqZAdPm|-{*p&^vyTFPKBav%3%My2S^PKzm@OcE+2 z$)!|?P%4!$MX3}?B`GTTJzsmTt*M{S=lA_Re!oB453hNx_iNqXYwfl6-sha{g-6bP zsE5X3boMB^!Mk3i|gM!|sG{q0k?mu1?uf$fjzp({=3abO#EobM{9WZ!UpU9x{ zLB6-pmH#_zHEg+W=SK3zRtS33XJlsItei;Xdu%1VlJ2S@_rRphTVx9eJz%h<56K!i zAgf^{5>`BoR>>p%Gjm3bprIqPM(3!_?J5QyEOl-$zTM!mwMaPLX6QR`*lpSUGDr5$ z$r_V2bX3j-jDs4mxRSTkIlo5<245W>o;@;i6b&6RL2igdzD8HaM-9vxs(RkF_HI}m z{iQOa1pD3~{Yy+9wXf27LB7&ni-bzK|G~o3c_Wx=$~8Q5)WEv8WsP4%YL%XHzU^)H z(Cp!vIXQFD)%(Nf%GZ)HRAY_RKfzWl@4_nYtr|i4d|2KcnH=x{Y^F+XUP8@a;vFYK z6<%ujJ9HJ0c0rKg|Dm9~oC|}7{Ii_HxIqp67}f+2Pp6FxLB$C3U{Lm`Y}^y+H+YOF zk~wmK&s8}?)U%v{*|#adzKa9o4 z$)|K<`ezT$qP)v556YVaYXLc2FBp;=>IeB-!>X?ky{^vf_X%ihR=^BnUKM6FlQyrI z4L`crBeOF5Vn)7h6yzJ- zIMDZCD}MOM?3^K)kx1i|z)y!@)iWPfxp%`fJ2!8-6^4(@8Z|0AYh(#3C`E!lqd`GK zv&N~O$iB2-Al|aP1ePBkgXPCbmIuJ9s1vM)H-}YW&cMu(!zt(2t0EC5W8O}Oe<(D$$PrHzOAIV-NY|hp-=Nx0?MGGep() zXSvt08QY&yKXeWv_QPs_-y!{OQ-Tj~3>wgigc^wjU4oHq2FsD%x&~|eH>A}_e%UP& zxd_hbuBj5qTaTR#cj^&Lp&Hma`K^eU=@4?>}R|= z(5J(iD$n)`dNvtb%kCIhJr8HZqFaK7o<;r&=n1gm`wq?-rw+bA$0}<|WoFA{US|ds z{@y#t@GY#VwiQ+d_rWTl4Cz$hgkfy%9Hp8Cb|LXf_bMz8<>ZXj42>^if8^={ zY1H`PS&^rS(9{?{ByiN7*m78zp@BofezCK&(PZTeKv%=lhXwsx56h8rVXZP#;Ht1^ z%PC-l%F2f2r#T}u;!K%45meD9_*Vtg&k1@ICfthdHzYHN?}M#^%8v?qQekv3b;1pI z3%Weim~<{YdbF77W?*Bk}(^BrKm7v}hJClU>)kuJY8N#bsdid{9nZ|GJq=i{Y6g zbFz-z8=UR^2WR?)ucaI{=x$ri-ur?Ezd(L9C}-5jp`)2!BZ${3Fub2v;jD9WJ3SCo z(-hX6_uETbZzP%g5uVFidk209uf;QnFRfy;2KUPvnU&?YX>iu~fe#1%7|fzgF_A+L z1~PJTlt@U29MvYgjU#wpai3z4O;pKwmj07cvY~30@c$d6r@up zysr%JC+9M+G__uOE=X6^J5s(up}t`97C22)+BG>0`I zZn5#@$**pG_(E{S)_7Uay$@iu?gdzj^rJ5ZS9*_OCux9h!XcXZYsgpyF0kC222{gt z1CucCtQA3nF0=Mmw);sh2Mt<@?fV&9>8E3>frC~CycSl6@@#`U!u|lyUKKdJ0KZir z!Og3KmRq!*edm{qU_wq!#iD_{T_@{afI zIrVZMdpDTa=h^(1z8AEoI;^E^x8-+W?Ro>=589PIVCb-sT$`xa%)vR4bGHY2Rt^{0 z=nq*tbI=$(!bQ~wfgh7#wfE0W{?yOS8$B|+?w}m@_0dDe_Z`+Rs|*b(OM)Lsa2EU( ztcL8ey!s=%mcnw-Hguht8{m@gYRjcR4*EGbYs^qJz`<7h4?6-r0lPFMuOB;3-Rzvm zQk(IaP2MHvo}Zh)D=7D2%fssq9@dv99&q*$HsObN2k}`sTy}6J5?=9LRT#9J2S;@o zgaHjHHko>F|0HnWFj)Pm@oCV$o3S+k+QS-`QJKRt`wZrZ)RhRDp%o~g2K>avV8nmg z8)2{E$pl;-E`*it+dVpELi9IFX)Q@mHbuVy|$d*u=KXD&VVamodHX~R6Q)x zJ-!Nh*yEevR9XRRWIo#;=mUlg_pivNV{2-B3~NMMSnfY;WL>uIfyKWL(tk&Jir;%M z=<#c$Qv)uCb?T&l8%&LlNq4T!;l~dJbEciGxX*XNqHz>fL040-_)BcL?gO|yyv4?M zgEci$$*&69lU`FQ8CyLrY56$1;`hQya61~5tDa`i5*0X-2o)XSaY+kO<(P6{I4FBM<@;d zN{dv{x3Dsn{Uy*}!dAxrz^Z5hte)KlEB(E{1{L(cRu7Y4H9Thd7#&nSufUoc^I&!G zp)c{jGEAn2s<6v%LBuF)pZ9y9C&KE{E3js9RpQm7Oj!2PKZ0_~oD3Q`7FM|x{{KjBm{H7YmvnyaTC4XP)_2s% z?4en6v8$2qF<2caO@4Lwx)MQojbW|N_5pLGI=0gJPas%s%45q>2a892k8ih3Tl^7W zy7}$wS2C*pmdwNU=U`;{zNG77HEyq*_FMM7H}-$zn_YXWJo4tF&dw2erbWX`4=lW| z?8hG$AHKYH@@A*pxqsGd{rb`mA1eLq`|md`_Qb&DKVI--Z28nnK2KOawce`Y<&rAa zDnI#x&hM;!;O92y{4jo#cU7bA&UcQN-ze^EPVfpF#iOOYDvi^lJ-i-`)18^cy!^)T zXw2Jg^_CX>l(pHSQcP?)6NKM=$ewq^3u2 z^LD2aQ^HGX5_b-j@On0hN9%jDo20va6M0-j{$k#~ZmH2kFR5wVU59p=U*^8l6z6cF zm)|rV?e6Vvn(khUE4va^+{;W!ahGDX!iswPnxwcVv99#96?999HNcS_y**9R++0FU zgW@KqMoW1;o5h`jrM&!RarY8tgbFC`6*NnU4)v-uPj_A{?e%OPcYZGIF!8Qh1R4i>lHLlaXv5O^^C`39T~>{-kfe}v6l!n^X4>7bACL_OG=NsjhJC-isLtI z3|335s2Uwxg+=0SY0l4Oy`-z+?uDF)a$zww!X1UBCgIR-Defw)_-X4GYZdp4y^`tC z*w2@oN-5+ooYsxKJt=9$qEq73?aKM*UIf@AYVt?mU04m*0lDa;{g{CLV3z zRk)9?Iz1ExE zF5P{TMKil1l9F-xBQ^1~p~1bBb)=0SC2JCvY6}Mb z4J_Lk>ONl0D{LQ+UgcHkknY}oeh^i{KL?g$Xqa; zgulFA&C{Y2yec=QyU$_QBWcu2ZkpomwpI-1u(;ir&gfU^k{yqYPT00U+ zAw6>r7Y)T~;#(T|1z6W%F)}SvV!vSBpgggRIy@Rt$a$`gSJ*Y~o^?quXn2-|tFJ77 zUN5@D%kLI<4sTC=)>X*_PzwSYV+WF!^U2?ESVznoZE@SS5Mns++nTpfw@^0iwD-K3DaMj?u3B-^CKDzXrC_o@v}iwz;f*+pm_ zAF!r@2!J$+OhWrm+c& zsi-;Hm_5|SvC6V=U!CCGg{x>jo^98Sye(r8tkY z^^$Vp&d#=8&z!h>HmA9!7$ey<#p&42E6j=4{uohb+1cSlvAiDr9Q1F?y!hkDBB#PtI)R*w_Fn$zxVr|SE77dI zZBm?S9lWG5akn$8gU)7_zpg3nOst@p``8oS$GXaoOYW2sE5~V`qJ`GErlZ$$Y}~oM zqn8go*U>8+8;?bqGu^#CW7A?iPKTBe>gsDHI1__VFG4r^+OpH37_;vNZ_c;PiV?Wp zk6b{gy+ZC$Lbgpera1L(@bV|b-61ywTMR2|YD#Pi7S|(V)0|T`cs*~AJA*rW`A|V; zuMoQ6Mlb1(cr5EiJm^)sBP}+MP<{Wp?>j=wtJG$RoGHu``Hn?&1D0IH^hil@s&w`8 z`^TL@UA@Boad$NlTD1LX>$=?|kwIZf*TcHyv~>ilcbGDk(}NY3s?yvYgqYbu>24L) z_0x65hGF3zPLBV@8CY8B{J7X&takp%Rr_Y02zzc!a|&-Zo4hME5rf6UmUsaT)$C)Vye7rH4NKE2xWfGitD#q|ZCb4Ot+dr&hT9R+ObP0I z04whGYM172B~%~Xzif^DhSlBc#ZcVP+snTz?hMHE3h#<1yp$R79zPi`*2ll(Yn$e@ z>*M9$9e3|XP`weaU~g))kC!wh?ws4#>j|~)>*Ygt_Vo&(4Sl_&d*W`SUsxNL6V5gL zy!?COv15q-hU=zfg;#ajZSKO7ql2rux3JWK1b_E)`v=pC0nbQrTJ`smrpDcS5Q7=7 zS+EI9*D>rMT!T0R!YRk;9gAb7dUIN)Ib#NRJ*UNEOMO8D_YI+7sZbm04h(AL8i!Nr zF|5GptawCFuukgOO(>vQsx9n|V?^|AAqYW2Ko{nBE& zggBwDPIGn)@_IfHkCnbnbDH{{jN80Igv|)8ygd)3#V#966a3InLQVb9LPBj6a=$0k zIB-kTl-Pws{PT`nlL`4LVsD)eRUb<8{am96$(h0Z(aTtDV>p_N4kuxlSNL!|cI_~~ zvWL^$j|jE*6KngdG2F|4B<|cZ+$($}9@{(IR^wba!s|Ib?qrVe@~6k$XGWafa=EAa z9E%Nx>a=|y9vO+Sc?6boO^%m8Bks)1@d{_e-R(KS5Hg`AaDhH5xc*7-G6$qM<3@S; zUflU`lvn7*-KwL*(;>52N~{Z3+?&%Z&GiUr*qP|fQk?fjdxek2-I`;9UALrv8Pgd{ zK4Uj%oZ`$Jh4yE#KDE=#S=7`bC{Dk zgmjX!|KPuQShjL@s&jAm@@L0mLvGipsk_>hw|hzXaW{HLc=j-;vFouo;kh1rh|pz} z#aPhvHCUR_!DZIj6NAOkzr}ERP4w~~kGszzst2^0;XgUiOL`*iG@a!2d?N0Sn8ffC z$GX!p#o0K?zg~880|(IB-YHItT(9RGwwqipA9^*{E1VN|Yvl#^^L`R{&}l1^8>8p% z_45A{cXv(=W=Uzkok`Pzg~o50+aD_!K%Lr8V9DW}WVrt$EOtKYt9thZp7XEW-CMBK z6@S`0v+ncq=f<5M?(+)g#@(j(2VL<`0yhuqO21<|(_g}3GgO)BDY1kH{H?TgntKZ& zU2L)n^=EouHSl_|MXV>(B*=~Lf5+o(j44a zUinDiqhK){jHP_6Tq?DT(6wZ|or$kq*z!CdK;0P=^&+%{2zsItjqLgNj z1&#=AXh&fMj!+G&vF!A~Ek~8o??|c%n#km1jh!XSKP}%ObQ$#od+>2A<>ua<_BEUp ziClw)!~3VW_h6-+w$@>__w((`NvS=2cHoY)BY!{6bRAjy7n@i~s}xCpro^!}`H{%Y z8Y%ZFLUOr(io|}xVsBssQy=&DAwmxk8l)?Q*l|L)_}2_wp9rsEGMUCtWA*m+VsnCJ z!oNw6b(E#0B^LdUW`@d0Bh=9kO*=YDug{kq_egrPWu1<^f zc}mxabDB3RMu07X*8NC`+l)?WZnJqo4`~3a{e4(B1kGVK?8j;vSnas&f7&k)PvsC| z@22@%2x&&L`f*LsV!r&KQtwwN(DB<2tmgh5Vufeup!R=f`vR}<)wnxmA-9YqWRgrt ziB(<1is$WVljhvA$je_Fcb`UR8ALOOzQ$_pTP*1ArOyU+u$0}FnurlJTqna9Sejn` zC7oOExuB7BkriVMR@{$E?!bcmoR|N4+$r|FSNM87miD}wr;d#!q^`3TalfLqQ6J6|sKdP22c@baO4FL;F;c;xaz=ororCu5n{^Ub(>U|HB@ZJrHZ z^a|gMJIh}5k~YR&cX{XmZBk>Gd-;gl5QB3txnD}`oR_fVUiT(KT~9k`8CEa9vjsC! z+>2HO4>f{?auQZ>-pH}>KDa@ZW=Vz*;uXl&g*ggW}=?VHIstqi-K+&0CX zh;>yE*FMGBvC=Et9Cxa(@{+d1onEWFp3st2UjCN2du&y>h9%GA+2rbAwg*GH7whVv z6z=*OuLUR;GooEulgtB z)--nsA)RnR&kth-vu)q)DQ@SrVO;Wy+`nKo_fux#mG`i8+S0b16!*N>!nl2Jrno(@ zS_N?nSbJX&2Wj7Rsro*E+!S=_Q>@c-HdgzMaHxh6(r(Vh$2^{Tzv1LSe znAAiJ4G~7G6n8n6989THc**+U1Y+*DOK}HdwFpvnOmViY_X^*S$0}_ggFkNF2Y@hilvDdJ;YvZ12#3rxs!?=6= zExz<#mC-xJy=+T3RdhB^*y1Jah`V1ScJkYi%)Cn3sx`G2 zHwGiNdWA%!$ZgRDeibIImW+kbGKk=tqPt3R(&TZ z1gEiAb;D{*92SpL9>luRxArkv)?wAhVteK>Pw8#`EYEFLi~x%%m%=j$rIG-*u`F%1 zmVaO7I`0NW`M2e<##r^eYQ59k{tA(Yrfp1#6<|>o*SVh&3Pw*SSp2=vJ39Fuz)~D* z5*O0@trc{x*89OY2R`?CDogVH;LO4!@`rMPXd z8vA*u#JOXq=67tFlK4G2L`dFb;&e-KFW6ONXK;I1%fFX#=VNK#3C8P7YXuLXlXnND z1Sxx9sY=RZ^zyNk4^Lz5vT@8Ou5iyP3@3lVjJNn#|(}T}NU(#@hWBR$DA)LTj!#_k`Wc}=JzoAdad#$S z7m{$5%~I^`4K|#>I`^|+V+pJrtj?!XZo<;?8pM_QJZKJ1XPmFa`m4;jSZY#`@&~Nb z`C?b@)1}%TuBm4b>Paep7R4_5!oOHyNt*D5SNLt*+4O~%bSUnA|7DQMzrJ_+edXmJ z;=$NAULkRBeiO`M|6FxS9?*x#v5W&cW%o>MR*XPPJur%`A;jo&mGHAd)ETt8-oe1@ z%tszb^~chCw}>7tWZ4b-mY%Yn=mxTG9*lgw`num;6lXUz)qaeh$w5!1)+F zv1de25y~KO@SNtFW8th+C-21yRyo%B*fuOK#BpuaU&2%@GO?SmxQ4{FhR}_HGjYlx ztgeBT!=>`C>L9la?o2{Db8#|f^lmIUlKuL-v?$M%IVHy)4@X(8*n*`N`YU~`{0Yr} zwR{+%?xF6!g=Nd(lfScn^V>QvEn&!S5$}`Vo4cE&kecU8om1R8zXuj&vKiinb-iDb z_KSD1I{FryVZwQTM7*jen8Y7)MOQ3hps#{uwq|`{^XC zW)#RN$o75OP}DD2SNc(G{O%>Eidwf|Y4xCuT%<0;vfgZxniz@N>lQ7-ov?xi^F+pd z5~~T>*fI{Wd}7Jje8fTAd3+HkC`26{iKTXNO~YfMRn}r47?#R>RVO&nxx$OxfOVBW zduI^RlnCwvf57UhA#++Mm_jGY2P}M(=kztC)2o>2nSg3gRhqwP#I|EG!+DtE#-jeU zOmK#AH|aZrErKB&hQ%Wa26{OmE$+cadjCPtg)UKa7680d>d zs+aNb*B}1=ou#J(2ebe>{(s)=`vI_h29%0(6LF50%03zgX#p0r7C4L#(!pgxm0`5yF_y=|I?lu~^gI06fR%qDP(`Xmb{^1?2c+Mr7)9I#bQI-8?E8H+V5NJ& z+G5!c0u}TyC;=V=I*PKqJsT)}zU9YZ9gmyrTG3KwaII)!raCYesJy3u4zcpj2g=Vg z3;z(yUJ#gnW946D^`aa#YimU-wN>~i$`R3X((Mq{WP@X?( z?%A-;^-2;gD_GguVr8#tZL#uIgXOmi;B(<7Hva#BgLC^#302T_wxItntRk-GkGPZN z8!UH@+H?Cx#d3%h>|$-Pf?X|lv#j4AN$;UQ|Apn5n}`?pvgvQJ=}&W5;jK18tPGjf zJ`-yQ`Vp@rSvH-xB({Di<(MI5qv^R7G4HX_|9`NWHPx0UmVKYK#R}eUZ8+DT64R|v zlr_a>qHD@L4$FQLR==Kt`4^d|KbFsiU&dCtHL%jHh1K7;to}C4zsNiMQT%%vS*^}H z5wz;=wGsO)e+8=n-`e;iuqrra`2?&(tOEbAy5DU@sQWr#&{d({1EM6C^5-nLiM7)ta^!{qu?lQvBgC?sTaLr( zVGA2CR`6dD!ZnkzWSn2y(eSp;m z!aBqX4zjjbP1=USEGy9oMRKLffZcKpP1QJkv&)SY{pc&EwI}2w$l8ARnL3qiu!;*O8=ovCsy!d zYl~IRF3W{h7c1W)KzaPBAq zDtL^I5Nng025as;0;|HAunK<6>T_V_d(!H2VQnoh!aAGRSp5}P<-H4Q%y+{oZ*LHv z8~KcY3fdP4kuPBNe81%bRzC>q5G#0?KkC^pu&&QaQ>yZnRq6j=m0#ZKe`m&Df)bn! z%Oy2nrLAT85?Di2A6B}Cuo}?V+Nm}^4y!@eSiLQ*bRA%Mt|P1lcCzt$1(&1w-^C{A zYPp-`?v{I4?g{Gp4CgAt{RGtV zM`2CEr(hL059VKFA%B$NSy%dbsRn8Mu7pvz_T3f7g=fX<&l+~ZoJ*4ky zE6gjx(x1jwK?|%dmc9^{w8ZLXVpa5ljTbB5GRrSoJy!v_<`pZ5m2s`L#me}awTrU! z*R3vAL)Y8%8(@v~TQ>eoO#a-+W}D!Du^P11rW32;x2;{2C2hC5SouDLmHs2E|D75C zzYBq_3_ENFu?pI0ZL#8aS>A2A(8h}u{|T&od#t_J#*4KQ9+ZAPfp2YsLpFg}1$+mq zfbXqdlvTh9bVZ%wk7jcTP8r9nJ&#>o*-B$-1j@mjSCNXaMyN8Z;;UFrf^~@XXz@~5 z`Rl^<;G1CO?+q(oCagm&yN`_@V0Bol8heaQFwjPbRnQPv?as0Bqb!ex)xdGq9uMmf zt0NO(<-gO$-(~r3%Tr)A{N57Oua-?k&>>cZ57~qdTYDy~0`p;2Jje1}SosUA{WPpY ztaJ-tHRw5OFM(C@3s!$Amw=9!tgy=Rt5z4QfH$lyR)y;geC!)nOy);b9~J!jQGreujx&7%@DE)J{FxK}`%!^B^Y2Fm!KVN3M+N%G zK$kE7epK-9M+N%GK$ounepK-9M+LgY;rREXf`30M`1hlNe?Kbt_oIR*b(O>+){V$q zSexa)9~J1M13dEYM+N_WRPgUd1^<3jaHfw4v~Wt-!ujt<1^?$C75rItWxwXpI!(=< z$S8kZiE%)poHTRI!r-WX=YD}c8jhuM?|Yl+k2ojra<(HIU#!0bh;N>YZi%KGtsHg z>!t@}2If-G+Nl(@&bZUi*PBey2D4i9rYV0Pw9#aXHkoyzw@j7$q0MH5Xp7k*+G>&? zfZjIaMemsHqHU(mgV4KXvgkdtTlBtZ@DQ}!OcQ-z_K7|;O&*3mGSfvn%t6t|ro|)B zPBUAy%N!ByHf^Uvg{DCCi8&$q)O4Bw?Jv zUzzeVqureS5i@9Jw5#)V#H<&86ER7T!3QE{r1)UOY!!bSF*OZ*C}JjvzvGt^;=>Vh z$t?K$h`CezL&Ow{e~g%hv*9BVbD#L9i1|W%G-8_O!#_vN4Dqpu`BwZ(#I$@I{xxFq z#m6J&C-I4hY4=35tLg4BT8p2EUhDiGF~3Pkd=#bE9F&t0^XwdyRZ`0Q2jx`6^!yLX zz?m9jlxWnrPcrD0A43@OBtn8&En%~SYI6}{CVMWzID=4^iR+YznhBFBr1mV7ZA#*r zDg`9jC1GL#LMgKaAzIobKLwRB<3(qg?V_@#&OE4`nJg-Ac8e;Q22Vq0n`w~Ac!E5K zpQfOSrpbJS;}Yh~N2p{DN?14tp~Eu>Rm|*X5W4>d;iQDBrtJcR#3vCJFF>efPDofK zq1Qr$>SobGgn@Gr$}B=iHa!+0R4zbRE8zm;K8vtf!jNYXYMIp%#yy2l?Ky;tP4;sL zwdWyhlTgQ0c^+Yxgo)21TxzyRnEEtA-NguX&G^L#sq+!`NVwe8S%Ppt!h=f?8kpS@ zW<7(@d?~^eX4+DOj0FgXB{VWkUO+f5Va^K(DdwPrg$ofnEJJ8wW-mkNz6jx@gf!Fk zMTEp>5f;CQ(A=Dmuu4L&_Z^DMH;<2p!D$RS2msAncKF zovE`L;edn(S0i*XyCuw8hR}QsLT58=4MN6?2!|zfF-=}UI4)t%D+t}pK?w_&BXoEb zp@*6MDnj>{5Kc<{J@m%(RUN8EX*^OBijMY(h9L zVa_ImvF4zJg|8uWcne{?nf(?*_tz0lO1Ry$-Hed<2EyXa2ouc-39BUZ+Jca47HvTo zxDKJrR)oo>$5w>O>k-yUxXZY2BW#v1RY?H9aRM~~FOTxrm2+x@<5~jY7PLh5#eJrb6hI)w-aBs^G% zu*~e1FzW+^=AR%eH`6{r$oLT9u!I$+$)^a%CCvF0VWl}JVc|yz9rhrsHnaC2bl-t+ zQo<{y?Oue$j}aE{MObT2NLVGI*JlW?n?;`?4BUxO=5vH~rpM<9m3JYmm9W9M`w%uu z7_tvxqggFs+-`&}2NB*f1qTso7b3*IMc86GeT%S5!U_p*o9H2gsh=QZ9YWYhuOM5jGFa_*}5|JqSX2xWk=ME{2t}FlpRub zMorBhP!@iMGUW%9-BI&_l4#N0h{UDEp=CiJFE-P*zEqc?9LNsQE(5 zz%Ni*|AewHYG(X|Qu#}iV^Y41nwCdVHcOd*6lH(Z{3K=ES14V6M)@Xcp86T3_I{Mu zF_eQ*bHg!|T~by^ITSU{FDO&LM#=gG<#5!zC?)k9l#0Ki{17#LenmMTWuufMQB&bK z%B%w@qmQE;#XnLq4x-dLfpQH0oIp7)Wrvhs@y~B43%^B~@*Bzt{3E6NA(TeHqx_D4 zen(0C4rRZTllbQklvPq@{(*7||412l7^U?|hAV2OpJccye~)lXLV{`WC&Fe4^Z!JM znIjU${eaNr6haA8a0;RJkI^zSV-8m$Gdnp<8ks9FOPOdCd+HI=XGIapm}L@De5gXIU-@)ZwOsVB3x_=N+Q($9U)cbP^&CLBQv5b!f^>Z zB&3++a!$9I3mx214!eojj%~U}5gL_8NHdemBP2Qq`z16t4Jsh4k}$IZLb}-}VPFD6 z>$4GBnCWLDR4#_lr6R)Brl2CiW(l!#5n7v0=OT=YA*_&ajfqx5s9hW(s}e$6vrNJ+ z2^A|NTx&8bBTOxUuu(z>Q@#p9Y9hkuDhSt^brKFpsFj4!$&5%snB^kukkHvAS4GGu zi7=%qLKm}L!f^?W&O_*CCZC6}uoS|62|Y}MY6#s+Bh0LZaFf|5A+ZcX>+=zMnd#>v ztdej{!mXx7b%cRuAeNehK4EgW3q)DmzR!e$Av%MhlR zPM0B!tBSBf!o4P17oqlf2w8OzrkQ0Dc1fsM58-~3Sr1`qHH3{49yH}IM@T&%Vf5t) z51Vxo4oIj~A7Q!~Q6FJeb%Y%fJd@l2A)^Mulm-Yh&2|aLB{XV?V9ex(2n&-D_Dh&; z8eD*Y0(H_;DreD8zB^!BN8gtLg>;M zVV)^yjIdckECpe{;XOh4<06C=5*Cy z7Mt=-5mM_QjBbjs)U1H`dtC%x|Ef!peG(GuA+%0MSZk)IBdn5eOv3A?#Z?FcFGrYv z6~a1mL_+2I2whqrY%m2a5H?GQwM5uxI<-U?*8pLKgttueYJ}Pi5wfmE*kYDR*d?K2 zD}=XAW-ElLS0HSZu+5ZjjgWdJ!syn{wa$BvS>M`W)0I-I4a#=MjBJB4s}af$DIYqf z<~1l8jZvmtgR;XhA4oYarBMdTPRHDtfwC|KWxtf&j%nByrF$yM%(f_>IOYo}iA_*i zw?oKO*R!KP~|bPf{wUp>%1F@}*;*YLBv6N~{CQe#hL< z0cBh>loe9Gag5UurFL_atd1xL9rL1;T~aDuhjPd$TqY>Bd8 z$_e~)BTDzHQD)wV@;m;KlGqBRbr+PA_@@iXDk;aLoWeg{Q3kd~nctNmjhZ7}8Pdva z5V~|jNH7K65H?GQbw`MqPTdj4U4yVfLJ1S?flxaGA*%<1YnDmaC81(ZgiUzeyVC3+)9$f>zpzxXWr_}i^eYI!LF+} z#dbE2WI7qKqx@v3r0h$*M;a9~rTaK}(fVfcolaHXe!h>B7~8=wxk{~EHp(fRpiITg zJ6X=Fv9zlE96~wMm9os@^ZXx7<*kIvDY0>+yWxN4K5XUWY-eSH^K~QBbcoZ~Fa42W zlzy}^-)>hq1N?Hr|3iFq6I;CBu#(|_A^u9!l^usWlN_gU#>#g`I(wrI%92seGcm7s zquPE6OM3_ZF;|s=d}V$m1-}wCHSTbV#l9cP4>u${9#z7U;s2*wag3qNcYQ7VuW;9l zTe)PC)76P}pJtmEI4E_p(>-<>-}m*K{F(B&;s4@VevPQIXz~T9BzN3`b3hMcXdLCT>X4lPxC7Q9igp{M63Ay%LK9QxU^(&;w<jA9C59s23Aw6b8T z)!w$6e(*NUYWiujg8DtreO7xHR$l!Y;(n`zKYi8@6dtgeeg^ITE>S-#f6$8ht+Rr9 zk;5Za`v_Kn`pWBctL?CwhHZw`KDJtAw8yL#{${!gT1l(vOHnFMzW~hDOB$r_=8s&( znH!m5wf#0Br)^{;n#TWYt7&fN9U$`JH)#CR|J)hrqw(W7Xwy|EtY1Ls_||GQ2%ijw zBsX%%W==-@%8t`vo3JLDUZJDod#hbQ_^2KCAFOsE+6Pwq(Q38O^y69`N33=c;rp!i zldm!U7b8As#iKT1ZM0YDuEy(UtJNX=qFlgn%xaeqUSPFftfra&1YsS&TJ18zv#fU9 zYIV`(>s>4whZ9!R55X2#?Ki7kj`p0@ez#hEw8d8Y!)guC^k2lQypw4B)4RGN%dB?F zrn>^|F*FTzt_GE`UgH&+Z`~iYS|hYMKx61wjTJePzVR+F&9x~Ujts0!coa4%piQDZFOaL9kAj)tF<`(fFdJys(Iztp+y(}NAz&!bMl&3Y0QzBj8E_WR zkKKO-+H_8U-+(roKfx)WEiS6peK-VSpg7RZlL%Z;5|jeHC|Ezi*DtPr1HXemz)A2Y zI0f{*?I>_SF%SdAK?#ruTu>5}0;NG2pdGD(+_;7UUIVX#H^6$Z3A_a!19~sOYv6UT z4r~IOf!-gm9J~ZpfVrRm%mYt@`QRC_04xO00d1L!!9<`J8|2=`pR<5o>!7XkUZCw# z+oQHaZGYPCw7WeFw4-SU(~hMb$^gA+MeoZg0TO`=v{RJ=r9l~R7AOnKf%2dN@LxCd z04LOgUjK&tQ6}%1J0o#Dq zZ!OJQina7=scp#TwH*_Za`g-BjbIbl4n6?-P4cJUDewl+ZdToim zg!T^D2HpoRqdx`afv3S{w3T2Dn20?|afJT^^n=HViJSzJ2;_pv;4W}CxCh(|rh;kU ze((Tz5a=hEH-lb4+jT!M5Zngzhs151>ZRfwyfZxF%`VFS`@*lxZ z;Afy;UVje01lrQ?qSaHtJzy#r3nqXZ&<|vR;ov6F1M~#hU=Vm1JOX9_4?GHHf?FxK zH^|gU&mK`YQ2G(@`sTnR1%HNn@+)tiaa+aA6r`~&zA909tncpvCmVh8wv zG)KTLup4{=7K5o^1jqup{rNKx+)4&raOeW#0ibINy>28G#6dc^3Y^kH3hV7GpMpJL zFZc|64)%dBz?a}FupitEdVyO&Z_o$y1^x79m;MA6b4Dx$y9sXqZ-M#P&wzzMud>m_ z%QHY1EQM$v16`=-!lXOUyPK{98K51g1)k=l(0j-9@~?YAe=rE>wQ=WwihAePxdh6B z_vzRk@Db29tS=ONzfB7OeZ{@@tpzm2C*Apy+B7V%{dBw2FJh- z@B?@rH|wQOE5OTOCD5CKUIHt?%Rp}?(p!q21J8rSKvz;rHU2k~p$n)3bk(Hysp*|? zU(&Fzz<%&G_y!yR2f?@C5cnAE1iL^wctv44vKHJ)co{qpj|>L-nf^TBzpwzl95m27 z02&gw0;GZ_APrm%T7lM}4aflPz_p+~xB+wqH-avpE9eHggC3wKxC>NbSeCigV<@Q>6h-R-vQfzZdP^eH~~xsS)e~?0ra9ty_K>U;1#}+la%!*I1XN* zku|CF!bHZu7J>DMtHJwZd=HEPCCKy}+E~Klz<6*E&^@Q_F?CNl2IxMrF6r_p=RR;N z=nX2;!+X)kgPVa~MO2LZdacv|u!QikT>j_}aYm``QT z0NrIR1dG74KzCTWqgn!%0^LdJ&PjJleZT;48_-)r=Fpf3jnj=#?m>h%vGqbEy)@|v ziS#z7lki#^uoCD_NKaN~gD5ym+-~pzSO?aFmEZ}mfbtemo}eErY$yHOKwJ-`fThIg zy+*w2sI&j#qvi;=6QOJVrr-_iRp52-DtHaN1oRFhy%;HnG<~oYFDUKsi)kfCt9H7? zubHd+2Hj)m-a~uBH9!m6@1PCgmf$DCSHhQq3&9WA-vf22Va0~U^CbRv{34W zntHir4Nx7N4;*lcHZaeU{0XNs>1D72r~{hd&#qk2J;6)J)r8ln|Ey�kY+tYk*FG z zM~jr{2UVFW-37GjYW4jPd;qosZJ_UgcfmIB4tN`E1zW&o@D|tvHfqb%yxRcQgLM`P zOHd)UZ zg^O31xj6A!$ijk)>RQ~SOH;ZqT!OIHCTZt^GC&tSDu)Z8T>sXg9EMg&T>z<|@K!>v zg^Lz)rUF!f?tRV_C+$p)Q<;BDukn}r zs}P~r1nV-eqD`a%WGg-_P~l28{&T`%oWfPnlZxb3C&C7*EX8SkxEj;~>Ebwlnu1Hf zg`f_&0MrIG!9^h1l<${NDOVF(NffOpwMpe%48&oapT)*s3aiLuYwLXlmx1z>l?pco zjlh-Q3eXTV0QJG;pdP3T*uHYLTSUeI3_p=4DJPaU=p|;OaNm+4p631mdC()k})2P19yOl zK%Sfo94fj8z8l;L?gCT5R1kI|?AU$LOM?pJine6*;2Gdy5V}>ZR>oUba>9HTZKBMA z@=OQHr=Ba%LqHyR5Xei)dmizAew}dN?F-;j*Gz2GD8A=nPy0o%ZP;B6q!>G+(y zTd=nRg_SOd`72KO{;8?1T#3pQ^7}TS8YE4ugdd!tfG}Pao+-W%eK!a@rF1G^X?KE; zHU2vYs309`hYPg!9no1Vb%DnHQ~5cBm6b^XQ36*z5&{cE5lW6n$NM5 z2v-6JtftC!c`dhxJ^g2SVIy-@!2fFLnI_+VYot6BRv5Zn6{!vltHL!|5cSAdkCBu0 zChGGE{7mF|@Go!@d>k$gR{@p4x!`mm6!shOKLR~>RzbSiOaLd)egZ1z2q>CIbsPgn zfzl{$k8W2LAwy6&j8r3jEfVKYL6}wzkUaz5MLyjtYVn#x_!O+Xe8aZokc5lQ{gd#O z=(=;R2To%D5jB&BaOQe!I zLQqzp>PZMiePj@Z#b;Yv4GSAr8BGOh_^T3@r)B%|3szVSRD4lyDP1-6a72BNQUB@Q zsRAaX|8D=V$I=v*H);SC@HtvhJ=BWkDLQN_Go0fW*!d32r?M|Iz*~qWh$B=tURn(g{V@c(}T34 z@p{UpGL%LQ)RVWOjl2x||K3piABt+No|>pKxjSre*b7yvu%6=Sab5|ahp1tmuyR!# zHd5)8u4t!Zhk1(YnUo5a+Z3TkgK}S(Aar%OuY?5^9k%A=2~W*5!fL$MnI^E#1eK9W zSnHY|358zKK(Q)AV+unaX$ zX=oJhB_*O6P(k6W3@dGco(|$5%p7_|`PA?*pBfW3TB~rFE{s>48WWa%m0u>~A5N~K zV^-9?q07Sp<+iZUqLp5a{ymlGsfV6|=*dTGv{pd-PIySuHwN_mhxr=+r@=g+M}AL% z0x%0a0+cBO9s(wU2f+>CHZTx80H%O@KsKmPrMm9EoA6ygpVHh3^u%u5Jq)hJcg5nK=YlD-o>k;Zg| zdxP$v8|VRU1-&%>`bU>dj&+z*t02$ehpKMV{| zgJ*(AK{MiJz|(<-C!7cJ+D__^cm#BxpeJ9C5mpa1c5{G+V=j>Ep9GJC{{Usyd{ISD zfKbmTtT^eq!&HT8KqgRmVOn`c;oM?GgrYJjkt$R{(lyqqFf3RNy_h@~0#(!n{u4e7 zPJ%zc@8EKE2p&!R_i%0aAp8x`uzd~Q*7!d|Kn1-87J&WWEATQ{2EGJefPLU4umo%Z zpM$+%4|pDY3O)hPf#qN^cowMQ-S95(0@w*Y2Je6!8vj=atOFl`55Z>e0eBB=1GLir zh-VAD5xfaDfc4-FunH^$VS|?vRwEVxH9(D1qwCO+qK#5xUed%0BbD$)u;L$D*dz5` zX+keZUkT);*MTZq4PFCl!K*->TLToQ1_??pR-RlLVT;u|c|wJrsYhY_nes?eN0eV- z4X1`lnmVK*k!Op>5zak5?n)dMqOnmpY^{2&9=vOH6|REc2cfsN6ILb4r+B3gE0h*C zOl2vr=0%~#Uy%|Nq48H{xwfbt7P^-F9by! z5cWnKR;B{gV-*@UP;OL#325?=z8$FH(N_mGL|PHGV(ROK1%w|38WOFbTAHuZ_RVJ_KY>{W=0eMsNK^|2vF9NlI9tU&=`fg)b z4voF$v=L4mwLVM`YGJSR8Dl%#sc#tSdx_)P@rR@EvXx`*NT?jWwh~+T)UDgguQbD} zJJDONsMn}oNC?!?kN%6#4S z0@5|8*PtGE-MnDqkx2=a8&#m)YTmM=pWLjOjoN>PWHs>IYyY|`VEmeEiB7#hf> zquKL+)%N89HKpPI_nvdIBuR>vo60Vv^;V=XW-OEJVur+I&(_%2Y{?!&k6m_Iv+rAW zVyxK-g)x?f8QWlfpXV$}b&dIbzhD0x_dLt{ywCo=?>Q$HqK!&gzhE!7PBom*tEAp& zXsGxo2r-5_;NtZQ@GQaTw7tLMo2%~SWIS&lcQ1MWvlt-9t{$kE@nG3S0ZQh76mdu_ zRnW&hfOjeB#3(UDIH9MKF`}FKWiVrs3_Uf95xpFF6QMAEzxH*XW;rV3jG*Ur3J+J1 zC`Rmx&vX0}BifVKXwd<$j06{uN=lHhGIbp-&UY*eLzx5Db+66CCJ%xWA(}t*M2GC+4 z7{>#FO?u4Y<^6Y#2SxzFn~jZr2@oeh>}#0|#)3o40r7D6XVUE=JsTt12?s!^5l$)=!Z095xxqP}BAJ4Zf5XZuAo{HaKpiLKZZm@lT-gO-gIzr_oyzl{~I7zj#Y zJ$VK%FF$;2aR(U>m}sjC)6H?BogoQe*2Sixr86c@O{xYAPj@d2rQ1@Ntj3FW#(gTr z&l4Mb+`6LNa2Z3MlFogPjQz45B)q56_N`NWAnh91Qg9hon@dwpEN``%#XrTEK};xsM}EC$i}IMH5s zW=&7xU>=_m%Jif*UM}{yeWYJ8~giS#Y&Niym4QY0Yx6ZfS@z`Pf-kzX@ukxr*?dS-2 z3$N_x&15meP|#k9m&eV18rF1jrI9kGCufAS_7pJ%{(219cD(}?3n^|=T3 zG;0cSMRf;M7+|Orls-kYHXnhUhWjz(Nbi|VB7Q>`G0wuh@Mh1R^#z*%#X?Dr+@>QXIl$=-0*S()RaH8X!NX?tNj z5Rn;JUpJg-0T7K{U6eU~h|(wbEmM!V1q=~5Fu8jLwz{h(iP_mr#+K&K7N*5d}-od9XGguShhmyAf1M&|@?o&ea<#Qt~fIL?E-+c-QmN0r{l4{#W7(LWbCtlg6BV5U#VLS)r(95(*3HCFcPrAdnWC5PAC;A% z3N6{uCRVZW@9QPFX+d#4~E#Gu@RC+?vp0_L1$WjKPTr92dFM zxY?qYaT_q$i+c4O`p3X6VW)w?Ss57T0AVk-FE%^eqQ|5h+^@US6O1oBb*BOeqL-=% z$LiG;9~#$cdbhs{R!+$tOi`5MNFZ=K;WH-QwdSvfD&$7c7=4S;*%`amEVOZWpYZ{} zQ}xiCoF3j|)R9W!6_YWe^eoYRFX{bHz&R~2AzM~le}KugWEk5*4A zmX=lk386FYSmBOo8lxYb16N_3A4M&IvS;{FX}+%TqeNT{zxyc}Gho9v-&hG#rVILA zxP$Z?qfuyAm7CLg~YI(S`rbsIL2kxO}G4XRxYz0}Ye)Ow-lW|#p?4hQW$;?XDnycXO%e4&+o zMGac8P^@8m3k)7`!|In4n$O#G68VIy1WYE>R7Me2W}WKNZ71}}04PppQIjkdiFQ5g zfWaC+-8$jSg-c^P2zvAr?w*jtQ-yfX{AuW+g^B2C%i#_?)z95JM)w7ev^%R(r~Nbk ztt8iZtb25|fWfkk_PpHRrphmEq)(DGt4Y%^p0O)1xJq3aQ*u+`i&dp;jFEt_i^XTH zPW^6RYT0Z^LQT2}TEhllaIkJ1HR_Rd;pcO*F^<e~RJ2}(4SXwql(b`HE^}Nlk*_MsAmCA-xtW6*le4xG#wJ8P|#^Jy~BNWr1_wsrldrG&mG3Kd|?T40b zHd<${$cF5!O-+}A`xRigfYwzimUyS-rhC~KuWOS57=n8J0;bB#XnHi$5~_3f!Yoxi z2t(@AlcjJtwa+moHBiE7x7m{A(#chu2 zz2n??LqctOCWX+!cZSm^_epAfav?BSs(g$hd@N!594! zd>Pq_ELT88H8&ZCBI7XT;^H?(y_saW263gf)mDwE-3rK&Pfo&~fV-zRauVGJuO7ET z6-oUYoqFaq-(fH$l`%YZ`R61=%olP}KAA@y51A)oCFY$^=20>7$vi3qnP&sj=976; zj7OLS=cKMv2V9&oqgxDIRfQlYy$3Dlq>`($bCOUbkRtILTNktnod^MEeARyRv( z4&Rpxidmf&cygWUY!U6STLJ@RwxH0}Kz-hVx~&%7g8l}avs>?i|ak31f z{cF(ixd5{SrrL4b;qO;PcPPm%v%Fx?d8?4|=_5x)*l)sW%L@gJokbSg-tZj|I7MDb za=yRMXYD(Mlv7o^Fsi*4V*CsYPJ}bdCv3mmuufPub5%RS+Fs%0xGt`gC?CnOfAE?9sL{{(@7EZY&+zf9YLvEF{7oxY_Q286vpumr+>A;P=iu;p@@04qP7OGZ$7x@bd9cZia3J%U1kEt+cL%P{9qHUQFFhO5p63c}jH*vCQ!j#VK64xv5H7q7(odFp0Sd?el6iTN)82KUnm+rM8{$nVH& zV4&aQ)@XGkSz*(`xD6Pr`IJ$icl+Gg6E5=r4i0w#VU-)+#1z?jVBKgy)TQRRND2q7 zAsraDz|eKsf8=R=znj3o9&YxQhOOl3kFDXgyRgY(VmA(%QQiI!6p3t|F|m9%I2Zd;S2LOt=&G|C}a=##&)BaJrG9o zI?ar!d$4_*)?G2%!baNsW}4Inn!vxlPVg z94cE(t}Tsv(4xJF>5e_n%E~b<>}y9EdqtO=0=Vo$r3>t-n0-)B@;HR$a8I&40DJv{ z+r=@)`X%*@9Y>^N3yM#Nu)m~R-jnw3!%TMeq_llF0RiE`{rGJWMM1b4oT8NNnH3f8 zbkjFVZj()^VXD`!!0g+LuJ4ET#wb#K8cX9;v^TYbv_jY36mbx}z_bJTn~8Td&}y34 zamS=ohQ{DNiZ)7?co0%4uE8Ow)X&|EkHy9V!ppAmM_0C}=-2~Wjtuc}_tz!%p{f|% zkOB;DYU5v#JSg=6W)MbiS%8s-4Q1{jt{F6=t~qNSRKc!9Pqn$D$&ZeX$8kn0dDjLO)7=2X8jxP2KK}D57S4MESF8T>D=DfR)EQ}N0EWWhsJaa966w0g=?`%{N)pfz>J zQx!rjO*SsP=&>H4j1<;?2xRW8gLJX9Sn89^~8kjOGd(Ag81!OIc!2o%DOkz_cDMTCxg zPl}E6v9l2Kxt(3^h*HzyxM_oNPbWnUx3jw+gK?lq*4RYMm;E;W)r!R3PU09qys&=d zmLZp;3i^%U!rEJ3ih5sxO#5QUq?)TU=lM{9D4t&cDsVGFa6{!O`*)2rQ)r9gb)FGEJt z6wn%`1A_za)wC;>AD>(^Dz_;3}aVd@LW<(_dB{PB(oKG`73rDp^kFe!@6qwI;Cv0Y2(MxZKhqK zau4tgpSie1pGTneP~@C-E?LN-F_i#5fHXnOjoH)i(##f+vuO-4kx%0V-;DKTfDS+`D9x)nX4S7l~qU;r=(J5;~Mn^ zgnbT?9XyscU_4_R72`~!z=XF(&tzFvlmc&EZ$LP)jTCBJ_|5-*&1^|VjHUOWHOv48 zdqTrvx|vNYZ0eVdku;V(&Vu_cVDMhroJK#6`T0!bz-){wfN(vn;#AXmh5g26*^n1w zX(ZDY9H;nd#<45?-EW#JT10;E)s+H-Z4*AP^`>Edlgr5S_2&v-Z5*Y7)(`*;mi^-K zhhoo#gXYPz3g8^rU|hnlVBQf3tjs#r5rIppT8;q%rxYVToB#+1a7y^{jj7dkIRU~& z8m-TyaTLn5^MS#lJB9z`u*##(9ho^A3{Ty5m22RF_5+FxiY+YD`oRBmr^nF(&>G$V z!vVBi+ehu|+2Z!0>}gw%r*pvY&0U*p^cBY|ipX7)z#TheEc6m`I){Si2Sm;=T?fU~ zD;!|aRTfO%2dks97}&C^S^2Z$r^yhOOV?~XMV*6Soq@p`+n2iSyFzon`%$6g=RNw5 zr$k^F-%=dqS_jizqrMHl0J+~*9@FzU#Q9g~vk*C9qj|9M2WO)OnKkIan{ZE*otr&y}Z*NU;!A6KJatfHSp zzgNFMG26$R>hhTZp0xsm<*T@Kam4ZhNds*3b#RB}=om{kFJK1!RobV2)E>BU?c?3q zh8r16Ru?gPgJ^QQh|wm+Qusw|BrXI6Yo$=F5nX4V%wVl>2L&%pily|6sK1+IY4|1Z z-mhX>pF4ZW&D`TQFxAD`saQ$|h7cT0r!IkaS}c9UZ)2uPQRQ?**hI_0e)3G@>iUN& z=f=p@;mafbP67n#W67XIv?vXAI7Y?j)c*Mx{iD+}W%=a5n>m4=q#*<5Zm6vE3qixanHwVLg%|~rw}L(d z4O{dtT-j?+d%z%b@5Vj4!?;-x{<;$_TRJT#1bCbM3^=c>Q$Z?Pg9 zk`PB#uS2rD1xTYs5s3hX(R8WEn{PE*zwxwzY4fHv4I^*T(jZ7$@2|tctKw+n4YX9r zag=%kk{-Y;%`wYrckEu=Ow*5p>-r$g`J<>rC)`9lpNyjgH-VTpo;B8p=X1c|cz%2n z5%otbmA;ivOjcCAHod~oQK##?@Xl5nVlnX+;^>Q!_KY#|Mw%uCA}#PXMpr%GCU0E1 zPND_3MVF>|AzH*Gt0wQfd~E9`bEk2i>x2FXIsf(~#gQJQyKIvlQbV}|#v0m7r!9!M zQ5MkTSGa?-0Br$bdO2WvDWNVl1a0x5E-mQ#9kH9C#uUYEYaZQXJLUQfekhK&-nr&Y zq40DVSlNBkHuP-B@~-Hw-84LoP^PiD>-HU;dR1A&n=*Kc3P}!|dBg8Qeb~%Pz6&4Q zIZfG9*IO-^TyfpoFnPkByn%BG5N_A&r5&D|alme)tR$p%Jmfu%K7v;GeHz)_6T1lA zrc=y4{5Hf>)BCu(#Z$yX(UzWPVg-Nqp6D!S6uB_WyfL^+q+JzaJ6dob8BODK=Dz4B z{5^vTWWYDp%~Y~uo9n*qLt5bvCve46iW+^bZ#J(+BW}9v8#4JHSb2k2B54O3y z5@^i>$dS*Gc2xeM7@$h#B_t=%tcOs^Q&b7IRhnf$Z)@A{;kH;HIHH~w_&EZ#Ae#pCmt_?PgElrUw5oGDa~LH*gRXI6arU`(%2lF}GBl2F(m^hi zolADl#qfZ-bMbm42FklzqCxUL+;R{!j>=KM4gN34m9fIhYDA{l$%j`ZC?iY6<9wUM zs^$Kj1P3Pa%wDxhvkoAWcZqV4|C+p_}shSj2 z%AhY%D(alGP+5Z5k8kshlUX=Fe95Z>7;wWvY6si@yLV{zojzbzyC8I3#exQ z3bvaUC%i%w<<)giEl(pqH~w)kg}y>e6iZY*|60MR55p!*U9IL4R8iBAd}aRkFx1Sd zDHtb-&0l|&l5%?9r^yE_RkEO?Rf{*{HZP0I*8abXqGkj`L-4SNZHKn%QgB9x;#0DD z<}lOw+}%roB=QO3%HSK6sDqZ{VeN4>y-l%=`Qg zOz||}+4oChA|5oLs58H9N_baJsDac{7iZ%e#Sap@MQ6voV zwC;VUNU(wlF?8RlkpAiZ<)%;i2Ct^@&J`ccMXaLtddV$l1TbtdN?wI(kP~`k@7*`? zMETK|Et^~EXM)B6nhmSS!vHxBtfH8*khu72MRNxI)Vp;@C*$!|Xv2$l5LJx{uB$0k z0EO>rTF07fxH>@uVJC>n!I=GmnK#-xu41Y(gbu4IRQw-`3)Lq|EbeMLhf#$~tEs8E z#E)lpu*BOj21&9u{|!^{f+Th|>7WI0KvTPf2h1O(`Hb;LjHE3rKXZfaD`26{c4OBrj91QDN5Vi%!(8pyXpnM1#vc?qEarb9dvy zUtk38sFD8EcXrGW656X!+N)9f3e!it5=GX9B!^G$N11-JN`5iQ9)HtmSRuT#HmR`WEvPo4k%jXb&fva5SrF{&X87Ct?O{Ga@y5P7@_X^slx_pl zBAP$i;tJo4FN$le4dhW-F}ds}s(Tokf)hJucc&){CI((}l{p#t9Y@69NT%qzffkud zZsj!3$Qw%*?K}|Vd;Gm6-SnO>FoAtHG ztHykF%hAgeS^$wn(HxXu`z3)ssaqTVe>8PAlp27>CCN&=^mJI@z2j~#@K_KmE@zS5 zD&%JBz`&p4Qy$6?IoV!JrVW+|!rb;TZld>=l9!OMi9CuSK_zd(7wzB!ALeYiaCph2 z56S|cYr=(16j@9P(J+Nsn<=%JOqpPX%a2>ghp(F9Kl52F^ewm1cB>qz0QuCy1*1A_ zS3Ga(lJSv)QyZsc=XKsPp9JM61ZwGZL`Bj{AwK)dgUCJsfCAyQx_SHS`7M^TAWaA+)?Ins~fic9pNo zLdXIyuYTbLG41tM^_4Q}zXC^E7Ds6s$c)ZMl`K{u^F@hPqRl{5DR>h;+M@FYgg1p= zC(o)c{x}e?Bj9~m`Qey`N9iVLM@0aGGf(Te88O8Si?AcEy@|B|5Z*2BaxHjst7`su z^=>fkl*66dDx`J)XG7ZlV|!T8Z^NC+JPxjWV$*p_iJCJ{Z|Q{b@Qgk`*<^i8c{%Y! z>e|Y{OKtRqmB8hlf+KA`UYk$ZjyH_4{V6}jnCM6` zkqFg|$0)=D3fl!tb6~m*Y?K^r)99c)UI6bYC|_T|d4`J7>e}5Z*3RE6&#B9&hbBH$ zk-cqUJOkPy;9k90p-#>-wmg=(%U=q*3J9P5&7WItf8$?P{Rs#j$mXX|GLDhK6Ov^C zgN<)9`TD(9sYlV{qH~bnSNM30ngYYO=y7F3!PaWio}trw&jE%yO9LQQpzS>Jw?WZu z@2&!b4@i+6CelJr$=+C1MevH+^77QL-MRvS-&04E6$l9Dm4_RK%m};J@3lOv{5gdt z$LR?Rw#Z#s18%l={{B#jvIXT~Wrh57oLs!%PQ$^2jaVzR?+~Z)DS^NMZ%D5rKuQDh z^WIi#HweZ40EA!LLp9uXoO*-Sa1j{gfzjHb!FlIDww#o?tCG=DFUd_Pev;05VY>>Z z%mRh)sgp{-7!=oR>Dvxb!$HA^Suo*K48;$2v_0_5Y{BiPm1JI?T*s9!fe1TKQ5$cB zPw`Zm;w_zJmhcW+XXxRNRK;{=4`&;D&)Hz1$^l8=r&7F+)I~@*OK*Ind4lt=G|LxE zRM#?8`Bl+illA8ZJ-uS@3rcQez%%t%dhd%lUIPXj|H+$9w>p$4|^pX$o)ugle-~ z4_m`VBh{ybff3~ois@G=ktya~rQQBgi0|}kY9Oo%I{09GC;m_qY-&;(86tlS#fF*$ zNM=Iq>(n{`e0^@vB)*2+p#1@uWxE@Su8VAK;^a6tY5@3p;kXWJG4W|81X!ONWKjdM z4ZA@VYGC&;6~j>Ct$m+{0worY26Hl+hYXmp$2)s)-}J%Cvp zev~`WTIq+~rrLq6ZsCUoD64Q)s+j+@|C}>AV-- zw0|2Y`F&w;7XBW>ywy498OwAgQKg~>wXi3fOGNSs!cCQ@!L+s%dGSh;GDBm&nMF?d z|6$H0>1hqAp!&rsY91_A6`tIsm|&d2vR0UBHtM zbZ{s$`aT_G3N7nQ1Ew`Fx6Ifi6pcU23r)^~SO_KFC(Am(+<2cV)xlEr1TZTAvq1*6 zts>{|8A5?E?qEs zTTt>mENdq`b{y6MXI)x0@0m#(7;|VQ1^s~Qj7-XEi|e9Hde8T_W>V8O*fnLM^&7}g;DM5@id_41 zcAM=*`pFpb`mgwdgnHoS^ne`dAt6+IK%xBmn+FsV2Eq^!a?M_Ixy_nmlapg*LZp6g z-473F0b@qu+6>p|2XqdOm0vz_v5|T4 zb7;E62UPl7@K6nF*aS>oVXl5LctV@GuKc7Ce|sPRUx<7_QNT3Z1_nR3ZCBx;>+Se? z$`=b|=Xmpg5`keff2cUGO&#C515$p)3qG2`Tvf>E<%g}WOH;X+vne5m|3iAl+#3Od z%WRfKsUF=fylb3|(e@#=`w^0U?l>WaZ7M~JpDfd=EC^R5mU$|6!o&Hhk)CX!~!O6NIkmvtSO}~d`5K1wPpu?~y zip%K&{v5cp{$wolG%afy=>!b6vhB3Nt{<?_|H};Q zT7ZX~UhV_Jfhx8dH0eQt;gw2@eo*mTTW4gHmq21oCeAfCI`5kDTt$M~6cOa_U2KER zn?r8xs>-kZHZ>2ZP)QmgT10*!R#e>>+QLhCK5f>ud*K?@{E|8!Paj<_fBFiZUq8Bn z`6)4dK~4=5iS%G&=tNCnT1qnpKUP*%mkkGRw%B@PxvEg;Vn3Xg*Gx+-=j<9Vbx&;- zg62%k3tEa5a`VnTCX#o2H+;#_L#K@n40x2S8J0|%$4v``$0_$evm7UJ&H2>~X-95N zJ|W9YGznB@V&#`Q>eE&#CFF_;!?>5qbfZ76eV2A`N_lxw^7|WFGKL6NtuUmGyH_C zX-q-3HG_Ge?&Q`8SJQJAB2%Bpous`Le+vw%N+P!rUlB3 zB1le?3Th$BJVdX{LB=}#7dU-hSMl%pnPN3#3R8sOQ>dq*DA`E6RB1y ztEolGZv2V4``aYlR~;F1(FRa4KUqYxz2dl^f<|ohPDkroNu`_|(VlP(wY6JVwWM$+ z2rPN|1a~gP=c#0lg_L zO^C4vFnHrA@l;o*=ycj*BKr6rvQ_8oiHs`%bwiyZf=jYNijh$_Y0%-#wq3NHd3~q zMB}D7+=|Tsj zf~x{OgR)G;9p;xHD%ROybUl*s=g@kp!r`pyYSAeX7*0^Md0?&48};!?GKTyF2&cJz z5h!An@6)6RY&V$L6GeaD?gqVxki3)yt1Z>&D3$(-1>ruCrgfC;L?lc4H4^#lU`I^q zv`9BQVvFe-zKh*Ss$pm#DdycdWB8rAiG$)*PrwwKNfh2mDNFffM7rJS3+Ylz4Ql?C zlkA;tn60W9;d}u~{s}&7dO7`D0m}FZ4%iWuq6AcE+xpD?s%4Mx7hU8Q!=keYVJ3cL$2DgguT`Pm9Qx7%tZCYR2%x}YpOR8RFY zT?9-78)BMM`MxevDMv(|ydzn(&NB&XD~5LBF@BJ2#6| z@!%AAcsQslLhqVAwdtCVbL6PE`8Z9EvY71=U#Sj_z?0&iiVk9=xt`WP74atu`NQt^ z=9Q{RI7Y!+ZXV>*U1~WhP*7G{v$s1XmzDq7IXR7ezTZ2l}spoi- z{}cp!SX7z#k|PiGEW30gZdl_6O*pvX#3s+P{Kra4;`f>h&lauk;CAqeKyE#xAbn%% z-a~TMhtfpll7vf{!B{r%iNcLm!PI6e{6hiPq(ATJ&*;Wh|GK9 zI*iCoy*A=2?)Tv9M50ORb&YyG#aG}z<}1@jNu{$#Zx|&7J2ZwWd9-omJwA!1p z)=FiIMD^+ObLVQEdk^g1h3fn+m8R*-@TlON@n(*cx=i|Ihx signIn("google")}> - Continue with Google + Continue with Google - ) + ); } function LoginWithGitHub() { - return ( - - ) - } + return ( + + ); +} -export {LoginWithGoogle, LoginWithGitHub}; \ No newline at end of file +export { LoginWithGoogle, LoginWithGitHub }; diff --git a/components/custom/auth/auth.dialog.tsx b/components/custom/auth/auth.dialog.tsx index cc85f7d..ba5e728 100644 --- a/components/custom/auth/auth.dialog.tsx +++ b/components/custom/auth/auth.dialog.tsx @@ -1,43 +1,67 @@ -import React from 'react' +import React from "react"; import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTrigger, - } from "@/components/ui/dialog" -import { Button } from '@/components/ui/button'; -import { LogIn } from 'lucide-react'; -import Image from 'next/image'; -import { LoginWithGitHub, LoginWithGoogle } from './auth.btns'; + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { LogIn } from "lucide-react"; +import Image from "next/image"; +import { LoginWithGitHub, LoginWithGoogle } from "./auth.btns"; - interface AuthDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - } +interface AuthDialogProps { + open: boolean; + onOpenChange: (open: boolean) => void; +} export default function AuthDialog({ open, onOpenChange }: AuthDialogProps) { return ( - -
- logo -
- - OR - -
+
+ logo +
+ + + OR + + +
- Continue to Acter with any of the given providers. By using Acter you agree to follow our Terms and Policy. + Continue to Acter with any of the given providers. By using Acter + you agree to follow our{" "} + + Terms + {" "} + and{" "} + + Policy + + .
- ) + ); } diff --git a/components/custom/chat/comp.tsx b/components/custom/chat/comp.tsx index eb59a0f..be1c173 100644 --- a/components/custom/chat/comp.tsx +++ b/components/custom/chat/comp.tsx @@ -1,83 +1,103 @@ "use client"; -import { Message, useChat } from 'ai/react'; -import { useEffect, useState } from 'react' +import { Message, useChat } from "ai/react"; +import { useCallback, useEffect, useState, useMemo } from "react"; import { CustomTextArea } from "@/components/custom/text.area"; import { PaperclipIcon, ArrowUpIcon } from "lucide-react"; -import { Button } from '@/components/ui/button'; -import { LibSelector } from '../lib.selector'; +import { Button } from "@/components/ui/button"; +import { LibSelector } from "../lib.selector"; +import MsgsWrapper from "../msgs/msgs.wrapper"; export const ChatComp = ({ - chatId, - history, - onHasMessagesChange, - msgs, - }: { - chatId: number | string; - history?: Message[]; - onHasMessagesChange?: (hasMessages: boolean) => void; - msgs?: (Messages: Message[]) => void; - }) => { - const [space, setSpace] = useState(null); + chatId, + history, + onHasMessagesChange, + msgs, +}: { + chatId: number | string; + history?: Message[]; + onHasMessagesChange?: (hasMessages: boolean) => void; + msgs?: (Messages: Message[]) => void; +}) => { + const [space, setSpace] = useState("default-ui"); - useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === "Enter" && !event.shiftKey) { - event.preventDefault(); - const form = document.querySelector("form"); - if (form) { - form.requestSubmit(); - } - } - }; - - document.addEventListener("keydown", handleKeyDown); - - return () => { - document.removeEventListener("keydown", handleKeyDown); - }; - }, []); + // Stable handleSpaceSelect function + const handleSpaceSelect = useCallback((selectedSpaceId: string | null) => { + console.log("Space selected:", selectedSpaceId); + setSpace(selectedSpaceId); + }, []); - const { messages, handleInputChange, handleSubmit, input, isLoading } = + // Memoize API body to avoid unnecessary re-renders + const apiBody = useMemo( + () => ({ + chatId, + namespace: space, + }), + [chatId, space], + ); + + const { messages, handleInputChange, handleSubmit, input, isLoading } = useChat({ api: "/api/ai/stream", - body: { chatId, namespace: space }, + body: apiBody, initialMessages: history, }); - useEffect(() => { - if (messages.length > 0) { - if (onHasMessagesChange) { - onHasMessagesChange(true); - } - if (msgs) { - msgs(messages); + // Add Enter key submission logic + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Enter" && !event.shiftKey) { + event.preventDefault(); + const form = document.querySelector("form"); + if (form) { + form.requestSubmit(); } + } + }; + + document.addEventListener("keydown", handleKeyDown); + + return () => { + document.removeEventListener("keydown", handleKeyDown); + }; + }, []); + + // Track changes to messages + useEffect(() => { + if (messages.length > 0) { + onHasMessagesChange?.(true); + msgs?.(messages); } - }, [ chatId, onHasMessagesChange, messages, msgs]); + }, [messages, onHasMessagesChange, msgs]); - return ( - - -
-
+ return ( +
+ {messages.length > 0 && } + + +
+
- -
- -
- - ) - } + +
+ +
+ +
+ ); +}; diff --git a/components/custom/hero/dragable.cards.tsx b/components/custom/hero/dragable.cards.tsx index 8e336ff..c044e05 100644 --- a/components/custom/hero/dragable.cards.tsx +++ b/components/custom/hero/dragable.cards.tsx @@ -111,11 +111,11 @@ export default function DragableCards() { }} >
- +
diff --git a/components/custom/lib.selector.tsx b/components/custom/lib.selector.tsx index 90569f5..35b1e3e 100644 --- a/components/custom/lib.selector.tsx +++ b/components/custom/lib.selector.tsx @@ -1,10 +1,10 @@ -"use client" +"use client"; -import * as React from "react" -import { Check, ChevronsUpDown } from "lucide-react" +import * as React from "react"; +import { Check, ChevronsUpDown } from "lucide-react"; -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, @@ -12,12 +12,12 @@ import { CommandInput, CommandItem, CommandList, -} from "@/components/ui/command" +} from "@/components/ui/command"; import { Popover, PopoverContent, PopoverTrigger, -} from "@/components/ui/popover" +} from "@/components/ui/popover"; const frameworks = [ { @@ -31,21 +31,19 @@ const frameworks = [ { value: "default-ui", label: "Default UI", - } -] + }, +]; interface SpaceCompProps { - onSpaceSelect?: (selectedSpaceId: string | null) => void; - } + onSpaceSelect?: (selectedSpaceId: string | null) => void; +} export function LibSelector({ onSpaceSelect }: SpaceCompProps) { - const [open, setOpen] = React.useState(false) - const [value, setValue] = React.useState("default-ui") + const [open, setOpen] = React.useState(false); + const [value, setValue] = React.useState("default-ui"); React.useEffect(() => { - if (onSpaceSelect) { - onSpaceSelect(value); - } + onSpaceSelect?.(value); }, [value, onSpaceSelect]); return ( @@ -74,14 +72,14 @@ export function LibSelector({ onSpaceSelect }: SpaceCompProps) { key={framework.value} value={framework.value} onSelect={(currentValue) => { - setValue(currentValue === value ? "" : currentValue) - setOpen(false) + setValue(currentValue === value ? "" : currentValue); + setOpen(false); }} > {framework.label} @@ -92,5 +90,5 @@ export function LibSelector({ onSpaceSelect }: SpaceCompProps) { - ) + ); } diff --git a/components/custom/loading.screen.tsx b/components/custom/loading.screen.tsx new file mode 100644 index 0000000..1746fcb --- /dev/null +++ b/components/custom/loading.screen.tsx @@ -0,0 +1,15 @@ +import React from "react"; + +const LoadingScreen = () => { + return ( +
+
+

+ Acter is syncing... +

+
+
+ ); +}; + +export default LoadingScreen; diff --git a/components/custom/mdx.comp.tsx b/components/custom/mdx.comp.tsx new file mode 100644 index 0000000..796b5a3 --- /dev/null +++ b/components/custom/mdx.comp.tsx @@ -0,0 +1,57 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { atomDark } from "react-syntax-highlighter/dist/esm/styles/prism"; + +export const MDXComponents = { + // Heading 1 + h1: (props: any) => ( +

+ ), + // Heading 2 + h2: (props: any) => ( +

+ ), + // Paragraph + p: (props: any) => ( +

+ ), + // Code Block + code: ({ children, className }: any) => { + const language = className?.replace("language-", ""); + return ( + + {children} + + ); + }, + // Inline code + inlineCode: ({ children }: any) => ( + {children} + ), + // Link + a: (props: any) => ( + + ), + // List + ul: (props: any) =>

); -} \ No newline at end of file +} diff --git a/components/custom/msgs/msgs.wrapper.tsx b/components/custom/msgs/msgs.wrapper.tsx index 4c0b4fa..540af74 100644 --- a/components/custom/msgs/msgs.wrapper.tsx +++ b/components/custom/msgs/msgs.wrapper.tsx @@ -20,7 +20,7 @@ export default function MsgsWrapper({ msgs }: MsgsProps) { return (
{msgs.map((message, i) => ( ); -} \ No newline at end of file +} diff --git a/components/custom/sidebar/sidebar.tsx b/components/custom/sidebar/sidebar.tsx index e2bc2ac..077207b 100644 --- a/components/custom/sidebar/sidebar.tsx +++ b/components/custom/sidebar/sidebar.tsx @@ -1,10 +1,7 @@ import { Button } from "@/components/ui/button"; import { menuItems } from "@/db/defaults"; import { cn } from "@/lib/utils"; -import { - PanelLeftClose, - PanelLeftOpen, -} from "lucide-react"; +import { PanelLeftClose, PanelLeftOpen } from "lucide-react"; import Image from "next/image"; import Link from "next/link"; @@ -21,28 +18,30 @@ export const SideBar = ({
{/* Header Section */}
{/* Logo */} Acter Logo + src="/assets/acter-logo.jpg" + alt="Acter Logo" + width={30} + height={30} + className="rounded-md cursor-pointer" + /> {/* Toggle Button */} - {isSidebarExpanded && } + {isSidebarExpanded && ( + + )}
{/* Navigation Menu */} @@ -57,7 +56,7 @@ export const SideBar = ({ className={cn( "flex items-center rounded-lg p-2 mx-2 text-sm font-medium hover:bg-accent transition-colors", isSidebarExpanded ? "justify-start px-3" : "justify-center", - item.disabled ? "opacity-50" : "" + item.disabled ? "opacity-50" : "", )} aria-disabled={item.disabled} onClick={(e) => item.disabled && e.preventDefault()} diff --git a/components/ui/aurora-background.tsx b/components/ui/aurora-background.tsx index 7627178..4123fa3 100644 --- a/components/ui/aurora-background.tsx +++ b/components/ui/aurora-background.tsx @@ -18,7 +18,7 @@ export const AuroraBackground = ({
@@ -43,7 +43,7 @@ export const AuroraBackground = ({ absolute -inset-[10px] opacity-50 will-change-transform`, showRadialGradient && - `[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]` + `[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]`, )} >
diff --git a/components/ui/command.tsx b/components/ui/command.tsx index ade5441..ef49042 100644 --- a/components/ui/command.tsx +++ b/components/ui/command.tsx @@ -1,11 +1,11 @@ -"use client" +"use client"; -import * as React from "react" -import { type DialogProps } from "@radix-ui/react-dialog" -import { Command as CommandPrimitive } from "cmdk" -import { cn } from "@/lib/utils" -import { Dialog, DialogContent } from "@/components/ui/dialog" -import { MagnifyingGlassIcon } from "@radix-ui/react-icons" +import * as React from "react"; +import { type DialogProps } from "@radix-ui/react-dialog"; +import { Command as CommandPrimitive } from "cmdk"; +import { cn } from "@/lib/utils"; +import { Dialog, DialogContent } from "@/components/ui/dialog"; +import { MagnifyingGlassIcon } from "@radix-ui/react-icons"; const Command = React.forwardRef< React.ElementRef, @@ -15,12 +15,12 @@ const Command = React.forwardRef< ref={ref} className={cn( "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", - className + className, )} {...props} /> -)) -Command.displayName = CommandPrimitive.displayName +)); +Command.displayName = CommandPrimitive.displayName; const CommandDialog = ({ children, ...props }: DialogProps) => { return ( @@ -31,8 +31,8 @@ const CommandDialog = ({ children, ...props }: DialogProps) => { - ) -} + ); +}; const CommandInput = React.forwardRef< React.ElementRef, @@ -44,14 +44,14 @@ const CommandInput = React.forwardRef< ref={ref} className={cn( "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", - className + className, )} {...props} />
-)) +)); -CommandInput.displayName = CommandPrimitive.Input.displayName +CommandInput.displayName = CommandPrimitive.Input.displayName; const CommandList = React.forwardRef< React.ElementRef, @@ -62,9 +62,9 @@ const CommandList = React.forwardRef< className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} {...props} /> -)) +)); -CommandList.displayName = CommandPrimitive.List.displayName +CommandList.displayName = CommandPrimitive.List.displayName; const CommandEmpty = React.forwardRef< React.ElementRef, @@ -75,9 +75,9 @@ const CommandEmpty = React.forwardRef< className="py-6 text-center text-sm" {...props} /> -)) +)); -CommandEmpty.displayName = CommandPrimitive.Empty.displayName +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; const CommandGroup = React.forwardRef< React.ElementRef, @@ -87,13 +87,13 @@ const CommandGroup = React.forwardRef< ref={ref} className={cn( "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", - className + className, )} {...props} /> -)) +)); -CommandGroup.displayName = CommandPrimitive.Group.displayName +CommandGroup.displayName = CommandPrimitive.Group.displayName; const CommandSeparator = React.forwardRef< React.ElementRef, @@ -104,8 +104,8 @@ const CommandSeparator = React.forwardRef< className={cn("-mx-1 h-px bg-border", className)} {...props} /> -)) -CommandSeparator.displayName = CommandPrimitive.Separator.displayName +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; const CommandItem = React.forwardRef< React.ElementRef, @@ -115,13 +115,13 @@ const CommandItem = React.forwardRef< ref={ref} className={cn( "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", - className + className, )} {...props} /> -)) +)); -CommandItem.displayName = CommandPrimitive.Item.displayName +CommandItem.displayName = CommandPrimitive.Item.displayName; const CommandShortcut = ({ className, @@ -131,13 +131,13 @@ const CommandShortcut = ({ - ) -} -CommandShortcut.displayName = "CommandShortcut" + ); +}; +CommandShortcut.displayName = "CommandShortcut"; export { Command, @@ -149,4 +149,4 @@ export { CommandItem, CommandShortcut, CommandSeparator, -} +}; diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx index 95b0d38..3db2a7d 100644 --- a/components/ui/dialog.tsx +++ b/components/ui/dialog.tsx @@ -1,18 +1,18 @@ -"use client" +"use client"; -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { Cross2Icon } from "@radix-ui/react-icons" +import * as React from "react"; +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { Cross2Icon } from "@radix-ui/react-icons"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Dialog = DialogPrimitive.Root +const Dialog = DialogPrimitive.Root; -const DialogTrigger = DialogPrimitive.Trigger +const DialogTrigger = DialogPrimitive.Trigger; -const DialogPortal = DialogPrimitive.Portal +const DialogPortal = DialogPrimitive.Portal; -const DialogClose = DialogPrimitive.Close +const DialogClose = DialogPrimitive.Close; const DialogOverlay = React.forwardRef< React.ElementRef, @@ -22,12 +22,12 @@ const DialogOverlay = React.forwardRef< ref={ref} className={cn( "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className + className, )} {...props} /> -)) -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; const DialogContent = React.forwardRef< React.ElementRef, @@ -39,7 +39,7 @@ const DialogContent = React.forwardRef< ref={ref} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", - className + className, )} {...props} > @@ -50,8 +50,8 @@ const DialogContent = React.forwardRef< -)) -DialogContent.displayName = DialogPrimitive.Content.displayName +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; const DialogHeader = ({ className, @@ -60,12 +60,12 @@ const DialogHeader = ({
-) -DialogHeader.displayName = "DialogHeader" +); +DialogHeader.displayName = "DialogHeader"; const DialogFooter = ({ className, @@ -74,12 +74,12 @@ const DialogFooter = ({
-) -DialogFooter.displayName = "DialogFooter" +); +DialogFooter.displayName = "DialogFooter"; const DialogTitle = React.forwardRef< React.ElementRef, @@ -89,12 +89,12 @@ const DialogTitle = React.forwardRef< ref={ref} className={cn( "text-lg font-semibold leading-none tracking-tight", - className + className, )} {...props} /> -)) -DialogTitle.displayName = DialogPrimitive.Title.displayName +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; const DialogDescription = React.forwardRef< React.ElementRef, @@ -105,8 +105,8 @@ const DialogDescription = React.forwardRef< className={cn("text-sm text-muted-foreground", className)} {...props} /> -)) -DialogDescription.displayName = DialogPrimitive.Description.displayName +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; export { Dialog, @@ -119,4 +119,4 @@ export { DialogFooter, DialogTitle, DialogDescription, -} +}; diff --git a/components/ui/popover.tsx b/components/ui/popover.tsx index 29c7bd2..bd49501 100644 --- a/components/ui/popover.tsx +++ b/components/ui/popover.tsx @@ -1,15 +1,15 @@ -"use client" +"use client"; -import * as React from "react" -import * as PopoverPrimitive from "@radix-ui/react-popover" +import * as React from "react"; +import * as PopoverPrimitive from "@radix-ui/react-popover"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const Popover = PopoverPrimitive.Root +const Popover = PopoverPrimitive.Root; -const PopoverTrigger = PopoverPrimitive.Trigger +const PopoverTrigger = PopoverPrimitive.Trigger; -const PopoverAnchor = PopoverPrimitive.Anchor +const PopoverAnchor = PopoverPrimitive.Anchor; const PopoverContent = React.forwardRef< React.ElementRef, @@ -22,12 +22,12 @@ const PopoverContent = React.forwardRef< sideOffset={sideOffset} className={cn( "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", - className + className, )} {...props} /> -)) -PopoverContent.displayName = PopoverPrimitive.Content.displayName +)); +PopoverContent.displayName = PopoverPrimitive.Content.displayName; -export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }; diff --git a/components/ui/tooltip.tsx b/components/ui/tooltip.tsx index 9e74821..92a97e4 100644 --- a/components/ui/tooltip.tsx +++ b/components/ui/tooltip.tsx @@ -1,15 +1,15 @@ -"use client" +"use client"; -import * as React from "react" -import * as TooltipPrimitive from "@radix-ui/react-tooltip" +import * as React from "react"; +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; -import { cn } from "@/lib/utils" +import { cn } from "@/lib/utils"; -const TooltipProvider = TooltipPrimitive.Provider +const TooltipProvider = TooltipPrimitive.Provider; -const Tooltip = TooltipPrimitive.Root +const Tooltip = TooltipPrimitive.Root; -const TooltipTrigger = TooltipPrimitive.Trigger +const TooltipTrigger = TooltipPrimitive.Trigger; const TooltipContent = React.forwardRef< React.ElementRef, @@ -20,11 +20,11 @@ const TooltipContent = React.forwardRef< sideOffset={sideOffset} className={cn( "z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", - className + className, )} {...props} /> -)) -TooltipContent.displayName = TooltipPrimitive.Content.displayName +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/context/user.context.tsx b/context/user.context.tsx index ea70e4d..5f6d891 100644 --- a/context/user.context.tsx +++ b/context/user.context.tsx @@ -1,6 +1,12 @@ "use client"; -import React, { createContext, useContext, useState, useEffect, ReactNode } from "react"; -import { User } from "next-auth"; +import React, { + createContext, + useContext, + useState, + useEffect, + ReactNode, +} from "react"; +import { User } from "next-auth"; interface UserContextType { user: User | null; @@ -12,7 +18,9 @@ const UserContext = createContext({ loading: true, }); -export const UserProvider: React.FC<{ children: ReactNode }> = ({ children }) => { +export const UserProvider: React.FC<{ children: ReactNode }> = ({ + children, +}) => { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); diff --git a/db/defaults.ts b/db/defaults.ts index 1742ecb..39b4197 100644 --- a/db/defaults.ts +++ b/db/defaults.ts @@ -1,13 +1,9 @@ -import { - PlusIcon, - BookOpenIcon, - LayoutDashboardIcon, -} from "lucide-react"; +import { PlusIcon, BookOpenIcon, LayoutDashboardIcon } from "lucide-react"; export const ragConfig = { baseUrl: "https://api.deepseek.com", model: "deepseek-ai/deepseek-llm-67b-chat", -} +}; export const OfcLinks = { github: "https://l.devwtf.in/discord", @@ -15,20 +11,25 @@ export const OfcLinks = { instagram: "https://dub.sh/saidev-instagram", sponsor: "https://github.com/sponsors/SkidGod4444", portfolio: "http://devwtf.in", - discord: "https://l.devwtf.in/discord" + discord: "https://l.devwtf.in/discord", }; export const menuItems = [ { label: "New Chat", icon: PlusIcon, href: "/chat", disabled: false }, { label: "Docs", icon: BookOpenIcon, href: "/docs", disabled: true }, - { label: "Dashboard", icon: LayoutDashboardIcon, href: "/dashboard", disabled: true }, + { + label: "Dashboard", + icon: LayoutDashboardIcon, + href: "/dashboard", + disabled: true, + }, ]; export const DATA = { name: "Acter", url: "https://acter.devwtf.in", description: "", - prevImage: "https://i.imgur.com/JwDi96s.png" + prevImage: "https://i.imgur.com/JwDi96s.png", }; export const beforeCode = `function sumArrayTraditional(arr: number[]): number { diff --git a/lib/rag.ts b/lib/rag.ts index 0b13788..5cef62d 100644 --- a/lib/rag.ts +++ b/lib/rag.ts @@ -1,12 +1,14 @@ import { ragConfig } from "@/db/defaults"; import { RAGChat, togetherai } from "@upstash/rag-chat"; +import { redisDB } from "./redis"; export const ragChat = new RAGChat({ model: togetherai(ragConfig.model, { apiKey: process.env.RAG_API_KEY }), + redis: redisDB, promptFn: ({ context, question, chatHistory }) => `You are Acter, an AI assistant created by Saidev Dhal. Your task is to generate complete, high-quality code solutions based on the user's question or prompt. - Use the provided context and chat history to craft the code. + Use the provided context and chat history to craft the code and reply everything in MDX format. Ensure that the generated code incorporates and appropriately uses the components and styles mentioned in the context and explain all the details related to that component. Only create new code without using any component from the context if it is absolutely necessary, and be sure to explain why. If you lack sufficient information in the context or chat history, politely suggest the user provide additional details. @@ -20,7 +22,7 @@ export const ragChat = new RAGChat({ Question: ${question} ------ - Full Code:`, + Full Code in MDX format:`, }); async function AddTXTContext(data: string) { @@ -42,4 +44,4 @@ async function AddWEBContext(src: string) { return true; } -export { AddTXTContext, AddWEBContext } \ No newline at end of file +export { AddTXTContext, AddWEBContext }; diff --git a/lib/redis.ts b/lib/redis.ts new file mode 100644 index 0000000..00c8a7e --- /dev/null +++ b/lib/redis.ts @@ -0,0 +1,3 @@ +import { Redis } from "@upstash/redis"; + +export const redisDB = Redis.fromEnv(); diff --git a/lib/use.local.ts b/lib/use.local.ts index 058fb7f..d649edc 100644 --- a/lib/use.local.ts +++ b/lib/use.local.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; const useLocalStorage = (key: string, initialValue: string | boolean) => { const [value, setValue] = useState(() => { - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { const storedValue = localStorage.getItem(key); // Return the stored value if it exists, otherwise return the initial value return storedValue !== null @@ -16,14 +16,14 @@ const useLocalStorage = (key: string, initialValue: string | boolean) => { const setLocalStorageValue = (newValue: string | boolean) => { setValue(newValue); - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { localStorage.setItem(key, newValue.toString()); } }; useEffect(() => { const handleStorageChange = () => { - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { const newValue = localStorage.getItem(key); // Update state based on the new value from localStorage setValue( @@ -36,12 +36,12 @@ const useLocalStorage = (key: string, initialValue: string | boolean) => { } }; - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { window.addEventListener("storage", handleStorageChange); } return () => { - if (typeof window !== 'undefined') { + if (typeof window !== "undefined") { window.removeEventListener("storage", handleStorageChange); } }; @@ -50,4 +50,4 @@ const useLocalStorage = (key: string, initialValue: string | boolean) => { return [value, setLocalStorageValue] as const; }; -export default useLocalStorage; \ No newline at end of file +export default useLocalStorage; diff --git a/package.json b/package.json index 7cd131d..cf7b0fe 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ }, "dependencies": { "@auth/prisma-adapter": "^2.5.3", + "@codemirror/lang-javascript": "^6.2.2", "@internationalized/date": "^3.5.6", + "@mdx-js/react": "^3.1.0", "@nextui-org/calendar": "^2.0.12", "@nextui-org/checkbox": "^2.1.5", "@nextui-org/switch": "^2.0.34", @@ -25,6 +27,8 @@ "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tooltip": "^1.1.3", "@tabler/icons-react": "^3.19.0", + "@types/react-syntax-highlighter": "^15.5.13", + "@uiw/react-codemirror": "^4.23.7", "@upstash/rag-chat": "^2.0.0", "@upstash/redis": "^1.34.2", "@upstash/vector": "^1.1.7", @@ -42,6 +46,7 @@ "prisma": "^5.20.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-syntax-highlighter": "^15.6.1", "shiki": "^1.21.0", "tailwind-merge": "^2.5.3", "tailwindcss-animate": "^1.0.7", diff --git a/tailwind.config.ts b/tailwind.config.ts index f74e309..1c5587f 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,7 +1,7 @@ import type { Config } from "tailwindcss"; const { - default: flattenColorPalette, - } = require("tailwindcss/lib/util/flattenColorPalette"); + default: flattenColorPalette, +} = require("tailwindcss/lib/util/flattenColorPalette"); const config: Config = { darkMode: ["class"], @@ -11,118 +11,118 @@ const config: Config = { "./app/**/*.{js,ts,jsx,tsx,mdx}", ], theme: { - extend: { - colors: { - background: 'hsl(var(--background))', - foreground: 'hsl(var(--foreground))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - }, - 'color-1': 'hsl(var(--color-1))', - 'color-2': 'hsl(var(--color-2))', - 'color-3': 'hsl(var(--color-3))', - 'color-4': 'hsl(var(--color-4))', - 'color-5': 'hsl(var(--color-5))' - }, - borderRadius: { - lg: 'var(--radius)', - md: 'calc(var(--radius) - 2px)', - sm: 'calc(var(--radius) - 4px)' - }, - animation: { - aurora: "aurora 60s linear infinite", - shine: 'shine 2s infinite linear', - 'shiny-text': 'shiny-text 8s infinite', - rainbow: 'rainbow var(--speed, 2s) infinite linear', - gradient: 'gradient 8s linear infinite' - }, - keyframes: { - aurora: { - from: { - backgroundPosition: "50% 50%, 50% 50%", - }, - to: { - backgroundPosition: "350% 50%, 350% 50%", - }, - }, - shine: { - '0%': { - backgroundPosition: '200% 0' - }, - '100%': { - backgroundPosition: '-200% 0' - } - }, - 'shiny-text': { - '0%, 90%, 100%': { - 'background-position': 'calc(-100% - var(--shiny-width)) 0' - }, - '30%, 60%': { - 'background-position': 'calc(100% + var(--shiny-width)) 0' - } - }, - rainbow: { - '0%': { - 'background-position': '0%' - }, - '100%': { - 'background-position': '200%' - } - }, - gradient: { - to: { - backgroundPosition: 'var(--bg-size) 0' - } - } - } - } + extend: { + colors: { + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + chart: { + "1": "hsl(var(--chart-1))", + "2": "hsl(var(--chart-2))", + "3": "hsl(var(--chart-3))", + "4": "hsl(var(--chart-4))", + "5": "hsl(var(--chart-5))", + }, + "color-1": "hsl(var(--color-1))", + "color-2": "hsl(var(--color-2))", + "color-3": "hsl(var(--color-3))", + "color-4": "hsl(var(--color-4))", + "color-5": "hsl(var(--color-5))", + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + animation: { + aurora: "aurora 60s linear infinite", + shine: "shine 2s infinite linear", + "shiny-text": "shiny-text 8s infinite", + rainbow: "rainbow var(--speed, 2s) infinite linear", + gradient: "gradient 8s linear infinite", + }, + keyframes: { + aurora: { + from: { + backgroundPosition: "50% 50%, 50% 50%", + }, + to: { + backgroundPosition: "350% 50%, 350% 50%", + }, + }, + shine: { + "0%": { + backgroundPosition: "200% 0", + }, + "100%": { + backgroundPosition: "-200% 0", + }, + }, + "shiny-text": { + "0%, 90%, 100%": { + "background-position": "calc(-100% - var(--shiny-width)) 0", + }, + "30%, 60%": { + "background-position": "calc(100% + var(--shiny-width)) 0", + }, + }, + rainbow: { + "0%": { + "background-position": "0%", + }, + "100%": { + "background-position": "200%", + }, + }, + gradient: { + to: { + backgroundPosition: "var(--bg-size) 0", + }, + }, + }, + }, }, plugins: [addVariablesForColors, require("tailwindcss-animate")], }; function addVariablesForColors({ addBase, theme }: any) { - const allColors = flattenColorPalette(theme("colors")); - const newVars = Object.fromEntries( - Object.entries(allColors).map(([key, val]) => [`--${key}`, val]) - ); - - addBase({ - ":root": newVars, - }); - } + const allColors = flattenColorPalette(theme("colors")); + const newVars = Object.fromEntries( + Object.entries(allColors).map(([key, val]) => [`--${key}`, val]), + ); + + addBase({ + ":root": newVars, + }); +} export default config;