From 4715e4409d7e9a5a1afe32a9726e31506320b4ba Mon Sep 17 00:00:00 2001 From: Francesco Romani Date: Wed, 24 Feb 2021 12:56:04 +0100 Subject: [PATCH] sriov: add support Add support to report SRIOV devices. Much like GPU devices, support is added using a new top-level package. SRIOV devices are either Physical Functions or Virtual functions. The preferred representation for ghw is Physical Functions, whose dependent devices will be Virtual Functions; however, for the sake of practicality, the API also exposes soft references to Virtual Functions, so consumers of the API can access them directly and not navigating the parent devices. This patch also adds support in `ghwc`, to report the sriov information, and in the `snapshot` package, to make sure to capture all the files in sysfs that ghw cares about. Last but not least, lacking access to suitable non-linux systems, support is provided only on linux OS, even though the API tries hard not to be linux-specific. Resolves: https://github.com/jaypipes/ghw/issues/92 Signed-off-by: Francesco Romani --- README.md | 61 ++++++ alias.go | 9 + cmd/ghwc/commands/sriov.go | 48 +++++ host.go | 41 ++-- pkg/pci/address/address.go | 10 + pkg/pci/address/address_test.go | 8 + pkg/snapshot/clonetree_pci_linux.go | 17 ++ pkg/sriov/sriov.go | 120 +++++++++++ pkg/sriov/sriov_linux.go | 128 +++++++++++ pkg/sriov/sriov_linux_test.go | 198 ++++++++++++++++++ pkg/sriov/sriov_stub.go | 17 ++ ...64-8581cf3a529e5d8b97ea876eade2f60d.tar.gz | Bin 44675 -> 47562 bytes 12 files changed, 643 insertions(+), 14 deletions(-) create mode 100644 cmd/ghwc/commands/sriov.go create mode 100644 pkg/sriov/sriov.go create mode 100644 pkg/sriov/sriov_linux.go create mode 100644 pkg/sriov/sriov_linux_test.go create mode 100644 pkg/sriov/sriov_stub.go diff --git a/README.md b/README.md index 4af2f9ed..92f92c98 100644 --- a/README.md +++ b/README.md @@ -1092,6 +1092,67 @@ information `ghw.TopologyNode` struct if you'd like to dig deeper into the NUMA/topology subsystem +### SRIOV + +*This API is PROVISIONAL! ghw will try hard to not make breaking changes to this API, but still users are advice this new API is not +declared stable yet. We expect to declare it stable with ghw version 1.0.0* + +SRIOV (Single-Root Input/Output Virtualization) is a class of PCI devices that ghw models explicitly, like gpus. + +```go +package main + +import ( + "fmt" + + "github.com/jaypipes/ghw" +) + +func main() { + sriov, err := ghw.SRIOV() + if err != nil { + fmt.Fprintf(os.Stderr, "Error getting SRIOV info: %v", err) + } + + fmt.Printf("%v\n", sriov) + + for _, dev := range sriov.PhysicalFunctions { + fmt.Printf(" %v\n", dev) + } +} +``` + +ghw discovers the SRIOV devices starting from the Physical Function (PF) and exposes them in the `PhysicalFunctions` slice. +Virtual Function (VF) are exposed as properties of the PF instance with exposes them. +However, in some cases users are interested in the VFs first, so it's clumsy to navigate the PFs to learn about VFs. +To make this easier, ghw also exposes a slice of VF instances. These instances are soft references to the very same VF objects +you can find from the PF objects. + +```go +package main + +import ( + "fmt" + + "github.com/jaypipes/ghw" +) + +func main() { + sriov, err := ghw.SRIOV() + if err != nil { + fmt.Fprintf(os.Stderr, "Error getting SRIOV info: %v", err) + } + + fmt.Printf("%v\n", sriov) + + // you will see the very same VF data data you seen from the previous example + for _, dev := range sriov.VirtualFunctions { + fmt.Printf(" %v\n", dev) + } +} +``` + + ### Chassis The host's chassis information is accessible with the `ghw.Chassis()` function. This diff --git a/alias.go b/alias.go index 0b4e149b..606f3647 100644 --- a/alias.go +++ b/alias.go @@ -19,6 +19,7 @@ import ( "github.com/jaypipes/ghw/pkg/pci" pciaddress "github.com/jaypipes/ghw/pkg/pci/address" "github.com/jaypipes/ghw/pkg/product" + "github.com/jaypipes/ghw/pkg/sriov" "github.com/jaypipes/ghw/pkg/topology" ) @@ -149,3 +150,11 @@ type GraphicsCard = gpu.GraphicsCard var ( GPU = gpu.New ) + +type SRIOVInfo = sriov.Info +type PhysicalFunction = sriov.PhysicalFunction +type VirtualFunction = sriov.VirtualFunction + +var ( + SRIOV = sriov.New +) diff --git a/cmd/ghwc/commands/sriov.go b/cmd/ghwc/commands/sriov.go new file mode 100644 index 00000000..c6048c8d --- /dev/null +++ b/cmd/ghwc/commands/sriov.go @@ -0,0 +1,48 @@ +// +// Use and distribution licensed under the Apache license version 2. +// +// See the COPYING file in the root project directory for full text. +// + +package commands + +import ( + "fmt" + + "github.com/jaypipes/ghw" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +// sriovCmd represents the listing command +var sriovCmd = &cobra.Command{ + Use: "sriov", + Short: "Show SRIOV devices information for the host system", + RunE: showSRIOV, +} + +// showSRIOV show SRIOV physical device information for the host system. +func showSRIOV(cmd *cobra.Command, args []string) error { + sriov, err := ghw.SRIOV() + if err != nil { + return errors.Wrap(err, "error getting SRIOV info") + } + + switch outputFormat { + case outputFormatHuman: + fmt.Printf("%v\n", sriov) + + for _, dev := range sriov.PhysicalFunctions { + fmt.Printf(" %v\n", dev) + } + case outputFormatJSON: + fmt.Printf("%s\n", sriov.JSONString(pretty)) + case outputFormatYAML: + fmt.Printf("%s", sriov.YAMLString()) + } + return nil +} + +func init() { + rootCmd.AddCommand(sriovCmd) +} diff --git a/host.go b/host.go index 5d82a53a..a9905011 100644 --- a/host.go +++ b/host.go @@ -8,6 +8,7 @@ package ghw import ( "fmt" + "strings" "github.com/jaypipes/ghw/pkg/context" @@ -22,6 +23,7 @@ import ( "github.com/jaypipes/ghw/pkg/net" "github.com/jaypipes/ghw/pkg/pci" "github.com/jaypipes/ghw/pkg/product" + "github.com/jaypipes/ghw/pkg/sriov" "github.com/jaypipes/ghw/pkg/topology" ) @@ -40,6 +42,7 @@ type HostInfo struct { Baseboard *baseboard.Info `json:"baseboard"` Product *product.Info `json:"product"` PCI *pci.Info `json:"pci"` + SRIOV *sriov.Info `json:"sriov"` } // Host returns a pointer to a HostInfo struct that contains fields with @@ -91,6 +94,10 @@ func Host(opts ...*WithOption) (*HostInfo, error) { if err != nil { return nil, err } + sriovInfo, err := sriov.New(opts...) + if err != nil { + return nil, err + } return &HostInfo{ ctx: ctx, CPU: cpuInfo, @@ -104,26 +111,32 @@ func Host(opts ...*WithOption) (*HostInfo, error) { Baseboard: baseboardInfo, Product: productInfo, PCI: pciInfo, + SRIOV: sriovInfo, }, nil } // String returns a newline-separated output of the HostInfo's component // structs' String-ified output func (info *HostInfo) String() string { - return fmt.Sprintf( - "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", - info.Block.String(), - info.CPU.String(), - info.GPU.String(), - info.Memory.String(), - info.Network.String(), - info.Topology.String(), - info.Chassis.String(), - info.BIOS.String(), - info.Baseboard.String(), - info.Product.String(), - info.PCI.String(), - ) + var b strings.Builder + for _, s := range []fmt.Stringer{ + info.Block, + info.CPU, + info.GPU, + info.Memory, + info.Network, + info.Topology, + info.Chassis, + info.BIOS, + info.Baseboard, + info.Product, + info.PCI, + info.SRIOV, + } { + b.WriteString(s.String()) + b.WriteString("\n") + } + return b.String() } // YAMLString returns a string with the host information formatted as YAML diff --git a/pkg/pci/address/address.go b/pkg/pci/address/address.go index 6a8a4e45..ad371055 100644 --- a/pkg/pci/address/address.go +++ b/pkg/pci/address/address.go @@ -25,6 +25,16 @@ type Address struct { Function string } +func (addr *Address) Equal(a *Address) bool { + if addr == nil && a == nil { + return true + } + if addr != nil && a != nil { + return addr.Domain == a.Domain && addr.Bus == a.Bus && addr.Device == a.Device && addr.Function == a.Function + } + return false +} + // String() returns the canonical [D]BDF representation of this Address func (addr *Address) String() string { return addr.Domain + ":" + addr.Bus + ":" + addr.Device + "." + addr.Function diff --git a/pkg/pci/address/address_test.go b/pkg/pci/address/address_test.go index daf0eaa6..c3989dd4 100644 --- a/pkg/pci/address/address_test.go +++ b/pkg/pci/address/address_test.go @@ -80,3 +80,11 @@ func TestPCIAddressFromString(t *testing.T) { } } } + +func TestPCIAddressEqual(t *testing.T) { + addr1 := pciaddr.FromString("0000:03:00.A") + addr2 := pciaddr.FromString("03:00.A") + if addr1.Equal(addr2) == false { + t.Fatalf("addr1 %v and addr2 %v should be equal", addr1, addr2) + } +} diff --git a/pkg/snapshot/clonetree_pci_linux.go b/pkg/snapshot/clonetree_pci_linux.go index 28ec3d14..e27a65a7 100644 --- a/pkg/snapshot/clonetree_pci_linux.go +++ b/pkg/snapshot/clonetree_pci_linux.go @@ -69,6 +69,15 @@ func scanPCIDeviceRoot(root string) (fileSpecs []string, pciRoots []string) { "revision", "vendor", } + + perDevEntriesOpt := []string{ + "driver", + "net/*", + "physfn", + "sriov_*", + "virtfn*", + } + entries, err := ioutil.ReadDir(root) if err != nil { return []string{}, []string{} @@ -95,6 +104,14 @@ func scanPCIDeviceRoot(root string) (fileSpecs []string, pciRoots []string) { fileSpecs = append(fileSpecs, filepath.Join(pciEntry, perNetEntry)) } + for _, perNetEntryOpt := range perDevEntriesOpt { + netEntryOptPath := filepath.Join(pciEntry, perNetEntryOpt) + if items, err := filepath.Glob(netEntryOptPath); err == nil && len(items) > 0 { + fileSpecs = append(fileSpecs, netEntryOptPath) + } + + } + if isPCIBridge(entryPath) { trace("adding new PCI root %q\n", entryName) pciRoots = append(pciRoots, pciEntry) diff --git a/pkg/sriov/sriov.go b/pkg/sriov/sriov.go new file mode 100644 index 00000000..a250b601 --- /dev/null +++ b/pkg/sriov/sriov.go @@ -0,0 +1,120 @@ +// +// Use and distribution licensed under the Apache license version 2. +// +// See the COPYING file in the root project directory for full text. +// + +package sriov + +import ( + "fmt" + + "github.com/jaypipes/ghw/pkg/context" + "github.com/jaypipes/ghw/pkg/marshal" + "github.com/jaypipes/ghw/pkg/option" + "github.com/jaypipes/ghw/pkg/pci" + pciaddr "github.com/jaypipes/ghw/pkg/pci/address" +) + +type Device struct { + Interfaces []string `json:"interfaces"` + // the PCI address where the SRIOV instance can be found + Address *pciaddr.Address `json:"address"` + PCI *pci.Device `json:"pci"` +} + +func (d Device) ToString(devType string) string { + deviceStr := d.Address.String() + nodeStr := "" + if d.PCI != nil { + deviceStr = d.PCI.String() + if d.PCI.Node != nil { + nodeStr = fmt.Sprintf(" [affined to NUMA node %d]", d.PCI.Node.ID) + } + } + return fmt.Sprintf("%s function %s@%s", devType, nodeStr, deviceStr) +} + +type PhysicalFunction struct { + Device + MaxVFNum int `json:"max_vf_num,omitempty"` + VFs []VirtualFunction `json:"vfs,omitempty"` +} + +type VirtualFunction struct { + Device + ID int `json:"id"` + // Address of the (parent) Physical Function this Virtual Function pertains to. + ParentAddress *pciaddr.Address `json:"parent_address,omitempty"` +} + +func (pf *PhysicalFunction) String() string { + return fmt.Sprintf("%s with %d/%d virtual functions", + pf.Device.ToString("physical"), + len(pf.VFs), + pf.MaxVFNum, + ) +} + +func (vf *VirtualFunction) String() string { + return fmt.Sprintf("%s index %d from %s", + vf.Device.ToString("virtual"), + vf.ID, + vf.ParentAddress, + ) +} + +type Info struct { + ctx *context.Context + // All the Physical Functions found in the host system, + PhysicalFunctions []*PhysicalFunction `json:"physical_functions,omitempty"` + // All the Virtual Functions found in the host system, + // This is the very same data found navigating the `PhysicalFunctions`; + // These pointers point back to the corresponding structs in the `PhysicalFunctions` + // slice. + VirtualFunctions []*VirtualFunction `json:"virtual_functions,omitempty"` +} + +// New returns a pointer to an Info struct that contains information about the +// SRIOV devices on the host system. +func New(opts ...*option.Option) (*Info, error) { + return NewWithContext(context.New(opts...)) +} + +// New returns a pointer to an Info struct that contains information about the +// SRIOV devices on the host system, reusing a given context. +// Use this function when you want to consume this package from another, +// ensuring the two see a coherent set of resources. +func NewWithContext(ctx *context.Context) (*Info, error) { + info := &Info{ctx: ctx} + if err := ctx.Do(info.load); err != nil { + return nil, err + } + return info, nil +} + +func (i *Info) String() string { + return fmt.Sprintf( + "sriov (%d phsyical %d virtual devices)", + len(i.PhysicalFunctions), + len(i.VirtualFunctions), + ) +} + +// simple private struct used to encapsulate SRIOV information in a top-level +// "sriov" YAML/JSON map/object key +type sriovPrinter struct { + Info *Info `json:"sriov,omitempty"` +} + +// YAMLString returns a string with the SRIOV information formatted as YAML +// under a top-level "sriov:" key +func (i *Info) YAMLString() string { + return marshal.SafeYAML(i.ctx, sriovPrinter{i}) +} + +// JSONString returns a string with the SRIOV information formatted as JSON +// under a top-level "sriov:" key +func (i *Info) JSONString(indent bool) string { + return marshal.SafeJSON(i.ctx, sriovPrinter{i}, indent) +} diff --git a/pkg/sriov/sriov_linux.go b/pkg/sriov/sriov_linux.go new file mode 100644 index 00000000..c64d96b8 --- /dev/null +++ b/pkg/sriov/sriov_linux.go @@ -0,0 +1,128 @@ +// Use and distribution licensed under the Apache license version 2. +// +// See the COPYING file in the root project directory for full text. +// + +package sriov + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/jaypipes/ghw/pkg/context" + "github.com/jaypipes/ghw/pkg/linuxpath" + "github.com/jaypipes/ghw/pkg/pci" + pciaddress "github.com/jaypipes/ghw/pkg/pci/address" + "github.com/jaypipes/ghw/pkg/util" +) + +func (info *Info) load() error { + // SRIOV device do not have a specific class (as in "entry in /sys/class"), + // so we need to iterate over all the PCI devices. + pciInfo, err := pci.NewWithContext(info.ctx) + if err != nil { + return err + } + + for _, dev := range pciInfo.Devices { + err := info.scanDevice(pciInfo, dev) + if err != nil { + return err + } + } + + return nil +} + +func (info *Info) scanDevice(pciInfo *pci.Info, dev *pci.Device) error { + paths := linuxpath.New(info.ctx) + devPath := filepath.Join(paths.SysBusPciDevices, dev.Address) + + buf, err := ioutil.ReadFile(filepath.Join(devPath, "sriov_totalvfs")) + if err != nil { + // is not a physfn. Since we will fill virtfn from physfn, we can give up now + return nil + } + + maxVFs, err := strconv.Atoi(strings.TrimSpace(string(buf))) + if err != nil { + info.ctx.Warn("error reading sriov_totalvfn for %q: %v", devPath, err) + return nil + } + + virtFNs := findVFsFromPF(info, pciInfo, dev.Address, devPath) + physFN := PhysicalFunction{ + Device: info.newDevice(dev, devPath), + MaxVFNum: maxVFs, + VFs: virtFNs, + } + + info.PhysicalFunctions = append(info.PhysicalFunctions, &physFN) + for idx := 0; idx < len(virtFNs); idx++ { + info.VirtualFunctions = append(info.VirtualFunctions, &virtFNs[idx]) + } + + return nil +} + +func findVFsFromPF(info *Info, pciInfo *pci.Info, parentAddr, parentPath string) []VirtualFunction { + numVfs := util.SafeIntFromFile(info.ctx, filepath.Join(parentPath, "sriov_numvfs")) + if numVfs == -1 { + return nil + } + + var vfs []VirtualFunction + for vfnIdx := 0; vfnIdx < numVfs; vfnIdx++ { + virtFn := fmt.Sprintf("virtfn%d", vfnIdx) + vfnDest, err := os.Readlink(filepath.Join(parentPath, virtFn)) + if err != nil { + info.ctx.Warn("error reading backing device for virtfn %q physfn %q: %v", virtFn, parentPath, err) + return nil + } + + vfnPath := filepath.Clean(filepath.Join(parentPath, vfnDest)) + vfnAddr := filepath.Base(vfnDest) + vfnDev := pciInfo.GetDevice(vfnAddr) + if vfnDev == nil { + info.ctx.Warn("error finding the PCI device for virtfn %s physfn %s", vfnAddr, parentAddr) + return nil + } + + vfs = append(vfs, VirtualFunction{ + Device: info.newDevice(vfnDev, vfnPath), + ID: vfnIdx, + ParentAddress: pciaddress.FromString(parentAddr), + }) + } + return vfs +} + +func (info *Info) newDevice(dev *pci.Device, devPath string) Device { + // see: https://doc.dpdk.org/guides/linux_gsg/linux_drivers.html + return Device{ + Address: pciaddress.FromString(dev.Address), + Interfaces: findNetworks(info.ctx, devPath), + PCI: dev, + } +} + +func findNetworks(ctx *context.Context, devPath string) []string { + netPath := filepath.Join(devPath, "net") + + netEntries, err := ioutil.ReadDir(netPath) + if err != nil { + ctx.Warn("cannot enumerate network names for %q: %v", devPath, err) + return nil + } + + var networks []string + for _, netEntry := range netEntries { + networks = append(networks, netEntry.Name()) + } + + return networks +} diff --git a/pkg/sriov/sriov_linux_test.go b/pkg/sriov/sriov_linux_test.go new file mode 100644 index 00000000..49f90131 --- /dev/null +++ b/pkg/sriov/sriov_linux_test.go @@ -0,0 +1,198 @@ +// +// Use and distribution licensed under the Apache license version 2. +// +// See the COPYING file in the root project directory for full text. +// + +package sriov_test + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "github.com/jaypipes/ghw/pkg/option" + pciaddr "github.com/jaypipes/ghw/pkg/pci/address" + "github.com/jaypipes/ghw/pkg/sriov" + + "github.com/jaypipes/ghw/testdata" +) + +// nolint: gocyclo +func TestStringify(t *testing.T) { + info := sriovTestSetup(t) + + for _, physFn := range info.PhysicalFunctions { + s := physFn.String() + if s == "" || !strings.Contains(s, "function") || !strings.Contains(s, "physical") { + t.Errorf("Wrong string representation %q", s) + } + } + + for _, virtFn := range info.VirtualFunctions { + s := virtFn.String() + if s == "" || !strings.Contains(s, "function") || !strings.Contains(s, "virtual") { + t.Errorf("Wrong string representation %q", s) + } + } + +} + +// nolint: gocyclo +func TestCountDevices(t *testing.T) { + info := sriovTestSetup(t) + + // Check the content of + // GHW_SNAPSHOT_PATH="/path/to/linux-amd64-intel-xeon-L5640.tar.gz" ghwc sriov + // to verify these magic numbers + expectedPhysDevs := 2 + expectedVirtDevsPerPhys := 4 + numPhysDevs := len(info.PhysicalFunctions) + if numPhysDevs != expectedPhysDevs { + t.Errorf("Expected %d physical devices found %d", expectedPhysDevs, numPhysDevs) + } + numVirtDevs := len(info.VirtualFunctions) + if numPhysDevs*expectedVirtDevsPerPhys != numVirtDevs { + t.Errorf("Expected %d=(%d*%d) virtual devices found %d", numPhysDevs*expectedVirtDevsPerPhys, numPhysDevs, expectedVirtDevsPerPhys, numVirtDevs) + } + + for _, physDev := range info.PhysicalFunctions { + numVFs := len(physDev.VFs) + if numVFs != expectedVirtDevsPerPhys { + t.Errorf("Expected %d virtual devices for PF %s found %d", expectedVirtDevsPerPhys, physDev.Address.String(), numVFs) + } + } +} + +type pfTestCase struct { + addr string + netname string +} + +// nolint: gocyclo +func TestMatchPhysicalFunction(t *testing.T) { + info := sriovTestSetup(t) + + // Check the content of + // GHW_SNAPSHOT_PATH="/path/to/linux-amd64-intel-xeon-L5640.tar.gz" ghwc sriov + // to verify these magic numbers + for _, pfTC := range []pfTestCase{ + { + addr: "0000:05:00.0", + netname: "enp5s0f0", + }, + { + addr: "0000:05:00.1", + netname: "enp5s0f1", + }, + } { + addr := pciaddr.FromString(pfTC.addr) + pf := findPF(info.PhysicalFunctions, addr) + if pf == nil { + t.Fatalf("missing PF at addr %q", addr.String()) + } + if pf.PCI == nil { + t.Errorf("missing PCI device for %q", addr.String()) + } + if pf.PCI.Driver != "igb" { + t.Errorf("unexpected driver for %#v: %q", pf, pf.PCI.Driver) + } + if len(pf.Interfaces) != 1 || pf.Interfaces[0] != pfTC.netname { + t.Errorf("unexpected interfaces for %#v: %v", pf, pf.Interfaces) + } + if pf.MaxVFNum != 7 { + t.Errorf("unexpected MaxVFNum for %#v: %d", pf, pf.MaxVFNum) + } + if len(pf.VFs) != 4 { + t.Errorf("unexpected VF count for %#v: %d", pf, len(pf.VFs)) + } + for _, vfInst := range pf.VFs { + vf := findVF(info.VirtualFunctions, vfInst.Address) + if vf == nil { + t.Errorf("VF %#v from %#v not found among info.VirtualFunctions", vfInst, pf) + } + } + } +} + +func TestMatchVirtualFunction(t *testing.T) { + info := sriovTestSetup(t) + + // Check the content of + // GHW_SNAPSHOT_PATH="/path/to/linux-amd64-intel-xeon-L5640.tar.gz" ghwc sriov + // to verify these magic numbers + + for _, vf := range info.VirtualFunctions { + if vf.PCI == nil { + t.Errorf("missing PCI device for %q", vf.Address.String()) + } + if vf.PCI.Driver != "igbvf" { + t.Errorf("unexpected driver for %#v: %q", vf, vf.PCI.Driver) + } + + pf := findPF(info.PhysicalFunctions, vf.ParentAddress) + if pf == nil { + t.Fatalf("missing parent device for %q", vf.Address.String()) + } + if vf2 := findVFInst(pf.VFs, vf.Address); vf2 == nil { + t.Errorf("VF %#v not included in parent %#v VFs", vf, pf) + } + } +} + +func findPF(pfs []*sriov.PhysicalFunction, addr *pciaddr.Address) *sriov.PhysicalFunction { + for _, pf := range pfs { + if pf.Address.Equal(addr) { + return pf + } + } + return nil +} + +func findVF(vfs []*sriov.VirtualFunction, addr *pciaddr.Address) *sriov.VirtualFunction { + for _, vf := range vfs { + if vf.Address.Equal(addr) { + return vf + } + } + return nil +} + +func findVFInst(vfs []sriov.VirtualFunction, addr *pciaddr.Address) *sriov.VirtualFunction { + for idx := 0; idx < len(vfs); idx++ { + if vfs[idx].Address.Equal(addr) { + return &vfs[idx] + } + } + return nil +} + +func sriovTestSetup(t *testing.T) *sriov.Info { + if _, ok := os.LookupEnv("GHW_TESTING_SKIP_SRIOV"); ok { + t.Skip("Skipping SRIOV tests.") + } + + testdataPath, err := testdata.SnapshotsDirectory() + if err != nil { + t.Fatalf("Expected nil err, but got %v", err) + } + + multiNumaSnapshot := filepath.Join(testdataPath, "linux-amd64-intel-xeon-L5640.tar.gz") + // from now on we use constants reflecting the content of the snapshot we requested, + // which we reviewed beforehand. IOW, you need to know the content of the + // snapshot to fully understand this test. Inspect it using + // GHW_SNAPSHOT_PATH="/path/to/linux-amd64-intel-xeon-L5640.tar.gz" ghwc sriov + + info, err := sriov.New(option.WithSnapshot(option.SnapshotOptions{ + Path: multiNumaSnapshot, + })) + + if err != nil { + t.Fatalf("Expected nil err, but got %v", err) + } + if info == nil { + t.Fatalf("Expected non-nil SRIOVInfo, but got nil") + } + return info +} diff --git a/pkg/sriov/sriov_stub.go b/pkg/sriov/sriov_stub.go new file mode 100644 index 00000000..55b8e708 --- /dev/null +++ b/pkg/sriov/sriov_stub.go @@ -0,0 +1,17 @@ +// +build !linux +// Use and distribution licensed under the Apache license version 2. +// +// See the COPYING file in the root project directory for full text. +// + +package sriov + +import ( + "runtime" + + "github.com/pkg/errors" +) + +func (i *Info) load() error { + return errors.New("SRIOV load() not implemented on " + runtime.GOOS) +} diff --git a/testdata/snapshots/linux-amd64-8581cf3a529e5d8b97ea876eade2f60d.tar.gz b/testdata/snapshots/linux-amd64-8581cf3a529e5d8b97ea876eade2f60d.tar.gz index 60454786f40f81288102ea44245b7be81c0d9085..1f8117078bab0ffd9fa47fc9686aa1e6cad2222d 100644 GIT binary patch literal 47562 zcmd43dt6NU{|D~2%C5xP6~&I*%I;#^x>$5rOKVB&vbmH=E)hz(B+@}v2)V6NY0wf% zA(To-QXw@+jdYnZ)ySySG}X+Ub6&sKIaBf3+h@Pu-}m=;{62r|M`zA?zu)KeeqElg z=j-)8f@#-er3I||n;!;T{{E-?!5!*Xb(87#lx%jMd8V;Cr}q~tMx9i>idlYe%&_cZ zIdPV=9!n{kjjNU)A2!b|X20a%p_oItU1v%?)}@!Yofb+C-d>s;rHR?5lI7oF>0c*- zcFv3Ekg~9NLA=t(LHfd%csAZIl3jBwvw99AfBquAV@22ltx2Vug@`Se-}Oxty2>>T z*G-{ZUM9;fbh7w{jJT5hFu=vrDls=Izd|Lj>G8}sPm>ruZ zt0Z+rU`msfzPB{$EQ3j3t6VlY$MS9SJ5V3F6=%j`{!L&5E*tKW%9`f4JRa`}Mo*cYjr zb;}kw*BL2zc6bz<`=FBj7?BX_C4deha!uMMIl(SyaayT%8kxuguQ$;o$~ zur%&KhV$3~pQ#GnPD=`c!Wv^O zG0i1)_$uYprLkR)(@k2hu>(#7MyI(r8T}F+U4JHNactN8{8w&Q7dtovrfs{H;#g88 z*VOsz3U8P?+CK`&xE?BuRx767UT9ov5~hst$gbQp_mFC8>SL*Yjkm_jB}-sgr@nSj zARy9Q7M;vn&j_XYHynFhE@YZEo(NP|rdRq}7W$QD=OpOzGYX<#dHLV2^NwG6d$BOu#p$rnqt;R;&iI|)u(`SA=lLUQM@3bxm>dB%W-)zMUR!!H zxVb6YqogSzI9lzyXz9`&ODm%Don53-|LUz43z-O^`!D`(lW!-5m)aHNufNG|u%J%a zM`u(;2liH^2H6TC$jpdNCo_X~B|kRL&sn!Pw;+f-6_l0jb@L?~UlS0Pw&3Pcqlk^x z{qIL+QMcnxDwBO1mW_csjy*1DMo?c_i52nyV^PB7Tf+50Yo0ZQFc-3}RxZnqyimFS znDfXW-N_{pBLY*spI)rFn3X#D&3@y9+gxrDpLa^t95lefK$*eU-a zdg_{69@~F?xNFJVZgtn<)lc)Zdp3ny{E%b2Sm5nkT4`P9qKu4Ecbm|pxsXv+D^MKh zG2Et?nZVM<%~X73n!sq4s_0PA07ZYw&HH0`7(KWrmda4 zw^wmw+IpL3E&W$-f6;igdR|`Rp8n0NkAwwHdiL9Z)!WBf+N|?^KHg?f)@0MSRS9O| z&KpO~x&5N?^_p$p9o|0vL5}SgZ<4Iv&6R%CHnIE*qb;hVQAs^!Cyg+7TIbt{4||V# z?rbISiBaBlYTA=fSlIGhSK?*& z8|Eo_xdpcN%HCeDBd5CCG&xFl?GKjU54;i-QD88ssk(`dQ>~d`;G-)wzWG1zP7x2AMcmN9iAj}T@zXwFYHojz=)ZB_M6L9NQ|n8@xH z3_KKXedlU*)lH(*Nfex&pCv3Qd~oRcCY>kYK6Who=6u?N!pH04nww>+3|8r1lf}%9 ziPkmbXE`~BtloY{?5fF)j-2;4M%Um8CnZ(!pl;AkHzgTQ(bAjq!js}+n?0oYzx!$v zpJqH*QJbH2CnYq)( z=8u$$y@};s*O*kA%64;FTAATtV52aO*Sw9>*lEuHXz3NXT4zBY6ZVOdU6}Q1ykE@I znj7J@j>4Q{xKM@ck;^fMJfX-p{NSiBC?P4XaEK#DSeRhEQ4i21id?g^9K^)SVZ;1< zg|KLpYh^{9GLE{3!_-u*)n!%n_ERqp$$Z$PYX~NQX^`3_ut`4@H8*5wN@89xbBH@l z4Gf*N=^Dx^H!9DK5#`@l>>)Z(JUujN9$k6UPNYtkB?uP>AB^zJWnDw<@h#6c&g=iB z$)fQGp1q9@CY|m)PtP3YL*KBEW43O$(yec

I0&2~2hn&G>9(kn9;e2$suKD>ZW8 z+bK(8#Dpq4D1$66IT1&WkMQembzVl+XRjqsANKa!bSsXz9eToJM{dqqouH|4bCOyEI;O+?3ZS_zmR6!Z@=(acFpIkR+??@RaKwmrFyx| zYxBE1DEDj^W>)Gx@vJIGw=c*QqNN+DNvS78t!D}%>4s3IIVebYXk8z|GVIDrSP#_K z=2COzyry~rtSmhrtH@p{&%yUwD(s4blVjv6IyiJw0z31>m;GVT!W~PU;<_p@e5J`f zf+=H%upZ5q!@Ikx@|`Tc$gPq$_*sVq8?PMWc=EXKxU*&`1 ze^pjA`A#+2uWN#;pQLV8{^kXT4J5)@PayWIfAqbNQ;8xw*ki-ZaQCiD6qTDdvn|iu-Zj_{ zC3d3vXX}y{I~rR;oaS!Sx09K~{%qIWN9vVh78zMlqfX`*>n7fA?pB&wP$NI`K=-Lc z(A?y@biVwz=BN_CCq?3oi{~h^C8c6@b$ThAlJUxYLF^r(E-&B?{wJ9JPy2>{D4$O6E}>qXi3{nUyPI~a;!!Q56qCg4G!9&`&gQNop!k0$i9^b z5;TvC{FWu1Y8fGk^07#!H14YGGT*s2F>(j7YQgraUz_K@tu2r4Lsxrr6)j!FrmDsS zjV$qQx)$%Z2C|sTYqn40k)7Mxm8KF>W zE(AWpcsj8(ckbRmw|VYK)%NqoUw_#2%6^bv?Q{=u)Es}Iu)o$NK%$DauMMtIoMKh6 zDc=Z)hk11=8WqwIcZke;r+h5_3VpFp1lu2c7R1xiDk=$<*Ri*A0sCk?8a)*Bq zIbo}h-7`-|*_B5wlYKN}3TYqJ{#7fl#a6}VmuUn)*c8e;tPW33)8zZ6#%lUaeiwfy zVpLZ}7#P}kS>)EpH(NSYm9gK7C^jv;Dq3c`VC;Ie6~yCPeCOA2>Fa|+VEZifpU#3w7ayi}EVu?4zRNwB{vhfJYf6=`nt5BGp2 z$6qHGdd*uG=Vfy#HrG`et*ShiSiEA*&&oJIoh~h{y1{*mU&7bHiY?>5i|O}is;@~x z;kLzfOwG#sqf??Y#g<~%i657+Rmy8iUu!;|Ffv+ldbUPXp1>Xt@29*zUamFXZ717c zams|+y!Fs9C3$HX!<+UbCN|QWSqQV2lCI;9pEfFPmJyQmxnlRjV)o8;R+JibD{Srf zOVmvZHIcu4B}4hzJ6TCr&xeZ_*r;uBF%Vq0=6Q~VX+Cl35?m_%MhTVMO}#fBnxT$U zg1vg_B8aN1b_@63WK^fM&AdO6fpZrvp*C`i!k+TGk#!w`#t3{FUY=O7zCBV%Bm- z5?7n#)Ol>Fl9+c-L+p*xdNkx0TF^>??Y#TiAuX3#$@-dyapfWyI_uK{LE0`Ywdrcu znEbC|%cWrMnwc?dhba(j-Gkw0YQk19vRKN<0UrOTlr`90XFa6E#|z>6#cz0?vp>bq%``=q$Lc)&Y zF;JwI_}_$4pDOrag7S&^y1K!h?2^=(1+b8b|JgBeCeypVB~CvH+3PA391FMfPYME} z$q~6^Ha{qNl_mNF!D9V`>1ue@)VeaV-&Mv$KfWv$Hs93-D#($tp-M7_JzD^is`x)( z2D5$&n0ubO!B{nAbn<9Cya<-7jmNY0;l=Rc5>+>G6(hSyeG*1q1Cu+?si*iiw_0{c zJp(1$aj-PS35Ks=BcJ=kz%8Gw7%)@Y?=FxX$RbUI>bBtu*d_HX9#QN%xMTebX*L!P zy^)m-h-b6j2u8uHdYHqUB86^m$YV}@LZ8bla``t%2}V}c{|fa<2rSfZH}MN>(AZb1UD>doe}=iNtJ{61 zRq!x#OQHLG(i8Zt$2VEcn9n(63$iz;Gk^FKRj8OHzmOBPAl)0P4KRi62iv#o5M;Mji)@6Vxj&pGF(p*21g$k z$*-~dQ&>xjuqGJVFmpf*xHA&lQDcJh+ItQ6vVoGyMJKxGcFcj}=tJ1vx1eX~WjJ^Fi#eMQb(NzL3GuFgH>AaO>xW6QaYip; z{7QCE|I5(QoLxU&ILgG_wCngau)IKU@2oaBVY<5H(g9fv6NIb53l6a@?vAmS!wTy( z*Vn=EGBIg(zCTQ}UI;NE!t89Xa04?a+M^EGaFw-kFuyayzg~1tBiL*8h9q~~TRZ+W zT$#Cu>|&rKmINQK8y1+q-~A)2HDDwq2c;~6>;<0Q=hlvYK%N`}J$n?8sY$8fOBX~f z?y&j@Si9gNW58vxQ|uh?PcBYnm&by$^?Z1EE-~gn(Qzkqmm`(N<#U;+O1sp@(e;%m zC&R1ra2r3lm!_3fSk>+keRo_VdR#BqGfgcH5P|*d$0*VHFg-O_sB-bVEZ8|rMQF*s zJqoCcsY|ZZ&ADY*JQR8{#)clxDaXgb%AcJgr!sl_7y<_n{g(YT@oNiw@2^chC?^dK zlw|U7cax~(8IkA{d-lkO+FKV#c?2GjkY9Gwk%lO6(MV}Ny=mN(I_<>eA!PS}H!wFh zb;;}owc2;WIs_%nO84CUhT)Hozf}R^RWWP_%49p5{o%ZEu$2# zI9WsNNmmo3Rz2Q!r{!w6QrRNdeTG$J4D~qQ$=zmAXr_l$_L5Ohc^sX0F@>#4`#r2# zH>lBU(9|OpP_M3%Ud*8$Zcz!o?4}C3JL&st`$PP${Lmm8359P=)taEDS}>~;?6wQp zk@G_XamqwfaeZO2-Q@+nzdB02H9H&}3V9l9@%$X8cQ5Iv>e?0} zevB%}dER_Mot4Md6*H>0PV5tCcjG1dn}s|6_q6A{Z3{v+E$I8R=e0AoICyecRdBo} zvHH`U%`LJ;$5%WicGrzakLfp)4X)gA^Kw=E1?f8hgpKfgOmtE?PhhzTn=98%5?N9+ z{MGPc26z2xzn1uqp8V*fwQ^>N*Tf0LU!7|tzc_Ws__`;pRXXBS^E{ewSu0n$?8mQ;Hxj`I*rI( zM+;Q4$wD^x5Pat06qn=s&Iq!f!W*+vjrh0Hj}zBig@8&%V92VQgF7+`GWUEVIq(VO z9r9+)9_(aQgsX-Yc2$*GhyQ$#zogd4k|Ed&jJsE*Wv+bOXUaDbngqMpastL3m1{&j zeU-*4${PHqz$~j$jjcx1NDO)c&km97RMz1;_+*ziGmkYXA`Oo&FN*6|M@Q1aSeSMO z&YRWI{{!Y ztZx?|tsov~JkT|~hyY6$?ajfDD5^pAvAhmKthFzp@Hev0^aZ1;vWErCt2s9bj%f`h zKu`_QCF>5gV8}!AhzeS0gDzSki600(@WB3)z++PdO@*-b;v*HreGOR*W}O*h{nUh3 z)N?B4<9(aF-EplAk7@ zBi4awWvqQty@Xf|Q3rLzpm(u^8l}3!POQ{<7Z5<5yK3o@#BMyW>CG^!R)^G@9ty8|_Yn89T?_GM2~6Skb|yP59BiR?X9=p-P#Ba8az@a-NCjROMBkjF1FS(< zt|1MFs*OEa@k*U>+RAl03;kZahN)*D5=Zb4hb%_M?M0nI1VnwLzoH{hSQ71e7N=v0o?X<&a@ar{>|%qsy?O=jSmQlc;ODW-;$D@+ zPB^|$OK?kg1y`AXvKjgn7(xJR)m5(ydmx=5NB3_e+3&&j6P%@<+zQ5>7y+jT_n@2= z_I(Z9T6(g^&1BjXu(jH(p$seF`@O7jr>TsXJ+e+huJgitWMc2>jnu%F0>Nf>$@lO{ zCke@!+*Ad%G6m2n!WAc>jiXyO*e)D?uT?*_6*Fw;)a;aT9EvdcGEPZA%5NO+B%h^HiUfY(8e+;yC z+m}lXFH6XjUuE0QP(aOOPD{89^5rFJC7XO^88bw@ zcKk(h#g-y6oA%!2%G`O$xXwP#h{kGVhUnXh;8z{>T^TFX8>5L0bljz*US|?$ccKx^ zs>Ej3|UO^ktV= z8L4CpD@4b{-GB^Ct?j8FjbRj*nDzPB5p5 zEW87-l_iRxc3EB=MuCkGoSq`3jY~#TepFRU8}wBC|O z3yL9Q1DK55s=(R$SDmhsQ7le4uGK~i}-XmBJ#=9^Ypnqu9{HttmsxT&1-7-+~bhyxpei#SKXWRZSR_aV@lO}~4~QU40PnlTVL zktfi}3R)4sJXRp)!mYhkgvMk1m(5}b8-92K*p@9JLm*2*yuVG#MH6m4Q(18&Mz>^k zI67df*3~=$Ic?mj8E@diji7xkCqR+d8bE^Ngy9K-Ti^)@-T(w2gUEI)GL>6NI=7Og znuMH)w0B}q(W1{%)d~&e@otXNo_|sNBfuv?69rNIfL75mE9!xF2wA7af2OD8Y2&M< zxBwrvZdvJC_BM#!QdANZX{?%~`rz>>O>-O}fyoahULo}EuM+yz@~<=rnn$B*>E##! z+e5s=NG%zP+ZE|LnpVKD1GjPE7+sriSB=_tHIc=LBX*}%#tkr5OB$wd`}vxj=FDq* zWYgaYC)kq_AT*z<15XTE4FP(U>fg3cwt(oTRYB`D1i!zhAn~CEE@cv!{OZBrtD50^ z=kbE)-+Mh<4QtR@;j82b8wOO#lG)a`TBk*WA-T6|4#mVj%CwG?Ac_rbgWEU$@ii=? z`LS<2qh;~}7=>-QAqtHb}($qdB7}81obpKev5NxiG$y(Zo!$^s25FZ zG4ywRB>je#lIu@CgPqQ)k(K8$nc#-Mm;({8a%`4LH1MrX6s9SQgq4TPCTm2aevJG0 zchSM<5Hht8DbP6$ zv#xJW`CZx95Y$ZGVr50F{coSER{AVDtU6a?HN}VhQe9UHo;ubT_v-F09@>_}P(;E{ z;3+O>DlKTjOjASD+6S?cy$(9!P$K*+LukAQjyJIA#dz?Hf4oCT)<|wbDAyB#l#u)3 zl7z$x)$HC7prEGqd`=vMbPSOCC-%WKFuqp+p0lZ6IEY3*0sp&)MI555Clc9DcCi6G zbR#is+3*B5G!i!kazp#;2toFl~z~KDErk};6RBL)+KOB7qQwCln z`+`5ZNBn_bm_KWRI54f>nZ>Ph?rxoP0t6^O7z-Vj0TZ;34d}z)w*iFjhiE3zBR}C~ zW2}{N^IsSRJ|QYH{8}T?)9?-A!+qV6YX~v;d0lGJ+m4$CKO{TAki#vsu#2i})VYJz z(gVYxMMcgI?>`X~`V_vN50k=6Ty}Ru0ly=xSa^%Me6&JP2iCpo5k<8N8vod{16;=m zd>hFa&q#B~nqIwNnV;k5!_GmTIj*-1UW7CQE|S~8t&kPEPlAxqcyBWC4UbsuGZp-= zb~`wvEk78EmdWc6T3{QhwV%!JPQNicV#e)#22%%KA`QWOIb!zfH4b{+;1fC?vbPY8 zSX8*cp#p>8`Ce*ys-BNfUEl?@ZR?P<3}Ly=nTP49 z?{6>6bY?r^qWmVkfeqI#A`yU_GxK%Z!ltzl=+pLat3kDUM}C^FAUVCab7BMMD#+=L zByJ}(2E2|OljGNyOY+x^o}XcHmqvMj>QPlJNJ7`(jIvsO2DgQ zzCz~$v@Y8@Qwj%We|D#V>M`6ouVI*|D!;`mpU$l4#{r`vjav;JTW-Y$S=Ep!YhVIf z7qLoBh!ojjUNtsJLA&FgQ|!FYHnPTNcQBF!nB26nOaw1Zg{W;eBx%JWyQ&P2fLN?L z++X>XGN|l1K6*%1g0vsh)1m@ud&A7lZsX&|{y(l4X94D9m9045$E$e(HbWQ^?s*XyXv4fSD)QjA1 zL+3qDZ7n;5_H&3HEIKR{RdpQT7@5{WY^j?J{o%Ox6my335#<($Y9AqE;mw#MVzJuW zLrI>BvymJarVg6@=~LMKZvN#A-?6vDV;`N%ztd=ip}wf1gaF+fEop=Kocl`%P*;u> zmrPo-yHo`a`s(n%b2fAnuuo^3Yp5%k@`h~ry;2n!eEXmdrj*eltJ4)!sFVHWup-6H z`!DI_I~dXo#%#UcJ%UVcn)3PS3J`l&mN*0%_Va*m;!mB2U!5n26xf%QZC>J(zMVE% z6r9@3ha+2371=X2M*+n;F$~(hxf3?7U5FRt z#eLD~vIJ^X#G?KiX@g~rN58ons<9M`So>9_$xuJ1?6t_Mq!P022G-HZBgWS4pkaG{{KZ3W9Eo0!_9tMOWut*b_$3a-h}r;-x3O2wELL zF>;~!tvoJ_Y>q+%)1u=F;5}GvL)>@dyzgf_Xh6Gfc;0=e&s2&}H0e0hfvq5AJh3*CBRMRAw8C@)z$JZ_>T`;dv*ux6dmy4ze7m4}>s27BKP z_nJ|y(u%jwpPct%@~P97B`QL^)YLJ>_e4oAYbVQX?7Lo!#N$+LL!F#_xdV=49u~*g zH{XQn(ng}h1XR@J!jkl|q|g)5S3Y`FoGMIuL^kGIVC)~9;!u#kwLwdbja|HXBFEegpO?J@j4bfs!1=#q?5_g&3R5N3IpNAu1K)!aL$Ne6ly~ZqogOx0Ixb<$+PRa;sLaxJ8aT5VHQw$_j{L^|=) zFxK^kl4PYo-@BVS3oR=9IXTN;166S$WCxQ)$Cf%eZs>aEggc_^M%goG+T-o^W>VIz zsGbb}(q0ZL#`pa`H?ulpi;SK3>3I{p5*S=hYOPuOS8vzQ9wGvMvp&8aavlsFLM#U5PTL+zGR8QZ1Q_BNmtgRCetvM7C1!9LbCi`od!3Jy=?9CD%tms`%zp+}p9&*`2dh3F|$zRWQ>^CP@=kLwBdgswzmV)4h zwTK3t?la=izOMaN<=~`?N*$uzY*dMRp+$BZ!~DPygY-P$2ojx_WrXlf>^w27^Jau{ z4b}H?`l>Ps^0volljFXX<7Be)mQYYzA^YB!HSy;#abc&`(~m)xG)$CEfz=o(j0rLD z?lq2a>s3iEDhc+R#yYI)9kJ53!DCBO z+__Tzd8v}J%pS`znml-+b~V%==&Ga;nS7)NbRK7XQ_fk!b~eCb5_C=vgfU|yHz~KR ztMX4~19;N@1Z#`%l6&&wx_T!Nbrs*Q3Ps^Lep0bMhh z2ot-$=jgL!2{6xcsRGtZAwfdEqp8|nZ4gxD{Bdv3nYJhxB=(SY9Bo`X_*L%?_}U1! zLhkohk+trDZyIj(6_;^b9P-BXBvNr39N}+pPXl?b#RwEx3ziMm5<9*_j*{aAcef%7 zjyyz)fhP~|a`qno z2FU7XgPftRjSj7YWqR0$Bb-G2x9@9>;G4ytXKsKfoAS2Vr+?K- zvA12ApcVIh>|dTo9pK?%j18dA8k?;m(Qwxmf4-yx7Q`efN*hid4}Gzr&za9=Vgin> zPj#;nS71ToA=#|Ma=A*((a+L`%|jj%67r2F>jNT-W0hJ)M7 zG(QBiC1ksuzbO87fIbDdtFaGbp++Sh7WnG=*Y5W9Msp*`nGEhBYU+lvC_Qa||3i)B zYM2V5@M$l|@`50nL40PY`#{IJtUy6jbCf=7%<#J0n!fFVfh01k1 zCQzwMf0M-St8buQjq81C#5r7Sv)AU0&uA0PVCwR)e61>aEm~3O8i*f?Kc+Qwu+9%3 z5Ap`~iNzZPRTad|V(8_6Q!t^++{bHFqALe{C#3qGGMKb99diUD33>1CJ7v}H=*zMT zw~2bk<&dA%G{LDz_-NVU!_oBh#2i{ppZ0` z$BQp6zWQAQ3MU_L=i?pZHE@3BY&3{!6m)o;YO{s7@_5wRtwAvOIP#9u%4mBl^BmZ9 zQyjlaMeRYT?96W7_>vCJ)9moGDAx*A_N5<1UTQrP5yf zOLk2i)RU|>%3kiKHtSqC3o~gi)*N~DsRA4BZ1V8JmR>zTwn5H1V)n#hL zTeh=`*OGOkxB2rGv)Nn01W8n$W5B00GAueq>5GosdblA18px7YOX~)4#p6p4kq&OH z)JKlNu=f+K6laW)z#im34B?w{R)j8Srd3_=kPfFY1-=W9y7NBro3R%}BahMEb&yy> zC+|bfV6>Jih3*9TSe}LEt7m0k%{45v5X7og>IMg-fvUV6ex2#?>zGzw(~%a3u!637 zf?_B1?x$_z5jwE;eKvwE7o^azi~f<9L2e{-NNmST2uKDZnIklO+k)N>nG=5{HL#uJ z;fNVJNIc`@duj%UZ)11Fs29x$7(*A++T2{@^xetzR;F#!E0__RxzN#jy zJI@c~=saUA4Zf&X@;=u9lc9Dhi=+9pg2V6S`p=Y?4a`%n4H?D;M8YnfJu=|fBc6-v z$r^|u4d>iy@B^wB@_8s}=d3s`M6?JT^%N$59cfhiYA^wQMXIe`zI+#k z-gS`6P<7A1m~(KJtD$q+iY2I4wRoqoZ#A4F49?4~wH=Zg&*EoY)&yl(&S^7*GZ>ka zq$BciZOYtfq90cfzYk^F_i{^P1^1?ceD`}zY6I}d-u{J!+CZ$DOLWtp{)wH zD|3b5mnl(+5CU4|p7OiNAvV#ra7>ALgctmULd*uZ4b|Z7Ob!eJxxqA;hCK-?I+(4( zpU`9RKYcimRuFngLapCn^bb?r?#h)3eArn*D#`2U8ON|B^h}O~*<4iLNpPOhpjIs8 zHCC*k8m)l$vWPybJ=ki_&bj*)c>j~xJ6I>)7ubHUR~y=x?>TAJZ?wZ(tbyxJH`JO3 z8sT4?NI2Z%)drQ|-yaGi;cnYY(e`D?8v3e6ndM)UvSr+a>*h}G7IaJXH9ug zlPaup^wrPD%NTz_w}_iSVri1o7JSr(+wfIyR37N;-qFDxeWqf4FMAP*wa@lDWQSCr z@ap-`QzhyR;y=g#Kx=kjS=>11xk7d`b?-mCmEQdRSygD%_J5<5m(2z6uB91sg>A`$pFUj?vOLsp1=eZ0Rbin^gm=xyle{bTc zue#600Q}D?qOYv|!LDVTUF)@1!fEd*Ep2-xj*Eg{{e2Wn>8!6izK??FB4fd&-L2}Q zAO`P$ih?{`n1;`U`D-Yf8jFJoa5NMF{FDuetbGlrZI`EdzT6GYrO1UtJRGXs%LZ{}zH-#L~kDCLvgJ{#od4BkVnMh-at*UV87J7@8^!?|W_|ZSZI+UkY$l(?q?&)FOkhA|5VP%tzoX^Dw zjUI+8i)TU^wnn`NWdg$`u>3y%raf8P`&g51h0aYFuiJ1G=g&R5qkOSNUXQWL+WBBa zhb^>uYs}xnA$lHhsWl0DSA~!KWzvUu(nQ~Na2?(!n*Xt@y4JRX*7%7USj_d{@NK|| zcK-@ca<2HF;m8B*!}u3)q`q_etFof^?G0GcYTedw>=0~CO$c{>(jVF}kb-O6Xa!!e zFa=-rqju;_vw5llUEEjWnxPk?zUr0a3Qf5lsMTt7lRm!90t8-bUXj1Io5-K?t#>{C$QE!31snK>{oD7NTs@TsP0fIH zhgOQ?ujXtJ`(ig!;XfeDUcAcuGu%7K&&O@@2UvmPu!0`Xia9(xPH&4_*=(!8GuVGt z8AGW*xT7vpqu0)Vp2`t58dLRuwSWKcR^eDnX~pBNjSKXu=!vP!MSUtGqXmsbYXbRS z@p5bK@!;=Co<#0A0w0C3RdWm7>O-+)+m20<9`|Rn1l9k3-~9f0-{M04Me-Q5m$&mj zWQ^F}$hmnA>P|pI9j|BW_9`gfc*8enUAfvNAKu~aoAG~acYnWcaeAZU^QgbwxBk4# z#D!v|qy0@jNLe@HKCi~m%W+m+SzEWi-?y^=QO=02H0v+9ocF*c4vRY}i-Ys>MCn^~ zf|-53L{on&<-Uz{y2;c}9V9tu*V_bZ4?U!$3i5VzW7U##Tv_8Vem@DnM%3qJ)+gLS zy;ZuPv$t49{yImS8`^EO(&J~7c-HWDH6g4@sJtHjxmakPACuy^06w)cQmd%dQS409 zr?BTpX1H$6jBs!(ZZTyw-iMV`-w{&3`9pHy_Y|Rd4pxiFgfN~Tzgt8l^-_>qtnPdr z9IR5}3G=3((`X%7W5b_Gm&33bpLx}!y8Ly+LwO^46u+CZ`1PKaW>|xrJbUl5BCA() zoV#k}gwzpzyn|DNc429xum<7}Vyox48;#Uwd3b`$w|w&@WjR$$b!*}1{qScD&-Wu5eNPa#Vdip(*PB80mXP=66C=HGu zmQ4K6Kq<-T1$c_@z8X6{Q-B*B8`)7q}XxsH4n0*@NdlEmk4 z^KpoY)?kmtclR~6I_fde#glo;3dKkpGqbGj(aDxvIaqdr6?R&~;1Lt7N^&FeGqD1! zjlP)?PTs(tdKmPsigM=%K`{Q^cZ{vYD>{-9RS7!f3-oW~!<|+Um5hH#+=ogoI}(*V z;Fgn|0OrlmwfxwLPFG#-YwDguiJEY9!!6z;a^=22QP^epbbb~!VfadmgW6!IN~T`V z2!V?^98G5x34v1<0f)QEKJ=OLgu3cEdS}K`!c;kXC znu!qRez=mHEP8CNGF$dYmf51CMpdy?&!L?8WH;ccLrqB&nMSf)14qCv2`Dp#P@2Hr z!V@PRAPDxtQvuD`PB{s31RX9)AOga?*nqUr^yQ-plK&={o&SWL&_Y;#m4#;pK!k11 z&En3_t4JBh@u(5@N@GWb;^b~9#0oG0jGb-U>m-H zHr}P=pEznlRazZVbTG=qUT*X=8))v>gjGmqJc_#!1U>tMa>hwe+#w>&I#Ca~1$gdN zAcwAvGMmRr6SBt&tSmd27DJE`-?pD`cbwME>G(!PDPb6PK4P1_gO!Iu7V*|JQ>lro zc>H3-BRqcaYuOJBwr)>Ov!LHlYrw8Q*K>YTP5QFQ`BJ%v3`^RBiT4$PrcIFJF4G9P zh3{ZLX{{z$Lzzm{AOF};?Z9pEHZ~g@edY{79?+VV950N?sdC9OF|?t^R%uX{%o zg16v>d&iGf_Y7`gdzF#OxLi@_b|>WE~>GwgY@Wvo*eS4;7j z0Vca{U`s_XwzRfsa|7+#>ITrUXyW>ARod$pj!XOW3%FqF$)XccwN8tEB?VhWa0$H8 zT);yvdbh+GO(`qJLqmIJ{q*tO1HBZ~&)_YE4VSPy*wgRy0_lPYt9qaLj2{iPWgq7w zIloxTp2G!3qHi*yWe=Xfblmx3z>|CJQsX=OxvfTTfrej}!+8PT@Jk@b2ixyAyWh7M zc!&3%6Ig8i<<&xO`PbKcioIQ1`WhWyW|`7=@x&WXpA4H8W>k~$r0}e~;!Ja!1N$!Z z*9p=ClfVhB8bM}&%S4Fk7}JMeEt*`rZ{)p}_Zz@aaw)KyoOboAFu$Ds*|04&#J}!}8x=Nb7%>qy=HzN$nJfGsDhbNk=!8pr(qrc36QsjRzX$ zu~`ekDk=Ol3fk#1XS^$pwpzljeF9l0b>PBX@MM?i$aPY9wFk#>#L_XItxRbdNv)Y= zuzECW@535&#bAv6UR^it#H02jUZHo-f~2FB;8Pc**n8JwY#D)PP0ym+mg7b=P^nHQ zHHp_cJ}G0#b+@^?Ag3EL?~mt-!3nJPFV_;B_^N(j?VHA}^A*GOMd9~-*-!AR0EA74 zVpfk)#_hMmo(eTOfetA-CKc!e)>lCc*}P9Fd(|OCTQ4is2v2cme$z%6QNIX_om!!YQGGzE7JP^pa26V5+JL~Hp?|B35z(-jL zsp{;E{%SkB#N|`8ZHsBP%rxPlhB}`PSarbfy3DkOfSzW(&3-)NR{wyMb2kg>PGd`q zU|Pl2mcUgN8V^72*5h~RsK>+}af5}Joqv#@=n@{O&`4Bj)0<+b#}Jhm4r#OgbWJaY&vgkZ!+XzD18X&|jt5crt{deV|B!QL53p^_Ip zhJVjbNl!Z><-7}+7(S;q;qun<%gcEUgL_I5wBWH6&a4_}e@0Zxoga&Huh3*^DLjPm80rudE~M@ksB>P?iB~9n1R*f8Jl<0%!65V$CBAMD(}O zvC&?ShfVp4pAxO(ffD2XZ5YSGB6 zuDdV7-v~|f9d*Ka8>pVc%7AS5t`f4^dQ9VQRu-Ik4VNZgmEV^ByjQ!X$1~( zdf@OC2FGIL4X)F19>FVZ+}%2i#~wo0R_Bf;H{l~hKCuusGzB3ND%jx)S;QOD%w~-+ zEMw+91=X{EG{{v{OAULJtYKzd4t5hM+-Slj!N=8ffpWY~ai$ z3Aqdn?L^#0%MRPnJkj5&jHfQ;VZ{$Tc>OTOoIJhI=DfiH`JKrNM*z%EV5;_w!-X`0&h7Xp-%Qx8?-76S7sJ(N7@% zkSz`&#LgBze?Y^FE0GY*WY#;?x|>T&KgZ(<%O{@c**ebDrMwFg4V;Ve8V|7<7PC8p z)Kp6u-dAJr$8$s6hC+Q*QJ-e_nS#PVcY#R*pB$hiVrs*s zGi@e>|CXZ!85tfExeZobgMa^Q=jUx^TK)_h2dB1d{>90mGQ@7@PyD;#7YziEsM{1BO_&; zv4yqoybyCvd~<}8?Xpsm7zGfsm8hv_7zOq^|7^*G{(s{KuJ2QD0Z^9oZ~Oor!T2Bh zfvW%4en6jBsB5l2&ayMw*|ixDiJ^cnWMTN49Mu5>xtct_rx`fy%{fXZ|Lm0BVgoDV zt!HXzlika?R3U-E>_H&z=lZGZLOpO`ll8#i6j!#3<-j_oW@wCP7AW`^In>5}T+#r> zTv)&?1bMSsh~@MF4Lt#Z#&Lm{%Yaa!6%?}6Tn5o*&$;AGY$h5#P5GkB>+=|671Rd& z{7T=o-3>Z&zyJ>*-rueu-f4v0kIKu1p%~4uY}%9wqwG-WiORJ$%%#5kxI7%FYoLSg zsAcbXSRl2AIR}WaeoO1RD$JILbyXqtC-(FR4mF41= z81B^z@Eb1Y(6-MisKkSjR;&BxX{ z~%!A*jqQ3CSK^vK%PY#gi-1kRNz&Q-9 zK%Wlb+#KuX!E(SKLDeQai}s-(XlGe@@tDhg@pF(FPouXv>-r9p)ncew+-R zj>zc@qT2so`hk_`2RQezsFhN*;3>s%m^z_ih0V}3hj&7rR0?*V@*k=YmGpl|;&%u8 z$`sVPK2ezN55i9hW+})b5qFN`l;<$d!+*#OZpIKCJj9@lpTGDZGe~}bjo7<$LdcxI zg9I3S^^gGVb)gp9H1&z1g!I`A&GncJV0vwJqkqTYT;i<<1tBl`-s1$A!ZCc%uGI=g*uz`L!a5Q?A1<4Xz`u%ysNv+&6X2cIV52RQ?G zV-(b56|G>;K8*t|5hHVTDqP+?NMLaV_hkxC9k3s8Mkt zsA!Bgj)(^1Hb!sU&|t(|Oz+B?&4@;{r$kA#Pw0 z1_VI?8DN0fx=+12-7~n6nET#+@Av!52AiJK=bWng>Z`BLq@iz8{#*jC-5%?(4J_S0 zf98M=_CK}z(&Oif^oZdDod&os3+Q|7-vb2*v|h{)kP5KB8u5*(-_pKNVw^Q(kLKnC z`e8ycjJvhvJO=+ZtB>I!iTH&N?`$3zl|^NSRPd+{#m2z42A*3qNT*#@qVz;c>IXjY zvlQf8%8)<`YJ=6|}unT}T#)n}j-#336=P9i4)6b$#PW zh2OYFd?IX0#`A1M z>c&DW9v6wl{o=VvSa14`D{6(W5kr+b`oBOd8osXxq{(xZd|gL=z>1&6C1Buv_sMQ@ z^uzP$9i;pK55+3y+gQ>8ganHP5yUbAp&|Cyv%P@9c_78qpwATQ7KBZF1J|qPo~*7sJ$aI@ zT~@tyR*S7PS&Yo2Lgei$rQmL_B5#awCE=t2qpE8uf-ch~Ynu%YE@!`~SDUq1(yl*o zP>93Jw2&llZWp>9wK;`}l$gRhs3K5hcrEID@ul|@zp1|q(YqAj{e`nsd7}uUN^vA6 zSBxt}IIvcP1Ly>^2&yn^t-ir^!$~PCLHF^tF3L%K`kg>fy-pKaUF35QP}pyJ&$L2%lhbJa|tVIS!gj;I^nl3%vI+P_7Whke2{_YvCZgl3$mnjDv zl?Y>)Un(I-(a77c9`~SXLE$_+!w%1|;KGjb3%96X-~M)U49ra~GF2P_RijvlJ+9;Co1^l~>MmONI@hdi9|I@! z^5$mZ>J6T`f`cZL=M+DYQ;Vi#*w|OYC~&a9i+`o(g6z}JK%34b#14OUGl8ilvE-lQ ze`$Lx3Ot>Xi0477-NQ7;{Lv}>i@@g|rG z?O}u7v~~O{=(){*)I*q1e&2vVcCg@4oFG@MZ8he%E!=8j1rpJLzd0WZ;`7_CN>GIO z^YMb>81zktcn>^iHHC~7yaH#yq+wra6Z@?I{Lh>fLo8M|+yMGgQ@L)>~mMj!k)=SDXRQA!RUB zkR9^sODeWxLqj~V?jFo9__Mq|V||gw*#-2!qeB;t_JzzkO1n!KKINH%~Mo|KfUMSFZ=Qm7B$P!SPg!>m3fy zB8{Bmh%)eeYg+NQ9?MkInoS!!EoEAVOMVZIrn{bQ6zI2?pHx7;0MGXtmp|;;n##iA z2a^}|ik~TX)zAE31^i-E6cc-VS6ue}FdMv92lC=;DTZry!tS_dO3me`5ai3nWM%*H z59oL3eVEc~*mr?mbkgeiygbU+!9#Ih@AY{iB@?3Ycz1~H4u`R}5PQ6et9hc0y9~1* zk+P;}UY8+%UlZ6Tvq>?lyV1zAa|KyQmmtkV16(k!jDC=FKdK(a*$z#sxdyi&@J=qN zcA9Y?f{MxLFsi}5VN585>cX|pxZMIb3S{;H5a?Y*?$ju*>*XVJ;9i`bZN<;Eq(cpi ziJ+>u-_^=*s3z*Z{9n;OEeKw3B1d3DBea^kW(C)1UM4i%gdc@Jw-rdBIe&TQV_!DA zn*pv{3pm$ux&i-I%gG;}Iz6SOjeQaLe+6D_Q}#6~E;b0)lfCePYZ!zLr5PSdgFH4v zx%LmUVoA#IG(px-xfPdPbB7$pv-Un2b?C@7L(gz$EXHXf`HPR$JaiKcbvy=ajUK`}Tz?I-eYE9duOdz+ zD9`~qj%hP8!iMW>j6(A_DTa-5=~}5+biABkY%pE`oYl2Me&^%eS3ny~T_-~1%p1gx z`>Cd9HyciLBUg!CO@-nd9?DFWX=a7f6G8im#mkt*FQ~Qn9I~Cgy=eX7b)x9K;L|jy z3^!2Ejhi~Yn}&}rA{CYa9;rAqD;xT3v{TL*veGF%DC7-mq9PUbYT)+tCc zq|EuieRJxfH)1J@$5qQRl z&a#LYsporP?c#76&}Z?g+84M5%s-6V3E%ND+^c90-g&UvsL9vM{b9=R_igLVNW>ZM z0|QgZk(mX8%#M8Hq504wV{E-oarth+Ip}_M2u0_o$K7MvjP6L^ogXnT3APoG*5QeY zA7D0p{&9E^{+VhPqyFHPv%qUuD4doYLH}FG0mxh;mL+xCt`MEUUC}Qll(EqS?S-B* z3n;fXvwGUogt8Nx&u$KEyTfOs>v7-T2sy5CSDH9Ywzh0V^oPl0+_B$a_vY=h z&=-6^!wJ$#vahGAss-z}{N2$DlUj4#Zr*5OEC( zn_`HJ+ywJW(Fx^Nd%b4wjf;uhelSN|h2nm3r$D$1J30#-?hGA<-I7$hEP_V}gi(c) zftn+3LBum|y_Rgd3@4>1axw?{m%{gB(U}~Uzahvw{?CGZRRLj}B(*($BTTKm7gE*g z=mdC7wNJUvP*-)aTaWoO_|_?*=mNCfbZB+HbK>N-1S1lXe~0MKq0okzZXa-~mRE-e z3OhTPhGxx<^L2LegKTC)So0QWk=yU^ndIm#E;`De0p z>`qusWw!WoE*rKdk&8#Kv7laXm^wU!+v(l+a(-<0U_q%E`ff4E@}ln@$Wm_;oz7}- zEY0V>0@Yzbb3o7aJ!8y&#pwU-Fh6kU0ns2HaSafbiI;dzK?s&@t)YlvrzTS1VTOiY z?kcYwRHN2w`th-W59Nb?((lXO?H}i2G13{%EP|UgjvI*~p_mMi;%L`b<0u+oCEXyo zk*HMYmIJEo=`4z(rI*2|zc%~Ty!PgsGx753-iNX8NMjXY(UZh3|WR3yNV+Ca7W##gxu^GOKu2*`xIM z%|WrkkNEB~Mi47BK`nPZ+H zp^PgQLa$Rr68gvfCgv;5_e_b!zb>~=9}l5bkUmt&S4A=0Rsu(B53N9B}w40|R-^)EcM7(A~| z$w$$PzDjefJp{Zx;l24^y<++Od$UL%#Ug$8mm>W;1Wh9fkK`5{?DvC#Z2>_MQB69v z6r5eh1A9L)XiGN4A;qJQC@l{{U!$5?lYUo*R2iJJ-0NjRqzc{sCSFk6t#TyB$gWrB!Tjza-V>~J5t24{-{t(|KeEADHS)A8EA(64H+QE9hi zMzKC+AJzKmV`8#@O0871JWmg6 zKLq`_qwvc}(zsBNwS=XL$t=Tm#>lP-s5c`Aut{m_V2nmzK>&iN{KAs#Ijg2{jWD5J z+Tj?uE~eUjjo@U4&3UTF+>f(fJn+l^Ji31azm&o!CNdv0_={l3m;X| zD3;=*!K{S*Gcc(M&eAr@NPwVU=-EpPr`h(s3ta?xUo@PE95D48ijH9vIwEFBPp~}b z9M$sUd$Z8#$mVy&Y|*5_Pt$9h7yT>aC%fSF_=OmFlBEPoC-tgVD5wjG=hGx$3GF^S z_%G*~Wb!pWc^K?HFxZ>41NjkHpxnHDSlP$~#nn;+Hx-6FP4kx1igZv{C_0rG)amqS z9wqJil*sL>NX6C%P-7Um26}vQi@4r+8wUH-a90FRJh$^Igkj_>r!mSD8XZmMqmv6k zEWkX!c*}J?d9R9y>CGI-%Hk#-fY>UMFU+++zImd}w)qv@Il*%_Ey*SA5MsUMvLUWn z?mID%`b^P`7CohkcE`b0bO&x`O%6SJhIZA(V_43A9yUuk|C5W*#iiSd z;6Xk$h<(wTFkUI~UVrz*=N=Vn>IqHelNxasRuDfnF%WWtA zK%d`VL_`iEp5XWHSVx9lK>vhg{qKZ{S^peplPYHYsG@bv3w>6YRam&UM_i9Na8ER` z+Tl&dMgJY>E=HMXM$t(j%lXGfMWL8n_|%Z!dF^Ku3uf3(+ zq&;^H;y7_Yn5>2~?3m@HBd$oy|9RT~C9is(_De*C&>bQlouS?9mA+$r9(rUqGa@{e zybPjj<&04-vyt9;6n9sLKq-w@*o5ol<9M&(a}cTX%vZ}7#p2fkN82w5Hksrb!VrBGSqM3a>$`El zlJ*y1+P_Oo`-fW6{>LQirL=zzO6^$MUx~by%fSl^##++;R59&8D5d=q&6+cf<{g7X z21jrvGkHteKSfOY8{%s-V3uUz`j(1Z-$)A>*bKi|z`zc7qcel8y7i!~Nn3pE3bam~ z+CNM3ju8OVMP}8V)wFU-_sC1UN0Pae? zv4Wno?JOu<%LRm#><&a>hpB8G<_5{VmNdNKHjYmEFnEt1E`aAuoSgM7Y~6#A2UISy zao3U|`2Abxku6|BlVcMROTF++2->t3Es#~V;r`4&90_K*0=s7>M0*v0Yr0wUX3!u; z+yy!=Oz(^-9eWFwZR)r|BM_4RHAB#}lB*)=%q_R3_=FepV82qp(fnP8zy*&-5jnw0 zj1y#>L!F#p`lEXineoPC;csySx&H=7Fan*Il~I)tI{LuKYG$#FxcIqaYRtse}ENq zN09IeE9izueepW}^zm|7qN`qX{>o1ZTO{Q^dgnjJ5~MQA|8JB6ZW2owK|{!eFQ!Fz zvvIlwx|@jYM2yRQYu8%~ePPO&&d`O0#hmiztl;e2S6G71N5)Thl_lui=TCBlGGdg{ z0iz6=k{5D?E`OaXv_e+!^raiEa>KhpYk{FOkrWKFkb-q43bt=Z6tqM$S&%>OGj!ff z7*SUp;1yOdE>C2taqk>}$8LznTeSRNB?ycOR)WA|M;)x-NPbc+<%j&h(9M(3WH8Hk zl@>IxTn8cZpV5MxKkP)J??|5(HY>1(A~I+rolqCPqdakiZsF3UsjYHbiFPUG*@$kw z#mqK}v+@JGd1dF<_={AiLD`bsH^Serc;pR##577AC#F#~cX)-Jtsd(Hr?q1|R!o|< zWm;*>-mr7Lk3wH*HeGPAe+- zs>|{UlTGw^aVB^b--on(jlO{NT?`tJ?`cLSp<}q78_TB!vhc4bm>3XUL(HzRiKTCi zh!UcaG9V8Fu4H|q#H1ZtdA2d48zI4ep#1lQr5D;sCC(?a?)MuyT)?B5hTCEdrC5kk z*!C@jb&UJLpSMshR;U>8_QVewVJTuqBYbZL!*v9NygAFW_u9T34U|M z^2Qxr*#of;^8)_Yp=vt!_Saex@1_bfE1KjuA?wdYf+bfN9ab@^w;a{(oR`t|UMT6{ zgFXQ9Vm5O6wLpMRybHTV)DYLMIk1=oDri%waLnYz*lFg*a^SzEitJ)^2GYk=7RE?;663DrM!icPV-6lUs8J^*FgDedgPWaS z7#&hZW=6p+q#jFPOC ztMa*E`LFww`}Qq}u!+nRG73o-jBX-@;SXQDZ2DL`!=f*y3zlR+jOjnqE^uT|^ znNQE>7GP1AgIded4grfle5#Ot#DiBw%pBk z$&*L3Rc|#~bufv1!m^pQ-~RVV0!&V)>LS3LEtDKm2zZYwr*+8%_= z5PlaEE_!l{UVmZwmQvm(mi1L{)`qMJt z1uF@lN8T@-na~YDb@b(Hd7*_{1C|KQ+9P3?e5H4xG3|rH8KxYkm!~$43vWlfQ!T`=^5#;NKAN8KV7L0e?Ttm&idfCUJw>?iW4xC^Hm!_g0tPP>Mw~ zc^1LXx6M)T^8f`uH1M`M5(PioN1)(mIqx+OZZ8I|*&e-fS0?*GVlUtMdo#B|uXfaP zNCuv_kbxDXG>MGD>UFrFRKo4?P;{t>AIY$al`M2P8i|}7Y9B;$uq}Rbv7ot0<~@m- z9A2Nl{fNvqtA67%JOyXO|NU=p^K72}Pszawx}lNCy*Yasx2A80XQ+}ovkjYhlX+PP z2C#4e6YYzrO0r)2!zcBzWK#-1N(F=rJBz;Pz(NVXeZWx7cqj z7|daM7;IVH@LKL~;qiKhaswp64XOjGvpQk9 zrk{9?0~6&y7OIi)$EEC6EbJ5I0mDRj05WrZMR|ZrIaRHF4hF>O zV0c=TC}0_LvdNh6gpl8qYb|NO09t941GzCRK{q6w8lXanjY4Iq5sH(S_k@=}uMws& z;&l%qS1jkhObc$DrulwR>FG;tV={fuE?ZLi=yTO9)#MHVepXs=a>ux(QAie`p5cYW zUz{2X&r*sGBJ2GBAuotH^?#KY4AIL2d@3y!gXyedU~8!u`~mC5q=4liY{d&L6@zTC zV$fqd)+Z2b?*y~f!Q*5}VS}O9jbs}-Oy&XJfdv)~pzGX9ISU=-1;fn17iq8z9rlLK`Z{80|nJP@;h$%%@b+AM&P!z>HvY~~z0uaYAr%qob~ zv%X%AR5AG-H9=a^X{AX%hKUm&V2YqRAY}na9%C^dON9;^SW;k?x%ghTDc%BwU#KwH5osptQ08O$r>;#J?j98Wd?u*ZGt-*#?4t0r?Rj`aWp<2iXCH_% zz)e_IY=PC%-@#AZx-zUF-LFuIoEp}2kotdwNhz#hF;irfD=A*f@tP6ZE2(P30aV+~ z`q8F*i^aScX({e;i`woH*VU@F6G1TIK86M!u>88>CWO2u5U}`f?@qn(ltkgEYw z1H?w**A4&1tA>v`z{`e@@;=vZY0r=@o!ACo+FsWXoip?9c*w`kG;O#Sj1+asOfh(y zDVq`hW5o>5!g ze6#3G#7ZEC2LPce=!QiKco-_gN){9UTI+052#vQ&0!&h@wB-J^(Y_Cp2b{Gnz-pUl zThfrRI#-u%A(POYt(i5X)hYkQLDJ|%VuzZlT7ke88tE;{e^=E}2vpu64Vlu2l_DPt z#LmDb4M%_@6LSC-<0asauYeqGeXMfh{dZn+NEj^59-=@%$^s<6h5`X>IC)VHDEdCB zqJ|$~kppg_`bbd@IH!)`;o%C7ECqNy-ZK#ew>JE?>#Cta;&WdtlA7n!s6na*2HCrR zDiE*$7EvHDOQacI&;-5wKpZO$BPE|XYt#fyaDfk8nvWF@_$Px<7UUZp)9*{VVA$t0 zdg|I%-Y(GdY9Ff3h}p1DR$`94GZMWf7`>UoHb$)W2^i1Abyj0V*w=-+qzv3quqpZV2+s5fu*eX>`F@ zI+E>D{tw8@4(f6@2fp)ZE^>Zt8Rw@hZ@)ZWtzNKWKPvp0KH#B6AF$*}%lxP~M0`|s zmpDFwN4OI=7s?}O?t}nNK=D({#X1djy!? zS`q`si^`(PCBSr+fj=5I&&6o+03IJh8Gxh!7G(frIUX3Jn$Zb95i|d8C<=-z3`IgT zQL?JKApTQp{r{vz3lNIn8Y2~>`d#pQb%u>Cwec5yf<+Yc=eC7`@}*#3N9r#I#0te~ zkvL?>!P7Mi1I?K(c1~rBnLo4*E;U0S1U}Ybquw_gd|oQlSmEB zI685VWY#!MX!n-QKq-frPrKNM=((=^+3bLVi{M-h7MMAL{UCl#j`cIBd3V zSl*k6Wv-33-rU@rO2WlxvY#!&<9zmx{~kVQ;}SpdCX6|=_#ImW8>6jCz`tGmUjT_#kpEHFGSb7(hewfV>~-bctt9rX z9tHc`k%s3P?l&KidkKcbLt6aBeMtj+hiQPt@Sev{s=rzOC!sz<>hTe8JY-Gr5xFz@ zFR3DVX4%ZrN3Fes6`0gXH2>7~i$~LB3%(CE%g2M~la{Fp-05N`Pc?Ds{JgwZ%3Xq{ z)U$Ue{3z-GTe2=6l(PMKpvV2os(V6_6g(|mKDCOUo5*=G+_>;Zjd!6lXC`X_t zI;=ATQ25JW9`!Aj8|AGxRLkvVM2qRoafw#7;)}uxiK(zZj=8N=%ztcY@o~bYTuX}& z{^$2I+C7*2XV*&py)1>j<#dv>wXiq;D~#M&*z?hILjAbQfTxB#HIYPsK6*zlSRp_KvKE1Gu@RlwQk;#2AWyQQGrWZAy>fxKb@D zX+@MCGynphGG(pjg;K|-4vDqkzL`s-IX2PAmf`uaB33jW29M8Q9U zc(u^J4v`=0RLNk63o6m+x@j2l46gcjF(%AKI*%)@0hFuhTa~#O3% zS>we^(B8))_ZKO6N$!6(5~3SairM*rW`ispJZ-VLZK6^0tB_GHq=o58KZz!K zV0PXhaDy?Hkg)f%#PYBA%jM(#GB7^@ykZ)>H_$`1atM<1L_xjP?t*mv| z++1w*>3n3nF7DNYe&%ZlJ)(7;!tNndiacGLGBPihXCbQ1GwAaZ=(azF_t;Qz=d&JQ zQO76RF29VLZ?m6Oi|@Hc*r3H@W1nNKhDS>01MULW8eiq`Hi{hHq_H+EWyH>(S4^HY z_PsI4TSFw8Jd^M|$MrgkgvV-GsLPftPU`V_*|IR-N5E$dWpy_8{S|dTkV$x6rSO_c zjeR29Sctj&&wj`dG9ZAG#}{G!S_qKfz7^J^h2e?QFM0zBBkan=}BX+5KuFt7q#xtdMx9;uVJ^Is`=KA@gr&!ni} zDHVkQFLd&XuG8vYYaNv+RaOjtzqYl{Xld;m@w~Oq>EA>3m>SiE>T{sxRaoEFQqL2+ za3ryR=~I;7^DHx0C_jBb7d(KbRhVgF^$LlFh0remmKF#Ku}oZ}sG*57LFT~F0yg+0 zSsHx&Uu^LC8jvl-cK&cwzBAvM3K`Mz>D^afibpm0<4CLNIB3AqG6BBt*$#mDk9uxN&jFu*|s2D~F-Dd{zPhm;!nr(6%L^FB^@*m}!yu|fO z!&48Df-X$N^E?_4d1CNpqrp>vdkr}aIPH6?VXB~c0xo~`hl(8OXkV>nccqv~MC}Tcuod_nhF|}SPr|JldLb!UI~B6di?|3@x_0Jc_+~zdd^(Ir+p4?%*W|cF9Yu3Ck!^EdHly7 zMDk&UZ{S|7_lXj&e=}P=E`y)N%ZXxe5Vm|?Nmiz$f&Z7FzYIUR@RQyjns)gyJWH)9 zoOzy}d$6cx-@PDxx}m*}CT@bjCa0k5yPPto5@t8_Goguq&$|%CnmCbDidkhyEH0~> ze=rB`h8kq`AW+v6)S%XzHe3jTxgFMr3C<0b+mK@t?!;7+_C0SA@1&=XyiJkB#Ct&% z?@{q7=|URkV>eae9eB?^Up^!XNGI?$v^NfH3wtW$LOsLoiqO1yye7}p#D!F-+rb@0 z@Ioi>0Zo37KYXN{8gAcR;gv|aMDMPNy{UUXG1+gAsK6B+eEP=@*A3iYs>L(K&Qa%x zd@iL(U7>D|&Jz;zy#&q%JzInc<_XZ;IuvgBz3e`iR8=S<___St1n79844<|aR6U>_ z4vK6z5i^_L(8c;Qmo=!&i{IMYmu5LX1~b-n>+I`w-L_sn;5-GN<)m1dVj=<1{T)PP zqHI5>23G1WC>CaPpWb+{o`jp!O$ANY8|6J3R{17Rp^3gGrp<7&HR5>`+aNFV8G6bu zpy=CWRNsj_w9EpO;RLR)n8&M(jf2@t(E`o9c97}36`qRkCU>WiWZk|5$b{Ly)k`3A zcrUF@dLQ~U6ZG>wS==n2-N4yo^rhllF2lK0hLQnZLYw^0=o*ul5x4_~8=<`_4p06Fh++!<7zvNxO zZddn&cypBFtPJ0y?PE^%O6XNH?H|)R#Q5DintAlVn!M0kr=aLJ5(c|OLc~7{bdR}4 zImoSFiyTFhWn3jxotA-IN1d-gM|VMu?aFFp&||D}RA9?N*|a&qjX>8wm#fd~QxyW} zQ?Jwc%k^d4+b1eD#?Cifwp78+at|va=tvF+@rk3T;<^lDeYKpH3>11eC6KXIL{(m6 zAk(uKE{cW=56ZaG*uYhn=MS{o8wI!1^3|qY7olg!6=w}j!1U~>*hOU@nrEBkRV~5$ zCMMl+g;B~mJQr)!-yuFZF!K?4uO7G_xee~f_!aV+L8m7JjFWL7IfLc&(xK~qiq{FB{!FfX%g6t>SeeHl#o{m!f+MSMA183QJ1emtC zQ{}IkvJay*UNQ9sl#l_H9Fn193{}GnRVG=u!&J9?0AZPK*|&`b-7VxMG;`en6BwuD z5F>nz&A#o=U#+fIs5@&p&lwmQ+ksb(`Qp4OsK=(E4RHGRg9l^^=HeTxf=huGt*btu z#8aAoq9;%fMr?6D%F~UZVBPHbzD!EBdWuPCQmSwD0Dp{T1}_%y_@H!!C`u0>JZpG zv#pF!=RK&N3tQg~)XnRqwGXs}DJU#@r=7;;i$ZJ{oBtb7{$Yh=oUrBcb zKBkjUBxjI*2m!|lPhn59jkxskEVJ`|)QIZXnxyGzW2|DLuSqmJBeeS_pRCu*FJPEK zxeJDn2RZmP5Q_RHHc$A_tAc~wDF}4O-J1jNqC_kADDE=3#_YU_SJh88sPl!;e`3Au z6viL%o*6KbP4X=`e+6(5leI>?UU~(>uw0YNS^lw05mhs0KmBkHMBjO16n{3eX{ z`>6V&Q&3Pym&A%{`Nd1$_{aH_dYPh@Haj}Y@_ydes)SHOhF;!TO9GbVRLQTTDJQBS zVaeDoMO>4dPT(F3R}o|mOU8Ys)(Q^Td*}z(EkE$8?PDNqQ;)b0mQrdup0s^#TF=|3e2s52n95@;CuHRE> zVn=#W&yd-CS|x2P5Z5ypda?Gg3f7=<)SyK>NvolasppIlZn66v_lWoj^^-TbN>MUx4VwZdF$y?`Q^*c+}0X& zMDQ*(tH9L1S(si<-D{U>riqR;mEc0@Nyfw{J)e zNE(#8Lz-F9SmVPJ`8!#iCiR%!sZ;sJz_JarT&;)*sLtTJHFt}@PELlZ=JQ75_T&J= z=KS6_PF|WT@4w#hr8xuKU@LRL@Z|DS5~S7~V58T$EfjVkh)$0gJto5C%;hpuxJ9}Sn)Id5cec7Kc zd(H1K%UELD>FkkK({pMrI90ZA0ORY!4?vqj7Y97t rz!~DAQc>~Robeh)+#D$R1{oL5L9Fx1uM3wxKu$w zqP6Y_Dk>n$h#MkHvRy_YmSBB9`f8q>S(jTD zq!pW1l;ka}j!#~sE?DUDyRO_qt~-PLRle)wz@!|}+A#uG%bH}cwNo;r9 zbFzI}#RBuC%c?V()l=zN9!Y-2s;WCB>oQ_vH@GWulVmmdE7Sa&d1uoZKQeQvz|sLK z2G{a$j}sg!nv;>TWb2l_X+-2N58}>~2h0~;ae*;bbXu3^yaP&Mo^4Ex#*c4WOG`^u z-drLS7fOPM>PkH~&9ibR#@>SDa_smGNB(;lL%%RLkK zy&|jeRH-UPvvQeLf^C{W5ps2js4?@ZcDS55BL^ z9Dls`f|!!!X-9h{*vYak9P6DhGAZl%)@y0cmfN`YPDqw1mv7mkI=pUt>avjG@fTi} zdnxWM|CEZAcuwhkrZoS=vH1EdrSfHE%hsgfp0-J8;1}jxn$;F?`DS!)TY>GNbyN6b zHkw|nTj!oQ?j2d(R+~k=YsFzXK37T>M7&g&dz>#m6*>{Q>fv23(UicZs22?7fuVlQqikEqUhf8 zq)S!{!d|Wm&QyOtCkloJEn6ZE%T+gQy`B&y3(&3}@4CTM=;9|X2|0Et(NuYD@b|KH zlb_O`2t_Yj>2i+@tLkhm+*;=tvs7MBW?oA4kWI^IPuF_kaw$p`H7hf<@;C{-iAa6A z)y7`1Y}rQl(kyA3yd@yezCHb-raC)iQM^aY%bRhY9)*gFF=>RbD5#BjR?D1SbM>Y@ z6_=k}SVNeH<*&0XN$`*gUwV)9m{*!Li_@km}wcu z1+h4X$;z_1z1scuCC8`>T~w(3HY=k zaGQLtul%b?_05UuibIhKo}2LcFr@=2xBs;2Sx|)Ea7Vwmou}d&CQAIjjv>9zteITD zNfa6IljW(nP}T5?z$aya@9qm|5eLarhbZ^VmR*mN${n3XEQ$4ME;uDEIOP3gUV80h z(HaM4|LWDHb44%IlSMBcT=KXZ$dfy+Yjo`HP4#RqoJxj%M=-B^B(eMjBxdsV%<212$bhUdL~NC1kwyAQO3xs6c61oxno*UT)J|d zNTC`YxT;{az4V#k$L!2?r~N1VhgfA<@~iCUGDW&eG{0n}C^fqvEix|6`RlXl!?W_$ zrrNFnB84B{Z&gLjB>A&)CsFyxny1qF5&5TciB&hQKl6RIWgPiMb91`7srFQD?IE8R ziu(N8-}a>i3Uh}qYOT5yo;-YFa@^0=aW0o^Ba@y@Z=4fuwYkRWzN5X@lyvpERQ0bz zRp|lAsS~coI6oP(G`n_5y0WSGRBiDgpEAYGn%c4;?^Mr+@2kFc@qb=1uch`*Oysc` z=ZBj_qmyGIcm+2q>I0Zs-&FX<7YX#jBGp zCdUL9*SIcq8nN`qp>Y*Ktz|*q#Vu*S`O^ImIqLV){E^FKpIyz3^Nl%f$9J?7?zH5q z>T7C$@pNplZ(b%our{jZS_JpY&z3^*OI!2CJLkNYW{S70I^`(+X0m)rK;x88!lxuI z+cb*W6N@SmX+Uyg%t-0}(w9$CDc5^An8UnT+Pk@+Br<+Y_$){~(Sd*ebBhTG1 z5!#hm^PaoOd${%rp{un*4>7q|wphOr5(n zBd0O5t?-wCmie;aqiI@MIb_28u}30+Zr|by*TW^M_W4ojGFMf;JS|?DR4z|Ti`!KF zEJv=@%wK;$#Nj6VZWU1?4Y(TI?&ja(sB;i}6H>0N9iF*Wl|g)Rw?Z5@;8}7a{cU2h zpba7f5D$_q8ON7?e@GCiv!h(cn3Lxd+#~1vEUJCEMkQ7IUSI4;M~@rg5u&2$mxaoP z0C~WSML0x0d3;Xo{9w90zx04gO^X@Z#Bp&tTMu6wTa`p|UZTof84N|?l9wCm${T%| zY|o77e7HfkO&%JfO)L-gA}KA8X>(h%bZ!H)gwdU)j)RYCA-VY1au0QNi@S9R9AY%r zvk4I;NNgkVaxx5~Lgki>^5C4bO>^552}N3Bx#Pu5Z7FTuQ!pu68w|lq^QE~tZgs)6 zicNJ+nWHFmi&ac^z(V0(Ir$_rM}|E4Ib2F^CL(q^_Zjj@wRsB^wD&cIjQ|!kZ?AT_$)1vJ|8EF(|T0|zidhlrY$oP z_I>oMdA-xSo8Wr(`s0N9Wo?X=gE~VJQk57ZDm*1JSWS~!oBW%pGiTEq3KejA%4iuVMVoCdeRgxEH=SV}B3Dz#p7>FXr>s2$pn3ew z6bD@xtjRO=ZCjgKax-be^~_@%%AHh?V_!0=Q})ecuQEJxk}P4$=55R@VQQ^L5aR7o zbmMB;&6vb3c4+}}MwNV1*j~I4k|JU@inq^h(n+MLH9CHlSR<*qn8ZG+VjMnd&^!na zd>J9IOlSO$z8_D7S}Mt)TNQiHFMBq)N(6cD)iP=l$dNOUIlz8GiC3#?J@i#&++~DFW6)C-|<}Nx<>AVH}zKMk+{DVqjKD2zC z&~F~hc3{@)Z%KUR2ddwck{kFlnaLFHRGLevn($S$a}iOZkVIsYV{z2v1tupBQrj6x z3*KKOCXX~RRs|gc&Bc>Mu$Xs0ncTDJUY9k(#^la9%Sqm)Zs-#pIEFMPkX>JW3RNOXC&89Sja@ z>Al-@b|LZPlacQ17>j7hkmh!;L?#_fH(g+CS2L&T`OQDFlj3}Y96cQ5MM5?2my?W@ z&%@8Zr`;5M4fi8?z-7E!y?mwqf2mB^KvOTYWV`;Vbx+jsgSq|c$rqSsQf`Wc7sy|f!ZB9Had2r0w-`Sb zlULJwZDW!(Xd4QpvmYb4)gCE@>nBe#IrpKZS-{#5o_DjE+NKk;i-t45QD^QA(srx3 zL+lxDw`if1xPfQX#lbTzAtF7ePp1nV;hutwgQvT8Y0kPre*z4KD(x=BqdLZOQ%V_( z0k7MrwlbLMdCl1X#(bs&7_3Y1Q4kX$2ZIT5_vyI81u1!p?y$6Sg}`u*M?HD87zlqR zx27f{n6s!tH8oNKIDu23+I|u2WS~v~nU@F}Y$rS+%G=?&R_H7f>9PyIh0QYZnY7~< zM%b=)2C8>&rE?AW{)kHaXLKAsRtrQF(n4XekRcsL%7l*~DiU5mGCLFZ;aM}kq!j>Ng##yH_PaV!P!wnI9vqSE1waJW?oi~u%IPP-pW`})%xj+B>! z;EO41LzTpDORHBW_FD$&6F!zjR&Jw7S%Tu-M57iMsFRL~$)BPj0&}w9nF6ipbqvDticPAcG2<48j;i!Ere}_7w zx=>(!P=}ngC_UkqD5Jp&!F$?j`0aTf5nA*s)2?nbj?6n3-FScH(dL+P>gxTywrQkC ztkt*?XP(a9b3S$9Bg>D}g0dwp(ukS~Tf19q)5+s=dMhF;RYz77@A(L1h%)9`nO_l` z@ge3@MIO=BcfCF1g1-noBIFblB9rC5rP(ENPp>EKI--g6bWde?S!IJgUckAJCqchYzin@q)TXXx=fbt!x-ju@ zrOxTW)Oq_&=O{Dx9@)3kih3R%#Y9}>6k1&x(2j_F& zd(-Bx9ka9Zm>?L^`Mo!E9P=EnbDurtpziDoxUF-0sw8tJofiM}5qzbgymh=4Vpx5b zvyG2vK{RQ$&x5!y^B~|qFW~b^hT8a%+W9y5f#K~uMGIz*)KII+K;HkLZe$&N4yIjI zu*EWmJjhtJk`|XC!f>>d_MS&u`OZhF%adfpswW}1|I-U=T)g2(vJTq!IVmWb`d<9vz*yP3%=Iy%|4g$6vQM5>zt`p3Qv8+UXw9JAMkBFi%Wk> z$4h|EPr%6-?z2YN_XWwW@oVuYS)F|Vytc+cuvd!^8{e0`FwQ9 zr7v5ACt%iEoY#a^Z4*0Z${PfR1z{2g?rS5}`)I*63vM2lK=>`1EXNang`N_8V*ORW z0&@-7_bJS(bn{09LJCBOnO_o3v6)d zn}`?WN_>bRUonT;`3}(K_FSlT((o7W=MJR#X060#99|FhX_xB{oW~t#jP^L8hKzjx z-bWbIuG46WnVu-G8iVtVgVyk~{gc$mscxDg_K|dvv{DcUJ3=3e(LC$Oq0&pWLMeF;?XZ>DruX8T z>!SyPQE%LO1>L@LGs=#_k>Vm^||5gDY0*B4az&Q$xM-Rv9jOhvzcpCNl;4 zQ4fXbmFm~7-w|e;)Vv)rlzya@YGUB4bM3hCJf!HpO5Y7np{D5F#bg`lzsn9mA$K7y zHB_2kD`djmLlq*%id_Sb*7^8oZKQpHYd#@@Z*dh%pk|WS1YAFMz1d%ebQ6%CB13W&M1!=;?@h9K1RK9 z;V`DLcKJ^WHxQrd`p#k@Er_eyi};Fl4DNZ7SerUpsWXgpP%wH19<@)gKp|2P-@keu zZZf%FW-3Hu*dejclY9)H=K|WmtBLBW;GbTFhH~n}UknA8UBl}%ffKmwoD*P-#zMU>QgpZ;jj3%px(#~eJ#qW)%{(0HxgE}Wq zHSvK??G;p@AU{BKwCIdrtp3}R_Q0%VHY`HzKXizV_811zmATNpN=DwuO9j&`U0j;3 z2*vLccGFEd@>t5H_i1Ab4V2vKDiYG{`AT)F3mI%pK1ghsfx?I z`_%l#>_DjAH&ROM*~UzlU>f)V4)|h1$EDO?QY(CQ3Qiu{Z(%H1su_%UWjXN7LN#Zb zJF+UGfo8nlw5Mu*gCb!7mt!!=Hf1HU`6d>_jlhs!-i0s`Y34-poM3uS?zC+? zWjC)_9c5FzBm=5=y2wy<`0}H{MPIf=s)*Q4o!7bf8@je6v@`gx;)uBQ`$+v+C+d3p9ki zkfr8#P9DZ_O#TC3Oa7PhGS}&GfgUpAl--6=b>!!h>d8GX$Tiat<}s#{*Cr}O??v26 zk6;(;Y58g^SHYc~T7JPo#8L=3s>p43Fn!>YR3F^;o&NedQ(T7Gdc1QNmNOqbwN6SL z^c8~;q71Uw%W(6X0>)M6pqc&(!Xmmketr<%W1ME{VJkPbCI{f~uYRCv#*}@ywGZK= z`4F|o06tJ1nq9`5?oA)h*|UNLlf=w-)&(*AcEWZv>!4+W1EXyB8EwXNiijH>tfxpx zqU%S8*162`W{9zNuI5|!HZ=>&)#Omv;=F_w-6+zmyRn5|?v&*>co``VF3?!65kOKo z#A)o!5=r;mP^D9okCI4>wi-zdPn)@o_I2@LcvYt{C>&j&72`20+I89A8p;@sTxG>N zz{4_ML8z`V6*ukV)GP6EEO?SSmxYKzXY&1xALU)En0-Ons@pXDQP#u{@59kRnOfQ|Oz-lUKO>qV z8c-_v=s>Mbo(Mn3$;p*3E;G`i+T4}z&Lh2iL<-U(Xl&6sd!bO^<$lOk>fq?quA@vD z@eqGTL0gq?_64duF7e{MB9}R1wlQ+Qub-9{z>ut(AoX;c|X_ zFcQRq?93sZI3m|SSXsAX>=kQhw193R^6vPQ>|Vo}T`J@Gn-2n6mbWp}f5u%Ct>E<7 zr!eexKo=MhE)s?CLSm?-CjewmExDz&SMsxZr=Hhz`^?u$#j*l*{( z*9}o~(`OR!^&**Yv*Mn&w0MBlny&r$1kMo!^V}U^*qs-aF54$6@UTsd`66i7jr7{y z7zfl>Q}?PRD$+sArl?afjV;uL;?e+DD|2ftF+*KUN7{9Df}3^YfZEWtn^bbRB3;=G zLw1M)%Qr{C9NOv%Tp^jjMXQjFg^rHR|Fpv7+HWhEPAKwY^%|{@7k+vK+l(VqTUIS&)V3k zG}o3j!nhJiQ{2vzX*x;6z5xLvA5dFNMPx2gi4dj{bYcOF4*-QT$s|%tRwh(s1EcUG zpglb8-3t1S1f*63Q?=<66)nir$|RsO4FqwTKvgXa8LWGm>pnScxUQzzFG=XTQyz4u@#IMaqXsZr^l$^4nUbv|ZRreNYw=TXO2wQ8`ocGc&Dn3?0^Rl%zi{ z`KE5D`Jzp*-e-O8*{)|Nwk^}c`^6~~A*>UN zAqZVifi8G6kV$SOQkkARdM2`lF_w15a9{aCU{_v4od$JrHh7s#k+ah)A{PT(W;y+UydoSA#On#9|GOfjNLAr3@C$&Z_*Tzt#KVGCDKeVLjoE(HFh*fp-45>;e#MYOH1ah;jMP+41{8p`!!U^P z%7(~0ur@<|cvHhjGzT%5Wz2MA_DXW8>)ljfv2Zy33z8dA)S-1DQx=uy$@Vs_-htk% zgiXxGuW#v$$5Vda8@-SGQdV>An7C*}<>0+)tDiD-liQ%{m19r%guHn9UetYR#>XVW zLr$cERhd-uz_g>$@wTxss_;sk)y9O2ihDkv9THdu>EsSta%FqQ>gb7hQDuW~#`&m- z?dx|&!trW#B1$+bROCGqDJVRxmnMWIV8Hev=}0;37@zECOjdNc_F)dJTDIZyTCH|M zt)x*7gPedDmOAl=oNcC$P<&AdBB`0}3dyP^kiC3k`6MKOh}`ZTf&QUl@LV(i6(3Q< zMbs8{kA;z6#IvV&h%M|vgB9du@cKFq!mBm`xoYOUjft>v%4G_?IO(mDAz4VrBG;^H z(&Lg;Lzpyz%y2n;h)bIsz!U*S19NVm9w+xrVg!gfmv5B6!=xLpIsFL~@?MfZ&shU@ zu8le*F0$d%=)!h>EKD1p?7q?=YBN3}3#O1``O5Ccy_2$-!vf=>?@%#0AGHMhO~&yu zRv|(1>ui>-;|U$B$sp?JKxa6G$e4w$YAXZIe2)p2>S-ef2B+zP!33$~MkY&#dg$Q? zDjv)$#RDnOWd-4LMu4CmF(|8FIfozwL!eWsv0}-h;adGs@UTQS)6F1&^n3+$-*ivP z6G3MqIqA@2m}+qjWsy5W5@2eIib(1C>-!w88I(=--O4!KU4Jk)`s z5eddym%$E1pY4smLe{;|;UBOf3-V+R&T&UK=?DWl?h2N6L14@d4JDT&7oevIwp*M7 zF*%AD%vas%yM*-kbp0X{X<_7n9fO5n%0%XmMI|loQnQ~h%F^h#32IgE^x#A3ht)ci zU?!$Ydu&GuhW~-_L@9XF)G9qRLr%x3pRCk5?iBELFp)^3*rRIU7Hld&rLE}&EUad> z$u-X_9IK%{|L(vz_-!P2&=2SYqB=kfeF`}`UZ|>?l)iu!^1SwIP22rWiT7KU#L$;r#&H4#{JnWL02h99`{xqon2ji5-1f$YmQc$Bd9HIi*&6wTU6VO2Pl! zTqzhURVZZno-N9`kCu=W!6Z4rAY&xM>7I;NvQ(CK;BMi16A>(_^KFEw%XM26zo_AR z=d($7#5-?eb%H%wOm4<+6V0O(n)*U!&A72DG3~z^mU>`7&g{U#G8u_5bc)00bq7x-V z2`@(2i^-#8%ZP0yI;+TKme15)Ls79vsW=s5o)2dj@fDj7hbX*w#bnSozz?;l{;hUs zw>34Z71X7D$9a;UNvTRpyq|djOsix!ob8`V%zOlJY%eeKqxP7xWX;R6U7t7qqNYl^ zpD-13Sre--zrpqIoaM!fv#LcFe{QOXj%{TRxI`kS#1&c z<44e4Lj+7mV46Cy`03-1t1tD(VAx7N$K-$!d|x4nVuBR^~piQLi( zis1ONO~1Sue#vp6vTubDFJ21s@>3h=fQ9A zC=_ciI$j)@b^dCo*BD}wp6R#9-#rco2E8Tg;UsL%YrTjiJvOykneE9mq@GTykEvC` zzika}c?#kQ>K>R}+`y|B>Nxt`jKJMcy}%22>Gd6$ASGAnW&T6${6SLkwL`2ha)zy+ zy3UYL-ySGY-9c3sZ2~XhfC05rQF>FNWkaMv>->|V)I@xp31R(PfO!lZ-bOq`k??Y-VAtLu z>fC}+Dcq9o(Ld^Kz!<>q%(&C^bpj5(Ek{#zq9gm!ys?~DunMOh&E;TaqVqtkks+>p zU7JKR__I#dU|EeT7joFE!0?-b--O)-X$Hwkj0#ezR9 zYdiBw1!OBblfmt_zM{*a?w}?%He#5-wADE{tP2cP5}BQdxRqd+4+q{IOEC)4TK~@{ zY?zAVgvS}5L#?h99kc;j*7bXWII%*R%vQ@Rxr^Jw#>M(z zi?}dSA$oxvi5a^b`l-aC-`hMS zw#$XiAp6=(8fFXaM?aHTtT7m>TJS2EsK}1vG*qX}sPyRsi&t1pE#w&0YhGm0pyM?f zo&PuYbolE%O_*>G@OTyE4I=tOk~v97Ud76(OT-BVXEuStI;3I#MQXpobzBR8ej>5V z^JNRxe;f<2im3lc=fhlZ`+^HR93IEGhdJ|)AB771)<&N$-)<&@ZP@BGE^9z6In#je zBiS=Mq5cyXSjZ(wgz*xrXR=oL$B$C>+u6R%QrY@}Z0*Xd9)~N}xUzM*4r*a{=|3E` z_8xHAMc$B%e}-q% zwfxn07^}nq(`c+BE+u81(=JrV&zR4qkaFwY?6He}lB#iLzU`PVzJg%ZaAAdASTFPt zgS)==(HFm6bH*NSC@1zpr(SHL#0&b-*r&zTfpA)b3#gc7-WFgNc-&>ky*T4r z9F)IUqUl^m>aSSmE8ycj@-D^fI~sy)Lr=l6(2FLE z^ZVyiTubipXTk>?RFc1Umst2hikcYD!`o3CM$KYMaMTF*ITUqX4av< z{X68!iiw7zuK~G!{Pw*3Um({v!m2rH6<28=$ojiMEvoJi=5SKDkbvo9FIF86=%q%zNW}#+y}G*dI9R)Lb$xbz z%uS}Wv!MY$zb>w_kwL?E>ul)4qF*P}!)k;f388lTx-^Bn3)LI8ru!yQRi8fpfzo0% zci3N12%_D;1FoH``mca12WjkHK^g;G?!@SN{I8!9X5=dprs5FooOw(Vt7G?mYjRug zFVbkH4M#5jIp<)1#4cK}Y;33oduGxYu9=3*(Nm<7IitB4#OC5n%-cZL9lbvAN4)bI z3VIFt{5>EEvzhuTz;;?Hb~1F@#lHitNR}i9JIz$G)v>w1b+`wLseiQ7tYH>^z9*^> ze_^l~g8!usUqiqn#;N43cwz0tm8@s{9qTv;*1!B;kdD1vtA`#IpGq9eF_&zXuIN8f zYNCTUvJ3ng!g}pv2iQvZJFvCjeU6hOG0JA!$@H{`?f?5;|IrSR7wg&LKi`R6vYl{X z$lKj~+`m&DviW+4!vtFMW`@&gD4)PRRswjtA6P}Rx&QB`vX<06Mmt5J>>nLr!{2d$ zjLN|*#QQsptR%*80St#j=Xavs*FFZbG$>y$=D(dl^(-*@2m0HQ=l|WJ?SU0~;QAxB zW&Ne#m16ws|7pjQmx5AXEh$J4FoQ=tg$J`-9>G*^+(U&M+_*gnA12##dlKXf)MWn9 zq>0LWu#hwvSx?%YA0b@4h97AnmK@Ey0_HpKYlKA+bqzO)RQ;Ect_v~7d?_Ps7vY9w zkBFQog?~o$aj$yvN3Y)b3W`=r(wneP>)Tba+O;!dAz*Ou-X`7TY{qNg7;(t=mIV;h z=5HIBHq)0;(atW5F%YHD7l&+O%qD8SZH7{9S#y1;mC0q%@Ee7GCt&%8&! z!FRJ~Gl>`HKf*l_Si@NDpQR>D+~Tc=nw*;v2itp7j@W-euZPV@*1n)Os-l%WWg%&?uD==juu$#*`{#WJ05OuEeNwvrN72_LzId%V=G*fU=2h`39L7<&!5F4 zR;%TGQb|Qps%W)5+3q|NO4nNlRfNdK3Mav65gr z7(L7Gwl2+9JiZ^3Xwype`%=bJk^U^}aIxd=8prlkCvN0UbU5WhnWq9>nv z;sQ6GPoeKQ=Ecld@*3n~!LOCv(*F>-8**{3HPp=mQfd~cP+pCLy;(Kgx-GxATOm0Q zX>u|p{W(USkVQ|Tl%5Y=w|~doWeJ2?Bye|-^xdY3*tk=z+K_;1y9Sq6Lw;Ym#%a38u6^#_@*i`EyMQ|lKhF%a7ysk{OEr`h^F#Pb zJ2=}Ve!wOMC$VG3*+*9rX3sQ!_0Xsl{Ghf(YZm)k!Rk=<3~()-w- z`X##ABHV9}FQRyQ11zf)q z-b{Gbc-@5qQgWUkPj+wq-JupiI^oe!>=s6=nzN0$BQ@HqCYrz}0m4qe*&%b8vs+?n zsAwfojg^*LQfgyp3qM(BUJWt7jR!Nm2R&5~SNGs0mO$a&QE+ix%la+vJDTnu2ol<- zmT!~|*iB91tybz#Nu0_~;Ub1#z-&wDw{y-rx3eL2YzdYHiiq;vEfjq%Zhqk!V~dqQ z*x*{SmSnBw9q)>T2npodV1ol|P;nwE_{#d|M=Hv*E+Q7Y=_btut%?*>4#vGdBNRcv z``nF|OJJjt-YJ$0xUq_6ZBq`nv4-0Kzo3^qMo6kJ$DrA$$SMRS<7n3QztK_+k&txz zF=_zK6l=QpYrDaFs9eS>TuK~nrL3QxT;21_d+0={*dlwsKgn&)b~Y-E(^9KUX?_nh zmTlR!R>%5D*^^AG$tVT3`xD=n{$yvAv0D+@h?{Sw_Z3rx_@j&}NJ2YoW5nq2mzKT5 z`V)2pOj}H*K(1Ebs=>Jj!_#{xYcDDaq1$7O1jo^^wB({H>}p*;%w_uo&cjwSA2g}i z@P}50{W6cBXwGcr1I9|K_whKS#<|#Tj}C?doCV_HwQMhd?%GpNvE88!8B3a`oaoD) z%mymM?Y@QIaC`||Kw4i1AMP*aH$n@RLpxl&0eW?QX5BrR*{pYWEaVond3Cxw7iIp= z-5;oh4jA!rd-k~X6OL~l_({OqKSx1X=&qi#l9l|NY;+puu#HS*Ogo3y)M{RCrjVB| zK{1@#$5?e;OIM)`Xb5Wf!0Yko&hepf-O4A+xnSZtw4I8>KBjnI%Y-grnLT3& zV}5m@F^0r3YTN-fx%E!a!amv4*M}GLHcYuz^JrgqL7!nGO*2N0fW8ogc2Lx(cFE`# z9iG&Pk~06Na-Hy<%Zs_tggXvig=_T9O*9*->BQUqn8-Y{Tq*Z&YRI%DW2L#HS3DGE z@6=M`s?}8Ak8q>k7<{2dPW=eaQaI40ru?ui)>wl6x{wJ=X0}d{Vh=Pw%9rNhKBvcf z9iZ9D2*0}pV<)l2Oo3gC&Z|DcKO^O*Xk%>kv6+Xvymn~ODMe)a&=c0!G$JTal6_lY zv*km$wlPU(p2T=KprN35&-s?AJ_0LsOqV8|U-<(CUt%;urxqUGh0QaS?d<$z+imYoGUh*=M7}P< z2VxIFqOPSSK8LK)ZU%i;&ky+VA-UW*x>m<;7hucj?frue4f^`Ty6z9i&Fr@xrc$a| z9ho)RmVCSi*Qob$4pZFx&;#A>+YRcrvn!vgBfX3YV*w>z+>1GF89TUsGOD5l>xT_= z;t<@25V1bm8-edHXGzctvVq&T;m z+_=X9DZc?Qb3a#_YAFZk)>Ua${w0=AIOjWp&c}fSgY(6a@!;B`%DUVwBTrK|%%2njm-+VCHZ`pWvqD967+~!V>#oUdy zjw2nWp+Y2(JEuSeA4H!V;(ll4q``}Au5DbCbaL#jtrIrC7dEl)VR9!6Xm$pf`X(Ia zp5pcJ@EqT|LK(t?KXVen6boY#$tXsS@9Egag1;KI*9H5dpnpHns!zz_{Tm@58_~e- zS7_jo0S)*Y(7-KS_(l#5?0{-V^yh8Z)z!6yPj{W#t`i;JhtcYYD5S{bxd9Bcb6}u^ z&EzZ?_<{-Jz(6Zt$4e+9+_*|DEFO!&pcvv$V|^3-U}p`nPHpu}Ei5VfR1XFm;1Rap zi7>N_gSweVVE#n)^_xE(H~wM|-rIN65MPNA6SEaMS><~t?7@^Ku-#_`+GtFFb+Xl# z-u*R9)Yzo>O0B@`n<8LnNt@U#fwD=h(UN_S$w*-QV!TGBGdCveQaT|*ya_$AVUOKE z$p&k3XgbvNV9~0ateY7}qL`1`b0y9fuK!iYWfa8d-q=;a4mXbU1oP?Gm50#~9Sof{ zTuY5`V?J0od2>UT^HJw?mbj6Y;jLJex0{Jt*0n`~EV1DP7z<%wx|_m0|A7L(F+ap_ zBUf;)Kf1!G^+OSH4I;)KCCyqiepuUCPK#aRuqQAB0dqbX6V(NU7S;?>7{vVs4&VT| zSNXZxi-QE5y>sy31xB@Tw1lRq_z6MS)VXCzm*3D$IDcXR9A|8Z;yL7yC9(gV+n)njFSK<-TpHBX znS8u=0%YD}r79VMmcC-7KnBpFcWypBh8bC>4PlhU2!Y(n&SFtV&eyp#X;z%tPrRL7 zBn(}M1-URQISDcqO_e=oS->#OiYa5lt505^E(^Ei|L(IUd%BbLLgS9ub#Ci;>0-`p~@4bcPFPE>**@3Fk)TC4tRI1+_Hch@$53m>QAW zZCZe6-^yezEgF%lY`{(W-G6T*@dXWX>`%IL3%6hQkA_E=sA2gCX>E-r$CIa8Ta z0wXgar2e)E@tTyBjj#ayE8lKQjjF04&mF^0CGPJ2u!Zknx+V`!Lbd@D(FGZ={hpx(*RCpX52xR$@+S%@^F7ZN6V$u8t7V!(**_I!c0S=)bA=Z4qIv8Dpo8_%Qqj6w@GElCUYDxJPPM|7ZY8U* z$JV-dV4to}-rdh0!V-Z`JBWZjRv;0;O*1SJaLuI855#Cs3p`OM*e~X20-No1Uaw{Q zf!L;Cr)S)lOjE#+GesmvjX1YzBe&nWL}22VoQ5F zxCnr;5b@NA|9}|>R#~{UpF9UKES!7I@2#+J`p5g0JTS zdO(9*U`D|oxBv%wST4{pJeCU}9C78~$RJu^@=SvwNCg?KMqJh$)RS1RQtB=>J!2Ooxf-Laa5~iSYGM^ z%m61LO-O3UQCk({;9KkTzTPqAnEL;a?VYeBBO(j)b97!&7i)t2Kc1ylAm|fMj)R`l zzDEtt$8j>MRiQU%es>`RiWD%u2{E8aEwNeV<%Gal0-|&S_ea3wL>WDb#rIWE*!2{) zqJ4h<{V*rkI?>#v%6B`aTX!4QYZ3JHQ}g1CC)C0tsMZi>8uI3W8gg;+LMCDnBppGh z@JGjw`-|h#|4YYrxs1#gUvY!C)2?;Ac;?DGQ|~h50&iq97-qkyA-sFw_`?{XJ;paS zNsMffoT<6ffA$Nl;6|R$9Tn9#_5#pa>Sba-Y=`&BMYcOZi~vAxEBSUCyg}meY6Dfs}7jYo-+{ALgnQ04k?g}Gq{@=13mt@5R^w~%Hpz$+W4zF zc`PSYX(W9+&?y^|xrEJbm*PAW&4qij2mf`4#~K(X^>Oh)FZFT0{~Np6(#5VL4Y6ox zJL_w>=6aMpOhdJehi(d9)!BRQX_-eoWi_FyE^W%mm+4C24 zk0F5(y@DYMv?!UgKIfz0``i=G41SGkaL-c)Tmbvy$XIY62T1d+Q_@cu#bb12aXHO% zd5%fswpE1YYTO+Ep5LOFhG<4cVvV!4(~&G~!g-w{kX=HG=yPS|fv6Yr&| ziQdbvb2Dks5;}MV#(EB0{3jhno~!}s%JsFYnB?3dpUm`wr*;0bQ$RLM1V30@zz+G; zxZ}zzU^)$0*L9W+$R(|1WHIh!{Uf$_aAW$hS`y|e zd;v?GLFgM}5c(!_LSOJvwJ9r?-B$3Yn4*GRttKp3b~GM%9;8E=S?CC3L>Xo8bv{f%w z=VJ|sU>Sdoin4fmP%TEZS;<&ojp3F;g8ofL(SkN1EW#ar95ule(qd!Yc0H((qg_`q zi6=41_a5tH^wW^6g3CQQd#Z*_9gB;78D?#L3iwE76<5>|?g%LHoUC@q`?ziA z4zK8l7x^DOu=pQ4yaV*s<4mOXxIOQWbbjnx>AXSf>qtOsMzvr8Hja=Z-v~hy9rH+h z6-@iuDp|U^gap z>J5a+jgUfpPDk|dV65DTMIW3*fMdWpznm>u*WTG#g6WjXW`!A+Lqzo)x087x zxznP>1;7f%SV3?a3o{(RCPs>Yd^&_EmSo`h7XzcXcb#uNDIXb$6}1DIxpgqN7000quozI)B_)Y%}D2Trr&fq zrog5q8#cb-lyQQeaT5J3_sGAyb@J0 zd`A{r^P749a+hBh8@T*s)DE!T*U9Ch!kVek?TqOz{)G+qhHPJk2~Ndw`v)@ic410^ z{3&vvvmtDXy1}KWIufOSmO`UHp%Tk^%2hDt_GEIdf(RRT6zQFT)$iC%eeu;j_G5&> z#D?r$zcM&pw%41LMgGL(eLCQ!p2@!n(W6IpFnRR%*O~kPtmSp+i=FJf4MnsLt_x9=Cb{- z)R_9*0Na|eQ$Kl?E7@u4j7JhK9*zAAkJp3fx*#p z<)Qn+i~C&S{~oj^_vA3%@nN5R(8Bn;P?9fmg1*Wqxyxlyg%W2W89qdC;6_N z{sA*FuG8N+`)7Y~cJn_wJ4cECsNco@JN>Rlo4#_kN-YUlEV{5ZzDwULAbcM=jvk8g zVzHQqJ1sp5khvfx%l}bl-pS<46#wY#u^mhvVLSVVInIKfiYVWYB@ntiwe1vQO_r&=M3q7X6ZKggcu>J+<_F$Jom+x)ns!fr|YlQ>%OuYYH*ZH%iGI+$n zVXfo?L~)hFVyHEG`ag6JEX`68<2$wcH~G90o2C_BdKUU7&EB6G@`^B{k+VI(2uc_^ z!w42E&IIGE&-xg33gh|#Bbfc~lRV;Qgv}?I(^ynkibaKiko@c4lK5g+4KBU*HM{)V z9KW5dHgl@Nf8q2`PzKhE_EoTWI#%#I^iRF_vJ=%F$ynk0bXZ*$0~)5;I5j)Qr5ftq z4v?h)FY7bAXM^{%L7CIo^#vVd8k%6Rvcp16`0`yFqkBhGtyz=*=;q1%T{i~){`k?+ zlhqfeWsK~=_G-4O_dmz>JMe}0{}r@va zELChGEM|p%!Tdvlix;2TPrcht<@xK`aQ`@H!Y?#@5p>BysJ~N9PSRFa&Fnj2kQpDO z3CqEXduikUAj#)O-Q3kZ7;=v+iu>mzk1yTP>-L>~j~-Wrb^DFYtayi_{2e6qWx!TI zky)4U!2|ak>*)qZ`H}l@S(6N>1$|UxZ`!Mu`q7c}ZZAIm4{XO52SWd_P4_2h1Z>F; z54jq~@a+E=c|H(r@fcakC92a{#P1NsI&IWY#Al0Qx!Br-F9^kmVo>a_Vco4my5qp} zU!^-ENXBw63%xnX{=Z1{Z}KU&ItU(rDAaMliDew6C5kC{FsstIOAVq`>Lk`k3?wDnIrwxL!~E-z?jiVjC0!6It2r z^-}}%7k&)|DYcAXV-M`pe)C%#vva1&J5bc;*Rf^iYmEG;KHyd)-o1^Cv+=^Q946_M zPC6tA4!=-6umf}Ylv2gr#u8Oo+nEk#5RtC|{PL z3~yu1SUh{Z2DP525a2sjLKb`8kj3QOST=4O|J&V$a-T&aTd>kf`kur3MhBU{{ugjR zofdd)V_&Yuu_d;!hp$cf_nDrnY_lh`ag&iBP~gjtc=}d7eN6&e^|;oMSFL(nGUilo z!vIs-PazTs=8%XO%W)X#u}hHdD79f>gTS|VM}&5eCAL!L!OZ8Pir1z}_^c78UoP02 z^3Jd3EcH&T#ws1hLpnsfPueju*lfPzxv-bh^!2-ndvCD4cJI-?T?M^{33}H%cIc1~ z{QgCuP6msSy8a6l4@+`-6;Dl;1XAT+`iyb5NtAxlYGnKVM=ymJx8EFSq5aVOMdJ)N z-yIn}wxzt+!)a9c^@A5LXE+mPE~7uo9s9Y%uW5Ar2}Q8E&HO|2s|VfFtqFe~86KI; zx8sRsWHXXa1du$Ih6&yvvHO9E8cq+((UQ2!Y(3iLM~@)et{dYbFnXXRav(AuCRk8j zJ#^&nAvYzBjSs~}HA>Pvu%7H53)(Zc;n~Eg#juu%q{)8IA;?Vu?t%B)1o@0$c07FC zM62c;h54oA`w|$}rysnJU+gU>*Ft3GDJJUHW1*KPL&Vz&#D3S;Z~sX{Hq^n#J2Voz z8YU{S%YWMNUFVje`0q>*1d{3Bn9PXS(W0T8jpgK5CmeZPuqVLY6H=>41wR_p?ClxFX@0Wf;sQoFBk_q1>5Qk6fzg^J4te248 z+pV&uFc<6y+-MSZ+qKVSuQR!Wu+R5P=7|JdV}4R@q2>XyoIQUQFlACz+r!%sRZ8QC4DZ(b#3 z3$tje9lAuX21XPOd*^|vE~=@tv975--QH6*xwcFAQ`%fgHVZ<7b$H`Oa+U>CgM+K% z1}FJ~aoORoD^d$;xeMYH9)k_Wa$=SRU9BG;jka?4B3^#Ig8ETT?VR$d@wWSoc;5&Z z`~WogaT2z|7}i&C09NaV(?ch;1})ZkTH(lk%?_i>ZaBcB;E2oR1)Fr{P1=oG|G>aI z?^V8sE2HyT1J1 z-Be_OPCh;#MLeqy&Rko`dtk-QA9@2$6#jZ&=M{JiWOtBEcfYbWCUa1XY{dN$H|8|N zOtNjh`PG%L#`LLhoX?DIq0l?xBP&x~xJL-AC)C9I*-E1O@?>r%&;M~4ZOuX(zzYxl z{fI7k=cMt9dvO{; zS1DwkZ=$yK-mfH&fg1=+)P&@zjw*@!f6aY)TohLpE`n=ZFsOrjyMe)sX^k4(+h7bT z5{$%P5>31B+Hs-+QMsDY5M00|2}X>qqk^a-8jYwRMU+j^pn`%yXap2lo2F@ctE%(P zz12Ky z4c!jaiviv9=M;&NUwWp&Ba60K$l)N~|H-czrq?sVvE0+16-PfRkws`>h^U{}1BM(R zu@^w&JkX$ST1a#|?t{hTy#+j)H4wLyS7FS&22M0b9=EFNN$xoGckC77h$0VL;j-fx;ss!H07h-maSzV`fh;``hUqT-0<-^QzA@c=!@6B&CUFd*M zIxa*^Eh3&5VZ>DMS==Fl3redZf?nRqKq|a3#40Vx)qd&hdZ|TFDnxe15DVrj)g<;l z_zpA@w_A{l>9J%4Tg9cE+l+L4_4fkIt!7SjL)@n4b{S=KwszbnYs5&=*(C!^X;pC2 ztjX4MD~>1OIz&Y-^Bhj+?Vo^rQ{>bq@5=aiBT7-RQzk&Q7X zjYx(gvZPgUBhjivTD1~p&1+EZhZPs0@1ckr4mdD59awXARUG3>2ln}6fwdHyR(#dOGw4p%l|y2FOKh%I_{N| zC1^gv97=EaES!Bz`kNJXT%X}!lqL{U!ay-Wy1<-$XoFIEO<9uKbEoo#ctX$RfV3Jg zNvK9$gB^X1;I`R)*sLK#Pq=^O9__x?xBI>eOQ$V%3HW>Am|>z1%L4V@wGUoj3uQO( zO|gEWU+OBs&oOV{LcnxsODl9z7hvWJ<`> zIIa*TiGj0)m`!{HW?{t&MS&_Xu+y@Qh_|hs@TvcTU#=nMuDvRuALO3JUw-1%swtvo zdDeaL1Um5t+LAyiDQHmoii+*6B(T3vRzSolM7Q=+9}IH`*}bT^%7ltx<0c4-HuVfM zqvpcv_Z&JI6asl?Dp=DV!!m6|ZrH))gQtE9##N<)oHC8HQh1nIQf-MI*<|V}QPa$p z19resnge3Ynxw;^rmH0QDr^&mbf2sxsb?yi*AS1OWxVnY2Q_p{Em3>P`j*7?QiyWb zFnQvB;Zj-+5u64E zgI^Z;wS5MeRD}NCwNNSB=z%UlY#ASJT0!tzal|2-w<_9f;$tKZpah30h4|u7)e}Ve z8Nw;TiM`qMVnAvR$blJf1`hu=%eR6PGdG0D@p{3W`hqQ zUm76I26jdzr9aFvewCOF2GDF^CkQkf)WCkT=9z3zMKiB08#I!F@mZLl4o&jSZFBQ@ z*rBl4uvr~K-B0c7xG&}I!9YJd;ldwKGfv(FL-1lke~2l*Aog!k^%utB?DLHo@kcgn zIwHMtd{hSU`P#{!TU1yNr%9eht6lyb?4No7X`(>f_NKwrg%D(2rLUd2x(a@%Gm!i{ zwsi1>l(TdYV}ykBm||!?@W+MNjN&Q}85X~*!|D>ElOd)$##&u-YJFRb$-py|yCc2~ z;N_n>%@@>QVG(UC>(!)gt_bksGoC^`6q7Oy?dicqhUir?{bDdv{18a_6jBIKl zCj73H5Z+=50mBptab?s1XdUSg4E?pFp&qj7vQ?R6a)U$)5>}QXDTqf>AmUHPy+2y? zsNZEJE_JjTuE@)InmvNi;_^&G62R9oYeVwFQWnMrIb{H;Uh=;=W>v5>i;PvjQde}kTc-NqKh$-D+CKEyrJE2`^6-LQ9^-V z)VNGjw0BsG#nT8ZZ_E)x>k(U?A^#ZR_@t{!@T7l(PaF&I!5X+RC7xcsVtijXLF+wU zu4n9qT^R#x(?4zb4}SpiRx!7XO<#{_v+@^kOZn!*swU=CmZ`85sZ~pr(F#93+3@5d z$a}xFBHMG`=LIQwDd)pBbVzsq)YIdwu+*OuVy=@3VkB08hX23f+)3cD(1YxTY+-F+ zKvHuIwS>I)rDC#^=o;7LM-lI>3byqE%H=)thn$C{4KNqk>?SRzy3WV_DxNTjfoD{@ z=i)})WfLziA!q{LYVL_$l%$890| zXh`303SsNK+!i+6uYm(L+`kC@dn4`}IXmvprMRyYSScR_sfgueH^_dA`c4KCjxbSn z3YS3$Y{8;`xoDy(Ud!zd!9sthz0fZ z21zFNu;xZ6zn{$L+mi?aY&UC$8%Q!~#Z@0@7m*cpbuBlq=VxD2+;auD zymY+SQP|eBSebOjLf#uvJ9Q6KXTX3#5y<2-d7D^(xu+g>(zs=1vIW;ul}%?rvhk$v zkd2MwV&VcGk3)Q6T#Iht4oh+eJ{e!p!ZA5qy1SvU>#GBZ7$KS!3YAK=*Kz+`nmZfJ6Fy%3p}f;dx}uifYPT#1kP z^RG($zGm68CH{s`ctrw@bKtF+20pW`6#gZ8|0|{UP%SUv958^tu_}|AAIpQo5YZC< z*;ydff^Oui9S1hQUI}B{q9};JyoTR(R`yiodj8aE<5oSaoQ+%r(cuHL@MpB&zK(CC?zxXi2SM4dJ=9@kvHEuciRFS&>5K@lcR=Z=Qc$u)xqz(IhWX8F zx7!kjU0lN)B562J$&56rmVlpyEc;i?9rFYdDO(bHHq5o-o);T`3-eEY3-e89>9qcS zn6q(07d=5Zrqw?N5qbklzsdRs}O~W`lZ?EhdRP!yS`De>` zq=dALm+}qGPE3F-!-KGlf2*;KFSnKP_y5Yu_m)8W&Dzfrnrr$23^EH-n*Fhb`sPZBq6UWq^Fo8n(`>=fTc`1paQ54_6?Qq@%Sw6 zgY^(PmQo*tcJ?2gd2N3!*LFR)o%5~w-jSd7w3hdER6hk)9XA`D_y+S}4?&9@#MAqIYrT7>s`b>X};hkZYqbI*Q6k7{+ zm}gUFQ{V5?YNEOyc!ocK$o5g^%cIU*Tse37-29ZJuz4NgqB=&U6c-ivmvH?c)1tg$ zX?b8>D$@e|;TpsaKLwK<5>lD6DRnFCqZkyy^jAK2=SXbZ6es6szmMk?Rk8-7b=2WU zivHi=n>M^b+3GtToW8Fp40$kmbYu@JiCHgbFflMS|2i)pOVxZNMg0vnF~3U8wKeV9 zVbf0P_Sow7xvXxVb5N?=uM2V|t=miCiw2mm6ZAW-K~(jKd@{^R4$;mE68f!tT)ueX z8ibxnmBjo8Wj-9P#F?RJ{U?Mx4;!D~Yvc1D^k;lN+19kvajUUu2SXu0&{nrAj9fyV zYV#eda@F#5)X7)^5E>J}1K2|ofVD9J45kS{P8emEV*l)8#e0IE2XX|j`P%ehD5*+S zy;V&W>`DpfC)$9%inBBVeHCT=;|rQER9ZF`IxgU`5Ba76(1YSY`ram_Z?_bZRq zDt?pg*;guPPj&p&xJsvZMGuTwEH6YvayW^nYasra*w6SHrHdzIbQ!HYBl-BIm8MKR zcLT7Ui1~_9>qydIGdVkEku`21$j{k&^SfXTM!gvZtwngosJ|gDvy#QRj?J905UKx)|yrfj|&Yt1_{b#C=QBlMe}jw{pn5jjw& zix|JO3qjZk;J{1tanf?w%A#RQ1-X= zm@%Y@36ncsosXQ|6F$PGeHBE1XXN@(Ccj-wmzqk*uPs4k8z7aT6G z6_n<_`VPTzZ(ftS?KBx+Xi~=n%L{r*_^_c3J%PO>rI60BYE?0`e}T$3w&YNSA7$&z zABOV%)Ha|wz{fdOQhdK5_1P&}Wm>Zu*D;mhO}1dt5Q)j#2F9*R6V}THrXB*L%3%_y zUj0`cIXnTDY>f@W8aXB)%>g~t4M*)n-LMAq9=B{LaUiIWg*Olf2jO3Ug^>Qll`pRT2`#J>b7;ChT!oyAAtT zV&Fl0roqI<@)FIIO|((MVtdNcaJ)5r8N$F)mzS_KL_NrE5FCql{c`iJeI_)D}M&C z^S9Nawh8chn*e{F3Gf|*z{e3I|33(E#mp*CiOJ6^wsqx2dsqJB8kj`8@`9}^ADY8} zoCYf&*<5PJf25b;56yMF2yVR}a?9}1O9i{2L0(Mm8I|vGP;krUz+p+iCd{3s3jLea zFmyNE8#HuRnFibNb|824@)oE7+y)#6otm;M|rw<@`WgjiG2@1^a06 zEVJME_P{hZTc7@X=bd4Z)Op9%Sx;EojG-8fJD?frEVgX2;L;)F`~Rab$J&53+bC4V zNJ*&03!QCB&=pVl0>H(^f^BUY{q}f|IQpJFiO$JmDoB8IZ&3tp8nQ#1yPzSGvTC5GOMyBT*eAhT0Eath^ zwmw@|@S%M+KRvg>+vc+S9MZQ5@4j{!I;F2&ei4oq?VzT*b(@&W?$UQytNq9tZ6_6e z*l6o**v=vJWJ;m@G?bq<=@IczA`3(DeLqqjtZ`9%zxP~>qpyfzBaA@kZ6IB*k!78u zf^K#!itGx_v|RlI$Z7v!?~@tiA}z|a-0B!B5hng#m@jj8;1G~G_!6+Bq{YD=L6f7y z9z>n&kE(K{%|eS-ImoW4gND|jW*H*8dKj$xLdzG$$iqP@ar z4K{s|a6e_R84BqyF!t3?Gj{5x-QHJxT~eri6=k#hkP#eKX!i1ChAQcl_INHDYGBYE z38}XVaWg1|uZLIPMv*HD;w~#b?f>PEsnp>YV>j8=*-UmnFq54lhAS2`(P?nU4b4H> zyb6EigemYS&D~A4HQGk4eE`#H(@dDtFDI)yMvzx#Wg?rq&)l^4)G_F$-Ps%k_%-~a z-x}&PhvV_bJ%K z2*RF*WL>i;e1h| z!og5?%li7jep-B`lV8_7bV-2>i?TRQvefpN0ZT5t8-m?Ln|FS|J?5Q%7ugE+&NIRM zY43a;dgp&(-uWk(crm!6`atD*7?1?B+Pr}3k0}F}yz~D(s&D%vRF9L}J+)`bo@ej4 zh2mNEK9uS3&&Y7LqFj*EikE{c80f!9q82juN?5u08ml^Rp(4vh0Av{Xlma)?Gt47- zFzVN=q27DT&J2Rii~k1FsZZ`U1WBkwTk4pfm^q!c)EPY6d~)nFig4Y3M`_2Eq+>oO z27E77+W)IC_Z2;g3>jq_~wo+0idKsy|zbpMafv?z5wi>*qPHv$*BXHft69+-Qk<^L_M9S1Uy^#>Ho zMB`8xb|laOGVMl@8Bxe)b5q@YXXcyZXO>*vNk}G2-xh>&{`%l;C zsqH26%w8cEO>)gKPf+trsm&yJnVRH6ciBvGRRqO=e~2+sS3QrHy6WFZUG-*#l1pU| zgvul0E2Ao!j!QKYSIl~}z#1k-zR{#kR6i!xaGQCig$S#x>7uU6M@jlH56x2Qp)r-4 zh-o#aSwAL8U#rU|Jy$NfDvK7Kb@hCVY%lI$5G%Ejs*QdjHINBw!pP2TWzg}f6kgtY z6bc~;*6LH|4OzSD1g>K__Iipnp247QS9$d#O8{B~cNw{%i8pGdIDUG~ER)xEn{Lod z6k>Xf5`FFx6vU6g`aMQ+$P&SaHmy)-<_lc1;#wzzrt>lASDFsIlk0>_7yVHfpW6%+g`QDXP@OnvC*k3c?k^Ypu&E`&V#RSJ$xLuwVmDk!g(wTRB!aY_mE1{@gQIG3gKOk13oBe zlHN4P1T~#7_ewC}G5+9Y!TcQoUIrO@-*A>Y^U7#E`5yYYl;_4-xqTMZ;#jJ}l31fg znr?S3cxk!!!FIJRg`@AM0) zitI^bS!G~mZhLVg?JqQ~Lo=;gA2kcpKIaXC7^hOU?BCIO?AzZ

A#SnN|Zm`Xh+^0(P+FfWr?@%+|%wM}+4yJrXQq1yiNU#TIdxX*- z{-?L|3$z{$??>XUA3v|Pyz6zCfZ7FJK)3|VihG1bsUBR0&6qBvW2&z*$*0@awr?Sg zJKN!9(Ch#lI{`rufai&{uSt3ugG{TKOxLY+tpL!8aW9^ykYIzpENVZv28oAHi6tlv z+}A0Oi}P4KMkPY)yCe}_qcJi9HS#3ePEBrV8B=ig7;~VhZMm|^7#R6 zOvhZZs`D2$WTNRBrn(WsKBVsnM z=?Oui?C4xRR8c zOT&CfFi>F#OP_Gf0*<7w;!7P_$IGX#$-Myu^Z7Cl=z?cg9;`Uk6|V6p>txY$J5CS0 zX)<;I+n+Tmb-P94yBR;g`8_ zwCrPFCkyGU z2JCgWO7{ENx z;YTq&r~(F|_ju6u!6!c)pFXr`&wg}aT`W-O#hA4fFj4foa`*1^z%iREPr%rgTW94r zRO{YZd^dD(h}CsfCrgbVe1Br?_7fK_UAi>+YUjBoz4Fr10Q@7IuJ)gidg9uvdmbqV z$(Cf8V11j72h82>YYF)k`bWPb`d{HtYAew|i7HkF>73Z00#QaC9}K_-2Db$GZ(yD3g%ubJ_@&UM7))Au%< z3MEy^w^MbTsGK|9DIzbTjL#kM)$U!=ohjV*H^A4V23{=(U14xGto~l}+F013nLO&5f9ua*hf$x zB0E+hf1)$g!m6Olj$IKS#tg05y$t3G3Y6N5>}TX7H|L}uQXUOolH8vi_%<#*A8W*2 zgJN~j*Jm!jmrnB2a(Z_AvVP7Cp(x6dJRtbD)B^7wT_O>Oxkw**fs-o92Q{@rCUMY z8m`M<-)wfljSY4XQT4VC4A%)_?abz*7dkL&_+Q_cwf^51@0vN*HhIw z1J;}f`PR}{7ss> z)6fFR{q?{8_KcsKyUF@R_@Za!Nx)wlaWV0><$~K4(SqtCD6o9UOCz|x&~k-whjjrx z6pin<=q%$c-~JrNJ600g`30F<`-FNawzijY9cQGGT^Q%!_U}deDH#G0UQ_y$>VZM9}r{D}rrDKtMqCny-a%MrplaQ1CIEvqf2f8m%t%;NTDx$7>xN901mLnK;Vf I9e0QS15`1~hX4Qo