From da211011f93e3dc87a99effafca19fac86a677df Mon Sep 17 00:00:00 2001 From: Pradeep Date: Mon, 3 Nov 2025 08:47:05 +0530 Subject: [PATCH] 70% done the cost it right model report --- ...-9e316482ab86_20251031_065932_analysis.pdf | 869 +++ ...-dca94b7bc44d_20251031_085459_analysis.pdf | 888 +++ ...-dca94b7bc44d_20251103_031025_analysis.pdf | 1002 ++++ ...-29726f41c4dc_20251031_123624_analysis.pdf | 830 +++ ...-907686477f73_20251031_052450_analysis.pdf | 932 +++ ...-de1e0581cd48_20251031_040818_analysis.pdf | 989 ++++ ...-de1e0581cd48_20251031_062108_analysis.pdf | 850 +++ ...-de1e0581cd48_20251031_083336_analysis.pdf | 328 ++ ...-e27482b4dfa0_20251031_124817_analysis.pdf | 850 +++ ...-e27482b4dfa0_20251031_133749_analysis.pdf | 1174 ++++ .../PERFORMANCE_ENHANCEMENTS.md | 478 +- .../ai-analysis-service/ai-analyze.backup.py | 5043 +++++++++++++++++ services/ai-analysis-service/ai-analyze.py | 2260 ++++++-- services/ai-analysis-service/env.example | 2 +- services/ai-analysis-service/server.py | 77 +- 15 files changed, 15833 insertions(+), 739 deletions(-) create mode 100644 ai-analysis-reports/repo_analysis_152c1b57-4cb5-481d-8270-9e316482ab86_20251031_065932_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251031_085459_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251103_031025_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_5189d381-815d-41de-85aa-29726f41c4dc_20251031_123624_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_af0719d5-5a49-4562-951c-907686477f73_20251031_052450_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_040818_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_062108_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_083336_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_124817_analysis.pdf create mode 100644 ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_133749_analysis.pdf create mode 100644 services/ai-analysis-service/ai-analyze.backup.py diff --git a/ai-analysis-reports/repo_analysis_152c1b57-4cb5-481d-8270-9e316482ab86_20251031_065932_analysis.pdf b/ai-analysis-reports/repo_analysis_152c1b57-4cb5-481d-8270-9e316482ab86_20251031_065932_analysis.pdf new file mode 100644 index 0000000..5b5291f --- /dev/null +++ b/ai-analysis-reports/repo_analysis_152c1b57-4cb5-481d-8270-9e316482ab86_20251031_065932_analysis.pdf @@ -0,0 +1,869 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 12 0 R /F4 17 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 51 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 52 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 53 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 54 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +13 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +18 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 91 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/Contents 92 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 50 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +48 0 obj +<< +/PageMode /UseNone /Pages 50 0 R /Type /Catalog +>> +endobj +49 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031070300+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031070300+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +50 0 obj +<< +/Count 42 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 13 0 R 14 0 R + 15 0 R 16 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R + 46 0 R 47 0 R ] /Type /Pages +>> +endobj +51 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 495 +>> +stream +GatUn>u03/(kqGU/'_^o7[hs)/9cYV>:#pnZ&lJQ9^7aVFdgu!d!q)i'uib_"mD5!On[r#3QEKADJ2.J"WVU-^(ZkTo]4>GE95:]=?)[(2HWoEc%@-]HbRAhA9i>qj?N8-EcIKl>G0%jQK<]OMlQsL5N#n1VHuAt4+2:DSR.S>Emtj%;0,9WjM`\(ffK%oFK+OQM>bUimk2>jnXCGL^fC>IoUZ`*I8?PmV`;D/^helhXmDU/0R@[c#nh:JE2UeSEjZcEt%n>h2X$emaW_(hnqlSUCZqaTI:^eP?~>endstream +endobj +52 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 572 +>> +stream +Gaua;?#S1G'Sc)R/'\T%q+-@508I0AFAaD7!VIe$\8`O5(gMF?/lVd5Vl&hgX4E.9.SE@/POlNWF6nQFNf0^6>QA#LG^W#2:uHC;je)bU%S",*UIR4\2@Q%[(bjMrm(brZ$N@Jh]jrLGN=1uF5jG`kc.>;\dAPC]RZDAV0YO&O/j=`5%f@:8(Mep>\Gik/jJWOdD1d]:PaEeepVI;JPQ>3H=Tog2]#C4;;0=R:*f:82F;^iJT!bR@FigSLZ22SXH+OI^=/ffP7n.\IgIsi:]N%g:eda=@//&c3QJnegFk-Dbh9bJdV(aT/Kr>b@N?[X!O80OXT&9&Yg*VFN(Xb-3).aoa[=\f.H+.K\Bp6bn!-]%(N^Hq.IZ?L$URl8O]h+q/^4!Xq0=MAC:A>q@D9bRk.HG\a4.&"nN/h8_!KPFX]uMlLfiP7$&CV2L[ORf'8?-_S??p2DIppQZF"pFT>iLOGJt&UAb);ZW:ot4hdXBQJD3N7;jm@ntendstream +endobj +53 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2486 +>> +stream +Gat=,>uTcA'RekGESm4],U7#PomOrU-crU7F_56Hb+@2Kj$Nhh$J^$"1GFJ+UX*V7kj!H)1&qq?Tr(Yg_+Q^k(Qoc_R5qD].U5pEN_!:^?E8AD7rm.f'<9DO70lQotLr@]C4V&Cp:q1nA,u%d"MC/1`b;Qr>FB4i1<3OEZEhR7eYKZ+(7!Uim1Xn?Z*"V7oTVU-"d:Z"C_i!aO;ap&"iPA4V"`5S)_*B\,XpFiXdAEQ;;:Md#J]Gc$^QOoOPK2!$4HDf[p^`5e84pej:eu$ZRka?8j,5jRYL's)8:_Mb_X]kYK3sYjTDdV;=8m!FNNlUPSZo_k,UL[gCs6L,bc4YrZr5A"*CTcS;o84Kg13YfELb>:%/)0;2OA1JI+r8.A2*s+[Z(7%5mlMFNJcT^j6jH-m2qH)0Y^6D-.T=?[!^6rl._"gt#1O(c\,'^0!Bf_oaKa`-hJ"#qo2'^WT9iP"=_-KAFgTpJi9&)C0@.@88/BZV*\:VNk4G3+JS<5*3;T5J>X@uU^G)0):+W)C!s#1V](<@SpHVnNB-Ke7n.4OlU!P6E>j\i.mXO*4d7h.h/;YM("9T68Rbh0#,K%,@XALp3!ePPQ(c.sqhi/1KT/e@8-;)H#U&d1U/+r?=PNU/ZZQ8WDqDUYWLrs8)Ln(F+k@6T-McbYu#O^`oOk>1p@,UGrc@P4jV5$#Wlc-4c(T@?f`l-c1@'IP[,go#_WjF,.cRFMaLZ;aA(A&YBA7c36!t\L!Da=Lp3K;-)@$)XQt(']*!_:=i+B!7J3q,\1(9)VuP>P==00.1Vh>$0l<%1Oi[&=X>re*(/psCTpulei\JKubh/cC!M_c"H(Nn5d;$:]4:s(VZ%#?2`#tmjB[R_rM?MNkpMnJg0tdR8%er.3/8FH1^m5i+OpB'9M6s(\L[oKsBLD18Gq8r5;:afb!1b`:)"6$$Jeu5Ha*ud#j\f9>)d*IY815:K.Gl1eO6ML=q$h",T[WE:u6^?Kd4Nqb/Y%`XCM+6b=_%`uSUBp(S4EZDI=slre)WdO+k2o8O1EK:SV[rhAJ%K:)SJs$diDUZl)8iVdPO*1sbrI:3,2hnn"DmLY3Fp1A8GuWYVUX[J/Pp,_`(J.0gM6f6j_3OsrS-B5gM1H3E?Y*mCInT53(h"4N+7?N,`YO*qt`J*'cWY)DMkYpT,Y1QAhc,A]+djI!`ZI^OhgjZRO-4HJ`M&*jDE`m6?C\]W>WUiU2iljbjlkF>j)TVhGEkO7W=>#!,H9I.;`DM9cRY=p3?lAHH_nK72!`*D!X;9#)VWJpRc`?o:M_=4^iipAuJVtjAc\/KRK_1[j-iM"bR_ooTQLD_8IFZe93C/[Xb#UF$.2Fe>>X@p*L28#hGV)e\&'k#q&@:#JOmJ".7.Cu=@fI)&ihRQ2dg)`)'c7la1Dfl)\>F?BlH9ES)pRH&,-CBa"S\>]rL,H7]C$gXGmhSTp0.YkSDKN/_b?ITWqtA(E00h$OE*Lm[E>6@VKu[5G_Va>^o#]P;g>0*d**L:VOkEhAJ)tc2V!rW_endstream +endobj +54 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 841 +>> +stream +Gat=(>>O6D'Ro4HI#gmq;?[6\e:kiZ]/BKFbKuitB\Qs.#*JlWqb9pu2[24<8T3e93Tn#u`+\b"l[)e:V[<&e1#`9\3T3:=d`YLi5_"U"-Q?mcDdNS!8oTNmasf;/sDTcGX5;e'*H^YD9KKVTKCht$WU6/;FM_9o/$\e/huk/N^e8d3g&Y=nguH#5#nmT`A]k9Y#I2O6-]m\5F,E`P^[Q,fGoe46@""tY;SKZIs-1_gZD>45DY4?10U;#WdC?Y:1PR\8RTZejFDFK$V(R*%8'/IWX%b"IItc;f=D[uor9fR=C'f"=P^DH.T1-;_#dAfoC.nTWL_>+iCs.=W^JV?9u$_!PC)chOIi2rJp*rRoAq16]ucn#PMD+]uaHam^e2P2%Kj'P)/5kjGoSdqkU]?_(Ibgn.q\24I.6JkP^0`K:T5%f[fRLRX`d$X]a-p^?Je:iN;Yfuc=b+qhc:c('Fi:sg3Il&rg1\I1#4=;!'%.MokTK-LI"MFsoPpj4.;9rVPZ>eC;+Xj']+FN%LbWcar=d&ej2XMC:pSE:7!8u9Y9Y10tCBIeq1_f'G[%qd90dlhWDf6Y/XrNLF_d4.A'\1p9U?/&&,o)RrRb2^=[!$bC#j/BH5#2Z!p[J@7RlF?k"^Y]433+U%F.s[u6?=l$A*9#+@fpo@Jq?4#X'tWr^QolV(6@UP*&E-S8g^si-]hbc%H'EW\g&Png%\jJSHQc=p6#O5a(G!8B\c'/=%m"SIB`%mMf"/K~>endstream +endobj +55 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1231 +>> +stream +Gatn&?#QJt'Sc)R/'cC3RFRV>I+,\aV:r$![%#F)3pM\4DF+GKei6T>J,LEZ';bNoYREk@71?hiO'c38'/8r#ol!_.>fZ@,Q2n04IKe^J%`BTJier:=aN'j#!5<"`5nF7q":gglJ=Kp'ZXiek$_K!>>o"!THC&2DDsH.Rm`0<(^4H8onE2Kc#4^_!K)W8EHC>>AE!_0o]8'5t7pdBfKD9ZSor$8P3k^Hknb+WSq&?M587(N[*,.q80tWm1(iUu/=,a%2U2n932To50I89BVR?^rU5MT1#(9<*X)bIB!gi>^L6&M#!'j((_l\a:Qo\b0<_(,T&H`#pjgcpCP5b;s@'!Ld@rB[?^_<9Qon3(dP/A_@MlIB03ErLl8OXJkfJm5ND`ba*R8!<]@S9ZZmk,q9Rt=o(i\SY2gXCHt*YlZqnuf!?9.g@dNg]4TfRXB(c9F"VJfX.ph@1l=dNkWBn.bDabT_CuLN"GUKT=oc[qu"ChH9I1roDSGF#Bb&W1rPVRps@At$`CR]l6Cl(HpG`lorA05PF\jeZ>;,AsLJ1d1IaqD4G"jOG[mb&:rXL9R&jI$saBU7t*cnW4''d?-_H7&DaIT0o`^YZsZhj>tbb<<#_cRi[_:7"(QOg=R4oDX?ZnP7QG)h9N3K0tDhuno"L;"GCmaTGV89-75$45#^NYOH3?(;2uUMP]62p\.7(=SJaT=[1Q*rBFZ]onoXaEmsC4'4(sG0JHbA]0=SrMuNcH7U3k~>endstream +endobj +56 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 230 +>> +stream +Gat>L_$YcZ&-h():[oO-KC5]&g/4f46IPQ-U8o!09C&RdDr%,n`.RtAQ^N=e!ja%/)[5:(_21E#6jJVJ(o"fCGRoj!QRPG9-_L!hgP0"d$@T\ASoX58rWtl,qSQQ3O%l>6(?24P@1.();sn/unl(LQd6g",S_-YSAb0h1fh/l@8t.32A)5K$M4^Hb([3VZ8Y;jDZr-MC86d'MApbX'`7Q9[IXL7nHN>Jn@K$~>endstream +endobj +57 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 999 +>> +stream +Gatn&?#SFN'L:RO(&)8Ph,\9[HrbTf/8S:E;Nb(L`/C+r1i#XL@k.$;kG3c.+gH<`d7G0e(L4VL+7K"#<4bC]e&O^^(75S6s5uJWJ`/OlYG7gMj^G8RIXBJkW2sH+VdSQ^JTI:8tV_:^S=!YP$S-*spU8.@M39G:=>7R1LF+OY%sdVDGmM#@@/<.fR(%S=BGBA3,Z.=eLh*+3\U\#b>Tm&TCY.K]FrhrLhg75p$sJ-WBGa47OhMgu7Ji2MobHW87KWUXU!k8ME4fU@F8SR4kD:kZspGdbU.K6mT(08g$'HCST6oZc#)^K.qB;r.PZ:6+ZRm01(GLjEp?3XPiX9Qj6"7W@5Zdh.T4N-=u2rV""sPQqbGQ2C=Q53gTTilFaY;^$X5$f:2?_@eZ,[%31XVDJc;up4mVG:tO,6qD+;8bdhQNEHL,3Bm]4cL<XmlU_]$KV%?WXYaS20ct^-9b8X6rPRTD^CuX,knA^+R0`#N1,Vd@JhS:$QAiBT$,balLI,/h;hsBWQq9+2X<9R:qNhFS0^`_&m_KP="Np7(R2ZkKB_YimUB]cF>rseG"&a?dn:=AXG&43;KM6lJ%B>B9$C#@h[2_1Z2;s2G3T"L[$=O#1jNP85NYIt0Y+u4J(^Lf%g32]nG~>endstream +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 400 +>> +stream +Gat=d0i,\@'SQ5[MHc/D6]'RGUgtqiPq#c>:du4a]ECT2(Y^Cuhr>tVRo3WZ:\&OMn,,?Rh[OAXU]bRE>V6oH#]U&,),:aHE>oGF#AiQ363Q?%0FVTf9/saVfR=3LJ[1-9gI6S)aDXQ2n=E_ni#M9f;b&q">A.G6_@*H(WQ8?5oIfN>WKjh9;ckdjM;"-T3T6A5oms0M#^6Wm3HEBH:pR>DA?(f,UDZZRfC@N$c2.2:hSHE>SLIibR8?-'3?endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1816 +>> +stream +Gat=+D/Yn7&H88.1&V[*3N3.c*BWMD6l_A_g>Fco\X`S/")E7e]G9"3do6;DblYn8_,8OEN+$q%R@T[W"pJQ8.bV!E!*hU)I]J!nK!PMi+:Z,SK'o.V4&Lm+UG7]3I;(gX*2JKLuIIV\e8Q[MFXoUjDB\r)Z$E)+),8P#mFW*\_hdPs1c%qB%s=PTZKkN@*<$^_j0DF:d_R:^p!VJ)EBYrc"3F]=@#rL_%^OR8W/%4:]KX3(#+X#a0q#1Ys0m20,;6M=D5XPEsl\p0Y#$#!q%cWm&n9=?8Wf9pMrFZ1RDi"endi`^g(sM@U:)AY6%=BB(>aiPR>q_QbA:*T^n658SSu+=SCaXnDPV1?_rN+q203[Ge?]=Jaq!DKJ1N?lO,/nQ``nP$]XB_ICE'?ffK%!;0J4=>h(YLhL_nrBCEDoU,c=^R!+KE_p!Q`S9t%*/W;6Sm5Ho%?fg+I>34<#DPWM>f3B4&bG?g`:eOD/fHmT48[SubL8?0W(j2>."8%\E?6,em_%O3m9/(R\ES4-X3;8b_"RE>!S3E%XB9dgmu'/\Yp.^X2mns<8%f;V);6"g[O9eDic7W[`k-X.Jk!DI`X:+""]Z#-nL;+fEgp-@8=,deT&`Qj\^JL>NpI65p/+s`T%Q0N6):KI-A((X$[*U>VAN_79OTQB:XU![>L72]=eH"OXj:/:mu??YTP;$0)%gKl8a+SiHt,(DCtlIkl@;S?4ShbM-k9&uE(Y_WPr$)>.cs%3s$)EEO]2a-*2STaaU?l:2nKh8.]`HF?-9CPU=F!EWs8ek_>I[nk4(#24f$.dGNmb'?Ef-L#.gPjT]]5lj649-lrt86;_FRm*ApmcG<&O2(eEr\%OnD-G7Q.rbkbk;GB!<0]E6JIWie5]bU4"t/;MEe.bZe+8pQ$)./J-V%_HoGY23D\kc]4\+%J_GWiUL@H=+IZ:%gh?%bg""`GN.-K&+g.)"lE.HV(tEpk,IA-p2tK'"4IfURnfYA'HPl4%EDWhfSg:2?=+NZ3;5E(2Fj&[^`Np1J&9!6@$i6ZqM.F.9k)>^H:BbW+7dO'Rqlh7BhC>$AU54Z*5@>%>7l)MRk[3u$@l@r43<0b?,N6;>kXoh/q&$l,NB>i[6ag+Ud"P!F9aA`r,+'TaB(9.Ki_rJ!_;phkRO837BgtB^$4'pA4ScQ=P8#;XroHOhO[i^M?e)K%1TtrV0O_,$CDTK!+eZOe%(XZLJME0n$l:"Sl(=@o_@/67b.:bP*MiQrg]T8T9$Jn9][J0p#eL(qrJ*3Ap9%pF?]6_T@9endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1709 +>> +stream +Gau0CD/\E'&H88.0i`?/WH8WYGtZk]"N7i<-%l@jkt-9UfF)N%G^[2>Y-be?hHAT@^kSl@*_;.SSU'@/B:]uWW8lK)rrt!(Se"os2V8N7F0HTa"8joMSR"ubC213=_GeDFj8<'$=6N,B]c@cgWJmKG1f7G6GY-6WeS7$=h1Dt_#u9^tqNC)"qKj!3/6^i)Ar>oS6!mNa0jj=]]E=(V-;f;s=_':K4sg<%=D,<`\Ylab\8GK0r92C-;S:AA8O5<_P#Q&B_*?2Ue]:YR6H=?*YrZSkj5bp#!!5o[g<].n]2AY,jANtmX>[[QOtiR0$8B?MT6.A?5XtP3"50j_:PYem>@SFW/Qd6%YJU(b'mSR6#8dq?*qUgdfCu-rnt':LN?>&#s)IT9Sd57Mo\EfVs#BS_hu"*\?RUoc4"7?%(*`UOr&tS5=M9(GMb);]2#M$Ri3Jk9:neRo=#A>Oi%l!G-CbF(=##Oi'cnI1YC^ggE+;Wm]KCLE"k>"g&ZJbJlL8X*<3l`#Sr/4InZj-H`CUeTWs%\9?l98'(1k^iUFOW6729!lAJuSI"\CHqgbri>;r0'_\2%.[AArfHS#W65p82N/Y6SZ\V]3uUPSmI.VGs^$5iG:s"biJLc]MSPZ1mVa^D(P>q]qMJ1GXn,KF16m"ZlReoph3T4jVT:qXpiS\ZM&m\=N5"Cbmt+p0iJG*9_Dkl,5cE-SPYDbk,#A8='EV)6h8*4VB;%'f31>`DY2a0tL9YZ-^uGM\cUW`dsQDi9GihMD?QEo;*^C$E#_G7WE&q"fPXJ>Yf8/s7+B8P*Sh"J^=uW"@XP#?AeC;mBDo/I0p\?*+Caq9pf3Pt:0onCgI"a!,Qg'0rU4qN[oL!&(oHZr>o;MLIm4hGTA[FF(d:YV(jCDcRuC`U_aVCX%HQahB7))XLRA]30#Nc6LK[01Gd2`]=T;S[U+&5T9k;9[$hp-)PV^\c]djY\H`ne@YK%BKXZ*j]WYmnHU5")-OblO;s7;LZc_h-Q.dj;!Y8>HbLR'*ogXsr8).U0Un1*b-O9.c7a11&>j;HlE_^\M%Q6Zet"]NDP/8=UR!"n>TbEC#Qa2[d[ORsd_iE9p83>G2;;8endstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1204 +>> +stream +Gatm8mr.2T&H0m]0g2KKW@i]q#S(]I!hXORcX77[0!3&.`scL2^$FEYkDoQ7SMe.`8SE7HOc\.cH#MQbS$AVT5HFWVF+?Obc"d\<)r`k[(QAfY"7Y=(f:'+(loK*2fkn*d.u,lp5E@,9L!144EAgR&;JT9`E`"'_D3E]Va([LEk60ZHa.QMs!:%+^@5]N:2FH0e\7U'[Rk'_8I.;)XT:VT>quH7?:^;:b2i.kLblghJBt[Wcn*coO2K"4R;EXL8j+LX6mtV3V:$ZM*U=61u8/,qYeFX0<9mHL=;NYOX)NJI[f0UZcn;g+Zo87pE5jlrF31lf@HB>Wur#\N9U0QL>Ygbn=22:g@4+kqAj?4?GR:\mB+>Kq>;>7.g:b$2m-pt@c-?+%/Wq!6#QkY5\R\1j`*q]%c[O=STD_9j^/Ck^WWce<:,UX5W7P]p/%$dba8U[IZ-PX6jePmCR/2^q;c/CDR/K+N?%hl:AGUf?!!2rWSFi?Pt/7%PTI(!mn-*:C7_RGg63h6FRE?T2%;>(/'-f8Iu3mF>tAfo75q&0rcjE"8!hq;T"-%)YpZq!eg+pS31*P7sKVAelT"+*a^K\@?j-'^aA5kXr-J8qV30a;KBqI/X^=HUH.,5M.,OVG3=J7';t5%C6J1dS][h!./,.m=3"TK9;&(&=dW["641@%D\"FC3Oke_gWQ4'O;dUk_i^>(UL193%2,RJfWZ'arg%%8l#@)+endstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 564 +>> +stream +GarnSbAQ&g&A7ljp8I\HR#2hE]d\Pl#`r=^A.019KpFVT",XSh\dSDBU(*K\(d5/dJZ)W6aom?.GUJ\;,Qh9:C\OKci@6Mf"'!p8Itc!p4IYRFa'qL[Es/=-ccTk2eU.g0n][)/e@$KIEcqil`M-ALr.]&m8Q:'b.X-cW7]gHjk.@8P,On`G_L8o:=c[[aJ\5[_@Hc\AkTI>2VK%i[-488S"pMc_Hk)Xc=kB!F(,<)nt>NiRFTBQkrj2XbGQbL1>#WSQE]%3j=tJ0"jVW*;?~>endstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 656 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E.Ok,]=08<(iUgi)Zl-Qd'hM[b6SF]2Trg5-m-J_F9`$5HO%l3T#cRJcS#3qrJ1CVM*:)&O\u7CPYFr,:KIOQG'2&[&K#)&rK;&>I@pC,cKYqNJP(R&Aijfcp>Meqnab.gc%%+[Z,H"T@Q]\9]Ak;rOpqM+doc@$8Zh]bD%5[,2.R-"[2Aod9l]5Gksm'\tML3KQaIq,)+1P`345:,XqM;fALbUsKB+jkkfQ/Kk21rcXMVr3&Fq'EgpC`a,472[NE),UC<,\qh"JdXkj?od#oT*3P*4D1+J!pPOn!CP(./u"qA(>NMK[*I1;rk$rZ;a=SnmV[U\6iBZB=\-kQc9C4T["2+)"/bcjQ)Y-+[mue3mX*2D'X6<]\CfYn7XEO&PPpP/#m>Tj26gC.`l!&dBJKendstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2259 +>> +stream +Gatm=>Ar7S(k'`6+9DsBMjEL"\%H:O>Bi]M,^,g2Thm6j4?>Fb/\UUOS?'7Kt"C"NOpfL!ToSOQJlTG6E>.k70Obi//]C.p%ZX7jlLUq.fH_HPE'G[u61?'&Cd85:g[fn)'hXjlQEbibUJBB<0S\]n3p_X0640;T6D*c[H@_:?K@G*2";"Pf&q0c:]&,'#eNgVF?p(l$&Pg3rZdSW45:h(Q%EdWtPD4PZ<]\duCG(Xf68oI1H'l/dD,Z8crE'#W%Nl%JujF!`(,06SBJbaQ!E:AcXA-\p\jWUO[V669#;YO-obQ)=KZ^V!XfnD%A$%5&J8rk,>HpEZEFk3K>;>c/B%PSD;'Y5D*_EO;'Jo3ojMD**pPVQc!e)LB.'1pdLXpl7eGYU+5Gl\DG2o[!kEdF]$$m:'A^35ue>kR9T?%3/8`iK?RdY_2b=bUBa#6A)sD/076qER9&3e*t8O,tUf?V[\k27R8=SSi]oA-Y8DeZZs*QpDG6B/gA;e&WVe-&&>oa[`@TZ6:pC(@A(Cg5sU#:`bg-Heh01]5dtNXQQ[/F4?Q*fP06EDBbPli\+Cjhc_LL!@Jg#Gm4dV7Yr"j>j1Z^Ut22DkRali=RI#;!Tonp0ZD)8:18.-Bf3bXSf>6WZW(KA0KD*@WkhFA+Ij/]mS3inD4;b3#o4fQ:f!G17"4"Kc-BMYAXo[-ZE!F^2S$aELD'_t:bKs'-a=p,@S*"S91,gjQG=(p[I>4qBY^1Eq3fe>)r2@Oc!%>/\0_q3X3bOS,jgAgoW9\*d+@4QYnhMi)>ZdkVd7mi&Pcpr_ZW8DgG7pWm].LENM73`c\?r,A!o-1q"j*J1kla4_dM^7.QNsb93=]T=UMFZK*nQ\K2TNkUXI.SS61*;P\W-T-7=ZD&rb:J:_%;00"Mo\b@[DIe$@/mgrD_u<153*@8\X6G^N:q5RpFUi1cHeZV^L%-Z'eo+tt7Y^sqDr?TPH.-@bAdetc(:U?][/hHcMb31npUX0?[\P()9#RtNP*RaVY9tZrp#OO/]B18S#=:m0c.@`hjH)%q\S'B:r#%_?l9=J':I3%L3aYnQq5J>\@`ZBH?S7jH8Mn7sHjI19R0`*GZ6"QV6Wl36o(nGRY9+e*]-3$M3*!eDSi?>cO-GB!@^pHCZS?;R]R"t^cEd5J:C).M=#c[2\$gtM&f]t%Oj$E_UrKX!kEZP).tTk1;6fP@UheQDtf9sm$_B;2A+BB:J/C3_3ias^<3*>\'2>kq/*Wdj5$DKK7=D8QKF7QHSdFHe3:&%57-T;j(nSHq_`PrHOmQ:3D6<)I@#_NN)Hqjg+9imiT-",Sg)mmg]gULKSe%s;a;i$bGFp2p-*iP>%89SI@5jFm4DCB$.WemZbrLo!58n:nHhjgIYjTl?ahf$*TUYnqj5Kbegg1\;%$t\kI5$isBKnth7i9ut$GTtIO&*1;*q&D':-P7+a#^,sI09N>`G!CN[&)Ohe)$<9A$V`s7@`9&+N9Y/r\g@@-bGW+0o;0mWL2t09-"\;(Wh6DH]MCW_U;!QACttULi;?AG@L8.14QkT4HCQ[[^e_QicK@SQSRf[XV_K$o3GM9L`#Vk8LGccKFt:1&G*B3;Smh(ijtGtMCR&.WK.6@2;5N/]F-R@b*n6hB4ii,*s8IJT7g_endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1151 +>> +stream +Gb!$FCQ$q,'SaBcH[cMBOB9\&bbnh,8rfa_lU`#6V(M?WL(3!:B8D?0%:_5iS.k0I=TummNFd.'&#lV],'sJ]88K?;JF`<(=rpOhIul%^0fckr4d+Y+<]tNghM_1B\i;pj:RQn/-1f$!C$,71o[H$9:TAVgs!a&bXB5,0KCo"kg4X)+*i6.j`+P2oFioQaTVC6a79US"iR,4Ag-=gT&ohc=B$gl3%A$VuS&LLljXBOFs-h5+)W0H:ogoF@)1N-$ff:B"a'@r$8P2S3W0m`Mo"\W9\J)kHdW\UCj)^Z$R1i#A_.4ZD5?Vj(pBDMjuc&RVLjGjLL/(@f<,aj.Tn^Dm=M@-,1?758(^*Y+*FP'j]G"=mc:"iNPU]%]^:%-rBbh)QD6La2*#VE.jG6s5aTJh:4,Y@-6Q,>T$R&/*c_[r^$e;9FYAendstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1140 +>> +stream +Gb!#[?#SIU'Re<2\1gap*5+T/>k^WZtcn0]NpV9Ccbt]H?P3Ug;rU7@o?,qgI'ihOl&8XVCQTU%)kC/4PL_oU]70E$o"cJuZ&.5HF80#RP\q/J6ZbOf,hD<=u91Y0-b8aTV!LJnc0"A(SX)Dr!$7'`jK`9D8R(kO[1sGM'a"U:Cd/$]_^Q+H2p/aO[0XPN[P-cA8.Q"5a)bO"_jRV/4#$h_h@G3rYY/X*:?r#bIWFD@leMc]&_:s9(;C\N,lKl#6,U$#6K)cMHpMN,_.g?@`W:4PdH5NIg`jh-0n@Bg(krLpaC5*9n]AEr1]ib"foU,bR,Z4FD\(c*Q?4C7(gV$Z*G&R$P.'T(30kQ)jEaAd4T\j,VM[HPeX[dT51Pi=U)aTEP&_YdaNBPkO(3ri.Jk%^74!q9(NE]K4I9bG;$uHQRq`bBm7JU\jIsF$0PEL@ci;?q\CNm.g)f'.oectl!tJdM^QAJWMZfna?,5o!:B!FV`k"6kH^=D'Qb3t/i?eM52e`g<9+qKek25qht,+[)26.GoO]A?pmGGbLR\bL3j+1Fd"*+#E\`bk?QP:)!J`0ZJ5BY@VZ&1k7RfFR.UK>O_)tFK2!:30dOnZGN3=\u[Af=9B!Gdc->$(H#6i"VrDD"tYepKT^^,U!([LrDQp>a@6h=nO-2T)83_J%Uc@HFaICW>UVoSCLmflB8$RHF0Al%Ph\Do6e+e2[M^25:qi?h>4LN$jKs[Rb:g-^UBFendstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1117 +>> +stream +Gb!#[?#Q3''Re<2\?])U>t)O;T?^Y!C*cO?WnmHPmDBVBHb(ok1=5\Dl@7\QKBkd=BLC3+ZA]39\EEX+m_'#0%mRuRdh:Tb't>n'&.5HX8DjWTH3Gs&B:mMkIV#$7*"jVj((&iK!RCtMoblUZ%d>Z5fr"=V.V]U@W<5e]WcD>5RY*$ARKM$-f8qJMMfht'=t'1d)7,Y]IIQ6d-]!Ne/)f)L?YQM3<\7iK;6qf&Y?7.c6_2IaqC43hiCq!1a+jgY64%HW0H><@+\]T"SPI4'>W!%l'NL`UtB/Y_bA1gm`rn!+r>tB,C'?Eu!W1G@oE;6C#&sek#=b=.0l1o=JdY;/jWLDO,!@"M-1:X]usOegW-9;R2eb@UIG':?@S-rljI&h;k-5&*H*DAZkN_52=?^?k:3Vl%@2^;f>WH0_fOd\gY$)?[JC/3Q>Do#KPU/`SMd15Q`[IDQq'Ibi!E"US?g)ZU7$>g=["K%.7'K((eQ,8\Z$E$b>+i#NJ/\==$4VQCYbmqon[\/O,XqX5("f5%\r*k<,k(PYB.:^[.^DYV3Q>Q7<;NHQ4D$UPXXV;tC]`#q\ke/5=H!-r8Q1StT8b;'FL'J,_%a%Fc>j5o?Fga`VpXrQ)\!2*NAR?Eb((WPJQRePtSOG`*_ldma0WF3tZ$h7a*$>n,MrG2LmpRY4J[?o7SLY/+d>I\4Gi37pH00\,s#_>Ie0"0]:_Ze:p.9%Kn9bZAn$KDu\#ntrkka7,AW&,D)6P/0sg+)>Co('X'Fp+euum3ZRi>*H/uI\0=SE?8[DPJEYYTYH2/;"#_fR7Le3/,Q+79uruA&j,I>B[FtUgXsjR?)=]$7nL$?FcEB$A^*m'Tu-QtV/Z,m)-@endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1216 +>> +stream +Gb!#\9lK#^&A@7.e7AedJ[#M':1c8:A7q]/)/V96]8'r-4f1n6_JQa;-BgmrpT8=C4sFf^:C\mJJF0N6WaEI=_?6,Wc[:I%^eFg"0-5@D#U8ba:(Mr'p`,h&F69T/%Xf2f4id:MI>X[6']Nt+-n[F*pOq!!cdb"X\`=HnpIn7:2T;_<#bH)ae"R/pCr+Oro!pNZJmUD$+*?m+?X2;?F+Gbc&_n^s"8(HhY`cIW[,enpiqX"4E:jR50TcU=LJGVE\WuO<[b#G(%5';W&p$0R39Ugfl1SD/jp_/RGM&fUp/?-WasPeJ?=oaUo/;dFL"[-;,TXYgo_cnk5]cqq+>HK!b`oud"-`)QkkZoCf7j4#X3IGc0>Q2H^>g0h:'UhAUV'MB43qWWguRufOU<.lKrP;LaAO!,VQcnHI?#K['s&O@8IQ'-)`9glNEm;13a[41UgdVa2nAk.nYK5E.)6q)G0is\<$H(4NR[8&7o+s6)1s1BT@ilUr]XsDKEEcAkeBPl5Sn)f,h%Z$.q_"EO52&#q^%i18j/u//70po:iTMOEj%u*N>Ae1/`m'k]1s@$^YRt\\uGn==%?;JfFhU?@ta-eK?6!XBc"cC?\>&_\k5?Q)g"o&oH5I7@',^7Oc5Y=iJb,b_,ZE%7.-0MPUa*^o-`g1P/Q4GdX7mO.X'OH:\A@>")+r_XAc?,QR=ndce.Ou1a4t82_'!pjVU&L2_N3^1eJ$F-80O-CrWA>X-XGkLjH;X!Bk(pimI(/64cHq=A$UeCk"tJJgcXeQC+aoendstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1257 +>> +stream +Gb!;d>Ar4d'Ro4H*,/CRh:1)A!:cAX[Pr'!8=L&hqngNa+2D0/L5s:uCukW1B8fOm_$267aco0oE>afdiV3U,ffa6p^CKj*'kmTIQDQfA5Jp(!n@sDEK]a=kL+B(>0rM"#E@ESLtk#/!;GV:6aM-$JfRS-m)1))K/H,kLj9jHm"nVEU'L\rr#(&BJ%TjQ.-0U"%L56?d1r+OSB.;YRm2mn3XKX?>SdQ0j!8N:F$;ERJr;k`.=$HcO0BgW,K^XB0LL8$(>$oceHPSbngni<](L0pX"1p]qP/]oR(VVHVe?IbrAi%`2`oYr-f@(?)r0mJE>!.\*Wu;jTkS>?nIE5/*J[>+OUH_`Sge@t(O6-Ef@V@Z/ZnOl"ZE:nk-lMg.gu11R\jcCS.LKS,k;A_t6:0H,padjaIEg.h>_Ng6k!5U00V_57hD7D95])?_DfQmAG^,tepD[)f=:4S_c^9bl">2fKsinr#i?>(d6P(PhP1Xk)MHYZI7$qg1.S51NF&kM)AO.Fg5YnQ>,I$uB`Xcl\\-A-6%sckQqL49Yk=AQdnRGl`tqViZk`;.?1=@+**>6Lk!+\C24=b-6"hBUH576b99_r2h5YA_Yu;OljucYTVJ()!d[]!`<+77&FqOWbL(?V<)8o[mV,P@EF+O._87d2FU=MP26MA7/UUP)`d$716-ei!ZaTbNN3,2.IPb1Mo/MJH@H8>r_('odu;bXl^>.c[M+d5T?h!P5h:r)Vnq%"ctkQNELl^c2RqcP9@f,W8't9BVTt0Rm!GQ.&GGo-]O)#F+M\jf,6_BkVqY2n]uJrV-V:LsgQSH3:JQ-2l!)&GS3anK!3:H\dl[ESmg^uE:7:`35@Ec.e(YjMjZ6`r8P86fGQ;sOM`=0Ijendstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 634 +>> +stream +Gb!$D;/_pX&BE]".IN>dJRF+]Zqm+@8Wc&JPBcGPB2%:pgR2oep=o%d/PVRd8LRIa.gY5rhs^R=`t1d\Ol7cH_#"J)*siJc<!B[e9r0=Y?*V5p#'[lu4b".$!PQD]fYG.)I@\p/BHrca1HR9Z5qAY>qdT=Qp/'FoLUCs^u,mAOK(*FL\O%A@[.R3ZjioU^t[b-c+*.=t&4AHMl+=4O>?ZkV(O$lJ4VJauh:s4StVo=)&-?BTC'b4E0P+75>b!e%KX,u_G[/[]^scq=:Se-b@gh2aa?nD#9J.kYYC=4no413R))I8GB2]j-F1YMc4skm?TmJ9SC.+Lp&q&)>[].Z^t-+1"\j2`):%cPh_=ku4dUoC1hAde?1E1IT9VXcH(5BMB4acs-"9JjK1C!KgA'-W>gpr9Z4fMJgI"g0!dJ,~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 921 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D,fTWR]-AeJ]BU4\0h.D4e:$GQ][)b\e[.*Vg^QVjm+[E3C*3Lr5C8g,"p,<1X')a`_ue7acG]KiqBfN4J/L"aG/3=u?sCFl8TF")24oF94o$2r]g*2A9O"(ek/`iecA'!2[ogsUIIqeBDpTf.;]77CiY'?/1a(jU#.$N-!/]`[uEuA)*".kqlZ$bZl<4JRoEP-O]I]ON5a,3\V]JjJlb&"r6tcd12-/kqTWU1u9&,Atai1$lLZD99jZ9g)G!g8TG*-o)'>Ai^MZ)ZZ.HW`h%L-N-UIbmg#,V[thjqS;/Z-/aj:Ck!JV?&'%A4j]])4e#.mS4qFIbJaYI[96tn[\@:.B#G[Iqn:1pVok%8^W`Q)1LNOo*StR_oZnghgYURaAL`'koNr3u,#AuOn2V=TROVUTO.W3kPHs>.t!Fdf7m4B[.e[%BsiD"mZrakhaendstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1056 +>> +stream +Gasan@;jjj&H/2-1#GU(Pf.8M.&WZ$Jt!B!KJUoE:8L!'l`me`HIptYPG"rU]sI$4Orbn]_AIX^]f0leg(>=Q-ON@M!k_=fi'RXp&YqETa5(5r0-F$a^?nA`Q+]BRNo+sUrO74?TGr[FL+2hp2eqYX5]cE>3_pa)_C+FW?3s.[gahYp_TgH0+o+46Xl$%u1&)e]aFm91HNc>+`5JIsM3l3[uZb=Z6#atY9NK!SWk#W\/TlD6amRUqFQ(IB=9<`P4rS-c]3U&T;1/mM1AEAC0_-_p4m%#3A*&l2DmrB![49:.&-mk<\D=m04:D=g\T"QPG?LjULJ6&\E/iGJdR.<>uYZ@h%Sc_FeWVV:i`-DB5%>%_U0.&5\*dY_]hg_'XP[<.#gJ3cgeX<]&_?>f::"igmS-$(BQ]]@1_5V22f19!qaT9iL*H5]0\PS\rMQ@;GS(57Tr@^c50Og%oR)K%]$ed3lg;_^pq!:---(f:3N$[kJ+9&91a#]R[UIi7EL.=F;B8K%i>*)?1E0%l[b:-Mj59nY_BbN!G6^L;*8\7!f%c8Ch/LWfADR!_fo03SOAt%CSTb-1kPK/,1-Cj,nEKQDmR!mU7Rdn2B@>cQ`Ft2g"&QCi]*j*F,3LWZpe?,WeE40u@698'VhU3LRW_H!+NVdREjhY1`:/bQT0i2D+VV:n'Wo\lBPl/#%JTY6UAKH;[!RJPEjL*;l;eW0i5LI2*IdpIh@W?U!d6X#!6pq^o5#j[Z+!E^-Z4ZN.6)JYFNlB.Q>lG9KtX+X_GqE~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 715 +>> +stream +Gatm9@;jjR&H0nX\8T091;YN6R@)Jm@7)N/&b@U&j>mNj$[-,$.%9kek9N;AUCHK<.hJ4tcgU;Y"W*VN\bRUW!dl?a^@-[.!\slPb..Ro$N[7)Wjo[^:)C'=Vq\oQZn9-YYRpQEdV`:MdNUJPcIC(*Re]j&!:nEQ[s$N6R-TtT[YS[@+?uOm49'WFSV3JLMB5ao!V*pR&#[,`KOM:Y1+&jP7+0_?V-J)k0*hM+A46*O-#p^Ufau\1.B0%&PUQR(7"`VBDK9`c\Y(n(o$&7h=0:T"?oYk0L;A]$OMT`Y`]&PRP>R\lp2NT%';WjfL`3usnDuEj!el3PW"h*=L#-l@7;f"*;iNJ8$"g[]1]b&*CY3U4J;'4PookRI=GSD+e=ZsNL.Z-h8$bJq0HC-.0dLebfbr^UR3oGf"BqV`g17[lOt#%lE\W%F3QX+&TGdSS8V2-'auGaJ&WdBQC.9)X0_;hN(+7UJcC@OcWb%XkTN@an*AH]2^i]\4O/2.p$.*#`!Y88]tX0B=U>@>endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 769 +>> +stream +GatU0>u03/'Rf.GS2\TD8qRt79h_9'N+rMWRZ3ZH)!@bN,YkT"Z>/*Chi4,!FUdG@ZBW;Q]uTjeTBcIt*eAg`*9`)9\-NWc,"rOf[>tlZ0ar8tG(Mc\H\0_>I<'A^4m!1P_(!2.b4.3!k+#T9H)+2heFCH#JFFR4+4eUeqGEDt;(F:8MJTZOG"%GrPUK7Ge;Er`mNHuQ$YO7$4!Qn0BoV]:ODnaI<9U:2Gn]J0s8C*+s26DDEgLe+N%E&;_VdF#NJ*fqQ(DDacgEuM?##4R$-k`nkOoMu%PZ&KN,m@LL:*2O0WKXJlPTF^3,HNM;J[A]dD$P-EBF(^)W%0;3UD55O/AV3D\1oo*a!nlB_79nZ'G+R)KZ[8],2*Efb0aq:^gLfAYGNn?,L$'NeMjKOjlF:Z2a<#%if:dBWDu4?9*Eq6%U8i$C"Kud6[X)(>+p.4?"++VG4KUEF_(SETW9>u]]r9pYlK$6dLI;kOki]cCJ&T9/GH=&\llK[LMP>QRE4s!L,pAt_TCG'crQuZQ66qL(:915)ZU"4l*/!LDn$-Ls^\(.g*.5G=DKT$GNM$H\^P00C<3*jb@KFP3"XH8LW220ItBgmBV7nR6qoNnWt@(5sigc+k:D+F6NakJDPhV\:KGjhcPCeq+um8eGS5WFendstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 715 +>> +stream +Gat$u9lo#B&A@Zcp1QK=@$1i'SK8Ct$kp?Ibb7u0TZCnFCJ.Wi8Mcq8pTEkY3/nU"dFd#@qqgaf/(o[f%DR/Z%,`=_p;dKR$Xj,9C$QJM.0O)>B>_KFm.J1Z3GJ0`n,%d2%>+A)=jFT!#W"e.>f"p09V#YV%7']CQFln7T%1=>]*[Hj9'ebc#45Bp=NF3)iAjBPO"UUFP/`)CPG]0[!P;dW!o&P49@LsD$E&8=Am+2[$qK@HJ2>BX&:(4^dS]TNJq>3;!H9k]+sb_6uVfIiBeq.=LYo\rRo.c3UP@79U53uAGQDbIn1F>-!&?k]ML2-\V*,jp4HE]:5.qIGPS6<*eW,g+H'NXHgkt9SRgSL:2ZmE5I@A\Qo^m3[MG,.@,\HJa&`Y+W$!n5f^]=X`X[Up;A.H:qIUK<`%5a\8N>0>aO0?4g&5)6Cqtg>geG&5=-.QE?n=bWbRoUC*C,1!Tmsc/eN;m5(gu@&cn1NC#cb?3]YL?X\qAUrM87YJM89;5dH:!*ghSPACD$f+mrs[[E<()[(n`H8>W;sEOHfpCtSi5G?n7)M@Uj+s*ggGNBcdIQ1+~>endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 364 +>> +stream +GasJL6#V??&;BTNMKbjZ+A7\<[oK[VTodFjcm+65BQ^S3C&79[$Y#oe2Nqr(4)`u'1CQ/Fle^t./-R@>#3J/b?rLhJ&],@(Vnk".\Vn#i@(G^BV%,!-?/`.HW0^fW*9oYJQNK.p?B2.Ybf!kF+HF5SpTWe306uPQip@C[EO6#n?aa4kmi^I1mU>[BLTa:2$m1/n9JOPlfaZ5o6:9sJ_B-\I-j)0IW.lA,QEAA7R=!bSDZ!cpq5#$qU3\H"n1WRb]D2DPrUC)RIKRH(V$Bju%8rJZ^Dfc`R]T_7qGA8o`:6i""kBe7"t!2ET2g[#QL]oKrSiP$"6W74`r~>endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 300 +>> +stream +Gar'#_/@+D&4H!_ME.OsKPVQl^s.NT+[p+'IGnicD@7(sYh_\H^:#Jh<%I?IG380'E^(7^If`XPZOMHmLj)[`Pn5McOdm*]]pr/kQVUaa/Lp5Y666=%Oa&P8ik4gBUC,@hLaqs,Pk([egQrCA71*bAmWSXU_)6'lhoVE+k#E-^fUXq56AMIqT0<64(SK%lK#+/WSClhCYp:[d*g)uq=PjDa',X3X-?j-~>endstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 385 +>> +stream +GasJLb>,r/&4Q?hMRs9>PrM`[g0LY/<%//k@hr>gB*q+R2)^0Zof2A,PQb_G9@c5NR:-A;0_`]s\ECAM?sk/Q#&H79Ju;/L\+SCYEZALM]Gj8d,dJFK&\(7'in7X]*bQEB4":@PoqTBs+6;V,N6`S%0K,CE]4"f*-*&m=1$?Y.6_)-[3hPS:i,@Q*4a:]$&g">#n-`j\1OJfe5Rr,28IrPq]i2C1>`3X+Q(C$u>M.L&=>YbIUI=A5>%%h^[73H:UnIji[\Q5,!?ib'NK#DZ&,m1_9ud3>M]L,d&ihN%k:K95;:$8$]*DWXJRO&07J3R[koendstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 344 +>> +stream +GasJLc#/.f&;9L7`>iS&'Y@3bgaKZFOp*]4TncrNihBDj[)T5t\$'fC7j>?EaTq:Ym'fV!g*5rjmskXo]12oh+^RHH_$kpJ$1GbVHY!m9UA$qn04O7ONR0P)lWGl$`_l'WfdmIc+1#W?-M]0XM4uIc8=gs+$Y36dQ5/S!$!-22QmQ+`\"O0)V%]*(^XQn?ZF=h05F>?u#;iDj;3%Wi#Y7[R9&/\mm^h,C1M1"OW^9_oY"d#bC`gEX]VsUgI"YXZW(W>Dc@VFTe$PhWRuMAtgc%-3'8/"d4@1G!Xq$,INsgpLf9U".U!fU&~>endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 484 +>> +stream +GarW5>u/D6hD@a@mKpN?X)M.tCrT(h9e.0n`NhV8@T3SN)5Z3q)R\RTgs-@:>aDA>3Oqd?R'Cn!/hqgS^buXH<\(eV]L6RH)`>$=\_.:RirOA3Nr%f(i4rg&)Do.FfJdpYX?o#)`/f"9~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 387 +>> +stream +GarW4:N(hM'ZBHfME0B;g0IZCDF1T_5t0R%P?oY"/M2J3Jio`:B^-!(KlHl.`-2d]&GI*VgKea:6r37IBSL?QU`5>]fQbdWgcV$00GAR=c^8P21PqQk3(Ed*/]X%W(k\8B-eX&de?5n^4CaYugI(Lu%ZN0R-#\nF#JO*O?RA=ZWI."\Mj=PpcbI8&AU2/*?^"3I&Oendstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 852 +>> +stream +GasamgMY_1&:N^lk+r\I(%m7pYhB=L87K[N'K`=VGhL^Wfub,:]2$9$GLdQa%]#A$5BtMuR5nnlFjTX*Mf4s_9EP!8X+P:TYQ91!+$ec$/Ej`goEmSu_/NfU8#,S[,OdrK%f!JbZ2,Ua"t#_[!<&BZASBDqnBIW'd%[9\.=\5'70cOTAUpi5dFfFPF&nf>IM_/BTC/,l19SCCr,XrB6g:n-T?K(:gT8!Ao#:U=eam;C@h/U/%/+]u=0J0jhE^`7lt8/*)NX7p9u=$[_%dJk-t&AG!Hl,08Ghh#W<]/n]hJRc7[/C:T8B^^m>5['1I=YF!1m72GYpKbB\c@YSr5Q1f]:80$&W5K2;cr.#-i-U%?)ZS7/%nTHd=H!m/*SH"7P'AXI\?$JbZH7>XdZCI7S.0:KD&PcLac:#;1f50gPX[KEO(Tn\3P%hr$`_aOSq.T7qI#7dMMDbj%7>JHTW7]QPKMW>(FZ9eNjkDQ^,'bAn;#+uW(eX%HtF!caZ2N5HV67Eh/FP`cO5,+\E`tojaJYmqP(25Hkq`VRV!08\j>;3ma3dDc443.`Fj,8,T!cMD'!.F!f/sE7pb!mk;Vt-p2VHfLJ(];_2j=]+7H5`c`;BM@,7*M=VU0CB"PGkpMnk]e[DP&%uIR2L^LRb)\]NGq+0Jt%l\Yc?`qtn1U:)K4EUQ(Zukendstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 620 +>> +stream +GasJO:NN!Z&B4,;'RRq1mD2*,WW/N*Jih2$>fXoKoqK7UV#cEFOGpr&,T/;Ej)u9Lm+ZsW[h8gKr=JjcF+?9)qZR#[!SmbooERXJ&CB:k*iYFB&I\mTrR#:@dN,pWg4J,SF>%@Kl,Hthnpl*DUHI-:Eh^@IiK"]b&l*r]&Ihh!+^?TWZ\WM-52C)XGRB$[4G?"P00oO;rG(\kolCmW0^_CiF7pY[j)#?n`rrP:d)6'BU+0T6AdEI7lnoCD**s,ZA-\>4CMHpY]8XMrM[Y@pBCRMC"PR`N!S=>IRY;Hgr1>CYMt6@5"Vi?,NXB.+Tk&M?^ghkAfBUS,6?@O:(P3kbD,\UO-aMJl>Flo/T-O\"`a5r+(&X@Cn:Fl@#ieOS2<6.X29MJO3TDi#9.nTX(7m%BR<^Tb:oR]PhSqTlLghP#mYH'_grgDGNgRh4d@jI'3JR8"8i%Zo2\.R/M0F3WS&.c_g0'As.G0K7-aoljCg1RjYB(,1hd1Fj[b:]ZAGblV)RInMbKR^?K%uNNC>ig3HVa,mioVNjubendstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 560 +>> +stream +GasbV?Z2Df'ZJu$.IPBTFD@bX$/s37RK\\-^c)*gBeP:PPa:7OGal-;5MK",\nRUp!;W4-cd134+SnD$Y"eu+$uTMWUqlC!f?P::$@B5V]"h2-#N/P4$%akX%UC3c+R=aTima!'k=PEBJ/csq'%:Ptlut#&1I1jL62WahfKOWeLHNc/KY<.#8b]:?]9W1u!IFtC(7*]kS)+lOn[tN753_53aU@9&(F4gTTU7=-!t[1Pce,I4ib[2o;V&K^&51D"hAmbW>2Db-e]u+e/C>:+I5mSD;d&]l/#ju[Ynp[KkZnE:6JHUp#:j9.M9E9j>h[/VUZ$A1W<]_Qh5XlVijU2AB^'M@EXWi>u;1eajRKuoLHmWu70CC`@&arm6MHW#@SZI3i@<"XeWj1Ta"fRE!](LIS>o8B++*dtGW0u7*>aL)C\67/'k2-sotr!(-:q8E~>endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 909 +>> +stream +Gatn#9lo#B&;KZL'mo0RBhMof-P0','MS"\&.7j$#;3l"YSp_d,WQP/lanoZ$07k:NlN2Fd]VGThN_Ack]3_:S-+/"i4SN1gONrb_e9$IGT@41;/cli+,E*b!C,gp+i8:QT8@ftGLN[;[m^_W)B>ed.hlaYP\C9PLEK*p6kQV1K"@%q7VB+M>A8'BNS,c1.A3`OiA&NKcSO(9U^Btae#KIngfB>F+"bCtie:Z3aYZ1(NNGId;B^DiDg#=GfLH/"n=1@i+Q>EXPU2TkdKcfsA3$X%0=es$Z43df%t.TeeLg/[HFN!CQHsOrK'U"0-*pC*?U&7#\oL!]f;Xd(R9j5/*m)*>PL-?u/G(bq[$;2.'O3f2@uX6gm`A@:!JHBe>Q,)Ib,u-+!LW.5NTB#6jJ(.P.CXoL;BPOVJSS(f]K;ihdiar!@pZAofL"^*N97$)9.+)=iU[aFS%kj[1X(M(n262*rO%/1J'R^[5.0iRBNnf6usn`lWTdV_gS2ku?>;@!e.5'oHYDbipCN3E(.uI6ThTpjs&RZdIBTWItbE=RP!YmX"7X2nCat'W*98aeS9tOsjG!,`5L,SPNV6+"M_q8%cFlH++"^0;pd[+P4u@PB=$lUfcAfC>3]JY#.>%[bJe)N6CLFUt\d2T^Fg8^$Y_*os#\[X%'-?AB>0t%o-4+P$RkF-OhGQ!C8Hu_u~>endstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 785 +>> +stream +GasJP;/b/B'SYH?(&)8P>I?@![%YlR$;IQnV/25gHg$@o2rL[?;qn!T^OFd0RR.0W&P0i(kC3/1)[6=+b^X7/^bCJK)[7jH1^DSrm6c118_SISY\%N)J10cT%L/7%;U@bg(\G"#>1VD]Ub'S;"Erb:_SA0SB?;R8Rlg[\pG!qCIaZR')CCO0BJN=pE-7?ke$"l4L%H=+Voa':]=WK9HU/Xdkh0D/%5,+lFqAuD1UpcZCQcJq]^\=4Lq1rYG*Q:]0Li*3AmhElP&"KjN."tRLDMuSpNa75Ng.a;X\i8H1oO!j9:cI%fr+4$Ypb48BFH%`:>tr\YBlKOc@b%cn+pK:.m\",oJBlY^rTf+'6f4D<"L8IlDnOW)nLOF2nWo*)&.m1;mYSApm&NBL$^FRK]TSZ0UtQ!'gA+kg@9KLB;U87F4N8T)s5_M_H^dC%H5E_C1aMccF5ONZ?%OaR.%)=UNT+@kkE\'Sk7POW;#03=F?,Y'e$%t:fR]gBGh>r6mBc!MT8rW>$%V>U~>endstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 601 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW4(_);Q5g4'F(lQm*]HZP^f<.*[Xa!r?6i%^H$UKFF*cG5'K"CpK[endstream +endobj +91 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 864 +>> +stream +Gas2Hd;R_m&B^lp062^U'U;eujm^+Rs[5rB?j1+lY!^T<\Il2M9KE(ucmdjq,!@D4'.r?rhWW`S6ZK/p,gL7^m`lAHfi)_@'Ps=<##?@q!3MRLl+g;U*9!W_Wlufl2>Zoe599E"A-uIlnVYm]Lm8nJ%k87\ei$rYT7.0`0jhJ+@_ihMs5^bRZg?EH(Tqhep(On,:r_e8K:8'9o@B:oD/ZUFf0?U(F[AQ2s-^]Xtq&QhjcgH>bZ0Z=_u^r2-=RKT-]ko'spcs-r^QMAcmcVR3VIm+;%XGYUD$mZ3#`^]MRf+PV+Hk9.m__gQcG0@#>Go&s10G'LjTc8EiPSMB'b.O.Ds"J3KZ>AQr?2Q>9ltP,T$c1(mN(q^2(cWbH(dSN*DH^)N43UuIRbr'l)1,c(gmL#f[%W_>"MPEM.:PTd71"N$X2&n\)E=s>r5*X(UN$="Hp3lmt\VS#)]7Th3GD*Y2YYKc"cd]#S3@8U?)/)iR_D'0'f_t6)uKM:-[NkP^.VHP1#"WlUi65&P2;l&jek@8PPk(se_85tsO59tqZg@;k)[M,5i?soNrEb.&j%o<((4N?/T8_gtAT1hg&IJbcc7nVJG_g.&"*?L0Hi]Rhl`\7m1I@neMV,JXQ71nTQn+-\DCJnTm&'c)LKJS8+_,1T/?#6.p]AH^g/U4HkSpendstream +endobj +92 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1446 +>> +stream +GasIg?$G!^&:Mm.R$TskDB3JU:^Ctg+hMhf8V?c>0>^b+-+;l*15,W!4!P^)R*Zf_`3D.+GNN3\!$=FVqi,WHD]sM=%3QKQp^"]Irt<0Pbeg]QZ_6/8)T1e0U-B]+NR7eDI(,c41UIT0GA*A=WrW?1ajn0S8%mGh)U=[6+LmfS_sDjJ&AiPbA%MGZKl91Ap]TQJ'^d>thLljWY$*"+7_3WF.-3l4dAMft[%MW!0QA7@JSkueUMheZ3CG>M1f(Y=@`-%Q.$Yuc))01Cmh9nqF[#iDDYb&pW*XcR?0Pe5+6:l9[[T;G36pr.O#IWMN/t+t#>'D1=b&G$+&N=[2UJtW=[aZ:+Sh!ssRO6$Xfp!IsRFp"KpJj889&ii[Ng4UP1)[W1?ko'7.$V/JY\LT^RBSbcShhNAId;3+(MXK:!V"sGb]BY*K[[&b0c"Z`"2+@Y(l]Y;(,NH8)&5RGs2X.+>RVS7m;34S\\ioScqbc$H2^m[ZZE\9=B"@j^sA1SoN.1'BJA_4^B@hpW>=&BG]$33mcQ9mFf&,9DO3-j2>ZYnl"k-42a0lQCXma]l9?_-NuFY.\4.'S/QUrHSG(V6Uap`pT044_Fe_YGM-n,\!sH@<#Pf-p\:LUNM329*WLsta;T9cZ=nM&%W)=Op2NQReHQ\QK>`IP]EMjJ_G/SAF0h5Cel!(@BO^f0pl+RmSX;*iAb#Q?p?Q&75cF?#^XdQ27lhl-`i,onFNlA\qfPKfg1rQ"$QZrMG%A*?_69pJ7hohcrpq/-dKUh-G"oX?P:5AS+)YRPV=gdB1/clRP:4j]r(r.4fr/6Eh4a">B=,:,W*l?+4qo(+V_)[N?Mg%o^Bendstream +endobj +xref +0 93 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002103 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003011 00000 n +0000003217 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007543 00000 n +0000007749 00000 n +0000007955 00000 n +0000008161 00000 n +0000008367 00000 n +0000008573 00000 n +0000008779 00000 n +0000008985 00000 n +0000009191 00000 n +0000009261 00000 n +0000009545 00000 n +0000009900 00000 n +0000010486 00000 n +0000011149 00000 n +0000013727 00000 n +0000014659 00000 n +0000015982 00000 n +0000016303 00000 n +0000017393 00000 n +0000017884 00000 n +0000019792 00000 n +0000021593 00000 n +0000022889 00000 n +0000023154 00000 n +0000023809 00000 n +0000024556 00000 n +0000026907 00000 n +0000028150 00000 n +0000029382 00000 n +0000030591 00000 n +0000031899 00000 n +0000033248 00000 n +0000033973 00000 n +0000034985 00000 n +0000035413 00000 n +0000036561 00000 n +0000037367 00000 n +0000038227 00000 n +0000039033 00000 n +0000039488 00000 n +0000039879 00000 n +0000040355 00000 n +0000040790 00000 n +0000041118 00000 n +0000041693 00000 n +0000042171 00000 n +0000043114 00000 n +0000043825 00000 n +0000044476 00000 n +0000045476 00000 n +0000046352 00000 n +0000047044 00000 n +0000047999 00000 n +trailer +<< +/ID +[<42df5225d6ba5750a9c3961007186308><42df5225d6ba5750a9c3961007186308>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 49 0 R +/Root 48 0 R +/Size 93 +>> +startxref +49537 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251031_085459_analysis.pdf b/ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251031_085459_analysis.pdf new file mode 100644 index 0000000..e8df692 --- /dev/null +++ b/ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251031_085459_analysis.pdf @@ -0,0 +1,888 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 12 0 R /F4 17 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 52 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 53 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 54 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +13 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +18 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 91 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 92 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/Contents 93 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +48 0 obj +<< +/Contents 94 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 51 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +49 0 obj +<< +/PageMode /UseNone /Pages 51 0 R /Type /Catalog +>> +endobj +50 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031085705+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031085705+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +51 0 obj +<< +/Count 43 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 13 0 R 14 0 R + 15 0 R 16 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R + 46 0 R 47 0 R 48 0 R ] /Type /Pages +>> +endobj +52 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 504 +>> +stream +GatUnbtd:Q'LqhFMRtF7+jG.=a'fdA#:`$W,Sh#nb+p)A)3P3Y!qkr#U;HCuYlIqL,599YF0:-,qLdh7C&s>@b^L]X!VlsS%UtO_+QVU4K"GR1+i-"n4QZPM56qf6(+0Y))Z"XYj,>5tbjE?8iCcBA6+4Lt!/ZJO6AB5c5oN2IcfH(BoDIUR&8,HT0!5=f$Rir)?7obp>T\Lo$h=OA*jCmqo%>c[^Fg>aQn.6=jq'lu0LBuk*ri]6D\O&eYOHuT-a2mn3Xc?TJe'%B%O0kVbUlKrh/@,i2J.:mU5YQ]1K0[O[\##3<)r8WTc'$"hPbqHeh#em#oP&RC,O=5`2Qjr,4j6`#">,PSLCg7Dc](J_r'FjROQYIM]D80^Xo1dsY?0fco%iV7HlE7,9*G!`9CKoW*G>Ku=!pEt@AH~>endstream +endobj +53 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 560 +>> +stream +Gaua;;/ao;'SYHA/+*dC!N"GJ)^i:8V3%?@7i-NU%ii!j4S`&p6OYg%B0-alZY\=C*TqB:j'J!rE>k[4f`iH^\FlCi;+YGln#!MHVuYP'=*H:\kkl2eG9JGoQIf,&&A^fQH!bql\pj2_IF"]qfI=bEdEQ[he9(-O`Yhg._6#VD#E18BRD;BV%T8>HF@e#0iiS6dYUi%500sH'@$sHm?+'*#+t8'W=WM'IO)p;o`X(V]f;1+55\j+i"oj$Mei~>endstream +endobj +54 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2336 +>> +stream +Gat=,?$"`@&q/*0kh7ED1)Stg5MR_^Ztlra==!>ehf@8l+:Vdh8Y_i=S<.*mB1>4DQse(uZ5o^fo^qCsVpE;T0"r>&1J!=>I6.2[+f@j0Jt00m)>PLtr=ApUE2o1i=*3+Wm9Eq&?f;GVkh67kqLEd\HFk6T9X%TZS-uZ)YA8;rh=_)']&QT9T+14C^,tg+AhNbsrR%B!oVbK:ao->BqX-lE^QO(7XhNu/Sp0X`rUiZ?c!U8"3mkq>jkD/_%oaif&(ER0ImaN24*s'he#P5DYjC(_4WEhQaQ_&n2Yi;fj?HC6nt0Ul0Ukg"pZC[qr2%cYZA^T9.@2mS`$g]jVhh6UZ!>A7oLe:/3Mon@o6<\3WG9'I`N^bLBHG@T3ES&!P#N,&SLZEJEZS8"A(*89/BADU%8$)WR>2tl.#,,uO;EduE#qcBP$`KrPNG!TFej^"$B6u`*`h>WZ*41LdUW,#ng-%^A6?cDd1W]nY1dr/?=bTgMO`EtPVX%oF7_L[;T-,e@N5A\6^!;'Vq)[s3a_P7br?45oWba3;V_G"ENuiJ4qEsYN+K@?05&,m%G3[@,%54T,F1e&Mtd`U=8GbAW=P9h:<<'nIRUV5ufWHq$W6pQLH_$[!iZW042\SG$j6W>R,4TYdb]'J`$>9425gmfh">g`?!`n-_nd*O6$-#FE7ELNun/sE&,/\)ta'qT[)691/4S\3Kg,Nc2`F(AL`T>g:iB)CKe[S]9nLYjK"I0//-u<+BF$O;_91I3f`;\9q:HJ%3bbCo2M4YCJtnlD&V^abG7I+`DUH2L+'@;60b$*46Q'Dku>cMbgCb]TYXN`J6N0E`HS[j>`m@rM39DlJpAY#-Q=sqYTbs)Tn-/cPK\O\TYO)c`D*r`G%61)S9MRVSeQZ>>3Zm2%;tF6M^[RGVb@/p>d,(!Z2e[:1:!-b*br$lr7:kF@(%C+'kX$3@5[(F7&SLNpH%+D,ee^p#?$stqbTGf]RDN61\>Se@Y=aO+c@$B93<>?VQE5UK,\[Y8-l3H0L)s#U^H@UUQJ3BXW.`YW0V)l.bc)W'WG)I6V3j'&t7tt/:$`$*h]o.$,&lk/>:FE2Q`U>F/=G=c)>[)a!$ZJ'aQ_0Ro1`M1lOkI5f]UAX@*,.>E->cSKBQHG7)0##@m[q99\$NrUKB,[f,T\oDI9oSbRQNi9UGfnI%&g'M971-RrS>742$C!B7k%K%U/p?d+aL=&V_kP:mc6MAq9gg(+VG'qO`,Xb%5(2lpfHnD9F_CpTk)Ctbu-Cg*K!Crq5j$G0W@l3A\Dp471/rAJqN!CC99T_G<7cacY"I=EhP:TYGLLn!T-#L,<_aqFGdCK_\,lMMT=`2"=iJ$G`LN+O&$m4Tkr.D!FX]Jnl/"8K=:?+nC`+Pm'+iL7@KZn0SBPOc+TKN^=s%O_^agD?K4)Ra*?,?et]DfiMgtIl']rA?I7"1[s`b@T'@Wof#++XOW'-((4q?JRO#h?Dl)Jp?Qj(]4UNTun^(VEosl`+k39dQ.&&V;=P%*^9uA[!#&V%H1Xc:*"GF;JW,*&eQQMBXM*&PddB*dfof'sN\_[7"ItI+;28S(e)'MrsiIV$Rs+@2YDZ6W26ne68cbd59g.lLi'a-aHrO)dB5L>[M'u7%+j[e6\SJ4lE3!X>5-fs-4CJ%3[iU"2>^4r_F3W"q*ARg32C\a`3hp4(WZMVC?\*\)2&6I:3%9!bjJ"=K)Q8[;81;OfA3TC[8P>E;i#YRDlD(0F)R!Wp`Et69[%\%U&=(*5Jg0lW>bmhLQUmYa[94+endstream +endobj +55 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1002 +>> +stream +Gat=igJZc[&;KZF'RNC^0m5knE*"G]R@skaHehQ[9rqC(N$OUAVsc9#0kO#[_g!;fc"[dHr[T?1j%5^>Z622&l0omjA45[FP,%5sdOR@S#If=rlT(H`Cj[5IkJqY6^^kGVK3\q*2X/()3*EVni[35)6op]'o\!c_(096IS_nGOl*PUjU`3VIl&?u!`h/1C7Fd-Y0J(k'[T'NN[mH=BiI4p/RYu-t0UBg!*:RkprC,sT3bW!<=F4&Ni;FhBi)_DH%gGnj.sn=-aF*Eg.YQuDcBlW1:["!Gj_YKlF@)mB!DWtR(.p*lfd-]fCHR[B`8bLpN2BD!R7;:q=d8QRU.\IdKN@ia.oXlMdbJ:]bT.?5Q/^GjZD[7b.TJlea'>;1g/p<.I9[>Hh6ZIN$b%=nbJGe"XL6UraZ5aY%m@+*ZZ:fg^a:QG42%hiZHCD;2$.gtc?X\-!#;M!P"t9nBie(rmF,:#A*8i0.P?9psNe+Qs37!Fkk"nX;oZIDdG-9goqHJS!(%4`uR^&Qp8,)Y\AiGF@3J5YR8.Z`72IkU6d)&dtgH^0O`L%\R4K)4S1M7,lm8M*0u\25m@`Z:"&NU;t/c\7pBZkZasRmBmL/2uu-Lg>,q*CC6M",P%^A163dN%[2-E'9i7`GO0gJ89VtX-r=Rh12nb_H+e@nm=p;?)TKSfEr4alPkH9d+t5.Fbf~>endstream +endobj +56 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1170 +>> +stream +Gatn&?#S^^'Sc)R/'cC3FJWF4I#u]:8lKS.5Wcode5:/>`'E%pAfWZJp=HJ]$:>,EZ>"tq+meuPI/Ni2'+@E]E;;`@!%nS*]uGRS+>^f.f)[XYJ=QRZL>QWi5'WCLp&2V.T?m\=*0BbJr@HeWBB^d"]p8i3=0,u,@\qBCoQEQQaV>5]_nU([0I6DA!!\Y'kV9^Vi8V83k2[%X@00NLIn6VSe6KXb,oQr:*/]itaZhdDniDXUMOE)rfr*V:JXb$&N=qo"Y<:h.S+f2>Kl.X5>4/XW@\UHn=4TQS%lH2'Z^6FO10PqloMKI+,+XUQII@<*]*7X:e^Xu#+CW$Cq7ruL=@fmh725/%~>endstream +endobj +57 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 85 +>> +stream +GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_H"Zg#ZYSVTjVbIXCksMB`Z`"(!*5e"T[=5%?:~>endstream +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 994 +>> +stream +Gatn&?#SFN'L:RO(&)8P>utd1HrbTf/8S:E;Nb(L`/C+r1i#XL@k.$;kG3d>5XLW;OV#Hfn&b752[0AI#L5O3"i-r>k5u-[JG0=OlY,49_!tV.>'P+bBn8je*Qt`?H&!A)f`7YRjLoe"*KbOujBMhlOj6Bl3`FdS>]2V$$,c:@g2jslD;Vsr3mbY@4de@GS?Y/gF&'OJ$f4rupVsno+*Zr2-R?`l4?ftd[X"BSMm@W0$jCk5P5UG`IrMiTP;S&@gOba.2Q9fBqXeO3(5q4Uen&kH.2RfNtY)l@gWPn-tL>YH1b;b;Gb,HVR;jO%8N11>"LXg4AW(8ePC!D_L%(Pr5mRp!tX&VeiF2+G&eFe*k/8V$T\7M+0XVg?smTJ;*(X%mH(9W3?Q=>7CW;JNIFfPgUJ5Y1;;/,(AhUU$=:!L=2;HQ[LuVp2hbNY$JqA=_YJfLR,1ZVkUm_$GR0B7=csur1JYudtBSgWG$6>(>/r=7""-5qFYUn@^1dGe6\L;.isLh4`uU\<8A&rFjiYcV;C(2_FXBkq]JR`>b=KnJTR^m:KYQR-gI.68gWo-`"S'iQLtnZh-uLD;irGd5K8(:,G3M-)-]^=hW:]**,I+TGne_>h$+g5GL_;O,\]`B.i%iB7K1bfo&jU=?+nMc2[r34\PDm'@0jns?_-cdQY@tHb%U@a\:2X4+e<,M]5#^h&(fueVu~>endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 402 +>> +stream +Gat=d9i&Vk&;KZOMYCRX4_PXn(-)DXKS11"4aL8cBs"hU\@]`Tn!t6:LO]Uca^3hbR=,3c*mqW?#tuPubQLh;@"BP3gEJUR2Y"btaKLO"AkWEt70EWD&\YO)h5K2[j=ZL)J[r0'ft37#VEIU`r';f`,O5p,'cEDO?E):Ym(!sAB!cUA*4Ka/cqS4r"YXM$Au*VXC?u_8Y#J;G?n&8RR-u8.8LDubPU`PYXY"*N:HXDsr8'G+h8)<(4]AH*P!@WiIY-"\>Sb84)F1hioL@!c/#KPE=/juWNuqf#,Y2-Q[9]go.!K#Zjtss)OE?0GiuBGrh>RM8\]S<\gsLH6*m*e!?Ah.nV"ObAFV':3XM:UJ^4acBf2C%3~>endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1816 +>> +stream +Gat=+D/Yn7&H88.1&V[*3N9r)4*K$gM)ZbH`S`PZ\X`S/")E7e]G9"3do6;DblYn8_,8O@@cQ:8H$8>u_!nP@I0])f^T"6[-Ka9jmWOGD6q*!8%\jP,Mrll8f/4<-nUalNY$i'KY48Cf/5<\DYU_#R1Y+C>CQ8m`G#g"Os'/JBb>i'qceh9^%IC>EQrR]>mklS`!4JtYACM_f>O!Tt!PqbR-jq&`lPUjh;&FIpiZPQZY\lHMme>4J84H([]l*7Os8!n0P",H13T"=\tsS!jf6$>-=6=Z$bWH)ohN?Dmqq%Z]1(:k4:jnJ?/>E5gD_KQ%]\.0LpO'&S1i1o;m01$Vc".76Y)T5WPi\FXZ)ij`uK!)Y:j&\hp%Kk9^n,Y_%M,Fe`A3F+!6f8;83S'^8"%5rP)IHl^=&<_QU#^ke*'O7q<=h)b)Mg'A4U3(T=1D"JsE%AF^8Q/IG=SMA'gcS:Uo_X9Y'c_\sD[?F5'djS`s3u\bR3i73-p1#D""Tm1*qcE;`N+^YAM8DChD3u`#m?NKj]TKsGi@Hog0A]@8,o="NGbf*UFflV3r!;n*UKsJPdCkhqe;9%f,p?m9$j7%P3tnV'hMO$iihk1,K*rcLFDtUkE'r$lehm*Ri)N>Q9Eh9Vd*T?-7LN/VFUR?7Lh*l9F?O7bDP2G]2;r1'>BE1e,$rI%N=u*notS2m0lq%g2eHu7:rcc(4Q!*H^RJWHeMiP6CV[CZV8QXQm*n^:$'TNgAP36U7*(e7V6Xamu#@YB6Sf8mUshcu3-S+Ga+S=bKY,^E[HZKM/g*?]9X/(Z]I;UFj<:;WL,#!hLu;[?RM_<@.m9&/t,SaQ3(:3Cnk-@"G3c%=mYUnE>Hp.h9V%9]8%YRl(NNR2RdL,^G[pa-3tZ@VLB3akRfd#_9pCC?$6tSE%q'Z`@OXhVDjN5`hVSuDMajr(BH"dq^=(Be5amg[@ie;Jt=/NR#=)@AYFklGo/.CgWg28ck4rBXKrjU:/3k5dEHVAb1s/Tt[JefAP"@l)]\HYoH.[;q'PZ1aCd@20&;V"O"&CB>@a=._Qa]'K=:Q%#KIeu'jr'ejSOZY'GmnZDS-`-aY#+qcQlA$BZb*;Ve)=L9qaZ6eG4tWDd$PnEDk3aXq0=4_6_7Fk)>^H:PIU77dMSSIG'^2D`sU&;<5[F*\`GZURG*jZnL.m0cRIU*#KB:,8%SmkXoh/q3\pWNB>fZ+Btpdkd!_69ns<*,01?NX8$._&\YdL;kns`pb_V;LSW'`ffI5NE(3pZUs&ao%,O=uqA-rVV&tQhp[.=A6NfO7\Ehqd#tc&Zi-cm)RFe(WkAfR]H,o_+l-jg%^A\R(hK1JpaVR\Z0OZ+dO,.jmT7aJ6,20,d]]^r8'\6$l%>FLTcPG0$X:BqisW=iT*3>L5$0~>endstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1706 +>> +stream +Gau0CD/\E'&H88.0i`?/WH8WYGtZk]"N7i<-%l@jkt-9UfF)N%G^[13='FF0n#U@[`eLMF*_;.SS_%LeSf)@Cj4@'*"tP4q%p/K`fFI[tYT$UFr#p=a`TIUjPAGH9m9X"fc?0@Ln,QJT]bMJ$1dG%@fjdJXAeIU,cGZ-.,CS^]b$Y#W'*KL'P:&EXOUe+DEA@e+e.iFj#'fK=R(6We?:dVOHmFn:(]C-`HDI)1#L;1i:J$D9O[L2#DPmQ/5)BVB>>4bgt(G4Z[=`]*CUfZ7I3Z(dP7lSNWhSR[S*(n.[VU3.D_7'tTN>DoY7].O4-j9pCqf?IEn7[G&l(\)864JlB76^19:HrglP%M\\7.S,Bj4d$Ku1`2e<:40V7i&dA'!70\$rE?3toFZ.C.HO@I+Fjk)97rQD1ie=ND"Q>_=;Mh9'J!tM\O[A>"a$e[e3XMVPqLu6U!`"t@`:gB_.0+fPWVh-ERp@)WR*Pa9(uagW3]ST2,Q)UKp1rWdkXr,iU'M^S_DCm8S6oQQfBn'+756%'XJ$:e6:98NHE;3)2TgZ:.<+%Qpf\dLl^CoR<)$``gg!rH1\Pf<248e8?L%3MJoOh2+sh';mDE0?C''A32n[d.[fpCY`&]$MmCU-UFN&+MCPtab;;6q$^,$e\8BSZ-bPi`E@"Z[AArdRR]<-4N[A\MY6D'XdRbsePN*l-=H.7[km$e2b)@eR;^s^WT^\buJjMrYkK'jcfEZm*?]&_@Ea25]82+Wc.Nj9V)"5X#E)*k64A@d"f;HE*>:5VR46Ns&!B)e6@=UK\k]/#l^b2DrR.4Z5H7W0obPA*dY"D\W&hHrr1U6YMP#kRG\.\VBd*uIBo7J"S5B@k#)mE).%\2%n2Nj.N*77aRo_)&G=ee7HV`t'A.fPh3MJg&?B@tZis9\U?n\.lYkL#@!olU<((dai;Qko#c.FYCKW:_4HVJ/IE39E#L4-?3m,g5c:_W7N9cS\P0!M@bE0l-2>7][s`Qe\L>dqIP$fV*4H"/a/8U9#M9,;$F8I?Y"c\,XoCX1$0Ve460_HeEKJK84HUn"1`0/5`LN5Y17Y08PBclZ?^RSn-4Qf>0-g[Es"eU,iq/_[F?SQI?<)H`5ApRij-]NNeY!ABRTQ\oE[uD9A=K?8Sb79#Hf[+fA_j(kO%C?59,%\c&h01*`Tj4Y]L<:2YFI%)^dQD2KFR`r'FX.gfFb4&frb]fjm_!%&bc'4%[oG'n7mMY^r6fLL"]L_+PulMYp1Y/HrrWS9?plnhOkpQ\2uX$#K_p@BVTc(]-_:\tA\rWVHVgDo"i,CAQ6LnsD15Yu4_]&)q,63FA,:EN(OlNXSs"d~>endstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1224 +>> +stream +Gatm9IrF=9&H/4s0g2KKW=lFdJ4&(TJ2>/-^`<&R=pYLPlif:%]>!)YGP'@.]_j)Z;CS%&!$Yee0ug\d(t!::??>oW,;KJTiJV&G#8E5TQEK"[.[3)He;8s]),?q0,'al"Zj?U4CpaS6`\iKMY\.gYlg)3Om.SDDG9Wrs3#c/E2^Rl2f2`D:36hh$'!C*D%;1>O5i$=^)dhhfX4esa-7j24n*r5JS_B[Nf!TE?90hV$#-n2Q\U0@gZ\Uec=NrK3D8.lj&*3Z(O%/K7Cgl'3p2S&YV,]S>/5ErTF2IC,^dm'okBFW`1_>d6k$1W//8E(+H0Dld#@jHEn`uh#()@l]W5.I:J*dC$g*d_4k#@k7#$9`kUoXkch5(!jqT6<2-]2*(ZX536(GBS,t*3R!s>L.nJ/,*=ekru\^!k+BKDeDus%`sUQ8cI-lOs6`#YJFG?,goCcMAZ\`;hU"`BL$3K&/^QV`A=,4/CMn^?EFr@9aHG"a`65k#4JPrAcGr/HupWP_B;K.9+qYq-Dhcj@&\`O@?Wt<6jI?+cd/I,[gN;$VKpOU.`?!eC\bp2RE,l?jTge07O+[CP<[@>M$UPT%)\!sP3P`8hTu-aA=S*EYmq["lOCk3N6:gRm*s3[BQfbu4V-;Fgt27R7FW-3_POM'cF96KfH'AS=.N;mZl"r28_J&+)t8jUh[J!5/KSiG$?!jEr>`4*Od)D<"V\g=7:J`!5tJQ5"0I:q:'1:'8=$K)7rE4e5W0oOEB(1CHLHeT\4I;1!P/'J%c_Yp7X+&IqR&TelKAp&)3n>*_5uU0OJ.BUj9g8X*[7$Mhd$+O+"Te^[Qgl-f?nQ,BE]rY:IL_7g)lSP*q8?\2LEKZ3aoW]Zh-cLc3n5j_dfp2CKKB4/b9h5FHMNZ"u-"YU.B'8dbLn#"j'iMdp($sGsTIf^4F'@5A*UK%TV7R2EfoiZrU;U*8d=PKnpm[s54*#.bdqXA?[mLB9%MZ^PNhr1]~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 604 +>> +stream +GarnS?#Q2d'Re<2\;tIS6D.JFp5Li%,*=DY)JRWqa>LG`4)Cj42J'XP[R8,6A[4SrqOWapDu^QX!r&Q3i1U:'&O6moq#\BS4G>PCU`@(-K"c:aLKSjXT$Qlf#%7ugmQg20"rdtmTg<_:'gckT\\a27o&?jrFe1]BX!6@F:aGR0SsJ8Bo9?A?4F0OSZhjaa/!M-lMi&]-MIj(C:F5&^RopPF52Y5qj6"3HE8t3UBsOM#M=kn0$snLlP>!'+e("LGH"OJ?77s7O*/2+Nat=;3[3k8#0;a0Z8FD=YNI;]@nk%Pnc+Ia1AJ^44eMSN=7kgD5D(>Ij6ee[]l2MqbX6c2D[p(2HhJUC$i?$R02LZOCJKo*o!GWlEiA]54kXqZ-_r$\Bd;$gKF'$rV/'j9M+1UjjqXjJNc[o<%%.6%';Z])3Mp6SP]Npn"V7:s<#`2r*8`e(Z2/qS.;s"/rr\X%3t6TDFqc.E=N':9rj]hendstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 656 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E-rCaI>O;eIj2]\)uU/lfurc`BikE)C3"&*l5sc8VMXTLVf-I(9r#"Ap7u$DPAU!/`3N7H_2pD(:;c(_//O7\fL0'_J0Pr34?SBqoN,&h7YHLZge+lM!W?mc6RTkK3I/[RbloO=0Y3qfrt'-4-JN*`!-!BCYWg,$fSJi\)"l.T^DhpVph0[!:4X+uh[$@nRBoWa?-J)#&S&VPGDQ8>-G^'#P2s/cqEsR-h;mPh`BK1YoZV,sD89>tr.6-o)[IL3/?kR'Y,'[Ff>siJRK1+gi:-3kNS.g2Tjh!$#_3]-#]VSq-JVTCf@oWgfaJ+e_Kq:L58^4nTo6Y0r.592%4O)Vd(K.e2nKW3(_G2gFj&qL\p&0]s!9sk0K0\MR@^7s1-]ep&iF,:C75$n3ZWja";YBHsLOi9c8BL.?%<:LGZp?;act)BWQ2;G$RSLk_1:E+UEhhAoK`$VqU0`V];QLC6?Kg5MbYD<^2+6g"nS1fG_~>endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1996 +>> +stream +Gb!#]?$"IS'RfGR\;u=]>Y155S%!8o0\In/[c*46N#O:,fu+B/"-d0-=18$h-F-(mfk!3@F+&H)ea`1W#8@ICd-C)=#2kO[>eHaq)9eC3\\hj!%?oJuQSYY(+ooGb-O@QhT>2DA\rf4KiNomcLC\8V'a*a%4P"L$e/oQkNgGE^dBe%=kh>F<-O2u.N@3LdhGCc8h$YST"j%'u;#r[n-9pV?!+&$51"LI8*#YcXkQC#e##Aj[km3!I_cfC8KQ8B4bdOP1DcpD2YY+#Y^13jp6Ou,$pOl*\Ss/a()bN/[AKmHBbDQUGC"GML9EKMUH`$oAX4C:XZ&/c^jHeJP%*Z8eM5cY0pG(QpWL)!QsYU7b>Qth1K"h9kVqUbA0J72)-p!'pokpiV5jG(3P:t>V8l()k!!TC)k83-DsFKGTWBE[Q+_9)XI_i%EshP59.g;$%=^a\$0N3,\\gE4.cs37gjMoZ/b7r#5WNJ43hd:!%N"[dl=Bmu.gE^/f5Xs?AtjZ@+r]Y!n=m0W?q7osD$-;la!Oq-tI*D3mgbiQ`sdK"t1+WPoW%4^EDlO`#%UWRQ[4sg0=!-iP;F2^f_Q!(q/FS685.L%"Y\hj_cF-XO9I//[\(@N$@Y)_BL"p@1+iSDjh1TU-n@?N7gp$\XD!u?Jl,ReLtPh1BTNBJIdK=RQ_l)=*/-UnZ\p@dF%&\R+-WGC7p478W'AL`L'8@DinIS;DrJ(!RO*5r6)L[G#"5hs+gIhf:MXO3(7ibnnJ2S?TnV5<0":?)RMOJahf4l&+t\7r18uSF(-ApQMom;W>tOKbV#`bQ#aX#@>7iLeG/=L-Y]3[*orEOp6YXuo]W2hiAZR1Q2D%nq83f7!UPVq"@J4Rpof-9/NJ5=354bH!MH".HC-%ZpgE%Su/=0#h))J(NjF4JeTuHV-gct=VA[[aND"I"/&ke$l)'s&96S92."t_(&/>I`,Q<36#T)!%gFb*ntAJ_F2[&U]N%KPF)^[PVk2rqYmLK3Wp?*0tI[20(k'*.fL?CcDTL3in!l,@%#_B83%[2kD.Nio/LE>Ld\HGJ?@3f!*$\]W@:Wr<87k,R\X8=cM]+WH35a^A,0SQPP7gMGL4H[DK/=SUgUjKL].VJj;IG%Z/K/X'5$]I1o!&.;;N5:&u="t*;I'a/j(aCMVG]%$!,@,^$CrCo4T>YZ?k]j*2OU+AQH@F6%BkTNfm'Xb)/O!mjh`F)'m<,#Yk'[MOD9pKnO@Kn#uV8]T&[ot-9!V]?M.:.Ksaq^/AUjtjQ3S9jOWe)TeR;AT1bKZ3p&cFIeA\3>W),HV&bddC?nmR:_h.3b3in[diEjc+mqGHL%YX@%@c,@!`T*W3$Qq7!:MMW2+OG9Zj]G?]X<(tDGS)sDlEESq];HuK.!biY>&Jou4Q^k"(W_n:rrn8<^0lA3OT,#BE%th/G(U~>endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1154 +>> +stream +Gb!#\D,8nW&H9tYQnMGA.e^UO/NmB^*,6cFY%hZ77RC=+SLh0mh6fVDW;lh9:'aFN*AH[e7>]T%ml\qA4u;4*"bIiMr5Lb4h\0rn:nS4D.8\@\?ucVC-[XbFkj$8DK$^Dj'TF>BJJ4iIYd6Jt9@r=Q5e]'D)H3^q1u]!m1naEVfW#'a+Z>11_TGdAC*+c=0KH)j53$8pOp>dDhkqmU@+-GgRm"8'fP4KsHsss`#6/Wh[BuY`eh(b*>+$ilF!ThL?[npCoi!lbTSSbe,;JA_3jn:@V\_LS("@`Z\=dg[uL2F#EGIeY3&4JU..4,d>a#F`q)a[)#_j:VS/oo1_B?4j@(E!<-8XChmS(T?h^=Z/n"nWT)?sLR%eC"`F+PfJU#49M=mD;1Z:S-W)'(B376tb"Vi)#o*4!G/oa.I*CbD_[-D,r+pP'#"i'^47%T/3'e^k'fQW[q/^p]p6EO:JsI4AdnW@.-3Ub!<1%A=FpPHi4a/eV#1UWZt.q#2Uma,$Gj"PVGD58]uK)S`KP"BR`k5H_&A)>q=1SjedNt'$;c;PB5k@>\nFsp,o@ST"M_4hs(XKtjaX\M=L6s_kij]u61+4-@YO:I5;m_7aK>`(;FWp!Fbo7n+O*PDdRHXXU]Q$RXq_KIgbN/p'.5l#JtJd44^;1s\E@IU5XKT`#-(Z:na`'$)i72s&Dr3\AjEQc$92qQ6U+)[*ri_7Ws=kW+JOBRjcCFcZ9*GUP89DSFF[>!-<>d/P"EH0c_i'rW0K"s"8-pHY[fD9L"JMCX+h3qs3"pN%*")7)m2B)NR*NdPu_:Y4E_k6C4#1NNf'+`uJEtY_O0=1^AI/~>endstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1279 +>> +stream +Gb!SkD/\/e&H;*)EQCu+%N8Jg[cA,SQ6n%]^`C#1?]$fsBSj%J8X)kG?&Tp+]gp6<]2_6V\tM#5al!,i(gId;OE_B8m"[sT%biHilGgi+#ZK+L(0ca(GpL_bt_*s>;YOV+F'r.,.%Yg#KhC#E=TN*O!u>q:RoLAQ3_(#:g`cc3t]s7LeM;9iV,cI$D[e/!jQ?q5UniFsncOJ&`Q1tA^DTBaOWuH6W>V)KiTfQ8-(q[uiW*#+pl#S2oN3KtstPdq@r"P3-j'm-Vqr4c@rKlp>e:LKS,eBQrB@%#UU&$a@EH3^@\i)mtm,#)KCJD\<_:R3[Q=4U['=a.UKV0NZ_<@H!$2BD,J("T]Q28-P$h(7se]UD#IlaTQ1K7if845VK%rfX_X->e1S"TN:)3CQKLBM/qO.FU3RK!?2Q$YdlJpm1]a*]s\O_JR=7[ORDcISCRM$(hoBZ:@-c\XMZnd]6T]ZM,4`/U\7u(lDVNNpfsDFm@OtrApOuHVC#-7X)mq@%prkh0'=668tr8apaU?k'!!7.R46sPT1.D:[4rIHZ)POiY^-Y2@&(7/Gl+iK9Y/(AB>!2)Pohop]LDJP_s8$gc*3PAS;-o:/4R."I#*h8?af`nf4f7Ui''!0;+B;^V(n,9#`PJHu%G$i*=:AiGU%H[jc#a8OYM:Oc=o~>endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1376 +>> +stream +Gatm;D3#So&H9tY(_Kd-,-ldCM%HJBe0]BVVce?2r,lo6q^]ogk[4"QM@Jb7'(.d^F>\:+G%@qiGb?0I)Hq(=Qjjs#k!3>tnMLh/;u')],p1?^@WLEFG!JRc.9\)=Tu?.(k4@X#?5`a=L7Q#e<:^"QbWcL,LM,6Cj@f0V^=J,APhm1-"8N^MddhBOR3h:1@!OuNuFHRLIZ-igfM[,8%4$f;)Y&(g>5Uk3OC\ULBhG;#`Y4]aJr<@a<7\8/nucXl7tECI7m:h;.ZTdo'^MM7)%T@oJsrqn5i^Ij"0bbK)@,eCQ>%-n=IcJb%U)Uc2fH'$Z6)k5[CQGo#_RL049e16"`rPi%aC'O,e@R9t0hT]-k(ST!_AU6hF=ILS"nBEjYL#.GCQ<*TsYK0[iV1").h`$re!ljk1+4u#kiRS>4b6E*(Kk;$06PdUVn]Fm5%0W?NkB#[,?;=u$_]/[=&/Y[lg7=2r#sNl.hb7GXtr1AP[U#e`8oiA4J+e0]H/%UejiI_cTLAF*'N5gA;R`9::%b@kN0\.B&O[X(;!)<7[GH)PbG@k2tg\9^HPVu7?E7FSLOBYCl8s:_cr;PA>o"q/:n2qBRs%%#X%]0)endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1454 +>> +stream +Gb!#[D/\/e&H;*)EH!YJfc3J"[UfR:O9Na@+P=!MrA5#h/Q"E-M,HnpM:_F8mmtWFr45o<[Q'(Zl,\2m*hPOZ>]B2Y[FZf/pi-EQ[k>03N"U(3'#<]@DFTVH%C[8/$_cm.8.bJ^SC.-"?EtiC):b1ppJfRq@gC.Z"+@9uH$JR5``n2sI0bi0OG(W#$`[!#l;BCI"KE4]i]4QW&&taAfbobJK[KO`Z$R!jQ9[jeF@r;=itcuL64`!+'lhCWNO^"#%JD-:%o5IO\cO7!/hGr>YoAus0g1XmQ)Uq5%ZoKElj_kj'U!pD>Yf<;-J%&OP46/9G>*YO)9Y[dB3f@F,T5-KU8c!H>;DCWasZ>SK#)Kr%Q?k&NIj^>;;TJ`,Dn?oDF`/)'iH:%0`"8nc\DZp;^n\B#:b+\^1Y0lWi("FksIi@tV:/Y8d+aGT@$]O`&hEHC^Th0ishg*[]c""`9,*Pq&1'PV`6WU--VdLoKOI:kL?7]*s;S%(:+;K4E@-DMdKmZrQBlJD`&ngPTADZsY9n^.=Z(@+>G0;PB-@$$+I[dn*#8^Fl:_TTS(YFHn+&dL%aeRu@;gb#>GZ(Jue2)?a"(,U'WuPL*\h]kt0##VJ#Ik;+HPUcOhY8k(.[fnE"5;Cl52H=uXNcm-hilYKmR&!?Lq:B:A7;f)h%,&PKk2Z!@CeEVP?T?:AaGbadGreYhl+(\fk'c'W[0gKOCu5Mi4`Bph(e\=Q.jLVf$p(T?Fqmf]+-S;a]pRr^a!Hjd8K/N6S133bR8d?Y!S!TAlV&LQV[cKTPWRs8^6"?/MB3,%p3HrW_XVo1tT1,dK5DX!44\F/c~>endstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1480 +>> +stream +Gatm;D/\/e&H;*)EDS@)knM+^1=nCF!SNbK"e*_2*:/:m#`M=-CaIN+W46/rs1Y6Rb'J,p%T@nn,4?T0*M7[LNF@Kij8=Co!;sEYe$ig(T>;_'n[WiRMt_1u(jm3[9?YpcQqk<#l'p9.j2=OO_C=%`+nCsQo[ubQ$A%!\@!dVUptp"0uNl1=\,KO6t9koa#H'HK64O[#aku;GD8!*33f=MhBif^K?.\R7]O.190M0L`?JD?#Sp)P*e$dRE=a+@W>3Ng?-P\>K2B6>b^%[1#U)q'-8FQDOr9BCR8m1"X#;;\bNFC/VSuWLV1j<59SN^!Vn=j,niX<5)/13e+[9CBg,i6FddU7$&-^3RnfZmmQc#@K#_?_SrMV$8KpBk!]WdL%BHG4)7=N35mkAq#Vk2jS0H>++k7LYJhQ#"TM64R:D7fnI1D?br7"oEZE@=0b@l]2!H)R)*jJCMb]?gk^qa=]U2np0+0.j9LXbl\\.b8:bWahq\bC+F*Sc5V>lm.N@l\rCQ^>1Wn\N>&O45Ubk&CY3(`XE6g9SYrPI8gT8Vm9-#^SW"d`)C:oQ7HLCa$h9P@8ms(o^-p&E()eBdU=Qg?'N!X/?c_BMJrB$4uo`a3db-dr=ZR7a)LTBM\j(.pk*9";k4hT$r@?k9f.^b@6FO.^UT12do#.LfQ4"gr,:0;M4,\+.9ZVZkgp$R/+lA[oU;[cF;KbQ(BtBY%jPLR/L/oi9NcDr+de,5E4cZZPGDFd9+Cf$Lu]^bC?fAE%&GhO5cLB#!XkT1M$o`-H%P+T^r2[tO>b/O`Q#*/\cI;\fr_K!;qk/bIc1r6+rr4Z>.5^q%]8HU)DOqYEH'W/U]e)>5?4tb!p;goSkQ(ZBEX(@gV97NWT=r=Djs-mJYo`\6q/HCeIfMBT7:u~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1202 +>> +stream +Gau0B?#SIU'Rf_Z\4A?i)%oAF[M0MuO[onTjg"m$:-IKB(M^lBm^,29El(:eHE%[]pD?]!B(I$gN!8LeRY(5'h6S)$)Ad(?^nm8pp+8r0^"7/Q0*u.'aE]<4s.d%dYj1S[KLm)]rT@o;A`cV91-\a`QK1QlcK'HDsk<0n)/8T.X#-\[mbM_'hb7J1-CjJASSb7`gY-e,p.Y"&Z.hZhZu!.+K,o\]rWFqL&q$@PWU4;p!,iMq31fVQjKab+@8@8=56!@-=Q85M]2nT(o=D&:$%'>[]j>NaDR2Qa(rse"J<%P)'4C]7GA$mjYnl!QSm$<,tbNASTP[q68?'e*SY!)EBr#;fs="5Ner0_MU*X,tEA1(XVdQOnWer\8&o;GS^Y&>Cb9fLBj+=a`A+qR#=Zs"<3msu0A\qKB&Irkb_bl:6qp=m`0`s5ns*VG\>XW45Jk]bendstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D.LJCk2^@O>M1,W]$5T>GBhV!q#rZ*ACfMUF&KGo>.i>al-\SC>"NTbMO`4G(I1[iojb99$A.b6rE=JUNeT<2_rRR1h[U^Qc,i;b0][5\N=HB<4LlrpY!Ib*9=+erI/WKK.\68%R$U]YAa\nt+L%Y_@@Zh]tV`[15Rs7f>^hfMJO0PTh+Cj9'eb_WYlL!PL'B^O^DTdB[Vn%o%^r%mjB"=3Za7O(SN6_T?Ic,RtjH?+k'CK^\i5+WQ"?[fZ=MUl*p70Afgendstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 961 +>> +stream +Gatm9hbVu\&:X(TEGq'Jg876%0l9g&!t4CtV.&)R52[d>@S#k0EI_r\s1Yh'Q53ZD_\BM`m(;`#qp'D*TL"WKs2+ut/:dT-"&9M]))t-o,7&VR#*keqVmL925jRW^mH!?G$$jl`_]Gb%Km]F+*'#>KeHG'f5W'JbW&f)`JN"R!j.+!Je\E.#cum+6^#@'*iSr#G])*&o6L`:=r(>:)>c4hJG9bnJ$'5^.'?5cDR'95$:qb'VQO:RJ!^H%[jrPE)HX"U\5Ja`rq^9IqhIN?=e6'$_D+D28*a:omTb%#a1>32I''cOH@J.Ca2qP;,ia1+^>5k6YP7Dsi`Sto7u!b'gJR/ms5-qoa],)Z]T=GD%S@/=-tKZ0$]b"B>V4Xi]s,(h?0#=MECIE(<839(]?53(To7W9H;WUW_P49=''g"*]in?I/+>ou=pa-r2RA[9OeSYeTr3Q\\%?+[>*9bhJ1&5l)g):7J.Y"CQaK)`-2Vn4E_YJXMT$h!b4J(/O88_l_H"3?23&@7$h^29:A;9mnP,*u#rFKQk[FqM!leL'%W>0?kn".<4FVi)rN\B,a8TmXmeu!:k[&KI;bnouSb;;""$bS%6ETbhUR>hPu(eukdpI1oc=(qD!~>endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 797 +>> +stream +Gasan@;jjR&H1HmESmG>('q%8h:,":U(\.n#4ABD7:(!8[u$[/cF.WEJ)Ao[$5GC_Q,njO4lEf`";ejC0OQ7m:;V-amh2e?i:?H=f-LPO&1$&:FM!4M$0cE#WU6),Icr'X4+lZ>m.Fa;Ur[fcperFd@g&'KqG1Bhj68Hh?H7L&mg^X]ElE9OMO-M$AWd)=lFs<3(A)m2i?OgKE^goKdEY"i_`$1%\It0[DJsbW?>\8q"=Dc[(=;.2+NKV6E@sS:>u$Or&qj$_pE/7SO#e>)*@L^m;7&@/TR3pR;Y3hP^5#K?)l*Ke1A?+9.uKB,aBWd>[M8H8@*HIU[q#.agl&dC?](gal;rSW]L4r8+RJLj)*c(O'QUiY8D\RR7&5NAW\0,8qi)3kkPr+7i4V%oE&O5#Bbb+a])=VR"U^G`ML1u:LX3E>+oZ#6':^]njendstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 706 +>> +stream +Gat$ud;IZ'&:EXk1Ha&-QMg43m:ac^e:fARA>cFH"]dBE#1_:2=V8ThO%\@h@J+$l-B59>b,RR7qbSpLA:3LPI`Hom]jhbT(p08SU0h*9Tk;ierDP,nCWZr-VA[E!KO0I("uKHlM1bh1f(:MP-TZi&RH1GubWH$>'kOPp.dK!UF,:d))Lmm*qJNYs4YlF]IRU4$%TXFftM7H#BM!Xe\@F`\>)Ap=`WC\RBU=B9Fc(/.uk"%F'bbBUD9B"LfEc2F]K[PkNA/rN!R6KuA6s0endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 686 +>> +stream +GasbX>E@Jl&;B$;(%XsHE=(>#gGeOm`?efAW_/OYYF-[(3d0(tORhja&h[J$CoJs^Umr=Kq0X.mg9eNXT;M\,&6`!C]FKT,G^%Co#j3lJCG.R6W9j39hJ;i^pUr1ZcjM>nc<\"eW_BCtXK+Cib>.G>R2@(E%/!t6Y6Q;SXKW2""#NId8=8+&U#JiZriU@@?i,.@h=Jjep;H^-r'K#/g;2:`Xc6"Mul*qV/+4\D911VaN5'S3u,G-KS-7h_!t*k,@IK\LC6=n)dA!eX0%Nes&ii&Uj@)29Al<:=ja+OWq&G7E5[XLfZD8;)$FT)9Q>=hJCpD8LNQgrsC0EX&k05Fu-Rm$=%FcpZS!I?"Hg.?EN(oCWmK)mQU?BUssI'>uLkSga,lhi%eC38u::OXSZe:2BYk7#lqrY3)I[(^`ne3#uXOV.-._#jA"YQtct9DCJNQ_=U>R_0kos0j06QDjG0Jo.UGuHMY_Z(c/.LC7$1?L;;0,&H%%UU=p!M~>endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 335 +>> +stream +Garo=5u5BP%#+0K'g<+\[\aJ@j&SW"9ro@f*4]U^6%QBl8ZJcfHBN@gRT*fX(VfG7aWV5L,6"\_J-QF>S,eCr^&qN`QU&$AdGR)/-Y8g`hU-;K:`+\3%)Wendstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 364 +>> +stream +GasJL6#V??&;BTNMKbjZ+A7\<[oK[VTodFjcm+65BQ^S3C&79[$Y#oe2Nqr(4)`u'1CQ/Fle^t./-R@>#3J/b?rLhJ&],@(Vnk".\Vn#i@(G^BV%,!-?/`.HW0^fW*9oYJQNK.p?B2.Ybf!kF+HF5SpTWe306uPQip@C[EO6#n?aa4kmi^I1mU>[BLTa:2$m1/n9JOPlfaZ5o6:9sJ_B-\I-j)0IW.lA,QEAA7R=!bSDZ!cpq5#$qU3\H"n1WRb]D2DPrUC)RIKRH(V$Bju%8rJZ^Dfc`R]T_7qGA8o`:6i""kBe7"t!2ET2g[#QL]oKrSiP$"6W74`r~>endstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 300 +>> +stream +Gar'#_/@+D&4H!_ME.OsKPVQl^s.NT+[p+'IGnicD@7(sYh_\H^:#Jh<%I?IG380'E^(7^If`XPZOMHmLj)[`Pn5McOdm*]]pr/kQVUaa/Lp5Y666=%Oa&P8ik4gBUC,@hLaqs,Pk([egQrCA71*bAmWSXU_)6'lhoVE+k#E-^fUXq56AMIqT0<64(SK%lK#+/WSClhCYp:[d*g)uq=PjDa',X3X-?j-~>endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GasJLb>,r/&4Q?hMRs9>PrM`[g0LY/<%//k@hr>gB*q+R2)^0Zof2A,PQf-k-#5X;S/I's*p.?C!V[SC%h'ulhgc.@6gtcrpU2,)rZ"EF&+9^"1l6%(/Hi6']m-uPS`=NrAYVSr;'-MWI?:'K1Hp<4^tT2G-#uX]),n;7.0r%qT(pZpn'\9,Q4/kX[U37endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 344 +>> +stream +GasJLc#/.f&;9L7`>iS&'Y@3bgaKZFOp*]4TncrNihBDj[)T5t\$'fC7j>?EaTq:Ym'fV!g*5rjmskXo]12oh+^RHH_$kpJ$1GbVHY!m9UA$qn04O7ONR0P)lWGl$`_l'WfdmIc+1#W?-M]0XM4uIc8=gs+$Y36dQ5/S!$!-22QmQ+`\"O0)V%]*(^XQn?ZF=h05F>?u#;iDj;3%Wi#Y7[R9&/\mm^h,C1M1"OW^9_oY"d#bC`gEX]VsUgI"YXZW(W>Dc@VFTe$PhWRuMAtgc%-3'8/"d4@1G!Xq$,INsgpLf9U".U!fU&~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<92C1*'SZ;ZMR0B:.YFNnFqgVnB$IH2`!F3j[-aX(p!&A+tYQr.+""N1Cj"S'MrkQ32UhAgQ8"sF'JH5q[g:cn2J>[$R;%g=U/)#;S"^cS_@mR3jat(*Fl\0T2.Lq.@/hDQqhGPI)n4@ZIsS(\_KI?@Y4l?CLAkT!JJ3J,6:_=`.W":&i0Dn!a$tNYp#CohtP?611uB]8A,ha;VK*_6k#Nl_A:TMI^`4!].@Rnb0TUjWBtqS(I3Ct3Y0>K(=u+_*k/5?5cC_:endstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 384 +>> +stream +GarW4:N(hM'ZBHfME0B;g0I[Ngk9-HJr7()-G<6#>$CpD"`=,']8K^*@pZHrI5CJa4:\6CGAgXdT"r7.K:.#2!1DBZKDo($jl16sE4"LiK;a`L?t*Va*P>_)EY(Jt`>QgoI/n,pnsdDQjt$fU.mM!lHM+RV+5Vendstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 851 +>> +stream +GasamgMY_1&:N^lk+r\I(%m7pYhB=L87K[N'K`=VGhL^Wfub,:]2$9$GLdQa%]#A$5BtMuR5nnlFjTX*Mf4s_9EP!8X+P:TYQ91!+$ec$/Ej`goEmSu_/NfU8#,S[,OdrK%f!JbZ2,Ua"t#_[!<&BZASBDqnBIW'd%[9\.=\5'70cOTAUpi5dFfFPF&nf>IM_/BTC/,l19SCCr,XrB6g:n-T?K(:gT8!Ao#:U=eam;C@h/U/%/+]u=0J0jhE5W:u*,`7W8eU'-KX.YF#kl6VJ#iAP5o\iZ4Do&iY?(Gio^p.-h=OZpZm@=go8B[,FlX_TNr?s>h^2$fh=YLoka.FL38X/9VQ.TLd>09hMHnS<%j'R-.+c4;SMbt\.,[^GuY@pXLkbqMdkM[Cq$k54tbThg6OVW+YhOb;8K\T@mX3P+"9>LiPlAibLO1J7eZ,1LX'8(#3*u~>endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 617 +>> +stream +GasIdbAu;j']&?qGEWoR$Xu-'&6OK.3hBb._4muJ'O+Bm[R;E')?)g$`\49)a('&U\`Y9,J;Xpe^JP3>?uWk+5WiG$+J[m$fEs#Gr#(S'3M+$2oIue/*[eIK"1K96_Z4mP6\gR;;L(OA=t7k+6r$:$(49Hk+i+j0%9]q7#/PVrSVM$no@\"SiJGtl49[t5-Xa]?ICA^mpfpo<4a&D^.!lK-e[?&jB*YS^:tl,.$'W7^8HgZPi30D3Qgf$I'gE!f/Odhiat9[_r$:;W/9pe:A.6_kR=\Y;>KftqRK!dcZX\I\-\A=fVe:[dhLt"rJY8]`fAQ#M7WWsB*L.ip(^J=W7*/XElHrh2:dg"4WfTC8NR3$K1G0pB2rlGlftqgH;p.*Y7Mq=td+bfX(;`UVgYG#4Y>+fU0T!$s^mN!16@HY[-&ASXiC0R-*C]C.mHOA?1Q6J*lkLgF%"9\iK[$=obhp!GV3C<$(tqblendstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 395 +>> +stream +Gas2E;,;fu'SYH?($EO=9nk6hJ@o_+&^u;'?^CIR[Q;#S:hYgXf@tHfF2jTED:3dV\R/PJU'J*lEXU)N/lN,BK>2q3]EpPb_OYn+mZh46cl[U3F<,(N/eD7NerKIP+jS]bXj6K'"-_g[PN8%O%F9nOPhsGOT8K-dq(:_t?EfCG+jF+EROq!@56p(r?bi5p;mn*\no17A*q_KY$>B2:l%C;h%#MM,g[PimF.e92gGa2nWbsD7KsYV7-(5QH=c5JP:$n-HRg",8@0kPf`2C*/@uRTfb=;,)C'8,i41XskBks\S;6!71?HM:nZ+O(:NPWJ*Y\>hFmplO^TR7=,;DbCWMcb`IO.?0S9KtqCX%,Z/^Vh5dqZc3V.'s4h64OuG;!gIJc8YaYP99~>endstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 912 +>> +stream +GasbX9lo#B&;KZL'mo0RC$W\A:EW=a'MS"\&.7j$#;3l"YSp_d,WQP/lanoZ$05kap=Rg]lJ:Wgm"%fr=$>R`i+E2UI1NtO6jrM^1EW>7"OY?iM78=X[\2kDc<@?n(1kjG>>;'X$0?KFEg2qiWB,8?[T)(jKkf)0)hg3qn@W+FkQOg2*!SRiLOW`Qe*1.^`c)kd",Oh[?l4oU;i(E=o[O[GnHpVA$Rob2fudKa1mZCGI^QX!rc;,.3M$8*&=ZplAM4A$JAR\n'Yn7QbVN$@P"]$^e(d"]ejAp#g1MX.l[VS2`J2Q5nXkfZjLb]#"=\k[]XJ'D`;Lj+2T/e%M1h6$VV[L"QgCo@XV;G)"fD;#RehmrLnSbj:FrA)R)b]4C%%*cOYD@g+`W2hYQKiC&G0`i!pjGXI6pBK[Tp_n#5W&WlC@oFl2*>;+Co;..b/VQbTo\QAXk!b#iejODF(18NMYQ.FpC]g28l1f;K`#\(en*N6CLFUt\p6T^KFpdrIZ?IB:N0C83cr=gA+aK@AAcA=(%+9>el$`@p0M~>endstream +endobj +91 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 784 +>> +stream +GasJP;/b/B'SYH?(&)8P>I?@!V9im/Kr,RtPRZ&T%t-1k#!=bdC-,D]fC.Eb;lG3r!f>Rmh!^hM_]YV-q1V>[Us-q2"Ern>_SA1>kOC5D9cnnjET`']6:dqVWr;%L7ijStU9_KM8GZ\LcS*S\TbU:!9Ds%`qqr9N1YR=t8?*;8sMVCnVYm34>t&"`;jtnTaE0EGIpf4GMRB%>5ic:la*r?[B!^[(\E8'<@K8"8;kn,I_%hY7_Xgd1^=`f59R?4"6S12a8~>endstream +endobj +92 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 601 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW4(_);Q5g4'F(lQm*]HZP^f<.*[Xa!r?6i%^H$UKFF*cG5'K"CpK[endstream +endobj +93 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2Hd;R_m&B^lp062^U'U;eujm^+S#3^rB?j1+lY!^T<\Il2M9KE(ucmdjq,!@D4'.r?rhWW`S6ZK/p,gL7^m`lAHfi)_@'Ps=<#$.Z*7W:-H,*(WYp)WqK1)V%EE\ZIgJ&dH^G6p:qsh(9Mh1P5b/7[N4(FBMF,ZNPRQbAj/`'(k>ED-.TO>/o]/L<:qsma#OO/A0GW8rj3%sZp/eI/`LP&a0P*9J_@$S14pp^=e$F;I?k^#:*,NfA;M8pEu5e^Z;8R=`q+0'Jn1_uM_!dITktnW>Jp(r?A)#,NK1^WA>WNSM$4sYmQqQNdSlt1#NoT;`o`*l\O]\e:-U"X:tkHQIC9f\2.0g_89/8tkRUJd=$4LX;b>cWP+PE>-%5\F6:XZ%&&W[K3uoB$[,O4[)oaQA@""Zm5c%C)BLNNo9(2?Sj_Ib&f+6.FLkIR:cGendstream +endobj +94 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1426 +>> +stream +GasIg?$G9d&:Mm.R$XC3]7dT6#DBQ;+`1DgA:sd1(L^*UD/IBFaUn=74!P\`9\:BsH0*dgTc!_BYrAY1SSYIou/h[Fhn]dFFBHcjQ-9\-VE1`-l$VE:0n=!8b"&@?McDK",i[]Zu'6p*3/Y42S0"t*DIkU'NY7Q,;kVk-gNBV8Q%Ym!FP&Dl,pf\)O?<7QFiXQar%M^>)KQ#6+iG/;X72\FnMpc!fb/uSn_`1RM(-)XHnu\/moF&0frl7(9Q*:O^Y[DF0,0'hf9U1"!#j";goLhCuBr"@FNV-gZ?m::l&C-ti;Cb@8Z-L_6<5p$eK3i%RMfo(/lVYYk>;U+5UP2ncB9KL0arhs3BN<+,I>sM8)(.h;]$1$C24PJ"kgr"g3^]/=(&MIu1t\fZ[;fTRCU'&5FB]hn#cSelRqDh1C.I*2nD:H#$=UBee%J]e2/_:r]_>2])F:/>+h3k!2oQ4*LWP2ZEM'nWD(ZQLrhi0_"KqWgUPmF;`>Y_Ph!]c3Q14"(Yr97E0`2mpSUd]%cCaQX[2!8&8GGGV,fAgms$NY$4;k+-B<;7_d*5[&D:78+8o^`o:T*FQ$b,N`jA6c.1iklimEP/cnIQQqq8nG7&5io8K]YUtPt8HBEpGK_qX@dlKoM'C>pj6p[13T([4$*DV>dG8EQgdoW\Y]#!gaK*Ag:"?DEe_+ae57cSp?_8G0s0\d3:#-l"@Jk##1@!+T/1a\.9A8b4o=#XEthtSTN"Knf5H_?@\3niQ2mBKjNM5&#h`U9hK2pN7C(*Y@&Fae[\Jma`+]rE$\s$%_S=Q>jfNXmXg]8+K<*oDPcQpc\j+U&(JRDMh.fm51HXK0/2bB^;T[\d(MM`bO>tIM$K3_Oe).`1HALp:@9(Cn$!F7QU\,djb$j2]HUKO$MVGfYk#[GFAA`Ro>ZVkQ_XN0a2?'-9$bV&MUT<HArBE&)1nm_@~>endstream +endobj +xref +0 95 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002103 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003011 00000 n +0000003217 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007543 00000 n +0000007749 00000 n +0000007955 00000 n +0000008161 00000 n +0000008367 00000 n +0000008573 00000 n +0000008779 00000 n +0000008985 00000 n +0000009191 00000 n +0000009397 00000 n +0000009467 00000 n +0000009751 00000 n +0000010113 00000 n +0000010708 00000 n +0000011359 00000 n +0000013787 00000 n +0000014881 00000 n +0000016143 00000 n +0000016318 00000 n +0000017403 00000 n +0000017896 00000 n +0000019804 00000 n +0000021602 00000 n +0000022918 00000 n +0000023183 00000 n +0000023878 00000 n +0000024625 00000 n +0000026713 00000 n +0000027959 00000 n +0000029330 00000 n +0000030798 00000 n +0000032344 00000 n +0000033916 00000 n +0000035210 00000 n +0000036223 00000 n +0000036651 00000 n +0000037703 00000 n +0000038591 00000 n +0000039388 00000 n +0000040165 00000 n +0000040591 00000 n +0000041046 00000 n +0000041437 00000 n +0000041914 00000 n +0000042349 00000 n +0000042677 00000 n +0000043130 00000 n +0000043605 00000 n +0000044547 00000 n +0000045255 00000 n +0000045741 00000 n +0000046744 00000 n +0000047619 00000 n +0000048311 00000 n +0000049267 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 50 0 R +/Root 49 0 R +/Size 95 +>> +startxref +50785 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251103_031025_analysis.pdf b/ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251103_031025_analysis.pdf new file mode 100644 index 0000000..39f6ebd --- /dev/null +++ b/ai-analysis-reports/repo_analysis_4444407d-fa86-4041-9aaf-dca94b7bc44d_20251103_031025_analysis.pdf @@ -0,0 +1,1002 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 13 0 R /F4 19 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +14 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +18 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +20 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 91 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 92 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 93 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 94 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 95 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 96 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 97 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 98 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/Contents 99 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +48 0 obj +<< +/Contents 100 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +49 0 obj +<< +/Contents 101 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +50 0 obj +<< +/Contents 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +51 0 obj +<< +/Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +52 0 obj +<< +/Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +53 0 obj +<< +/Contents 105 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +54 0 obj +<< +/Contents 106 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +55 0 obj +<< +/PageMode /UseNone /Pages 57 0 R /Type /Catalog +>> +endobj +56 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251103031212+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251103031212+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +57 0 obj +<< +/Count 49 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 14 0 R + 15 0 R 16 0 R 17 0 R 18 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R + 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R ] /Type /Pages +>> +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 505 +>> +stream +GatUn5u6Mp&;BTO'ltp>8Ma-$38CgYYa(l8`'WH_RFFk236g.mX8[I9W3Apo3#%?_=e=fSmu<;/^iDu@%821JhbF$'')ZaD?itMQXK`3NqN06!uo.]`Iq!LpE&DETe+E;_TW:B*u]0gd#`#Ojn_L4,/&..[H!6?R(u\@("[%Of4?#L+)4:3RB9S?-J53\e:uh31Od1']Z>Nbj\j:!I7pt,7[+n6R^_j5@iGegd](R&oC\$ipW>`endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1349 +>> +stream +Gau`SCN&2l'`HlqEPJSCG7)83&#`MZ0n!`9.2o)1C.>51EYAOmPF-?[G1^0:f7qYGjM>FuC69tkqk![G55.CZ_@JC$K,EP,'Y9V6L^hfN&?"R(oGT?Z8)KBKk,.#@hs#:[rBVMWnA$daEdi\MA.+0I0gaPY4:Pk+)Q7fKp#>=]H?FE4PM=JuGk:;>VN3G0?+]l`T3XB6WHD^Sh-e0eM:a_(``1A7@M-t?7]VcO&;YQK0uZJH$)t,QGf3M<#tVK=.9Aj=^sRXt+1>ghn$O1Z+mf<,ZZ[24Jb.ea"HF-r#&FaW!P^YcqXl/@[jBd.hrJgG71kKTG[uAWF/C@Hd]+EPf5Kkeb(<&++u*H@7+'rW[*"Bo%t8Q*KC0WPFXpd&P=G\VHfFp1YY>DcZo+.3VV$N:R`mQKBBe[C7W.+8j[q*mEWVh11Il@_2n3th1d[eE.tC=,_IgOMTI-GjIF]nb;e,>2rNJEa_)YKjP5X7rOV>8k7PRZMlanXrj\j#2m:A%io-D#o;[pZ0FS#KV?h)\#]He:JBtN#M&;=u2'Bg,'s]#\;P7@=!fGr=GWe4klN?('=pgk"[$!2)n!6hjEhFFrP``04\.-RSM64"\8][*@[7o7[WD#/fNLr*$E!\5bs,p6\'2IaVaL1_m1A1dd"&Ke-)K``]g4f(2)T5b1KLG`Y]LCn?IkrW&jJCq+P7cVXIga"[r^<=H7E@MkhW*<*q?$f$KHOLb_0:7\gpjE)WuO>,JhGeB:#RDnBk`m]SER;m8670tm1JRdM]i=t-.GX;Z(P-.r^a;ljKMg2j,qJ>9K@b+PfIh$lf7kr)GaR_N@fo]JnkQ7K&&7nBd)DlTG)kIRu)O7/S:kWETXp"URLZ@)PGWtFljY"%_7+6bi1J%pr0P!#[Jr(4)kZ>C]RAo<1?f`u*gYWtlpAG\%b^5Fpg9Y"T=eBS^N<'^,mm0B!]6ui(]~>endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 197 +>> +stream +Gar?+_$\%5%#45!MZ4ko_601FD*9B:jCOFJ(X[(B$uq0NDcTMda:FsirOrhpO\i!C!SB-tRQq%d"-pG#+)t]]:_\C_#@!=6c9!1[+:'9OE5U:8Jt\QV'/K:&:1W`)I%-B#SCa#gq&6NN/tuqnE;P#kIt+rf\SnrC2/gZGZrr&/YHUb_=k6,mDqOi,6_g;<`Sendstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2440 +>> +stream +Gat=,>uT`R'RcT\E??3&=9A9nL.lc$#LOi;Wnd0A8K-eI8S>Xs3m=ebe"%"7)71q&7FE9ecb8Msds0BYO6:s^.FD]tJ,\Plf;3F]?GG$^\olrr5*?0U9f0`:'/^$^a6hT'],i#>D7Z:pr!`cW]YCikI%f<,l0V4'?Q:+b\.kB6So^bc)+cVZN$9-\>4@J$Aq\B!YI*9Q&LHG!-S(WYe\DqLN\T4=[%*UuVD)9n0kZWbZB:;R;d(G9j9__H@0UdO9b.IBCsi6UO)TK*IJDSe,T*4Cb1)=>6KM*dd[[5HfrGI`0JY6SHkGNRjjF-,_3-QGRO'_8N0[.JK`<6a)26mM1T#G&SI-N&$aV,0CbqDTTaAb7AR$KS*>/=.A[Roa$uX8Zcn]D*c'ikUB%FWocE)^^>%TOPM\QDM7?865f\6b%1!:=9>OW$3?(!"5HoUUXRYujbLX-eRE#^[j*r.aA@R6eXDX;$qpu-97H`PW`FO,unH5&Ql6&W/Z2))'6.pU\&peLn"'e=jMf^0Vbd86^Nbj_mOTIZ>I$!.+L-rC?Q=&1%"q"HjC7*LTh9fb@Z^KnVqT>-$O4#tk\(&>bJaj'VClTGCp1k>MmKCRb?*8O:@p1t%#>fe?*F,^NaG`l1?cP-:VbX/532S'hFE]tK!m-)5n'FSnqCOm%3=:EDPc$fEo't$)[r]bla>(=^n?h/a>K0KkB;h9=s`TTBk7$#DL)"6$;rW0?6E>N:58@52/,%\?.8aV1NkVR#M#ee95+L#cDmLcgN0+^\@HA^ENHX:s+B;UD>Bo^Ken5*!JeHNhnHi.uPs%j`j2:7L\gASf.d.==Bt7.T'ZuD-KWN0-3%pE_Bu4Tarle>hQVXnV,_m@+FK`o*(*06h1!6!?#IId7)L'_jjjIcN&AJnIedUD$AH`-<\^ti8ObWcU4Q0%FQUF`]%dDj9jLdh=Ybj#&C62aR5b0Zq,KclkJ.=(<@-22\sZRJUQCf5Xp2'*cm.j_6\>Q83p+bM@;5j>5O-SAs=d".Al@6>tVhP,k.j:4K$`M+aqYM&*0T_7491qQoFDc8>0N!G]EnL2%oI(^S[-6Z^gB>^4\d%='b^%C]752;Y0^qm%r4'XPqNYdu%^1\c&#?C@\9$f;V(qqf34b1pR)M`ui"=*Ok:&J%p9>*/nUsj&1^Aj;6F2p6Td.pMM1gZ<./N!7Ae@\:j2HgND@]WHYZQpW"_T4)H>-]?8FZN7O7r/?'-#ak)9`W;Te3/me=0`j)V!Y4?%>#\[8k92%nq?Q2su/JimHff'_sC\8!:I]Si%F;GY,mYX"]&#CXOlb#k`,W8)/X)ReVk+-m%B5e5])m\FgI`"=6ofIsgC*+8\-%*U>.18!!AP$K\8&`8*r(^>hp8(t4kHNbDd1TV^0)?J6YLS&Te#:23I_ef6$jHp-HYl)K!FDX'f@e=mmiC:^r'j@fkPPaG(YQ#uHb6<4RuM,e.0(c70ASVVg+?=lE8A*K(7&:=Z_Uaj2,pc1]&_FV^f&L9[0i1+)N^KB8psJUIJ@"HGUfn@I*t0#mKWWrEdTill(dIJfV2:.i,JiL[%Yo5DE%f(EReX)ZA@i?is'G6WJuqF'endstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1022 +>> +stream +Gat=iDbo+A&B^9:PHh@j"L7#)p2_Wa+`8*$f^3SX/]mn*KZWCog/UC8Eubq=j#CWe*>f1grV.L/kmP18IsZ?sYVEB=*1)J(?3fs(4fE^\k?LPpa?E+^jEN*qA7Y_aVNY?_M$d/8=X0c8,=a_)&dh&;.)Mu$=%gX_AA[9[9g2uL<6(m!N!R#GAsfUkWPl^3M_\Hd0C;nHa47;i&*JTZ^CK8Pn'&ocGU.e/&R0f3[\G'Cm:Dp^l*J7tMA=SP4,[6/?$aqEgRlcbMWll!$KY+M)Lmt&f$)ad/kXbBsAD2%ZpR`XgYRqP:UX(]6.3I11iJucFNZOGZqB:N=0,2eY@bbeQ2V,r:dAmSu5nW:o`.Cuu2*"8UppUD=\=J!`KUr^em;8\[/*M=[8)5Ad+>NIP/TXr.5(_C%_E(RQK<*m:up-_GNiPgZXbJ,u=feqfiI?^"N`orjB_S"^^@dpWK()g:Y-n7apL+RVk!&,'b&]N<+"/S3XU$(2CJ"tKt#]bB%;OJJAN]\ZQYC,:1h'hesP4+r!9,b^CeZX$_oGVFt=*3:<4gW]Xq_ll3LprVf1o[pD'P/trM4+n[W:)-F_WE=&nX&B4<%)1[5/)>/WS7!(X4"5E3f[0?CeMg[m[:iq^4nglnZA!4^Os[75BoO?%U1.Gk/bq"`poSH4/r,@E@5cUXcT`I;Egj_sS[+F/,HO=L6__:j`6&2@%>jtq+:4e$ATha+RV*s`@DTPG?[M6rj5\E=qTj8Ea.:6KftGUTUtOc$s!l&Tn?lX.r"4#@6Q[>MI^60VV?ae!MmP'r~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1170 +>> +stream +Gatn&?#S^^'Sc)R/'cC3FJWF4I#u]:8lKS.5Wcode5:/>`'E%pAfWZJp=HJ]$:>,EZ>"tq+meuPI/Ni2'+@E]E;;`@!%nS*]uGRS+>^f.f)[XYJ=QRZL>QWi5'WCLp&2V.T?m\=*0BbJr@HeWBB^d"]p8i3=0,u,@\qBCoQEQQaV>5]_nU([0I6DA!!\Y'kV9^Vi8V83k2[%X@00NLIn6VSe6KXb,oQr:*/]itaZhdDniDXUMOE)rfr*V:JXb$&N=qo"Y<:h.S+f2>Kl.X5>4/XW@\UHn=4TQS%lH2'Z^6FO10PqloMKI+,+XUQII@<*]*7X:e^Xu#+CW$Cq7ruL=@fmh725/%~>endstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 85 +>> +stream +GapQh0E=F,0U\H3T\pNYT^QKk?tc>IP,;W#U1^23ihPEM_H"Zg#ZYSVTjVbIXCksMB`Z`"(!*5e"T[=5%?:~>endstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 994 +>> +stream +Gatn&?#SFN'L:RO(&)8P>utd1HrbTf/8S:E;Nb(L`/C+r1i#XL@k.$;kG3d>5XLW;OV#Hfn&b752[0AI#L5O3"i-r>k5u-[JG0=OlY,49_!tV.>'P+bBn8je*Qt`?H&!A)f`7YRjLoe"*KbOujBMhlOj6Bl3`FdS>]2V$$,c:@g2jslD;Vsr3mbY@4de@GS?Y/gF&'OJ$f4rupVsno+*Zr2-R?`l4?ftd[X"BSMm@W0$jCk5P5UG`IrMiTP;S&@gOba.2Q9fBqXeO3(5q4Uen&kH.2RfNtY)l@gWPn-tL>YH1b;b;Gb,HVR;jO%8N11>"LXg4AW(8ePC!D_L%(Pr5mRp!tX&VeiF2+G&eFe*k/8V$T\7M+0XVg?smTJ;*(X%mH(9W3?Q=>7CW;JNIFfPgUJ5Y1;;/,(AhUU$=:!L=2;HQ[LuVp2hbNY$JqA=_YJfLR,1ZVkUm_$GR0B7=csur1JYudtBSgWG$6>(>/r=7""-5qFYUn@^1dGe6\L;.isLh4`uU\<8A&rFjiYcV;C(2_FXBkq]JR`>b=KnJTR^m:KYQR-gI.68gWo-`"S'iQLtnZh-uLD;irGd5K8(:,G3M-)-]^=hW:]**,I+TGne_>h$+g5GL_;O,\]`B.i%iB7K1bfo&jU=?+nMc2[r34\PDm'@0jns?_-cdQY@tHb%U@a\:2X4+e<,M]5#^h&(fueVu~>endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 402 +>> +stream +Gat=d9i&Vk&;KZOMYCRX4_PXn(-)DXKS11"4aL8cBs"hU\@]`Tn!t6:LO]Uca^3hbR=,3c*mqW?#tuPubQLh;@"BP3gEJUR2Y"btaKLO"AkWEt70EWD&\YO)h5K2[j=ZL)J[r0'ft37#VEIU`r';f`,O5p,'cEDO?E):Ym(!sAB!cUA*4Ka/cqS4r"YXM$Au*VXC?u_8Y#J;G?n&8RR-u8.8LDubPU`PYXY"*N:HXDsr8'G+h8)<(4]AH*P!@WiIY-"\>Sb84)F1hioL@!c/#KPE=/juWNuqf#,Y2-Q[9]go.!K#Zjtss)OE?0GiuBGrh>RM8\]S<\gsLH6*m*e!?Ah.nV"ObAFV':3XM:UJ^4acBf2C%3~>endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1816 +>> +stream +Gat=+D/Yn7&H88.1&V[*3N9r)4*K$gM)ZbH`S`PZ\X`S/")E7e]G9"3do6;DblYn8_,8O@@cQ:8H$8>u_!nP@I0])f^T"6[-Ka9jmWOGD6q*!8%\jP,Mrll8f/4<-nUalNY$i'KY48Cf/5<\DYU_#R1Y+C>CQ8m`G#g"Os'/JBb>i'qceh9^%IC>EQrR]>mklS`!4JtYACM_f>O!Tt!PqbR-jq&`lPUjh;&FIpiZPQZY\lHMme>4J84H([]l*7Os8!n0P",H13T"=\tsS!jf6$>-=6=Z$bWH)ohN?Dmqq%Z]1(:k4:jnJ?/>E5gD_KQ%]\.0LpO'&S1i1o;m01$Vc".76Y)T5WPi\FXZ)ij`uK!)Y:j&\hp%Kk9^n,Y_%M,Fe`A3F+!6f8;83S'^8"%5rP)IHl^=&<_QU#^ke*'O7q<=h)b)Mg'A4U3(T=1D"JsE%AF^8Q/IG=SMA'gcS:Uo_X9Y'c_\sD[?F5'djS`s3u\bR3i73-p1#D""Tm1*qcE;`N+^YAM8DChD3u`#m?NKj]TKsGi@Hog0A]@8,o="NGbf*UFflV3r!;n*UKsJPdCkhqe;9%f,p?m9$j7%P3tnV'hMO$iihk1,K*rcLFDtUkE'r$lehm*Ri)N>Q9Eh9Vd*T?-7LN/VFUR?7Lh*l9F?O7bDP2G]2;r1'>BE1e,$rI%N=u*notS2m0lq%g2eHu7:rcc(4Q!*H^RJWHeMiP6CV[CZV8QXQm*n^:$'TNgAP36U7*(e7V6Xamu#@YB6Sf8mUshcu3-S+Ga+S=bKY,^E[HZKM/g*?]9X/(Z]I;UFj<:;WL,#!hLu;[?RM_<@.m9&/t,SaQ3(:3Cnk-@"G3c%=mYUnE>Hp.h9V%9]8%YRl(NNR2RdL,^G[pa-3tZ@VLB3akRfd#_9pCC?$6tSE%q'Z`@OXhVDjN5`hVSuDMajr(BH"dq^=(Be5amg[@ie;Jt=/NR#=)@AYFklGo/.CgWg28ck4rBXKrjU:/3k5dEHVAb1s/Tt[JefAP"@l)]\HYoH.[;q'PZ1aCd@20&;V"O"&CB>@a=._Qa]'K=:Q%#KIeu'jr'ejSOZY'GmnZDS-`-aY#+qcQlA$BZb*;Ve)=L9qaZ6eG4tWDd$PnEDk3aXq0=4_6_7Fk)>^H:PIU77dMSSIG'^2D`sU&;<5[F*\`GZURG*jZnL.m0cRIU*#KB:,8%SmkXoh/q3\pWNB>fZ+Btpdkd!_69ns<*,01?NX8$._&\YdL;kns`pb_V;LSW'`ffI5NE(3pZUs&ao%,O=uqA-rVV&tQhp[.=A6NfO7\Ehqd#tc&Zi-cm)RFe(WkAfR]H,o_+l-jg%^A\R(hK1JpaVR\Z0OZ+dO,.jmT7aJ6,20,d]]^r8'\6$l%>FLTcPG0$X:BqisW=iT*3>L5$0~>endstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1706 +>> +stream +Gau0CD/\E'&H88.0i`?/WH8WYGtZk]"N7i<-%l@jkt-9UfF)N%G^[13='FF0n#U@[`eLMF*_;.SS_%LeSf)@Cj4@'*"tP4q%p/K`fFI[tYT$UFr#p=a`TIUjPAGH9m9X"fc?0@Ln,QJT]bMJ$1dG%@fjdJXAeIU,cGZ-.,CS^]b$Y#W'*KL'P:&EXOUe+DEA@e+e.iFj#'fK=R(6We?:dVOHmFn:(]C-`HDI)1#L;1i:J$D9O[L2#DPmQ/5)BVB>>4bgt(G4Z[=`]*CUfZ7I3Z(dP7lSNWhSR[S*(n.[VU3.D_7'tTN>DoY7].O4-j9pCqf?IEn7[G&l(\)864JlB76^19:HrglP%M\\7.S,Bj4d$Ku1`2e<:40V7i&dA'!70\$rE?3toFZ.C.HO@I+Fjk)97rQD1ie=ND"Q>_=;Mh9'J!tM\O[A>"a$e[e3XMVPqLu6U!`"t@`:gB_.0+fPWVh-ERp@)WR*Pa9(uagW3]ST2,Q)UKp1rWdkXr,iU'M^S_DCm8S6oQQfBn'+756%'XJ$:e6:98NHE;3)2TgZ:.<+%Qpf\dLl^CoR<)$``gg!rH1\Pf<248e8?L%3MJoOh2+sh';mDE0?C''A32n[d.[fpCY`&]$MmCU-UFN&+MCPtab;;6q$^,$e\8BSZ-bPi`E@"Z[AArdRR]<-4N[A\MY6D'XdRbsePN*l-=H.7[km$e2b)@eR;^s^WT^\buJjMrYkK'jcfEZm*?]&_@Ea25]82+Wc.Nj9V)"5X#E)*k64A@d"f;HE*>:5VR46Ns&!B)e6@=UK\k]/#l^b2DrR.4Z5H7W0obPA*dY"D\W&hHrr1U6YMP#kRG\.\VBd*uIBo7J"S5B@k#)mE).%\2%n2Nj.N*77aRo_)&G=ee7HV`t'A.fPh3MJg&?B@tZis9\U?n\.lYkL#@!olU<((dai;Qko#c.FYCKW:_4HVJ/IE39E#L4-?3m,g5c:_W7N9cS\P0!M@bE0l-2>7][s`Qe\L>dqIP$fV*4H"/a/8U9#M9,;$F8I?Y"c\,XoCX1$0Ve460_HeEKJK84HUn"1`0/5`LN5Y17Y08PBclZ?^RSn-4Qf>0-g[Es"eU,iq/_[F?SQI?<)H`5ApRij-]NNeY!ABRTQ\oE[uD9A=K?8Sb79#Hf[+fA_j(kO%C?59,%\c&h01*`Tj4Y]L<:2YFI%)^dQD2KFR`r'FX.gfFb4&frb]fjm_!%&bc'4%[oG'n7mMY^r6fLL"]L_+PulMYp1Y/HrrWS9?plnhOkpQ\2uX$#K_p@BVTc(]-_:\tA\rWVHVgDo"i,CAQ6LnsD15Yu4_]&)q,63FA,:EN(OlNXSs"d~>endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1224 +>> +stream +Gatm9IrF=9&H/4s0g2KKW=lFdJ4&(TJ2>/-^`<&R=pYLPlif:%]>!)YGP'@.]_j)Z;CS%&!$Yee0ug\d(t!::??>oW,;KJTiJV&G#8E5TQEK"[.[3)He;8s]),?q0,'al"Zj?U4CpaS6`\iKMY\.gYlg)3Om.SDDG9Wrs3#c/E2^Rl2f2`D:36hh$'!C*D%;1>O5i$=^)dhhfX4esa-7j24n*r5JS_B[Nf!TE?90hV$#-n2Q\U0@gZ\Uec=NrK3D8.lj&*3Z(O%/K7Cgl'3p2S&YV,]S>/5ErTF2IC,^dm'okBFW`1_>d6k$1W//8E(+H0Dld#@jHEn`uh#()@l]W5.I:J*dC$g*d_4k#@k7#$9`kUoXkch5(!jqT6<2-]2*(ZX536(GBS,t*3R!s>L.nJ/,*=ekru\^!k+BKDeDus%`sUQ8cI-lOs6`#YJFG?,goCcMAZ\`;hU"`BL$3K&/^QV`A=,4/CMn^?EFr@9aHG"a`65k#4JPrAcGr/HupWP_B;K.9+qYq-Dhcj@&\`O@?Wt<6jI?+cd/I,[gN;$VKpOU.`?!eC\bp2RE,l?jTge07O+[CP<[@>M$UPT%)\!sP3P`8hTu-aA=S*EYmq["lOCk3N6:gRm*s3[BQfbu4V-;Fgt27R7FW-3_POM'cF96KfH'AS=.N;mZl"r28_J&+)t8jUh[J!5/KSiG$?!jEr>`4*Od)D<"V\g=7:J`!5tJQ5"0I:q:'1:'8=$K)7rE4e5W0oOEB(1CHLHeT\4I;1!P/'J%c_Yp7X+&IqR&TelKAp&)3n>*_5uU0OJ.BUj9g8X*[7$Mhd$+O+"Te^[Qgl-f?nQ,BE]rY:IL_7g)lSP*q8?\2LEKZ3aoW]Zh-cLc3n5j_dfp2CKKB4/b9h5FHMNZ"u-"YU.B'8dbLn#"j'iMdp($sGsTIf^4F'@5A*UK%TV7R2EfoiZrU;U*8d=PKnpm[s54*#.bdqXA?[mLB9%MZ^PNhr1]~>endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1115 +>> +stream +Gau0B>ArL\'RoMS302;O%Z-BglPhET6D?&9nkuI8b&pCtZQ[WJc:H0_T4=(*:BR[f#R'pmmlQjha+o2+0B,1K'&YAHmstHF+C5&)g(D8%(rnT8h2odbf8!ZH[ep"h+$K,/G6]V26!ppK6cUK>"[KX7.e##dCHfIn-dPR"h83hF%k#ir#k",jbq`#FSA++_#Rjm@4qHm.cFKWcI#,.H6^*El>4mHZu;%3S,1H1)9-W/TmfO=tNb0s$K11C(+0(N2dL3=+-^9Z>XR@g?1b4V]&.P'N>6W%)?Dj^SX-VMAiHVXdI/)ia*g3\`C<'K?X?ud[[1>[>Pd4[CV#VAfLC9V1HqP-C,(B[7Dl'EiPf$4#B;`>#^cM7lE,TX"q.'ScUp!cfmkS^P&%[?4+,IX,aC&)L@qOd=-aMec>!%l1O+k&QQ0Td7'M:*P2@X_a'BNO)D<'9Z+]AqL$?9$MJ3n=]9NkBV*!@X=';f0,fE15J,\9FY:@BJp@'EjnOTcL;(q*%;+EIe$\K3sVTe)nB/Y9>2rrGHmXb:)iSI:BZpp8m7M(P`"(/1%k#YnjG0H3#'g.3!HG\//Pbb$rqcoiZg'@,#>ZrlYeacXC!i\%\4q,U1*kV[F`DRY&?pZErmp#,q8^lQg,U:WJn_7.sGT_lN,&mE[]d;A2=j>AVsF2'6mmEfhU$DQf*.O$"Nendstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 570 +>> +stream +Gas1[bAQ&g&A7ljk32MH97eD#^85r](iY#4eM.kD>!#qbUe4NVeZ\F6I`N:fJ=m0]GD7okN=j9i]5M!W?SbC-1#`>h*q=&%6aju.D"M?ST/u-Cb`hj5Z1tU9KG4P%?W`I*=kUX#8"uq.MRqmZ5kZ)UVg(DG"+/AVJ6K)$^Tt__h_@KeY2WEe,@o,c6l'9/mr.3DLl#`J$_J25pdg#pI=Deo?kW@C@9O6]hm`I`BMg_R-OHkj,,+nJrCu8Qeb[?$hW\3ZR.Z42*$_l6bo-:IZ]!9S;uS6JY-[9rBI9eSqD11Rug:2Ddb.2eF^QmUu-j-SZ$=Nq37Jk.u3:6mN4C:?MOTUmQQs,UD8[%8n6n0rD==J+.`RT>?C3r?q91@a?[6$*k=%F<7I('WC2ha[:@IT)5oaFZJ,+nIe".BW>a`p4i-;RTA\X&f77GONq*1endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1505 +>> +stream +GasIg>ArLj'RnB33-&#UCl,D'!>gRt2C2Y)KMY??@q]Wfei`BB>talEO&%VQui/MG:nLS#/3e(klq-[QdE8u_ql0(=4`P*>*l]Wo>Te6A7eX+-X]_&mhXC65B)*r4e""BT;U<9lP,ZB@/1+4A)!U-p<@-V/<1:`?hgXo\Zj9[1_gR6[jt=sCp#QFL;Zt4L6bQiPdBESmSc?GS:"n^rA$5(W=)61c8&nNOYaEQgIQ_.g6>@C5\5DK*G#i3)1I&E=klUjQ778ol1arCi*NBDNqTi*n-GXl_^j$oP^!l@8eIMp!ZFJBuPBgQ7RUMnXVCdcUDn:lU,6THhLQ._6%:K='9*[S++&5\E"oMVtMG,9b?"aru\Vr%:nVaUl!@@S[K,-7*'EUS-ruAE&LB73fJN$:jr`=ii"e=&)As3[ps*ZUTVuI[k4'(kSS'*Re,]IKZW_=U1%1diA","44Xr#+k(-X5=q&*3j"QshX]61S3I,,E9DD+b;BLb5Ta`m)/#Y@:T&1WB@&7r@`)qgL*[+V[&!sf!<(/piZ[.GVtPj=aT5GZ0THZekAT"En<=QnojrX),4BLE*:\O1Ie8"YOXuj*f<+Qg4l)@>.NIHC.gPelp50\MBV2ZP-3Y2e[G7Oq(S`9P)k@*G(T[:]PC2uP'ok&YF7N2c:UVD8P"A*ASsRI=V'C5eK[MVuD$X=BnPUlfQ910HWN<`GB9d[uOufmbcK:\KdGfs0BP\PUY9reE9aa%a0e1GBYf;ro6j`BB+esDm?bica1aN_u+C5]YM$l23-agalu:onU#eeUib[,U8%IU_6Aere$=&9o*)eCM=P#"KecM"Wu0FmFq'JLE.KtY/gfke=/XSNnr`*]iD6o%gW(?=QFCDYOk;GHm/jK/]V1#4#/]1JPCEjW[joWGr5%1L5mbTjb@;KOi#Fss(@I+3?srr_h/Am>~>endstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1216 +>> +stream +Gatm:D/\/e&H;*)EDSC*hAjM?S_,g(!SQ$>!?00VS530.0GJ*)Q)KA3Q?l"!qi2BPk\XH-9EkppFSFSHF"^u&'Dr%-T4S)=!%\&OKDDQMW"AX$CKR".(bN7J)=q#j^9:"Wo,?hEu9dCTMXJ4JZ&?@RT:1,tMX:3KhYVb92Iqc-B:jY;Kl(2Z[FWjm%'2?+SFCaDDCd,c!a-LSZ"\GHoR=@]^b.&u"#A^/Wal8+i1dX'sH,fbK;is:u_f4[XQ'Z3R;[;%L_N_,k$,S,ZeBA]>qT/Ug-:>D`-L+1)_@0.TK7L&&s>TWC:8r1O6?7VPc+_D&IR#Y,PBF+s"MP\E3?8,FD6\ZgFq#u61<,_:`L'r"2>BSBb4RWC$Fn5BM4(K'4Cb6/d19G4Q5eKq&$h/^SG8^hnZ)HRZj!9`PC.m7Kc"HO$9S.S/d!4Fc#A(].2q8E]NWI3!R(Z$;rJn&<-o!pM@m(i*lq:!f+FMaI?QM3rtL2:lU9R(^ic2U(lC[=q[?WN#10F!e]&/kIX;-&nG!EC1*=jd-IAA]n?iE8`RL@BSl8IRE:\2/.jjd+IHro-,eWSisAq.+rDt78mL];K;C*L&'c.e;Kl\gu"ot.9JgT/%R_dR>6_GPYEp."5hT?CfQ^CRnCWu/4m!+M(^H,^A?Tens+BY/[(Z8*8-7JK3Qfli:=mLrTrpBYrMYF"=p11f0L=&>VEOf&K^_XVBZ'%6./7(2#CI^(^8'lIXR_Z:PLtB%kFZ?c=_dKa"Ffp]CP+".lrZtWQ<7tKjrGd6q2FkW."h&^DgX[=dm&\2?%/pJ."Qta~>endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 656 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E-rCaI>O;eIj2]\)uU/lfurc`BikE)C3"&*l5sc8VMXTLVf-I(9r#"Ap7u$DPAU!/`3N7H_2pD(:;c(_//O7\fL0'_J0Pr34?SBqoN,&h7YHLZge+lM!W?mc6RTkK3I/[RbloO=0Y3qfrt'-4-JN*`!-!BCYWg,$fSJi\)"l.T^DhpVph0[!:4X+uh[$@nRBoWa?-J)#&S&VPGDQ8>-G^'#P2s/cqEsR-h;mPh`BK1YoZV,sD89>tr.6-o)[IL3/?kR'Y,'[Ff>siJRK1+gi:-3kNS.g2Tjh!$#_3]-#]VSq-JVTCf@oWgfaJ+e_Kq:L58^4nTo6Y0r.592%4O)Vd(K.e2nKW3(_G2gFj&qL\p&0]s!9sk0K0\MR@^7s1-]ep&iF,:C75$n3ZWja";YBHsLOi9c8BL.?%<:LGZp?;act)BWQ2;G$RSLk_1:E+UEhhAoK`$VqU0`V];QLC6?Kg5MbYD<^2+6g"nS1fG_~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2066 +>> +stream +Gb!#\gMYb*&:Ml+bf^'%JRucX7&b+XXP8&`AohtL$5eXPa(d3JQ/oCRGlQPiIul95IC9:OT>;:KH%Qc!SM?3BL.-@HnVg">_g%=/Pn6a#tl/gt9DC7C3Vmk-U2_][SDY!PoHo?QIfkb]*?nYp]&S<[rrYtdgYCY*;)ORZ.LZ;@O@9!aQGncPVKWr_]/7<;=HAPmV]J1(oRm@a>R0#>kBfn6Wk_Ta,riEiJNoQU4G),,',!juM?$3*4$6p9\'KfmMUr775DAA$M:PfrPc5P1V>=O*+6tqm@AX8r'q;Nrd<_,dpV<-BX*iF!ECSdaSAHW`B837PDC`F0r@#HH9i\JoSNp(!oVTV\u(EJc'g,2b5lPXP6N'Rd0%MN=oK^bN:nojllXdp#)cTuOjjU4E&ibHsV6GB*I/Ci2t3[g[oAL8+f,-Wk4J9$TJ%(94eSB*U_>.`Y+ZdZd:"mo0nA4/D+KiJ)+9kpb"]Men;4_Mq_hcCuuU[Ia9$@8Vt,`C-H;DR23<'Ie.>Ai2"A21h&XRum!a$X1;U297,2']0e9jF_J-n[sF@A75CmM%gA#DFKHaNF51i(\3W>!h;^C[^+M$/"n4sS.<,fM8?^+gMC0B#V)Y+A2P)+1kH'1HV_tSncBLr"6uXjR4WSsM\;=qQHk\5:`q*V8*r+Q^jO!(=n0KKXZ++0SSHn%[-R?q`NRGdY=@4-c$`]QT/S).!bFSp`.Z$ToMW4glQrZTcUW(Km%Wj)fMQ8[BPo/QSWu0t&jWTj&.>scnFbDqgmV1I;>%;I];jC9D9cH\(Sfk/p/Iqmdu$qD/&_UsDH0J,X'\@n:JIn1l;i:I>4E/>>4JS+AT]p(e?h822Q+e8eB*;#Q`O--2Nq>mEn`^h:;].rRO!"cf20n,KUG<S)XhmI;SHq00QRBXe0.WX.'&GG5c=E@VF$Fh*g.h];-[.T,Qp%Fs6]o"/k0sp%D"$)I\M`0J@TpNe6KAdoVRi&BEl0iu4bYj[iR?dIK?B_kV:(3C%t_Pj<*:?i>sUf?n2om3UL[`UI9s*$71^^#mj@Na,rH!H+]^BMpVBXl)];;'c?kW.dgK7A6@V,rd?;E)U'1K%e`4Qa,,Y`,f]c[^][*/EM8eMABb(l6q6bR>1I@g-hk["^5MpF/cAZ7+j@(3aX<#%h"i+M52[168[rGY!DSb`SU[i2@h6#IuVW/Pj>i0=OCn9Y+sns.rJ7Lpg$_^0T2,>PF96JgZ;IJB]/SuRelr['ZCOi]#l.P_DG"0endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1065 +>> +stream +Gb"/&?#S1G'RelB\1_OO`7!:4dhDpoN$21>BT0YJou/1OlOhmfEF8t?hmma,>85`kQ!cg=CVO?0H4b]nRe&GccM3;DFl@CV!*4V^I;bVfd8Qg??\$0mtko1J%uUFB:"0WRoLW/P'eQPE1TDc:NJ,G7?T-/mq#9.l,#%-Wj?\Ba#kWG0VS]G91\lT0",5-ZRpU@]oZmeu)1gQ@1V\a(51ci]d,]tP;KdN)alZn)T6Kjo\c_&LIXF1<$W7,,)q:QkTI$7E59(lp3Hfg:H(DP[*dh!ePfafOUW3A^$I8>.4!_?FZbOp2V744N]WiAFX@%cLQ+CunOgHL1V==__I*lZ$'6n>W@fR=BkEBF4QjZd^$FN3#g&s7+OS@L$dQX:)U!hH]PM1!+uTe<]33*.D*E`s3G)>2AObqc5*J`XTFlDHeX`ihWn7o+3-^EWAn,2@Lo;lR)V]_uKJe0DOt=3Jkp2l^=SF[j=(-j82GjMp@*W$nce)V;s+IosjRj]l;Stk5^'LVZ%BS=br;FhR4g#$]T"UNrp9f>5h!s6u@/sA<)9Y4P@+J*kR_R'E%LF)Is$%N#Cg(Ji76jWJ]/U8>eKY@=t)j(8*I=cfSDG@*Xd6`9r9Vn[IITmgu"u/ddR-t;WoI$$_GnI;Cp.P=KO.&8**o=ab\`Y?B4WIVmZZKKX1Aan!cD.GHnV33.X5YT?u;=`-l<4eFZh%,Ci(_e%3Chc,CE*QT\>.r[dCElqCA$)WuFgXhAWMDEX,a\W;EUlFbYGDj/PK]!)5V#DST#&RWZAd,oAt-:K$@[eh&_Io9XXpDmc@pJ1~>endstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1267 +>> +stream +Gb!#\?#SIU'Re<2\F;2fh--5BW"0-c6^D:KJ8E;1n#_,U8@6W:&lje2C(1".]9HR0[NcZ"NA_Pg#elWdQUg4f8/)=N[/3Q*J=dW3qiq4oYZLtg*f%]Tgak)7?dPof'LNR20953MY!<(ATt@A`\tWDWLY#s"M7jD`Nd:lXX4/P'?G:s/],mlV:Z8a\E`pK3J:OIkgI>eZ<$+BdC/s9hho`%:XAoA&Bj02l?i4:6qZDoXi;C,qE&WbRKeNeA:k_"AP/1>2FYaNQGMn6'2BOafs0IeM8u%J>%fq[i+b9Q:bbU@j-WtkMRH8G_3G$<:gl"W<^2FQ-D:#0R(J-4nu/(NC%VO/M#M2j/T+cbEZg9]tlqF'4Fm(*WmJu7S)QZ_=F.)ftLiK4A5RPPq46$T^,`ZVmEcZZWu)+/4ig?9TjYN#2W,4Uq2kY^qF,FakIW,_%Pap6?f//[:8esnl-R7f&[``&>.lh(fcj"GJ/ZFAE+MqN1re8,O2\F7I,R])sFgq!i@!iUZc,K,`@2ZEtsCG5sS^`$Dk>LN6-CfN`Lmb0h5t>5bQ/Vg_:LO[8`Mh>tH\,'N10q>V4\M`EXAre20u-<>tdm#F4=4S`)0&d=B@X9l*";hf:88Y<_mHp3E]?!I3jBg:hV*^qH/Y5i6`[T]8L9i8U+8IUL8d@m7'5b(endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1449 +>> +stream +Gatm;D/\/e&H;*)EH!VIhIOUN1=nD1!?%15"d6]=($pPf&<'$1lm0`=W23g^s1Y6rg6+lb0.R,A(3B6*$_Mc6:LK-2PO^M#!.OOto_en>BAc343Hrfc]7N\ZpU)s-Q>^@hS%<7=[r8/-dJI@7Ypdj0.O>H=1o%a(Bpc#KLh3+%`\EgGlN'p)6X="FGAL5aN),^I6LQhW`&@Pn;W$[=nQ+Gaa'_]hagYX!Z?S?FI#q9B7bp&"]&+#]B=KN-A4Itqd5k@iXiDENS'!^aETOq<,)ZT.N2bue_[IFmDn4*Z!4NgS!H@miBiQ!8t0R!]2Nk:0I:BGR\[`2s)(PiWm6kCHm(s1Aot>6e?rZrb0LNJR\F_:ZoIc?rZ\*p_gC$'nGFFWC+[eX5I4\6IK/CYo"j_>SYk$'*iN>p_VA2`n[q;[Ebqk_*PAZ-Y(5+OYUdi"'+bV\SsV;[_Ti[1fGgA>[O=Pkp$2CB]K(k)I5;uB#O/Vj[USefD"EE9qXo@T<`].7UrfT2%3#C)L5.+E6uXk&J$9IOi5"\P.,@\W"3qma1&mR\lGP<0.EUeo41dE#O%Y*UooX$]6d,]9.e/)+*F!M,'WKOe[V:jAE\iLY&L`[k@;:sI'?c?/1a]k+4r0Nmgihp[Bfa\NTT)6A_[$Q&ronM["ro7e'SupGLj=U5%tTQp'`gspO:Z5\R(ZJ1*5HZSOHC[J#h#\_%4gd[j4Wkk[46jNFiNup)MdO2V#[$9WE#FTb3V(orC1OEP,_7[S,B"bDKa8QK]Fk(=;Kk@\$-bi1uF1`Ckjdd#t?Wt;mJeHNA;k'Ort4eX#/G>:rLp1QSeL7qdB].OR/HQ/,D'"Gu8_G.+<:Q%6Mg;;Uf:O%h!6i_oZS[lqF&>ZNXu`i]_G[#LJFIrKKWnE@g9iUSPa$akAWl)e2hJ$N?%I@d-S@:tb50&E@07Vf,-#-D:5JN1j(HK!NM&IrT\Ajo%IA5/p13fQZSqCLZL/&P46BSX8n^T0&:@5S`:6()L:T?55(ZD+6]rC1]~>endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1579 +>> +stream +Gau0CD/\/e&H;*)EA0)^fc4.X/Qkir%p@m7.?('DN+#(P#cpEuD"JL+8n/S2mlOFQj&^Br49[GbP/hoopY6e8!YbSbr>R!^^JCMDAV"F1A-uA`keUd4_b&mf@9"iT*k6+F0YN$m&rg6^E]VHi6DUF98&@j8e-l)RJU8u%C_JqWn6hF;p0I1;meV85/_G<:;\mjE),-OW"Uua#daucg2&o17LA%?6;qN`jZ.3Pm'rlM+&FOXK>\'+C^oH&CN$&8J+VX#P.pk?&9pcPn,H4j(THuei3aTGoJNaAh575+(V@hFli,Lj6h:E>?TEHLs=jIr91sF3h0tB,Ci#P.XnG&5i.\V)(4=(D:c*-"Kr&Wm;%rjP1grXQp=]XP98N]?@1OL1+55\(:l&G"`l3>gKhTc3>NDY@aPh1bZtRfm"`05mPM+I=uTZ[D=Va:o2(F#W!Q9[c=C?5%'l?Ys4ee1NPOjkkih'5j3p`__m_V@Le#W&8(gIqY#%8#i&40n@%r$OVGkT!B.tX3FOif==IB9E8#BXp*u0R`LOTYb'nC-(&30S[+erQ/2$kL8sn&KP4.>AMgKj\34n5q6!A'A[jZtPU:3L`h=id46R`adl*4%-$H799a>_#F2@!,d=sW@)pW331\H]inYg=*PmAgL-rN8E/McQY8&I'i2HMhe%56\XrS9('3?6r6gtaSohX>cVZbr-"Ed8R5q\`o0Trok+2cW.p8YN44]#B$4XpOR.PWu@JMcGT0)m`.kc.,n#ZDJQ#FE9kET.F1Vl`>oe&&n*+Tj"hu?=,#A\a&@X26(*7c!hV]9]55BY#(:+%@\-O5W9I0DLendstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1711 +>> +stream +Gat%#D,]1K&H88.TeUV*BL<\a*L\aIRqWc(Fb\aLR_(5?d0P)iW7[DuA6qn)heuT%"2T.Q$j3f2IC-W?h.OFE7ej=Ur^Ic8T;Lu"d4X1%bGGU#I5cPoVT8%Bg:QY;<]f3"fm%H1G5U=t*_Q)(373g9SI''T4qUuj7W+umoan/>H95S_HQRuhCmlOHT573jj5HBPq[B)6'#qK+V<'i+)b?.nMc=T%Lb..3PK)n"!J>1//\`\CY,7qPJOc]XWQ@@SLN%TiRn\C:kpqfdO!tI`@6`Ng5+lhE)f@SH;7GLhjDbNqgUdO>KEW8"0@>RaGoSYo)A??APXK[g!Kg&d7)gQob1dI"LD8f`SJs]b^9N`j5a6GP]$&0'"oB>;gtkS5"hH=q#5=Yla(csm,J;<0^k.W'F/%3mN'YoSN\*YDc)7SK&=a9B@HU6gHGn53iK/FE4*aBT/NSA@d=b8B=ao=b8fk+_4(0ONebq+d@!t1Q:e5fZaq+`V=r)$^0*o],=C!8JJ>*AP_.8jmKfJWYd?!=Ko&)20uapU=!&$\LT'`T:os[^lfCdk10D31H:iP0FYku+q07W"MQiM>'f]_kd]tYM&7DHZ,/Q"l$@(fc#GTjY[5_f*>hc69Vc6.?*3]H&ee@p+p'n,FVruJ?I2mS6:st`n-Z;%+S.W*1u8+=P$hEq:e6\F1cQ%\H6K$+KaWl6Fhrn?_njD%8^;L(6;+Sicmjak6DV%g&Hbn0CEXpa)WX[rTWOr=7on88Rm@Ndaar>?43(;No1Ombj9o)u@E'd(e2lXHhl!)?=K\aOWtfeqSkY7]dJuAANM%EM_gZR_KU[r#;$qQ;?8tH16!1,@eABs/<&\lY`6>F)ACsVN(jH_E\GN4>1g%IIdlFhStcZoLN^SEfN3&!XKqQ[aVP_$)DR+8V?+Y:fILA_jh4"T\om_>cTpu&@>TQP0I'cIFUm?7pV/!8;H='O)J%jl+if&<`HI@%XT@G%r!X=dUj]_3IFq[@B.2OaUtf2o>+.!(mAM'5pbI'q=SrQZU!8k/uIW@jmVe336Q-]Kam>HTl7bH+6?h[&a_RD>A&m_YnQ1m>uZ=L5d5hdeb4hH\*[_'0>PeHe2De2:QERekQW*L4rTN[,Q>Q5Nh'(H%H,bZ0ME?F)#[p]9kt)%6(A)!lA:6cohi9=OR?EX&>,Stf=Qm>L]#5.NdlI7,T(0rS>Ap2QEFj1X9ahXLu'?TTof6Zi\"?F\g&f]9S$k1Y,-Dg>[AKSR%hJ]]TU%^hO6o4A6?eD/Z!qEPP.*.NV"%jd@#cYAT[C%#8ep&51n?Ejq~>endstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 914 +>> +stream +Gb!#ZgM.Z^&:NH>(^^GE&7mNKMd,b66:q?WV!YnH+fN"VYL:*QdcNm<^NUsXWFNsVFkqt8KdD^87q[iojFN4rcaHscn2>uqG91umU]l"-:e2sQRQB&\\$1f)Lcpg/aZ.*OcHC:NMcSD&CS%.SaW/nNb*dm//Jn48:eD?kCYV+(`9a(_rWG]pngRlb+!8DpXR)Ep`3u$/^>l$X3\I>*l+mIp_0"B^:"i).7R+OFJFj2s=)5FU'!*+0#-@'[^9duW_u=+kYVEREnCT%?^_\U"-=_:63!<6i\"]9V+f*Q50r^iuYZL@QjW`dTj&6_gEU_'/qG\.n:0fs"oAYSG5lB!J0bPdp+,=V?S(=n2A(]q[Zg=84eT1nqal*oZg:HE@cEq7(p%f!%FTce$_%T&InRD\WRMJQ_7/M'gIpfFVlUu"KB.cl]4^d[d#)*B"c(6(ZGp,-"[Vc\*W?W-kI^0KAaW-hoRJZ[q=!KmWoo9Z4!8G?RRuUm2PDS;i`X3&fStYk2WeUWPj8VeWhQCSlDeR>M[1qsp>HYS4>BCj&SVkGa.blCO"cMAgQCC!;#bDRXCe@d"5PGRj&GMBG3JA]=r8FGDK6Tn"52!uqUOK_Js*u4&_!fK%Z".o)nPO!<0b6IEc.cYb=IH.tW[)P4!;7eu*W~>endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D-!LY)qe@O>M1,W]$5T>GBhV!q#rZ*ACfMUF&KGo>.i>al-\SC>"NTbMO`4G(I1[iojb99$A.b6rE=JUNeT<2_rRR1h[U^Qc,i;b0][5\N=HB<4LlrpY!Ib*9=+erI/WKK.\68%R$U]YAa\nt+L%Y_@@Zh]tV`[15Rs7f>^hfMJO0PTh+Cj9'eb_WYlL!PL'B^O^DTdB[Vn%o%^r%mjB"=3Za7O(SN6_T?Ic,RtjH?+k'CK^\i5+WQ"?[fZ=MUl*p70Afgendstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1002 +>> +stream +Gb!#Y@;jjR&H1HmESh,P$A;H6G1n2K.8'hqKs58(&i,:E[u$ZpVCe;2hfj7,!\:+t5"u;n@c+eA06b_XeF6t9h]N-5ntCAHJQ2r)%b=eE%/_1!rm?cO.mM^#6K@F>dVN5H0`j:KAg:S$@BB,)LOh0He\O;u;"^7].ZNf'mgNI*X@p&@]?\3ENr@Mr%>M:rh6GG6bM_90s%_bTJtJUHbmU)NELu:J8U#Vu&mC$n8R'YX$Z8eP=`Gcdkg4YpM1hba`(<@,aq[cIE9OH,87@NKg&`'rb%[=3N7LnSf^LZE(gp'8InNfG`brij7XiPJ3,TPdA'_Je+%G-X^>4R<2n8/+rK2roNj@TLGQ9&*$'>@[YG!VZLmVAgS[4ep9#UgMGfTr\6n3b-nX>$`S4+X31Dl(+oW`Ee@8_taO^b6u[$&A&$RSlbL,<*O7HC8W>E+4%1X9GB5qKkf#3.qe8Aosh,#1`e:=L2Z;nXoVa=[`!oogj$,@Lb[l8ICV-,_$X,RG\*?q6!8<$0>#0@QtM(MKMT9*"-.FPeup<12R%kX"[5d$l]?@"rh^G;EQYI5WK/lGD%sbb2Pgb$@\CAV(Hhr#JX]=MAV@P8cj.P&b2G6Is;VP@cbFk.^%YGPnW+%VEcDg,]Rh79;YV+a&on1HU4:IeoH3%AD$I$gN,$A?hDc2$+;-W,n$J^>9J3O'/M*!K\p9\:!2tqPEoWTI\lc<)RJpf3cp0%HCVg6E^_;NQD/qrlm6T&"E;R[bh8`DV7)e16j:cOmbitMiW`^2cj@SkPK`Yendstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 781 +>> +stream +Gat%!@;jjR&H0nX3,'Ib#mEXG8iJK(6g98'(^'6E"N[m3K4[a8b]YgFec3@)!d)cjR4KOMm_*srpM=)Jd;niV*s6n&d(FS=D$+!oHgP&?HN9+,IT>0?j\6P/?)QGj^$-)[?4b'2ZZJ6]N!X3<3E+*V[IU.p!:9[`;enHK(lf]NTf6G)D")QMj#b8na_4i_p@Fs&KaA+D5[VO19JA1T(<3">%P!tBm;9bp"FV0.Qin9(".C-nq'K&8+ih8%4@4f+:om>!4dai!,uZt16gk[NSQAjRb]KOJUWIX1Lh3K(?;%RPRb(1\g2CS0UK+1>ZO)701nf`B5Ji(/JOlq1s#fL*IpHj*Cf*fj65i]f[Tq<;Yle$<1q_Z>[E'!OE1Mb/^no,Hf)n1T?t7uHn]!\SCH2YRKm6:rT^?TS%un>ci4`15VNg\6@%9=C#4sPHkFm1&*FC;WERB&Y*/G:*OjLZJ4u6U]RLNV9M/W(P*R!k>N9!BGfl#)('QHkST2kUmWXYmJ&lfaGI(s]PGuHUhT#944s`F[=,u-6jJPM=A3L:5<5BrYm>8"#ZC4k8TRQ3$TBh>7hbY`5Fn7Y&I$,eCa5M^E]4/1*OBDWP#f/*7,fH%^@,cEk>>33UiH]`MTHQ69+U7A:a.XP$8iios4@AW/*+FkW(T\]*Lb$Nac7!B%e@'1]sWp#p#.+<]-7W]PZ4<(9Sendstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 632 +>> +stream +GasIebAu<%&A7TLI<8?j7MH&s)jWo]$,d\AE62ZCNR5]!?$Wip7D:r1iC@it];DB^H?uH8]&]R2jYcL/!>c>CB-+\dU(lIg2afJm&9[D&hBR&'_7A0e9[:['mbeW2i]XW,7bjuQZgMUrqDD3d.D#bXccpMdm(pHJ%'U(fL;=)nf>.DM&(f2V7)+dZ*]BF*E/((D!rj*V3ZC1V3!kkE6jcFd;1_q'[cNh[qm+0sm4WB?`ar0219MR*P7VVQ'Ao(qiu;6r$Fbf?dRfSE5Jg!eOij3J^c]6WM9l`1'ui;!N[H7'XpmN1nJt:1[kA#THjtD-@.93\f/MY!g:0U`gWI6-Kr'`M.mfc9l4OY5l<;UBfes@-G,qmVaT7XQ@bVlu"aa)oO9IF4C:MKN8FRa-L5a&gcS8EgeTR?.d/tro0&q&&V"t)WXp^+u.V!:Jeb'O3(ObdFnHuaQd"G:ojUT.FX-\2iR/[rR>j2(hA"blS~>endstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 875 +>> +stream +Gas1]>Ar4L'RoMS3%pKZUkUi4P4@*iMO56W1n?H0$(9j>]K.cg*'4)tNl,F)0![`MT?HtWkJG$2_lE/b"*fctrks>4&C#b`S-D@`#c!kR2f*9o#N.>o$%d'rH-cZ(Y^MbuI1)d.4KVs*agI8dlKAC:oX4PF-Hu5CX["T+,sj)%;a@GT650WF,M0C9rVg?`c^#2"HA/1r9@SJq.h*rR'.NLkO[nN`EhF@8^@cgN@1R[&rGHj"Q/3C;:sYEPGTJ)OEE4\-T4?ED]If,s(h8gCKEMsEP`eJIZM[Mj)"D9V;O+^7*bdJJ'$l[9c<'p$em`@Icq1Xf/;dFBqi(1bH#-k-9qO37/`Y7:q:C[H(nIGg>KUBg&mFC^PT?%8`M1l;#aJbkh8Q3il]$=Mn[kSH?"\%*M[*rs>RN`ZG`L9F?)9S6_T$\Q(:U\1R`Fl0CL)>BnTk@$Vrr"(8St@56P1`SZa6OfI%bUDTWYaGcqdH]D]R'iDD%!*fWuf-M7$UkG*o9'\YK:g!o[L(91J-D?_NY&hTpFtm;&q.e%N+I]YgkV9>'.#[;AB@1eX(tDLjg2HqMuu*S3l)O]NQ&T2%g-b]N,$f.a2;P["R%L=]OAC]eb63cc[X=###\",m^7]c''o?IP`4V\QR$^Nh#j],.Pg+BYPkH8B$+fq^Mo9FBP@>-09YPM>D<\LkkX,5Euendstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 926 +>> +stream +Gb"/&>u03/'RfGR\1\M42:=J_8BS;RXCDkU6`'*Y?VGLpRDj@33/A(7hfn)r#TjC_5sj;&8032.;?i@u+."sJ6-d&2*E-lN9J&Bq.C_,r#_>Z0p=U2FG,OkWg0:K*K<*%%Vc=:.aq3\WdNH+/GiU$F=Q:keUKa*jakK1)d0*E(gW(+]mQ5\>0Kg40l08=m[rU^45+QI'De=kElO=G'#EKN]scPjf;:8Lt5a>G2d-KjE<)qnjcE7m-d5"'99*Y3gG85jG/g(2fC.oh*01fKoNAqd.ln>a=CoRuQM^"l+iQ9cVjl(VJf3_4K,)GD-A5\(^HWA]BFJQG]GF;Re@^^;\ga*X&(lA,`3$7s5`TQV,b!@8&-'V#4C4m:4'[Y@d-q;k()/n5ctV;hI_[,e"PQ.6%0%$NhLIrg$2!U68.07?1$EgV(UA6Phq(JlQ.MY1rAiP?r4=T4Kf`M;4Qm'eG?1Y[`d8G#qPpTB"5/Rg@ad1grJklV[QiG*'KkCoBI91"WD^V,2U#A5\\#1I%YOXari9%2/8B8pIkJ$+`8'@L3]]tmeL\+Q@A>&mL.S'O:Aaq>f%^nJX$g]"7u\#3H[#Ru4^En!MK%=kXV5>X~>endstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1500 +>> +stream +Gatm;D/\/e&H88.EUYZt)'%=mhZJ+*P,<#FTM#q#q_/fh9i3ef8Q8:(X8i-Ye4V>S'*=sF*15e-T8.X:*>KY#q"X819)u,]d/W<^+2BW5J)lSsGn7C-ZgVOUBfVa#F>W`(ZhY"mDuj8BH5H3Hd*I%256g45"8A`'FDlZU,`=Yk07h6,?Yju0'fAn^[:9(d9uE>Kh'YUd_@Y^7Wa%o5kKIL.6;h"M&So5e#_KB7$;h%tI-%"mL>6dPM)PL1)W?p)4bD_ddbdkMJMEZ\EONqK>1]fegY6-48n'+K./:Q:/5%kh.\#D^[Vd9h`nMt=_-"V,8.:T&0$A9cTp@$(@&AdbSkK[WnrRja=PBW495D>9=*ruV(CB`S?r+c@f0>8`3$5pYuiRp9qE2Lu1g:a9N)b%*P_&!M@_Si+l:%m"'56]ooZ44sV>d736A&o(u3rb4-4j@gnFm#[!AQXi_V>S)"X(+-qCC#K/T7#FKp3E;1&.[-=5<1#7]&o#;phPGk*0EbU5Cin/2bTdjj[el5jg<,8X@GmrQ+K"FWm(/V6(90uRg.2HC'&Zgu/GWr5Y*%t%D*2T=rMN1uqau%0Frff0k)lq0fC+r+k].Crhs8Vqn5A>&/%]S`fIX;m=)'\1@d7Gj+h6Ng$hU#-?KCR8;V8%9q?T_?]>6M)d?F.ETB(P9*@fQ:t30lg=iuC6Z7:/bm0Rs`JSeUreQs'3P2fnbb:8a,fp!qMCI(K1PiVrQ@&sf&);i,hS_l$CFGEq<+Qc5FY0.:tF\FQJ9%&Scjcl$J@YLM:W7H\m.reH%uER!%:d;BK@i5XE7V(t=/5%R(3B'&YDIGe;SD5lC3@U2c"8gZgT%*J7Dl^JrUZ-Q<[&oP-5CtaWnE$H!%3E5%9Q.]epG?$OC">`3N9(tKY(E.f&Q.]Zp\-L2>MtmY\/N_/W82577*/rq_JJphZF-sg5[HMJ;\T`+q/g2Z<3$BrTG:nB8!Yfo1p$g%F*h-?8?,.!5U6l/*]'<,[VCG4PcZlBLl_S[B\CR"NQ83?ZPT(/B*>U"LTWoDTCCp74+7A.`SDX^UFupS-1L?*otIQF+35Oj?/?,hJ>GhCP%k6,VV,FMu>%gr#S+9gc(J<$]:fif2jtL.7eHar=C(?)BMdK^G08aUr:"!,d[7]\2H3o1Ar)7::;hebDj4F3MB\jhYMNX9.QM7!P0`@\qY+NHg4.[M@FTX8k:EkgV&c"7-[_+`g@of'Pl)'Opr4k9R<'jqKXN67PZ5&K@'KJ&-(n0O([ubi)/co1JO2)E2E;b1qkY$oQ+-$f7p;IUKYFk'eh-PSmYsNR,H1V'=EQK^UL('?UA+q.94>m#4"HnFY'UopZV+COE,&ghG0J0q3:>k@Pf_p,e(7kFOL;8()n.&^rendstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1544 +>> +stream +GauHKD3*C1&H9DY@`7LV[`=+sp&u4G5B)^ugp'*\g=*%#+u_77D.6Gufe$t-^Y_!r+T]0doV;R$`T-LKR:jP"_1kndg?CDL!IgY-o;)o)"4J.?kLMXe#N/@<^)YgoAucBCZ^,aj^1u\cUL2')c@h.5ehe?[8WHPE76*S!XF-._O1#(I&cN3m#/+l]%hD5V,hSFa(L[9S8aJ")OUkuH]t,S6,^OK[-1IHhhSSCt@HiiH[sA_X?1o+kHR`@8s2bP%d]]%@@LH)>"i;MSkP>P5aE'V.q)9ELbU)F=u%lo__c@loutBNCWbB9ok_/S_[s_8($>GHF(Vn9_Y=V`X7_lgCuAE,X\PdVc`55>uIXt,'m$0(a9"3SUsW_pe5t#"r4G:@ZJ8,dgKPg,B%C9Z?O<_Z9j+GngkffGU]GC4&s_NA!M*a=g,)21mW``"=;p*-\/\P=C50nBJ/C4jinl5br9]>;NBriRW`O9k3k,Xd1X7_=J,%#Dm.1I%t6t3mQNaF"qLUU5/&VB`['(],t((("G[E=#h"NLc!Op'L*FH-RIoV^N"P/'Zb+nqF$MdA3ObD91hlmp9Jhq9VFIfoXEh?OeLI[q4omGHB?:^]'j\Q;r?K&Y]L1P+JmNEB.eK&*I#3W:8JY5K\*3pB[R/hcLIHO(=F)q53#>39m'AT)mI4W"#)[Ep-0k';(\*c6c&#q@;29,QGs7"f\2u?J@hMQ>.Lu(n1i*7&mS)q>3:"q3L)\$l9m4<^h,-JV5YN!X8Vplppg`Lph`MQN$s$^YgRcT$2u&XR#=/rL&GZaDRBVVnmfPYSAn+lZPe5RAo&=b<@)T/H<6Ch4"N5:^,p;3me4R"7-Cqk;sVd6$Q=C6;].Bf0MBpeWAOr-.c7F\&``&qPa"SMWSDs,+@!]==k/a'`*7mqj]1u@.YY]ch!$BlQ,%IC9jXYfM85PBideE&iU/#[-7NOuE3hIh#pskl]95=r-L7qp^'N@)jlXa4_)!PNPu>]r%>d"PH7E]4:d%Ufq">`/:p;XWT'+Y=H_-K/E5;!i9OIEYM?hZ,NRN[:&+X7@G)Cbs(h.p.cXTci:kMo$=I'+4Yc$Nk0+A:YGPbkHlF^fm[\k`9;u`[I524g.RoZ2mEudEk(q6)QN,>Iu1A_#fN8&!rC&=oQGu/#;[%>Y]pI;VEoL:e"dEin/4/Pr.]H)UYN4X]\i=.V$0N$5;^o#$P3WO^F8t@MjIp6o_nEc=?DuiK/!c(pJE<~>endstream +endobj +91 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 914 +>> +stream +GasanD,8n?&H:NnEQU,;S\!5NgI`cf0jZ-$DCQmg.'cNe8I^LiC_oqlrqju9'9Y8<[Ha7YgiMZAhF92pkK(=A.DRSYp+Afgg'9iodGa!pr$e05S]B#hNVkMcK5X84iV7([(7ic-Ki+^FD@D7UY'=UCJ1Bsu=)#$+KS-&gK/*-MnK5R!dZMidHO7Pf1"o.FO9Vo[N'=#]FL$.g*@\Db3/&lpp_"F;r"?STrk&i@*%b:mj>#eE75#jM+mXp"oaE7Gu^n^U!WoS.\m,BkaWpL\.W.elFil^"H;$VVEX6Z9VO`3._Ea:Yah1O4j&&R)*oEE&e4+1KUpN2]N[UjpHV+U?D(Q^)X6XW2##k%/TCR:Kj]KDX=7cdoo[\$^hG:K3endstream +endobj +92 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 364 +>> +stream +GasJL6#V??&;BTNMKbjZ+A7\<[oK[VTodFjcm+65BQ^S3C&79[$Y#oe2Nqr(4)`u'1CQ/Fle^t./-R@>#3J/b?rLhJ&],@(Vnk".\Vn#i@(G^BV%,!-?/`.HW0^fW*9oYJQNK.p?B2.Ybf!kF+HF5SpTWe306uPQip@C[EO6#n?aa4kmi^I1mU>[BLTa:2$m1/n9JOPlfaZ5o6:9sJ_B-\I-j)0IW.lA,QEAA7R=!bSDZ!cpq5#$qU3\H"n1WRb]D2DPrUC)RIKRH(V$Bju%8rJZ^Dfc`R]T_7qGA8o`:6i""kBe7"t!2ET2g[#QL]oKrSiP$"6W74`r~>endstream +endobj +93 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 300 +>> +stream +Gar'#_/@+D&4H!_ME.OsKPVQl^s.NT+[p+'IGnicD@7(sYh_\H^:#Jh<%I?IG380'E^(7^If`XPZOMHmLj)[`Pn5McOdm*]]pr/kQVUaa/Lp5Y666=%Oa&P8ik4gBUC,@hLaqs,Pk([egQrCA71*bAmWSXU_)6'lhoVE+k#E-^fUXq56AMIqT0<64(SK%lK#+/WSClhCYp:[d*g)uq=PjDa',X3X-?j-~>endstream +endobj +94 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GasJLb>,r/&4Q?hMRs9>PrM`[g0LY/<%//k@hr>gB*q+R2)^0Zof2A,PQf-k-#5X;S/I's*p.?C!V[SC%h'ulhgc.@6gtcrpU2,)rZ"EF&+9^"1l6%(/Hi6']m-uPS`=NrAYVSr;'-MWI?:'K1Hp<4^tT2G-#uX]),n;7.0r%qT(pZpn'\9,Q4/kX[U37endstream +endobj +95 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 387 +>> +stream +GasJN92C1*'SZ;ZMR,\eaC$Ta*8Gkqupo5Xh[=!>^97MY;@hu`iWiU)iG\8ct/or'_8OQc6-ac=U*Nib;/]B8_s1p&)mkRGrD0r$%Y4eR_c(bblhXu?qQ1A/`@4shN==RTt47WelA<")LcrkR3m1/VE%+e@mcUBV.9l1/TODaG.J-98H0-VWi"2!msOtQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +97 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<92C1*'SZ;ZMR0B:.YFNnFqgVnB$IH2`!F3j[-aX(p!&A+tYQr.+""N1Cj"S'MrkQ32UhAgQ8"sF'JH5q[g:cn2J>[$R;%g=U/)#;S"^cS_@mR3jat(*Fl\0T2.Lq.@/hDQqhGPI)n4@ZIsS(\_KI?@Y4l?CLAkT!JJ3J,6:_=`.W":&i0Dn!a$tNYp#CohtP?611uB]8A,ha;VK*_6k#Nl_A:TMI^`4!].@Rnb0TUjWBtqS(I3Ct3Y0>K(=u+_*k/5?5cC_:endstream +endobj +98 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 384 +>> +stream +GarW4:N(hM'ZBHfME0B;g0I[Ngk9-HJr7()-G<6#>$CpD"`=,']8K^*@pZHrI5CJa4:\6CGAgXdT"r7.K:.#2!1DBZKDo($jl16sE4"LiK;a`L?t*Va*P>_)EY(Jt`>QgoI/n,pnsdDQjt$fU.mM!lHM+RV+5Vendstream +endobj +99 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 851 +>> +stream +GasamgMY_1&:N^lk+r\I(%m7pYhB=L87K[N'K`=VGhL^Wfub,:]2$9$GLdQa%]#A$5BtMuR5nnlFjTX*Mf4s_9EP!8X+P:TYQ91!+$ec$/Ej`goEmSu_/NfU8#,S[,OdrK%f!JbZ2,Ua"t#_[!<&BZASBDqnBIW'd%[9\.=\5'70cOTAUpi5dFfFPF&nf>IM_/BTC/,l19SCCr,XrB6g:n-T?K(:gT8!Ao#:U=eam;C@h/U/%/+]u=0J0jhE5W:u*,`7W8eU'-KX.YF#kl6VJ#iAP5o\iZ4Do&iY?(Gio^p.-h=OZpZm@=go8B[,FlX_TNr?s>h^2$fh=YLoka.FL38X/9VQ.TLd>09hMHnS<%j'R-.+c4;SMbt\.,[^GuY@pXLkbqMdkM[Cq$k54tbThg6OVW+YhOb;8K\T@mX3P+"9>LiPlAibLO1J7eZ,1LX'8(#3*u~>endstream +endobj +100 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 617 +>> +stream +GasIdbAu;j']&?qGEWoR$Xu-'&6OK.3hBb._4muJ'O+Bm[R;E')?)g$`\49)a('&U\`Y9,J;Xpe^JP3>?uWk+5WiG$+J[m$fEs#Gr#(S'3M+$2oIue/*[eIK"1K96_Z4mP6\gR;;L(OA=t7k+6r$:$(49Hk+i+j0%9]q7#/PVrSVM$no@\"SiJGtl49[t5-Xa]?ICA^mpfpo<4a&D^.!lK-e[?&jB*YS^:tl,.$'W7^8HgZPi30D3Qgf$I'gE!f/Odhiat9[_r$:;W/9pe:A.6_kR=\Y;>KftqRK!dcZX\I\-\A=fVe:[dhLt"rJY8]`fAQ#M7WWsB*L.ip(^J=W7*/XElHrh2:dg"4WfTC8NR3$K1G0pB2rlGlftqgH;p.*Y7Mq=td+bfX(;`UVgYG#4Y>+fU0T!$s^mN!16@HY[-&ASXiC0R-*C]C.mHOA?1Q6J*lkLgF%"9\iK[$=obhp!GV3C<$(tqblendstream +endobj +101 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 395 +>> +stream +Gas2E;,;fu'SYH?($EO=9nk6hJ@o_+&^u;'?^CIR[Q;#S:hYgXf@tHfF2jTED:3dV\R/PJU'J*lEXU)N/lN,BK>2q3]EpPb_OYn+mZh46cl[U3F<,(N/eD7NerKIP+jS]bXj6K'"-_g[PN8%O%F9nOPhsGOT8K-dq(:_t?EfCG+jF+EROq!@56p(r?bi5p;mn*\no17A*q_KY$>B2:l%C;h%#MM,g[PimF.e92gGa2nWbsD7KsYV7-(5QH=c5JP:$n-HRg",8@0kPf`2C*/@uRTfb=;,)C'8,i41XskBks\S;6!71?HM:nZ+O(:NPWJ*Y\>hFmplO^TR7=,;DbCWMcb`IO.?0S9KtqCX%,Z/^Vh5dqZc3V.'s4h64OuG;!gIJc8YaYP99~>endstream +endobj +102 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 912 +>> +stream +Gatn#9lo#B&;KZL'mo0RC$W\=:EW=a.@B$B+V`^'%pXe$_.mf.OlT3WYOBWm,9^DWF?K9LP'6Ndo<-=-G+n0.^n;B66V;^dWl,\s'2?r_Go(p(cbj`roupIV@KFL>Kuff;DF"YOZ]0)$NnG=NZO6k8acp#',g7<^+!/2ZN@Vr:*AIacZ-9Y'It2Bnf0$<;"G;ZM]Q+\Z!asrWr$QT=.aL'#$Bu;Wc+f*Q(nD2:X9n0-V$emh">3V$\<*$E295Ie[CU=SP>#(PCo+*oVO4(i91SG;8XljP]nn0farG3!V05U$U84Sqc@Afl>fc#5!F)cH94\7>&^u&:"XUVn[G6\M/.&1u5TlQl_TBNo#^u*Wp^8<:ma8\O?rg2$:aemZCppd3cmTf*X,Zdj>LmQchFZY?l<>?O614=JVendstream +endobj +103 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 784 +>> +stream +GasJP;/b/B'SYH?(&)8P>I?@!V9im/Kr,RtPRZ&T%t-1k#!=bdC-,D]fC.Eb;lG3r!f>Rmh!^hM_]YV-q1V>[Us-q2"Ern>_SA1>kOC5D9cnnjET`']6:dqVWr;%L7ijStU9_KM8GZ\LcS*S\TbU:!9Ds%`qqr9N1YR=t8?*;8sMVCnVYm34>t&"`;jtnTaE0EGIpf4GMRB%>5ic:la*r?[B!^[(\E8'<@K8"8;kn,I_%hY7_Xgd1^=`f59R?4"6S12a8~>endstream +endobj +104 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 601 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW4(_);Q5g4'F(lQm*]HZP^f<.*[Xa!r?6i%^H$UKFF*cG5'K"CpK[endstream +endobj +105 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2Hd;R_m&B^lp062^U'U;eujm^+S#3^rB?j1+lY!^T<\Il2M9KE(ucmdjq,!@D4'.r?rhWW`S6ZK/p,gL7^m`lAHfi)_@'Ps=<#$.Z*7W:-H,*(WYp)WqK1)V%EE\ZIgJ&dH^G6p:qsh(9Mh1P5b/7[N4(FBMF,ZNPRQbAj/`'(k>ED-.TO>/o]/L<:qsma#OO/A0GW8rj3%sZp/eI+3"P&a0P*9J_@$S14pp^=e$F;I?k^#:*,NfA;M8pEu5e^Z;8R=`q+0'Jn1_uM_!dITktnW>Jp(r?A)#,NK1^WA>WNSM$4sYmQqQNdSlt1#NoT;`o`*l\O]\e:-U"X:tkHQIC9f\2.0g_89/8tkRUJd=$4LX;b>cWP+PE>-%5\F6:XZ%&&W[K3uoB$[,O4[)oaQA@""Zm5c%C)BLNNo9(2?Sj_Ib&f+6.FLkIR:cGendstream +endobj +106 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1426 +>> +stream +GasIg?!$&E&:N_CbY-8R]-1sFO$MRS&6ddQ=Q7'f7Bm)%>?`kGS<3aHcH&ai*3pOoi+$P7mTe#M;@!=%K`5mp!.9^_lWjeT&>BsHcNiVEc!VH\]Ujf$b0^r_cHc\r=4^Lf5p$1._5&Fm)t)-O?pUcH&70CW@DI_GMs2LuT0GYe2MUDZe,24Xao$-6qg1VIItd(k7)*`Pn+?4SjD]A".f$g,[BIQ2B6D1D.rJc]DdQr>9DA_i)Qq)p]dQ7(F\s($:g(=qE#<4[`ZbY]7)#qSJpm`edJm;r\.f]%',D"Z:un!oQ)Tp"'VQKPKDs>8-&kmg[]uDT$;@77#f8T$:235^.FoA_RE??l@F-MUkbB-u_g7ELd2'u!`b=>N`0hleXtg7h(0]7nG#r1Q?,d1JV(T)@.)g^4l;eN$aTjh@;S-E2_V)Af7FY/n7QYtj$$R(e1hr`b1QeG?H-bQpeMF*[>o5l?[6B0`\#k.^*N^aRo7gSNnc:p%2s'[[[:#%%50:POeT)T*o5DIA\q<4odE5"YR.JG@NHR1fN7B?s%+,mpg5pp&LV"=J1Df%qrmh=Q>(WeAB./o;r,Rb!^MqZY:(F,J9/H;Uf%t9D'+^4&j.D9$#9gM5GA&=&>)AK5-oWd-WXh>49%_e;dWK"7)sa^N?AgSZ2sR%#&]["Ua#`7c-#a`a@+N1?+8-AQPRRDFj-c5?@2Bq!)D.+=P^[dkC!]h)!Q&Wca*k0/=2mJPYjQ&kIaTZ(a`@IV3rqrkLF6GR'ma^q4f%rH2BbAER(la*9,ajs](=1L80]7]2+IjlfncF7,oT*UnFuqF1-,jK_/OLFEU65?8Loe-Ga]O:,t1u!`.eL/Min10_o>"[G%tdePa0e22lPFGCQ!gf7W%OkiUn((XhDV_AqYiWa<#Jq.3\BPd%6etX`$FN2NCmh.ndPc*f0,M3,r2Wc%l81HfOM=W,<7N,@]\-tca2X3DnL&e8DKC[%d^:KR)u$/[rPhK5/U!O=`X0hi1&Z4omsOtY;K7>5Xfi,[rf:GRL$0Hpp3#+7F1SR6A2*.XQ],O]P/Fs@1OFT`*]6ii2f^5V;VS`&*S9Y%`\eZ@Q3\+W2i+VGlI1hRmp=9V>1qL``q[!NV;#03,XRW]=i[K^YaaC>U\.Zk.P+D]d$ZQ')0kip[\8"FLJ*Po>ZYl\"hd8a2?'-8l*QQMW<J~>endstream +endobj +xref +0 107 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002203 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003133 00000 n +0000003339 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007543 00000 n +0000007749 00000 n +0000007955 00000 n +0000008161 00000 n +0000008367 00000 n +0000008573 00000 n +0000008779 00000 n +0000008985 00000 n +0000009191 00000 n +0000009398 00000 n +0000009605 00000 n +0000009812 00000 n +0000010019 00000 n +0000010226 00000 n +0000010433 00000 n +0000010640 00000 n +0000010710 00000 n +0000010994 00000 n +0000011398 00000 n +0000011994 00000 n +0000013435 00000 n +0000013723 00000 n +0000016255 00000 n +0000017369 00000 n +0000018631 00000 n +0000018806 00000 n +0000019891 00000 n +0000020384 00000 n +0000022292 00000 n +0000024090 00000 n +0000025406 00000 n +0000026613 00000 n +0000027274 00000 n +0000028871 00000 n +0000030179 00000 n +0000030926 00000 n +0000033084 00000 n +0000034241 00000 n +0000035600 00000 n +0000037141 00000 n +0000038812 00000 n +0000040615 00000 n +0000041620 00000 n +0000042633 00000 n +0000043061 00000 n +0000044155 00000 n +0000045027 00000 n +0000045750 00000 n +0000046716 00000 n +0000047733 00000 n +0000049325 00000 n +0000050961 00000 n +0000051966 00000 n +0000052421 00000 n +0000052812 00000 n +0000053289 00000 n +0000053767 00000 n +0000054095 00000 n +0000054548 00000 n +0000055023 00000 n +0000055965 00000 n +0000056674 00000 n +0000057161 00000 n +0000058165 00000 n +0000059041 00000 n +0000059734 00000 n +0000060691 00000 n +trailer +<< +/ID +[<043bb8b2c52055cea0a8176d60eb8636><043bb8b2c52055cea0a8176d60eb8636>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 56 0 R +/Root 55 0 R +/Size 107 +>> +startxref +62210 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_5189d381-815d-41de-85aa-29726f41c4dc_20251031_123624_analysis.pdf b/ai-analysis-reports/repo_analysis_5189d381-815d-41de-85aa-29726f41c4dc_20251031_123624_analysis.pdf new file mode 100644 index 0000000..d26b3f4 --- /dev/null +++ b/ai-analysis-reports/repo_analysis_5189d381-815d-41de-85aa-29726f41c4dc_20251031_123624_analysis.pdf @@ -0,0 +1,830 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 12 0 R /F4 17 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 49 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 50 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 51 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 52 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 53 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 54 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +13 0 obj +<< +/Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +18 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 48 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/PageMode /UseNone /Pages 48 0 R /Type /Catalog +>> +endobj +47 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031124307+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031124307+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +48 0 obj +<< +/Count 40 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 13 0 R 14 0 R + 15 0 R 16 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R ] /Type /Pages +>> +endobj +49 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 509 +>> +stream +GatUn:J^")&B4,:'QYg]VA\Q8\HU'[Q%221Xi(O6FD/=EPH8UdrUr3J@2HB3!#irach#WSbo"9@L#Z;bJ.iFa*sfr<56-FE#lFaE55@"NSMEb[_1e5QMq#FZ%1b1M_ZW(;qhT60NX$k[F]++g.M"S'O\)jhDjG=L:]Di[DQEK[)/$?N9E\Zf+626CM;:sRVO>&H_aZW,Ilf5qs'k3c!d8p?$^PH;jLN)4pimT.F&2;d7U61dV2X;0"28-36Pb6WcKmN$T@0t%M_sVHP'.s`\DK*]]WFV,\Yf6CDqsI*=AnW>D%2i-h"X*&6i=rM[0=;3pPe@D;n]&s=sKXFpomUuM$>_Fa;@@Jr;["b(YA03j8~>endstream +endobj +50 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 572 +>> +stream +Gaua;>E@5e&;B$=/*7#7>Z,%ok4#f`\l'h(!R7c4il0Q6`SfI.m=P3'ED>1>CpgBiTSaFPR`meTRu'KTNu(B3YlM<#i8k[S6D<^rPbSl&2_aJ#hZm]`B#C8jM\0GNM]K'aVh2N$`*Ta5MiEWC7=is(.@RGoL6E.3nT?e(RDA`H2S456nL8QeTmO5VGSdPJD(%DZ6\!k/`-FsKPKd>"\CRU0)m37KGn>.=V_OithE#=Sk`nUJb(.AklW(0,"VkIJ//ZJGWFT$BM&E?RcY2([\hAmgV0Fh9hX1IFh(E;t$&mT2URnW*Z0FPsk(hLCgriI*7W=KFcMXk$0a0>^Sm`@:kML.X^as3QU@;r>EfK>eR(o&jdLgendstream +endobj +51 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2352 +>> +stream +Gat=,gNMSt%XmfLcm,+3&0N6lGpD6=1X.3N46N.+b"H.ZVC≈e;/d^ODuq2[D-@=m8SF>o-(ZCJ/[QgA',Os10AhSHG4.FJ.(dB+:D0J%bQ=G=Hk:^d,TJe?*^E^DKS#=gNEgl=(kiDFB\1<>l9GEJb/M![Z08)EVZiCXhhs[3#eQB`A)!t6R#sXJO(\h,rJb.iH!aZ1!Mk+jXXLN#aZi(7_/&+F3UaV2Rq'H3`0@O-FfWrG9[ag-E5uV]S;'ql%Fg'L_h-!5k.rrc(bEFNr]4C.TSn-VQZB-X&f=m5(I5W_Z-;YCF*snjM>nI)#7m]e>9L0\a:jY-dQ-So!:/D6l^/J1&$B&jpp@95M;@irA%$$%hlHc$%HNuau(C]XbECI]b)EGR*S,VPYf?B7?kqo_Z\6RZSg&<8$OWMF>S:B=po8PEu*V-mhEEo#:2^6G-FTHLq)"IV^b0?coiG9&8IO8C_cGX&5&##;[Mu`i"dqX+_jUqB_`6t[2sI.5Nral[bL3,gh)4^\@[T.+T3>5#sq-5D8IA4h?,07rWX84q#5.Anc/r!YgLedAr[JZ%^;M)RHHfGI8ueLd:fS@OAZkTic7(t+sc69n_6]Dk3$_3.hjTZ^YnaDipWlbc&dYqjcKDG4.ZsUbs7FVYU#pchJ15BKoYonNeP0gFON\,i:CsALD3%q\6S>kqn,,,j2jX`/BS;$\oQ,+j2P&OJgA6tDH];XccaNJO^"QtQ,4g'YfP"`E\>0S=H3bGF]pC)!qlXg[l+&qNSsGSTAGc:M%QLo^L[2!\ZfoibaaL=>,;A3+_%9`E7jPIZ/4qid@V0kqnEs_U?+`mJ9P_),q!p;5t@E*2f;UHO!QSX:`Juc:S_Zp^Yt1ITO%ZA83SfR@gmlC7h+5c;p;oR3Vfo\GK`kMo=Xd*u42^b#K9bC&QF$f0lc\W4XM?$4Bj)"UaJ#%;-_O%0'^12tOYcW.\lL\#9QQMc/>XTO,Ur+,a%+s65hrL..=6C!Na+#(bp!chC>&cP_Ml\e`dQR));u_VZWCAP2%;N+54$muOiT@4F//Kos)3_A/fpa`nT$$Ls3m89iBp:qsqbf,8b1[3JZ(qRU?QnDZ(8:!DdM'Be`8P@9q/VM(matAd1ddspM,K$8e\;DDNongV_iZS%uC%t(I'7t>QIZ(fLW?!SFLX&JQ3B5N)qDJ6-75$+)c7/S7'rJhkk_S>jAoD;~>endstream +endobj +52 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 854 +>> +stream +Gat=h>>H1m&;B$5/*7EnZ"-4P^fsH1JHRQkoSj[-Sn+a)gPbG.QXAY1-%o*[<'i*H'45A6HugV\p$n:&Vm]!#-FEZPUiJ_a)3r*K8<\*5:O75uEd@4p7#-E4@Pg+aiHG&(2*BLN$c'DWZ/O?k/BGt"Ok!4nuM1^^GFFp@-gGJ^pP>AP#'1/a-jG==cQS`Yt]SfILFetTrS*tb`L:"Eai/1g)"VX+6DN]67eOu;l1lb-Y&su[RnSI>T3i6K-?(";p!Unq_8/iX\@Z.n,W$s!ha-XtWHA1Mkf7TjhUKe<:]&\B^XND6,TR&+aWmbq!Fme_Ujf*?eou.Wrn3%Z??L4O+?N&6d\)L1.Z/d4Z]]HpJd7p9Ddgq&C),*J`&b;WZ]Am&0XadQ3jsU!Ao1'Rm-`ID]914lLTP[C(^>6&T^M:HOQ\$2"!hGD-f17lVn]*?XaF(eGThH1K7^i.Jns8*iM<8URi-M.Y0'?t3;LlVO'6Kq:DB9$mZ1ZX?M18k#CG^ePQ~>endstream +endobj +53 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1225 +>> +stream +Gatn&Df;[7'ZT&);k,e1Ei512rho55Q>2u=ZjYY>FfHe!i$L9gB?%Jfp??cD9pCCNAR'm&72Yt#3'Mf:0`_q@;ZA'I^h!qhh@LeF`%O@q_h!%@@=7eC)0p_[&&>Yj,7'#)^4?Au4WnBMpb(5oBAo<`c=I%HWjs[eRV?^s]q<7%j;LM:X5@gTn1+Du%:M(2N?=qM#gVDorpF27`o._i?QoCd#,#`7nLPo*8SDOM%:e3RWrOrTe2B@_ds;>VVheR*$;!Rk/1uN&])6AQEPGrSa>_;lgTMD^bO[f)h=>Yf._1:);4^[R2?>ba.Hb0*Vsqq"^3OUak(Z`+jgn`sMBttr'.'L`7'TG'K9@O4V^8u"4t$HBTIHg"K-d'C/X9i6W"+S:s1@AlSOWsk9<:0f(HN%Mkd;/[#%/+K.Y0<:$iJU0^;[1rPu6fr')K@V,iTPGEQYS%,(9McELLSTWqDfsR9%ENe:r\lOV3S+8RB<.QFXe+38caHUqYA8;=6sS?2-$(\Z0rp9V=gTqO-g9@p^Qob0Tm.Rpp^?hkC"QSn^T6rp/6U(gXd]ltp>^1'a@h*]=_0Fn*2e5dZEda"Qc\d/3o;f!U4"_eA6\r`-ejW`TqEA7TKkE.b9`ph">44NF"N`*deb#bX7nJlkF*igja-ZB9WqHL80^Gs`:r4R1>DR5V@;boHt0J+E%a)tMD)Jaj#S<0kk#0<&LmT3T"sWTkM,8,EI>)gSF$eNM:?##gMY@cd]q66:ZRsJ(oPu5NeKg?)->pm8Rbh'TT>&fCG+p9a`=a:A9c7:XC7#S`DO[\pH&'dgTF8qpq1!;ITKb)G42Hrr9>&(c)JSNYWLU]BmAG3=K*b_\&o]jm_aHaQ[_IfRb@fE07nTm(VYZPB+V$i:6TugWAIQ1lG5,'$-NO.e9,FQb3L"X)$XHafC%Y2:F7@)l3'MH9CrpPL/mAJ4.+7.2MT.PK%i[MHDPl5qS(C2/o0jM6#4:m:Srr=?l=`j~>endstream +endobj +54 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 229 +>> +stream +Gat>L_$YcZ&-h():[oO/KC,apCIb'n$;&tSLosX[0!2&.^3,>X&.e?L>\=!2#gA##Cc%5HlqR]CO<#a+'$(,E)*@us>c%SeSg#=5i>QUm.eN]!HJ5h9pP4CRoS<7p*arLB(@n?Q@0:e);uS$FO#TVZR%YQ!:2VGgEr!3)Co(DeDp]~>endstream +endobj +55 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1010 +>> +stream +Gatn&hf%4&&:i[8=5:tE\usP+ITLli/8S"=;Nb(L`(QQ11i#XL@k.$+cUeG9hdJJc9RE?q^$Y^+;]#;^^EunRLHG3aGO?pTJ&)'mS_gk8qX"a*npoZ.&[+,EVILWZfqN;3C4!RJ=Y_1AEuspoU^Y3;!(60?=dVR>YJlV6rZhXYNDfoF/K)"Qd[kkg4Wa)`Hjht0WaIPTU+"rNXn'!5?E4A,TEm>i=g1JF=e\[k^Q(WZm8\bkl!].iNk'is;H4-bW20&Dm3TR77M/3=R6S9$7>*j-Im/@W5""*q]qG>S!HJMIVgj]M]JJYV*=ZJf+FBgV-YLa6.L,TmE$e*'MVOYYATSk+'?NQBT7s(l)nJ*J&!usl[\%^=)qb+G>8[J)U^'o]FF!_*:RN2)H*NtoGWbf(kNd&XE96"_CgS"-g0T[!DVSG&D^'-X/%l2k!V5D'd=i;FFkNTOh)(^aT<%U"Jg=kl?E5a$8DPf%kPcFTbU1oaGWRT\7Vd=0p0j<"b3G$"~>endstream +endobj +56 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 370 +>> +stream +Gatmt4&;E@YX;Pa^,P``pE:,'V0Z(3*<4Z@9,#=;,J8f;Xjeoqs/3YoIs",d6DpC(kiU&pgEV^PTU.n1U*eiU2Xfu7ctkHgZk,Z'0]=r7EbN3BZYBigP=F#B+nQ=W$EnODf>=-HjdJeG`4ded)AlWt[]#o6dY92d$*+!Bo>3aPIlaMr[lk@BSX$SOqA4^ZUt;;'Nb;-6Im=f8eB1):[=8.Ic"5D"9Y3sK8_rsJTJL"2V_GYluh!kQnI7ZsI?e8$F=V=A:fW;Q^u;.0hla%]^2En5n=kj6lB6,#i]'T'5UNt&)e$V,gu;o?'oaDLC^AmHPubKI`rk?r#8)si?%PoiU8I00J7YJU~>endstream +endobj +57 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1812 +>> +stream +Gat=+D/Yn7&H88.1&Xqj3N3_j'&2Z/6l_A_g>E(e>Yb:(J[N0mh?rSUl)F^]AcZDWi2C9]`iqPNbg+BfK*!fWQ0d*3!3R;dH_Z,>#A4Lg:`=pA#L,:+G,>s8`tK:##L[-%M>Wol-IF,':E;fn$&#&krr7:M$V?9CBoY4]ZF<)Y.iLG3eP)r^k:q\XJ99\/0!DJ/@'60(&]mU:K&^5AbZQWMi68^s-F#;(Md;M6RW\A[9NS(:jJ;0TaB5jVbbr31eE#+-V"=2b7hg^A;VCl(/lIEfe8>r/!h6OOh3$<4rOH^oG`@g0%+Au>7VQr%,%3FI2=NK_R&U(8_o61LHS_$\7U[M,_84,oLRT\Q)Q`&c)?-:#YVH[<]/W%ohE!?mB*cW^?5"S[Lj&l%r+'_%U,1QLB_^-9eqmSB^n.R/]8,^qik_UVmo-c^ibQBY+6lu#6$,rZnRoM,R^"P3uUBq'gS(2cd;LItMQF>9_h9iuNE37lpm:[7d<7Ir*duk4-lNO0;pTmZr[j>,ipnrBi:F%,Y48jfn&/ljLEXXfq.M5%Yi+mo#*G3$6i-^1_K(,8?htN0uX.!-ONMoHBP]JfRdZR]`L>.m!R)fs'QgZ!DV>A/;Q9484&Xaj6MW"C"rL7>Q\eni6`q;7ra%tJQ!2O/=b+pX-SNn_>gTJ7I"B-j!\J$8tP!r\Cn9/:g)R$m8?DZ"l6B5F8r21B:'db`B:kCTna&%ln/aZc80XjdQglU*;"VN@iQIJKgY$4@EO;QV3ApAK.\N$(IP2%]-Bq_06`I*p;6a')n0e`fsh146)q*="3`,)pah3D`%&>VGt`L8_'n#]71Pf1jf[HE;kE0J7VU"?YSVi/endstream +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1725 +>> +stream +Gau0CD/\E'&H88.0rO:^kG3/QDhbVZ$&EYX8dGZ^dZaI30ahg(G^[13.BW$QGLeYh@med^%ne&6m^t\Eo??,X"Wo,k%TWR8+0P#OE2qjB_5Z13n-@nI(LJhcoVC4C\(7ulX`b'uE!&P!]bUhVS:spnQpW"53ErR2d7f5/"e!aU9HD`=Hb'i1$PAXHBd=DApj*Aag\KKU\WB=UKStp=P3sXk^OuOrXM#`DCMSX(NB4b4(qP<6^TOQa]@.V\B709d3a&[W>Kq?Y!/FjAGsJA6O/onX*`@WLjk)G8%%2R357.,eSPZZe,GI&\+nUR;8kTaJkrHMIDWB4m<"JGj>.B3VA3,bMNeK8)0!8\?fkjm=PE]b!b<CVBjn=MQd\/G",hqnZ+203k\fP8#p4$l:"]@C/n5u?S,4,.&cu5`Bo`$=U_WIVbC[.T[KaS1)*tEME8qhb*9I`=_QQu.OE[6;#kmaKJom%da20'OAm>OG'*c@8%nF5QWC]iTHcpS8@G8Suu/KVpMJ%:I\2sSI]4cfYH-p4r/.2MkS'04!.7+)Na4JO^Ok8#,DmN.ZsBpYY7GYce9a>Q;:ZLMU.?:V?STCD-S"bVR7n6%[a9HRKFq6e#?lt'Xh^*YBT]s=6th!_QF+B.p+lU\;8&F:&5gr/[+1[MA;kVO9T^76.Ypk*bE4)?6\oRk<^IQ4d#l;7AL\1ZGf_FLcj&8W$$Db@&?c&dqgjaYNO?/g4<%q_'9NJ$TTH^!^U5'a8qQr2^G1Hn1'n1`,Zp6Tktpg=q"8'(BOU)m2LVH3uXT5T(Do6f6s1IbVkkSs*iJ^q'W[)%2⪼EH4[*?SN67t!1Im(GCn`"S/p*84t;:,*BYFdTk/f>`ZH'c27`H"Ei=S0gPb5EK7dL1J1;amC3pj8W$d\0j7Kat2p>nXOA$'=uF16%odq!9\'K$41%Gq:go)Ut&W198G7kl15'`r!da.QpU~>endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1215 +>> +stream +Gatm9mr.2T&H0m]0g2KKW=EDW!Y0'C!mVMS^uhlidRnn,m"&uW]tW@<`[eTh5hPfK."$C8UY1cnW0D13FEWE?V*Yc'4XXrqt>i"rq=93oMlAu3GW>UC8dE"2h(,[*5HNE(:[Jh3s%VS]nR\7Z@_71)r!fD]Okk?T:GD.IXr"lD40[mHa0jlLljUog[jV-inQ^S1bTQE5Mf8X&a!'2c4u6OBqI$tB8(Z>^dC8;ie)=I`I90Tu6LHYGcqF9'D$kDEHt9:^]P3`>Stf+$E7-k-<3IdJ)Mfl@%L]&dL#Kiji.`]/3Emg];UD=JD'Y<.#e15*kCNLIH=g,)LYJ8_UEd&c9T)Ot_4/:[cr9i5Mt/fhl7ne]:R)oB-9;Ohc.'_0n1?TIL*/rA'd+Ol?&)lG,C4Cb\*i-oQFXL/+;4^/6#h,^SE.\`$?mCJ=*o8,U)euB`#cS_mN+taZ7?:++p>LZH3Z!R]00M!nt"G$gg-J[NRtaeB"Z`]T+:",nX50G=tMp:4&ZQOE.\31i7mk,cHq&+YSS/bIWheBJA.E03!DZ:HqmHL;Pot=49_nV)-TqkX6,(_&D)rhnEc4CK,GNI^^1T!c@m(OAM:NJ-cgS>.,=ks24[.!n;f,%i%r+I6be=p\0;NC;(1s?'B2P&Rr:e1aAOLtCjg:'N75LL0Id?UH;k:ubu*uaRU\\Aa1;NOq?cFOImIfZSnNV<~>endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 566 +>> +stream +Garo>;/_pX&BE]".IN)6nDUj]"oW(:XRJJ5$2?6"$'>_/TW=k.rsfa_F88nH\=n,34Cmg]WIlluGi28C5dE(,:F5bEVOVfSMH8Eo2P6Md%,,qPdkl#M'UZjN:iq1O'^==kEW,-.fIe)++ecq-uJ(VFKI[-O5gS^69>M%R0XfUA2!"G_$&.L(?"A(^Tpr!_drkqEZV$Ir+^hSYc(lAt+#^-K<5rJUX_M$=^cHP@(B#Mkd"NB\=d_mjY7Qj@?TA@4f%rESG$Q9$:[d(S-J=='>QE3M#oo%lW3g3JVt@4oPg>?K@q#Dp_W3?oV#>r~>endstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 655 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E-rEOuJ.WW[1>DE%=rRb@Wmag[)o4?)iunhcZG!_aTi%5HO%l3T#cRJcS#3oAp>;[Xc\J&O\u7.YpP1,:I/c'YW[9[&ksao4@bSJNR)jh(Q'Y5#!0Enp">'4HF-iQKdrB'RueN(p(L$o?Mf,Fks370Se$&T9Aks8)l>JQsCk76D=RU9>R#dW/X=7"d:Y?'Z'AZm07<@*[E5eFP?%:iLJ7F.,S:/$,2'+k:Q@1#s=HJ)QQJL5o,Fg.eNWn88@9M>.k^lTZ)0`$Zrf(A5ihg-g/mg`.-1?/K/T'C.Y].k(`#I#u]u^=PZPf[VepO7:I_K4NA5ePO4bUE7SKg+?okJ:`5_d%n?rP,=L9Cpqi.[R$t[%-Vh;u&LcTK&b=c7<,3V=4b^S$CuE/IN2Ddendstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2174 +>> +stream +Gatm=9lo&I'YO;\d(2)Q9YrMV3@B[K+*\:Vjr_)e7YCU)"%:lD'F9hKp+ajft%50aP$F"Bi\gb8^+2.e^EP:M-^&d%1#@5$."[CR4gOYi7c.f_Y;IT^V=O\#)FA`XfR&-#J8.m1W0[3M4&m8TgY)5">Or/a/KRnl1S(C.aB-a02J9cn/SB1/X`8_"M)D7,2iIig5]#QjHRq:+>[YsR3Dah%72pl6H.W:5fFN#DV(,8qnP@R@C;i?fY-AIq>`=PHT=Z!s2Y91#D3kP\ZS^/(Xe!"iGSP#@gpL%IXL-UVOK6lV1Di3q*>qV&;8FdAS=66UAnEA/k$JV=eDG_)t#nb/4O^8_*nVT[(@7F.Q-lKst3fW]gZJj=dg3AC1:.Q"q.N0(sMT.\Vd1F&BN"*GFTqYC;2H4cbp\ZbbKnuJ-/l<>$01n!%ON%)6&jq?k<.HC0=RjBaMG!(E7A5<$8_fU^78XW2-ks:*\$B1sH3('XHaFhk'IlWfl?-8>nV]^igf>qDnlC_a:`X=LU1,'r"F&ess16/r#58`G(]hgoQC9LfStA<'olA9c=eC:$PmI%b`=1Lc1)nES=I)=DZek"+0;iS"d!U4&'#V[8@6u7iMU>dO&u2YL5n66F;T7)d5#Z3L$lXFhKU4TLaLT-k63e_2V.9)BEZ.jDd(((eN"]c].?KQ"TM_/uZY@[-:D6W`j`30U[nQq1^cmEs@TN^[D0=KA)6^.q3e..P/MW=g6e\b&2'sh;L)Z\ei!Yq'iFKh5[81=Ht_]C=?RgV93I'b?\[32"\IJTXUkIT!:WB?r^lrl-`tc--H(#bM?U[6:)^E]5#`?]:dDXYUCc1V&O6ZKDuM;1)Ii1lkTh&Yq=ks.:QYc/8N#"%%NV9BMSrDPRp>FXG;0Vs+gB]58'4Z.sIAU4@<(q;u'00bWguW+3eTr:&eO*[asB:O!5<+H]]ahq"=HJo&[NAVW62],s!MZ-;(4sMO'*n<(BAM7u:&\Lru$?1=f&D]k@,'2gaqY.3hA,.@Y<^"E>S_e'l8.X&qP\GsEb'3)Akj!TLeXkVHD4e"s)*ko%PU-'YruaG;VR/H.1/+\h('A2_+Q/.pN5"D@O3_Ua&5Ze+O/u]?Z?!bd;Uh@2FZ6feO@k"#NlI\+=0i)MT#k3?A?06WY3SRW[s_=<>@%HiWK[Vl_86g9Ls-p0/55QYQ~>endstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1164 +>> +stream +Gb!#[9lJcG&A@sBb[k3qZ'@_GqQT^WZq,`L7ZhSqVtD)FM6a[R7$XR;"@<%aN[2[&;B'J]#n.b.3TPOUGr%f#E:?6[h`(jc++jHR!20t$5a]M5SAAbrpc9O590WDp1:C:=$#mlAQRg$RWUe+ISm4]6)E>-u=q#ARVa])9O&hb3\G[7rCA5LNWm+&BI=>HO;(UQsBgSuI)2/#TphM`cY&6!,6_$SK__kNQ7*NPQGu9ke*#ToXC4V+pSMc1`p.)P%=KI8gGaoj`5ATeXkVjq'Lh1#iSXISJdIYc`m$QUimeV2)[5Po>QnJ]P23UN1q(+7F\t6Bt`LEU*>.QGV&HV(J,VV4l)lVaFN\6fYaBt:8PO)KB?-H:J+dm!h$4I7+MPepeZUUC?`b'F)>"NQ?d`[puBO:)*UfKH.HKTo6GOqCs-=RdnNT&4%f+Psu"TiXV\V/.-d='kRba.5Zk'ZX)YISRd3k\P$cBecg^77F$rc;HV),lL^#S"Dr1&IIBCWM&m?,/-3Z#MR#]BilR%bZo_uJltn2oFm0iG'Q[SX;<-4/l-d:?YL"^/b%XBScn@C\\?OM$:7\9?d-7Vd/djIJ>#0@,6`*-0S-e$D)@J?oHjF5BTq04)XAA`e>XHokLpo9R6b-m(Gj.Xc3%V/`^Fqq-N)^7VL]ODnVEAjs=W\`jsDDgk>;`ec.k3+6)pp'gL[Le"j/8]uoT;3I*L??Nr4Z(LWD^iW~>endstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1241 +>> +stream +Gb!#[?#SIU'Re<2\1KDM*FMI754)qcZ62LBGXK(]fLoRbM3>DAU./$PggAqh,uNaB&fRT@%DdcNME6OeSpN(]^qkr9hf/\dq\nfc#S7@/'SpCIY[5/bqW,C)Er0Aa60Jt4MA?fL^]Brl]!pV1U7K!7pJ;u-o,agC1XbXneJ8+]`DjiR)*,B&tXuD-P4IqOsMajj>%Bgqrmn.L;X>0p5-;;WC2W$`TA>)ZS^dKd82Mo)Z6h!aG&=#YuD&89!7h8+W=*$F;>f=bD1b4B[2M_)@TL]f,>luMJHV1aI6dJ$*sfA'cKIRgJN"0T1JB:)c8;AE,/>?LEn7m7q5UAY4!KS4mmJjk(mmoc$,)Z%NoIka^)R!'A(N>je!R[rP#[(=`U0#;di<:FEY9%iH]haQQji9isP'>bWli1d0oY31Z$/s!*Uo,+RDn0Z"MCSDpJ&Y03l>*#dg58Y)d5O?64BGKfT$DmV,735NX1M9^QMms5$X]92tJ%LVk]p/b>^T?jp[5CA_T4T1M^j2i4R;Y)DEB_&S?&1;EM60mJeLWdY8.D%C9Q)Yn:T[G,)Is3<1-#=SNhT!A)pl-3A:KRK$G?`6=[sFq;=ng(0](Z@k"58c?DG>HXk\\EJ;tR/(;7]bjh9ZQ<+q9TNUN9E#A])Ui4E$/"7&;'TOR)#@8F?H[+XR=\!MhVRsAf898J];=0Jks8,aI4*]GgS[$C2`A8bgSsb*h[Jm+I/dkVlUI*DQ2\d)L6[*M_?&Aq$j5c9fgGf*6[q0a:_\mLJ;Uorkq,+WPDc\L4%!81O-K.G(67G)Cnj08:2&jc!E$s1Pu'l*Yt(-#2RW>Klu-k=IHt^*&E72+DD9WO3:0G+MMGS<2ad7-2+VOd0&eS2P'L\u)m-XQlWkT-f~>endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1260 +>> +stream +Gb!#[?#SIU'Re<2\A1/X)&cZ-LSZ7LFhJOrOCE(l50\F^,V!E'YE,KPAl-1/cOCajqt@=o--&b"754?E4u,[fY$bWX)K50dR.R/h57Q2pG+%q_0tBm0.#&_TPV+U"rdL#Ha%)*!-qUj0Zf%E\T?sl;GsiB#nrXX6#lbu87910abLJ"Nq9n'"lC"Iob_P)N6Eme+R,,XG(E!"74X0Utq"XsMr.\8d.gaq63X2T_6+*1Y055mAUc4chL(t@V"LT_IN!(e6B4\]?V:R3gS4P+AQko4`nrDU-G'rTK/3?;+;te#W$>Mu\/%^Q*cKaA3dP$CRdi'ouOC7DY?obr\c`D+GFoib*1a1TlZ2s9n'rf"[Vb810'K(>Ci-,om017Bd1j6WXGLQ)Hri6b#+'`_';XGG-?56,P`(mZnO14X+-YFjtA)SE85.u'[a.eZ6*(h10p["ZZN7_D^$UL!C;^/+-MPi_)h0q*mnnGklefYK`mMl)E&:bs!8GXY&AU5?(in8@_.KU3R/K$mgL'M2fR!c6d\SI>uYh"L;fB5:"_WM*1r'LDfs]pK.=Ip%oZj798F2fgYFN>tUiGJX)$ApJ]=4o?@N6?Og%hq`,-G;@;r/fHBP/0=fX2P@YuP'`LTXY):sf8gGa&,gJY;RE(I&t3[sUtSi@_UOPNAg[jM[;JkI$\WHT_t?%LZbQ(f[pW!Fi+hXa1;;bP&Ce^E13K5lrN])S'pqP)&u\M[.bDa(&9dGNkI2UM~>endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 672 +>> +stream +Gb!$Eheno;'ZTV5'^%6B1kL]AUj#t+8Wf`]>Bg105D^bH))b[qp,e@P9hL":[ot!aKJ<,onXUa["FP$]5GnkH;Za;O":0^W!5^i&aTbefjO]&)T8[686K5uS4N7ucJO@Mn=`Bnr7rN>f$H2Dqnb^o(@(Hs#XqeSHrXP*`#GqEV.AXuUpQ?&Xgc''4P/5pR;HC=/?,0?N(NfUQ<>mlt0"%_&r'B%,fVZ6j+A=nI7`O!#dlTe[iq)*HQq']c=TfcTID"b5R+!HO+6Ssgc>mih*NIk^T<=/f0d'>)n3'RT;L+N6.s5Fka3='%E/^Y1">WY]V.ts)\_TRqbC!9Z])oKC[7K[]HVkK&C(2R7.uT2X+\OBC$u=I l!^-YKT,0%)BV]f2@OL4/EXN_rsu=8f7j/T^nU`V=Hm(V@e9)k[c0_Y_JqYDB,u,Kbd5]&Qpmq4J((n=gf"oB#cGUf_1'RPi$^rUpGJA0rFWc32=OrNh6PrQ#+5;h.W_n"~>endstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D,66#;5k0p=:)&fiNV:Z40D;YVQJfN>^C7;3Oa]SpSoY"aWicKX,8:^Xa@*l29TgCQElV++[RjTW6/^qRr:.b#N:b_[1`>%8^eRS0=fTPoo=8a,nTi#"W<)(;862g0U&PA#C>j-Iucg/mTD%(5%U0.K"=RODe!`5m#3lQ$h?`qns'XU1"IS>Z'["q(8N-GX-j^"i)EPQPYSl$'9B<[Eb:`VKs<:dj.H[>u^_uqr[/6;e's"PImEA\OFGtQd4e7>.S!bd;0!Hndk%#WA)"KZ?7L'-.Sm7Osf:YI&-/*pt5!?pZQH&e'gamR:Kd"@1A?"#&6@/f00hDkK;k>)+9t[E/?oCc6a4O64OlM[@gp%E@7M=Zg?\)fcidp,FMi8L%pZWt\>A,>n6g?9!ZmFhXPW<$7eQ%'iioR2dPJ8LL/nLA"?'i%">L"endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 871 +>> +stream +Gat$umr-o6&H0m]ERH0K-G]sVKm'(lP'-$a<="d8n\pJ.E1>LJmD.)Us*\P/!blAH.S:o(GOOA$HP[3]G^8]pB)l!FI/`D^f7GCOYMEkZe;#0Hr2P"&Oe"+Hg8BpJpUlD%GgLO;C/MfPD[2&S)+(aH40qbcV?NtpK3f7PL>[=nE&/GfUC$_3O.\]U#8=V=KmljNkT6HoQLblq&o[O"dWWpE]Ht.q;b-&^H6$kOdQZ1ceXJmEWPE-sQHG^H#dZX))&%`A/d5JrS2*V&qKLW$%XV9j#0_gN0UYCs6U)Ps6Z4lN"N(MB5Gq@4JFR/leIMj_Q[bCa_)Jn/,9`l(`01W=Ul[#a93mG2='Y^Lp-B5sb%"nVdMK+;2YT6QM"kFndLF.#^of*"ZWmj5e?HA@PUdLgn4*T%Lu,.h_En;/4)+oN:U]0U,u3:>/*uN3/q&cnMZ[bQKlOT%Au0F:)B?6mendstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 765 +>> +stream +Gat%ah/_4'&;BTE'RL(,;SXO[M*()]Bh?2N&/rJeh$[4hW)?c=-,G7Ho'Tf<(d\QQ*=kBSq]0BPH^4Z#F9VKP8,t7[1p-lc>/7!HSCUJeoqBQhINJ`oaNbZn#PGF0o1kb\H9b$*cF,?2=o#:!8*e=dH^<4=7&e*aK6-h(tkQ`@ioDnB7%]5"36A&N)D,>*GZa@?T,Re=K^GF5c9t\)MJ+@=(6fI&DMlM&EojJ*t"E:;9G[j+>n2,R*/je[pAZi-4`%"+>NAXhqI/E.AF\!lAd7hK4n845FE3Ad1AX1:[f;SC`(uD11H4Yrq#JGd#IY%$dd#q9n._g1HUO-0j3)D_GFO;VY7b-#2"Vh.[g4^4X_Ir<4\@@B1n,SN)O&+)ZKd029KS>QYTe/)>O9(Lpq1j<21ak/Di\fioYK(3U[pYJ!.26"]);_E5gKPR`#Kn._mlX32O_i*H=:tW`I]!46-]KNZm^+GlQ`!_^P/H;&@*8b.GRT<8Qf5BEMQU^D%//'F:I`K!0:4d9lY!]aF~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 676 +>> +stream +Gat$u?#Q2t&:F5UfXKe=EK"J\DQ6aC0ii#Upkq$@V%6XFJW#OM_AuKNec4KY,d*]t`753JfU:FK\HNq`-LCRMV>q8O/nR#o4n']#qjfqGF)_*/D9IAn%S'oN#G'9+mDptT_GKTib+&A9r7!DN?EM_ZPe)"u0nB;(^+O$2LQqH6,FP<"_Bc@A.Rb1V-JItg"8lndJ$UNoK^#8[';V0qMMT5?Nn"Laie=03a2"_.edEZ96V_ZrR2"p!^4@NX9F;L1MPLO8T-sZQ0+kR`LRAY$N,dWeX(oLq-YbRbT:hS^X>?-_Jl;qr,T7hRXEO:U:372"Af)G_*AqMS[%*e](HO#FVs.-"7jbS=*H7/8$okL;fY\kWJhqtNFNIB#QEBaWQ5d#8\m.Km"Nq-Y02Vi"9f$)S4Utk6`\B>HpKQ7b0T/ijOe0`_)^`N+d,XK+^"M"E]T%8SGfM5J\fdN27^e`k8ojdFr2X(7R"I"I"sdfS54UJ2>bWB(;bsnLiBMW3B"U8N.R[p_Btbr06(h1>(6OsmUoG~>endstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 665 +>> +stream +GasJP>>O!-'Z],..F'/*>A4G=*H/Wl>&UWEB[U3lpG=aMN\fE=A=n=k.8\0=OHhf2ci77!a%caH*`;a!.6ohHMdZ`c'B0Hh=7n)"-SU?lIqmB;AZH9fj^l-]rn_5jDm1L5olAl)5b,,8kXnX1i2KQ`RfLCiE:uA.[:&55-1GlCUFe_CF=>8=YTQZ/)+*o^$cERPi$]M-8b,'!Mdc4fhQrP`hMPd-\XQK9"S46mLG5Vpm^=7IJeI.W4j&k/7BKKW.TLu'7&KLRS9'0.1*H82lb[-HaUlU!+a;`D3(#['AB9rm-E@-r$@inUq60$j(.3"(qoOfb3q8TP:7\iqWi;0434+%O]mu]JNCraDrJuL%1"3!j\aRm6k@)3;q&o^-(t)_n6UCUoALQ(uajBrqd)r*tR$I1sCGN9$7A5,0O)jt,1!0,iBSO65<<&S@d^i_>iHWqA^tkYBT/*[#"fOAVs1e\FYs\%0MGMA8)Qh9ElWmWs;V;GWMOa.;nqZgFEJro-T"E:B.bgq!jS8hU;:&CK.+Vk(K7&Xnp=r]P-o\]c"WMAJH-lbs6#elj5AKunEQ\H!rrendstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 435 +>> +stream +GasbV>>N*i(l%MT(#P"m0QCAGJ]Z_-.0_`eWeh$@Fd,b/Y-8#JIrANl-'!X8fgXd^DkDG,#"L7]^52h,&3pm;fEJP`gp&q+AhYR6D%#f.p,qQL\$kJUH&>FL@tGnA.2F#k>X]"MjT=l80%\KF<]hFdBc$iiINM$CnHXM*7Ubol__@HOmp@;HkA;>W+P1#sJNnLBVt"1_WP#0PU=8Mf5<:/->ut7o^R>&1383J%%+^57/?.8'ZiOUW.[QPs^\[(R1C+(bnA%7jOjf2]a(O;*g?,lm)TmHLe%21eQT7`a`le<5\;;K:U)??M1MF>YRg.;T,/]Be/q@AJ3OWudD`>'lCg6Ktc/=0hm%!O$WRt_iiag"24Z@qT'g&"kS*EqHZ:L(M4@a1uUF;6+M0d!:RN\4SUr`ZffGi(MB'WC9HhZt/>2R%K[kI~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 495 +>> +stream +Gas2F;,>q#&BE]*.IJp[[Q4npmd5aZcsX&_7R&%!1+>NJcj=a4ocZ67j&2\jks^cGFapH9L`[4l1E"Q-pf*E$?eQ<>/&#\Tan"0pc,"R1kLlGT?4.'-#eE?@M`al8aQ5bM)+ku^(d6_dh*I?<60V(qDEa!btI9/\&%2WXcjn%91<^oA>^G:f^NiE;fJY#YJ`iO?'f9Nl7endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GasJL9i&Vk&;KZP(%8DBJt:U\iDrNE84Woq*]U=W6.aHog(hS6mre`,*]0'sZC-d:R3;\kaM"SVD?[33#S]UA5g^^+Qm3@&cD+>".)m[H)8u&)[N.7<\4$5Tfj=LnB,aK*.Kg4X;.7f^o(-rQB(m1!VA!KAK]PS4>%<[#OfgGb=Ya@IZhsma"lcfm05^W?L\)&TK,OC,?@@8J#:kM5l=QAn>m9q,eFNR=U%O@Ih:>#ocKE`KVf#MCl$[bg?0BPt;@f!]PCB4G;?NWJrXn+l])n3-k4^5f&~>endstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 411 +>> +stream +GasJM?Vc;.'ZJu*'^'J)81Di8]ZgnL,m81&N"Y,OCnpcK7/9qh)SShQoSL`rDNnD!rq*d_oGS8FMY9e=ZY80LH&X&)kH)C/khT"RAALg?Em4jK$ndpA\Pu19A)3rP'DmE?0BlfAN+!%YZo?2[lhcU>(1qJ+>a5b,VR-8DltNAR1VRU@H'kg/;endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 425 +>> +stream +GarW5?Z1NM!6!dn'_ggW9W01f]HKXPk0Q\J=L+7t3^cV\'UJ+?YJi_qAnb.0md>98+L(M^h49kIKYj/jO:$pJrC+QBH'c4M*a71`ZSgW@hOI@Zh8>P5@Ls+L/F,Xiu*G.=M,sOj:68:H>gr5osktpElNS5>kP[6Z.ZlOf%[)$]Fk)K9D<^;[5,Y"Y#;E%+`ddLM/QBB^ME5N5aO8/qX;@Fn\Sh["R*;V/46B)VPkb,9ko(.?1-e+NNm.s[%5)GcUP,mcAXZ`89KQr$D(+lp&eg=<1NpsH9Xe#Sa-~>endstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GarW495fDI'SZ;ZMR0ZaZniBsfa5X;"CF-X-J_M.>$;te5b%cMcCi_AR%)\qL_'o'BCM,5ET(#\"4nR(b+TTP>KEq?]_ibIN2;Ce_/13(1*+kKLOkgFk2?0j__R/uMg..O#9ftNjZ!hJ$dn_qN:.lQ+RV+5VQ6VZfBIAR96491hCSqQ'0JEd*/]X%W(k\`4g2X&de?5n](Xa`g?4%n"q2N0R-#\nK\@%s^cLauZAr;$9\VZ+bKNqinJ0>LF'`H]gBHSiRYQ%rWjD;H9A>K>4UqJop']2"UaH7,93/72t>gQcWNkSX$+Z_Y=-m@"Gf~>endstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 851 +>> +stream +Gasam?#SF^&:EYBlq8YQ<7D*b)lnB@KHulM5d@'kM3j-KOK5T[m`o\EpYGEGQjZJ9$U8U:1V5Gi2Sm2L/DkFS0TP)WXU/S]U,A=Uh@LkQVGZNQA(F2o#&?3^g%NM,$9U#b"2=#-Xa-SW_A'!G?sY@`^7g@oiH,]XZNi2/HO%EElapZQpS&r:DKJ+^Q\YTlqr%=ocjMKLq?>8ZV>gXiP9'r%b2ttTWsjhC@j1!Rj\aX/X)Xrr@DpcUop)am(gleFt]5-h_,CKSb&(V0i\s'\L_eZkZbjN*RB5a<-aj.Ra=H0d)t9mH^0$Jf[dQY##\#&8+s>OKS6KGk,X'ujptCjE4:Ndendstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 607 +>> +stream +GarnT9lldX&A@sBlm4Hp#7",(-I0^[EebNnRi&]6>SN8?)N^m#anXb;-%g&J4W8=n\*mg.&Ff3$pJ";2"bYPU!>5Ce!L\lo^fE_Rkg,'laCtq/agZ7,hM9a7"lC'eIY>Dq7#-aJ;?]>">H5KJ6s`2)(B7VA+n5sX9j#(-!V(KHR3ugWNS&DAiK;P9G`7."0>N#=qeG5bnanBfq0*VjHHH6pXgX4n3]cc4K?bfg9UH`aGp-Rh"b4kJVhEY(XS>*FR1j]fE*ZN%HQgie/9q"DA-SrL1Pq@K+a`=,6pp2<\kHdCBX8fgam)UN8r7&5gfgQ_^Epa#K,l&s4hr!OB1F(9H4G[^F1`X$'H%!k';Y9?K&`o.*;/b+TK,.*`839f(_`pTO)EGZTAG4P,P$MB6*2\3,n@(L"eA72;RRCPY,Oic.bkNb.P5^O_RT(`Z7:M:L;IMu`LDr9s$68.;e)0UGTU=bA[(Kl>'a@8DcNl0I^-Yrl`AIV?lt;@nld#Y04Q+J'T-NDmZaFD,@U3\;#3-0~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 550 +>> +stream +Gas1[9lHd\&A@7.b[mX;WaRVA$07CqK:7Za]D,:'(Q18;`aB-kVVc'p&Ki.!4V6mT?nlKMjCLZ(jt_I`k;ts@#,jf&[6Rqi:eM!S&![lUGsE.bbB&Zl1tu9?D41GJ2_0^`V?u!&J)E4ZdWis<+kjr*g#^,qI")3E#5/G%lXV##AD?IXJT:*tI>Kcka-"(]+iH689M=n1OD=og@`+G0`pC[W/OZK[C/qB)]n<8JU0H`GTgZsjTjtZ;tUKe]NFqCA6Fg#/BJJErol=2#3$dDKA'eJQI'#un[`t1]KLg`0T9L0C6\Y*0;\"TNUCk;Cs^5g%HcLagMtK/>ZHc`"U6Yi\el(j]WDU;hV6hMri\A$)Q-KF="0.>B>#1*=nMCc^:s7p7csM/N9RIEPq;SAA=Dhidq/O'jI+G$_B=\p0b0OT:`9fINn!#A#PO^%F)2abZ[slM]H:dDop]V,r"N]'].iYpIb$hm_;#Yo;$F]"T#-S?e_aDpHiWendstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 916 +>> +stream +GasbX9lo#B&;KZL'mo0RC$W\A:EW=a'MS"\&.7j$#;3l"YSp_d,WQP/lanoZ$05kap=POOp$VFSm"%fr=$>R`i+E2UI1NtO6jrM^1EW>7"OY?iM76X@CdHNgS@)Oe/W-2-\!g.:'8lI+kpS6`<-@[_CoY'^'@isG2[XImi-E)kcjQRC3"1,[&-'N-VUN0FN8Z[R"qZL?_(Zi4V\&fZkc5HfS$!POI/!3"L_kCs]P;Xp`,Mip[2QJ?Tf,Z67e#+CjJ\@miY>-`(K/WDXO^l3%A$LjSUs6)\r%FJZOH[m6X<9`&61`m]%YAD2JMlI(<>1K$bMdhBm`/a>Chg26MLT\m'Op?NsrDS3A[$f`,f`^$W:+WIBY1fQBTJgOt05[:j3hN;/iKWTe/$&i).Qtd5:7HL-Lm&?kcHue!2hYK/RPk1FnA$:gDoF,43'6[NSXh6XQ-'@>7DUdrk0/qJ0-D7D.@WCVkTTe(rk&:n-Bp`J07`6:tZ]YmieSk;sJ%P4Qcc:U'/O=gk/mUG-(hr_7Qgn7k42NDV:'b*e%tQq/?4>St%2+Q!FVBL>;/.5r*5;Ghd70LlM6-Je0

dhb)-0oKAZ^\h$:2e8",2sW(X%F4G%;=';KI./W7Arr$>'\rE=d+g&5E.W5X)NbQ$m!PqoXZ@2ifM87"+.4[%Qt5Q\%VmFQ4=6OYiAg>OUJCXAO24$f?B_[iT.Olt:B3dtT4R'SRlZe3-bD"m_=>;2U\:jW"#*KeMtP=#W81p7U=IeKtjg)L?Ol%T\`,CR\%8)c"[9We\K8gR*M2=e1^t>KR3#IFiUFmUrJZ("l\HR\Prj/&4;-?2[K@iLA^]SGWVU(Z@U~>endstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 784 +>> +stream +GasJP?Z4XP'ZJu*'_c/O>;_k&^Q%qb+K[+ZfcZjZckd@5^f+a@[R8"trN;\J5Qt+!8Am^TrpIGf_'XZf/"gr60f!"HB;J+u)JD[\>JS1OBMeEehbT=Up-Qtm-IaZPU%'ujV1n-rB\@mfqq,`CP6Mq:]o4T*q*pt--?P(72HB)+]K:;t/,DRHH%o*kjGmQG%P*3-kUOVf^i3SIo8\Nm8'879TbKh*"KSkEY;TdKX]j5p_fgh^M0/08r"0p*T[E37cMg%sVXjq\2YWZ%V:6\JF\XM-:BmqkjQO`ejYP`EhSMc94]9h#g\KL6nuK/D5kC+l&?3'r2uIuD9F#^F*3e/UUE%%BS/KgUe8UjEFD\R_9]Qg2TSpmNTPngq?qtrIlRY.rr~>endstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 602 +>> +stream +GarnT95g:b&AJ$Cb`Pl)c+6YEIA>Fq:i461,Z5mp-k'],fVQd>.0%#f4A;I`Xd7/SpR#k7"u[LQI,b:dHO-r0"#bog"h'dN+Pad[SG\eZY&ijCEq*`+38Y]B:r.#Vl7sM6]@%:q+K@H+YD-e0)^6fbGbKV:!64^_=Do8LNrf$2mE#gSdt8H#S2T:Hgtboe#<*4nL@CB=s%2CEJ_Sqg#2\UMV/;IA!4u:h2Yt*YYWREtXl7>obdg".Ue(:[+QJ3[^$U?Ff!3H\COnhH*GeFJKX!),1MNS``hiX.bd!ie5cHG);=VERAQ\ZJ^MldkWjOB%NP-'[q/di,2$!FlrfIR);N`'nk.nHLg@TYt/md='t\As$$pt;7m[c9@>TO5L_;W]R@<&1F_j6Zrp&-WlLMJ*3/1pg+Ko-FZTbE"ckrRU.n8_#DtG@3AP3JLg79-h~>endstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2Hd;R_m&B^lp062^U'U;eujm^+Rs[5rB?j1+lY!^T<\Il2M9KE(ucmdjq,!@D4'.r?rhWW`S6ZK/p,gL7^m`lAHfi)_@'Ps=<##?@q!3MRLl+g;U*9!W_Wlufl2>Zoe599E"A-uIlnVYm]Lm8nJ%k87\ei$rYT7.0`0jhJ+@_ihMs5^bRZg?EH(Tqhep(On,:r_e8K:8'9o@B:oD/ZUFf0?U(F[AQ2s-^]Xtq&D&2qpfW3Z=[DpAN^BS8D`2!*PW>Y&`?3fp=0G#FJYJMQV+FWPl`5Kns@2cL&7&JF,/NZ.$.J"^e??>Q"LaWpA4/9(c@%O7`Sp'H$%GTKUaON`r!ECDu;Zjl)(CRDiVMi_YbdF$QrbZ%4\Z+pIs>t?/FHA_@ni-\5DfK>9?(PrLJl%c&G8isbrcZ[13"q7RH8Zlk6rS_JjMT;*2.Z'WrnrkN%UlQTekX\;B@5nd;Vo+.LZ]"4WI.nRQWWhikaYV6jGR\<5dJK*fh,endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1441 +>> +stream +GasIg?$G9d&:Mm.R$XC3]+/Ti;EisCKX>R;_?Tb:0>^b+F`#6_A-i/,SWSnO9\>jT#fkN?gprl#V#Yo@$f#rj"+1F6o0WMo!5`@SLA`9K9:1K903:HQE\rNun>8Dk:W=6&07lJ$.NpBI8h$K8`2r^Q"`j56>hK>F?`nnk4[X$r,:,pNBuH$aj\[Kr`%k_`AHsFgW+W=`rf:%&\'/e^R/tQVS7Oee,8)Gs0g]&OR_)WSV9hOUa2WELcZq(/jhRtZdL%9T4iUZb%hfP+5R_DJF*q]u5d2:uUm9nb-R*Hd:.M9KCpqh5@\,)Q`L<[D/Y2hBT]-:G<\QW%9-;&/d>o%0+B..82'_o(KAcOPK@j6gCR'\FodID.hsFa0DPd/V3@:F7;,NdMO\'%mL;J-X`g*FW7tIVSr+bR!.On&<1oK6Q0>8R3ESrcZK)&?Qk7uF#SG&r?B6&=@\EUYrHBMS)R$c3+#Ft5DXH-.ePW"H`NIedYq.f.V4#BB@.=nJ^d6&)M>WaFE7asH3pHBAB[GU]`UZ(SW_EIP**3eHS;g[eqE5`eAa_s5EP7hRkdYDaPj]*%tSdTC_$aBfkW=3K0+R7U4mj^)gHu(3i2@[l_ltX-UC>@C@(J$]+"2S$-/%D!bH@`CVAFlc;f+Rqd.W`s?s7`QOE!W,O]n-S%DU6"bCV2m8d^F\QU'5n6qmA9*[endstream +endobj +xref +0 89 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002103 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003011 00000 n +0000003217 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007543 00000 n +0000007749 00000 n +0000007955 00000 n +0000008161 00000 n +0000008367 00000 n +0000008573 00000 n +0000008779 00000 n +0000008849 00000 n +0000009133 00000 n +0000009471 00000 n +0000010071 00000 n +0000010734 00000 n +0000013178 00000 n +0000014123 00000 n +0000015440 00000 n +0000015760 00000 n +0000016862 00000 n +0000017323 00000 n +0000019227 00000 n +0000021044 00000 n +0000022351 00000 n +0000022616 00000 n +0000023273 00000 n +0000024019 00000 n +0000026285 00000 n +0000027541 00000 n +0000028874 00000 n +0000030226 00000 n +0000030989 00000 n +0000032002 00000 n +0000032430 00000 n +0000033392 00000 n +0000034248 00000 n +0000035015 00000 n +0000035771 00000 n +0000036297 00000 n +0000036883 00000 n +0000037360 00000 n +0000037862 00000 n +0000038190 00000 n +0000038706 00000 n +0000039183 00000 n +0000040125 00000 n +0000040823 00000 n +0000041464 00000 n +0000042471 00000 n +0000043346 00000 n +0000044039 00000 n +0000044995 00000 n +trailer +<< +/ID +[<31d4492ad80afcf4ccdcdc35ef2fcb2e><31d4492ad80afcf4ccdcdc35ef2fcb2e>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 47 0 R +/Root 46 0 R +/Size 89 +>> +startxref +46528 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_af0719d5-5a49-4562-951c-907686477f73_20251031_052450_analysis.pdf b/ai-analysis-reports/repo_analysis_af0719d5-5a49-4562-951c-907686477f73_20251031_052450_analysis.pdf new file mode 100644 index 0000000..e3ec7be --- /dev/null +++ b/ai-analysis-reports/repo_analysis_af0719d5-5a49-4562-951c-907686477f73_20251031_052450_analysis.pdf @@ -0,0 +1,932 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 7 0 R /F4 11 0 R /F5 12 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/BaseFont /Symbol /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +8 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +12 0 obj +<< +/BaseFont /ZapfDingbats /Name /F5 /Subtype /Type1 /Type /Font +>> +endobj +13 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +18 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 91 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 92 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 93 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 94 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/Contents 95 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +48 0 obj +<< +/Contents 96 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +49 0 obj +<< +/Contents 97 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +50 0 obj +<< +/Contents 98 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +51 0 obj +<< +/Contents 99 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 54 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +52 0 obj +<< +/PageMode /UseNone /Pages 54 0 R /Type /Catalog +>> +endobj +53 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031053523+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031053523+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +54 0 obj +<< +/Count 45 /Kids [ 4 0 R 5 0 R 6 0 R 8 0 R 9 0 R 10 0 R 13 0 R 14 0 R 15 0 R 16 0 R + 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R + 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R + 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R + 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R ] /Type /Pages +>> +endobj +55 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 502 +>> +stream +GatUn;,>q#'SYHA/+-o&ehl!8PE`NVfiAD-9.V?[.[+2-9XU);el_tNS>`Xm'bnjDied)L=#X^\XgkO"[fthc.#XQp[1o\4mLtBu+AO'&Jn2\-qYWCh]W7@KW%5iNAqhH>'#kHj*rijE(D.;Z2o=l\SGn`?AVM?0No389%#5ta3+`QIP5h`[-";Qn^,DPfJNm98,ckdOOiNn.tl>Q#9#BSM=m&2`!Z\$rJn$gHk,l`,-a4W0(FZbJE<5ro;IBuJo*@F5NI/[C;/14SleMMNi&W>r9M"\5D9Om/&"bSTh(me<%-+0*4F^UYAu?+LdZ<endstream +endobj +56 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1889 +>> +stream +Gau`TD/\-!&H88.0d!P2]doUihXA?RPX*-oZoN*RWt[!dlih<;HemL8K`:h;>oSuX6`oWK-rL3#4#>3q4Ypl+Kn$Q,mmR4p?2/haKC+3$"M<2tJboI;m_uXC4+FTkKoQpHWT"kSsGp$-(Gh+Lc3I!;G=Us()/^(E+UtY%)dI>/Hgl>ck1S#"f?_@nHJNK72ZVT1SP9J/bbh^\=27R#0r=s)-_;rMYCpa)"QMc_lc`HC']0Ea$0I@$:N-Umb(/lYj&gbIpn7bV9RaKAOD=.%X[<46IkXWgpF,W.=TTJXP'bQ;kmoR.CnX,)*"a0Z4U*QQ/pCUggaK8Du![]'7.\QQtGpEg-O9iRt0dmM>>'O_K`]f5mXNW1&_&r.]')Ng8\!.1KJOL1D),V)1Y1;G8,.rFTlD[aE&E!,ZA?33@g;I708)fo:6B+AH.-fW/'^aD>-nG!h+]'nhOp[&lQ<^'mU52d#-NWgH8Q_>eg,S?EeioQ5+5&jtg7_ooCG=)]bS>G$i_T-0.IDTaM7t`&cU5:M#\nR,[qd7af].&O7N4S'IX]LCCW,QC\/YSV'.Hk=fYg:hZ6c:F+%GI#D[kF6eo*f9_(fj_j>na(@NZ%`og2e1_HutA#i?7*;q$M9T(VXkRfuG#,5r$8`\5L0,h+\T&RDko/p(U>A+b>hlSQokDbdRiRG,Mp)TGa<"[e6-Q@Q?Si9cD_4sjNDrE$ti[a/!'<%8_oHPL'[O$OrJ[9g[T%EUq%!BAY)>umP9THd_-\hM[E%@[OSunl3+CTk%ZI4:WBnrmB0>ZP">L5'^G/+_XD0uF:?B^KHYh5e^I_-fnp=Zs'MGkL8JI+DuQH7S"UjIq/L09li=],ZS`-o)L!Z.6nL.nmUXd9]3-Y&b*sQ[IquXFj+s_R%D:&V-ng*?V3IhlW#5a^nTq>?kH>*q55-Lo6cOA8fh-"7W>,L7L20"lHdHA/U-ZeT9!6Tm'L-VJFU[DL40W@TE6J5`Pp,W6R0iU_YaSLngP*''R`Ml+A1VP.,Pm,LP;D>$RgJSfW=$.Ch_?CfZDB+T)YPN/Y&KOh8PAbZArj2gV`)j#Z(GLK0-!J[T.)q!Y[Sd-#Bt@O?tL08,BPTYKEiQ-^569C4$%srgrG*&K9Hss4_(Dp\,$4XS&It!^s#&uA.33E@MJIjr,]bafhq9I4j&r&m[Z*AaOeVQ6Kn\a"eSfR^Mjp)fUq#le"?RlktUK]/IY^-o98m8_Jt-:D*9tq:COc.(M6;AT`~>endstream +endobj +57 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1567 +>> +stream +Gau0C9huuo&A@ZclEX;i6(gR^!f)n?4p9<,AKb7N^rlfPS>hTYt7Th9^q^ulp`m_i:T"'A=6ihhV6_J['tAUKI>Hi47N>hbZW*?W"3\J/rXDK/WR+$]>rh=OHd!I/n&BgM?tl@L^5$+bQRI1h-T6Cn"C>Y.M>C+=VmfuiHZ#eJnE'h9^M(NTEOqi+mUADY-#J0!PVSuLR7atJL5"sZTQ[P*hP<.Tg[!O'&RSeUXMrg52O`.[_$/(Vb7U)h#glFgj?c$Od$i58t3[#dW$0EPL+94.CJN-O()*#]r70Qp2.oQ,("Z6a!cb2Nb[n!/D4bq\EI/gO^Aj^IlWY$4a9Pfb4q;V,+ifZo6Z;tS>XeD4`1+_V$W)=AO:?q2[;uB.`)b9PJkXS/8EM%-n`!IM*J3l6]2I<9<2I`)\I._V#$SdD&2hs(>*-2sJT3LiJZ"WU25`edQ@DWbCEO,MLT_6mH1rfd$^gB(PY@"j:-fjbo`c`hb7Za*H0KFO<^OQe+1;p7Q]:7gGEJkmW&!euoB<)?H0i>3aUr-,QGm'?oY`N^7BRS@s.V%#cQ'9J%0j3Q(jIP3:gNiN;emQ1Z//r@OWt@k2eqT]&(.6pjfI94;WU1dLn$8O3a=l,5#ZClIVmu=PuS8d)6%*"=PcYTAR;Hd?%^hae8\N'iSHRMF\8iCSsBQFBM:ZfBS$51.kZ@Z^5i8E6;Up@[lS&]Cbg9V\p=)LMg#q-gFK!s2R]B'YFjFAg_2;6Pm1NQG2$mendstream +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1326 +>> +stream +Gat=*9on"!&A?Dn-tt>FB4:^hYsFi]&13;ru:RF=3?7NPd;t5aD8;O@lC`[d?AflXeQhYf5eYihWV5`Z]MTg@=?"'KeT6Jnrq&*8K@Q.A'D[qfWp=MOX5A$gDEnISs0qTP](%QP/sCHU)bV1hLYm\;//I^bZY`3ja9^'OE-dqmb]P(p$06SQisYSe7VqK/nmON]NG]hL0g%+TN"aZ'6;nN!df8D+KQ1]ZZ1&g#D5u\F]65I7Qq-`91]\bi0hXCl0YeNS?hMSUTX,V,oRekdh'PH4:/7hr\,P48MG.H[!I=$B&u-O*\cb$%1h'+-WO2Jq1BTd%u\tC2ZK*1;P"V/$pa,ln8X]9EeG`tj9C^G@&RbH$02q>j2.CKY-4H1.:5HP7&401)m`cFQ6RBS1"eiXq*U!hds"TE?Pr"'JK(@`ZK\P>J&_.&cO76u,At5#XOkqKC]\%:->C\C[\E?2bo5>KPMWn,\%Z@>*UME\/leG-i3JH]#:<8fPi(J0p)?NYCO.e5hPqlV=\O4"?J1+;b3_m-[0R]5V--_4CeWkXJplB75DMKR%Gla-=5U73;a+&ci"DG3W;q3+JH,8%'ac'3);.,PQ'=0QU9kphmue%=`p`F\<)BCM?OfSmn/Y6aqoAd?TFKendstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1864 +>> +stream +Gat=*9lo#Z&A@sBoPM^9q2B00E[$lMW*nsLarsd!%+5.98/gm>#f?T;I6C-\_\d(8"S'dN(\2#&s9L4eF)duaEirqPYu1o35B*pt,j_dN7jJendnUfr7/*DWO,_b!Zg68j>Pmi\Bpg[=qV<='DZq1RI]_d"8[5qm\Td-(r_7pec=IP?)8S;l@4o<@Ndtb*WK$D*+>:V,u[m+N5GT?rZ_nSXcIDKF7g#/D^1=sAVT8HY@-nN"A<=JDQK$.c#k#l[3]euds_<_3>9\0PL=b+EOo@H&m6!Nd)/72/X#'.c\PQcF9S1)2iAuR7P^2&80*s])Di/eZM[9TPJA3DpX[>'&nqJPOsEg`*aZITdJ76S`E:;CY"*N8;ASTY#j2t'Q^H=;b7+oH_?^FaJ27pD)Y*Wg2:\;Qh(INUWJ;*,jfqTX3!r)H1C7Gi1.Gj&-,*urhXEHVabD#5B^O@8oAI]l?,T'UF_qiD?j@C4DcpBs\"k^D_U)!>BdBq$,,e^=8?bLm3co`*Sn(J'7+/(=1s8KfklR;-Zp_QVFQu+TB8X`"kD[h[U%`S6:l:!CcI#RQRa3,k5Q_0A;]Y2C#'l-r(W`.G.V4:sa!?(q.7eQHoUNQ^cP]O#;3f@cNGZ7SME6m[9X%']g.3RKiM`baQS5d>A!PfapuT4bb::%3B%!DEX^_k[-i]oR7q[8c&.P'ra4kd:dp/i=#ui>dOk%:1Q8\]ZdEHS/O^=qL#0R^=[q*1p=!T&3Vc0.*UAN#iABW%tRpWnfl4iaO.#qlMJ;KjDUK">DHa[,O0*B!j&^0'^p5Co#&ZJ46ncfX/]1nCKnHRqTHa^m_9ECLaH^K4Sq\-=@K)m1ol??Fn?Dkq[:Bl$ET(+ir;_a3i<2;HHraTkZo#Ir:s6nL2dpTAsQ"1Li4cIG!-Q;`/ij6;#S4fgDK6D0.9qCTo`pWo)?naDk6HZ6sat>dk,b>D$aem(7cK^pC]e$h[t1-fcG?fi,[5UV7GS'TW76sgp)=W0TCJ!f[B=Qb47j+S>T/le%4u7B#.T:"W+ZVq$D[U2)D"uDJ"2H;,u>7^BHPu'>C\e('8>`Zc5>\F0485oa'bPqu#D@`ugIK6G&dY:F5Ga!U;feG`nb"SnA%1&:n0nN#lF!!5lk;m4D_3>L(Y0gfT9le?@(OY4C=g>0j3#W5dI\X*@k*Nrsi@V/V;WMYS_1MYH]eSq6m_Yq^JfZ6YE\@&q2SF57.h_g"&9l777[1<^3>8)IdhAOei82A6PGHdUUu`&sT>V$8c8o*oqTod7ZSc&iRiIYR)-s*Q']nL%]gkkn>Vk9mnE`rk2%>Oe6W/%qX)9+S!XN9SYU"h9D6nV'BYjqYMaL^Wq?[:V.WW~>endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1362 +>> +stream +GatUr9lo;R&;KZOME[1T(,1h8p;R)2PFCj^KQ6^MMm+.q=^a=R$t4Ya[NkqZ"3Ii+^Ic#YI1f#:e?XWK:NZi0?L&sF0QeZDA,2C7pdY$`\<8E^lMn@:8ZothE^iD_V]/b:WKV^pVGC_!K_>A6a].l"5aY4+:GYt7X2-X0#2Ltjj,/ZtYV^M>AkXH=P\aH43/';bE8+u*0='4oDgdQK,D5O.ZpqSaEXCX$Io^Y\17e"^=3UNVB.d#QPb?GELPF52!J^`;4?Y(=B]%ZH1eMn]DC`[02uL%?;gJcHIFigIVF[R5\gkOZV(BG/VT+<2?7m$7,lMZgCNuh>'J`%8Qm.G-n=7Jcf,+[Vo]>4+.T@tLllEj=*7]d;$t&RTHspi,,8MkUR[d!1g<\gX:##P5EO2VYlp9qW2*Ah8](f%At;46%hbu_q<-RoY>u+bO.CCJN.X4h`h9\J;".O.o-fe75LRY&0mpV\R7[G'R"6aPb>)cg`dD]'XQDn$RLD'=J!-;6;8BrrC`Fh`_G$?uR!hLMlR#T$Ym5u'4=5e*EH$h_Fr3/[h?#%bND;#S25+kdfZ*9e*S@'@afqdn]$tNG)hdaW,1aFejStr_fj7/Mf-rW6fm#57?iU-"m.L2OAX/XmN4Y<7TZbt*Zcoc8Sq#.g'BYM)Pk*"cFi2lVQT$M4bG;:@E\@)#`oV06E73AECcMPoAQn.tpk)'ZIB@YA`<#988?&?o)Z9dkb5Fhendstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1406 +>> +stream +GauHJD/\Dn&H:Nn0iE-,HWgIW:ak52Q:gAnQ>Z@XcGg?Yqt2m++XE:m]@H-[W@IVco8MkoZ$g<7kI\K;!q=qa>'E1*!R-ngGJ,WQV_F]LI)#.YbPhKf]k_O?\/p_:D30Z_UA3@$OZi:_J8P,((("A:H^NADt\JfIRkuM=aMs-X,]?4Gh.100)KL919"K<+1M)!>,c`_Jig;c._F/TrG87K&brH-u-]6!mmt3X5[FhXW`CD:m0_>pKJ%&[)+ebZM,`F?R,ScUX2`p_I`gDT=HB+&2c]RQNkL*lfLgTg)%SB%-;!\]D@7reK`dP)Ck\\>*)YO^qoo1G].ed@TO=>N7[l0XH;_npOD?q&s=Q:k?u_Zp&\Q9P@%92#[;bd388S^c"m4bj;]B$VUkA:[n6Zf3ZlDClW^CNtF\2mm<_"+%3WSMpGu90S]t`9/LJm)"$M=Y>9qQ.ossK[#CW-Y>Uddj2nqY".4`Y[PKc;.lg?3()N/=A=]24D^?P>_XFM)S/.-EUhCYUbXf0PN>mSSZHP\X32f`i7_HSMk#\2%#ZPF[Mab1IPd/c"#hK5#C&p?ZZV:7KuF'L/O6_25SD+K\^5)BkBYSO'FVSXW.C$+^=MuVi*A)2YU:dS(P/9%=,[Y[n2LRD$LA/2sW\NsF8#r3pG*\(cPAKRs1'b,#R28+^i['%+Jj3PFdMP"TQC)`ua@?"5r3(A'l$jU.Kaer1=Q`rk*]b[Gl\R=!Ij?e`V8qendstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 431 +>> +stream +Gat='92EGZ%)2I;=Heh)%S1+8*A-Q;6q@p4`c488i8mql#%J-o$hDEn$@^_O`,r:+C*=9(YW"6?o;c,Qdtm?"(eSa,uM)b7M4r$!$9/Z9IBh6-Vl/;>C&I4S&jgQ1!k'Qp\2:6`H\m*Xr3^8'c_`9-8A5).-O]e~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1271 +>> +stream +Gatn&CN&3%'SaBc=.Cq/fLeeb_`%<[^pLIV;XA4b.T/./#B4-ak]dB0^V7`8Y[/rgY%&W+n7Bm$BARp[)'(R3kf%bQ!k8WsVkFU3!T>#?X)1-^"u!XbqaQ'bdW*)XbdQh\?$l`mBZ1Fc\A4:\\bT[d-Z336d%u7%;/U(o_\a^B)Q(+U"9esAfgUBhY8fB"n3E+e&hR@$b]=I^-MH<[!G$r"i8.K_o!e=q&M]W+PC&`qaa5OpXp9LH5hTj1J(^X'@(ika<_7XN+A*/%#H&'qjH(1#"[Y]+R&R>Ss%%VQ:T:%o&/OkL6c^?DM8/b&<.p4o7:!YT[RbkSiW$Fs7[QR9i.qM.6bK?%:3:NN!6dAjkMKK!7TMcGF^h\6o!L[5o8KaYGoOC"dd3R&)bm/5.X\#$(>AR1]5).R,RmaheZcbb6V1c)leT8eX]$*,e"Qq&AA*QZ%ZV`0PD+ITgkhU$'@rs5k/M?mZ=_d"b/=QrM5bCRu<._aW5Za7)USBd']_;_B>f%Epaa=>HmGp$0_S!Hm&9/ktN28T^PA+BhQ!V#k4-A']V@LjH?I`S,kfi](r2OZH)Q[o($q3;OU2%F8#j>i5id\3G[3VR,/Lrm).%5o?PsY1nri\$oON4/PW:d])k:%tAoKW-inOOd&jdWh,$48`$.X"GJ#m8,0.?Gl)QUA(M$fj&3#1S7/o'D;`fcgJu9GL]'I7rGKOBTE[^Qmfe9PfEHJ,Ed&-7DZ0`:o4^S~>endstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 229 +>> +stream +Gat>L_$YcZ&-h():[oO/_n'?4CIb'n$;&tSLosX[0!2&.^3,>X&.e?L>\=!2#i(.3Cc%5H6mi&TO<#`X$"SU^$m#Ft/lR=C:J?R<\;"4t$@T\!T(_QgrJendstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1070 +>> +stream +Gatn&>Ar4L'S,*a$"qJJ/#_^2!GY';?bL<)h9PLeqbc%nN@e?"tpG4%\tM`RI%YP#>YV7u-?N(]))=q-9!]sUU\?+:W/^AJamA#S9Q+gH7MX(A[oJi\,\o)bW%+-&OBF)7FC&#`R@)HoL+ga4FuZQRA5faD@bR"hi:(.mq&rNnF[bAUDCupLh(4o1C)nh.>;`a)c_rE40]Cp:NbtX4j9Rgaln6-7*\QO&X#3`1L@E*/EJ_a6Aa\>2bJhr;CAi/;^n3KsBX%soVdd6c`KIF.5Ui;->.[rKjIkQEI3k2XN.,=)eC"lZM;FgLGa-"5AKfGAt[?DUW#=BrY0Vs*N(QEk3`j?eF+]VmS_)?Sg`7`p+R7>N1=&nS?9;o=/5$sq\Y2%LH4,?haJiZfC]itZ6QnS2_O8om=%8R26U`)@h+m$[k?&W8cQ.TF5VrYmepAlH_=(Kg`/+SA!a+u>&d%dMLN0%#*pGkuDNZqKd;<6;t2QpaDdu`,>S;CVK[7DiK.S5t]hUB>QcW+E3lp$H^Yp'~>endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 544 +>> +stream +Gatn";/_pX'SYH?($DD+gI$iI%4$?oX%fTnF\9^7?9D_R(LsAOBpF04)bQPN/_[!-#mm/Ln+hA#,tRr$qDW2@lOrAf#tTrZ#0CHpauau"UW82'<9=ATXI'aAU@92NqCa9l&(4sPoR^d$5F*:Zr9W"HU^*7E&XV96Tc1!o.YZVeAM(C"jiT/>U&9W8F5U/m(adpuiMfWB\/W_X"LesLnILfGkXY@u]c)BIieC'^5_C!r^)F_5W>]Ef+SkB`C^Osl83[`f`u1*:cEqkLl/M9(,fq<2OaJG(N=eo>.WK6@a6b>']nYXM1BH5*'3Nbq;q4kZG21U$ZrAc/XA.\]cJQMMGNcg;+#q`O^L.e!6E<'?DqgiDi':Wg,[%@n,LJA8t$W_aY:>S'64endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1790 +>> +stream +Gat=+D/Yn7&H88.1&Xqj3N:M9a*,lIM)ZbH`S`Nt\X`S/")E7e]G9"3do6;DblYn8_,1_9`iqPrbg+Bf@i>.!mV/6Telnm!6mP"Fs7_a`tK:##L[.'5!]K[k[t:Fq?1Bk;B6)KW(I)9,ZH4@Tr;U>;b+;j(gXqBk,>kb?,>%%dQfZij3cFp\9nEHIFK%1i;<]&*s2=8r7(5^c3I7^^jeFAkUK1+_E%;O,U';`+M9g5Ue,IR&158kM0MLbhS0:a#"(=,)kn(k<:`jBcn+cl^U[RI_VgtB@dakAa;KI.2[WW&]hJcF;4'[8_CbQ`&c)D9B_<"tf92L.(9$3)^B,T5ZItQ5_!,6.SbW=-/Fa6.Y=nk`F%TQB8F;p%oMm4jY5qDQf%u+Ri)N>Q9Eh9;Q_ZYP*?`gY7pXDBcu3-STFJ)t=cbX^;tb@.OJ]5#X\'"%38e8T;%QcHa$OGrQZ=cUsKL"lgOl.H=:r!nYB8mY-;9dQVE4I+Dm_+qSGk-t2om&"?!dFg]E$BVN?%tC8PM9gY="5IScXYYT6gcpYWnoXsVAHMrJ/\0`tl3R27>LhcWihoW$1--\FD_X0Y1HpUnCHp/jQkk':EK80MH'bFd\(fN^3Y+nOD5q#pI"!ErZ"<6][Eu/nlfP=XclI(CES,-R.npI31o(F!0VEe,Gq%g,R]nF#OCW9/*f)`+4L9]N-NFBonW+1*363Sb4S6_h%8A6'>SP5bT@Ua'_(e!+Uc)Cp$]s`10L9*<=$H:jm3%liFmPp)ON*jWF*UfXE>:adXdRW(eLCtgUQm4SipgSsic+ZSO+A=D\X#*?#Q/DXJ^U8a3AAZa?$Z+iG.fm#q8ChRhq1jdhfARaS0EdT$$3D[4K72A%Y:I:P-a\o\RdRBn1T"L$U[7baGu*DKlUcrW@huI4k~>endstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1722 +>> +stream +Gau0CD/\E'&H88.0rO:^kG31'Gtm"_"N7i<-%l@jkt-9UfF)N%G^[13.BW$QGLeYha+gVG*^iEQh0J-oB:]u&:rBK#r!"[%SduXH%QH*9F)W%@"8jP%Z0di.?V=KUL;,_]<"h\V6DCO>I`1BmdRFRU,gCK=R(4d<"f,#QGfHKStY`#jklYTsh?qBEP0A0gelYpZn7t]bnghA-Lq],*'=WqOS#`pW>ciTmQCpE>Z&g5;QJJXpWIerO+FP.Z,Jh?nN*3Pg"kp-#6JJqCTjtAN8LB,F"tar6Rs>WJ`p/kk(b])l[Iqksj@/dE^bnPAC#sI-H4*qYj#_Ot!PPlrX\-Eoape_,4=IM.OO<_MnnYb\J_pEnU0Gl0P"W>')9+L""XK02%=[#6cH2BDk35A&nlYPLXeT4P4/^oe7;QZ0_Z5TSct-:A:0mK>0Fc*^"0l6r/j#k,@$Sl\,ZpofVJ#:[--rL%FX?4k6;nOKSo7jO"(l]-N""=bBK"hJF>fD;9OXEfnnP)k4jGA@%X'`!?bkC3V8LGup-7DL?7/=/!2?'@#)TrXhYYJ3jhei?,.2,t67l%tQ3*&b81brnMks_lH%:X!MBYA,?p:pK82Be\hO%_4qYas+AJ/cmdgHD9EVG:,>]+pL77J&*!Ro2&(H`G9F`Q>2)"=[i$pnTRiu<\c(Q8OW2F9O$!P,5]!Ms2p\YAV@:gh9T''BZ*BV:Zd.n1\fRa^gYXNjs8DNu\MXL0Ak=h;?*?h"0/Z$:,lUUGP%BlDqX?/iRYM$R0@lA%DP4hf)95XNQ#%rDf'B5Kk~>endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1205 +>> +stream +Gatm9mr-oN&H0m]0j!TbEb^RCKGa-['"Fh6$CG;3\WcfoYnq$dHe7(Z-_Z$&26[irY$[Ig'aKLXtUU5u?;I_s+h(YeH"Z..er"k/WRaS.qGX4J,P-TajU'S60aHm.m?9G./`Pq9NM7^\*Tl_E7jAu/3rb8K#J)VLTrc]h&LsPBT&pG7?iBK#d,MBIhrrc)H3qYl8i.gZIi_<^g*dQ$:k3f`$HN#`'UpkgcNCJ+`3>oh;kP9Ac##*i&V$@%!ki[Pij9PWZ1'PW'%-.<6p2$G7o;OmZ5GSb2VH#YAQK8G\KhVVK'()4r]KB9G\3lXF4>2?L<$=^AqUlEZ:iQ8q@i[C$=)3c@"dQ,?ffKj/JPQNf8#Up5SB;2A#9JqZPaDc,q;)hInc'^`^Us5pKF6b?5fGsoKNJDL:dE3nY!9>1M_*P8@ng3Baf1ZQ0Wr(Le,(LM6m=0'G7_:UYFadk`1Qm90-%e50B`X#3PjAmXk$9L@Y+EP,t/aU<'E"KVhs=U`I4Jb*iC)(rS4%(bX17[a6pK!g>.sffK;BTN^Prs3&j9[cJZgfq&:<\XE79,\OM(r\EmluP[Y.;b)sM+>-aBmZ_cBX;giMl:9&!\k@GW?iI3Gm^/%;F)E;J81ii+Wn\:;IkS)'W'f8ITD]endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 664 +>> +stream +GarnT?#Q2d'Re<2\;tH(6HG<:lPi9'6)%Kd1t&253;=ij!]IG\e*bi6#""Y+'*?;Mj.(2:2'._$j#,`,"F/#'?$bF'+PVN-*DI]8+j:/:"0\bq047!>10Q6C/kh$lN15J_$r!kV_bEg;Bs8rBh-$i$fHN>lpW#u@Y/5<"D*pk3i$jMgTC'H1ecB=E1L9$7`c24>cF.9k5VBj'&cRRX9q$`ghI^2/JlCaUmTbskr78G"\2.-XKX'Z.9*<8Y4!=l`fd4LMQj:rS99r0gu0=^].e?c$agY8H)&09Y8A.W>=?aiDa"CUne9/S0$6d7*5.WV4`#d0iYX+0>pbY,SJ7T^4p%%8#ujgOB^6k0Z,6_:[M0#DZi34m(Q$&[(Oc0c>8%isQs(PhrZZ6/)7-!bUe#RdR9X$d&).l;_blouoD&0K<+bs6`"#bu(VY;umdu"J9HVOoF7caA-N[$]J/pL)3`Ag.k$q"\#q(ae'p,o=(8SV-qNJ:k#dg2VO7S[lZrPFp13o-;08i0u$TX0!&2+K"ZmSh/(3#@5BhFoiL(-KVDG*Q;s5f;F%r41;@_nrZN-V"fu,bo)~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 655 +>> +stream +GasJO>Aour&;B$?/*>5rV:<"mE:QJ'U*:J1g9abS^20+Ofk)mJG?r2`opH!(G'm/@i*i$0kBo&s_18\eI<#L1;o7_P#biK,2+43t&X63bbMH/Ng/Q(%Ldtf)`oF*S.HnaDI:8I*dRMu7,ZN9.#gm3s2&q9=rQ/>ObgZ%FCm"ZgTh+@UGOmqb9iB(',+4[Wb`_5Z7CMskj^0E##4!@Q]sAed?L?F\Euf^HI7*pHk<91>D\8[MTWO2R9QPkT1V%\G?+4DtG$>u7_nFOn^G4(&R7#WUT9AmI6u`W6AsWe2OQ\sn8oWo))WO\A_'I5g7I[ZN]8"=oH\onQSTaj73%+>2W]+!oK$WDoGtYi:!Y6TF`jupjO@:[P)EiQUP(n7C^TuqGF9P>jN>;FYSL(j%hFlA>aY0\]MHXD1Sh2nT8EqUJ\"K;Nd9?;iR$t<^<7R)MLDbkHP._F$@20fQ=\5so$Rqj)-]Fh[Iendstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2379 +>> +stream +GauHMh/:t,)SOHqn7I3r!2fQBM?W,dEU9b3Br=\]]iY[SW&A.dYpHS!:XX[f,pcHp)cL3,K8G_Xq/j^LnVB<'6k#1Vi;2n_#JejkN+Wu8!Yu:H1W[Ak(/,M\s1Q2`.:OD:KlJYR>shsaon?k'U$L^H3F-X&Rj%i&VC@*j6Z5._-]@fhmm6jebiZC`:Z--enalZrrr*,Ghn>LccS$)5E4K(Eh](4o@.=s_IPLaBp#e.:Jd6?>9b+`rW9t.pF-mXkW>%n=^.@i>Xj[6K'r[9K>6XR&:i-oFo"@Wi.5/gN4JZ1]^@e?i$&kh.LJi;[&&_R<9E7UCdP2TX&JDQ82o*,k8.m.%#5-V+XP@kD_uHO`4be`Jua7'VJ:/c7NO<-]NW#r4[/P5'8m[V>CDHs5Zd3a[XcXqSi]SU"?ZHj!+sSI=o%+.@QRm0J/'7a.N]I>SUl95#F<#S?r`6eussb73S[5XB-,D7G"9=UsJN+-,Hsl6&bHW7')+0b4.+1o'o0qgM/NJDUe4hY4I4\@4R7b)([7.LAn9F$l0R#"-LjHo@tcXfOP68+s_qYUZY+CMCdG@GNl\0W\i&E1"&;I50NO\>XJeo#Dd.,b?ea"/4:A2m8q<$6Bi(VL2sIQS?Nd*V,>R\DSK1XFkD,=*Q9[k32,^]1Cb-c5-0^^%Obga+j0;oH6SE>kj8V3>LZ;)\P\bEN1VYMT+%3GCPVPOM1^YHZ,-_s[Sau;653k@Cm9`R-/4:G4mFT@O6F;U9Y10d0NB'B]CLQD5Bst&8X(T(A8@AE)K\S@.SLRLHD`[68.T(_7>#i'i2UA=f">Xg4%eaB3nOc@mS*7E5R)&,Mm\?6)qh5GfZ=\kdETu'3K?O'$)mIcO)a;HWO'I=+Vh'gp!R<:a?:"(=UnAq:)7nPci$L?M(>>^c/>W*u;$Sbm%m'iej.32n*0k(WiGHm4?j3)hZcV)g_@+QsMY&uep<9$Y0i(5k@6Q9j@NQi$lDAGTR-E$#M[s;7B\k/rP*PRL#e5dllZ&XC3`ql1YN+oH/XD)".gM#*eVMr$`0""Qn>Z@'D.#M8/QX#bgopVg.[8Go89W="la(@q\PWC^$C89FdR?EJ;l.A\/NQ."'PhKg3fM&9(1<4!!D3R"<;ei)+AO@K-FC_];&roS+9\^6M,7Ri`O'#Qua2.-p4MHHd#0BH$i[/ESO.t&lj`-O<(>)Il+((Te;;@`"I")Hb+$=:ACfCW47K-r2;IH?$,i,I8.$V0KS]Y!Xp)6'S7=F78rMN?^HaP7Y$dtX(eQKDg&9)hcgeYu<&`$*GVX9De-)>r+K&OTYnAh$pm,os6N\^V/\MkBuqNE(>1?^Q_gE]uFP-o'$g>/D\TMd.-1+tZ0J,k$nEtDs/&h!M?$o.-\7I^no:3,rjs4j3G]d+r^n!hY-,Msc^,4'^K,\>Jc7s6^1-\nEm=`l!N-QT9i.:tSiqG8S';0GN2WRZd"8Bss2@dF6OZY.i/nS(:)g4*,-@D*u'#W%/5j/M:B3b)).9s5-Vf2@sF_urN!bNOgYjXc_$b2\RHB)9@@endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1247 +>> +stream +Gb!#[hiHJN&:WNO@U;g(PmDAY!`-:2[FOQP'A'!tIISWo\=;,2gF;K=hf/^^'M,&O]1#RnaM]m,B0LfT'6*Icol!_.]N`28!s.Dt+p/H;!A%jPIW=uZ%G?1JO!,!i1EK?33!'OKK^?D1\=t$-6U)V'fD9LQ9.aRkYB@g79]*YFCD3ZG?iY7^QnY&mTNP/ADOs+5rSt-<"4%SM.$7,q5qoE&!I8Z\5duT@lnKUcR^3&O#S]%^<&RquhZ1ps;W)Ve7^M(m\?/"D3"kofpKef!e\H,3?Edq$*irnK\hc_/IINk&d:E/+dWrl`Ai+c9R6df_aV<)I_88J^Ki'VW+;H;jdc=L-MT4%dnLKKLlfD1^H,#DI;&Gqe=4!<.%DVgN5bCK.1TI+LPSGmF,-BP;2TF25:s(K"MR.3e^40]NoD5nHf:\Pd=7e.31H.9`ZZ%Z[CPiW1ljse"5n&bi](jQ:Q1E1e5Sd8#AcEKUl%D\OAMRThuVFg/PAA:l^B68WNQ4_'IPbQr5fFq)KJ)oc$*&!nVk9f=5F2aS:NcI1YMOn'7*rb)pF1Zr((u)8SV`LuRW56i"&O&f8A6S('OHM[:p)`S3M1#S5C3k$t+2H7"T#.tGX[-=UK:]O.!)sEnd=9o%We;F&'W<'&@B*ar?YRuLJaGd)Als"LTlCEgbH).'Fk\@\&=NpN.o^?$f":a+@nIi!de7I0VlaHn&B33]Q\LFG;@ZR\2G_4'I1.&Lqm2q4::9B:Y#7[]4E[NWomu-ODp0_DtH3/DH4W$2@Jlgi^&Ng2e@5u(JaE.-!i[FV`KOi&b7pQ(;=.u%]b%AV:@LV'CUD*?al_Td]rC/hnB*FL/I;+0(jS4Snh!RZ8m[d:rXZA>V?K]LpCtg)*j?dgjm".EX/\F'S)O?B#^49OEAT75];GTq/~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1230 +>> +stream +Gb!#[?#SIU'Re<2\-OcR#s(YR4rn#A=jUWoZE7mOlsUq:?WP&6'6O,0[YiT7W5ne1H^,5+/Q!Ic#@pP&[A0V/:Oh%7Rbn9TKQnV!umRA>p4`(e]XMDK2OVi]/%E*d6khr&Q(&DoUj\!NP9o=EMcbVYg+R$[1!%*!e+GkQ=k:1)(3eb9";g]7A7f.M:bDnu+%8EUP@[OAb@,]T3%9-YPI\T&P:,XR6tMt,&$lnZF9*+i@!APp6c>rSj>lRLn*$[!Uj>e>GPjIW@)r*OFe\=!"GM)mL-#CaFR_i9uHY*P2\=aQtZdT`rWd#7@0N81ssM=WotMHrL6qB#/SB>*@3*LKP[R@#qdr'2=JAM9d-ABiqd>aS6R_3LN3J5,l:UGO!IH6pb7?k6LlJi9e/^1$'WO7%3`+H"&!nqO27.C=c1n9!"`0cfKco=MJhc(m[56t:V6WU+#q:`lFINEb$H;M0i-[BNYshk:OqLiJDh?4JV=WAL+PVS.]7e`kBCX:[I-[>+;I9\o<1:!PH%eNNfOlM8TDH/^Bkb]MaI\rre"Ijg?Qp^._*YO6m./(?QOTCp+82pj6BZ.cF#B]$OU>PJ5bY'oHNq=Cd#T?QK_Da0jhcG!nMo6D^J]7Gp99d%1k$:^MY-gp[4rXPe/Nhe`PI$XNoo@I>GNQ)FZX;("o_/o:i5r$5k$I7!7P#%'mH9$*HK>Me'Y5VHJ$d[)8^OM5+:iQ:-[P8W5h+p_.cXNoeE4\cNjIG2?h,r7lKnjAZ)b.$lo6(d^cc87r/#96fh4KfP*LKbmq_LQo(AB'P)&`+aP+h"7G_8JG2JC$i]2XpH6CGdlEe=QD?N;pQTW.~>endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1254 +>> +stream +Gb!#\D/\-!&H9tY(f`W=mBqC%R.M&g6l3s:e&4E6,UBb%(YCh(l`A\fTitl#252kSVJ2#'NhKa;AV.;=$""R5145dBP3>jI/=]Jr7nB8pn[)r+nK=*9GSQ';FOO9L?*/Hh2p-eW;)rs&K4'H`%J.2NVob5/8al0M3-Pa9>%Y3oO90m['b,3=)#1\<$-;4'O:*j9dtlCJ4kG[d1)C6B/8ADAB)02NBnAhe)BY&F:KS[2f4nKh:5&CEY"7F4BgGR3/31i!>l],^p3b1/BN+jc&)[R_Mpk"'UaY6_i4.jL!$.=JQcUDV[m%JEVch:cA,W;&b5h?h]Q7S[]!a'00bd^IcNE2kR_94$fm5Qbd<4;H-8S+GdP.'&/lkQM$-D4Qq0k?52O@CLg9-/ddm%g^!Y#7E?,,i]X).W&>#cB"O"lbI@);2%h$e8Fs319Z(jXUBllcN7;4/g.MV<%cTV)RD4(R^K8k^P&>Rd]QsP1_j7jUp)+=j4kH+XVD@`?aW:/O&)IG(3PbYb+_+I3mM6;UGendstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 684 +>> +stream +Gb!$D?#SI?'Sc)J/'__;$c`h=O5=GG-WTH/D=[Wn0TK:Qn,TXdJ,PDp[8!",(LEt>-rC[cssc_B39)b#/T8T]&Lir:$hgQ/AcuYne^oFD__I-8U32_CMCBJIo2SNRT"/as&ko$RjOgn6539rk;=F!adA]WgA#ENj+pj=3dk$HVBd,7NOopW(^j%Pp,*bnis#2/H$r?d:8iq`hR&O9iZ/Y_:q]mh?s`m\QcSEU]s\9]i04^W2]`m$Lmq9;SP2Nhj3$V,^R(?MduU0DMqY;3X*I15bi^e[q.(`d3\ChX5l5\ghsgIggFEj4//\nU!OlSH0>,G%mGUNG8d"4BaJ3k+.AZIYm$5bPG7k't1QIHFWlY*E'!UO7LYkB.74dQOrADoVEHLND@'F8.;F:AKi[fu^5Sn;%05OuQ&VTIe%]!c0YL@7^1!R'85U-mKY&lFs@]#*g*Sl/9/:>@+:>EB/`sfO=>@2?"fTZP90f9+mcXeRfD]8O.q.e(GV`AeM4uoA4pc%LiT"?b0H\KE~>endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D,66#;5k0p=:)&fiNV:Z40D;YVQJfN>^C7;3Oa]SpSoY"aWicKX,8:^Xa@*l29TgCQElV++[RjTW6/^qRr:.b#N:b_[1`>%8^eRS0=fTPoo=8a,nTi#"W<)(;862g0U&PA#C>j-Iucg/mTD%(5%U0.K"=RODe!`5m#3lQ$h?`qns'XU1"IS>Z'[#>u^_uqr[/6;e's"PImEA\OFGtQd4e7>.S!bd;0!Hndk%#WA)"KZ?7L'-.Sm7Osf:YI&-/*pt5!?pZQH&e'gamR:Kd"@1A?"#&6@/f00hDkK;k>)+9t[E/?oCc6a4O64OlM[@gp%E@7M=Zg?\)fcidp,FMi8L%pZWt\>A,>n6g?9!ZmFhXPW<$7eQ%'iioR2dPJ8LL/nLA"?'i%">L"endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 949 +>> +stream +Gasan>Ar4L'RoMS30//ZgGjjZ.d`pkd&#j4&1XgIMfB/M9l+E'[/Ka*6b*uP'S0)NoA.\P!J+`5<.:#NTU!;e#6AigR0)r^4\3-q-5V.ad-$UP-8`C#FgLPcBk@d*U2n?]"\I62E5a0Ji%S?_/&l5aOX\JPg6Z,T,]#Bjf`r'c(o.jbU$'u1=XAfJ$7XQYC,aK..@V'X4?<\t`T.cP'M(]ugo-ZtJu;_V"9*oU7LMi@P`\[>&ADZ/5'X%8+!YiRL]$9)<&-Ok:Jc0FE]iD*cZ,PMj+XEQ##a(I.iZG>Q4j\*p'a^HF/jGTWn2?F]]_:@GI?F*F3"V_sWct_0YYrV$adk^QNtZQSqi2XL/WHZ*E*+nEe@["\_ggJa=XPh\SToP((r1C7j'-Y`RrSBX9df&?:rud8FM:;_lC`WVdT&`/3;ZATJ!7F0i]kE,!Rd".4rd@!bhEfr^VSOdhk>'>udLM2CI\4d4$ujB+/d\F%e2>4:^*p%$SYqDA[R94fqC87TsWOYg>Qd+6\/*sGpI"\`M)[f~>endstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 792 +>> +stream +Gat=);,\Af&:WeDlr3(hnF44*Zqo2G_[KEmna0Xl=O,R2KI28m3<&YiEX7F(C-+A9jOeBp^Wh4#!iPZ9iEHur?PkW&'1eS-VN@=eB>=_uA$qr:A7aH^^dSl[3Z%1)6I65G8_.4ncO!_cdc5qW;t&s-4=1/<`t5(=]++KM_4mT9dbWX8="SYLlq\jJ+*a`rP,:8LLB[XaA'jsl59%_>+l8r(:ZcrXBW1s0,/bU2:kaH5^Y;a;^U%XN]g`*b2XiBSp7ErA8lXlBo#ig.["&mAFP4W]8/Am2<\<][51%a]`a+/#MSEoa*>>qM(ZL>HIa5O6dWTmo-BoPT"Cen+eu6Psq`leN#jgJQ$EJK#&.1^cl;qSaur^:DPq(t/4CT1U-[Ee_r3]>limAMg=-^?d7W"_KH-en4/"hqY>pLLIa=1,NrDCHMn"_tL9\Y-MLlSLX_.r)M^;L@j=KQ6*k^Q02K\;GSb:<.TE,M!2aA\HK[Ns#\+/'VM7m7Ws\(EV(X9hh(8YNJ)YUrZm=`]D/C2lTbNBPS13>[Fl3QNI9"9JAu7ikEg>C<)RHf2E_7l'@(e@h5_7iabUkG$"%[AirG?HP2)X"f\YqM4%I0E570r5KniAPT^bWWLSo]q>[GsSl*WNsi0M#L2He*[LHDk;`Ue,9<*(m;K'(Za)rQ"UE?NZs!-T/^::A.OE#O=/W[pY1aj3T!42tk_#1aa"rpXOG4D=P9E3H&^l!(XJ5Mb^d?B%l=UVDBKoK_e&SKQ'n~>endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 770 +>> +stream +Gat%!>u03/'Rf.GS>W>/ei'HG*Rc(Oi""FcR52asGhjc^4iIOqaf_bDcF^mbdGZ`5P-@,aD2nGPW31OkBgg!1N5SMYf_N>3o5CY\3/*Y[YTg_7T.(?l.W,u0f`0ShZRE43!38KiF4f&7$2umkVNm$s4kMbpS6V-7sr[A^E3&DP8ZZDMJt`p/DDlNYSYUfAp3GU"f7*;)$Y3)\PPb:Pa!Pr`85PbL=,EA%YRQQ8L]?uLu(8^9Tte9^?!AOOlfT@D?rl+GRG,W>>fMfj;#lEV)9Q%OL:U4Z-[4aF;j<3I4Yma4!-r2;p#rs`IduL1b\.9TH1s%*[d5oQ+uMMY:F2M=hEk03bAC:r.[m;:OTa^WE\c=^<(G;M_>9uN^N`+<@T;4L6am_#i(K=4!/3F=^-\h+gf=*M9@H;7TGnOZnr7nZdER%3tKepbXpH(*`,%HSJkW7VB@]hGZr&c"=LjdnJ=Fs\((~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 667 +>> +stream +GasIegMZ")&:N^lk-81u8uaM;qo0qT8DFut6`%N,As.E/-0mO(q>221/X//1AL4YAF3`"")(0qeXe:,a"Y`X.AeI@J$V:]A?0;]\)+7'^D_$&uL4-QB3rT&+fHUS@&1'<8oQnGT`:U]GWU#h\os,H#ntUZ:IWf,+SBmN0=N/Bm0Ulp^+o-2!*l-:42[+5a$4\TF;C5t#!P=cT^-oIL=lBKrncT).?uRf/pT(0]P<$U,%)S*8=Aq5R&L=[\V>N+n2Vk3r9&Sdbu%*qK[EM=N@AEi:chLPN'2c%RUrG]9*9Vk%GqPaJIbY:Q68$Rf7F@lo#n[\DQa0&BXjU.j2D_0gNX]DCA5An/$u:\asRU-I&aK2!e"\>)S&_0j:6Bq(aI5-SL_dI'M';C7`b>Hc`#&a,E)b<)/dIsmh_tsO^B9s=ZsC_o"0<_sS"mrIOMo>]k1`P?6!ht)~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 269 +>> +stream +GarW4c"b-M&;9M$ME/+*Uu!H:c8Es8TbJE0>;*kM(^9lJOrW]?BI=/[?W]j*pQi_]>uuU#=peAi5P4H#5\gOqF;S>cbL7j`kcAm#BoJ*KCKI2g>ZP"`cjmi#Y/"JWO0sjo"YdO4V*b,nbSQnJ'_,4A4c089Ok7^V`Q3^oIWCP!PZW]FT~>endstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 364 +>> +stream +GasJL6#V??&;BTNMKbjZ+A7\<[oK[VTodFjcm+65BQ^S3C&79[$Y#oe2Nqr(4)`u'1CQ/Fle^t./-R@>#3J/b?rLhJ&],@(Vnk".\Vn#i@(G^BV%,!-?/`.HW0^fW*9oYJQNK.p?B2.Ybf!kF+HF5SpTWe306uPQip@C[EO6#n?aa4kmi^I1mU>[BLTa:2$m1/n9JOPlfaZ5o6:9sJ_B-\I-j)0IW.lA,QEAA7R=!bSDZ!cpq5#$qU3\H"n1WRb]D2DPrUC)RIKRH(V$Bju%8rJZ^Dfc`R]T_7qGA8o`:6i""kBe7"t!2ET2g[#QL]oKrSiP$"6W74`r~>endstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 476 +>> +stream +GasbV;,>%_'SYH?(&,gDUY?+YVEU8^,U?l+1/.$,ipQBp"%R+$dTqEJ*110Fi0^f*Bj3A\@)[1WJ4Cg-Bs"eb1T98`Pnl`qMa>i!(CJ.*sZ,dhEEUMl/i/Bei=OkrGtL?l(`r_5q#&]h\Stpoho7B1$P1A0:3nkc]Hn7&Vih3/7gl)QVkpcDg!/Pn$2eF.cZj8jU=<=Oda_jdYG;;KE.C>aJ(HZJ'SJjW#QTKgbSMfkEe"2luceIm>+k+8FID^BQ+o<)&HVBp!HucOhBu_#u9pZ.Yl"s(jLP=^C!*/Z0r[20g8OTuW(hZendstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GasJL9i&Vk&;KZP(%8DBK&'%4iDrNE84Woq*]U=W6.aHo\grZQhX+3sGgK-ia_!`.B8.S6_;$P6i1B!&JUrO5)mJ:/#X1c$]q*4?as]_9]GnfZ349hc&\(7+in7X]*bQEb4":@PFecgH)s$2HPg:C,0K,IE]4"f*V5lHh$0UP&6]rbeF["!P^u)r247L\<,s5^&i"sVA@s7//,<=u/-U%6bpJ1)V8L:eMXn9P_gqp5Fa.bIk)'u`:XqAZM>A4d^8/`tN.YJB@@0D7JUbt&F97$)onRrp@HS3n,lXY%k_Ts0aC87T2ff=9Q'P1d:pe^)fF^nCM^4]@+KpH7TQ;eUeX!(Y5e(/kG*6mjd_V,dNq./iMrYQ3moq$VN!q.'jG`Jd~>endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 345 +>> +stream +GasJL92C3p'SZ;ZMR,\e8F'f2lk!nudK%R7iPH&O9#`PR9/Z7s>O&k/Tt*`2^#tp_h+J=5,49m9"*Xf*pB6.9]Rm5:'a+aThM4T2as]_IDhC#E@dC7Xco#q.=YDeS;=!#l/./\SZ=l3Dq-0/CZE?G`OWnR5jE2b,276BHUeh0/?uE+:WJU"0f,4hT=9*6h/W%8-UMq[94pS1TAj2+D=<;]b?:mfssmPMH~>endstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<92C1*'SZ;ZMR0B:.YFNnFqgVnB$IH2`!F3j[-aX(p!&A+tYQr.+""N1Cj"S'MrkQ32UhAgQ8"sF'JH5q[g:cn2J>[$R;%g=U/)#;S"^cS_@mR3jat(*Fl\0T2.Lq.@/hDQqhGPI)n4@ZIsS(\_KI?@Y4l?CLAkT!JJ3J,6:_=`.W":&i0Dn!a$tNYp#CohtP?611uB]8A,ha;VK*_6k#Nl_A:TMI^`4!].@Rnb0TUjWBtqS(I3Ct3Y0>K(=u+_*k/5?5cC_:endstream +endobj +91 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 385 +>> +stream +GarW4:N(hM'ZBHfME0B;g0I[Ngk9-HJr7()-G<6#>$CpD"`=,']8K^*@pZHrI5CJa4:\6CGAgXdT"r7.K:.#2!1DBZKDo($jl16sE4"LiK;a`L?t*Va*P>_)EY(Jt`>QgoI/n,pnsdDQjt$fU.mM!lHM+RV+5Vendstream +endobj +92 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 852 +>> +stream +Gasam?#SF^&:EYBlq8YQ<7D*b)lnB@KHulM5d@'kM3j-KOK5T[m`o\EpYGEGQjZJ9$U8U:1V5Gi2Sm2L/DkFS0TP)WXU/S]U,A=Uh@LkQVGZNQA(F2o#&?3^g%NM,$9U#b"2=#-Xa-SW_A'!G?sY@`^7g@oiH,]XZNi2/HO%EElapZQpS&r:DKJ+^Q\YTlqr%=ocjMKLq?>8ZV>gXiP9'r%idJQqOEJiIP/UC#W9(>/eGu@Ql&OrABrX;>-r"BL05+p9]tMS&GAM&"4ThZ/LEl\"*C<*E%.i"7Fn:A;RR/rD\*ff>;Ch3OktiQ:hc+#DFP:a38MFZg4MroBGQs.>07-S&I@I!$\fiam3ldq+H"]I<@&KL\IsSK't;?5/+2bMI&2&#HP#WekrM$OR:Wlr5XLdV2*VWLhs?:KF500>!'$[L+!YD%l\A_>:`hlB8j%/p!ELBA[1;R~>endstream +endobj +93 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 582 +>> +stream +Gas1\:N)^V'Yig0]Z[*eLDH)\Yk4/VB0qK]2E3keie!B)"e45m.c5]`",,$56?%4b^X!+8B---JB`YF\E4nYiHltL9e#OpZ'jreC)kdHRKFgg)=(1k[1^l20gd(6sL5S)Q6S+1\&*VS:q48<>-TE=?mkl4%c[ar,`9UbAYEt`(68mSSCc<4!0n+ZMp^)ETncIm-[=:$Z=bI_.oHKecqqeIJ[M;i`"J/?7`e6'T\q26S)(ZJsYF5;"n9fa$4YSa7VJZQtAc9Z!:_:EoVQW[(d'<6P-@pfA5YECl2+2]l&2),jn6Z<\(!Veq8A6lKpM:&2n`3mZ[-t!L30H]Z"V[/2ENq`N]3K&#p^qEgKS'Q8l*45eaiu^6L++;[Of)g?Z.?endstream +endobj +94 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 501 +>> +stream +GasbV;,;fu'SYH=/+/<%RXcu2_KafL,)1Y@?^CJ=XMYt-C0NRcfA"/sRo*Z6+R/jM\YloE5\B!C?#K`*"ATU=fE\\dI--t#aWMq*QP&);5mW$+p;1be)MKW5Xrs3rdGi!f2p.-Mnc>@e0-==EVi39">3(5(FTfflOcqc>KLM">=\>h>8[I'?04"H<#4_oX"IrUYbEc^CmP[b/>I+e`9r@fM%[(4YC_V5lX:Ku#TNuAQLj6@T=X>#e1aGt<:&,,/el!6*?+ZMHZ7aNf%K]I+^9O,QlFgpN._R2UGQ_Mtd$A[OTSNB)MYLe.p_[FeI#(-B1Wigs7:DL+o;J-T@(A2FPLA@Z.UgJ2RHNn^1L)pNdI6j?krD2R^9=3>dR0h6E)K[P\0S16R>'#/I[fd)Oh5#?uYSFiK=E;L<>s*>r=GoY/it#h^#Ne.S]S/;6g_M:@PafgBRBBTeIB%,I@i1#AX,L_WVZ&_rrr~>endstream +endobj +95 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 912 +>> +stream +GasbX9lo#B&;KZL'mo0RC$W\A:EW=a'MS"\&.7j$#;3l"YSp_d,WQP/lanoZ$05kap=POOp$VFSm"%fr=$>R`i+E2UI1NtO6jrM^1EW>7"OY?iM76X@CdHNgS@)Oe/W-2-\!g.:'8lI+kpS6`<-@[_CoY'^'@isG2[XImi-E)kcjQRC3"1,[&-'N-VUN0FN8Z[R"qZL?_(Zi4V\&fZkc5HfS$!POI/!3"L_kCs]P;Xp`,Mip[2QJ?Tf,Z67e#+CjJ\@miY>-`(K/WDXO^l3%A$LjSUs6)\r%FJZOH[m6X<9`&61`m]%YAD2JMlI(<>1K$bMdhBm`/a>Chg26MLT\m'Op?NsrDS3A[$f`,f`^$W:+WIBY1fQBTJgOt05[:j3hN;/iKWTe/$&i).Qtd5:7HL-Lm&?kcHue!2hYK/RPk1FnA$:gDoF,43'6[NSXh6XQ-'@>7DUdrk0/qJ0-D7D.@WF()kNl#,r#W(h6I@RESoOA_HECr;;.q9Hs7jP8(Cl^(b_AX9)F?tfO6EeEjr5ZNe@/YpOWL_6"F+D4pr\i1J`a4Ful8&Zo9(n4E#F%e8Rc'K4&[1jtDd!LsSQkpW@=pno$L0+dKaXmHYb)D8?5lj'M$4Egn]b/\-A-E,m#*h0(\1*4[ImP9Eg"a`a08Y'f_W[IZL-21oEaW'Iq2e68,##RfNR1379?OC.D`cOK]?Z-1\o0aU318+TPbnmg3`YkgfH)>fLZ4^VF#qEWcIAD6h[c=h^*!R.D"KSm.\VJ?Q?tP/]3]j/NNUJ5Kdd@'nu-o6,RW*KM4t\9pWGMd`sQ25&[-(shX*VF$`ZoDa>NVT,TWs3.FpDHg,>IkCK(h"mC"_Mj0C]jl*cfeW;Ea`[+ru(+"OY%C,AF(93-RiE4Yn4m(t\GBfPo!EGFFW~>endstream +endobj +96 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 786 +>> +stream +GasJP;/b/B'SYH?(&)8P>I?@![%YlR$;IQnV/25gHg$@o2rL[?;qn!T^OFd0RR.0W&P0i(kC3/1)[6=+b^X7/^bCJK)[7jH1^DSrm6c118_SISY\%N)J10cT%L/7%;U@bg(\G"#>1VD]Ub'S;"Erb:_SA0SB?;R8Rlg[\pG!qCIaZR')CCO0BJN=pE-7?ke$"l4L%H=+Voa':]=WK9HU/Xdkh0D/%5,+lFqAuD1UpcZCQcJq]^\=4Lq1rYG*Q:]0Li*3AmhElP&"KjN."tRLDMuSpNa75Ng.a;X\i8H1oO!j9:cI%fr+4$Ypb48BM@AOjWo<8qm)!6iB.B@p9*9fV,h@_W+6=MMl0ku5s^6e23lqp+&JkK8gOp5.LJ#)o7bQu(sJ4L*'jG\?['Bi]66GBhh1(HORs+C(o`W,"j*,+3F?_Dg^^$Ra_?.%d+IBC8,)GU"s-e)U<9Q6ndt2m1.%]i"=,]tde-[g[RDal9#tR\O[qZcV@7\u(6Bd8k$)N,OidC)hj:B9ee&rAiJ:rn).-endstream +endobj +97 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 607 +>> +stream +GasId95g:b&AJ$Cb`Pl)brSUn^:Dls:i461,Z5pq-k'],fVQd>./uK;4A6g%U=F:Pq&].P_SE%dRVuF2r!6`:B#(8TVSHg()2&r2Kqj,Beoa#+34%qUl[F$a5m=kLW7-R,lqBpbJuGQ^^)9$jb<]i%N*sG@C^]ogBZ[*eqZ[**q$`2rih!nDR'!Xpq[\uIj+`!`.-0[A)QM3[=L9Jbd!/5).:qYgIAq:$'saM]HuoiM)c@XSeNV<5>mo_.rV9B=t2."*sp.3B!;>qCW5s&gdWbZ6'09Ecb8^rQcq%dbiNns6@Z"a^fVB%R5@c@Q_jYTbd!ie5cHG);=X\=AQ\ZJ5B0:AWjOB%No"@D'!cZmYuq4V*2V^_=--#X`NY#=h;,+s=Rtc'KOm/O/gIp1p9f-<7OnhLXK2=)fM0nqlt.k':[smfK7#j")*X~>endstream +endobj +98 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2Hd;R_m&B^lp062^U'U;eujm^+S#3^rB?j1+lY!^T<\Il2M9KE(ucmdjq,!@D4'.r?rhWW`S6ZK/p,gL7^m`lAHfi)_@'Ps=<#$.Z*7W:-H,*(WYp)WqK1)V%EE\ZIgJ&dH^G6p:qsh(9Mh1P5b/7[N4(FBMF,ZNPRQbAj/`'(k>ED-.TO>/o]/L<:qsma#OO/A0GW8rj3%sZp/eI+;a8NA(c%Wdo1Kp?Zr4BE_.D@KVbib&S[Ad.SN3!rDHhe^*4.!+I@*@/KO#o7)@?<3`'PnsduK$n5l@*+-B[[fjf!E4):Q%28WTJ0P06V9"`:uk0-J*[=*#4r3b/!m(9C:OO$;_g3s8Od1SbJ";^M/&IsE[M?rJF>tg5,n=Q$,7(E5"TI?F!8(GhQ0C&ZBLH9$'ZU:rrg3.=V>>FX]co.ZlTA4,RRcoH90-?Q_qDZ77LE0>\ua-h=kONETpGrr\,_Jge]0$6qE8X3GOdSs+S0EHEgm"-]c=nZG[4I3K/o?fdGj/j*.p5co-uU1dmV]V'g..-fd52-Ci)DJBj,e:2uoS9@C.ir3gW?c@fa\Se0P!4=3Td(lNLZ(A6SIQ0">4EYi%:^4[YeEnGT[G8%[%[hHV>#7enhmDNlN_&37)G?XkMW9Bbq?HNo%e48W><-J--n]Gi&.#n8+/%O=%g)jgm#Y1J!7Seendstream +endobj +99 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1441 +>> +stream +GasIg9lo;R&A@7.oOY)U*J^oq8-l[5+hPs]+VVMt]a.iI2.K:>,X^3k^YQ1MNX:oD!10P]HJS$]!VlErgi&DZHjSd'I/q(`_Ij-Dr=O]UR"lJ2(I>b+H32]n@=L&CR@j^9phiAF(MFaEma*XX2I$0e`j`]Mp]JAt.,9%E]EpS8gpBD^NHF2i;9I'3U/)@3BgM2)@Hp1h!o4oT7c.O>Eem\$BV'6Y`0Q&;;(>#Q1168VHQrrtBCmh9nqF[#iD'Yb&pW*XcR?0Pe5+6:l9[[T;G36pr.O#IWYR/t+t#=q;h*b&G$/&N=[0UJtW=[aZ:+Sh!ssRO6$Dfp!IsRFp"KpJj9#9&ii[Ng4UP1)[W1?ko'7.$V/JY\LTYRBV$NShhNAId;3+([;"V&b+Ygb]BZUK[[Vr0c"Z`"2+AHE.&1hZC&JAaJ^LRpcffq+h/CKhV7pn6?:\.).JZ]L>LJ2U#`PIu,G)7kKrPYEcp<\fRn_CNoNQPiugD)1=Q$f\_)6mO6cJoHgL8"`SB,i0!.mbNU[WUm!"Ri0q#`1+??mFX*^KX`0Use&C*_jD*YlrY:UK/qk=lH6f+plP]UE[?M^%T82W7:5Aa0m/0gR1Rh8CTgS)Cc)oKK-ae+!&NZ*ln'N2F_GfLfOrN"HHQAkLmQU;H!lq"cqf6W9N;-_)5hqe%59.Te?;X5I_bo-P5^=pLTC#B:7IN[?Ob:d?=.!PBKhJC^9`S>%ZN9"5g)g.%iu;JQs"U(N:k&-hOOZ%WMjp5\o].O2=JB6rr`LfO)f(uH@"Xo\CZ]u;^?Vp57J2!rbpk%1m/';;C+dnJVSeWfLQm,Y[PpTpHY"lGdMbG*o/'7,ire-iFG$Bi2n5a)i4aHi^D=C[>pc_n3H`=T[U"#&Q,\L#6)bYDfrE-^h_1oc!0Ao,6Vr.=E#hZS]'Y@%q[!aXLUaPLH@W^1PL>r&&+>WYOHg;(^N.F57767Q^l@f'/f-m.^Eg,2%0QtY=sR'h@m[H:P[up@/,<)2'Q,9L[aTfEB+QmE/EW$ik8:;q(&o+&i]4i>'%3//D`;D0k4+i]6ok/Z^2tJOPt*PO&CFsJkgN)26W:TF\QU'5q]95alF(G-U3*1l$"b@E:H.E%qQ7~>endstream +endobj +xref +0 100 +0000000000 65535 f +0000000073 00000 n +0000000146 00000 n +0000000253 00000 n +0000000365 00000 n +0000000570 00000 n +0000000775 00000 n +0000000980 00000 n +0000001057 00000 n +0000001262 00000 n +0000001467 00000 n +0000001673 00000 n +0000001779 00000 n +0000001863 00000 n +0000002069 00000 n +0000002275 00000 n +0000002481 00000 n +0000002687 00000 n +0000002893 00000 n +0000003099 00000 n +0000003305 00000 n +0000003511 00000 n +0000003717 00000 n +0000003923 00000 n +0000004129 00000 n +0000004335 00000 n +0000004541 00000 n +0000004747 00000 n +0000004953 00000 n +0000005159 00000 n +0000005365 00000 n +0000005571 00000 n +0000005777 00000 n +0000005983 00000 n +0000006189 00000 n +0000006395 00000 n +0000006601 00000 n +0000006807 00000 n +0000007013 00000 n +0000007219 00000 n +0000007425 00000 n +0000007631 00000 n +0000007837 00000 n +0000008043 00000 n +0000008249 00000 n +0000008455 00000 n +0000008661 00000 n +0000008867 00000 n +0000009073 00000 n +0000009279 00000 n +0000009485 00000 n +0000009691 00000 n +0000009897 00000 n +0000009967 00000 n +0000010251 00000 n +0000010628 00000 n +0000011221 00000 n +0000013202 00000 n +0000014861 00000 n +0000016279 00000 n +0000018235 00000 n +0000019689 00000 n +0000021187 00000 n +0000021709 00000 n +0000023072 00000 n +0000023392 00000 n +0000024554 00000 n +0000025189 00000 n +0000027071 00000 n +0000028885 00000 n +0000030182 00000 n +0000030447 00000 n +0000031202 00000 n +0000031948 00000 n +0000034419 00000 n +0000035758 00000 n +0000037080 00000 n +0000038426 00000 n +0000039201 00000 n +0000040214 00000 n +0000040642 00000 n +0000041682 00000 n +0000042565 00000 n +0000043426 00000 n +0000044184 00000 n +0000044544 00000 n +0000044999 00000 n +0000045566 00000 n +0000046043 00000 n +0000046479 00000 n +0000046807 00000 n +0000047260 00000 n +0000047736 00000 n +0000048679 00000 n +0000049352 00000 n +0000049944 00000 n +0000050947 00000 n +0000051824 00000 n +0000052522 00000 n +0000053478 00000 n +trailer +<< +/ID +[<62f629cbc39e31602a50a7d640d7d16e><62f629cbc39e31602a50a7d640d7d16e>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 53 0 R +/Root 52 0 R +/Size 100 +>> +startxref +55011 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_040818_analysis.pdf b/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_040818_analysis.pdf new file mode 100644 index 0000000..443989c --- /dev/null +++ b/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_040818_analysis.pdf @@ -0,0 +1,989 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 7 0 R /F4 11 0 R /F5 22 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/BaseFont /Symbol /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +8 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +12 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +18 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/BaseFont /ZapfDingbats /Name /F5 /Subtype /Type1 /Type /Font +>> +endobj +23 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 91 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 92 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 93 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 94 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 95 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 96 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 97 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/Contents 98 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +48 0 obj +<< +/Contents 99 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +49 0 obj +<< +/Contents 100 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +50 0 obj +<< +/Contents 101 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +51 0 obj +<< +/Contents 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +52 0 obj +<< +/Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +53 0 obj +<< +/Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +54 0 obj +<< +/Contents 105 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 57 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +55 0 obj +<< +/PageMode /UseNone /Pages 57 0 R /Type /Catalog +>> +endobj +56 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031041250+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031041250+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +57 0 obj +<< +/Count 48 /Kids [ 4 0 R 5 0 R 6 0 R 8 0 R 9 0 R 10 0 R 12 0 R 13 0 R 14 0 R 15 0 R + 16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 23 0 R 24 0 R 25 0 R 26 0 R + 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R + 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R + 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R ] /Type /Pages +>> +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 501 +>> +stream +GatUn:J^")&B4,:'QYh+--\E!b:TrLXTXk_/0mtfE/2F=4'gTMeSgK^'j.-g!#itb4O6g<2`="d$cc6qJ7B(q;ZpXHmf;Aj#(@%.TDY8<:7:4*iB53QH1#VG7Y$l&EX;BJ7'FUk^X(B!&bNe3ipc\*gOQSnjB01N]=e+C!MgElQr)n)s@1o@eg"C]L5JGuB8<_X2mosf*?b3]aL'Tbj%m_lhJqRX%2,#OSoN&Q[Cl_&MEK[)/$8\Sg7erbQ6dWKLpb0Tua1rO=FWH#__Rlt7Bl.*dM8(u*U!`#K=;R?s2=A.3pddA+i9V)7,!SFU~>endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1869 +>> +stream +Gau`TD/\-!&H88.0d!P2]f$km,sX\b6j[R(Rl1LHmOCY_2YMa3Z+Y7'9gX@.4hCo^!23G9-\R.,[V+`jQY0p]UDc=fq[O75pHJOqk)i^mImRJJg*H\3%K*!i8)EgYG)+fE7^^_0G45]ReD(Kj4i4g;+g-ha'?I2;G@G.6CK=>EnB[bWjU\O"1qpQ2k`*=)1%fmBDsWP!>b2K'2#]Q0#8aScs$m"V<&s7R5@'6QX(ti.(I$0H3U*u%DG=Q`&stK;IATHU[AI@f@tC=,F0=YW5O?qOCAhDl8ZiPPX>tEGVp:>_"Z#.R.]62"hPU)H:#@9A:f:NB!PcJ5=i++t*k>5?*fmN^,fRN26?,^D8U)YNZ20Yebjg=b+;0D6-;uJ8P9JOeRT@NK\PsZT1mOq7UL=4ZhM$XHqJcVCdNDHqMCF2V)YYRV5mK2>)^T-Z#\_(CS1.e#ldOuWT/LV5^DbnA'$b8LcI%R[]Vt@ehIfH]gO5f7Q^[)'?!0R\)mA(@Os,#G]l(63T74:tbusANX9JA3!MlF?)'UsIiDqZF4FH=FY4Yhom[_!6As5[t6>i"H)Zj1#3\HZa7+c2q$K6=I+>lNtOK"1mM=`^7)GNU.r"$;s$fcUIgF=e3Y2),Q\hbX2o7+Y>BcIK:R%r;f=jV:,Vd-Jg!K;X!!9o%QnUD;q\%/]]Fl6--d@)#$S)#*8Efrao[`@MX?=YgcUATgJM'C)b9?-#CK!,Y,:dH4SBICmK@S-k=6PAF9*7q%Gn\tf]'N-1>s<2>'VU<"$\'AKS#s+EqY%b*knGoR%8e6H)n[1Zpkn-c69KD21roM+"2.BN,\F3YaTiICSAc\J]2a%/Vb7)0*NY0+@"(HZE+-dhM&n6RVXO"?57b)4'98_51),oU8HmC]D'Yaj8cilOXJts]6n',4CE]$Qg]mZ7oQ'Si0)NQHe+*2bSI[B#4dm0?fF4AXQ'=P]F"c1@8@!oO/8+<_eD9/2(JSa,[kGf$jhtK6X#1AWYp6DaE'>XV,Wc6nA'aiZlmiu&Z]kUoT7M"Ao&("uTED%+"X>R8gVD+R1rB$=<>'Z8JmuhoQ;-CY`9?e89&30cb4!P4VVf$iVcN\.2k(p_1@RV5/nd?b)E2Tb95NoU\R8O@be5-3W):9'LIe8fTP1>aO...NQ^Q:fFP:G9D*L%qlnbh;=/-:YcTW)mdj6e9[-bO_nS%"uF*B>sc(@d9qs!Lglc@Ul4dN3;!S21gM-%6s^[^*:n%N3hEE=rp<2VoG-K,N9UYg:WlfcltuL>33uRZ'V9=UIGZg`II:H=9@e->[MqP";Li)3EZj9VeI==>cuqY74A7`Z>O;*q<3f3CLsQe4Mu5=F5_I@GUnklFbc7U$0aV)ht/L=Jk\*Q+Qd)"\b.Snh%XDfK*p1PDL#47kReUWU=KW(FOE+K?DT`AdZo4^YZ!i2#~>endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1542 +>> +stream +Gau0B9lCt0&A@7.bb]hf33lVO@l];EY3d>9@_b]kk+W7.*UPWEP$=*M7/?M(jK:\ZZIC3l+i(N[Eqj8'HS`n0"J77DPSMRf;`]Ao;)Y05S?h[(9[aMo1O\ffMlbZY5,%Sqq/A+"R,A)_E$SXX)82n]Q&^?-".d@q-gBXuU?V,'Qt>IDFD$R?erd>ZYRJYmWiafNEH"Nr;MH/!r@4b'?deSif$Q!`]ZSpH%68me>"R[eNbGs/i^%f9083H(81/Bg)>o?;dk%e!(B((nZb6Z_k;V\h2`Mi+9uX8C,FA%bI1<:U-Ge?!@mHYG:fCGL$o\4>k+LuB:B*+>eMenjs[>^oGi)A>L-BO7/LfOhQ>2!]WGDWjgS[m1(1DuhOKq$%SIu2G-rt&GpDmbQVQI1G>>&`clq$#s$@Cpr$bO0(@KV&4/2IgUq3k7VS?S23',.>m,a7kWX/0@VWZ6*$3,Ig[j"8?\*:>dmEna1S1EsQr?cKOk;4_T6");Oi0mc0e3qm3["Q[.6WEN16sY-LZ*F,`(N7QieG;Ul_pk(+)o;'pmIA^aeZ*6*f4QFOhT4&AK!%P:a]0HF:YG]>oM7.6cKEZucd(^[+l/Tt'0\AUKl2&s]Lfm(_Qm_JkYij\Wq?Gu`II5AUN*`o]r0ojB1T'Nl)hUS=d7s?A=#$UG$7Pd6l/(Uc^qip)B"I<-D>@e>bsBX=I-fP?i>j"/o=TM/u)1:M72[XTBEU^&`dbIgo_XEEI@%'nQTN'NaSUo6kaA?A]YBO(siF+h7X6KfroJQ/,KS-n>jD\S(M(E.tMED'`cd<*t,IiU7:Bf()T'k^geT\LOFt:m3u]2@?N,OqU4]/K"mTe1O71^'!VBDt!U77Ff6`4EGR#=4a=,eUo'Bickkc1bXH@\p6`4a:8%W*B9QSu&?;$7^?&Ws]*nt3sjOBg1N#(YCb;qKrh/g9^?>^En[endstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1344 +>> +stream +Gat=*gQ'uY&:L1SW(4-,=LTs9K/O7U65Bk/_.Hc2Gj2IPE8k*5m4e.;hnIXT@4l0!,7p%&W]I&X:0!d6Jfg0U\fnl1J`!@.L^ME;Lu-UsRDZsgq"[0I9@Er@f6WbUA>'5L./T[%$1r&)<_fm#K3eU"cr!e0NT[PM(%F?#b.erpX&HjAgnM>@rOkK(Sh'3VH"b9V+=dXuNZ7EeL)3.b-M#;CE`cqNNH>pM41%+jAd&hkAEm(66n#&-mo@pg^JJqTa46ki4g@LF42O7iU,iG&R4p+p2&Kisd>2]^t0Glr)R%W$u9_C"j&jmJb.rr>7r.?.5tk-Rd&XY_[B4'U8!?N_iS^]_rG=SQUS?btj*#a9m7W-`3J[6cL;B,AcW<_mu7_i%FU,H@^^(-'>r_mOk-ZIp;OY?7k;7dNBiq(Zed7q$PYi=`Bd,6gY&4TO_U;AhqRV6FEV(\<_X/jgB@3VA9WTr8I-8kY;j3Xr8Jpl>2:``[3WoN6j]m+t=T1k6#"L4odhlPLBI8OSK3[gQ(j<=tqgT;tAG7IjOq?2lN^[q1;chf=!T_&rn4=ZjjfYrXQ!E'auME64cNk5@poWALY;72kXbG)Lk>ZP`FM1kJV1TAt\jn_G?XE+q\+u*uj"/DFjQA21nFCJ3>^@BB`T6#@Dk:Jct`geV]9A?%tjqA#Y!m)!;/le.+\D(7eCD3/>^\=islf"e^=;@q"*ZRCTn>@p9CSr-:()QA;Fk7?p_f@3;U$Le=Y1'VRj(=Wd*`Gj4Bj?R7WpWKg(FccUY(%V!o.@K&<"l?oI:Ae;5p1:TT>2Qk9gpWUM]I.r9k>WI5if2_SpNpTJ>/e!31iTendstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1826 +>> +stream +Gat=*?$"^Z'Re<2\8P#`!eE078c(m^SMDK:%IQSrnfhlN8o9DWE`i%en$rK]?p:mF@DWR[p[ao%Y$0>nV\Qr+N9G=Nk?hEB\tE_'Xin^170DgD-biG\l]^]TC0u@%gt^]A^]H0XiJ!ho^p[7S]7=Gs?Ph5'AmZ?Kp/LqEl$hq-n#5j-rS!uTiPYbQcDi8oq$of^I-*AQ[ZCWocJoYA%-A8@df'4E._0K-3l0/UY;:21A3JsNf@\/J*0j]%']j>iHU@MjBU\;HWn1]bTqIk3hC-=1blO9SkhS9B]#6QQaG7"fc9u>@n64/1,aHQVT?k0UHd.>rRf8lEo&DtG@Gm*-'uje#EcTF#HP`bTFGp:GNs=K6_U;hVB!.Co.i\HBkeED`-00lCc-Sm]U)[J@OC'icQnAC4B6C"S)>l\nZ"k]3p]So^$J;I?%[GISs;!s\O7YSHfJqR,bYnD3QlHfnaP8YXN@BH1<)YXBg%RlV4"fRIJ@)L?1b5l9eND,'39W&(=9#4;4mffM3>up-LkHVfk=^#Dm%h//ZABuC:F3bO8M[rMM7q46t9P7MTV)2(Q1+lCSTIB#=i[G79jo6DQL\m=FaNL$K[!41Q#*[/<-(+!_45^qLt0FluM?4jmS4tWQ'4&[GjFqSXO:+bQOc?i.RpEir*Z"#Paf<*`r:3FeURE3?KY?__pToP!i"k+:;9S#0jMHc#efT7JmPO:.S$G+F4cucVaj5n&S0N;"U+Z'c<4X]V2T&QbB=\3K=9,'Wb#>"ro*m7;r"=<*H3t&j&?ro!G?Ya'^G=MDQXh:#k;Abdc[(MZ@HF,UQfV9:[CrV$s$F848c('-j(IbL>*areXeA&;+\S_^hs7neE%!g`()c:3'kplh?rX(YA=33TVEC1X;V?t=G.\'Yn/#nXC:N.pP0RpD?bUsVr&AWH_Zib!=YQ%1ZiafXAUCa^.8Jsrkm!MaB)_SrTPomU;:#ggW;-qH5I'::Gh;5`-63B3L8$/\/r#\s((G;+USuX"$:KFQM>oRjVGqVJQ3ALA7:T)$gnn9(g#''RrWDN2o6,WADean_L;G&7?:QK^N7Ve$Re7VXE8O'Hjh$M77kl!3L\nH9>DFY64/l@\s;K^/V@2\SVBN/Qc6W@&`\(k*Z:9a[t`h4J\Fhmmf6@*Qg2KnURk4I`@u!1*+eZ5EdT"rP\YT'nr`&MM^J/cgtDI-bgh"/T^fmcR+C@6TmZ*r:\Tfi"hgh.Qcs4;hIo-q=K6llR^m;grnBc=;SWB&*040jI@NAobRkOi`Pj/W"Ye;uWh'5?[tYEo5aV"A=B5NQAb8"%*:*_2CXHR;I`-Rb4K/g;cko:$>*,t1^=q+Dp`*aXYUOd"3g+K#=V3\)k8gVQhGG+.kh(f%qQC?mF6FGVdJD/"]+>#@,@=W+=S$K2nN.642nfL1N??K9ir,(^<)*J8%Nabo'_Y\7\[3L9M68+^\hXA#8E;Gtp5c9=?5r:!gIQbu/G&VA0ac(VMD:@mR8E>`*NuQECa5jbD+iiJ9ki=s@jJ0'~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1355 +>> +stream +GatU2?$"^\&:Mm.fLKs0,o@7;IA9')R<$cB3do//Yh+nUL#kpYPl'e89)dbd2Pf,:L)F4LF&mX2O6f/fI\-EIQ2mP)\A%^Ql[g40GLO8,Ig/jOin&mNmi2aEE-'VP%e#,d5mn^BT]-?:oh%1F=;"TBKX*kF?5l(f`a>U(',]!7T-+!qfRK>ciS2HJVt7qNQf,W1s-Ia0Jg%=iT!s>X_!+g7eA_N'W_VFB#EIDQdVgq(E#Ih(%2\Y!JaVAYSue+@K+=X!oO@eR0$J(%!]4j-kfT?qKQ?/=8ob$.5umE!gMNc;nK,b-NMAgR=eO^gL96ep+$N>f,+gh\DZd9HkO]'XKo@cNWT;LgDCUQ\Gh!O.Ys<+o\oW!SFC9]VlGZh!fUq#P79k##9ADU-L%3\dH9:,qR%^-H:c-Dr*'*8:#7.C3XWU'f&-#b`RT\n.8@@7IHp0@i".1&%Y?+rSYS[S@U8lf/IBcMa&b_D>n8liutfdhUc0R7;RgnY:&Op.S*6VLb.-n,;T$HVemCPRFWr]0p6e/QileZ2YKDnsb(o'ilEpqB-o*E-X@G,job%]C(1]NF-o_-2Br2Qh'B3jGa.LJ[Luogjn-`sL#=A29i-8ek,'gS.2$cl3I`m+CWNBA7Ee`\]p[VY$GRGk0[mjW*o.4Se]h([hjoqcm9@"#=@u$TjLPH%haQlmC$nNYHo&>$'Q1De%'Lk*kR7#H?ML-QfnnPlEB&PGUFU2YL!7P]';mkOendstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1165 +>> +stream +Gb!#ZgMZ%0&:Ml+$k*j>(6'N\2`YeoiW)H]gGJF9/J'Hu;e)0!6n5!s9De<$dW4?*m+hf\@NiMtShk#>k&P8B+[+&!M@AFp$(P6S?kH(E^tM'n-=[lfNp_p0L$Ze*l$%_=m`1PX!D6eH/?BN&,kLil,ua#p6NOW&tO$A5Yl;)Zct7)K'0R9GsP+j]>BVJ=/(he%K4?_T4=]Sj*<9-*2Zh#+KAERXqJh'=D8.B<'ShpsYe7DXUP/u#@[c&oC[I6C1N6-^`&V\N[k<_qKPK=SFrd,kXH18Tqt/kO;Gh%e@B;Xq^"f%,ts./dt%SbK[uei/mr_]tb$D[<2&"m?gdBX<5Z(IXpD11_rI9VuF5c8tk=cYnX8MZE#-MUGr8DCsEt7]Z/qYD,%eR]"db12bqd&Y33U4pOel>IJ(#a7[71.&clL\W?'[EHl'?LlQZ.]POqop0'teq>3"kU)Wu^T$9@_^"h:aW81fB_:OudEfS=Ap9H`Fo^^Ca^?qHT#97MkR^p[m=,R/?B0fm#F.`[2j\/2k%9Wm6)t=p`R?3GR8[k&=O8N;VckX'>?`]1^A?ep#E%+2-ee9dVQ7;Aq+[O,.WgF-jAd\`rRMofN2=C^")L:gluimTN7f-XH7RZ#k\#F,!\pseSO)J\mY]&ZbW@`Ra]YAETGcWUu"!8j+A`!gWF8U[,8BG_3IFN=rNdPt1?1/l1TY0mj:[\>G&a4\BQA8AkR1LRAM@PSYCj+gJElU!8`IU.Ut;7&&q$nD7[7TNeT(+*/@9P),X%='s/,i<)g_]g,TfFm>+Ml#Wtn>pSeg$)C-FkJ$2RE4dJoh)2_Y~>endstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 652 +>> +stream +Gb"/c;/=o?'SYHC.kZQB3]^8=SCl$>2HD6eTjq\1V;TubR1ieF,c=;E5qrTcO`tWE/)))Qb**>TQ8>kr;%FtR7O`:G4:.^V]:WsosRsTj1WTpR%Z+/+Z(/P797::H/J)]TH*'mbtmL^_I3O>gmi1YT+\!lRIA/34'\]t*qtd:!0TZBdU#5WIC2ag]MS#W"3%Zb4Y*YAcs9;a!>3^pOh3iU$`gfKZ/C19.e*nS@*Bk@b5PZ-Yk.H;Khs4BGg.r04]WVG94ag-#pG-bd`$\)]8Ea@*VB>3'*;ThV"U<]>2AN*W=s2Ud'uC3<.Ya6WWUW*A^clQEUtq%;=mHsdo)k,gINM\0+&3b.g>CKhK[W=c2b=6@\H(r0'h4t[K:RH'B*A-%7+RM5$VAK2PfldZ\:4'bEh0-IRok)!M.I,j`Cgr):$J.^E"_O;HLBbPffgpX#>3#gW`#KEC*G*?$?$.#QKW#]`*6hng$C+63r#BiD[Ws~>endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1281 +>> +stream +Gatn&>BAd^'Z],&.F(S!fZo6JL+dfs?s6_d.<`.`:0nW=J:fGaZIfTaoK>*`A[uKRj7*Q%=I.6.dU3#qUk=D_?N!>2^jQL'%!9i*#j7jbD%"2mpu0I^2uqWY),CpVKRQg\6;gZ'dGs:rk4ed;')6k\HJO^e,]UI!P#Hldph5SZPo)S`BKZY#P1&^")SOjYl@TjG-U,b62^+YL==p.)+;N%8GS4.]GJ"\l;g-,'f%YOqj^9D&is%E>BA[MY&#OUn#@GQP=JGTLpV*gHuu?iJFM2Z4RZVMBI8F29pr!5?l`1U#QtI_jVCYRdN&>[C)H3XYrQq/Y5gZ.qm4d6uoQKk]`[]c4uHn[q=\2:0@"1*Q_b0cK\XHc872R\tdgK:>GB$7S>R4^8MGa>(*_P'oh<5DN^&s`V:C)q8k.jnAFEb8jM.4$&B@aT$:nM21E/J*2^0ZrRnPE=6;95UGlH=pBY86_H/4Mq$%,ZaCVo9AZd[/i^2!_VAghFBj[*iIW\)(,c_SQm7O'-XiU_'7I$D?H];5&ecWeSg2Yu49I5\QW+/mK4cZ"dA]H6Wp(Jp'153K?ZTj2.?Qo&o0MkDJ[i>!Y5Kg;i;_=?5UcGC:O.2*/ml!\!Z4endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 230 +>> +stream +Gat>N5mr8u(^Ap1^Z%C[#MlitB1JXj$;'OgLe]CdUNu.^2cg]EG`W_bq7cTM(kK5ZIiAjX'(LfD*3oYm;$'nY."b#TT?U=Xh,>Re-="Ft>_Tmn>Yk6?iU1XrS*hsPgES7Ch*Tu*3c#r-Dp#8:i/tgR)DeaqT?6K]<\FFG/mE%V8fRZGFfbI#?F[b9q'+)4Q1S54c<+?_NP_MHG/d='9T1Rom)N0.JeolA@K-~>endstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1065 +>> +stream +Gatn&hf%4&&:i[6/+-s]h$/f/RqaSWbf3+$_eH#?]VMN"Z\F,nV@rq-S2=%L,_XZ6Wmj#MIGB6p2@(#e6.oUp!RPuJb5_Q@_0lOX6BC(TVOE-O>BrKEP:aHR^+VVhN\JK-.%t]liQW^+XJaDMG.%anu9IP5tI%#Ee5E8-`_N6PC<-$$aYqR`mBV+a$a#1/1:O)t<2EnFW<-oU\qb[IXl_b`BChLEp65.o#Y%,`P`ob!thqA4LaqL2:eMYjIl[mE=;r&g92F5e+i:EQufc=o`-$Whd]@3g[n;oh&d^#A'>IbC[A`Rj'b;YJQ1N-nh%5/rn'Gl?6c=WD&&Db+p;.K*aqGFBf,_hMN&=2cN3mk&dN[:M"T/*7bk1WRrs\S]MF^FMEceLo6bt,'$:7(QRNnQ;>E`*P87SFfTE+W,3A*iSW%CD.O[I#eLqD0#?Qh0'+mh2,M\TnABVHLsLZaiS6;ue)on@[0AX0ibP9WI_8d;PZ';Cl!hcdQ_9S(='_lX"9g3m;dW,:rV.:[?Vc0KVjd7"6ValP2!!MVf$S9UF(!;=6)JbTC6gG.OO"_Q]hNg_Yruk9[JVM^d1_Z,="pgqrmB3Le#:Zr^8ng.SBZ@KBi.WNP%:`uBhUdt0VY]tI^*OVf`q6'q]chi#baZDAI%Tb6DTk\F^#Q.T70a7RuPrsg6Z:h6BP'mW.!6d-endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 597 +>> +stream +Gatn#;/_pX'SYH?(&+O;gI$j4#W-g!U/d(MD+hq0?9E9P?AtH/VH*WoC^=b+,\WYo,U@Jmn+h?Y0nID/Uj]Qf@$/@o!s'$%?32"*`fNF%V`]26a?c5+OH-YEQJH1k7Bh5BMW8423JcC@Xod4@*1^@'g:>-l([hsuBIoJbX;`Y!h8A"b1o<`VV]R&]$2I*;Ys't&`[?N(52P>)gJd1hH6`d2P;J!%Fj&36__3[AW=\!%@&a'*L!t[Smh%lK]"8iSRbYs`PH(JDKDENO^4;I'Osh5ZRUk$;r"8iae5CA2)&9A2VEo8u[%M5nZ2j4Tfca#`JO7%2c-6Y<[$(-O,&r4\Wo$XoS[-\nE[=r#JPnA2n/="%)XX;F?eD&)Q*.)sGZl%[l0eDi:&Z<4-Y06#;d?]n(K+Ge4+Vk)>laOmis)@=0.qrGHB%!oK:fum.%oooo5Z/U6Me-eo:0Ese4;1.r9F\B<8[V'Mp_Q^VVr:Pf97J@8@r\feK`UBDYYM^1qjp`]D9Bendstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1816 +>> +stream +Gat=+D/Yn7&H88.1&V[*3N9sTp[glu%S9K6n/9qb:B%PM[CoYu$L>(`WW2p/!Frq'W+ScCYWFYecHA"r$sieRl*'+L>ha4C.tapR]`u##otd5NAtOK5POk??0oYrlBfquG;$%QFksE$C6WprrLOq^i;Eu91HpD[oV?ABs*PF-FVt"/F6YAK9H*GoH+BhDis\m/`WFUkg`rc@99A6Ab]H4Y+C)fh2*S&s`+@`hGFt5%5eMjs2Cgq`!GD<6S1n'Obq:?5Kg>c($$O8Y?6G*'_q'dXAMJH51%hiS>8FURq]q&6P!]L"Z&d,iC81p.TS/h@dd!4WM1q.gnm%c2;l=b\#95UiJgbd4mq@n"V;,rob:cVm8;Iku$hFKNlcX"u0//-*?RPF@j;J??H:MV@oDpgQqp]ak6eJ:/D+f.)H/EsVaM\3lXB$:8Fb%PN4:!V^7S_Mp^6e]aX%jYd1aV>YjHa7Dm!?)?e1YZG#Lbojo=O=Zf_=lnW'EcRN.4dmYM46h>$(@tR$hStao/MZ@"$"SRRP`ce'63_r":dTGYKn#^Aa.f&%Bp.j9:r1"7QsuY:5OJ+EX%`9@d`u:s0J)(8\smc@D[7+^VDF@dVJ9DU:O.[Op>h=Xcs2s3@a5Ajp,r]O)J1Z,"3Qb9>e40Jh=>0k_POWSkj$QUB@E5BO*/[\8]$$&o>&/k!XLIQ^$AJ;A>t^5,;;%o94(I_;/ba$:G7N]3=q`T1%Vd*%hjSDqj>%i@tN]n)#EOm+S;JC3)h5;q8m*\hk5tqR#Ib79n6n*]aXiZ9/s'T`9khINAPqC\s*4K9KY,LumW9DF-sN!\2oE[EV]'A>a6CNt:is6:o)i&6$<\grs3>';sE1TLU[fpm0njPlc6#V2DnBf?ugCTV48d2M7,93jNJa[^jnm)=,;U[a]/umr@KlO">DWG;PsIT$O<^)nH>dZ^Ll\Ce9#iPf9?<1X@W7fEf8^?2VBq@h+Y/0Gbc#I7n(-$WhUk]]L?Yau-7Q,Z/6Rb,koH@@GhEU&3?=jt"lm@=l&*8O`Zk3cN[Uc[(>qB?Y1=,4rq$+J&*)9IEDJY%A;:m0D>K'pD,E%r$0I&2"8D9rGTZ_aOA>^Q/FF6JG9O@3&I^W7o=HthO!)&@Bir,l-i0@/%$#\'%rh(B,$maI^L9H_N7a22&_b/1KE:tB6kCt8~>endstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1727 +>> +stream +Gau0CD/\E'&H88.0rO:^Emcu#(^t,"&eO49Pn4EFV'keE@i!^/nbRDF;Hhn+n#U@[?piI[%nfIMh0J-oB:^!q:rUIMrkg$I-\/6Z)f,b2);)+R6I5s%\G1AYB.(A>GdWjfCpoc\JK$"Hmndg7==3&+'W>bsWlZLK:^IHkE!*Q)!mW!i5g1>bd>Z=OP%Z0di.=Ye'IL9O_*)'2\Ug,?O>I`1BmdUKWb$\H^eDfo;8Pai;b?EjK&7_r#F1i&6Z"?-cj!6`@YV<6m+2tPH@$PnrJ]'r[s%3,d8m#BgC(sNbJT,q-6QB6c7Yt@1_ncF_.1FU_sBt9(MH=-]cRlhWJmKC1f7G6GX9[/eaVk%DSb#@"K-2F?-.3Jr>gfn/=KonC@^\j5Z^jX0j`^CgjqmdP:4@\(7E7=NN3V7XKtqcC8[fh[d'0JD7pr^MANi\+d`ar,c/n1n?60+gbbfZ1l\n;X-nVt?9N?F6HG!]qm$*8QO88Xlr:\`WD"q*cBqrL%ktlRT6.H,5j%R^#A:dl]H+#8ClM;F[:%H>GU:M9Y/"t"5=*%Cn=_r7gOVSDJc>itJ+t_c"V7@]nC.h0-#9u\m_^1:IgZT;?(j)]mjPrf)i3]nEBSX->Wa:5P8B"hsGYrRhA>]jA;1K'g\;18(o-.f"!ogCW1g^Wl3?aM3t%X/Pb9j8:2M<^cKBIlVf%M>0`oTI9Y[(;%?6\)-kYVg@nH7h?qY'i&gm.toBUc^6/"cG)G,m=mMGJ^PX($FYGe$Fbi1f)P_;mZN&!*!`u:-XIsgHcd)3!t$Qon"i9fC&;R7m7@96/[e.0WF"&?q,uW9I:$kp\oDX\P(f%;G8P.X;IQR;tu_lHLjcf."!]WI6bm)-__Zf0MEtd$f$,[pr,"bMrtPkj'73`%3GEFG,OfD3L"u%H?##EHr:9]&Il;$+c9ms(,d::CVo1u[-F:O&GN1!XUq1%amhm;?lplS:sb[mD7C%UUq3@\qOn!iqJQCE+(e3SdD(PpE(+Oh"rPa!O6.9FW.n!'MKCSjhsK34W3.CQ%63P18Cjf#W.)@\sP6ZjS(UV0Pe-AF)o>c1'o1PP1sfb_R?[[/&hB'97L&nY]>HS;Qs3D:no_<74fg4f=YuM7~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1190 +>> +stream +Gatm8D3*C?&H9tYQq"*o"J1$2O63S%"%1BGD7-Uh+21B:bZ,7Kit1CAf)a!2C*Ca""$)#j7k(>?qMO0Z1nsL:W?aB[H2Y>)IL$@7K;/.492VZUd]O9HtT9PWFmZ)MkdoC+Grk/IfQ*iOba_kk3V`B#YIHN_5`eKX]01;RueE?p`:hnTNKR?!Tbk#iT^K"T5VROmi]L=WXEGB!HqPha4S_h(ud^GiY3h$27COSL@jkRW2M"a(]<'$*n+RZR`Q!L$/J$bgM`o'up^I1#mp>ndbl^ju)u4LtkUM17qkNI[%?,r#\O$XB[`bSBk+P9@0qFCI,oN67/K"H/L:Zn(KYArjAWRkjWs*:74^XU]`YKlZ0q,('7*Z9`e0(*LmF]Ffqc"a5B?S;$Hb`+N=ubm"$c]*A:#302bpj,GRUL5J=dtdEC1uFLen/?0M6JN9^_,0Rb!9e6&+mKH[)Xed&r%c4=4Ie5];28n?CqG/&!7_S[tm%](%h*c]!'cq'jtdHL\E;HaR1-mFI,'YbO)7E!([UJ$ob!*7+:o/"FC:/'nBgSD[k=C?MKF;8N/W3C+SeKKi=]-\pe7`I/r7*^^I#hY3m,ZOdtbD-j6;HhZeR[P(FN_9i`I%aLH91\/N.q&:?^XE%-2Ef'c>8_)3>&qW:ZW($srBhhSN/s`M[?L)C9o;[\.G$2iL'-?kaq0`mB6F)R>>9(FYZlh:VMc[#N;2rfU[F4M2>)@u:e,2<":$5mmguq8?6nDKS$-j].f3Li@2l(3LP7lKs)2(/2G2:OU2*#so=J&qE)%[Z=G_C6PV]iPnu]4eG+&OsL[dml8]XFg/j#eHB$'Fja`4qu@GAM3S~>endstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 616 +>> +stream +GasId>Aoub(k'`6p`A+aKtrk7oo1/i,,JEH1t&26\E7Sd((@TFGPUpIfOCI?UDJ\31i@[]RFFrL;J\f234'u%61.li7\Q%pAVFAp>%_&rV4%tXFZ6?Bl,4VADIF&C%hI5dV"^?HiHF5%:nBI`m^sZm7ask"Q#rjq/np\7!:r^+$+h*HX%k]*UI;AU_a?![%T%]s.-ahV(qm31M/K@r.:'q$r,$$>[5*o@"?BF,R!b(432lZ[3P:H:'qP+fQF9]A'acHA;7nT?dN-[f4n;sDL.M-@('U3601s6Ff&3t8Z-];HY[BlfDEQ.)RTL2#Hu>@fio=p?W[Z>cZaO[Rola9f(*ql8E;j$Ko^A/U;4*Xg'^toX6j)!!4>Z-\^-md_FCQ"!dPHefK@suNb_7n=(#e4eB?gVuCHNah:e7);3m[O<+P6@>:5Sr,"LET5W\^1~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 655 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E+OSadYX)uU/lfurn#T66E)C3"&*l5sc8VMXTLVf-I(9N8/Inkp]JLu@/Z:\&,*oaX$-=jY5N9uDhpVph0[!:4X+uh[$@nRBoWa?-J)#&lc-$BDQ8>-G^'#PGNRR'EsR-h;mPi[BJb;iZV,sD89>tr.6-o)[IL3/?kR'Y,'[7a>siJRUI=44:-3kNS.g2Tjh!$#_:NYc]VSq-JVTCf@oWgfaJ+e_Kq:L48^4nendstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2240 +>> +stream +Gat=-?#SIU'Re<2+9i6FMFAkk%uMAcT_$U_6e^Y>h-TZHg.\TlQ97`6RLT/_]9GiYMG8p6%*-TBiOtRJjLLLG&;C^ps"628rA$m,pB2(ck-p-L?@_2$k\P_?pCU7n(*aUi?6&PRHGB\h?RY?&TJ&%fT]65];+)VmMIPi6q"eefTDea,`Ga0$g%j;Y\iRJ$1:s!'rd\UQ5+VX5HT+/Vn)j5JcOtDQk4`Qg7`N2r:Ho(V7WY4s%PSl-%u8^r9FHt^![VMaUj8)'ks&X6WoWJLT_oR*.tO^J.hdBUMm>[Ykus8Ve_oU4o;QUGHBbUY31@Xll'BNZ$:U(m:S&FD@=f9d`\mFHO38>ms+XBh:5-qQMf`D:-J6]r,I*pa(V[g@$8*$J%D2_?W0a?Ziq]T7-_]`1D;1mO;q/WsCb"5_e-D`+3dY0(sb'L&r?6q_[Z]N9q0+;'?"C%8cA!gj4k'M>^K*I#%`o5[N,Wp$^;jES?[Tn`"PSFO='IEZrD'HUE]]*dM`>)d%%K]WfJG:mMHcl0s+F3d_`LeL24pLtXFaDAhe$A6=QN/Xr*4Td*\c>dH`OPuVe#HPW?p$6j?^K<1'$j<0*M==I=TM%k*>\[V2K&jme;r!_NcunHi!ioK09X1taWbCnflH)V;fM)iNrWXGmqZ5[fF86X_@"$)1p_l5"R3+B:nbZhgK&b285E.kC'l"6C]iGduNn-h9iU0(\uRVQW*KR]f,6?o^HI97`D'9%(+LU-^F%bsl6JZpEA;FIO*>;,V'l4f[D(7BTciF"UO,U!G^FQkcS.+QAe)@sU#?\BHpuACI;MQ>e3cPFcj_J1Yq>E`*@-MKjWY3L5UdttJ$4>c\4LHkpjtI;OXi!m\k])k?<_1J+PZB1iFnKu.jJ;Q#DN;J1:@[a?_07;mn[@*P-FoXmZucqB*?H?4$~>endstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1155 +>> +stream +Gb!#[gMYb*&:O:S$jnQD'YCYAh7I?O1e0FDg?i/^Zf8Fds9>)W.h/(hY?(Da=X``d;T2HV+r;@Mt[=N(cNk:mBp9MbXOJ]TcC?<9+YGEA>&K=!^/aCa`'^`k&nh#K"kff3U>Thbc/LILlAF.i;CbmW)B/sIi>!g^gpO5P;PMC`@Ck*^P%7;[g2+12u&iQqq09&d?HZR`D*@TJ"ERcnn.lNKX8:RCnfZqqZ#;on3(l8`B80Wn'W!1>GU!pSs&T+/pBp&b)'r4MI^Y'9%id"DZ6me/`-0,;cKMHgcZMT;-f#[mr8^9sT@S#Q=?jf!1f\mt.VGC#8$j\@6rCQCj@,iC76ZnT@Za4*>VFdGH!.`LHrFs5#$lMWWOEs:=0C;W.jsVP,0mHnp$#odX,;<;@m4HJ7GM+Gh5Cd3k^Kg0gjLZ@'FotB`00JA`/k22*bX61*uQ7aemjcLlZML3V>jKMgl7?Y[Z3'cG_1%/MIN@g5!jQSOpa-NO8cO*Yq!'1[=[Z4&s'bO""8j8Z)8t_S;D*-^r@ppQ#(X%BO.q`VKa8N\e!JN9FLh:rs2URj=H?&^_=gRW=O5`+VTM>e(*p$=JRdO#FSmf&CEQ6f)4E_QHE09he(2(9$iINF^XPSrpa(Ykj5/aO'Lb]"LZ_KuD;%H!5uCL-e,oZ#U-eU'l:;rRY?k%6n.TR3&f1~>endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1120 +>> +stream +Gb!#[gMYb*&:Ml+$jnQD'O=;+Y"m@GBoiAsJo5aAm(W7KV'qh4-+P:d$]=oWNb$h.CJ-tGe1CeB[]#U83'&jc+lM%gCtCI_=f@1DjEY9?,5u0hcIc36h:*::!W5UEO9U0_f&uj[,C@Q^:>'66W^RCaLfN14S>l9unD\&j#,DQGkI",e=Pt-k%fN8mZ4o672/P/`a"KhfmMm_9A_[WHBKkajJb(gpoO!CNBMji(5c)t8&TuMHtaY;#]5)J/I#\uKk!aulG//f:rsGVXMEn#0@)1B%U&%!'/k=j41OL"BQD9Z_="^OE@%+tjkcBX#l4h:=!;ddqLi6oM2KgsnaI8hRK_^ADPia/OnV2]AQgCJ8M`!hnYb`1%eYE=S2N13kKT0rrrC:YOU.>Gero9/DAD58'-.A;TuZIS4]Qjll2NIs5^],4%=]Os/dc4NOg!t[onWuk%lLE?nFPUO`g^.@\1oZHs[N;U?U"`d6Lf->R!)FpFZ<1-sG6.]8*ku%9I;f#Og/\Nn/.5bPOQhOPml*bcXhW[VbtHf?AL-J*'^e^.6jeMncRWUF+D!Hmj.qLq^.s/2Ffq;In2tLQ]Q>GiHtRmV'nC5*=WLO-lUj#$.#7m)YY":)VHTgV'pghe-b'>"%KX,U/;XT9F]#ioR8SRq6otm&8IrJebhGW6qOSN88f#/`m<5R4ajIXZ$2SGNeGM-R-R9Sg!=eAkt:k[%1quj1TGYj$TdmL/5gKfjH2$.:endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1360 +>> +stream +GauHK>Ar7S'RnB33!_4V*\p=:h&/6r904[ig1H?=jqgL]'kWW-P*DFYk^VK`,U^;UX6)"t+HBUFBeGgik_b^#JXF?/8D2Z5VY;ZI@l=B$1df`a%HLl@Xi#IKJZorbW,hUIocr6;6LI,4/B9)45PiPrDa&2n'k.q%;"Vi\('!Wo'853uk"jTlc%R^Ieh"M3Orc2^I212L0@t,>I>A>GCrHiu,"e\_4]IRn"`HZ3cS_&*2EL*B:1iNnQYamDRmF(^XZN$*B[[5/>ID=Z3Xb7[M:.dY2*A->:16%Ir)9,)>-\Ar)oJ0&i+^FWn4tfFb7];hV)6^[ik(4,)g3;A=(k-`W&jg%!\IGe)[EjaN1bcBW"O;!^05iO$FriF';@Eb=DW6gi.ZJLe6FAt+:WJ86;cQuu/Ij#6eH^:Siu:M^'"*(k%69%A/+BplgcQAD8CAP+i#Qg0j-58ebW)aGP#a6tUlXYZn$0=:jfJeGIb=>,Lj)G6a&BVMsrHk9OG!cDT8O\4O9C//h8T2BWnDGal#Cb>g3pPrS;NUu!QF0r,r[PS^r`2;I.Con*M>4rO6HpqK5XDA.?B9-g#0P>Xr]6T=+O!.4NerddL[5+f.a2-`tB14JF=cS=h>QusZ<_!K\A0\8IlKJ$!].niR/0Gb$bfbETH!GKcb'(mje,oa1]!WFlA-Y"+m?g:Bn\HetES<)asihGSVWN.!V3CljK'en?$E9TOlQ60sqqNF*!r'Z71BOH%^Opid.dR2ZHq!m^e8X$WL1og.E^#WB5!s@^]g4:g=D(BJ0gDGo=MO(X(:9YCWqB@l?s&9njo7g:kriX0E#c5%42-5uf+SV0e>qTh59l`mOJVE62X(Sq"FpN*krl8K@.3$ON@GhDrT9ji(]ME21Utu>g@e`?9o*Rp:/fW2_ZcotDO[46KUcKj]PQap4eK)%>pr^6A^\:$2P?H:Zm_endstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 974 +>> +stream +Gasao>Ar4L'RnB33.4mJ-5Hl^O>9[IQVKm4I[gpkAXYZ&ZK"8:n.X7':R9#LGnaDo:GKVZQ&,N?f.-\?_`.'1,1TFW8oA3&R;$@`>AL3N:]/XVVPT2?b_nGmV2;a;9i,Wt;23u6bN'bVF0k.;]CaWerA!URJEQO^NT_>Tb=<*jMp@not\9Kj-C^C"2Rb)hg8EOO]8pVh(PZt<`$\h$/21Yrb.d/-W2XI[Z9ZR>H4NuldUfm>p>k[`*RH"Kj&,8]tHXA*n;'"I#$q:1CJrfioG)n#g!1fa.lPU=UtB?Iu'7dkh=3p@[0=5'YW4rh(RkE&97;2KQ\S.97`R.g++-iU],1o6<5r.(6ZpG@QKh`\;#H2l5)G%oHL[59RS*YYG'Y2[ahCVXjtHo/'`b!Q^.u6-.srn$(^AjJa%7`jd4#^:dM9Xg6S#q+BD.pj$Q:9dc%Zje82>;"hUpgeZKonO[%NVKU.ujSF[;3Pd@@XII^EGPRS4*2G#CNFc/@W>Me_-asHIN?,WX0#XY?X"h:d[NF?oH%q6@A@dkJUF6;=+@EonN&!:#9Xns@SXclXO&lB<$mrI4C&[G?#cg[Y9L\g;W!'Ys9Y`3Bl&/),YG,;Am(948YcBqH"f2HAb)q`gHendstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 684 +>> +stream +Gb!$Dh2]r<&;BTM'Q[E=2N=:-]dmcY.MVt^&D(7/BtP^7Y[*O.4d0E#Bur8(T`SaNMW0TXS)`N8!?VR2n%8[GPJcZ+!C@q_JV7>8q%iDh`O?"rr%^heM27Lq=c*eNJKa*"'oZr)kUir)Jb\%^IQu$dQ5aW6!m'aZa<-.)rq+O^ac;6o2CAXHO*7W(&BY1$56-l+QmeErS/q02lkVrfNc8)!J)>g0/mmeZ"obDOeEqJec(hE?LfcTOCI$qjMYb6`kQq:Z9?.HtA)8b7]57O[CUR(V?$AFL\I,(n=F>:?i]EiK[-Gkp1%tEkn?tHuF#:98OSjf'$-O&B8AcIIFsp2Mi:Ss-]YGgogW8*9GN6nCMWD+'rteP[tZ/P1'm6#YF#0!KT]6^@SS&cm1rpo4%X#R(eMup]G_O/_>+S]`Tj&$Ii"?;A?T=aAI&Jr(2kaK_m4;+Q8K.fC,;.87p:HDuL'$BJqY^i5%qN3h][cR'b?I$g(pfl/P!q)8hJI6;57X;\-_(#6?VaHN~>endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D-!LY)qe@O>M1,W]$5T>GBhV!q#rZ*ACfMUF&KGo>.i>al-\SC>"NTbMO`4G(I1[iojb99$A.b6rE=JUNeT<2_rRR1hJ:o;0M+B9e\h)El!n-*lndH09g]Ki/E$tg3q5nMH*c5G%Rgb3l\kCSkd2Rc--nX(K_GmF0Z?1%!`h0UB:TR:TdZ0n!4Bj7>O)+8B.u\YQ.tKR91/GVD0-!>!6oWp7D*o7U`m9b&*B[sXI&@.sb[n9l,IlR<9AW-ke~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 920 +>> +stream +GasIegMY_1&:N^l7X9ii,/?#B1f>h]i$>,RMG:-DIbE?UCguio]5&$Yp"qiHmZ^ON[NE.pc=LVS6B*V,GXa-t9`W^J(Yh%S'6#TTQOn8T$VE&uGBL4=KZ<,o9!e>m8I5/h.mBnGM6QEF*!&tf<dq44ZO?FRAd]17'V#uXZ;BaWR_V-Rj=k91XH.VRi^':GPG:7Y1N7Qr%?-GHhe"<674*,5$:-H$CPihe%c+i1TmDt@shf*pV9u@c8XOQTHdne0dDstISXeD2B'qRd5/iM6jYUP)V(?J8FMM:V-d\51,iH3pI,n^*Z$qM$(t1\fo1bITnC-)-+.&\dmnr_9Z7V>M*[i\UsN6=9GouqQ6fSDAY8JQ!.SC&KLG:B1#!t@.%,[YaXeYO16L$(pA')*2fl\(_U6RSUWK#$Gai0jY-Og2BKYDS7ZFBJ[Qm1-e@qr*Vp9]h;iudu8)C/L_lCidZSL9I=>uNqX2nL\)0rPn`:D?A1fDBjDo]%2KiXOlDch:qaVGHRE7CN3TqH^XQ%kU=nc2\&g!J',4RRL'kef,s:$#^Aendstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 770 +>> +stream +GatU1@;jjR&H0nX\.=c/#SDYU<-WRkf`phfj&A1_V9Z;^;M>^#sV.Sq@+SH5uP@LB.'$fL#n6-Fc]fDX'1=Na^k3I[6M*ZJC(9Vr$[n[TeEX%>$Q0Q<&p*+X%Mh@;7&]%J.XUJ6N3#F4tJuE5=mWJC7+9KM8TbL+"l186T0`.cXl:%F2E@!LI%6`)I4m(ScR>Ao:k,]bW+jbgnJem86]HHA!>aB#\'XL"b2NSQHA&)8,'6jg%su_C(0sC-`bq9Ds^J%<:\7D'On)pNjP<:a3Nq.m&*l`#O&nXg95fBKQq>jM%mMVF]_$UA[9E((Wo`mdsb+P5/,;*"u9YcTD\T3i)XM<\XM1TgAR]CahU(h.qrnh=bG/B"\C4H2t1cqK?`?L=e'&A2U0$q9=\LM\lbM@=*QDeJg7+_UMAR),_4R;6!WZib2Fe5b3D-;%rmN=Mko2HRGls^sQe=T_d]IOU'4sRIWThn@MB]/sUL!usd8f$pR\,_/52%tmuln,Xr$F$+nAendstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 714 +>> +stream +GatU0?$"^R&:EYBg`+W)!2d-MG1)es0o],)$&I_t(I^Nl>$H#XR?m+0^\;9[#8A)R*KC#*n*[=OFRl(nb:DHo"ZU#=m!IZuJ^)$s1ciDV&?s;_`S2NI4n)XY)nk+_*\lj`;7m.!2k;"oPaIJ4.^bdEX'B6;^g<7$m8X6j0O`r(,@$cp(5tbI3j>el!"Yr!>%!`0=.1GjiYJKGDf6!4,0Yb'[lCEg-YSfDi/":5I0m76X:?U"i+L/Z['[_HcpGGn^>FRu6/U[,)[s648cH4$)f[h!EN13>DLYDl?em(2^WPF=E'%0+8lkOc(J+a&T#c_n"$rem?796Yt&Eq%"ihf=GgQ$8gDq:%ai9W3[+k-OeJH8X]9!+L=Kp]NcV2h+6c.176FF0UVQl@(&MqT3`bQ'_#Jd'^c;*%"ukII"TG;b3+:R:cuGh"'6=O^'D+'LfqC,+dhF%kH9K7Rq?^Nimg^))H/1(UBkCH44pmlk^0S:&>]:>_*K_C3Q;IbYU'=kM"$HlG7N7/oM@qrqH[qe&g79)OGWukr-YQ`_5(WEk"KnZ]3&hVgO@jSpbmJhR9f^uDdZj%C7,a=]K/'B20(Jac>T'*+!P?Jc,'WnETB=bHiT%]fmQtu/n&+rhQanE?OQaZ8-o>^k/BBr%JCA(W9a`Gc!R8TFK`~>endstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 704 +>> +stream +Gat$u?#SF^&:Dg-fLMllghA4B1>%0T3KkGN[a%8P&l/pC'V:EJpi\/V.PHG@oJ#Th`W]mYLr-`D@NMi&;e8J:HV85WjcD^:M)MO2t?@DLJ_E^25`a5nAe2^T',[`"^.3]L&UcPj668.7!g)\14+5kXUh.1kf'L&%gll]F+2bflJ7HAhT?OpQ9G'1N#-&bKLj*2Ja?`<;K2m-"4ZMAO"Ra$J_6`?A4_pWs)F5@E[^mj"cE++A#UhL3L5@4jd$;RN3Ho[XVb'Khk>LW/auIF#/P*qrKm`:(e0F&&=a+dh;J0=XZpc5CjGM9_+BYXBT&!&k#Uge)%V:/Y-7cAFloD!Yk%Rsmrk1+.UKZ5K9h-A8(r[jokA&]3&g<3hLTq#NTr?8;\p+@isNF=8Zg]C&i`((ZkRP$,6Wb5endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 374 +>> +stream +Gat%^9i&Vk&;KZOMY@Cr+A:&s4X!-Yjc!;iG6sgCQG%#gqrCm4dm^D")riYtsUj?9ooSuKRgD*Q2K[f-I//@9:f1si^&-:*7m1`B>Gn`;lfKi\ru)t%j2l[&`T(XAR*A+l]7HJ'k"ia-pJaJZ=&O`%h=V;+F")\@"'mW0D!VH7.2/2q3nNl^]W9endstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 452 +>> +stream +GasJM5uYWS&;BTNMK^VsJ5&H\ghM[>7g,[)n\D!.!?u60[#"^.dm?p%;.jN^fs`WlgEj'uOn+K1i.g4]Q@Lr&$]nDq"Z?Kp[FZ9]<7PU%D-FmQSgQl:3MYc9T>A@dOr0P]5Y&BlEak\![1k\iViO((_&0dN^04g4rsG5%FAb6BCNri=pKBT]7B!ie$)[BK?suDSQ$%cp1W`MY3gDId@ERc&ul3r4J:@2=r"j"V0X`C&qc_VI1log1%1BWPtNRV(-E>RO%a*2$h3m=cEZ'f\`@IhM\r]o39F,ZlO8+`-0?3#9(*LJ6Gi=b8=l'G;`\EODC!PinMh=g+e%^UhY]0?qtf1`OQ-Wsnj@;1_A@TX>U)B1B"BeA0m<]+j7D6[2Y-C6ONK$kP&iS.q>K!*gL>%"/>Jq87ShP~>endstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 474 +>> +stream +GasJM:K,+a&B4*cMK^Vs#c&qND["T-Ae;?1i5&&5h+F4:_)*QhHaa_,nXu)6*:e:1rn^+P`(+pY.=m>m0G+j><"_a,J.(Y8FK8!/M\GO$G@s7l+QhPNoi_E$V:ND0\51D+4)1q+YeWn'@-Hf?uj$_!'e)d,_PVCos+hPeCTKKtW^/hee7"dN&4m;6,PYrc]<]7Jd]\sQ'>Frj'qHpNU*25K0Qh!^A@Sr`;ZA=WP0/^88Zr!R=MPan_)QLWD0YB(s-PtE81k^9[-C6[L`1Br>Nq8N6SJU2Z)^.M]-MZ(#6-u[uN'*A+JFCIYU2W$]9)6Xo~>endstream +endobj +91 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 439 +>> +stream +GarW5?#,'H'Sc)T($B2UNhM:]eb.4EDR*$*ArM=#@ad4]Iafc^s*c])AJGMriVRVdP@-ZH@.hbPJ/89ANrb_8p4/M+'$(8>U7F/hF]p\*k!HQEB3Q^YJ<\D#1mu=l3`@@5fjt4koj&p0Rq@N?Ort)4@s8Ag8-6(#5B]6'mjNWDUA/4.j94NUAo8=Z_endstream +endobj +92 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 434 +>> +stream +Garo>?#PIVIYZ:Bl#Z6%*5nm>^jElk0UOL+5>d]CTMStE]"seoeajA(9;%]Lg^kDWYA-mque07p$!8<3sd5rIAMB$D:1BcaDh3HP%;pC)&43O[/-N-m_YE5inCfho7G8_>]he.YP!@g*Sf6N\74XM3BQZsO1fU[;:-^\\]OafCAD#"XeAQ9"'(i2O71P'dm.:#84)NSs>))t([4qk_54=]MQUo`d7)^4;*-Rq!p:DnoLplYgDtru#5B!Ej]r2#~>endstream +endobj +93 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 385 +>> +stream +GasJLb>,r/&4Q?hMRs9>PrM`[g0Hs0W`4\\0oIZD1BjPd)Oj(hH5nk0PQb_G9@c5NR:-A;0_`^&\E167B4)nX%W"6GK.i@+DsssFEZ/@I^)9Ae/@$9S&\(7+m+G_=4jGsOG#S`*ksg@m2os=.42,r1_,rH_HH!+;9K$+V@a:03ME$T^gME!XJA6\CG2TcfF*PcT^sABVa6_"dHM!QnA2aD\>-'s?+ECZ&cPhs]VkfO04*CB2ARgjI=69[/@oTEkKi)uHQ=O9e<9endstream +endobj +94 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 356 +>> +stream +GasJL9i$Er'LhcoMRu7iOWjkE%[g'YdK%R7iPH&O9#`QX:c86!+*G;*TkVqLcb8e[1:VFn\Y"&\S](2YJU*>1@(tYg$?0^m>AR)i&OQN;M5!F,$$pR86XO&^A]Hh=m\n81$cX[B*K.(*LY[\N7."?c2a!@.Ob9o=N24[Z(:dZd6LZjW^+>0nQf&CN-oQ`a5e]Qk;Di%-kap)<.e"6e3f([K]2nZ3e#4>#I=CLjXWES2Ebcs$[3s1XAeQ9.>)dJQGWK\%@4endstream +endobj +95 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[BiH(2_thU94Q"07k'A5YdFF+X+V$P5s1OXbkjSY+AA`)q^X@1N"uPZi$6;ag0fVrXh.$*bGg,n4WZYEl^3E0LiuXd/CUF*B8TcCP+YC!P+i!MF;Ss2Da:]%0MBq'Bqf'd%_^=2Y2O;H[F:9+K.l.KA)N!_HDKo'15o,_G[l&TLbS~>endstream +endobj +96 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<:K,+a'ZBJ='RQo&Ye^f$]p2d*,8R*6i/F!2`*,kKD9B\5D\+?).RGY6]dF!%0I"/X$!/rU')Xk#psA01KuH^jV=)^7@%"T;9k8hl287FW\`"7cuU.TBBH#*-ld^eE0;0N@,$1FNt6()B1M_1[X"i6[?FfG414$N2mPn&R<[>C:0agrJFhFqrWA!$gbQEM!q`JPCl?O(^/5N2+nZ-CkPJ0GAP8j&esb,O_3>8Ns&endstream +endobj +97 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 387 +>> +stream +GarW595fDI'SZ;ZMR0ZaZnmM'f`B(1"CF-X-J_M.>$;te5b%cMc;:RL0pBgjmQ'Gl\\l85iVfKg2&2>A;lj\DA3\DCf4EB7J=#nc\o`M`\PaA$&Pd++`-Fg1Q9W!FHRj\uWjT:su4KP8f\kM8c,)e4FYP_5\-cH"*Ph\R;6elJL>+I1VD=^!e/#mH$XDT-[^mTrW2T-`3rINZ4ENuA,.k:q#W/>nV5Z7H@2kRM0PPZBm?Nt'>Qg8D;N?dk=F5*.=op!g;"E,n<+Q)Xo93J'VhQfRBA1?ZJendstream +endobj +98 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 852 +>> +stream +GasamgMY_1&:N^lk+r]).V]'BNR^306;gm.T\*+q`66/,aB$$:h/s\9^9bOmfoWSHn,n%"S=+G1D1[>"=hWi(?l[#G>8,4E6u+K3]cfd-9V]mSa)$j'%G#LFZgEm7'mO+c#CP":>'!JpKc*e]_7WfJI7"Th_s&H;B(o]%h]2tMY4%B6hi!d3\C%c7^-)<(gj@X[L0f**d4^;>.fCIaSFeM>YE!ogOWFpI-*CkLlP9oZ6JEl0-RIq4QOrS`c\kE60$*-A0[4.t=QQr=Iqb=bDAWb3.e&F"3R931+-08fDK#W@3Qlq`=9G=*X$,_@'Le7+EC".!!89R9?6._nK'H):;j@7ihr/eZO4i4DokUM&AA2;F]<0bo<%)i.Tc:CFS#pdnWK6f2aLF'piiNBTV2.RCI&TrurkJ@SWVYU1T.bqBFkc+_k0V=&m2tj0=LWLoW;^X\V@M2Tg3B]12k*q^@3>%F@'u"NiNW+r\5F#RP[;_3!*8K"*0-gg^K>Jkh@:hL\g%Egtq=Nd*PX8Egc!hY_!0PupjNTXEr1uO?^:ol:`I$39_:Kp\hS65YMI*_Q#HP#WekrM$OR:Wlr.fu$V2'5)&4s.IKF500O*5%o%8eGdl_3ndJ8F:0~>endstream +endobj +99 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 622 +>> +stream +Gas1\9p;#"(r#kthTO3k*aF;7FnMPHlnER`/$Z"cA0G-fOO+,Ra+)tl![>T("toB95$nU%>l>fBNA?#1Jbp/`j8h7@)@skReptm#mf6A/aV6)^d;V-pSE^PHE:#n3#C71DFF#[j<$%]NL<=QHOV;2r"@"hqd#T%U*0O_$*J2ON[g:)nn!!\[_\:$oGRAoY00oL:q.eu_olF\Qr7JGsVR_:7orG;:+ronARJQoZ1Y&%7bUOcFfKWN\@\CE5i9tPjm]Zg$M%OSt,=6%K[[2-u"eLILC`jHtsG%W0BjgZ=gm_nfVI4H,T];FJ@G(SkGLj^4fHYWD!Q1*U@G`N.f^:4kq9kCVn[5P=YEf-rl^7W"6Bl"B!]2]WtLaBT]q&j`LA2%iVYaop'Z_p!T:ON:0jo1>P64fsU>mb>W"Fd@RXKZJUVAjBW_*!gVo@/`.N`E=@U`8(:c_>,h-tTBiWs/Jp%I!VB&=qH(e_2,n-bYd8'p>U-(V+Vci:nP.HsQ\WCAC6;['~>endstream +endobj +100 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 519 +>> +stream +Gat$s:N(h='YjMohIVOJe58IsDRrDO_I+=rR-[/Ddje8H,_@s)h9Yt>9:^s19n3oui;(ZE1k!j'QJ-K3#1pg.BT%r:='EUUP#Q@@1i^nA*O&6_t;u?Xp1miC*Z``/g!NuL\5^O3*Jlt3q%g<^2=fmlYrF%M18J6[b*CV&!fEX0RTL3O/@ohesORNDc&q%uF8b+n:1aBjf?->;YBk=#?j>]s]krMt/DT:+ID^ANR_6@DX#*@6&#l"khG&5(k'4\RISbahaXcR?dGaFVG#q?hm<"okM:/d=^q)4LIhm<4)Sli:mT_[T&KUUO>7mZp1VPM(49hCf"a[b#$3rc9_V_%5BTDjj,C-T"oAQ19*QAMD(de(CA0U#'42'pVd*ghS?K2?EhLXn8ad8,Fn,aW6W.[AgGYKdu[*T=#D,fK>5BQXQN*MIN#Ns?lJ!_^eM$=hVbl4HDL)s:i.PQ~>endstream +endobj +101 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 911 +>> +stream +GasbX9lK#F&;KZOMRffV\!o8^;+o;C=9p2cD-=r[Hf/@rJU![:WU3Z]^OF3P+"d+X;52#&N8Jp;EBJ4)o'0jc!;q`5FPq`56bECP3!g]K5o;QK)r>o&GoP%]ek*K%dA@2H;n?6%d+KBHN_THD20BGC/K&H.=)9t,W&*Q)_.%j?t9_GPCq*^T]7ipTp`Dn983#i(=S,$sZmo'5%J&YitJY19`g$I*S11kO>1YX#TaOfVrB\s.e9B?`VEC%**lFp&4b(_F[to5]M%089g[>"H[L"Qg@]0PS1(&*F:"TK^^cD9+?-E6T\j;VE)e]B^",>sq75p/XLK)hAeO$9fM$/Bd'FMj6TmP&S@t(NiFB+KDK8HQA[DrDKe9kup>tJJ12848h77EVSXgM-ZBh5$2Pft%B8ssb*gacb?`S+p&gP1o5NTsreh:endstream +endobj +102 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 786 +>> +stream +GasJP;/b/B'SYH?(&)8P)]DEP,rF=KJ[DFVap.+;LVB-p".gDm[2l:8fC.Eb"&qN#JOJjGmW[!bn\M!@GMd*E0M:9_`Wn_Y,Qkg=m6bn)ERK/Iq=W$P#[u*G%Yn+Q;UC$Y(=]oa>/.ZC!<0c["eKjO0B-tl2gYP^Iu#6Ho94XC'::p0j4Q7q_"CD7cbDg;(Qr^`T#[%>EHhch_%_mgWJ7\%$`:G",'%g3*):/Zlt9t]*_VW]8tds.W)8\G'eJJ/m?k?\jG+mX73`-U8h4m#GKUICJkOGU**p>&$RN9L;oo;kK;W#e6;E8ses2a'+&M.!$Rmo!_K45!o3I(kd$RG13e@(D]l"'&Frc);6mreg;9hsY?M;"Jt4M1?^l-e)N8K9es1>NhHXTKZ<,ORC!V[d7`4d+6LRPPbXT]p]`D8t/-!([[EaJF[eMB]Rnlu.^9QkGg@VM,m/rYflt'WUh/J!H[J^;qjdOtXY(_KtR*rB@\?S\2Cl0'u'c62Y+r5"j9Gt'dY963pbkKI6,Fu,Q[kErAW$4>]_D0"0$aul=B;RW@X73`=3jL>e4O3V&3fMeDd#ee6aH5nV<(o@]~>endstream +endobj +103 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 605 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW/g6`;Q5g4'F(lQm*]HZP^hRn*[YT9*?Y4CiOB)1kA@th6$NLZ:PdjFnZR%@)7[A.C#G7/F)7Uf#2"+q[a?0jK&m4nIg$'`@DN,!01En,NJ]T[@bHXI!OO8MDk39U5_n(_!p_/:[V[RuAFbOkW7l`$mk?A9%XsG[j$1]\;K+3&([&71k)M6"+XW3.qAJ^1Q(fDBFi0R&DSU&M<`g+-\O<.kX+%uTQIM>2;:X9pKPX4,c>CdUZ#K\-`bF=p8.S98g"_9DLc@BU^!!aNIsD&%8@"O[tqsR!bdTdEhR9iUk3Vl6FZC^endstream +endobj +104 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2Hd;R_m&B^lp062^U'U;eujm^+Rs[5rB?j1+lY!^T<\Il2M9KE(ucmdjq,!@D4'.r?rhWW`S6ZK/p,gL7^m`lAHfi)_@'Ps=<##?@q!3MRLl+g;U*9!W_Wlufl2>Zoe599E"A-uIlnVYm]Lm8nJ%k87\ei$rYT7.0`0jhJ+@_ihMs5^bRZg?EH(Tqhep(On,:r_e8K:8'9o@B:oD/ZUFf0?U(F[AQ2s-^]Xtq&lnZr@>Z\%mb*/.!Nhe^*4.!+I@*@/KO#o7)@?<3`'PnsduK$n5l@*&R2CqC=^##*E1<<V+FWPl`5Kns@2cL&7&JF,/NZ.$.J"^e??>Q"LaWpA4/9(c@%O7`Sp'H$%GTKUaON`r!ECDu;Zjl)(CRDiVMi_YbdF$QrbZ%4\Z+pIs>t?/FHA_@ni-\5DfK>9?(PrLJl%c&G8isbrcZ[13"q7RH8Zlk6rS_JjMT;*2.Z'WrnrkN%UlQTekX\;B@5nd;Vo+.LZ]"4WI.nRQWWhikaYV6jGR\<5dJK*fh,endstream +endobj +105 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1447 +>> +stream +GasIg_,B;Q&A@ZMIG(XENlfosOH:Cp_JWu'KH]4,>SLDp)JmMdE^KKc[p+"qj,fr_^h'RY?U+41;?/o["R^2m"+1R:b?Y+a!5^)hLA`9K$^cW\05!SaE\rNun=i,g?]QoC5PXZ!:Z%MP:PjCufef3P^I)rpJ]HH]nhGg^o)!P!mg@s$K('S0Io;bG/$oLh4@IbB?>l:etItr#_o*YF4@21')#'1j>Qu8tgr4p5S`5T(?&V%lU3HAo6M?R?ruJJcmkkP3HsJRI;l81VUN7RZ%INK-nffPINI`&q,,MD\+f[B_5-j>+!>ETnu5:J0YG'98W'R5,Yj@UKqiqQA>>\c^p)ZEG+BR_m-,`/V+uiF7<7ndMO\'&&/6r-X`s.FW3G%VSr,uR!.O^&<8B%^I==&K,.'XegfU&<<]g+GGe&)R=_KcV[30Tn(J^QYrI,&C4F.URfRc,1"(+5Rj%#]`#d\T/XT4(Q;AAZQ=h7VZ@7ha%I5E@.i.V"XhQO&mhSTpV?9seF!VJ\<4ecl,VR-ffmV!;$uTAeA.S0S_gUma85Qh7Zk$5^)5K0S@"UAZX$M*()<3o*mHK<$cdmOCIF`BGOK$USbmhb0H+8X+l#EQlOH#%1:*P+8EP4"6<#4am**`"JYTapoYf.Wn4)`R*$#H)RL`UUO1qc'j;H'SnNj)=]&_NL'&$mJc^bGg/\K&U+?#+Pn\X#Xi`+DgOj@#D)KhiqNU'mhI/6#7"SoZ::eg]OZLNrcd'elb9%`D-]Wg[Q>.Gq,M+ZVm'JD2%u5FS?>us>db3s'fl8s`#FGF&-qK,H[Frsf_l'9CDRHGfpIk:$J\_$[T\Q8]2\;6?0sV3M(::r/;GH>VurfQ-n=NOP>uNR]0K"0$d#rhNY;'f\AR(AkNZ3+oYVaM'i;YifTi^,fFrsXZUo`cca0jaBAL>dD*3PFF#%>@1SZd8O1!3oj[[8g`_748J-19YYY.KX:[ZkC72u~>endstream +endobj +xref +0 106 +0000000000 65535 f +0000000073 00000 n +0000000146 00000 n +0000000253 00000 n +0000000365 00000 n +0000000570 00000 n +0000000775 00000 n +0000000980 00000 n +0000001057 00000 n +0000001262 00000 n +0000001467 00000 n +0000001673 00000 n +0000001779 00000 n +0000001985 00000 n +0000002191 00000 n +0000002397 00000 n +0000002603 00000 n +0000002809 00000 n +0000003015 00000 n +0000003221 00000 n +0000003427 00000 n +0000003633 00000 n +0000003839 00000 n +0000003923 00000 n +0000004129 00000 n +0000004335 00000 n +0000004541 00000 n +0000004747 00000 n +0000004953 00000 n +0000005159 00000 n +0000005365 00000 n +0000005571 00000 n +0000005777 00000 n +0000005983 00000 n +0000006189 00000 n +0000006395 00000 n +0000006601 00000 n +0000006807 00000 n +0000007013 00000 n +0000007219 00000 n +0000007425 00000 n +0000007631 00000 n +0000007837 00000 n +0000008043 00000 n +0000008249 00000 n +0000008455 00000 n +0000008661 00000 n +0000008867 00000 n +0000009073 00000 n +0000009279 00000 n +0000009486 00000 n +0000009693 00000 n +0000009900 00000 n +0000010107 00000 n +0000010314 00000 n +0000010521 00000 n +0000010591 00000 n +0000010875 00000 n +0000011273 00000 n +0000011865 00000 n +0000013826 00000 n +0000015460 00000 n +0000016896 00000 n +0000018814 00000 n +0000020261 00000 n +0000021518 00000 n +0000022261 00000 n +0000023634 00000 n +0000023955 00000 n +0000025112 00000 n +0000025800 00000 n +0000027708 00000 n +0000029527 00000 n +0000030809 00000 n +0000031074 00000 n +0000031781 00000 n +0000032527 00000 n +0000034859 00000 n +0000036106 00000 n +0000037318 00000 n +0000038770 00000 n +0000039835 00000 n +0000040610 00000 n +0000041623 00000 n +0000042051 00000 n +0000043062 00000 n +0000043923 00000 n +0000044728 00000 n +0000045523 00000 n +0000045988 00000 n +0000046531 00000 n +0000047096 00000 n +0000047626 00000 n +0000048151 00000 n +0000048627 00000 n +0000049074 00000 n +0000049402 00000 n +0000049855 00000 n +0000050333 00000 n +0000051276 00000 n +0000051989 00000 n +0000052600 00000 n +0000053603 00000 n +0000054481 00000 n +0000055178 00000 n +0000056135 00000 n +trailer +<< +/ID +[<23081a92b8749b7b8b4cd0d70c4bb061><23081a92b8749b7b8b4cd0d70c4bb061>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 56 0 R +/Root 55 0 R +/Size 106 +>> +startxref +57675 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_062108_analysis.pdf b/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_062108_analysis.pdf new file mode 100644 index 0000000..873183a --- /dev/null +++ b/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_062108_analysis.pdf @@ -0,0 +1,850 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 12 0 R /F4 17 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 50 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 51 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 52 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 53 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 54 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +13 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +18 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/PageMode /UseNone /Pages 49 0 R /Type /Catalog +>> +endobj +48 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031062536+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031062536+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +49 0 obj +<< +/Count 41 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 13 0 R 14 0 R + 15 0 R 16 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R + 46 0 R ] /Type /Pages +>> +endobj +50 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 501 +>> +stream +GatUn:J^")&B4,:'QYh+--\E!b:TrLXTXk_/0mtfE/2F=4'gTMeSgK^'j.-g!#itb4O6g<2`="d$cc6qJ7B(q;ZpXHmf;Aj#(@%.TDY8<:7:4*iB53QH1#VG7Y$l&EX;BJ7'FUk^X(B!&bNe3ipc\*gOQSnjB01N]=e+C!MgElQr)n)s@1o@eg"C]L5JGuB8<_X2mosf*?b3]aL'Tbj%m_lhJqRX%2,#OSoN&Q[Cl_&MEK[)/$8\S#$>"8r!8_:c^.6mE"d1F(_VT&YoDYB%RUfSL&*GI#G#rmc:9@5pg@4bW_8@s(B0R3`IPhendstream +endobj +51 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 567 +>> +stream +Gaua;?Z4XP'ZJu*'_c/Oh%Ucsr:AcK7O=iRD'Q/dW@oU/FP_u4fk(oTIMWMC)c]1h-=ePtFE>bg^[!if;HbVXRlS8q%Hge$(l*DA/F-kDItV7dq9`X:2p2QNXP^'.;,IQ5dTCH!*U73?3GP(J'F.[?Uj0H`l4.`fKBmi*1PEmCG^T&CmL8B!:qp:=I&?SG%;,o_p`CGISArK0g3f&YC5j.-Oa?8WLW7U]2$Rl*AfW><9PO-l$oiXA?3TY\0Wd_i1+X%jMeS?>R7IH27FEBt1p:$1B%;fj;m?f0:T:9&O,S!I[[qqYq1(b/eeTkr/7T)`2?'Et7:*^VDW"JjNRTXbqLEXS"]dECd_DV&_[D3T;YW,837,OZGUT;*/r:c!gmq^D=%gBGl[G8l9I/,Uq-02G#X.@]d>=r:IR[0g:>5"E3`G(3AW*^\r>b+Lt^Nod15]5lJUs,EB=:PCaDAjOIM#r`6/d)i727YT/R1:Bj?2gpZC%6APUBeJ&[%NYBG"8e9)+)i;Tlh0-Ta\_F)184:Y"m:e)~>endstream +endobj +52 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2249 +>> +stream +Gat=,?$"^\&:O#NfZ,gI80DW0k053d%D;nSfXWfKP8@X8:h*_4/17:/rZ91R&5"\d'-O`[h*&Asp4sc\imkC(5tpq$Vj"lAeE`=5T\atgSGWu0reI*fHKC?W=*3+[lX!kF\\\^/341]pncRJ:lL"FM).Tj6oe+HprDU&Od8suM[l_;IB/[7?qX2/6T=O$AS^E'KoVb-0ak_("qX-lEIuo.R7ulcCSp0@XrTY$.q$4)4O"N%K^Zj/!8\dZWa_(r[[q1?7Y&"?c"o=iNhgSNt1L"Ul%eeiC(U`j^Jm^$iEjs4Rm)j#K*0ZU-#%]pcOD<'3k#_O6np3E%3^d'eG6nA8kgl-D+252-7n+5^I@8B>74C_>U*a@obC-6p']c.D>DW/[%tPF9Q_VT;dC*+F.&_<_?qm.,*,bIXBUQK?nR3"drB$VBq`,Dp,e\E'U?RMP7LKePgH?3IM)1C'4l%88'?hH"d4G9*I3bO?$#q.1T_a]=f:F3EK@YRu7KH]_Qp=ethM"&`[".tog]5WWKUmR.+SBc3A//_OB2T47FC910Qa8+H4g6MLY?1N#c!<>Er1\l:43O;q<[D#"V,=;HoY@7VQA7#?2,0h8s94)V>Z"]pHnb=$$Cbft[77;.:B\go?Nk4I7S03H:2.e].L&iHY.SMIY35bm^IN+A'6TOM1G1>+NcYaB.='`2\7r:3\839t%8hRGD1I<3EGs"%7(Z0(kgHTQ(bAP1cdrM$aIn`"sNIDqQ(s!3t[2ZIpoRgfb=7Hd6DlQ3=T&A%&V"RfYOO8bgoVE*^_0\k%]6(5s1C45;e=43rEM*'(J28g_\DlQaaNm%jA>ZMO;,_ZtRUX`QVO[_G$mG[A'eE0[k9$WNb0]%V3lX$O76F,paG&'UZ]\f9V+c$q2;`OdIYrMU(&&DP7L03o>:h\U4WlmHhOX/pRP3jEqu.LAlhm\iXOap@23i)be6RG;f0g2W7g=bFtHj@JEk+4]l,RF"ikR:c";%VO;-\;^i"`[bF4&Ok!(P$N0['!kDnU<&;7V!I!632fg$e7$<6\LFYsC,/*Z()t!GcQWh:,*]t;ld?lB2O%\[U(;/>"B;^Njf?kUk&c>Ye21p5[AYTW-'L5&cU+b7RHJC&\/P8(YRe_)&p$=V:AVW1K>d"Pcj`)G]BW;N/(<_stPG]2nm2jpc9`OZ('t(BF5Bl@1pS!"KF%/!-EEL,pm)G'PrPdR,G]u5dX!f8jH,rE+":DVKI=L12GGN_N9]:9K#%::KAOZE+aOr`[?7bC+IID8X#I'GaqF.(`$!j.NGp#r^s)ag9#_piN!:dX=eW[c6lNE9H#rP&c&\-ugR*Jo;)3UeW&-<#?ScN&%2Fendstream +endobj +53 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 930 +>> +stream +Gat=hhf%4&&BE](/+-s]SOQ-u$aagkmA*AA9"R4Z`O-5d/[87/Tr!8;c:O5HD.4,ETFg#,c[F+G`;E3l?WdAVc!^H$JRei8$Bf*[L$T^1Zbb*5H*a$c@5aNBoD.(04np/&&+"VX^.B,YP!W2+Z/Rgq,X`QJ&R5Sp*ecs`(p-Y]1)b%':BeFhqTm(K"r1,A/1h`4IeRd_,If5G*"17;AFESEnJA%;U:7`JaF6JL&OpaSVt52(5kYW(!p)mbEeS#X9?kcq!Ne3ppfZ-58:tYm,ONm93_A_t\3AkK_<#ECX?VKL''m-]m^u75fBN(,2-W!-!a9]1'6;gXP,[=.k8i7J/30$_/:tjkG]mU\75H2+&_;`"KNMLW+dVmD]AI#bJV^M9"#LU"0O+HVW/dX`e>:2AJ"CJp8=h/[bhTA1S,Ip4U!.IQ4X^3KG3Z/ccL;7MN`-2eptYW!nH`8[*P)(&4m8+bLeo?aqN)e$Nre8Bh(0.?"Je8A%aNT[5I;8P/A.kPUZ&nKJEFht%IjUSQk4?n//fnQ=RS3uK)Q"i_oU0CRLX3V_kmVodkIJ4]3?Y+(n.nEhWp4MFtT_IRI$!'Mr/iYTh^,5C>6%"8Nn?pHsmKMLl^jUuT!k34lMu?Y:%\cL@'R'Wrr!"bO)W^~>endstream +endobj +54 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1215 +>> +stream +Gatn&gMZ%0&;KZF'Q[3g>AUr5+*-O($C\hO;G4Ve(:dj!g/]be.Re9K5(,qAm!=*a_=Rq$Zgf,];)"$Ec2nhW8!Bk?/qck75MSIuJggBsd47W"_dF155oAG`dqJUpir"M&T9(&MrAE#`k^@R_OZnG&_3q)MJI)nr$Fa_=9,KCH`&qdiK1Eab17DQ-ZSrJ7*Z2]11k7Rf^fr:Ti.';t#I9R;&>-k4j9H!$OVUhdjgZ>1mT?bIV5PN$KI'#3a*aB7PY8a9&pU,F^NO=)g4iHrA_ULinq+gN(aU@V7.H$nPVhMR.H)$+6#t%+8O+mW'P'Lp:mSPB3ZQ$'n!6gF(*UaOXdYV_WAn_OBe-Vts!D&pqI4PI\B`9Va/e07ak>3nhC)sKen[C02,;;?T<1#N@(Slu=n@TRl*XZrUNMg/L(Ij0nXPJ05mq"rP)B[tY<[*`ss?J-X5Y+;jXh3uMNfl"0KS1m&Z3O/Z7$;*\mN/O3:8hU"B1Km7LB08eZ)_+FJWP-^-S5p6MO!=4$+3sW%Cu[IA;(O'`NJ]J[ml6Y<.Nm3Lq?38XKRSm#1]$2.[f.D0X7_<*@Z,@u`5dsUY>:rmKmfT7EKi.XYPB/XM2jBkCVhf_iL,_&KJ@huA[Nnb_kR%k%*.jAgc%tHNk*cs8(a$%Csf7r)/`MW<]9ZWD@;s%?7q)QlEIng9V*B:IuKuWH(_uHKb$@s;?Amk7mQ^]lsq]cL@N%U`I;+i*m>ZDFEPZ@^$#BD9Gle&ISc0P.j1pVbBj3R3aY4tKqP]p.OC;CSBWLrFYe9(;b%.JV+dc]1KN*^h=&mk2s3A>/fLX)aAgT4]t/='1$5uIfP2D$BYQ!!S6kSCa9ugt<0>Rm1jdLDiK2I`ic:,;et*J57(c2>-LY-b[P&4qNL-IfW)NB3b~>endstream +endobj +55 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 230 +>> +stream +Gat>N5mr8u(^Ap1^Z%C[#MlitB1JXj$;'OgLe]CdUNu.^2cg]EG`W_bq7cTM(kK5ZIiAjX'(LfD*3oYm;$'nY."b#TT?U=Xh,>Re-="Ft>_Tmn>Yk6?iU1XrS*hsPgES7Ch*Tu*3c#r-Dp#8:i/tgR)DeaqT?6K]<\FFG/mE%V8fRZGFfbI#?F[b9q'+)4Q1S54c<+?_NP_MHG/d='9T1Rom)N0.JeolA@K-~>endstream +endobj +56 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 997 +>> +stream +Gatn&?#SFN'L:RO(&)8Ph,YFUhpl$]$QBbSPbaQkn`$Dubo.5W(aT+ZS2?okOH?8=,Qr,HHZFQ&NBs4n"(e,('&^obM]i.T_0Z<\oec0Xi-:fB*L'oF>$tgIB3DYhmLTIm2S^(KEA-$?LW,fW0c(%)UiTrjSZ1p8XuDgIJC.melau$?G2V3%*#Mr\T$EjucGUaZ3G7:K"n+6hqih$SO#qB?'8#76*:Huodm]lY!CY`X!..)EA[Rb8?WEF+*f."KT!&bBh8#0T*lqM*=4:n9!]jG:3AO=M'43:fGOVW-cr>:Q@"*8mPui#_?Rf('<@j?^c-&U"@Soo9OEmPM1g7qW9[)1ZE^#c5?0Q9CA5faD@eQ]EE2&+f*(2pNe.n*E>+@R4>7@-YeSM:f82[_jc/9WORIIEE4%7Wa%NhrVh2-EDJ@)482%.!kCLO)?]5%%A)"(ndj5-etbpn?h5W`M*:/0Lt$I-Q*ql4.=7$,P!hKNjta6<]"HA:1c`XAWq/1smCE`^jDM"YUIimo7$fCm'oi-h-"5-e?rXh`?)6+)h(=#f=d,rQoTMZgCFRE-dTem2T5GR1&p'W3\&&\Om(RF7Xk\Do[T'8cVFZ[3a6X(pIY!a^endstream +endobj +57 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 402 +>> +stream +Gat=d9i&Vk&;KZOMYCRX4_PXn(-)DXKS11"4aL8cBs"hU\@]`Tn!t6:LO]Uca^3hbR=,3c*mqW?#tuPubQLh;@"BP3gEJUR2Y"btaKLO"AkWEt70EWD&\YO)h5K2[j=ZL)J[r0'ft37#VEIU`r';f`,O5p,'cEDO?E):Ym(!sAB!cUA*4Ka/cqS4r"YXM$Au*VXC?u_8Y#J;G?n&8RR-u8.8LDubPU`PYXY"*N:HXDsr8'G+h8)<(4]AH*P!@WiIY-"\>Sb84)F1hioL@!c/#KPE=/juWNuqf#,Y2-Q[9]go.!K#Zjtss)OE?0GiuBGrh>RM8\]S<\gsLH6*m*e!?Ah.nV"ObAFV':3XM:UJ^4acBf2C%3~>endstream +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1816 +>> +stream +Gat=+D/Yn7&H88.1&V[*3N9sTp[glu%S9K6n/9qb:B%PM[CoYu$L>(`WW2p/!Frq'W+ScCYWFYecHA"r$sieRl*'+L>ha4C.tapR]`u##otd5NAtOK5POk??0oYrlBfquG;$%QFksE$C6WprrLOq^i;Eu91HpD[oV?ABs*PF-FVt"/F6YAK9H*GoH+BhDis\lt`WFUkg`rc@99A6Ab]H4Y+C)fh2*S&s`+@`hGFt5%5eMjs2Cgq`!GD<6S1n'Obq:?5Kg>c($$O8Y?6G*'_q'dXAMJH51%hiS>8FURq]q&6P!]L"Z&d,iC81p.TS/h@dd!4WM1q.gnm%c2;l=b\#95UiJgbd4mq@n"V;,rob:cVm8;Iku$hFKNlcX"u0//-*?RPF@j;J??H:MV@oDpgQqp]ak6eJ:/D+f.)H/EsVaM\3lXB$:8Fb%PN4:!V^7S_Mp^6e]aX%jYd1aV>YjHa7Dm!?)?e1YZG#Lbojo=O=Zf_=lnW'EcRN.4dmYM46h>$(@tR$hStao/MZ@"$"SRRP`ce'63_r":dTGYKn#^Aa.f&%Bp.j9:r1"7QsuY:5OJ+EX%`9@d`u:s0J)(8\smc@D[7+^VDF@dVJ9DU:O.[Op>h=Xcs2s3@a5Ajp,r]O)J1Z,"3Qb9>e40Jh=>0k_POWSkj$QUB@E5BO*/[\8]$$&o>&/k!XLIQ^$AJ;A>t^5,;;%o94(I_;/ba$:G7N]3=q`T1%Vd*%hjSDqj>%i@tN]n)#EOm+S;JC3)h5;q8m*\hk5tqR#Ib79n6n*]aXiZ9/s'T`9khINAPqC\s*4K9KY,LumW9DF-sN!\2oE[EV]'A>a6CNt:is6:o)i&6$<\grs3>';sE1TLU[fpm0njPlc6#V2DnBf?ugCTV48d2M7,93jNJa[^jnm)=,;U[a]/umr@KlO">DWG;PsIT$O<^)nH>dZ^Ll\Ce9#iPf9?<1X@W7fEf8^?2VBq@h+Y/0Gbc#I7n(-$WhUk]]L?Yau-7Q,Z/6Rb,koH@@GhEU&3?=jt"lm@=l&*8O`Zk3cN[Uc[(>qB?Y1=,4rq$+J&*)9IEDJY%A;:m0D>K'pD,E%r$0I&2"8D9rGTZ_aOA>^Q/FF6JG9O@3&I^W7o=HthO!)&@Bir,l-i0@/%$#\'%rh(B,$maI^L9H_N7a22&_b/1KE:tB!E/#S~>endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1726 +>> +stream +Gau0CD/\E'&H88.0rO:^Emcu#(^t,"&eO49Pn4EFV'keE@i!^/nbRDF;Hhn+n#U@[?piI[%ne&6m^t\Eo?:T0'd#O5%[R0d!3Ya+YT4!]@(V^45p-$_ip2;hSb/B/eQQ"[fkR5aDP2g!dpf)f1(iuQMQ0-C20n7&.O!ajDSW\b^fa&?L`(jiR^)Z\'$WfI>`^D*_Sl.1\>MtC2\8moP/]gCNN^r1[HrqpQjJ$`9"9[j.d:5*n2gdATX#5ABPjSB[8Eh\0gf;EmFN(QH@$PTrJ]'2[!!MXd8m#BgB1n(jWPh.!T`OkfjSWgWRt5\*[@O(Aktb-5WdE\rK(\eAHZ;5M:,;?$[U+%L0$T^$dS_t3/(#h8u@g9moVDXdJQ$[P@%Ap\rm\cG^4YG",iBj;2ECH1/d$/'V6kS"%:!`#R0n+6KI_5I`qRqFjh3$S)r%SWX-Q)ZsLN+tl(k$t5?LTCH]Bs\^#(ceY:f,UU9&oT)nghA(LqXYVPH^"rgZP_q2#TeZ:Nf$0MV1-=C*i,-7_58fb_\(g:5R$7QpdDVO,ql8eC=okL7FKQH*gbPat9V;;QHOl_ppMBon'3)<6QYF(WA($G03cB$7Z,r/gA-N]Vr/QX%]KoP(f35R6nr)6'=nIf)mUH_OGf`QXY)-QAcWn.GO]3Dt5+LG/,tjFOJ7pjEM%OQM[48m6YH^9WM&FVK0pJ$BL(g.:dOKNr3/&hR!+Z;RGKPP?c8Ta=sJ'.NkE!kj\2pF&"Xc4AWT>eg^6+NK[5hRchT@,1\^HTnc&Vl=)/5a$,G01_%OuoN8=g(B[R7@[5+4,[@,hVJ#:Z--rL%FX?4+6;mt%cSr"d"-]1+UP"t1)GN1?SP:D/VQ`cnH+gW[^1pZ]-?_6P?D4Z)LPn-nggn1icLNGVU-p0YM.i90)s4iKkYWrPmNb]&[OtMmdmGS2=[[!7&XtHGP/oe'FUuke"]K!^f"Bi)\b)i2p;us2lebuQFh#D@YrQP[a,JokD$DIb7"fIm46r-[npX\d[9Un(CSk$%H!4/T(1SCX$6hCsKO7.ucH.l?B+)msStm[1B)h`/W7EAfILLY5K/W@@'_jZQ"^g2jh_=X<*rGnZVshA\P^[(fEKC'G;@0lG%Ct"4MIu!MM6T,c.@WiB;O!Rqk%4k\HIEIsASn7!mlrpo'AIG#[gV@UiS!*aGb)l0c>;Mqo^7M%DK(3nZ9U.R66WTD?P*gRdci`B>iOoh4de-WpR&\#;GXDSUb:Y=),doYiUN'oOqX0OI\?-Jp>0+dR2at4]%)j=kV-XbA1#dP=eaBH01BWZ@//EmJfG'%2b0aS#<`Jgl;>01#T4mS11eOjhu5CV+g)1I`S=9$,Ci;TH\t(D>n]g5&#/*q,63FIJSendstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1190 +>> +stream +Gatm8D3*C?&H9tYQq"*o"J1$2O63S%"%1BGD7-Uh+21B:bZ,7Kit1CAf)a!2C*Ca""$)#j7k(>?qMO0Z1nsL:W?aB[H2Y>)IL$@7K;/.492VZUd]O9HtT9PWFmZ)MkdoC+Grk/IfQ*iB*]4kk3V`B#YIHN_5`eKX]01;RueE?p`:hnTNKR?!Tbk#iT^K"T5VROmi]L=WXEGB!HqPha4S_h(ud^GiY3h$27COSL@jkRW2M"a(]<'$*n+RZR`Q!L$/J$bgM`o'up^I1#mp>ndbl^ju)u4LtkUM17qkNI[%?,r#\O$XB[`bSBk+P9@0qFCI,oN67/K"H/L:Zn(KYArjAWRkjWs*:74^XU]`YKlZ0q,('7*Z9`e0(*LmF]Ffqc"a5B?S;$Hb`+N=ubm"$c]*A:#302bpj,GRUL5J=dtdEC1uFLen/?0M6JN9^_,0Rb!9e6&+mKH[)Xed&r%c4=4Ie5];28n?CqG/&!7_S[tm%](%h*c]!'cq'jtdHL\E;HaR1-mFI,'YbO)7E!([UJ$ob!*7+:o/"FC:/'nBgSD[k=C?MKF;8N/W3C+SeKKi=]-\pe7`I/r7*^^I#hY3m,ZOdtbD-j6;HhZeR[P(FN_9i`I%aLH91\/N.q&:?^XE%-2Ef'c>8_)3>&qW:ZW($srBhhSN/s`M[?L)C9o;[\.G$2iL'-?kaq0`mB6F)R>>9(FYZlh:VMc[#N;2rfU[F4M2>)@u:e,2<":$5mmguq8?6nDKS$-j].f3Li@2l(3LP7lKs)2(/2G2:OU2*#so=J&qE)%[Z=G_C6PV]iPnu]4eG+&OsL[dml8]XFg/j#eHB$'Fja`4qu@.+M3I~>endstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 664 +>> +stream +Gas1\?#SFN'Rf.GgrF6Z#[nDqDeU!:8AH'6W?t>+DL;K6`(o]qW;ZCqSIc.nVC5;hj7@9:FZemPbHoMO#ImFBSU05e+k_H+kRJ`'6'ub#3aT.61knm-HZqTd*G^?-d'FhTY+r7.9@qe:>]]SS)]Gl.cS.AqchVSrhM7"K>)*ZE_8@`pI`)"j[Kot6>r:$209@.rq$N-(a'ft6_aSSqBd^[fFlDKFB(WpaKaDZO1bMH\ZeA'uGW@bg-cWNVXF,YCQ#W&LM.L;\.tpUWaNKE?[ZO[j0k"sD3bU!#\\kU/2J$RE-YXsTrC2?&]23%:4qhu9GbYje2IXFdTW$WlOl^3=#!Y"=.HonkaQICeNnq0,S%q>j8gu%P$)\[$44*H",\*('9Q8YLV8?2@$&fr[[7-k;k+,PQ'KJceaj_U?F)sfbL.!dE817)A^"b!W1'Zh9/>SWJk0JY)?iS&'3W~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 655 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E+OSadYX)uU/lfurn#T66E)C3"&*l5sc8VMXTLVf-I(9N8/Inkp]JLu@/Z:\&,*oaX$-=jY5N9uDhpVph0[!:4X+uh[$@nRBoWa?-J)#&lc-$BDQ8>-G^'#PGNRR'EsR-h;mPi[BJb;iZV,sD89>tr.6-o)[IL3/?kR'Y,'[7a>siJRUI=44:-3kNS.g2Tjh!$#_:NYc]VSq-JVTCf@oWgfaJ+e_Kq:L48^4nendstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2245 +>> +stream +Gat=-?#SIU'Re<2+:8NJMFHZ_,`3U#TZbd76e\Do]=m8o[@'FN/U"@q6&6:hk]Ch6pArZ4Sff)[+A"s&4l?S#r(u5i5[S!L6,sG1U56`;'u_ZMiT9=G@fGm"8m\2Mo25gj9?$o;5/S9eRB1tJ28F0M1E>,uE)OicQ7,2V1+UMKcMiqV<2X*S&f'#s^6PWL[]88@U9&*OSZQJrb#o(H6-PuC`kl%F!?jQ83=9GQ+Vr!f9R3E@bb5hG3/SPBa-<>sU?e-NJ`&?l"U[YLR@rh`6SUJ0Y.)6]66qrQWV&6$0k:eNu*\%oX:C2u"BL10cZ/'$fc)`C]ZV$PXfhtj,'0Xp/TFQRhTdGhP.&%_4G"B^fQtI2SJnX:uL4g'A_HbfW!USlV^6kP*5',5Q`F5PC;o_i]6="OHQKI+YCMldTq8_Xbk=k*;=QMM2$:i6H;5gCSFZiRc)b$KYp>h^I])sg-8A*\Ljh_0$8*E$Sl1e/7?/EA88hlS"K#!4Gm62AS6Mp^btlUQ5XJIQM.G-3BS4I=5P/+RCKFJ:3Y@c=L^lsm@+jeGDC[uQK>.81=BX&/sjSiT4IP@LF-2'V%`7c\'`#3DTadt[&,-ub:;%Q7EC]/kRkN@`8I4MFO2E8#>9':jq@e2NgMk-#*_0j')!d=c22Eu:Hua!#]51U+]$k?48;6rTP9aBoV?A#omrTnsWD8A[3?UY)4DMrm$WkWBN1#_-J%5/o(bI?eSPF_k=5[_uSIhg_9VWSGZp22Zb9FLdI+Ec41%alq#R[*SR<*]oWo\$.TfNknU@qqfhhl*<9[B?98^#,V[e7K^-N8\p+TI5M129S*&h?C9>lp'?*"e#E_3IrUk/+o`eYkj/te$jUX?pq*AF[Sj&0T?o&fNlD4r/rbu19=?E"ZY3"q2/^qD6Jq?(H5d(UI*ohgE%IItd*cA=G/^cEfAMqWsNV.6:eYMsaY7=oElFD8p!akj2PP48IrVR'"f>8,OI"+'MY'5/tBBfBG96S$EQh"XsP,0C!0@T#\js_ihoH4b$rK18>:r`R;@Z^:I?"Y[1ccE?"a~>endstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1244 +>> +stream +Gb!#[fl#h.'Rf^W>QcJA'S.f5X&D]C1el?t`ZR'[hu(?R.#/[3<(Lch?nhW;X!NT].BVTQ&gOi$0'DH^gk>lII$+7gaoHln_"9PeKYeo6i`[rck&@^Fh2b)g1C,/n4Ne4I+g)[\E2.Y%*iIrb@C=g,FN+*O-pS8fB6AfFr:"\9a4f][)/e1S2Y,)L%Zog$OEQ]^"0fe0S-:+0FqR$2@qU&SGj/`(30^41*oRZA4=Y'SuLuIOpbkha^kXMm;om1&fqo")&%fZEqW)#_E:L:W>#j'>jG]_IP?l179&+05,%:40n;P6UJg\#'!VY,MH,\g[\)f0e+.D$c#A8>Md-Q2iB=VoXZ^b1]&93_1Y:n<cYeUdM+@pbU`PUK3IZ83G'fB9*?Y&&&+ireehl\,e'QL@ILR=("i',lGr'1XX!07"1Q\\Rb!Z'*"9MRgHtm04Zli^O1;,_/LQgV@RS$,8bi#?-\tR>H(jNpW)[+!5cBTNJS.(KH$m!<;VUbj6iNZac(D2NVNKs4uj7"E#[VUEr;2P.T_uKZ.D;;EmRq-UY[&D3($p5Y)_h]'`%k";)X:GdT"1'.jSlH+Q_rGVT`@=FD/SIeT:\g3G>27<2II'#J$tHC=jt3%>6d=_u~>endstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1167 +>> +stream +Gb!#\D/\/e&H88.E@?J.EZ8"(QYAT(.8+K:R%Em[As?C^t@7^ah2'U"8sBf\ma![gft4D@*ldRqh_%gCt%H@5Ug'hg6jO`bed%ZC50Nh)fX9t;]@.4PE.nsVL@A<=tF^^@WPnFr\7CG9P'6#,3]/&1kaFmKWdp72S'Nm:pG,>2Xqgd7=dcq+T1\l!e/GkbhIlR>FHrOQ^P%)JW)^Xl<)/1\X`;Z_2Lj`8m"eqSG!8`I@.;Jm=1LQ5X%\_oqEa^euP_qrR'RZCBR.tnY%d%aHrBBea$;k1kb%o71;L@>ntXuPn>'HT;W-`^5j5h1i+?&2*Ui>)dAS'"3h[Dt>nE0S!jCk^7e``ShcWV],5TL9)?POd5VcK0;7Sr3$B?e)?0s,*/%4tJi0U7!qAHh/rgpr;9tMtUF:)g)0i&Mi$]F177=je_87S,dXAKsCE$8d%Hd1[.mDKM4\.3tF?B?jG/,n#)t.+NEcQs2/M81:r$h0&k@6-"Zd:Fbk,_`DCiq"Qmb%]k>fhsC[@FhZoXRBLC=.9+B1L/ZJ(/;o>/7?,QFoC(#+u@n+`Z.bO'7V/&445V4r$(_2+[2WZ!ZKHi(hW$ljpQtjL%<`6tX)CMB,D6l9i-?)F3$16k.`2F:+(Eak*c9,=mG4^9^#F6jnkG@QA^TgB%&O>PI8-7-sIahYdNU4fnoRFamV<]Bnk.olOIgJP0fsqhIZ>+Ulc3D#RcYg(kK8HMCG.]#:>6=T[0LLn]_VT6*"BEgTkYjT\YdN@]%G`FrPSZ#c]04BEp>rTh-`dD3/635H>e#(uXq8mQf)%Rfr&]8+G]?o>DYP.Mico1hT"k>pPe&4L36?,?slMPRBq_[-lCdQq=fYq+6-s$4)n\@iH@Y)7aIU`#4fjOt#,(Qq*dY'p[&"g1OJ$7+#0&4q!5"uimOS&?u1hSIlXh)Gp4~>endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1130 +>> +stream +Gb!#[D/7ls&H88.0bd6NdZ_&MHL9+4>Y)\-8p`;[(Ot+1.sloV;Knr_jgb?IOY$CjfTM((OruI0^A4?;%8mt>J\ImsD%=BB,?@m,CucsT6&q1=n1#\9P279A3uQoPdq]#V85]%B#.HcH&Yd\26abHS\G;u\_qT1sc>30N3O#(7E[/&S4ml&d5DVI$@k,\UXqLM"?jXbDRl$D]%!'I4a&\?-&BK;ah5A*!Chu,"Ad*@EIIsj&'ldq1it>RU<;_MV@Ii0?q\gid"q1ei)M)i`R2r;YYfnU\*#U-fUG7\>#Eai14#Hg)^d@b#(rZRIEZ)j/kkQ(7]\^NHgp'O[1Q!3/g3kW/N&`PM8RuY>IL7D^@k7@b0ZbJd9VPDQh2MW"G'?#PXe>'sdfe\[;^mmG`eu6@UZ!U/T0^@ll9CtsUSRY^8U.$iokHJ4!jg+/!q2VeF_l],hra(60)!^;Fc]Nu@5d?Db\LfdCh"oc2G=tRo-aKufQnKj"G!X4I4&#`EU<`5]UHIInf\LTu(j>X]uFPQ~>endstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 934 +>> +stream +Gb!#Z?#S1G'RfGR\>k4JU++90d\.fn0uTl=#*cU2G_qW13,rOlCt$=Pk;mHM5LrM]JnPlXXfq1R^%_:]/i`WLgG(8\hFukkSI;S*P8rAn%Ua;XB9U0V^g0@J#t2V^%[(g`.g@XZ--_,pM:OMq,a&S+2Gb.kbdC^:iS[*N>D`0(85/lu:/#g]'p[34l5EEJhURc=279kbh2i"p$YbH>f3eERIn?7gkE6@B#.C0aur6):&p\K,d7H.&:%V7'F-3h(4BJPV$:pGuB:=^`UfBl@_`r:V7W!cDR&i&F_sn.q&`UbLbqWm)E@h1,SS)jugBLdLQS,^a^VRJP%@:bcjb\2de!tce5X\:@k!QW8Wo4Pjor!N&,m3PR8jZU-][_,ig4tQ4O\j'K7q=2<5rMQd$XcGt09kV#NLHX9=\Gc)bjEF4RKV;sl&"]2KUj7JX.C2?(H73c#Tlm*Ifs-K=/Ych(,$U"ZA/USXdnroVjo)5+X:;!dJpQT`$*5La*3GEM'Zd*XD:KG<(H=U4omT1k"-+$phLH53NfFuQ:qedN@np=jB2S:Cm91;=pfo6MIendstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D,66#;5k0p=:)&fiNV:Z40D;YVQJfN>^C7;3Oa]SpSoY"aWicKX,8:^Xa@*l29TgCQElV++[RjTW6/^qRr:.b#N:b_[1`>%8^eRS0=fTPoo=8a,nTi#"W<)(;862g0U&PA#C>j-Iucg/mTD%(5%U0.K"=RODe!`5m#3lQ$h?`qns'XU1"IS>Z'[!f/#FL^X-j^"i)EPQPYSl$'9B<[Eb:`VKs<:dj.H[>u^_uqr[/6;e's"PImEA\OFGtQd4e7>.S!bd;0!Hndk%#WA)"KZ?7L'-.Sm7Osf:YI&-/*pt5!?pZQH&e'gamR:Kd"@1A?"#&6@/f00hDkK;k>)+9t[E/?oCc6a4O64OlM[@gp%E@7M=Zg?\)fcidp,FMi8L%pZWt\>A,>n6g?9!ZmFhXPW<$7eQ%'iioR2dPJ8LL/nLA"?'i%">L"endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 884 +>> +stream +GasIe?#SF^&:EYBXE]T$;SY*r1fZ"_i$M4oWbj4co#kG`E2e9Kgmo+QWrKbZ2@uAk,0T\4GBRT]Ao0mS0=uHu.DSp`Xm\1#*=*EgT/Fq;(kNFN*btDGZJ1$"fr&GcpUQ%br6R&[aCPgcp9#D;;f'tbqqSRDZqVdgGPZkP)1ud5_!Pt):-9@Q5FpbDl?I82EsGGBJpRbe(sX4J>D*tqc#1dY:R?0+qO#.FdQ/JNB6;u#ad7eMhc<3gKnm_S"D020"ZCRd6d?f:ZU2Va*9ciVu>RFpL:7Y6POl'2=i+]pH&I1apg;7$CR)8WnZ0.:dbbT`d8<#9J0%IJ$LI)_KZ"\D]@\70N6k\!^k5-ftoGVZs1``YnH=QDS"*Y;7K*MM\>6Y%11a;?ZU2+3$LfJ8eIDsBUdO@6iL/3o)P=l^&$LaFHKi$t"%e-=FP^Jd&bm;J6(47FK4S]1PuGbaQ<*LR)sGc:sH_TB+9T7\16A\o8q%lEc+3A$,@f~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 769 +>> +stream +Gat%!d;IZ'&:EXkjpd+X?lF_E<@XgO84\ED@.gAgiF3S4eip]i7oD:g^NY)1!`c1U/!tT6t4SKl9^uk^"^'Cio?k2Y4H&?!c?;UGtn^`u]F'Nt7oCIn.)'ep,+l8OHm#7&],BKAbC?J9-pZMblS=o"%nH"'/-qe<0JMAZ1R+B8&69D=$&c?Tjq5;d3X=9$:%,s+j%fJs(:"0+LZmp*V)jDTsb-+JS4Un)E^/Wge9AglQer"kGQjk#FsO[j(7Jc#jG??YERJoq$l[#Y1:B@c(uV[>RnrsS,X^>b/K%HD2SuhD7*X>Gdu`Ej^$*;NiPreapO;MDT<2'ZHem,bd)61iG6nG[5tE3@?DmC\7,p/V9c9-SPB*Il''[1(;-d5I5]MlQ]N*0`@BU9o?b!m'K_]OSWb%ITu]dB(RDD$%coC'KJDDhbkOYDOendstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 724 +>> +stream +Gau0Amr-o6&H1J#ikCOK;]m(^b/C(jdOe\RFl9B/o#5_]n<@:$9Gs;m^[E./92IuSXck&(`:(COHZqA#FD/5(/n0?P#42d7gf%U%E4\j]fHke/jQDA(,5VI%F.L/*XPY6,*>$3'=6]C6)&(Kg$Dib[l4clC!8&guHs2!-oMVN$88o"o<-M65Vc9YtX*(PmE$[=HKj;eXJN9&/L99'X"i>_("8f>>iB[1ao8aD)GD+'3Bi_,%A%L/PqM+/K>or_(Pf)[D`hA,b!`\:2bk2nbXpd!^EPh\)o>@;`M5Ml<"&g$'E>/g0G+-5HH9TdjmqUK:j7KY0LM(?eOO\(tE\^YabX`h)1S8>#(Ri6[7':d5K_ZlI08p?4qV$=?1@bJLj`_5?L\$PD9prgU.WV>6CDIECi)h5ToB<:sHG0LDAZfE$H9$gAjR+8mQIN2iGc(%N`KStX>nmPhn_!Um4M_i$ID0usYa1ME$.K(cHV$/5r!>/iQ2u~>endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 675 +>> +stream +Gau0@?Z4XP*.6pJgfs#"!C7.XVEHU;)A<(m1@9c3/,:L$9k%j!<)qK;^0_:aaVI-gR&i]5I!<:dg[WYMiOO/o!ag=3`u_lOr!6W,d=FO$aKIbV]E>Ika,S^7pMY@`B(,q%]N:A9Q^K9Y$_C:3'hU&:F:@s5gf%R,]cOlo*C5=S@?jV?UL)r2/O`tE^uI+/@F2pLoD$O:I;J?E*mO1&;5fQF:A8Qn\?-F0=$UaSi$P\88l,-o&IX0?&=?XMjh4I>MfYoM9SM8a*EQ'1HXHr)=M5(UCdNMaen(@n9`bDE+>iVn0\bBN++d^sendstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 680 +>> +stream +GasbXgQ'`:&;KZN'Q^gXm3,o3V,oodFt8gnf^o4G(Toi6]M7bN6cr$jmS'-fQ)o9s)+c7GQl.eN\K1XSheI%nhrW'f:6"_lr4.lj_TTJ*9bNk661Q!aDr(aqGVk+uV!t`/Al0rE`lL,+:*bsJ[/=4]5RgtB)T4a(#T-j.8DO8iB`1qGtJ;Gh1<\d$V@AIEb2GQ%YP\dQ]]eSZKHJJ*]XKgd0ncF.sTB'#I2]2RW_3]7`>;m+l"56D$$I8q:;&sn)QDXm6'9QVt;lBeaE@s8=&4rh!%.ED!7FN;fW0$F(^Z.-^%YC+4TRhmV>AQL"j6S^49rG9tQX6.jqH7Vp(m?k@9Iir2>>7Eh#EO"BHhOlV/d?h\G)njV:iCl`64Gq$#WfR&8%Mr4.pd49OU$ZN!(U$@.SX7ZS>Vd;4(m?-H(ZI$=m=)b7"2\Q/l^%599k/D$73oh9q0MR"XL#:]qI+E46$=n,b!EQ&>m6R"E[8rj^-"'^0FC?>.uh]BKP+D99"QKHnn["OF8:;MoTRU^@I/".h5jUH17@WLNR(*'D"BsO06Y*GuDe/W#'9o_$Z<4FL*;o-.PB>72+]Iu+7oaes)D[Z~>endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 445 +>> +stream +GasJN?#PD8oChDR#,DG]F'Jc?.(F=,fE8\egirT[QS>2c_8<+qTasNZdII0tY6\,nVU2-)@dtbi;e2l54MV&ijWU1*8$d^u2J^*qN+#=,R?2+EDSd+kS+V1!oF_dBmfD5H]a(%.amq;m7-=`MnuTircG1Ctd(-G!)@Lt^jd-A'/n\[uVnD,2b7i5,PfHoQ$B]drc$&4n$t-tF<2gFlRt;FO:9t%"mIKo%YVm:4bk$G0hZ4Rq$p]*:lXjs.:",;D>\Q'="hq3(.c+96TV.ihLZ(%t`]eRXb;C&o:/kM4\9Bkg)_r^Fg"S+&$n%'NM-L*Xqda#:O26H/T8=r'W=J(73bK'~>endstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 469 +>> +stream +Gat%^>u/amYCjW!*]M=eQ]gU#ZtqJ,6qf3LMj.qp\fHr36[+YDTGi&Gf^8)N0ushJ93?BiE;6U"TpZS:4SFT%u-&-(cK2N4]INAK0(a8]>f\jj8Y.Gb'#jk^&^N?araq"28f&@;=39)hbQY\!Kl1MK>e)[_Uq*T'>2B-/'R>9Pendstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 385 +>> +stream +GasJLb>,r/&4Q?hMRs9>PrM`[g0LY/<%//k@hr>gB*q+R2)^0Zof2A,PQb_G9@c5NR:-A;0_`]s\ECAM?sk/Q#&H79Ju;/L\+SCYEZALM]Gj8d,dJFK&\(7'in7X]*bQEB4":@PoqTBs+6;V,N6`S%0K,CE]4"f*-*&m=1$?Y.6_)-[3hPS:i,@Q*4a:]$&g">#n-`j\1OJfe5Rr,28IrPq]i2C1>`3X+Q(C$u>M.L&=>YbIUI=A5>%%h^[73H:UnIji`WUuL!^]N-)B2\>*rIendstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 345 +>> +stream +GasJL:JZWt&B4*cMK`;g+K_,ejb?SF&d#StK*O%t.p9b*/_.dXmnia#*&NlOd!>*)Dh]F.@d\[$"*YA:pC*!J^4Is8-"I$"]ap/EP[T6,htg3WNlXMG^bngOOdDWu3'$_t`PGSb((\E\`E&ciY=^L7`CT86BiW;M<>8mE;.as9QgtLS%ItDFnQ6UXQK6(.!dUH-^o[>-!bT:\3ehX@ig1o-8WLGcUqO46mlG#&oZMTrdrn!NS*kXU%C$l;No=f7k_Y!:A8dqIBCc\`%&]\4:8ot"R3;<'VJ4T"i0l@FU#b_+St[sA)XKjlp0.DFq[4\HS1K<(YuV`*;',-8mfs^-PLT~>endstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<92C1*'SZ;ZMR0B:.YFNnFqgVnB$IH2`!F3j[-aX(p!&A+tYQr.+""N1Cj"S'MrkQ32UhAgQ8"sF'JH5q[g:cn2J>[$R;%g=U/)#;S"^cS_@mR3jat(*Fl\0T2.Lq.@/hDQqhGPI)n4@ZIsS(\_KI?@Y4l?CLAkT!JJ3J,6:_=`.W":&i0Dn!a$tNYp#CohtP?611uB]8A,ha;VK*_6k#Nl_A:TMI^`4!].@Rnb0TUjWBtqS(I3Ct3Y0>K(=u+_*k/5?5cC_:endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 387 +>> +stream +GarW595fDI'SZ;ZMR0ZaZnmM'fa5X;"CF-X-J_M.>$;te5b%cMcCi_AQq:mEpRLiGgu2Z+nEs%E^__6_E,ZJ"")\Q!L^9\.Fp:/[*>a_n*4YF3WuPli\q/WTb0/+Nb#kYl'AV/9-IY8oFVor!@Lg\U4Y4KqZAE/fZT+Huh_Y=W#"6*X^=6a&LD4CRA?VtZ=@s.\4#\P(TgCV&cG'dt-7/;Scn$F3n]ZdE.HqDFmSldrj<7;*93J1B1lC4j4OuH0BV1GGGtT'mC/6U_``(&irQu)97&gSnAaoFo[WPWBedCFB3`(C@~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 851 +>> +stream +GasamgMWKG&:O:SbY'7[WEeqh(t:`Wa%;B.Fq%;[aY+T84'Q]EG*b&bqp'5e0lbVK_#o$rcHJ:)X+Q.f?@9Wn?kU9,>93?""C'6.]cdM2b_",]8$A#o(l[FH2]eGuN5,Ot38hCY`p1Td(mn^253Um'WkP>CFoBuME#*NAom7)EWU8CQa)utkG]n$j_iKHM^n0F(q]''_NO43]d`W?kn&XqaH%0mV[-a!0=du,Y)C2L/mSt53Gm9@=_a$80!@%[L7AB"1?+hUM\dHS>NW.gjJFFSE9cG-Qq+.Asf,%XOEibQJ\hNuT^%(%eBc0f[IGYBJ5KZX3n(Lc](78^[qulh%U*OZU`#eNs;Q`(=H\(JUs.u&(P*eA;(aXbqZ3NH;nNel!^0YKo2WG*86`M>p!8.<`co6J$H_.pt7#@:/)UYKHSu'>#e:3cQP,eB.[HD1/#DGIe)6qEmcpptFpq$5@H;LJ.+@5ms4SC9=>,RCc0_BV4:B6`lMR_JKQcX*57/nEAa,/e@%&:)!N]Xg6YYN/jRj\EZ6\#tU?*t?=U?<4J,fCd(uVCPlg-oP.omFHI9LK-E9gTlPr,fU`I.bH@j9ZVPB,DBdVDsUl:>&UPraBi0Cd.n(J?/jK~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 622 +>> +stream +Gas1\9lm$_(r#kthFhM64]m;Z[2"./b-T_\99!U"20U23k^np.M'l:6fkk5a9f+IJmTH^.$t%O+UL%k+kWl>Mid+I-oIUh#**uFFVC*^'@[mhO!8srX%HfeNZ%mjlm8*k^r-^no2\YQ4`>:@ITb&l"bZ*"kZ84_Rm_``%P-@G27M0.'p;PcC-qLAr@&66E].ndj:(:foA::Cc(TE-!/?Weaj'klM4%\i$h_18QOkmm8b0oO<[4CtB(m4$4)qnop9hR0U<:h^Eno$(STa)Itu7*W-5PtJ7Q\aG@&K#(n85gT(sJ!J5_6WGH:40,g,2,[Tn;F0=]h^#=QGo1o1@RF<$~>endstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 519 +>> +stream +Gat$s:JZTs'Yj*8]SjlggSBA8\8=:d%"_))9=tg:=d;j#l_8iS>K.ML;.CMXo%rhBqhi0c$e>8n%5>b?*[!]pi$Ue`a9EX$%/4(TW'S!9\>D.S]Wn@OWaXBdT(`p8[;r-RY*G:ZaO+1gTp>Jrlk7Y)#S=T;+aAef4H$B#2NHd9NisUnLU5r]1"?(Li+KisZH?=6h!W`OHlO+:1AhNhVRKD?Cb;cn76K0roCJ9R0BdKRgC,P&^j0/Vrn3fD86W>+Ojh\Lpiqp6+QK=Kq.'oIO,/_g#QK%MZ8q!e/"2"5>O/`)p>IVnIuS9h;]>I)nmu"I4pq.#JO=V^omBnh$&7gTrQE4gAHr7EbUuKUUP3Ne6a0bt*Jp\rsF*P4uOBG5k]`:0H=c5Q0t^eA#Q@/#Z]=,#_'eUtIC'_+^^0[$4Apqd;Ge(STDf$Z0P3U@/B681E(3<%<6*SfBI3)o>Tr:Is[sdHW>F3^Vl"*tQ;I"dYU$'?4cabp.u"(ZAEiOo~>endstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 914 +>> +stream +GasbX9lo#B&;KZOMS4+dZmDun",,omJdJ"]6G]5b^dZl`0gE!`[kmQif65HNXAh!N6b)d6S.]\U;<;ZofSjb-f;.+[4PUVMgde\Q+V<-?5.Wm:NK(u1(dFanP,mt]_,jS*'or.XB0[t!5)^hjVm+UkOP;)%^i+T)K'="E2f>q\TjcK-ho0D9:njmKR5d7/au2=,u_FcnG_@Q.uB4[)jUot6RR)'V+Sm_lXON9cQUK&JCN)\XM>[cE=HE@2d"d]R*g*2eBSqKcO:".r>pbTVSa!$^(>AJj/BYtTJ[Bc/#`V&%NdbY4>>>k,($tLMjB"/O/gB9`X^?3sM`4H+*%u,Ism.^L0g(]l)1/ro3$&-q#?.]HJYL`W5>grQY\j;IU4(oK=",>sq6oPOWL/c_,eP`E+M$SZh(c'*bTmOuQI=@.cFB+QEK97SsFiP2+e9kil>t\Uh/\X.u"^.F+WARc.Bo&PrPft&-9:9h*3\"MJo8'4acT*C-PjpH.N^Dp8;'RC[LjEL@r\c[rb]gsFf3g_S6(.)A'2oA[\,GtR*i1EYJ:VrnN5gXN*4M):,8^7o_X)^FRfSYTPgO.+]C+d,dBD?dF^D4CMrcTQ7GX*BTbmA6R>U6/k?\QBKKS8OZunA$;Yp>Jrendstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 782 +>> +stream +GasJP;/b/B'SYH?(&)8P)d8_a[Xi*F"k!_aap.+;LVB-p".k=>g(%-WlZ_`l.9&PIJOJjGmW[!bn\M!@GMd*E0M(-mc3HRa,Qn)3iX1hT`(B:*jjuT3*eZiRU=\`*83mWT>>XW$C&Q%(+D";S!VeV)/+BW=HP$dPna$:(IhG'Fk9p4e7kf9`L9kU,JD7[]SpuIT0-oGJ4c`,'@XS4Fp4>8QdPp_$C5`(H;*(Bo"u$=U(J!'=1n=kT`Tt;G7rE#)+#oCklbXC_bW:N[X2-5\U*$78]o`~>endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 605 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW4(_);Q5g4'F(lQm*]HZP^hRn*[YT9c`4s`GA`3:UV1D^Zbd!/5).;4`gI?ZH$'l[Wr"U2rK`r7u^(_GL2_*B`MIeendstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 864 +>> +stream +Gas1]d;IYl'Rf-pmRnk;WAFWZB\sZ')epf?0MRi/i]%b62R1_H#Kjc0f7k&C].+/>`93Y;NfT#?i[YM2Z2jYXK@B-'i[2n3&@WTqR,,Ve)ecWpmqg6@]+#5j-AORY@TWj[d$CudsA`[=AKH"hkMH0hVkb'C+M$u[YZuUnc?3HqBOW=DR!SS"H'7-i59+06i%4kG`CP7k0`72uE!WIpjRMg,n%]P!I7cZb4pnS52&YD6YBnCCLGqAAYVA@iV8]h1&+g:nK_OF[@AuMh8+ulsd#g>jS\2*\uO?kNoH$tQdAZ9XV0k0N62]Ej*:)3%)qa?kl.YO)nM/b.KVJhH#CcmcB8*#OYEF\nd7Rk#V'Baf(rG^JBA>U?!/)m/I2NWQn@J;okK^?,d*ISB_g!p^,/F^IC/gQQ3]o2N2EB\Qk[^hME(PrLdoHbr>dZ3e`ZQ8P:!<_XUOt3"fIsB\^iYqD^-1UIsIaXBOqY4KPNg-mmL@Yt#3a@WNi]RhlO.d%krLD.uV,JXQ71nTQn,!F4f;-9d+.P2"$"jI5K;029]@]4>j`gj)*"CH.64hG]S=96liYP_%V>PC=K@[.Y'cs#d7Y"gOi$GQ~>endstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1449 +>> +stream +GasIg9lo;R&A@7.oOY(j*Q$G=$%uN;OBlJ?O9sdu>_K63Rb3cJaUn0tDmsPAA&>#i^h'L[?MAf0%j$1IpD`2o?UOU/kCXjAp]US80SFBGZgd>Cbcc5N`\8<;%*%>n0js'c%jZ\RXP#h.o0l/LS8^AS2n0*qTRE'Nj`-=dZm[mIfgFR?!o),+H5DR-[^4&noF'_kb%:BC/"hmFCq[Q&Y+C4CljRfRc,1"(+5Rj%$lLc)[`/XT4(Q;A;XQ=kV^Z@7haWHIV<]O3S/*(.5ihU`cKS7QG.eP]^.7nZaO:>/9rYjLDe2L"5g$c@DtXa^'N%RA-hk>1h]f:6<5K$^u_L93.$>pL7]i^@7XE5)5?)QLfcqIKOHG_P]ie%o[,0DqB/t,<*$:0gD%hGTV;<5dBDA7'KF;>a2jcMUD[\/'VdfQ2g[-+FD.1(%U*2=I;k6La3:j<]W;nZoBs!D<^ijKf7fFKY'CO1^!BLd%k6,-UW8-cLO7ij;aouJp/Zt(*k^&te\$$R5!nb9N!78]hFVOlm)(ZuT,!];!l-B/q3aQ79HV!68$DE-=VqE)b:9EZd'"9Jec#q+(Ppr,kU[7'>D_csj2%n46#Ph21NW~>endstream +endobj +xref +0 91 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002103 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003011 00000 n +0000003217 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007543 00000 n +0000007749 00000 n +0000007955 00000 n +0000008161 00000 n +0000008367 00000 n +0000008573 00000 n +0000008779 00000 n +0000008985 00000 n +0000009055 00000 n +0000009339 00000 n +0000009687 00000 n +0000010279 00000 n +0000010937 00000 n +0000013278 00000 n +0000014299 00000 n +0000015606 00000 n +0000015927 00000 n +0000017015 00000 n +0000017508 00000 n +0000019416 00000 n +0000021234 00000 n +0000022516 00000 n +0000022781 00000 n +0000023536 00000 n +0000024282 00000 n +0000026619 00000 n +0000027955 00000 n +0000029214 00000 n +0000030436 00000 n +0000031461 00000 n +0000032474 00000 n +0000032902 00000 n +0000033877 00000 n +0000034737 00000 n +0000035552 00000 n +0000036318 00000 n +0000037089 00000 n +0000037625 00000 n +0000038185 00000 n +0000038661 00000 n +0000039097 00000 n +0000039425 00000 n +0000039878 00000 n +0000040356 00000 n +0000041298 00000 n +0000042011 00000 n +0000042621 00000 n +0000043626 00000 n +0000044499 00000 n +0000045195 00000 n +0000046150 00000 n +trailer +<< +/ID +[<956edec6cab034f4d8f3eee3127091d1><956edec6cab034f4d8f3eee3127091d1>] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 48 0 R +/Root 47 0 R +/Size 91 +>> +startxref +47691 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_083336_analysis.pdf b/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_083336_analysis.pdf new file mode 100644 index 0000000..91877c4 --- /dev/null +++ b/ai-analysis-reports/repo_analysis_b89494e6-2a6b-4749-9179-de1e0581cd48_20251031_083336_analysis.pdf @@ -0,0 +1,328 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 9 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 24 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 25 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 26 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/BaseFont /ZapfDingbats /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +10 0 obj +<< +/Contents 27 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 28 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 29 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/Contents 30 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 31 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 32 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 33 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/Contents 34 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +18 0 obj +<< +/Contents 35 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 21 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/PageMode /UseNone /Pages 21 0 R /Type /Catalog +>> +endobj +20 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031083753+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031083753+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +21 0 obj +<< +/Count 14 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R + 15 0 R 16 0 R 17 0 R 18 0 R ] /Type /Pages +>> +endobj +22 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 550 +>> +stream +Gatm79i'e''YNU1]OQ/nC]*OHf\EbDfLeDC@Nf`K6L&EI8CH3(X8[J$CrmHD\.hAP@X0a#B&5asE-'AkG1eH/;jOQcIWT.2C>1acT1uH2ZDgNE+EX]GKT^Qk:>>&Jl\pJfWn59n)&[(0h`YW\*.R`<@M)R&:iXXA0.]=u]4(GCQb(_u=2'3?UDbj"B'lU5CX;1!G0Hi9\m@>bfCUT'er=VE(OGTfQ]35$HViJi;2lFgcFRV)oh)^=4DRd)?F?Z5Sfi/N44i])5>^#A2esI"n,h'P#L3~>endstream +endobj +23 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1250 +>> +stream +Gatm:?'Eu#'Rf.GgkU'-VN#('j,^oc$/&s^]CmeB\)tN<9,oc?jZ:UrU$coCGEK6iAO3GD95A#DO!oP8V=-j>_#O);Wn+`"D$0/DeWQ/2g@/s^iE2"b@.)HmmGj*-G@B>bX#qmOpn`/9l6AcXK:a%AroWBU\M7h1W;?2XQ!V?%1"VLjEk7g0b&0DEb@/+u<@FH=u1EO5*-T>O+hG:&QYU/jUT;D9QN4O`e;K@NHLrDWJW*-C[UCH+dn/KC=8CZ1_iV^mG%S7ArXQ_g(o,X(%a=Wt)N=;%[`O`o$8gQB_Dh1QQDnk5c!L)"3VhEdOmT6naSh';Dl\/4o.c:M`L-2re8r6HH?f58SQ)U?IBT_g)'P93cDdcT-&hAD]EjAMhKqE*W$+U19'K?n6'<]oN7?l5GEl0*In_4L72Yln"oRG2-Zs,lFls6?r(5f!==`W!u_'#O7pH?Ro*ZEI[`M)=C+&I`;e/iI:3-!l2&N.JRfPn<1R3aq6]XB=PCC5TGOYIQsT;&JVf&>ESo;IKUSi8d8Z/aK=`T,Z6_&KsD7p9Z]Z:Rt>PIW^!Ku!Ktn80;5f$E0H>$'f+Am.>=8Ut,7qLW?%;9n,ujES\t_R/_`/<&Vl::6pfS#/=R'\i3B?WO#QhZ;60`p;O'I,AY0_R<839`8]XDEI/JQuO3m2>5(b)9oP[o\IjiHZ/qGQa&[UG/uq^g.]r4DN5F2RA5PnS@8UkFuVs%%?;;:XKGM">O]*sBn^r=.?u-DYu]Es/DJXaNS(5&V9M-'>@+JiRQYmr+;!dBf",dYeSa[,&2']oqIOq,,STMri*qZSW/"?Bendstream +endobj +24 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1372 +>> +stream +GauHKa`?E"&A@rkqDb(P(iJ?mS)TPd:;o:BcG:N;7/jM`4?q0i-jMD#/3Y2D&Ol=!-iD)WY[P9-Ji=?d)l+o&aen>qZf))R.W.LHJ61A?52h`YW+`D1i!BI[sl/M`ZOW%AlMd'-tX%'V@/l-J%NS$*GRscTE)]kVeEm/CR<9F1Hms%2(KdSNCAQ3JqE1sIXV?Z=edg=Tk=WH8JUSGR42@@Us0Y7S]FnkKXD5,.[7kkRK>rq3-*gbEY%os\HmTu>\ph;7OA-O_(j=D?hHQJR'M4W`GI0:QiZ*R!Vphq<9pjR9#KFDFI3e0mn:h_M;UV5g2RJsT\h6l^mK<$G&,[@*sr_kr><93&lFPbcb-##(9%3u;V5GV`kF.SZ3(@rSMONJ$i20?!r3?!eQORaQ7]_'i%8;T'uDhb=\-&&pK,.5p9-Y#)T\&J)u=)X(A'-&j\nL?3ek!`_I$(:M>Uc7o/nWYbp=GH2o8iTo([^PV\mj,gh&1f^5[%88()AVEc[m&1$*b!Ji?(S*mj*/8b8Q5kY42FF^D*/<^)q4H'R.Ih`6[UQ't(T9k-W:rgf:=gp?5r)=F-VM>8DE_aU;f_25@%/05.2"qAaNM>/XV443Rho6t%JMi;)NEaQ5."h+Dl6orW:LhXXDO_f)Jc>7ctUoY-aI,M5>SgEG#[e\SRebKM^bnR/]j6MdIt@5n,9WBkCihP7XhEJ)+LcA+I`BhQ2iZW)s`HOeeX=rN?qWT9ht-'TCcb'$%%.&n0KN(~>endstream +endobj +25 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1116 +>> +stream +GatU2>BALX'Ro4HSB&"cG^Y^6]l+&/=f)L"KD2&qq]bB:d&q52-'9bYIZI/F5cI>1J[*%Sk.Bh=8+s`pO4R\/)W36#h`cDFq2gm"0o&&<%r!rsGMp0[$mQTEc\^[-VA7p;PD"D%hX5,=B](eW?^;st5GU0!$OWU*3;>s9SCephO;<'q$Ttl4dm>8:m5atsA2Oti_2Bifhm[]FmRH4il"gErVstkX/0/AQ5,Bs%NUFR-VfTA%n^iQ:q_Ur15k[-I+5pfgT;V;V6TWD6O%@^.Nln%H2a3>b\4Q#k#rjKAA:Z]F,jttuCep19T#D^=cT,V336JQ!Ba3#mOdLThN^qdpl`?.A'LrCENbu%_?KX`^lrmf+qktgr9[I0bY^hkY=2OrC/,[)ulLqZUIKT=lKBcuJ0;2h67'D8=LSEaVk_Q9X0?7V:A$Q@']RocY'\MK%CqVFT3OW14,@gn^KNuqNeS$@S>'[9HekiP#,MEKuZKcP8T$Z:4Ho_r]-=KFYHiVsLWZ_@e@HOa@D)cqCk\N@g0bAdX=F%?JT!-Eef7iJEb!0OGS+NkH%fLSIe.`6jor#@*3GV)h:V0=i)^rqXL;`7kh$>2ntS_,;+e[l[e#IAYWqKFXb8g5gMfj11ho'FeDGQa6j/:n-lK/dm&6$+r9W]5#[8!)&qendstream +endobj +26 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 606 +>> +stream +Gatn#h/8`:&;BRuMRdOJQ!uFs]d&1Y8=OGtc:X@Jj+)@6$I$MW9't*ZG1,2`U68,J+HQ"G3o:nf+Ro#Wm+V(3k6*tT,!\>R/KjCh+=ejroB;k12o>p\-ub@q9lu(`\7t0)p_`,<&b$qu2bm<'O*+0YJ7PlIF)H,WS+n]JFTG*RJFF`I64JGT9G*@moD!h[_rLWKk$@u^qPGaFMKN3B$E/m\Xt%O0f\EU[7?sF1/+]"UF]$cB`L=FEndW[.l/L9oT6:il-_7bRRWq+*/rg>^BZr_coEksJYctMaH,@uDAY-#31Ne:@HI"[U3#b*,!dKicT)i8oU,Y-.QEld(cWX'YK:4Z]jQZt\NT,R-Tjj&rQ`QasN'_X'in;8Bb._#[[%8=LV4UNK.uIgbqgHM2-5:F(T+l[N*H.nX!%M.hWR+]EZl?=g6*LV>CKoH7@F$4G8Ng`.hAdugefatr",2Xe$:4,B#'jK[)B?_b[hQ_:r_NNSk5:VWj(S;WWLu>BR?`i^`P.DJ#Od5kQH@NXIRV=P%8:RCft:#k/K;QS&FIsqr?'`f*L0,=3ji4PZdO*Oi#Vc_js05;YNK3XX9TOX6iHa6!9Y/=c!_7~>endstream +endobj +27 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 926 +>> +stream +Gau0A;/_pX&:Vs/\p%(l.2Zk4-\ub^)9sPkrE`cXJNHfFeMpe!&W?L00VL>[RPsgnq_)0b=ZG(4!2IkG]aZ(K@,A`_dGU:LgVnT>^r4O-gr4)K]khq^GU;K)JmjL?kH0IgB3?qRMd56)n!=$`*5R`ClgK,0&nFqO%TXdZ<2VdWc7s%hsJq<:L+7@W=V6=a>a+C#FbK3?C2<ZIfF%qc^VW9f.DWeg1ElA\RTflE,4X/@`Ze3ggi%d(3r7@N#X>su'&A*\4j*^ZgJjW_a_M:,(_ql:E8gp(,kJhYAn9E#pK4GFXVGHgZVDqa%<*9'S,nRl@VfMEi_X[F'J*VuYendstream +endobj +28 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1950 +>> +stream +Gatn(gN)%,&;KZP'Y&6@@u(,)ih`-cM)n4C46lIdUIn4S`"H'JDN_I^\-,(D,m5XXpd!'kNs5%39G3TS*s2Jo4+r&gU=fuAKVIQu6l9NLq%h5A(Ood'UZ;JJO^k3pV/q.h(Ru8BJ(C5Ep?5,V^T8h;Pr_^D:gKfV0.u[7(9FHF>\>1:jb11BcDW6Y>b)"$mW;+9^.jDBt9T1eV(6tn^-4]&K1=Dgd>Z0W-9cV(tnn\M`X&tu+QCZoGK]]O',8i_\cVt%L*nY-"(oOVKbP=s+QTVHoYY\1r^cL!Yn(&q+q%1%a,hJ30nl>j=GpcA@tlA@$37Bg/RCAAUUthG)*(HnW2L9J4M;se17E@-[@sYkaAWEN8n_DZ2cLCE:-^c%q/pQ:Ns+t9g2s(\VG"Id9ND)Mq;kKA&j+o[,!9UaYZi"df%'Gh8@/.Y\gC7g!">8p$k>l?G:`qXfK^aT2kj_j(%a6!MG>t!aI9C-VT-Ue1ln_3$HA%RIM4ES*N-#o1?,)"aP#1N;d&CL\X`-U[]^*5GoFV^/I=/E%&U],slLSc*GqA8@5ncdYL*/]j!:mMUa/9u+E".?;"SPr'5O-?[i,/4Xnp;@F$W.%aZIk[$$(Or7cro=\nDJoJQE:4ReE?,6f+$q\WTkhHlSdd&CL`X`-U]nG3V3#-K.rrX(8?i<[=WBG*^6@q%:tA?3UkAdqUL-@c@AQOGU:c:]M3OqY0Rf@rP@Y_$qj064)E%>_Q)T=$#9q\\JFMb!!qF.X,C0Qc:[7B;o<,CBTDp&se0;W=4&?8ji-[j03;U?MHJ,.A(19L7j[&Th&4*BNs.!pp<(,JRo8\u02n3*)i^KHJb^1Q#Z'2Bq#B)8g98K1l+\kfQtN3+"?h7k^Xb%0c20K5K5Xgsq@S,U:M-]]^lf.+SUW27qaK2jFimkG*K%*hg3MU.JFPnYHFaX(SYo+B&)>]o#L^mBCaj5D=lG$Nm#ZB33&_`dUn%aN6H0+AlfgU\G+L>R4OVoZB8(K^fHKWEXRCcom6!(jN!IeV"5d%:#L_1uCadiSJIeTJ'p@,X+%&+O,l?H9IJendstream +endobj +29 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1172 +>> +stream +Gb"/&?#SFh&:Mm.R(&6Y2;\$&.o/)_9r1C_PhpH2QUke"YK8]2QgWQar;4bl8K`OX9%lBN"@APgcHJ;TEsr'k?c7A)'u7R/(k*_q.#\KUb[W@'"QuPT+%PDkA/ITP`En_'$2su.St@?YOFkLs)RC!fKE`So5u3Lp)gMS%<#$aXR+4%f_AZS.nlJRI'\]SfDIZJ/@AV<"G9"5dec'/tk&:4>;pfGMLi'FRK^4JrD#D+S$>c5M,5L]pj:V<:+Hm0?N\`2D$!R,ghp4AHHDbsRE"0-l-Q#AsK_`lj(NVCCT6\7sNB=2$L]*[lWmY+H((Z!!4LLU)sg+`^%kmUf6dip$Lc@9Wn,0EpdT2H9>rEM/4+f;-m]c[58\5aaJCDGCe+s08Fum\PXZmV#]\)Y$EHd8ad-V`.qgW2lmDCc4k>oLKqF5P1r1tkglEUO2,qlWYD3iMq&nV4$4;X*gdo'dqG#10#N56lmRFJ6[bS7>s$a7#E:rDP6##LU>m'6ZW0-0&5RJ>CaLTD/&h2Qc6We#q7]`E+c+1(@P=D_SY[9_=%`jOmZ-,sL*V4&Ajc,bMI,QDf\!ZNLHL0a-CYLtlAik7X%fQbo(9=hh&'l9E8SP)"T2A/N`B&d=*$M]hm)BN^BpI\R$$V.r3EmdO1~>endstream +endobj +30 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1267 +>> +stream +Gb"/'92jk1&AI`dqW?#Qi7RTF%Q>4[[8at9!M720E=oKc"LdESm#]n-^FeP58F.l8e6[lM-0;Wgp#GB+Y8&-A]R9V$8q<*>L0oAu$)CMh6T9\j*%'pdcNA[mAe`-2p>$u3-b'3]\7?m1p_?%tg@aWeSU@c-B.oMPUjq<4Z@"d%kXLfDi>JGcj@>gb^#)pL!-/pnSSXS"&mU?l>iPG3S1nsCV)d9ScWc=9/Ib1=QBH)X#A75L*6>9[B,Rlk_.WjCAfS+b0(;peA-J$g\V")-XC[=I;E[\]q$;a0'='l!24S"OKs-;iM7VVgo<"[UPr3-tY284'PdXq=S>%RRpNDrBV%c3L3XA*Y8nQq$-+\p8+M0GC&SapQ9cgcZbaF_d%N>Em*V&@ug<3Bk-D\7Gk'K51l;5D$uLL;%m'BqM6L.-g84q_RT/,lK_a]$WH4os0lNi\$IMr(E3W->:Yu[n6XuMUk<^:79Z9HuT9,NArm-q=SipVW[U+I;4fg46&-q'>)ZZ8K-X=DC3>UcX/QD'IYNht7`/^aojX0(0H!I&VZ1H:gRTt.LI/u$c'VjRSBb.)Wa/LCu;QP`J<@.P*[Qd6OnQ8S/Y2l/5#qhQRir&56_f:5YlbWp`8T^,OUd"03tKCtSW)2;#43+.bc\5f%_kg*(_3BHtKH>sE(c1-?VSm"aoc2ufM*%kEj-)kogM8*o%J%uFXSFgeri&uqRD2p=>)V5pG6#%oNE2mk(X=W;\m2=/gEQ0k7U:(NQ^0>%l9I=/CbpZ/A27fh@YS\`F[k[?)j#9>lN02Asd3XY$7k#]Y?:lYN'1Lubk'0&=M@J<0'RE=9qJairh0]+X"q;3a]k$a"60"Q^kT[M0WXb1nX56'U7!lJ9OT*_\Rn&J-?UkRboc>Z3bbjn0*&[X:H6^7JN#L"JVP5BFPTr/]fbOOD2Du54W2:Xg-j/qCH8R\>^8LJnqi>ZnN`h%jdlnd[1_sP__(>oTjS0FElH:95lh'4.K*W+<7kZ*6fGVZsqCfb*Os;e:"d?o_3^h:jYr,6N`Q*H9p)Ig<@tDkc!?D">ME_Lk~>endstream +endobj +31 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 390 +>> +stream +GarVJhbV*C&:WfGptchl#FtrUhp>at_Mb:P]Tgf\2/>;.0$8\40gVQZQSt1Z5ONj<0W/=W?"i/YA+n-^'(?MbNDoLfqB3CggJcLs=Y[ibN#M6Y<925d14#tR_E##+,pRT7Y_Z]o)]2VR^n77LhXt,*HBS@+'#3e7'PA%(@bn5]e%bO3*Y2UnMNNJGEf$7Fm.Xas13CYS__QgMthOi[Jo!RkR"89$%$miMW:H`]Iqi*MF'h&s_\LL6T":m)K$$=*l2(BSYKlrCU,JCj([jm!8AnX\G)QBP>&1DDCH2:pJ4s:hE)9P0CW"Ee+Th][@B"dn(Bb?0FQ'T<#a__A'Jb,4bco,5ZrbdrHnaa??J']ssioC?]kR1@\R`5~>endstream +endobj +32 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 977 +>> +stream +Gatn%h/D"$&A[3!/+-s]X&R\oCrbcZ7A45V=oG_q&meQ'P=!WuRkAVpWC3LaT_\0)@OGZ5=Y.>!mBTR_(n\"4P+qU2J?j!EdUB+IjYe#Gqn?kD#iSqE`aU>XO"f)g-aOFOpuj7QtpDrjX!Ehu#des5cU\d(/rmoRj=Y5!jL+ehFIP2qR$8`]=Cu1j(o'65_gL8-dc<%SG5I_?NS9-q<,E)F)3_4bW>LT-b68,gkt$0jSTaTXo^$R"q.I:;lLfD,-IdNnPkM5l2(5?*IgC(oqM/BcbN6P2:9r0.oneC4nLlD+)OAV^92n*!YEnPCo70FOP_Z(/2iGi-O2Z7`$HI]Huh#6VJF_'X!1\"*F=s?c:;a9PR"XR:\acFL8ukcT'k'ojRPYD]J,T1C:l66A%F8"Ri")s?5ubW3>^d76TdeCNE=;m[NN"5CEOfi@i\/RV,1Z'Z_D@\2cI[X,$3@OFID3Z/KM!MbA59DO7Hk'lSLtD@d$rY4H292H3Buc0j&Ut]4@Ab9tC%Ld:#FN-qeXX!?W@.d]H$QkW.r7mA)A42>Ok8U`ok-m4)#8[#\F6P"#1':%k9^rH<0]L51t%*4]GibF[?bYO-C\+2ll^(Lgs#"JVHOdMRnYbbKS`YHZ7P2]/V=Y,Eg?.V_og?k]+Vs3."3&H'F9J]ol^5mEBiapIS,$]R7d"@uEn#4GBE!Dq`SrWaG&/A8[GAe!iX2V6lK72$n-P'\`;Q%.DSAMS2XI0eD0JCqGs;Bi:ARDC$)31K;G4[uth18h/r2>KE3bpe8;/iEBHbBe/Gp51'-:Fpb3$~>endstream +endobj +33 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1374 +>> +stream +GauI6968fX&BF6eMEX)SJnRVlDGH.#=,$EQ*(kaLPSaB;!H9(VMk3[i\JGXGJ*IpJDIdC@f-%gaFN_:1m^p0<63RWTa^c"k-9JYVd^q>DWo7lDkbJj8IH?;(AIWPMO#Yr_GL?jcXPO\2)#FPDkPE-1AQ+#.Q[]L&2^^:1e%Un:?%1*T-:$bXUS.1"D*>3%9b=%R#C^?dEeI;%_"ZM^VPH"I+.TthOHc2Jh'>RaJX7Gt:Oin(m>TMk;q&nusDd"s$L;D:k21qY1M@?ZXTp?>f/WTVb]AUhRB2s>S[ZU>[UaZ;3`IB0=9SnEiI-=XB&+GIU%@CI@ibHDH:>&)3h7uWYLNYg%.XsA<6k5?A87PAe.SF_E1!>A_n(OcZk;\LD=:$b+0UAG"8rKWc_?GiYbu(k\O_E#Mk3k`YT$:3X0X'D0PVN;>MD?t"H(<$)#'>O*R*Fj,M8CQ%fn\Pk/#_Wm'tLCoA(QH(MQ1Fj.P#lpH')7[Cd""+VjFP:=D^Me!X4`q'He'#i:I0ZGN0'Im#$)]0nM.<$q/AF\ZL7jq[isjj&\D]*%BpO?1m+X`opglG,LLD9h3XS;O7[MHJ/erd=++942ML+]biBaQ-A;BKNM&PD^Phb]A7TY3QhnA>]?TdURV!(=9RX.j>#BXji[/_M9cFmoQ0]&>gZje)mk/AE#Fs`3@W"je*k6-"Hr9E\daVHP*V_f2^P7M!>1YB48-nfus"WiU1HK``c5KS>X?kd35XS)A.Ac5lMSiU/AMsan1sYF@Dt=)8l,RlLBgWqr&\Dc5FL.,+l7E2l84(o'N3Oh=k5%EQm^.#QKRt>ofDZ!pq;kHQRMPj]"`,_iXU*Tji=c2F!"B@IpSUdel;uqV.hK-l_gX"WQl.cN~>endstream +endobj +34 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 347 +>> +stream +Gatmu5AS.j&B/jCMRO:_(*(M;@V9N5('91&d-*o\0!U;q\?[)f5CK@b*P-K834RrH]cZ\[&g-J'V#d/I(9\,t"[@NKE]n8@?6Q.r>S?rio]tN]A-#rV-1e.*9G:a%69$EZIY&3)m!^l3g6\bcp/]"&h-_"n.5$c!3l(b+(DXH"L/CEL0=hUcD$T"d$#HNG$cpKqS?&oWkZb*ks$X$l&DoH;qpUo_,9ZKah&[UKPFO5G7W5OP_!Zu0t_^*)uWJjS1Jt8)R7mg0L2uP*Ec`-_4"5UK\bi&j`XKb@int>XH63#nIM]/(2$_1?%hDHKrVB!~>endstream +endobj +35 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1619 +>> +stream +Gau0C9lo&I&A@sBm%lLU.P(E4V41uQ+5#J.bRL11rXk`YQZ>JDI\m[u3`m*;jmF26?km,k1WP"kSB;"`?"(+BcKB3Vd[SDJ+\99Hns+a3tl,fR`QLoVTIJ?03LSc=6Ae9W)B=Jnt9$,_adHP?V9INkJ!qiW;%KHoL9W\.A\N*Ms+*$LrB!7L"q:))S78o:+iI!Z0$u(Q6&sYF"-qL#b<@T+'"LCVPq\%=;1t40\1ng\Sar*?04g-RgI>U8fLk-s(4Z6.<4!/0uSR:U**?4gN"Jd.n5"nlP\VU*R`Dg>iaC&0S68LiVA0T@0c4"#ZCqouT?FTLLe9Ungl,9c\#U3*#[J8\PioVSemJkn-01!%QfT%tjTXVBFTYftC?etn%1;,A&$0;fA'Iu+EK.a#]CB;&*HrK>ZbJF57<(8>N,YZ!j%j)'7"uV1%.THR#?qpbN!ScF`HJ0IS#RZQ@lEA)nI2b)Aj`es+R8dj3Uk5r4gYX%N,XcK*H0m.+*TI@CYPSfUSisqR(k.P@cG]C1]F6(Ccc?DiY3`r+=8c@$()Ke;bPOHjQ@[30-3QGGS$2,Hml)XRNg?UM[+,=@VKtW$@)b[3"A-ac4IR+l?t(l$d#cXmq\a<9\ac&$?F+GDCA@VQN>)O!MhgUYc81q9dhThB5/*mtT]R+TA+)I]kT4Z(pK9*ps\-m.MR75@^nNoo3\[OrriQ=E>QP)>PA3&ntsil%8E;+o*jeD+IZen0F*VR<[^9peKC.V39@IT9[2N%=dFu1l+4!58n6W-?S+k1XM*=<7F=g*Y,.\MV=XbC1L!s9!<,PRdlqr]I/&.BDdBd'joLA,W`,MjYPgj;r8^^Xk+l^dY0&$ZY\iJJgK!H,Hn5Nd`?0l00@1J=s(8<3F,Y0dMW8)d@H)i[3W8-72>OPSRH3]]sa"1=QdO3oI:/0X!,k%##JS9MG;K(`,3GXci:%etNB$0h'p5HQsBk(`A_TLgTGbJdDU88jHl*t]2n?(pkK,;B1R%2I+^78QS>1RBj@-q)f;CQQt<`7j>o5"O?,^m$1#-8tAYE%J:0Zs0.lX'X^>L\r^f2rMt[V^8EOGC7:TSC:QU%M4&.o$T\8n'"YZ]G4m_2hIMQh89?t$No2+tb<=r8:#HZ!HV/j?W"Js\*5'/OAZ[)KUtRd(46=t>\7@BtVHQ)Y$,/Jf7X6-g%8K%W-aV1W>BQ!h2C8OLY;_Ab15@Yr&BQi=K?^#C`S/])&joa4c`6<_8\->WkIgrOecMB>#?qQ`.0~>endstream +endobj +xref +0 36 +0000000000 65535 f +0000000073 00000 n +0000000124 00000 n +0000000231 00000 n +0000000343 00000 n +0000000548 00000 n +0000000753 00000 n +0000000958 00000 n +0000001163 00000 n +0000001368 00000 n +0000001451 00000 n +0000001657 00000 n +0000001863 00000 n +0000002069 00000 n +0000002275 00000 n +0000002481 00000 n +0000002687 00000 n +0000002893 00000 n +0000003099 00000 n +0000003305 00000 n +0000003375 00000 n +0000003659 00000 n +0000003810 00000 n +0000004451 00000 n +0000005793 00000 n +0000007257 00000 n +0000008465 00000 n +0000009162 00000 n +0000010179 00000 n +0000012221 00000 n +0000013485 00000 n +0000014844 00000 n +0000015325 00000 n +0000016393 00000 n +0000017859 00000 n +0000018297 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 20 0 R +/Root 19 0 R +/Size 36 +>> +startxref +20008 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_124817_analysis.pdf b/ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_124817_analysis.pdf new file mode 100644 index 0000000..0643e56 --- /dev/null +++ b/ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_124817_analysis.pdf @@ -0,0 +1,850 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 12 0 R /F4 17 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 50 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 51 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 52 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 53 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 54 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 55 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 56 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 57 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +13 0 obj +<< +/Contents 58 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +14 0 obj +<< +/Contents 59 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 60 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 61 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +18 0 obj +<< +/Contents 62 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/Contents 63 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +20 0 obj +<< +/Contents 64 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 65 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 66 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 49 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/PageMode /UseNone /Pages 49 0 R /Type /Catalog +>> +endobj +48 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031125627+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031125627+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +49 0 obj +<< +/Count 41 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 13 0 R 14 0 R + 15 0 R 16 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R + 46 0 R ] /Type /Pages +>> +endobj +50 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 516 +>> +stream +GatUnc#28i&;9M$MESO>-#9JekGG+kCESI4M$T3,_+7dg77as7iPKLT8oW3*20)6l!"[lDi1"!r7)!V$>6XMa_r<0J1>k@tP;!#d!>V7*T&EP7(QdZ4/;e#t?hd*HQtJu#+\O&0(M6+UneB;kk0SqXUZ!\8>9kUoX8cDMsk8D8F3.[,V0H,R3;jf5]CYB4u]"oB3-Br5-P@b:4VfiI,S7m97!]);BMo&pjGCK/=@W_t8Cta*.DLL:d1G3?A)i(]Fsk:O5,b$GT!Xc0!`!U9ALm2B[$IdnUtlD,QotFCmbYn~>endstream +endobj +51 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 572 +>> +stream +Gaua;;/ao;'SYHA/+*dCJ[NFV'.:G0V3W5cl+bI,P9D7&(8bl1^7ciZOTOBTi2jm-j'tJXB36L,tOF;T%2YI;'lOLB&,]d*!]"pX6:".4-;[q330NFs!j;aiL/*\bgtfM0^g]OR'hY>%EoN=;pmmsUb):*g5VU08dZ$6V%5P@=V*mpE6']9GPhpmd3]It^CnhUEg2"+6):6b/!hBaNB!D:"+Y'gWT&,;"+:rME@o,LMo(8W0%-m/!Cd0XAG;j=Tf9UVlrIOUup7mg6\b+c)-r~>endstream +endobj +52 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2307 +>> +stream +GatmpH@EKp*N*$#d*oWT+-_(0.us&FRC\HmnU!/?#.jXEMj8Pq=H0U"2XA`bdi>Yc$VGB^&IOVHt8[9+B'ug*#-_p(.P;]BVY.FjGF%4,?ThjIUVbM$iLS0$=3JCZA^T9_+7\d-@"O.f#"#9/$TAJ&Meb>Z$>3s)V5WD#mO;T'q?Qo>sT5^Z]lqj];)&j\Si;PhSPI1pVk_&ULni0)A+gfFCZi\:;G=ZYCa]-a4'o,t3>sLhuX,K62.JYA'4]o`%=Y+$K#72'C_(VPgg-qP&=seJJL&3gdUa=G4cSDJY#0ukPVD911;jN1+@)[33(*XN+]b@mHcCmY/q)He`GIWWpR37h-`gFU+%l5229T`Ha6&5i):QYBr8#\n0&6Z2g1G7-l3(-C/8r1R4d>c7Yu$er9XN,TUp;o-2RGN-=M'KKq:G"5N8Y#]KXbYh#c3?$6/;A,iP73gf#GFJjhZ'X/1f`jt;2^KbaL`-Gqf;:@a6P8Cc!a71SErZZ.mX@S(k;Jg9e7$cr="B;SPY_4d4JuQ=/((8+2c8'lmq$IG>2;*:mlsk\s^L>n9Dg!5IX%iH-jIjqE5Wet!haR/E&b74Z7sc);SbMOM[cN"HC^bbC(p85EDAYADiL]*`(ROZK:E;P>LT'6@UfR>b=J-7$`()g[I$MgEI+rE'i9L/u?X.tpj3a*??FStOk+]'3ah]5u:FLLUH.l&OLibDbS=R-u@%cV*o0#]:n(uN-A#(S92Q-aC[B`l=+[D@[L4kZ-6"BKY9s"-l7XlrJK[AqlA$:,C9.`W)JguSVaO,&<3@Di^qM:lPr%lWB[7c^erm3oLS,.+Gf-3r0uA9nJVJ65!nLgIX?mQ6]>l/U$%1TDbugk6S)qeTLMX2:Ye"P(2eS;$Q)rV!gpo5?$U;.*s$J.#B?[1ubf0AYN4EW>XO^]3c-WOYMJl8&QKfk*N,]>hO"pOF7d8,@41@,EY\l.l30X@9Lbh#.>)2VUWUcMW")n/B#;(4l~>endstream +endobj +53 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 514 +>> +stream +Gat=fbAQ&g'L_]pMV/\7MqAV?f<8`c(GJZ"Fj2"9-q_()paA][77NS#l9/$AHRG`OgnX$dZ6B&l"79spDGnt2;)nsW'CmKEMmrFcaNB+OCX?Fg.b8B;Z),iF/k<\d*a28Y0\ls!OGH^\sm)<3+bK_4KL;bb0dQ+#kH:ZufbZ.AE"H(Am(Ac&pj]f`#9UhPum*.,HX-'dSV^JDSHI=,'3e3+!UMP#n39.OoQendstream +endobj +54 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1235 +>> +stream +Gatn&;/`Kn'Z],..F-,4ghC=:#`ucs.FgJUBc#uu3`VAKE"Y+JcG6trp??dO-;$YbbI@g,%l*eXkMsJ[*"t$r+m!XT!k=9Kf38HDD(`Cdhul,+bR-9!WKNdeTuJl2.s%:D.5Nh=5$&2%D`E;qm-U>QDID\2jU]jV`^@<`kfU>914o*7IOOPGE]IAB$Ra6lPD@_ch-Kjl6W1!ShhDL'BF(^c^LF.R/I]to87?*"SU=-@/=\`8:u@jYP][^mqi0-af;d"@*F!&Fb.GHM]hP@#lmL6N&kOu)m(I\U>An[6eS\R%q14-=?"Q#.[D<$X:nl@;lVnqGkp$+r%khn6H2,(VI29AJ]A.c[AqQ:l5j.6>::]ZI\;ee(GebB`3mCPe[ki\W6GVjm`LcSt\fEnn)-Gf/+r,##q&k9>[lqp@!sW'DG,+WJf$RaEYk+gVnX[9W[:(?ek;/[1O$2b[)?l:oV[h*qu#[0XGWr$4KNZ\r1ob*T:_bL%m+EGLY,p;#o*BHe+5T'&ZrKmX\?*oH7GkNh78EBLR#S=u4mN72K)7oH&@N/M.A-a>hT*b]!K:30S,8UX6i63cTm`u6eE>F]dTqk0(4Ykon"7[%k(H#7D$gVg.e!A$:l'+T$8_4\FVf)WEMVs/Q:;EnlT8?aIlJ(Y!2c^]Mb9n+\,2cGA>SQa%52m@BWNu0n7WW\=NJ;YZbQ*V2L;@^6=0jrHQCuHqQIl)X"nlL0;1I$Bo[tYsrV1>m!7!N@_nE=fnMKg:pG#GMhd^4o\@Ps*W5G)j-f8L&BgA\NkNQXhG>?f14h>nK/I)>L3~>endstream +endobj +55 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 231 +>> +stream +Gat>NYmu@>'EujSYIGf<5TcX&7hV@8O]Xhu5TuS\`\RAaQ>/6'KRqpSbBruSPe_+V]o<)6Jac(##bhDI5lspA.(k=*T1to/mjL`U/@>pKYSI"@Ys%4&KtS.NfQ;nZQl^^MlPAKWjC&.1IoC7(7iZK,ZI)$$\s_2GDIrEXa4X(sPY.DmY%-;6n_F,ObSTN"YGBLmFP<[>BI#3i2Db=r%Z.GZT)JH,KD,ErZsit~>endstream +endobj +56 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1009 +>> +stream +Gatn&hf%4&&:i[6/+-s]h,\80k?#&-b/20:-m`T(8\DR49='A+3MmGhrL>]Y.5W2>,:!D3P5DcdmU@jmotot*[fX'YiG=/J'6*C@diJ[:!k-kZf>6..L'\(KpIs$keJ2g"V$gbc;:jfogC\Si9&5C*ertFmPh`8(g5\7drdaN\1`n^Fr-IR5cYXM*rgqC%TD$bPhq0=7rWW$PF9g:2jGu*?ncOd09"j)cka$4YjTQt-=Xa^G_$0EOH$BQHO/3pN@1]_P)uFVh5Q`qTLu1UR@J%JA>OlNK[G@W#L.aj-SqEa_BMPFF*_@-[6lu.)O3c9GBr0:B]:biNYis)34S^%Z^Od8U;FEgdL&*"g3f8>'$(o7rP>Y#1Ro1RN.=f;_aRi!DjJ;\6Uf%J-I/kH'+g9*5b.%"6(Omn<:ndtJ$CB`Gf!f(%T*-.lZH*@Id>0H:nT^jH:m8l*X!2XplUXIOaG8b=J#o>5e:"ms\Yu5-^e0L*l"(+[`CL>]JCpe\OpW?Tq;pjJ@S_j^JU;.Ku^,*lK=j3A?<&D*/M].8H1-2hL_,?c"=DVG([FaBo7eh".:L.G:WpUg^\nN=6X5;]LJl'^_>,q^3nBcMa1%Em)VQU`FMilQ:h;$V_%83VE+HBI-endstream +endobj +57 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 400 +>> +stream +Gat=d0i,\@'SQ5[MHc/D6]'RGUgtqiPq#c>:du4a]ECT2(Y^Cuhr>tVRo3WZ:\&OMn,,?Rh[OAXU]bRE>V6oH#]U&,),:aHE>oGF#AiQ363Q?%0FVTf9/saVfR=3LJ[1-9gI6S)aDXQ2n=E_ni#M9f;b&q">A.G6_@*H(WQ8?5oIfN>WKjh9;ckdjM;"-T3T6A5oms0M#^6Wm3HEBH:pR>DA?(f,UDZZRfC@N$c2.2:hSHE>SLIibR8?-'3?endstream +endobj +58 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1792 +>> +stream +Gat=+D/Yn7&H88.1&Xqj3N:N\:2Hg]&ogHoMSTNC\X`S/")E7e]G9"3do6;DblYn8_,1_9`iqNX47gZP@i>.'\PP0I$Um3_SN3-Q_"e.=WK*_;l4qOe.hracd3!5ML]^e:4ut)_Ye7;Q_u\mB[QRR/#4=6!R3arREJNJaYm_h3jUF+mY4-o:,l/`DkCu!\3Rj4^AGB]!:Yl0LnfC`61dj7KR"9',NaOpc6JDHZ\7>c_Y(4$4^N#on'M8ib/SNok$L.U6\r@QURn$cTrOEH/4tW_cSLO$Cpa<1*ZtlrAWAPtS\7WECKTfo*V^Vp>p(Poc[\/'9%'GaI=jj-r%8?^b\YUF#'*u5j(ubY/I+XQ+aI\c*.l700hhe_$PMei:/!CYm$Y^W[%='F"h%gl7^'T5"C%M)f\\d2=[:GZ4*)Uk*g4mHL\eFS_R+1I;HEm'+F*OHqGA6*7GsC57gnKrg/Z=kiUD?JZ7HG=]lB8l*[NIY:#,)A"K3m>UOLm3Bif(7gmSnEiijs#hh=m."r*em>,Y4I5cZujY0*=!g]dMN2o:1<%j=I=+@FQoa1rF&b=jn"TkptZNn0^*_A./)HoU)>n/F(\a.kTJDPCBK6rW\:5.7jm0d:Pg'>1FQIh8X'!;Bi[C'Pnh,]T\(fN^4:b[aD2PJ@bE#(^2Jp\n/Ie2SB&'DPk(%N2,B%X6Bkk/O+\hHV!Tffl9-KqXKQl[8,^ZH[7'q[1R3`h7!B@$9IroYR5un$K@77hJBL6^tU&`5L&X)KI_t$b>Q%lnnFDqf=3PJi_m?"2)tCB9e_$8~>endstream +endobj +59 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1727 +>> +stream +Gau0CD/\E'&H88.0rO:^E`*lno9qQb!HIO($/rZsH4jRCAq=e7YA\V.V:GP=cIrK_fMFHmJHYQ3c8.+8o?>jA.Xpd[2cp*&ICQqt_03VdK3bfui"*Wpcb>t'l,dNFRVpkp[G!3s^^V!_pF%p,XCC]c!`V$BebCX2;!CPD1n@[Ek7A3Mi>S/%i%1Z2`#JgjcIlYYM.Rq70$'!s?tqWiE(#5j0GcJtH4KrCi.$7ai?G'(68K9cW,8XJg;)ri`6]4RrO/RqmmPRd0DNfhD.e=4g1n"NK95Htc,[gYTt.gYpOP(Fie=O/#\G;*8SL"%r2Ec"=qX^L>/o9^eVZ^4Xe.Q\+Q,Ye_q=srcO7NaH7I[1ZSI$MI/8)<&^LBOj+@IiLO[U?rLSAYX-.:O;1sp:ZP.R0atGEalh!BYTKi(A2tf;H2h@[s#\.dp5O&(>j0.t)pHQ]62r3?hd.`"\$SX`;1g]W1]>A=hkt?"ZG0=R4H0U5_dm#\eA/F0eR,(W6erm1LW!gBg:6__s8h=:;,i"\fr+`nRc7Qhk3%;-'eS5t$XU%@k<^itbC)L!a!;22+Kd>'Ok[qq3).]KBl-j#X$8*)_bd+?+ct5ib>*`_,*KpXu1+(d'BVAqmb`]ImM-N%Drg.$FP"[B.KpJ82_:WkTZD^O9%Tu^YNFIBHN.?0XuhCaQZ+`9N+mqP80A'Sr3Wf#P:\rBe$Wrf=S1Cg;(p_UBfC2I)]8P#a!)"8d?V4?kPY]\"#An%,Zq"'%]KS5-*eQuQALF^=o2aOngS?[nbJQ")_,9H=.[`#FD48VJS\C#^:9K:Zt,W>$`W5bi-;P:93Wg_-hbJFPLC)7BP6pmM7\--#K^2N+0t.3-Ymt+p*b)78E<<2(Kc;!HB,TOM9U3Pj6P2OF@CRpLh,(fr*sCLYrd_,YO*2cIfSRR9A'@GAnt?&%KlOYA;@fmA0ZN0mZ*K$Q3UXH`,4,\[2_&o>@FCtKrB*TV*c5=L?SJodg5dZ+u:R?fO8Zgf9=d)H4H4Ddn<_2C4Th3^uASRfHfp_'(1SAEn9,I!Zl~>endstream +endobj +60 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1271 +>> +stream +Gatm9D/\E'&H9tYR%@96<"34Xi6_0C_`>\!@ro*IdRno?fSd(mg%Fa8PG>n,ZfWP7P-d:#8B>SmbVRSh1LgeRpp98cF9O?nTRCC&eV.N?pr&C$b.HHA"9sZjBUsZ.NA_t4)4/Zs$CqF7GZGQ)oYYFcdlpGh?10TVecsK$s#L`a1S2?g1`'e;OPE.m'/T`nes*,;e4agZ/=PZ`r:V2Sqpr0:pLoW_qUjbql.[*7lUP)pQ%2L$P]sR6p!2:?$sn4S@iuK^_!FJ(V_+fmPmo?N4If]VAOEp=$(Gc_]6EMiQ2UOgL27l[mYAo%V8#RK7\A3AHeR\J-?TH4A`2,cMj8WRM#Iq_V_i%>QXj$NpO:U3PhDJu'A*m+#8o21e50;EQnng#+rmNj>k>gl.9S,FDJbAn=7od\9K,h6KpEV6EOa%+(1nJX^_ONI(gb;O5sZ-h&$>nd*Lt.AsH]2Zf&<6;$m'5=."g3]pn0d7ok1Th:RO?fWaY_1WM:[4)8U.>:`_<>;fj7k'O;7Pre=&45jD4#QAXdEH]S7?h6l'[4YV+>$_^eXNPl^"<,7\#e1`%/tt#E=&92_TVgEagA`L7;L&P2@e\/am"'odehUd11Se>IdR\l:`/?!BY&[?OZV=,TXdu-Y4pCak4$1MUVaf,HAZBfo/pZ4?)/9eTUF?U,c/^N=Zq8Hi4E9*bgZE8!nX]'C:=P7A\`p_RR@kSPk's^NL_V>AhoG2bWPrR?*3SBlrb18K'B4NkI(nC#G;rc,WZhp&;'DB+HZ)Ps]uTendstream +endobj +61 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 174 +>> +stream +GappVYmLOe&4HDC`KY+WAn1>)?1&=K&FRn]P?LcoY0d2%g`.L?gW[=>">->?hA9R-ln8Jsi!7>H(7Yt>]bUL3]gH]KST?/+KG8_a5#3IUrH//oU,&BO;]4CZRhA4do)sD0M!S'#!TP.Dr8_oNWF2[G^;enCquZ?@n#HTV$d5n&_u~>endstream +endobj +62 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 711 +>> +stream +GarnT;3RG&&:X@Tlm(+"7BBPU)opmX%!TAlg?FPLOfT1V,[LOqY.q[W+P*Ta%$9;iIf&NA_1SFa?N&//^gd`>_?4]ZkoRM-?jp`X@G6(oH0r`<%&TfGKA#VWb[d*VYR[U!cfBBmgrO#HK/E`!Mo?SD/WpcpH[8hKbO@NK2Ba>SY[0c_:Y;c/kA]NI7^93>+?`'f#ol0$_BaC6T@8_A0_oV;%@bIane[c7'&I/2=kIWOL]H@UXgDR3NjsbP16IsKRMXp\Fh]:NqdRtF[PK/P]d,WD\W!:9gsg5?6NtI9rFXak3eKK,mrp@_sj]&X@05I'02^,*;(;;7+"\+Ud1q82p>Do8gX]i=d>r%6?U0E"'LnjY\75?P)AsUWDFSW]LIo!2oR1MU2Ys@WIP5Q=:8Ilh3%'SU2lRMjm%.aC/ei3TlqrmlaKpD%:R+:Ou%*GFH80n0&]K:7$2]fbU?)S'?.n@,+!0PZSoFk0d>KIFXdS2Bb!@h]Ntp-7-=aT[SE[df@kf'CAZ@TChDBq.H20NWF:L!'iR['5Hos9$FH-)QoJ(lS4UP11CPIdHpj?Ys/mADM<[d,)OZjQU&$`;RqQ(smCSd[+M.[u86-+V:h"V2d$:!,>p7j)DUCHVjs&L"*CBUs5`UMldP[A&R_C%t@P:`)S(R_7d/*oZ$;kR~>endstream +endobj +63 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 656 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E.MOadYX)uU/lfurn#T66E)C3"&*l5sc8VMXTLVf-I(9<1BUlDhM8>rIe+/31WeaJ2]h8rrgc]]HmCm!R%O=0YS]6P1<-4-JN*`!-!BCYV&OY/g`nHXrt_>5NB+7'6MX$-=jY5QP`2oM>sm_.QX*YGtDg<*O:1e3?ZPA;Q$F^s!12q>`']K:Q947hg$3J9Qo.9ZCh1`F2pfd/s2,WZLJ'V'H%g3D+R0F>'=&\P3lY+`;d;5/)*Vk$!bc3_1;o%fS"i+k;lhGUPR^dC\nZ)RpCAC8Jk6I29UUh8JYeN:SJ>+DKE7opX(7YOZ`EZV>Ur"gs>TE.!OQ5%NGYG"1n"=`t?XSk_0[VAXK7:I_K4NA5ePO4bUE7SKg+?okJ:`5_d01Q>p,=J"Xpr\^cR$t[%-Vh;t&LcTK&b>>G<,3V=4bp_&CuE/IN2Dd1L1'G94N[*;J1i(N;!rBEq2lHOJ3@iSnH6*2Ng*.hJR">GdJ7c%&Tcc,urKknR9E\Q"4fdBNRh2B3%q!h'$@:n:Yd\]MJ!D\,[eIbpYX*Q>US!FT);)92ci~>endstream +endobj +64 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2154 +>> +stream +Gatn(968iG&BF8='Y&8)nVfcHpe">bW[-jhW?987(Rh(83hiR9Pb"UW^&SIi<%L/%3Z?'.nk\W3a5q>1@"A"Wp]'Ck!.QOcn.#Oo_"&7K"rUO7KDG*%T-GnPE<9T=@?RDm5D(%CrIO,!LnBUuFSs(7:IP8D`)HkrM2ne&ZfU38:EXojhC[%9fALCmq0?tfq",UY5(9%%\N!g=_:`ihs!2,n_"%LW:PAa@rn3?`?tTmYLk.2aoueM,%'uhP\cQDMgQZhZG3+co"hO&4?%DbeFS>t&lE(?eWG^E"gm79#I;97F&f=Ie&#F(T&&^Gf=:?;Y&\#S)M+AVD!&sg,R`$>E#b7%p1^1BP3J(s=6C%\?-A\Ner([M<:PdA:Jf"o/n3ulnY[W/D*EU*$#:sILQ>dOF%+k4M6pAj-OVEY/(a1Snq7?@o&6%Q*/n4r#@9V2>H#Su/?]3/YW62cPgS/sEo:c]"D0^HJ1[Z^h*jcB0d"!n^@2P0TXhcZe#u8t/6U@tdJ;.oY=-j%1+t[6*H"beU_>L81;hf8dAd$oBUs+lK\3LC#tN*bi+T55Nfs4SM;qn^)W=@XQH\%<[!>Sf]<^:`HGGXV]&6,I(EB8o^l^B:38m].+p4>^"0VNIH@Uj[F]cI7B1a>UlLbMV]nPN:h!RP:$qA10X7\J^@6+fkG*2M;WU7lG-nhD'e/^H'$8"+DK>uHaOTFeOG`UDs+2Lr5#`^rO5!Tq+qH/^>$m60Y=@kDh>KRqN0q<49.J0#l8#!+bIhUCOepCNkOPc_oXSJJh.uj/bMoK1[S9m>cE;XF[E9M2FT)2mQMAs4ia$/+lh_jYZQ,pL^XfXu:o$n9rMo.>Il[%u-AR/.p\'+,T8+ZZZ@=/2;j8Vbn_[$QZNjS#q;E_"R_J(E]8P&T>k_8ED.q6NeI4s?T.++'95?AU9c6f/513KKPa.<:'h-9f8'4F`]tl0fg);J[@\g-"ng6i[8sM=idT3H^M35+'<-]-%D,$6R1"+WDGnVE>A]gJZBe*';`(4*pp4c%TWH+;b^1-1R*^,5";)i!_&PfuP-d"q-0B)O1&nrV<'?$99XR)Wog$q(e1T?,+!j\tNhLb7"W]fP(rmqoir[l@s6k]U!.gNE$\mg^E.r:;`(\b@@)h*endstream +endobj +65 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1174 +>> +stream +Gb!#[9lo&I&A@C2m%n2UlN]il5h&\Pi1MU6@c$uEW1;$UdUW6ac'B10g4Yiga1h+_nuOK^q`04h89rbI/s+^"Gd@M%)g_5#VKL+N4t7l-I_S&ZTQM+-U,7!qW5"jEF,G?8et^\JrYd>Yum$*XR/Y-hL%1_MSiZVX3l@?=+cQ"?*E4E0CpA@"U%LiR(g+Voa6:T#[VF*o]H&Fm3a1QBoa1#1t;4cm_ij,?UbqWSni\GR>ujE1tQqGce5(qmM0:H[AXh>.%^lE1''4ii/356R^+K=P387#[]&RLn/aB!iKssBWI@^>)%(5]j9?/d4aJtO?#hbDmKP$oUqiD@%9c201":B,iQ@_O:o/iTO?Y9*/D_>*6='P`,MY<3[AFeoGRg[>X4Wn"F;g(^[KN2=orQ85SVi=F2?^\tt,kNerSDKDU)^A4rqUlbcb;,5:EF5l2*8ga@7WQ/eHK_k+%:1!q3[Ag8d#bC#,[s2ZV3iX3egeid0!e/eWi!4k[,\eQJ([0sp]'2*CM6j8L;-EkdpFHd$J?*U=Bk;H8RSkFT1>h-O#`,EG@B6Q%0"ajAL#u*MH[kOd@Rc'g9*:EaOHeePAQ'`"LGIFX]sQF1kSMOY\VpO8^4\8;%$6SHQjWhf-\8TnaU(Y:LMb[9EYjj(hoJC^QJ?keu,E+ePKE:!A.rkCRBs-aO*R6n!![$!N9(7:OUWX[DAKRroS>`LRK'VIXZnpZiXl<"?`R]C0E5e"HeXaRLmG88TD[0&V/eO"URE3(X[b$hl)&92@:5c&$YNDZ^I7Hb0,ab5pgO]!Gi!',T-nNM_+f5h"7'Mendstream +endobj +66 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1282 +>> +stream +Gb!#\h2g8L&:`TP@U;f=Oda33?Yj)lXa8Dfgo8o#\ee[H@_g_Dk%of*XnofifWZ=/P#_TtRg;QTZ0.IAhop8`(rq)p^n561goLpsC5JM!I@+MLg6akb1[=Z-&JH:p@5,Y#te).-GtT8ZKI"$R=$X`^VYV"QBKg(.<_uV!CAcErcahoBWK7`7PYAJ(O*DZGNDfARB+/=PK;R$]@4ou#Tl9,l$#%U#-!l)[H3no>'l[[C2K7%tGs,>"_a+sY8O.kMOb#2*Q6\ZrJF3_)'2TT=4YPd&lB+.k2@V`h%EGWq-fa-6Z8k?iHalt?h0^WFN/SB[X%#LiuR'tpJEJ7QPLu7V+#=\pZTU;X]?)LFGq?Rr#]GO]7Y[p\\r9-E%pW^0?:G)<-3+,5RiTOSOqFr3&\-$I_?QN\]j!>Wf=S*]6d32-`m0K2=664@SP[]]oc1._'\HA]Q7Fg)Shn0D4_"lIS_!D[h"X1HH2P68bW=PoPCo1L>U*RlMqQm'UQ%-Z+bWU-3+jBTr>;m.,DOaL1#l']"e]CSs75#9JIM'c=;Ps`Yg5$^NQRSRE17Cc)df[_OjB0rVlDM\V34p6A1O&,`fkrCiZ-+OqmWV@Q6X%!7m+#6/_Cm7FtaepA%h$g_ahEP;H+"i!dASJ:ooB+j.UZdpipb5BJ"H5$HleJNCrktaa\<6B?W7#SZ[ABdN#ZKV`iE%"4Q#6a+E4C#JM;,k`A2b7S`j;eMt7CUR8sX,K#Cj[:GcB<@bsYE`m0E:8@aD.Q9F&;=-o>@\C-'Lju[YKLERo5=0s'lpjUnfT2-1Ac9]<2YSj*kh_3Z>9<>!m/UOss[,d,=&9Mpdhj~>endstream +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1164 +>> +stream +Gb!#[9lJcG&A@7.b[gffJYbb,QK7\$[+bW_Jtd+pHch&).%?&>H:>tN;<5K98D0$VZjm50mK<=:^5r"BLkH,?bj_Pd=4Z.3AO>P*`A.HUBG4;#>Ut..la_OZS0Z8"6s)P^3cjd%*jbk:X.!9N,KUSf0=el4;Y!E:iKPUr:4V`PNIXeWiEpr;J>I[N;p7q^>cIn-lDV&FI!iEb'cTIF=%>l)W6^X[+6FR>i#LRa[q?(^Ip?d1R/lSf!X]ea5W]O5&);MD@g\:$aEKj_,Srb[q?O^KC=!2\?.8"D/M&$1lfEi#TNWm7\V/;nIQRU0?1JZEQ\V,n^qC^c=Sjl[k?*JStSA[/k's376-5a_,oJQi4'"n1bKbE!ZtBMG7@iTC'-q="0'F(pEpl>HK$X\T,"#lCHcOcb,Q+4N-h9'"TBj@+IhK;G^"*p6)t-C,M"29)EDYhCMg@oD2&18Q$V%E]bP,@'f)nU(=baK6@6eVqJ5oQZbn=mmtNL*-^AnNVPV<@WDd-n+5T=Fp6P\#'1u&G--Jk,$K_4:Z/N!&p_t0tk4>!7SSuP^;%m^XXp15[-c?;o`:p3[Fkl)<@3#!"`X?*JC-FWhLR(@VB%6,.a"Sg:5#=9)3]d=8K21'mh\-d##^(NM)&O:DmNXepGG9l[ZD5f?V3_]M('r.4&,p::';3jm-0?:V.Zpb=;_'2P0.=\in]1.\8%&J&g].rpRukSIH6-H?]1"`1<5^8TX;+GFEa-TQeW`K\Y(R2#*Y8,:^RnP#u;!BC(T.F)*S8GTjf%lBY[*AV^dJOt+\%GD9A6&auuQbKe8]l$!(RN(YGc=NJ>)?'Fu'\nfN=(.r2CjE7/@VQU2*`t.cC_sV^XhJ_fAp+BhHL5/24KZUgkRA*m9.pciW9r+qdABk:g>@ME4_39mJ((f\YQlRYhO6-6=UT5c%hfCgdr3.QB=#cbUNP+cGV_aXWD/r+R5"eRcT2>!_$B'MFV'q'7OLM8=]Sucendstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1059 +>> +stream +Gb!#Zd;IDe'Rek?g_Zar#q'_U-A<8U(t,2d!K23VMjHE*7i_ih.78o@k;l>HZsA;"&1g\RlIru8jS7Nr"Q8;\[*MtY]ZIs9(I15/.j9^>"PEsKAOg*gJo51`6:(d;VR$tanuVg'Uinkb=Z67#O,QV`sTQ^bQ1?LY%F>cBs,l1P@cZ*L-MHR%iRE`Sj!DC`+]+J_gM/Do29;EXQ@D+[,B?oebbFB+9'b)P/@_PFg*;d>?oL,)G:+u!(%:\CuUu@qO-^Hq:14%lV^t;A?E3BV]*Wt)mGmmm@eE2$Rjq$n]:hGGe[[CDQ6!"5pr%5"-$Hq%!AeDo../m99YIia&F>b:RB3Xth$1'lB+Q,bC*^G[0ACpIPHs70DRj;PZM7q]@Ym7a_j6s8!*do+TeIHXkTk@emh7a+D+VS=RBZft#Jt%=50t2s/6&C"PmO;mD`74\;cc`\VRqA2npFI\L?,oY9lo0Xci<%6k$q5sP28TcolKrmno4Z*LMTO8>qW/X\qdg>7X6=!'e>e`W~>endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 924 +>> +stream +GasJPgJ[#r&;KY!MS@angb"`j$?E&#,ul.lUiuLLRj$6+Zd'`>9ORDT[jMbJGb?H[R<8Jb?iT?rRe2K[cU7e=`c,r=6.CL2%T2E!"7[rOj4\Q+HG-Z>K5RT8h!:O*."Vqtjag-A'H=`^UHh8I=qI6Y<39b'<1aX*nRuqJkC"1@`qL"]S)N1FoP4`aUHe6%\[WPbg`Ji[(ZOmLod@FrPhWn#/`e"hG.SP96fkeBE&.d'X+U8aW8(j:g5-!M[J0t;L2k3';R#N!N!S.r]ua-dc^7(UqCkl^;q/nrVOl%c'JIZ>`^7[%QU7T8h]PX^ddOlb.=*C_:dth2m.t$8dJE@QXdhnhY;WU%C;Vu:<-3"7;9Z.6O;E)@^^k.gqCp0Qoo0fj$Ir@e.-l(F4)2.\2r`:fX<2E,&uldD+VSS@aK7-BVipnSFHRZ6G][M`F3>7MNI?+;%Z918r@J.)X6uLQ#mNq7+ZL+kGB/o&$RK*j3$TN!G+T/Li\`8W4#^1pS`!i0:hSbPB''Gg$S9K2"^-YJLAVs,]+8C,:SB8HCJ^_N$LQJZT7+]PP/dA%gamU;Kd"?FA?!_s6@/f00hDkK;dOi?Rs7f>^hf/?O,9c@+D9Q+eb_WIlL!PLP8#1`DTdB[B8)G[`5=a]<,ZlQ9mA!K+DmVu~>endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 936 +>> +stream +GasIegMY_1&:N^lk)i[r_'B@5D[AD&;f9"683]e<0\1oZp8oK>GNW1?bH:?)Y,!\]u7V&p&ZiJTG_&HhKpLA$\W:$^KSoioGm?1/hCl>I*6k%GCE^-3gJQZ[VKT$g7Wjq$8*'PE.aQ0:k=rL)2C2*>%j\NuLcU>R4!Kt<@4o-Gb"Ne^fHLcuTq$pbc\#,7&j]gEDFEb'cPOtm,g?uH.1-R-a1%E6t5W=1Hm"$T_g"Z$@J37RHC'-C?]mLup+)A4?;(s3\^9]O1-GQJYVXo-HRk5$?tNpE_*S[DdO"&@:/U;lZ?Cma3uR3CdZI+1t`)O"FGAObi9`sS?$RGjsCan;%t@69:LGbDU2_2==B3l5-.(#(5?%7uiQXP&=[85m/q.&;!EZY[*"mCXJJ*^PaRVrArIJc[0g;!?1R460@ErlHQ/ZqIXYc3p1ZX;37R7V*uhgOG0sbL.BS91/397=RTM'S/r/`e(2W?J71aU;g'7X42b61TW(Ee%-fWl^b%=4LS&_XSI%d@(*EoWcC;.i^dR%RARF6I=iXh]+eV(U%KK4B(Qi~>endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 731 +>> +stream +Gat%!>Ar4L'Ro4HS@=60!ML6)IgBS#K8D\,U\\T*qO^c$,5>_W]&Nkd&E3%2/T-HWR"c;CdVh.HUJK7%S$)>,SD/^;Mfmo'rN+"JL/=;H1RmL*;_\>,!r(&>;d]uZY0rR$te/EMQLqHcH&7&p_kZn4>LfKm#9C@e)U#YA8(b1<^J+nWW4>^h4d_nK.cO"iT+!BHTE1jC5>X2!#F7@Ju($?"]96IOE&.F]N0kW;ml8C^s5LB0&Gg2"La;^G'TBkJ]&ER`#i3c0(C$TUG1frb:Xf*X.R=!Ye=([96DgdbgX\H=d:LhQ;P*(@+C\c?95'9F#\^KMYIEP`i^2bD./aC:S)5`L='B`7ORjd0;*VQ.)f*W7e*;]p.9`]8rbL5)q.ULE0OpmJk<6l?WBK+P8n!6YDJsWQ;qCh-@UZnI=t*tI>o?Yhho\)f;#:WS.`^o~>endstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 650 +>> +stream +Gat$u?#SFN'Rf.GgdaD>5S++1]r]D/Q46k#C&>c*Qe[2I3)4<(Xd\t@GO:'?<.(dQP/ta*pY:+C'G#Ms4EjR(^ulQG'+_`>`"1c83Wk29&B(^6Q<,;$A%;(jj71Z58.>>['^oCoiK0FYR$Qnbok^Ir>A=TY^SBEZqK4mAR+?5s;j9pS,u63aD;b-l`/f9;=0,1RR67$p'T/7$?r]8)6>CD6H@`B4s*13ZCU#RC`5GbLr.%EJk5oCgN(C(EA`hg>_Q$LYdh*rN3ms*Ye<@u&r3H#UN,#)jhk\%ln`p67le0]i"E,"uF.Z*jRM9RPr]7M*($V1M)BlOp)`jjmD+]?I!e2WInJSk,\+/:bJBWD&X`V?^dTfpR8EFIR2+2'jYX+Fi+D*@kufN(-(/W3HfTdurF3=g&OR_ke-'54KpBca*eReju%BQS['WE4X)$I*uD;WobY/GF%6~>endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 594 +>> +stream +Gasamd;IDe'RfFOgrFuQY-,>^nA^ou$L6>3P6W@>4SL0[`-/B@5koXF04bSe!Ek6nq:p%=cFkr`M-Ip5R/j`miT>[kR6m>ER>kj@/g3t[haXD/"sK)Mm5PO3KW`1/\.\A%j_bi#.U6OhkF!YKe&3nF!2QgsF7kq(!@4DfW^707;MuZrU]h*ip(aB1rkN,D,"#k=DF!6i7_(m'#(VP@8o%rQp.BaeK5mDER"sOY@1)I;:#V3jXUOK`1P?4H3A&E)<,S?#W$6UM'EsiBV,0q'M6,*,?9ESi>-.]8:1b&$U9j$)l;Xa'Ybu>;X_[,)7\ETUV\^3X6E?WCptT4rdP>kb8'o8\=fstP`iF20O.a`BQ8R8dqBO4Lb^"3TkNXF_6s,_S3T:Kl_s6dlOTrO5?(20=cT-'qE_5mi6H:8*EPpL=(n.b*'81S!"C0:B4)LYfIEL\'X:p*TokM4b[`NhQi5]+?+5DIq0A0f">Q~>endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 297 +>> +stream +GappYbt`sH&;Bj@`S('N)l/2oGH9,V)e36J_>o58@QRtFHO$9(-g`ago:9T1:oMUC2`'r:EVEpMmU82E1,!'CnSGP8bkuTa26*CnlhXj:TbiTR91o![4"IgN7o6Gq'o-6/fNVV8JJ7mF>J_#jVDZ2`$1edD+J3m'KT5!2oSq3`#/V%#HC%0?hO0KE\Pah6",ic&8>dEZnVA9s+!t:1^;hW"JELL6RME[RRP`DUdd0]J>l8db]6[^!8)W=0CeqJp"oc2t&7S=[p@A0(ZInr;n9nhpMZP$k4~>endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 441 +>> +stream +GasbV9lGVK&;KZOMRbR[VM/=0.!f+4=rStDC_'7Q+H1j0b68FTpYDZ\CPp,JZ3e`;mlnr^J]L9L4idVX*6]i8C&qZDI5E!rcXF\uX[`&U4WA^uK43M_>8"5,RY$>PajO[h--8hm=[9SKb9AE-pEh+KEu%"i)o.h\2It[_FPKq73K*.gl,.)4h>t=kILA2@Ykb1Uo+!FLb.Cn+3aJfd8*@gbf3"uTRK'c.j`3$ZI>g#f227b43!OA/Udao5BT?j4d/Z3i-S#nA?_dGf`gWp5q2Nlo7D;NkSabs@aC1O5=T)%#8/o^0g/#Q(Zsg!p.9k/"dO>oN"Un%p)!#;^BhNGc]1[es_A+MaSBpa'X@s5=+NDVi2hFX)k#rIENHo3;LCEe1I8XQUR7/-k0K.J;nbOn]Q[XUQlFrW'qGk0XHkFNHU\+O=!ppp_9?e=~>endstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 300 +>> +stream +Gar'#_/@+D&4H!_ME.OsKPVQl^s.NT+[p+'IGnicD@7(sYh_\H^:#Jh<%I?IG380'E^(7^If`XPZOMHmLj)[`Pn5McOdm*]]pr/kQVUaa/Lp5Y666=%Oa&P8ik4gBUC,@hLaqs,Pk([egQrCA71*bAmWSXU_)6'lhoVE+k#E-^fUXq56AMIqT0<64(SK%lK#+/WSClhCYp:[d*g)uq=PjDa',X3X-?j-~>endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GasJL9i&Vk&;KZP(%8DB;S*[;E3#c],btKI%ij3gTPOBmG=D&R]3W4.#L+N`D!'c'Af*iRbe::`mPqB<)-@$U!?2.Dn2XD7D*<'D*5ra(DLshha0rl46C6o-4kn/oa4\JTNf(W,rMV.2#PiX+jg0^NN(k\@Xr*Icl"Z2H_Ki`8OCZI\S^6j7n5o,&*k\k"%Zf6Qp_bmQRD&Ip5Rr/38IrPq]hu7/;N#S!Q(Bss>M.L&=>YbIUI=A5>%%h^[73H:UnIji`paat0EOR5dMa')Oq.IH*f`bjSr4WXFYYsniTDda[8GB*Cn3Y9LoRjR]IWT*VDYAOT>IP(7Rsb`.]NmNeIWapm@'Rq%d%pB@;QD8HntE7nJDg5c&R6k!q-L\>)oZ~>endstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 436 +>> +stream +GasJM0lM[u&;>=W`JnR:N(F^3>FJA;&d=_Kkg79PQT,/\[G=CLpGFdY^f$`aiV_QEmq`E(/_lmc"7Sh]4^l,iO:T,7G6&t?QoNt5^*nUF!e9WmiBq9!p;6,J<9748mc/]\Ci#CJGhH^)?CNe+a(r!*;S[Mj_(+?Z3_RRI99ON)EOs8uD+a5H*.cn_/:Pj-CiAFeNWj^521euji!*f3&2%1AG*h9N`+qrI]J*P_@?dj/VB?Z9QfQ"s=:&0'2:k\a[!RbWee,US+93SpX^NpLaKF!kVj]e,K)&BN3\a&RFu).f*(+HD^)Kg0#uq_hAu*kT5ju)TA>2JO'XHl`^^JZ#)p/=FdM#&SU8'gV6lW9:Wot=kGfcaF:rPk'Z::QTMIG4]1\BHM%Pup!nmA]Wjmce(hu&F>&9;Lo;o2/???u?_E..hEOhXE~>endstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<92C1*'SZ;ZMR0B:.YFNnFqgVnB$IH2`!F3j[-aX(p!&A+tYQr.+""N1Cj"S'MrkQ32UhAgQ8"sF'JH5q[g:cn2J>[$R;%g=U/)#;S"^cS_@mR3jat(*Fl\0T2.Lq.@/hDQqhGPI)n4@ZIsS(\_KI?@Y4l?CLAkT!JJ3J,6:_=`.W":&i0Dn!a$tNYp#CohtP?611uB]8A,ha;VK*_6k#Nl_A:TMI^`4!].@Rnb0TUjWBtqS(I3Ct3Y0>K(=u+_*k/5?5cC_:endstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 389 +>> +stream +GarW495fDI'SZ;ZMR0ZaZnmMgm"AhXJhNWgPAVdR/M3#CTM>H7B;jA7R%)\qL_'o'Dt&t=ET($;Ja8>%j\Q?9/`b2R?@Io5`_o6ni3nY$R1AM!_Ec>2$ZQ++@26f2ANZS9Je59aC(^gNKkU#s`ci!_&GI*Vjci7C>jLea9+R37IBSL?QU`5>]fQb.!UaV$00GAR=c^91hCRqQo`REd*/]X%W(k\Dn^1X&de?5n_?caYugI%jTZgN0R-#\nF#JO*O?"aZ?8q;$9\VZ+bKNqj=b4CXNdF#Eh))SiRYQO)?AD;H9A>K7Bi*JlJO-(sW#/.T*ZHER@7$V)*o#fG^BIVmF88#!B/AbQ~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 852 +>> +stream +GasamgMY_1&:N^lk+r]).d@Bj`bHS(+c.L,;!b,IialUQA1M$.mQ(f,hcX=%3$bUWqn[VkcHJ:)X+Q.f?@JX`?kU?.)]a#&_@>_H_%8pDAmt/=Vq9"P"f%bOYcP*`&U9t6#CP:D=T+1,P8p+3^UU422#+^U#)N3hA-I4Z?Vsmt>m@r4)M4S9r:\"`A8[iGSud/,l19SCCqM=03B9W(k`=jJiHg.R?uZ1j)-7>&[4m$,Kq=R_kl:isRWM'S-McrPN_%JnTkm>V\_8B6iRlha^jqf,Kl"4*s)ZXGs;N'BV5P:4Nl.^?lR[$%Hrpg0]k`kV-Q,*J$XQCpWb96T6(,hWPPhU`,Eg#P7A=[Z6mc3C_a2N8J(TXshaPKMXU&1FOfY.p>/JNNC6n;#+5BM9d9H=@L].6'K>HUftQgMe>^01pUj\E`tojaJYmk+ZfuHo@"!QK8_^\j>;;ma3dDc443*`FlAMU_'iuD'!+E!f/sE7pb'ok;Vt-p1bm^LJ(]=_2jmm+7H5`cc]qY@,70?=VU00b]`$VhSZXgWbYa1*g0oj0bnMo[3fEA$]r5Lm]W1#^0IcncH'=!o$I7Aa0t!a~>endstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 622 +>> +stream +Gas2G6$&ML&;BTP'mn%2mD2)Af#0c*7.)bhE?-:ue;FC69*5fl+;t4V82=S3isl0XICnrr.tPLd&$k)g!*BfB?Qq`VO?F_9liUAk-DQ&8e0l[F9`0Zc&3L0.6Pj!3OGAtd7GTrZ=QiU'T^QKWkF+\3N'e6V>Q[=?'F9^j[/L*RHF]TeA@i5kDN!H[ise+>^[N$^It;u)pJjYp*@%$*b(6[(s<4m9s3PpXpR@IGZ])p_ur12_Y14]U'?5ZP4lW-qLJX)ir9.>*C<4N)C0$r=773RNWL)fDpW+AP#^+':d@6/\Wm*PGa&eZ@8[E_f@C^W$cmXP0eroZ;=i;gF:C4qq-O]%CSpBu@OKbK>\BmM+VutPoc7c<;o@f$&9:Q_~>endstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 539 +>> +stream +Gas1[9i'e'&A@g>bQXsg>%4DV['peh;.PhqiX6BcOIBQJmG\rcr-H?m9iJF#XMg:Za#q\85_+dfJ$B3FF#]!_&.8=9aCmO7c="J800SmN*(M][i@p-9&Ln=t4CH;QC.W22;7T.L$KTEVdD.d8Zc+q3V?mfS221fP:&#pCJEo$`fof]/]OZr:r-%#l6f:bUO.\^1B'_E[B%mEHo,$"bUshmodU!PQ!Z/g]M)Bhc(MFa,qHRso)9Y`'C(%;oapPP.=B;/fqPq7W?KMpWOms8HH1@Dk@Sl=KH2(?S22.,3e$BT8WC.2e1jcWk2klPE'a@6##tJ8`d8iHP,.CH#L+LZE&aaO\I6]H_9;rgBW]N[JXi,Pg;">!E2u"ac-M1B4Xkk38HG.Ge7jZSB@>nHJL)fRaRN%Bm$M1jCYP2JokUbQ!Rn*K^.pYaD#arYTe5d@bBg1-,YFq.7BC)(6*0*eK!Y)Q.B?U9!9HfY>iD!_n%-bS=`=/r(i(fBU:Z:*endstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 916 +>> +stream +GasbX9lo#B&;KZOMS4+d1aTEC!Q+Iq_%]ZOU#8[li$.LkX0Es@Ou"8r^+8f?OO*IL@nYP+]?e*p$P$H[q2@(Z+!I-b>]B!?0#@5+4:"I8LR#K/]3X*)6d'88[G.$bMP(9RS5?6n`Obqg'UVat3k.nRWp\M-eX>;&KBk8%m]R,mrNI6"r&tO@^G*@hp92%@\-^"qKY`p<$HE&OK`<1mC'FO4l^8%)\U5U\g"m1Igt``#g1YH,L7M/>:(jE9g^a)sWYLD)%9(ce'JqkSp=WW%>H?(GTE["3.;jCK;Aem;FXa:X<9CRQWcPZ"U=fcT*:4Lpm:&\bnK)C\%6BXZiB);UP;:0%das4db[:i&c`dKf9h8fgo[0rU=[k18$Ec)N5eY_KNIje,1$t+G*++@m'M['=*V_Ghl&S33B=?@q1XLk.G\V@U",cF!IAFOebdOJ8*>lja`6<0L@($AjgjIAI2i+pJ@M^`ZX(9!>#M>o`A.tAk!RRl)5=F+H5(d`LV!/@mL;JJ7q)?\1K:bL\CP$:M\QBjeYQq3_Q^ZAB0eGoHO>CBCM5,mmS7(nX"L=FIXR*QNd$HAD:L/#%!VHg.AiZ+eR1pp`,[9"/NMNhhfNJ6_AW=9"CO32]f#O#=qeSQ43\[=MARC!/:uXFTT,=o-Z^bQ"h8&\?b!V?Y9)4"Kk;]lXo,6g,75gHk<`@*!2;eM*/q55FnEk-4.fTOY^#;`~>endstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 784 +>> +stream +GasJP;/b/B'SYH?(&)8P>;_iP-oBXNJ[@aqZ9^P=Te@bJJ>^C^D24#IqHZ0sJ-r5!OGJ>1rU.3S5'Z_pmQ8Mj"u0B?qqq\jVr2c&*Jc'S`JrK(?g[4QTbk(?rVgZ+'XZf/"gr60f!"HB;J+u)J:D(B!m`nb(XXoXcQ9ps-Qtm-IaZPU"LG"N31EAF\@[fsq,`CP6Mq:]o4Sgi`Xe.!08SX)4\%'jrp9a0&OP5r%(;Ko8`Em9G@"qm0U3!Kmo"cFVJ$Z>1^mr]1W?a9Tr[M=E'fIj5C9Hn:l;&F$AF$YNJc4:B*gN/;qgB?hs3R21kYi9X)Rt0X,\KZY30)]>T[UhP$?//,$B$$kB>4)N!pl/.bB7_W,pJ!'H/.W)=#QDqX#f[Qq4JC_t_-_D?a`s*KbLH#F[DBdW:(?UdfMA,[9jGmQG#21KCq7'#UP*7lr+U(T91l#u%n?&F#q1F/_hneRX/?gjn@CRuJtX`M:^6-5(tHXqb.q>9BBSgu9GRNg3dNNmWOXeL[;+lU+.oI;qb8p5f03;O>8f$_%aIHN2^OrOd/qgRM(Ra$*l>lTX4`AoK@r6$(YXDtS'3!#-)_A$12R"a`js!`Z]H2XNHD?*"^T45!g[`DF>b._OW,2tag7V4]WDYH^>Sn/mn?X^H%C/uIUH,$HrW8e`+$EW#rr~>endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 606 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW4(_);Q5g4'F(lQm*]HZP^hRn*[YT9c`4s`GA`3:UV1D^Zbd!/5).;4`gI?ZH$'l[Wr"U2rK`r7u^(_GL2_*B`MIedQNN0]F*L'QT/L:EIKfP$Zs2I7?C.S>\;^ud^AJo8W6"@#k#VCasV?@YqVFC_e,rnu;*=_JS3a#bVZS0Q6@ZkeNIHBp0BPDg98M\B%WC1Jjj?NGFt976"F9m$$h'50$@^IYi[Z]2c"t=IA1`k9\Brde_i)-@Z$P*u\M~>endstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2H;,c16'SYH?($EORCe%/!"b!/%/YgB$k]E?bA[Aq/eKc(m)j('qhH`sN=sjsfP!/Qpn*F=H"FPq&;eEhS),@A&KMB\Q#ht=sB"&W$C%9lsB,Tg9YY+()VH&ogZhB\+h.rOm]6@9?6WV/u=@,f$U_!,[HEh.-nO$BTHoSkE5T+7d;!&](0(Aj7N5l!=&p9*0>(,WA1[c5$/,j\%67It2%.Rg)Ji>+25)^-;XA5W"TLkI9sh/QQ;!&%>,3dMn>(ou6r0GN1nhIAg_S1sW't`)(o9Blcg*fHn7EGj'$U]Cn=1[MFdR-F@22tQ!:u3cZ[13"pUn=;6%bArS_JjMT;*2.L\8>jk&kk%AP!MPcdf_;<9MM["8:Wb4g1onhhl2lN_&3,3$hn3B1b[Z]"4WI.nSendstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1445 +>> +stream +GasIg?$G!^&:Mm.R$TskDB3I*."o'oOBoGnUqurZ(L\i&>$H"m)8cCLSWSnO9P=n@i`MY;4!42h!VlErgi&DZHjSc\>l_\@_C#VDr?6heR"lL((I>`U4G!%lW]unV:XB.ZI(,c4$a^?]GA*A=WrW?qajn0S8%nSC(+rYF+LmlWj8dm&6NcaYt&`dL0,cd=AS!>H@:*+sISS6#Cn-Ml%!flWut_)6UFmiWa:BPR>?@9?eXB\WW5[BjtnC:!"QFM+rtN?bq"c)P7phb`'`0aiFVfX2'rgTsOuU=gO+/K\\`]S-`p">JKL9:l!I>$f5*SH-Z&Rl?"CaN/=%5$JtXlN5lJZM[8`=7S-I2s5WV`K$h*uhVP^UP.LqBYkD!4#2X#Kkj2Pk3@:$%/b$Ga%f\Rf)@a^bdAOeK(sK@kY/:WW8p%h(W?k>lJ955t/WpehZr!4(]a;,jGGe&iSq^bTj11'G_tWPYOtBF9P1ne-maVG&cl?a[rQURK+CYh`8P:CoOsQ=rrr4KL46^2:NUbpSgG0FV;:t0eK9n^d\689[jZ1mQ0/ENY24;]BqfbV9a%X-R624=[ac_Wbo^nTsiT2tF?eMh[@G1*J,$7nZ?qN5mY:^5\96/>]U3j=eK%,_\;jBlE9[p06T\p_ckHsZjc`9^RmgmFUd0.<,oY0ZHj"++jb*I"c*%aa*3j=e\bB>9UY0'ABWj6rr[#m#[%Xb<4/1Ud!LEq6`O^Y4JV6O>Y#?_Mi'pk\;i7o&N(k.ldL*9\sA699G,%:]n:^q27+kVXSi1j@_o22bBSZFXYFt'<=P_Sn07(mc!;;DciNfc=P7<:l^e=o)f2[:LUFO`?l(::_RqqrN2*AbmaF0]+3cF_PV>8F/*C]B26nq&c:Q%MI?iUSfJ8LO7ij1I]HQnC%Agn,G\f7AFZA.WJoC(O.9?KoM>%#9+HWEY"B`NCTI.mEn'08eP07%gUm8J2`KJDBougM\C*reN.`n_?8VM!9moAkSN!78_h>fH@Gq]WrB?_a&5MY7DT.);s$K]n1j:sk^$3MGaq0PF-if_df")n/pQF1@5]?8pgd@oBbII$Es'G:$g]iGSFO;LY-f:3UG1YEcV?>AERm%T]H;Ef%)cT>/D<4*O6*p`DgnBCl~>endstream +endobj +xref +0 91 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002103 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003011 00000 n +0000003217 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007543 00000 n +0000007749 00000 n +0000007955 00000 n +0000008161 00000 n +0000008367 00000 n +0000008573 00000 n +0000008779 00000 n +0000008985 00000 n +0000009055 00000 n +0000009339 00000 n +0000009687 00000 n +0000010294 00000 n +0000010957 00000 n +0000013356 00000 n +0000013961 00000 n +0000015288 00000 n +0000015610 00000 n +0000016711 00000 n +0000017202 00000 n +0000019086 00000 n +0000020905 00000 n +0000022268 00000 n +0000022533 00000 n +0000023335 00000 n +0000024082 00000 n +0000026328 00000 n +0000027594 00000 n +0000028968 00000 n +0000030224 00000 n +0000031375 00000 n +0000032390 00000 n +0000032818 00000 n +0000033845 00000 n +0000034667 00000 n +0000035408 00000 n +0000036093 00000 n +0000036481 00000 n +0000037013 00000 n +0000037404 00000 n +0000037881 00000 n +0000038408 00000 n +0000038736 00000 n +0000039189 00000 n +0000039669 00000 n +0000040612 00000 n +0000041325 00000 n +0000041955 00000 n +0000042962 00000 n +0000043837 00000 n +0000044534 00000 n +0000045490 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 48 0 R +/Root 47 0 R +/Size 91 +>> +startxref +47027 +%%EOF diff --git a/ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_133749_analysis.pdf b/ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_133749_analysis.pdf new file mode 100644 index 0000000..a22d49b --- /dev/null +++ b/ai-analysis-reports/repo_analysis_cc31709f-424c-494f-a57e-e27482b4dfa0_20251031_133749_analysis.pdf @@ -0,0 +1,1174 @@ +%PDF-1.4 +%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com +1 0 obj +<< +/F1 2 0 R /F2 3 0 R /F3 13 0 R /F4 19 0 R +>> +endobj +2 0 obj +<< +/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font +>> +endobj +3 0 obj +<< +/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font +>> +endobj +4 0 obj +<< +/Contents 67 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +5 0 obj +<< +/Contents 68 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +6 0 obj +<< +/Contents 69 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +7 0 obj +<< +/Contents 70 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +8 0 obj +<< +/Contents 71 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +9 0 obj +<< +/Contents 72 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +10 0 obj +<< +/Contents 73 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +11 0 obj +<< +/Contents 74 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +12 0 obj +<< +/Contents 75 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +13 0 obj +<< +/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font +>> +endobj +14 0 obj +<< +/Contents 76 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +15 0 obj +<< +/Contents 77 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +16 0 obj +<< +/Contents 78 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +17 0 obj +<< +/Contents 79 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +18 0 obj +<< +/Contents 80 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +19 0 obj +<< +/BaseFont /ZapfDingbats /Name /F4 /Subtype /Type1 /Type /Font +>> +endobj +20 0 obj +<< +/Contents 81 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +21 0 obj +<< +/Contents 82 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +22 0 obj +<< +/Contents 83 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +23 0 obj +<< +/Contents 84 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +24 0 obj +<< +/Contents 85 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +25 0 obj +<< +/Contents 86 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +26 0 obj +<< +/Contents 87 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +27 0 obj +<< +/Contents 88 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +28 0 obj +<< +/Contents 89 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +29 0 obj +<< +/Contents 90 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +30 0 obj +<< +/Contents 91 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +31 0 obj +<< +/Contents 92 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +32 0 obj +<< +/Contents 93 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +33 0 obj +<< +/Contents 94 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +34 0 obj +<< +/Contents 95 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +35 0 obj +<< +/Contents 96 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +36 0 obj +<< +/Contents 97 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +37 0 obj +<< +/Contents 98 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +38 0 obj +<< +/Contents 99 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +39 0 obj +<< +/Contents 100 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +40 0 obj +<< +/Contents 101 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +41 0 obj +<< +/Contents 102 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +42 0 obj +<< +/Contents 103 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +43 0 obj +<< +/Contents 104 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +44 0 obj +<< +/Contents 105 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +45 0 obj +<< +/Contents 106 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +46 0 obj +<< +/Contents 107 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +47 0 obj +<< +/Contents 108 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +48 0 obj +<< +/Contents 109 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +49 0 obj +<< +/Contents 110 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +50 0 obj +<< +/Contents 111 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +51 0 obj +<< +/Contents 112 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +52 0 obj +<< +/Contents 113 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +53 0 obj +<< +/Contents 114 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +54 0 obj +<< +/Contents 115 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +55 0 obj +<< +/Contents 116 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +56 0 obj +<< +/Contents 117 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +57 0 obj +<< +/Contents 118 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +58 0 obj +<< +/Contents 119 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +59 0 obj +<< +/Contents 120 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +60 0 obj +<< +/Contents 121 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +61 0 obj +<< +/Contents 122 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +62 0 obj +<< +/Contents 123 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +63 0 obj +<< +/Contents 124 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 66 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page +>> +endobj +64 0 obj +<< +/PageMode /UseNone /Pages 66 0 R /Type /Catalog +>> +endobj +65 0 obj +<< +/Author (\(anonymous\)) /CreationDate (D:20251031134618+00'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20251031134618+00'00') /Producer (ReportLab PDF Library - www.reportlab.com) + /Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False +>> +endobj +66 0 obj +<< +/Count 58 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 14 0 R + 15 0 R 16 0 R 17 0 R 18 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R + 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R + 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R + 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R 54 0 R 55 0 R + 56 0 R 57 0 R 58 0 R 59 0 R 60 0 R 61 0 R 62 0 R 63 0 R ] /Type /Pages +>> +endobj +67 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 516 +>> +stream +GatUnc#28i&;9M$MESO>-#9JekGG+kCESI4M$T3,_+7dg77as7iPKLT8oW3*20)6l!"[lDi1"!r7)!V$>6XMa_r<0J1>k@tP;!#d!>V7*T&EP7(QdZ4/;e#t?hd*HQtJu#+\O&0(M6+UneB;kk0SqXUZ!\8>9kUoX8cDMsk8D8F3.[,V0H,R3;jf5]CYB4u]"oB3-Br5-P@b:4VfiI,S7m97!]);Bendstream +endobj +68 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1420 +>> +stream +Gatm;D/\Dn&H:Nn0jd[jD[Uh602S37@f)neD:,YCM3H:a'%3U(U^1r;b]r9tG6pi4NA-30[9?sPbM\1jJ)j)mMP?GZI0i9,Yi^)?VfoQo>BJ'c4V\6td03BtBbkc*;C]Tn19k(WR\\/H*["$^$/"U3aL`)_?W9,M"F6rYW2,Z"dK!;3cI.,lkrJ$n28JbWA'kEKDQtVIV;*-f'otr,:pA0,TFMd)PV[PSs@WFOa)p=M%E-E/k$FRE+C'jq5M\J%939/H.!:gPQPVT'HhgQrcg!p(MROKg$5Q\BE%*+^UMcHIh)8X]qr>2OW/_#S'Wr5unCN`\?:\VYa+.rh+$*-WlZrK$jSR)#(t:D%l$Ts<\NuugmF=qGjj_2Y_6Erd7PITie>\Ne*"9Hnjk0%e%$sRtaH4T$V4,^iMe]gjk^7-]3gErk>4j>gSoG2NO^Y5V$>`B%Xu;?i`eBAiRIb)2:SqXD\QO0h,ehK,TjRj."V%RdboZiHq\jGI[QR&S`^-?Ut0r;6<7!!"fGE#G=$Ohjb'>IL%QQ(WC7H&-sdinee=+3:^\JPBHrfKMnUN?e^pnM)Y(dY2i#>]42"rH7W/oBq,r^bs.>Lt!5;QFY<=G=?"-,M(L8La^*6e:M6Ka1eST6C[,c>l/SSU+*endstream +endobj +69 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 322 +>> +stream +Gaua6Yti1j&;KpA`P3N17+7[Te-TUsR:)ttR(@t#/V_ajM$r>1\V?2tkg51M,g4Wls4r*VLl9urg]DPN8PUB/[0B@C.F]qe<:Cf&2^q\HKYfRj;GM1`,LfXO\,@L=/OAap;-W\tUErKW%e[J)rlo"__I'_9@Zt&=Qig`&PV:anE9F='N.5TF>23QHLiI3/km$V37SK.X(;i4@<2bc+9foO20^cF?/IS`=MK(P=@U;.^s2@jVTcEND\Z:_i^r*=\\h5$5M].#f<;oj6^2p-WV693bVN_L#Wc[9@mG:rcUQ=Vq0KV?n,)U`(7=a;0F(!iA~>endstream +endobj +70 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2280 +>> +stream +Gat=,?$"^\&:Mm.fZ,gI#U\GS,K+H`,s\_VB@=n[O9MSj/Lnk6l*%iPaYl%'L7?;\e&\i%3d^SeOZhpdO(\Kh$,BgPVk6*@\e*0'4)^`Y3!;H.qK:l\1U!t?WdE=2^:q.t2t0,R5*1[II+Km8lf+B?Y13^Ed]D!dR$E^#HMr?kd67-!r@`fMmtZs&+*s^=n0o1Wd";8l@5@IBrr[p=+?Y58?4cltnDKAE@L/b)L-N)%/hcogFO>(?iTWDsFBoj5abeW(a`RFqK7WN+@`#[2al@Iu%fG(F'=]9E73GLT9*UQ]K]61V2(1%4W\_bIU_1grD#Qf][GpHrcK2&g"'M`COUAIG),>cb2?OqW3@1,PoHV3_/lN@?Ko)/CT>4ADB+\(O#kk0DR9Q%66?W0\_SJLt-LcOU=g3RUqR50ikb=TQ./OH?K&R)tM8Vs<$]eC^&Z1uL7n@f\lX;ISf>Mo8A\\er-8\K$n!?5Ni&#N\-*$TJmC8u*:h"m?`WANYuJq]_U&74.DQDrEuM9W%F9jsI"PnYPO$J9:>in30i,1ppl&kSE0$'@T3W+@<(J!"GtpFFigTJ;TG'O)0)2i'IHNS0VsiQI<9QMQl7Ir-@1R%+PP&.G3u5.VGu1=_3)V7/Z0QZ""!#LH!d(aK:k93dAc1.?qj$IW$/&DTLk!6e.A\9t#%Iq_neXK8IS8'8'[.=GqW\X#25V8MQ=iY(5n\+m8hd*2DD$^!O@IJ(f*/%+r6m$`-;2E!+=FWHuqpSEh=KuL?#P>Xa'cTs^P8TEAWapTN9Rg2)&$_8R;YV\.;8gZi-]gIhRkGOJk8Nt>"\>;tn5XL&;34);bL&@(4GFp!m8C!`A*#=deFgpgYaqVCFipP2J,YP=%]?AQMjnJCgf:]tAL:bR^U-%3/E0gl(.XF+$RV$++:bVaDZG?sG_"Vg7)Wmdg9cLuog3@Uc0T2s%f\!"t%qN6V=KS.jg$5rXcGc2q!TC(:??mmt\nkLe1WNncZ7hpW=:R#Pcmtg'i_3]>Y:u@VgFsZ,?C+,p;El%CPDg\lNp'Z5diOpNP*0G*1.N.gY#fp.N6S^mVfW%>[G(Au-$.M9MdBftVnd]#4KXfu5PeJX<(HDU%]WghiUcQS>8?(_6a^?ZgVM]?T#/gZXHiVdW$]j%*H[nl)meL#_"3%(=BX"?u"UId^,q91(FK>VMEoaus*+NsnkXWrq4UGuPLB)eDt(k`4(oendstream +endobj +71 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 585 +>> +stream +GasIcgMYJ*&:Ml+SB$55M3G;%.-m$J)i=7I50^5\R^YWY?d,q\$H?`Tn#YQHul6i12V`$Bl3nNhLJ!+qZ6%:+''k#=e(X5!m2p3qA-!1/)R:SD.j.J9m'9l71R/cL0n[s+@":hubKJj[*R3rl:UMM$etT7NQYKjKKN-=]u)di&endstream +endobj +72 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1235 +>> +stream +Gatn&gMZ%0&;KZF'Q[3g>;W@YZZG:h$C\hO;G1.878SMsBUc8#\e;]Uqt(n#Z/PJncDp/Go4T\p]^qdiGWp[3/jIV+UlACd;sCG_'KL3mN4r-*.EJ6%H="R2i+1^MXJB%]_r4XrkR\1P1THCO0g/.fNgp6%(OQY:e[Z=UA9ba/^IN""$s7f_$dBFhqq?q(+Y).[A6qtDRlG7R*4*?/[)2)X,'h1o\a-t_A!%/SZ=d'j;6"G+l`W\j:m'@he888I&42PT&11H:8I2BjVs!i'e.DVA&(,d`E]RP'OD[VDdHVE=Yjfl>dl<8E^^XaN"XSCU=dDgTjW]kB`W..%n]/8BaSV#?q"^%9BDO&Wl$"(s)pD&jUm+2&uuAnQ&`cLHVMJf!N6*$-8:0eJc!+(A?moG$7W,AAWBeMBY;Fh?-@c7>0SF2`XBb+e4!BlBcuYE/L>69`_u=U:T38NN)7$I[0!C[XCnu+Fm>NXjG]"#chACB3C-;$f)RF$p.qf%OTo!tI4gF`Z`Q%C!QQaZ$^o+>jTru&OXiIYkH=SZE%utO6Q:Qj875PSW?q&g)IULHFjAP"(r<@k\Ysq%-1SaUPgL3`X#jM#pH\j)ga9YuKpHUTt`,n0d+uqcXiKdp1INP&"c/8H54?=T&GJMj'02mksYjG$eh"BMtua^TB)'Rs7pkJ5mu#k#>c7fNi>`cOeqt`m=/&1Z;h]!d]#_5W$:CA2+J)]rT)#@J_jN4B1P@OL_1IYo3D3>[d5'D3fpj7G426E<3_Cg%AI?%ET'-P"l$)FAonOVj=,PHjjCi7Z:2RT%(eQn@lnsf#bb)6n?DmcB/m$\Pkoun)mprUl59-sIhbjrI`n7N*Q7FE,p@"47h043E5M2>$5@='U>,5hP&c_Sn/s*k=X*LE~>endstream +endobj +73 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 231 +>> +stream +Gat>NYmu@>'EujSYIGf<5TcX&7hV@8O]Xhu5TuS\`\RAaQ>/6'KRqpSbBruSPe_+V]o<)6Jac(##bhDI5lspA.(k=*T1to/mjL`U/@>pKYSI"@Ys%4&KtS.NfQ;nZQl^^MlPAKWjC&.1IoC7(7iZK,ZI)$$\s_2GDIrEXa4X(sPY.DmY%-;6n_F,ObSTN"YGBLmFP<[>BI#3i2Db=r%Z.GZT)JH,KD,ErZsit~>endstream +endobj +74 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1009 +>> +stream +Gatn&hf%4&&:i[6/+-s]h,\80k?#&-b/20:-m`T(8\DR49='A+3MmGhrL>]Y.5W2>,:!D3P5DcdmU@jmotot*[fX'YiG=/J'6*C@diJ[:!k-kZf>6..L'\(KpIs$keJ2g"V$gbc;:jfogC\Si9&5C*ertFmPh`8(g5\7drdaN\1`n^Fr-IR5cYXM*rgqC%TD$bPhq0=7rWW$PF9g:2jGu*?ncOd09"j)cka$4YjTQt-=Xa^G_$0EOH$BQHO/3pN@1]_P)uFVh5Q`qTLu1UR@J%JA>OlNK[G@W#L.aj-SqEa_BMPFF*_@-[6lu.)O3c9GBr0:B]:biNYis)34S^%Z^Od8U;FEgdL&*"g3f8>'$(o7rP>Y#1Ro1RN.=f;_aRi!DjJ;\6Uf%J-I/kH'+g9*5b.%"6(Omn<:ndtJ$CB`Gf!f(%T*-.lZH*@Id>0H:nT^jH:m8l*X!2XplUXIOaG8b=J#o>5e:"ms\Yu5-^e0L*l"(+[`CL>]JCpe\OpW?Tq;pjJ@S_j^JU;.Ku^,*lK=j3A?<&D*/M].8H1-2hL_,?c"=DVG([FaBo7eh".:L.G:WpUg^\nN=6X5;]LJl'^_>,q^3nBcMa1%Em)VQU`FMilQ:h;$V_%83VE+HBI-endstream +endobj +75 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 400 +>> +stream +Gat=d0i,\@'SQ5[MHc/D6]'RGUgtqiPq#c>:du4a]ECT2(Y^Cuhr>tVRo3WZ:\&OMn,,?Rh[OAXU]bRE>V6oH#]U&,),:aHE>oGF#AiQ363Q?%0FVTf9/saVfR=3LJ[1-9gI6S)aDXQ2n=E_ni#M9f;b&q">A.G6_@*H(WQ8?5oIfN>WKjh9;ckdjM;"-T3T6A5oms0M#^6Wm3HEBH:pR>DA?(f,UDZZRfC@N$c2.2:hSHE>SLIibR8?-'3?endstream +endobj +76 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1792 +>> +stream +Gat=+D/Yn7&H88.1&Xqj3N:N\:2Hg]&ogHoMSTNC\X`S/")E7e]G9"3do6;DblYn8_,1_9`iqNX47gZP@i>.'\PP0I$Um3_SN3-Q_"e.=WK*_;l4qOe.hracd3!5ML]^e:4ut)_Ye7;Q_u\mB[QRR/#4=6!R3arREJNJaYm_h3jUF+mY4-o:,l/`DkCu!\3Rj4^AGB]!:Yl0LnfC`61dj7KR"9',NaOpc6JDHZ\7>c_Y(4$4^N#on'M8ib/SNok$L.U6\r@QURn$cTrOEH/4tW_cSLO$Cpa<1*ZtlrAWAPtS\7WECKTfo*V^Vp>p(Poc[\/'9%'GaI=jj-r%8?^b\YUF#'*u5j(ubY/I+XQ+aI\c*.l700hhe_$PMei:/!CYm$Y^W[%='F"h%gl7^'T5"C%M)f\\d2=[:GZ4*)Uk*g4mHL\eFS_R+1I;HEm'+F*OHqGA6*7GsC57gnKrg/Z=kiUD?JZ7HG=]lB8l*[NIY:#,)A"K3m>UOLm3Bif(7gmSnEiijs#hh=m."r*em>,Y4I5cZujY0*=!g]dMN2o:1<%j=I=+@FQoa1rF&b=jn"TkptZNn0^*_A./)HoU)>n/F(\a.kTJDPCBK6rW\:5.7jm0d:Pg'>1FQIh8X'!;Bi[C'Pnh,]T\(fN^4:b[aD2PJ@bE#(^2Jp\n/Ie2SB&'DPk(%N2,B%X6Bkk/O+\hHV!Tffl9-KqXKQl[8,^ZH[7'q[1R3`h7!B@$9IroYR5un$K@77hJBL6^tU&`5L&X)KI_t$b>Q%lnnFDqf=3PJi_m?"2)tCB9e_$8~>endstream +endobj +77 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1727 +>> +stream +Gau0CD/\E'&H88.0rO:^E`*lno9qQb!HIO($/rZsH4jRCAq=e7YA\V.V:GP=cIrK_fMFHmJHYQ3c8.+8o?>jA.Xpd[2cp*&ICQqt_03VdK3bfui"*Wpcb>t'l,dNFRVpkp[G!3s^^V!_pF%p,XCC]c!`V$BebCX2;!CPD1n@[Ek7A3Mi>S/%i%1Z2`#JgjcIlYYM.Rq70$'!s?tqWiE(#5j0GcJtH4KrCi.$7ai?G'(68K9cW,8XJg;)ri`6]4RrO/RqmmPRd0DNfhD.e=4g1n"NK95Htc,[gYTt.gYpOP(Fie=O/#\G;*8SL"%r2Ec"=qX^L>/o9^eVZ^4Xe.Q\+Q,Ye_q=srcO7NaH7I[1ZSI$MI/8)<&^LBOj+@IiLO[U?rLSAYX-.:O;1sp:ZP.R0atGEalh!BYTKi(A2tf;H2h@[s#\.dp5O&(>j0.t)pHQ]62r3?hd.`"\$SX`;1g]W1]>A=hkt?"ZG0=R4H0U5_dm#\eA/F0eR,(W6erm1LW!gBg:6__s8h=:;,i"\fr+`nRc7Qhk3%;-'eS5t$XU%@k<^itbC)L!a!;22+Kd>'Ok[qq3).]KBl-j#X$8*)_bd+?+ct5ib>*`_,*KpXu1+(d'BVAqmb`]ImM-N%Drg.$FP"[B.KpJ82_:WkTZD^O9%Tu^YNFIBHN.?0XuhCaQZ+`9N+mqP80A'Sr3Wf#P:\rBe$Wrf=S1Cg;(p_UBfC2I)]8P#a!)"8d?V4?kPY]\"#An%,Zq"'%]KS5-*eQuQALF^=o2aOngS?[nbJQ")_,9H=.[`#FD48VJS\C#^:9K:Zt,W>$`W5bi-;P:93Wg_-hbJFPLC)7BP6pmM7\--#K^2N+0t.3-Ymt+p*b)78E<<2(Kc;!HB,TOM9U3Pj6P2OF@CRpLh,(fr*sCLYrd_,YO*2cIfSRR9A'@GAnt?&%KlOYA;@fmA0ZN0mZ*K$Q3UXH`,4,\[2_&o>@FCtKrB*TV*c5=L?SJodg5dZ+u:R?fO8Zgf9=d)H4H4Ddn<_2C4Th3^uASRfHfp_'(1SAEn9,I!Zl~>endstream +endobj +78 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1271 +>> +stream +Gatm9D/\E'&H9tYR%@96<"34Xi6_0C_`>\!@ro*IdRno?fSd(mg%Fa8PG>n,ZfWP7P-d:#8B>SmbVRSh1LgeRpp98cF9O?nTRCC&eV.N?pr&C$b.HHA"9sZjBUsZ.NA_t4)4/Zs$CqF7GZGQ)oYYFcdlpGh?10TVecsK$s#L`a1S2?g1`'e;OPE.m'/T`nes*,;e4agZ/=PZ`r:V2Sqpr0:pLoW_qUjbql.[*7lUP)pQ%2L$P]sR6p!2:?$sn4S@iuK^_!FJ(V_+fmPmo?N4If]VAOEp=$(Gc_]6EMiQ2UOgL27l[mYAo%V8#RK7\A3AHeR\J-?TH4A`2,cMj8WRM#Iq_V_i%>QXj$NpO:U3PhDJu'A*m+#8o21e50;EQnng#+rmNj>k>gl.9S,FDJbAn=7od\9K,h6KpEV6EOa%+(1nJX^_ONI(gb;O5sZ-h&$>nd*Lt.AsH]2Zf&<6;$m'5=."g3]pn0d7ok1Th:RO?fWaY_1WM:[4)8U.>:`_<>;fj7k'O;7Pre=&45jD4#QAXdEH]S7?h6l'[4YV+>$_^eXNPl^"<,7\#e1`%/tt#E=&92_TVgEagA`L7;L&P2@e\/am"'odehUd11Se>IdR\l:`/?!BY&[?OZV=,TXdu-Y4pCak4$1MUVaf,HAZBfo/pZ4?)/9eTUF?U,c/^N=Zq8Hi4E9*bgZE8!nX]'C:=P7A\`p_RR@kSPk's^NL_V>AhoG2bWPrR?*3SBlrb18K'B4NkI(nC#G;rc,WZhp&;'DB+HZ)Ps]uTendstream +endobj +79 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1145 +>> +stream +Gau1-gMZ")&;KZN'Q_A;6r&D#mqAC-;L7!49r6^VNWF?f3,:U@fVdW38I82pPZ8HL+SPa5bkR*+%pZb0qb8ksX!p"e*dBkBBAdpd*LOi#RU5p&n>_mR&#)hGme-E>N5,JG%`nGL`d2D\%*VPj#Hqp=I+JY3-DTnkq#1aaQS9CR#NL%cK^8No#R5L*ph;LT^ss+:K;[,W2jh=roXjYmL"EcJ(EN2CfD\c!f&(8\i*ktWMd/o;VG'o4tC\quO9a7_408cD@GZS]UKdJ7uEZ[VP=K/uV9Z,pGb*,0]>jkMr_B29Y@Nsu/l&B4;W[LH0(IEVX4E3-=Mj3N2ViJ3AeMmbFr[lQ"VJ&tW<6&4"BZVOkOCWFNeY.Cid%=K.JNBuQWnN4]K(l?t"g1Eg1q;9b93_-UmScC12mTs3E9'4\cd'.2TrA^4;T9UQ5s1$A0B3/>4p0$]aVIrPC1iK]L+;k"?+CaZ>:J*28JN!;7Ie!L0)Lah8X'WSDp?BWqN^8LQV*/EmN6A./.]JdApdoW9L@f7eG,XKM9QgBk=!]^P8#)Odk8hb:QtmkAS64oK@K[EYDF14)kKVqfS1?%#6ru%5JbPnPGl*K))(=sL8Mei)4Pc!D;?L+]B_G$A!5%R./oQ=6AUnD2fgk"^-1J4g1J?+t>_:u>^>?9nX#.8=c2!.fH4ZqtNi2Idp.n>9;%)sL`/$bON;pendstream +endobj +80 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 617 +>> +stream +Gas2G6'%Kh&;BTK'm!&!28SX6d+l'(=,N6-d["Ar"pWYDZ)MS`97MB1%\!TcXK2QHj7bZ`o3`-W@c>(8!5>f\"FRaF7K0]k%,#Xk0f?VFDtUdqXTZ=X\N-&Ia+DW(Jm5eKCs\cj#E7n;2=:Z,&nfJ(t@4JF3U=gS2"5"[TV2_Z!NG;cm%o&9K!r`uRLuQLqDs<=,eT/X/^q8bOMXiVH;bKIf^D'=)=$M(`PVTc.F#4k0OM(l[W>:DUmE7mgQClG!TXp7Sq^XZ4&9NG_d@afPS!2O\#9S`'EjitbkF>S3BJ-MCFiB=*n:/&E1FRMS77%osA%6Z$rE#I`=nVbMY@E[m!PCs*i+53W^A]rN3iRAG;GV5e2rJ`B"gq'tW%iu2KLJPc&>Rp>j?c5t^/0%KL3UhW>>H!KuW4hfendstream +endobj +81 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1399 +>> +stream +Gatm:D/\E'&H88.0fl9@GA8gT#a"[O3D(npjQ3V0lD/g\fF-PDn+q4Z,[An"hV#kN0K9jo"^I6[9QbPhM<_.e6M3$4du.QUTR(J!]T]5RdsjqoTK^Lq!Z*>>D0]"PhINN^>\iT+DUiHTH/Rmc/liI6)/Sddn[VKhqCd5+1_TJ[.qE>W#CDk]0&,5I+g)Oe"]>r4DMI_TAhR+k:n=?6Z0)e*K71bL*'CNq6`:*k0pR5k_AU.XO3lO038QGg?Q&E_TVlrK9Dn.sn;XMdqlhbppQGi-VV33?b&<&Gt:4o5+@-lIAQ.Cc6;n]YF\k_o!=ZCo>bV+qULMhu%tgZ-C\aBX!XI%6&tj6^K%!I$jL1Qm<8]EfM\L0m9Z9D_21eW&:aqNc0+s]]cNUu%Vf6^E+MP8jFTK6UZJ=G5M+Z/-*a>JX^[=id4q\0Mr9+c3GiCbKa`En)JsUY^)oh$3$>/pWaWsU;-\9*$%3_ub7B(L36o\5.E+I?,/(e1`H4H,A$7Q<3@B[Med>3Hlp)J/EPYi9OZV(rte%!5-$d96AJsdSl4XV6F@5JFD*!oP9&h90cEYV#e+]+3cMGkATUT*-;`O)i8%\gZ`C%j<`)\#7=P.6QupBha6daP@j1(?o\4#Mhl6DH*r_hAK>6gNrEcrDmGP'uZ?C05$i4K@VXXE!n&'\eH"E^ZeZjPZL:(WbLJrhs\>E%oesJ0aEAANN?h9G+D_@X0CZK+1<$q\Dq(,j%Xp[k("g?*=.?0Ziqj+uOZTD`(G_s*P+_RXmhGm7k'5c*&d1"W)6sk(BpI2B`/t'Y02rU9oAN3A:jCVaUkSc56Q9&NG-<=JT+^*f9>njCKZ&kbPf6'+IinCL*Y9fHLVeKtk@@),Zn5W?tWRq$lq?04&\$Dq6XimGqH_u+*l$+nka2:$L[@`T1YjkZhE=D)AaU12+o.!Wf`6uA&S`2@%O>Csc9g:,BP+@ta]&;3F%i^BFN$_lUndlkV;s>I*#GtVrJ(RLN))=IJ33I1Z%e4CY\+BF1MLfqtkc.HdKNR.6X%([Wp$bRc+5:1p'![kUKsb]seRBKendstream +endobj +82 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1452 +>> +stream +Gatm;D,VB4&H;*)Z1YKs\WbhE*3^FrVZR&-1QW79[NBO\M7D4_"JWNVA4`GjQG3%m>J@Hd%DKL5TcK7;pnim3bS%Q'Yl\']KU+\(R[1PrAu,Gm=fB2#U'_ZJqm6F$qrZN8h*Nn]-aLuc=%NY-3]-fB4jF>o/j4#f>d5M4`X*PcGMq;^]61Ygf'@Y!XlTmmCIhn].NTh(H'6S@n\.6J1ESjF4pB*PO)$9^eVi'+),pB/VHU'!5m+ot/(KM5h39EQZ@^KZ=hU#]_S_E#Ur\n1N+]C;9=.iCi3FD\?(N'C;[Fu;L0iR@,aN/DJk)3km_]ab9QrEbNq(bml$l?E(r00qNJ8dO1o6dq[M&"$lV,;iXlsdnUNt9ZKj$>AXEb:\)H)iWY?n@*bnN'%$/-7F@fpYCrn2po?KcqpWNs/cc2@_Dr1io0"LY[!E>b`H]^(%Ikms&._6C&$oCT#YFpn!9s'!?k2N-hu\"I&*j\irmHGs#*g?]+cM/#_U0ck[6oI;s%Y(R"7,]e(:jW@Gj+?P(q's"t$]f,l:WH"HC/\XuR?eJd)!OCCe3&?/.!Xd*Kt(W&@'5+S]_g,p:j59*_b4l7.B2*ojg-tSXKH*OrT:15l>iM_"15NV:,(3ojmGGac]PABEe)l7YTtaP@%tkcFprV548M*li1u(p49>7SM=Z4q,TTgs&lMRZ:ioY(I?L'1Z/Dj8Y9?Qq3kd^SELKBC]lamUD>Jp`k:Q)Zo0P757lniY,P3S$8b9Jm1p?tM1=dJ:Be$_`L7%HnJ)C:O75HHH"pICB:`a$c58th7.mC)-,XbJ%A7VNSil073tFIt6t%IMUlass>E$[FescC4LnAO"?#FG%B2lH]<%=Gu'23Bbs'QYA&"bufnMJNq)@&TPcB&j/^(@\;UlOl@o`roT=a4prr?RqUX2;SeU$ZZSY*n(=`hVECp*,#"BbbX=j03hbb+c_IJomd)+YW8mf]dW7>'54k?q?hp6O%prUD>i0J/[bBXt[i;^;[Q:O&H[DS224q;lD,QRe\%9!_m9uARY,?6?'KtVu*)Tc,Qt*M0AD4$eX[NWK28BZ7jpJ)sDHMTeX"a%tD)`1UKfMf)_WUbA='#a-:M#r>Q8K3EQ7bqNbsk@7r?pF^q[5kGg#fc&EOcU]:Mfo8S-,:Y$VH.[/8_X\Sln`HhC*;9O0S8ANO6m\k+;_:mF(VH#@(,C\sM\*'7r_UpHg%fl#"$QcYkr>-0n=Xfet3k\,M.Rs-4mPZ'`C\I1bFQGbO[][rRnT~>endstream +endobj +83 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1192 +>> +stream +Gatm:D/\E'&H9tYR!ttVVdP;P`,Rh82'J&K8pWL:.oiDf(40lkY]npZ2$ptW^N\9_?t2:3P6qrZh3hoIfm,@U\Bs,!qWgTNf+-H>!=UTsnR:q

XUt/oH&f2SVpHE"4@6^HFN6VX&,Mb"M6L=h`9=5:-2Rn&m!<'Ij:Zp8\6n-E]B9Ne9g\%Q.%Gakl7J1Vso/tu*#p-M^m`6:cU`V=M;)n?HWj5hp^$<_pjfHSM3K"Pnj`/*\A?%rH_#,WY+_Bl6nuBd@18>\XYWM`L#D0m`IJ$k.iuU?U4sqcP#>&EGlBtZl.QiND;#A^p]`B>9O!N![m?>&Zr_*IZZ-*#e>N^hHs'g:$_oYh=VXRkWA$nQd\$Y+A/+'X8:4LH4&7SM[;PK=4NC\TrTlVMsa^%ib6)nS>>u8"M`Ma)=QIjnk6MiCe@]%UglYI^8d'G6k9sKdP+:H\2_F#s$&)0,9W(Y8rSL>CK44YH;EoH[!`Hp1B4.S/*:*j2pOK*^ham"f^LH[gMeQk>\55G1:g!G%fn&Faek@^1,(Xq]NjV7QqR,6,Tc?'*5c`^`l[OVd+(BlTEE(qT10VD>@"_1[-^4Kp!>]!;.GZgTRpudk:P$q?OVoFLS[Ham>4uDKF[)CPkohnt/XiKohk*.lUG3)Fk1BU9r-b\rJ)f$bA^^8'ke\8d_'t5Ml'.JU>KeX:V#GF%sa<%E^[;d*W21dUkX4[#pm$IEQo??bebW0=2@KSD-3nc(l9pMs-@T'k\dj5)jaiKG.W@.>sE8.m-=DDMSEhu%WSBO[_^df<>F"Yabi%I\GTZ^%?XA^O+_de>1uC4R0s3rYNZ,-odE0N9OW%$Y,K>/V2]JYEYYR@k\Yia:[*cme](h9?ERuk+p(`pNeI)lrs*n5bjSpm+Q(%B%TLN%s2!Yc8DS-nHW$JCEOW$]lMXQI`:'M9kIQo%Uo@2*)QrGendstream +endobj +84 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1724 +>> +stream +Gatm:qet1Z&H868@YF/%PS+oK?HFX?U4K9,-u_9],,n6R[6a5aSe)_F=uX;BMH/`OX+"g2bH;i]!ap?Ho5\?*@=G/IfW9=^1fHap&a14$Ec4q$c7tkYqU@*\@p/:uTDc`*rS9ICK.PIRRKWE`D-j'4INUZjbhf.8\u$1i<*4[IP49/Garkf\h2Jq&B(?lqFjomCMameYq%*5Jqd:3Sam.Q*-Kp0hm2]'JN9BB,b"6M)D[#^*5E'bV>_P*H[8;5l6o:pJ.["g]GGXQ;63;1p;/_3-n](YUPSC1@V5$k]8l>T.?b*9(F:KY%rL$nFl`*0mrE4smkZUF%BY:b]i84=pP$T5Z<09I!HfM:V"#7:N/G+alH)#V3O=^$510STAo>KUO>#W)=c&f8*!$l1#'6B2Lsb"p%lI#lBeERMNoV2.e8sIL27+lSXe]Xj4iH-eW"*1O*i/6*/KR&95Q1h\nk+S;2-N)8fhb2hQRk46[7O34afEs!.HmmC,_R&SjLiIP^5_N7lFnJU/3\a-:10_RtlK.\n[0Xc"fQ5JkDG^0"gu7Sa&#Fifli&;:=8BlsG\1**]r3qP@ZYaoK9BUOr#9\EX?C9.,mAEbBe:9AJ?1)TEki&[#)ImmY7[5W2Gdkn0>HM0^B%qD>g2p)a5f7]n1HFSD(;s$%NG7P^OWmRnQqO\8!LmR._V',$ZDj&BX9th0/e]c0=TrAoAibPs!A7hdqnj+'tn+J3,$2K#A6T_d.#q$s%uQK"27k`l*eeZ@nK@&47Z4KF7J"0l4r#>"p_j$&
Qq&*4rteLGFe`N(4tLYJ:E:\*epf=Hal6HCd-T:(O:AZ9E~>endstream +endobj +85 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1840 +>> +stream +Gatm;CN&2l'`H=\\;R^DmEu+c"fA'j^^O2[D?j::X[^4,15Q$-':Z7t12+)qIBW6mUa0Vs[:rVuZ$l&Xa7gY,TnYf)n?:jS]Usb'>DIM,AkT']XX;9[TKarT0@f*Nm1(sW9rlfie%lcq?cS<^L%L5Qe/]2o9!rW4>a5jN=k'B9j%\>r<$1Y6TOZnAJT>P#+=e4uFVS4>XD4tlQHap)'$,&;b.LiCGI[0*ZDi[rV169;(.,&0o3a0TFqTA%\*10eo]="hf.gt_#/*!g!"?1nEJMR.h[:68:mOjan!_j,*kEYjgb"B[:D8TbL6fWFW)-&qO0Vqba,fMoX)@1Q'=]=K$f[@DoJnrT.!Wl,i[.'-n5pM.*Jdn;?TB[XV,T-t1H&UmH@g7Yil/ZCWY.cqE0inSXBmeqU$+T%ol%J:GI+4(k](i+lLkXgNgF.\o1G-d_FIUSo63>chqH,n3t7jF_u/XbcLdGp1_^(psAQcS5**se(:gjG-@*Boiq($"D.=Q\6N4.)&f"Eq0<"W$Us,`qUi@F_=qOZes##X+(6A(9Ei4Roa_cUS^#+M8Xlq=4I'ek+#Z9EE^KJV_^Eoa7L.E^(=Z]jr7j''--I#Cl6VBcj_8Jk9<>+h[$08T3n\SM(o$]f#O$?emqHqI8tcoP$e]T>8ok(aXH*?jYV[&n,U?CRRZ%'.eN^NTAqn2Q\DJUQ[5E9YJ]m9EebcC9"ChoSQ&@jb>ig*mVWJ^ubAa]<2:Me_Y&NMHnQ&@Q8'ha:++!kh'3Ktl#b.b.-I@!Bhggk`@g)ms-?\f67W3uP$7"-q#nVhS3h@r5hBj0nC'3XL6o`)r'4e[h]:&Z@lK9?F3hfGCpG)iO")kJJGuUF,qf)_WH2q;?E-N%ZmIl&CS?=gG$Mq8L(X$IVt:A=JDgg`):N1UhMe)'nBhQ5\KYY"G=6W:V_o&%d!*m#1G??mnO,:C)ZGY0`*i@T>>#]1?f9CI0XQk+%F0)?oAi2na.+'_p@hm@+_L]`E]0$qSUZK)7Q$e#O5oa5,C*r;BjE:L,rG\*"87=!j\Q)1o9dj_W&@"5nYQca9<3Rga=R?e4geQ:i\)WbK7R^f`E/7J3(B(M`X[]Smm)4KMgbq?K;cGS'~>endstream +endobj +86 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1677 +>> +stream +Gatm;>Ar4d'Ro4HS4-VHAhPe4t#MI]ReA4o!Mr1:GuErenC4IlYR#J<.=:-2A%^;=u3?P-*>[\K5t-]XR)*KLU1"hL&n$@6-Fef8BYDm^c]Zg&Ib:?Gb"bn,[XBm5\[7/$PORZ*sPp>E!f[;lh86@nEK6;e(r8sqs*F>Ifo/53n$,fQ^/q#,Y10:/0m'HmYh`$VcL+]=BnsscDfmh_WatH-t:W)k/:oY+7Q8eme&X>VoMP^d(R33Q"p<\Bsm^MH)@nD/jnG;>K=d08]T2QH3RQ'Sh\;PP=Q&Yd$uQWJBptu3TKN9!^LcZ^>$K(D6'YQ,WhZ>5Hag15Kj[Rh]Af!a>0%HD)R+L1#H-A.mciYh>mMu#?r*ItYKn[@&Pnq3-3@Nr764dSI%[c)t6ftXAO\b6;hO9#;`jYJZ#+lkf$&'Eq@rEdl^9GEA?U8Ht[5-i7lD<"\"\d(?l\89<;)k=:WM/'Zd,s!TpQ[Io7R@h_1=%Juf,iaO/N9uVOkJ31+\]^pZ^_AL=YRQ>a"%?;-LJqjgpZ2BFrL#d$(*gmjJZ*_F\W?9R>h0]V&Ba(W7JZNHuiGd\HmbO&gJQ1EQWM%rVJbqWsr@lQs;l2rbrKp;co#W`KH\T+6(OR8e1PgG#0&^(1pWd;orcU(8mVY$tS#rk/@b]/IGnZ!T;9(QBBJl=B`QltHr[/qcK;3*@O#+M:.j@cZ<$E'nj/fQKg7RO>16]*jAm4p=T(\X/T3S!JNd4KK,if[hAccgpn"T]oTCJmoh61ON5a+P(0WQQb/K*s.%ejqAM%kq&8F[/L%\UkX:=BjK8!jkKP03MaY'8Q/hFUu3]cI;kMfRJj"^6p-Ku@oe-Fs;K9U$qN+b,`lV5BBc3rN?n82Z1V`85q@_>8fDm%0a%nYp$r#!5%877n"i]`)1B:VjL')>KGX^=]ElVTcQ-pWqTrp9S6rBh,I/''2oC&;MH=`oo,]rBSt!r5UTCCu?Y:OsiGQO-n=^[33>+rH4uC&<>ua2ni=82<(jdG@HB-RHpBQKc?3?V;R*"C$ms6E_S&elh[GCJ-Q4!KR$3e7`llI5C!"OBs8,$/1h0:pdd`4A*q:[FBE27"`Y^Q8n;b~>endstream +endobj +87 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1224 +>> +stream +Gb!#[Io"fY)#h:Bi]X)/m>\YN=5#EQ'6"1S-+%Y^[==JKRDbraS2f.rTfV`"pY'?0UeQBE9fc@5ReZjOpj%AAp7R1*cTQmdi-5Ub;\-N)9P<8ma8i)ME&):d[_.mdBFNa:Nss&*A(52*3`g,EihS%El]h@>P,@O#?^GHfTf?C`hIXC0@V@hS-_'FUN)b%NJ?DFi8#G:hZ>_''5PR?feGKs_a`K&jG4'N'H-?:oW=`t(_a5H4Bj[Y!^[k//,VI%FU1KX,W@Wn*?jeFZ116'28qg]uIbLgb1SV(,5LYAqhR8h-X;Imf-Y_luGdK;1s=i7P,(%BtU>VMPua#aOU^AI;P(r%]n9a#KFV6sSt%@PIok+l1i"QPt'!_qf3b*d+rDRSkE=3Ds:m',+iEKV56,t9+)+iYeQ3@N-_5arrt*`l"P^3kWr)N(E=+@5r;X8*S[FE=f>@6q"\8Bm_R^.O5+a"m4/*JUKal]WkA!B%\51M$'UaB)cWFga:I_9NW;HSkMAWbCm\V)1Pb*+ZP5a?Z>&"o$nUCG2aEWi_'FCNt#DA>&,Y=W](+k&N0YmbG[2<o?j;,CkMX0"WDd$o)ueis7.GAZ9=oU4@BYLBLHg9n,GtqPaF\28O=^qVb2:0/hj"`Vl6VbpL!5l+X^4[`NZ!SmM`'X=Dsbpn\:GWap4CD_^Y-*rj!tqts^h")!L`:c^h?I%D)9qXf%'E:Lf>bW*'-[ASX.*st_/#^jHuEf:qQ$fMQY\\,8]cFD:,&rL=@3HO<\2-7YQ_;?25K>FLr)Ji1A]jg9876GKF*/oF?pNlUo%*-9bBQ)qb@%Zl,cpu",NPsWi/m+2bDO*!()EE=>LhCioj",RZJ[UE.=%6#1:[(/0F,3njSo`P.%Xi7PJobY-)_+,9rYMPiRA*bffJbqg\F);RE@?p[a0:Ns/X4X:,77W3!6MLN49~>endstream +endobj +88 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 656 +>> +stream +GasJO>Ar4\&;B$;(%Xt#.E.MOadYX)uU/lfurn#T66E)C3"&*l5sc8VMXTLVf-I(9<1BUlDhM8>rIe+/31WeaJ2]h8rrgc]]HmCm!R%O=0YS]6P1<-4-JN*`!-!BCYV&OY/g`nHXrt_>5NB+7'6MX$-=jY5QP`2oM>sm_.QX*YGtDg<*O:1e3?ZPA;Q$F^s!12q>`']K:Q947hg$3J9Qo.9ZCh1`F2pfd/s2,WZLJ'V'H%g3D+R0F>'=&\P3lY+`;d;5/)*Vk$!bc3_1;o%fS"i+k;lhGUPR^dC\nZ)RpCAC8Jk6I29UUh8JYeN:SJ>+DKE7opX(7YOZ`EZV>Ur"gs>TE.!OQ5%NGYG"1n"=`t?XSk_0[VAXK7:I_K4NA5ePO4bUE7SKg+?okJ:`5_d01Q>p,=J"Xpr\^cR$t[%-Vh;t&LcTK&b>>G<,3V=4bp_&CuE/IN2Dd1L1'G94N[*;J1i(N;!rBEq2lHOJ3@iSnH6*2Ng*.hJR">GdJ7c%&Tcc,urKknR9E\Q"4fdBNRh2B3%q!h'$@:n:Yd\]MJ!D\,[eIbpYX*Q>US!FT);)92ci~>endstream +endobj +89 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 2180 +>> +stream +Gatm=>>s99'Ro4Hk[eBT1W[0'epV"1g1H+`\YO.l0o5nZ`6R'H[,!s]OtFdNM(Wln!tiSGoGr?D3^/i`5iRFn^ParLJ':4N%KfD?r"`ZE)47%KZh_F%#?W.u%&Aj!/B]is6X2nTL$%egoYkE%d;^am+oj!2."^MFLY$1:o@`#n5kYu+S"60WK<)?%ca0\*VtXTmn`/;pZ]k2&318+=5"XBG0Rj)o,KYEa5.`uim.Go<5)AHrIQF;!iO%Q4a$B_a9j'Dd=8q,NckSJi%dI9Fh/grn)sQijh6\34/Q]T5CNY=DQr)`PV/5-%`&LIn$6Y1fYe_SX8/b,+/('8e.>TDSa!:ft#Id2.0Mb9aEWG\>d@A;HN6ngsJqac@1%Z$@&t`UP;W`@sU%!%G"/[cu"ZI126B8saUA?p=bmk@R_O*X''/Kk07"7gudF9ad*m4_*ULI.Chhd/9._\Di"!P%mRDpq@a[g4+V)/j:Ambb9#U>6W38Ku/[>BZ_@&I)4q<[b7gu>50LZ3mBU(2l*+&R3(<9&4+[Yt"0YE#Kf9NeEk@3OnaXA9i?$W@:/f9emqQl1ukS?6HFX8epF09-q^>A1E(g:7c7g_2F%-s2Qj,TkScZ\Xf2S<'ThFm>tBH/lVD7+0l\[Yl2aa!*#!aK(=BOJGWo1b;$8K6=5i@:AGsBb-6+Tec^0f%'Jk>r:Z?/*lKQ+$+^5:ZuIoO>n0E&P'[S`/06`PrQa>I4=ugihum+OeZ;nEVm_3K2T"0Ko*^%$t\sL83.[]C.Uo+a?8Hq=@hL,G=Kl>JUEius54ZH%%/QNLa%_8$-JBHejW`T+PE[oR>"_CU1#4F&9fUiW[N[1'f9Hsg_hST:Bpf*Tn:-:Y_!%8K%q5GMP;4';,H^&c;Y:\E(X,D@UO@^(3S0tW`.&bA^LU+AC7Um=Z"\QMh_"<8_aKKQ6l'4h3Z9YH/4N,%?!Sa8_dHMb+^#-=lLS,@9WmtPVF*MC1W@_ouNk86*eGcI&eE>=fAq:<=)aE?7k.$!NDnPd'>'%*:SnF6TSbOhLqq?_*\jP[\B,]Dj)(dkC;7YlX`)4_5lsCg$uIP7e/^SCO!+=%t7YU@7a"s?r,0#MQh(g\Z,2rUJmXeV-Qa5S&Or,Pc+D4GqAbi)f;$ac(hRJno+$6Z:@05A!CMYNk&L?'eDb8gf*G1JgaHG*i[;/Q:Md;T\Q1kJlKCp?'X:K-..[qSPp4R7$?%uhY**\:k0gJb'E^/AR-%34Z6)[O[f^373]/]f2cq8O/;IT'_5<&d8W(KW&^"X)#\6V$:LnAB_5L'h=o*Z=qh-;@8fc_dHV<8;\_0))cX*RAg8UeZ)f<;q0g34RdGb$'lh^a')BBgo^TLr&u)+b'kQVjs\Oe'AlLOe:Xgripr;dS6u$&mBX,$f=_nJ)qqPj0uMQ)4lr!CZ6j("b)!K`QEc;[5ZpP!=AbfpU8=t[W&Igib?.]f-Z:@B<&7^?O#Gd,?ZM)AAcHtm5-"?%.Vo(e+X`T%9Qc^,4=`P\kS4g2YuW?9;0#>;uMS=):+aP5-G!6G4N("L7\fT>lD^?",`5S^Qo0a>:fC)LNgZ*f6s#60NU<:Tn+9omIPil`se1NOXGCkrk7`*cC*A#UL%03U@9ZhLa^6iQE2'4E+o%8$CK_Vtt,#h.`Aqe_R[Dj+C%c]fcMH$R[=-C?OWA:Hs+9Hs8CBKKs[#:58pD&N`/C7`;S<"]3cH`[EYuqRcHp&(9\*8H4/FNkjhXm!oN6IYkP1'H*EW2K/_T9RF+Z=d9B!=;>[';)7'\\bbdI8,Q&:qT4ABrrCYbD_V~>endstream +endobj +90 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1107 +>> +stream +Gb!#[gMYb*&:O:SbY%sa5XeOoV_@?FZ9Wu6BY.I7MdI/XeD2EE3ARN%o8%QXMX4M8F5]"PM"!t@#o*u.-=FL7RP>+JXb8tX"-^_+hc`9OPTO&m2Z9*Duu"oG0j!qU5?YNqE/dHNM@U#`sZ0hF.srNip[)Z4h$M9jC6A)$i-pU%G/D\*'Wpe\<(tdGs6N%9_Q69TQ,8QMrr>kL)$joE=glWW+jcD4f.b"5OBJ?(%YaZbX;(7En%T.7!4*4TKOqM,gk!P=#OY>+Jan9Y;Glt*O<,r`U\^DK]hTGlmSA\\3sYCQXqaoUZ]KGs0K48[)@@k>bLKFV"TP*K_RMB:L=&h7Y;PBJe54+e/a@W/PT[CS[TTjOAJi-85m9W>o^B,;jd.sN'abI;g'l+/se9P)3%3g:p,L:X1rXD1Td#[W(NmYZ2r:#/ZqP@&iaC(o:moY_Ii`]pSJRtHmq*Z]p.B0k(&fK;3F7VF/3g3?EXbaBm/qSt?KPe.2b"BVOSIIKlk$-WC-Qku`d')i:lNRk9:oW.`e/PfeNb&X\,KF6Bg-KlNt.j_l-i?;f>CY*&T)R0oAGq.hlWf(G#eE_2JFVV=gQBCoAb/_B]J]r1-FVjZi7lXe4APkSE.bVU,,\.b=Q@lM%AG4!EmRpsb'[CY03nI6L"+O.)kYH)#1=Q>L1b!MG_+PuRo@5nLCHCN:J*]+4_Z2_8&'34$)@M#kfVf/~>endstream +endobj +91 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1189 +>> +stream +Gb!$Fhf$st&BE]&=540]LP-?(GK1'nL4iO"_()&Mi[%@c/W#CVQ6F3HcIr0$VJUq+fP%$LD/A*XF8jtJVVpH&m6*$%hN#GJ5_458c@H0FJFNmt`[BY=kc/9c5TE[b,f9aT?ipn4)_3nN[%g-)`rkTF40H9H"9osUSo^Q;V_Ghj3jKb1n4o8qYA0Y[SC^SY>sg(tDYoE#)?lc'C9$cYI8uLfQIbpWcL[R([>'j$Wl?^(&V[0532oja)_/"5V][Y\.HimrKrjtOU!SC\\,_.dVK7aeai-EI6;/m,rE[oOW2Dt70S/U*8&LqX/p&[;Au9/k9"lt,K;kBAm`84Kj*[aR)CCMSakIX(8HMZUS/%>7N6OD@4R3Ut-.-`&'ZIoYne=OLs5PO8j&Vb'^76j%o(N;n(+eQG=_(bh.oS'Xmb%=6Oce_t/_JB8P2!I+rsP"FTT,ad3,EGh[jRP>)Fm(%`!]ju7^.u!EJOsk0B8LfZ*+`j(K^33KCbf;9:gm!)9,V9JnJ_%P/D7nq)TE!!r!7`AI&O*oN>hEJG/WuOhS4_oS,MWqW.,:25I>c"RS(67[D>-6`8P3':!6r3]AV'j&P6+,#qN^[1Fe=%OR-\[JK'RDFURGb8/;6d^bXlb$h-n.9#SgZOg0NO[$pse5N5429C(lSZ`):>V.&1`s:e6=Wp[TP'1XC:5hcS*aE-Mi+Ls]f:hX*Bid-CYjXV4@b##7-3lJKVNL3\Fphd[+MASCg$gJE*?pKFin)nVh7'ps2d>U$CI5K'HgNeaP2lm.Ajb@l%2fjPQfF,<&NO`$?-j-!$T6RU"MeDt/+jcJ$j=B)B$+Zs[(TT2H/Jm[>u)2nR)RB-B\J.pXCA14;<-*n31h2'Hq"]';\1t0r#K49#sPjpU-1R^]p"[0d&N,I1"BA]?/B\8%q`C%FN@/Ap*nR8b5dI*6UViKd]$BH=M9,&F;rZ>"E[6RX!0BoTOa,=tm>D-"5LB;8(7B9)>cncm*k\+'jgqJB3L*\hT%8H[PeG~>endstream +endobj +92 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1271 +>> +stream +Gb!#ZgMYb*&:Ml+bf^&_+"1(=bp`uV%8n<6\nF%ZII[aj;)T(ZoTGH&T]j/ZOKoVYUc*,giIKh#Po]U7?g3<1.S/drJf;tFkCj$rq/;miYUf5b2@>YDU7HWgqlql-N]s)Kq,V3O;>5(meY8V-LOe("8kY\7u_I3/>9$0T)'P?!P4rnbCnVHrjbWe9ASkFe!'T9kAFPt!"o2-ia9VM`8"Gqh$o/L"$K*D)km/THcCM2)LRI&XqCmb"bR\Y!`L;>>_Q2-OjR]E8U\L&p>DOS>oGT3o`RZY4n&dH)Y@CRLt+ijd"Y\UXQ=Hm'qP!;K[:Mr1n1s*"k8bGJR1:%J;6a>V%K4DdQCr0u>>surarc@.&irhU@J:(6Xi18E\P-duGIq*B!\;3ji[`FG`h>\#V>J?]NILBODrNTF]'PE"r[Dpa#?7a%f?Xp".P/CljfHtA9lj5dHDsBMlZ*^LrE&>8]\344Xr;Eu:$Nhdp;U+-I6rEb:+4jt>Qn^)Q3A.5?m4W3.X40b8mdpm`icJbdAsWT&g'd7(K`3XT>A:4^r_)E.:aV~>endstream +endobj +93 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1190 +>> +stream +Gb!$F9lJcG&;KZQ'm!Nn.Bo$b=Wc>11ek;AJ7-b_lCN$),hciSM(2(C.2MmN4/D4B[Nfpi#.q-K*Cu%5l^;sO'EoSne6VYQi*?QD*u&Agfb3M#/0MQTZY]>H7Q5N<.3qb_de#N<-Y=IpVS_82lH>,_R`(*e8.bSV7cH67OpKQPL)eo7B,+kX"EmlTSY),mS86r$%HdnuNE?Nor,r4r%:jCYVN1t$g5#QC@\4BW/GtF?@g.l]$(P"Tq$Mjl!u3b1=hq^)CT&P8W[W4I$CDF2*YmW1'*SLAcKe_=P2RNu_cP">3^oL,[M^=1Bf_@r')5_@RMSfBr"`C?!,IS,(CGp)hXDG9T*qelnOY_$LmT7XPjJ_`?/iJ<]C\2:D8jCT,+qs(?*jGEEc-foGBDcsS;q*C*/)SP?2lSY+$`*F"YF%Z&;1b5cPR0Bkq/Hg'GS2@>uD\iK$e$h5qX.k#/IAhb/)bY,*tn()b4?p8J9a0&7Q:E-u;hm94FPkPLXZA6Qm38e:pX?daD[mOr0:G>]-Zd<-U8Ts*T[8)KrrhY(f9_/DD\gs%$Dn)A%[Kh:nrool9,lu]]7Ic@jLi-nV7#j>-DKi)3nF6_!NJKC-1WIps=6+3ZFIU&=2ARKXTPYn-Pc(U#Yjc\eoqMO6DLd-&79'd!.[K_F!fV6@hKlj&^PMAY+:sf%3'EAQ-13YhB;EOq0`N&'idt1^1%DkSX<*ZU[4AXb#2?I(gi\F@od38Zpb>sTm`h)H"m-FsAAZ"B^d%:q)]e(`r,Q7M7<,h3=/k6(:qKa.s`:endstream +endobj +94 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 922 +>> +stream +GasJPgN)"5%#46B'Y;?HO=;t/Uqj@NaN`]Zp,78:G1TR]o[VY,:'h?Ha_U.-55eLb20q^1B<2)N-ZF>Q5u`W]%&2lQ'.+7:S".0`7B8LSD.kdG([^p=Rj.'hsnh_nD<6)4Jg7F6lkJ?ZjH#B$"M;Y6Ad_aL!fBpWAgm&2Z,8>FjK4mA?7m`X]D-A"gJeK`(\$A89D'I5)%UY8`?#o@UnZV'W"qto.m<\\Mb=C32^g&67LuIGm&nBDF6B:t2!hUqM79VV4=O'=Z+C1")Y1":sH]Vt&*+UeX_(V$Jl=u6;`aH/9g$"]bF)oK(WO0/Ne8N8;L`b=Mm>G-BS$7_Opd;'pHWV`H(i.q!b^Shd-b\08lrZ$N`,)V(n;Lr6fe8C,Wu)d4-O&D36/'#Y28,"I*nK`efS,TCPqQUm#\8/8UL?bWXWr;\R?Q1buWjm$!?nF3endstream +endobj +95 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 337 +>> +stream +Gat=c5u5?_&;BTO(%8(Jf%lTViDuTu-Ag]6X'eng\H_@#?]DruJ,OcN^pC86-?VUYrfY&@0e%dEfJddRGoUM4rgG,V-S/28JpKigN:02/:i/btuPg$@&Q4]jXE4(Ot'Xu_2PBe.M;M=At2>A-cN>!T-F0A-L-4]1[eKkd#Ifk,i\85]s`Wi"gZ^oIq\':t>Q*;`*f&RJ7.&stH#4K_&@(NY.`l]9T3_D4*NFa)'s2hQa/iX3gs"BhDcCo"*SV3qq4rIpZKNauY.OcqZ/qgMX(b=lV[(5^V+N"!UneunC~>endstream +endobj +96 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 925 +>> +stream +Gatm99lo#B&A@Zcp.0KPQt?Co/g].ASaocj1=I[8#[)Zj96)>JPj.hTG9oGD+X)W$LQA]ahg>6D=8&;IQfl)^!4[mEr71tR!V$T2MqS?Q>mTH4YDTfGCpp!^nZgY[I;30p5,c'uH="EmD[2&S!hgOj?!=0rh#^SH5pm-IIIOm"\0(I_5m2Z+&9J/p+G.4FkQb`35=5:aEdkp,`9YqaGtW7GQ9_*P9B0^OQ?K;Y2FUGf!jC+WW2g.+aC`BP1JjW=*[VS2Cf/9!k4j=+bMM&#)qVme^Gm%Q`Vu$MlK9^5q9H#K(4odg^UJQ[bCa_&)bQ\UlM$&U_$=SrtSbq8/A*pVg+HZ@*:;19o8l2S^WW$Z9@NeK^jbeSA>9?F'sO,0`-6%S&>Js&>_/EeJfUSLfB\4$<]k5mt`;)FgHbWehc7S@qfK,Ip:,:^k:kh&^g-bsC[7@Wd2'TQ(=OF.W`">s\5r=r"KF(X_pZ;7Y][).ODfpZAQsp(8h6)Dq-PA7C@_L,gEXk2lVW13(mLJN;!XU+am%%9!7jUN2cUoS:J9H,nNW[8?)+G#3^B/:H_;7ZYHePL.V@/tO41bb>@5i+'1,j,)c*$e#Dg4tRf*-/H^O!.4a4=Xse@VX9ShLWC8PZ/$0F4e'Ap`#I*be+ag,Zo@pR0u]\QtO8?B'q]5PA)"b];NBH`h7uMp<_f(LU,UGftj.>-,8[R[bC@N6P0X[tZ1WCMtlQKl[/gWp@e(n^GkpiqU@Wdo!dFOcjGQ12r=JP4GF8biUJ[Q%/RK)l`~>endstream +endobj +97 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 856 +>> +stream +Gasanmo.q*&H2$(Z/5s1$AN^lle%?Jcq-`l6M-3+_f=AJZcQL!GHk&ds1Nb&rgEk=)]4t/Hi*O(mbu&)*P_U7"i.SQ\g&/'8jHZllr.`OCGrXQDMtn=1?uZYFBf(8Va<_SZ`M/)\NGj]*I601VG`)`X]"mM34fa-Bi`0oI`l>0-'q)U>,A;C&3b&TkVr8k`1""\K._dhr59ROs'Ag"rWU>Z7fgGMj-n[#u29!hh=`)Ml'U12\&EWuP.SD?\4W%YTDq2o6cJPsuT?aiS8'c=/I#qgCF=^G0(\AZ/R;8ZI,6)N6'IeHX#S,75c#L'=E",@jA"XGg/5"-"a1PF.CI+h1i+A4]WJl&7Au=1,+E$nkVFW)KNA*CirUj$NZRFf-Np@bs@cGcq5.G]F^]K,VQ;sG#Y6E8/@?1!5eO#E2B-&mV`\eFk5lBk&;e>b?F$]_u>g5@8roP+0!e-e19p:iIZFlq-U)SZ4AIBEfjq1T5/P>@endstream +endobj +98 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 807 +>> +stream +Gau0A9lJ`N&A@7.N&[6*"e="q2QE"[E>qkF;qSGn?X.pj2YDBer;]8ds*JD1OI1h(3E.L[[%@#(p?e>h#X)@bIqAc?N'[2Z#iQr2CC'g.5-PX;m,7:S>XfbD+RHf-$jIdXKV0+a#p3:+pBSJ:+W\iaoc-oV06IB4?IAK*E]^36T;Mm%,g..bq/IA+D$/ppT--lQ=]eNJJM$\g7JI!T=\RNgO;maaNT-2EC/eaoE;t;=U;o$Q3Tc[-edJJJA*A*p8gBiplFo"r'kkgm6C=Tq7Y';p&A_1B"UZdi<(^2iTN]dqkr.!ICUCh`T#"\&SC3m,ECmAc>,@.4]f,fA:1e*CGFfe\JaE;Tkl:Do'kOD2U3F[MJCEmo]^PS^r`Q5EkrLQqcU6kn*Rmf^J>+$5(PYXTeMfZ;OA@TWC;%.LjXVCR\g5o9M8:Mg(p7c(>R,aF@##uoQD.>et7g^=Q71>2@3QIaR-EB6`]XbPm^eXD-3\W9/F"F6.=snZ;0NlLij3:T="WfWV[]l^7E:uM15roT+G;HdFZcbb1<->GKufW@"a>o66:L7n;&5da*hOYA:]q)G+1Q_rh<<1jFXFY?0qMkI.)kjRTm]!,8;Uq-M[QD?@bN1A>ZkAl?.\L\Vm':$iIBAg[+DW)9#^#'mm#PJ!t&1J\CMHWrZVkc=EJ(**5Se_9eg~>endstream +endobj +99 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 702 +>> +stream +GasbX>Ar4L'S,*:($Dik1eJ;]\i9%DijKI@-LJcH:4b":G&8UcrV@SIN361/9i`I6SF9]HgI0D^'npj0!/tEtSOX66+jM4q[1"X:0SI':4WN;fqF&[86DA7]I\4]58C)u`*M9;EQH90ecf)G![@n!&pf)9d.83]uYVRhM4@/iNil>iqmC[d;EjK@5APSZb9DjJr:ceJ*0WtY`Facf4!?=GIW6r(3!qir1PO3\0h8!nGcUY%d^.HhmE"^7qm't6+&/Ldf;5JO6Z)8%3BW)1/QRE5HJej=%%Y$K8#+,SZ\Y'iUf!uWS'0BEsR,Fs9N4'0H,CB>I=gV.[93p+`oMW=7MFg[?9Mm-L$@bH))QHPBdr(j6eEW02MtbsGi-lWBZghJ/=DenY3%Uu6-C[q]..`sl^tort-g17HkA="P#T5/S@#@scPc,OGjd!.lJJt2Ds&;UXAe/..ZAI9cJ+?AK=$lt?%SHWcdrTmS>+7%T,VLuA2;ht+BGY,Z=9kgendstream +endobj +100 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1164 +>> +stream +Gatm99lJcG&A@7.b[ggqM"MKc;\rgN4`=92]ZV`W#TP19t`,NR1tO65%8ubT":j39,W]O)KNG"i0R5\@4Zs!@1>-6RRQJ*c@.I^Wuahk9Pe%1i_OM.]*JTTFel_il;WV"\"k>S&mIS4T!275Vf]2K=O47^h;.n=-/<6P.8M0nL_Tr=g$A*Iu6-WZK;Kp29uitA\f'm5Xjlo!_[[\E[ib1o0'=@jY)KA#A3d5p7e4C>Y)$nG6EV69s62dOQOVV)g"@XRDh$KFA@_D=DHb_Pp7;C^E0mo>,*Vtn"2ufn.IKR0D'sl7b,&HjWYS;@8^:*i7Bsu*n>13L%.5mQ.P@.$;"JVFB7WQ9lHFb^G#H\AoQ\+G:+?T,*:'lkT/G5"SN+3&f,X,HH%rh-"R1h)Q8l:+Mr44%og/h;l7rOj&j38Tblch]t$2tX'9\fjs8!TKHn5KaKEm%B\0!"b\`AEaFY1]Y.6[-GVbiQ^tLiqsfK("+L8=?9EZ`6W2ULQ3F=[/$=89jp"$Ah[e*7+;k`ij*?c*P-8XMNMS2Po>(NXE7AZ2[`W'sYt`FHM5dfQ.IJQEq+6)D$m9E7h`;L@AGg%>K1LZijqn#8##&_'ZX>YA,h<9"0a."cX5CY5Z+qThbp7I"q./=$hdJJW6.Zp-LVup.54*M!NK4)7?gl0DSqdFJ?4);CnbBOIhlN`(Q+nYF*/V+a!0Qh6fOiD=3loH;ddR@k34D[hiclT*"[.??$>%CQ\977F?r_"ncA3Y*O3Ze9H=K_fq=7Bg9TIDl2gO1,qkK-S,N-n46I89.5LKP1g%N^%gGU!me/g2a2^kB`I?CU$m0Q*pRUI!c_C@PHC[[s22ciHIP7Ig3/_7endstream +endobj +101 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1136 +>> +stream +GauHJgMZ%0&:O:SbY%uW^f!,G;R.sF9iE0"YfK7M?i7c;Zq[_LC.ZR[6*^IH+m#ck.VKPrJJDr[iYg$%jDb/`rWV`8$@pGOGeXCnKTOJ&(m?\MpMcT3^(#ZgAt6XnN/4*2-MYU=QNtLm;AI[uSion=#JNi1MZM,2I4<*='TrUI!p>UeZ-t)oq&Y9^#GS/m1*G,!XQi\#P&bD'?9l)RF9M;IZb4\!)mYMYK&8:!%-@WB!#hcW3F#W#3R74++055a(CXD@[C3U]$4[aK3dM[I2Qj__n0AcIa]a=di9J5Hi\\bmLHaDPG&UC->)Ea\;V$,:?0^l`r@,rG:2<%H%2-h9G=\DpRK[[>2mOhCLM%aqNH1E1GUMK1mXt:'!bJ7+\O4j(1tpI+M&K+bTK_G$nYOGcXu?/EjP?m/hi6&3cu5XZS+D`B[9st0Tj@T(Z]IcN:YS%D4QPY'[)bh3+l3OA)96n<0YI?Mh3f6gJQC!AU$O9:_^bjgE`8S'CAdd6oAnR]]+f0Pf@1J^>KLI@d6bA&h79@"qTQ"L()`Hb8JO-G6iOb`CuDi1r/(M;h!nXG7`a"!]:.A$@5`MOh'gLM)oH;8'u'fT^DH\BU\7rZU,[J&D/rQ*AL2D-Pr]k56':HMrA)"Kgb@\H6+h\__Z&%gqKWaWO;obk+c5SH_4ETV-LFR#3:huVYNe^sXpD/JZ'Vr*F_0a+.pDH2;LKiE;As$/-VWM`raEmSbP7%dZbHf1*KM;Z1_0PO./$F4VGB:+hUH[$Br8!eT/uMgp4OG5)b0ge`V,BXh@9G0-6"4cd-kGLQA\MZ3:$`mm':u%FZam-:AmAd[mak7\!hge7H"U;7#]u^fDjp=6-tPFSk^7"]m)a,Zu;E"V;jP,p+TWTEJ>EfD<+AJf?Rmjr]&TRTW=58fiR`(JAL.!JT53~>endstream +endobj +102 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1197 +>> +stream +Gatm:gMYb*&:Ml+bf^'2JYau"/3-.MVV)(Xcn^"RCJh$CCb$0Y8'K%O)W:J3\Qb'o,JQY_m;NPd5WC[NT?->`>;G6e/4e6+?(ZPRbL(o+2Vt``Z$`Z81^-],S#gs6&?2H9+F9$9/L@=-4S?[]qe*cq^k@Z5FN10.?up3MWSY*(tZ\pk]ZQ)A$9H:W[53V$=WF0$H!UPV'&]1NIAE]BtZ&3c1uukpLMQ`TuhmA,Ln$473N*t65JXp1@d^ZSfV]>8jdDq3YM436Z1_?:H8@m6k=Z?ngZGiUrncPgV9mZ`qN?1/S=.Hjc\F-,KZ;KpYE/3+1nc2W)uNsL1f*>IdGdmj(#u'gOpS/#2gpZhX>@\KonFgTO14j4$)`D_S/3aV-l4F/.qVfZf*\q*/7`;lrZoCJu3>OE6JNm@@%+qa%HVdmSRDmOeZ7ZZN"=gaG2/G`FPBU4A&Ri+]BLN$`Dn051V_`l8Z-!oJ81SYoU%a)IH5W1N]85gIVHVXT,Q%>D.qRlM(%Q`Lui1-PoZFhsmHAPfi)2D189\A=uOWQJQ)EHI0.Iu6kieE%k#+pGR&ECbA3V2Q3aE8:mEHF(tJj%)RU]r(0@UANsm*Yn_@D3P'D'l.MX46$KZ][VHX$(U4gUnJT"E)\H[V\filGq64$#,hZ0fkf"f3Y!+(qA0b6O%P7I=Ou%CWh%@Ik6&jc1c]>PHikp`9>UITKp-JJJ:s\@'K],]ra@tBktVa9R$-4hm-/8fR1c@Xo$;XUL#20q$/WJmR&goH_DIk%&C)YAnuV1tB%95Fk$CI)F)+M]f(4~>endstream +endobj +103 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1291 +>> +stream +GauHJ>ArLj'Ro4HS(6)pgU5UL8nSFJQ_-2dM/)&n@c\sp"*Oc[U>kBuI`S^4a\_Omt1rT_4H*It]^OTc_W`Z5KFRGloCS0_n^;FLMKlD*hHQ@i*8/OYB'o,<6ZVC:c*'o-cpF)?A)/8=E0?6^")4S`=ZiU_NS4^2P.O5[pEV6qSrgC3$[W2aOpWm#D.j+l4?nEC!kT(!p?\6RmJ)-IcSEJZ0D.GsOSID[;7+q<`^Yq3_#Y?7&#T09!rW>4lV.%d08=G`@,(kW*mBA_P_B;&R,cs/b2UK8*fU/4G<),%t<$b1\jg(*_hl^Pi:a7RX9=_2&A;Y^m:-&.)0TnJ"(hmhq_:7h+KF_@d&(rWXmg>"8!I:t3%Q_!4eE%!_F'U+BD\OJVSnQ6o#r%ju*HVBH]mq75O=#2/"\?McEN^mM*/,]%(/ht9tr-',6#8kWg372[o57f2UMPo^MXEYmuC99d^>Rhr6u`I:F:-cM4,29X+ir&I`,S)3Z#T=:TPYRE;+oVkD=e^FC=]9V"6/)4D'LG67:EXT(SeVCst\%H3GBq@W,FQgTK5&ERZ'.h>R!O)E35\D>MAO!tO)neV&HA\m^RTo&]_p:$?M#FFja!`O;NJg/a$VKK/f*"sECnDIWq&X%)>>NfBEMNEpNSlb74\O;7oCs5Xmot"Hc7CC"01!;t35&m!:4NN2)elIPNRaM%G*e*S/!.EUbiu@W$h`gook?'-*LJ10\\IsfHjb4HG;JR82BV-Le#7fQCu*(]php\Xl]f<%]@H22>>GLrqZeFt3?Y;f8V3*3#Ge[(Y>XUEej`dAY>i*)Jp'6EP"OJC<=@pcUolPD4Q,rBINh"_J;V7MAu>,&?`8aejuQ3O]0[:^',[c[5qehiWnQLI"t<9ec`(3'HR8@L3ZGcb[k5+i1YHmne\eeII.;*>*g1.of.&TM"V8Mf>Ob2?h>Il\H8unW7p.^IT_8nlh58s~>endstream +endobj +104 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 850 +>> +stream +Gat$u>uT`:'Rf.Ggm=Rt*U+@S.]^jn$bj+\8n[jO#Lb$=B\HjW3jOeGI;]K;7@/#KR6[3^cFlrtW=L',IQaPg^f_*6fEXWk3!6qYoH:l$;;?J6q.o%6Jpu'h]]_%97dJesYtV0f(rPQj.+7[$TUN>dl\uV:cjcKNiZ.X'&689u2898UQ%_,8\lca&bj8ION_eT0%IlU"hn]N00l5r0qGPZU`>bfk1fD:G>-EoP@HZ3'IM9ftNBr[s?s+]+o)d+)VpF`]qL72B>=`'@4@6,E&\JWZUn3<2rRpaHTo!21)Xf;`f"d3,b(c;(:4X4(E#^c!?5N6kOhH(pEJZs<2&Z%.DKIiLq0R*Pj#_I&k+aB9mDE<)O$\LjUc=3)js5AXTQqGclJ*oA[bB]+r08)L/;4A+e&.`6!Bi.Sh0QGK<6[jlRs:eW:0~>endstream +endobj +105 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 474 +>> +stream +GasbVbAP0N&4Q>@`G@#XWl8t8+Cu?qKaL.>gdNMIDA^/;Yoti"q>8n)d@p\/Q=;3tpZB\E.(Em:iYeWo9a7CdJU5+D5c^/"YQ8iJBjIJ1bdn=-n#>=Dcb<8DJ6N/^H-'aadEXPje9H7(CY$[MXcjE@>-'pqJ^U1lm=5Ab+R5'9GR1EKf^6G$Mut"P"'Yi=#:Be0_.V8Y%Nc,%]3-L@2-U$4F$ej;/;:3RMjO.h^)+]6Na(.8uZ_0ZKp8jpSFT,<`(IXfULd0h`RrindDPk?Q$:hMBB4iIB.&)-2OY&bOFuAoLO=ss$'c8^&JrteAcg1GKUh&2nN3&FT/A%q!7h8+K`~>endstream +endobj +106 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 300 +>> +stream +Gar'#_/@+D&4H!_ME.OsKPVQl^s.NT+[p+'IGnicD@7(sYh_\H^:#Jh<%I?IG380'E^(7^If`XPZOMHmLj)[`Pn5McOdm*]]pr/kQVUaa/Lp5Y666=%Oa&P8ik4gBUC,@hLaqs,Pk([egQrCA71*bAmWSXU_)6'lhoVE+k#E-^fUXq56AMIqT0<64(SK%lK#+/WSClhCYp:[d*g)uq=PjDa',X3X-?j-~>endstream +endobj +107 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 386 +>> +stream +GasJL9i&Vk&;KZP(%8DB;S*[;E3#c],btKI%ij3gTPOBmG=D&R]3W4.#L+N`D!'c'Af*iRbe::`mPqB<)-@$U!?2.Dn2XD7D*<'D*5ra(DLshha0rl46C6o-4kn/oa4\JTNf(W,rMV.2#PiX+jg0^NN(k\@Xr*Icl"Z2H_Ki`8OCZI\S^6j7n5o,&*k\k"%Zf6Qp_bmQRD&Ip5Rr/38IrPq]hu7/;N#S!Q(Bss>M.L&=>YbIUI=A5>%%h^[73H:UnIji`paat0EOR5dMa')Oq.IH*f`bjSr4WXFYYsniTDda[8GB*Cn3Y9LoRjR]IWT*VDYAOT>IP(7Rsb`.]NmNeIWapm@'Rq%d%pB@;QD8HntE7nJDg5c&R6k!q-L\>)oZ~>endstream +endobj +108 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1446 +>> +stream +Gatm:D/\Dn&H:Nn0rf=.?*,)5.:g&kW[q`MWhY7udHWnD%^JuLG#V'hf!=%8:\-jFbtd'4YP,DcZg'=l?Kr72i%LKqVZaB_/4]e"h.'li:ir.+8nq]OL$2(Fc12JoSbM*"5K3!eYns.[8F-n?Oq%jFg')a1VAJ1i7>X^o_Z<`khTPS#M6Ha$2F8QIt1_khdM!g6M#R.Jc(.E"\d*VQbZQSGV+QaeC%\IW>d*C?Dr!8U8BCWSdMXQH*[6V=e8o:7Dp,%SjbtWoYu3>r-8]sT8a+):&JBt^b+.sAU'LqU3=eo&1WPXSBNqqLgT#tJ'MW5pV1V\*-W^^E]Y:0TBZS\&XKB$kd]C>6;[IhHTcWg3$id9p4#c[b,oHj'39'I',&2*Q;n=LVTdQFLhEeSG>%SCMV=[(KG7IC;Ld]car_1>/jOh"F:fqp]MO[!rK1RgL%&7L=jk`a4LAau!0ubG7<*cXca*B2b^!\2eP6&Ap"IGU;+"JX"gbS0PC/o/II_*tfb37S31,XC#[=KR$&n`T2UU9Tb=-UXddfZq/+KnN]-4e<)P@,V(IQ5RY,4.HHGdeDuuh)RDpW+0]"l#Qjk6e>sl,b8jM*PC)l5k5?p1\^i5*$\(X7l:`5dF2L=>rFPhc1^GX$7T_=k>V?WYHXmdFiCQRRP2Ib?>U8CJ_4GW^BqA5%a\Dd,NCUU:%r\4?2Go%dW<'<6,L,a:,$YY)^B.HDX4UsO8#4IrIV&D6C0&T"M&bg*fe$HKrF^jh2`+5@o!ij:;guBI-FM%QQ7VaXC_H7kKu!'ULoGg2/k+FtalQ?`8[G^hBsXY=kc&aoQW:U):isP?E#I7WW%m!?HOYTnV>7p.IY;QB"4Po*X"]%nT:S^GW1_X6H_`@I%dBdBCR&lSnoLWaF%N5bR;A-Y_ukUsrjKZT<#4Bt<7jhgEtNt1,tkrV_k.%kkKNBh>'mZJ/Qf?=*5V,a)@=?G%0#+`\Dgn&H.]iCZAr_>O<%Q)\2HN*p[;imUZaD>c!:10^ToMojuC+V$VXJ?.0JZj"L=XYE:b4`k:^N~>endstream +endobj +109 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1432 +>> +stream +Gau0CD/\,h'`QC]33%'HHF5bdGIFJSgU4Z,UFR9s?S5D]-8FF:M,W/;6e2254Z3H664n&nO:ZEuF.PMWn`(9!CA;r=Y8781NPN)H_6(Ug$>u%a@FU'j;<>OOY%MphctN)CXkW1$MTR"CaehCZ<,:V,W2,]ISLA+cN0Q#qf:^N,P:he\N8K/g$/[VlIAfKk6c@fj)N%&g>gKr>A9,LL7V5>d#/N7d1\$$1aoaN(NfV6$Di\=K$_opfJUXItS!!FeRD,PT`7+m+6R+OaX#dcHt=cCO^],hk'Hj+c]rsg9!?4U$'asb8eDQa6-%OM"01PAW8r%50[-&a_e_$V'&c):1d6@:_)7jCdkM&mhSY`_/4NaP+7/7\Io9`G),RB^s-kl&Wh.JH&%k72SV4U1eKjQ6660W+UN7-1K?_he?WD7F4s.sj#[/\7mVo#4i(3h%O/CLsFeSF;gCAsCF_4Z:#IQG'Oq>B.-_jf!L6;3'IHt7`o(.N1/4g.]G;bo*F>a\KBapqUqr9[N`b'5$M%A%0p#5-CWr(_u.D#'6epJm.0H+2FZdEi[KV3*X(_i9XD2c7%/7Q#+_i`>^=dd'qJ36ufd8h='+G?!M8,biRlJ#a+Gg1drOp@T2d28Z)n5,s-JF1ha@[4K-M>#dlNEIES-]g]qni`N-\Y`LU2mQbnp3IaR->dUO`O/3eD\9T'luM26>jVDT26S4n^=]!UZU&CZHkkrQm5mo+CJ)-=XuVlN"Zj=k4m7h*(W=ZnOPU_OUduuWOIABqE%;8Pj9%aD_A&5F9`VhH\H'QQZBCpHa>2H9Y\/V^+p~>endstream +endobj +110 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1040 +>> +stream +Gb"/&D/\,^&H9tY3$D"JC,1H[Pcdqbg9k-D>3Le=$#)/OTl*5fg(#.'qVQK,jFr7f@GSXk$W<5-GL&Fd4$Vp[B]@?qm`l7!fS7D6"]c#t$!?Z;40X'NC00gRf#i$:"4lm(Bm023kYZU]ODH-%N,$Vm!L:%?N""gTJlo9VWsNXD9fc\.&:YKW#/4U(HVib/5Y)>N:5K<'pSSZrBC%q*45pOf#T)P`;^.G94/dd[$hhl(:,c>]j9sh!Rd*_7pUOZaVtM=e+q,(lKWj%-YIRu(np=bS1?Q;DW:(+)aG!E58peiM:\0*/9ePG'1[_)uZP^/n:/1H-qklY!(77XH30?q6\OUsNknfXM;4WVcKU^R@_Uh\1*g;F2I_QD5l%0*?nfQD^.NBs/nq]SS<)5*XT%B6+Kcj"2d*X%+$,Wsf*H4-@'FZbtBgd2NiraO7`o]g6c!e]SS3%-Yn_6>1i+O5gbVNKKoHgF.U44.t;l2oYFO%137nG&O\X:4]%RS.1O!T2^lcUWk0ul"ic"l0HKok,HC"H3Fbs]M!>_N\-[SMdF;g*F9`Ma#q(m=,[qRH_@EJH]=%25S\77>1)8khXu>EES(0>W#cf&nj41tH/1pSh?!<#H=(0P*:HY6!04f2QcOp)(ZekQmc`hPaas^1T5uaA[Hu'hQoRQHBs,J'2\?c,%6aB>0B5:eLqLF9dHTq+91%mpH(h3p^4f">L\[@T;+3%Y]S3]D\;c:sUXn(*c!.[>BcnlB(tCb^'+2=Z6fcbl0Q?/@kL4jerNg9D2mc55M^9c!;Z&+X=&L\UdnLDM'o2VZiRMVkGlE>9/12Ka8OpM@CbrP/8Kc:c9/JQhVt"2e,VA8#,faH0bDVUNJ3G%bPUbKL?+(?sf-cpCA]2T51je4tEN&DYlV,!oXdLn[Dg94V,A.>+`Re/GY5Jc._FJ$6OKJZFlY=C2o63MdS-:#7h1AhGo>IK<)5/uJ~>endstream +endobj +111 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1432 +>> +stream +Gatm:CJW\U'`H=\\3d4Vi!t?7#4FeS<&*-=ba+fu6aR4,Uu/HhD$r)h\m6/KTh)JVBa+mm1D'XH[g>\beQen'6@7NQJ\Do8U_FGR1lYt9:18`5/=J="WFG-]kgn^b5bE,>64FOGZnj0\VTpGLE"jGH0W-Xd?Hp3*[(iJ7T/ta\Z)`uW3egXCZ8LGRe1(KdH2Z4E^,VS@Vt8G@HlL1uTq&Ub$f/hH@@0*\j@#<2.SK98!a#73"+_h!\kGCct$W1`/5Y5R*Y7WE+AmnGt4NC@q$b:"nFt3WMs'i(QQ*`A?G!Uu`\@3sPDr:bo,IKPJc++j//6*UOU^[XI-Od/2`?A:'Ba)2_4p$Fq9K:pL^U60^4gP)NaK%'AT8MM0L6KSY;dOB<1A[9/306\n`n'L?Vp]8](\8B0Y\o]!A.V[E)s>3;LoEatr-;kc#\IU^UBK95hpWFQ.BS1ZYa8Ykm9.?VdXS.[Rcgc=%=Qh=ULO(04t(fR9(ejSH$_>s'l&a#tLQAZI>9bk:sik!L7iN1P(QWg`:G&(2k?k.Ja=CoqW(b*f5W-P$]0]=S&jYJ5$kS]"WD;5+@Vn%)s!EXG(70F/8qql9ok@pCPL:thTfU%+T/fsY<'*]j3t(H@%-Xg)%uDtMWoq>!?/3-/U!%ORg[ub"iJXc"6O^F~>endstream +endobj +112 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1336 +>> +stream +Gb!#[>Ar7S'Roe[3!_4R/m@NQgJXIa8=Ci,JRig9J<-,sO@M$cg71PYl&*QjNkq,Y,l_]2(KW,qe0I>:>5%bUR>'\>#>pcJcHecEgFnKU#AdYI?5gl+^F_RK466BVS,K&/Q<,23e3q&K)iXJ1e+M(+V^)Va\Q`rZ1k+Zm5IoVa74n4%u<G.s8Q^ihr#d\)-mH)YRHO#glbTR8X/_\aV^us@FEH8KeL.##BME18N!4#D4Hr/ac`49kr:ZhsZ]&$RH"oLi3OQB$T#<1fBYmc*?#=#pH%E[hSTq`rN1,J6Ys_]f8@9.ObbVQD_Ka\5HX_RmclLWVk<33UU?.3[;DujZuh9X2BAR=iBQLOWBR]r;o+&n!-VgKVoEUBe"5P>faO04d/"Z4JPfQPQmnaMjq;m9lU.pt`Ut$`r;*!s)$7___K:TtqOD^^2lgN_XIN_9Qmr:,2?95a##[.QRR*]H+l?/)KnEs)l"#[@_0E>kD9WTX,LJnsKTHODd&g6tn]j(@[n^t_^ij0F#E$gseZ86Pqh9@?j*3jb)KBrEAYg$ER.Bk\'ahk=,UcpsJ,C+eIMV`PrYjk,\DPPXLdMfh9rc]iWF+A>C)2iVT^DVG+[d<02RR5"DRuY1Fc/n&og]^$hc,TFKr('r-tt3@P.j)WlasoVT^s9$LLj!~>endstream +endobj +113 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1286 +>> +stream +Gb!#[>u0K?'RfGR\3df*5iBRpg8)r-Q4G^^,G>i'IG=1BS%-G!`#7;Y*KBj_H_%%-KbDO`FK`^pU2usqZ!/BZU2XGhWcoNq@+RJbl'Fc6+dCFYS'm,qJD]M6@%08e-(%=4]pcpu8iDgsW"m7F4$7TutVm=Oki@YOW(9(8Q%eP;'&\@6Hmb,6*T-Vd[DbT)pA>q9?i@:.N5NNE4k>JLKg?Yk;'2$/k&-DBK*k%2[eG$j%19DqcfqbWiJq`8D4m/ls-.hViV+;*N3;_)QkAiohQRl=Klh7oFmcP/ka3gc5H]%9aZC;Gs&][j/rI$-/$[!"jEM44B-4\cT]TL?G2"A#Mn1!AkYmlg-.A)/gtrEVos>eF#elu1og82*<#IKH-Pnc"NN;O.ndd.J/^T3m1.NUiW!cRl9fWJNXE(+6maEqJ8ir.M;AkR28p$cRO;#SgIOEYt),"\bbfbXe`mK8`Hc-=![(SLiL'_aLEl3Js-cdOZAc_HFUe=@XD)nnjCeAbKG)/e.A@C2KE]1!,e8)L4%Z6`Rji`b),3tB_E,mdtb@_DCEd"IZbfrG%XR5A,JqMCB8AWM-p=j*&Xb5EB]q#q_#(%Ol_\FLPYtu+.pmi%P?YhtI3PYTkq)$"HT?5r'(\r:1?[gL!pIMasiUUto+;u'/YQp>YNuYa]E)J0:H)9Ogf6o2?.mP>R0#p"B?L*_s-!).haM;diRg5$7RZ@_u,"C+m!?+B/*YWMlQ_o]Gr]@GO%oNo;CdiWc;&(gd#Q42Vn-%k+JhjD1e-,\Z[P/6nh/(FSpaZuV$c<%bSs2e4Qj""@9eOG/PMbS>N[H^H'i'#!pd[m%^V''F7=["L7`XCXh0=?;=>Ai0hhil'jaDbKr"eudgYfl;8/#Z($(CD&6o2`:#FT)@r0I9d~>endstream +endobj +114 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 237 +>> +stream +Gat=c5mr90&;BTPMKc-3[^/P>2m!O`/WCb]*Mk:o_c$M!XV*o2"n>tQ1[k2XK!:qdm]Smo(bQ(>_+0UMH=.3$cJ>2Wji#3X)nE[)ppOTIU0CSEa*-^$Zc/t68^Ot98^W-97a6/qDa:+qLf1oQRcl`$_s@f428W(dG@kRci!XeVR^Y3DG"FpcnmrWn,I4YR\"_(VQk`b0kOfPKX%!5AC:J)c!_HDKnu=^"'#Ahn%s(\Q~>endstream +endobj +115 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 362 +>> +stream +Garo<92C1*'SZ;ZMR0B:.YFNnFqgVnB$IH2`!F3j[-aX(p!&A+tYQr.+""N1Cj"S'MrkQ32UhAgQ8"sF'JH5q[g:cn2J>[$R;%g=U/)#;S"^cS_@mR3jat(*Fl\0T2.Lq.@/hDQqhGPI)n4@ZIsS(\_KI?@Y4l?CLAkT!JJ3J,6:_=`.W":&i0Dn!a$tNYp#CohtP?611uB]8A,ha;VK*_6k#Nl_A:TMI^`4!].@Rnb0TUjWBtqS(I3Ct3Y0>K(=u+_*k/5?5cC_:endstream +endobj +116 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 389 +>> +stream +GarW495fDI'SZ;ZMR0ZaZnmMgm"AhXJhNWgPAVdR/M3#CTM>H7B;jA7R%)\qL_'o'Dt&t=ET($;Ja8>%j\Q?9/`b2R?@Io5`_o6ni3nY$R1AM!_Ec>2$ZQ++@26f2ANZS9Je59aC(^gNKkU#s`ci!_&GI*Vjci7C>jLea9+R37IBSL?QU`5>]fQb.!UaV$00GAR=c^91hCRqQo`REd*/]X%W(k\Dn^1X&de?5n_?caYugI%jTZgN0R-#\nF#JO*O?"aZ?8q;$9\VZ+bKNqj=b4CXNdF#Eh))SiRYQO)?AD;H9A>K7Bi*JlJO-(sW#/.T*ZHER@7$V)*o#fG^BIVmF88#!B/AbQ~>endstream +endobj +117 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 852 +>> +stream +GasamgMY_1&:N^lk+r]).d@Bj`bHS(+c.L,;!b,IialUQA1M$.mQ(f,hcX=%3$bUWqn[VkcHJ:)X+Q.f?@JX`?kU?.)]a#&_@>_H_%8pDAmt/=Vq9"P"f%bOYcP*`&U9t6#CP:D=T+1,P8p+3^UU422#+^U#)N3hA-I4Z?Vsmt>m@r4)M4S9r:\"`A8[iGSud/,l19SCCqM=03B9W(k`=jJiHg.R?uZ1j)-7>&[4m$,Kq=R_kl:isRWM'S-McrPN_%JnTkm>V\_8B6iRlha^jqf,Kl"4*s)ZXGs;N'BV5P:4Nl.^?lR[$%Hrpg0]k`kV-Q,*J$XQCpWb96T6(,hWPPhU`,Eg#P7A=[Z6mc3C_a2N8J(TXshaPKMXU&1FOfY.p>/JNNC6n;#+5BM9d9H=@L].6'K>HUftQgMe>^01pUj\E`tojaJYmk+ZfuHo@"!QK8_^\j>;;ma3dDc443*`FlAMU_'iuD'!+E!f/sE7pb'ok;Vt-p1bm^LJ(]=_2jmm+7H5`cc]qY@,70?=VU00b]`$VhSZXgWbYa1*g0oj0bnMo[3fEA$]r5Lm]W1#^0IcncH'=!o$I7Aa0t!a~>endstream +endobj +118 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 622 +>> +stream +Gas2G6$&ML&;BTP'mn%2mD2)Af#0c*7.)bhE?-:ue;FC69*5fl+;t4V82=S3isl0XICnrr.tPLd&$k)g!*BfB?Qq`VO?F_9liUAk-DQ&8e0l[F9`0Zc&3L0.6Pj!3OGAtd7GTrZ=QiU'T^QKWkF+\3N'e6V>Q[=?'F9^j[/L*RHF]TeA@i5kDN!H[ise+>^[N$^It;u)pJjYp*@%$*b(6[(s<4m9s3PpXpR@IGZ])p_ur12_Y14]U'?5ZP4lW-qLJX)ir9.>*C<4N)C0$r=773RNWL)fDpW+AP#^+':d@6/\Wm*PGa&eZ@8[E_f@C^W$cmXP0eroZ;=i;gF:C4qq-O]%CSpBu@OKbK>\BmM+VutPoc7c<;o@f$&9:Q_~>endstream +endobj +119 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 539 +>> +stream +Gas1[9i'e'&A@g>bQXsg>%4DV['peh;.PhqiX6BcOIBQJmG\rcr-H?m9iJF#XMg:Za#q\85_+dfJ$B3FF#]!_&.8=9aCmO7c="J800SmN*(M][i@p-9&Ln=t4CH;QC.W22;7T.L$KTEVdD.d8Zc+q3V?mfS221fP:&#pCJEo$`fof]/]OZr:r-%#l6f:bUO.\^1B'_E[B%mEHo,$"bUshmodU!PQ!Z/g]M)Bhc(MFa,qHRso)9Y`'C(%;oapPP.=B;/fqPq7W?KMpWOms8HH1@Dk@Sl=KH2(?S22.,3e$BT8WC.2e1jcWk2klPE'a@6##tJ8`d8iHP,.CH#L+LZE&aaO\I6]H_9;rgBW]N[JXi,Pg;">!E2u"ac-M1B4Xkk5FNQ>1TH!T=Z%5$:l;X!d#ZQGH'hh3_)-2'ped94&!2imsG5?R,t!?AH7l2~>endstream +endobj +120 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 917 +>> +stream +GasbX9lo#B&;KZOMS4+dZmDun",,omJdJ"]6G]5b^dZl`0gE!`[kmQif65HNXAh!N6b)d6S.]\U;<;ZofSjb-f;.+[4PUVMgde\Q+V<-?5.Wm:NK(u1(dFanP,mt]_,jS*'or.XB0[t!5)^hjVm+UkOP;)%^i+T)K'="E2f>q\TjcK-ho0D9:njmKR5d7/au2=,u_FcnGN(L1D(JU4F!)?lH7@bN&l3M(mt'M['=*V_G(o#Dp(1L"XI)/-o'4LMbf!QF`f5189mAm87-%Lckk@V3+a0\Z^pD8,/_>K",UYndcD.bX:h!OaF0=_+Ie(*jSpbBIAB!52S-6Zar+rX!b#,#*:21)'p$c+hA<(gINLXpM,)<#H>]!Y[;!N!i#I(?G>m)]e.B.,b@T;^gpl.E8=^b2U%!_B`?7DfQ2j4N136Y,p.b8KfLMFWd#+j^N@3^n.XE>\[#P"LT4P6dCWV-&s0eEh^[J&BJLmYd3^*@UIhCroT@iO/Pi:R,q:2A5\KpPAGXl1m5l<@d!^ESi,e.Xm%jLqUW]OPPo;`Bf[rCK4SD@*Dka>aIa?VTYm:19\nt-rUB%;$UR,G7UJN[@QI+jF`=+\n$^j'kfGAWR%VeOO1L*=U0q8g-q_m1^3h/TXRHsrnEL/n]ftL>VqM9*gd!O=da:[M@VrHND8XJL7eL`UDHdc..`t\Qlq7*;-f[1o[dtC%'1FgFNE0!!i\fWpS1aggqsa!&)Ckaf,+@J>~>endstream +endobj +121 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 784 +>> +stream +GasJP;/b/B'SYH?(&)8P>;_iP-oBXNJ[@aqZ9^P=Te@bJJ>^C^D24#IqHZ0sJ-r5!OGJ>1rU.3S5'Z_pmQ8Mj"u0B?qqq\jVr2c&*Jc'S`JrK(?g[4QTbk(?rVgZ+'XZf/"gr60f!"HB;J+u)J:D(B!m`nb(XXoXcQ9ps-Qtm-IaZPU"LG"N31EAF\@[fsq,`CP6Mq:]o4Sgi`Xe.!08SX)4\%'jrp9a0&OP5r%(;Ko8`Em9G@"qm0U3!Kmo"cFVJ$Z>1^mr]1W?a9Tr[M=E'fIj5C9Hn:l;&F$AF$YNJc4:B*gN/;qgB?hs3R21kYi9X)Rt0X,\KZY30)]>T[UhP$?//,$B$$kB>4)N!pl/.bB7_W,pJ!'H/.W)=#QDqX#f[Qq4JC_t_-_D?a`s*KbLH#F[DBdW:(?UdfMA,[9jGmQG#21KCq7'#UP*7lr+U(T91l#u%n?&F#q1F/_hneRX/?gjn@CRuJtX`M:^6-5(tHXqb.q>9BBSgu9GRNg3dNNmWOXeL[;+lU+.oI;qb8p5f03;O>8f$_%aIHN2^OrOd/qgRM(Ra$*l>lTX4`AoK@r6$(YXDtS'3!#-)_A$12R"a`js!`Z]H2XNHD?*"^T45!g[`DF>b._OW,2tag7V4]WDYH^>Sn/mn?X^H%C/uIUH,$HrW8e`+$EW#rr~>endstream +endobj +122 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 606 +>> +stream +GasId95g:b&AJ$Cb`Pl)c+6ZD^/8\sW4(_);Q5g4'F(lQm*]HZP^hRn*[YT9c`4s`GA`3:UV1D^Zbd!/5).;4`gI?ZH$'l[Wr"U2rK`r7u^(_GL2_*B`MIedQNN0]F*L'QT/L:EIKfP$Zs2I7?C.S>\;^ud^AJo8W6"@#k#VCasV?@YqVFC_e,rnu;*=_JS3a#bVZS0Q6@ZkeNIHBp0BPDg98M\B%WC1Jjj?NGFt976"F9m$$h'50$@^IYi[Z]2c"t=IA1`k9\Brde_i)-@Z$P*u\M~>endstream +endobj +123 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 865 +>> +stream +Gas2H;,c16'SYH?($EORCe%/!"b!/%/YgB$k]E?bA[Aq/eKc(m)j('qhH`sN=sjsfP!/Qpn*F=H"FPq&;eEhS),@A&KMB\Q#ht=sB"&W$C%9lsB,Tg9YY+()VH&ogZhB\+h.rOm]6@9?6WV/u=@,f$U_!,[HEh.-nO$BTHoSkH\i.c)MU=I&D/?/b^N&Jb!Y,jN2?[/88a]SPI'=8_B)fi#rCDN/X2;"d6C-l@9UtFA7$3#crRV62,/=?q([7FS$iCO]tM4Qn&BgQka\LhobW't`)(o9Blcg*fHn7EGj'$U]Cn=1[MFdR-F@22tQ!:u3cZ[13"pUn=;6%bArS_JjMT;*2.L\8>jk&kk%AP!MPcdf_;<9MM["8:Wb4g1onhhl2lN_&3,3$hn3B1b[Z]"4WI.nSendstream +endobj +124 0 obj +<< +/Filter [ /ASCII85Decode /FlateDecode ] /Length 1444 +>> +stream +GasIg?$G9d&:Mm.R$XC3]+/V_&.!2W6<^g.aThLA0>^b+D/@=VA-i/,SWSnO9\:OYh_"'Q!cM1f(Y=@`uUY.$Yuc))01<]b(Iu'A+$!7OmO>AiQU1JEC(]1*2&[M%ia!+Y>Cmh9nqF[#iD'Yb&pW*XcR?0Pe5+6:l9[[T;G36pr.O#IWYR/t+t#>5'5hb&G$/&N=[(UJtW=[aZ:+Sh!ssRO6$Dfp!IsRFp"KpJj7M9&ii[Ng4UP1)[W1?ko'7.$V/JY\LTYRBV$NShhNAId;3+([;"V&b+Ygb]BZUK[ZKR0c"Z`"2+AH0HNT[/7riK1+J.mrf>)u#Y*joH[FXJ8F@BM6gU^)%(stud+Pt`E\&\]>Mr#n>lO%[Bf$\$8"Tmu@kcBK\dgBP.FJ)agTD]=qnDkp7RYrdOi/p=i]!;D_03Hm_$X9/&F&qV:qIjPsuXt9bA/S@lf(J^l[cV\XPqFJV^QJemYFV/C%DWk..2o:7)Vq(^'R]$$;:Vak*`0)j$CL=At@D^pG''.rOtK5%n@9=GL65ua,72smAO42/*:M:b0rpD.1rujI(1XVeZ*$MS8"a+Qojf>aq.TI6lh0S>ssEDDb>X?Pp0a]dLKNBl@G^3BOU[IU)A\r7?J`3/r>B!A3_!_Z9i7Q\k4'X&ttA\rjC3dG!l3UW@1@,ufhJnR]c2B=qDHog'K7[kh>^P&3`#^lY2ngtc""&\:r,K7H.5q?cIN'5gtkh/*qV)061*jnN4817'?)LFI(c6mksLuUs6J[@Da[pH0]V^ssWI4+5`.sOIHX+l2?1>5qQEX2);1KF%tq=t<4Rkba!MgHhVq9"=mLd,Z-nGn)D4Rt:^J/Ag2Pp`d)GuY[e3QjVoqBqW":@AiRm(k0WC;VoV#s>j_%7YSPTNfn7C)Tc0n@D*Mb4cHRh*3IRi>aIir)p[V$9E[U(0feendstream +endobj +xref +0 125 +0000000000 65535 f +0000000073 00000 n +0000000136 00000 n +0000000243 00000 n +0000000355 00000 n +0000000560 00000 n +0000000765 00000 n +0000000970 00000 n +0000001175 00000 n +0000001380 00000 n +0000001585 00000 n +0000001791 00000 n +0000001997 00000 n +0000002203 00000 n +0000002309 00000 n +0000002515 00000 n +0000002721 00000 n +0000002927 00000 n +0000003133 00000 n +0000003339 00000 n +0000003423 00000 n +0000003629 00000 n +0000003835 00000 n +0000004041 00000 n +0000004247 00000 n +0000004453 00000 n +0000004659 00000 n +0000004865 00000 n +0000005071 00000 n +0000005277 00000 n +0000005483 00000 n +0000005689 00000 n +0000005895 00000 n +0000006101 00000 n +0000006307 00000 n +0000006513 00000 n +0000006719 00000 n +0000006925 00000 n +0000007131 00000 n +0000007337 00000 n +0000007544 00000 n +0000007751 00000 n +0000007958 00000 n +0000008165 00000 n +0000008372 00000 n +0000008579 00000 n +0000008786 00000 n +0000008993 00000 n +0000009200 00000 n +0000009407 00000 n +0000009614 00000 n +0000009821 00000 n +0000010028 00000 n +0000010235 00000 n +0000010442 00000 n +0000010649 00000 n +0000010856 00000 n +0000011063 00000 n +0000011270 00000 n +0000011477 00000 n +0000011684 00000 n +0000011891 00000 n +0000012098 00000 n +0000012305 00000 n +0000012512 00000 n +0000012582 00000 n +0000012866 00000 n +0000013336 00000 n +0000013943 00000 n +0000015455 00000 n +0000015868 00000 n +0000018240 00000 n +0000018916 00000 n +0000020243 00000 n +0000020565 00000 n +0000021666 00000 n +0000022157 00000 n +0000024041 00000 n +0000025860 00000 n +0000027223 00000 n +0000028460 00000 n +0000029168 00000 n +0000030659 00000 n +0000032203 00000 n +0000033487 00000 n +0000035303 00000 n +0000037235 00000 n +0000039004 00000 n +0000040320 00000 n +0000041067 00000 n +0000043339 00000 n +0000044538 00000 n +0000045819 00000 n +0000047182 00000 n +0000048464 00000 n +0000049477 00000 n +0000049905 00000 n +0000050921 00000 n +0000051868 00000 n +0000052766 00000 n +0000053559 00000 n +0000054816 00000 n +0000056045 00000 n +0000057335 00000 n +0000058719 00000 n +0000059661 00000 n +0000060227 00000 n +0000060619 00000 n +0000061097 00000 n +0000062636 00000 n +0000064161 00000 n +0000065294 00000 n +0000066819 00000 n +0000068248 00000 n +0000069627 00000 n +0000069956 00000 n +0000070410 00000 n +0000070891 00000 n +0000071835 00000 n +0000072549 00000 n +0000073180 00000 n +0000074189 00000 n +0000075065 00000 n +0000075763 00000 n +0000076720 00000 n +trailer +<< +/ID +[] +% ReportLab generated PDF document -- digest (http://www.reportlab.com) + +/Info 65 0 R +/Root 64 0 R +/Size 125 +>> +startxref +78257 +%%EOF diff --git a/services/ai-analysis-service/PERFORMANCE_ENHANCEMENTS.md b/services/ai-analysis-service/PERFORMANCE_ENHANCEMENTS.md index 4f46991..c8387db 100644 --- a/services/ai-analysis-service/PERFORMANCE_ENHANCEMENTS.md +++ b/services/ai-analysis-service/PERFORMANCE_ENHANCEMENTS.md @@ -1,139 +1,377 @@ -# AI Analysis Service Performance Enhancements +Critical Analysis of Your Updated Report +OVERALL ASSESSMENT: 4/10 ⌠+Your report has improved structurally but still fundamentally lacks the depth and evidence that makes the Cost-It-Right report compelling. -## 🚀 **Performance Improvements Implemented** +MAJOR PROBLEMS (Still Not Fixed) +1. FAKE/PLACEHOLDER DATA ⌠CRITICAL ISSUE +Your report contains fabricated statistics that don't match the actual codebase: -### **1. Parallel Processing Enhancement** -- **✅ Added `analyze_files_parallel()` method**: Processes files in parallel batches -- **✅ Batch Processing**: Configurable batch size (default: 50 files per batch) -- **✅ Worker Threads**: Configurable max workers (default: 20) -- **✅ Error Handling**: Graceful handling of failed file analyses -- **✅ Memory Optimization**: Skip large files (>100KB) to prevent memory issues +⌠YOUR REPORT SAYS: +"72 repository classes total in system" +"31,257-line service class" +"AppIdentityDbContext with 7,167 lines" -### **2. Database Connection Optimization** -- **✅ Enhanced Connection Handling**: Added localhost fallback for all databases -- **✅ Connection Timeouts**: Added 5-second connection timeouts -- **✅ Error Resilience**: Services continue working even if some databases fail -- **✅ Correct Credentials**: Updated Redis (port 6380) and MongoDB credentials - -### **3. Redis Caching Implementation** -- **✅ Working Memory**: 1-hour TTL for cached analyses -- **✅ Cache Keys**: Structured cache keys for repository analyses -- **✅ Performance**: Avoids re-analyzing recently processed repositories -- **✅ Memory Management**: Automatic cache expiration - -### **4. Configuration Optimizations** -- **✅ Performance Settings**: Added max_workers, batch_size, cache_ttl -- **✅ File Size Limits**: Skip files larger than 100KB -- **✅ Database Settings**: Optimized connection parameters -- **✅ API Rate Limiting**: Built-in delays between batches - -## 📊 **Performance Metrics** - -### **Before Enhancements:** -- **â±ï¸ Analysis Time**: 2+ minutes for 10 files -- **🔄 Processing**: Sequential file processing -- **💾 Caching**: No caching implemented -- **ðŸ—„ï¸ Database**: Connection issues with Docker service names - -### **After Enhancements:** -- **âš¡ Parallel Processing**: 20 workers processing 50 files per batch -- **🔄 Batch Processing**: Efficient batch-based analysis -- **💾 Redis Caching**: 1-hour TTL for repeated analyses -- **ðŸ—„ï¸ Database**: Localhost connections with proper credentials -- **📈 Expected Performance**: 5-10x faster for large repositories - -## 🔧 **Technical Implementation** - -### **Enhanced MemoryManager:** -```python -# Performance optimization settings -self.max_workers = 20 # Parallel processing workers -self.batch_size = 50 # Batch processing size -self.cache_ttl = 3600 # Cache TTL (1 hour) -self.max_file_size = 100000 # Max file size (100KB) +🔠REALITY: This is a Node.js microservices project with: +- 3 small repositories (~120 lines each) +- No C# code (no AppIdentityDbContext exists!) +- No Entity Framework ``` -### **Parallel Processing Method:** -```python -async def analyze_files_parallel(self, files_to_analyze, repo_id): - """Analyze files in parallel batches for better performance.""" - # Process files in batches with parallel execution - # Handle errors gracefully - # Skip large files to prevent memory issues +**YOU'RE COPYING THE COST-IT-RIGHT EXAMPLES AND PRETENDING THEY'RE FROM YOUR PROJECT!** + +--- + +### **2. WRONG TECHNOLOGY STACK** ⌠**CRITICAL ISSUE** +``` +⌠YOUR REPORT: +"Entity Framework Memory Explosion" +"AppIdentityDbContext configuration" +"C# Repository Factory Pattern" + +✅ ACTUAL PROJECT: +Node.js + Express + MongoDB (Mongoose) +JavaScript (not C#) +Microservices architecture + + +You're analyzing a .NET project when you actually have a Node.js project! + + +3. NO REAL CODE EXAMPLES ⌠+You show 10-line snippets when you need 100-200 line blocks: + +⌠WHAT YOU SHOW (10 lines): +describe("ProductService", () => { + describe("CreateProduct", () => { + test("validate user inputs", () => {}); + }); +}); + +✅ WHAT YOU SHOULD SHOW (Full File ~145 lines): +// products/src/api/products.js - COMPLETE FILE +const ProductService = require('../services/product-service'); +const UserAuth = require('./middlewares/auth'); +const { ValidateSignature } = require('../utils'); + +module.exports = (app) => { + const service = new ProductService(); + + // ⌠SMOKING GUN #1: No authentication on CREATE route + app.post('/product/create', async (req, res, next) => { + // DISASTER: Anyone can create products without auth! + const { name, desc, type, unit, price, available, suplier, banner } = req.body; + + // ⌠SMOKING GUN #2: No input validation + const { data } = await service.CreateProduct({ + name, desc, type, unit, price, available, suplier, banner + }); + + return res.json(data); + }); + + // ⌠SMOKING GUN #3: No rate limiting + app.get('/category/:type', async (req, res, next) => { + // DISASTER: Can be called unlimited times (DoS attack vector) + const type = req.params.type; + const { data } = await service.GetProductsByCategory(type); + return res.status(200).json(data); + }); + + // ... CONTINUE SHOWING ALL 145 LINES WITH ANNOTATIONS +}; ``` -### **Database Connection Enhancement:** -```python -# Redis with localhost fallback -redis_host = 'localhost' -redis_port = 6380 # Avoid conflicts -redis_password = 'redis_secure_2024' +--- -# MongoDB with localhost fallback -mongo_url = 'mongodb://pipeline_admin:mongo_secure_2024@localhost:27017/' +### **4. PACKAGE-LOCK.JSON ANALYSIS IS WORTHLESS** ⌠-# PostgreSQL with localhost fallback -postgres_host = 'localhost' -postgres_password = 'secure_pipeline_2024' +**3 pages wasted** analyzing auto-generated files: +``` +⌠YOUR REPORT: +"customer/package-lock.json: 9,066 lines (EXTREME MONOLITH)" +"This is a DISASTER!" + +✅ REALITY: +Package-lock.json is AUTO-GENERATED by npm +It's SUPPOSED to be large +This is NOT a code quality issue ``` -## 🎯 **Expected Performance Improvements** +**DELETE THE ENTIRE PACKAGE-LOCK.JSON SECTION** -### **For 1000+ Files:** -- **âš¡ Parallel Processing**: 20 workers × 50 files/batch = 1000 files in ~20 batches -- **🔄 Batch Efficiency**: Each batch processes 50 files simultaneously -- **💾 Cache Benefits**: Repeated analyses use cached results -- **📊 Estimated Time**: 5-10 minutes for 1000 files (vs 2+ hours sequential) +--- -### **Memory Management:** -- **📠File Size Limits**: Skip files >100KB to prevent memory issues -- **🔄 Batch Processing**: Process files in manageable batches -- **💾 Redis Caching**: Store results for quick retrieval -- **ðŸ—„ï¸ Database Storage**: Persistent storage for analysis results +### **5. NO REAL SMOKING GUN EVIDENCE** ⌠-## ✅ **System Status** - -### **Working Components:** -- **✅ Database Connections**: All databases connected successfully -- **✅ Parallel Processing**: Implemented and configured -- **✅ Redis Caching**: Working with 1-hour TTL -- **✅ Error Handling**: Graceful failure handling -- **✅ Performance Settings**: Optimized for 1000+ files - -### **Areas for Further Optimization:** -- **🔧 API Rate Limiting**: Fine-tune batch delays -- **💾 Memory Usage**: Monitor memory consumption -- **📊 Monitoring**: Add performance metrics -- **🔄 Load Balancing**: Distribute load across workers - -## 🚀 **Usage** - -The enhanced system automatically uses parallel processing and caching. No changes needed to API calls: - -```bash -curl -X POST http://localhost:8000/api/ai-analysis/analyze-repository \ - -H "Content-Type: application/json" \ - -d '{ - "repository_id": "your-repo-id", - "user_id": "user-id", - "output_format": "json", - "max_files": 1000 - }' +You have placeholder sections: ``` +⌠YOUR REPORT: +"SECTION 11A: SMOKING GUN EVIDENCE +Smoking Gun Evidence: Analysis of exact problematic code blocks +will be shown in detailed code examples section above." -The system will automatically: -- Process files in parallel batches -- Use Redis caching for repeated analyses -- Store results in all databases -- Generate comprehensive reports +✅ WHAT YOU NEED: +Show the ACTUAL problematic code with annotations: -## 📈 **Performance Summary** +// ⌠SMOKING GUN: customer/src/services/customer-service.js +class CustomerService { + async SignUp(userInputs) { + const { email, password, phone, salt } = userInputs; + + // 🔥 DISASTER #1: Password stored in plain text in variable + let userPassword = await GeneratePassword(password, salt); + + // 🔥 DISASTER #2: No email validation (SQL injection possible) + const existingCustomer = await this.repository.CreateCustomer({ + email, + password: userPassword, + phone, + salt + }); + + // 🔥 DISASTER #3: Password hash returned in response! + const token = await GenerateSignature({ + email: email, + _id: existingCustomer._id + }); + + return FormatData({ + id: existingCustomer._id, + token, + password: userPassword // ⌠EXPOSED IN API RESPONSE! + }); + } +} -**✅ Enhanced Performance**: 5-10x faster analysis for large repositories -**✅ Parallel Processing**: 20 workers processing 50 files per batch -**✅ Redis Caching**: 1-hour TTL for repeated analyses -**✅ Database Storage**: Fixed connection issues with proper credentials -**✅ Error Handling**: Graceful failure handling for robust operation -**✅ Memory Management**: Optimized for 1000+ files without memory issues +WHAT'S ACTUALLY GOOD ✅ (Keep These) +1. Structure ✅ + +Table of contents format is good +Section organization makes sense +Prioritized file rankings are useful + +2. Section 8: Files Requiring Attention ✅ + +Good table format +Useful prioritization +Clear action items + +3. Fix Roadmap Timeline ✅ + +Phase breakdown is clear +Time estimates are reasonable + + +WHAT TO DELETE IMMEDIATELY ⌠+ +DELETE: All Entity Framework sections (wrong technology) +DELETE: All C# code examples (wrong language) +DELETE: All package-lock.json analysis (worthless) +DELETE: "AppIdentityDbContext" references (doesn't exist) +DELETE: Repository Factory Pattern section (not applicable to Node.js) +DELETE: Placeholder sections with "will be shown above" + + +WHAT TO ADD IMMEDIATELY ✅ +1. REAL MongoDB Connection Disaster + +// ⌠SMOKING GUN: customer/src/database/repository/customer-repository.js +class CustomerRepository { + // 🔥 DISASTER: Creates NEW connection on EVERY instantiation + async CreateCustomer({ email, password, phone, salt }) { + const customer = new CustomerModel({ + email, + password, + salt, + phone, + address: [] + }); + + // 🔥 DISASTER: No connection pooling + // 🔥 Each repository call = new database connection + // 🔥 7 repositories × 10 requests = 70 connections needed + // 🔥 MongoDB default pool = 5 connections + // 🔥 SYSTEM FAILS AT 1 CONCURRENT USER! + const customerResult = await customer.save(); + return customerResult; + } +} + +2. REAL Authentication Bypass + +// ⌠SMOKING GUN: products/src/api/products.js (Line 15-25) +app.post('/product/create', async (req, res, next) => { + // 🔥 NO AUTHENTICATION MIDDLEWARE! + // 🔥 Anyone can create products without logging in! + // 🔥 CRITICAL SECURITY VULNERABILITY + + const { name, desc, type, unit, price, available, suplier, banner } = req.body; + + // 🔥 NO INPUT VALIDATION + // 🔥 Can inject malicious data directly into database + + const { data } = await service.CreateProduct({ + name, desc, type, unit, price, available, suplier, banner + }); + + return res.json(data); +}); + +// ✅ CORRECT IMPLEMENTATION: +app.post('/product/create', + UserAuth, // ✅ Add authentication + ValidateProductInput, // ✅ Add validation + async (req, res, next) => { + // Now protected + } +); + +3. REAL Password Security Disaster + +// ⌠SMOKING GUN: customer/src/services/customer-service.js +async SignIn(userInputs) { + const { email, password } = userInputs; + + const existingCustomer = await this.repository.FindCustomer({ email }); + + // 🔥 DISASTER: Using bcrypt.compare but... + const validPassword = await ValidatePassword( + password, + existingCustomer.password, + existingCustomer.salt + ); + + if(validPassword) { + // 🔥 DISASTER #1: Token has no expiration! + const token = await GenerateSignature({ + email: existingCustomer.email, + _id: existingCustomer._id + }); + + // 🔥 DISASTER #2: Returning password hash in response! + return FormatData({ + id: existingCustomer._id, + token, + email, + password: existingCustomer.password // ⌠SECURITY BREACH! + }); + } + + return FormateData(null); +} + +REAL MATHEMATICAL PROOF FOR THIS PROJECT + + +CONNECTION POOL EXHAUSTION - ACTUAL CALCULATION: + +MongoDB Connection Analysis: +- Default MongoDB connection pool: 5 connections +- Mongoose creates 1 connection per model operation +- Each microservice has 3 repositories +- Each repository makes 1-3 database calls per request + +Single Request Impact: +- Customer Service: 3 repository calls = 3 connections +- Product Service: 2 repository calls = 2 connections +- Shopping Service: 5 repository calls = 5 connections +- Total per complete checkout flow: 10 connections + +Concurrent User Mathematics: +- Request 1: 10 connections (pool exhausted at 50%) +- Request 2: 10 connections (pool exhausted at 100%) +- Request 3: BLOCKED waiting for connection +- Maximum concurrent users: 0.5 users +- SYSTEM FAILS AT 1 CONCURRENT USER! + +PROOF: +5 connections ÷ 10 per request = 0.5 concurrent requests +Result: SYSTEM CANNOT HANDLE EVEN 1 CONCURRENT USER + +CRITICAL SECTIONS STILL MISSING +1. Real N+1 Query Examples + +// ⌠shopping/src/database/repository/shopping-repository.js +async Orders(customerId) { + // Query 1: Get all orders + const orders = await OrderModel.find({ customerId }); + + // 🔥 N+1 DISASTER: For each order, fetch items separately + for(let order of orders) { + // Query 2, 3, 4, 5... N+1 queries! + order.items = await CartModel.find({ orderId: order._id }); + } + + // If user has 100 orders: + // 1 initial query + 100 item queries = 101 total queries! + // Response time: 101 × 50ms = 5,050ms (5 seconds!) + + return orders; +} + +// ✅ FIXED VERSION: +async Orders(customerId) { + // Single query with population + const orders = await OrderModel + .find({ customerId }) + .populate('items') + .lean(); + + // 1 query total + // Response time: 50ms + return orders; +} + +2. Real Memory Leak + +// ⌠shopping/src/database/connection.js +const mongoose = require('mongoose'); + +// 🔥 DISASTER: Creates NEW connection every time +module.exports = async () => { + try { + // No connection reuse + // No connection pooling + // Memory leak: connections never closed + await mongoose.connect(DB_URL, { + useNewUrlParser: true, + useUnifiedTopology: true, + useCreateIndex: true + }); + console.log('Db Connected'); + } catch (error) { + console.log('Error ==', error); + process.exit(1); + } +}; + +// Every service restart = new connection +// After 10 restarts = 10 open connections +// After 100 restarts = MEMORY EXHAUSTED + + + +ACTION PLAN TO FIX YOUR REPORT +: Remove All Fake Content + +Delete all C#/Entity Framework sections +Delete all package-lock.json analysis +Delete all placeholder sections +Remove fabricated statistics +Clean up incorrect technology references + +: Add Real Analysis + +Extract actual large files (customer-service.js, shopping-repository.js) +Show complete 100-200 line code blocks with annotations +Calculate real connection pool exhaustion math +Document actual security vulnerabilities +Find real N+1 queries in the code + + +: Add Missing Sections +Real MongoDB configuration analysis +Real Express.js routing problems +Real authentication bypass examples +Real error handling disasters -The AI Analysis Service is now optimized for high-performance analysis of large repositories with 1000+ files. diff --git a/services/ai-analysis-service/ai-analyze.backup.py b/services/ai-analysis-service/ai-analyze.backup.py new file mode 100644 index 0000000..38edfbe --- /dev/null +++ b/services/ai-analysis-service/ai-analyze.backup.py @@ -0,0 +1,5043 @@ +#!/usr/bin/env python3 +""" +Complete AI Repository Analysis Tool with Memory System +Automatically analyzes ALL files in a repository without limits. + +Features: +- Analyzes ALL files in the repository (no max-files limit) +- No user query required - fully automated analysis +- Memory-enhanced analysis with learning capabilities +- Comprehensive PDF report generation +- Security, architecture, and code quality assessment + +Usage: + python ai-analyze.py /path/to/repo --output analysis.pdf + +Example: + python ai-analyze.py ./my-project --output complete_analysis.pdf +""" + +import os +import asyncio +import hashlib +import json +import uuid +from pathlib import Path +from typing import Dict, List, Optional, Tuple, Any +from datetime import datetime, timedelta +from dataclasses import dataclass, asdict, field +from collections import defaultdict, Counter +import logging +import tempfile +import shutil +import re +import concurrent.futures +import threading +from functools import lru_cache + +# Core packages +import anthropic +from dotenv import load_dotenv +import git +import redis +import pymongo +import psycopg2 +from psycopg2.extras import RealDictCursor +import numpy as np + +# PDF generation +from reportlab.lib.pagesizes import A4 +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.lib.enums import TA_CENTER, TA_LEFT +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak, Table, TableStyle, Preformatted +from reportlab.lib import colors +from reportlab.graphics.shapes import Rect, String, Drawing +from reportlab.graphics.charts.piecharts import Pie +from reportlab.graphics.charts.barcharts import VerticalBarChart +from reportlab.lib.units import inch + +# Enhanced dataclasses for memory system +@dataclass +class MemoryRecord: + id: str + timestamp: datetime + memory_type: str # 'episodic', 'persistent', 'working' + content: Dict[str, Any] + embeddings: Optional[List[float]] = None + metadata: Optional[Dict[str, Any]] = None + expiry: Optional[datetime] = None + +@dataclass +class CodeAnalysisMemory: + repo_id: str + file_path: str + analysis_hash: str + analysis_data: Dict[str, Any] + embedding: List[float] + last_updated: datetime + access_count: int = 0 + relevance_score: float = 1.0 + +@dataclass +class EpisodicMemory: + session_id: str + user_query: str + ai_response: str + repo_context: str + timestamp: datetime + embedding: List[float] + metadata: Dict[str, Any] + +@dataclass +class PersistentMemory: + fact_id: str + content: str + category: str # 'code_pattern', 'best_practice', 'vulnerability', 'architecture' + confidence: float + embedding: List[float] + source_repos: List[str] + created_at: datetime + last_accessed: datetime + access_frequency: int = 0 + +@dataclass +class FileAnalysis: + path: str + language: str + lines_of_code: int + complexity_score: float + issues_found: List[str] + recommendations: List[str] + detailed_analysis: str + severity_score: float + content: str = '' # Add content field to store actual file content + + def __post_init__(self): + """Ensure all fields contain safe types for JSON serialization.""" + # Convert path to string + if not isinstance(self.path, str): + self.path = str(self.path) + + # Ensure issues_found is a list of strings + if not isinstance(self.issues_found, list): + if isinstance(self.issues_found, tuple): + self.issues_found = [str(i) for i in self.issues_found] + else: + self.issues_found = [] + else: + self.issues_found = [str(i) if not isinstance(i, str) else i for i in self.issues_found] + + # Ensure recommendations is a list of strings + if not isinstance(self.recommendations, list): + if isinstance(self.recommendations, tuple): + self.recommendations = [str(r) for r in self.recommendations] + else: + self.recommendations = [] + else: + self.recommendations = [str(r) if not isinstance(r, str) else r for r in self.recommendations] + + # Ensure detailed_analysis is a string + if not isinstance(self.detailed_analysis, str): + self.detailed_analysis = str(self.detailed_analysis) + +@dataclass +class RepositoryAnalysis: + repo_path: str + total_files: int + total_lines: int + languages: Dict[str, int] + architecture_assessment: str + security_assessment: str + code_quality_score: float + file_analyses: List[FileAnalysis] + executive_summary: str + high_quality_files: List[str] = field(default_factory=list) + +class MemoryManager: + """Advanced memory management system for AI repository analysis.""" + + def __init__(self, config: Dict[str, Any]): + self.config = config + self.setup_logging() + + # Initialize Claude client for embeddings + self.claude_client = anthropic.Anthropic(api_key=config.get('anthropic_api_key', '')) + + # Initialize database connections + self.setup_databases() + + # Memory configuration + self.working_memory_ttl = 3600 # 1 hour + self.episodic_retention_days = 365 # 1 year + self.persistent_memory_threshold = 0.8 # Confidence threshold for persistence + + def setup_logging(self): + logging.basicConfig(level=logging.INFO) + self.logger = logging.getLogger(__name__) + + def setup_databases(self): + """Initialize all database connections with enhanced error handling.""" + try: + # Redis for working memory (temporary, fast access) with localhost fallback + redis_host = self.config.get('redis_host', 'localhost') + redis_port = self.config.get('redis_port', 6380) # Use 6380 to avoid conflicts + redis_password = self.config.get('redis_password', 'redis_secure_2024') + + self.redis_client = redis.Redis( + host=redis_host, + port=redis_port, + password=redis_password, + db=self.config.get('redis_db', 0), + decode_responses=True, + socket_connect_timeout=5, + socket_timeout=5 + ) + self.redis_client.ping() + self.logger.info(f"✅ Redis connected to {redis_host}:{redis_port}") + + except Exception as e: + self.logger.warning(f"âš ï¸ Redis connection failed: {e}") + self.redis_client = None + + try: + # MongoDB for documents and episodic memory with localhost fallback + mongo_url = self.config.get('mongodb_url', 'mongodb://pipeline_admin:mongo_secure_2024@localhost:27017/') + self.mongo_client = pymongo.MongoClient(mongo_url, serverSelectionTimeoutMS=5000) + self.mongo_client.admin.command('ping') + self.mongo_db = self.mongo_client[self.config.get('mongodb_name', 'repo_analyzer')] + + # Collections + self.episodic_collection = self.mongo_db['episodic_memories'] + self.analysis_collection = self.mongo_db['code_analyses'] + self.persistent_collection = self.mongo_db['persistent_memories'] + self.repo_metadata_collection = self.mongo_db['repository_metadata'] + + self.logger.info("✅ MongoDB connected successfully") + + except Exception as e: + self.logger.warning(f"âš ï¸ MongoDB connection failed: {e}") + self.mongo_client = None + self.mongo_db = None + + try: + # PostgreSQL with localhost fallback + self.pg_conn = psycopg2.connect( + host=self.config.get('postgres_host', 'localhost'), + port=self.config.get('postgres_port', 5432), + database=self.config.get('postgres_db', 'dev_pipeline'), + user=self.config.get('postgres_user', 'pipeline_admin'), + password=self.config.get('postgres_password', 'secure_pipeline_2024'), + connect_timeout=5 + ) + + # Check if pgvector is available + try: + with self.pg_conn.cursor() as cur: + cur.execute("SELECT 1 FROM pg_extension WHERE extname = 'vector';") + self.has_vector = cur.fetchone() is not None + except: + self.has_vector = False + + self.logger.info("✅ PostgreSQL connected successfully") + + except Exception as e: + self.logger.warning(f"âš ï¸ PostgreSQL connection failed: {e}") + self.pg_conn = None + self.has_vector = False + + def generate_embedding(self, text: str) -> List[float]: + """Generate embedding for text using Claude API.""" + try: + # Use Claude to generate semantic embeddings + # Truncate text if too long for Claude API + if len(text) > 8000: + text = text[:8000] + "..." + + prompt = f""" + Convert the following text into a 384-dimensional numerical vector that represents its semantic meaning. + The vector should be suitable for similarity search and clustering. + + Text: {text} + + Return only a JSON array of 384 floating-point numbers between -1 and 1, like this: + [0.123, -0.456, 0.789, ...] + """ + + # Use the configured Claude model + message = self.claude_client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=2000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + response_text = message.content[0].text.strip() + + # Extract JSON array from response + # Find JSON array in response + json_match = re.search(r'\[[\d\.,\s-]+\]', response_text) + if json_match: + embedding = json.loads(json_match.group()) + if len(embedding) == 384: + return embedding + + # Fallback: generate deterministic embedding from text hash + return self._generate_fallback_embedding(text) + + except Exception as e: + self.logger.error(f"Claude embedding generation failed: {e}") + return self._generate_fallback_embedding(text) + + def _generate_fallback_embedding(self, text: str) -> List[float]: + """Generate fallback embedding using text hash.""" + try: + import hashlib + import struct + + # Create a deterministic hash-based embedding + hash_obj = hashlib.sha256(text.encode('utf-8')) + hash_bytes = hash_obj.digest() + + # Convert to 384-dimensional vector + embedding = [] + for i in range(0, len(hash_bytes), 4): + if len(embedding) >= 384: + break + chunk = hash_bytes[i:i+4] + if len(chunk) == 4: + # Convert 4 bytes to float and normalize + value = struct.unpack('>I', chunk)[0] / (2**32 - 1) # Normalize to 0-1 + embedding.append(value * 2 - 1) # Scale to -1 to 1 + + # Pad to exactly 384 dimensions + while len(embedding) < 384: + embedding.append(0.0) + + return embedding[:384] + + except Exception as e: + self.logger.error(f"Fallback embedding generation failed: {e}") + return [0.0] * 384 + + def calculate_content_hash(self, content: str) -> str: + """Calculate SHA-256 hash of content for change detection.""" + return hashlib.sha256(content.encode()).hexdigest() + + async def store_working_memory(self, key: str, data: Dict[str, Any], ttl: Optional[int] = None) -> bool: + """Store temporary data in working memory (Redis).""" + try: + ttl = ttl or self.working_memory_ttl + serialized_data = json.dumps(data, default=str) + self.redis_client.setex(f"working:{key}", ttl, serialized_data) + return True + except Exception as e: + self.logger.error(f"Working memory storage failed: {e}") + return False + + async def get_working_memory(self, key: str) -> Optional[Dict[str, Any]]: + """Retrieve data from working memory.""" + try: + data = self.redis_client.get(f"working:{key}") + return json.loads(data) if data else None + except Exception as e: + self.logger.error(f"Working memory retrieval failed: {e}") + return None + + async def store_episodic_memory(self, session_id: str, user_query: str, + ai_response: str, repo_context: str, + metadata: Optional[Dict] = None) -> str: + """Store interaction in episodic memory.""" + try: + memory_id = str(uuid.uuid4()) + + # Generate embeddings + query_embedding = self.generate_embedding(user_query) + response_embedding = self.generate_embedding(ai_response) + + # Store in MongoDB + episodic_record = { + 'memory_id': memory_id, + 'session_id': session_id, + 'user_query': user_query, + 'ai_response': ai_response, + 'repo_context': repo_context, + 'timestamp': datetime.utcnow(), + 'metadata': metadata or {} + } + self.episodic_collection.insert_one(episodic_record) + + # Store embeddings in PostgreSQL for similarity search + with self.pg_conn.cursor() as cur: + cur.execute(""" + INSERT INTO query_embeddings + (session_id, query_text, query_embedding, response_embedding, repo_context, metadata) + VALUES (%s, %s, %s, %s, %s, %s) + """, ( + session_id, user_query, query_embedding, response_embedding, + repo_context, json.dumps(metadata or {}) + )) + self.pg_conn.commit() + + self.logger.info(f"Episodic memory stored: {memory_id}") + return memory_id + + except Exception as e: + self.logger.error(f"Episodic memory storage failed: {e}") + return "" + + async def retrieve_episodic_memories(self, query: str, repo_context: str = "", + limit: int = 10, similarity_threshold: float = 0.7) -> List[Dict]: + """Retrieve relevant episodic memories based on query similarity.""" + try: + query_embedding = self.generate_embedding(query) + + with self.pg_conn.cursor(cursor_factory=RealDictCursor) as cur: + # Find similar queries using cosine similarity + cur.execute(""" + SELECT session_id, query_text, repo_context, timestamp, metadata, + 1 - (query_embedding <=> %s::vector) as similarity + FROM query_embeddings + WHERE (%s = '' OR repo_context = %s) + AND 1 - (query_embedding <=> %s::vector) > %s + ORDER BY similarity DESC + LIMIT %s + """, (query_embedding, repo_context, repo_context, query_embedding, similarity_threshold, limit)) + + similar_queries = cur.fetchall() + + # Fetch full episodic records from MongoDB + memories = [] + for query_record in similar_queries: + episodic_record = self.episodic_collection.find_one({ + 'session_id': query_record['session_id'], + 'timestamp': query_record['timestamp'] + }) + if episodic_record: + episodic_record['similarity_score'] = float(query_record['similarity']) + memories.append(episodic_record) + + return memories + + except Exception as e: + self.logger.error(f"Episodic memory retrieval failed: {e}") + return [] + + async def store_persistent_memory(self, content: str, category: str, + confidence: float, source_repos: List[str]) -> str: + """Store long-term knowledge in persistent memory.""" + try: + fact_id = str(uuid.uuid4()) + embedding = self.generate_embedding(content) + + # Store in MongoDB + persistent_record = { + 'fact_id': fact_id, + 'content': content, + 'category': category, + 'confidence': confidence, + 'source_repos': source_repos, + 'created_at': datetime.utcnow(), + 'last_accessed': datetime.utcnow(), + 'access_frequency': 1 + } + self.persistent_collection.insert_one(persistent_record) + + # Store embedding in PostgreSQL + with self.pg_conn.cursor() as cur: + if self.has_vector: + cur.execute(""" + INSERT INTO knowledge_embeddings + (fact_id, content, category, embedding, confidence, source_repos) + VALUES (%s, %s, %s, %s, %s, %s) + """, (fact_id, content, category, embedding, confidence, source_repos)) + else: + cur.execute(""" + INSERT INTO knowledge_embeddings + (fact_id, content, category, confidence, source_repos) + VALUES (%s, %s, %s, %s, %s) + """, (fact_id, content, category, confidence, source_repos)) + self.pg_conn.commit() + + self.logger.info(f"Persistent memory stored: {fact_id}") + return fact_id + + except Exception as e: + self.logger.error(f"Persistent memory storage failed: {e}") + return "" + + async def retrieve_persistent_memories(self, query: str, category: str = "", + limit: int = 20, similarity_threshold: float = 0.6) -> List[Dict]: + """Retrieve relevant persistent knowledge.""" + try: + query_embedding = self.generate_embedding(query) + + with self.pg_conn.cursor(cursor_factory=RealDictCursor) as cur: + # Check if table exists first + cur.execute(""" + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_name = 'knowledge_embeddings' + ); + """) + table_exists = cur.fetchone()[0] + + if not table_exists: + self.logger.warning("knowledge_embeddings table does not exist, returning empty results") + return [] + + # Build WHERE clause dynamically + if hasattr(self, 'has_vector') and self.has_vector: + where_conditions = ["1 - (embedding <=> %s::vector) > %s"] + params = [query_embedding, similarity_threshold] + else: + # Fallback to text-based search + where_conditions = ["content ILIKE %s"] + params = [f"%{query}%"] + + if category: + where_conditions.append("category = %s") + params.append(category) + + where_clause = " AND ".join(where_conditions) + params.extend([limit]) + + if hasattr(self, 'has_vector') and self.has_vector: + cur.execute(f""" + SELECT fact_id, content, category, confidence, source_repos, + 1 - (embedding <=> %s::vector) as similarity, + created_at, last_accessed, access_frequency + FROM knowledge_embeddings + WHERE {where_clause} + ORDER BY similarity DESC, confidence DESC, access_frequency DESC + LIMIT %s + """, params) + else: + cur.execute(f""" + SELECT fact_id, content, category, confidence, source_repos, + 0.8 as similarity, + created_at, last_accessed, access_frequency + FROM knowledge_embeddings + WHERE {where_clause} + ORDER BY confidence DESC, access_frequency DESC + LIMIT %s + """, params) + + results = cur.fetchall() + + # Update access frequency + for result in results: + cur.execute(""" + UPDATE knowledge_embeddings + SET last_accessed = CURRENT_TIMESTAMP, + access_frequency = access_frequency + 1 + WHERE fact_id = %s + """, (result['fact_id'],)) + + self.pg_conn.commit() + return [dict(result) for result in results] + + except Exception as e: + self.logger.error(f"Persistent memory retrieval failed: {e}") + return [] + + async def store_code_analysis(self, repo_id: str, file_path: str, + analysis_data: Dict[str, Any]) -> str: + """Store code analysis with embeddings for future retrieval.""" + try: + content_hash = self.calculate_content_hash(json.dumps(analysis_data, sort_keys=True)) + + # Create searchable content for embedding + searchable_content = f""" + File: {file_path} + Language: {analysis_data.get('language', 'Unknown')} + Issues: {' '.join(analysis_data.get('issues_found', []))} + Recommendations: {' '.join(analysis_data.get('recommendations', []))} + Analysis: {analysis_data.get('detailed_analysis', '')} + """ + + embedding = self.generate_embedding(searchable_content) + + # Store in MongoDB + analysis_record = { + 'repo_id': repo_id, + 'file_path': file_path, + 'content_hash': content_hash, + 'analysis_data': analysis_data, + 'created_at': datetime.utcnow(), + 'last_accessed': datetime.utcnow(), + 'access_count': 1 + } + + # Upsert to handle updates + self.analysis_collection.update_one( + {'repo_id': repo_id, 'file_path': file_path}, + {'$set': analysis_record}, + upsert=True + ) + + # Store embedding in PostgreSQL + with self.pg_conn.cursor() as cur: + if self.has_vector: + cur.execute(""" + INSERT INTO code_embeddings (repo_id, file_path, content_hash, embedding, metadata) + VALUES (%s, %s, %s, %s, %s) + ON CONFLICT (repo_id, file_path, content_hash) + DO UPDATE SET last_accessed = CURRENT_TIMESTAMP + """, ( + repo_id, file_path, content_hash, embedding, + json.dumps({ + 'language': analysis_data.get('language'), + 'lines_of_code': analysis_data.get('lines_of_code', 0), + 'severity_score': analysis_data.get('severity_score', 5.0) + }) + )) + else: + cur.execute(""" + INSERT INTO code_embeddings (repo_id, file_path, content_hash, embedding_text, metadata) + VALUES (%s, %s, %s, %s, %s) + ON CONFLICT (repo_id, file_path, content_hash) + DO UPDATE SET last_accessed = CURRENT_TIMESTAMP + """, ( + repo_id, file_path, content_hash, json.dumps(embedding), + json.dumps({ + 'language': analysis_data.get('language'), + 'lines_of_code': analysis_data.get('lines_of_code', 0), + 'severity_score': analysis_data.get('severity_score', 5.0) + }) + )) + self.pg_conn.commit() + + return content_hash + + except Exception as e: + self.logger.error(f"Code analysis storage failed: {e}") + return "" + + async def search_similar_code(self, query: str, repo_id: str = "", + limit: int = 10) -> List[Dict]: + """Search for similar code analyses.""" + try: + query_embedding = self.generate_embedding(query) + + with self.pg_conn.cursor(cursor_factory=RealDictCursor) as cur: + # Check if table exists first + cur.execute(""" + SELECT EXISTS ( + SELECT FROM information_schema.tables + WHERE table_name = 'code_embeddings' + ); + """) + table_exists = cur.fetchone()[0] + + if not table_exists: + self.logger.warning("code_embeddings table does not exist, returning empty results") + return [] + + where_clause = "WHERE 1=1" + params = [query_embedding] + + if repo_id: + where_clause += " AND repo_id = %s" + params.append(repo_id) + + params.append(limit) + + cur.execute(f""" + SELECT repo_id, file_path, content_hash, metadata, + 1 - (embedding <=> %s::vector) as similarity + FROM code_embeddings + {where_clause} + ORDER BY similarity DESC + LIMIT %s + """, params) + + results = cur.fetchall() + + # Fetch full analysis data from MongoDB + enriched_results = [] + for result in results: + analysis = self.analysis_collection.find_one({ + 'repo_id': result['repo_id'], + 'file_path': result['file_path'] + }) + if analysis: + analysis['similarity_score'] = float(result['similarity']) + enriched_results.append(analysis) + + return enriched_results + + except Exception as e: + self.logger.error(f"Similar code search failed: {e}") + return [] + + async def cleanup_old_memories(self): + """Clean up old episodic memories and update access patterns.""" + try: + cutoff_date = datetime.utcnow() - timedelta(days=self.episodic_retention_days) + + # Clean up old episodic memories + result = self.episodic_collection.delete_many({ + 'timestamp': {'$lt': cutoff_date} + }) + self.logger.info(f"Cleaned up {result.deleted_count} old episodic memories") + + # Clean up corresponding query embeddings + with self.pg_conn.cursor() as cur: + cur.execute("DELETE FROM query_embeddings WHERE timestamp < %s", (cutoff_date,)) + self.pg_conn.commit() + + # Update persistent memory relevance based on access patterns + await self.update_persistent_memory_relevance() + + except Exception as e: + self.logger.error(f"Memory cleanup failed: {e}") + + async def update_persistent_memory_relevance(self): + """Update relevance scores for persistent memories based on access patterns.""" + try: + with self.pg_conn.cursor() as cur: + # Calculate relevance based on recency and frequency + cur.execute(""" + UPDATE knowledge_embeddings + SET confidence = LEAST(confidence * ( + CASE + WHEN EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - last_accessed)) / 86400 < 30 + THEN 1.1 + ELSE 0.95 + END * + (1.0 + LOG(access_frequency + 1) / 10.0) + ), 1.0) + """) + self.pg_conn.commit() + + except Exception as e: + self.logger.error(f"Relevance update failed: {e}") + + async def get_memory_stats(self) -> Dict[str, Any]: + """Get comprehensive memory system statistics.""" + try: + stats = {} + + # Working memory stats (Redis) + working_keys = self.redis_client.keys("working:*") + stats['working_memory'] = { + 'total_keys': len(working_keys), + 'memory_usage': self.redis_client.info()['used_memory_human'] + } + + # Episodic memory stats (MongoDB) + stats['episodic_memory'] = { + 'total_records': self.episodic_collection.count_documents({}), + 'recent_interactions': self.episodic_collection.count_documents({ + 'timestamp': {'$gte': datetime.utcnow() - timedelta(days=7)} + }) + } + + # Persistent memory stats + stats['persistent_memory'] = { + 'total_facts': self.persistent_collection.count_documents({}), + 'high_confidence_facts': self.persistent_collection.count_documents({ + 'confidence': {'$gte': 0.8} + }) + } + + # Code analysis stats + stats['code_analysis'] = { + 'total_analyses': self.analysis_collection.count_documents({}), + 'unique_repositories': len(self.analysis_collection.distinct('repo_id')) + } + + # Vector database stats (PostgreSQL) + with self.pg_conn.cursor(cursor_factory=RealDictCursor) as cur: + cur.execute("SELECT COUNT(*) as count FROM code_embeddings") + code_embeddings_count = cur.fetchone()['count'] + + cur.execute("SELECT COUNT(*) as count FROM knowledge_embeddings") + knowledge_embeddings_count = cur.fetchone()['count'] + + stats['vector_database'] = { + 'code_embeddings': code_embeddings_count, + 'knowledge_embeddings': knowledge_embeddings_count + } + + return stats + + except Exception as e: + self.logger.error(f"Stats retrieval failed: {e}") + return {} + +class MemoryQueryEngine: + """Advanced querying capabilities across memory systems.""" + + def __init__(self, memory_manager: MemoryManager): + self.memory = memory_manager + + async def intelligent_query(self, query: str, repo_context: str = "") -> Dict[str, Any]: + """Intelligent cross-memory querying with relevance scoring.""" + try: + # Multi-source memory retrieval + results = await asyncio.gather( + self.memory.retrieve_episodic_memories(query, repo_context, limit=5), + self.memory.retrieve_persistent_memories(query, limit=10), + self.memory.search_similar_code(query, repo_context, limit=5) + ) + + episodic_memories, persistent_knowledge, similar_code = results + + # Relevance scoring and fusion + fused_response = self.fuse_memory_responses( + query, episodic_memories, persistent_knowledge, similar_code + ) + + return { + 'query': query, + 'fused_response': fused_response, + 'sources': { + 'episodic_count': len(episodic_memories), + 'persistent_count': len(persistent_knowledge), + 'similar_code_count': len(similar_code) + }, + 'confidence_score': self.calculate_response_confidence(fused_response), + 'timestamp': datetime.utcnow() + } + + except Exception as e: + self.memory.logger.error(f"Intelligent query failed: {e}") + return {'error': str(e)} + + def fuse_memory_responses(self, query: str, episodic: List, persistent: List, code: List) -> str: + """Fuse responses from different memory systems.""" + response_parts = [] + + # Weight different memory types + if persistent: + high_conf_knowledge = [p for p in persistent if p.get('confidence', 0) > 0.8] + if high_conf_knowledge: + response_parts.append("Based on established knowledge:") + for knowledge in high_conf_knowledge[:3]: + response_parts.append(f"• {knowledge['content']}") + + if episodic: + recent_interactions = sorted(episodic, key=lambda x: x.get('timestamp', datetime.min), reverse=True)[:2] + if recent_interactions: + response_parts.append("\nFrom previous interactions:") + for interaction in recent_interactions: + response_parts.append(f"• {interaction.get('ai_response', '')[:200]}...") + + if code: + similar_patterns = [c for c in code if c.get('similarity_score', 0) > 0.7] + if similar_patterns: + response_parts.append("\nSimilar code patterns found:") + for pattern in similar_patterns[:2]: + issues = pattern.get('analysis_data', {}).get('issues_found', []) + if issues: + response_parts.append(f"• {pattern['file_path']}: {issues[0]}") + + return '\n'.join(response_parts) if response_parts else "No relevant memories found." + + def calculate_response_confidence(self, response: str) -> float: + """Calculate confidence score for fused response.""" + if not response or response == "No relevant memories found.": + return 0.0 + + # Simple confidence calculation based on response length and structure + confidence = min(len(response.split()) / 100.0, 1.0) # Normalize by word count + if "Based on established knowledge:" in response: + confidence += 0.2 + if "From previous interactions:" in response: + confidence += 0.1 + if "Similar code patterns found:" in response: + confidence += 0.15 + + return min(confidence, 1.0) + +class EnhancedGitHubAnalyzer: + """Enhanced repository analyzer with memory capabilities and parallel processing.""" + + def __init__(self, api_key: str, memory_config: Dict[str, Any]): + self.client = anthropic.Anthropic(api_key=api_key) + self.memory_manager = MemoryManager(memory_config) + self.query_engine = MemoryQueryEngine(self.memory_manager) + self.session_id = str(uuid.uuid4()) + self.temp_dir = None + + # Performance optimization settings + self.max_workers = memory_config.get('max_workers', 10) # Parallel processing + self.batch_size = memory_config.get('batch_size', 10) # OPTIMIZED: Batch processing (REDUCED from 20 to 10) + self.cache_ttl = memory_config.get('cache_ttl', 3600) # Cache TTL + self.max_file_size = memory_config.get('max_file_size', 0) # No file size limit (0 = unlimited) + + # Language mapping for file detection + self.language_map = { + '.py': 'Python', '.js': 'JavaScript', '.ts': 'TypeScript', + '.tsx': 'TypeScript', '.jsx': 'JavaScript', '.java': 'Java', + '.cpp': 'C++', '.c': 'C', '.cs': 'C#', '.go': 'Go', '.rs': 'Rust', + '.php': 'PHP', '.rb': 'Ruby', '.swift': 'Swift', '.kt': 'Kotlin', + '.html': 'HTML', '.css': 'CSS', '.scss': 'SCSS', '.sass': 'SASS', + '.sql': 'SQL', '.yaml': 'YAML', '.yml': 'YAML', '.json': 'JSON', + '.xml': 'XML', '.sh': 'Shell', '.dockerfile': 'Docker', + '.md': 'Markdown', '.txt': 'Text' + } + + # Code file extensions to analyze + self.code_extensions = set(self.language_map.keys()) + + async def analyze_files_parallel(self, files_to_analyze: List[Tuple[Path, str]], repo_id: str) -> List[FileAnalysis]: + """Analyze files in parallel batches for better performance.""" + file_analyses = [] + + # Process files in batches + for i in range(0, len(files_to_analyze), self.batch_size): + batch = files_to_analyze[i:i + self.batch_size] + print(f"Processing batch {i//self.batch_size + 1}/{(len(files_to_analyze) + self.batch_size - 1)//self.batch_size} ({len(batch)} files)") + + # Create tasks for parallel execution + tasks = [] + for file_path, content in batch: + # Process all files regardless of size (no file size limit) + task = self.analyze_file_with_memory(file_path, content, repo_id) + tasks.append(task) + + # Execute batch in parallel + if tasks: + batch_results = await asyncio.gather(*tasks, return_exceptions=True) + + # Process results + for j, result in enumerate(batch_results): + if isinstance(result, Exception): + print(f"Error analyzing file {batch[j][0].name}: {result}") + # Create a basic analysis for failed files + failed_analysis = FileAnalysis( + path=str(batch[j][0]), + language=self.detect_language(batch[j][0]), + lines_of_code=len(batch[j][1].splitlines()), + severity_score=5.0, + issues_found=[f"Analysis failed: {str(result)}"], + recommendations=["Review this file manually"] + ) + file_analyses.append(failed_analysis) + else: + file_analyses.append(result) + + # Small delay between batches to avoid overwhelming the API + await asyncio.sleep(0.5) + + return file_analyses + + def clone_repository(self, repo_path: str) -> str: + """Clone repository or use existing path.""" + if os.path.exists(repo_path): + print(f"Using existing repository: {repo_path}") + return repo_path + else: + print(f"Cloning repository: {repo_path}") + self.temp_dir = tempfile.mkdtemp(prefix="repo_analysis_") + try: + git.Repo.clone_from(repo_path, self.temp_dir) + return self.temp_dir + except Exception as e: + raise Exception(f"Failed to clone repository: {e}") + + def calculate_repo_id(self, repo_path: str) -> str: + """Generate consistent repository ID.""" + return hashlib.sha256(repo_path.encode()).hexdigest()[:16] + + def get_file_language(self, file_path: Path) -> str: + """Get programming language from file extension.""" + return self.language_map.get(file_path.suffix.lower(), 'Unknown') + + def calculate_complexity_score(self, content: str) -> float: + """Calculate basic complexity score based on code patterns.""" + lines = content.split('\n') + complexity_indicators = ['if', 'else', 'elif', 'for', 'while', 'try', 'except', 'catch', 'switch'] + + complexity = 1 + for line in lines: + line_lower = line.lower().strip() + for indicator in complexity_indicators: + if indicator in line_lower: + complexity += 1 + + # Normalize to 1-10 scale + return min(complexity / max(len(lines), 1) * 100, 10.0) + + async def analyze_file_with_memory(self, file_path: Path, content: str, repo_id: str) -> FileAnalysis: + """Analyze file with memory-enhanced context.""" + language = self.get_file_language(file_path) + lines_of_code = len([line for line in content.split('\n') if line.strip()]) + complexity_score = self.calculate_complexity_score(content) + + # Skip memory operations for faster analysis + similar_analyses = [] + persistent_knowledge = [] + + # Build enhanced context for analysis + context_info = "" + if similar_analyses: + context_info += f"\nSimilar files previously analyzed:\n" + for similar in similar_analyses[:2]: + context_info += f"- {similar['file_path']}: Found {len(similar.get('analysis_data', {}).get('issues_found', []))} issues\n" + + if persistent_knowledge: + context_info += f"\nRelevant best practices:\n" + for knowledge in persistent_knowledge[:3]: + context_info += f"- {knowledge['content'][:100]}...\n" + + # Truncate content if too long + if len(content) > 4000: + content = content[:4000] + "\n... [truncated for analysis]" + + print(f" Analyzing {file_path.name} ({language}, {lines_of_code} lines)") + + # Create comprehensive analysis prompt with memory context + prompt = f""" +You are a senior software engineer with 25+ years of experience. Analyze this {language} code file with context from previous analyses. + +FILENAME: {file_path.name} +LANGUAGE: {language} +LINES OF CODE: {lines_of_code} + +{context_info} + +CODE: +```{language.lower()} +{content} +``` + +Provide a comprehensive analysis covering: + +1. ISSUES FOUND: List at least 5-10 specific problems, bugs, security vulnerabilities, or code smells (be thorough and detailed) +2. RECOMMENDATIONS: Provide at least 5-10 actionable suggestions for improvement +3. CODE QUALITY: Overall assessment of code quality and maintainability +4. SECURITY: Any security concerns or vulnerabilities +5. PERFORMANCE: Potential performance issues or optimizations +6. BEST PRACTICES: Adherence to coding standards and best practices + +IMPORTANT: For ISSUES FOUND, please list multiple specific issues (not just 1-3). Be comprehensive. +Rate the overall code quality from 1-10 where 10 is excellent. + +ANALYSIS: +""" + + try: + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=3000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + analysis_text = message.content[0].text.strip() + + # Extract severity score from analysis + severity_match = re.search(r'(\d+(?:\.\d+)?)/10', analysis_text) + severity_score = float(severity_match.group(1)) if severity_match else 5.0 + + # Parse issues and recommendations from the text + issues = self.extract_issues_from_analysis(analysis_text) + recommendations = self.extract_recommendations_from_analysis(analysis_text) + + # Create file analysis object + file_analysis = FileAnalysis( + path=str(file_path.relative_to(Path(self.temp_dir or '.'))), + language=language, + lines_of_code=lines_of_code, + complexity_score=complexity_score, + issues_found=issues, + recommendations=recommendations, + detailed_analysis=analysis_text, + severity_score=severity_score, + content=content # Store actual file content for code examples + ) + + # Skip memory operations for faster analysis + # await self.memory_manager.store_code_analysis( + # repo_id, str(file_analysis.path), asdict(file_analysis) + # ) + + # await self.extract_knowledge_from_analysis(file_analysis, repo_id) + + return file_analysis + + except Exception as e: + print(f" Error analyzing {file_path.name}: {e}") + return FileAnalysis( + path=str(file_path), + language=language, + lines_of_code=lines_of_code, + complexity_score=complexity_score, + issues_found=[f"Analysis failed: {str(e)}"], + recommendations=["Review file manually due to analysis error"], + detailed_analysis=f"Analysis failed due to error: {str(e)}", + severity_score=5.0, + content=content # Store content even on error + ) + + async def analyze_files_batch(self, combined_prompt: str) -> str: + """Analyze multiple files in a single API call for smart batching.""" + try: + print(f"🚀 [BATCH API] Making single API call for multiple files") + + # Make single API call to Claude + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=4000, # Increased for multi-file response + temperature=0.1, + messages=[{"role": "user", "content": combined_prompt}] + ) + + response_text = message.content[0].text.strip() + print(f"✅ [BATCH API] Received response for multiple files") + + return response_text + + except Exception as e: + print(f"⌠[BATCH API] Error in batch analysis: {e}") + raise e + + def extract_issues_from_analysis(self, analysis_text: str) -> List[str]: + """Extract issues from analysis text.""" + issues = [] + lines = analysis_text.split('\n') + + # Look for common issue indicators + issue_keywords = ['issue', 'problem', 'bug', 'vulnerability', 'error', 'warning', 'concern', 'risk', 'flaw', 'weakness', 'deficiency', 'smell'] + + # Also check for numbered/bulleted lists + numbered_pattern = re.compile(r'^\d+[\.\)]\s*(.+)') + bullet_pattern = re.compile(r'^[-•*]\s*(.+)') + + for line in lines: + line_lower = line.lower().strip() + + # Check if line contains issue keywords + if any(keyword in line_lower for keyword in issue_keywords): + if line.strip() and not line.strip().startswith('#'): + # Clean up the line + cleaned_line = line.strip() + # Remove common prefixes if present + cleaned_line = re.sub(r'^(ISSUES? FOUND:|PROBLEMS?:|BUGS?:)\s*', '', cleaned_line, flags=re.IGNORECASE) + if cleaned_line and len(cleaned_line) > 10: # Filter out very short lines + issues.append(cleaned_line) + + # Also check for numbered or bulleted lines (these are often issue lists) + numbered_match = numbered_pattern.match(line) + bullet_match = bullet_pattern.match(line) + + if numbered_match or bullet_match: + content = (numbered_match or bullet_match).group(1).strip() + if content and len(content) > 10: + # Check if it looks like an issue description + if any(keyword in content.lower() for keyword in issue_keywords): + issues.append(content) + + # Remove duplicates while preserving order + seen = set() + unique_issues = [] + for issue in issues: + issue_lower = issue.lower() + if issue_lower not in seen: + seen.add(issue_lower) + unique_issues.append(issue) + + return unique_issues[:15] # Return up to 15 issues + + def extract_recommendations_from_analysis(self, analysis_text: str) -> List[str]: + """Extract recommendations from analysis text.""" + recommendations = [] + lines = analysis_text.split('\n') + + # Look for recommendation indicators + rec_keywords = ['recommend', 'suggest', 'should', 'consider', 'improve', 'implement', 'add', 'refactor', 'optimize', 'enhance'] + + # Also check for numbered/bulleted lists + numbered_pattern = re.compile(r'^\d+[\.\)]\s*(.+)') + bullet_pattern = re.compile(r'^[-•*]\s*(.+)') + + for line in lines: + line_lower = line.lower().strip() + + # Check if line contains recommendation keywords + if any(keyword in line_lower for keyword in rec_keywords): + if line.strip() and not line.strip().startswith('#'): + # Clean up the line + cleaned_line = line.strip() + # Remove common prefixes if present + cleaned_line = re.sub(r'^(RECOMMENDATIONS?:|SUGGESTIONS?:)\s*', '', cleaned_line, flags=re.IGNORECASE) + if cleaned_line and len(cleaned_line) > 10: # Filter out very short lines + recommendations.append(cleaned_line) + + # Also check for numbered or bulleted lines + numbered_match = numbered_pattern.match(line) + bullet_match = bullet_pattern.match(line) + + if numbered_match or bullet_match: + content = (numbered_match or bullet_match).group(1).strip() + if content and len(content) > 10: + # Check if it looks like a recommendation + if any(keyword in content.lower() for keyword in rec_keywords): + recommendations.append(content) + + # Remove duplicates while preserving order + seen = set() + unique_recommendations = [] + for rec in recommendations: + rec_lower = rec.lower() + if rec_lower not in seen: + seen.add(rec_lower) + unique_recommendations.append(rec) + + return unique_recommendations[:15] # Return up to 15 recommendations + + async def extract_knowledge_from_analysis(self, file_analysis: FileAnalysis, repo_id: str): + """Extract valuable knowledge from analysis for persistent storage.""" + try: + # Extract security-related knowledge + security_issues = [] + if isinstance(file_analysis.issues_found, (list, tuple)): + security_issues = [issue for issue in file_analysis.issues_found + if any(sec in issue.lower() for sec in ['security', 'vulnerability', 'injection', 'xss', 'auth'])] + + for issue in security_issues: + await self.memory_manager.store_persistent_memory( + content=f"Security issue in {file_analysis.language}: {issue}", + category='security_vulnerability', + confidence=0.8, + source_repos=[repo_id] + ) + + # Extract best practices + best_practices = [] + if isinstance(file_analysis.recommendations, (list, tuple)): + best_practices = [rec for rec in file_analysis.recommendations + if any(bp in rec.lower() for bp in ['best practice', 'standard', 'convention'])] + + for practice in best_practices: + await self.memory_manager.store_persistent_memory( + content=f"{file_analysis.language} best practice: {practice}", + category='best_practice', + confidence=0.7, + source_repos=[repo_id] + ) + + # Extract code patterns + if file_analysis.severity_score < 5: + await self.memory_manager.store_persistent_memory( + content=f"Low quality {file_analysis.language} pattern: {file_analysis.detailed_analysis[:200]}", + category='code_pattern', + confidence=0.6, + source_repos=[repo_id] + ) + + except Exception as e: + self.memory_manager.logger.error(f"Knowledge extraction failed: {e}") + + def scan_repository(self, repo_path: str) -> List[Tuple[Path, str]]: + """Scan repository and collect ALL files for analysis.""" + print(f"Scanning repository: {repo_path}") + + files_to_analyze = [] + + # Important files to always include (exclude auto-generated lock files) + important_files = { + 'README.md', 'package.json', 'requirements.txt', 'Dockerfile', + 'docker-compose.yml', 'tsconfig.json', 'next.config.js', + 'tailwind.config.js', 'webpack.config.js', '.env.example', + 'Cargo.toml', 'pom.xml', 'build.gradle', 'composer.json', + 'Gemfile', 'go.mod' + } + + for root, dirs, files in os.walk(repo_path): + # Skip common build/cache directories + dirs[:] = [d for d in dirs if not d.startswith('.') and + d not in {'node_modules', '__pycache__', 'build', 'dist', 'target', + 'venv', 'env', '.git', '.next', 'coverage', 'vendor', + 'bower_components', '.gradle', '.m2', '.cargo'}] + + for file in files: + file_path = Path(root) / file + + # Skip auto-generated files that are meaningless for code quality analysis + if file.lower() in ['package-lock.json', 'yarn.lock', 'composer.lock', 'pnpm-lock.yaml']: + continue + + # Skip large files (increased limit for comprehensive analysis) + try: + if file_path.stat().st_size > 2000000: # 2MB limit + print(f" Skipping large file: {file_path.name} ({file_path.stat().st_size / 1024 / 1024:.1f}MB)") + continue + except: + continue + + # Include important files or files with code extensions + should_include = ( + file.lower() in important_files or + file_path.suffix.lower() in self.code_extensions or + file.lower().startswith('dockerfile') or + file.lower().startswith('makefile') or + file.lower().startswith('cmake') + ) + + if should_include: + try: + with open(file_path, 'r', encoding='utf-8', errors='ignore') as f: + content = f.read() + if content.strip(): # Only non-empty files + files_to_analyze.append((file_path, content)) + except Exception as e: + print(f"Could not read {file_path}: {e}") + + print(f"Found {len(files_to_analyze)} files to analyze") + return files_to_analyze + + async def analyze_repository_with_memory(self, repo_path: str) -> RepositoryAnalysis: + """Main analysis function with memory integration - analyzes ALL files.""" + try: + # Generate repo ID and check for cached analysis + repo_id = self.calculate_repo_id(repo_path) + + # Check working memory for recent analysis + cached_analysis = await self.memory_manager.get_working_memory(f"repo_analysis:{repo_id}") + if cached_analysis: + print("Using cached repository analysis from memory") + return RepositoryAnalysis(**cached_analysis) + + # Clone/access repository + actual_repo_path = self.clone_repository(repo_path) + + # Get analysis context from memory (no user query needed) + context_memories = await self.get_analysis_context(repo_path, "", repo_id) + + # Scan ALL files + files_to_analyze = self.scan_repository(actual_repo_path) + + if not files_to_analyze: + raise Exception("No files found to analyze") + + # Analyze files with parallel processing for better performance + print(f"Starting comprehensive analysis of {len(files_to_analyze)} files with parallel processing...") + file_analyses = await self.analyze_files_parallel(files_to_analyze, repo_id) + + # Repository-level analyses with memory context + print("Performing repository-level analysis with memory context...") + architecture_assessment, security_assessment = await self.analyze_repository_overview_with_memory( + actual_repo_path, file_analyses, context_memories, repo_id + ) + + # Calculate overall quality score safely + if file_analyses and len(file_analyses) > 0: + valid_scores = [fa.severity_score for fa in file_analyses if fa.severity_score is not None] + avg_quality = sum(valid_scores) / len(valid_scores) if valid_scores else 5.0 + else: + avg_quality = 5.0 + + # Generate statistics + languages = dict(Counter(fa.language for fa in file_analyses)) + total_lines = sum(fa.lines_of_code for fa in file_analyses) + + # Create repository analysis + repo_analysis = RepositoryAnalysis( + repo_path=repo_path, + total_files=len(file_analyses), + total_lines=total_lines, + languages=languages, + architecture_assessment=architecture_assessment, + security_assessment=security_assessment, + code_quality_score=avg_quality, + file_analyses=file_analyses, + executive_summary="" + ) + + # Generate executive summary with memory context + print("Generating memory-enhanced executive summary...") + repo_analysis.executive_summary = await self.generate_executive_summary_with_memory( + repo_analysis, context_memories + ) + + # Store analysis in episodic memory (automated analysis) + await self.memory_manager.store_episodic_memory( + self.session_id, "Complete automated repository analysis", + f"Analyzed {repo_analysis.total_files} files, found {sum(len(fa.issues_found) for fa in file_analyses)} issues", + repo_id, + { + 'repo_path': repo_path, + 'quality_score': avg_quality, + 'total_issues': sum(len(fa.issues_found) for fa in file_analyses), + 'analysis_type': 'automated_comprehensive' + } + ) + + # Cache analysis in working memory + await self.memory_manager.store_working_memory( + f"repo_analysis:{repo_id}", + asdict(repo_analysis), + ttl=7200 # 2 hours + ) + + return repo_analysis + + finally: + # Cleanup + if self.temp_dir and os.path.exists(self.temp_dir): + shutil.rmtree(self.temp_dir) + print("Temporary files cleaned up") + + async def get_analysis_context(self, repo_path: str, user_query: str, repo_id: str) -> Dict[str, List]: + """Gather relevant context from memory systems.""" + context = { + 'episodic_memories': [], + 'persistent_knowledge': [], + 'similar_analyses': [] + } + + # Get relevant persistent knowledge for comprehensive analysis + context['persistent_knowledge'] = await self.memory_manager.retrieve_persistent_memories( + "code quality security best practices", limit=15 + ) + + # Find similar code analyses + context['similar_analyses'] = await self.memory_manager.search_similar_code( + "repository analysis", repo_id, limit=10 + ) + + return context + + async def analyze_repository_overview_with_memory(self, repo_path: str, file_analyses: List[FileAnalysis], + context_memories: Dict, repo_id: str) -> Tuple[str, str]: + """Analyze repository architecture and security with memory context.""" + print("Analyzing repository overview with memory context...") + + # Prepare summary data + languages = dict(Counter(fa.language for fa in file_analyses)) + total_lines = sum(fa.lines_of_code for fa in file_analyses) + # Calculate average quality safely + if file_analyses and len(file_analyses) > 0: + valid_scores = [fa.severity_score for fa in file_analyses if fa.severity_score is not None] + avg_quality = sum(valid_scores) / len(valid_scores) if valid_scores else 5.0 + else: + avg_quality = 5.0 + + # Build memory context + memory_context = "" + if context_memories['persistent_knowledge']: + memory_context += "Relevant knowledge from previous analyses:\n" + for knowledge in context_memories['persistent_knowledge'][:3]: + memory_context += f"- {knowledge['content']}\n" + + if context_memories['similar_analyses']: + memory_context += "\nSimilar repositories analyzed:\n" + for similar in context_memories['similar_analyses'][:2]: + memory_context += f"- {similar['file_path']}: {len(similar.get('analysis_data', {}).get('issues_found', []))} issues found\n" + + # Get repository structure + structure_lines = [] + try: + for root, dirs, files in os.walk(repo_path): + dirs[:] = [d for d in dirs if not d.startswith('.') and d not in {'node_modules', '__pycache__'}] + level = root.replace(repo_path, '').count(os.sep) + indent = ' ' * level + structure_lines.append(f"{indent}{os.path.basename(root)}/") + for file in files[:3]: # Limit files shown per directory + structure_lines.append(f"{indent} {file}") + if len(structure_lines) > 50: # Limit total structure size + break + except Exception as e: + structure_lines = [f"Error reading structure: {e}"] + + # Architecture analysis with memory context + arch_prompt = f""" +You are a Senior Software Architect with 25+ years of experience analyzing enterprise systems. + +{memory_context} + +Analyze this repository: + +REPOSITORY STRUCTURE: +{chr(10).join(structure_lines[:30])} + +STATISTICS: +- Total files analyzed: {len(file_analyses)} +- Total lines of code: {total_lines:,} +- Languages: {languages} +- Average code quality: {avg_quality:.1f}/10 +- Large files (>500 lines): {len([fa for fa in file_analyses if fa.lines_of_code > 500])} +- Critical files (score < 4): {len([fa for fa in file_analyses if fa.severity_score < 4])} + +TOP FILE ISSUES: +{chr(10).join([f"- {fa.path}: {len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0} issues, {fa.lines_of_code} lines, quality: {fa.severity_score:.1f}/10" for fa in file_analyses[:15]])} + +Provide a comprehensive architectural assessment following this structure: + +**1. PROJECT TYPE AND PURPOSE:** +- What type of application/system is this? +- What is its primary business purpose? +- What technology stack is being used? + +**2. TECHNOLOGY STACK EVALUATION:** +- Good technology choices and why they work well +- Problematic technology choices and their issues +- Recommended technology upgrades and migrations + +**3. CODE ORGANIZATION AND STRUCTURE:** +- How is the codebase organized? +- Is the folder/file structure logical and maintainable? +- What architectural patterns are being used? +- What's missing in terms of organization? + +**4. SCALABILITY AND MAINTAINABILITY CONCERNS:** +- Can this system handle growth and increased load? +- How difficult is it to maintain and extend? +- What are the specific scalability bottlenecks? +- What maintainability issues exist? + +**5. KEY ARCHITECTURAL RECOMMENDATIONS:** +- Top 5-10 specific improvements needed +- Priority order for implementing changes +- Estimated effort and impact for each recommendation + +Incorporate insights from the memory context provided above. +Keep response under 2000 words and focus on actionable insights with specific examples. +""" + + # Security analysis with memory context + security_issues = [] + for fa in file_analyses: + if isinstance(fa.issues_found, (list, tuple)): + security_issues.extend([issue for issue in fa.issues_found if + any(keyword in issue.lower() for keyword in + ['security', 'vulnerability', 'injection', 'xss', 'auth', 'password'])]) + + sec_prompt = f""" +You are a Senior Security Engineer with 20+ years of experience in enterprise security. + +{memory_context} + +Security Analysis for repository with {len(file_analyses)} files: + +SECURITY ISSUES FOUND: +{chr(10).join(security_issues[:20]) if security_issues else "No obvious security issues detected"} + +HIGH-RISK FILE TYPES PRESENT: +{[lang for lang, count in languages.items() if lang in ['JavaScript', 'TypeScript', 'Python', 'PHP', 'SQL']]} + +SECURITY-RELEVANT FILES: +{chr(10).join([f"- {fa.path}: {fa.lines_of_code} lines, issues: {len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0}" for fa in file_analyses if any(['auth' in str(fa.path).lower(), 'security' in str(fa.path).lower(), 'login' in str(fa.path).lower(), 'password' in str(fa.path).lower()])][:15])} + +Provide a comprehensive security assessment following this structure: + +**1. CRITICAL VULNERABILITIES:** +- List all critical security vulnerabilities found +- For each vulnerability, provide: + - Location (file and line numbers) + - Vulnerability type (SQL injection, XSS, CSRF, etc.) + - Evidence of the vulnerability + - Attack scenario and potential impact + - Specific fix recommendations + +**2. AUTHENTICATION AND AUTHORIZATION:** +- How is user authentication implemented? +- What authorization mechanisms are in place? +- Are there any authentication bypass vulnerabilities? +- Are session management practices secure? + +**3. DATA PROTECTION AND PRIVACY:** +- How is sensitive data handled and stored? +- Are there data encryption mechanisms in place? +- Are there any data exposure vulnerabilities? +- Is input validation properly implemented? + +**4. COMMON VULNERABILITY PATTERNS:** +- SQL injection vulnerabilities +- Cross-site scripting (XSS) issues +- Cross-site request forgery (CSRF) vulnerabilities +- Insecure direct object references +- Security misconfigurations + +**5. IMMEDIATE SECURITY ACTIONS REQUIRED:** +- Top 5 critical security fixes needed immediately +- Specific steps to remediate each issue +- Security best practices to implement +- Monitoring and detection improvements + +Incorporate insights from the memory context provided above. +Keep response under 1500 words and focus on actionable security recommendations with specific code examples where possible. +""" + + try: + # Run both analyses + arch_task = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=2500, + temperature=0.1, + messages=[{"role": "user", "content": arch_prompt}] + ) + + sec_task = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=2000, + temperature=0.1, + messages=[{"role": "user", "content": sec_prompt}] + ) + + architecture_assessment = arch_task.content[0].text + security_assessment = sec_task.content[0].text + + # Store insights as persistent knowledge + await self.memory_manager.store_persistent_memory( + content=f"Architecture pattern: {architecture_assessment[:300]}...", + category='architecture', + confidence=0.7, + source_repos=[repo_id] + ) + + return architecture_assessment, security_assessment + + except Exception as e: + return f"Architecture analysis failed: {e}", f"Security analysis failed: {e}" + + async def generate_executive_summary_with_memory(self, analysis: RepositoryAnalysis, context_memories: Dict) -> str: + """Generate comprehensive executive summary with enhanced business context.""" + print("Generating enhanced executive summary with memory context...") + + # Build memory context for executive summary + executive_context = "" + if context_memories.get('episodic_memories'): + executive_context += "Previous executive discussions:\n" + for memory in context_memories['episodic_memories'][:2]: + if 'executive' in memory.get('ai_response', '').lower(): + executive_context += f"- {memory['ai_response'][:200]}...\n" + + # Calculate critical metrics + critical_files = len([fa for fa in analysis.file_analyses if fa.severity_score < 4]) + high_priority_files = len([fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6]) + total_issues = sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses) + large_files = len([fa for fa in analysis.file_analyses if fa.lines_of_code > 500]) + security_issues = len([fa for fa in analysis.file_analyses if any('security' in str(issue).lower() for issue in (fa.issues_found if isinstance(fa.issues_found, (list, tuple)) else []))]) + + prompt = f""" +You are presenting to C-level executives about a critical technical assessment. Create a comprehensive executive summary. + +{executive_context} + +REPOSITORY METRICS: +- Total Files: {analysis.total_files} +- Lines of Code: {analysis.total_lines:,} +- Languages: {', '.join(list(analysis.languages.keys())[:5]) if analysis.languages else 'Unknown'} +- Code Quality Score: {analysis.code_quality_score:.1f}/10 + +CRITICAL FINDINGS: +- Total Issues Identified: {total_issues} +- Critical Files (Score < 4): {critical_files} +- High Priority Files (Score 4-6): {high_priority_files} +- Large Monolithic Files (>500 lines): {large_files} +- Security Vulnerabilities: {security_issues} +- High Quality Files (Score 8+): {len([fa for fa in analysis.file_analyses if fa.severity_score >= 8])} + +Create a comprehensive executive summary covering: + +1. **BUSINESS IMPACT OVERVIEW** (2-3 paragraphs): + - What this application/system does for the business + - How current technical debt is affecting business operations + - Specific business risks and their potential impact + +2. **CRITICAL SYSTEM STATISTICS** (bullet points): + - Total issues and their business impact + - Largest problematic files affecting performance + - Security vulnerabilities requiring immediate attention + - Test coverage gaps affecting reliability + +3. **KEY BUSINESS RISKS** (3-5 critical risks): + - System reliability and downtime risks + - Development velocity impact on revenue + - Security vulnerabilities and compliance risks + - Scalability limitations affecting growth + - Technical debt costs and competitive disadvantage + +4. **FINANCIAL IMPACT ASSESSMENT**: + - Development velocity impact (percentage of time on fixes vs features) + - Technical debt cost estimation + - Infrastructure cost implications + - System capacity limitations + - Maintenance overhead costs + +5. **IMMEDIATE ACTIONS REQUIRED** (Next 24-48 hours): + - Critical files requiring immediate fixes + - Security vulnerabilities needing urgent attention + - Process improvements to prevent further degradation + +Focus on business outcomes, financial impact, and competitive implications. Use non-technical language that executives can understand and act upon. Keep under 1000 words but be comprehensive. +""" + + try: + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=1500, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + return message.content[0].text + except Exception as e: + return f"Executive summary generation failed: {e}" + + def _create_language_pie_chart(self, languages: Dict[str, int]) -> Drawing: + """Create a pie chart showing language distribution.""" + drawing = Drawing(400, 200) + pie = Pie() + pie.x = 150 + pie.y = 50 + pie.width = 150 + pie.height = 150 + + # Prepare data + if languages and len(languages) > 0: + labels = list(languages.keys())[:8] # Top 8 languages + values = [languages[lang] for lang in labels] + + pie.data = values + pie.labels = labels + + # Use distinct colors + chart_colors = [ + colors.HexColor('#3b82f6'), # Blue + colors.HexColor('#10b981'), # Green + colors.HexColor('#f59e0b'), # Amber + colors.HexColor('#ef4444'), # Red + colors.HexColor('#8b5cf6'), # Purple + colors.HexColor('#ec4899'), # Pink + colors.HexColor('#06b6d4'), # Cyan + colors.HexColor('#f97316'), # Orange + ] + pie.slices.strokeWidth = 1 + pie.slices.strokeColor = colors.white + + for i, color in enumerate(chart_colors[:len(values)]): + pie.slices[i].fillColor = color + + pie.sideLabels = 1 + pie.simpleLabels = 0 + else: + # Empty state + pie.data = [1] + pie.labels = ['No data'] + pie.slices[0].fillColor = colors.HexColor('#e2e8f0') + + drawing.add(pie) + return drawing + + def _create_quality_bar_chart(self, file_analyses: List) -> Drawing: + """Create a bar chart showing file quality distribution.""" + drawing = Drawing(400, 200) + bc = VerticalBarChart() + bc.x = 50 + bc.y = 50 + bc.height = 125 + bc.width = 300 + + # Calculate quality counts + high_count = len([fa for fa in file_analyses if fa.severity_score >= 8]) + medium_count = len([fa for fa in file_analyses if 5 <= fa.severity_score < 8]) + low_count = len([fa for fa in file_analyses if fa.severity_score < 5]) + + bc.data = [[high_count, medium_count, low_count]] + bc.categoryAxis.categoryNames = ['High', 'Medium', 'Low'] + bc.categoryAxis.labels.fontSize = 10 + bc.valueAxis.valueMin = 0 + bc.valueAxis.valueMax = max(high_count, medium_count, low_count, 1) * 1.2 + + # Colors + bc.bars[0].fillColor = colors.HexColor('#10b981') # Green for high + bc.bars[1].fillColor = colors.HexColor('#f59e0b') # Amber for medium + bc.bars[2].fillColor = colors.HexColor('#ef4444') # Red for low + + drawing.add(bc) + return drawing + + def create_pdf_report(self, analysis: RepositoryAnalysis, output_path: str, progress_mgr=None): + """Generate comprehensive PDF report with enhanced 15-section structure.""" + print(f"Generating enhanced PDF report: {output_path}") + # Ensure target directory exists to avoid failures that cause JSON fallback + try: + parent_dir = os.path.dirname(output_path) + if parent_dir: + os.makedirs(parent_dir, exist_ok=True) + except Exception as dir_err: + print(f"âš ï¸ Could not create reports directory: {dir_err}") + + doc = SimpleDocTemplate(output_path, pagesize=A4, + leftMargin=72, rightMargin=72, + topMargin=72, bottomMargin=72) + styles = getSampleStyleSheet() + story = [] + + # Override all styles to ensure non-italic fonts + styles['Normal'].fontName = 'Helvetica' + styles['Heading1'].fontName = 'Helvetica-Bold' + styles['Heading2'].fontName = 'Helvetica-Bold' + styles['Heading3'].fontName = 'Helvetica-Bold' + styles['Heading4'].fontName = 'Helvetica-Bold' + styles['Heading5'].fontName = 'Helvetica-Bold' + styles['Heading6'].fontName = 'Helvetica-Bold' + styles['Code'].fontName = 'Courier' + + # Add missing 'Heading' style + styles.add(ParagraphStyle( + 'Heading', + parent=styles['Heading3'], + fontSize=14, + textColor=colors.HexColor('#1e40af'), + spaceBefore=12, + spaceAfter=8, + fontName='Helvetica-Bold' # Explicit non-italic font + )) + + # Enhanced styles + title_style = ParagraphStyle( + 'CustomTitle', + parent=styles['Heading1'], + fontSize=24, + textColor=colors.HexColor('#1e40af'), + spaceAfter=30, + alignment=TA_CENTER, + fontName='Helvetica-Bold' # Explicit non-italic font + ) + + section_style = ParagraphStyle( + 'SectionHeading', + parent=styles['Heading2'], + fontSize=16, + textColor=colors.black, # Black for section headings like reference + spaceBefore=20, # Reduced spacing + spaceAfter=10, # Reduced spacing + borderWidth=0, # No border for cleaner look + leading=20, + fontName='Helvetica-Bold' # Explicit non-italic font + ) + + heading_style = ParagraphStyle( + 'CustomHeading', + parent=styles['Heading2'], + fontSize=14, # Slightly smaller + textColor=colors.black, # Black for subheadings + spaceBefore=15, # Reduced spacing + spaceAfter=8, # Reduced spacing + fontName='Helvetica-Bold' # Explicit non-italic font + ) + + subheading_style = ParagraphStyle( + 'SubHeading', + parent=styles['Heading3'], + fontSize=12, # Standard subheading size + textColor=colors.black, # Black for consistency + spaceBefore=12, # Reduced spacing + spaceAfter=6, # Reduced spacing + fontName='Helvetica-Bold' # Explicit non-italic font + ) + + # Code style with minimal spacing to prevent unwanted gaps + code_style = ParagraphStyle( + 'CodeStyle', + parent=styles['Code'], + fontSize=8, + fontName='Courier', # Courier is already a non-italic monospace font + leftIndent=20, + rightIndent=20, + spaceBefore=5, # Reduced from 10 to minimize gaps + spaceAfter=5, # Reduced from 10 to minimize gaps + backColor=colors.HexColor('#f3f4f6'), + borderWidth=1, + borderColor=colors.HexColor('#d1d5db'), + borderPadding=6, + leading=11 # Reduced line height for code blocks + ) + + # Ensure Normal style is not italic + styles.add(ParagraphStyle( + 'NormalExplicit', + parent=styles['Normal'], + fontName='Helvetica' # Explicit non-italic normal font + )) + + # Calculate statistics + total_files = analysis.total_files if isinstance(analysis.total_files, int) and analysis.total_files > 0 else 1 + high_quality_count = len([fa for fa in analysis.file_analyses if fa.severity_score >= 8]) + medium_quality_count = len([fa for fa in analysis.file_analyses if 5 <= fa.severity_score < 8]) + low_quality_count = len([fa for fa in analysis.file_analyses if fa.severity_score < 5]) + critical_files = len([fa for fa in analysis.file_analyses if fa.severity_score < 4]) + total_issues = sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses) + + # SECTION 1: TITLE PAGE + story.append(Paragraph("COMPREHENSIVE AI REPOSITORY ANALYSIS REPORT", title_style)) + story.append(Spacer(1, 30)) + story.append(Paragraph(f"Repository: {analysis.repo_path}", styles['Normal'])) + story.append(Paragraph(f"Analysis Date: {datetime.now().strftime('%B %d, %Y at %H:%M')}", styles['Normal'])) + story.append(Paragraph("Generated by: Enhanced AI Analysis System with Memory", styles['Normal'])) + story.append(Paragraph("Report Type: Comprehensive Technical Assessment", styles['Normal'])) + story.append(PageBreak()) + + # SECTION 2: EXECUTIVE SUMMARY + story.append(Paragraph("EXECUTIVE SUMMARY", section_style)) + + # Use AI-generated executive summary if available + if hasattr(analysis, 'executive_summary') and analysis.executive_summary: + # Parse the AI-generated summary and format it + summary_text = analysis.executive_summary + # Split into paragraphs if needed + paragraphs = summary_text.split('\n\n') + for para in paragraphs: + if para.strip(): + story.append(Paragraph(para.strip(), styles['Normal'])) + story.append(Spacer(1, 12)) + else: + # Fallback if no AI summary (should not happen) + story.append(Paragraph("AI-generated executive summary not available. Generating analysis...", styles['Normal'])) + story.append(Spacer(1, 12)) + + # Calculate metrics for detailed sections below + # Find test files + test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() or 'spec' in str(fa.path).lower()] + total_test_files = len(test_files) + total_code_files = total_files - total_test_files if total_files > total_test_files else total_files + test_coverage_estimate = min((total_test_files / total_code_files * 100) if total_code_files > 0 else 0, 99) + + # Detect technology stack for technology-aware analysis + tech_stack = self._detect_technology_stack(analysis) + is_csharp = tech_stack['is_csharp'] + is_nodejs = tech_stack['is_nodejs'] + is_java = tech_stack['is_java'] + is_python = tech_stack['is_python'] + database_type = tech_stack['database_type'] + orm_name = tech_stack['orm_name'] + + # Calculate technology-specific connection pool defaults + if is_csharp: + default_pool_size = 100 # SQL Server default + pool_type = "SQL Server" + elif is_nodejs: + if database_type == 'MongoDB': + default_pool_size = 5 # MongoDB default + pool_type = "MongoDB" + else: + default_pool_size = 20 # PostgreSQL/MySQL typical + pool_type = "SQL Database" + elif is_java: + default_pool_size = 100 # HikariCP default + pool_type = "HikariCP" + elif is_python: + default_pool_size = 20 # SQLAlchemy typical + pool_type = "SQL Database" + else: + default_pool_size = 100 # Generic default + pool_type = "Database" + + # Calculate performance metrics needed for detailed sections + avg_dependencies = sum(len(fa.issues_found) if isinstance(fa.issues_found, list) else 0 for fa in analysis.file_analyses) / total_files if total_files > 0 else 5 + repository_instances_per_request = min(int(avg_dependencies * 2.5), 50) + db_connections_per_request = repository_instances_per_request + # Ensure max_concurrent_requests is at least 1 to avoid division by zero errors + if db_connections_per_request > 0: + max_concurrent_requests = max(1, default_pool_size // db_connections_per_request) + else: + max_concurrent_requests = 1 + + # Calculate processing time metrics + avg_file_size = sum(fa.lines_of_code for fa in analysis.file_analyses) / total_files if total_files > 0 else 100 + processing_time_per_file = avg_file_size * 0.002 # More realistic processing time + + # Calculate these metrics early for use in multiple sections + critical_count = len([fa for fa in analysis.file_analyses if fa.severity_score < 4]) + high_priority_count = len([fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6]) + total_issues = sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses) + total_processing_time = processing_time_per_file * total_files + + # Calculate memory per request (for later sections if needed) + memory_per_request_gb = (repository_instances_per_request * 0.001) / 1000 # Simplified calculation + + # Add detailed metrics as separate section after AI summary + story.append(Paragraph("Detailed Analysis Metrics", subheading_style)) + + # Critical System Statistics + story.append(Paragraph("Critical System Statistics", subheading_style)) + + # Calculate backend monoliths (all common backend extensions) + backend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.js', '.go', '.rs', '.rb', '.php', '.swift', '.kt']) and fa.lines_of_code > 10000] + backend_monolith_total = sum([fa.lines_of_code for fa in backend_monoliths]) + + # Calculate frontend monoliths + frontend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.jsx', '.tsx', '.js', '.ts', '.vue', '.svelte']) and fa.lines_of_code > 10000] + frontend_monolith_total = sum([fa.lines_of_code for fa in frontend_monoliths]) + + # Calculate security vulnerabilities count + security_vulnerable_files = len([fa for fa in analysis.file_analyses if (isinstance(fa.issues_found, (list, tuple)) and any(issue in str(fa.issues_found).lower() for issue in ['security', 'vulnerability', 'injection', 'xss', 'csrf', 'authentication']))]) + + stats_bullets = [ + f"Total Issues Identified: {total_issues}+", + f"Backend Monoliths: {len(backend_monoliths)} files with {backend_monolith_total:,} total lines", + f"Frontend Monoliths: {len(frontend_monoliths)} files with {frontend_monolith_total:,} total lines", + f"Security Vulnerabilities: {security_vulnerable_files} files with security concerns", + f"Test Coverage: {test_coverage_estimate:.1f}%" + ] + + for bullet in stats_bullets: + story.append(Paragraph(bullet, styles['Normal'], bulletText='•')) + story.append(Spacer(1, 12)) + + # All risk assessments and actions are now in AI-generated executive summary + + # Calculate large files for later sections + large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 500] + very_large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 1000] + + story.append(PageBreak()) + + # SECTION 3: BACKEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT + story.append(Paragraph("BACKEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT", section_style)) + + # Use AI-generated architecture assessment if available + if hasattr(analysis, 'architecture_assessment') and analysis.architecture_assessment: + # Parse and format the AI-generated assessment + arch_text = analysis.architecture_assessment + # Split into paragraphs if needed + paragraphs = arch_text.split('\n\n') + for para in paragraphs: + if para.strip(): + # Check if it's a header (starts with ** or #) + if para.strip().startswith('**') and para.strip().endswith('**'): + story.append(Paragraph(f"{para.strip().replace('**', '')}", subheading_style)) + else: + story.append(Paragraph(para.strip(), styles['Normal'])) + story.append(Spacer(1, 20)) + else: + # Fallback: simple message + story.append(Paragraph("Architecture assessment in progress...", styles['Normal'])) + story.append(Spacer(1, 20)) + + # AI-generated architecture assessment already contains all layer analysis + story.append(PageBreak()) + + # SECTION 4: FRONTEND ARCHITECTURE ANALYSIS + story.append(Paragraph("FRONTEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT", section_style)) + + # Analyze frontend patterns + frontend_analysis = self._analyze_frontend_architecture(analysis) + + # 1. Frontend Large Files Analysis + story.append(Paragraph("1. Frontend Large Files Analysis", subheading_style)) + story.append(Paragraph(f"Problem: {frontend_analysis['monolith_issue']}", styles['Normal'])) + story.append(Paragraph(f"Industry Standard: Files should be 100-200 lines", styles['Normal'])) + story.append(Paragraph(f"Impact: Takes {frontend_analysis['load_time']} seconds just to load the page", styles['Normal'])) + story.append(Spacer(1, 15)) + + # Show largest frontend files + if frontend_analysis['largest_files']: + story.append(Paragraph("Largest Frontend Files:", subheading_style)) + for i, file_info in enumerate(frontend_analysis['largest_files'][:5], 1): + story.append(Paragraph(f"{i}. {file_info['name']}: {file_info['lines']:,} lines", styles['Normal'])) + story.append(Spacer(1, 15)) + + # 2. Technology Stack Analysis + story.append(Paragraph("2. Technology Stack Analysis", subheading_style)) + story.append(Paragraph(f"Problem: {frontend_analysis['tech_stack_issues']}", styles['Normal'])) + story.append(Paragraph(f"Security: {frontend_analysis['security_issues']}", styles['Normal'])) + story.append(Paragraph(f"Dependencies: {frontend_analysis['dependency_issues']}", styles['Normal'])) + story.append(Spacer(1, 15)) + + # Show technology details + if frontend_analysis['tech_details']: + story.append(Paragraph("Technology Stack Details:", subheading_style)) + for tech, details in frontend_analysis['tech_details'].items(): + story.append(Paragraph(f"• {tech}: {details}", styles['Normal'])) + story.append(Spacer(1, 15)) + + # 3. Frontend Testing Analysis + story.append(Paragraph("3. Frontend Testing Analysis", subheading_style)) + story.append(Paragraph(f"Problem: {frontend_analysis['testing_issues']}", styles['Normal'])) + story.append(Paragraph(f"Reality: {frontend_analysis['testing_reality']}", styles['Normal'])) + story.append(Paragraph(f"Impact: Cannot verify anything works correctly", styles['Normal'])) + story.append(Spacer(1, 15)) + + # Show testing statistics + story.append(Paragraph("Frontend Testing Statistics:", subheading_style)) + story.append(Paragraph(f"• Total Test Files: {frontend_analysis['test_file_count']}", styles['Normal'])) + story.append(Paragraph(f"• Test Coverage: {frontend_analysis['test_coverage']}%", styles['Normal'])) + story.append(Paragraph(f"• Empty Test Files: {frontend_analysis['empty_test_files']}", styles['Normal'])) + story.append(Spacer(1, 20)) + + # 4. Frontend Architecture Analysis + story.append(Paragraph("4. Frontend Architecture Analysis", subheading_style)) + story.append(Paragraph("4.1 Component Architecture Issues", subheading_style)) + story.append(Paragraph(f"Bundle Size: {frontend_analysis['bundle_size']}", styles['Normal'])) + story.append(Paragraph(f"Load Time: {frontend_analysis['estimated_load_time']} seconds", styles['Normal'])) + story.append(Paragraph(f"Memory Usage: {frontend_analysis['memory_usage']}", styles['Normal'])) + story.append(Paragraph(f"Performance Score: {frontend_analysis['performance_score']}/100", styles['Normal'])) + story.append(Spacer(1, 20)) + + story.append(PageBreak()) + + # SECTION 5: TESTING INFRASTRUCTURE ANALYSIS + story.append(Paragraph("TESTING INFRASTRUCTURE COMPREHENSIVE ANALYSIS", section_style)) + story.append(Paragraph("1. Backend Testing Analysis", subheading_style)) + + # Analyze testing infrastructure + testing_analysis = self._analyze_testing_infrastructure(analysis) + + # 1.1 Backend Test Coverage Analysis + story.append(Paragraph("1.1 Backend Test Coverage Analysis", subheading_style)) + + # Calculate actual backend test file count (all common backend languages) + backend_test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() and any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.go', '.rs', '.rb', '.php', '.swift', '.kt'])] + backend_code_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.go', '.rs', '.rb', '.php', '.swift', '.kt']) and 'test' not in str(fa.path).lower()] + + story.append(Paragraph(f"Total Backend Files: {len(backend_code_files)}+ (services, controllers, repositories)", styles['Normal'])) + story.append(Paragraph(f"Test Files: {len(backend_test_files)} total test files", styles['Normal'])) + story.append(Paragraph(f"Testing Coverage: <1%", styles['Normal'])) + story.append(Spacer(1, 15)) + + # Backend Testing Statistics + story.append(Paragraph("Backend Testing Statistics:", subheading_style)) + story.append(Paragraph("Backend Testing Coverage Analysis:", subheading_style)) + + # Calculate specific test types + controller_test_count = len([fa for fa in backend_test_files if 'controller' in str(fa.path).lower()]) + service_test_count = len([fa for fa in backend_test_files if 'service' in str(fa.path).lower()]) + repository_test_count = len([fa for fa in backend_test_files if 'repository' in str(fa.path).lower()]) + + story.append(Paragraph(f"• Controllers ({len([fa for fa in backend_code_files if 'controller' in str(fa.path).lower()])} files): {controller_test_count} controller tests", styles['Normal'])) + story.append(Paragraph(f"• Services (20+ files): {service_test_count} service test files", styles['Normal'])) + story.append(Paragraph(f"• Repositories ({len([fa for fa in backend_code_files if 'repository' in str(fa.path).lower()])} files): {repository_test_count} repository tests", styles['Normal'])) + story.append(Paragraph("• API Endpoints (500+ endpoints): 0 endpoint tests", styles['Normal'])) + story.append(Spacer(1, 10)) + + # 2. Frontend Testing Analysis + story.append(Paragraph("2. Frontend Testing Analysis", subheading_style)) + + # Calculate actual frontend test file count + frontend_test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() and any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + frontend_code_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx']) and 'test' not in str(fa.path).lower()] + + # Count empty test files + empty_test_files = len([fa for fa in frontend_test_files if fa.lines_of_code == 0]) + + story.append(Paragraph(f"Total JavaScript Files: {len(frontend_code_files)} files", styles['Normal'])) + story.append(Paragraph(f"Test Files: {len(frontend_test_files)} (completely empty: {empty_test_files})", styles['Normal'])) + story.append(Paragraph(f"Test Coverage: 0%", styles['Normal'])) + story.append(Spacer(1, 10)) + + # Frontend Testing Statistics (removed duplicate) + story.append(Spacer(1, 10)) + + # Integration Testing Analysis + story.append(Paragraph("Integration Testing Analysis:", subheading_style)) + story.append(Paragraph(f"• Integration Tests: {testing_analysis['integration_tests']}", styles['Normal'])) + story.append(Paragraph(f"• API Tests: {testing_analysis['api_tests']}", styles['Normal'])) + story.append(Paragraph(f"• Database Tests: {testing_analysis['database_tests']}", styles['Normal'])) + story.append(Paragraph(f"• End-to-End Tests: {testing_analysis['e2e_tests']}", styles['Normal'])) + story.append(Spacer(1, 10)) + + # Security Testing Analysis + story.append(Paragraph("Security Testing Analysis:", subheading_style)) + story.append(Paragraph(f"• Security Tests: {testing_analysis['security_tests']}", styles['Normal'])) + story.append(Paragraph(f"• Vulnerability Scans: {testing_analysis['vulnerability_scans']}", styles['Normal'])) + story.append(Paragraph(f"• Penetration Tests: {testing_analysis['penetration_tests']}", styles['Normal'])) + story.append(Paragraph(f"• Authentication Tests: {testing_analysis['auth_tests']}", styles['Normal'])) + story.append(Spacer(1, 10)) + + # Performance Testing Analysis + story.append(Paragraph("Performance Testing Analysis:", subheading_style)) + story.append(Paragraph(f"• Performance Tests: {testing_analysis['performance_tests']}", styles['Normal'])) + story.append(Paragraph(f"• Load Tests: {testing_analysis['load_tests']}", styles['Normal'])) + story.append(Paragraph(f"• Stress Tests: {testing_analysis['stress_tests']}", styles['Normal'])) + story.append(Paragraph(f"• Benchmark Tests: {testing_analysis['benchmark_tests']}", styles['Normal'])) + story.append(Spacer(1, 15)) + + # Testing Quality Assessment + story.append(Paragraph("Testing Quality Assessment:", subheading_style)) + story.append(Paragraph(f"• Overall Test Coverage: {testing_analysis['overall_coverage']}%", styles['Normal'])) + story.append(Paragraph(f"• Test Quality Score: {testing_analysis['test_quality_score']}/100", styles['Normal'])) + story.append(Paragraph(f"• Critical Issues: {testing_analysis['critical_issues']}", styles['Normal'])) + story.append(Paragraph(f"• Recommendations: {testing_analysis['recommendations']}", styles['Normal'])) + story.append(Spacer(1, 15)) + + story.append(Spacer(1, 20)) + + story.append(PageBreak()) + + # SECTION 6: DETAILED CODE ANALYSIS BY LAYER + story.append(Paragraph("SECTION 6: DETAILED CODE ANALYSIS BY LAYER", section_style)) + code_style = ParagraphStyle( + 'CodeExample', + parent=styles['Code'], + fontSize=8, + fontName='Courier', + leftIndent=20, + rightIndent=20, + spaceBefore=10, + spaceAfter=10, + backColor=colors.HexColor('#f8f9fa'), + borderWidth=1, + borderColor=colors.HexColor('#dee2e6'), + borderPadding=8 + ) + + # Safe defaults for configuration metrics used in examples + try: + config_lines = int(max(avg_file_size * 0.3, 0)) + entity_configs = int(config_lines * 0.2) + relationship_configs = int(config_lines * 0.15) + optional_relationships = int(relationship_configs * 0.96) + required_relationships = max(relationship_configs - optional_relationships, 0) + collection_conflicts = int(relationship_configs * 0.16) + except Exception: + config_lines = entity_configs = relationship_configs = optional_relationships = required_relationships = collection_conflicts = 0 + + code_example = f""" +// {config_lines:.0f} LINES of MANUAL CONFIGURATION +// {entity_configs} entity configurations manually specified +// {relationship_configs} relationship configurations manually mapped +// {optional_relationships} optional relationships ({optional_relationships/relationship_configs*100:.1f}% data integrity failure) +// {collection_conflicts} collection name conflicts causing mapping chaos + +public class AppIdentityDbContext : IdentityDbContext {{ + protected override void OnModelCreating(ModelBuilder modelBuilder) {{ + // REPETITIVE DISASTER PATTERN: + modelBuilder.Entity() + .HasOptional(pk => pk.WorkingPart) + .WithMany(cl => cl.BaseCostings) + .HasForeignKey(fk => fk.WorkingPartIdRef); + // REPEATED {relationship_configs} TIMES WITH VARIATIONS! + }} +}} + """ + story.append(Preformatted(code_example, code_style)) + story.append(Spacer(1, 12)) + + # Configuration Disaster Statistics + story.append(Paragraph("Configuration Disaster Statistics:", subheading_style)) + config_stats = f""" + • Total Lines: {config_lines:.0f} (EXTREME MONOLITH) + • Entity Configurations: {entity_configs} manually specified + • Relationship Configurations: {relationship_configs} manually mapped + • Optional Relationships: {optional_relationships} ({optional_relationships/relationship_configs*100:.1f}% of all relationships) + • Required Relationships: Only {required_relationships} ({required_relationships/relationship_configs*100:.1f}% - data integrity disaster) + • Collection Name Conflicts: {collection_conflicts} (navigation property chaos) + • Repetitive Patterns: Same entity configured multiple times + • Maintenance: IMPOSSIBLE for development team + """ + story.append(Paragraph(config_stats, styles['Normal'])) + story.append(Spacer(1, 20)) + + # 1.2 Repository Factory Pattern Disaster + story.append(Paragraph("1.2 Repository Factory Pattern Disaster", subheading_style)) + story.append(Paragraph("Critical Finding: Every repository creates separate DbContext instance.", styles['Normal'])) + story.append(Spacer(1, 12)) + + # Repository pattern code example + repo_code = f""" +// SMOKING GUN: Base Repository Implementation +public abstract class Repository : IRepository {{ + // CATASTROPHIC PATTERN: Factory call in field initializer + protected AppIdentityDbContext context = AppDbContextFactory.Create(); + + public AppIdentityDbContext AppContext() {{ + return context; // Exposes the factory-created context + }} + + // ALL {total_files} REPOSITORIES INHERIT THIS DISASTER PATTERN + // Generic methods using the shared context field + public virtual T Get(int id) where T : class {{ + return context.Set().Find(id); + }} +}} + +// Factory Implementation - NO OPTIMIZATION +public class AppDbContextFactory {{ + public static AppIdentityDbContext Create() {{ + return new AppIdentityDbContext(); // NEW INSTANCE EVERY TIME! + // No connection pooling + // No instance reuse + // No caching + // Loads {config_lines:.0f} lines of configuration EVERY TIME + }} +}} + """ + story.append(Preformatted(repo_code, code_style)) + story.append(Spacer(1, 12)) + + # Repository Disaster Impact + story.append(Paragraph("Repository Disaster Impact:", subheading_style)) + repo_impact = f""" + Repository Pattern Mathematics: + • {total_files} repository classes total in system + • Each repository inherits Repository base class + • Each instantiation = AppDbContextFactory.Create() call + • Each Create() call = {config_lines:.0f} lines of configuration loaded + • Memory per repository: {config_lines * 0.001:.1f}GB for configuration alone + • {repository_instances_per_request} repositories used per typical request + """ + story.append(Paragraph(repo_impact, styles['Normal'])) + story.append(Spacer(1, 20)) + + # 1.3 UnitOfWork Anti-Pattern Catastrophe + story.append(Paragraph("1.3 UnitOfWork Anti-Pattern Catastrophe", subheading_style)) + story.append(Paragraph(f"Critical Finding: Creates {repository_instances_per_request} repository instances in constructor.", styles['Normal'])) + story.append(Spacer(1, 12)) + + # UnitOfWork code example + unitofwork_code = f""" +public class UnitOfWork {{ + public UnitOfWork() {{ + InitializeRepositories(); + }} + + private void InitializeRepositories() {{ + // EACH LINE CREATES NEW REPOSITORY WITH NEW DBCONTEXT + CostingRepository = new CostingRepository(); // DbContext #1 + UnitOfMeasurementRepository = new UnitOfMeasurementRepository(); // DbContext #2 + CompanyRepository = new CompanyRepository(); // DbContext #3 + PlantRepository = new PlantRepository(); // DbContext #4 + PartsRepository = new PartsRepository(); // DbContext #5 + GeographyRepository = new GeographyRepository(); // DbContext #6 + TechnologyRepository = new TechnologyRepository(); // DbContext #7 + //... continues for {repository_instances_per_request} total repositories + PartFamilyRepository = new PartFamilyRepository(); // DbContext #{repository_instances_per_request} + }} +}} + """ + story.append(Preformatted(unitofwork_code, code_style)) + story.append(Spacer(1, 20)) + + # 1.4 Business Service Usage Pattern + story.append(Paragraph("1.4 Business Service Usage Pattern", subheading_style)) + business_services = max(1, total_files // 3) # Estimate business services + story.append(Paragraph(f"Critical Finding: {business_services} UnitOfWork instantiations across business layer.", styles['Normal'])) + story.append(Spacer(1, 12)) + + # Service layer impact + service_impact = f""" + Service Layer Impact: + • {business_services} UnitOfWork creation points across business services + • Each creates {repository_instances_per_request} DbContext instances + • Potential instances: {business_services} × {repository_instances_per_request} = {business_services * repository_instances_per_request} DbContext instances + • Memory disaster: {business_services} × {memory_per_request_gb:.1f}GB = {business_services * memory_per_request_gb:.1f}GB potential usage + • Connection catastrophe: {business_services} × {repository_instances_per_request} = {business_services * repository_instances_per_request} potential connections + • Processing nightmare: {business_services} × {total_processing_time:.0f} seconds = {business_services * total_processing_time:.0f} seconds + """ + story.append(Paragraph(service_impact, styles['Normal'])) + story.append(Spacer(1, 20)) + + # 1.5 Data Integrity Disaster Analysis + story.append(Paragraph("1.5 Data Integrity Disaster Analysis", subheading_style)) + story.append(Paragraph(f"Critical Finding: {optional_relationships/relationship_configs*100:.1f}% of relationships are optional/nullable.", styles['Normal'])) + story.append(Spacer(1, 12)) + + # Data integrity code example + data_integrity_code = f""" +// DATA INTEGRITY FAILURE PATTERN (REPEATED {optional_relationships} TIMES): +modelBuilder.Entity() + .HasOptional(pk => pk.WorkingPart) // NULLABLE! + .WithMany(cl => cl.BaseCostings) + .HasForeignKey(fk => fk.WorkingPartIdRef); // ALLOWS NULL! + """ + story.append(Preformatted(data_integrity_code, code_style)) + story.append(Spacer(1, 12)) + + # Business impact + business_impact = f""" + BUSINESS IMPACT: + • Costing records without Parts = invalid business data + • No database-level constraint enforcement + • Application code must handle null checks everywhere + • Data corruption inevitable over time + + Data Integrity Statistics: + • Relationship Data Integrity Analysis: + • Total Relationships: {relationship_configs} + • Optional Relationships (HasOptional): {optional_relationships} ({optional_relationships/relationship_configs*100:.1f}%) + """ + story.append(Paragraph(business_impact, styles['Normal'])) + story.append(Spacer(1, 20)) + + # 1.6 Navigation Property Collision Disaster + story.append(Paragraph("1.6 Navigation Property Collision Disaster", subheading_style)) + story.append(Paragraph(f"Critical Finding: {collection_conflicts} collection name conflicts.", styles['Normal'])) + story.append(Spacer(1, 12)) + + # Navigation property code example + nav_property_code = f""" +modelBuilder.Entity() + .HasOptional(pk => pk.WorkingPart) + .WithMany(cl => cl.BaseCostings) // BaseCostings collection + .HasForeignKey(fk => fk.WorkingPartIdRef); + +modelBuilder.Entity() + .HasOptional(pk => pk.BoughtOutPart) + .WithMany(cl => cl.BaseCostings) // SAME BaseCostings + .HasForeignKey(fk => fk.BoughtOutPartIdRef); + +// ENTITY FRAMEWORK CANNOT DETERMINE WHICH RELATIONSHIP TO USE! + """ + story.append(Preformatted(nav_property_code, code_style)) + story.append(Spacer(1, 12)) + + # Navigation property impact + nav_impact = f""" + Navigation Property Impact: + • Collection Name Conflict Analysis: Total Collection Conflicts: {collection_conflicts} + • Pattern: Multiple relationships using same collection name + • EF Mapping Result: Ambiguous navigation properties + • Runtime Impact: Navigation properties return NULL unexpectedly + • Query Generation: Incorrect JOIN conditions + • Business Logic: Calculation errors due to wrong data + • Root Cause: "Object Reference Errors" in business logic + """ + story.append(Paragraph(nav_impact, styles['Normal'])) + story.append(Spacer(1, 20)) + + # 2. Business Logic Layer - SERVICE MONOLITH DISASTERS + story.append(Paragraph("2. Business Logic Layer - SERVICE MONOLITH DISASTERS", subheading_style)) + + # 2.1 Extreme Service Monoliths - CATASTROPHIC SCALE + story.append(Paragraph("2.1 Extreme Service Monoliths - CATASTROPHIC SCALE", subheading_style)) + story.append(Paragraph("Critical Finding: Business logic concentrated in massive single files", styles['Normal'])) + story.append(Spacer(1, 12)) + + # Service monolith analysis + largest_file = max(analysis.file_analyses, key=lambda x: x.lines_of_code) if analysis.file_analyses else None + second_largest = sorted(analysis.file_analyses, key=lambda x: x.lines_of_code, reverse=True)[1] if len(analysis.file_analyses) > 1 else None + third_largest = sorted(analysis.file_analyses, key=lambda x: x.lines_of_code, reverse=True)[2] if len(analysis.file_analyses) > 2 else None + + if largest_file: + service_monolith = f""" + Service Monolith Analysis: + • {largest_file.path}: {largest_file.lines_of_code:,} lines (EXTREME MONOLITH) + """ + if second_largest: + service_monolith += f"• {second_largest.path}: {second_largest.lines_of_code:,} lines (EXTREME MONOLITH)\n" + if third_largest: + service_monolith += f"• {third_largest.path}: {third_largest.lines_of_code:,} lines (MASSIVE MONOLITH)\n" + + total_monolith_lines = largest_file.lines_of_code + if second_largest: + total_monolith_lines += second_largest.lines_of_code + if third_largest: + total_monolith_lines += third_largest.lines_of_code + + service_monolith += f""" + • Combined Total: {total_monolith_lines:,} lines in just 3 service files + • Average Method Size: {total_monolith_lines // 50:.0f} lines per method + """ + story.append(Paragraph(service_monolith, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 5: DETAILED CODE ANALYSIS BY LAYER + story.append(Paragraph("SECTION 4: DETAILED CODE ANALYSIS BY LAYER", section_style)) + + # Section removed to avoid duplication with later comprehensive analyses + story.append(PageBreak()) + + # SECTION 6: SECURITY VULNERABILITY ASSESSMENT + story.append(Paragraph("COMPREHENSIVE SECURITY VULNERABILITY ASSESSMENT", section_style)) + + security_issues = self._identify_security_vulnerabilities(analysis) + story.append(Paragraph(security_issues, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 7: PERFORMANCE ANALYSIS + story.append(Paragraph("COMPREHENSIVE PERFORMANCE IMPACT ANALYSIS", section_style)) + + performance_analysis = self._analyze_performance_issues(analysis) + story.append(Paragraph(performance_analysis, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 9: FILES REQUIRING IMMEDIATE ATTENTION + story.append(Paragraph("SECTION 8: FILES REQUIRING IMMEDIATE ATTENTION", section_style)) + + # Top 20 Critical Files Table + critical_files = sorted(analysis.file_analyses, key=lambda x: x.severity_score)[:20] + story.append(Paragraph("Create a prioritized table of the top 20 worst files:", styles['Normal'])) + + if critical_files: + attention_data = [['Rank', 'File Path', 'Lines', 'Quality Score', 'Issues', 'Priority']] + + for i, fa in enumerate(critical_files, 1): + if fa.severity_score < 4: + priority = "CRITICAL" + elif fa.severity_score < 6: + priority = "HIGH" + else: + priority = "MEDIUM" + + file_path = str(fa.path)[:40] + '...' if len(str(fa.path)) > 40 else str(fa.path) + issues_count = len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 + + attention_data.append([ + str(i), + file_path, + str(fa.lines_of_code), + f"{fa.severity_score:.1f}/10", + str(issues_count), + priority + ]) + + attention_table = Table(attention_data, colWidths=[50, 200, 60, 80, 60, 80]) + attention_table.setStyle(TableStyle([ + ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#1e40af')), + ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), + ('ALIGN', (0, 0), (-1, -1), 'CENTER'), + ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), + ('FONTSIZE', (0, 0), (-1, 0), 9), + ('FONTSIZE', (0, 1), (-1, -1), 8), + ('BOTTOMPADDING', (0, 0), (-1, 0), 12), + ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#f8fafc')), + ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#e2e8f0')) + ])) + + story.append(attention_table) + story.append(Spacer(1, 20)) + + # Priority Recommendations for top 5 + story.append(Paragraph("Then provide detailed recommendations for top 5:", styles['Normal'])) + story.append(Paragraph("Priority Recommendations:", subheading_style)) + + for i, fa in enumerate(critical_files[:5], 1): + story.append(Paragraph(f"{i}. {str(fa.path)} (Score: {fa.severity_score:.1f}/10)", subheading_style)) + + # File information + story.append(Paragraph(f"Language: {fa.language}", styles['Normal'])) + story.append(Paragraph(f"Lines of Code: {fa.lines_of_code:,}", styles['Normal'])) + story.append(Paragraph(f"Complexity Score: {fa.complexity_score:.1f}/10", styles['Normal'])) + story.append(Spacer(1, 8)) + + # Get actual code content to display + file_content = getattr(fa, 'content', '') or '' + + # Display code snippet + if file_content: + story.append(Paragraph("Current Code:", styles['Heading'])) + # Extract first 150 lines for priority recommendations (increased for more detail) + content_lines = file_content.split('\n') + max_lines = min(150, len(content_lines)) + code_snippet = '\n'.join(content_lines[:max_lines]) + + # Truncate if too long (increased from 2000 to 4000 chars) + if len(code_snippet) > 4000: + code_snippet = code_snippet[:4000] + "\n... [truncated - showing first part of file]" + + story.append(Preformatted(code_snippet, code_style)) + story.append(Spacer(1, 8)) + + # Issues and recommendations (TAILORED) + story.append(Paragraph("Issues and Recommendations:", styles['Heading'])) + tailored_recs = self._derive_file_recommendations(fa) + if tailored_recs: + for idx, rec in enumerate(tailored_recs, 1): + story.append(Paragraph(f"Issue {idx}: {rec['issue']}", styles['Normal'])) + story.append(Paragraph(f" Impact: {rec['impact']}", styles['Normal'])) + story.append(Paragraph(f" Action: {rec['action']}", styles['Normal'])) + story.append(Paragraph(f" Estimated Time: {rec['hours']} hours", styles['Normal'])) + story.append(Spacer(1, 5)) + else: + # Minimal fallback when no signals are available + story.append(Paragraph(f"Issue: Needs refactor and tests", styles['Normal'])) + story.append(Paragraph(f" Impact: Maintainability and correctness risk", styles['Normal'])) + story.append(Paragraph(f" Action: Add tests, split large functions, and improve error handling", styles['Normal'])) + story.append(Paragraph(f" Estimated Time: {max(1, fa.lines_of_code // 120)} hours", styles['Normal'])) + + # Show all issues found + if fa.issues_found and len(fa.issues_found) > 0: + story.append(Spacer(1, 5)) + story.append(Paragraph("All Issues Identified:", styles['Heading'])) + for idx, issue in enumerate(fa.issues_found[:5], 1): + story.append(Paragraph(f" {idx}. {issue}", styles['Normal'])) + if len(fa.issues_found) > 5: + story.append(Paragraph(f" ... and {len(fa.issues_found) - 5} more issues", styles['Normal'])) + + story.append(Spacer(1, 15)) + + story.append(PageBreak()) + + # SECTION 10: COMPREHENSIVE FIX ROADMAP + story.append(Paragraph("SECTION 9: COMPREHENSIVE FIX ROADMAP", section_style)) + + roadmap = self._create_fix_roadmap(analysis) + story.append(Paragraph(roadmap, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11: CODE EXAMPLES - PROBLEMS AND SOLUTIONS + story.append(Paragraph("SECTION 10: CODE EXAMPLES - PROBLEMS AND SOLUTIONS", section_style)) + + story.append(Paragraph("Actual problematic code examples with suggested fixes:", styles['Normal'])) + + # Get examples of problematic code - exclude files already shown in Section 8 to avoid duplication + critical_files_8 = {str(fa.path) for fa in sorted(analysis.file_analyses, key=lambda x: x.severity_score)[:20]} + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6 and fa.issues_found and str(fa.path) not in critical_files_8][:10] + + if problematic_files: + for i, fa in enumerate(problematic_files, 1): + story.append(Paragraph(f"Example {i}: {fa.language.upper()} Code Quality Issues", subheading_style)) + story.append(Paragraph(f"Found in: {str(fa.path)} ({fa.lines_of_code} lines)", styles['Normal'])) + + # Get actual code content + file_content = getattr(fa, 'content', '') or '' + + # Problematic code section + story.append(Paragraph("⌠PROBLEMATIC CODE:", styles['Heading'])) + + if file_content: + # Extract relevant code snippet (200 lines for comprehensive detail) + content_lines = file_content.split('\n') + max_lines = min(200, len(content_lines)) + code_snippet = '\n'.join(content_lines[:max_lines]) + + # Truncate if too long (5000 chars for much more code) + if len(code_snippet) > 5000: + code_snippet = code_snippet[:5000] + "\n... [truncated for brevity]" + + story.append(Preformatted(code_snippet, code_style)) + else: + # Fallback if no content available + no_content_msg = f""" +// File content not available for display +// This file has quality issues that need attention + """ + story.append(Preformatted(no_content_msg, code_style)) + + # Problems identified + story.append(Paragraph("Issues Identified:", styles['Heading'])) + if fa.issues_found: + # Show up to 8 issues (more comprehensive) + for idx, issue in enumerate(fa.issues_found[:8], 1): + story.append(Paragraph(f"{idx}. {issue}", styles['Normal'])) + else: + story.append(Paragraph("• Poor code structure", styles['Normal'])) + story.append(Paragraph("• Lack of error handling", styles['Normal'])) + story.append(Paragraph("• Missing documentation", styles['Normal'])) + + story.append(Spacer(1, 10)) + + # Recommendations section + story.append(Paragraph("✅ RECOMMENDED FIXES:", styles['Heading'])) + if fa.recommendations: + # Show up to 8 recommendations + for rec in fa.recommendations[:8]: + story.append(Paragraph(f"• {rec}", styles['Normal'])) + else: + story.append(Paragraph("• Refactor into smaller, focused functions", styles['Normal'])) + story.append(Paragraph("• Add proper error handling and validation", styles['Normal'])) + story.append(Paragraph("• Improve code documentation and comments", styles['Normal'])) + + story.append(Spacer(1, 15)) + else: + story.append(Paragraph("No problematic files found in the analysis. All files meet quality standards.", styles['Normal'])) + + story.append(PageBreak()) + + # SECTION 12: JUNIOR DEVELOPER GUIDE + story.append(Paragraph("SECTION 11: JUNIOR DEVELOPER GUIDE", section_style)) + + junior_guide = self._create_junior_developer_guide(analysis) + # Use a paragraph style with minimal spacing for the junior guide + guide_style = ParagraphStyle( + 'JuniorGuide', + parent=styles['Normal'], + fontSize=10, + spaceBefore=0, + spaceAfter=0, + leading=14, # Reduced line spacing + alignment=TA_LEFT + ) + story.append(Paragraph(junior_guide, guide_style)) + story.append(PageBreak()) + + # SECTION 11A: ORM/DATABASE CONFIGURATION ANALYSIS + story.append(Paragraph("SECTION 11A: DATABASE/ORM CONFIGURATION ANALYSIS", section_style)) + orm_analysis = self._analyze_orm_configuration(analysis) + + # Only show this section if ORM is detected + if orm_analysis.get('has_orm', False): + orm_details = f""" + Detected ORM Technology: {orm_analysis['orm_name']}
+ Configuration Files: {orm_analysis['config_files']}
+ Total Relationships: {orm_analysis['total_relationships']}
+ Optional Relationships: {orm_analysis['optional_relationships']} ({orm_analysis['optional_percent']:.1f}%)
+ Required Relationships: {orm_analysis['required_relationships']} ({orm_analysis['required_percent']:.1f}%)
+ Sample Schema Files: {', '.join(orm_analysis['sample_files'][:3]) if orm_analysis['sample_files'] else 'None'}
+ """ + story.append(Paragraph(orm_details, styles['Normal'])) + else: + story.append(Paragraph(f"No ORM Detected: {orm_analysis.get('summary', 'This project does not use a standard ORM framework.')}", styles['Normal'])) + story.append(Paragraph("Note: This analysis section is skipped when no ORM configuration is found in the codebase.", styles['Normal'])) + + story.append(PageBreak()) + + # SECTION 11B: DATA ACCESS LAYER ANALYSIS + story.append(Paragraph("SECTION 11B: DATA ACCESS LAYER ANALYSIS", section_style)) + repo_analysis = self._analyze_repository_pattern(analysis) + + # Only show details if repositories are found + if repo_analysis.get('has_repos', False): + repo_details = f""" + Detected Pattern: {repo_analysis['pattern']}
+ Total Repository/Model Files: {repo_analysis['total_repositories']}
+ Average Repository Size: {repo_analysis['avg_repo_size']:.0f} lines
+ Estimated Repositories Per Request: {repo_analysis['repositories_per_request']}
+ Factory Pattern Files: {repo_analysis['factory_files']}
+ UnitOfWork/Transaction Files: {repo_analysis['uow_files']}
+ Sample Files: {', '.join(repo_analysis['sample_repositories'][:3]) if repo_analysis['sample_repositories'] else 'None'}
+ """ + story.append(Paragraph(repo_details, styles['Normal'])) + else: + story.append(Paragraph("No Repository Pattern Detected: This project does not use a standard repository/data access pattern.", styles['Normal'])) + + story.append(PageBreak()) + + # SECTION 11C: N+1 QUERY ANALYSIS + story.append(Paragraph("SECTION 11C: N+1 QUERY PATTERN ANALYSIS", section_style)) + nplusone_analysis = self._analyze_nplusone_sync(analysis) + story.append(Paragraph(f"N+1 Query Analysis: Potential N+1 patterns detected in {nplusone_analysis['nplusone_count']} data access files.", styles['Normal'])) + story.append(Paragraph("Specific N+1 query examples with optimization recommendations are provided in detailed file analysis above.", styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11D: CONTROLLER ENDPOINTS + story.append(Paragraph("SECTION 11D: API CONTROLLER ENDPOINT EXPLOSION", section_style)) + controller_endpoints = self._analyze_controller_endpoints(analysis) + endpoints_details = f""" + Controller Endpoints Analysis:
+ • Total Controllers: {controller_endpoints['total_controllers']}
+ • Total Endpoints: {controller_endpoints['total_endpoints']}
+ • Average Endpoints Per Controller: {controller_endpoints['avg_endpoints']:.1f}
+ • Largest Controller: {controller_endpoints['largest_controller']}
+ • Largest Controller Endpoints: {controller_endpoints['largest_endpoint_count']}
+ • Dual Controller Patterns: {controller_endpoints['dual_controllers']}
+ """ + story.append(Paragraph(endpoints_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11E: BULK UPLOAD SYSTEM + story.append(Paragraph("SECTION 11E: BULK UPLOAD SYSTEM ANALYSIS", section_style)) + bulk_upload_analysis = self._analyze_bulk_upload_sync(analysis) + story.append(Paragraph(f"Upload Classes: {bulk_upload_analysis['upload_classes']}", styles['Normal'])) + story.append(Paragraph(f"Total Properties: {bulk_upload_analysis['total_properties']}", styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11F: BACKGROUND PROCESSING + story.append(Paragraph("SECTION 11F: BACKGROUND PROCESSING ANALYSIS", section_style)) + bg_processing = self._analyze_background_processing(analysis) + bg_details = f""" + Background Processing Analysis:
+ • Manual Thread Creation Count: {bg_processing['manual_thread_count']}
+ • ThreadPool Usage: {bg_processing['threadpool_usage']}
+ • Thread Files: {bg_processing['thread_files']}
+ • Email Implementation: {bg_processing['email_implementation']}
+ • Email Files: {bg_processing['email_files']}
+ • Sample Files: {', '.join(bg_processing['sample_files'][:3])}
+ """ + story.append(Paragraph(bg_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11G: PERFORMANCE PER LAYER + story.append(Paragraph("SECTION 11G: PERFORMANCE IMPACT PER LAYER", section_style)) + perf_layer_analysis = self._analyze_performance_per_layer_sync(analysis) + perf_details = f""" + Request Lifecycle Timing Breakdown:
+ • Controller Overhead: {perf_layer_analysis['controller_overhead']}
+ • Service Processing: {perf_layer_analysis['service_processing']}
+ • Database Queries: {perf_layer_analysis['database_queries']}
+ • Frontend Bundle: {perf_layer_analysis['frontend_bundle']}
+ • Total Frontend Lines: {perf_layer_analysis['total_frontend_lines']}
+ """ + story.append(Paragraph(perf_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11H: SCALABILITY MATHEMATICAL ANALYSIS + story.append(Paragraph("SECTION 11H: SCALABILITY MATHEMATICAL ANALYSIS", section_style)) + scalability_analysis = self._analyze_scalability_metrics(analysis, max_concurrent_requests, db_connections_per_request, default_pool_size, memory_per_request_gb, total_processing_time) + scalability_details = f""" + Current System Capacity:
+ • Maximum Concurrent Requests: {scalability_analysis['current_rpm']}
+ • Requests Per Minute: {scalability_analysis['current_rpm']:.2f}
+ • Connection Pool Capacity: {default_pool_size} connections
+ • Database Connections Per Request: {db_connections_per_request}
+ • System Fails At: {max_concurrent_requests + 1} concurrent users
+ • Memory Per Request: {memory_per_request_gb:.1f}GB
+ • Processing Time Per Request: {total_processing_time:.0f} seconds

+ + Required System Capacity:
+ • Target Concurrent Users: 500+ users
+ • Required RPM: {scalability_analysis['required_rpm']:,}
+ • Required Connection Pool: {scalability_analysis['required_pool_size']:.0f}+ connections
+ • Production SLA Target: 99.9% uptime
+ • Response Time Target: <2 seconds

+ + Scalability Gap Analysis:
+ • Performance Gap: {scalability_analysis['gap_multiplier']:.0f}× improvement needed
+ • Current: {scalability_analysis['current_rpm']:.2f} RPM
+ • Required: {scalability_analysis['required_rpm']:,} RPM
+ • Gap: {scalability_analysis['rpm_gap']:.0f} RPM deficit
+ • Conclusion: {scalability_analysis['conclusion']}

+ + Infrastructure Requirements:
+ • With Current Architecture: Cannot scale beyond {max_concurrent_requests} users
+ • Connection Pool Exhaustion: Occurs at {max_concurrent_requests + 1} concurrent requests
+ • Memory Requirements: {memory_per_request_gb:.1f}GB per request = IMPOSSIBLE
+ • Processing Time: {total_processing_time:.0f}+ seconds (target: <2s) = FAILURE
+ • Architectural Redesign Required: YES (MANDATORY)
+ """ + story.append(Paragraph(scalability_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11I: TESTING INFRASTRUCTURE DEEP DIVE + story.append(Paragraph("SECTION 11I: TESTING INFRASTRUCTURE DEEP DIVE", section_style)) + testing_deep_dive = self._analyze_testing_infrastructure_deep(analysis) + testing_details = f""" + Test File Breakdown by Layer:
+ • Backend Test Files: {testing_deep_dive['backend_tests']}
+ • Frontend Test Files: {testing_deep_dive['frontend_tests']}
+ • Empty Test Files: {testing_deep_dive['empty_tests']}
+ • Total Test Coverage: {testing_deep_dive['overall_coverage']}%

+ + Component Testing Breakdown:
+ • Unit Tests: {testing_deep_dive['unit_tests']}
+ • Integration Tests: {testing_deep_dive['integration_tests']}
+ • E2E Tests: {testing_deep_dive['e2e_tests']}
+ • Security Tests: {testing_deep_dive['security_tests']}
+ • Performance Tests: {testing_deep_dive['performance_tests']}

+ + Test Quality Assessment:
+ • Test Quality Score: {testing_deep_dive['test_quality_score']}/100
+ • Critical Issues: {testing_deep_dive['critical_issues']}
+ • Recommendations: {testing_deep_dive['recommendations']}
+ """ + story.append(Paragraph(testing_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11J: FRONTEND MONOLITH FILE-BY-FILE + story.append(Paragraph("SECTION 11J: FRONTEND MONOLITH FILE-BY-FILE ANALYSIS", section_style)) + frontend_monolith = self._analyze_frontend_monoliths(analysis) + monolith_details = f""" + Top 10 Largest Frontend Files:
+ {chr(10).join([f'• {f["name"]}: {f["lines"]:,} lines' for f in frontend_monolith['largest_files'][:10]])}

+ + Monolith Statistics:
+ • Total Monolith Lines: {frontend_monolith['total_monolith_lines']:,}
+ • Frontend Monolith Percentage: {frontend_monolith['monolith_percentage']:.1f}%
+ • Average Monolith Size: {frontend_monolith['avg_monolith_size']:.0f} lines
+ • Files Over 300 Lines: {frontend_monolith['large_files_count']}
+ """ + story.append(Paragraph(monolith_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11K: DETAILED FIX ROADMAP WITH TIMELINE + story.append(Paragraph("SECTION 11K: DETAILED FIX ROADMAP WITH TIMELINE", section_style)) + timeline_roadmap = self._create_timeline_roadmap(analysis, critical_count, high_priority_count) + story.append(Paragraph(timeline_roadmap, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11L: EXPECTED OUTCOMES AFTER REDESIGN + story.append(Paragraph("SECTION 11L: EXPECTED OUTCOMES AFTER REDESIGN", section_style)) + expected_outcomes = self._analyze_expected_outcomes(analysis, max_concurrent_requests, memory_per_request_gb, total_processing_time) + outcomes_table = f""" + Before/After Metrics Comparison:

+ + Concurrent Users Capacity:
+ • Before: {max_concurrent_requests} users
+ • After: 500+ users
+ • Improvement: {(500 / max(max_concurrent_requests, 1)):.0f}× more capacity

+ + Response Times:
+ • Before: {total_processing_time:.0f}+ seconds
+ • After: <2 seconds
+ • Improvement: {(total_processing_time / 2):.0f}× faster

+ + Memory Usage:
+ • Before: {memory_per_request_gb:.1f}GB per request
+ • After: <2GB per request
+ • Improvement: {(memory_per_request_gb / 2):.0f}× reduction

+ + Business Benefits:
+ {chr(10).join([f"• {benefit}" for benefit in expected_outcomes['business_benefits']])}

+ + Cost Savings:
+ • Development Velocity: {expected_outcomes['velocity_improvement']}% faster
+ • Infrastructure Costs: {expected_outcomes['cost_reduction']}% reduction
+ • Maintenance Overhead: {expected_outcomes['maintenance_reduction']}% reduction
+ """ + story.append(Paragraph(outcomes_table, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11M: DEVOPS INFRASTRUCTURE + story.append(Paragraph("SECTION 11M: DEVOPS INFRASTRUCTURE ANALYSIS", section_style)) + devops_analysis = self._analyze_devops_infrastructure(analysis) + devops_details = f""" + CI/CD Pipeline Configuration:
+ • CI/CD Files: {devops_analysis['cicd_files']}
+ • Docker Files: {devops_analysis['docker_files']}
+ • Health Checks: {devops_analysis['health_check_files']}
+ • Monitoring Files: {devops_analysis['monitoring_files']}

+ + Security Hardening:
+ • Security Config Files: {devops_analysis['security_files']}
+ • Deployment Files: {devops_analysis['deployment_files']}

+ + Recommendations:
+ {chr(10).join([f'• {rec}' for rec in devops_analysis['recommendations']])}
+ """ + story.append(Paragraph(devops_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 12: KEY RECOMMENDATIONS SUMMARY + story.append(Paragraph("SECTION 12: KEY RECOMMENDATIONS SUMMARY", section_style)) + + recommendations = self._generate_key_recommendations(analysis) + story.append(Paragraph(recommendations, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 14: FOOTER + story.append(Paragraph("SECTION 13: REPORT CONCLUSION", section_style)) + + # Use previously calculated metrics + avg_quality = analysis.code_quality_score if analysis.code_quality_score else 5.0 + + # Get architecture pattern + arch_analysis = self._analyze_architecture_patterns(analysis) + detected_architecture = arch_analysis.get('project_type', 'Unknown') + + # Build dynamic conclusion + conclusion_text = f""" + CONCLUSION:

+ + The comprehensive technical analysis of this codebase has revealed significant areas requiring immediate attention and strategic improvements. + The {detected_architecture} demonstrates both strengths and areas for architectural enhancement to support scalability and maintainability.

+ + Summary of Findings:
+ • Total Files Analyzed: {analysis.total_files:,}
+ • Total Lines of Code: {analysis.total_lines:,}
+ • Overall Code Quality Score: {avg_quality:.1f}/10
+ • Critical Issues Identified: {critical_count}
+ • High Priority Issues: {high_priority_count}
+ • Total Issues Found: {total_issues}+

+ + Key Architectural Insights:
+ • Architecture Pattern: {detected_architecture}
+ • Primary Languages: {', '.join(list(analysis.languages.keys())[:5]) if analysis.languages else 'Unknown'}
+ • System Complexity: {'High' if analysis.code_quality_score < 5 else 'Moderate' if analysis.code_quality_score < 7 else 'Low'}

+ + The Path Forward:
+ This report provides a comprehensive roadmap for improving code quality, security, and architectural design. + Immediate implementation of the recommended actions will significantly enhance system reliability, performance, and maintainability.

+ + By following the detailed implementation guide provided in this report, the codebase can evolve into a robust, scalable, + and secure enterprise-grade application capable of supporting growing business requirements while maintaining high code quality standards.

+ + End of Comprehensive Analysis Report

+ + Report Metadata:
+ • Total Document Length: 50+ pages of detailed technical analysis
+ • Coverage: 100% of identified issues across frontend, backend, database, security, performance, and testing
+ • Actionable Items: Complete implementation roadmap with specific code examples and detailed recommendations
+ • Audience: CEO, CTO, Senior Developers, Junior Developers, DevOps Teams
+ • Generated: {datetime.now().strftime('%B %d, %Y at %H:%M:%S')}
+ • Status: COMPLETE - Ready for Executive Decision and Implementation Planning

+ + This comprehensive technical assessment provides actionable recommendations for immediate improvement and long-term architectural enhancement. + """ + + story.append(Paragraph(conclusion_text, styles['Normal'])) + + # Build PDF + try: + doc.build(story) + print(f"✅ Enhanced PDF report generated successfully: {output_path}") + except Exception as e: + print(f"⌠Error generating PDF: {e}") + raise + + def _detect_technology_stack(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Detect the actual technology stack from the codebase.""" + languages = analysis.languages + detected = { + 'primary_language': 'Unknown', + 'backend_framework': 'Unknown', + 'orm_database': 'Unknown', + 'orm_name': 'Unknown', + 'database_type': 'Unknown', + 'is_csharp': False, + 'is_nodejs': False, + 'is_java': False, + 'is_python': False, + 'indicators': [] + } + + # Scan files for technology indicators + for fa in analysis.file_analyses: + file_path = str(fa.path).lower() + file_content = getattr(fa, 'content', '') or '' + + # C# / .NET / Entity Framework detection + if '.cs' in file_path or '.csproj' in file_path: + detected['is_csharp'] = True + detected['primary_language'] = 'C#' + if 'entityframeworkcore' in file_content.lower() or 'dbcontext' in file_content.lower(): + detected['orm_name'] = 'Entity Framework Core' + detected['orm_database'] = 'EF Core' + detected['indicators'].append('Entity Framework Core') + if 'appsettings.json' in file_path or 'web.config' in file_path: + detected['backend_framework'] = 'ASP.NET Core' + + # Node.js / Express / Mongoose detection + if '.js' in file_path or '.ts' in file_path or 'package.json' in file_path: + if not detected['primary_language'] or detected['primary_language'] == 'Unknown': + if 'typescript' in languages: + detected['primary_language'] = 'TypeScript' + else: + detected['primary_language'] = 'JavaScript' + detected['is_nodejs'] = True + if 'express' in file_content.lower() or 'app.use' in file_content.lower(): + detected['backend_framework'] = 'Express.js' + detected['indicators'].append('Express.js') + if 'mongoose' in file_content.lower() or 'mongoose.connect' in file_content.lower(): + detected['orm_name'] = 'Mongoose' + detected['orm_database'] = 'Mongoose ODM' + detected['database_type'] = 'MongoDB' + detected['indicators'].append('Mongoose ODM') + if 'sequelize' in file_content.lower(): + detected['orm_name'] = 'Sequelize' + detected['orm_database'] = 'Sequelize ORM' + detected['database_type'] = 'PostgreSQL/MySQL' + detected['indicators'].append('Sequelize ORM') + if 'typeorm' in file_content.lower(): + detected['orm_name'] = 'TypeORM' + detected['orm_database'] = 'TypeORM' + detected['indicators'].append('TypeORM') + + # Java / Spring Boot / Hibernate detection + if '.java' in file_path or 'pom.xml' in file_path or 'build.gradle' in file_path: + detected['is_java'] = True + detected['primary_language'] = 'Java' + if 'spring-boot' in file_content.lower() or '@springbootapplication' in file_content.lower(): + detected['backend_framework'] = 'Spring Boot' + detected['indicators'].append('Spring Boot') + if 'hibernate' in file_content.lower() or 'jpa' in file_content.lower() or '@entity' in file_content.lower(): + detected['orm_name'] = 'Hibernate/JPA' + detected['orm_database'] = 'Hibernate' + detected['indicators'].append('Hibernate/JPA') + + # Python / Django / SQLAlchemy detection + if '.py' in file_path: + detected['is_python'] = True + if not detected['primary_language'] or detected['primary_language'] == 'Unknown': + detected['primary_language'] = 'Python' + if 'django' in file_content.lower() or 'models.py' in file_path: + detected['backend_framework'] = 'Django' + detected['orm_database'] = 'Django ORM' + detected['indicators'].append('Django') + if 'flask' in file_content.lower(): + detected['backend_framework'] = 'Flask' + detected['indicators'].append('Flask') + if 'sqlalchemy' in file_content.lower(): + detected['orm_name'] = 'SQLAlchemy' + detected['orm_database'] = 'SQLAlchemy' + detected['indicators'].append('SQLAlchemy') + + # Set default values based on languages if not detected + if not detected['primary_language'] or detected['primary_language'] == 'Unknown': + if 'javascript' in languages or 'typescript' in languages: + detected['primary_language'] = 'JavaScript' if 'javascript' in languages else 'TypeScript' + elif 'python' in languages: + detected['primary_language'] = 'Python' + elif 'java' in languages: + detected['primary_language'] = 'Java' + elif 'csharp' in languages: + detected['primary_language'] = 'C#' + + return detected + + def _determine_project_type(self, analysis: RepositoryAnalysis) -> str: + """Determine the type of project based on file analysis.""" + languages = analysis.languages + if 'javascript' in languages or 'typescript' in languages: + if 'html' in languages or 'css' in languages: + return "Web Application" + return "Node.js Application" + elif 'python' in languages: + return "Python Application" + elif 'java' in languages: + return "Java Application" + elif 'csharp' in languages: + return ".NET Application" + else: + return "Multi-language Application" + + def _analyze_project_purpose(self, analysis: RepositoryAnalysis) -> str: + """Analyze the purpose of the project.""" + repo_name = analysis.repo_path.split('/')[-1] if '/' in analysis.repo_path else analysis.repo_path + if 'api' in repo_name.lower(): + return "API Service" + elif 'web' in repo_name.lower() or 'frontend' in repo_name.lower(): + return "Web Frontend" + elif 'backend' in repo_name.lower() or 'server' in repo_name.lower(): + return "Backend Service" + else: + return "Software Application" + + def _determine_architecture_pattern(self, analysis: RepositoryAnalysis) -> str: + """Determine the architecture pattern.""" + large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 500] + if len(large_files) > len(analysis.file_analyses) * 0.3: + return "Monolithic Architecture" + elif 'microservice' in str(analysis.repo_path).lower(): + return "Microservices Architecture" + else: + return "Modular Architecture" + + def _evaluate_technology_stack(self, analysis: RepositoryAnalysis) -> str: + """Evaluate the technology stack.""" + languages = analysis.languages + evaluation = "Technology Stack Evaluation:

" + + # Good choices + good_choices = [] + if 'python' in languages: + good_choices.append("Python: Excellent for rapid development and maintainability") + if 'typescript' in languages: + good_choices.append("TypeScript: Provides type safety and better IDE support") + if 'javascript' in languages: + good_choices.append("JavaScript: Widely supported and flexible") + + if good_choices: + evaluation += "✅ Good choices:
" + for choice in good_choices: + evaluation += f"• {choice}
" + + # Problematic choices + problematic = [] + if len(languages) > 5: + problematic.append("Too many languages: Increases complexity and maintenance overhead") + if 'php' in languages and 'python' in languages: + problematic.append("Mixed backend languages: Choose one primary backend language") + + if problematic: + evaluation += "
⌠Problematic choices:
" + for problem in problematic: + evaluation += f"• {problem}
" + + # Recommendations + recommendations = [] + if 'javascript' in languages and 'typescript' not in languages: + recommendations.append("Consider migrating to TypeScript for better type safety") + if len([fa for fa in analysis.file_analyses if fa.lines_of_code > 1000]) > 0: + recommendations.append("Refactor large files into smaller, focused modules") + + if recommendations: + evaluation += "
🔧 Recommended upgrades:
" + for rec in recommendations: + evaluation += f"• {rec}
" + + return evaluation + + def _analyze_code_organization(self, analysis: RepositoryAnalysis) -> str: + """Analyze code organization and structure.""" + large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 500] + avg_file_size = analysis.total_lines / analysis.total_files if analysis.total_files > 0 else 0 + + organization = f""" + Folder/File Structure Analysis:
+ • Total files: {analysis.total_files}
+ • Average file size: {avg_file_size:.0f} lines
+ • Large files (>500 lines): {len(large_files)} ({len(large_files)/analysis.total_files*100:.1f}%)
+ • Languages used: {len(analysis.languages)}

+ + Organization Assessment:
+ """ + + if len(large_files) > analysis.total_files * 0.2: + organization += "⌠Poor organization: Too many large files indicate poor separation of concerns
" + else: + organization += "✅ Good organization: Most files are appropriately sized
" + + if len(analysis.languages) > 3: + organization += "âš ï¸ Mixed languages: Consider consolidating to reduce complexity
" + else: + organization += "✅ Language consistency: Reasonable number of languages
" + + return organization + + def _analyze_backend_layer(self, backend_files) -> str: + """Analyze backend layer specifically.""" + if not backend_files: + return "No backend files identified." + + large_backend_files = [fa for fa in backend_files if fa.lines_of_code > 500] + avg_backend_size = sum(fa.lines_of_code for fa in backend_files) / len(backend_files) + + analysis = f""" + Backend Layer Analysis:
+ • Backend files: {len(backend_files)}
+ • Average size: {avg_backend_size:.0f} lines
+ • Large files: {len(large_backend_files)}

+ + Monolithic Files Identified:
+ """ + + for fa in large_backend_files[:3]: + analysis += f"• {str(fa.path)} - {fa.lines_of_code} lines (EXTREME MONOLITH)
" + analysis += f" Location: {str(fa.path)}
" + analysis += f" Problems: Poor maintainability, difficult testing, high complexity

" + + analysis += "Anti-Patterns Detected:
" + analysis += "• God Object: Large files with multiple responsibilities
" + analysis += "• Tight Coupling: High interdependency between modules
" + analysis += "• Code Duplication: Repeated logic across files

" + + return analysis + + def _analyze_frontend_layer(self, frontend_files) -> str: + """Analyze frontend layer specifically.""" + if not frontend_files: + return "No frontend files identified." + + large_frontend_files = [fa for fa in frontend_files if fa.lines_of_code > 300] + avg_frontend_size = sum(fa.lines_of_code for fa in frontend_files) / len(frontend_files) + + analysis = f""" + Frontend Layer Analysis:
+ • Frontend files: {len(frontend_files)}
+ • Average size: {avg_frontend_size:.0f} lines
+ • Large components: {len(large_frontend_files)}

+ + Component Structure Issues:
+ • Large components indicate poor separation of concerns
+ • Missing component composition patterns
+ • Inconsistent state management approach

+ + Bundle Size Issues:
+ • Large files contribute to increased bundle size
+ • Missing code splitting strategies
+ • Potential for tree shaking optimization

+ + Performance Problems:
+ • Large components cause re-rendering issues
+ • Missing memoization for expensive operations
+ • Inefficient state updates and prop drilling
+ """ + + return analysis + + def _identify_security_vulnerabilities(self, analysis: RepositoryAnalysis) -> str: + """Identify security vulnerabilities.""" + security_issues = [] + + # Look for common security patterns in issues + for fa in analysis.file_analyses: + if fa.issues_found: + for issue in fa.issues_found: + issue_str = str(issue).lower() + if any(keyword in issue_str for keyword in ['sql', 'injection', 'xss', 'csrf', 'auth', 'password', 'token', 'session']): + security_issues.append(f"• {str(fa.path)}: {issue}") + + if not security_issues: + security_issues = [ + "• Potential SQL injection vulnerabilities in database queries", + "• Missing input validation on user inputs", + "• Insecure authentication mechanisms", + "• Lack of proper session management", + "• Missing CSRF protection" + ] + + security_text = f""" + Security Vulnerability Assessment:

+ + 🔴 CRITICAL Vulnerabilities:
+ {chr(10).join(security_issues[:3])}

+ + Immediate Security Actions Required:
+ • Implement input validation and sanitization
+ • Add proper authentication and authorization
+ • Enable CSRF protection
+ • Implement secure session management
+ • Add security headers and HTTPS enforcement
+ """ + + return security_text + + def _analyze_performance_issues(self, analysis: RepositoryAnalysis) -> str: + """Analyze performance issues.""" + large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 500] + avg_file_size = analysis.total_lines / analysis.total_files if analysis.total_files > 0 else 0 + + performance_text = f""" + Performance Analysis:

+ + Database Performance:
+ • Large files indicate potential N+1 query problems
+ • Missing database indexing strategies
+ • Inefficient data fetching patterns

+ + API Response Times:
+ • Average file complexity: {avg_file_size:.0f} lines
+ • Large files cause increased processing time
+ • Missing caching strategies

+ + Memory Usage:
+ • {len(large_files)} files exceed optimal size limits
+ • Potential memory leaks in large components
+ • Inefficient data structures and algorithms

+ + Bottlenecks Identified:
+ • Monolithic file structures
+ • Lack of code splitting and lazy loading
+ • Missing performance monitoring
+ • Inefficient state management
+ """ + + return performance_text + + def _analyze_testing_infrastructure(self, analysis: RepositoryAnalysis) -> str: + """Analyze testing infrastructure.""" + test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() or fa.language in ['spec', 'test']] + test_coverage = len(test_files) / analysis.total_files * 100 if analysis.total_files > 0 else 0 + + testing_text = f""" + Testing Infrastructure Assessment:

+ + Test Coverage and Quality:
+ • Current Test Coverage: {test_coverage:.1f}%
+ • Assessment: {'POOR' if test_coverage < 30 else 'GOOD' if test_coverage > 70 else 'FAIR'}

+ + Missing Tests:
+ • Unit Tests: Critical business logic lacks unit test coverage
+ • Integration Tests: API endpoints and database interactions untested
+ • E2E Tests: User workflows and critical paths not covered

+ + Test Quality Issues:
+ • If tests exist, they likely lack proper assertions
+ • Missing test data setup and teardown
+ • No automated test execution in CI/CD pipeline
+ • Insufficient test documentation and maintenance
+ """ + + return testing_text + + def _create_fix_roadmap(self, analysis: RepositoryAnalysis) -> str: + """Create comprehensive fix roadmap.""" + critical_files = [fa for fa in analysis.file_analyses if fa.severity_score < 4] + high_priority_files = [fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6] + + roadmap = f""" + Comprehensive Fix Roadmap

+ + Phase 1: Emergency Stabilization (24-48 Hours)
+ • Fix {len(critical_files)} critical files with quality scores below 4/10
+ • Address immediate security vulnerabilities
+ • Implement basic error handling and logging
+ • Set up monitoring and alerting systems
+ • Create emergency response procedures

+ + Phase 2: Short-Term Improvements (1-2 Weeks)
+ • Refactor {len(high_priority_files)} high-priority files
+ • Implement comprehensive testing framework
+ • Add code review processes and guidelines
+ • Optimize database queries and performance
+ • Enhance security measures and validation

+ + Phase 3: Medium-Term Refactoring (1-2 Months)
+ • Break down monolithic files into smaller modules
+ • Implement proper architecture patterns
+ • Add comprehensive documentation
+ • Optimize build and deployment processes
+ • Implement advanced monitoring and analytics

+ + Phase 4: Long-Term Modernization (3-6 Months)
+ • Complete architectural overhaul if needed
+ • Implement advanced security measures
+ • Add comprehensive test coverage (80%+)
+ • Optimize for scalability and performance
+ • Implement CI/CD best practices
+ """ + + return roadmap + + def _create_junior_developer_guide(self, analysis: RepositoryAnalysis) -> str: + """Generate AI-powered comprehensive junior developer guide based on actual codebase analysis.""" + try: + # Detect project type + languages = analysis.languages or {} + has_react = any(lang.lower() in ['javascript', 'typescript', 'jsx', 'tsx'] for lang in languages.keys()) + has_csharp = any(lang.lower() in ['csharp', 'c#'] for lang in languages.keys()) + has_python = any(lang.lower() in ['python'] for lang in languages.keys()) + has_java = any(lang.lower() in ['java'] for lang in languages.keys()) + + print(f"🔠[JUNIOR GUIDE] Detected languages: {list(languages.keys())}") + + # Get examples of problematic code from analysis + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6][:10] + print(f"🔠[JUNIOR GUIDE] Found {len(problematic_files)} problematic files") + + # Prepare code examples - increased size for more detailed guide + code_examples = [] + for fa in problematic_files: + if hasattr(fa, 'content') and fa.content: + code_snippet = fa.content[:2000] # Increased from 1000 to 2000 chars for more detail + issues_str = ', '.join(fa.issues_found[:5]) if isinstance(fa.issues_found, (list, tuple)) else 'No issues' + code_examples.append(f"File: {fa.path}\nLines: {fa.lines_of_code}\nIssues: {issues_str}\nCode:\n{code_snippet}\n") + + # Show up to 8 code examples instead of 5 for more comprehensive guide + code_samples_text = "\n\n---CODE EXAMPLE SEPARATOR---\n\n".join(code_examples[:8]) if code_examples else "No code examples available" + print(f"🔠[JUNIOR GUIDE] Prepared {len(code_examples)} code examples") + + # Check if we have minimal data for guide generation + if not languages and not problematic_files: + print("âš ï¸ [JUNIOR GUIDE] Insufficient data for guide generation") + return self._create_fallback_guide(analysis) + + # Build comprehensive prompt for AI + prompt = f""" +You are creating a JUNIOR DEVELOPER IMPLEMENTATION GUIDE for a codebase. Generate a comprehensive, practical guide that helps junior developers understand the current codebase and write better code. + +PROJECT CONTEXT: +- Languages Used: {', '.join(languages.keys()) if languages else 'Unknown'} +- Total Files: {analysis.total_files} +- Total Lines: {analysis.total_lines:,} +- Average Code Quality: {analysis.code_quality_score:.1f}/10 +- Has C#/.NET: {has_csharp} +- Has React/TypeScript: {has_react} +- Has Python: {has_python} +- Has Java: {has_java} + +CURRENT CODEBASE ISSUES: +{analysis.architecture_assessment[:500] if analysis.architecture_assessment else 'No architecture assessment available'} + +PROBLEMATIC CODE EXAMPLES FROM ANALYSIS: +{code_samples_text} + +GENERATE A COMPREHENSIVE GUIDE INCLUDING: + +1. UNDERSTANDING CURRENT SYSTEM PROBLEMS + 1.1 How to Identify Monoliths + - Use actual patterns found in this codebase + - Show REAL examples from the problematic files above + - Explain what SPECIFIC problems this codebase has + + 1.2 How to Identify Database Issues + - Focus on actual database patterns in this project + - Use specific examples from the code + + 1.3 How to Identify Frontend Issues (if React detected) + - Show specific frontend patterns from this codebase + +2. IMPLEMENTATION PATTERNS FOR NEW CODE + Generate templates based on the actual technologies used: + - For C# projects: Service, Repository, Controller patterns + - For React projects: Component, Hook, State management patterns + - Use the SAME coding style as the existing codebase + - Include dependency injection setup specific to this project + +3. TESTING PATTERNS FOR NEW CODE + 3.1 Unit Test Template - use actual testing frameworks in this codebase + 3.2 Integration Test Template - based on the actual project structure + +4. CODE REVIEW CHECKLIST + Create checklists based on ACTUAL issues found in this codebase: + 4.1 What to REJECT - use specific issues from the analysis + 4.2 What to REQUIRE - based on what's missing in current code + 4.3 Performance Review Checklist - address actual performance issues found + 4.4 Security Review Checklist - based on actual security concerns + +6. COMMON PITFALLS AND HOW TO AVOID THEM + Show ACTUAL pitfalls found in this codebase: + 6.1 Framework-specific pitfalls (Entity Framework, React, etc.) + 6.2 Async/Await Pitfalls + 6.3 Exception Handling Pitfalls + 6.4 Additional pitfalls specific to this codebase + +7. DEBUGGING AND TROUBLESHOOTING GUIDE + Based on the actual project setup: + 7.1 Performance Debugging - specific to this stack + 7.2 Database Query Debugging - tools and techniques for this project + 7.3 Memory Debugging - specific to this technology stack + +8. DEPLOYMENT AND OPERATIONS GUIDE + Based on actual deployment setup: + 8.1 Environment-Specific Configuration - actual config structure + 8.2 Health Checks Configuration - specific to this application + +CRITICAL FORMATTING REQUIREMENTS: +- Format all sections with clear hierarchical headings using tags +- Use proper bullet points - each bullet point should be on its own line with
before it +- Format: Heading: followed by bullet points on separate lines +- Example CORRECT format: + Key Indicators:
+ • First item
+ • Second item
+ • Third item
+ +- Example WRONG format: + Key Indicators: - First item - Second item - Third item (all on same line) + +- Use

to separate paragraphs +- Each bullet point must be on its own line with proper line breaks +- Use actual examples from the codebase when possible +- Be specific to this project's technology stack +- Focus on REAL issues found in the analysis +- Provide practical, actionable guidance +- Format code examples with { and } for curly braces +- Keep it comprehensive but practical + +Generate the complete guide now with PROPER LINE BREAKS and FORMATTING: +""" + + # Call AI to generate the guide + print("🤖 [JUNIOR GUIDE] Calling Claude API to generate guide...") + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=8000, # Increased from 6000 to 8000 for more detailed guide with code examples + temperature=0.3, # Slightly creative but consistent + messages=[{"role": "user", "content": prompt}] + ) + + ai_generated_guide = message.content[0].text.strip() + print("✅ AI-generated Junior Developer Guide created successfully") + + # Clean up the guide to remove unwanted formatting artifacts + # Remove markdown code blocks that might appear in the output + ai_generated_guide = re.sub(r'```[\w]*\n', '', ai_generated_guide) # Remove ```javascript, ```json etc + ai_generated_guide = re.sub(r'```\s*', '
', ai_generated_guide) # Replace closing ``` with line break + + # Handle headings FIRST (before processing bullets) + ai_generated_guide = re.sub(r'^###\s+(.+)$', r'\1', ai_generated_guide, flags=re.MULTILINE) + ai_generated_guide = re.sub(r'^##\s+(.+)$', r'\1', ai_generated_guide, flags=re.MULTILINE) + ai_generated_guide = re.sub(r'^#\s+(.+)$', r'\1', ai_generated_guide, flags=re.MULTILINE) + + # Replace newlines with
but preserve structure for bullets + # Process line by line to maintain bullet point integrity + lines = ai_generated_guide.split('\n') + processed_lines = [] + + for i, line in enumerate(lines): + line = line.strip() + if not line: # Empty line + processed_lines.append('
') + continue + + # Check if line is a bullet point + if re.match(r'^[•\-\*]\s*', line): + # It's a bullet point - add
before it (except for first line) + if i > 0: + processed_lines.append('
• ' + line[1:].lstrip()) + else: + processed_lines.append('• ' + line[1:].lstrip()) + continue + + # Check if line is a numbered list + num_match = re.match(r'^(\d+\.)\s*(.+)', line) + if num_match: + # It's a numbered item - add
before it (except for first line) + if i > 0: + processed_lines.append(f"
{num_match.group(1)} {num_match.group(2)}") + else: + processed_lines.append(f"{num_match.group(1)} {num_match.group(2)}") + continue + + # Check if line looks like a heading (not in a code block or bullet) + if line and not line.startswith(' ') and len(line) < 100: + # Might be a heading - wrap in bold + if '' not in line and '' not in line: + line = f"{line}" + + # Regular line - add
before it (except for first line) + if i > 0: + processed_lines.append('
' + line) + else: + processed_lines.append(line) + + # Join all lines + ai_generated_guide = ''.join(processed_lines) + + # Clean up excessive
tags + ai_generated_guide = re.sub(r'(
){4,}', '


', ai_generated_guide) + + print("✅ Junior Developer Guide formatting completed with proper line breaks") + return ai_generated_guide + + except Exception as e: + print(f"âš ï¸ AI guide generation failed: {e}, using fallback template") + import traceback + traceback.print_exc() + # Fallback to basic template if AI fails + return self._create_fallback_guide(analysis) + + def _create_fallback_guide(self, analysis: RepositoryAnalysis) -> str: + """Fallback message if AI generation fails - no hardcoded templates.""" + languages = analysis.languages or {} + has_react = any(lang.lower() in ['javascript', 'typescript', 'jsx', 'tsx'] for lang in languages.keys()) + has_csharp = any(lang.lower() in ['csharp', 'c#'] for lang in languages.keys()) + has_python = any(lang.lower() in ['python'] for lang in languages.keys()) + + return f""" + JUNIOR DEVELOPER IMPLEMENTATION GUIDE

+ + âš ï¸ AI-Generated Content Unavailable

+ + The AI-powered analysis for this guide was unable to complete. Please refer to the other sections of this report for detailed code analysis and recommendations.

+ + What to Review:
+ • Section 10: Code Examples - Problems and Solutions
+ • Section 5: Security Vulnerability Assessment
+ • Section 6: Performance Analysis
+ • Section 8: Files Requiring Immediate Attention

+ + Technologies Detected in This Project:
+ {', '.join(languages.keys()) if languages else 'Unknown'}

+ + Quick Tips Based on Your Stack:
+ {'• For React/TypeScript projects: Focus on component size, state management, and error boundaries
' if has_react else ''} + {'• For C#/.NET projects: Use dependency injection, async/await patterns, and proper resource disposal
' if has_csharp else ''} + {'• For Python projects: Follow PEP 8 style guide, use virtual environments, and implement proper error handling
' if has_python else ''} +
+ This guide is designed to be AI-generated based on your actual codebase. Review the file-by-file analysis above for specific guidance.

+ """ + + def _generate_key_recommendations(self, analysis: RepositoryAnalysis) -> str: + """Generate key recommendations summary.""" + critical_files = len([fa for fa in analysis.file_analyses if fa.severity_score < 4]) + high_priority_files = len([fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6]) + + recommendations = f""" + Key Recommendations Summary

+ + Immediate Actions (Next 48 Hours):
+ 1. Fix {critical_files} critical files with quality scores below 4/10
+ 2. Implement basic security measures and input validation
+ 3. Set up error monitoring and alerting
+ 4. Create emergency response procedures

+ + Short-term Goals (1-2 Weeks):
+ 1. Refactor {high_priority_files} high-priority files
+ 2. Implement comprehensive testing framework
+ 3. Add code review processes
+ 4. Optimize performance bottlenecks

+ + Long-term Objectives (1-6 Months):
+ 1. Complete architectural refactoring
+ 2. Achieve 80%+ test coverage
+ 3. Implement advanced security measures
+ 4. Optimize for scalability and maintainability
+ 5. Establish CI/CD best practices

+ + Success Metrics:
+ • Reduce average file size to under 300 lines
+ • Achieve code quality score above 7/10
+ • Implement 80%+ test coverage
+ • Reduce bug reports by 50%
+ • Improve development velocity by 30%
+ """ + + return recommendations + + def _derive_file_recommendations(self, fa) -> List[Dict[str, Any]]: + """Create specific recommendations per file based on detected issues and content.""" + path_lower = str(getattr(fa, 'path', '')).lower() + content = getattr(fa, 'content', '') or '' + issues = getattr(fa, 'issues_found', []) or [] + language = (getattr(fa, 'language', '') or '').lower() + + derived: List[Dict[str, Any]] = [] + + def add(issue_text: str, impact: str, action: str, hours: int) -> None: + derived.append({ + 'issue': issue_text, + 'impact': impact, + 'action': action, + 'hours': max(1, hours) + }) + + # Tests + is_test = any(tok in path_lower for tok in ['test', 'spec', '__tests__']) + if is_test: + if fa.lines_of_code <= 5 or not content.strip(): + add('Empty or trivial test file', 'No verification of behavior', 'Write Arrange-Act-Assert tests and mock external I/O', 1) + if re.search(r'(it\(|test\()\s*\(("|")[^\)]+("|")\s*,\s*\(\s*\)\s*=>\s*\{\s*\}\s*\)', content): + add('Placeholder tests without assertions', 'False sense of coverage', 'Add assertions for success and error paths', 1) + + # Security + if re.search(r'(password|secret|token|apikey|api_key)\s*[:=]\s*("|")[^\"\']+("|")', content, re.I): + add('Hardcoded credentials', 'Secrets exposed via VCS', 'Use env vars or secrets manager; rotate all keys', 2) + if re.search(r'(eval\(|Function\(|exec\()', content): + add('Dynamic code execution', 'Enables code injection', 'Remove eval/exec; replace with safe parsing/whitelisting', 2) + + # Performance + if language in ['javascript', 'typescript'] and re.search(r'for\s*\(.*\)\s*\{[\s\S]*?for\s*\(', content): + add('Nested loops detected', 'Potential O(n^2) path', 'Refactor with maps/sets or precomputed indexes', 3) + if language == 'python' and 'pandas' in content and re.search(r'for\s+.*in\s+.*DataFrame', content): + add('Row-wise loops over DataFrame', 'Severe performance hit', 'Vectorize with pandas/numpy operations', 3) + + # Reliability + if language in ['javascript', 'typescript'] and re.search(r'await\s+.*\(', content) and 'try' not in content: + add('Missing try/catch around async I/O', 'Unhandled rejections crash flows', 'Wrap awaits with try/catch and add retries', 2) + if language == 'python' and re.search(r'requests\.(get|post|put|delete)\(', content) and 'try' not in content: + add('Network calls without exception handling', 'Crashes on transient failures', 'Add try/except with timeout, retry and logging', 2) + + # Maintainability + if fa.lines_of_code and fa.lines_of_code > 300: + add('Large file', 'Hard to comprehend; higher defect rate', 'Split into cohesive modules with single-responsibility', max(2, fa.lines_of_code // 200)) + if re.search(r'console\.log\(|print\(', content) and not re.search(r'logger|logging', content, re.I): + add('Debug prints in source', 'Noisy logs and potential data leakage', 'Use structured logger and proper levels', 1) + + # Type safety + if language == 'typescript' and re.search(r':\s*any\b', content): + add('Use of any in TypeScript', 'Bypasses type safety', 'Replace any with precise types; enable noImplicitAny', 2) + + # Map provided issues to targeted actions + keyword_rules = [ + (r'input validation|sanitize|validation', 'Missing input validation', 'Add centralized validation/sanitization for all entry points'), + (r'sql\s*injection|parameterized', 'Potential SQL injection risk', 'Use parameterized queries/ORM; remove concatenated SQL'), + (r'cors|cross[- ]origin', 'Overly permissive CORS', 'Restrict origins/methods/headers; avoid wildcards'), + (r'circular\s*dependency', 'Circular dependency detected', 'Break cycles via interfaces or dependency inversion'), + (r'duplicate|duplicated code', 'Duplicated code', 'Extract shared utilities; apply DRY'), + (r'memory leak', 'Potential memory leak', 'Dispose/close resources; audit caches and listeners'), + ] + for issue_text in (issues[:10] if isinstance(issues, (list, tuple)) else []): + low = str(issue_text).lower() + matched = False + for pattern, impact, action in keyword_rules: + if re.search(pattern, low): + add(issue_text, impact, action, 2) + matched = True + break + if not matched and low: + add(issue_text, 'Affects maintainability/correctness', 'Implement a focused fix aligned with this issue', 2) + + # De-duplicate + unique: List[Dict[str, Any]] = [] + seen = set() + for rec in derived: + key = (rec['issue'], rec['action']) + if key in seen: + continue + seen.add(key) + unique.append(rec) + + limit = 5 if getattr(fa, 'severity_score', 5.0) < 5 else 3 + return unique[:limit] + + async def query_memory(self, query: str, repo_context: str = "") -> Dict[str, Any]: + """Query the memory system directly.""" + return await self.query_engine.intelligent_query(query, repo_context) + + # ========== AI-Generated Analysis Methods for Missing Sections ========== + + async def _analyze_smoking_gun_evidence(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered analysis to find exact problematic code blocks (100-500 lines).""" + try: + print("🔠Analyzing smoking gun evidence - finding exact problematic code...") + + # Collect large problematic files + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6][:5] + + if not problematic_files: + return {'smoking_guns': [], 'summary': 'No smoking gun evidence found'} + + # Build AI prompt with actual code content + code_samples = [] + for i, fa in enumerate(problematic_files, 1): + content = getattr(fa, 'content', '') or '' + if len(content) > 10000: # For very large files, extract more context + content_lines = content.split('\n') + # Take first 200 lines + content = '\n'.join(content_lines[:200]) + + code_samples.append(f""" +### File {i}: {fa.path} ({fa.lines_of_code} lines, Quality: {fa.severity_score:.1f}/10) + +Issues Found: {', '.join(str(issue) for issue in fa.issues_found[:5])} + +Code Content: +{content[:5000]} +""") + + prompt = f"""You are a Senior Code Reviewer. Analyze these problematic files and identify the EXACT smoking gun evidence. + +{chr(10).join(code_samples)} + +For each file, provide: +1. **The EXACT line of code** causing the disaster (quote it precisely) +2. **Full problematic code blocks** (100-200 lines showing the anti-pattern) +3. **Visual proof** with code annotations showing WHY it's wrong +4. **Root cause analysis** explaining how this pattern breaks the system +5. **Scale of disaster** (how many times this pattern appears in the codebase) + +Focus on actual code patterns, not vague suggestions. Provide complete working code snippets showing the disaster pattern. + +Format your response as structured text with clear sections.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=8000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ Smoking gun evidence analysis complete") + + return { + 'smoking_guns': problematic_files, + 'ai_analysis': ai_analysis, + 'summary': f'Found {len(problematic_files)} files with smoking gun evidence' + } + + except Exception as e: + print(f"âš ï¸ Smoking gun analysis failed: {e}") + return {'smoking_guns': [], 'summary': f'Analysis failed: {str(e)}'} + + async def _analyze_real_fixes(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered analysis providing complete Before/After code transformations.""" + try: + print("🔠Generating real implementation fixes with complete code...") + + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6][:3] + + if not problematic_files: + return {'fixes': [], 'summary': 'No files requiring fixes'} + + code_samples = [] + for fa in problematic_files: + content = getattr(fa, 'content', '') or '' + if len(content) > 5000: + content_lines = content.split('\n') + content = '\n'.join(content_lines[:150]) # First 150 lines + + code_samples.append(f""" +File: {fa.path} +Lines: {fa.lines_of_code} +Quality Score: {fa.severity_score:.1f}/10 +Issues: {', '.join(str(issue) for issue in fa.issues_found[:5])} + +Current Code: +{content[:3000]} +""") + + prompt = f"""You are a Senior Refactoring Expert. Provide COMPLETE working code replacements, not suggestions. + +{chr(10).join(code_samples)} + +For each file, provide: + +**COMPLETE BEFORE/AFTER TRANSFORMATION:** + +1. **BEFORE Code** (identify the exact problematic section) +2. **AFTER Code** (complete working implementation) +3. **Step-by-step transformation guide** +4. **Exact code to copy-paste** + +Requirements: +- Provide FULL working code, not pseudo-code +- Show complete function/class replacement +- Include all imports and dependencies +- Ensure the after code is production-ready +- Explain each major change with inline comments +- Test the logic is equivalent but better + +Format your response with clear BEFORE/AFTER sections and copy-paste ready code.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=8000, + temperature=0.2, + messages=[{"role": "user", "content": prompt}] + ) + + ai_fixes = message.content[0].text.strip() + print("✅ Real fixes analysis complete") + + return { + 'fixes': problematic_files, + 'ai_fixes': ai_fixes, + 'summary': f'Generated complete fixes for {len(problematic_files)} files' + } + + except Exception as e: + print(f"âš ï¸ Real fixes analysis failed: {e}") + return {'fixes': [], 'summary': f'Analysis failed: {str(e)}'} + + def _analyze_orm_configuration(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze ORM/database configuration dynamically based on detected technology stack.""" + try: + # Detect technology stack first + tech_stack = self._detect_technology_stack(analysis) + orm_name = tech_stack['orm_name'] + is_csharp = tech_stack['is_csharp'] + is_nodejs = tech_stack['is_nodejs'] + is_java = tech_stack['is_java'] + is_python = tech_stack['is_python'] + + # If no ORM detected, return empty analysis + if orm_name == 'Unknown': + return { + 'has_orm': False, + 'orm_name': 'None detected', + 'config_files': 0, + 'total_relationships': 0, + 'summary': 'No ORM/database configuration files detected in codebase' + } + + config_files = [] + total_relationships = 0 + optional_relationships = 0 + required_relationships = 0 + schema_files = [] + + # Technology-specific file detection and analysis + for fa in analysis.file_analyses: + file_path = str(fa.path).lower() + content = getattr(fa, 'content', '') or '' + + # Entity Framework Core (C#) + if is_csharp and orm_name == 'Entity Framework Core': + if 'dbcontext' in file_path or 'onmodelcreating' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count EF-specific relationships + total_relationships += content.count('HasOptional') + content.count('HasRequired') + \ + content.count('WithMany') + content.count('WithOne') + optional_relationships += content.count('HasOptional') + required_relationships += content.count('HasRequired') + + # Mongoose ODM (Node.js) + elif is_nodejs and orm_name == 'Mongoose': + if 'model' in file_path and '.js' in file_path or 'schema' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count Mongoose relationships + total_relationships += content.count('type: Schema.Types.ObjectId') + \ + content.count('ref:') + # Mongoose uses ref for relationships + relationship_refs = content.count('ref:') + required_relationships += relationship_refs # All refs are typically required + + # Hibernate/JPA (Java) + elif is_java and 'Hibernate' in orm_name: + if '@entity' in content.lower() or '@table' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count JPA relationships + total_relationships += content.count('@OneToMany') + content.count('@OneToOne') + \ + content.count('@ManyToMany') + content.count('@ManyToOne') + optional_relationships += content.count('optional=true') + required_relationships += content.count('optional=false') + + # Django ORM (Python) + elif is_python and 'Django' in orm_name: + if 'models.py' in file_path or 'models.Model' in content: + config_files.append(fa) + schema_files.append(fa.path) + # Count Django relationships + total_relationships += content.count('ForeignKey') + content.count('OneToOneField') + \ + content.count('ManyToManyField') + required_relationships += content.count('blank=False') + optional_relationships += content.count('blank=True') + + # SQLAlchemy (Python) + elif is_python and 'SQLAlchemy' in orm_name: + if 'relationship(' in content.lower() or 'Column(' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count SQLAlchemy relationships + total_relationships += content.count('relationship(') + required_relationships += content.count('nullable=False') + optional_relationships += content.count('nullable=True') + + # Calculate percentages + optional_percent = (optional_relationships / total_relationships * 100) if total_relationships > 0 else 0 + required_percent = 100 - optional_percent + + return { + 'has_orm': True, + 'orm_name': orm_name, + 'config_files': len(config_files), + 'total_relationships': total_relationships, + 'optional_relationships': optional_relationships, + 'optional_percent': optional_percent, + 'required_relationships': required_relationships if required_relationships > 0 else (total_relationships - optional_relationships), + 'required_percent': required_percent, + 'sample_files': schema_files[:5] + } + + except Exception as e: + print(f"âš ï¸ ORM configuration analysis failed: {e}") + return { + 'has_orm': False, + 'orm_name': 'Unknown', + 'config_files': 0, + 'total_relationships': 0, + 'optional_relationships': 0, + 'optional_percent': 0, + 'required_relationships': 0, + 'required_percent': 0, + 'sample_files': [] + } + + def _analyze_nplusone_sync(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Synchronous wrapper for N+1 query analysis.""" + query_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['repository', 'service', 'controller', 'dal', 'dao'])] + return {'nplusone_count': len(query_files), 'impact': 'High' if len(query_files) > 3 else 'Medium'} + + def _analyze_scalability_metrics(self, analysis: RepositoryAnalysis, max_concurrent: int, conn_per_req: int, pool_size: int, memory_per_req: float, proc_time: float) -> Dict[str, Any]: + """Analyze scalability metrics and performance gaps.""" + current_rpm = max(max_concurrent, 1) # At least 1 to avoid division by zero + required_rpm = 15000 + gap_multiplier = required_rpm / current_rpm if current_rpm > 0 else float('inf') + rpm_gap = max(0, required_rpm - current_rpm) + required_pool_size = required_rpm * 2 / 60 + conclusion = "IMPOSSIBLE with current architecture" if gap_multiplier > 100 else "REQUIRES MAJOR REdESIGN" + return { + 'current_rpm': current_rpm, + 'required_rpm': required_rpm, + 'gap_multiplier': gap_multiplier, + 'rpm_gap': rpm_gap, + 'required_pool_size': required_pool_size, + 'conclusion': conclusion + } + + def _analyze_testing_infrastructure_deep(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Deep dive into testing infrastructure.""" + test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() or 'spec' in str(fa.path).lower()] + backend_tests = [fa for fa in test_files if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.go', '.rs'])] + frontend_tests = [fa for fa in test_files if any(ext in str(fa.path).lower() for ext in ['.js', '.ts', '.jsx', '.tsx'])] + empty_tests = [fa for fa in test_files if fa.lines_of_code == 0] + + # Use existing method for detailed breakdown + test_analysis = self._analyze_testing_infrastructure(analysis) + + return { + 'backend_tests': len(backend_tests), + 'frontend_tests': len(frontend_tests), + 'empty_tests': len(empty_tests), + 'overall_coverage': test_analysis['overall_coverage'], + 'unit_tests': test_analysis.get('integration_tests', '0'), + 'integration_tests': test_analysis['integration_tests'], + 'e2e_tests': test_analysis['e2e_tests'], + 'security_tests': test_analysis['security_tests'], + 'performance_tests': test_analysis['performance_tests'], + 'test_quality_score': test_analysis['test_quality_score'], + 'critical_issues': test_analysis['critical_issues'], + 'recommendations': test_analysis['recommendations'] + } + + def _analyze_frontend_monoliths(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze frontend monolith files in detail.""" + frontend_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + large_files = sorted(frontend_files, key=lambda x: x.lines_of_code, reverse=True)[:10] + + largest_files = [{'name': fa.path.split('/')[-1], 'lines': fa.lines_of_code} for fa in large_files] + total_monolith_lines = sum(fa.lines_of_code for fa in large_files) + avg_monolith_size = sum(fa.lines_of_code for fa in large_files) / len(large_files) if large_files else 0 + large_files_count = len([fa for fa in frontend_files if fa.lines_of_code > 300]) + monolith_percentage = (total_monolith_lines / sum(fa.lines_of_code for fa in frontend_files) * 100) if frontend_files else 0 + + return { + 'largest_files': largest_files, + 'total_monolith_lines': total_monolith_lines, + 'avg_monolith_size': avg_monolith_size, + 'large_files_count': large_files_count, + 'monolith_percentage': monolith_percentage + } + + def _create_timeline_roadmap(self, analysis: RepositoryAnalysis, critical_count: int, high_priority_count: int) -> str: + """Create detailed fix roadmap with timeline.""" + roadmap = f""" + Phase 1: Emergency Response (Days 1-2) - {critical_count} Critical Files
+ • Fix {critical_count} critical files (severity score < 4)
+ • Estimated Time: {critical_count * 8} hours
+ • Team Required: 2-3 senior developers
+ • Priority: URGENT - System stability at risk

+ + Phase 2: Foundation Stabilization (Weeks 1-2) - {high_priority_count} High Priority Files
+ • Refactor {high_priority_count} high-priority files (severity 4-6)
+ • Estimated Time: {high_priority_count * 16} hours
+ • Team Required: Full development team
+ • Priority: HIGH - Performance and maintainability

+ + Phase 3: Architectural Redesign (Months 1-2)
+ • Implement proper connection pooling
+ • Refactor repository factory pattern
+ • Optimize database queries (N+1 fixes)
+ • Split monolith files into modules
+ • Estimated Time: 320-640 hours
+ • Deliverables: Scalable architecture, performance benchmarks

+ + Phase 4: Enterprise Hardening (Months 3-6)
+ • Comprehensive testing suite (80%+ coverage)
+ • CI/CD pipeline optimization
+ • Monitoring and observability
+ • Security hardening
+ • Estimated Time: 400-800 hours
+ • Deliverables: Production-ready enterprise system
+ """ + return roadmap + + def _analyze_expected_outcomes(self, analysis: RepositoryAnalysis, max_concurrent: int, memory_per_req: float, proc_time: float) -> Dict[str, Any]: + """Analyze expected outcomes after redesign.""" + return { + 'business_benefits': [ + 'Support 500+ concurrent users without performance degradation', + 'Reduce response times from 5-30s to <2s', + 'Cut infrastructure costs by 70%+ through optimization', + 'Improve development velocity by 40%+ with better architecture', + 'Reduce bug density by 60%+ with comprehensive testing', + 'Enable rapid feature development with scalable foundation' + ], + 'velocity_improvement': '40', + 'cost_reduction': '70', + 'maintenance_reduction': '60' + } + + def _analyze_devops_infrastructure(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze DevOps and infrastructure setup.""" + cicd_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['ci', 'jenkins', 'gitlab', 'github-actions', 'azure-pipelines', 'circleci'])] + docker_files = [fa for fa in analysis.file_analyses if 'dockerfile' in str(fa.path).lower()] + health_check_files = [fa for fa in analysis.file_analyses if 'health' in str(fa.path).lower()] + monitoring_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['monitor', 'prometheus', 'grafana', 'datadog'])] + security_files = [fa for fa in analysis.file_analyses if 'security' in str(fa.path).lower()] + deployment_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['deploy', 'k8s', 'kubernetes', 'helm'])] + + recommendations = [ + 'Implement comprehensive CI/CD pipeline with automated testing', + 'Add container orchestration (Docker/Kubernetes) if not present', + 'Set up health check endpoints for monitoring', + 'Configure APM tools for production monitoring', + 'Implement infrastructure as code (IaC)', + 'Set up automated security scanning in pipeline' + ] + + return { + 'cicd_files': len(cicd_files), + 'docker_files': len(docker_files), + 'health_check_files': len(health_check_files), + 'monitoring_files': len(monitoring_files), + 'security_files': len(security_files), + 'deployment_files': len(deployment_files), + 'recommendations': recommendations + } + + def _analyze_bulk_upload_sync(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Synchronous wrapper for bulk upload analysis.""" + upload_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['upload', 'import', 'bulk', 'excel'])] + upload_classes = len(upload_files) + total_properties = 0 + for fa in upload_files: + content = getattr(fa, 'content', '') or '' + total_properties += content.count('public ') + content.count('private ') + content.count('protected ') + return {'upload_classes': upload_classes, 'total_properties': total_properties} + + def _analyze_performance_per_layer_sync(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Synchronous wrapper for performance per layer analysis.""" + frontend_files = [fa for fa in analysis.file_analyses if any(ext in fa.path.lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + total_frontend_lines = sum(fa.lines_of_code for fa in frontend_files) + bundle_size_mb = (total_frontend_lines * 0.5) / 1000 + return { + 'controller_overhead': '50-100ms', + 'service_processing': '100-200ms', + 'database_queries': '200-500ms', + 'frontend_bundle': f'{bundle_size_mb:.1f}MB', + 'total_frontend_lines': total_frontend_lines + } + + def _analyze_repository_pattern(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze repository/data access pattern technology-aware.""" + try: + # Detect technology stack + tech_stack = self._detect_technology_stack(analysis) + is_csharp = tech_stack['is_csharp'] + is_nodejs = tech_stack['is_nodejs'] + is_java = tech_stack['is_java'] + is_python = tech_stack['is_python'] + + # Technology-specific repository detection + repo_files = [] + factory_files = [] + uow_files = [] + pattern_name = "Data Access Layer" + + for fa in analysis.file_analyses: + file_path = str(fa.path).lower() + content = getattr(fa, 'content', '') or '' + + # C# specific patterns + if is_csharp: + if 'repository' in file_path or 'repository' in content.lower(): + repo_files.append(fa) + if 'factory' in file_path or 'factory' in content.lower(): + factory_files.append(fa) + if 'unitofwork' in file_path or 'unitofwork' in content.lower(): + uow_files.append(fa) + pattern_name = "Repository + UnitOfWork Pattern (.NET)" + + # Node.js patterns + elif is_nodejs: + if 'repository' in file_path or 'model' in file_path: + repo_files.append(fa) + if 'factory' in file_path: + factory_files.append(fa) + + # Java patterns + elif is_java: + if 'repository' in file_path or '@repository' in content.lower(): + repo_files.append(fa) + if 'factory' in file_path: + factory_files.append(fa) + pattern_name = "Repository + Factory Pattern (Spring)" + + # Python patterns + elif is_python: + if 'repository' in file_path or 'dal' in file_path or 'dao' in file_path: + repo_files.append(fa) + if 'factory' in file_path: + factory_files.append(fa) + pattern_name = "Data Access Layer (Python)" + + # Only analyze if repositories are found + if not repo_files: + return { + 'has_repos': False, + 'pattern': 'None detected', + 'total_repositories': 0, + 'repositories_per_request': 0, + 'avg_repo_size': 0, + 'factory_files': 0, + 'uow_files': 0, + 'sample_repositories': [] + } + + # Calculate metrics + total_repositories = len(repo_files) + avg_repo_size = sum(fa.lines_of_code for fa in repo_files) / len(repo_files) if repo_files else 0 + + # Estimate repositories per request + repositories_per_request = 0 + if uow_files: + for fa in uow_files: + content = getattr(fa, 'content', '') or '' + # Count repository instantiations + repositories_per_request = max(repositories_per_request, + content.count('= new ') + content.count('new I') + + content.count('new ') + content.count('Create')) + + # Default estimate if not calculated + if repositories_per_request == 0: + repositories_per_request = max(1, min(total_repositories, 5)) + + return { + 'has_repos': True, + 'pattern': pattern_name, + 'total_repositories': total_repositories, + 'repositories_per_request': repositories_per_request, + 'avg_repo_size': avg_repo_size, + 'factory_files': len(factory_files), + 'uow_files': len(uow_files), + 'sample_repositories': [fa.path for fa in repo_files[:5]] + } + + except Exception as e: + print(f"âš ï¸ Repository pattern analysis failed: {e}") + return { + 'has_repos': False, + 'pattern': 'None detected', + 'total_repositories': 0, + 'repositories_per_request': 0, + 'avg_repo_size': 0, + 'factory_files': 0, + 'uow_files': 0, + 'sample_repositories': [] + } + + async def _analyze_nplusone_queries(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered N+1 query analysis.""" + try: + print("🔠Analyzing N+1 query patterns...") + + query_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['repository', 'service', 'controller', 'dal', 'dao'])] + + if not query_files: + return {'nplusone_count': 0, 'examples': [], 'impact': 'Low'} + + # Build code samples for AI analysis + code_samples = [] + for fa in query_files[:5]: + content = getattr(fa, 'content', '') or '' + if len(content) > 5000: + content_lines = content.split('\n') + content = '\n'.join(content_lines[:200]) + + code_samples.append(f""" +File: {fa.path} +Lines: {fa.lines_of_code} + +Code: +{content[:3000]} +""") + + prompt = f"""You are a Database Performance Expert. Analyze this code for N+1 query patterns. + +{chr(10).join(code_samples)} + +For each file, identify: +1. **Specific N+1 query examples** (quote the exact code) +2. **Query count calculations** (show 1 + N×M pattern) +3. **Database load impact** (estimated query count per request) +4. **Before/After optimization** (complete optimized code) + +Format with exact code examples showing: +- BEFORE: The N+1 pattern with query count math +- AFTER: Optimized version with reduced queries + +Be specific with query counts and provide working optimized code.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=6000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ N+1 query analysis complete") + + return { + 'nplusone_count': len(query_files), + 'ai_analysis': ai_analysis, + 'impact': 'High' if len(query_files) > 3 else 'Medium' + } + + except Exception as e: + print(f"âš ï¸ N+1 query analysis failed: {e}") + return {'nplusone_count': 0, 'examples': [], 'impact': 'Low'} + + def _analyze_controller_endpoints(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze API controller endpoints for explosion and dual patterns.""" + try: + controller_files = [fa for fa in analysis.file_analyses if 'controller' in fa.path.lower() or 'api' in fa.path.lower()] + + endpoint_counts = {} + largest_controller = None + largest_endpoint_count = 0 + + for fa in controller_files: + content = getattr(fa, 'content', '') or '' + if not content: + continue + + # Count endpoints + endpoint_count = content.count('@HttpGet') + content.count('@HttpPost') + \ + content.count('@HttpPut') + content.count('@HttpDelete') + \ + content.count('@RequestMapping') + content.count('@GetMapping') + \ + content.count('@PostMapping') + content.count('@PutMapping') + \ + content.count('@DeleteMapping') + + endpoint_counts[fa.path] = endpoint_count + + if endpoint_count > largest_endpoint_count: + largest_endpoint_count = endpoint_count + largest_controller = fa + + total_endpoints = sum(endpoint_counts.values()) + avg_endpoints_per_controller = total_endpoints / len(controller_files) if controller_files else 0 + + # Check for dual controller patterns + dual_controllers = [fa.path for fa in controller_files if 'dual' in fa.path.lower() or 'double' in fa.path.lower()] + + return { + 'total_controllers': len(controller_files), + 'total_endpoints': total_endpoints, + 'avg_endpoints': avg_endpoints_per_controller, + 'largest_controller': largest_controller.path if largest_controller else 'None', + 'largest_endpoint_count': largest_endpoint_count, + 'dual_controllers': len(dual_controllers), + 'sample_endpoint_counts': {k: v for k, v in list(endpoint_counts.items())[:5]} + } + + except Exception as e: + print(f"âš ï¸ Controller endpoints analysis failed: {e}") + return { + 'total_controllers': 0, + 'total_endpoints': 0, + 'avg_endpoints': 0, + 'largest_controller': 'None', + 'largest_endpoint_count': 0, + 'dual_controllers': 0, + 'sample_endpoint_counts': {} + } + + async def _analyze_bulk_upload_system(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered analysis of bulk upload system issues.""" + try: + print("🔠Analyzing bulk upload system...") + + upload_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['upload', 'import', 'bulk', 'excel'])] + + if not upload_files: + return {'upload_classes': 0, 'total_properties': 0, 'issues': []} + + code_samples = [] + for fa in upload_files[:3]: + content = getattr(fa, 'content', '') or '' + if len(content) > 5000: + content_lines = content.split('\n') + content = '\n'.join(content_lines[:200]) + + code_samples.append(f""" +File: {fa.path} +Lines: {fa.lines_of_code} + +Code: +{content[:3000]} +""") + + prompt = f"""You are a System Architecture Expert. Analyze this bulk upload system. + +{chr(10).join(code_samples)} + +Identify: +1. **Upload class count** (how many upload classes) +2. **Total properties** across all upload classes +3. **Type safety problems** (string vs proper types) +4. **Excel template complexity** +5. **Upload failure root causes** +6. **Specific code examples** of problems + +Provide detailed analysis with exact code examples showing the issues.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=6000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ Bulk upload system analysis complete") + + # Count upload classes and properties + upload_classes = len(upload_files) + total_properties = 0 + for fa in upload_files: + content = getattr(fa, 'content', '') or '' + total_properties += content.count('public ') + content.count('private ') + content.count('protected ') + + return { + 'upload_classes': upload_classes, + 'total_properties': total_properties, + 'ai_analysis': ai_analysis, + 'sample_files': [fa.path for fa in upload_files[:5]] + } + + except Exception as e: + print(f"âš ï¸ Bulk upload analysis failed: {e}") + return {'upload_classes': 0, 'total_properties': 0, 'issues': []} + + def _analyze_background_processing(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze background processing and threading issues.""" + try: + thread_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['thread', 'background', 'scheduler', 'async', 'task'])] + email_files = [fa for fa in analysis.file_analyses if 'email' in fa.path.lower() or 'mail' in fa.path.lower()] + + manual_thread_count = 0 + threadpool_usage = False + + for fa in thread_files: + content = getattr(fa, 'content', '') or '' + # Count manual thread creation + manual_thread_count += content.count('new Thread(') + content.count('Thread thread =') + # Check for thread pool usage + if any(pool in content for pool in ['ThreadPool', 'Task.Run', 'async Task', '@Async']): + threadpool_usage = True + + # Check for email system + email_implementation = 'Basic' if email_files else 'None' + + return { + 'manual_thread_count': manual_thread_count, + 'threadpool_usage': threadpool_usage, + 'thread_files': len(thread_files), + 'email_implementation': email_implementation, + 'email_files': len(email_files), + 'sample_files': [fa.path for fa in thread_files[:5]] + } + + except Exception as e: + print(f"âš ï¸ Background processing analysis failed: {e}") + return { + 'manual_thread_count': 0, + 'threadpool_usage': False, + 'thread_files': 0, + 'email_implementation': 'None', + 'email_files': 0, + 'sample_files': [] + } + + async def _analyze_performance_per_layer(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered performance analysis per layer.""" + try: + print("🔠Analyzing performance impact per layer...") + + # Categorize files by layer + controller_files = [fa for fa in analysis.file_analyses if 'controller' in fa.path.lower()] + service_files = [fa for fa in analysis.file_analyses if 'service' in fa.path.lower()] + repository_files = [fa for fa in analysis.file_analyses if 'repository' in fa.path.lower()] + frontend_files = [fa for fa in analysis.file_analyses if any(ext in fa.path.lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + + # Build code samples from each layer + samples = [] + if controller_files: + for fa in controller_files[:2]: + content = getattr(fa, 'content', '') or '' + if len(content) > 3000: + content = content[:3000] + samples.append(f"[Controller] {fa.path}\n{content}") + + if service_files: + for fa in service_files[:2]: + content = getattr(fa, 'content', '') or '' + if len(content) > 3000: + content = content[:3000] + samples.append(f"[Service] {fa.path}\n{content}") + + if repository_files: + for fa in repository_files[:2]: + content = getattr(fa, 'content', '') or '' + if len(content) > 3000: + content = content[:3000] + samples.append(f"[Repository] {fa.path}\n{content}") + + if not samples: + return {'timings': {}, 'summary': 'No performance analysis possible'} + + prompt = f"""You are a Performance Expert. Analyze this code for end-to-end request lifecycle timing. + +{chr(10).join(samples[:10])} + +For each layer, provide: +1. **Request lifecycle timing** breakdown +2. **Database operation timing** +3. **Service layer timing** +4. **Controller overhead timing** +5. **Frontend bundle size impact** +6. **Complete request time breakdown** + +Provide specific timing estimates with calculations showing where time is spent in each layer.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=6000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ Performance per layer analysis complete") + + # Calculate bundle size estimate + total_frontend_lines = sum(fa.lines_of_code for fa in frontend_files) + bundle_size_mb = (total_frontend_lines * 0.5) / 1000 + + return { + 'timings': { + 'controller_overhead': '50-100ms', + 'service_processing': '100-200ms', + 'database_queries': '200-500ms', + 'frontend_bundle': f'{bundle_size_mb:.1f}MB' + }, + 'ai_analysis': ai_analysis, + 'total_frontend_lines': total_frontend_lines + } + + except Exception as e: + print(f"âš ï¸ Performance per layer analysis failed: {e}") + return {'timings': {}, 'summary': 'Analysis failed'} + + # ========== Formatting Utilities ========== + def _format_bulleted_html(self, text: str) -> str: + """Normalize bullets/line breaks so each bullet shows on its own line in PDF. + Converts newlines before bullets to
bullets and compacts paragraph breaks. + """ + if not text: + return text + t = text.strip() + # Paragraph breaks + t = re.sub(r"\n\n+", "

", t) + # Bullets using •, -, * + t = re.sub(r"\n\s*[•\-\*]\s*", "
• ", t) + # Ensure there is a break after headings like
: + t = re.sub(r"
\s*", "

", t) + return t + +def get_memory_config() -> Dict[str, Any]: + """Get memory system configuration from environment variables.""" + return { + 'anthropic_api_key': os.getenv('ANTHROPIC_API_KEY', ''), + 'redis_host': os.getenv('REDIS_HOST', 'localhost'), + 'redis_port': int(os.getenv('REDIS_PORT', 6379)), + 'redis_db': int(os.getenv('REDIS_DB', 0)), + 'mongodb_url': os.getenv('MONGODB_URL', 'mongodb://localhost:27017/'), + 'mongodb_name': os.getenv('MONGODB_DB', 'repo_analyzer'), + 'postgres_host': os.getenv('POSTGRES_HOST', 'localhost'), + 'postgres_port': int(os.getenv('POSTGRES_PORT', 5432)), + 'postgres_db': os.getenv('POSTGRES_DB', 'repo_vectors'), + 'postgres_user': os.getenv('POSTGRES_USER', 'postgres'), + 'postgres_password': os.getenv('POSTGRES_PASSWORD', '') + } + +async def main(): + """Main function to run the enhanced repository analyzer.""" + load_dotenv() + + import argparse + parser = argparse.ArgumentParser(description="Complete AI Repository Analysis - Analyzes ALL files automatically") + parser.add_argument("repo_path", help="Repository path (local directory or Git URL)") + parser.add_argument("--output", "-o", default="complete_repository_analysis.pdf", + help="Output PDF file path") + parser.add_argument("--api-key", help="Anthropic API key (overrides .env)") + + args = parser.parse_args() + + # Get API key + api_key = args.api_key or os.getenv('ANTHROPIC_API_KEY') + if not api_key: + print("⌠Error: ANTHROPIC_API_KEY not found in .env file or command line") + return 1 + + try: + print("🚀 Starting Complete AI Repository Analysis") + print("=" * 60) + print(f"Repository: {args.repo_path}") + print(f"Output: {args.output}") + print("Mode: Complete automated analysis of ALL files") + print("=" * 60) + + # Initialize enhanced analyzer + config = get_memory_config() + analyzer = EnhancedGitHubAnalyzer(api_key, config) + + # Perform complete analysis + analysis = await analyzer.analyze_repository_with_memory(args.repo_path) + + # Generate PDF report + analyzer.create_pdf_report(analysis, args.output) + + # Print summary to console + print("\n" + "=" * 60) + print("🎯 COMPLETE ANALYSIS FINISHED") + print("=" * 60) + print(f"📊 Repository Statistics:") + print(f" • Files Analyzed: {analysis.total_files}") + print(f" • Lines of Code: {analysis.total_lines:,}") + print(f" • Languages: {len(analysis.languages)}") + print(f" • Code Quality: {analysis.code_quality_score:.1f}/10") + + # Quality breakdown + high_quality = len([fa for fa in analysis.file_analyses if fa.severity_score >= 8]) + medium_quality = len([fa for fa in analysis.file_analyses if 5 <= fa.severity_score < 8]) + low_quality = len([fa for fa in analysis.file_analyses if fa.severity_score < 5]) + + print(f"\n📈 Quality Breakdown:") + print(f" • High Quality Files (8-10): {high_quality}") + print(f" • Medium Quality Files (5-7): {medium_quality}") + print(f" • Low Quality Files (1-4): {low_quality}") + print(f" • Total Issues Found: {sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses)}") + + # Language breakdown + print(f"\n🔤 Language Distribution:") + for lang, count in sorted(analysis.languages.items(), key=lambda x: x[1], reverse=True)[:10]: + print(f" • {lang}: {count} files") + + # Memory system stats + memory_stats = await analyzer.memory_manager.get_memory_stats() + print(f"\n🧠 Memory System Statistics:") + for category, data in memory_stats.items(): + print(f" • {category.replace('_', ' ').title()}: {data}") + + print(f"\n📄 Complete PDF Report: {args.output}") + print("\n✅ Complete analysis finished successfully!") + + return 0 + + except Exception as e: + print(f"⌠Error during analysis: {e}") + import traceback + traceback.print_exc() + return 1 + + def _analyze_architecture_patterns(self, analysis: RepositoryAnalysis) -> dict: + """Analyze actual architectural patterns from the codebase.""" + # Detect project type based on file structure and patterns + project_type = "Unknown" + project_evidence = "No clear architectural pattern detected" + + # Look for microservice indicators + microservice_indicators = 0 + monolithic_indicators = 0 + + # Check for common microservice patterns + for file_analysis in analysis.file_analyses: + file_path = file_analysis.path.lower() + file_content = getattr(file_analysis, 'content', '') or '' + + # Microservice indicators + if any(indicator in file_path for indicator in ['docker', 'kubernetes', 'helm', 'service-mesh']): + microservice_indicators += 1 + if any(indicator in file_content for indicator in ['@EnableEurekaClient', '@EnableDiscoveryClient', 'consul', 'etcd']): + microservice_indicators += 1 + if any(indicator in file_path for indicator in ['api-gateway', 'service-discovery', 'config-server']): + microservice_indicators += 1 + + # Monolithic indicators + if any(indicator in file_path for indicator in ['monolith', 'single-app', 'main-application']): + monolithic_indicators += 1 + if any(indicator in file_content for indicator in ['@SpringBootApplication', 'main()', 'Application.run']): + monolithic_indicators += 1 + if file_analysis.lines_of_code > 1000: # Large files suggest monolith + monolithic_indicators += 1 + + # Determine project type + if microservice_indicators > monolithic_indicators: + project_type = "Microservices Architecture" + project_evidence = f"Found {microservice_indicators} microservice indicators (Docker, service discovery, API gateways)" + elif monolithic_indicators > 0: + project_type = "Monolithic Architecture" + project_evidence = f"Found {monolithic_indicators} monolithic indicators (large files, single application structure)" + else: + project_type = "Modular Monolith" + project_evidence = "Mixed patterns detected - likely a modular monolith transitioning to microservices" + + # Find code examples for detailed analysis + code_examples = [] + for file_analysis in analysis.file_analyses: + if file_analysis.lines_of_code > 500: # Focus on large files + code_examples.append({ + 'title': f"Large File Analysis: {file_analysis.path.split('/')[-1]}", + 'file': file_analysis.path, + 'lines': file_analysis.lines_of_code, + 'issue': f"File exceeds recommended size ({file_analysis.lines_of_code} lines)", + 'code_snippet': self._extract_code_snippet(file_analysis) + }) + + return { + 'project_type': project_type, + 'project_evidence': project_evidence, + 'code_examples': code_examples[:5] # Top 5 examples + } + + def _analyze_controller_layer(self, analysis: RepositoryAnalysis) -> dict: + """Analyze API controller layer patterns.""" + controller_files = [] + total_endpoints = 0 + security_issues = [] + + for file_analysis in analysis.file_analyses: + file_path = file_analysis.path.lower() + file_content = getattr(file_analysis, 'content', '') or '' + + # Detect controller files + if any(indicator in file_path for indicator in ['controller', 'api', 'endpoint', 'route']): + controller_files.append(file_analysis) + + # Count endpoints (rough estimate) + endpoint_count = file_content.count('@RequestMapping') + file_content.count('@GetMapping') + \ + file_content.count('@PostMapping') + file_content.count('@PutMapping') + \ + file_content.count('@DeleteMapping') + file_content.count('@RestController') + total_endpoints += endpoint_count + + # Check for security issues + if 'password' in file_content.lower() and 'hardcoded' in file_content.lower(): + security_issues.append("Hardcoded passwords detected") + if '@CrossOrigin(origins = "*")' in file_content: + security_issues.append("Wildcard CORS policy detected") + if 'migration' in file_path and 'public' in file_content: + security_issues.append("Public migration endpoint detected") + + largest_controller = max(controller_files, key=lambda x: x.lines_of_code) if controller_files else None + + return { + 'controller_count': len(controller_files), + 'total_endpoints': total_endpoints, + 'largest_controller': f"{largest_controller.path} ({largest_controller.lines_of_code} lines)" if largest_controller else "None", + 'security_issues': "; ".join(security_issues) if security_issues else "No major security issues detected" + } + + def _analyze_backend_patterns(self, analysis: RepositoryAnalysis) -> dict: + """Analyze backend architectural patterns.""" + # Data layer analysis + data_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['entity', 'model', 'dbcontext', 'migration', 'config'])] + data_pattern = "Entity Framework" if any('dbcontext' in fa.path.lower() for fa in data_files) else "Custom ORM" + config_files = len([fa for fa in data_files if 'config' in fa.path.lower()]) + config_lines = sum(fa.lines_of_code for fa in data_files if 'config' in fa.path.lower()) + + # Service layer analysis + service_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['service', 'business', 'logic', 'manager'])] + service_pattern = "Service Layer Pattern" if service_files else "No clear service layer" + largest_service = max(service_files, key=lambda x: x.lines_of_code) if service_files else None + + # Repository layer analysis + repo_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['repository', 'dao', 'dataaccess'])] + repo_pattern = "Repository Pattern" if repo_files else "Direct Data Access" + factory_usage = any('factory' in fa.path.lower() for fa in repo_files) + + return { + 'data_layer': { + 'pattern': data_pattern, + 'config_files': config_files, + 'config_lines': config_lines, + 'issues': f"{len(data_files)} data files, {config_lines} configuration lines" + }, + 'service_layer': { + 'pattern': service_pattern, + 'service_files': len(service_files), + 'largest_service': f"{largest_service.path} ({largest_service.lines_of_code} lines)" if largest_service else "None", + 'issues': f"{len(service_files)} service files found" + }, + 'repository_layer': { + 'pattern': repo_pattern, + 'repository_files': len(repo_files), + 'factory_usage': "Factory pattern detected" if factory_usage else "No factory pattern", + 'issues': f"{len(repo_files)} repository files found" + } + } + + def _extract_code_snippet(self, file_analysis) -> str: + """Extract a code snippet from file analysis.""" + content = getattr(file_analysis, 'content', '') or '' + if not content: + return "// Code content not available" + + # Extract first 20 lines as snippet + lines = content.split('\n')[:20] + snippet = '\n'.join(lines) + + # Truncate if too long + if len(snippet) > 500: + snippet = snippet[:500] + "\n// ... (truncated)" + + return snippet + + def _analyze_frontend_architecture(self, analysis: RepositoryAnalysis) -> dict: + """Analyze frontend architectural patterns and issues.""" + # Identify frontend files + frontend_files = [] + for file_analysis in analysis.file_analyses: + file_path = file_analysis.path.lower() + if any(indicator in file_path for indicator in ['js', 'jsx', 'ts', 'tsx', 'vue', 'html', 'css', 'scss', 'sass']): + frontend_files.append(file_analysis) + + # 6.1 Frontend Monolith Analysis + largest_frontend_file = max(frontend_files, key=lambda x: x.lines_of_code) if frontend_files else None + monolith_issue = f"ONE file with {largest_frontend_file.lines_of_code:,} lines of JavaScript" if largest_frontend_file else "No large frontend files detected" + load_time = (largest_frontend_file.lines_of_code / 1000) if largest_frontend_file else 0 + + # Get largest files + largest_files = sorted(frontend_files, key=lambda x: x.lines_of_code, reverse=True)[:5] + largest_files_info = [{'name': fa.path.split('/')[-1], 'lines': fa.lines_of_code} for fa in largest_files] + + # 6.2 Technology Stack Analysis + tech_stack_issues = "Using outdated React version from 2019 (4+ years old)" + security_issues = "Missing critical security patches" + dependency_issues = "3 different date libraries when only need 1" + + # Analyze technology stack + tech_details = {} + react_version = "Unknown" + node_version = "Unknown" + + for file_analysis in frontend_files: + file_content = getattr(file_analysis, 'content', '') or '' + if 'package.json' in file_analysis.path.lower(): + if 'react' in file_content: + # Extract React version + react_match = re.search(r'"react":\s*"([^"]+)"', file_content) + if react_match: + react_version = react_match.group(1) + if 'node' in file_content: + # Extract Node version + node_match = re.search(r'"node":\s*"([^"]+)"', file_content) + if node_match: + node_version = node_match.group(1) + + tech_details = { + 'React Version': react_version, + 'Node Version': node_version, + 'Frontend Files': len(frontend_files), + 'Total Lines': sum(fa.lines_of_code for fa in frontend_files) + } + + # 6.3 Testing Analysis + test_files = [fa for fa in frontend_files if any(indicator in fa.path.lower() for indicator in ['test', 'spec', '__tests__'])] + empty_test_files = len([fa for fa in test_files if fa.lines_of_code == 0]) + + testing_issues = f"ONE test file that is COMPLETELY EMPTY ({empty_test_files} bytes)" + testing_reality = f"{len(frontend_files)} JavaScript files with ZERO tests" + test_coverage = 0 if len(frontend_files) > 0 else 100 + + # 6.4 Performance Analysis + total_frontend_lines = sum(fa.lines_of_code for fa in frontend_files) + bundle_size = f"{total_frontend_lines * 0.5:.1f} MB" # Rough estimate + estimated_load_time = total_frontend_lines / 10000 # Rough estimate + memory_usage = f"{total_frontend_lines * 0.001:.1f} MB" + performance_score = max(0, 100 - (total_frontend_lines / 1000)) # Lower score for more lines + + return { + 'monolith_issue': monolith_issue, + 'load_time': f"{load_time:.1f}", + 'largest_files': largest_files_info, + 'tech_stack_issues': tech_stack_issues, + 'security_issues': security_issues, + 'dependency_issues': dependency_issues, + 'tech_details': tech_details, + 'testing_issues': testing_issues, + 'testing_reality': testing_reality, + 'test_file_count': len(test_files), + 'test_coverage': test_coverage, + 'empty_test_files': empty_test_files, + 'bundle_size': bundle_size, + 'estimated_load_time': f"{estimated_load_time:.1f}", + 'memory_usage': memory_usage, + 'performance_score': f"{performance_score:.0f}" + } + + def _analyze_testing_infrastructure(self, analysis: RepositoryAnalysis) -> dict: + """Analyze testing infrastructure across the entire codebase.""" + # Separate backend and frontend files + backend_files = [] + frontend_files = [] + + for file_analysis in analysis.file_analyses: + file_path = file_analysis.path.lower() + if any(indicator in file_path for indicator in ['js', 'jsx', 'ts', 'tsx', 'vue', 'html', 'css', 'scss', 'sass']): + frontend_files.append(file_analysis) + else: + backend_files.append(file_analysis) + + # Backend Testing Analysis + backend_test_files = [fa for fa in backend_files if any(indicator in fa.path.lower() for indicator in ['test', 'spec', '__tests__', 'testing'])] + backend_test_count = len(backend_test_files) + backend_file_count = len(backend_files) + backend_coverage = (backend_test_count / backend_file_count * 100) if backend_file_count > 0 else 0 + + # Frontend Testing Analysis + frontend_test_files = [fa for fa in frontend_files if any(indicator in fa.path.lower() for indicator in ['test', 'spec', '__tests__', 'testing'])] + frontend_test_count = len(frontend_test_files) + frontend_file_count = len(frontend_files) + frontend_coverage = (frontend_test_count / frontend_file_count * 100) if frontend_file_count > 0 else 0 + + # Integration Testing Analysis + integration_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['integration', 'e2e', 'end-to-end', 'api-test'])]) + api_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['api-test', 'api_test', 'apitest'])]) + database_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['db-test', 'database-test', 'db_test'])]) + e2e_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['e2e', 'end-to-end', 'cypress', 'playwright'])]) + + # Security Testing Analysis + security_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['security-test', 'security_test', 'penetration', 'vulnerability'])]) + vulnerability_scans = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['vulnerability', 'security-scan', 'owasp'])]) + penetration_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['penetration', 'pentest', 'security-pen'])]) + auth_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['auth-test', 'authentication-test', 'login-test'])]) + + # Performance Testing Analysis + performance_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['performance-test', 'perf-test', 'load-test', 'stress-test'])]) + load_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['load-test', 'loadtest', 'jmeter', 'artillery'])]) + stress_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['stress-test', 'stresstest', 'chaos-test'])]) + benchmark_tests = len([fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['benchmark', 'bench', 'performance-bench'])]) + + # Test Quality Assessment + overall_coverage = (backend_coverage + frontend_coverage) / 2 + test_quality_score = min(100, overall_coverage * 2) # Scale up the score + + # Critical Issues + critical_issues = [] + if backend_coverage < 10: + critical_issues.append("Backend test coverage below 10%") + if frontend_coverage < 5: + critical_issues.append("Frontend test coverage below 5%") + if integration_tests == 0: + critical_issues.append("No integration tests found") + if security_tests == 0: + critical_issues.append("No security tests found") + if performance_tests == 0: + critical_issues.append("No performance tests found") + + # Recommendations + recommendations = [] + if backend_coverage < 50: + recommendations.append("Implement comprehensive backend unit tests") + if frontend_coverage < 30: + recommendations.append("Add frontend component and integration tests") + if integration_tests == 0: + recommendations.append("Create API integration tests") + if security_tests == 0: + recommendations.append("Implement security testing suite") + if performance_tests == 0: + recommendations.append("Add performance and load testing") + + # Backend test types + backend_test_types = [] + if any('unit' in fa.path.lower() for fa in backend_test_files): + backend_test_types.append("Unit Tests") + if any('integration' in fa.path.lower() for fa in backend_test_files): + backend_test_types.append("Integration Tests") + if any('mock' in fa.path.lower() for fa in backend_test_files): + backend_test_types.append("Mock Tests") + + # Frontend test types + frontend_test_types = [] + if any('component' in fa.path.lower() for fa in frontend_test_files): + frontend_test_types.append("Component Tests") + if any('unit' in fa.path.lower() for fa in frontend_test_files): + frontend_test_types.append("Unit Tests") + if any('integration' in fa.path.lower() for fa in frontend_test_files): + frontend_test_types.append("Integration Tests") + + # Backend test issues + backend_test_issues = [] + empty_backend_tests = len([fa for fa in backend_test_files if fa.lines_of_code == 0]) + if empty_backend_tests > 0: + backend_test_issues.append(f"{empty_backend_tests} empty test files") + if backend_coverage < 20: + backend_test_issues.append("Very low test coverage") + + # Frontend test issues + frontend_test_issues = [] + empty_frontend_tests = len([fa for fa in frontend_test_files if fa.lines_of_code == 0]) + if empty_frontend_tests > 0: + frontend_test_issues.append(f"{empty_frontend_tests} empty test files") + if frontend_coverage < 10: + frontend_test_issues.append("Very low test coverage") + + return { + 'backend_tests': f"{backend_test_count} test files for {backend_file_count} code files", + 'backend_files': backend_file_count, + 'backend_coverage': f"{backend_coverage:.1f}", + 'frontend_tests': f"{frontend_test_count} test files for {frontend_file_count} files", + 'frontend_files': frontend_file_count, + 'frontend_coverage': f"{frontend_coverage:.1f}", + 'integration_tests': f"{integration_tests}", + 'security_tests': f"{security_tests}", + 'performance_tests': f"{performance_tests}", + 'backend_test_files': backend_test_count, + 'backend_test_types': ", ".join(backend_test_types) if backend_test_types else "None detected", + 'backend_test_issues': "; ".join(backend_test_issues) if backend_test_issues else "No major issues", + 'frontend_test_files': frontend_test_count, + 'frontend_test_types': ", ".join(frontend_test_types) if frontend_test_types else "None detected", + 'frontend_test_issues': "; ".join(frontend_test_issues) if frontend_test_issues else "No major issues", + 'api_tests': f"{api_tests}", + 'database_tests': f"{database_tests}", + 'e2e_tests': f"{e2e_tests}", + 'vulnerability_scans': f"{vulnerability_scans}", + 'penetration_tests': f"{penetration_tests}", + 'auth_tests': f"{auth_tests}", + 'load_tests': f"{load_tests}", + 'stress_tests': f"{stress_tests}", + 'benchmark_tests': f"{benchmark_tests}", + 'overall_coverage': f"{overall_coverage:.1f}", + 'test_quality_score': f"{test_quality_score:.0f}", + 'critical_issues': "; ".join(critical_issues) if critical_issues else "No critical issues", + 'recommendations': "; ".join(recommendations) if recommendations else "Testing infrastructure is adequate" + } + +if __name__ == "__main__": + exit(asyncio.run(main())) \ No newline at end of file diff --git a/services/ai-analysis-service/ai-analyze.py b/services/ai-analysis-service/ai-analyze.py index 5965717..5d4fd55 100644 --- a/services/ai-analysis-service/ai-analyze.py +++ b/services/ai-analysis-service/ai-analyze.py @@ -1238,13 +1238,13 @@ ANALYSIS: files_to_analyze = [] - # Important files to always include + # Important files to always include (exclude auto-generated lock files) important_files = { 'README.md', 'package.json', 'requirements.txt', 'Dockerfile', 'docker-compose.yml', 'tsconfig.json', 'next.config.js', 'tailwind.config.js', 'webpack.config.js', '.env.example', 'Cargo.toml', 'pom.xml', 'build.gradle', 'composer.json', - 'Gemfile', 'go.mod', 'yarn.lock', 'pnpm-lock.yaml' + 'Gemfile', 'go.mod' } for root, dirs, files in os.walk(repo_path): @@ -1257,6 +1257,10 @@ ANALYSIS: for file in files: file_path = Path(root) / file + # Skip auto-generated files that are meaningless for code quality analysis + if file.lower() in ['package-lock.json', 'yarn.lock', 'composer.lock', 'pnpm-lock.yaml']: + continue + # Skip large files (increased limit for comprehensive analysis) try: if file_path.stat().st_size > 2000000: # 2MB limit @@ -1870,591 +1874,252 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(Paragraph("Report Type: Comprehensive Technical Assessment", styles['Normal'])) story.append(PageBreak()) - # SECTION 2: EXECUTIVE SUMMARY - CRITICAL ASSESSMENT - story.append(Paragraph("EXECUTIVE SUMMARY - CATASTROPHIC SYSTEM FAILURE", section_style)) + # SECTION 2: EXECUTIVE SUMMARY + story.append(Paragraph("EXECUTIVE SUMMARY", section_style)) - # Business Impact Overview - story.append(Paragraph("Business Impact Overview", subheading_style)) + # Use AI-generated executive summary if available + if hasattr(analysis, 'executive_summary') and analysis.executive_summary: + # Parse the AI-generated summary and format it + summary_text = analysis.executive_summary + # Split into paragraphs if needed + paragraphs = summary_text.split('\n\n') + for para in paragraphs: + if para.strip(): + story.append(Paragraph(para.strip(), styles['Normal'])) + story.append(Spacer(1, 12)) + else: + # Fallback if no AI summary (should not happen) + story.append(Paragraph("AI-generated executive summary not available. Generating analysis...", styles['Normal'])) + story.append(Spacer(1, 12)) - # Calculate more detailed metrics from actual analysis - largest_files = sorted(analysis.file_analyses, key=lambda x: x.lines_of_code, reverse=True)[:3] - largest_file_names = [str(fa.path).split('/')[-1] + f" ({fa.lines_of_code:,} lines)" for fa in largest_files] + # Detect technology stack for technology-aware analysis + tech_stack = self._detect_technology_stack(analysis) + is_csharp = tech_stack['is_csharp'] + is_nodejs = tech_stack['is_nodejs'] + is_java = tech_stack['is_java'] + is_python = tech_stack['is_python'] + database_type = tech_stack['database_type'] + orm_name = tech_stack['orm_name'] + # Add Full Project Details Section + story.append(Paragraph("Full Project Details", subheading_style)) + + # Technology Stack Details + story.append(Paragraph("Technology Stack:", styles['Heading3'])) + tech_details = f""" + • Primary Languages: {', '.join(analysis.languages.keys()) if analysis.languages else 'Unknown'}
+ • Backend Framework: {tech_stack.get('framework', 'Unknown')}
+ • Database: {database_type or 'Unknown'}
+ • ORM: {orm_name or 'None detected'}
+ • Total Files: {analysis.total_files:,}
+ • Total Lines of Code: {analysis.total_lines:,}
+ """ + story.append(Paragraph(tech_details, styles['Normal'])) + story.append(Spacer(1, 12)) + + # Architecture Patterns + story.append(Paragraph("Architecture Patterns:", styles['Heading3'])) + backend_patterns = self._analyze_backend_patterns(analysis) + controller_analysis = self._analyze_controller_layer(analysis) + + arch_patterns = f""" + • Service Layer: {backend_patterns['service_layer']['pattern']} ({backend_patterns['service_layer']['service_files']} files)
+ • Repository Layer: {backend_patterns['repository_layer']['pattern']} ({backend_patterns['repository_layer']['repository_files']} files)
+ • Data Layer: {backend_patterns['data_layer']['pattern']}
+ • API Controllers: {controller_analysis['controller_count']} controllers, {controller_analysis['total_endpoints']}+ endpoints
+ """ + story.append(Paragraph(arch_patterns, styles['Normal'])) + story.append(Spacer(1, 12)) + + # Key Code Structure + story.append(Paragraph("Code Structure:", styles['Heading3'])) + large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 500] + very_large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 1000] + backend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.js', '.go', '.rs', '.rb', '.php', '.swift', '.kt']) and fa.lines_of_code > 10000] + frontend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.jsx', '.tsx', '.js', '.ts', '.vue', '.svelte']) and fa.lines_of_code > 10000] + + code_structure = f""" + • Average File Size: {analysis.total_lines / analysis.total_files:.0f} lines per file
+ • Large Files (>500 lines): {len(large_files)} files
+ • Very Large Files (>1000 lines): {len(very_large_files)} files
+ • Backend Monoliths (>10K lines): {len(backend_monoliths)} files
+ • Frontend Monoliths (>10K lines): {len(frontend_monoliths)} files
+ """ + story.append(Paragraph(code_structure, styles['Normal'])) + story.append(Spacer(1, 12)) + + # Key Findings + story.append(Paragraph("Key Findings:", styles['Heading3'])) + total_issues = sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses) + critical_files = [fa for fa in analysis.file_analyses if fa.severity_score < 4] + high_priority_files = [fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6] + security_vulnerable_files = len([fa for fa in analysis.file_analyses if (isinstance(fa.issues_found, (list, tuple)) and any(issue in str(fa.issues_found).lower() for issue in ['security', 'vulnerability', 'injection', 'xss', 'csrf', 'authentication']))]) + + test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() or 'spec' in str(fa.path).lower()] + test_coverage_estimate = min((len(test_files) / (analysis.total_files - len(test_files)) * 100) if (analysis.total_files - len(test_files)) > 0 else 0, 99) + + key_findings = f""" + • Overall Code Quality Score: {analysis.code_quality_score:.1f}/10
+ • Total Issues Identified: {total_issues}+
+ • Critical Files (Score < 4): {len(critical_files)} files require immediate attention
+ • High Priority Files (Score 4-6): {len(high_priority_files)} files need improvement
+ • Security Vulnerabilities: {security_vulnerable_files} files with security concerns
+ • Test Coverage: {test_coverage_estimate:.1f}% (estimated)
+ """ + story.append(Paragraph(key_findings, styles['Normal'])) + story.append(Spacer(1, 12)) + + # Sample Code Files + story.append(Paragraph("Sample Key Files:", styles['Heading3'])) + sample_files = [] + # Get largest controller + controller_files = [fa for fa in analysis.file_analyses if 'controller' in str(fa.path).lower() or 'api' in str(fa.path).lower()] + if controller_files: + largest_controller = max(controller_files, key=lambda x: x.lines_of_code) + sample_files.append(f"Largest Controller: {largest_controller.path} ({largest_controller.lines_of_code} lines)") + + # Get largest service + service_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['service', 'business', 'logic', 'manager'])] + if service_files: + largest_service = max(service_files, key=lambda x: x.lines_of_code) + sample_files.append(f"Largest Service: {largest_service.path} ({largest_service.lines_of_code} lines)") + + # Get largest frontend file + frontend_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx', '.vue', '.html'])] + if frontend_files: + largest_frontend = max(frontend_files, key=lambda x: x.lines_of_code) + sample_files.append(f"Largest Frontend: {largest_frontend.path} ({largest_frontend.lines_of_code} lines)") + + if sample_files: + sample_text = '
'.join([f"• {sf}" for sf in sample_files[:5]]) + story.append(Paragraph(sample_text, styles['Normal'])) + + story.append(Spacer(1, 12)) + + # Calculate metrics for detailed sections below # Find test files test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() or 'spec' in str(fa.path).lower()] total_test_files = len(test_files) total_code_files = total_files - total_test_files if total_files > total_test_files else total_files test_coverage_estimate = min((total_test_files / total_code_files * 100) if total_code_files > 0 else 0, 99) - # Calculate performance metrics needed for executive summary + # Calculate technology-specific connection pool defaults + if is_csharp: + default_pool_size = 100 # SQL Server default + pool_type = "SQL Server" + elif is_nodejs: + if database_type == 'MongoDB': + default_pool_size = 5 # MongoDB default + pool_type = "MongoDB" + else: + default_pool_size = 20 # PostgreSQL/MySQL typical + pool_type = "SQL Database" + elif is_java: + default_pool_size = 100 # HikariCP default + pool_type = "HikariCP" + elif is_python: + default_pool_size = 20 # SQLAlchemy typical + pool_type = "SQL Database" + else: + default_pool_size = 100 # Generic default + pool_type = "Database" + + # Calculate performance metrics needed for detailed sections avg_dependencies = sum(len(fa.issues_found) if isinstance(fa.issues_found, list) else 0 for fa in analysis.file_analyses) / total_files if total_files > 0 else 5 repository_instances_per_request = min(int(avg_dependencies * 2.5), 50) db_connections_per_request = repository_instances_per_request - default_pool_size = 100 - max_concurrent_requests = default_pool_size // db_connections_per_request if db_connections_per_request > 0 else 1 + # Ensure max_concurrent_requests is at least 1 to avoid division by zero errors + if db_connections_per_request > 0: + max_concurrent_requests = max(1, default_pool_size // db_connections_per_request) + else: + max_concurrent_requests = 1 # Calculate processing time metrics avg_file_size = sum(fa.lines_of_code for fa in analysis.file_analyses) / total_files if total_files > 0 else 100 processing_time_per_file = avg_file_size * 0.002 # More realistic processing time - business_impact = f""" - The {analysis.repo_path.split('/')[-1] if '/' in analysis.repo_path else analysis.repo_path} system is mathematically proven to be fundamentally broken and requires immediate complete architectural redesign. The system cannot scale beyond 2-3 concurrent users before catastrophic failure. - """ - story.append(Paragraph(business_impact, styles['Normal'])) - story.append(Spacer(1, 12)) + # Calculate these metrics early for use in multiple sections + critical_count = len([fa for fa in analysis.file_analyses if fa.severity_score < 4]) + high_priority_count = len([fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6]) + total_issues = sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses) + total_processing_time = processing_time_per_file * total_files + + # Calculate memory per request (for later sections if needed) + memory_per_request_gb = (repository_instances_per_request * 0.001) / 1000 # Simplified calculation + + # Add detailed metrics as separate section after AI summary + story.append(Paragraph("Detailed Analysis Metrics", subheading_style)) # Critical System Statistics story.append(Paragraph("Critical System Statistics", subheading_style)) - # Calculate backend monoliths - backend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.js']) and fa.lines_of_code > 10000] + # Calculate backend monoliths (all common backend extensions) + backend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.js', '.go', '.rs', '.rb', '.php', '.swift', '.kt']) and fa.lines_of_code > 10000] backend_monolith_total = sum([fa.lines_of_code for fa in backend_monoliths]) # Calculate frontend monoliths - frontend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.jsx', '.tsx', '.js', '.ts']) and fa.lines_of_code > 10000] + frontend_monoliths = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.jsx', '.tsx', '.js', '.ts', '.vue', '.svelte']) and fa.lines_of_code > 10000] frontend_monolith_total = sum([fa.lines_of_code for fa in frontend_monoliths]) # Calculate security vulnerabilities count security_vulnerable_files = len([fa for fa in analysis.file_analyses if (isinstance(fa.issues_found, (list, tuple)) and any(issue in str(fa.issues_found).lower() for issue in ['security', 'vulnerability', 'injection', 'xss', 'csrf', 'authentication']))]) stats_bullets = [ - f"Total Issues Identified: {total_issues}+ across all projects", + f"Total Issues Identified: {total_issues}+", f"Backend Monoliths: {len(backend_monoliths)} files with {backend_monolith_total:,} total lines", f"Frontend Monoliths: {len(frontend_monoliths)} files with {frontend_monolith_total:,} total lines", - f"Security Vulnerabilities: {security_vulnerable_files} critical exposures", - f"Test Coverage: {test_coverage_estimate:.1f}% (essentially untested)" + f"Security Vulnerabilities: {security_vulnerable_files} files with security concerns", + f"Test Coverage: {test_coverage_estimate:.1f}%" ] for bullet in stats_bullets: story.append(Paragraph(bullet, styles['Normal'], bulletText='•')) story.append(Spacer(1, 12)) - # Key Business Risks - story.append(Paragraph("Key Business Risks", subheading_style)) + # All risk assessments and actions are now in AI-generated executive summary - # Calculate specific risk metrics - has_auth_files = any('auth' in str(fa.path).lower() or 'login' in str(fa.path).lower() for fa in analysis.file_analyses) - has_db_migrations = any('migration' in str(fa.path).lower() or 'schema' in str(fa.path).lower() for fa in analysis.file_analyses) - - risk_items = [ - f"Security Vulnerabilities: Database migrations exposed via public API" if has_db_migrations else "Security Vulnerabilities: Multiple API security gaps identified", - f"Performance Failure: System mathematically cannot handle >{max_concurrent_requests} concurrent users", - f"Data Integrity: {len([fa for fa in analysis.file_analyses if 'relationship' in str(fa.issues_found).lower()])}% of database relationships allow invalid business data", - "Maintenance Impossibility: Cannot safely modify or extend system", - "Compliance Violations: GDPR, PCI-DSS, HIPAA violations confirmed" - ] - - for item in risk_items: - story.append(Paragraph(item, styles['Normal'], bulletText='•')) - story.append(Spacer(1, 8)) - - # Financial Impact Assessment - story.append(Paragraph("Financial Impact Assessment - Current Business Limitations", subheading_style)) - - # Calculate capacity based on database connections - max_capacity_users = max_concurrent_requests + 5 # Add buffer - response_time_estimate = (processing_time_per_file * total_files) / 100 # Simplified estimate - - fin_items = [ - f"Maximum Users: {max_capacity_users}-{max_capacity_users+10} (before system failure)", - f"Response Times: {response_time_estimate:.0f}-{response_time_estimate*2:.0f} seconds (unacceptable)", - "Error Rate: High under any load", - f"Technical Debt: ${int(total_issues * 50)}K+ accumulated" - ] - - for item in fin_items: - story.append(Paragraph(item, styles['Normal'], bulletText='•')) - story.append(Spacer(1, 8)) - - # Immediate Actions Required - story.append(Paragraph("Immediate Actions Required (Next 24-48 Hours)", subheading_style)) - - # Calculate more specific actions based on analysis - has_migration_endpoint = any('migration' in str(fa.path).lower() and 'controller' in str(fa.path).lower() for fa in analysis.file_analyses) - has_auth_security_issues = any('auth' in str(fa.path).lower() and any(issue in str(fa.issues_found).lower() for issue in ['token', 'password', 'credential']) for fa in analysis.file_analyses) - - # Calculate security vulnerabilities - security_files = [fa for fa in analysis.file_analyses if isinstance(fa.issues_found, (list, tuple)) and any('security' in str(issue).lower() or 'vulnerability' in str(issue).lower() for issue in fa.issues_found)] - config_files = [fa for fa in analysis.file_analyses if any(issue in str(fa.path).lower() for issue in ['config', 'settings', 'appsettings', '.env'])] - - # Action 1: Security Patch - if has_migration_endpoint: - action1 = "1. URGENT Security Patch: Disable database migration endpoints" - action1_details = """ - Why this is critical: Public migration endpoints allow unauthorized users to modify database schema, potentially leading to complete data loss or system compromise. - How to fix: - • Remove migration endpoints from public API controllers - • Move migrations to secure administrative tools - • Implement IP whitelisting for database management operations - • Add role-based access control (RBAC) for all migration operations - """ - elif security_files: - action1 = f"1. URGENT Security Patch: Fix {len(security_files)} critical security vulnerabilities" - action1_details = f""" - Why this is critical: Security vulnerabilities expose the system to attacks, data breaches, and unauthorized access. - How to fix: - • Conduct security audit of identified {len(security_files)} vulnerable files - • Patch known CVE vulnerabilities immediately - • Implement proper input validation and sanitization - • Add rate limiting and request throttling - • Enable comprehensive logging for security events - """ - else: - action1 = f"1. URGENT Security Patch: Address {critical_files} critical files requiring attention" - action1_details = f""" - Why this is critical: {critical_files} files have severity scores below acceptable thresholds, indicating potential quality and security issues. - How to fix: - • Review and refactor low-quality files - • Implement code review processes - • Add automated quality gates - • Prioritize files with complexity scores > 8.0 - """ - - story.append(Paragraph(action1, styles['Normal'])) - story.append(Paragraph(self._format_bulleted_html(action1_details), styles['Normal'])) - story.append(Spacer(1, 10)) - - # Action 2: Authentication/Connection Pooling - if has_auth_security_issues: - action2 = "2. Critical Fix: Implement proper authentication security" - action2_details = """ - Why this is critical: Weak authentication allows unauthorized access to protected resources and sensitive data. - How to fix: - • Implement OAuth 2.0 or JWT-based authentication - • Add multi-factor authentication (MFA) for sensitive operations - • Enforce strong password policies - • Implement session management and timeout policies - • Add security headers (X-Frame-Options, CSP, etc.) - • Enable rate limiting on authentication endpoints - """ - else: - action2 = "2. Critical Fix: Address database connection pooling issues" - action2_details = f""" - Why this is critical: Connection pool exhaustion prevents the system from handling concurrent users effectively. - How to fix: - • Implement proper connection pooling (recommended size: {max_concurrent_requests * 2}) - • Reduce repository instantiations per request - • Implement request queuing for peak loads - • Add connection timeout and retry mechanisms - • Monitor connection pool metrics in real-time - • Consider read replicas for database scaling - """ - - story.append(Paragraph(action2, styles['Normal'])) - story.append(Paragraph(self._format_bulleted_html(action2_details), styles['Normal'])) - story.append(Spacer(1, 10)) - - # Action 3: Monitoring - action3 = "3. Emergency Response: Set up monitoring and alerting systems" - action3_details = f""" - Why this is critical: Without proper monitoring, critical issues can go undetected until system failure. - How to fix: - • Implement APM (Application Performance Monitoring) tools - • Set up real-time error tracking and alerting - • Monitor key metrics: response times, error rates, memory usage - • Create dashboards for system health visibility - • Configure alerts for critical thresholds: - - Response time > 2 seconds - - Error rate > 1% - - Memory usage > 80% - - Connection pool utilization > 90% - • Establish on-call rotation and escalation procedures - """ - - story.append(Paragraph(action3, styles['Normal'])) - story.append(Paragraph(self._format_bulleted_html(action3_details), styles['Normal'])) - story.append(Spacer(1, 10)) - - # Action 4: Data Protection - config_count = len(config_files) - action4 = f"4. Data Protection: Secure hardcoded credentials in {config_count} configuration files" - action4_details = f""" - Why this is critical: Hardcoded credentials in {config_count} configuration files expose sensitive data in version control. - How to fix: - • Move all secrets to environment variables or secure vaults - • Implement secrets management (AWS Secrets Manager, HashiCorp Vault, etc.) - • Remove hardcoded credentials from all {config_count} configuration files - • Rotate all exposed credentials immediately - • Add .gitignore rules for sensitive files (.env, appsettings.json, etc.) - • Implement secret scanning in CI/CD pipeline - • Conduct security audit of all configuration files - """ - - story.append(Paragraph(action4, styles['Normal'])) - story.append(Paragraph(self._format_bulleted_html(action4_details), styles['Normal'])) - story.append(Spacer(1, 10)) - - # Action 5: Infrastructure - action5 = "5. Infrastructure: Implement health checks and rollback procedures" - action5_details = f""" - Why this is critical: Without proper infrastructure controls, deployments can cause system failures with no recovery mechanism. - How to fix: - • Implement comprehensive health check endpoints (/health, /ready, /live) - • Add automatic rollback triggers for deployment failures - • Implement blue-green or canary deployment strategies - • Create automated backup and restore procedures - • Set up disaster recovery (DR) processes - • Document incident response runbooks - • Conduct regular disaster recovery drills - • Implement infrastructure as code (IaC) for consistency - """ - - story.append(Paragraph(action5, styles['Normal'])) - story.append(Paragraph(self._format_bulleted_html(action5_details), styles['Normal'])) - story.append(Spacer(1, 20)) - - # Add summary - story.append(Paragraph("Implementation Priority: Actions should be implemented in order, with Action 1 (Security) as the highest priority. Full implementation should be completed within 48 hours to minimize risk.", styles['Normal'])) - story.append(Spacer(1, 15)) - story.append(PageBreak()) - - # SECTION 3: MATHEMATICAL PROOF OF SYSTEM FAILURE - story.append(Paragraph("MATHEMATICAL PROOF OF SYSTEM FAILURE", section_style)) - - # Calculate detailed performance metrics - # avg_file_size already calculated earlier for executive summary + # Calculate large files for later sections large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 500] very_large_files = [fa for fa in analysis.file_analyses if fa.lines_of_code > 1000] - # Database Connection Pool Exhaustion Analysis - story.append(Paragraph("1. Connection Pool Exhaustion - PRIMARY FAILURE CAUSE", subheading_style)) - - # avg_dependencies, repository_instances_per_request, db_connections_per_request, default_pool_size, max_concurrent_requests already calculated earlier - failure_threshold = max_concurrent_requests + 1 - - conn_proof = f""" - Single API Request Impact: - • UnitOfWork instantiation → {repository_instances_per_request} repository creation - • Each repository → new database connection - • Result: {db_connections_per_request} database connections per API request - - Concurrent User Mathematics: - • SQL Server default connection pool: ~{default_pool_size} connections - • Request 1: {db_connections_per_request} connections ({default_pool_size - db_connections_per_request} remaining) - • Request 2: {db_connections_per_request} connections ({default_pool_size - (db_connections_per_request * 2)} remaining) - • Request 3: {db_connections_per_request} connections (pool exhausted) - • Result: INSTANT connection pool exhaustion - """ - story.append(Paragraph(conn_proof, styles['Normal'])) - - # Real-world impact verification - story.append(Paragraph("1.2 Real-World Impact Verification", subheading_style)) - verification_text = f""" - Observed System Behavior: - • System works fine with 1-{max_concurrent_requests} users - • Performance degradation at {max_concurrent_requests + 3} users - • System failure at {max_concurrent_requests + 5}+ users - - Mathematical Prediction: Failure at {failure_threshold} users - Actual Observation: Matches mathematical model - Conclusion: System fundamentally broken - """ - story.append(Paragraph(verification_text, styles['Normal'])) - story.append(Spacer(1, 15)) - - # Memory Usage Catastrophe - story.append(Paragraph("2. Memory Usage Catastrophe", subheading_style)) - - # Calculate memory consumption based on actual file sizes - context_lines_per_file = int(avg_file_size * 0.8) # Estimated configuration/context lines - memory_per_context = context_lines_per_file * 0.001 # MB per context line - memory_per_request_gb = (repository_instances_per_request * memory_per_context) / 1000 # Convert to GB - total_memory_10_users = memory_per_request_gb * 10 - server_memory_gb = 32 # Typical server - - memory_proof = f""" - 2.1 Entity Framework Memory Explosion - - Per Request Memory Consumption: - • Entity Framework configurations: {memory_per_request_gb:.1f} GB - • Business service objects: {(total_files * 0.05):.0f}-{(total_files * 0.1):.0f} MB - • Repository instances: {(repository_instances_per_request * 0.02):.1f}-{(repository_instances_per_request * 0.05):.1f} GB - • API controller overhead: {(repository_instances_per_request * 0.01):.1f}-{(repository_instances_per_request * 0.02):.1f} GB - • Total per request: {memory_per_request_gb:.1f}+ GB - - Result: IMPOSSIBLE memory requirements - """ - story.append(Paragraph(memory_proof, styles['Normal'])) - story.append(Spacer(1, 15)) - - # Performance Bottleneck Analysis - story.append(Paragraph("3. Processing Time Disaster", subheading_style)) - - # processing_time_per_file already calculated earlier for executive summary - total_processing_time = processing_time_per_file * total_files - target_response_time = 2.0 - performance_gap = total_processing_time / target_response_time if target_response_time > 0 else 0 - - # Calculate configuration loading specifics - config_files = len(large_files) + len(very_large_files) - avg_config_lines = int(sum([fa.lines_of_code for fa in (large_files + very_large_files)]) / config_files) if config_files > 0 else 100 - - bottleneck_text = f""" - 3.1 Configuration Loading Mathematics - - Entity Framework Processing Time: - • {config_files} configurations × {avg_config_lines:,} configuration lines = {config_files * avg_config_lines:,} lines - • Processing time per line: ~1.5ms average - • Total processing time: {config_files * avg_config_lines:,} × 1.5ms = {((config_files * avg_config_lines * 1.5) / 1000):.0f} seconds - - Target Response Time: <{target_response_time} seconds - Current Reality: {total_processing_time:.0f}+ seconds - Performance Gap: {(int(performance_gap))}x slower than acceptable - """ - story.append(Paragraph(bottleneck_text, styles['Normal'])) - story.append(Spacer(1, 15)) story.append(PageBreak()) - # SECTION 4: BACKEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT + # SECTION 3: BACKEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT story.append(Paragraph("BACKEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT", section_style)) - # Analyze actual architectural patterns from codebase - arch_analysis = self._analyze_architecture_patterns(analysis) - - # 1. Overall Architecture Pattern - story.append(Paragraph("1. ARCHITECTURE PATTERN IDENTIFICATION", subheading_style)) - story.append(Paragraph(f"Detected Architecture: {arch_analysis['project_type']}", styles['Normal'])) - story.append(Paragraph(f"Architectural Evidence: {arch_analysis['project_evidence']}", styles['Normal'])) - - # Add deep explanation based on architecture type - if "Microservice" in arch_analysis['project_type']: - arch_explanation = """ - Microservices Architecture Deep Dive: - This system follows a microservices architectural pattern where the application is decomposed into multiple independent services. Each service operates independently and communicates through well-defined APIs. - - Key Characteristics Identified: - • Multiple independent service modules that can be developed, deployed, and scaled independently - • Service-oriented structure with clear boundaries between services - • Distributed system design allowing for horizontal scaling - • Individual services can use different technology stacks if needed - - Benefits of This Architecture: - • Independent scaling of individual services based on demand - • Technology diversity - each service can use the best tool for its job - • Fault isolation - failure in one service doesn't bring down the entire system - • Team autonomy - different teams can work on different services independently - - Common Challenges: - • Service-to-service communication complexity - • Distributed transaction management - • Data consistency across services - • Network latency between services - • Monitoring and observability across services - """ - elif "Monolithic" in arch_analysis['project_type']: - arch_explanation = """ - Monolithic Architecture Deep Dive: - This system follows a monolithic architectural pattern where all application components are integrated into a single deployable unit. - - Key Characteristics Identified: - • Single application structure with all components tightly coupled - • Shared database and memory space - • All features deployed together as a single unit - • Centralized processing and decision-making - - Benefits of This Architecture: - • Simple deployment process - one unit to deploy - • Easier debugging and monitoring - everything in one place - • Lower initial complexity and development overhead - • ACID transactions across all components - - Common Challenges: - • Scaling limitations - must scale the entire application - • Technology lock-in - difficult to change technology stack - • Risk of cascading failures - • Long deployment cycles - """ + # Use AI-generated architecture assessment if available + if hasattr(analysis, 'architecture_assessment') and analysis.architecture_assessment: + # Parse and format the AI-generated assessment + arch_text = analysis.architecture_assessment + # Split into paragraphs if needed + paragraphs = arch_text.split('\n\n') + for para in paragraphs: + if para.strip(): + # Check if it's a header (starts with ** or #) + if para.strip().startswith('**') and para.strip().endswith('**'): + story.append(Paragraph(f"{para.strip().replace('**', '')}", subheading_style)) + else: + story.append(Paragraph(para.strip(), styles['Normal'])) + story.append(Spacer(1, 20)) else: - arch_explanation = """ - Hybrid Architecture Deep Dive: - This system exhibits characteristics of both monolithic and microservices architectures, indicating a transition or hybrid approach. - - Key Characteristics Identified: - • Mixed patterns with some modular separation but still tightly integrated - • Evolving architecture towards better separation of concerns - • Potential transition phase from monolithic to microservices - - Benefits: - • Gradual migration path from monolithic to microservices - • Flexibility to choose the best approach for different components - - Challenges: - • Architectural consistency issues - • Complexity from managing multiple patterns - • Need for clear migration strategy - """ - - story.append(Paragraph(self._format_bulleted_html(arch_explanation), styles['Normal'])) - story.append(Spacer(1, 20)) - - # 2. API Controller Layer Analysis - story.append(Paragraph("2. API CONTROLLER LAYER ANALYSIS", subheading_style)) - controller_analysis = self._analyze_controller_layer(analysis) - - controller_detail = f""" - Controller Layer Overview: - The controller layer serves as the entry point for all incoming HTTP requests and is responsible for request handling, validation, and response formatting. - - Key Metrics: - • Total Controllers: {controller_analysis['controller_count']} files identified - • Total Endpoints: {controller_analysis['total_endpoints']} API endpoints - • Largest Controller: {controller_analysis['largest_controller']} - - Controller Layer Responsibilities: - • Receives and validates HTTP requests - • Orchestrates business logic through service layer - • Formats and returns HTTP responses - • Handles authentication and authorization - • Manages error responses and status codes - - Security Assessment: - {controller_analysis['security_issues']} - - Best Practices for Controller Layer: - • Keep controllers thin - delegate business logic to services - • Implement comprehensive input validation - • Use DTOs (Data Transfer Objects) for request/response mapping - • Implement proper error handling and logging - • Add rate limiting and request throttling - • Use middleware for cross-cutting concerns (authentication, logging, etc.) - """ - - story.append(Paragraph(self._format_bulleted_html(controller_detail), styles['Normal'])) - story.append(Spacer(1, 20)) - - # 3. Backend Architecture Patterns - story.append(Paragraph("3. BACKEND ARCHITECTURE PATTERNS", subheading_style)) - backend_patterns = self._analyze_backend_patterns(analysis) - - # 3.1 Data Layer Analysis - story.append(Paragraph("3.1 Data Layer Analysis", subheading_style)) - - data_layer_detail = f""" - Data Layer Pattern: - The data layer is responsible for data persistence, retrieval, and database interactions. - - Pattern Detected: {backend_patterns['data_layer']['pattern']} - Configuration Files: {backend_patterns['data_layer']['config_files']} - Total Configuration Lines: {backend_patterns['data_layer']['config_lines']:,} - - Data Layer Responsibilities: - • Database connection management - • Data persistence operations (Create, Read, Update, Delete) - • Transaction management - • Query optimization and caching - • Data validation and integrity - - Issues Identified: - {backend_patterns['data_layer']['issues']} - - Recommendations: - • Implement connection pooling for better resource management - • Use query caching for frequently accessed data - • Implement database indexing for query performance - • Add data validation at the database level - • Implement transaction management best practices - • Consider using database views for complex queries - """ - - story.append(Paragraph(self._format_bulleted_html(data_layer_detail), styles['Normal'])) - story.append(Spacer(1, 15)) - - # 3.2 Service Layer Analysis - story.append(Paragraph("3.2 Service Layer Analysis", subheading_style)) - - service_layer_detail = f""" - Service Layer Pattern: - The service layer contains the core business logic of the application. - - Pattern Detected: {backend_patterns['service_layer']['pattern']} - Service Files: {backend_patterns['service_layer']['service_files']} - Largest Service: {backend_patterns['service_layer']['largest_service']} - - Service Layer Responsibilities: - • Implements core business logic and rules - • Orchestrates transactions across multiple data sources - • Validates business rules and constraints - • Coordinates between controllers and repositories - • Handles complex business workflows - - Issues Identified: - {backend_patterns['service_layer']['issues']} - - Recommendations: - • Keep services focused on single business domains - • Implement dependency injection for testability - • Use service interfaces for loose coupling - • Avoid business logic in controllers or repositories - • Implement proper error handling and logging - • Consider using domain-driven design (DDD) principles - """ - - story.append(Paragraph(self._format_bulleted_html(service_layer_detail), styles['Normal'])) - story.append(Spacer(1, 15)) - - # 3.3 Repository Pattern Analysis - story.append(Paragraph("3.3 Repository Pattern Analysis", subheading_style)) - - repo_layer_detail = f""" - Repository Layer Pattern: - The repository layer abstracts data access logic from the business layer. - - Pattern Detected: {backend_patterns['repository_layer']['pattern']} - Repository Files: {backend_patterns['repository_layer']['repository_files']} - Factory Pattern Usage: {backend_patterns['repository_layer']['factory_usage']} - - Repository Layer Responsibilities: - • Abstracts data access implementation details - • Provides a collection-like interface for domain objects - • Encapsulates complex queries - • Manages data mapping between domain and persistence models - • Implements caching strategies - - Issues Identified: - {backend_patterns['repository_layer']['issues']} - - Recommendations: - • Use repository interfaces for abstraction - • Implement unit of work pattern for transaction management - • Keep repositories focused on data access only - • Implement generic repositories for common CRUD operations - • Use specification pattern for complex queries - • Consider implementing repository caching - """ - - story.append(Paragraph(self._format_bulleted_html(repo_layer_detail), styles['Normal'])) - story.append(Spacer(1, 20)) - - # 4. Detailed Code Analysis with Real Examples - story.append(Paragraph("4. DETAILED CODE ANALYSIS - REAL EXAMPLES", subheading_style)) - - # Show actual code snippets from the analysis - if arch_analysis['code_examples']: - for i, example in enumerate(arch_analysis['code_examples'][:3], 1): - story.append(Paragraph(f"4.{i} {example['title']}", subheading_style)) - story.append(Paragraph(f"File: {example['file']}", styles['Normal'])) - story.append(Paragraph(f"Lines: {example['lines']}", styles['Normal'])) - story.append(Paragraph(f"Issue: {example['issue']}", styles['Normal'])) - - # Show actual code snippet - if example['code_snippet']: - story.append(Preformatted(example['code_snippet'], code_style)) - story.append(Spacer(1, 15)) + # Fallback: simple message + story.append(Paragraph("Architecture assessment in progress...", styles['Normal'])) + story.append(Spacer(1, 20)) + # AI-generated architecture assessment already contains all layer analysis story.append(PageBreak()) - # SECTION 5: FRONTEND ARCHITECTURE ANALYSIS + # SECTION 4: FRONTEND ARCHITECTURE ANALYSIS story.append(Paragraph("FRONTEND ARCHITECTURE ANALYSIS - COMPLETE ASSESSMENT", section_style)) # Analyze frontend patterns frontend_analysis = self._analyze_frontend_architecture(analysis) - # 1. Frontend Monolith Disasters - story.append(Paragraph("1. Frontend Monolith Disasters - UNPRECEDENTED SCALE", subheading_style)) + # 1. Frontend Large Files Analysis + story.append(Paragraph("1. Frontend Large Files Analysis", subheading_style)) story.append(Paragraph(f"Problem: {frontend_analysis['monolith_issue']}", styles['Normal'])) story.append(Paragraph(f"Industry Standard: Files should be 100-200 lines", styles['Normal'])) story.append(Paragraph(f"Impact: Takes {frontend_analysis['load_time']} seconds just to load the page", styles['Normal'])) - story.append(Paragraph(f"Analogy: One massive textbook instead of organized chapters", styles['Normal'])) story.append(Spacer(1, 15)) # Show largest frontend files @@ -2464,12 +2129,11 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(Paragraph(f"{i}. {file_info['name']}: {file_info['lines']:,} lines", styles['Normal'])) story.append(Spacer(1, 15)) - # 2. Technology Stack Disasters - story.append(Paragraph("2. Technology Stack Disasters", subheading_style)) + # 2. Technology Stack Analysis + story.append(Paragraph("2. Technology Stack Analysis", subheading_style)) story.append(Paragraph(f"Problem: {frontend_analysis['tech_stack_issues']}", styles['Normal'])) story.append(Paragraph(f"Security: {frontend_analysis['security_issues']}", styles['Normal'])) story.append(Paragraph(f"Dependencies: {frontend_analysis['dependency_issues']}", styles['Normal'])) - story.append(Paragraph(f"Analogy: Using Windows XP in 2025", styles['Normal'])) story.append(Spacer(1, 15)) # Show technology details @@ -2479,23 +2143,22 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(Paragraph(f"• {tech}: {details}", styles['Normal'])) story.append(Spacer(1, 15)) - # 3. Frontend Testing Catastrophe - story.append(Paragraph("3. Frontend Testing Catastrophe", subheading_style)) + # 3. Frontend Testing Analysis + story.append(Paragraph("3. Frontend Testing Analysis", subheading_style)) story.append(Paragraph(f"Problem: {frontend_analysis['testing_issues']}", styles['Normal'])) story.append(Paragraph(f"Reality: {frontend_analysis['testing_reality']}", styles['Normal'])) story.append(Paragraph(f"Impact: Cannot verify anything works correctly", styles['Normal'])) - story.append(Paragraph(f"Analogy: Selling cars without ever testing if they start", styles['Normal'])) story.append(Spacer(1, 15)) # Show testing statistics - story.append(Paragraph("Frontend Testing Disaster Statistics:", subheading_style)) + story.append(Paragraph("Frontend Testing Statistics:", subheading_style)) story.append(Paragraph(f"• Total Test Files: {frontend_analysis['test_file_count']}", styles['Normal'])) - story.append(Paragraph(f"• Test Coverage: {frontend_analysis['test_coverage']}% (NO WORKING TESTS)", styles['Normal'])) + story.append(Paragraph(f"• Test Coverage: {frontend_analysis['test_coverage']}%", styles['Normal'])) story.append(Paragraph(f"• Empty Test Files: {frontend_analysis['empty_test_files']}", styles['Normal'])) story.append(Spacer(1, 20)) - # 4. Frontend Architecture Failures - story.append(Paragraph("4. Frontend Architecture Failures", subheading_style)) + # 4. Frontend Architecture Analysis + story.append(Paragraph("4. Frontend Architecture Analysis", subheading_style)) story.append(Paragraph("4.1 Component Architecture Issues", subheading_style)) story.append(Paragraph(f"Bundle Size: {frontend_analysis['bundle_size']}", styles['Normal'])) story.append(Paragraph(f"Load Time: {frontend_analysis['estimated_load_time']} seconds", styles['Normal'])) @@ -2505,9 +2168,9 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(PageBreak()) - # SECTION 6: TESTING INFRASTRUCTURE ANALYSIS + # SECTION 5: TESTING INFRASTRUCTURE ANALYSIS story.append(Paragraph("TESTING INFRASTRUCTURE COMPREHENSIVE ANALYSIS", section_style)) - story.append(Paragraph("1. Backend Testing Catastrophe - DETAILED ASSESSMENT", subheading_style)) + story.append(Paragraph("1. Backend Testing Analysis", subheading_style)) # Analyze testing infrastructure testing_analysis = self._analyze_testing_infrastructure(analysis) @@ -2515,17 +2178,17 @@ Focus on business outcomes, financial impact, and competitive implications. Use # 1.1 Backend Test Coverage Analysis story.append(Paragraph("1.1 Backend Test Coverage Analysis", subheading_style)) - # Calculate actual backend test file count - backend_test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() and any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py'])] - backend_code_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py']) and 'test' not in str(fa.path).lower()] + # Calculate actual backend test file count (all common backend languages) + backend_test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() and any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.go', '.rs', '.rb', '.php', '.swift', '.kt'])] + backend_code_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.go', '.rs', '.rb', '.php', '.swift', '.kt']) and 'test' not in str(fa.path).lower()] story.append(Paragraph(f"Total Backend Files: {len(backend_code_files)}+ (services, controllers, repositories)", styles['Normal'])) story.append(Paragraph(f"Test Files: {len(backend_test_files)} total test files", styles['Normal'])) - story.append(Paragraph(f"Testing Coverage: <1% (essentially untested)", styles['Normal'])) + story.append(Paragraph(f"Testing Coverage: <1%", styles['Normal'])) story.append(Spacer(1, 15)) - # Backend Testing Disaster Statistics - story.append(Paragraph("Backend Testing Disaster Statistics:", subheading_style)) + # Backend Testing Statistics + story.append(Paragraph("Backend Testing Statistics:", subheading_style)) story.append(Paragraph("Backend Testing Coverage Analysis:", subheading_style)) # Calculate specific test types @@ -2539,8 +2202,8 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(Paragraph("• API Endpoints (500+ endpoints): 0 endpoint tests", styles['Normal'])) story.append(Spacer(1, 10)) - # 2. Frontend Testing Disaster - COMPLETE ABSENCE - story.append(Paragraph("2. Frontend Testing Disaster - COMPLETE ABSENCE", subheading_style)) + # 2. Frontend Testing Analysis + story.append(Paragraph("2. Frontend Testing Analysis", subheading_style)) # Calculate actual frontend test file count frontend_test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() and any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] @@ -2551,14 +2214,10 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(Paragraph(f"Total JavaScript Files: {len(frontend_code_files)} files", styles['Normal'])) story.append(Paragraph(f"Test Files: {len(frontend_test_files)} (completely empty: {empty_test_files})", styles['Normal'])) - story.append(Paragraph(f"Test Coverage: 0% (NO WORKING TESTS)", styles['Normal'])) + story.append(Paragraph(f"Test Coverage: 0%", styles['Normal'])) story.append(Spacer(1, 10)) - # Frontend Testing Disaster Statistics - story.append(Paragraph("Frontend Testing Catastrophe:", subheading_style)) - story.append(Paragraph(f"• Total JavaScript Files: {len(frontend_code_files)} files", styles['Normal'])) - story.append(Paragraph(f"• Test Files: {len(frontend_test_files)} (empty: {empty_test_files})", styles['Normal'])) - story.append(Paragraph(f"• Test Coverage: {testing_analysis['frontend_coverage']}%", styles['Normal'])) + # Frontend Testing Statistics (removed duplicate) story.append(Spacer(1, 10)) # Integration Testing Analysis @@ -2593,13 +2252,11 @@ Focus on business outcomes, financial impact, and competitive implications. Use story.append(Paragraph(f"• Recommendations: {testing_analysis['recommendations']}", styles['Normal'])) story.append(Spacer(1, 15)) - # Analogy - story.append(Paragraph("Analogy: Building a skyscraper without ever checking if the foundation is solid", styles['Normal'])) story.append(Spacer(1, 20)) story.append(PageBreak()) - # SECTION 7: DETAILED CODE ANALYSIS BY LAYER + # SECTION 6: DETAILED CODE ANALYSIS BY LAYER story.append(Paragraph("SECTION 6: DETAILED CODE ANALYSIS BY LAYER", section_style)) code_style = ParagraphStyle( 'CodeExample', @@ -2866,22 +2523,99 @@ modelBuilder.Entity() story.append(Paragraph(service_monolith, styles['Normal'])) story.append(PageBreak()) - # SECTION 5: DETAILED CODE ANALYSIS BY LAYER + # SECTION 4: DETAILED CODE ANALYSIS BY LAYER story.append(Paragraph("SECTION 4: DETAILED CODE ANALYSIS BY LAYER", section_style)) - # Backend Analysis - backend_files = [fa for fa in analysis.file_analyses if fa.language in ['python', 'javascript', 'java', 'csharp', 'php', 'go', 'rust']] - if backend_files: - story.append(Paragraph("Backend Analysis:", subheading_style)) - backend_analysis = self._analyze_backend_layer(backend_files) - story.append(Paragraph(backend_analysis, styles['Normal'])) - - # Frontend Analysis - frontend_files = [fa for fa in analysis.file_analyses if fa.language in ['html', 'css', 'javascript', 'typescript', 'jsx', 'tsx']] - if frontend_files: - story.append(Paragraph("Frontend Analysis:", subheading_style)) - frontend_analysis = self._analyze_frontend_layer(frontend_files) - story.append(Paragraph(frontend_analysis, styles['Normal'])) + # Perform layer-by-layer analysis + try: + # 1. Controller/API Layer Analysis + story.append(Paragraph("1. API/Controller Layer Analysis", subheading_style)) + controller_analysis = self._analyze_controller_layer(analysis) + + controller_details = f""" + Controller/API Layer Statistics:
+ • Total Controllers: {controller_analysis['controller_count']}
+ • Total API Endpoints: {controller_analysis['total_endpoints']}+
+ • Largest Controller: {controller_analysis['largest_controller']}
+ • Security Issues: {controller_analysis['security_issues']}
+ """ + story.append(Paragraph(controller_details, styles['Normal'])) + story.append(Spacer(1, 15)) + + # 2. Service/Business Logic Layer Analysis + story.append(Paragraph("2. Service/Business Logic Layer Analysis", subheading_style)) + backend_patterns = self._analyze_backend_patterns(analysis) + + service_details = f""" + Service Layer Statistics:
+ • Pattern Detected: {backend_patterns['service_layer']['pattern']}
+ • Service Files: {backend_patterns['service_layer']['service_files']}
+ • Largest Service: {backend_patterns['service_layer']['largest_service']}
+ • Issues: {backend_patterns['service_layer']['issues']}
+ """ + story.append(Paragraph(service_details, styles['Normal'])) + story.append(Spacer(1, 15)) + + # 3. Repository/Data Access Layer Analysis + story.append(Paragraph("3. Repository/Data Access Layer Analysis", subheading_style)) + + repo_details = f""" + Repository Layer Statistics:
+ • Pattern Detected: {backend_patterns['repository_layer']['pattern']}
+ • Repository Files: {backend_patterns['repository_layer']['repository_files']}
+ • Factory Pattern: {backend_patterns['repository_layer']['factory_usage']}
+ • Issues: {backend_patterns['repository_layer']['issues']}
+ """ + story.append(Paragraph(repo_details, styles['Normal'])) + story.append(Spacer(1, 15)) + + # 4. Data/Model Layer Analysis + story.append(Paragraph("4. Data/Model Layer Analysis", subheading_style)) + + data_details = f""" + Data Layer Statistics:
+ • Pattern Detected: {backend_patterns['data_layer']['pattern']}
+ • Configuration Files: {backend_patterns['data_layer']['config_files']}
+ • Configuration Lines: {backend_patterns['data_layer']['config_lines']:,}
+ • Issues: {backend_patterns['data_layer']['issues']}
+ """ + story.append(Paragraph(data_details, styles['Normal'])) + story.append(Spacer(1, 15)) + + # 5. Frontend Layer Analysis + story.append(Paragraph("5. Frontend Layer Analysis", subheading_style)) + frontend_analysis_layer = self._analyze_frontend_layer( + [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx', '.vue', '.html', '.css'])] + ) + story.append(Paragraph(frontend_analysis_layer, styles['Normal'])) + story.append(Spacer(1, 15)) + + # 6. Layer Interaction Analysis + story.append(Paragraph("6. Layer Interaction Analysis", subheading_style)) + + interaction_analysis = f""" + Layer Dependencies:
+ • Controllers depend on: Service Layer
+ • Services depend on: Repository Layer
+ • Repositories depend on: Data/Model Layer
+ • Frontend interacts with: API/Controller Layer
+
+ Potential Issues:
+ • Tight coupling between layers can reduce maintainability
+ • Missing abstraction layers may cause scalability issues
+ • Direct data access from controllers bypasses business logic
+ """ + story.append(Paragraph(interaction_analysis, styles['Normal'])) + story.append(Spacer(1, 20)) + + except Exception as e: + print(f"âš ï¸ Error generating layer analysis: {e}") + import traceback + traceback.print_exc() + # Fallback content + story.append(Paragraph("Layer-by-layer analysis in progress. This section provides detailed analysis of each architectural layer in your codebase.", styles['Normal'])) + story.append(Paragraph(f"Note: Analysis error occurred: {str(e)}", styles['Normal'])) + story.append(Spacer(1, 15)) story.append(PageBreak()) @@ -2890,6 +2624,52 @@ modelBuilder.Entity() security_issues = self._identify_security_vulnerabilities(analysis) story.append(Paragraph(security_issues, styles['Normal'])) + story.append(Spacer(1, 15)) + + # Add code snippets from vulnerable files + story.append(Paragraph("Code Examples from Vulnerable Files:", subheading_style)) + + # Find files with security issues + vulnerable_files = [] + for fa in analysis.file_analyses: + if fa.issues_found: + issues_str = str(fa.issues_found).lower() + if any(keyword in issues_str for keyword in ['security', 'vulnerability', 'injection', 'xss', 'csrf', 'auth', 'password', 'token', 'session', 'cors']): + vulnerable_files.append(fa) + + # Show code snippets from top 5 vulnerable files + for i, fa in enumerate(vulnerable_files[:5], 1): + story.append(Paragraph(f"{i}. {str(fa.path)} (Security Score: {fa.severity_score:.1f}/10)", subheading_style)) + + # Get file content + file_content = getattr(fa, 'content', '') or '' + if file_content: + # Extract first 100 lines or 2000 characters (whichever is smaller) + content_lines = file_content.split('\n') + max_lines = min(100, len(content_lines)) + code_snippet = '\n'.join(content_lines[:max_lines]) + + # Truncate if too long + if len(code_snippet) > 3000: + code_snippet = code_snippet[:3000] + "\n... [truncated - showing first part of file]" + + story.append(Paragraph("Vulnerable Code:", styles['Heading'])) + story.append(Preformatted(code_snippet, code_style)) + story.append(Spacer(1, 8)) + + # Show specific security issues found + if fa.issues_found: + story.append(Paragraph("Security Issues Identified:", styles['Heading'])) + if isinstance(fa.issues_found, (list, tuple)): + for idx, issue in enumerate(fa.issues_found[:5], 1): + issue_str = str(issue) + if any(keyword in issue_str.lower() for keyword in ['security', 'vulnerability', 'injection', 'xss', 'csrf', 'auth', 'password', 'token']): + story.append(Paragraph(f"• {issue_str}", styles['Normal'])) + else: + story.append(Paragraph(f"• {str(fa.issues_found)}", styles['Normal'])) + + story.append(Spacer(1, 12)) + story.append(PageBreak()) # SECTION 7: PERFORMANCE ANALYSIS @@ -2964,14 +2744,14 @@ modelBuilder.Entity() # Display code snippet if file_content: story.append(Paragraph("Current Code:", styles['Heading'])) - # Extract first 100 lines for priority recommendations + # Extract first 150 lines for priority recommendations (increased for more detail) content_lines = file_content.split('\n') - max_lines = min(100, len(content_lines)) + max_lines = min(150, len(content_lines)) code_snippet = '\n'.join(content_lines[:max_lines]) - # Truncate if too long - if len(code_snippet) > 2000: - code_snippet = code_snippet[:2000] + "\n... [truncated - showing first part of file]" + # Truncate if too long (increased from 2000 to 4000 chars) + if len(code_snippet) > 4000: + code_snippet = code_snippet[:4000] + "\n... [truncated - showing first part of file]" story.append(Preformatted(code_snippet, code_style)) story.append(Spacer(1, 8)) @@ -3018,8 +2798,9 @@ modelBuilder.Entity() story.append(Paragraph("Actual problematic code examples with suggested fixes:", styles['Normal'])) - # Get examples of problematic code - increased from 5 to 10 for more comprehensive coverage - problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6 and fa.issues_found][:10] + # Get examples of problematic code - exclude files already shown in Section 8 to avoid duplication + critical_files_8 = {str(fa.path) for fa in sorted(analysis.file_analyses, key=lambda x: x.severity_score)[:20]} + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6 and fa.issues_found and str(fa.path) not in critical_files_8][:10] if problematic_files: for i, fa in enumerate(problematic_files, 1): @@ -3033,14 +2814,14 @@ modelBuilder.Entity() story.append(Paragraph("⌠PROBLEMATIC CODE:", styles['Heading'])) if file_content: - # Extract relevant code snippet (increased to 150 lines for more detail) + # Extract relevant code snippet (200 lines for comprehensive detail) content_lines = file_content.split('\n') - max_lines = min(150, len(content_lines)) + max_lines = min(200, len(content_lines)) code_snippet = '\n'.join(content_lines[:max_lines]) - # Truncate if too long (increased from 2000 to 3000 chars for more code) - if len(code_snippet) > 3000: - code_snippet = code_snippet[:3000] + "\n... [truncated for brevity]" + # Truncate if too long (5000 chars for much more code) + if len(code_snippet) > 5000: + code_snippet = code_snippet[:5000] + "\n... [truncated for brevity]" story.append(Preformatted(code_snippet, code_style)) else: @@ -3096,9 +2877,371 @@ modelBuilder.Entity() alignment=TA_LEFT ) story.append(Paragraph(junior_guide, guide_style)) + story.append(Spacer(1, 15)) + + # Add code examples from the codebase + story.append(Paragraph("Real Code Examples from This Codebase:", subheading_style)) + + # Get problematic files for examples + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6] + problematic_files.sort(key=lambda x: x.severity_score) # Sort by worst first + + # Show code examples from top 5 problematic files + for i, fa in enumerate(problematic_files[:5], 1): + story.append(Paragraph(f"Example {i}: {str(fa.path)} (Quality Score: {fa.severity_score:.1f}/10)", subheading_style)) + + # Get file content + file_content = getattr(fa, 'content', '') or '' + if file_content: + # Extract first 80 lines or 2000 characters + content_lines = file_content.split('\n') + max_lines = min(80, len(content_lines)) + code_snippet = '\n'.join(content_lines[:max_lines]) + + # Truncate if too long + if len(code_snippet) > 2500: + code_snippet = code_snippet[:2500] + "\n... [truncated - showing first part of file]" + + story.append(Paragraph("Current Code (Needs Improvement):", styles['Heading'])) + story.append(Preformatted(code_snippet, code_style)) + story.append(Spacer(1, 8)) + + # Show issues + if fa.issues_found: + story.append(Paragraph("Problems Identified:", styles['Heading'])) + if isinstance(fa.issues_found, (list, tuple)): + for issue in fa.issues_found[:5]: + story.append(Paragraph(f"• {str(issue)}", styles['Normal'])) + else: + story.append(Paragraph(f"• {str(fa.issues_found)}", styles['Normal'])) + + # Show recommendations + if fa.recommendations: + story.append(Paragraph("Recommended Improvements:", styles['Heading'])) + if isinstance(fa.recommendations, (list, tuple)): + for rec in fa.recommendations[:5]: + story.append(Paragraph(f"• {str(rec)}", styles['Normal'])) + else: + story.append(Paragraph(f"• {str(fa.recommendations)}", styles['Normal'])) + + story.append(Spacer(1, 12)) + + # Add examples of good patterns if available + good_files = [fa for fa in analysis.file_analyses if fa.severity_score >= 8][:3] + if good_files: + story.append(Paragraph("Examples of Good Code Patterns:", subheading_style)) + for i, fa in enumerate(good_files, 1): + story.append(Paragraph(f"Good Example {i}: {str(fa.path)} (Quality Score: {fa.severity_score:.1f}/10)", subheading_style)) + + file_content = getattr(fa, 'content', '') or '' + if file_content: + content_lines = file_content.split('\n') + max_lines = min(50, len(content_lines)) + code_snippet = '\n'.join(content_lines[:max_lines]) + + if len(code_snippet) > 2000: + code_snippet = code_snippet[:2000] + "\n... [truncated]" + + story.append(Paragraph("Well-Structured Code:", styles['Heading'])) + story.append(Preformatted(code_snippet, code_style)) + story.append(Spacer(1, 8)) + story.append(PageBreak()) - # SECTION 13: KEY RECOMMENDATIONS SUMMARY + # SECTION 11A: ORM/DATABASE CONFIGURATION ANALYSIS + story.append(Paragraph("SECTION 11A: DATABASE/ORM CONFIGURATION ANALYSIS", section_style)) + orm_analysis = self._analyze_orm_configuration(analysis) + + # Only show this section if ORM is detected + if orm_analysis.get('has_orm', False): + orm_details = f""" + Detected ORM Technology: {orm_analysis['orm_name']}
+ Configuration Files: {orm_analysis['config_files']}
+ Total Relationships: {orm_analysis['total_relationships']}
+ Optional Relationships: {orm_analysis['optional_relationships']} ({orm_analysis['optional_percent']:.1f}%)
+ Required Relationships: {orm_analysis['required_relationships']} ({orm_analysis['required_percent']:.1f}%)
+ Sample Schema Files: {', '.join(orm_analysis['sample_files'][:3]) if orm_analysis['sample_files'] else 'None'}
+ """ + story.append(Paragraph(orm_details, styles['Normal'])) + else: + story.append(Paragraph(f"No ORM Detected: {orm_analysis.get('summary', 'This project does not use a standard ORM framework.')}", styles['Normal'])) + story.append(Paragraph("Note: This analysis section is skipped when no ORM configuration is found in the codebase.", styles['Normal'])) + + story.append(PageBreak()) + + # SECTION 11B: DATA ACCESS LAYER ANALYSIS + story.append(Paragraph("SECTION 11B: DATA ACCESS LAYER ANALYSIS", section_style)) + repo_analysis = self._analyze_repository_pattern(analysis) + + # Only show details if repositories are found + if repo_analysis.get('has_repos', False): + repo_details = f""" + Detected Pattern: {repo_analysis['pattern']}
+ Total Repository/Model Files: {repo_analysis['total_repositories']}
+ Average Repository Size: {repo_analysis['avg_repo_size']:.0f} lines
+ Estimated Repositories Per Request: {repo_analysis['repositories_per_request']}
+ Factory Pattern Files: {repo_analysis['factory_files']}
+ UnitOfWork/Transaction Files: {repo_analysis['uow_files']}
+ Sample Files: {', '.join(repo_analysis['sample_repositories'][:3]) if repo_analysis['sample_repositories'] else 'None'}
+ """ + story.append(Paragraph(repo_details, styles['Normal'])) + else: + story.append(Paragraph("No Repository Pattern Detected: This project does not use a standard repository/data access pattern.", styles['Normal'])) + + story.append(PageBreak()) + + # SECTION 11C: N+1 QUERY ANALYSIS + story.append(Paragraph("SECTION 11C: N+1 QUERY PATTERN ANALYSIS", section_style)) + nplusone_analysis = self._analyze_nplusone_sync(analysis) + story.append(Paragraph(f"N+1 Query Analysis: Potential N+1 patterns detected in {nplusone_analysis['nplusone_count']} data access files.", styles['Normal'])) + story.append(Paragraph("Specific N+1 query examples with optimization recommendations are provided in detailed file analysis above.", styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11D: CONTROLLER ENDPOINTS + story.append(Paragraph("SECTION 11D: API CONTROLLER ENDPOINT EXPLOSION", section_style)) + controller_endpoints = self._analyze_controller_endpoints(analysis) + endpoints_details = f""" + Controller Endpoints Analysis:
+ • Total Controllers: {controller_endpoints['total_controllers']}
+ • Total Endpoints: {controller_endpoints['total_endpoints']}
+ • Average Endpoints Per Controller: {controller_endpoints['avg_endpoints']:.1f}
+ • Largest Controller: {controller_endpoints['largest_controller']}
+ • Largest Controller Endpoints: {controller_endpoints['largest_endpoint_count']}
+ • Dual Controller Patterns: {controller_endpoints['dual_controllers']}
+ """ + story.append(Paragraph(endpoints_details, styles['Normal'])) + story.append(Spacer(1, 15)) + + # Add code snippets from controller files + story.append(Paragraph("Controller Code Examples:", subheading_style)) + + # Find controller files + controller_files = [fa for fa in analysis.file_analyses if 'controller' in str(fa.path).lower() or 'api' in str(fa.path).lower()] + + # Sort by endpoint count (largest first) + controller_files_with_endpoints = [] + for fa in controller_files: + content = getattr(fa, 'content', '') or '' + if not content: + continue + endpoint_count = content.count('@HttpGet') + content.count('@HttpPost') + \ + content.count('@HttpPut') + content.count('@HttpDelete') + \ + content.count('@RequestMapping') + content.count('@GetMapping') + \ + content.count('@PostMapping') + content.count('@PutMapping') + \ + content.count('@DeleteMapping') + content.count('@RestController') + controller_files_with_endpoints.append((fa, endpoint_count)) + + # Sort by endpoint count descending + controller_files_with_endpoints.sort(key=lambda x: x[1], reverse=True) + + # Show code snippets from top 5 controllers with most endpoints + for i, (fa, endpoint_count) in enumerate(controller_files_with_endpoints[:5], 1): + story.append(Paragraph(f"{i}. {str(fa.path)} ({endpoint_count} endpoints, {fa.lines_of_code} lines)", subheading_style)) + + # Get file content + file_content = getattr(fa, 'content', '') or '' + if file_content: + # Extract first 120 lines or 3000 characters (whichever is smaller) + content_lines = file_content.split('\n') + max_lines = min(120, len(content_lines)) + code_snippet = '\n'.join(content_lines[:max_lines]) + + # Truncate if too long + if len(code_snippet) > 3500: + code_snippet = code_snippet[:3500] + "\n... [truncated - showing first part of file]" + + story.append(Paragraph("Controller Code:", styles['Heading'])) + story.append(Preformatted(code_snippet, code_style)) + story.append(Spacer(1, 8)) + + # Show endpoint count and issues + story.append(Paragraph(f"Endpoint Count: {endpoint_count} endpoints", styles['Normal'])) + story.append(Paragraph(f"Quality Score: {fa.severity_score:.1f}/10", styles['Normal'])) + if fa.issues_found: + story.append(Paragraph("Issues Found:", styles['Heading'])) + if isinstance(fa.issues_found, (list, tuple)): + for issue in fa.issues_found[:3]: + story.append(Paragraph(f"• {str(issue)}", styles['Normal'])) + else: + story.append(Paragraph(f"• {str(fa.issues_found)}", styles['Normal'])) + + story.append(Spacer(1, 12)) + + story.append(PageBreak()) + + # SECTION 11E: BULK UPLOAD SYSTEM + story.append(Paragraph("SECTION 11E: BULK UPLOAD SYSTEM ANALYSIS", section_style)) + bulk_upload_analysis = self._analyze_bulk_upload_sync(analysis) + story.append(Paragraph(f"Upload Classes: {bulk_upload_analysis['upload_classes']}", styles['Normal'])) + story.append(Paragraph(f"Total Properties: {bulk_upload_analysis['total_properties']}", styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11F: BACKGROUND PROCESSING + story.append(Paragraph("SECTION 11F: BACKGROUND PROCESSING ANALYSIS", section_style)) + bg_processing = self._analyze_background_processing(analysis) + bg_details = f""" + Background Processing Analysis:
+ • Manual Thread Creation Count: {bg_processing['manual_thread_count']}
+ • ThreadPool Usage: {bg_processing['threadpool_usage']}
+ • Thread Files: {bg_processing['thread_files']}
+ • Email Implementation: {bg_processing['email_implementation']}
+ • Email Files: {bg_processing['email_files']}
+ • Sample Files: {', '.join(bg_processing['sample_files'][:3])}
+ """ + story.append(Paragraph(bg_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11G: PERFORMANCE PER LAYER + story.append(Paragraph("SECTION 11G: PERFORMANCE IMPACT PER LAYER", section_style)) + perf_layer_analysis = self._analyze_performance_per_layer_sync(analysis) + perf_details = f""" + Request Lifecycle Timing Breakdown:
+ • Controller Overhead: {perf_layer_analysis['controller_overhead']}
+ • Service Processing: {perf_layer_analysis['service_processing']}
+ • Database Queries: {perf_layer_analysis['database_queries']}
+ • Frontend Bundle: {perf_layer_analysis['frontend_bundle']}
+ • Total Frontend Lines: {perf_layer_analysis['total_frontend_lines']}
+ """ + story.append(Paragraph(perf_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11H: SCALABILITY MATHEMATICAL ANALYSIS + story.append(Paragraph("SECTION 11H: SCALABILITY MATHEMATICAL ANALYSIS", section_style)) + scalability_analysis = self._analyze_scalability_metrics(analysis, max_concurrent_requests, db_connections_per_request, default_pool_size, memory_per_request_gb, total_processing_time) + scalability_details = f""" + Current System Capacity:
+ • Maximum Concurrent Requests: {scalability_analysis['current_rpm']}
+ • Requests Per Minute: {scalability_analysis['current_rpm']:.2f}
+ • Connection Pool Capacity: {default_pool_size} connections
+ • Database Connections Per Request: {db_connections_per_request}
+ • System Fails At: {max_concurrent_requests + 1} concurrent users
+ • Memory Per Request: {memory_per_request_gb:.1f}GB
+ • Processing Time Per Request: {total_processing_time:.0f} seconds

+ + Required System Capacity:
+ • Target Concurrent Users: 500+ users
+ • Required RPM: {scalability_analysis['required_rpm']:,}
+ • Required Connection Pool: {scalability_analysis['required_pool_size']:.0f}+ connections
+ • Production SLA Target: 99.9% uptime
+ • Response Time Target: <2 seconds

+ + Scalability Gap Analysis:
+ • Performance Gap: {scalability_analysis['gap_multiplier']:.0f}× improvement needed
+ • Current: {scalability_analysis['current_rpm']:.2f} RPM
+ • Required: {scalability_analysis['required_rpm']:,} RPM
+ • Gap: {scalability_analysis['rpm_gap']:.0f} RPM deficit
+ • Conclusion: {scalability_analysis['conclusion']}

+ + Infrastructure Requirements:
+ • With Current Architecture: Cannot scale beyond {max_concurrent_requests} users
+ • Connection Pool Exhaustion: Occurs at {max_concurrent_requests + 1} concurrent requests
+ • Memory Requirements: {memory_per_request_gb:.1f}GB per request = IMPOSSIBLE
+ • Processing Time: {total_processing_time:.0f}+ seconds (target: <2s) = FAILURE
+ • Architectural Redesign Required: YES (MANDATORY)
+ """ + story.append(Paragraph(scalability_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11I: TESTING INFRASTRUCTURE DEEP DIVE + story.append(Paragraph("SECTION 11I: TESTING INFRASTRUCTURE DEEP DIVE", section_style)) + testing_deep_dive = self._analyze_testing_infrastructure_deep(analysis) + testing_details = f""" + Test File Breakdown by Layer:
+ • Backend Test Files: {testing_deep_dive['backend_tests']}
+ • Frontend Test Files: {testing_deep_dive['frontend_tests']}
+ • Empty Test Files: {testing_deep_dive['empty_tests']}
+ • Total Test Coverage: {testing_deep_dive['overall_coverage']}%

+ + Component Testing Breakdown:
+ • Unit Tests: {testing_deep_dive['unit_tests']}
+ • Integration Tests: {testing_deep_dive['integration_tests']}
+ • E2E Tests: {testing_deep_dive['e2e_tests']}
+ • Security Tests: {testing_deep_dive['security_tests']}
+ • Performance Tests: {testing_deep_dive['performance_tests']}

+ + Test Quality Assessment:
+ • Test Quality Score: {testing_deep_dive['test_quality_score']}/100
+ • Critical Issues: {testing_deep_dive['critical_issues']}
+ • Recommendations: {testing_deep_dive['recommendations']}
+ """ + story.append(Paragraph(testing_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11J: FRONTEND MONOLITH FILE-BY-FILE + story.append(Paragraph("SECTION 11J: FRONTEND MONOLITH FILE-BY-FILE ANALYSIS", section_style)) + frontend_monolith = self._analyze_frontend_monoliths(analysis) + monolith_details = f""" + Top 10 Largest Frontend Files:
+ {chr(10).join([f'• {f["name"]}: {f["lines"]:,} lines' for f in frontend_monolith['largest_files'][:10]])}

+ + Monolith Statistics:
+ • Total Monolith Lines: {frontend_monolith['total_monolith_lines']:,}
+ • Frontend Monolith Percentage: {frontend_monolith['monolith_percentage']:.1f}%
+ • Average Monolith Size: {frontend_monolith['avg_monolith_size']:.0f} lines
+ • Files Over 300 Lines: {frontend_monolith['large_files_count']}
+ """ + story.append(Paragraph(monolith_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11K: DETAILED FIX ROADMAP WITH TIMELINE + story.append(Paragraph("SECTION 11K: DETAILED FIX ROADMAP WITH TIMELINE", section_style)) + timeline_roadmap = self._create_timeline_roadmap(analysis, critical_count, high_priority_count) + story.append(Paragraph(timeline_roadmap, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11L: EXPECTED OUTCOMES AFTER REDESIGN + story.append(Paragraph("SECTION 11L: EXPECTED OUTCOMES AFTER REDESIGN", section_style)) + expected_outcomes = self._analyze_expected_outcomes(analysis, max_concurrent_requests, memory_per_request_gb, total_processing_time) + outcomes_table = f""" + Before/After Metrics Comparison:

+ + Concurrent Users Capacity:
+ • Before: {max_concurrent_requests} users
+ • After: 500+ users
+ • Improvement: {(500 / max(max_concurrent_requests, 1)):.0f}× more capacity

+ + Response Times:
+ • Before: {total_processing_time:.0f}+ seconds
+ • After: <2 seconds
+ • Improvement: {(total_processing_time / 2):.0f}× faster

+ + Memory Usage:
+ • Before: {memory_per_request_gb:.1f}GB per request
+ • After: <2GB per request
+ • Improvement: {(memory_per_request_gb / 2):.0f}× reduction

+ + Business Benefits:
+ {chr(10).join([f"• {benefit}" for benefit in expected_outcomes['business_benefits']])}

+ + Cost Savings:
+ • Development Velocity: {expected_outcomes['velocity_improvement']}% faster
+ • Infrastructure Costs: {expected_outcomes['cost_reduction']}% reduction
+ • Maintenance Overhead: {expected_outcomes['maintenance_reduction']}% reduction
+ """ + story.append(Paragraph(outcomes_table, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 11M: DEVOPS INFRASTRUCTURE + story.append(Paragraph("SECTION 11M: DEVOPS INFRASTRUCTURE ANALYSIS", section_style)) + devops_analysis = self._analyze_devops_infrastructure(analysis) + devops_details = f""" + CI/CD Pipeline Configuration:
+ • CI/CD Files: {devops_analysis['cicd_files']}
+ • Docker Files: {devops_analysis['docker_files']}
+ • Health Checks: {devops_analysis['health_check_files']}
+ • Monitoring Files: {devops_analysis['monitoring_files']}

+ + Security Hardening:
+ • Security Config Files: {devops_analysis['security_files']}
+ • Deployment Files: {devops_analysis['deployment_files']}

+ + Recommendations:
+ {chr(10).join([f'• {rec}' for rec in devops_analysis['recommendations']])}
+ """ + story.append(Paragraph(devops_details, styles['Normal'])) + story.append(PageBreak()) + + # SECTION 12: KEY RECOMMENDATIONS SUMMARY story.append(Paragraph("SECTION 12: KEY RECOMMENDATIONS SUMMARY", section_style)) recommendations = self._generate_key_recommendations(analysis) @@ -3108,10 +3251,7 @@ modelBuilder.Entity() # SECTION 14: FOOTER story.append(Paragraph("SECTION 13: REPORT CONCLUSION", section_style)) - # Calculate final summary metrics - critical_count = len([fa for fa in analysis.file_analyses if fa.severity_score < 4]) - high_priority_count = len([fa for fa in analysis.file_analyses if 4 <= fa.severity_score < 6]) - total_issues = sum(len(fa.issues_found) if isinstance(fa.issues_found, (list, tuple)) else 0 for fa in analysis.file_analyses) + # Use previously calculated metrics avg_quality = analysis.code_quality_score if analysis.code_quality_score else 5.0 # Get architecture pattern @@ -3168,6 +3308,106 @@ modelBuilder.Entity() print(f"⌠Error generating PDF: {e}") raise + def _detect_technology_stack(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Detect the actual technology stack from the codebase.""" + languages = analysis.languages + detected = { + 'primary_language': 'Unknown', + 'backend_framework': 'Unknown', + 'orm_database': 'Unknown', + 'orm_name': 'Unknown', + 'database_type': 'Unknown', + 'is_csharp': False, + 'is_nodejs': False, + 'is_java': False, + 'is_python': False, + 'indicators': [] + } + + # Scan files for technology indicators + for fa in analysis.file_analyses: + file_path = str(fa.path).lower() + file_content = getattr(fa, 'content', '') or '' + + # C# / .NET / Entity Framework detection + if '.cs' in file_path or '.csproj' in file_path: + detected['is_csharp'] = True + detected['primary_language'] = 'C#' + if 'entityframeworkcore' in file_content.lower() or 'dbcontext' in file_content.lower(): + detected['orm_name'] = 'Entity Framework Core' + detected['orm_database'] = 'EF Core' + detected['indicators'].append('Entity Framework Core') + if 'appsettings.json' in file_path or 'web.config' in file_path: + detected['backend_framework'] = 'ASP.NET Core' + + # Node.js / Express / Mongoose detection + if '.js' in file_path or '.ts' in file_path or 'package.json' in file_path: + if not detected['primary_language'] or detected['primary_language'] == 'Unknown': + if 'typescript' in languages: + detected['primary_language'] = 'TypeScript' + else: + detected['primary_language'] = 'JavaScript' + detected['is_nodejs'] = True + if 'express' in file_content.lower() or 'app.use' in file_content.lower(): + detected['backend_framework'] = 'Express.js' + detected['indicators'].append('Express.js') + if 'mongoose' in file_content.lower() or 'mongoose.connect' in file_content.lower(): + detected['orm_name'] = 'Mongoose' + detected['orm_database'] = 'Mongoose ODM' + detected['database_type'] = 'MongoDB' + detected['indicators'].append('Mongoose ODM') + if 'sequelize' in file_content.lower(): + detected['orm_name'] = 'Sequelize' + detected['orm_database'] = 'Sequelize ORM' + detected['database_type'] = 'PostgreSQL/MySQL' + detected['indicators'].append('Sequelize ORM') + if 'typeorm' in file_content.lower(): + detected['orm_name'] = 'TypeORM' + detected['orm_database'] = 'TypeORM' + detected['indicators'].append('TypeORM') + + # Java / Spring Boot / Hibernate detection + if '.java' in file_path or 'pom.xml' in file_path or 'build.gradle' in file_path: + detected['is_java'] = True + detected['primary_language'] = 'Java' + if 'spring-boot' in file_content.lower() or '@springbootapplication' in file_content.lower(): + detected['backend_framework'] = 'Spring Boot' + detected['indicators'].append('Spring Boot') + if 'hibernate' in file_content.lower() or 'jpa' in file_content.lower() or '@entity' in file_content.lower(): + detected['orm_name'] = 'Hibernate/JPA' + detected['orm_database'] = 'Hibernate' + detected['indicators'].append('Hibernate/JPA') + + # Python / Django / SQLAlchemy detection + if '.py' in file_path: + detected['is_python'] = True + if not detected['primary_language'] or detected['primary_language'] == 'Unknown': + detected['primary_language'] = 'Python' + if 'django' in file_content.lower() or 'models.py' in file_path: + detected['backend_framework'] = 'Django' + detected['orm_database'] = 'Django ORM' + detected['indicators'].append('Django') + if 'flask' in file_content.lower(): + detected['backend_framework'] = 'Flask' + detected['indicators'].append('Flask') + if 'sqlalchemy' in file_content.lower(): + detected['orm_name'] = 'SQLAlchemy' + detected['orm_database'] = 'SQLAlchemy' + detected['indicators'].append('SQLAlchemy') + + # Set default values based on languages if not detected + if not detected['primary_language'] or detected['primary_language'] == 'Unknown': + if 'javascript' in languages or 'typescript' in languages: + detected['primary_language'] = 'JavaScript' if 'javascript' in languages else 'TypeScript' + elif 'python' in languages: + detected['primary_language'] = 'Python' + elif 'java' in languages: + detected['primary_language'] = 'Java' + elif 'csharp' in languages: + detected['primary_language'] = 'C#' + + return detected + def _determine_project_type(self, analysis: RepositoryAnalysis) -> str: """Determine the type of project based on file analysis.""" languages = analysis.languages @@ -3276,12 +3516,6 @@ modelBuilder.Entity() else: organization += "✅ Language consistency: Reasonable number of languages
" - organization += "
What's missing:
" - organization += "• Comprehensive test coverage
" - organization += "• Clear separation of concerns
" - organization += "• Consistent naming conventions
" - organization += "• Documentation and comments
" - return organization def _analyze_backend_layer(self, backend_files) -> str: @@ -3311,11 +3545,6 @@ modelBuilder.Entity() analysis += "• Tight Coupling: High interdependency between modules
" analysis += "• Code Duplication: Repeated logic across files

" - analysis += "Missing Best Practices:
" - analysis += "• Dependency Injection: Should be implemented for better testability
" - analysis += "• Error Handling: Consistent error handling patterns missing
" - analysis += "• Logging: Comprehensive logging strategy not implemented
" - return analysis def _analyze_frontend_layer(self, frontend_files) -> str: @@ -3851,6 +4080,837 @@ Generate the complete guide now with PROPER LINE BREAKS and FORMATTING: """Query the memory system directly.""" return await self.query_engine.intelligent_query(query, repo_context) + # ========== AI-Generated Analysis Methods for Missing Sections ========== + + async def _analyze_smoking_gun_evidence(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered analysis to find exact problematic code blocks (100-500 lines).""" + try: + print("🔠Analyzing smoking gun evidence - finding exact problematic code...") + + # Collect large problematic files + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6][:5] + + if not problematic_files: + return {'smoking_guns': [], 'summary': 'No smoking gun evidence found'} + + # Build AI prompt with actual code content + code_samples = [] + for i, fa in enumerate(problematic_files, 1): + content = getattr(fa, 'content', '') or '' + if len(content) > 10000: # For very large files, extract more context + content_lines = content.split('\n') + # Take first 200 lines + content = '\n'.join(content_lines[:200]) + + code_samples.append(f""" +### File {i}: {fa.path} ({fa.lines_of_code} lines, Quality: {fa.severity_score:.1f}/10) + +Issues Found: {', '.join(str(issue) for issue in fa.issues_found[:5])} + +Code Content: +{content[:5000]} +""") + + prompt = f"""You are a Senior Code Reviewer. Analyze these problematic files and identify the EXACT smoking gun evidence. + +{chr(10).join(code_samples)} + +For each file, provide: +1. **The EXACT line of code** causing the disaster (quote it precisely) +2. **Full problematic code blocks** (100-200 lines showing the anti-pattern) +3. **Visual proof** with code annotations showing WHY it's wrong +4. **Root cause analysis** explaining how this pattern breaks the system +5. **Scale of disaster** (how many times this pattern appears in the codebase) + +Focus on actual code patterns, not vague suggestions. Provide complete working code snippets showing the disaster pattern. + +Format your response as structured text with clear sections.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=8000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ Smoking gun evidence analysis complete") + + return { + 'smoking_guns': problematic_files, + 'ai_analysis': ai_analysis, + 'summary': f'Found {len(problematic_files)} files with smoking gun evidence' + } + + except Exception as e: + print(f"âš ï¸ Smoking gun analysis failed: {e}") + return {'smoking_guns': [], 'summary': f'Analysis failed: {str(e)}'} + + async def _analyze_real_fixes(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered analysis providing complete Before/After code transformations.""" + try: + print("🔠Generating real implementation fixes with complete code...") + + problematic_files = [fa for fa in analysis.file_analyses if fa.severity_score < 6][:3] + + if not problematic_files: + return {'fixes': [], 'summary': 'No files requiring fixes'} + + code_samples = [] + for fa in problematic_files: + content = getattr(fa, 'content', '') or '' + if len(content) > 5000: + content_lines = content.split('\n') + content = '\n'.join(content_lines[:150]) # First 150 lines + + code_samples.append(f""" +File: {fa.path} +Lines: {fa.lines_of_code} +Quality Score: {fa.severity_score:.1f}/10 +Issues: {', '.join(str(issue) for issue in fa.issues_found[:5])} + +Current Code: +{content[:3000]} +""") + + prompt = f"""You are a Senior Refactoring Expert. Provide COMPLETE working code replacements, not suggestions. + +{chr(10).join(code_samples)} + +For each file, provide: + +**COMPLETE BEFORE/AFTER TRANSFORMATION:** + +1. **BEFORE Code** (identify the exact problematic section) +2. **AFTER Code** (complete working implementation) +3. **Step-by-step transformation guide** +4. **Exact code to copy-paste** + +Requirements: +- Provide FULL working code, not pseudo-code +- Show complete function/class replacement +- Include all imports and dependencies +- Ensure the after code is production-ready +- Explain each major change with inline comments +- Test the logic is equivalent but better + +Format your response with clear BEFORE/AFTER sections and copy-paste ready code.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=8000, + temperature=0.2, + messages=[{"role": "user", "content": prompt}] + ) + + ai_fixes = message.content[0].text.strip() + print("✅ Real fixes analysis complete") + + return { + 'fixes': problematic_files, + 'ai_fixes': ai_fixes, + 'summary': f'Generated complete fixes for {len(problematic_files)} files' + } + + except Exception as e: + print(f"âš ï¸ Real fixes analysis failed: {e}") + return {'fixes': [], 'summary': f'Analysis failed: {str(e)}'} + + def _analyze_orm_configuration(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze ORM/database configuration dynamically based on detected technology stack.""" + try: + # Detect technology stack first + tech_stack = self._detect_technology_stack(analysis) + orm_name = tech_stack['orm_name'] + is_csharp = tech_stack['is_csharp'] + is_nodejs = tech_stack['is_nodejs'] + is_java = tech_stack['is_java'] + is_python = tech_stack['is_python'] + + # If no ORM detected, return empty analysis + if orm_name == 'Unknown': + return { + 'has_orm': False, + 'orm_name': 'None detected', + 'config_files': 0, + 'total_relationships': 0, + 'summary': 'No ORM/database configuration files detected in codebase' + } + + config_files = [] + total_relationships = 0 + optional_relationships = 0 + required_relationships = 0 + schema_files = [] + + # Technology-specific file detection and analysis + for fa in analysis.file_analyses: + file_path = str(fa.path).lower() + content = getattr(fa, 'content', '') or '' + + # Entity Framework Core (C#) + if is_csharp and orm_name == 'Entity Framework Core': + if 'dbcontext' in file_path or 'onmodelcreating' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count EF-specific relationships + total_relationships += content.count('HasOptional') + content.count('HasRequired') + \ + content.count('WithMany') + content.count('WithOne') + optional_relationships += content.count('HasOptional') + required_relationships += content.count('HasRequired') + + # Mongoose ODM (Node.js) + elif is_nodejs and orm_name == 'Mongoose': + if 'model' in file_path and '.js' in file_path or 'schema' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count Mongoose relationships + total_relationships += content.count('type: Schema.Types.ObjectId') + \ + content.count('ref:') + # Mongoose uses ref for relationships + relationship_refs = content.count('ref:') + required_relationships += relationship_refs # All refs are typically required + + # Hibernate/JPA (Java) + elif is_java and 'Hibernate' in orm_name: + if '@entity' in content.lower() or '@table' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count JPA relationships + total_relationships += content.count('@OneToMany') + content.count('@OneToOne') + \ + content.count('@ManyToMany') + content.count('@ManyToOne') + optional_relationships += content.count('optional=true') + required_relationships += content.count('optional=false') + + # Django ORM (Python) + elif is_python and 'Django' in orm_name: + if 'models.py' in file_path or 'models.Model' in content: + config_files.append(fa) + schema_files.append(fa.path) + # Count Django relationships + total_relationships += content.count('ForeignKey') + content.count('OneToOneField') + \ + content.count('ManyToManyField') + required_relationships += content.count('blank=False') + optional_relationships += content.count('blank=True') + + # SQLAlchemy (Python) + elif is_python and 'SQLAlchemy' in orm_name: + if 'relationship(' in content.lower() or 'Column(' in content.lower(): + config_files.append(fa) + schema_files.append(fa.path) + # Count SQLAlchemy relationships + total_relationships += content.count('relationship(') + required_relationships += content.count('nullable=False') + optional_relationships += content.count('nullable=True') + + # Calculate percentages + optional_percent = (optional_relationships / total_relationships * 100) if total_relationships > 0 else 0 + required_percent = 100 - optional_percent + + return { + 'has_orm': True, + 'orm_name': orm_name, + 'config_files': len(config_files), + 'total_relationships': total_relationships, + 'optional_relationships': optional_relationships, + 'optional_percent': optional_percent, + 'required_relationships': required_relationships if required_relationships > 0 else (total_relationships - optional_relationships), + 'required_percent': required_percent, + 'sample_files': schema_files[:5] + } + + except Exception as e: + print(f"âš ï¸ ORM configuration analysis failed: {e}") + return { + 'has_orm': False, + 'orm_name': 'Unknown', + 'config_files': 0, + 'total_relationships': 0, + 'optional_relationships': 0, + 'optional_percent': 0, + 'required_relationships': 0, + 'required_percent': 0, + 'sample_files': [] + } + + def _analyze_nplusone_sync(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Synchronous wrapper for N+1 query analysis.""" + query_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['repository', 'service', 'controller', 'dal', 'dao'])] + return {'nplusone_count': len(query_files), 'impact': 'High' if len(query_files) > 3 else 'Medium'} + + def _analyze_scalability_metrics(self, analysis: RepositoryAnalysis, max_concurrent: int, conn_per_req: int, pool_size: int, memory_per_req: float, proc_time: float) -> Dict[str, Any]: + """Analyze scalability metrics and performance gaps.""" + current_rpm = max(max_concurrent, 1) # At least 1 to avoid division by zero + required_rpm = 15000 + gap_multiplier = required_rpm / current_rpm if current_rpm > 0 else float('inf') + rpm_gap = max(0, required_rpm - current_rpm) + required_pool_size = required_rpm * 2 / 60 + conclusion = "IMPOSSIBLE with current architecture" if gap_multiplier > 100 else "REQUIRES MAJOR REdESIGN" + return { + 'current_rpm': current_rpm, + 'required_rpm': required_rpm, + 'gap_multiplier': gap_multiplier, + 'rpm_gap': rpm_gap, + 'required_pool_size': required_pool_size, + 'conclusion': conclusion + } + + def _analyze_testing_infrastructure_deep(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Deep dive into testing infrastructure.""" + test_files = [fa for fa in analysis.file_analyses if 'test' in str(fa.path).lower() or 'spec' in str(fa.path).lower()] + backend_tests = [fa for fa in test_files if any(ext in str(fa.path).lower() for ext in ['.cs', '.java', '.py', '.go', '.rs'])] + frontend_tests = [fa for fa in test_files if any(ext in str(fa.path).lower() for ext in ['.js', '.ts', '.jsx', '.tsx'])] + empty_tests = [fa for fa in test_files if fa.lines_of_code == 0] + + # Use existing method for detailed breakdown + test_analysis = self._analyze_testing_infrastructure(analysis) + + return { + 'backend_tests': len(backend_tests), + 'frontend_tests': len(frontend_tests), + 'empty_tests': len(empty_tests), + 'overall_coverage': test_analysis['overall_coverage'], + 'unit_tests': test_analysis.get('integration_tests', '0'), + 'integration_tests': test_analysis['integration_tests'], + 'e2e_tests': test_analysis['e2e_tests'], + 'security_tests': test_analysis['security_tests'], + 'performance_tests': test_analysis['performance_tests'], + 'test_quality_score': test_analysis['test_quality_score'], + 'critical_issues': test_analysis['critical_issues'], + 'recommendations': test_analysis['recommendations'] + } + + def _analyze_frontend_monoliths(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze frontend monolith files in detail.""" + frontend_files = [fa for fa in analysis.file_analyses if any(ext in str(fa.path).lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + large_files = sorted(frontend_files, key=lambda x: x.lines_of_code, reverse=True)[:10] + + largest_files = [{'name': fa.path.split('/')[-1], 'lines': fa.lines_of_code} for fa in large_files] + total_monolith_lines = sum(fa.lines_of_code for fa in large_files) + avg_monolith_size = sum(fa.lines_of_code for fa in large_files) / len(large_files) if large_files else 0 + large_files_count = len([fa for fa in frontend_files if fa.lines_of_code > 300]) + monolith_percentage = (total_monolith_lines / sum(fa.lines_of_code for fa in frontend_files) * 100) if frontend_files else 0 + + return { + 'largest_files': largest_files, + 'total_monolith_lines': total_monolith_lines, + 'avg_monolith_size': avg_monolith_size, + 'large_files_count': large_files_count, + 'monolith_percentage': monolith_percentage + } + + def _create_timeline_roadmap(self, analysis: RepositoryAnalysis, critical_count: int, high_priority_count: int) -> str: + """Create detailed fix roadmap with timeline.""" + roadmap = f""" + Phase 1: Emergency Response (Days 1-2) - {critical_count} Critical Files
+ • Fix {critical_count} critical files (severity score < 4)
+ • Estimated Time: {critical_count * 8} hours
+ • Team Required: 2-3 senior developers
+ • Priority: URGENT - System stability at risk

+ + Phase 2: Foundation Stabilization (Weeks 1-2) - {high_priority_count} High Priority Files
+ • Refactor {high_priority_count} high-priority files (severity 4-6)
+ • Estimated Time: {high_priority_count * 16} hours
+ • Team Required: Full development team
+ • Priority: HIGH - Performance and maintainability

+ + Phase 3: Architectural Redesign (Months 1-2)
+ • Implement proper connection pooling
+ • Refactor repository factory pattern
+ • Optimize database queries (N+1 fixes)
+ • Split monolith files into modules
+ • Estimated Time: 320-640 hours
+ • Deliverables: Scalable architecture, performance benchmarks

+ + Phase 4: Enterprise Hardening (Months 3-6)
+ • Comprehensive testing suite (80%+ coverage)
+ • CI/CD pipeline optimization
+ • Monitoring and observability
+ • Security hardening
+ • Estimated Time: 400-800 hours
+ • Deliverables: Production-ready enterprise system
+ """ + return roadmap + + def _analyze_expected_outcomes(self, analysis: RepositoryAnalysis, max_concurrent: int, memory_per_req: float, proc_time: float) -> Dict[str, Any]: + """Analyze expected outcomes after redesign.""" + return { + 'business_benefits': [ + 'Support 500+ concurrent users without performance degradation', + 'Reduce response times from 5-30s to <2s', + 'Cut infrastructure costs by 70%+ through optimization', + 'Improve development velocity by 40%+ with better architecture', + 'Reduce bug density by 60%+ with comprehensive testing', + 'Enable rapid feature development with scalable foundation' + ], + 'velocity_improvement': '40', + 'cost_reduction': '70', + 'maintenance_reduction': '60' + } + + def _analyze_devops_infrastructure(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze DevOps and infrastructure setup.""" + cicd_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['ci', 'jenkins', 'gitlab', 'github-actions', 'azure-pipelines', 'circleci'])] + docker_files = [fa for fa in analysis.file_analyses if 'dockerfile' in str(fa.path).lower()] + health_check_files = [fa for fa in analysis.file_analyses if 'health' in str(fa.path).lower()] + monitoring_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['monitor', 'prometheus', 'grafana', 'datadog'])] + security_files = [fa for fa in analysis.file_analyses if 'security' in str(fa.path).lower()] + deployment_files = [fa for fa in analysis.file_analyses if any(indicator in str(fa.path).lower() for indicator in ['deploy', 'k8s', 'kubernetes', 'helm'])] + + recommendations = [ + 'Implement comprehensive CI/CD pipeline with automated testing', + 'Add container orchestration (Docker/Kubernetes) if not present', + 'Set up health check endpoints for monitoring', + 'Configure APM tools for production monitoring', + 'Implement infrastructure as code (IaC)', + 'Set up automated security scanning in pipeline' + ] + + return { + 'cicd_files': len(cicd_files), + 'docker_files': len(docker_files), + 'health_check_files': len(health_check_files), + 'monitoring_files': len(monitoring_files), + 'security_files': len(security_files), + 'deployment_files': len(deployment_files), + 'recommendations': recommendations + } + + def _analyze_bulk_upload_sync(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Synchronous wrapper for bulk upload analysis.""" + upload_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['upload', 'import', 'bulk', 'excel'])] + upload_classes = len(upload_files) + total_properties = 0 + for fa in upload_files: + content = getattr(fa, 'content', '') or '' + total_properties += content.count('public ') + content.count('private ') + content.count('protected ') + return {'upload_classes': upload_classes, 'total_properties': total_properties} + + def _analyze_performance_per_layer_sync(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Synchronous wrapper for performance per layer analysis.""" + frontend_files = [fa for fa in analysis.file_analyses if any(ext in fa.path.lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + total_frontend_lines = sum(fa.lines_of_code for fa in frontend_files) + bundle_size_mb = (total_frontend_lines * 0.5) / 1000 + return { + 'controller_overhead': '50-100ms', + 'service_processing': '100-200ms', + 'database_queries': '200-500ms', + 'frontend_bundle': f'{bundle_size_mb:.1f}MB', + 'total_frontend_lines': total_frontend_lines + } + + def _analyze_repository_pattern(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze repository/data access pattern technology-aware.""" + try: + # Detect technology stack + tech_stack = self._detect_technology_stack(analysis) + is_csharp = tech_stack['is_csharp'] + is_nodejs = tech_stack['is_nodejs'] + is_java = tech_stack['is_java'] + is_python = tech_stack['is_python'] + + # Technology-specific repository detection + repo_files = [] + factory_files = [] + uow_files = [] + pattern_name = "Data Access Layer" + + for fa in analysis.file_analyses: + file_path = str(fa.path).lower() + content = getattr(fa, 'content', '') or '' + + # C# specific patterns + if is_csharp: + if 'repository' in file_path or 'repository' in content.lower(): + repo_files.append(fa) + if 'factory' in file_path or 'factory' in content.lower(): + factory_files.append(fa) + if 'unitofwork' in file_path or 'unitofwork' in content.lower(): + uow_files.append(fa) + pattern_name = "Repository + UnitOfWork Pattern (.NET)" + + # Node.js patterns + elif is_nodejs: + if 'repository' in file_path or 'model' in file_path: + repo_files.append(fa) + if 'factory' in file_path: + factory_files.append(fa) + + # Java patterns + elif is_java: + if 'repository' in file_path or '@repository' in content.lower(): + repo_files.append(fa) + if 'factory' in file_path: + factory_files.append(fa) + pattern_name = "Repository + Factory Pattern (Spring)" + + # Python patterns + elif is_python: + if 'repository' in file_path or 'dal' in file_path or 'dao' in file_path: + repo_files.append(fa) + if 'factory' in file_path: + factory_files.append(fa) + pattern_name = "Data Access Layer (Python)" + + # Only analyze if repositories are found + if not repo_files: + return { + 'has_repos': False, + 'pattern': 'None detected', + 'total_repositories': 0, + 'repositories_per_request': 0, + 'avg_repo_size': 0, + 'factory_files': 0, + 'uow_files': 0, + 'sample_repositories': [] + } + + # Calculate metrics + total_repositories = len(repo_files) + avg_repo_size = sum(fa.lines_of_code for fa in repo_files) / len(repo_files) if repo_files else 0 + + # Estimate repositories per request + repositories_per_request = 0 + if uow_files: + for fa in uow_files: + content = getattr(fa, 'content', '') or '' + # Count repository instantiations + repositories_per_request = max(repositories_per_request, + content.count('= new ') + content.count('new I') + + content.count('new ') + content.count('Create')) + + # Default estimate if not calculated + if repositories_per_request == 0: + repositories_per_request = max(1, min(total_repositories, 5)) + + return { + 'has_repos': True, + 'pattern': pattern_name, + 'total_repositories': total_repositories, + 'repositories_per_request': repositories_per_request, + 'avg_repo_size': avg_repo_size, + 'factory_files': len(factory_files), + 'uow_files': len(uow_files), + 'sample_repositories': [fa.path for fa in repo_files[:5]] + } + + except Exception as e: + print(f"âš ï¸ Repository pattern analysis failed: {e}") + return { + 'has_repos': False, + 'pattern': 'None detected', + 'total_repositories': 0, + 'repositories_per_request': 0, + 'avg_repo_size': 0, + 'factory_files': 0, + 'uow_files': 0, + 'sample_repositories': [] + } + + async def _analyze_nplusone_queries(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered N+1 query analysis.""" + try: + print("🔠Analyzing N+1 query patterns...") + + query_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['repository', 'service', 'controller', 'dal', 'dao'])] + + if not query_files: + return {'nplusone_count': 0, 'examples': [], 'impact': 'Low'} + + # Build code samples for AI analysis + code_samples = [] + for fa in query_files[:5]: + content = getattr(fa, 'content', '') or '' + if len(content) > 5000: + content_lines = content.split('\n') + content = '\n'.join(content_lines[:200]) + + code_samples.append(f""" +File: {fa.path} +Lines: {fa.lines_of_code} + +Code: +{content[:3000]} +""") + + prompt = f"""You are a Database Performance Expert. Analyze this code for N+1 query patterns. + +{chr(10).join(code_samples)} + +For each file, identify: +1. **Specific N+1 query examples** (quote the exact code) +2. **Query count calculations** (show 1 + N×M pattern) +3. **Database load impact** (estimated query count per request) +4. **Before/After optimization** (complete optimized code) + +Format with exact code examples showing: +- BEFORE: The N+1 pattern with query count math +- AFTER: Optimized version with reduced queries + +Be specific with query counts and provide working optimized code.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=6000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ N+1 query analysis complete") + + return { + 'nplusone_count': len(query_files), + 'ai_analysis': ai_analysis, + 'impact': 'High' if len(query_files) > 3 else 'Medium' + } + + except Exception as e: + print(f"âš ï¸ N+1 query analysis failed: {e}") + return {'nplusone_count': 0, 'examples': [], 'impact': 'Low'} + + def _analyze_controller_endpoints(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze API controller endpoints for explosion and dual patterns.""" + try: + controller_files = [fa for fa in analysis.file_analyses if 'controller' in fa.path.lower() or 'api' in fa.path.lower()] + + endpoint_counts = {} + largest_controller = None + largest_endpoint_count = 0 + + for fa in controller_files: + content = getattr(fa, 'content', '') or '' + if not content: + continue + + # Count endpoints + endpoint_count = content.count('@HttpGet') + content.count('@HttpPost') + \ + content.count('@HttpPut') + content.count('@HttpDelete') + \ + content.count('@RequestMapping') + content.count('@GetMapping') + \ + content.count('@PostMapping') + content.count('@PutMapping') + \ + content.count('@DeleteMapping') + + endpoint_counts[fa.path] = endpoint_count + + if endpoint_count > largest_endpoint_count: + largest_endpoint_count = endpoint_count + largest_controller = fa + + total_endpoints = sum(endpoint_counts.values()) + avg_endpoints_per_controller = total_endpoints / len(controller_files) if controller_files else 0 + + # Check for dual controller patterns + dual_controllers = [fa.path for fa in controller_files if 'dual' in fa.path.lower() or 'double' in fa.path.lower()] + + return { + 'total_controllers': len(controller_files), + 'total_endpoints': total_endpoints, + 'avg_endpoints': avg_endpoints_per_controller, + 'largest_controller': largest_controller.path if largest_controller else 'None', + 'largest_endpoint_count': largest_endpoint_count, + 'dual_controllers': len(dual_controllers), + 'sample_endpoint_counts': {k: v for k, v in list(endpoint_counts.items())[:5]} + } + + except Exception as e: + print(f"âš ï¸ Controller endpoints analysis failed: {e}") + return { + 'total_controllers': 0, + 'total_endpoints': 0, + 'avg_endpoints': 0, + 'largest_controller': 'None', + 'largest_endpoint_count': 0, + 'dual_controllers': 0, + 'sample_endpoint_counts': {} + } + + async def _analyze_bulk_upload_system(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered analysis of bulk upload system issues.""" + try: + print("🔠Analyzing bulk upload system...") + + upload_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['upload', 'import', 'bulk', 'excel'])] + + if not upload_files: + return {'upload_classes': 0, 'total_properties': 0, 'issues': []} + + code_samples = [] + for fa in upload_files[:3]: + content = getattr(fa, 'content', '') or '' + if len(content) > 5000: + content_lines = content.split('\n') + content = '\n'.join(content_lines[:200]) + + code_samples.append(f""" +File: {fa.path} +Lines: {fa.lines_of_code} + +Code: +{content[:3000]} +""") + + prompt = f"""You are a System Architecture Expert. Analyze this bulk upload system. + +{chr(10).join(code_samples)} + +Identify: +1. **Upload class count** (how many upload classes) +2. **Total properties** across all upload classes +3. **Type safety problems** (string vs proper types) +4. **Excel template complexity** +5. **Upload failure root causes** +6. **Specific code examples** of problems + +Provide detailed analysis with exact code examples showing the issues.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=6000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ Bulk upload system analysis complete") + + # Count upload classes and properties + upload_classes = len(upload_files) + total_properties = 0 + for fa in upload_files: + content = getattr(fa, 'content', '') or '' + total_properties += content.count('public ') + content.count('private ') + content.count('protected ') + + return { + 'upload_classes': upload_classes, + 'total_properties': total_properties, + 'ai_analysis': ai_analysis, + 'sample_files': [fa.path for fa in upload_files[:5]] + } + + except Exception as e: + print(f"âš ï¸ Bulk upload analysis failed: {e}") + return {'upload_classes': 0, 'total_properties': 0, 'issues': []} + + def _analyze_background_processing(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """Analyze background processing and threading issues.""" + try: + thread_files = [fa for fa in analysis.file_analyses if any(indicator in fa.path.lower() for indicator in ['thread', 'background', 'scheduler', 'async', 'task'])] + email_files = [fa for fa in analysis.file_analyses if 'email' in fa.path.lower() or 'mail' in fa.path.lower()] + + manual_thread_count = 0 + threadpool_usage = False + + for fa in thread_files: + content = getattr(fa, 'content', '') or '' + # Count manual thread creation + manual_thread_count += content.count('new Thread(') + content.count('Thread thread =') + # Check for thread pool usage + if any(pool in content for pool in ['ThreadPool', 'Task.Run', 'async Task', '@Async']): + threadpool_usage = True + + # Check for email system + email_implementation = 'Basic' if email_files else 'None' + + return { + 'manual_thread_count': manual_thread_count, + 'threadpool_usage': threadpool_usage, + 'thread_files': len(thread_files), + 'email_implementation': email_implementation, + 'email_files': len(email_files), + 'sample_files': [fa.path for fa in thread_files[:5]] + } + + except Exception as e: + print(f"âš ï¸ Background processing analysis failed: {e}") + return { + 'manual_thread_count': 0, + 'threadpool_usage': False, + 'thread_files': 0, + 'email_implementation': 'None', + 'email_files': 0, + 'sample_files': [] + } + + async def _analyze_performance_per_layer(self, analysis: RepositoryAnalysis) -> Dict[str, Any]: + """AI-powered performance analysis per layer.""" + try: + print("🔠Analyzing performance impact per layer...") + + # Categorize files by layer + controller_files = [fa for fa in analysis.file_analyses if 'controller' in fa.path.lower()] + service_files = [fa for fa in analysis.file_analyses if 'service' in fa.path.lower()] + repository_files = [fa for fa in analysis.file_analyses if 'repository' in fa.path.lower()] + frontend_files = [fa for fa in analysis.file_analyses if any(ext in fa.path.lower() for ext in ['.js', '.jsx', '.ts', '.tsx'])] + + # Build code samples from each layer + samples = [] + if controller_files: + for fa in controller_files[:2]: + content = getattr(fa, 'content', '') or '' + if len(content) > 3000: + content = content[:3000] + samples.append(f"[Controller] {fa.path}\n{content}") + + if service_files: + for fa in service_files[:2]: + content = getattr(fa, 'content', '') or '' + if len(content) > 3000: + content = content[:3000] + samples.append(f"[Service] {fa.path}\n{content}") + + if repository_files: + for fa in repository_files[:2]: + content = getattr(fa, 'content', '') or '' + if len(content) > 3000: + content = content[:3000] + samples.append(f"[Repository] {fa.path}\n{content}") + + if not samples: + return {'timings': {}, 'summary': 'No performance analysis possible'} + + prompt = f"""You are a Performance Expert. Analyze this code for end-to-end request lifecycle timing. + +{chr(10).join(samples[:10])} + +For each layer, provide: +1. **Request lifecycle timing** breakdown +2. **Database operation timing** +3. **Service layer timing** +4. **Controller overhead timing** +5. **Frontend bundle size impact** +6. **Complete request time breakdown** + +Provide specific timing estimates with calculations showing where time is spent in each layer.""" + + message = self.client.messages.create( + model=os.getenv("CLAUDE_MODEL", "claude-3-5-haiku-latest"), + max_tokens=6000, + temperature=0.1, + messages=[{"role": "user", "content": prompt}] + ) + + ai_analysis = message.content[0].text.strip() + print("✅ Performance per layer analysis complete") + + # Calculate bundle size estimate + total_frontend_lines = sum(fa.lines_of_code for fa in frontend_files) + bundle_size_mb = (total_frontend_lines * 0.5) / 1000 + + return { + 'timings': { + 'controller_overhead': '50-100ms', + 'service_processing': '100-200ms', + 'database_queries': '200-500ms', + 'frontend_bundle': f'{bundle_size_mb:.1f}MB' + }, + 'ai_analysis': ai_analysis, + 'total_frontend_lines': total_frontend_lines + } + + except Exception as e: + print(f"âš ï¸ Performance per layer analysis failed: {e}") + return {'timings': {}, 'summary': 'Analysis failed'} + # ========== Formatting Utilities ========== def _format_bulleted_html(self, text: str) -> str: """Normalize bullets/line breaks so each bullet shows on its own line in PDF. diff --git a/services/ai-analysis-service/env.example b/services/ai-analysis-service/env.example index 0106cad..2b8c19d 100644 --- a/services/ai-analysis-service/env.example +++ b/services/ai-analysis-service/env.example @@ -38,7 +38,7 @@ MAX_FILE_SIZE_MB=2 ANALYSIS_TIMEOUT_SECONDS=300 # Rate Limiting Configuration -CLAUDE_REQUESTS_PER_MINUTE=90 +CLAUDE_REQUESTS_PER_MINUTE=1000 RATE_LIMIT_BUFFER=10 # Memory System Configuration diff --git a/services/ai-analysis-service/server.py b/services/ai-analysis-service/server.py index 6f37683..9bda451 100644 --- a/services/ai-analysis-service/server.py +++ b/services/ai-analysis-service/server.py @@ -70,10 +70,10 @@ analyzer = None # Optimized Token Bucket Rate Limiter for Claude API class TokenBucketRateLimiter: - def __init__(self, capacity: int = 90, refill_rate: float = 1.5): + def __init__(self, capacity: int = 1000, refill_rate: float = 16.67): self.capacity = capacity self.tokens = capacity - self.refill_rate = refill_rate # tokens per second + self.refill_rate = refill_rate # tokens per second (1000 requests / 60 seconds = 16.67) self.last_update = time.time() self.lock = asyncio.Lock() @@ -98,27 +98,35 @@ class TokenBucketRateLimiter: # Batch Rate Limiter for parallel processing class BatchRateLimiter: - def __init__(self, batch_size: int = 10, requests_per_minute: int = 90): + def __init__(self, batch_size: int = 10, requests_per_minute: int = 1000): self.batch_size = batch_size self.requests_per_minute = requests_per_minute - self.batch_interval = 60 / (requests_per_minute / batch_size) # Time between batches + # Fixed calculation: batches_per_minute = requests_per_minute / files_per_batch + # For smart batching: 5 files per batch, so batches_per_minute = requests_per_minute / 5 + # batch_interval = 60 / batches_per_minute + self.files_per_batch = 5 # Smart batching uses 5 files per batch + self.batches_per_minute = requests_per_minute / self.files_per_batch + self.batch_interval = 60 / self.batches_per_minute # Time between batches self.last_batch_time = 0 self.lock = asyncio.Lock() async def wait_for_batch(self): - """Wait for the next batch slot.""" + """Wait for the next batch slot (only if needed).""" async with self.lock: now = time.time() time_since_last = now - self.last_batch_time + # Only wait if we're sending batches too fast if time_since_last < self.batch_interval: - await asyncio.sleep(self.batch_interval - time_since_last) + wait_time = self.batch_interval - time_since_last + if wait_time > 0.01: # Only wait if more than 10ms + await asyncio.sleep(wait_time) self.last_batch_time = time.time() # Legacy rate limiter for backward compatibility class ClaudeRateLimiter: - def __init__(self, requests_per_minute: int = 90): + def __init__(self, requests_per_minute: int = 1000): self.token_bucket = TokenBucketRateLimiter(requests_per_minute, requests_per_minute / 60) async def wait_if_needed(self): @@ -343,8 +351,10 @@ def sanitize_analysis_result(analysis): return analysis # Global instances -rate_limiter = ClaudeRateLimiter() -batch_rate_limiter = BatchRateLimiter(batch_size=10, requests_per_minute=90) # OPTIMIZED: Smaller batches +# Read rate limit from environment variable, default to 1000 requests/minute +requests_per_minute = int(os.getenv('CLAUDE_REQUESTS_PER_MINUTE', '1000')) +rate_limiter = ClaudeRateLimiter(requests_per_minute=requests_per_minute) +batch_rate_limiter = BatchRateLimiter(batch_size=10, requests_per_minute=requests_per_minute) # Updated to 1000 requests/minute (configurable via env) git_client = GitIntegrationClient() analysis_cache = AnalysisCache() content_optimizer = ContentOptimizer() @@ -1204,14 +1214,43 @@ def group_files_by_similarity(files: List[Tuple[str, str]]) -> List[List[Tuple[s groups[group_key] = [] groups[group_key].append((file_path, content)) - # Convert to list and ensure no group is too large + # Convert to list and ensure batches are exactly 5 files (for smart batching) grouped_files = [] for group in groups.values(): - # Split large groups into smaller batches + # Split large groups into batches of exactly 5 files for i in range(0, len(group), 5): - grouped_files.append(group[i:i+5]) + batch = group[i:i+5] + # Ensure batch has exactly 5 files (pad with next group if needed) + if len(batch) < 5 and len(grouped_files) > 0: + # Try to merge with previous incomplete batch + prev_batch = grouped_files[-1] + if len(prev_batch) < 5: + # Merge into previous batch + remaining_slots = 5 - len(prev_batch) + grouped_files[-1].extend(batch[:remaining_slots]) + batch = batch[remaining_slots:] + + if len(batch) > 0: + grouped_files.append(batch) - return grouped_files + # Final pass: ensure minimum batch size of 3 (merge very small batches) + final_grouped = [] + current_batch = [] + for batch in grouped_files: + if len(current_batch) + len(batch) <= 5: + current_batch.extend(batch) + if len(current_batch) >= 5: + final_grouped.append(current_batch) + current_batch = [] + else: + if current_batch: + final_grouped.append(current_batch) + current_batch = batch + + if current_batch: + final_grouped.append(current_batch) + + return final_grouped def get_language_from_path(file_path: str) -> str: """Extract programming language from file path.""" @@ -1713,8 +1752,9 @@ async def analyze_repository_with_optimizations_parallel(repo_path: str, reposit "processing_mode": "smart_batching" }) - # Small delay to prevent API throttling - await asyncio.sleep(0.5) + # Small delay to prevent API throttling (reduced from 0.5s to 0.1s for faster processing) + # With 1000 req/min rate limit, we don't need long delays + await asyncio.sleep(0.1) print(f"🎉 [SMART BATCHING] Completed all {total_batches} smart batches - {len(file_analyses)} files analyzed") @@ -1880,8 +1920,9 @@ async def analyze_repository_with_optimizations(repo_path: str, repository_id: s "processing_mode": "smart_batching" }) - # Small delay to prevent API throttling - await asyncio.sleep(0.5) + # Small delay to prevent API throttling (reduced from 0.5s to 0.1s for faster processing) + # With 1000 req/min rate limit, we don't need long delays + await asyncio.sleep(0.1) print(f"🎉 [SMART BATCHING] Completed all {total_batches} smart batches - {len(file_analyses)} files analyzed") @@ -2057,7 +2098,7 @@ async def get_performance_stats(): }, "performance_metrics": { "smart_batch_size": 5, # NEW: Smart batching - 5 files per API call - "rate_limit_per_minute": 90, + "rate_limit_per_minute": 1000, # Updated to 1000 requests/minute "api_calls_reduction": "5x fewer API calls", # 100 files = 20 calls instead of 100 "token_savings": "37% reduction", # 250k → 156k tokens "cache_ttl_hours": 1,