From a1fbf3679a96221eaf6ad69520777e9a953d505e Mon Sep 17 00:00:00 2001 From: Stephen Thompson Date: Tue, 10 Dec 2024 18:06:10 -0500 Subject: [PATCH 1/2] Added differential pair finder script to PCB scripts --- .../DiffPairFinder/DiffPair_Finder.PrjScr | 1017 ++++++++++++++ .../DiffPairFinder/DiffPair_Finder.dfm | 79 ++ .../DiffPairFinder/DiffPair_Finder.pas | 1180 +++++++++++++++++ Scripts - PCB/DiffPairFinder/README.md | 15 + Scripts - PCB/DiffPairFinder/gui.jpg | Bin 0 -> 143754 bytes Scripts - PCB/README.md | 1 + 6 files changed, 2292 insertions(+) create mode 100644 Scripts - PCB/DiffPairFinder/DiffPair_Finder.PrjScr create mode 100644 Scripts - PCB/DiffPairFinder/DiffPair_Finder.dfm create mode 100644 Scripts - PCB/DiffPairFinder/DiffPair_Finder.pas create mode 100644 Scripts - PCB/DiffPairFinder/README.md create mode 100644 Scripts - PCB/DiffPairFinder/gui.jpg diff --git a/Scripts - PCB/DiffPairFinder/DiffPair_Finder.PrjScr b/Scripts - PCB/DiffPairFinder/DiffPair_Finder.PrjScr new file mode 100644 index 00000000..3c292e86 --- /dev/null +++ b/Scripts - PCB/DiffPairFinder/DiffPair_Finder.PrjScr @@ -0,0 +1,1017 @@ +[Design] +Version=1.0 +HierarchyMode=0 +ChannelRoomNamingStyle=0 +ReleasesFolder= +ChannelDesignatorFormatString=$Component_$RoomName +ChannelRoomLevelSeperator=_ +OpenOutputs=1 +ArchiveProject=0 +TimestampOutput=0 +SeparateFolders=0 +TemplateLocationPath= +PinSwapBy_Netlabel=1 +PinSwapBy_Pin=1 +AllowPortNetNames=0 +AllowSheetEntryNetNames=1 +AppendSheetNumberToLocalNets=0 +NetlistSinglePinNets=0 +DefaultConfiguration=Default - All Constraints +UserID=0xFFFFFFFF +DefaultPcbProtel=1 +DefaultPcbPcad=0 +ReorderDocumentsOnCompile=1 +NameNetsHierarchically=0 +PowerPortNamesTakePriority=0 +AutoSheetNumbering=0 +NewIndexingOfSheetSymbols=1 +PushECOToAnnotationFile=1 +DItemRevisionGUID= +ReportSuppressedErrorsInMessages=0 +FSMCodingStyle=eFMSDropDownList_OneProcess +FSMEncodingStyle=eFMSDropDownList_OneHot +IsProjectConflictPreventionWarningsEnabled=1 +ConstraintManagerFlow=0 +IsVirtualBomDocumentRemoved=0 +OutputPath= +LogFolderPath= +ManagedProjectGUID= +IncludeDesignInRelease=0 +CrossRefSheetStyle=2 +CrossRefLocationStyle=1 +CrossRefPorts=3 +CrossRefCrossSheets=1 +CrossRefSheetEntries=0 +CrossRefFollowFromMainSettings=1 + +[Preferences] +PrefsVaultGUID= +PrefsRevisionGUID= + +[Document1] +DocumentPath=DiffPair_Finder.pas +AnnotationEnabled=1 +AnnotateStartValue=1 +AnnotationIndexControlEnabled=0 +AnnotateSuffix= +AnnotateScope=All +AnnotateOrder=-1 +DoLibraryUpdate=1 +DoDatabaseUpdate=1 +ClassGenCCAutoEnabled=1 +ClassGenCCAutoRoomEnabled=0 +ClassGenNCAutoScope=None +DItemRevisionGUID= +GenerateClassCluster=0 +DocumentUniqueId= + +[OutputGroup1] +Name=Netlist Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=CadnetixNetlist +OutputName1=Cadnetix Netlist +OutputDocumentPath1= +OutputVariantName1= +OutputDefault1=0 +OutputType2=CalayNetlist +OutputName2=Calay Netlist +OutputDocumentPath2= +OutputVariantName2= +OutputDefault2=0 +OutputType3=EDIF +OutputName3=EDIF for PCB +OutputDocumentPath3= +OutputVariantName3= +OutputDefault3=0 +OutputType4=EESofNetlist +OutputName4=EESof Netlist +OutputDocumentPath4= +OutputVariantName4= +OutputDefault4=0 +OutputType5=IntergraphNetlist +OutputName5=Intergraph Netlist +OutputDocumentPath5= +OutputVariantName5= +OutputDefault5=0 +OutputType6=MentorBoardStationNetlist +OutputName6=Mentor BoardStation Netlist +OutputDocumentPath6= +OutputVariantName6= +OutputDefault6=0 +OutputType7=MultiWire +OutputName7=MultiWire +OutputDocumentPath7= +OutputVariantName7= +OutputDefault7=0 +OutputType8=OrCadPCB2Netlist +OutputName8=Orcad/PCB2 Netlist +OutputDocumentPath8= +OutputVariantName8= +OutputDefault8=0 +OutputType9=PADSNetlist +OutputName9=PADS ASCII Netlist +OutputDocumentPath9= +OutputVariantName9= +OutputDefault9=0 +OutputType10=Pcad +OutputName10=Pcad for PCB +OutputDocumentPath10= +OutputVariantName10= +OutputDefault10=0 +OutputType11=PCADNetlist +OutputName11=PCAD Netlist +OutputDocumentPath11= +OutputVariantName11= +OutputDefault11=0 +OutputType12=PCADnltNetlist +OutputName12=PCADnlt Netlist +OutputDocumentPath12= +OutputVariantName12= +OutputDefault12=0 +OutputType13=Protel2Netlist +OutputName13=Protel2 Netlist +OutputDocumentPath13= +OutputVariantName13= +OutputDefault13=0 +OutputType14=ProtelNetlist +OutputName14=Protel +OutputDocumentPath14= +OutputVariantName14= +OutputDefault14=0 +OutputType15=RacalNetlist +OutputName15=Racal Netlist +OutputDocumentPath15= +OutputVariantName15= +OutputDefault15=0 +OutputType16=RINFNetlist +OutputName16=RINF Netlist +OutputDocumentPath16= +OutputVariantName16= +OutputDefault16=0 +OutputType17=SciCardsNetlist +OutputName17=SciCards Netlist +OutputDocumentPath17= +OutputVariantName17= +OutputDefault17=0 +OutputType18=TangoNetlist +OutputName18=Tango Netlist +OutputDocumentPath18= +OutputVariantName18= +OutputDefault18=0 +OutputType19=TelesisNetlist +OutputName19=Telesis Netlist +OutputDocumentPath19= +OutputVariantName19= +OutputDefault19=0 +OutputType20=WireListNetlist +OutputName20=WireList Netlist +OutputDocumentPath20= +OutputVariantName20= +OutputDefault20=0 + +[OutputGroup2] +Name=Simulator Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 + +[OutputGroup3] +Name=Documentation Outputs +Description= +TargetPrinter=Virtual Printer +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=Composite +OutputName1=Composite Drawing +OutputDocumentPath1= +OutputVariantName1=[No Variations] +OutputDefault1=0 +PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType2=PCB 3D Print +OutputName2=PCB 3D Print +OutputDocumentPath2= +OutputVariantName2=[No Variations] +OutputDefault2=0 +PageOptions2=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType3=PCB 3D Video +OutputName3=PCB 3D Video +OutputDocumentPath3= +OutputVariantName3=[No Variations] +OutputDefault3=0 +PageOptions3=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType4=PCB Print +OutputName4=PCB Prints +OutputDocumentPath4= +OutputVariantName4=[No Variations] +OutputDefault4=0 +PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType5=PCBDrawing +OutputName5=Draftsman +OutputDocumentPath5= +OutputVariantName5=[No Variations] +OutputDefault5=0 +PageOptions5=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType6=PCBLIB Print +OutputName6=PCBLIB Prints +OutputDocumentPath6= +OutputVariantName6=[No Variations] +OutputDefault6=0 +PageOptions6=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType7=PDF3D +OutputName7=PDF3D +OutputDocumentPath7= +OutputVariantName7=[No Variations] +OutputDefault7=0 +PageOptions7=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType8=Report Print +OutputName8=Report Prints +OutputDocumentPath8= +OutputVariantName8= +OutputDefault8=0 +PageOptions8=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType9=Schematic Print +OutputName9=Schematic Prints +OutputDocumentPath9= +OutputVariantName9= +OutputDefault9=0 +PageOptions9=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType10=SimView Print +OutputName10=SimView Prints +OutputDocumentPath10= +OutputVariantName10= +OutputDefault10=0 +PageOptions10=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType11=Harness Layout Drawing Print +OutputName11=Harness Layout Drawing Prints +OutputDocumentPath11= +OutputVariantName11= +OutputDefault11=0 +PageOptions11=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType12=Harness Wiring Diagram Print +OutputName12=Harness Wiring Diagram Prints +OutputDocumentPath12= +OutputVariantName12= +OutputDefault12=0 +PageOptions12=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType13=PDF3D MBA +OutputName13=PDF3D MBA +OutputDocumentPath13= +OutputVariantName13= +OutputDefault13=0 +PageOptions13=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 + +[OutputGroup4] +Name=Assembly Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=Assembly +OutputName1=Assembly Drawings +OutputDocumentPath1= +OutputVariantName1=[No Variations] +OutputDefault1=0 +PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType2=Pick Place +OutputName2=Generates pick and place files +OutputDocumentPath2= +OutputVariantName2=[No Variations] +OutputDefault2=0 +OutputType3=Test Points For Assembly +OutputName3=Test Point Report +OutputDocumentPath3= +OutputVariantName3=[No Variations] +OutputDefault3=0 +OutputType4=Wire Bonding Table +OutputName4=Wire Bonding Table Report +OutputDocumentPath4= +OutputVariantName4=[No Variations] +OutputDefault4=0 + +[OutputGroup5] +Name=Fabrication Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=Board Stack Report +OutputName1=Report Board Stack +OutputDocumentPath1= +OutputVariantName1= +OutputDefault1=0 +PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType2=CompositeDrill +OutputName2=Composite Drill Drawing +OutputDocumentPath2= +OutputVariantName2=[No Variations] +OutputDefault2=0 +PageOptions2=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType3=Drill +OutputName3=Drill Drawing/Guides +OutputDocumentPath3= +OutputVariantName3=[No Variations] +OutputDefault3=0 +PageOptions3=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType4=Final +OutputName4=Final Artwork Prints +OutputDocumentPath4= +OutputVariantName4=[No Variations] +OutputDefault4=0 +PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType5=Gerber +OutputName5=Gerber Files +OutputDocumentPath5= +OutputVariantName5=[No Variations] +OutputDefault5=0 +OutputType6=Gerber X2 +OutputName6=Gerber X2 Files +OutputDocumentPath6= +OutputVariantName6=[No Variations] +OutputDefault6=0 +OutputType7=IPC2581 +OutputName7=IPC-2581 Files +OutputDocumentPath7= +OutputVariantName7=[No Variations] +OutputDefault7=0 +OutputType8=Mask +OutputName8=Solder/Paste Mask Prints +OutputDocumentPath8= +OutputVariantName8=[No Variations] +OutputDefault8=0 +PageOptions8=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType9=NC Drill +OutputName9=NC Drill Files +OutputDocumentPath9= +OutputVariantName9= +OutputDefault9=0 +OutputType10=ODB +OutputName10=ODB++ Files +OutputDocumentPath10= +OutputVariantName10=[No Variations] +OutputDefault10=0 +OutputType11=Plane +OutputName11=Power-Plane Prints +OutputDocumentPath11= +OutputVariantName11=[No Variations] +OutputDefault11=0 +PageOptions11=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType12=Test Points +OutputName12=Test Point Report +OutputDocumentPath12= +OutputVariantName12= +OutputDefault12=0 + +[OutputGroup6] +Name=Report Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=BOM_PartType +OutputName1=Bill of Materials +OutputDocumentPath1= +OutputVariantName1=[No Variations] +OutputDefault1=0 +PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType2=ComponentCrossReference +OutputName2=Component Cross Reference Report +OutputDocumentPath2= +OutputVariantName2=[No Variations] +OutputDefault2=0 +OutputType3=ReportHierarchy +OutputName3=Report Project Hierarchy +OutputDocumentPath3= +OutputVariantName3=[No Variations] +OutputDefault3=0 +OutputType4=Script +OutputName4=Script Output +OutputDocumentPath4= +OutputVariantName4=[No Variations] +OutputDefault4=0 +OutputType5=SimpleBOM +OutputName5=Simple BOM +OutputDocumentPath5= +OutputVariantName5=[No Variations] +OutputDefault5=0 +OutputType6=SinglePinNetReporter +OutputName6=Report Single Pin Nets +OutputDocumentPath6= +OutputVariantName6=[No Variations] +OutputDefault6=0 +OutputType7=BOM_ReportCompare +OutputName7=BOM Compare +OutputDocumentPath7= +OutputVariantName7=[No Variations] +OutputDefault7=0 +PageOptions7=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType8=Export Comments +OutputName8=Export Comments +OutputDocumentPath8= +OutputVariantName8=[No Variations] +OutputDefault8=0 +PageOptions8=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType9=Project History +OutputName9=Project History +OutputDocumentPath9= +OutputVariantName9=[No Variations] +OutputDefault9=0 +PageOptions9=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 + +[OutputGroup7] +Name=Other Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=Text Print +OutputName1=Text Print +OutputDocumentPath1= +OutputVariantName1= +OutputDefault1=0 +PageOptions1=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 + +[OutputGroup8] +Name=Validation Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=Component states check +OutputName1=Vault's components states check +OutputDocumentPath1= +OutputVariantName1= +OutputDefault1=0 +OutputType2=Configuration compliance +OutputName2=Environment configuration compliance check +OutputDocumentPath2= +OutputVariantName2= +OutputDefault2=0 +OutputType3=Design Rules Check +OutputName3=Design Rules Check +OutputDocumentPath3= +OutputVariantName3= +OutputDefault3=0 +PageOptions3=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType4=Differences Report +OutputName4=Differences Report +OutputDocumentPath4= +OutputVariantName4= +OutputDefault4=0 +PageOptions4=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType5=Electrical Rules Check +OutputName5=Electrical Rules Check +OutputDocumentPath5= +OutputVariantName5= +OutputDefault5=0 +PageOptions5=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 +OutputType6=Footprint Comparison Report +OutputName6=Footprint Comparison Report +OutputDocumentPath6= +OutputVariantName6= +OutputDefault6=0 +OutputType7=BOM_Violations +OutputName7=BOM Checks Report +OutputDocumentPath7= +OutputVariantName7= +OutputDefault7=0 + +[OutputGroup9] +Name=Export Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=AutoCAD dwg/dxf PCB +OutputName1=AutoCAD dwg/dxf File PCB +OutputDocumentPath1= +OutputVariantName1= +OutputDefault1=0 +OutputType2=AutoCAD dwg/dxf Schematic +OutputName2=AutoCAD dwg/dxf File Schematic +OutputDocumentPath2= +OutputVariantName2= +OutputDefault2=0 +OutputType3=ExportIDF +OutputName3=Export IDF +OutputDocumentPath3= +OutputVariantName3= +OutputDefault3=0 +OutputType4=ExportSTEP +OutputName4=Export STEP +OutputDocumentPath4= +OutputVariantName4=[No Variations] +OutputDefault4=0 +OutputType5=ExportPARASOLID +OutputName5=Export PARASOLID +OutputDocumentPath5= +OutputVariantName5=[No Variations] +OutputDefault5=0 +OutputType6=ExportVRML +OutputName6=Export VRML +OutputDocumentPath6= +OutputVariantName6=[No Variations] +OutputDefault6=0 +OutputType7=MBAExportPARASOLID +OutputName7=Export PARASOLID +OutputDocumentPath7= +OutputVariantName7= +OutputDefault7=0 +OutputType8=MBAExportSTEP +OutputName8=Export STEP +OutputDocumentPath8= +OutputVariantName8= +OutputDefault8=0 +OutputType9=Save As/Export PCB +OutputName9=Save As/Export PCB +OutputDocumentPath9= +OutputVariantName9= +OutputDefault9=0 +OutputType10=Save As/Export Schematic +OutputName10=Save As/Export Schematic +OutputDocumentPath10= +OutputVariantName10= +OutputDefault10=0 +OutputType11=Specctra Design PCB +OutputName11=Specctra Design PCB +OutputDocumentPath11= +OutputVariantName11= +OutputDefault11=0 +OutputType12=Web ReviewOutputName +OutputName12=Web Review Data +OutputDocumentPath12= +OutputVariantName12= +OutputDefault12=0 + +[OutputGroup10] +Name=PostProcess Outputs +Description= +TargetPrinter=\\NDG-PC-SVR-03\Brother DCP-L2540DW series +PrinterOptions=Record=PrinterOptions|Copies=1|Duplex=1|TrueTypeOptions=3|Collate=1|PrintJobKind=1|PrintWhat=1 +OutputType1=Copy Files +OutputName1=Copy Files +OutputDocumentPath1= +OutputVariantName1= +OutputDefault1=0 + +[Modification Levels] +Type1=1 +Type2=1 +Type3=1 +Type4=1 +Type5=1 +Type6=1 +Type7=1 +Type8=1 +Type9=1 +Type10=1 +Type11=1 +Type12=1 +Type13=1 +Type14=1 +Type15=1 +Type16=1 +Type17=1 +Type18=1 +Type19=1 +Type20=1 +Type21=1 +Type22=1 +Type23=1 +Type24=1 +Type25=1 +Type26=1 +Type27=1 +Type28=1 +Type29=1 +Type30=1 +Type31=1 +Type32=1 +Type33=1 +Type34=1 +Type35=1 +Type36=1 +Type37=1 +Type38=1 +Type39=1 +Type40=1 +Type41=1 +Type42=1 +Type43=1 +Type44=1 +Type45=1 +Type46=1 +Type47=1 +Type48=1 +Type49=1 +Type50=1 +Type51=1 +Type52=1 +Type53=1 +Type54=1 +Type55=1 +Type56=1 +Type57=1 +Type58=1 +Type59=1 +Type60=1 +Type61=1 +Type62=1 +Type63=1 +Type64=1 +Type65=1 +Type66=1 +Type67=1 +Type68=1 +Type69=1 +Type70=1 +Type71=1 +Type72=1 +Type73=1 +Type74=1 +Type75=1 +Type76=1 +Type77=1 +Type78=1 +Type79=1 +Type80=1 +Type81=1 +Type82=1 +Type83=1 +Type84=1 +Type85=1 +Type86=1 +Type87=1 +Type88=1 +Type89=1 +Type90=1 +Type91=1 +Type92=1 +Type93=1 +Type94=1 +Type95=1 +Type96=1 +Type97=1 +Type98=1 +Type99=1 +Type100=1 +Type101=1 +Type102=1 +Type103=1 +Type104=1 +Type105=1 +Type106=1 +Type107=1 +Type108=1 +Type109=1 +Type110=1 +Type111=1 +Type112=1 +Type113=1 +Type114=1 +Type115=1 +Type116=1 +Type117=1 +Type118=1 +Type119=1 +Type120=1 +Type121=1 +Type122=1 +Type123=1 +Type124=1 +Type125=1 +Type126=1 +Type127=1 +Type128=1 +Type129=1 +Type130=1 +Type131=1 +Type132=1 +Type133=1 +Type134=1 +Type135=1 +Type136=1 +Type137=1 +Type138=1 +Type139=1 +Type140=1 +Type141=1 +Type142=1 +Type143=1 +Type144=1 +Type145=1 +Type146=1 +Type147=1 +Type148=1 +Type149=1 +Type150=1 + +[Difference Levels] +Type1=1 +Type2=1 +Type3=1 +Type4=1 +Type5=1 +Type6=1 +Type7=1 +Type8=1 +Type9=1 +Type10=1 +Type11=1 +Type12=1 +Type13=1 +Type14=1 +Type15=1 +Type16=1 +Type17=1 +Type18=1 +Type19=1 +Type20=1 +Type21=1 +Type22=1 +Type23=1 +Type24=1 +Type25=1 +Type26=1 +Type27=1 +Type28=1 +Type29=1 +Type30=1 +Type31=1 +Type32=1 +Type33=1 +Type34=1 +Type35=1 +Type36=1 +Type37=1 +Type38=1 +Type39=1 +Type40=1 +Type41=1 +Type42=1 +Type43=1 +Type44=1 +Type45=1 +Type46=1 +Type47=1 +Type48=1 +Type49=1 +Type50=1 +Type51=1 +Type52=1 +Type53=1 +Type54=1 +Type55=1 +Type56=1 +Type57=1 +Type58=1 +Type59=1 +Type60=1 +Type61=1 +Type62=1 +Type63=1 +Type64=1 +Type65=1 +Type66=1 +Type67=1 +Type68=1 +Type69=1 +Type70=1 +Type71=1 +Type72=1 +Type73=1 +Type74=1 +Type75=1 +Type76=1 +Type77=1 +Type78=1 +Type79=1 +Type80=1 +Type81=1 + +[Electrical Rules Check] +Type1=1 +Type2=1 +Type3=2 +Type4=1 +Type5=2 +Type6=2 +Type7=0 +Type8=1 +Type9=1 +Type10=1 +Type11=2 +Type12=2 +Type13=2 +Type14=1 +Type15=1 +Type16=1 +Type17=1 +Type18=1 +Type19=1 +Type20=0 +Type21=0 +Type22=0 +Type23=0 +Type24=1 +Type25=2 +Type26=0 +Type27=2 +Type28=1 +Type29=1 +Type30=1 +Type31=1 +Type32=2 +Type33=0 +Type34=2 +Type35=1 +Type36=2 +Type37=1 +Type38=2 +Type39=2 +Type40=2 +Type41=0 +Type42=2 +Type43=1 +Type44=0 +Type45=0 +Type46=0 +Type47=0 +Type48=0 +Type49=0 +Type50=2 +Type51=0 +Type52=0 +Type53=1 +Type54=1 +Type55=1 +Type56=2 +Type57=1 +Type58=1 +Type59=2 +Type60=0 +Type61=0 +Type62=0 +Type63=0 +Type64=0 +Type65=2 +Type66=3 +Type67=2 +Type68=2 +Type69=2 +Type70=2 +Type71=2 +Type72=2 +Type73=2 +Type74=1 +Type75=2 +Type76=1 +Type77=1 +Type78=1 +Type79=1 +Type80=2 +Type81=3 +Type82=3 +Type83=3 +Type84=3 +Type85=3 +Type86=2 +Type87=2 +Type88=2 +Type89=1 +Type90=1 +Type91=3 +Type92=3 +Type93=2 +Type94=2 +Type95=2 +Type96=2 +Type97=2 +Type98=0 +Type99=1 +Type100=2 +Type101=0 +Type102=2 +Type103=2 +Type104=1 +Type105=2 +Type106=2 +Type107=2 +Type108=2 +Type109=1 +Type110=1 +Type111=1 +Type112=1 +Type113=1 +Type114=2 +Type115=2 +Type116=2 +Type117=3 +Type118=3 +Type119=3 +MultiChannelAlternate=0 +AlternateItemFail=3 +Type122=2 +Type123=1 +Type124=1 +Type125=1 +Type126=1 +Type127=1 +Type128=2 +Type129=2 +Type130=2 +Type131=2 +Type132=2 +Type133=2 +Type134=2 +Type135=2 +Type136=2 +Type137=2 +Type138=1 +Type139=1 +Type140=1 +Type141=1 +Type142=1 +Type143=1 +Type144=1 +Type145=1 +Type146=1 +Type147=2 +Type148=2 +Type149=2 +Type150=2 +Type151=2 +Type152=1 +Type153=1 +Type154=0 + +[ERC Connection Matrix] +L1=NNNNNNNNNNNWNNNWW +L2=NNWNNNNWWWNWNWNWN +L3=NWEENEEEENEWNEEWN +L4=NNENNNWEENNWNENWN +L5=NNNNNNNNNNNNNNNNN +L6=NNENNNNEENNWNENWN +L7=NNEWNNWEENNWNENWN +L8=NWEENEENEEENNEENN +L9=NWEENEEEENEWNEEWW +L10=NWNNNNNENNEWNNEWN +L11=NNENNNNEEENWNENWN +L12=WWWWNWWNWWWNWWWNN +L13=NNNNNNNNNNNWNNNWW +L14=NWEENEEEENEWNEEWW +L15=NNENNNNEEENWNENWW +L16=WWWWNWWNWWWNWWWNW +L17=WNNNNNNNWNNNWWWWN + +[Annotate] +SortOrder=3 +SortLocation=0 +ReplaceSubparts=0 +MatchParameter1=Comment +MatchStrictly1=1 +MatchParameter2=Library Reference +MatchStrictly2=1 +PhysicalNamingFormat=$Component_$RoomName +GlobalIndexSortOrder=3 +GlobalIndexSortLocation=0 + +[PrjClassGen] +CompClassManualEnabled=0 +CompClassManualRoomEnabled=0 +NetClassAutoBusEnabled=1 +NetClassAutoCompEnabled=0 +NetClassAutoNamedHarnessEnabled=0 +NetClassManualEnabled=1 +NetClassSeparateForBusSections=0 + +[LibraryUpdateOptions] +SelectedOnly=0 +UpdateVariants=1 +UpdateToLatestRevision=1 +PartTypes=0 +FullReplace=1 +UpdateDesignatorLock=1 +UpdatePartIDLock=1 +PreserveParameterLocations=1 +PreserveParameterVisibility=1 +DoGraphics=1 +DoParameters=1 +DoModels=1 +AddParameters=0 +RemoveParameters=0 +AddModels=1 +RemoveModels=1 +UpdateCurrentModels=1 + +[DatabaseUpdateOptions] +SelectedOnly=0 +UpdateVariants=1 +UpdateToLatestRevision=1 +PartTypes=0 + +[Comparison Options] +ComparisonOptions0=Kind=Net|MinPercent=75|MinMatch=3|ShowMatch=-1|UseName=-1|InclAllRules=0 +ComparisonOptions1=Kind=Net Class|MinPercent=75|MinMatch=3|ShowMatch=-1|UseName=-1|InclAllRules=0 +ComparisonOptions2=Kind=Component Class|MinPercent=75|MinMatch=3|ShowMatch=-1|UseName=-1|InclAllRules=0 +ComparisonOptions3=Kind=Rule|MinPercent=75|MinMatch=3|ShowMatch=-1|UseName=-1|InclAllRules=0 +ComparisonOptions4=Kind=Differential Pair|MinPercent=50|MinMatch=1|ShowMatch=0|UseName=0|InclAllRules=0 +ComparisonOptions5=Kind=Structure Class|MinPercent=75|MinMatch=3|ShowMatch=-1|UseName=-1|InclAllRules=0 + +[SmartPDF] +PageOptions=Record=PageOptions|CenterHorizontal=True|CenterVertical=True|PrintScale=1.00|XCorrection=1.00|YCorrection=1.00|PrintKind=1|BorderSize=5000000|LeftOffset=0|BottomOffset=0|Orientation=2|PaperLength=1000|PaperWidth=1000|Scale=100|PaperSource=7|PrintQuality=-3|MediaType=1|DitherType=10|PrintScaleMode=1|PaperKind=Letter|PaperIndex=1 + diff --git a/Scripts - PCB/DiffPairFinder/DiffPair_Finder.dfm b/Scripts - PCB/DiffPairFinder/DiffPair_Finder.dfm new file mode 100644 index 00000000..099bc689 --- /dev/null +++ b/Scripts - PCB/DiffPairFinder/DiffPair_Finder.dfm @@ -0,0 +1,79 @@ +object Form1: TForm1 + Left = 0 + Top = 0 + Caption = 'Differential Pair Finder' + ClientHeight = 679 + ClientWidth = 930 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + DesignSize = ( + 930 + 679) + PixelsPerInch = 96 + TextHeight = 13 + object Label1: TLabel + Left = 8 + Top = 608 + Width = 166 + Height = 13 + Caption = 'Hold SHIFT to select multiple pairs.' + end + object StringGrid: TStringGrid + Left = 8 + Top = 8 + Width = 912 + Height = 592 + Anchors = [akLeft, akTop, akRight] + ColCount = 3 + DefaultColWidth = 300 + Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goRangeSelect, goColSizing, goRowSelect, goFixedColClick] + ScrollBars = ssVertical + TabOrder = 0 + ColWidths = ( + 300 + 300 + 300) + RowHeights = ( + 24 + 24 + 24 + 24 + 24) + end + object btnAddDiffPairs: TButton + Left = 744 + Top = 640 + Width = 176 + Height = 25 + Anchors = [akRight, akBottom] + Caption = 'Add Selected To DiffPair Class' + TabOrder = 1 + OnClick = btnAddDiffPairsClick + end + object cbDiffPairClasses: TComboBox + Left = 744 + Top = 608 + Width = 177 + Height = 21 + Anchors = [akRight, akBottom] + TabOrder = 2 + Text = 'Select DiffPair Class' + end + object cbHideExisting: TCheckBox + Left = 8 + Top = 648 + Width = 97 + Height = 17 + Anchors = [akLeft, akBottom] + Caption = 'Hide Existing' + Checked = True + State = cbChecked + TabOrder = 3 + OnClick = cbHideExistingClick + end +end diff --git a/Scripts - PCB/DiffPairFinder/DiffPair_Finder.pas b/Scripts - PCB/DiffPairFinder/DiffPair_Finder.pas new file mode 100644 index 00000000..6fa2c962 --- /dev/null +++ b/Scripts - PCB/DiffPairFinder/DiffPair_Finder.pas @@ -0,0 +1,1180 @@ +// References: Altium Examples CreateAVia.pas +// PCB_Class_Generator_Form.pas +// ChatGPT 4o + +var + Board : IPCB_Board; + GlbDiffPairs : TStringList; + +Function DiffPolarity(txt: String): Integer; +var + polarity : Integer; + t : String; + isIn : Boolean; +Begin + result := 0; + + t := LowerCase(txt); + + // If Else to Force priority ordering + If AnsiEndsStr('_dp', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('_dn', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('_dm', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('-dp', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('-dn', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('-dm', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('_p', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('_n', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('-p', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('-n', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('dp', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('dn', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('dm', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('_h', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('_l', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('-h', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('-l', t) Then + Begin + result := -1; + End + Else If AnsiEndsStr('+', t) Then + Begin + result := 1; + End + Else If AnsiEndsStr('-', t) Then + Begin + result := -1; + End + Else If ContainsText(t, '_dp') Then + Begin + result := 1; + End + Else If ContainsText(t, '_dn') Then + Begin + result := -1; + End + Else If ContainsText(t, '_dm') Then + Begin + result := -1; + End + Else If ContainsText(t, '-dp') Then + Begin + result := 1; + End + Else If ContainsText(t, '-dn') Then + Begin + result := -1; + End + Else If ContainsText(t, '-dm') Then + Begin + result := -1; + End + Else If ContainsText(t, '_p') Then + Begin + result := 1; + End + Else If ContainsText(t, '_n') Then + Begin + result := -1; + End + Else If ContainsText(t, '-p') Then + Begin + result := 1; + End + Else If ContainsText(t, '-n') Then + Begin + result := -1; + End + Else If ContainsText(t, '+') And Not(AnsiStartsStr('+', t)) Then + Begin + result := 1; + End + Else If ContainsText(t, 'dp') And Not(AnsiStartsStr('dp', t)) Then + Begin + result := 1; + End + Else If ContainsText(t, 'dn') And Not(AnsiStartsStr('dn', t)) Then + Begin + result := -1; + End + Else If ContainsText(t, 'dm') And Not(AnsiStartsStr('dm', t)) Then + Begin + result := -1; + End + Else If ContainsText(t, 'p_') Then + Begin + result := 1; + End + Else If ContainsText(t, 'n_') Then + Begin + result := -1; + End + Else If ContainsText(t, '_h') Then + Begin + result := 1; + End + Else If ContainsText(t, '_l') Then + Begin + result := -1; + End + Else If ContainsText(t, '-h') Then + Begin + result := 1; + End + Else If ContainsText(t, '-l') Then + Begin + result := -1; + End + Else If ContainsText(t, 'h_') Then + Begin + result := 1; + End + Else If ContainsText(t, 'l_') Then + Begin + result := -1; + End + Else If ContainsText(t, 'p-') Then + Begin + result := 1; + End + Else If ContainsText(t, 'n-') Then + Begin + result := -1; + End + Else If ContainsText(t, 'h-') Then + Begin + result := 1; + End + Else If ContainsText(t, 'l-') Then + Begin + result := -1; + End; +End; + +Function IsPotentialDiffPair(txt: String): Boolean; +var + polarity : Integer; + t : String; + isIn : Boolean; +Begin + result := False; + + t := LowerCase(txt); + + if Not(AnsiStartsStr('net', t)) and (txt <> 'gnd') then + Begin + polarity := DiffPolarity(txt); + if (polarity = -1) or (polarity = 1) then + begin + result := True; + end; + End; +End; + +Function GetAllPinsSortedByComponent(Dummy): TStringList; // Dummy hides visibility. Use Nil in call. +Var + Iterator : IPCB_BoardIterator; + GrpIter : IPCB_GroupIterator; + Cmp : IPCB_Component; + Pad : IPCB_Pad; + cmps : TStringList; + CmpDes, NetName, PinDes, Value, FirstEntry : String; +Begin + cmps := TStringList.Create; + cmps.NameValueSeparator := '='; + + Iterator := Board.BoardIterator_Create; + Iterator.AddFilter_ObjectSet(MkSet(eComponentObject)); + Iterator.AddFilter_IPCB_LayerSet(LayerSet.AllLayers); + Iterator.AddFilter_Method(eProcessAll); + + Cmp := Iterator.FirstPCBObject; + While (Cmp <> Nil) Do + Begin + CmpDes := Cmp.Name.Text; + + FirstEntry := ''; + + GrpIter := Cmp.GroupIterator_Create; + GrpIter.SetState_FilterAll; + GrpIter.AddFilter_ObjectSet(MkSet(ePadObject)); + + Pad := GrpIter.FirstPCBObject; + While Pad <> Nil Do + Begin + If Pad.InComponent Then + Begin + If Pad.Net <> Nil Then + Begin + NetName := Pad.Net.Name; + Value := cmps.Values[CmpDes]; + + // If NetName not already in list and is a potential DiffPair + If Not(ContainsText(FirstEntry+Value, NetName)) And IsPotentialDiffPair(NetName) Then + Begin + + // If CmpDes Key already exists + If cmps.IndexOfName(CmpDes) >= 0 Then + Begin + cmps.Values[CmpDes] := Value + ';' + NetName; + End + // If Key doesn't exist, but this is the first entry, don't add because we don't want single net entries + Else If FirstEntry = '' Then + Begin + //cmps.Add(CmpDes + '=' + NetName); + FirstEntry := CmpDes + '=' + NetName; + End + // Once we have at least 2 nets ready to add then add first entry at CmpDes Key + // After this, the key will exist so only the first if should be valid + Else + Begin + cmps.Add(FirstEntry + ';' + NetName); + End; + + End; + End; + End; + + Pad := GrpIter.NextPCBObject; + End; + Cmp.GroupIterator_Destroy(GrpIter); + + Cmp := Iterator.NextPCBObject; + End; + + Board.BoardIterator_Destroy(Iterator); + + result := cmps; +End; + +function AlphaOnly(const InputStr: String): String; +var + I: Integer; +begin + Result := ''; + // Iterate through each character in the input string + for I := 1 to Length(InputStr) do + begin + // Check if the character is alphabetic (A-Z, a-z) + if ((InputStr[I] >= 'A') and (InputStr[I] <= 'Z')) or + ((InputStr[I] >= 'a') and (InputStr[I] <= 'z')) then + begin + Result := Result + InputStr[I]; // Add the character to the result + end; + end; +end; + +function IsNonAlphaNumeric(const Ch: Char): Boolean; +begin + // Check if the character is not alphanumeric + Result := not ((Ch >= '0') and (Ch <= '9') or + (Ch >= 'A') and (Ch <= 'Z') or + (Ch >= 'a') and (Ch <= 'z')); +end; + +function TrimNonAlphaNumeric(const InputStr: String): String; +var + Len: Integer; +begin + Result := InputStr; + Len := Length(Result); + + // Loop to remove non-alphanumeric characters from the end + while (Len > 0) and IsNonAlphaNumeric(Result[Len]) do + begin + Delete(Result, Len, 1); // Remove the last character + Len := Len - 1; // Update the length + end; +end; + +Function IsOffByNChar(txt1: String, txt2: String, n: Integer, var diffName : String): Boolean; +Var + i, matchCnt, digCnt : Integer; + ch1, ch2, prev : Char; + ch1Valid, ch2Valid: Boolean; +Begin + result := False; + ch1Valid := False; + ch2Valid := False; + diffName := ''; + + matchCnt := 0; + digCnt := 0; + For i := 1 to Length(txt1) Do + Begin + ch1 := LowerCase(txt1[i]); + ch2 := LowerCase(txt2[i]); + + If ch1 = ch2 Then + Begin + Inc(matchCnt); + If Not(IsNonAlphaNumeric(ch1) And IsNonAlphaNumeric(prev)) Then + Begin + diffName := diffName+ch1; + prev := ch1; + End; + End + Else + Begin + If (ch1 = 'p') or (ch1 = 'n') or (ch1 = 'm') or (ch1 = '+') or (ch1 = '-') or (ch1 = 'h') or (ch1 = 'l') Then ch1Valid := True; + If (ch2 = 'p') or (ch2 = 'n') or (ch2 = 'm') or (ch2 = '+') or (ch2 = '-') or (ch2 = 'h') or (ch2 = 'l') Then ch2Valid := True; + End; + + End; + + + + if (matchCnt >= Length(txt1)-n) and ch1Valid and ch2Valid Then + Begin + result := True; + End; + + diffName := UpperCase(TrimNonAlphaNumeric(diffName)); +End; + +Function CompareSameLenNets(matches: TStringList, cnts: TStringList): TStringList; +Var + cnt, viewed : TStringList; + i, j, cntIdx, cntsLen, cntLen, polarity: Integer; + net1, net2, diffName : String; + IsMatch : Boolean; +Begin + cnt := TStringList.Create; + cnt.Delimiter := ';'; + cnt.StrictDelimiter := True; + + viewed := TStringList.Create; + viewed.Sorted := True; + viewed.Duplicates := dupIgnore; + + cntsLen := cnts.Count; + + for cntIdx := 0 to cnts.Count-1 do + begin + cnt.DelimitedText := cnts.ValueFromIndex[cntIdx]; + + if cnt.Count <= 1 then continue; + + for i := 0 to cnt.Count - 1 do + begin + net1 := cnt[i]; + + for j := 0 to cnt.Count - 1 do + begin + + // Don't compare the same net against itself + if i <> j then + begin + net2 := cnt[j]; + + // previously viewed can be skipped + if viewed.IndexOf(net1 + net2) = -1 then + begin + IsMatch := IsOffByNChar(net1, net2, 1, diffName); + + If IsMatch Then + Begin + polarity := DiffPolarity(net1); + if polarity = 1 then + begin + matches.Add(diffName+'='+net1+';'+net2); + end + else + begin + matches.Add(diffName+'='+net2+';'+net1); + end; + End; + + viewed.Add(net1+net2); + viewed.Add(net2+net1); + end; + end; + end; + end; + viewed.Clear; + end; + + cnt.Free; + viewed.Free; +End; + +Function FindDiffPairCandidates(cmps: TStringList): TStringList; +Const + pIdx = 0; + nIdx = 1; +Var + pinStr, netStr, cmpDes: String; + cmpIdx, netIdx, pinsCnt, pinCnt, len: Integer; + nets, cnts, tmp, matches: TStringList; + doCompare : Boolean; +Begin + nets := TStringList.Create; + nets.Delimiter := ';'; + nets.StrictDelimiter := True; + + tmp := TStringList.Create; + tmp.Delimiter := ';'; + tmp.StrictDelimiter := True; + + cnts := TStringList.Create; + cnts.NameValueSeparator := '='; + + matches := TStringList.Create; + matches.Sorted := True; + matches.Duplicates := dupIgnore; + matches.NameValueSeparator := '='; + + // Build a dictionary of dict[StringLength] = DelimitedNetList + // For each component, build a cnts dictionary that holds the length of + // each string as a key + for cmpIdx := 0 to cmps.Count-1 do + begin + nets.DelimitedText := cmps.ValueFromIndex[cmpIdx]; + + doCompare := False; // Reset for each component + + for netIdx := 0 to nets.Count - 1 do + begin + netStr := nets[netIdx]; + + // Filter out all other nets for speed + If IsPotentialDiffPair(netStr) Then + Begin + len := IntToStr(Length(netStr)); + + If cnts.IndexOfName(len) >= 0 Then + Begin + tmp.DelimitedText := cnts.Values[len]; + If tmp.IndexOf(netStr) = -1 Then + Begin + cnts.Values[len] := cnts.Values[len] + ';' + netStr; + doCompare := True; // There is at least one set of matching lengths worth checking + End; + End + Else + Begin + cnts.Add(len + '=' + netStr); + End; + + End; + + end; + + If doCompare Then CompareSameLenNets(matches, cnts); // Iterate Same Length Strings and compare + cnts.Clear; + end; + + nets.Free; + cnts.Free; + tmp.Free; + + result := matches; +End; + +Function GetNetObject(NetName: String): IPCB_Net; +Var + Iterator : IPCB_BoardIterator; + Net : IPCB_Net; +Begin + result := Nil; + + Iterator := Board.BoardIterator_Create; + Iterator.AddFilter_ObjectSet(MkSet(eNetObject)); + Iterator.AddFilter_LayerSet(AllLayers); + Iterator.AddFilter_Method(eProcessAll); + + Net := Iterator.FirstPCBObject; + While (Net <> Nil) Do + Begin + If Net.Name = NetName Then + Begin + result := Net; + Break; + End; + + Net := Iterator.NextPCBObject; + End; + Board.BoardIterator_Destroy(Iterator); +End; + +Function GetExistingDiffPairs(Dummy): TStringList; +Var + Iterator : IPCB_BoardIterator; + Existing : TStringList; + Diff : IPCB_DifferentialPair; +Begin + Existing := TStringList.Create; + + Iterator := Board.BoardIterator_Create; + Iterator.AddFilter_ObjectSet(MkSet(eDifferentialPairObject)); + Iterator.AddFilter_LayerSet(AllLayers); + Iterator.AddFilter_Method(eProcessAll); + + Diff := Iterator.FirstPCBObject; + While (Diff <> Nil) Do + Begin + If (Diff.PositiveNet <> Nil) And (Diff.NegativeNet <> Nil) Then + Begin + Existing.Add(LowerCase(Diff.PositiveNet.Name)); + Existing.Add(LowerCase(Diff.NegativeNet.Name)); + End; + + Diff := Iterator.NextPCBObject; + End; + Board.BoardIterator_Destroy(Iterator); + + result := Existing; +End; + +Function AddDiffPairClass(ClassName: String): IPCB_ObjectClass; +Var + DiffClass : IPCB_ObjectClass; +Begin + PCBServer.PreProcess; // Initialize the systems in the PCB Editor. + + DiffClass := PCBServer.PCBClassFactoryByClassMember(eClassMemberKind_DifferentialPair); + DiffClass.SuperClass := False; + DiffClass.Name := ClassName; + + Board.AddPCBObject(DiffClass); + + // Update the Undo System in DXP that a new object has been added to the board + PCBServer.SendMessageToRobots(Board .I_ObjectAddress, c_Broadcast, PCBM_BoardRegisteration, DiffClass.I_ObjectAddress); + + PCBServer.PostProcess; // Finalize the systems in the PCB Editor. + + result := DiffClass; +End; + +Function AddDiffPair(DiffClass: IPCB_ObjectClass, ExistingPairs: TStringList, DiffPairName: String, PositiveNet: String, NegativeNet: String); +Var + DiffPair : IPCB_DifferentialPair; + pLow, nLow : String; + pGood, nGood : Boolean; +Begin + + // Check if Diff pair positive or negative net name already exists + If (ExistingPairs.IndexOf(LowerCase(PositiveNet)) <> -1) Or (ExistingPairs.IndexOf(LowerCase(NegativeNet)) <> -1) Then Exit; + + PCBServer.PreProcess; // Initialize the systems in the PCB Editor. + + DiffPair := PCBServer.PCBObjectFactory(eDifferentialPairObject, eNoDimension, eCreate_Default); + + DiffPair.PositiveNet := GetNetObject(PositiveNet); + DiffPair.NegativeNet := GetNetObject(NegativeNet); + + DiffPair.Name := DiffPairName; + + Board.AddPCBObject(DiffPair); + + // Update the Undo System in DXP that a new object has been added to the board + PCBServer.SendMessageToRobots(Board .I_ObjectAddress, c_Broadcast, PCBM_BoardRegisteration, DiffPair.I_ObjectAddress); + + // Class was specified, add to specific class. + If DiffClass <> Nil Then + Begin + DiffClass.AddMemberByName(DiffPair.Name); + End; + + PCBServer.PostProcess; // Finalize the systems in the PCB Editor. +End; + +Function AddDiffPairs(DiffClass: IPCB_ObjectClass, diffs: TStringList); +Const + pIdx = 0; + nIdx = 1; +Var + i, pairCnt : Integer; + pair, existingPairs : TStringList; + diffName, pStr, nStr, pairStr : String; +Begin + pair := TStringList.Create; + pair.Delimiter := ';'; + pair.StrictDelimiter := True; + + existingPairs := GetExistingDiffPairs(Nil); // Get existing differential pairs + + For i := 0 to diffs.Count - 1 do + Begin + diffName := diffs.Names[i]; + pairStr := diffs.ValueFromIndex[i]; + pair.DelimitedText := pairStr; + + pairCnt := pair.Count; + + if pairCnt = 2 Then + Begin + pStr := pair[pIdx]; + nStr := pair[nIdx]; + + AddDiffPair(DiffClass, existingPairs, diffName, pStr, nStr); + + existingPairs.Add(LowerCase(pStr)); + existingPairs.Add(LowerCase(nStr)); + End; + End; + + existingPairs.Free; +End; + +Function ValidComponent(Cmp: IPCB_Component, NetName: String): Boolean; +Var + GrpIter : IPCB_GroupIterator; + Pad : IPCB_Pad; + Cnt : Integer; + HasNet : Boolean; +Begin + result := False; + HasNet := False; + + GrpIter := Cmp.GroupIterator_Create; + GrpIter.SetState_FilterAll; + GrpIter.AddFilter_ObjectSet(MkSet(ePadObject)); + + Cnt := 0; + + Pad := GrpIter.FirstPCBObject; + While Pad <> Nil Do + Begin + If (Pad.InComponent) And (Pad.Net <> Nil) Then + Begin + Inc(Cnt); + + If LowerCase(Pad.Net.Name) = LowerCase(NetName) Then HasNet := True; + + If Cnt > 2 Then Break; + End; + + Pad := GrpIter.NextPCBObject; + End; + Cmp.GroupIterator_Destroy(GrpIter); + + If (Cnt = 2) And (HasNet) Then result := True; +End; + +Function GetConnectedNetName(Cmp: IPCB_Component, NetName: String): String; +Var + GrpIter : IPCB_GroupIterator; + Pad : IPCB_Pad; + conName, CmpDes : String; +Begin + result := ''; + + CmpDes := Cmp.Name.Text; + + GrpIter := Cmp.GroupIterator_Create; + GrpIter.SetState_FilterAll; + GrpIter.AddFilter_ObjectSet(MkSet(ePadObject)); + + Pad := GrpIter.FirstPCBObject; + While Pad <> Nil Do + Begin + If Pad.InComponent Then + Begin + If Pad.Net <> Nil Then + Begin + conName := Pad.Net.Name; + If (LowerCase(conName) <> LowerCase(NetName)) And Not(ContainsText(LowerCase(conName), 'gnd')) Then + Begin + result := conName; + Exit; + End; + End; + End; + + Pad := GrpIter.NextPCBObject; + End; + Cmp.GroupIterator_Destroy(GrpIter); +End; + +Function IsConnectedDiffPair(cwn: TStringList, pStr: String, nStr: String, var pCon: String, var nCon: String): Boolean; +Var + Iterator : IPCB_BoardIterator; + Cmp : IPCB_Component; + inCmps : TStringList; + CmpDes, test : String; + i : Integer; +Begin + inCmps := TStringList.Create; + + result := False; + pCon := ''; + nCon := ''; + + If (cwn.IndexOfName(pStr) = -1) or (cwn.IndexOfName(nStr) = -1) Then Exit; + + inCmps.DelimitedText := cwn.Values[pStr]; + // TODO: How to handle if net has multiple connected R's or C's? + if inCmps.Count > 1 then + begin + ShowMessage(pStr + ' is connected to ' + IntToStr(inCmps.Count) + '2-pin components. Skipping...'); + Exit; + end; + + for i:=0 to inCmps.Count - 1 do + begin + CmpDes := inCmps[i]; + Cmp := Board.GetPcbComponentByRefDes(CmpDes); + + pCon := GetConnectedNetName(Cmp, pStr); + If pCon <> '' Then Break; + end; + + inCmps.DelimitedText := cwn.Values[nStr]; + for i:=0 to inCmps.Count - 1 do + begin + CmpDes := inCmps[i]; + Cmp := Board.GetPcbComponentByRefDes(CmpDes); + + nCon := GetConnectedNetName(Cmp, pStr); + If nCon <> '' Then Break; + end; + + inCmps.Free; + + If (pCon <> '') And (nCon <> '') Then + Begin + result := True; + End; + + Board.BoardIterator_Destroy(Iterator); +End; + +function RemovePrefix(const InputStr, Prefix: String): String; +var + LowerInput, LowerPrefix: String; +begin + // Convert both the input string and the prefix to lowercase for case-insensitive comparison + LowerInput := AnsiLowerCase(InputStr); + LowerPrefix := AnsiLowerCase(Prefix); + + // Check if the input string starts with the specified prefix + if Copy(LowerInput, 1, Length(LowerPrefix)) = LowerPrefix then + Result := Copy(InputStr, Length(LowerPrefix) + 1, Length(InputStr)) + else + Result := InputStr; // Return the original string if no match +end; + +Function FlattenDiffsToNetList(diffs: TStringList): TStringList; +Const + pIdx = 0; + nIdx = 1; +Var + i, pairCnt : Integer; + pair, flat : TStringList; + pairStr : String; +Begin + flat := TStringList.Create; + flat.Delimiter := ','; + flat.StrictDelimiter := True; + + pair := TStringList.Create; + pair.Delimiter := ';'; + pair.StrictDelimiter := True; + + For i := 0 to diffs.Count - 1 do + Begin + pairStr := diffs.ValueFromIndex[i]; + pair.DelimitedText := pairStr; + + pairCnt := pair.Count; + + if pairCnt = 2 Then + Begin + flat.Add(pair[pIdx]); + flat.Add(pair[nIdx]); + End; + End; + + result := flat; +End; + +Function CreateCmpsWithNetsList(nets: TStringList): TStringList; +Var + Iterator : IPCB_BoardIterator; + GrpIter : IPCB_GroupIterator; + Cmp : IPCB_Component; + Pad : IPCB_Pad; + cwn : TStringList; + CmpDes : String; +Begin + cwn := TStringList.Create; + cwn.Duplicates := dupIgnore; + cwn.NameValueSeparator := '='; + + Iterator := Board.BoardIterator_Create; + Iterator.AddFilter_ObjectSet(MkSet(eComponentObject)); + Iterator.AddFilter_IPCB_LayerSet(LayerSet.AllLayers); + Iterator.AddFilter_Method(eProcessAll); + + Cmp := Iterator.FirstPCBObject; + While (Cmp <> Nil) Do + Begin + CmpDes := Cmp.Name.Text; + + // Only consider Resistors and Capacitors + If AnsiStartsStr('R', CmpDes) Or AnsiStartsStr('C', CmpDes) Then + Begin + GrpIter := Cmp.GroupIterator_Create; + GrpIter.SetState_FilterAll; + GrpIter.AddFilter_ObjectSet(MkSet(ePadObject)); + + Pad := GrpIter.FirstPCBObject; + While Pad <> Nil Do + Begin + If Pad.InComponent Then + Begin + If Pad.Net <> Nil Then + Begin + If nets.IndexOf(Pad.Net.Name) >= 0 Then + Begin + cwn.Add(Pad.Net.Name+'='+CmpDes); + End; + End; + End; + + Pad := GrpIter.NextPCBObject; + End; + Cmp.GroupIterator_Destroy(GrpIter); + End; + + Cmp := Iterator.NextPCBObject; + End; + Board.BoardIterator_Destroy(Iterator); + + result := cwn; +End; + +Function GetConnectedDiffPairs(diffs: TStringList, alreadyFound: TStringList): TStringList; +Const + pIdx = 0; + nIdx = 1; +Var + i, pairCnt : Integer; + pair, cwn, newDiffs : TStringList; + diffName, conName, pStr, nStr, pairStr, pConnect, nConnect, suffix : String; +Begin + newDiffs := TStringList.Create; + + pair := TStringList.Create; + pair.Delimiter := ';'; + pair.StrictDelimiter := True; + + cwn := CreateCmpsWithNetsList(alreadyFound); // Components with nets + + For i := 0 to diffs.Count - 1 do + Begin + diffName := diffs.Names[i]; + pairStr := diffs.ValueFromIndex[i]; + pair.DelimitedText := pairStr; + + pairCnt := pair.Count; + + if pairCnt = 2 Then + Begin + pStr := pair[pIdx]; + nStr := pair[nIdx]; + + If IsConnectedDiffPair(cwn, pStr, nStr, pConnect, nConnect) Then + Begin + // New name is old name + designator prefix, unless that already exists, then it is full refDes + suffix := RemovePrefix(pConnect, 'net'); + conName := diffName + '-' + AlphaOnly(suffix); + If (diffs.IndexOf(conName) <> -1) or (newDiffs.IndexOf(conName) <> -1) Then conName := diffName + '-' + suffix; + + If (alreadyFound.IndexOf(pConnect) = -1) and (alreadyFound.IndexOf(nConnect) = -1) Then + Begin + newDiffs.Add(conName+'='+pConnect+';'+nConnect); + + alreadyFound.Add(pConnect); + alreadyFound.Add(nConnect); + End; + End; + End; + End; + + result := newDiffs; +End; + +Procedure AddDiffPairClassesToComboBox(Dummy); +Var + i : Integer; + ClassIterator : IPCB_BoardIterator; + ClassList : TStringList; + DiffClass : IPCB_ObjectClass; + Name : String; +Begin + ClassList := TStringList.Create; + + ClassIterator := Board.BoardIterator_Create; + ClassIterator.SetState_FilterAll; + ClassIterator.AddFilter_ObjectSet(MkSet(eClassObject)); + DiffClass := ClassIterator.FirstPCBObject; + i := 0; + While DiffClass <> Nil Do + Begin + Inc(i); + If DiffClass.MemberKind = eClassMemberKind_DifferentialPair Then + Begin + Name := DiffClass.Name; + //cbDiffPairClasses.items.AddObject(DiffClass.Name, DiffClass); + cbDiffPairClasses.AddItem(DiffClass.Name, DiffClass); + //IPCB_ObjectClass.MemberName[0]; + ClassList.Add(DiffClass.Name); + End; + DiffClass := ClassIterator.NextPCBObject; + End; + cbDiffPairClasses.SetItemIndex(0); + Board.BoardIterator_Destroy(ClassIterator); +End; + +procedure ResetStringGrid(Grid: TStringGrid); +var + Row, Col: Integer; +begin + // Clear all cell contents + for Row := 0 to Grid.RowCount - 1 do + for Col := 0 to Grid.ColCount - 1 do + Grid.Cells[Col, Row] := ''; + + // Reset the grid dimensions + Grid.RowCount := 1; // Keep only one row + Grid.ColCount := 1; // Keep only one column + + // Optionally, reset headers if needed + Grid.Cells[0, 0] := ''; // Clear the header cell or set initial text +end; + +Function AddKeysToStringGrid(list: TStringList, HideExisting: Boolean); +Var + i, RowIdx : Integer; + DiffPairName, pStr, nStr : String; + Row, existing: TStringList; +Begin + Row := TStringList.Create; + Row.Delimiter := ';'; + + existing := GetExistingDiffPairs(Nil); + + // Start adding from the last row + RowIdx := StringGrid.RowCount; // Get current row count + + For i := 0 to list.Count - 1 do + begin + Row.DelimitedText := list.ValueFromIndex[i]; + DiffPairName := list.Names[i]; + pStr := LowerCase(Row[0]); + nStr := LowerCase(Row[1]); + + If (HideExisting) And ((existing.IndexOf(pStr) <> -1) Or (existing.IndexOf(nStr) <> -1)) Then continue; + + // Add a new row if necessary + if RowIdx >= StringGrid.RowCount then + StringGrid.RowCount := StringGrid.RowCount + 1; + + StringGrid.Cells[0, RowIdx] := DiffPairName; // DiffPairName + StringGrid.Cells[1, RowIdx] := Row[0]; // PositiveNetName + StringGrid.Cells[2, RowIdx] := Row[1]; // NegativeNetName + + Inc(RowIdx); + end; +End; + +Function InitStringGrid(diffs: TStringList); +Begin + // Set up StringGrid columns and headers + StringGrid.RowCount := 1; // Add 1 for header row + StringGrid.Cells[0, 0] := 'Diff Pair Name'; + StringGrid.Cells[1, 0] := 'Positive Net Name'; + StringGrid.Cells[2, 0] := 'Negative Net Name'; + + StringGrid.FixedCols := 0; + + AddKeysToStringGrid(diffs, cbHideExisting.Checked); +End; + +{..............................................................................} +Procedure Run(UseGUI : Boolean); +Const + MAX_CONNECTIONS = 3; +Var + cmps : TStringList; + diffs, newDiffs, alreadyFound : TStringList; + DiffClass : IPCB_ObjectClass; + i, idx, cnt : Integer; +Begin + // Retrieve the current board + Board := PCBServer.GetCurrentPCBBoard; + If Board = Nil Then Exit; + + // 1. Get All nets for each pin in a component + cmps := GetAllPinsSortedByComponent(Nil); + + // 2. For given component, if nets' chars all match except 1 char + // add pos/neg net string to TStringList. + // Format: DiffPairName=PositiveNetName;NegativeNetName, ... + diffs := FindDiffPairCandidates(cmps); + cmps.Free; + + // 3. Find all DiffPair Candidates that go through 2 pin components + // and add their nets as well + // Iterate until no new connected pairs are found or max + For i := 0 to MAX_CONNECTIONS - 1 Do + Begin + alreadyFound := FlattenDiffsToNetList(diffs); + newDiffs := GetConnectedDiffPairs(diffs, alreadyFound); + if newDiffs.Count <= 0 then break; + + diffs.AddStrings(newDiffs); // Append new diff pairs list + End; + + GlbDiffPairs := diffs; + + // TODO: Run until no new pairs are found + //newDiffs := GetConnectedDiffPairs(newDiffs); + //diffs.AddStrings(newDiffs); // Append new diff pairs list + + if UseGUI = True then + begin + AddDiffPairClassesToComboBox(Nil); + InitStringGrid(diffs); + + Form1.ShowModal; + end + else + begin + // 4. Create diff pairs in layout + AddDiffPairs(Nil, diffs); + end; +End; +{..............................................................................} + +Procedure RunWithGUI; +Begin + Run(True); +End; + +Procedure RunNoGUI; +Begin + Run(False); +End; + + +Function GetSelectedDiffPairs(Grid: TStringGrid): TStringList; +var + DiffPairs: TStringList; + Row: Integer; + Key, Value: String; + Selection: TGridRect; +begin + DiffPairs := TStringList.Create; + DiffPairs.Sorted := True; + DiffPairs.Duplicates := dupIgnore; + DiffPairs.NameValueSeparator := '='; + + // Get the selection rectangle + Selection := Grid.Selection; + + // Iterate through the rows in the selected range + for Row := Selection.Top to Selection.Bottom do + begin + // Ensure the row is valid (in case of invalid selections) + if (Row >= 0) and (Row < Grid.RowCount) then + begin + // Construct the dictionary key and value + Key := Grid.Cells[0, Row]; // Column 1 + Value := Grid.Cells[1, Row] + ';' + Grid.Cells[2, Row]; // Columns 2 and 3 + + // Add the entry to the TStringList dictionary + DiffPairs.Add(Key + '=' + Value); + end; + end; + + Result := DiffPairs; // Return the resulting TStringList +end; + + + +procedure TForm1.btnAddDiffPairsClick(Sender: TObject); +var + idx : Integer; + ClassObj: IPCB_ObjectClass; + SelectedDiffPairs: StringList; +begin + // Get ComboBox selection index + idx := cbDiffPairClasses.GetItemIndex(); + + // Add Differential Pairs to New Class + if idx < 0 then + begin + ClassObj := AddDiffPairClass(cbDiffPairClasses.Text); + end + // Add Differential Pairs to Existing Class + else + begin + ClassObj := cbDiffPairClasses.Items.Objects[idx]; + end; + + // Get selected diff pairs from String Grid + SelectedDiffPairs := GetSelectedDiffPairs(StringGrid); + + // 4. Create diff pairs in layout + AddDiffPairs(ClassObj, SelectedDiffPairs); + + InitStringGrid(GlbDiffPairs); // Refresh String Grid +end; + + +procedure TForm1.cbHideExistingClick(Sender: TObject); +begin + InitStringGrid(GlbDiffPairs); +end; + diff --git a/Scripts - PCB/DiffPairFinder/README.md b/Scripts - PCB/DiffPairFinder/README.md new file mode 100644 index 00000000..2f074378 --- /dev/null +++ b/Scripts - PCB/DiffPairFinder/README.md @@ -0,0 +1,15 @@ +### [DOWNLOAD](https://altium-designer-addons.github.io/DownGit/#/home?url=https://github.com/Altium-Designer-addons/scripts-libraries/tree/master/Scripts%20-%20PCB/DiffPairFinder) + +# Differential Pair Finder + +## Overview +Finds diff pairs in layout by filtering through net names. It will also find non-obvious nets by looking for pairs that connect through resistors and capacitors. + +## Usage +Run with or without a GUI. In GUI mode, you can add pairs to a selected class or enter a new class name. If you run without a GUI it will just add all pairs to the `All Differential Pairs` class. + +![GUI](gui.jpg) + +## Credits +- From the Altium Script Examples: Matt Berggren & David Parker's PCB_Class_Generator_Form.pas on how to add classes and nets to classes +- GPT4o \ No newline at end of file diff --git a/Scripts - PCB/DiffPairFinder/gui.jpg b/Scripts - PCB/DiffPairFinder/gui.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2e4c03d3ae59e5093b4993ea853caf7f93bacb57 GIT binary patch literal 143754 zcmeFa2UJsAn?D=`1wlYiK)Om*n$kNW3Ib9DsR1HVLx3o~M^uVb0RaI4=^#y{*N8L$ z0U~V13V!80fg?&$XD>6KW4`=<{UUw@Fi@T7BF`l!V+5RFAR}iWBeny$Nh3c= z;>jOu`SBtp;@)01AeajF+yfo;r8Wn)34F z^WwpASyVhXD_WTh2G@Bd9=bg}P0h@5ft8JqUqJB6RY@sn8Cf}bwOhBiPqO}` z>~C~2kmx!=K|xMINfHl$?1VSzAZMUBdFlEoM%8CSw2plTF=9_#h#h4 z^s%{>I_)Bg(&S6ldyz8Mo?F4^rl~mJz#WF&)NT?W0v<%_;TfxSmbA>zBzz2_4w31b zg3@Kfe7C>fAOgOE15EN;y`|H<1N}rwR?;){O=GWd1k`c*nJ76`hSZx(;%rQBicj2I zCjwe?PbglQ+N6J+-$n$qk0^_Q4lz&q{z7i%Wqt)}h zkqDqZYQ=6}`OdvB5=I2PC|15cDypdRP3$a$S@RqQ+z_yLPx#|2hdbj>9#HYxx<3{2 z)lObN_TW#KG0{oC2}I*Bx_JnuG^!-0lLqEJM&OSeQ-< zf(ZE3vhIzi_M;@wSQ7!$kiH#kRPwHjm5?;^TlWUa&VwPiejg5fB##0;nQ@N z$=#>!z$Qg+dqX_EteOKEw`yPFh=AO!fNCN@G{bUmk$b(oiIWJpnGs9`JRO7Wr`o}z zJqmXebhvgm%{(3MjDjyATp1}66CP=}mAq^`!@v;>pTF0yu93HcA_79EkFM&KAIr?E z5SaF!!M_`RRapnp69MP$^X%tMnQcQXby2H?>Cu(ial$|@rkl6tUC9tHguyG?TTt}W zSKT4i>1h1}OH>Ui;3()M5wLGENk;@^>5&B8>a23CW0Wv$67mpvD#=p-Qm%Y~HK!_N zN|WEnQLU%Y#&QY?wkLb>v73V2vKdB8SZxl;t8ajAl7{6A`P*o2OB zmJJs(bavC+Xb1Ha9HUcgsM>E?%u0VbFZ+;|p(!5nu3?+dvYHb==ceZgImSWz0=BVg z?tkwPwa^}U$0M!tYdaieY?5@X&!q^w$K0-=G}P8?eEVi^ti+jmi}IjXH@6<&JJRhP zMIHwiTj9^ac+2`S|4yZyPp{?1$%2R~7w$F_Kc%>)il)ZY8KcVhDUEn*GWG5p6n&~& zmu#0-vceUaDkE$>TgXr#3M8F|XD$A_#+Km4rlnJ4LXRa1A!jE|HOqmjS08rzK6o*Q zV&d{tW3zir)|@QIRh^q7*oW|cnfiEskpN8nKeV72GShrnp;4Q?@2({lYlQ&<`7+WT ziCe!`U%Ejb9r8*d{`_Ve&6~SWA>ccB@8JOxU$6f*-iQbg36vTm>DIqAqcWTJ47mnG zkkIX^fql&Yu`Kg68voZw(HcumPdn{a&grI$RQDVwBY!DsF+qA}Q@mMp1mCV^2R zAf)^tr-1Yk_-*a*{5JhD^B=Z63OUyJT2+_m>7qX|(dX{VaeeX7sJD^E*XvHUB%{QI zP4a8szP%??{WL$cw+Kt#L0WGrpfJgkWi319GZlG%A76>eg#g1r5AIVKCwa>y%gOGX z?xL~h)u}!a&in$2FCWT|hmv{ej9uh-_Ee|SqTE04`(&^#*U&_>S0L@c-=)cGB|8YO z##N=P@)HIVZ5Vxx-4z+`EY{ojK7BpoMsY%!oz*^2dzl9|5 zz5K&jA`I&OwXq=@X*iI_LTi+;uLW;m-)guC{0-)!pSq;}F2=H?$oCa}u)lf9yzCWW zchKM6+@j;}UVn4oHwS)m;5P^UXLFzo(jvUR7eW{y0!~Xe=YhGwm|2+Pqy}^z*NJQV z+%F^g7{N12iVS*xi;$Xm$2Zqq>))vre9sVBCuG5t1B!u4x~z5qC%T-986S}ea0ZiN zhuD8d=&6sTU7WnQaXU1tNM{Cq)(qA@V^9-=>PPEsX2-CPXGNQQskT?)g~Xf2yOSdL zA`$TSnTE#4TDDB|F(`it)jU~_k1G+WZtk1a&usyknfFyUy`C`)OIi0?pz!Qqv3|Js zpH0(b^HX5D{5%b$NJJos|IX?|BZrXii}Il-H7Q?G@x-W}w+xBm{yV;K1FgT8D#yj{ ztG4t(hyWV$-Yvxy?h1Ue?2(s5di_jyKb|y8@e10FtT5w*{>vfPmb^_u>()G-U(&9h zeqo@UVq`S`03h0WLtk_D31H#LNfw)mXa6cd*r>&w%UNs?Xb)7z-bR$Hh+ws2)FXyY zzR+g1I~lHj>JebzeKEFb;W&{~hS17D1bkmCHut|UJaGt|+B=S4J52imEgQli5r8$S zj7TB^MnX>aFdD>s-&&3hYe=fhankomv#M=q$-I-PSry-_2k{ZHNxb2EMn|afvsRhr zqib&g^$#bX&3EBdr*co&YW0ACajtHprL~Qu2`cA-U z-hy82DPOGx(f1$|Iv&gHCWY3@JZiYyMTm9dH9UJY;*rt%I8T|-pyCgf-Hf>R7^px{ zz|UmDU0suoIS1$D!&+a9DJpzBl6agmiScpjE_t==cNJ?s!E^PL&FMI;78`>LD&&vk z2DnOp(vvoykcKG^MALRRVvC{kYu@{nPhp`1`;-zO%u$toHz})N5?AwKb0%yhd&1W- zt)Ho7pi4#2Ibdv|`3GO`52u26UCK@BYK#eMV!f6sEc1^@oS-YqZhZD-G)LO2;rOuc zgND7ak%aKnjDz^uG4SRE!H*Va-Q%#nKScVxl!@zw)TV#=vgb^BAf1IFIiozd_U|W+35c|Bzh-RH)iN{I4tcV(`NX0 z_r}7tk)H#4eN@`*N(AVrqaV+aW+f}gr2+Ykuuogl0~gGeHbG-0(pdZJ9p3pgDK4q3 zO+zlT;$-wGpX#YKshgsxw?Wb>YvuTzTT0#T8vYXodpVzXD?tMF9gc8PE}-IA2mB5O z_J!N087B7}DPyqCb($6FUF^~>i(3wg9%abB*rR2VsvAbmSrkL~HqEoT>!BExREy$u z1mScveb{j(7sw|JCwF9=c`|wY7~VM7EwqZsaG#&KFatHrkPi5vB7Cd)$tJM$68<&F zc5{mtd^ScveIJHTnAWz`JJRkuQf$c0Fd5%nJ+k|x6Sb=1Zas8j`biojl!Ppd}wJ~h)Dm@{jVIBqQ;8}5 zz}aSBgOntBZqn+f9JZTT4YNn(!87Mpwxpw6(Fw8nI?g{OTcp{IiC#jlq7Q1l_ha*a z{`)2O-JkjlICS{uRo+q}ep(wqIpv4R6q0QZ{8PL)=>I$$5Ge6OX!_)f8O|^)=xFK5 z?;d~i@t@)CxAy$oHbZ%`z{jN1oXraDn8Ck(XsTCeIoY0^!JTSmh+|>YHA;t`l|GYu z;`}2@rpccU1+bvVGlkPo3-nt64wp*N;2rc?J~XE%n76;K4F$Z577oh=!~=`DPI?6W z`|MG}pYuzD=NG?#4fLeq-S;}e>i45RE110$Uj=-Nt8>WLFi-etK766e!}l9^$z*u-`AWj3NK=gPW%obxf8Tv(n!ky;Y7f;$8cs9`qX|-e&WU0mGDCt z5?t)`4=hIW5w@wLC`M|Q2Ew1O@}Vba7K9K1E9Xc+GCS!*(tO3(XrRF-Iac15Y7+xB zp}TLNefKSsFmHkD==St<-LJ3Ev}sBVX}oBE*-Jm@p&xXBO8w?+@Fx7Wu)@2ltz!{_ zJyQik?#|{hl%QdUFE4<7y@?DcBB~LJ zp5`=?aqUFL&h;PLTtWNI$Pod?_5Hxd_)J3*01P9PFWdYc!EYY?)`Q=+@Y^5!_KCma z!tdDl--Zu5Z=$L@Q0j^r#kc2MzJ4BLOc9H6y-6oiCQg4?-S2kvYW-Z4MW)`q3UXk$ z&}Qn2U>ST}r93%n{Qm;zxDy77@G#PPu*nVy7daY|a2LGT4^&S;BH-UIfr$WE@-ZaT zx7rI^+b;jk6%$>~-J8DOX;`z<=}sthe^WDaq+CD(X!Ll{XxDCt$})ldur}`~6BnpJ zc*>l)cL3|Gb4W9BISNpFmya7mZ5-EQqwEx*77i*)NV#5DmC7X;h_ugS1n&&{ef8g* z|E+buE$+9s`R!?cN15Ld_P+&P#E3hU7fih0I8_*Br=Mq~`1Z0@iY_|2{CM;3!aPQd zTuKxKYFoeu?&ifji} z$7`~#A2w3vo`eDYnTg88QNxhOGCNT1y?^)V6Rnl* zI9ya@m3Py@L-wj0RV(ciUYb4AfTH+V6# zf{M#OR)ps2DesTM?N?)qc*&OTl&O{E{k7TX8#lQWGOy05$tM>z%y>+qpYZ^UUd=Kr zUCoFi0xpWE5SnL5w;$aG1hgLAfpu#m;4A023DHThC^dqX6=`kn!E4fbrE_()Qk0Wx zAk#OM1O5yaBH+DFIU&Mak&+1DMSLRd@;O~i1Pp5bW1E=!VdG4@xgWH1*}ttaNFuVV z(K~8J$xB*dFIm=Sr}uT~4qjGI{#H5DSF%}Z*61;#8K3T6fU^4BlZpDa!`G)0%NK}% znhYx?8Gm0Gt}97ne(_MLr4d@R0jXjS=e&* zbas7WPJNRan&$Gh4d&g30d`S$OK*lHan#K4YGD0fJ`Q=e-2{txhic1`kn@OT#PHm! zObJ(!G7NmGluyteeN) zy;cA@1Eo`{4`m)QXAd`^7rAR^8#_n!dKKPsmoBr}B5*2QfZFg?`d+;M_MXQ9X%|p1 zoslhqGj%D5z98 zxiX32i7AX(?UP);8tLA}2<@byW$%SG%Yc=k6+|UaszAa(r^}823!8IrEy!F}VUTK; zK3oMVIEqRp0Si|aQor6h^R@GfDzu8_5u3E(Q7&hzqU%bs&bl*l2veFFHo3aRWjigX z-Pa_@>TLIcUv-raw05S@YR?@zaMZns))6UNz9+<+5ISj@(0sImt1arD++S`t=SI(u zTplX>R*^J~iAPT(1GyH-23WWTRsxWSdfi9F^-Io8}@ zC@nCZj?$u%V`rQWdQJJ*Ivpe1U6}*iH@r=!sKWf>p=bm%v(R}fu!8i0s|>6(mV0NA zq){aTOzfZyxN8IKZhx-rBsK(2>#wrNNqbMnMkm1`xp2G&-{{p};Dt+jJRrAa(^dW& zKFL}RrbHeRQjb3Gx?8H0FRIiv-#0Wx*pAOFNxQ&ZF_lG_M*9i({(!NK<$1BaP`w|` z+s6Am2=H9O^v=K8yHYMUX!#JbM(-enI3y$-MULE-ik8;Nu*$JV@8Zz%>F64lF2#ku zSgwEQs_pK}Kv?-=d6Uu`q~7wO-l~|<`BBMnXM-#YXEXIqVia37pDCjyX0golNT4V`KHd3Jwzv=-A{T)Hl< zQ>kv@%|XQs@(aoJ&spViUV#h}KbQpKpn#ygfJlSeD6 zyjV`1&NWUazg*{my2Bedw>(+{(jQzi;EP}Vkp4l4^a=4+;o{F z_~#}dT;~c(7q~F;LKs*pR&AhKESzn);ePT5G;nOO))5Cx=CaM5%6p)upx-@Vnb#)qQm@^^xmj9*^cjn%BQCDT-r4B*VP!LStV+( zny~VPp1y#K3y|P1OMPRb;i7dT3(C?X{{GU>^mKJr>pwI(~8;!%E z^xYo~N3}983`tOo`?Z;?tidOm(0SmY5-ZIv0 z_gao945E=jn+f zuT|^*Aw8+D=G?Tc1whj=&dUmd<6M&{ZejJ(dRFSfZ=6Hz>Iw}Ed!gVuoll$Sfj|*N zU%uA-vxIw-cQB?}fUX`1c=TtG6RS>jr~Z zZO6z4t%)=-AcUY<>V>T62k#LCnl>`SlJEOSjwa~T`}ZkLW9QGOO3_K*?a2)_kPEE0 zPU_cCg}O}Liqwr5;yj~a+qz=F7f!{x`=Ff?BhVMSy0gV{)FywsLoY3LPZNsnb?`64 zh}1Lcw00$-u+YU)xWx1S5}+5*rzyjkd_dq%OmE15l^ow1-9|6hJLBHg4Vk&-RAxX_ z&q}DVUq9LM)$*g`xZdhZZ;Fk^50)~ml^|`enjmif#xK4J;aOtR>u>EUl0K(U)+NH4 z#IyV{12B~}fdUuFn#R&wCGooKzFxX}Ysi|(0s;S-at22jH0^$*R^!u7V5FC}V{S;U zZS|2>%e)u$_06-Ygk23x*`mPuaV2j>Z(dXU9X=D|s3foZH$Lw1*+sig+{wu~lPH@sfEUz9g!Jpr6O4p6U2w~4qecyZQQ`^Dh{ z&W=!Tj~V{{Xy}yAdD-=2bH4BfK~vL`d%n3V==3@ap+*sgyiHi|fB)vb3#=30u!xtC zk4x|mVm_84-FB1fA@y&9EBodjV2tNCcKeMxe`Dsq&xC$s=KmthJY%LZ%dUd=j6G0t z=qLjlm{x&{#wFvs+10bBPCvTQO0Gx*ltmH<0(+ru?vcgJnHr=FQfi^50jcZ>5rB?i zF&~C*4{$7@o?7;M^l~a=amJl$bGfbv*VlBxuinM`7eZAn-9U~Xz6^DF7AV%<3Ge@K zNxZzbLUUCm;5GO52q{iJd~6UkY*zy3kFUkPgFtq43N)*G@;F&`4i$)ikBELni5ao; zSXy}@PLZ{$WkHwA%_&W_aeJ*Cu~*{Cm|9QV#chJTu+2#a{veX8rL@4BV(^;}xOnni2=0lSEv<+6r=?f~i8V?{J}y}GoZsHbBl z&{MdiY>gjr#;-Hgb>%_T`*@8A<9OZ(ettW~g+4$g=1f%lDTvygb=b3&9g&-x+NCN6 z3C4P&w=>wKG?_5mCm%*rq@~``1wB4Upq!uQ5fE&439=L`&uH(VHM# zdk4xh(q8vYgBX{}bGn3gQ7-tJa;3asH(+|@$!hS8E1bP#t&8(AU&tRvSEDqnzwIG- z5L4A(X`kJR?{bd&WFr>->6%qad)xz(NM0`q#?MDoC9aI(QQ!mg?S;oy6O*gEi)fhk z_+da4CwoU~+SsCTyqc@)nssFc8gFBd$;L=)%h`Kw&H@rfX8PUSM}ZTLG<-RzzI@7v zOSF}@2A{^&CO^OHVc5b&N$KVnF={aX>Wy6vdZajDr~wT1ZZ3&J!FtOVy$E<@fqj{~ z)yWN+7mDf|lTIit^!L4_>}k{#h1S{l>s-duYW%7y*Y9l9CN7Xe^lH}AWAa1@33Or5 zKwrX#`SHt|{FC~dy}hpDw*q?$_CmD`B8=T|qeQ@5GcqVs#>`#COB!2Hmf=-%w7B$0 zv((AY^0|srOJfq&5LtuPLNI>r4KTvB_Ip)9UN&DVlYd~6lY2<<{`MJCzUOqJeTXr-dIXp}?gayy#}#W#KPPV!Qwf4Vun^a-gNv!HKT z*+=mxtd359DtxYu)n@t4AGwg^oap+7j5{?%B8r z(cum$#qC_@%HMM~2iiGWrzcICP|N`J z6X)rL=~Dj4SdyTVgxlP!SFcL*l8fgmw+_|7b)tXH~iJN(ALP;q5YzpOODC=sJ*`pr-RaQdudj_eRD!Omo z7K)kUeW9)(PxsuYe+VvIYf#e+)Kziw+JfJ|x#uy5!YEjgZk;?T4eXb=y)p3OShWPr zDRWB$aTYByj}=VZvW`)QT`yyLC72Mh33>!--U?_o*@ZnTD=&d6cfZy4cCN^KL$DCu z5FDQiN3)XeRm}X;8@P&F4fdv~W36KCph9KMEw;(^Jvq?iv{6EaC3niu$iJ23O8c1; z>-r7be#5rkuHf}RLudfXxvtRib6l7vR*EtpTrSbjog~clx8i<`2*x<;hYD<_VJD1?P#xXzJ z1Pm>MprxA}3om)=k~<;&&CVuv%Aiq0apCP}2sa7|-y+>o$U!P!bzxU0mS${;&Gm(y zLkTvpW%HCRB>S43{(`j%&KaH2w2&}7GUUl#wBzqHm+U6tCLN4kyuq>^dq76o2*0z& zO?WCeq%wPwR7wrm1Usb43f`i`T_OVb#B@oEly_l=(&j2)`hzQe-uS0Bq$SD^qrae^KVsR9N+k_fmhVkgpPQ_-9|W{v@)S6yb}+P9uq zx; zbOWB2jEn?A`5r<>Yt+v1LN3}KunYH78B@4XC7Wwq)oHf*(k$oOaum?iwPN#SIv(LZ z46E2C0uDBx5%!tp8kF{4ly1|XwzBf6)E}mdC{?V#HJTK$Ybce||KXDX(}h#wdA4R` z6HQTPk;d-1^SPMmw4fK`cqHg;mhQQ6AuDWj^0Z&_u5u<3psWwWo@jDXIp>qr#9Z4u z4IHR;Y+Ktc;&aRT30F_cFz3 z%T;8Y7eE9INDl}IAfyajHTieI0q76MH%WCoJ(7?I<_qrlSd#n(UUBbzESE+~iJkRP zvly&OnD$TCQPiT%H8GF!DiTc>v_4wD9K!S}jEejUmqR>!^XrJZ;j8*{$n7Npu%$VH zg;!1~$J~3%KadDm-~GCsxe};C2zX1nb^E06WahLIgutkyVpu;S%8&5mbRq&YU3h`F z20tZD2Y$%9zonhvl8|J5^yx&@8Nq%Xt6fCeoM-uTWNOeAMB>q{N z3omYu7yGSk{L`YDWyXuY(0zS_r9Fjz-#r^+UQ?UrEjCAEFji)lQm0v6jijT~7}y~X-ruC6B-8w? z<>sz$Fi9%C3EjNQaXEXgw_@Zkc5-!xYbda7ysbjxh+B^c$P`pr3pOd-O<3jX=ZsJp zJA@q{s1gAI)Xf@InU8iKt=#*iYDP;+xkq7@VGm<}iJ|-+PGCamjl%iASdL#TSb1t? zYAoj$i;IW-HTUQp=sLK6QDl{a(yQ~A^%DF&x?kG!U&TAxJk!pQnW_*=_506RPnBsC zvi0_KM17TWW+T4e|0QB$?%1+5oZ@w=A?Q3})zy<-0aUHZ;kuEV%#f4FC?x7tv6LTT z;Hq_{v5{~Z-c4BHf9-%6mdm?S?Q&7uZoW%0Sg)Qv2EI z@Rz$ES51d;59FVAbh>8@K(KSYL_qh&MA;6@+<)OLdz4JtU8bXX?qs$nXKsiga}lcr zp`+ulDr;ttlioE+m+CO8PNgTu?I%B@5;cJ-z1nht{R8u_wcb3ewuG~zHy!f-qF6$G zO;@J-%;h`+wJnCrJ!!blem8K!IWR@^IGdR>@`OBy{o*O4d<{Kz@ZcFza_$}|WxUuD z1eu()WE*^5q%L0FP`w2t=&f$UbN|}wfUTv2@dhD{D}6@qoEg|WJ)~p3IzhK8B>Rf+ z)k0>7-gOg3X|-dF+|IppjXW-MM}Y4pOKJpb~1K!#(=ol7Sf-pnRMx*m!(tPufZ<}G+p8Lg|jB0{<7 z?dr8Hpyz7bGVGTTPgj*Q>1CTQ*RbIyi{JI-FRAxW5;(6c#NYUOTRi1<6_5p*YT`8v zdgbsYL84U9aG}vpW+4Ym5OjLwTW^lrCj#_V6+pkn=~I?7t;e+QFclOx&8lb^Skzm# zC@#S_l32DZN9f}F)JvbpXr~%gWMa}kH~S!TNH^C>-esv2*{8AY0$M*0?$laz^f&qC zJ?d0w_EQf#X|2|bGusc#p0UL30{hf%#48|EYESC}+gxJ?3mIM#^yf0?FFtxRn>f*c zJ|t~17Z^*tpp-L23N`qct-t6VpTh=u`!%4GAFgyB{;t*b@J(`!d}vHfjq%r;_M3MN zFYpK-#q$Zx-+46T3MjkvF5$63s<(Ovg+CI~u~4b>24KgPR$7*%$cw65wBCg-;@juru{_- z9qU|qMNSzEz-YI5_HkB7szk%?|F!-BsUO|!Ym zSto+>sPlFvla=H8VuMS`x+-UB)%&Kht=Zmrb&K-V;j=MetgV!(x>c_@&|bO&t2%@; zK|Q2; z_(*I0##N7?LCxEZmgt2qGy7Fyb}XVsoc=*!6|i3z{0ppF@x~z`D_`tIHIt=Adt^Sk zZ`a>)_iQAOS3vp1)a$rPamr6KEt;?UbK}9y(9L^Z&^3fM9u*nSR+Sj9xAp;)vWWeQ z|Jv4Luy6`usUE84)G&)Q%a~v4mU2GFQevL+R18H@2#4~dRqwX_5wCb`F=Q^dGa*-h` zh5{xTo%aYU@uZHd$lr{Qd2WLj*=I>>plc8jjl#uQV|(I8Czf#7G>Nl8qp=2(+oLD=NnH0%$u`M)+PWjmQqMk;k|X?S}xzq&6@1Gc5%s68twwsm>I zex`NNkhR|cERzjg1qVU5SooB!AflNs(0>`>XHr$iYa7PNGdB4;g`8Rgq&u6z^1;mE zA3z_A9jEUKPMZ$R&hn4Ah0U=)F_3tbEF+y7i0cNfMQ(0!6m_aNz?O)B(H4!ezjXPf znmat18Ft#!p9rX0qA!+TQt#Xy(2AcHY&X=ZNb-1*ZE>|sW=3|cPrv|@Y~t&7Twe;o zA0B^_%;F!?*894R{S{Drl`_MdbohqZj510~l`~7M+Q5)9NW)#PWPNyoWaYb?gSY6I zd8zss*mIo^f*%Q`LT_O~^+1r00irCORq=hTRALF7#kM(6&-5?+yEJXL!5tFBvj23c ztGzt15T(ZVMW!JyO80xPxS{i9UV)2=51VXlrR6L(=c9aU!GWuv^K?ZIojpmD&_4li z!}Hg}8M*fclxGWDi^uYQ#e;ufS?=F3_-Hor;cY%D$Dai zQoj#c)@NK-sY5_ciJk4aaS<2Tl6#k_c5nW;YybW$`|q$#4$>xTA0mJUXe@u1xpuvm z{j(YHNxKbV=m{+k;f6U3@83lPyp53jYjWhlf7-rok3*K@r?L0|(u^%9BQ2{){$5)g zAx`BkY``J6)6VQzX&o2y4moI!>AsSx{XAmfUR?%N-pdMKo{-t=owJR{pWjA*IYlOg zSb-jV#}@1xe3+YCgakDD(bizbyB9NQk7aU!RmP8;C<0STFN1d=MUyCgfcT9yAxXd! ziMhn1V*FrCr44LA9k22!Z7)HuFrl(Rj(gwOiiOaR5KisiDE0W-b)#E&H8+O z!rtIhSxp&14ggt)Cz_q$C$mU6e~>97Lt1PI{Pf4w3I2&YO43NvA=ho3x|n?bDu0CI z9@9kBHFZ^r$KRbgJBfgd=tEeD*!2|o*pTgLAP$a_E|oz)(Drqgh`M~;Zafq}e#YC? zf+Iw(Cko>HPr~liw0IwsX1=3^izVAoV_O^e%3okDLs8a+75409bB=MZ0jn>QuIIeJ zAo}jY?ChI2t3NoR-#lW6hrk9v`hF<9$`o9L4r;c}^{jlEzHsT$WYgxS_jlu*Os=&( zW=y)o7sAWX16Qz>f2nrXjZP?c47)W5*IUm5zhCW1PSuIYvO8Hi(oo&pRH1X;NsGd9 zOwrbclU21#SLy2HPqGvmw>$|iOY<67&G$k*;OA7KT%~79MnCx0Y@sc>T_kCr=H^z2 zH`p@LT_7E*rIyh|fD$_?IYn(eIu$7F&H|_3=2UAN^;7Cuf>~E);usG6nkU>+yrGku zC0UqS&T)HLS*06gnLmUUjX4bME}QOrDjRpc!U%BUiz$J3Gblgd$Iqc_#T2F4+;@MF zLaN#*EpxmLMH~x~ZTJ0oX;O*CAMHtn8UL3zJptNbgf)OaT-gNeMFkm>)R#=d@~g9= zX0CE(G4Fu$5N~E(eLSU!I$hKU^`0IzK{*PKQrbURB~tonK|r7lO51JCRPjvTIA#F{ zg2Wm(YS$!N$GTg*xK+M+{a*cNn&7Y0%RgC7fS1>keIX?<;p>~}99=Hn=N$KF-JPw6 zU3vKJk2bYyR2LL%SHUvO6XX3e8EHR6k?NvQx_jV7JCf1K75NQwuI(_dkB|%z_Lia6 zPjSsld3duU;#N$@!<$_SHq=dYvKJu6n{3Scl!npo7caOP4}#bOF$yOTP?atiyeKVu-&^;qWRbAs=e)C8INnmF_Jm%c z+DV5bbqDvacCX(6BSk(ID>xK81@ihw7*3D@gu438%N1mFQ+XI_# z`sXyqm_C!JVC7ASvW@pk9s41W0&mF4>bgVwpX0yyzuw6HU)>Bjp&5oz8A`o>(0kN* zRDeLEp2%SwKKjwYOO$hp+WfY9sawTw7g@B?wriO_Pdfin1h zep{oQuQKPptEH2ry0&&wyqN)5L^td4u7-!veH#~eH{VVE)4J3}OJrp^e_EAONJHhe zoY%hZ)Gk}u_i9d5=@4c@Ww&~CC&f=uXMX-%Z1SF6kUq=X6AjUSn!WL$Xe9I!rZyvp7zf_7MUWsPM;{`5kbrf_@GLruOHyz!d6sntIeMW<$ukGDpAYJD`3!Yi)B zxtB9&D^aa7W;=1q4Vk&IiBdMU%OuP;{@&6_}X5GAMG-{sAnQTX1(K!^kYry ztF89H-cX_Ondn#D^S*AE>lkmb$FYarrX;&D-B9}H09hJVo8Yu9tLec<-33Tk2C1@h z!ZiIEa0~y_QKkEq&%iS26iMC)lqNgQ_Op*A`)cJG2aeI2pDM}xNAR&(3_3UHVOE-l zaBeCp%}(Nb*|YkE&(4>1{DtVs=iElS7pwva>A#pF4?HC0YUT;Mr$lO>ODd>P^-VSE zC|&wGZ+5R_#> zWiWoh%`CQ_clalaK|>$&Cbcc5{cupB$|*ktLn>zcW9*~~#y@`s{IX|K3ETg&zpe-7+#v#9GLu%ntVm71 zUk;`G!d(@1{Hj@j(0ZNpk8wwQuF7oQB6jz5ED@mI3p5<-%wHI^A}0dk!Bem!3KXeP zUe3QL%3A%ZRw|}TFAMgWv}%BCCjt)TzW-%i@OA$Q?h8KeM%#{H_mXebeFYgO=t{pd z>!occ$LYA7&j6>4>Sfx`jlH>k@wiUGE0a#-ZT;nCi&3aYt1sV*yanzAxqi9W5`ZNl0v$ou2%YP= z)e6tII@~XCDqkm&x~V*Nk6cimj6AxNZY~-Wp;1pMEwQ4biR&m4=}y!nh!IlTrdKVE zf?(LKcL9dIShn1&B}YEAf&ph{*wbV{An?kzjizG^}zH%HpPWR*$wW z;PeMx1CHlsdUykiotO*Tb0rw4J{8*Q+l-Cb_cFShcXy$sYe+W+eDo{!uHM-mF`ovV z%-k!-;CdZ~Q24#7kd1<<`PxCxlmMn_ZaV4Wx2SISzyiygu5;8ZS4%1e*l%YVQx;A) z(zA^Sv@OZ*cGi4Vk1fwso{lSUGwkh+E;+sV#?!7W!E#+UbDI5y!>~ZZ zR{IsEl5l;g1mUN8;^(TSdUI`8C+L%ME_@ah!|t`Plj_~-E|+TqC)0hIT14?GW&NX8 z{-Qy>ovDpJF+im#I;_W9!IfarLqtL=r!yIy?j6gH9t#ELEspBz(zNg0T+#rmsS89rs2~E~ zkt=XSkGFOT`J1k5?3Ra@dCCT;l`dv)q7;CQz*E5nK40qrmA8g2;b)=;8@PNfK5=qB zV2g=wiN-;MyqAMA*SV5S(B&}1mWIrr1;b$C6V@}icK4&s zQkhtq=yl?~7PF5HUBCM)Kt1<7*GfqnHibMFj&+KB25zip?j|@Xvu~9=ByH=gI{4g@ z5OgVmZ!7pk<|SY8^e+I)CRA8kz2|8UFt$^fSG!NB&vBJRsDqxAO`*aN$w_#HynZjG(H{otUWm+u(DCd;D{H)p4R zCI;XjyYvXqO|sOa)%MQgcQfB}uVp`>76kmq-pJyKfWibk;ud^~mk99qN~tts3A{IW zEXRT3L1_dk;Yv%~tZpFGGn^M$A4Yr!lD+7hGCtOx+CSFL4t%POZe%{!@tCtOGkIQp zP?W5f<1$!meL)WUD2i8$nQfc7(nx1pWhxII!W+bN!#xgWHg|LxRzcu5Y zGeyP&*BEs)^dc>BBp;1Bg88ojw++yk!A00UC)}#nJDEGO$&kM}7cAbJ-R4R6{?PSZ zuY+);cqFu1_$A@su3gT@tCRMlt|ct@#R_!+HH#CDR3Tj1xEzsssNk!ik&RqCz0A@(x4f{ojU3QP(g;(81@hLgObRs& z;yjcfcM?o0U-1Cb1mkjg^msn^EI4l*e^Vzj{x)lqwZ0ZyaxC{Qu#8qszu}HcUtV-I zLSxSKhUxVPk?`E|o@b(#?;|9TQUyY_doClT2W7|GwRtNwu3qj9sI}E2p%L#*zedah z>Bi|&y-qLY7LE;p5LZbh-G2XN;Hx3NI{bv&t*n6dChFOPOdo)<)te3UKz6H2c zmI6H7O6;pL_n1#CFu83{e_7sU0I~~VEhTh660w>xzJX9lV>O*%JY#!SR-wfzl|F=7 zWlSi~DRsC0-8gz&Dly)&xd9)|rXu``;bw5ALl4`H**^lMd~f2gO8|?x=YBE)?b!kk zC#ff_?GRUxekf01*^h(pvNaKSHe^CwxBa;<7KE3uuhiV#bUk%qKr+JC@|`ZPqE-$d zCXi2kgd7o(v|XDyh29xGLRXwt!a}u%DvXZsP@) zV+6-gUFr>^<0>ngyD6`pK7O_|8pMjg1;}~l+==!qm{e-hc?@KtF~4{;6rst802t*8O+dX3nVo3HETNmEoEBnA^`uPksgXvW~gA z$LpM{ZXU@SO%K8c`QeY^XcoWhAgwaJ=L(M5GiXP4EOk7?rHV>KvAQh~)3xn=E-Ke+ z5g@98OD8$192Q*lx8+V?Ljt5HS%z5j*qV29T+ZGPcAcsTzwzY3WvWY2HcO}9dCh4b z5?c25DN&mQcp2KW(SP`Ul;GPF5rF^Tn>7h1!dEjFNxM(}@p*$ox%{0^!%Syte%h3O zG@YO%n#RAJ=U!#vGr zEr-h^duw*C$cA}DpA|NL)*KoQuL@8AJ9w6UXETW`E6C`-P}bs+;V9sk>-bGPry>4% z2z^{!cbAgxvuyOf_sv>_3va4zq`M^Y44Y>9>&DOR02v91>mSJlo}4-J^SKFQ+K8(m{Pf2Y3jV{4@0gh4^ zb}y4HFXWoPa@tb!C?4H&1kytsF7KDA7;nHML`1|yts}Lb9dT<~LiB6uYJJ&EdE*UU z@|3*gjpPt!{p=~Mex6Rq92$~pGX^wMeYdo`dk-CX<)g>ERk@|#q60%-oSpL3bK2yCy9_0k{;ei-07{J=|Uw$@VR8|jYY7p2Cz}AL*>1rY){05J3oxi23gTQ! zO(Ya#n=NXQ)cN@Ms!RO1&e zJ2T6a_p=-`zJQl{w~2{~IUxy`J+c<)m)A2V&~t>|L9P#i2@tmJ{hqeA zpCznm8#M~Kt$;w(u4pZ(mS!yI|xV@ zDFG>w5+XG!9R!3xkc1F=FQNB%pZ8OFzi#vc3Zd-mPu?lBn27>pR@=2~m6 z-~3G!1*6zRs?SZiuK6F_V6y%?t^a~~QQ7F-q5pM2=K)NLYwzoGvHuew-rgBsOj%Sf z)t>T!Dtxkh4_hI!bAoGk8;A&~$zKsuVt{+Ymoq7K-jkR{A&}Z;Q10lwx}VH$M74`K zVJ^rx7U%JTP2Gg)bTQA1)tVTPSF^fVM}k(i;f~2qs>I46zmi1{dHTavaPce0z}47_ z)MEVx6aV)PxFG1Yk$$|jw_p6N2GN_ms+xl5+RNw@%A=%iQaJRxxIHLg-FE)Ur$oj>~{Pf0BrLEaMJV1E0_>>_!%$Daibo$ z!ZVt*($*Q1!YFFg&>-!`wJ(H?f;~-n^GwMF%sKPbY8gk31K?0n58vJRJmj@( z+=IOQaplSjo0GZuO#uJE+Xabh!d5kz9&|Srk6vs&VU}LJx)Zs7GR4rZ5I#>{+5{;f zq;!BIFLBq=^T*#E2`gRc?)2y$c&lJrHXc<}B~$!4{3y ze1fcT}ytpl}BQ6V_@-X_lM@jwrPb|p7naJ&c zULmDD?M3D;!SGj3k(;6CnaW?gyn`Jd)zvHzU|p5p*k^>1?`u6GS>-oo4ukim0ep

p1S!qn}htkyh&I6H=E9R%>iSpIs)_RmM;WX%6(mO$ck+ z$FOjbmdEn|Mf;C+xkE93^$KqexJ;f7E*4o9KXX~Ya#oJfAyBH7{d|+7@(D!T9hyhi zU#Fc#yz+M0_(`QWZ%(``SeQP{M_C2RA}SvEJc6ziUa+}w1W!~e&6?p`DtUd_OWk)? zq5@kk-9I&Y z((;eRBEBE{Z~ubh52;tdH$LIv!GKM}-pzcPAj}?Pxs_gG#=hLj83` zH+7#qx!2oX`m*bM>oE^6{obe#^57k*oh!^e_050lWi2&2gl(U#xbo#N8#bwN&8!G+ z8*gM`Z()}g`_wqF%7s3b2P%4vj^2?$$O9tgT#9}+7O>kUBFV0k8IR88q`w~kU!iCW9(1eWM%E4C{hRW~{;1J8 z;KE90cZh_RI#N8pXaVKG+~<}WvP{=0ce<56B}ig5lcAAt*LjWW?fH)Ka{uBvBnmhG zlwk{$=~3_C4j3zSx$ONvwzAPMcj?NCJ0^1M`@;V1cbyj+Zw-BM6|NDtZenlFDWg@z zw|oP?5#``YdE-A%K+O9F+`p8F(f@R4Jm%gkjhm@jRf+N!!{^T=qBoJx?w~PoHbH{W zy_@aEXjaj$Oi+XumC0ZUCUVcmonl_eiE=%t@k{1r(1~PPq zLz;|S(Kp8K^FvD1%{wJ_CIjyL7{B5)=jt?*BwmuX zya_l}t9|$7fK}hhpZPT)Hi~2*&G~d8vgh&c=~0D6|L04Yj5v9#f%y zLG$zU_2rk3E>+PuT(SWo)B+B&uzvqZmwG32H2T|m?cs>pW_PEOttWAjt0T8=wsDUVly^lJc6`!>|Mno<|Nn3s|67ia z=kosKPLixH`9OZQ%-P%60pFCGJ z4mQywH=nbIb}?O%dCs0~`ITZt1yS;cef#R2O)0}b9*wbt>{z-EcFwHWkAz#Qw@!Lp zO7vgcUZ6D?fB_XuFiKf}kI2Dxg&h>E%(fgVC!cHN6(Be$1QT9#PZqxPgAYlo*@|nW zv*@#4YBji_c3f|8tKYAGV3=*L26hnOpICD#;cv&fthXJTZ(`Es3LBm9x>2NBkYBV_ zO!v{aB8t~d={)J0dOBY6DhsY&e-X<;FLw0FL{Yjc>mWqK*}u(hgg zrtMdHy<95j?-d03ds_z8k}JiN^Cr#D@2w^Zm#X`yML?HviK~+t`SR zHAbW=Gn7XQg*-SNEC7`S!z8whF`fQn^+~IkaaecW^!vkoL5bKyAl=>#PS*kdFjLP} zmO-=G$xjNoZ=lyuasF}|VX4iM5fb4_y7&zZ1ykk3WlYd3~@3204aBS??87u@d&_W@up1YmkBnsn{!hhksjs+uJREOyIybYUFJ*+3xvJNVj;n7?tw8PWu)YY$3>Cod%lL+ht1?d9NZxL z*lM_!kmMpPw#_T)i_3Nxg}u3-4L`1?oL?gt;s(wqAoUQi7#^8jpy3G>pv4N+5hLQ_- zx`8Aj_M;p6+ZZaEcDvA+yn_|?)6KgGgHBcUh1&(b4!_L1#oK)_c&bVDCzbd!8tSyo zs>9BUXHdYwNzov!)}$f3?h1S({}_8y^@V{Dw-XiE zWs9R+k;F{YkN6ady|{F= zU*Dit;^M}Q}qYA^sb^14xI$q1J zf7;OVzp+tQyNO?h&y7Rd&AL1HhnIJk_R5da)8LI9s-aU+i8y8;)mZ)wv*hL%9zEXX zk>@#7)Ja=+rakq-NQVZb2A2h*C;kJLi<1S@h|%yOsXR_dVAuQ7A#-&yi!p30`Dxh1 zwE!v`yj5HK4SUvmbi2&|EQkQk8j#&yF=s>ZfnnP$Ov|wnbXKx^bTP0i-5UrbzhN`L z6bzfA){__^A9%vRLRLylPQ6U{*mqs4E;QZJoQa2xJ=D~j^tG=)01tnW1;~<2;NVOT zZ&yFTz70icQ!jX922XiSId1hUmzXtI5-k7F5fr*O znRUaruTdb13hyd@e2)HH&lKK(d@m3remA>~J5lQhqLJHMdgq(3N8*TU#ER+8AM^NN zUbD_%R>PqXNk%lt=mZx2$V)&J?S85bo7?T}6q@#W8k^cNjFDuzsn<<@_2RoH>z`ld z4_}wR03g;J>JKz^dZ$g(BBO%GWqofysa|n^O#zjL^;*1NjQ`fY80R`2d-*f>>+{Dx z#YTz#?S8UqmJi_I=!XxrVDr1PgskputA;HfIehU_F&yUm!G3^N;#*>35dM6nMC83@ zQ0vYE>m*Cvcb_>=9?DR}ZWTaYi!Lp%?l@2!|Hpm&wQm2r+#mJtQ zH4ey)1K!Rh3Y)$DEXgXmG0d_CJD}N@TUC0i!}V#@l!U?B9gTaMbG_$ALx~@)F3cWI zuMclhlB7UfosI{-b;N{a3%4??e+6m_RXOPBY_ip`EiBQ&>G{=pCPgYlXenY1+?f;F z`CU}b)OwIlXGr0$NHg^X{Gorysqh5%6M+SsQ|Q3%*(TT7_u7{JY9@6c&G847RpAc} zD$nOOXir2Zcyfjm9DVoDX#9BTZGlgRGEp0Jo>|7yHAKk2<*ZuxzxKGL>br!at1OsOr+_fWsoG3r3 zIwsLdv31+O+z*7; zkapMCSC7Z(2o|(gCX9m@CJAGa?0ah6Pd%YDomCMbl8iO zDbjaEd_fQwk^8%x!Bcr)J>Fn#jU{eaAfqs=pEKwwf*N6 z03LJ;z>?l&f^e-K1sGE1hZPTwKlr@!YBL4^EF~e}KdvYqunYYw4AsHj_hR4BuHe4_ zO)I?UDH@2tpHvHs4nL{hCzd5nmHwDr|ECKqwtvdVif8?X-`A*2A=4I9o0elQt(snS zH^!Yr$63c_6IM05Qqxa8oOzc<_wqAGh#c3LZ?VMs8BHNJl9INGwzBzM?;8V*(J0h6 z=eH48OZN#rU1ze3{s9oK1_+0)peMio~QVjcH0)@`rQwI zh(e|4(#>!3KB#ag76;K&A+(cjy?=0p!%^-=T&it@D1#PYIf*g#h#%h1LXPJNh86V=a(G?ZSGzy@mAp4 zF7^{Rn_RAJjN&}XdF&Akt=R!%QdMD8+KaJys*&~vCUX4hkhet98~<`G2jo6=A;uT1 ztIfHR~e(aIwYBa8~Ge|%lLI!3xHww zbRN&uUtxJU4qPXX8Hv|~m%@t%L!9 z=y@vlS`|kvzc{Wol-QXx$NFwM%NOU4n~DujHU^koxt6ZAWYK-sGl!>? zBJ3r_@OKqnR8DI$i1L`mueS2<&^!`#inu_epi)_t5uCOVs5^243-$4y?~qx&QZGzY z9NkAE-LplEx97UnnrL%{GxKv8x+RM1^X6Fw5gFX~ONBW;*$}upxF1?Qp&6I1G^fQe zHhRQ>*pH0PpV3)+95g0apwNEr zoPY*v0P+;ywMnopMv5Yfx99h`%&W0k&>h5YF{_Uu6`-I49<%AS;-9MzxF9)wRUI(36oMBc4+~pg~u-_x&EL{!(m0m%aOh zlT7=r0IH}?hJ@T_$?e~q10vV)GU>KWi7AGG(2W`g-}HyWvm;t|MfZKD#bk1P??;8d zG;=X>HY+J6zwes=ikD2b^(_d-szjW?pq54=vtFuqoab;lZ+$(Oj!Dva?JO#%&mVmQ zT;quZ_@h11y4AaU2RLBmCcDiOx^1Ya`9007_A~xr-ek0tu_wETdDHYGGy5-fFBIOVL79C=m&vgGQt^yk zCM>RfX$RP}w?J(tcjDyYZrD-3oynfEXtQ`M=a4fe(-O=ZtgNLW@~#e56D8Y*zes9N z=erKlYoEBriih}rLR6yn(lPAx3+)7g5}R&lZ1ai<{Hqu;-9;5b!bh0CYCs^^=S6@>PLU+xZxH6!j*dXl-d+=51_ST5bQb=kT>ntNkK z+a)ETwzms|DFzLYYU?M_kA>=p9y9 zeQ$ip<#0UlCECk|^`WP*i`r{HZLScvbkp{psZXg!{#uW~m0E0{^9B|QITWj5;zeHk zsU1TdJxYEB;F5i$PTBw#EIqg3bMQr;XUDJ3?*N*cUVlJR86|NHZbv`b<6{fRvX3`S ztzl2ijc&(0zo~!2lrsdJe3paPqHnz9_VQUT`bRHKX%)}OSNNER=4j*?Y2}f+l332y zs3n6EtZr8R;2mYHdb$&I(m}@%wnWJGT?2VTV5Xp@v;~9>ibUK57cNe%8!uMj7b z!UmLdPi%)xjVZ?&Jq1i576(`bKA)Kb%uMDmkF+y}llUYsrNE@GvXUKZ4_39_<_t01`QFBJfuF;F z;U$9GIR!_eUzY_5&vkJvK9Y)vboP))?M7*oFBMd+`4O`PXfbwe}qIkC}>}-Jtx8zzIY>M@QvP(tyYLnp6nRl<{Td4(f zx8-xA>EgK0V3ey?K^~TYWm_)*ZeoxU19he#L%L zYX};laF9p}sDl=h0BE1W#T8I=I5#F$J8Vw6s3fw~;cYEOY(nj9_HF#*zL$3t`cp?R zClIe;wQ78xEUqdAq#NV|gx;qbo4a(7HP+;)#rFM|E|M?3s7?=eiIkxCh!`r*X@|UE z3zf@(OjLSzPW;C{=oIG%4zLGTe}5f|$L+fxL?c0v@7u0s{R&M`&VFKZT8zwH_9UtW zh=H17ja8+%RSSS_Ec^fo5Jayu=jLxak(A>G9)3il#7M)M(T*z>EncCP7FQeJEv_-j zI>)AkZdLK&%IZTG9Yl1{bNZ-p|7uKTHzJmGJNt=~Q*N*-PT+enU)1f59|qK@Xg>(I z%X_fw6Jti9$r0=L=QJD}(GA__W_?bUkFsCrg^#lJ8%VS3C$1{FbMWAjvUl3 zEW%~R&jTs53W9BKfnEv-?99igbq z0x(hG{YtARJH$2)6q>O2jrBo>ZgE7%77N#(8|D2^=d z-bN}2KyZ~SW-7UJXoC!0{F1N`j-j$LPgS|m zA=Xv6H0Mfa0Z~gX_U&loB&{>s4Q1I1*V}e&cZ#U!)FkxurnPc`0)o$Hza4mD^HS8o zwjc#Tf~j2M&(GU9#V8hsKD#hN1o0>S8_QsVjA*YV=9`A76HVISpG zM&`Ho@8--8U%2a;k2hz{L-nIN@)rl`7*zI9gzKs#-emp5mqvquG7IN$HY2Tdn zy;@_A$Iopk7rzhRp=6|sVB)og=d4#EBLYtM?W;|IBr?)BGjH)fUIVv!s^Mv^;(}Ru z^ScBi;elId60NYCKUgnL+dsShQAYQJY7{CKk*IctPyLJOazv0Jp_O$`AAGcaKPjMc zYQ3^Py@CVUDY)qQlZtAXi$TaTY)VK?30LGEl5!zjJyF{FQ`MU1j;a_F^3uf??hcv2 zA5E1=2?GEq-e=;+EH!+d_MiqaoIBQ0WUlMxRLb6H8RtzGcYPsYGdAY+#I=s22ZWsc zpHy1Hbudq8Q4uOG!IOEH0F#~H5>D#hnAvQJ;6;-cafo8O-IBP?)t!6IvpjL$Y0n?2 zO|;JKmA?p@JL~-Fk#Mb`>p1PH$rV(Qhe=>goPVgBywl=w%~qzwgyT0F(^k+_&fR>| zhUuy+3kPuIHk*S>R)@b|onmqQR!O1^l;v?Sh)hZUfaeQ^!C{<@kgG@fK}u9V_-v_5 zB{D~fkL(ML$TO;>DBZv@J2&tq4?i)xN(_RhI=Mb~e({_N@Tg^B`F)aN!4h@j0b$=h z{^w*roqWthwf&F#(D%RdNslT1Yw~F1Ki`sGj54l#X5?c7XQeBTTYOy|9X%TDYjSXrUHHxnomliK64oJjw zU=VNdkim4FO(4_=-GxWG$k;Y^)6LCv+B)akE);t+=;jbVZ{5s4k#WN7#ak-1-H$C( zm$HRsJ$9Xhh}G#Hhrd%Km-~qvr01EVCdcq|&Y>2u>m3O+tWVw>yK*gA@sU@d4{slT zk>cSuROjonxD_^^l#1AKawq)mcla2L84_?FI0#P@a07ImLV2mq9;Jb-{QGZ7Pg*=a z7gX1Ul@H;ENo$=L-IbE3*s+r@JkPA{pf{V_hd|mFHj~^Pu7$*9#oe|t2msPM1o-I3 zSUnC{Iv48wPt<4PQqv{>bk!CaB92%Q*kk~I#sggESYyGb${`onf51=i2Z=?jMU0G? z3=^ej7pLrCu$?J@gJwXi1mM$Ypm6kCm-Zv-qU$F?5|VjvEQRF-yr%lH25gZv6X*I?BG$`3x^1Jcs>a!;O-Z86t5|;u0lVY&~msTc>Uyca{+gt_U}a^tIdRKYr9EHGL+(b ztY>h^>5p{__^xo>{Ww5S{}gU6^PCtmM&8)Z`WnNUfMY0nSGNB-wsks11MyJ;+ExBr z6lLN+sV>ambC_L?hJ(XadyrPH?Dhj>c5nhS5;xydOZ1_G&#gv(u(;b z7$~AimuA>l+XX!kqjVt^e9SwSXv+HT0j%Omy+Kmh`Z#Y@_GkJ< zQa8zfLlt_(TdIwV!*+06mHH<4Uj#jlaOF|Jz6xrlF`yzpTUc}kng88ES4qWlezN&M zjyD-J)N)I%C)BA(SZE}6j8DC^ljnxZ1$<+m<+CE6qxb$2CZ^-la8$Q{y{-12zD`At z*HN2Sc~#7ZzYnK16KZM-Y&@sU5Sz@CqHHt?PS%-tdXanmcGgVE=Gn?QH{ahLP)lV% zoCIL_=S(;!q^kXj<~hHesp7*oT`ZVUeKZn9uNSMGho&8>`TZK*od21v$5o=!Fg37h zfBCwJFJZyv1E)1cuiH;#4Oa4u8D@VYEeo!0m~ z^?DhN_~v0Zi~i;Q91>E;6oa4}2y9+$l`(IMtY?*sf6E|)+GA^d*U263k8aK2xXpeL)*uHbYJ7AMBa@wbgPb9ygmyRX570n?|Yxfz`t59+S0lAk#z0M_g5x!ZbCT+!26 z$b(W`Rru#!Q3-&D@oDO>kaV#RaVj}eaf>*EPV5oS_OM#x57qb33ld9nGLCxg!^M%F!uW261yGwf#uA zmctCa7AXt;`=!PT+$##Hqi=<*`?Uw9T)l6q*;>gD#VO$Yjt6qq&y{wGHnHHoK!qLt zI2S1^VB3GjUMl5rab8}rbD{TFoIsHBQ@aob-jjNh)$uQ*QRT5wXK27q13RAUXHYwS zUGaasOwNjAJXg@NdvmqopofBI=FQMHUH)Y2ojXI%^n$6TIc&p3tTTO0r_rSE5Xl9! zgy(PdC54X(1WoiVEnC-CRcfgz$I%iM#)e1AS1uayMcTMbU-l>%x=R~(D%%3yuwRp| z`o}Z5!pWIlE{bP}^PU6C2nf!_TVJxkK_WGK}2F3p!PaeH?@ogHD#cGC*yh6qA z^^)$x)gvqaxav{{&jZT$dT=rz_MdCWv;E8c*G+{d|4Oc+_HPO^;4_*fq!hybP3?tC z|H{2mlv`EgA>&U=xvNI07XT_abZdVf5`J@+nxY^u1MpyX0OW(-wK9q!s53ORq9Vag z3-6;%;|?}V!&6;p8_~rsFZngt?kz|PbDpCzijO(wGw`+^2mtu8C9!`|SvM=hCM7MG znsq0)xeu*sbLp<|cL(kBL%c^pO1cUcP^7CFbNv~cdUoU+4~{1%9dFfuu*q3?-RAd) zeFFn9vHCNQ4HvzK&~cDm$<+No>bCdzt-W*r)!Q&m?ha%5;$T_NR=a0_8uf*qv~ei3 zI7sJHeI%x-jBq(GIXbxvi%&Q{R@d;mDYFl^A5HuB6;Bl-yE;0wWr(UP8p28FghhCp zlXLxba#w-xsK|x8kPmZg5h;n8e9YC3V?>_7_H&XqBf;?pTNd5+3$;z_u)UE!AvXUM zxcKtcaercsDY7xPY`O zQhAM~2ebT2MWrY0!$+#n?QirM{8B7{sTyF5|3`E zd*;Q}fHz1V0~vax9;6@p;*|K3f7K?U?rXAz?aygXa0T|r-Jz@EuREDmd(_}zRulLmuUa!>9eRA5)l(>|X4(HRLuHKM)-(EyKm{h60 zLW+Uj=6K28EB8yPdAQ+Bz;+}_sXjvhzN-$PCT~OSaL|XBxGx%h!JAbMGxSZ=%jBXO zQ~W#)G91qf#v1@C)Va8JSQ|ZgbcEj0OLRn*D-yYQ~ zP1uy?3s8;!{S@7~UEAMs1OS7-{|Vp)r$n;hq>}(x@Rzaxq@eddMhd_LfA#eHvDpmE zU8w`I-I4WfQGa&Iwm8-Q*PHr%Bb3Vb{OkCcEnRX7)l{uN1nxN+q7!c+ndJ)2A0+xG z(g0j2yq_Y6uEi#}qI3-|V1Ma23&PJ|{g*)B`X{mUt!gU)6S*bI?I#s$^yxW%%Z#h= zGT!P6DJ`aFAY{tKH=g5lt?UM>vX3t1+8#AHdzw4s`&yqzUTBZJ_<91oEeJv{^EvUGS!2Rwp;o1%T##p zmJh$w_`$_#ACGpZ-^4&=fUsZ8#7-_;k^)1H0Z0-pm)M!=NMvM%L)(?AzISE4!o^c{ zpKcbFsjq%+KmAUn?G%ye?CmD^fPbjp-eU@lN00gjID%?Z;oj2$G-L{Llyu%9X)DFj zTj4Ubo?Box$yRcl5*FZhPARxOuHGU&^a!qw@wc(js=EkPdwcHf4(~yrPKrKe%kUn@ zdNAChTbf)SjU;*9a?nBz$O*bLXL~wN78+?fWhX-T9t&)Z2y+~JSse4sxosW(5BW-n zg{4bSmziM%`Dd{ovGzJ3V)q#g;3R9c$u(-^Jujyk z=(oUdb$xcjSMlhfU%m}jmYSezxAl{1@eM{Cb61UMR%jJhL6*Z+ZuKI=+_A;r8ydnT z^LDmI**6~Y>+-gprmX^IeEg?1EGO)@qJowY-P1sL@-ygl0tPup;%!}2U?P#WW%Vm? z8=ZQ~m$cP?n3{S|}>ou0c0JFZz*b{8H7g=@(rVHxsv43~Q5x<~0>a zD7XVR!vhx7cUoG=X*Dn41h8;|xIS(z26T91#oQU0MI zNLv-ShDTJd%v3n|GI>%$T29RQBlpR0t z%i!Nr7OV#OS2g%|=ofE${_zCr|D7Gczsti>0T}(iDCzT(snZaDxrt1Bs!<8afeK`Z zNz-uhXn3c|87*xTI%rHb)ovu}k@qS;i91GQnJF%0n)Nf^ldbw+6T@5o^}EAmrCX#ad z%?NQYQ`!BUG>jw-O4tUof!xTNAPoj^Yr`M(4K&Dv3#X5%^c9cpsg&$(YsXe77%qP- zq9KKzws9tL`*i=d#}G7A+$=mLz6KmnZMyW`#6Gc;f6ExzI<_w`T4yq#ft{}F+c+bv z@9ysHobzQ9!UI$Ae5=NLaj-1wD`oL>t2Ez}0mv`2Oy5K+C$$M4>#y7ed`gVXg_dQk)zgPqJl+aJT(J55pxRs{>-_W!Ybe+Rf`S9grtNXzjw z3Qv*P-O`DNUII-f!Cz|jXjA9wWQ|kg)xPx>nGcRsdFLg>-_l@xa`SV5e+ya5Nz7D(_QhHJsYSweT9;X<+j|1sGhbyWu>c6_@%J$ily40RP5kYljU5b1^?12X08iJ&B9o{ zT6v7C8xsi(;CV?;WB+W9C8o^*ifD7Ud-|-E`fa23Rki8v3E3+6B@wLCM3YP5pWQ=_=zp8N z!oSN^{9#X)wo9WTxotd@eQ?s|zbM470D$kckQ*h zKIqlaAd`qvh(~yZt5x?yw{~z3z{+cC6{BcwXan`D*e37S4#I__+kWy6+4c=)Wh+br zg|5!Ix^xCTw6lB=2JiEF=&zbb*u`!p_%3fNh2k`FP+(ZG4d4P zTKpuuFN(-qlnqa3o}yN#wDzECEyn3ZA(E0mUPTj+KJ$1wPg%yh%(tiNW9}c~u86(iSCM$R@d(ugl>)N_R6L6!TTU)!L z8l4Z>wV7;WyWt>Q^fBl8Frgw$`P5O$diLeF`F#5?MEAyZB;V}#;V=lKQ_4K_b{=Ic z)0_w|+4T`9oo${v;>vN-u5mS6gTu6W`Z2fIk-q1~F1}8eP}BHVCWL)AY>ALtO-0?O z9z~&P zgF^w)IwO) zo1+JokYn5@Zgo7ig5%gI{ZnTlKf}T+D#EaGGcr)DyITahHxThwhVAI5*VlyG}bPS@Jvmgaf-*s1$XD_3xrEN&b*^BOga6!e&PTZE--C8mnJ z)g^{QNKhXK3dnsgy>|m7+bAQ6g!|j(%;EhPhtnva31;*)UV@}Lfv14~?Bk%bGF+Og z%O`%!ExW(N8{vl__{`vaS>bel?*d5N&Kb8}B{bxUVui3}0$O!@=fw?Ly8b%c7FxKD zbJ^F&)Vz8wzNf0hcy$N0YO1KVTL=P`EG>_zy>vU!F{S-Ub#dDRPhpj-63Xl6);PZl zy>80A_xN!|-`I9w7RWx;Ddi0Fs%&bFmRcC&<;0=qOyvoDf)<_(9w`YGC7bARcsqVK z6d->i)-SKg_(Dx}YMGyQQE<-wG@nqS_lu_+C8w0X>?BR=sBzugxG*(*6l>eNL3}os zqK${7RET)y<;1k{;7wU9aS^F-k48*tIjaKX&Z(g29gnGXAG=*2N(#7IS6MMq#l8mF zF|cb$^m#4y!0cY{7rBSZ5v^TOr|5DDkE%VpOa1+oIcUVromGK@o&L0PHG_#gOKPz@ zjNYt~j$SUBt%+TnJwVm$+{LqRTbr~EMzyu!LKF{eWI_w))3IGyznb*C%yA5jJ#Gs- zYku|n@@4G!n$tvOpJgl*o0)R2$Rmng;8@s7u16nl2~t-WGvKcPtX+%m zx5HIegyMVWoah&s> zR*Nxdp;Ku`#tBO$T~X^`^_RXl1&Uk4jFQ$X>vm^p(8#29Od&fS9$qV3=wK+LlYpF+ zO35u*R%pj>-o6qJ!4qONY`$=FMA0;PKSn;UH7wc|-Zr1}AP<@77HZ|<8xRsj^?t?9 zY_)N<(QgC=Z#@s+dJ{+RHodE{)C-q_8QOR(*QbI8?c&^T8~Vac;YsNzc?Ej*ZId~u zsvwwQrd%sGyUj0l?z|}KvGmh7CwHji7=ARl8Yo=rF>FwHq;O_nV2|s*r5kp1=TYN_ zbN(qjtqcZyRLAePd)P`-^~kEg+})A7U-#Ar_FG@Mp!zea-6=@`W87x7LRGF;unr6U zB*Lb^nEAT!jS>dCj)0^;{IC zcyZf7rGEq~5q)l!nJwY7{+V3jy0g}m@j!gU=d_qRpC<;mO2DQNisA|fTV-IOePVTG ztOJaW8GnD^Ch?}j^B(aRbQJWDQWd5V{6sI}u`r&IejCYwU67y!AKi}sl9HEDXuh4e z)oN-Qz0j6I0>F(kXfAu}Rkb7@mac=r=;x+X^X*mdB3GVgn5{Yt-ra@f;qy{I4Fz1{l*D)cJMa=Cv5DiG>))|+VhBcvK^aa z;wpX??}$$Fd^o#>cMKYDOPtc+c?^?~i#wlmIW}bG4tE$7+B+-n0|Fr*S9bK+$JM3I zKgDHc?(E8fjO)@x#;9Lybl#H{Vr)t|ndN=0(PPu+&8^ny6CW=a#eXf`JvM8mjSDRR z`w2nWdhv4uW;M8y;jfEX?t8QcWyS`RQPM|lvwn_$c7JphtX|`%p{P|zVVBQzs8OkL z;P*8q3{bdsd#Ce-5tg{-Q5ZDhsFjlqLrIVDPb!h8u8{&3*V_yTy+31VfN2AcRd89?$hg) zt-ymegwD!BN$S>bn#(ZBf`G=6bEG?wll%bV>Ff+ zl>fZ}O)Q~bYIj0Rsm2BgOInUXfa0P83YHMmG zdqCQwgfa`*Ri{sJm$}j&h_ox{)jqGHO=7&V6lXFBpzhi(T=1PIOzx1@4*Z!}vp>DO z{VtX-Ooc9v_h?a$^*J>?qhb1rGVDHM_TcQj8DmqEoCgObgNu{bvsvwkkKe3(&)1Dq7P?@oG`{>9j_`~je+>x}-30>oc`=17JkoCMyR15iwB zR)29VkRI()*`{)B4N!Ig=#$)!zxWZh`hlz4|7r1mCC8)J_>^d$&!;2mWd2cj%8u%P z#Q9%kM5iJ`r>_lv!uuXvJER4>^gm|)|Ni7Y{!l%VG0n+aucD)Bp-Hu+eKnwCQ;M`n#9UdH z?Py6|gBP{1&(G{u1IZJc>9^y}wH__cReRJhaS7^{V=}f#-L?~cD6V}T61k+J2yV3u z+^*{oDCfa~9o?HHJATV$i__g}0o@qe?ljvve=U>t+W&rddCPMj4R1g0I3bW;>jS#FS3AE`ybT6c`Qv{99lRtw4>II<~Q|Gw={oc9{6=_w4zG}o8 zpF9kB{=JDx6L4mdJs`%8vRvZ8?u&Tmn(iy1dmQB$z2*BBbDK4K9i2{py&T%{`d;w= z!`^#FHQ9CTqF7M@5mZ#FN>gcqRB0jtA|fJ652!Rl2odQuiqbm>NEhiPASDC{Nkoud zgaDBQ2puV*_k=v>eqP1*`_35WjJ@Bz$N0+L{z2s~Yt1$1Tw8-N@$hI0XgL#Nn+hhAjj7^1m>YV49kyOs%EG}8$5FjSLD zgh@)%(uzdxGH69u6WzwnKjm}F*{n%S9NYE+=Y1I8@v_{t#4k+^Fv;3|M%igaB+Cd2 zDA>sV)N?lI*Iv^GBtwkzH&6V_1k?ZErT+IU(=TxxxC+&=gHd#LR$!%I4YxP;Ev1lr zqC_bAj%#v0XeWY_k@vk3+TXO9p^%O0rNuVo{-{(Lfn|1&qWeT8C6)74S!|Y-o|c2Q zOA9DJSUh^m7^qcE%aBMyZ*Lj(Z0P&oq9)o=u%IP}NBw5_RSdk#XcHgC$=6jY#v z;p4}>VYCsmw=sciYpKE5jt3_pKk|WNFh|}LI)-4AgB;oA>eN{!^}E4}=63m8XonCo zga+ZLFZkJ;3vRpd>+TZHh?*B!a_r@0(E^?P@z)wWx!y3k%go2iSW&L#t4>W(V~yy5 z!`M#N{(We<+}swcF($VSFi1Bv_GB2T@Fn@&miAA%uln343@0%~p4svCsmJZvj>r-E zU5oQN^}9%w6ukCTzXVXpSBb=3!tTW)(!$c9co(h1rAB?#Pd+0h5s`q8pX(dehCkL{hi z-RtV@xe)|X*NxA{_GL?%U#=Hk%;Gu}|5OKiUw;{c4auoIbM8)J9J1EUZKEo&pR6G< z;*4>{ZS0w~tn3}NeA}L5p%O3jP5>&|RPxiwd6M1V62-Q*IHb9xINb&0jA>1^6{#qx8c_`7|9!)fuB_9{r2zK>xVyK+tdY9LC>289chf@L!~S3<;;3 z8#Lwev?}Ob=gd@on03^255lKPlhUeJu~3pzmk80`)3;R%joC%8)5Kg1;)g6@Ybw@d zx-9D%Yyg!6izp4m;^^S!K<}d({eW&dkf_7ywiI$b%5N#r)mP4RjoM~7h{{cAZ6ily zxagVfK=F%|NuNdXav*TKMT^XEJjo6)0j@a-jfMOS z4W^cbdppA?J28qf$c-(>+9+JIPPb+{-K`HG&1M|zF5EtJA8&N02dT$6tml&H$`tse z{G2$nuKK=sx$t{_kp%tM)e~pu&J3rOB4SN5(lg^h{dEH`zXUur3%B+L z8Obg2>w~TPYav`FZufS@pw^|CvRi_T2B5hqMXk4a0pb0Yu-!_)@JEwQ#F9!P? z8t(a)#buo-+M7vM34##{P1l#=LO15(7hBs~OEG!7X3tO_tGj-T-KG|?1PdipMt!4D zM(#IX*RhzIcT%@m61Kl*>^xnxd(zx?_I+L(2R0z@TsxQ8I-#eP)agBdvc}%Q%v-{` z>8wekTbzLiI8|}J0&MyuwH7q#g&wNPbQP>ye(R)iMt$Sx+Xp zk3v8^OCLzu-iMvRw-+?gpWpNf!9~}ZPrmXBEVU|#okr!&@3@2RJs{A5ETn^)>Y%B1 z(?l#!vQ`Y41$+*EA~vJAL`ukQ}r}Qy^p0z zSkCX_bRD7~tH5!1Is^dX5<*`jK&>)8E>JcQZr&NEXFF=+kzGh<1rK^luS}!Oqy&>_ zy6Iy0$GxA7Y1OsuKWbyV>t**&Yty~l7q574LLj829=O>CG7dtd0n^eG9!%6dSj>LL%@Z_iXH>5}arJdm7OKLxp?{3=nODsr*@Nto{y0Wl6P0 zwpg&(0OScQ+#HEpzH;kxL>2#kHZ_^12}#qdAK{OMu(Hic{TyHi7;sGIng*_B*m`hm z9UvWciD#IPL?)wSK}1X01+2w0E^VLEZOf%qWs$Zhx@YO$nuY543%>f@>8NK}^PFG7 z$;2?|lTsOxqNeiTmcm4~R)O%I8`9|y)LF45^1=Af>5R){J;F-QEPB>kQH03bL)iun zzr4k(Ow;S9w18SK0)3}MWzKBgGOX$fYOCT$=cnPj(!(wM>;j(|+P??}KbKm#ML`K) zwa*2JR>=T-wFUOT^2X<-UwoB~6ygyz_P4Uab zvAnI6z;lPKLKDSJ9kZ(*jCc$0MiOE}hk@ETxG67cza6E#D{`SS)TKa9Mj}mh{D4!w zc#>fMNRlT@?o8~9x)wHU4|jfNEat2y^=oA+w>?!H1z7|Rb!Ymt^UjHrXJC418?&{_ zLHm}Hv$89yLT7C|HyS06L}l7nfQC$ny2WTqHcs_&qE5EkD;=(o&lRVUw->J!X9{+r zG~BmH-Gp931z7TD2{mWU{x62S9ZNHB;eGFgjq47eKYE;4Z1@`E5xAsXQCXb~dX6^; zG#QUEDPwAvZWr%YHir3JF`to+dtfh8q_gC5t)So$#e(-^+oX`hPKW%K)2E zKows1HPxMI+*T*BDYgH&zqhLP{TC=Cu>0L+U{~wUSOJv=f1by1qbYlbUeu@rneAJ!^bDrLW;@PqbXx}D<$D13ELOL+za{+w?*N53G$iW(9ET1B zl}tumhaZ10tWDV~)uXrrN%^!P4yMDPm(v!;C0!8hM@ zwXYZ$jI2DO_QLbWONDv6nlpFy{TMRiYpT=DLc99iRg4cr$my3EK4FLPpD<1z`@kgh zen@K?eLl&Ct>kB0)W~ai5NF#-8IXA4NOG$d!L1fD|51I!yd5@AL+>o4Sl;>P2z1g! zWhh6_blJe6J(ZeyvF@{4h|&(0FCIqcRqkh8x}WB3U*W zV24Zh;9qKHd4C5pAfxi2ZpGZo0x_=3(a`8*KB!%!<1AZHw3j0QL5QCGf~>pWQp8-6|1q{+tL;!YyZcj}p>QgB z8S0nu(Q?FTou;Spr#<*t=Ktnd=zlVE1~;X@iU^CyL-nS@38mD$-G>MM_FuDfwBq7uP7Fn(cS!xQlwDOkeP))U00a`39k^Uq&L{iUv%_dUB7JE-WnkTGW@ zHgz6B-XZONUoZU~)gEUfMzVZI_1HbSAN9M2NwEJoFHnU7J#ay-MWmq-HAsmmHi7ap zO`U^r{#=LcXRF&J6AdTUrk!X6M2N+jQ{=2=`x0pe1swQq?T4kzre{iHa>Uy?Q=-XS zx`>Wqs{PijhGU^meXmtJ02V zB+KddW^eGslD3`5Qxb09ItPjeC1h9tbDSz&w6TXFiz^IRhPEF zXRMN31_NaOvWTKr#d#b-FoHs2n-VBp!e$f^l$7qZkl0EgIBAj&Thg>=dsPz z|0dWaN*pc6x&vgCB^r%ZnbICKnM?=2mN-nfia9TDcc(p?&BX2XspVruQ+~bDBa6Tn zhdEAnlRruR9>fNyY}}#IN;7Buem8I}NRBD_|rpI``B_&rL$^ z$OXsnyoVtwt<$#`^p<#-E1F6MpSB!gcef6E6s5dS*}qdG<}LDVzN&K&^hvw<0S-^4 zAW#(VB5LV=oSV)xnMO2!L0CTQMIh7eDOPW2Um9>I8P|94_pGa^nKn6kMtnH*2ZPHu z7MT`AaSePG;%CJD=oO>_vZ$Q5?;pZ|P=!mCTcX}LE31cw zz2mvb2Q~KbhhG*&%08UFCuc9>3ujWKtJErsrU=pJGw#GuhcT*Le#fc%8KZ8Zk%O2R zBz@ea^k~C4i{XW7D{m#!N_RO!rl|sAl>7Ck#!tg5&JNw>5xExkFw8g3&lI4Q)@y5< zY7)cv;P@osR@bmWS^u08K5RR|T?=Sp%ipFmd3r&*dAEDHYB;pH7x)yf+jcEsVx7C? z70zNz{kj}^!pFpIob&z|9zQSjf9&e(;8lK&khV{6D_0qjzt8m!T?=LK`BlQHe{L7} zo)|fEAR`;z!lVa)l05)WGMi@1zpd+JX8oWFX5G08aNYS^0VSB_J=DAKRvkQU;WQsT zBB3g;EJC;YQyt@93GiU>-K&tRju4*6jDH7x#=A(f z2O))|Y?*MTChLmmd&NNiPao#ZDIvpKdMqZl*riYDrKcl*UB2bzW7rstyS zkQ*@SLQgH~*1TUX`!@gAvijWH>6|@=JVNT?8RzliOfRP1as)$njz2wV#2r4clz;`k z0ezF*-Ej|RpP^(wTM%`io`(%c_j3dSA2Ubhf__Up$ zuxjIrgV>^MFmXCXED)7PwC9kT=%}g-u!&fHB~^S({vzL3#IFv1A~5}^PyB*CopI}} zMoI%Gcd~L_ps@p=UT{5E>QsUAIN9=nyzD_j@d~S=7{2(rG5Hu$-ZJ`Hoh{3d5 zr}av`HlO-1Ia9EKVEr{h38C#zz0lU2vk*k4=YVYRy&nJi^ZxDW)q+O+nP1im zevL^FWZ0eQJzfLPZ{`}MTk)g{2$6s{TJgt89}*)^QOxrvrg;5Je)ThxO2C2Y0a=q9 z(w59WEx0O^Ne#8)DLJGEq^Z!az4C0N^X-QjPDd&rRDU%?`AK?xMNL315T-=wbDw|G zIeQ$Q;q=7k6hSIi62?4t%&$c>#MO5jm|=gJ26t=TY46A%pOP9G80k8FHk(b2&CNIF zqJGVX3ht9rAp%9(cMIGhlQ+A?Q(aXj*lFzGwB

{>#z% zrxNc&b842@mfi}VJwt1s&!w?WD-%>d0O*~St4*sSU*4Q+Q?LyK51~QtWBgxT_mC<3 zZPu(>#=;88?srP^K013?AJyzMcLh3LR(~%`(QT%agkD@B%%&AVeWzwup0B*+II54DxfG({uClS!V^%K0=9T@?`u|D%ofabA`sdctDqR^ zm0a!*9YP+9kyJaidn4TS%j{JQ~ z*pb1cqHR0%m7{4ak(f`jwejK1oFWj?on+~YPtO`2K6rpXvZ<2xE6;7Xd;9m8oP|n9 zDC(I#DZ^9561q;q9520jsLs};e_iFtj?tUuHsx!C{Sb#eEHeh*^qP(R!NjEhO!hAZ zsUNqoW=jHCqw|U(0=u!!hQDT!Udq(2!(ln1Z+bzVu2q4ln!C--GYKQ(k^-+JvaTLx zTd;@yiaZ%#AjhcR{VpBFI-A>|)>|x1V*l2Oj4xNeVAV%?c=W*$%U_%*AG;FQnCKp@QX}>*S>qc56eW5l*s;qseU8HZSFJ@Y?v8mfJJkR%Sg9-g&Ieut)%AnfsHuuIpDF+# z@C~s=ZG$?adUrkHpeo-7!dloB8SI-e0QbRR&-r@gNnYZWPNJ{dIBsT9={RH!Q4RPze^{0{Sx^0XM z3{IwP`mU+5y|c80m8#*5VKOK>A-aMvzB4jFaD}=p`F3RR&Z7)G>?{%+YMXGM=1k9~ zCW`jVsy$78*H)V1uj>V4;?uUmU7dIN=qK(2?;u(c&+LoLVw=K6hand3?j0HF#6fbUSo&_i9pJT@SsPNgZr^`KiEA z%nq9P zoWgKb6%=j*0xjf5YD-AW(^)NA=U#;s+S8?0+&(KQjDzgdEAf?7@KaPxPwyE|(995^ z3vxhGZ#aL)MCyh=t4#mA%AxPBd(Sp_9&i!TjSY{-iroWf7cM_)6!@I&uV6Ie5cKHS z^OI`dbTjyMw7m0h8c?NV$6-gsIW)IXFjk;dt|5(Mt{;gJG3e*V&%}DOa6n?1opsK~ zSUDe#xk0f#;AcC#I*qxxrd`%2`Vm=+GDM*gu6~Npz7@g67#?nwbwz%*IR`9v!EoA= zWh6r=v7`#VOw7qP1(2qU>!y~a9jkl7#w(ho1%nvpqSA@eI^d5EX9WdA;_(-wUp8Ef ze#IiPMcF0K47%x*jBffaVyAZ8-9|-?ZfYxpy zluP!q>_Gj~cc)GsjEnKx8l%6>_wef0ssZUO$U5(RQk5`5M;eGzs3T9_D^^XQMVlEJ z^Uny|$0TZa)9^ZrZti3?v!U3zO*&4!Ft^EHKITl>6NZBw#&m&IzudT0&NZHYjoN*m z5nk#ShV-|L^0bn#I~+U~tQiNF&2Vlu(k3nZG-b*<6AhA!9sT-TK>4#`f{dc^$&Y0V*4xmr8qv#D*X>XA4DA(B zoaP8%x84QGMM%t*c)I2_IfVl+ZytEUBS(P8??C4(QN&Ht6Q&4hFSv!J*lud7S7|Wm z8>eQBYKVmDxMit!-mo4EqWmw07hgrOed$kMkRT`7!o3gd1T)2;fd3AFk4@cF01D@X zdKNjSe>CI|Y2NSLnoM+f+vV0e)axi#Q<2tu6--z_!etlJs(Qe_BV)?XdsqKrcv}ik zUxS@vmh-}7UQG3Dh&eyP^ojbYXKEKAQw>F~mf5_x8+q1WRkE*my8&i3<zd{ zP0x0hW_IS7bQgZhZ)Kx87_ORSf6{zZR`aOgZR9-(Wli}4i@8JqwLzzrR_j?4@t&iv!D3iyt=S zI8H({^q^82ItBXKsOQJEo_;CodN8iT(%IcHsPe6LwlptM2R;eF8wPk+vF#wa9ddV7 z&rfF}YiJ%&(Rh2ppwHD8_8?*XTedwoyK=Sre8j6ov1iBl*W?1CKNVeJ6gbsf+M{&i z*%0D7LY$E~L8xnS=6=BKv`3R4SKHRkQ+OEYMUjtiG5Dz<1~i^?)6 zbCNSEM9F9@BVbo6*m^~GGfy0y-O`b0XoxPJp>iiOiK;x-jz21u1G4j>D#XDc?R3G~iana)lI)EA%*Up3Cs*#+O2F84i6cfaw4;b}zk@Fm>G37qJJwyR4%c%zMe7WI%wzWcCc1g!?8jWqs1F$nq-x z({i!TKh$5a8;ZGVDWx75_wvXq<*N3(W%%`3Q3SLfDi~|RDyEB4T5}|s-62$>iCgr#I^>3=G!K_W<>j?UD>hB}TO2dKbpvj*urqmw zr7cWF-!OK_)A^?~Hs@ic7e!U^4^LROQ2$FbxXpYI#ojJCiH8x^usFjm)zp5ty zNMyd+O8sP(ZKM0kY3~M-uV9P?<8y7$eZsYhKc<3jD6++B%QtBY7kt_Z_s)*n&=#V@ z^!M^enW+E0{Oqs$vsR9lPEc&SwO5`@N1aT`C3YWXBa(EO+Ll!AW36r4=oGbMKb=xf zc_J`&U%XD@idC`-8obupPt;3k6qq-#G~P3QmvAOp>l%#`J*UR3)*@d}F&R5Ij2~%h z&nt8!DZVGx!TE5sC|P{nlX0k3{qA23k(UT16sz7|k?ik46+Xo}YT;$q3dd?A=|jut z^*Dbc{{sd;%Y77=hidz3!xIw41j@5}P19~qEJXe+%x@yWWADAY&z^eLpzo0Bh*E0~ zM3y@2EC-`8>WQbECV&tq8V}t&)qOKBn9s6L`rC@^r=tAr7#ET!wi|-|%4Y4@9ZyZY z!7giiYunttRXNN@X_?Am zIX#@VI|#PR1NHL3HMVj~bBTky<}E!+8cqe<7J!`3=xRc7D#sNBK%BD zD6pr)K2||Xmb&%kEky=jLT=S&i7VGlC;Q7BM)5KGB01h@QVwic5SmKSD#4oGjqKR{I_D^ipEJf0mH z7yP8(WMt*QywGqYaF5U+!91+|mdRIhaD6ga(eQKsBIUleNRZ3Xt433zN6&p^0R9-@ z(`QYsv!6%FR&+kJSemh$HgNBy)|d($4AxfJ65R?OFv?!#r{l- zy(v-nl5Ej?)hj~>cl{E_l+S4-6G5`=ZOO!|&rO(17QPx9#iV_RUF-(uATBC%C$^&Tae8H8+;}<`dNgJLGC} z!XNy6BW2)lSwQ$={PQ|%YgvW9IAEP87qH}Vm0*ylhmGr~S(EXuO164k4GzaXGrz*+ zZguE<4%~~iLU&iVaIF?^`Q51;Lxo!eJ$(0}FFpH-H`A5MVHGAtx3tVR2l>q(thL;t zuhob)55Ghx{-fPIubaJ0fkGS-?{%m|iHpi<5CkCp4nTBw(t!v!OV2ztF z^IcVO<~6~y!u`$?I?jHke=*dH#IMPhr0l>OTq)S*yam|KPk=|2 zq!lmTtTNn8mS4u0g-XULCBu=^K?dYc(nPm6Cvk-mKWv^zWWVw%HK};md@2L zO_4B)yW3ZST!yZrQ$&u7WrhB<`EWl%F*e=89Qsu6{X~(NbWKhhYEN-j98-y%o1-r& zl5iU(7{zsEJ}Y>)=AP=;YK)fY%F(Ea2wA3f3_FNlKUu>}x++He>6=TUTP%|A3!c0z z)JkAjJLA|Tm4I5+rNyDzXQ~${aJ}ZdjJ7>*MYj|#x|iH6{p>WL1@r-;a&<*0hp!<5 z_7z36NV7RSTBqkCp6&Kt`ng9g6W{K~8)YrSsoc-w+`>{TwE<`_02O{X7YjhwEP}Ef zeh=S=?XdBYIOwRa)L#s`gi0PcqrR;2YBOI`8)xX@)r(+@OP3{|7zr!BcN!?vZu09~ z^7aLiQ?v_oeNS3h@ps4SN;Owzf|WExIaNZOGl$5!G7VbehmrBc!d1a{?w8#bY)@M| z_F1S&pXAikCc0&T3$sjiTY?lJZf}xXeRt_*oAb5G2K!c0J#BAsK0GTy}7K zXmTSh4=+uuD7!igItrj-(<64_0V>f=zpn$zCx6@X3_xD{=l8EK{2qJ&UH0GZ%469E zlenexv^+fRYVWUYyjy=v<2)kMkL2NNi0S;Kob8SuArhMfCt0My(_JwMS4sjtpHFo> z0~0)p2HYf_4aA|60&y}*KmA~-YACsEL0jif$Fz5a9pPz@-i&atz z%Lm&pcYGpIbOcnf1{Yo|pFkxcQ;Lr41lX4Lc9L5aRh4-&mJb?*653ZVSgLBvdM5z& zROVX$i{Zo??4$>MSKC3N&d4>3_|t13MyS;8iY7`{pI_^Jx)va(H#o8LCHx?wzNMi; zo2-d&C2pZ6_inCp$AzI%EM;nGe2BDCt6n!b+B%>iAkxJJS~1L@CdEPwp(`#jXo7!yPK;)%pO;7EWCbf(!P!EwzIV3ws+y` zFbT*m1X$8f>hDZ9?xuP{{7C22WO826M$r`k+*&1u_Z$@zE=vbTg3Wa=UZa~zNao&e zQOx??>3pozw=XqXisD7mI*0N_MJ!S3=Q%t zKa3Wlll0PGa~uu`PCdxbbqI{$1=`TQA}Awf2qa4cob~(sz5^sJJC+vCL5kH7y3gEp zUDr&T;dx({)t%lw+Sc?uc4aC{Rq<6&X3LS%vw{^|z>w|YHs%Soktx4(TgKi0ektXD zyhq1EGZf$+WS3oUZ-c1ajlUQG0K+{7+264h)W4y3&fEk481EzDl=KXt1;_tGw;sVY4+Kq z<`u%y5$6sU+jaC>+@BFV6KR6jt58dQd{%9b&wPZd3r5x|x4r5J^=hqMl3!2KgZj@$ zBxw!GCl4333e}RA-Qbbw*nCs_rBB-AfmYuw%Ys?-Z+C70V`b?*%aok70n|sZg?Mec zxBT zbsR_ze6ouoSV-Pbw%VV)fsGx44=8W@nzGmNbrDr@#%e%|vezWt)|OYJTIUtp}!SBQM!TIM5W+Mi0N$Y=7&W$Z9O8A@?_v%5 zI@xR}stS`FERZ-IsF3wk`qs|m%^l8{UeiTVh zgzL4NEl}pU_LoY@dEZ1p!eb)^1(tJOg6VY`M83gIcY}9St--07Gr{eFey1FXzFv>X zV<_Sjgg%1AN#=OUkn{kI^q&N|s(WKxvn>C<3r6JO@+QvR)0G7oS(96T*;u6RRqM6d z5bKc@0mWbw%_W&L@2UOf2+GVhuw)i9M1x4a$7_)z1Goto79b3XQ-@q}i3=Jn;`g-(f;H^+VO>pk(=VJbWudZEeV^wleW`}cfHc8Z%NP^3)Qs8wY7 z)3A=^flSXL550SRGCKNTZ+8fHg;_YAGN{I%uJwIw-blV$Cq6dq@B5cbRRYuZU0NmE z>UY>(1!QslJPn|h*iTfqn17E4fX)A}f2qdhnA5Qfeg^f;dA(`>!OS0e|4!wqmUn3( ztMau|5nI0T3j)bMb?O047K$?W37Tt|zDNmuB`Bs>zQ+^k+uK z!-X-#=Xy&Ldw?t`A;+e@y?0>8bbwm9{@vZZrV(t(@(J$%MNF*-p?##O2GCqgPZi(O zBTAT+!rO)2sMozgU%Dh~DoEq|kI0koqY=q)RpF^gfrUkkpB;nBnI93H4G(T^Ry{>k z=&Jl&L>cyp>4)64z04Nyu;XKM+2_s#foU{Ndv6K=g28t;%sbmNN}{H#{ED#SD0DmC zvKfvmeHB@gMVhDc;(B46cdD>&Mq@HBN)<74TeGG6vRE``j95}<0QWTLSLswu?q>m) zbwRMl@icWO(cO1j79IhYkufKZmfJ*YPv3S+Rd5MUBfVMev%0{T_2<^xJ;N~XJ(3^J zd$A#>mOBUKFHpIHnF)TjB8$RqM0Z-x+b_RY3kbe(%f`4~u&U@y&4&%E^ip=XCwwV` zj$zw+lDP5Gi@0~v$aq<6voyHGRo+J(G5cwisAz^ZJNo94$M+hBiaWiR_9h~FYI!{_ zzJ?V3dHKDzP8Y8oH_~K~dtOYu=NOs^!``g(1OgE`j+pY7KgQ(~WTY|4mw4sC=HktP z5&=4J$U#=!^U4#N>H@fPrSUW_p;oPUhiBViUzg|CjEA-0zBzNr-l~I07UgIi&gui- zL)d!aUteI(ws{e$eqH|rpJjCzMp3P0R-7ta)rP~2{A4DrnIMDTo}3Iv)62un$6 zJGO8id~)v^<8a;biW0f@+WO@og=T}-NA*4*4BsEl zbva)(krygSA*yw_t#06(5rC=vc{zYo`{R57SWQxRE0GRV2FwHO`yb+{?LckYUkn>R z53G0mc^bp6?VrvA7`Xk$03f*kPA@qA4|%QJ7QR-W@(D1VkB(um*-mU&*-pGeJ)DSg z6BP~x*tu0DIwB@wtZyqdx~fV=o=6_}V^^)myQQnB$*;RILt``B&@-J!$TWf4)%h~> zu(!p4)SmQG@QBRqhywu+MWa@WA+2ItA;Q&v?$#v1jgWMzL=9s>Q&f=Ktb5i_LkWa! z2)tDamqved!=>TdZ9i0M`M>*Uym`bRfC=fgY5dROGKCUH484$06oK&2t4MW@jKD^51*3!~A`nE-~MA3D0An=cK+>{w1 z>{yUfPL61Ct8o8N2fOp86ac)F-xkvcjEoWt1e_n3wC{ba>Nx&ZDf{}NB(5kls_c&m z)U}IT@XMq{5?(hj<-s1jqkfqX$QrnQBPR`@uhvICX8VeINYdDJIdtHm8nYGOLx}gj zE1urMKN=Xfn6H&TrgFykFNUWj@r4lLbdep*dcaWIZF7E8`US20p~i`$z8P1*hoWzU zJ34G_|1sa}nu?<%X7?wa+%G(L=sonIvV88J?3#Vt?2h%|ww)ewd1@r$vdln+#}`O^(JKcg?Vh!EY0C`$iOD<(Pg7w10RmEtq=f4*c+X8zNo1^Q85>>e z(Z7V`df}hVgx}m72uuNzuV{rhPJeZS(^9t)d1=^Ru`P0%hN&t7+Q7g(m+7};>X(X(*ej~tLu6q z*Xa|7&*R+gyrEmZ(x&_g-dUIHA@jc1XwS2rY35Cf=ky z>1pwhZ)(a=Yv`lZd-J$RFYZ6{1AxpzwGGfJ*K6mReQ90n6Jz1JyaBu!<50L>)NK=v z){C;`#m}PJS33`dfAXVnarv`Lxl1aK{K*?Km|Y@SfJbcYx{}(MEdjBPs2#}58<}l^E&^<+?8lxyd3#Fja46wVw$nlE`uDtAmrv6f8>+2} zgM#4`eC#@+=e}-H#5QmDO64DmxPV#>y?WrwDt()!@1UZ?AA7q#ntPiCYH^{OIIRB^ zTa<8=n2LBwFcLW*YcTg!=1F(Yt%5)4==*T}|6K_De=KEwANizQgkRl~im6;Tcia8` zpOkE0z8xNHS{p@S(PS?~wO z6rq;M=Xvdi9ObyD1GYhhtS5=H8Ot#yZ^Yv`A_`lQ%~+A9O`V_bFweBbS;ta<@fxM@9`c`N}3*Oxx82)(g6nv?(SF9!Ax3o=*5tf;*8|6P{M0Yc%t%i- z!o4A-^E738KbA+E5CfMRo0;(&ze()!e53{&PuaWCFv3&Oe;HpqhOP#?s>5!C zaH^FHteTjVu~B<33cQIK$S-XuN;_v>m-5BERw8g6O*KX=ic%_XnVgV**UBWCA3W2k zROu*n;9}%8*GaeS(wt3XeAOCeck`#RINDWK27dm$4^!Seov$+NAsz3nQ4u;mO3L#6 zbVoyUj60vJUf!U$LMG~6`k8(g=*`wjkSHd&@*T+hhn7;g*_WRqI+7Qz)yqadQ26O( z7&qmLAqOrkR-h(ebDKJ2zPrA=o))Ba5fbfAU#U3hPQ~})sTFJYNA)rv`&GYB821W$ zvNXrnl?;xXA9II6vl*BSOEO0TQ1q6J`qReSUh{WNo})rU4<|%0XJ6p=(9aqzF9PUL zrM8Z|F?FE&$<6;Pjz{&Q9awD%u3N6CqAIEgDO0D>;>HSVkdiVO?)edXT=AUtXo~q& z?5!V>BF`_1DaA6}%X};_>Z+t$>|y!Mv^%IP$$8xOdV@DirYhU)j;MgialRT}_+kry z`P<2QeOGA;(wR$y*RO5#?6`7!`Vlrz>p0#ZhX}09^WvP>ie~wn((N7`1HI?@MIQ+q z%Zb!xu!?&k;;iU!N1?_@cCzyE`!f&sVUPdwfBW}9$;K5&wCfnH8R6&c^7FhBwr$=l6?sPJe%**1WVvopL7TpZJ+$~ZMDRw;cKk% z+Zu`HcmN+26^n)*AE921BHf?q)CiS6l`M$VjUqvXeiZl=gE`Nkgu;$_rkZ&Gq-<^ zl`YnZ=C4<2-l|;Rfl~;pQ*)}wT;dXL4F9)|g5=+NaAf=Fc}WPT1BYo~jML=(ghbov zb3y{|&qO!9TOK|2@ab;&>G*6PrMGmp>h;p|X4~FoI^g>Qu`E3An=iG3&AO6p!8+{U zwhn45v`*&&6jqrlCVP9*UVdiw{<1R!sOl&MfKT@|!a|d~GR8!p&KAqx(l8}Cd6j>tJ~FcG}_XDrLYN+p|iOv%s(Dpo!P7AbdymGt=D_*^{~WO+xA`NdnUST)gv zLwdotR-M*9Y*NI&%v>1HK|%mLWzfbfF5z>@hA)l}zoHTSOQtMWUHK@(KZJG;_D=N*##cstVd7+IYX7dkpn~# z6W)f&T`~i5ZI%%+50s+IVp#<_AIfH6>cz^w)9he&qUS8cKWDU8Nt)i529*`rQ3W_wsbMsJ=Z-^7nlFdWOPoo|Kqc0T9JpDMaDN2G575_lk!a# z%`PsT_lfs!bok3gFNNwUJTYTWb&U9Ok^NXp!B&kREOgfm8IR*47d#+DIpW|u=c8#4 zadnk_uAQoC$eQKI)Sk+%hDRbUmtXKF<#0^%WM6AL&g=LR@%q65S6l-VNkmsiy^J9C zbU83*s(4c*PqKD3;n{5^o^Df3sD3%mlTW4+z(pmAxuu&$3pLIMs_o*j-PD{@YhR)h+IA&bU%O_Y=8OQa zK)c&+?OZYhZlls}cZ$nR+la!4F<|9B-{OG!6dcvS3*DRFTT0jyb0n^rOlpi|pdO@-LY#3Yp*{YEv z+I8Z!EK}p%Il6G={&gXCoPDHrx~1@?YEV~Z?b4Hrug~`m^eoxH&FryzwLU?MBSyqs zvt@FgUlr+5Rp|teU-Q?ZQd1B60bLbEaH+V)NbbOD_O(}U3|bx9dT8Iye>7N4P`1y_ z1ZXzQjbCuMja)5Hz-zT$pG(#mLf}OX9cr%{m+Izx(-&{Iv*~{hg3r(k(%o7!b%jIn zR{ghqDH|j@>w{tMEbm4ve_v%;W<%zz8v#Z9*6J@`y2RPTfAHM<1e;LxR839U4P}U& z>9!w=6Ps4D{qlvWQ3z#GiHgu(hsjaieO);usxO`ly~6kzh9lb7F%X7L{6`_VYOYKkU7CR8#M=Hy#x`il9;jl&aD!6s4+&fCva8 z9r9Ibh#}HDvC*p_M7l}|NQu+{fkb*UAOwgckkFADdMEz2NA#R?|M;zS&wJOp_dW0Z z2Uv^j$=>tKGkczy&&;Pj#7f}pZEN0iU-)WpuuDnyqYCve>^nhq*|ElHdc9~P{qk;! zg2&x)`L7^PiC%(Z7EO;Y-pD=`f2~GbN7JcG&bwOWI(WhnEJkfBlz5U347b_#U6pJb zxuY8--w~q!`6>keq#-A5uPR(9WNmdDTUE6~3}0(_gsD9yFg-N=UB0PLMqASgtL5jg zr5mX^v^44=uEf&O-i0kpz4|P1onu{U-NhdZZhJT42mwQ}-mXhqvlEXdhGjFM2<5OG zdqc$h8?LijT4KBp+F!u0+t^55tq)JS%~l*G5q$qhkSGjlxvfI{t5bZ|m;YE)kfiHY zjUPlfB2@eqER*L;hVq2Pz6|Wb;n3D=?k|L{Ci(RN!Y)VpjBpi^jUo`mNO-6;e3oA+ zVW31*c3j{c6RTgwwZCq{8dbZ)tvD0FTJAdt7&yv zDLz)1I5z;0NIYjbY{Qh(d{7W|mjAxIfhEt^;dxR($pAOmC|>Lk`{~!8_kWTfe5(BN zc~?oAlw9Rq91cB)OM9NHcB3{F^skKbKcL0ZVJSis{HDPRk}@)y)gM3Y+ym^?gL@ijm)^zi3q@jd2k$RxlK ziU9{)cU)pbRtioXmY`CJUnBhhnU=%EhOJHG^7Fbp?ZAcH0qGWy58usL{rAHAc!Xv? zj(HtDcQ1TouIx;8+Y$t}T}4B_jn5Y*=_d4#>&^jG0zW{#1t4F;LV20M53amVZaUc} z27IMB5>RC9iP(EgO&4oSo<;dQGP`)F!AMMhbo#?aH8OX$96h(>N}8w5O@E^=iLM#_ zBpaAEQW>V7mV4!DA|v~CMai)15Y;S@Nbcuky`yz0-gt>NH>c>Djmz=)0SdezmYe?W z@0zgN7B`kiHFhH$HSUt~Zx<~sse;=2^p{7qy=u6c<454EdBiAGI2n3(uB~l>Lf_$k z&)_!{Fj!Uo}bJLn>_(}>qW%7^Z7Uo4DRyLY(Via>~u(! z@3@^o6y$a1Q>{p?;}=RsBn?YvC(+;QOU>J?Jgy+z5Og%7)X8dCskruBlxlAV3D>ns zcrS3vQLl&njyMAzb4pzZR^AqsVx$mBRsfo?UUqIwmc#JK5e$vt7fJjr!Z{HWl?O}- zjewgH-Ly21{{XGWOKYr|+@lYfzXx4_)vS&jR18(_iZa4*D-J??B&ovA2gv-?-`drzwy@DSg%JCy^Y>DTNbe@Q~X;mMn^^Kn@2qJRff1o?G?gb z%j7S!x5*zf%UR7&ZXFJ(-lt38fk7zG|Cf4(;?YFMU<#I1PZ zyFAg{L9XMGwD_kxy(b0WHgBcVBc7FCrZcBs)ER3orIa$vEE$#FljTY$;V8f#FuVU* z@m%CQJ@U!6`bWQ*V=DJcHS-Ar5rnR$G4N;33-J<>^-^DgjA$VQ2}4z=Dq1l84jII=n)hqOXfc0n`%5rh$i^_*vBGelWYwi( z9XchV1Rqxh{tk$_m}$=FE9v$)fXI zl(#hT1Bd0o#05(4&?qoI`WRy*?~mmfd$WWJk|b76N+uz)EFnc3MutWot_oRyXucjX zzaTTbo$Em|mBR zm~^Cx_zH_qMW}X-&@twibNYHs)aHxM2f4&&oy@6!Zv5x_q3y5~rvtZPZq{U$Pm-sb zR^c8@suto>^GCtB3~>AfV-7W@b8|N?P9u{t(TnuSk0gS}#rExLI6Td&?C*l8A;S~B zA`(tRv(USr?74?|cGS*kWZsN?T2$PqajvX2+bQ|kO_2W-Y|?S_umV;>C-%4cAA4Fg zxGRglV8CR>vWJT*Wg7|}FK&0dJ|iDK0Ws1)4BFCzovKt>!i>Mz{6_injsL#8{lCf^ z9tuHR_kY+<+y?79I00}9{9M}PjRSu?>gWod7hyF`GIdoxLz2-gG*fr;a6$yEi^vk{yNpM{3wdeB6;*d%E@$PSgz`^U!?oZ8m=Bqyg|mkvGo-7rS|%;t>P zK5`RII{LbvRLUpukod*?kB!`CQ~py8R}IYw6+dX+p4v`0F3$EYnnkaqm1DPy4{PRm}v~nPa!4i&$HAQ zEnJ*RJz)XWB1+Bm2lDr|jR}8#ZJyrfQQ634d`U%F`N0d%=H(3rRz>%+gd^5JkoxD^ z!DU)Vr==R)1u+!iqe&F0k`=v=gI;CU53-+USkx6oU3Pb*M0}|l9FL@Wqm`skelp9X zzsL-AuRm|0@>$hkW_Qyw^40jD(zaQNq4;qvtiem``{#au%spB&;6dQ9&4P17wp$$vaafxj;2x2C~--FkmDqRAu; zvLx^jEVCWt>i4ef`gx}q`S4)?T0*9JQ0V1dSf{DTm%leM5MHR|>6tfVfA{W*EIfIu z5W?2PjO0*u`~f=O_&9E)j&qdD?mm{YtY!G%}u z4BpD_m3;n(U6xevdE)^gech|kM}oH#c){*ZFAdymzXZ8^_s9%;LG$-Nk>Nunj)y@O z^Nf^_WT6l^0?u0xIlrgJLKXB)$nIdFjB{9cvP~r$B=^JkAC>!QH2yK>f3JYyKkGsS zqVaFG;%<<=WqthqbZPu|9d0)Nftf7neId7A?McRKm3xQ|yNt%C(Vi;xYo^fe+;2=} zaDj;>iNRGb7EKC7`JvFaBbPb#tTxIVVf5PQgM_%{0U#5qNC6Iy+^Gh`A2!9Lw452H zh#IkkrR$PFZ?mPJ|7_HyF2xJO^cg7@6DWJ-DV6zfGsOGMf^=y-EZI!)h_(B3#WzRh zG>)DV4${WUq3H09ai9gQ$6$wkHGWZBMLid+;M%R{i-q}6CfwGiDRb&ks5*dL0{v=; zC~F@koBmGqokPUxqzP;|xcP%U!kIa*R;#hO_JyZbhYGV`*$yAtJ9&=@Um{M1B1CyMw1g5@Ie- z7pl1>Q5asBNruePJBiZAD=MqEtnH6bA@R76~u5Et-X77 z1vMZjmP|^A|I&6>>F|)m0}o7#ROdm1-s#O{#Sz1GJv+A{7|*@p>h8M94~=_iU-yah|iA?#Z&n4js~W4OK*m#t5XaO{_3r#x+0;&?na?yg~fX;`|Tw_}r$wC(e$GuMkY zff++BN69Z3)%8_54VhKA)wBCwNUViwv?t|J)t`iZX<%JFwPZ9mTH>2F)VSYU^0$_` zFI*7r+i3^RHY7u7@-~8h(yvYe7(mr{)Si4t!^+@+c!c1I1J`YZ-)_Zd(sg$gnniJ( zdE207!jkn{GXPNPw@3ijSdE`Z@=qH9ppv`)2f&fLmLUzGA^+Vz`Rg1cdq-J|F&otC zr_%WBk|H!?O1>#bFzB|HrqsLYQf#C`3z?JFnj&=3La%l70v8$jepi|4kP8yPk@^&A z^qVVWMX`3PHdV56K`koGzwI3k!@Q6~R4K95U>i7Beq(=Av`K$;o7`q5XYEo1VRCEN z7DU_TCw&;Qct*_gt=5jQu^j}`+ADiLDkOd3cx?N@wN=f(9AH_%A&O+Iasmk2^Miym&(2g4sli3ZUi3i6Ww(tDHNSe3>3FojhCAy zy&LUM*`{n%(}s5>XQ9d6mRvDS4f5Kv;Ss{|X<6nb0a$E2Bw;j$UEkX8OWhhQ=8LW% z+7Y=cDvnk?0k2)%{#HV4q0trTTJz{o-)oyYj4QICBykD2yoUSV}T`yoS#c$oL zfaU{pgVpH5Hg%d;h1@sJfCS0+&ja1|r)j$`w=3~Ml-Lp&;aIDULQLyUQG+7;x0M#a z!ODD-j58#T+lAUZI-U}i?VAw7m+_w2o`LYo8+X~&ukC3Oa+ckuHtcQ=!_hGn`?VjS z7nzfl;P@Jj)_h((db+pc!}Tx#fx=sWbhBew{m9dJryR>om>_5Ltr_%h;2b++1861I z3oQj{yQ;~YE{`c|N|*#{Z6$?6DTZwieG<@U+`t)^mTYqi;UaUzxAr4(p@K6{IX}Me z|4Wl;g7`-%7u<`s^5Ll=n^XGkNENgG;lVCNwP9XK*vY0cZn;%0%7$}Crh}1~L|dTw zrTeen9%PCZa%tu|%jTo~$DQ$4=au>Z=TNEXTl!;N@>0_ig)N>^HIN}5I%^AWLw~1( zN1LJwq}x%l@4hOxZ=K}ObZ(jON4_fm zz1@uhpsj!3`JR9H0061pRRsXk{gf_#w81yHlHy>AVGD6K2!7A0eMo?phS1 z`?Pa~2&=yJ?!1H9vE$diU-6UsZNHWmgu8&H$8Ni=EZ-tNgmK@c#zW_dc63zh{ExEB z`=`hjI=SrR?{8=r&3%;JuLc|MxcX(v%J5;_P3JwXqs)VLr%AhelUSV(6OY*tw#E&5 z4^%tScf3u6`-Gkv@g2b8=TG6-@iE^fH{*7QQ&MMwoXX<8guf+#t7_s7kJyVFjPA3T z`)!Wev3j~Q8ORnBm50P)l53(bLAG~h$pU<9p@$mq0V2WvGUpp5T_ii!;YwfWYU5t< zH<)N98=j2tJ+X^(7s^#KcVBxw7E3PG%iHps8zI7+i}@TYC={~I>N#m!FbANTv1go{ zpSj!*;Gt}NawW7Zv1aC+LgB%IEvFAjvb3>{?n}1C&i>g4S_838U29+;-KCpVPgW@N zie%CdVPGv7?WW77X-~+d^oMt#?%$P*P$_n2>gDBrRqueF{JaRoqH7R= zJ4a}~)>m-U8yyd(%y!L*f(@Gm`W<4(v}g$)zd6RzbNsp+d)oepwO7EvXUEC49M7U@ zj@SX7ygLh=8L6s5p;%$R4C`~(k2rr``)!jJDAz590z+#~*Y#D5o)e?w+lXV8n9In~ zLt_i2dG4kG88Ln#u1b!xOm~}4#m6y;*C#JvKu#S(tGl-$b28jIaV~!Xy|R8PNq2#P zTU%Sbw0-)WNz8nqU`P8ulYkzwD(j^dRk6F^M$B@YzpVDku z5xA^psQNodk=g(MSmYuix}Vb*6&t0S53<#}!4kIPi=ZD7_*GAOc6Iq5i$`55qx(@n zxLAeQJoNtg(!p6EwID2|1C)vGAvR@A|9ND1Z};luoQh?me;NvIKhM7%t9$eZ=$i;o z)KQbLksw$V62JeQcuHDoV?Y1qdfE?=x{}CMZql$^AYCSE=KEa1ND3;RdR@|$^7d?^ zaofSj>#3K|gv+WNsZT+1)fC9{^4FUNzM^s>>oD$m>iI4HoB0idihyCW-in)S84>5) zc{q*-gTytP_q?z0krBpA&|=4`^QSX0-C0Nli<86-20va0Ws>E4Z@#@Cyw`&}(7%=R zT4+M^jf@>^Bi1lD=|7Vp<(XrntT4^9wd^uNmg86@{rk zfBa17OS#A`Esf5RqctsJZaW>2mi$;uQe_b)aVtOjeXbD^T)VR!kMrS$Z;R6aUD!d8 z`Cgu7mC28dt^KZy-MV9ZKHj`(>urmoVv<4R&9k;ut18Uv?|s?J#D;P^N}-k~ z-6b1mONn;ulcyx_KQDacu$@N79``ZSGLa-?E;awO{b6qyw43e(jlroUacgZ1mRwxrzb zL;4=kI`;mdT*M&DrCTnq9Gr^N#5ygYn*cf@$$qYd^jZrI@7QW=@Z-;lMNK?H&_y}P&!CLtWNpeRRhdy!k zeUN@dVl9&<>qP4pj@EMr-&SSlIHhui8w@PUmO^IB;&leHq)wTA)iTrh_u@An(C>m7tP*h5E{ZS-CCwgD(aon6yUQ zxO@Vx)OM8b7vJ;v_~nx2e36*^7LK`r>Csr|LJ?`~tJV+0g4etY z*ou1Ofj;rZw5M?9caE2LkZntt{Tt1FYyNO7!DVS3*wMBAg2bwu>69rxk@6oPO>J$P z@&L&R$nA5sHyY17e;7CkZA_QL#V#Ld0}T+6D)au}vkvy4l&v^cwyt;??zkaLHH{SeAi0tdq zkVazUZHV$Y-P4ouRjGVcHr+B4-I9+2#|QAmL$Y8S-Ag556`Kl&)}Akc%s@rpC^7dX zofa_6ux#MT$u0@BRFj`PMca4A!&EA~ME8UPQkL7IyU3i9<1Abne>!g8X{nQy0df17 z9m9(juaDXV&7%TVR*>qSsxZ}^f&k5mNOWR`K1IWE)b`ckN9N6Y1750B-#~aCAhus@ zi^I}}ipgu$%ig&V9I0$1@vgg>#ZH?YLYeA+Z%WEv@VhMc7KDQp+H{|%@QfuN{>?T0 zeOD@LAHHD+zh%3AW=V@LEStPexlIzc`uq09zrmNET5W~0-O^{k1&Q7p zD*$eB746D0T+{7@m8+XGoY~^WB#Zhqj(Tf3l-hjencnm5& zlooHxQY`$}VDU(Zqz_nIMQ(9&eKWB)?X;q(myJv-&GII*AqK zIIAmGVNqr^dMMWnS?I@^G;xmk^1y~b;+#M{QB zVx=KR>W7S%nIc7qL)trlk1AErhMV{BEsSGk3p*No zHc?pcikftAVJrShO7oXXH@~~+ts~4yjxQ(xN0M!do6^&C<}z559)y z)STf<7pR~GUC5~!N(z?AXIs-u1`pgT9B5+-=rW-`JXUcul}3y1 zMqm+@5|UNXhvYm^4@Ke-?hJNN^1!jn(w_}s9P{vQsVFcOi#IqndKb# z5}};4KY(@7J^Y#0F)ynxF&;*cWnx0^POrb8oM?Wf8DgDh8>4g#cW&M9PHv@zx_g{! z8S?N>tXp-KV+h-Z$=i|fop10rf!}WyC~Qg9A4X4cC$8J+*$}HVD&wkD>`Q5g!$q<| ztvjoypDQe!yH}tvdML6m%+CwG=-4_SS&AiQ&9dM>Y*CCzFv*=K-a`H&M7#MSXfN8u zC94wt0BR@Q^*Wh#^h1K&zGx%I!JEyTGS7!pj!pGe>ZB>np|T;)Nx8Xg5h5(bnkT)M zs%o!uHWK2FbF4WYxLG53Aj!;3`=p;+S+1_qejhoK(HPLCu0t~W0D!3M0$0Lv?VpVH zoER|YvA4l?!X-XH?#wieYq4d`q%+%H=bUbMWU;Pl(2e8L9rDUg99YrTpUlLXoJcyK zIHeh5Q)lNd`=s$M_JZIMHL*z!SQora3tzE3Fry&WV%ef3Ph;>yXE1h}*}gaD8A#}{ zhA(SqCLDy#41$z9l6&%rhszmQ(Isz%M;fDS*9#t)7BB3dsPmCx(H!Dw!pg!N`S0Oh z@ED8Suu>I}PWQtytHc}LHyZP7;nA4Mis^xj;Vsb&4Y`k@kLIntGvY z`#RK4He>A`rf9=((#A?=G^VU;{qPY5)>7jM&d&wv_1sdyPh@Dvr|&Bl4$Bl*UD3`o z^9vNh93UIF-8R3i(LWOOx?J%HVsW8yQ-}eRMp6s57(xvg?Yrd3b^03bv8bqRnQSV= zuq-jLv@w6;sBtP6Yr==K8sS{(@l!fSlzZFnT$8C+9aJ(hT?kk$%ryl*m}hjdk^iOuD>oueP|pRpIV@auMmaxtevSm4^)G|^N4+&84I$p{DE}0 z#!8hwcV&;XOCc?~!U@(JH~OFI1%W2c*o7{6DV`k8R~;PK2_URcQ}PIW>EjSXsVDR1 zRm8h32}0qYIRCoCCBNN29t++}Z$YF~;ATB2XuZaEeO+tX(7GRGS-}`5;OVF>Ik&3S zmSkPxs(H4WI43c8RE0I*g+{NDq%(&@O8tq7v!N4iD*GI`EgDmXj~-1?t*;!5n0e4I zvHi6{_{-r_ox$mc3TrbJ*WCI+w#~L&%xJ9)AR(wFC9*P?hctTpu-|NP8@?%-sE`hX zC9k&XUavdS&2V@>1)bv9)`U_mle__bP{882nzP2ElKmS+mlK;79`;rbO9l7~ykI%( z@N|kJx&;bDwYb^aK5ahuwqASe;|pEBN7uNTu4R_ItCWph#-Ur=ED(B4W;D#ol*i!c zUU}|Zl&(Z?0$ipcdG&!NrxfgIvvn}=QV+c<=^w6MEt}U8<|t?L@xrP9eDBWRuK4E$ zp4Jb~_;*RQ)EGFGwE&RaB>&=GB7hX6s_Zc7{S(iY>b`N7e}-I^_;>Ly>Mzr`m;kh9 zx=nu0jMW2|@8~^0KrPbq_?;Ip#IkXda=5-krOT4W!^qB>(LpD5tspZux$TB!_|{-A+d8eb z=w{ZvRN+ojUQ<=}w6om;V(vpP;)3TknjatFP)vSMTwNKYm4th|DYr8Zl`>z@c|H_8 zh+vyew2X<35rExVyvFp(?Pyi_h#)FoyJv=d%E2q_J8i8dPg|}rm9tkIEm;!9`kmBU zrniB4U`lJacq2{j%S_&_sJIG6U)0wglewctHWiq0sdNPGKoO}yo+(vOo(-C41%2+p zD{Xnl5k$c%TY6YQ4x)4*67I+H$A5nTOt(>)yVK26nqXBguNIj3^i&=6B`)RtWD#xJV>Qt)+;~Y6E@GU1FPXXc!~xBH3m;aG znwS3iWMN0xwk(dDd&~2s2KUJ`$L>*^Rv&x7nv$?^>ImBMytm^~i-@SpemsnInU`{r zRibbx%3OEY@3?~B1A#`PZh@n2FJF$aee>7gm-LdJp|^EQq2yG3zJTulAk1UR(acL6 zop}070E6^PSpa%K@oy_a1W1Gbrs|)x!+(?ilU;asc>xULZwb%1e%&a5U;Ljf>QF{B zr}-n?B;%ycF1x_52ko&iG6F`w%bM*tGKji`VSF}((Y8~N*yr(&K`m$fr7dfq@m0T! zlqpql{*64d{1@DXud(W>515T+v+K`#aJ7mjmBkOvANQ12lG|U<_ye@7rp8#nE<#+h zkoEHNlAmr6!@#$d`(i+gI5^e$vv0+e5~PnhpqjbKqx{RLRdg1PN959ICX@1IX+9n( z6{Oex{8o)sLX2$lM@`kZM=v9Tx?*}Pp0KFf+W%Uw0$cj9`U}?`9Wx*Y#JTQHW^gH1 zNM!Y#)nwg-T{JtprLV2@JlD~c`nPXzc)oBTvh1=&is@%lZ3oipcE<-+pWkcU$|6Wi7 z{UEjRYm*&QY4T_5$)}^bs`TDdRZ&gj11+%Z1_266MLNKE_6(oS!Bei~ZkPv%UCXii zjuYst(z0IjKhv|kW7vD08KxA_r4zc&lw&Ql@5OPY1_fyj>0fKqdnav}4rF|K+G8`J zo7&?!P;5t0S#_l52eNzFsJ_Wlje~+OoHQK@$_}O%%WVHzty6q*^QGP7a6_DMr!7)T zJ!V6&TfoZU<5R-mK-JxCSMDE_WA>Crgza(`nN$5;rh6F&FBL z=e;u~WUU9?-}cM%{JU(2|DXN7hc()(^(oC2$i1whc4KtVt}p#hySl<8U=Kvqzr2Y! zF?qCr{fIQtkF#8;U{JA|QXJ{+Iv!B)dAYyu*9sV`H}Rb|cDrs?Pd*!_`84rm$}Mq| z!pHCKdicKjBzP?H&Uqa2dy}1yo1E|8mbizjbXI^;H)2}e^F*LCTg2C4pX48gXM!-vLS+>W_$>WW7Ak)qepH+j{LncX=|Gx#O$-)@^Q>0h%?2GLws z^c5ZeutPo3t*rm9S>?vDAGF1Ex|K_AUq+?PDuku5j~~=vGvhTN_y&Y>k5A9}?N7oV|o3csUCDl9oS)5y*q%dX?1=Uhe)Y4RqH+7GhZKqp~ zXm1riH2qt>Yf{8l%R4qkY=JjNL0z{gqvX7kXQRcwOUbIxfxa8lyC@lTy_Faw0lMbp zN04)p5Qv#1z_+|fmD3p1orJn|qRzsxrsvyWW~3~#m&E;~u+PL~a#7;5^Q%W`gh%H@ z-x+`#u~EOIndEc(B_dqP)d#ln*Np)fD*xmfGWC4t$}yFDRpl?$B5Zm9>I@!=`)iHo zATaff_0`i%Y0)AozR+&P-RC>8X4gT|t?;k>zGfleWnsF!lSElyU<;}py~@xEQ(#u< zFh9NyLz6ssqE@hDNrGVEy}Gko#%T^ALK{7|Hu9sJ&U3p5`}KhO!lc7NkP6amO47~H`N?SmzJ$- z`FO~3g`aDihH4DR{q&T?48W!OVU11colzteYZPUwW zA0~?wQxPl!o~n)V;1HSa3X)YKGzXp8wTy9sx(PjPI#oy!O*jv}$Q~Xi`MFth!+3UO zSM~ZykpubbG+iUS|Hnz`fsDK@)S8$ddArgLAGcmtZ)j9`irWtrs@K-LpPF z)}0S`G!Jn(<#aVfsO2KBfwM)$9{!%+3n3;6T_(~ke0TU>>O&vm5m-1DQQ501p@=WM zIVzTCX*y%1pLgIIlib-YJ_zFpf(G82N=~6zH#j$(TkiO!E)A>6)L;Jr03g4Y1fZQw z;$I^%Hh&Vz?yfq3OdD_d*#(Bn23Y=nUHp@Hw(w`i5B(zmB-vHmeSmxRf4sy!zlM4C z38@}^Hl2d1205p(hKCGkd5x4|E6iZ}jb4JqWii9rA#Oa^SsU{R0Zj8Occ*{v@FP=B ziIa#1na#ijCqLcOxN@-tfwo5WO-T$(&}dbF_2RNwtYT4qK3S>GEYJ2Y6)$G9ls(GE z4Bm__qhE?e9c*#q!)$vYHcqd{Tes>0Uc17-3y zn3!2mdi|>9{B33RgsU9&Nyc8UJ~7EEA$K*duX%oPdCY04*SuqaqK%tRa@N_JTnDOF z2f-3-nx1PfX52g~zXB8Z9HnP<>lnO99b8p+NsDh_CFC5XB$l7darrJK-PiYX{Qf|{ zpk1L4s);zD_gR^TO!L9(gtmFe5yUoHw#V?m$j~*&)hIJ<9jRc`)4e%mlkYm=f)&`3 z63_QnxM0nDw65#lD&uexg%s5NzCrB*s2gSovBVw~ryPN=T2whq(Hfejofv>}AJ3GG z&8~%)P&{X?%Vo=`5DDlQtQBXjJvQRBbmTl-$f)4Ajd5W2ADYRBBUez1J4s?fT2!Po zrWlM^LHlDA>*~s==c-B;_V$EY;{a$}4PceGl%jWKk;bQlR3UWO# z=y%u7A6|VCCuKLi4h+0=Tj35nAD~UG7A@k?6Dj(=OZBuPu1AlZywz*fE3L$4 zj25ZtoG7z7&@#Lw@0A^K0dfx(yv8zM9qm5x9sX-an6~-?XDTdoJ_cDZjZ4jF8i=|` z0oz8)| zJ7Yp+RKMa~%^Oe#^k!l<#Qcx9PCF)XaGCltJQ(=gmHs6P|Ece}LunWJ4@^(*L}gu; zhs$}a(4&g+rK z%x?9RYFU_R0J;97FcIim$G0+{?GtYV3bn5s{9<#TN9cL1W$dnN{%C&c{YB?K?8Xf8 zyOB&Lmjr2pw%I+eq+EBubY3b%k?SMGw3HqK_YEj5XM9P>-yX7Y40Bq|(iQS@KIcmx zc)Py;6ASM5BJ^}Szp;@ZI$Kt?gOgS;`bL%g$cJz#EIgiS_;mqYat|le4X0`MQaiL3 zOfAhvG%7{xwS)TVUrQkqo+TYzd-UnR+*{GU-(K^!S!k3S;Rh&ImX?Lql~CyKBDg}N zw)bb@C3H^KaQovAJkM%@OBAGJwRw5CNv8Q_H9IOMI9kUD8!kO)ImhM9#Tof(@1X+v zZx2Ooanq9J~ua=N&(5}w$u?T4NQ_N|gp^t8ua+R<6* z>}A~(lbfZDDZ)h*(@Fh-!xqj_Q0dw$hI0P*GC%aAyql{&trV^fuLnW-gE+q)o^PTFENx{g=WG=vq>^FG{^{WXb30G!$nk_so zaj_O$xoY|QeVel+BPZM=vj*71tyB70@5!|1!|bW7_?~Syc4B^4!QmSmpOW^B0@FsW@6y6Vh8~#_;MCrL0h8X2jKD~Ul{y&u#5yt zoi~wcLFKV8$eN$+yM%coXRdi7s{K6282@?d4fBAuD7D|tT|#t{)UjEpNm<@TbO5Zk zJT!N#RuViPi&EuJ^WW|JeW^3@YQ+WPKM{>V_@6)j zuLy4b1#blUl@@#wBY1nrLX+%y@P8mRGYYH#X&I6YNvadnP&q-WH&U@@wD+xc9;9R} zF^I+Ei&YV{X=U>b&y6yJ>*T~V&n3iYRWBlLi*hU3Z;h{=Hc$I7<#!T%%~S8^JcdI} z0sOTibqu>zGnUgl{9-LzQr~C@iu-m_6)1u9FZ^l<)h6BUN^k>`msTb#|&s`v>Nup*J zRa1&=XCmuNHLGP(kNi0M)$s0|rU%4tj`nnfE*19!baZDT$0*1Xqx#kNa)C+1P>L+^ zUZ;P1dPDrCO^Ke`>VeqNE9dv6jNeN}eB8RDbBh={o+g?IOjY;+I{Ce_S~3J*jsgZc zVr+VriTGs`vliHy{tZdNV`SYENDm}P5gvh?*IOav!1e6o0H+hG3YT*sj) zzLo7*KY&1K=kzyfC?hQb-!VtJ?ZfLSTR>&Uu7~9V_@{xwc|ukRS^FJvC~|35j(=Jb zG15ssKfdIG*(*GNbv%46XMF9Ev5E>KF;c~qGZN8ePE-C5x=ND0pgzI_=nAV1)#p0*L6T2 zDxV)u8}cDsqz&`p!X6DKwalSll2>$Mt)3dPGV7QNoKmohhDR6?{6Vk`w3HY_mWWHl zk&L?eLU2eeI-P<^!n6%c*ZR8Rk2xyylj|}%h8`Y;JCnt)))pOpgY^nQjn0~w-q@=M z6(M2{)q!%!=IFMCMH&$wJzRlD>)@4q_-5~$6e|T_uV3y zT)g1x&a<@PE#j?sV7-a6WBr@TIG+$jQT|Y0fue}B_I33{MD5j8!rMhQ?U05e{D1b!zaSc zgsNZgqH6l7e+je4x~hvw(o3CN&3Hateh7EN&bF21P`8w^?tT3(=CNZ-(7EZ!iE(Ty z-BQhE5OIv=YtSXRtqH&um_^>ZWKb=@`%5E-nA>D*+) zD$^KFaL#}|stSDC7L4C-!Qz?7;R$1$F~N*V@s9mEeeuQ*CmK8_uf^>C;428szz_C ztk86$T1qPo))bSy~3idcw(s-vE;>0>a?Q2PjCDrc{=|0g0B2{{U8F}cF z=2mv&=P_e8dh97*DVx<(X$EQWWkjMGwYO+lTCZA1jY^wG3_ALqv{ZT5Ht*${+tiiu z^;JaHwVr|FlD;qQYpo6|`%!`iCVcy7X~QVtwzW*4o5$2+Q9vrG4Pl|uhPL`9M(}5C z%2Kr(KEJK(n&XO}J@IwG-bq~Ew=Ym}gEhy-BID6K9m(u`wNT3^)PlZ_uuOYOjTzfu zAV$3(o_hAL%mw-zKnM8oXg4Cix%>MD3z~hw+w*{KD0$d(-M(@8`zoTZcG`||)C+li zOKQ7x=_-cLh=6sx-k>X2alzdkV-dUKx_qIrT@1hRZ8dQtra@Y+%U6A;O1gN#Ri>h_ zuXyXhEcg+ouNY2u_e#Pb4h(GJEPBwQRq1{dQ)o#teBEO8_6jDBPNdI{`^kY7Fx%(w z6sqtNeu$UR47_&ARMs_By1guQzeRSGtoE(q=?mkI^u*w;&TuU7-pkKdz*Lv4Ic~Dx zV{|(V zT7ztA{8TJSyN9vz&8P>}S(=3>rP;aVN8LxK&H4&{m;|%v(`z)cyI zj&CI=I*}%_E-ldG*u6^q#q25&jXl@2>MqsT7+qZ7;CZG#M^KwCBhx9B2%DXP=Cc*s z)vmL6TQu5=mfNK0=LD6_89Kclo3-vtsuk1|w&_9F*HC6${?a{DC~mLnsz4JxHM`Yx zyaiv8xf#ph?ckplGUK+?i_9n`MM+G|I~_(%7J@B2tsNgRN58beNsBU!6%u-!76WW9 zECzg#Z%X)HvTcqWn4|6_es%6@aiFcNZTO3REgf9r4$MbvDNGkbOdlp!T8w&Q`^(F`yR-m<%t|{=!oZk0ef(W+x?{AiH3=AdfiN8xL(d|YMfyQ(PqGI+B z&;$@7(STlCyEy*sCGgfbkQrSBLcLTdfCu>s1lI<{7uTK_iIN zyEb-L;$0?Qbk<{q`akl6K+ry;8otw!$F7{3?+yJld4#vwir5+A zhNycr_g5!(Lq9x^qZdoaJH)~1M5Vx}Jm}#psDnhQVO4hln!8m{;G?;^P|VfaU%I@m zGb?YF4+~o6JEc!zZY|B4`eo1@U)^*YzmY%Dc=eTURKlI{!BO9)-ee2Zm(@z*%F4EM z@1`@Mx`8*%A3sl1SS_PJBc1aT8cUzhE9ffPXLnP2&%?E}rfu_Id2VoJ?K*JP%I)An3 z)7ZyStZzP)p$&np;Bq$VTYdG0X{-b5FAyg^4V9!c%MyiP(3#=xxpIlCLMN+^UkXKd zl|OoV=NekI+xOfM!O8^F;|6D$l&efBqY11|wO+RkgY;u9-n@R{e92Qrw(5*w1a<&k z1P(ys!PPW_H7%4bY0)mpGpT`lXRYqozFB|%1yFf6$Gw;-`n{?^qDzakrS&12eWZbH zi)Col&X8rb6BO>jo!QTNFLYWUFPrm#K9}*n{u76kg7ZbXb6qG}7`Q>#HW0{(L97ct zbkP_rw6W?f+JmONCoAqGSHyA8&?U3ZWeGzlHcUaY6bT&`)NnV`bd7A+v~rSVf9#%Z z(eUt%cO&}4r2koBVv{BDNvRmeUj&$sWAPmTV4ioVIn#e?(~M|FTV6C3i6ipmP}JSl zU3dHpFK9-o;Qg1r6!-7W&k#qzj#sFp?FZnO9vdt(EgtGomVHIrn#J?J z+`ZMx&oG}_L^Coi2kInA&gySfUS;zoNj>)!RepXTOfFFRy0niM z^QUjhX{;~guD6N%xW8-}JwDOYm)r?HB&brgte2qBet32KK@F z!v?D#+%E+N)G{HBdgwrpKwHj~yc6yUA|o$)@K&q_8=p;_dyd-14aID<9JGDBZgJ2y%AuqOp!0|jUxu5ak3>3W3x-sp& z(75tMGDnKl|Hs~YM>Y9%>!K(qq7<=!fS^)UI#Q$vqEr!3lr9A6A%;lrL{Lz=fPjKD zX(EIOB!nK7CWIbHBtYn3fY5vMzW#p5x4(VwIOE*2_Za8w{hdEVWhCoe@0@GRRpv9F z$MFT?oCxbHk&2mMLsy0KEO!#-@=ak7ej&;xhnk|Z-qIi(LAVYwZ?Z> zRQjVCPOoD7?rWTf)6yAs(Mu{yDOpQu>3)()54JlY-MI^sVJ`NG7*6F>QIsdb{&llc zWCSgA@FbnpB~pduOUJPw%^wrKH8OrxUcl7cBVOx`F?AD_>vH!T%EfkLKq?F5ocy0` zWInv{T>{!X!s4a|VZrIcibIomjO`2meX2K7fS(!&S8$@r zU$uD&?Sq#hPZKBZ(chSMQg2BTSS2p*1kS)dd35uN+`#axcM9)1q`qMPdB z!px{F#NE2;^wf2o>!Nkt{7IAQ4P}$m$pB!Sa z?ey-HG};)ux@+D-I?t34>}Ywx!tGmSC~`Ewa;>g4m^}6fY||rmM$lH<}?b+;O%w0rwF#9ORJ5aFIrxUNKw2z8uui%$?fuy5}&CWdB1+gDsfz1ZkUhB zt2{1{@!^#)z5|1n2J8uluIkW|1MHe#pRhHey$Gy-d0hC!^pXr?j?SYzx{hsi245Jw&1ZvUk?e<9bS+!lekKr(40?$|9B$ z)?Zp=cg7`!MAP(~__D2&`%~~nq`-VIrC&#RYc39J!HL~F0#UK7I*$oOimig^O)2c2 zW@~viGQESD1W}o@VIM-d-tmQHCv|8yUyfM5XsH@h0&ZM8KZPI~5t3jq+|I5=VPR63>SK@09mS-2U%@OS z**g?(R36>lK5tfC8NF>c@HwYclRvWDcFa@RfHr<9-m*PeFO|z2<;nI5n&Xoxd_3l= z=3osmngb)NH9jXl4Td;ouW75uCZLyK#zb^#c3M)r(>mO1M^2xjBD_dPdv8M@h5&Ev zWqNqP^0YtRs5k3vh;Ddl>r<~)*LwNOi%=tzFI*=sHY0CUEr3GBC(()9b;&aIWvKkNqHMS_r0C9IdaA!$c;ZcU@vKaNC zg)cCpDVR|6tSddd`XxTEt4?n>-4fje`WRX zWWCFqyDSNThQlsPF?VN&kL6Cp^ymkthZ&M8uuL z@#Hx@lX@zw@YyXY{^za=vd%bX^(spOd9VhKY*I&{B=^pP2A$w1{3U%pYPu&q0C%E7 z=hWjg73tesIZCVMZQn1qGpoCotu6GC8lYgtr{>>+_`(H_f6TDDO#6(6YEDQ_)#S%q zd*Ndk=2(dPuY5__{nL@_4u3pw!FzheT4kaXkNP*bXTfW?aUfu8T-)Z&oVCc+P-e#R zs_;XlSFc^%*0ydB)2An8rI=)`@!LyO`v>QpFS=H$GV$2VMtsOgiluNO+& zFNWrDw+$qt>zwQftt|zRr>`~HhWKzlyk6R1JT(~)ebLQf4t)Pfzxjr7TLCoyP4S)R zE$T>`D%fSQULy8l=SwY(KW?neKUiQ7ZOGorO)7%ukEPdJ?%~$1j(p3RjWXW%Nng)& z+iatXIaOK#k(lCUcTL@2K zeqgU8Gq!hu#eK8pj**K4qEwWem{QN;#V-@LI{!F(+-zb!424UnIplBp5miP^wvC-G06PjfIu~)$hu(ZFd8&%zxrmd` zJ-1+!;3=>e0;!QCH&K+d{dGGZLjnlM;2vEwwSV~-(h6LRu+D%M;=o&}?fEXUDIaHy zw{*a~B*Ex2nA6mR<9W%CQl7joWg(wDWA#|mFaR~VX#v^DqfBLtzjwz#HZ26PGU)Zy z8!G$b!Y6n-85>z`QOLsVon+ccm8L3_Oho70-9vbcebza$DxTeauybKmKNaDe>-vV?2@xUlnqEs zHtO6gt(4V~W_iIF^f}~TK^(b016lvU4ietu{6%AoA^SD$_bj@71SSHVvpGeVEaP#i zvFkIPLxL5Delbn-3JKg7E@hzoL4SWL-~MkpZU0Ac=~$#q`~Af2yp0(2^*=`*+CPH> z6rto&xB(iy(a$2gek;0#a0EXZqRsBbA`!A4RDRSujxQd?ac0;m`M!ViUmnGe6GzwX zLd}NYfJ48p{%u&9(KOcTMP#^8&v4aZPFuoS0>FzeA_6rdgVhHIY`-JemfnUOW$hg1 zadlHm7gcdw!!L#>4QFF@BB-vb#2qZMer-RNk9Gl-A?(Ei)1Rl;Jr|u6>>~+lN4ea% z-z4ET#d+h|)-E5NU~a7tx)^!L`ILdnOzYV49qN_G_rEmP&>9+8?sncO)?;6Gx+zKKuiIrN%vSSs@J9^;G=8M>|-2Bbs+djW&>W1*GEBkwmDI>Wp zY>Y>gvo2S?S^CRa>3o|q3`SR$KheR_z+gG2_3jAVJL4kj`=k7+b&l~)+m~v%tC3rQ zF{?M&_g(LOG!xiK5iBn(GDUjn3L^NEFeJ|m=xIB2PIb5DRaOkxPO>rUDgSP!zM|fl z8+$qdMW7^^!l8I<8b;?~Ckc$&3KVrtO5af?r2){QzxN5qdmGO`!oLwZ-9L`@7NQ!l zephS)n8y(#OZ+eiJ?qOSrE+CuT`Jy&oVh&&)%*aP1FLk*VXe(4!sC~AJa0VM@0)T^ zjm*Dvrx5%V7`!X$;R zi(W}LynMiha}oH4S!7nslDif9@dD;i;a8+eDtuFAL6!9pGf8Mk2; zmO)6|bPUvsyA?08tO@)0=r-L_k;Kx?xMSn61Rpzo>Z6sj-TO~_*k?9GsCrH`vX5b= z*xdTu9f$*zs&|#XKr@%Q#wAKnkEVo<80X73$sq4TOo&C9X`ODQ~N&!xde+(gzLnW^CFT=f^mERR(r?LXmM*y_O zll}JvnAN%VeB~&6X8>mPKVJc08~?hWJoUFGo^Gsu+%KAHo27L9g^Xh!OtN@GOf=U< z^^dVM`ChNH^|9sdN~~RP&bwcqEZjHd{Zi~|{}OYeq>}3JE>{B+7esbhDOT|NMDU!s zm+B;cy0Auz>d+a7i&GQp^8Ne6JF8=BW)C(W@NJh_4;D)1D)0J5Q#$_q-cnSzMYGg2 z5#l0}zs{pwU;8BGsqCEf(cVVcNRK~0!-I1xpK$NA3d4{7Oso|O@ZT$S)a z!-}@@mPupu7puyTHt}(;ZdLm()%N>@+adsSvo>QDy#=oeG&@f&9lk*iB3!uNGg9L- z5n}a@x2NcF=%|3mEuG_9do{dEK)dAI_8JHNOP$P(`Qoj$i$hIu`=vM;+ zlXn(U4D^h^pNoXw>=}Q>3}MLA+C(X7l@nk~ZXeK{V7o*|g1lYYwCVV3;i{+(K1rKO zV|gJVFQK5QfP5iVRrMWQ+1On9h0Tf>9Vd;?M=@c zy&J&${WG9WKzz(0zV5T!=5tDnH1w)>_x+L~d*R@p^mtjhofUxL{xZNEe(*Q|{j@*% z0eIA(Z~be1lx1rbI1>J%xdVPMB|gtJm#z64+i+mY9w)dmz+&p|n*LdvX8I{lO9UIy<#K5L=z1^LC5gA%G3|8AL)^d!I zE6t5kZt(rF6xY2rgT+~u;mXLM-e@WF(RBH{K7D$^54W^hw8MS}qf&uG z!;BiYXy^YO|NmbWI1E}n1+N5`Tw#?LYno6x?;CKLRw|svA2b6{0ej!yr};XR{!g4< z8nM4GwT9#KFrQ7kLn*J9JKmOY&UNW%KKn&8 zp6m_U`znjwx&pc44B?JW2dLCv1HepV7$D8+)|CnWei${)?{?nX9JTR#VtB$t9)a zWC!P?@3sl|*B0bh8&yKw-rv{PcW6UYz@{)V+X&Khe{Y{@g=vef2X?S~FkQ2oRB!_% zX#k0i3-+E1U1bSkA!ETGPil3MSh9} z0Ve$u$zS_ir`(b5WP7)CO5^v0AxQDnqS=h$;RJ(YeV2!vEsTveec}D2In?%xt#!)8 z%+}BOiOMPWp|czK2k26O&~ssfFgMX-Yo3S~JSid@FT$mSMa_xLP4{C)G&H(>6i@C* zL=S04lUUAd1c~z|Pin0SY+p<@7{TbW@A%FBXs6w6`w|pNb4YvHl|Q|vC1LA|2Ta#_ zt*g(S>J@X1+KOG^c3-VY*Hu`#GOco&TI7Ezvo_?DV_B^bA?}+NYNnZP{*2ctjhxo2 zi&dXqDowbBPowpZnNIVtpgKjxoLBlGe9ln&(#y6lzO;0WwHiMNj#z&)S>()&?p}9Z zSt`Yh!8UHVMeU|oK#3r{p9f|T&)d|fpK0l|c7at!m$_@@=Wsda2g%a1#4E|_cMFRE zIoU8GSHH>?ItRzWPJcO`&~@WeL*!}SgvlY46Z>qa>EUtSQ5iMEdwPejM#kxx#2NRM zlIQ12N+^i=rRgm>2xV7g1GZrY!HN`bG(Q!CiSzd=sUS>M0dPoa&d&ubY4$N@`L5fY zQSc$-r7oW+DSHEkMwSB84F`Sn!UQ>rSB8-8z0RcMbq+e}<&h?l<^aar#~-vC-0jq@?PSfukc#5Zc>Gj%j4e#@%FEv3=Cwd>jj(NmDJ!elHf%k08^Wi}>GPo4>ZsL;r_bMu z`3}3E7!f~_&Omu!%4B2E%a=H+^K2{l3kRo$*s#xi4GGh?OU&0Aj~?N4ZK_GwH86(D zx$Nfk=Vf+wX+2h_`H$qH|N8Dfa|2HL2Oy?N^e@cj>pqioKWTfwV02#Ljj~dAV~0oH z{ARvh2=Fy(EY9kmNqpKrSpD(!psIT=?;+7M5xmb|d$&Yx`x;=d-0lEbzP9Ji6UA+0 zO^iVGM$IRuE%f_9mKc3q*|l>v;Y(X&?eGC~8_G3bJywd3olEPxVsEHMH;cz8%S&I& z3W4gxb#^l~LVq%cbVG=&;v>zcwxq?9L@70f@A3nEbnkmL28eOgO?~z8ln4TKrn~uy zs3<#`xCxu8Z59{EZ+9XKFNP*MONWV}Sf~Y%DwdV5yt|$HP>*Z3@|u_HG`}1D@v-*#S=V-o1@8jdzl9&W|oag5z zx|G)vtDrgLFMI5`8Z6feHFtMg*aBa&m|H~VLzUMCNGi$0^U2`*8kgM5gLPcQ?0oKq zaG3PtmS!z7lP0grlS&svQ`5uQ4J~fpk2{u^JUw*RGh((=|1z(s@v-xz&aX$_f0UA> zaS02JC1Un;J&-xb+>{)LN+AbKLUlsT%z9M~W>AsRVg>*9xNsw{KKTutSq6K22<+?e z=5+Aljn2wg(!H**(YGS->1XXte4bBT!pQ_B*4=_p;Z(f~Cue*etIMJZbA+!M57VT@ zZi;kCzk+*@xjVm1J9d#XMOh;&8=2*2)-t#?l($2l)4Mh^w6fFn1$=>hUIxpmy2gE5 z)!P{+%KNe|m|h{}tCGZb{QT*YY$`Hu(}kRWyc)O`JDtoDI;$j`R7|ZPHy$V3 zPsGpA}rHxQ4Zql&sJ zb!52(yGUO0L{X6p8~aUNE)6yszVaAI>a5GM9PSHJJ4q9hR9{w!Q^Goxp%Z&gvVJa% z;*#X!Xt#OfHn7K`uHrjyA-XZ7TLpu+uaLS20l3jj=g3O>Y45s52I)#h1*1?A>kwze zs-Jujzh6?2pku9ZM9VRL!-3mz+MCACTy75+6vz;-9d(7FN;-zub zMA9+x{hQmb$L1n!gs!oar6<%HV~6s_It2nv`UA1V)%8??GmQU{@~i#t{(Gk6DIWff zShUL@{rNQQ@b7SpKZ@=PrXvICDp*JjC0%xM&A(-UUo?DaV zAE{j*QVqu*&{j209~*ftFW+(GVWjmNqbRwmO;QVCxn{kRKvlfdj1cV#l$)7wCIqBW zHj$y#j~8hh^t}@iBL#{zvP1rBZhd;AKFWAE_C&$cEF#u4a!&$H-rGzRMFq0=_fNCC zQEK^#v%IxNIyi_i=7a*OyG3J}Ayz)^CZluVQ3=;;x2y6TDWW%&&u#7Ih$Rn5PZCXL zfX!}RvP9CTScSXu>IpWyO39o%RSK%W@ML`1CUFaNg|UR;^Uuf=CqL!{ec|J{!Jp3L zzA27oIQ_6^6jfDHI1kts{UTMixrZc?}#a{8Rg$npef#T)v1Jxt*P>};?>Dt*Q!JM%+8ZkHlx_cQ8eM_OQ z_He$iC9iy_L9>y2OJ7+t=$ z9~Dr{2L*_33~tKhY*|>C`h9}hT>!Yes(~N`om&lrU1-RwUPQEV0@w@j{2zijM+!OB zBa-yF6v5Eo6#tJLi)qX?T6oP9Wz?$RuZGX zt5E|0e-mFD4Uu;SYpFbmq``TE-u~S51$Z7@@1@L$g?>ZerI)(I+!XcaH+vp*#OSfb z?dD!L)sBjs)Xj-$xwCnbsoq)9mEf*Vi+ni`q-RU3RS`uoPIH7UJ|#ht=$D<$YNT|= zz@5z3ABPWx&=^;(xv%yDGkb?P)PjFVGvhYljeVPgFp-Hz<%@3g~5BY_b3^RpDrI-gd<~i zN7Vj4Vca_!_)mukPR*TXC}6|C9`lPv^^AnF)o!-Rcn)P~jRE+D22S(eDe#ce8fD~^ z!~dPg4i7DmQv{E|x9Nb4>Cc?PoQgtE1q&9hwfm%-7aY?+cI=eFeLX{fLkv(R209IV zW-7bU(OQ3Ad>2R>5|LLcH`>mozf@B7QI3S8P`JK}WuMIpQ_2&@LDywF5?tuUBhUNT z+IC&=OB`|{Y?8>y(yKr5Tt-mkm!C!tT2U_E2r9hO1#;ryDScjtpEdv&lfQoAu-B%e z(m_Q;j~~%^eQ2pFw#J)}|Ae{ur^;m`>;wYC4i}%KJ;V{q5FZE3wuheXTX^ekeipOtjs$tk*k^Te+<#T}@mMJL7)Kh5N~ocExLJ-fmiu zW~s~64W9Tgm1^vI2T&bbp{vvQB%NiYtv*CSoycQ-DJ%{)nf2*p&^D0hMOr#4U+J*=Me}5lE#AQ{1LqO| zgL%O6Ir0RFZ6e*bx-J?D)4ngLWw_@%E>P%`1ldU~q+$)%V-l8KS8Hk=at^Fpbf@Xj zVn|!zI=k}e;vjxBxNwxSouac?a-}JbO-gk<>&_tq`Qg|C*e=|{&qF|Z4Zwq>ZgD#w zyvCOWfRwwitN>aF?lhU^wCKdVgNn7airfWXymCpadGzM7%Mt+^Op1P=EG|$owtfs9 zyn}u=t)$R;(jLHLGXtO`-o|eOR~Ue3&njhwrd4})0s#8Jw^p`j><^v=ATLhAecjJ`r;prW*j{je*gyKU*rMdH}`ZVlDPDN1Jx=8fUJLv-^JfNdSJJy9q6b| z48w+zt{zTTA@zIOIlfZU>MTBO-i$+K7!|p@Zun?aigxzaUKnOWurVH7+oXD6-Ri1` z8(*HA1~=7lK2rEJ&~M(%)I-cYmaLr!S&RPTxs?JrAugxXT2I)L{@mHw zqK^9qKC$%p=zo*AGUJ1ASRkZT?$!)uOOeVx4>>p%*-AD@yB#|rK|Y?~*cpY0jH-H7 zWFI$8+RX8y|SX9hxyfGsC!_N=P~ zCC)O0S`~7Kk)*P`jtjp7=>A*Qu(^QB@$9K}ucaNs-fjP#s??$byNr1N8YRI)4RTu! zFRK+DKB?!K)_Fbco(?5DoRWTSt36&)YR$KveN&s34G{JcQ?y&h5c=`042@HU&BGb9JfuM(QYtwQxSmTef$vi9Xc}>QZ>F=+N?11TM-y zIPw=wxzMCLht;*1F16a^9$6UW0xv{^W`7Jyhlt^^-Qb;5w9M^8&EbX=G&aUB%56H$z z)f*<#GIwX@-h=zSrj=!uco;CAJOlr>zFoLCf*Y*aGTogDIPg+AmA=7j{gpB<-*m&X z$J=SulvqDi6cl+!i#hw5E6s{=U@hDeKs44-T{ruuc40qe{}DJP zN3g8ZTcH&J*&7iWC_EAY&8)m&-NQ6s$M0~ju<>$Bxg_Qs-?>XM*FC#x+rI`>x2OMc zG9Vam@LB-A@n3Lx{YQZPpW1;O%VwESo-~k6i-;aF`vagnYIufb150e$TlgTpx(MW$ zFVm`M0oU|wfMTU3@c*B@QG9zh&EUI!O}}U|!p~ih_-A>KthLv`W;`hm{zFh@mrE3? zZ^N0AuI|mUr=16Ez-LbbBn=-DV-EdW@ehK*06~#k`JeXZxj*f&CDEP7w$*m^0DSef zfsMRQOh~c?AtZnf!O=T~!Ir&zAd%YH;C1Z|uGEu@E{Ldf-p1uDc~XB4AZ7kVL&)?i z!{~u_l15fBZvmR{Ww>l1P`>mGze8J~##U!QoSlY$!z^sbJ# zg8uj`ZS`@+=R^N!2@G*Jvb;msL9xTHwH5C1Y=qb8W8#SQBx{H#-g46`{YSUYEv|gJ zl1mX(c{0D@)$IkEuMe7)V3bxIX1IN&tGUsdaA13!VQ2oEZ1}<`Hq<;xNs1RbCJ;T(s*c{b1uIxm=^iKV$F7M8aN$*cAfGBr#gr` zy;xoYl#g$~FPij8SJ~Pl7%XQbS%DMws%Z6Wn2@&ngt=ifZ=-<1?MsuH=Acl#9eZRMw(Ob$rMi+4f88$hHv1 zGj2N}+h9-|JcgC);n@8^Nt5bd%oEE|Lyf^+R4jvuAFQHa?hyjp$N_or-N zH%ZfTG~R|$+WceZXiE+ru2wVQ@OzWKdM02H5CvcO=~m0wDRY78XJ{S3Y3uy0!g0K~ zIB}p@sY=T>%_z1n%z8XnTfTX+QlxnoI1$%kw|WLr28;+}ly~vl1;5#iSMwPIu1Uc? z;Pc2mG=L5{usV?WK6osEDzX1FGyt}bYeMVBzxl0a0LH+Bb^zw&)`N!th?9et29oLj z?c1mO8$pe?6(6rPbOFxf?7+BvcFq6xhhH=>@EU;(j~yrXTg>%UDL=#s4%mA1N3ON| zAnqO*Oq4$xV+<72##;e}X-ZQj8xNcszi-?bC8}+oiBWR7k@ZN!-ml#G-8=vK>!J)? zx0$&jj~uSy`eRtubttZTC>R`g3hv!MSp)dy3y?wdnamkx@-o200lejuUo`#e>_%~I z?j)TQk8sj${`;E8-b+P|m$Jn+5B&H-V((o3MZ>E7d(c-5v!*DG8yNx!eLUqsJC};(lJ2& z)!2NDNaS#Q`I6$g{GS=}$!5-90lHyH2I@_XZYR}LG?6!qEigp1@I1ptFj4oV(dBi| z^-6HniK`hgtuMlCel(m_W#o2!HtgSD#dzRiaW5<1`JXPIH;n69chplXQ!Mdfg(ZygC$t44umD-86M@M~1 zPj8MGJ}bY-rpa+ni%-}x=D^TD^jYkmaw#;#Hc5PloLD2n>Xgk>x3yT zhlRCoQ+m|^f~18>7}PT_ZnmWphU#Ti7f&qC43`5RhiY{?_{h^uy=TV#2`+cz-uPIO zkXYmO&w7BkCLx_THJAnh@QN729wk0VrgubrVv=knG{Ou#WZj)SWFyT)pCU%dmXgr0 zI{fCsHQNhGu#X4pN5NElx{Ag8Py9|d{GypK-|O-XzdVbL(J`~Cr6LieG(}`yx*)cIh4XoHiv_Vma}92iVID3Jm-mMZUdZJ zSNGg#z*=`*Zo_Gk`gpdbfdt2irQ$K#DL$T>#DjRE+##e3XMgHj_1^yZ2#D1?Kor%l ze~P3%G9zG%#-!+oy62-_jrr_Q3qRgji86UXQ|7AgaNwes^MdIh?EKJFc|Z~D-FNQ` zb(~Y7aa0c~M7MXm5+)1zD2*vAPjf!xW0Ch-j^?tV;c=Sdho8}d4q8YZM0D~L&2Q~t z|Lwy0>|bE9{Lk7<{DE`6#=hB3xJmMr_4_{-kMsV`5ZlTLI1{9@dclc-C(3utp#L1c z{atVPTqNx41N3+PXx5UWOtzN(ygGxY?5IgcMpcj_gg;(< zD)8DZ8DQ4K)xze6rkw32pw8Q-0)F3JG17=BSl8wd#NBrg!L}PyAK_Q^vl~iljso;h z;~JTaJc1At@Aw_pcH&BNrwl$>oH-rz+JrVfZ$q}b(e5{Wu*m+14Q zN=~xTM&d)$@{@u7p^%F#DOWWJQEL;#N`DM~kBoQ7BMSxittsfq6h>}gY$Uer|L~0orJ~n3G;Cgy~jz97W9cL5X|H_!I6rtl@Furce9F=rG z3YzlZ?U&BM*3$W9<+gGKg{#!QP!7eQVWGC~$(HL^J%3L0-f%DNH}oLZkd!(wQo!EE zgGgAjaHsT8(faItlsy&{kt$lWDh$Cpi#{$r#{agxrFg8>_I}*V`djM?3(b+jGV;mJ z;ZBFRDU&XPue{Ooh8397chK>uXlsMTf|D}1BwML#hP~fza>jF@z zA}T3c^Ug`zTdQQAMQPt0+&sn;U=T1d4I{%#haox^Z>e%&*K~dll zt~Tps!=7r(Z{5rH!%w(CGpD^+kMV|N+g)(fzp5#al>VbXNq65l`ZC1isVub8l_(_Nao zDX#$kN)_>TFf8e{oP^BGV>Hh%IkB^AKS^Q{=(14R;_*HGa8a&Y9Gq7@ToM9MWzU z&eLuLZmX8{w5^t<=4tx4P1a>o+@uo;Hdc(R@AxKuTq|SMFj>$uNq;O?3*_PZZRHlh zm>DF+d3(OgqsM^eKPKn?S2^`RYr0!+R5h^GGB5Oy8Z)6@Zgd8k9N}$e$F1j1T3w^@ zc|1f(d*hv_nf|C70Yz8}czc}C$(4#bq?M6`h{8x>c&uBfH-Avwi2SkZA$jebkD)Bo(VRcL}Pjet+%C@>lqRS>XI0%Y&mR? z-+gjO$$<^`)%TlsboYrYE2SHc^T|%12h=@;NI8kaI&WL(?gi=Am%Cizzq*qVr&eb& z1Hd5!EAib#qD6dVUwlb_3)zXhx@}7Cf0BTnlv%}c!)<1WX70-8i8A`d=9(T}E_wXS zuQevVC~_LccFg^tMx9&y!arJUvylF(T5dEz14iFu=l1wx-&bd6k2a^dQ9lQbH%TPQ zr3AR|vD;Szx}_@G^s1wpOhIaE=%hSzAjSo+RMrlHK*S}xjX*)lI%j4ylkmfME%tk6 z+%8JbA(MAwQMV6+zDxf5H+LD`l7Y% z7nW9zeb1r%{@Le)q7Zc31vmoH=|-jLDjvP^4)m}}oHD=ekL;l+sgF)}dO&U{5O4OP zQ*Z@7&T76c7@kKiZy3$n6P1_54v!OL_=sH#&s^Pme9KjU~|-+qX8@Sr8FKMYDgrhw}%zn zJ~A*#8hRM}m~9C+AzfwY-yt_w;5I>RNpoqlw{YZ~%UPt??l(b0h_SQ{In%U_cR z`e$J)4ly{IOP-8y-?7WgollLx(}QcoW&BPhdA-wh!+&L0e5eDBAUX{GFLP!66UA2D z-#7Bl_b=w#AE)YQSFt* z8@q(ErrA?Du`kS93~nwcP4t#GHfe`T>3HtJnXiy0B; z@OCikwd=}U*jbnk#{rZ*lvspzWkrIC+UHm?wvj-Pq}0QxFWfzf+lmc-BuAjUkZl!D zbrYg|HYb<%TNoodmf+WX^~22ky+|*>In%BrGt>UTh5*)}57q2UWpuB6s&G|y8WZ

J2_W+^qw4elMYRZzvdFZI&Qo0a+mij&$@MXb;BDxS(ND846ksQn1~MAZ#> zL|}E95j=p<4{@HsWNp^?JRs^&0^H|&R+#APV6bW z^LB!rmEo&8X1CY!yDDGhqZ-JNwq z+gfu!m)O*L67&KU3^Se&bS9@NQYKgOVRk^ao_>!@-!iu> zX)LG^q`7v1WhN^7Zu{pM!OJ1lRjTp~lRo|02DInCVdzeAXlIT@i8m^9;|rCPFLerZ zt^Clfsm)n?r?#Z_QSB0}Jva!=8$7)tknW^Gxp@bjZt<80p9VrO3_h&*%SVw5x*%W>Gyyh#x8zx`>N z)Q}jPy<01N%EWP9T@ z5=deDY4Y)3u|N+%{2Hn=15%H?EsO>~5{ikr->W!jAHiF~=K@zRJesA2ySu zJv55`bk@#MS+ILY7v>@sFI`CJ_Ax&B$h;XQE&lALcaEVu|4EI9wkI`IKad`YBcd#* z0GoCH$}bwu$tQsqH@xomjsxWd716dnS*Hd~9+`jTtJjLPNmer%7ekyp7MsEn$$69J`@r9%h&M z9c?T6*i9ZiMiNMP+d8bHnb%YT$rtEm}2_<2)5Zv&t6 zH^A;0(}Atp7Fk}QI*$KzovvJMF8dr3YkB{4b8zcf?|b?NiY`Op0A0t+cR4lKsg%I< zu}1{VB5hsTg&yUGd=R!@xjl*Z1jMw+BFo2!|7tPcDV>sM^g{BD@>vLM5po6Y#+;<^ zk6|@#yYX)1?TTj)=h(faII2i?h+^6~YtmS9TkQ_1zQ;lf2JW`8+PXA(Z*%*Do~_9=i}&hyFcZ zvt9TIkRjF`Jb1}TkB$o)@Vex}L&5S{X;+y1I!qI`Aio&-`R783E6Y%*4i7lUzGpJi^n6t(uu!sq(T zon3l+*!~0{ihuN1TOg#0I1=#|Nf`4u5;StX;Eae=oK|PntFCAK*Ipl^i+uL}S10Uugy7dQlj&otFXP zo%nzG3Gx3UB(Sn6yY5kIDJyI12ZG^$!WC$TpQN>Dv*Cd}Jj389&QzuG#YZuGjwLGZ zwRgMU*cs;(D)u!LcJ0Bwm&!dhYKEsm>|friPVQ-#y3wOxIPkiTXI*zmtN2Wmm&Q&7 z?QwlQ$GzHZnf1YdpDM`mx&7bRBg|8GjCtAq%I?r9$RvvDczz$rws2j(o zbT#XmBpr>`MQ-saSUL=Jkvi#~vOj=RK5Rtj5m)lXSDNi4)TrkRZdAY4IgKP6hpQXk z?i_h@{-iIfT1~HyW02D<1^_qz6-^<1$3lEJewm!Q_L zuTyF7IX#_bFf*9(2KU}J(SOX(p{8WIK*4zRxKXM&U%9zMENVOGNvTw*Nn2CW#L-Jh zw1L`I^!&%~ua^<`j*bP+O=dYu_|7STHx*f!8hKtcI z!0HXfbbP+SeGvQrSjfKX0U+nTc>%^O`#*~w!?fWy2m(uiZD5EI< z+o9S4|At&%w{t-3jVk?~ve3_L;Eos&{qT{^Tu9s7t|QeDC`MZ*=#!ONwo7yNK2x%I z_Q7Yk^X(Gw+KR8Lmc)Jecfa>#+e+9?QN((mU~dtsPgr)YKL7@($QtX^R;As~qbT!M zc8x9!HoX)V$$V}RprLEzmtu3G9@99Xb|(%M^5e)Og$$Zvp=VsZI}Iza?cvUpM>V5` zwR52FMuT1hi-Wv%^(0#(&N^=ugSg3VU9&+{ork@EU1hoUSdv%z#4OigiNPwNkc+n4 z>~CwM0IV>lt`M`{`%mI+qU>$LROl+jX|lI=K4t3DuD)=OKRc3=c6ebx){B&zFB@Lz zg!^EI{?H&9Y?7>LoWQ#Nn1Lff^~-3@gI16R0DoY5lsjQeTK%niy<{seS6&0#^QujA zIAQZ)#%vB*IAhF`?`@#7?FTX84Wrsus)yuQ&nG0GG-=T|1W!=?&L1@B6Y+Cs{cHZV zQmxl!pLp{njGqsWCU_xt?-$KiQfe-y$SKBq$w}iIX(Z#MS@paW0Gp|ZG7XD1&~muw z6ZI_b+-iqp0N37zbikV=wWL8vpmsl0_KJ4?a?v^nj2KdAduUP z7KZd|-W&edf0R?hj?YU*zqMZe_A8(jW4$G}yYO2R=I>VmL}m6}20%Xc z4Gthm{);vBr^s82QA}dU{TB^G1~a^oq_#zV4go`*G3R;;ClY0^9tsoV^I_fLkP3aJ@?L>bHC@A=gv3t%-nB2|AMeLD|@fC_Pf@8-(PX^+@T14f}@R1tz74| zJngq$hYe25!mR|Jo)xJrC}^EKqS>qg0slT`_aMC59{NN0-mOO@Zj`` zF;{=hy!kSFG~3`MrwT+N!tu?=o9*bMZqb=ewnT;=xp!jAZ)m2E%~OBBEp=6AQApfi z`b%Td+^6Z$iU1fwjxS-le&tbTX6c$z5XG{vR@SS0vZ)`nZ}+sn#OCu0=6i5*`Ehcn z%BPtso% zz`&;na!qT9Q2kaDbG7Z8#V>2Y)31x@sZpufLY%|GQc)@18&Q9mu97MGn#FyUdrJsx zAeyqGO(dEEo>BGc$@4W{g{#|-28t+36W}^a^*XXuDO9f2fB<(D7iHMFw^)b>EYbxl2?b&c_c!GU4|n`NAse;No0kq%ym=~HXig-wZQbR# zwguNSeEg07TKtLgu3y~L&U7jW{&o1T0>vkVql3xje# zQTXLC|1n&M!H9&_Pj#Mi8Kt%y=mU!#r&}ykFUJu%Pwk_zVOyR zBK?E^NGsQi-&-qBF__<1jEAnkuuTzCIbHKR2yFmCOyu;NK(g#4Oaw<{v`rM&iB75X zab8>zU3!B_{^!JP^3r#5MG1`i7$Bl~~1munreuQLTr-VCVV0bY#VM2Hm` z{;)8ZSv~b*oco3L=%K%^IK9s9u|sQ4)Z~gB)TX5`W-pLCaju>vs!`TEL;}c6LUs@j zE3~vMt*AT|wP^CG>#Ukt$2;pSpXv-o9eFeToZk0uI|{ztzPUjF#IIbJ(}@CpQ8)zM z>hWhC2LsW5hhUhv8KDDoU4Sf}I7$@BT=s+~mR)|sXzU`R@E}~%GW=iLanM$6!C=P| zrm@AsN!ob?%JSb|0t+uMU= zIN|`AcM#le6udCEq&f5TN{YCg?Wr&CPRNH3g)AT#Hw%#`cEWs&RQpP>s1hfM^vjg} zWK>o9Pu$g(>v{vB%g=UE4 zQekF)tAVxX%I-9r4Str_`StswQZ~-gxnqq?18OTiWA$&y#Gbj_dD8N^#hE^A-h9@2 z8O9`xj(4Em8gXlPccP#+)^%vhg>1jE?^(X*) z4!Je#sSVNozR@Ph0DXw+`+21$(GxD)bjfPm`onW^4ekg)yD}noP)tHZ+PK_1pyzq^Zm64Hzzy*Hq{IR(|03mz?L%o%fM(S}G;k%MK*@Q<0)};JJ*x1+WqX~V6>zWnLf-qv&2*l_kx^=n^!493n6N){Cx7|OP zL}+`gdxEfb;opWjxt@k|oF@!9XE|saZ}zUB4f7phlle-{9%T7$qz& zBd$^=^{#v21PFFS86OeU#%HTb3{OEh;C)GJeSJO8@|G)Lp3psNy~bwP)&F{wg>k>9 z90OMqQW8pl3f;3dN?WjgbL834mz~OOd`A|v-4RTv*y0@>dRmlUl}-Q8*Q=Rqoe=vd zIFA>7jPBD|0AtbQiJf2rv|zxq3NqjTrt(6c`3BsJ9FJ+2p!TS&~1vA;5OJq*1?#k`2EAa%U@s_4MeBvtVs^=Sdy^p!k^0^m~1ierd zzE?7;v0k`Qt|L9PwSADPTM!4u%cZ@ZRj9%Pbq&HLJG5dz<2$qSX%iWbI}2$1&bb%F z&Va?wBaiIFYuJ2V6Ubtb^-RmMbeDiUwRH8AXB%vkHIqp8$BN5ysA=LGTzc5u_%?kl zO!uS`{D>Wu+k^Pd)ROou$Y3RUZYJQ2*+50=EtNhi?2sh8f^4(+u~B08=jQAbkV)t< zz87Y+XvT`HovC|6l!tGM?Y1Bek(aaVaHvW#9u0MS!je)l zuC|;=V;pbcn9qzn|Jf-TMfgym^IR`ewASPOVt9OTHyHNa&2 zmnMQ`Hz#ZFKHfo0(nq~Ud(}LM-`X;DTew5Ihr#hzd0Vu4t>FdD6RAaw z9kZcrc#d3mw7l(wE_iyFJa^GzI@6}m(y8%zwBE>wGMcPLu%LqmRYzPnQ_mVb)H^7@ zs(qEHxi{i9qTpZQo4r+$>?>me#;vSWrUmK@t>mOzi#491`|1sYNxzjiu`JpxG8u6H zY@h#(q8>(M{hEc`OW81T)XA@OL89_1*$%`DgHDdlOQv{SyT~Q@WR(isFEnxM!gtmf zMJsEw+k8_=><1)yPhb0?$ITW2URHDuc(` zuZ{8QGOw*mJXtbU79I=#%~fCiflR zQP+HEVq>4X3|I4C=*kN;kqnI2l-pc!js+xBSV@$nT*5LE8NG0JOvRO6i)Kxe`4+G2 zZ65KMqLZ9oX}Iq&z`b95?6=x+ag@Kt{6o|JlZ8{oK&^uN*&Fg?c_@qHci8Sl7v(3i zmb|Q~MibiF2ob86HZrb-(`Ir{&L5MSn?8j-=`gt6H*azE`^x3MsdcC6%Km53u)g%9 zJ4IfRX9SOhtrg!NTx=xK%PT$2`XSryfaiK6Y>XSTKZpPP$f}p!N<0&lGjp?&cNAMg z6HT5oxii2iu~B0@Ulc=0-JU1tsT+FdB|sKuoaIK80;3+5Cq3p3Tc(Sd7O8era@N(sEV*}=zc)j+B4l*l< zlE+-kFHi&41(ODZ1d_%SBj>g8dRQ=(el=hyu-IY0%eEdaE}iekSSH+wN5z?5hePXI318-ce;togM*XHM4{ww z--s9aPOY=Df8Y@mdC}IQVqu;Sz zQn%&oC)TpxwQwYUmsGZYyeG5p`F2elcqQS$5|2c@&-+2;>f6Ab1qSh;I z2QmFc^hEjM-k*T0kZvr&S5vYUTh5pe! zp)Uxsw!GLO=t(lutRVL%RYjbog#7Stw7Km8 zpt>>J@*6j@J|D0Pky2U#h?2hHn!KO;B9u8YX| zH#>=6)BL~V;SSSe%5*8oUXnkyr1QIVE2zChu&JJRkRnv1>c{wDFE_{)^s2q`5Cmo& zoE`QJ7~(%ye_|?y4z&CXcvI)z|5jEjc2MG>C9ozKBWY{{k2zD#HOK!DQIlhg)yc~T zCH!{~)7edJ@{Y$Pe|1UFy3%v=8@|1P)`;gN%d4-f&))U0)~|9Qr9vhd0I1gqRD{>$ zEOp|+d6oL_xc1&pM>!myz&g@08o$t1^&3hJ@VA%e&h(wQ7+JU43h|TAv8&D-oN;q}|E`o8g;HH94AU8^bhC=$UBn z1QA|>kQ%wE)k@V+1ObEix-7SkO9<$`)%@0TvMQsOA6FzQFY6>?TNS_NWHQav8M&5> zC}(+Ms4=VK-dfTfgEQ*^2NsYD*?MQpi(I{=ipLkbAk?$wqFo+^AIAM)S5&J}FRwLd z2zZ`!=7})z&#Ev!{)+hsUm7l|yaNZ+2bCVK1IkRqys*bR(vK^uYis*Z2lRIaA0(_t z*nAVp7Zo#|>LO3393+YJsztN&r+;_^^5h!2Qx;wE{ zj@gh260MJ$u9A9hM9xP1?8%iUrHP`V$DWjHT{S1m@NoXrvK5pOsF8&c=Qjm};s<{` z^$~fp+7dMM0PrfZiCma9jQ&`i7^W%Lib)-Emm0jt7n?%%9b7tJqq(6O(Eb$$Ue-Fm zSkHR{R(_8VYm%&&V-7)1BfjQ`pm7!wMO#&w`Pb)v>i#$r;MSF8eRPG7=@7&P3?WN9 zXtp-M+ImX&L}eIY%n2=o3jm2b>XLxE|JjgPd>+@%yt#;wP#*pe6b9YwE9b-meD-JS zUoRowNJ16vHs5+oYQG$eTNuTgwVi&a>JAf?Lfz)4KVX*X->rmu80lkV-a36~2i zt?X|UKi-1~0fkRwQaPYJY_779w30Wo3)W5S);%q>#!PB7it=gWN|4L~x1+(*<&CX| zQY#)fMuzrNl`A9GHn<>lL%g1l1SkxY~h|`659g9zIuD?bKT7Lxn&U5_|V}} zS9};gzZQi_Z(LPz!#^i~4B`(u|FeUvVd=@&5m8oYuz|EKX2E-JQk)Uy#BIvi-0G6F zo;{2BdCPWxaLz)S$QozPG74qk9Ke~{H_*WUH&nO7ClI|GDY2-2vi zUmu%_Bx7M{KQLJ+abv!KitSu47W^tJ*$$M1=#O5W^b36!jBj4p*GV%D=6k`KdN-e( z4Zjy@!l?5|*el#u1RU#h;EYJ$ES1va?-c?lw$qUT6Tngv6bqfakb@ap%x&1{EQf0e2=^`MeWbbWlY zh`eN1acd)_Ui{`!-k74*n#k8#*9a*?nK(_pA+=@7)**<04y(3Ia3X@?T&feupnA@7 zzgCKNF2O;M9&zQ{M3JpuvhzlAqBmdejo$i^tlj7rquF!MbxZnuTN3()?!{1;ci$ER z(knV=zWE-nPXLsa-OYkedKQjd>TX}A;=Wm@nY_E5Sle?A%q+FXUUVpSjxnMHrwh4(iF1*o6p21yOO|I(JYV*?PZBOM)VKL2<8#^t zWOQ*V<7#x^>MjvX>p4nG379-nYS?bp=N*o~R!dy{y&i>+6D)<`z7Xq(;$j7ZyT4P3$$y90V z>~>v^W6{it^UMzHfHz_l87wc8bvJjxH!UfFODsZ~2-V8#?CZL9jhS0A)=#igS>J`_ zD(E=K%g}f!FGB$gnA9I2OgVtZ|08;JlN73@6(B4dpY1fUZdsE$@Zjd<)3|F&aCQ*$ z(ecxabSnC&un<*0e*)r@g4N8x|LlTqsWqw1d@}9YW`wMa<+G9~kLURuXVrWpj+Fm# zTM`1KrFC8a8me7Ds^AzeKmh=aQpd_RFhKe18g?hC0ayd_lmW%2*#w}J6b;n4Ku(B1 zEZa{3=+&bP#CLZs;2&BKLCw#lmC%lLqQHbZheUCGHjP{6~i`+Zk zY3KeBPY1av{IYZhbP`y~=_rcbG50?PSLhikbLuhbt0V}OR-Gzwr25zW{)fgFrdVy$ zTlT^`=ENZ=3YY_7P5F2U zB(gpLZXb@QKg)&{=l`^PwDX6c&)P_8m}xsWsl_rZy(Nia#12*; z(C1&{HQ{`65Kj0&oAHc*?pjwGh)5)_r@2!Mf50Y|Zf>mE431QuPj?!bmEK#C>mEy) zJ9s)4nOYioJ&$iT#V=64*#BTrsl}x-Mz@6YVm2wH(Oiu>qy{d&JxG*-J z$~(sM{JNJnM2teKWsWS=wJs05o0gvg#P1|DqW%yRxJcKKCNNlgcdCwUf!wShr;hD) z5-pmDJjjI`bkMdWDTx?z2zi{|8EsIk6MZ`#K-YjzC!mr|rm7yNouG8ItV8Q@&^9#%5;UPexsfpCimgmZD z30PX+7Le@u+;T^SEe5l4o~*qtmSi93cf~T(c%6cx=qjM9*37rVJ;5{s^0tz35kIBg z!k==5f4;tZwp`++0dssuxl~g#Ba0VO2j`*1$#^lVFDuS}+k_vU7h@a!Qut|N>f3V_ zELLf*v26lLW#&ZeTd)1NAmli9JSFcH%rkzCJ5&ipF)m#2+Oyssxl&pEvWuzzD@*c+ zrlV5hR!-rxH@}uN_i0y@R@Eg9io`&)=SDdjR|3Kkr`O1t;inm|>U`HKLH{PI{cfhH zq_U6Pzuro*pM)Zq7kv?1hCyqwrfiq=D>I(bzqLxN#qr1)@Yu8x3CT`3q>Xhy?a(*u zFz4ktEXULOwT#nNkB>{;qANnK?vN2&|O{PI#Z)CKIfi$ZKmi@QSnJ;S*bkgLaTk<*De3&d*jgQ?jLknDiai-F3 z?xp~tPu_Y`#{c4E1h@fj9WKRo)~q;ZscHWt{;{T-CEdGr7V&!V>C`M9+sH%;!$(ce z{PwMFRmpqNqD$I{Vq?ura;j1!yb9_m09$5i>x`W*-(}T&1-TO7#?oc%4 z%=*TzP>7oaVX138h_}q3)(LTiWLKOGH*S2}E=ERr`4Ap8X zGi!eHt!Z6Te_2gT`0E5O;W_B%-8YLrujYFPT6B{paU>A{B#-LDUDNVIV)9#n%Bgj8 zd6B)5vG0X)*@6a14E@*3XSHZ>S+|F8?7n#aiSP8w3me5FRBj))Ng|QgT0#wf;ps~- zbYvo)FUZ{T!ndMUg68IFK)-Hd89gD9&wyb{Xu2z&XP+9iYtVjMsO9VKEofjXSg1dfE#N^u3|Tnu-P>RbmBdC{`zaJ^&Pv#d z@QGjMf&1Xy7~S!iUF(am;vLckwM5b?D_{lru~o2HW4Xk`xC}>Gx}_gU=t>hzohgrT zk;+bn;g9o_x%3?irn%N0ylB1SK9T60Rkcr38cMvzhG!p{M4vgU#|}R=snE`(<~4VU z?tcD$w-Ig|9Un=GNQZo=5nBXaU__)Kya~8KeyDWXSPZ-deh{Kb%RjA+AJ`$zLlIvIaLhi!^dDxM$3e=V&y{{yx){}IQ zwT;@1S+RvWV@Mu(nPwRCJ%X0~Vjv!BUAEzHUF{!ry}E3z|MA1omQyDeT+^o+Y@xD} zmDNu~mfvP&o#d%{y%ckjPW|q1RO?F>8s-zUku!|vT}D-SY-8vkvr4kxzEhM$BKnge zOW_AOMeX%qbGU_R3zv^ZpWu`6b8W(K!6V9`tc*htkbFLP?TpwcFqPomS*-!Kw-GDU zI4x!FTT~o3S$|_?p9av@&9eT#meOTq3I0cK`2XSaXjK8NraV<)HrdD&5j@;RPx2K; zERk13<;oLAdZzD2bs)WUd3E5GiBk}O1eGDy_Ue>b{Cj{b@OO1hfa~O#P6<)3^)!kEnO9aUallq*K`1fU#QG{MF2VtZz`5Yr?{(jnDD*$>Tbgqu=Y} zG;kc(1VL;qk8ma5>Dm#0f;rgz+3*GYXt+6duGiw&pB!DX{se-kc#oEhY*95+3i8nA zZInuSkB`hR=*U;khroO9PSRJ^ei|fuL~YyOIDvV1$AKXyZcC6Dji64pIL|a#8;vpAxoIoCxfG%_H;*zCGE4Y zb$-&MY@#~f>CcI7y%)U4BWlM_Gml)>7FfbUDRBu4?1g)Qa-3tXzRrz3jF7tb+>Xu_ zW*00i8FCs3EyAB7L;Eho8M}BAu=b8G!q>EOQ)?D?fGVbE>cMe8p>kA-v+7!R&?Kk9 z@VvCNc;_>CR`gHX$cs}(r+QdQUhtchk;5C_`Rbb%7GryyYn{iu`~WL6(0>lW^CzXG z|KX-MrYqyOFO_8U5t?{UzPJ84Hzk!{wQ1L9XXjwDxNmCG@%tw03G;tEgiRh_RJENOMb#2+-^L;A|;vSLVW66_&C>TYKJ5bWqD7I$W*5RFmmJ+T!qL*Tq~+ za65gm8|h)x&)%l`ZOelU0?I-2aqou)wENkk(`QZb3P4?`vgv@jJNJiwifv-29rIZ!lszS)Ke#OUJJz;hTnK|cKO}ZF}ve+%Mjfr z$j}~c>zPw87CEuQm3NSAc?eSUB5ltjzSSP1GK+v!%Cx0**8=J?rE)$Ulua4bRg|;E z6o0+>%?y9Pz{&_NRTJ!Jec>ukr|J7g=K2W4t^)TIG=9on)60vBMe5|$>B4gG%}7s% z_gA}13pK(r%FnXGmo-6*(?bypidQfLl0x(__a?Sdl4`!ag<4b|T!dlamhzHYQLD92 zNBQ&i_N*r~wlY=Cn=Jm**i{zNYz;x%&w^j*ZgM-2Va676_5Japt00$r?lvUlMaT=e z7x*AFYpZIoKFj=7Wsz!eMuX1^8uNvZ81itd%s*mp*HMT?xNB{4prWKR_q!MOrCO-| zOV|}4!yE)pdo>B2TiYy2Pzd+H73KEY{!t(sw2*XjN7{u6$p;b6;4| zs0&*=f|0|9I318g7Yq)l#$$v&qU(VuC3qmmnQya~t2|$KVu=HsYGHo8(X9RQ^Dzlm zco|nHrZishRT6oToqox-$<(?X>Rn^?84tZ)nD^D8K#FudHYBL}DOxc9`WbyfPDear z)`*%okav$ooPlU2*5sYz2!OAqdOINKf;)10g{jEnk#Htu{Kq#uqMCvkUpQu@?XGPbqrs9cI?K%mO(hAo zP?4rlwugkqoauN2Lj%437@woHibktof0=q|#0Yk^RH?i~acs_VU&9P8Hg{6|K^lbE ztkZ>&TB|G;^A*B`^%)jwZL%B1nj?1*>AJjQh;m0)p#J~Y#|OBkNw!k%aIvXAPr_9g zqK{{vEz9$Cgw@(zUg5I4tW`0$w^iSn8uK%Ht&dlDux8}VUtAiAFx9?GyD!5zWNa{Fi)_jp5w4Vq+_EIWIuQrB?{wxCE(@XMd z5jMkzpq^Cp!5(C_kg4)VboGqN^b@Liz9j7U`Oer|6%2}95|~OY4c7ScJfUBB#`g_V zwWuoR(>H-E{>C}w?yxY>uI_&gess!a6%VMlR+dh1Gikdre)K0naVsKMz!>|InGbiS zM};IDORDvc&?(6D6zE@UH5(;4>|ukRRIZlfL9EUr_pBZbjoc zsHz25vj>`9u4UhfVvtJMTB;t1%$ePlS@d%9vh=PWog;A;7G*l)p`wGk-~_VQiG4Ks zQ726CJZX5ubiR_x6SB`~Q&wH|Vq?-e9_;xh&_sUp%8j5v{UQ~?*%sFM{^`-wnUX`$ zuH?%0*uex$1gP~dF3azKK`=a7m0XlWS#a9vj}n^P?LUeXuji_8c`ROL<~WjaWtoRd z);OcLbLmOo`m8N$_KtIttQa2lvsNWDRdQL>HcZCD#MD5%l?>_@ef|WHJ{Y}tjN@E1 zzMn9r_am-e>nR%U?m0@{QDjbLKW1rJbkDJN-l@^p*SGu9BozKE@q^Q;)+HWyt{aNh zG(w=XkGeTEFmjETc^t0Kxh`mPb`jeHutcclOml1qMo%FT(eB%liypP*{ie$-;EN0? zH&F~HUtYcBW!DE~KH63R&U`^0%IXD})LYQ$?K`G{+`%pB_6P=J-PMGxTMNO4(v`+) zdd}!8V?5?nV-yQ@vo%b;%*G{mC*O`9fQ(y5rP^-4#BBl2S;pg>bd7_7*D9%aw2z1R znFj%Ky3k}F%OpeFD0@rR&abPV!%H7m^U}8w7T))#Ci$YF^(8}xAgOD7ct6uUkqRp6 z)Ia_r{m=hiNlR09!BcK&b@VK`P>7FlJW7P_;fVzX=kK(1_ynpC5YNVi(*fbNU!VVj z{Xus#;AXN;b)=kM*~+==QDtpyJb>S+xdLE4{tvzU<@sn$(Y@H{Irc+J8c#~_w9or` zy7wT)3%__N_~OY|tqNB^e!cO?ZUop0i~))v)K@?l;0I!R^N*~NjID5`32%QTpwJB* z(KJJ>)m+`OQ^-2AV@^5)pz47GF~-~!r!a-2GjlgWuS98QjKxoat2gBD8{q1qLjlMNdd$Qj=z#7J zM7}=-?2CKV%T<20`>P**&4*vl#jp7ATlD=ECx2gXe)Yq@^@D8>iCz9t)()nH&6vnl hyKi3P>w5 Date: Wed, 11 Dec 2024 09:24:21 -0500 Subject: [PATCH 2/2] Updated readme --- Scripts - PCB/DiffPairFinder/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Scripts - PCB/DiffPairFinder/README.md b/Scripts - PCB/DiffPairFinder/README.md index 2f074378..d6d7627d 100644 --- a/Scripts - PCB/DiffPairFinder/README.md +++ b/Scripts - PCB/DiffPairFinder/README.md @@ -11,5 +11,6 @@ Run with or without a GUI. In GUI mode, you can add pairs to a selected class or ![GUI](gui.jpg) ## Credits +- Created by Stephen Thompson - From the Altium Script Examples: Matt Berggren & David Parker's PCB_Class_Generator_Form.pas on how to add classes and nets to classes - GPT4o \ No newline at end of file