From df144e298cb25881f75bc40e1c0f86cf210bb300 Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 6 Nov 2019 17:30:02 +0100 Subject: [PATCH] Add POC for diff against temporary merge result This fails for files with merge conflicts, because results for these files are not added to git and therefore there is no blob the diff formatter can use to render. This has somehow to be fixed by making jgit use the version from the file system. Taking a look at the implementation of Git.clone() might help here. --- .../repository/spi/DiffCommandRequest.java | 26 ++++++-- .../repository/spi/AbstractGitCommand.java | 26 ++++++++ .../java/sonia/scm/repository/spi/Differ.java | 36 ++++++----- .../scm/repository/spi/GitDiffCommand.java | 42 +++++++++++-- .../spi/GitRepositoryServiceProvider.java | 2 +- .../repository/spi/GitDiffCommandTest.java | 14 +++-- .../spi/GitDiffCommand_Merge_Test.java | 58 ++++++++++++++++++ .../spi/scm-git-spi-merge-diff-test.zip | Bin 0 -> 27099 bytes 8 files changed, 172 insertions(+), 32 deletions(-) create mode 100644 scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java create mode 100644 scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-merge-diff-test.zip diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java index e26b2eb5aa..0b7592b446 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/DiffCommandRequest.java @@ -90,8 +90,10 @@ public final class DiffCommandRequest extends FileBaseCommandRequest @Override public boolean isValid() { - return !Strings.isNullOrEmpty(getPath()) - ||!Strings.isNullOrEmpty(getRevision()); + return (!Strings.isNullOrEmpty(getPath()) + ||!Strings.isNullOrEmpty(getRevision())) + && (Strings.isNullOrEmpty(getAncestorChangeset()) + || Strings.isNullOrEmpty(getMergeChangeset())); } //~--- set methods ---------------------------------------------------------- @@ -101,7 +103,7 @@ public final class DiffCommandRequest extends FileBaseCommandRequest * * * @param format format of the diff output - * + * * @since 1.34 */ public void setFormat(DiffFormat format) @@ -112,14 +114,19 @@ public final class DiffCommandRequest extends FileBaseCommandRequest public void setAncestorChangeset(String ancestorChangeset) { this.ancestorChangeset = ancestorChangeset; } -//~--- get methods ---------------------------------------------------------- + + public void setMergeChangeset(String mergeChangeset) { + this.mergeChangeset = mergeChangeset; + } + + //~--- get methods ---------------------------------------------------------- /** * Return the output format of the diff command. * * * @return output format - * + * * @since 1.34 */ public DiffFormat getFormat() @@ -130,10 +137,17 @@ public final class DiffCommandRequest extends FileBaseCommandRequest public String getAncestorChangeset() { return ancestorChangeset; } -//~--- fields --------------------------------------------------------------- + + public String getMergeChangeset() { + return mergeChangeset; + } + + //~--- fields --------------------------------------------------------------- /** diff format */ private DiffFormat format = DiffFormat.NATIVE; private String ancestorChangeset; + + private String mergeChangeset; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index 73159da5c1..c705e36e12 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -151,6 +151,32 @@ class AbstractGitCommand } } + > R inCloneWithPostponedClose(Function workerSupplier, GitWorkdirFactory workdirFactory, String initialBranch, WorkingCopyCloser closer) { + try { + WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context, initialBranch); + closer.setWorkingCopy(workingCopy); + Repository repository = workingCopy.getWorkingRepository(); + logger.debug("cloned repository to folder {}", repository.getWorkTree()); + return workerSupplier.apply(new Git(repository)).run(); + } catch (IOException e) { + throw new InternalRepositoryException(context.getRepository(), "could not clone repository", e); + } + } + + static class WorkingCopyCloser { + private WorkingCopy workingCopy; + + private void setWorkingCopy(WorkingCopy workingCopy) { + this.workingCopy = workingCopy; + } + + public void close() { + if (workingCopy != null) { + workingCopy.close(); + } + } + } + ObjectId resolveRevisionOrThrowNotFound(Repository repository, String revision) throws IOException { ObjectId resolved = repository.resolve(revision); if (resolved == null) { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java index 0204ca4e3c..b781176972 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/Differ.java @@ -8,6 +8,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.EmptyTreeIterator; +import org.eclipse.jgit.treewalk.FileTreeIterator; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.filter.PathFilter; import sonia.scm.repository.GitUtil; @@ -37,6 +38,17 @@ final class Differ implements AutoCloseable { private static Differ create(Repository repository, DiffCommandRequest request) throws IOException { RevWalk walk = new RevWalk(repository); + if (!Strings.isNullOrEmpty(request.getMergeChangeset())) + { + ObjectId otherRevision = repository.resolve(request.getMergeChangeset()); + RevTree tree = walk.parseCommit(otherRevision).getTree(); + TreeWalk treeWalk = new TreeWalk(repository); + treeWalk.addTree(tree); + treeWalk.addTree(new FileTreeIterator( repository )); + return new Differ(null, walk, treeWalk); + } else { + + ObjectId revision = repository.resolve(request.getRevision()); RevCommit commit = walk.parseCommit(revision); @@ -46,40 +58,32 @@ final class Differ implements AutoCloseable { treeWalk.reset(); treeWalk.setRecursive(true); - if (Util.isNotEmpty(request.getPath())) - { + if (Util.isNotEmpty(request.getPath())) { treeWalk.setFilter(PathFilter.create(request.getPath())); } - if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) - { + if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) { ObjectId otherRevision = repository.resolve(request.getAncestorChangeset()); ObjectId ancestorId = GitUtil.computeCommonAncestor(repository, revision, otherRevision); RevTree tree = walk.parseCommit(ancestorId).getTree(); treeWalk.addTree(tree); - } - else if (commit.getParentCount() > 0) - { + } else if (commit.getParentCount() > 0) { RevTree tree = commit.getParent(0).getTree(); - if (tree != null) - { + if (tree != null) { treeWalk.addTree(tree); - } - else - { + } else { treeWalk.addTree(new EmptyTreeIterator()); } - } - else - { + } else { treeWalk.addTree(new EmptyTreeIterator()); } treeWalk.addTree(commit.getTree()); - return new Differ(commit, walk, treeWalk); + return new Differ(commit, walk, treeWalk); + } } private Diff diff() throws IOException { diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java index 1ac64c1b5e..86c2c9baab 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitDiffCommand.java @@ -31,8 +31,14 @@ package sonia.scm.repository.spi; +import com.google.common.base.Strings; +import org.eclipse.jgit.api.MergeCommand; +import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.diff.DiffFormatter; +import org.eclipse.jgit.lib.ObjectId; +import sonia.scm.repository.GitWorkdirFactory; +import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; import sonia.scm.repository.api.DiffCommandBuilder; @@ -44,15 +50,42 @@ import java.io.IOException; */ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand { - GitDiffCommand(GitContext context, Repository repository) { + private final GitWorkdirFactory workdirFactory; + + GitDiffCommand(GitContext context, Repository repository, GitWorkdirFactory workdirFactory) { super(context, repository); + this.workdirFactory = workdirFactory; } @Override public DiffCommandBuilder.OutputStreamConsumer getDiffResult(DiffCommandRequest request) throws IOException { - @SuppressWarnings("squid:S2095") // repository will be closed with the RepositoryService - org.eclipse.jgit.lib.Repository repository = open(); + WorkingCopyCloser closer = new WorkingCopyCloser(); + if (Strings.isNullOrEmpty(request.getMergeChangeset())) { + return computeDiff(request, open(), closer); + } else { + return inCloneWithPostponedClose(git -> new GitCloneWorker(git) { + @Override + DiffCommandBuilder.OutputStreamConsumer run() throws IOException { + ObjectId sourceRevision = resolveRevision(request.getRevision()); + try { + getClone().merge() + .setFastForward(MergeCommand.FastForwardMode.NO_FF) + .setCommit(false) // we want to set the author manually + .include(request.getRevision(), sourceRevision) + .call(); + } catch (GitAPIException e) { + throw new InternalRepositoryException(context.getRepository(), "could not merge branch " + request.getRevision() + " into " + request.getMergeChangeset(), e); + } + DiffCommandRequest clone = request.clone(); + clone.setRevision(sourceRevision.name()); + return computeDiff(request, getClone().getRepository(), closer); + } + }, workdirFactory, request.getMergeChangeset(), closer); + } + } + + private DiffCommandBuilder.OutputStreamConsumer computeDiff(DiffCommandRequest request, org.eclipse.jgit.lib.Repository repository, WorkingCopyCloser closer) throws IOException { Differ.Diff diff = Differ.diff(repository, request); return output -> { @@ -66,8 +99,9 @@ public class GitDiffCommand extends AbstractGitCommand implements DiffCommand { } formatter.flush(); + } finally { + closer.close(); } }; } - } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java index dc43b8d9b7..2778fecf1d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitRepositoryServiceProvider.java @@ -169,7 +169,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider @Override public DiffCommand getDiffCommand() { - return new GitDiffCommand(context, repository); + return new GitDiffCommand(context, repository, handler.getWorkdirFactory()); } @Override diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java index 52932e83ae..854a217f1c 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommandTest.java @@ -40,7 +40,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { @Test public void diffForOneRevisionShouldCreateDiff() throws IOException { - GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository); + GitDiffCommand gitDiffCommand = createDiffCommand(); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4"); ByteArrayOutputStream output = new ByteArrayOutputStream(); @@ -50,7 +50,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { @Test public void diffForOneBranchShouldCreateDiff() throws IOException { - GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository); + GitDiffCommand gitDiffCommand = createDiffCommand(); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("test-branch"); ByteArrayOutputStream output = new ByteArrayOutputStream(); @@ -60,7 +60,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { @Test public void diffForPathShouldCreateLimitedDiff() throws IOException { - GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository); + GitDiffCommand gitDiffCommand = createDiffCommand(); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("test-branch"); diffCommandRequest.setPath("a.txt"); @@ -71,7 +71,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { @Test public void diffBetweenTwoBranchesShouldCreateDiff() throws IOException { - GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository); + GitDiffCommand gitDiffCommand = createDiffCommand(); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("master"); diffCommandRequest.setAncestorChangeset("test-branch"); @@ -82,7 +82,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { @Test public void diffBetweenTwoBranchesForPathShouldCreateLimitedDiff() throws IOException { - GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository); + GitDiffCommand gitDiffCommand = createDiffCommand(); DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); diffCommandRequest.setRevision("master"); diffCommandRequest.setAncestorChangeset("test-branch"); @@ -91,4 +91,8 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase { gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS, output.toString()); } + + private GitDiffCommand createDiffCommand() { + return new GitDiffCommand(createContext(), repository, null); + } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java new file mode 100644 index 0000000000..300fbee4dc --- /dev/null +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitDiffCommand_Merge_Test.java @@ -0,0 +1,58 @@ +package sonia.scm.repository.spi; + +import org.junit.Rule; +import org.junit.Test; +import sonia.scm.repository.util.WorkdirProvider; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; + +public class GitDiffCommand_Merge_Test extends AbstractGitCommandTestBase { + + static final String DIFF_HEADER = "diff --git a/Main.java b/Main.java"; + static final String DIFF_FILE_A_MULTIPLE_REVISIONS = "--- a/Main.java\n" + + "+++ b/Main.java\n" + + "@@ -1,5 +1,5 @@\n" + + " class Main {\n" + + "- public static void main(String[] args) {\n" + + "+ public static void main(String[] arguments) {\n" + + " System.out.println(\"Expect nothing more to happen.\");\n" + + " System.out.println(\"This is for demonstration, only.\");\n" + + " }\n"; + + @Rule + public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule(); + + @Test + public void diffBetweenTwoBranchesWithoutConflict() throws IOException { + GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider())); + DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); + diffCommandRequest.setRevision("feature/rename_variable"); + diffCommandRequest.setMergeChangeset("integration"); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); + assertThat(output.toString()) + .contains(DIFF_HEADER) + .contains(DIFF_FILE_A_MULTIPLE_REVISIONS); + } + + @Test + public void diffBetweenTwoBranchesWithSimpleConflict() throws IOException { + GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider())); + DiffCommandRequest diffCommandRequest = new DiffCommandRequest(); + diffCommandRequest.setRevision("feature/print_args"); + diffCommandRequest.setMergeChangeset("integration"); + ByteArrayOutputStream output = new ByteArrayOutputStream(); + gitDiffCommand.getDiffResult(diffCommandRequest).accept(output); + assertThat(output.toString()) + .contains(DIFF_HEADER) + .contains(DIFF_FILE_A_MULTIPLE_REVISIONS); + } + + @Override + protected String getZippedRepositoryResource() { + return "sonia/scm/repository/spi/scm-git-spi-merge-diff-test.zip"; + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-merge-diff-test.zip b/scm-plugins/scm-git-plugin/src/test/resources/sonia/scm/repository/spi/scm-git-spi-merge-diff-test.zip new file mode 100644 index 0000000000000000000000000000000000000000..9d957ef6f53ea51baf7339c0a2c293734d6f5023 GIT binary patch literal 27099 zcmbtdcOaGR`!^#a%Fc?&<_u>U8QHQop>vLNkiAJN$%u?dl$ET88Ii2)%p?`rk(p5n z75P0!-}lAa^1eU4_j&cl`CQNSd9M4uujjfx&z-I&DH#r6wXKn<6D5+WgQ3AQ*u!Q4+C-;B^#VXk3*B{-y|w zJpcsO#TjpJyZL?mY@H=x{Nwu(+MN;_k#FCKYKT3N=oD>{xO==!qE$;&NK;I>v;C<- zp%G~0&GEK&^^Oi5b@C4y;Ti_z$hZR$BOF9qrU_S%h@jw>1I(%egBmbxgY&?;+q-(& zyEy;u`l&nGG~2bb^aTI5Ut+AL)gr1V*z!cwSPd|2q^qMYrY+toD%b*CkBMN53DGoB zYYwk{_ZZ2xYnTGAfwsDma|E!D1=yhiuEEyc(?J}I21wkz1nkc#d=OiHgenWD;t?vRH5^vuGwQi> zQo!Ca$MU;9T6%`>VrvV6qtP#^L_Y{-lvLT{SA<|iBc#-jYi)F4rN{2V6Rt0}%Cor7 zUe9`^tCgi)&3u#{W9=h)5mRwXTtW2+RVSnrq^e||eJ zImiIA*7YEfcd(Nz3c^hebTc!rPMDQO@bTyk|dS)i&k7-YbwnzDk@-!};TV}QBi@KT3>4-W}D9NNZ1!rs{v zXX}n8+*c|>1Z*J#fPeoGg3r#y#bLL>ONgKYoVLQ3fIElZLqx>#_xD}habj2(CntMP zaSybUtK;`u`HR`$WQca@htsb+u7}@a;G;eHT3rsWMO5EbNTfiKOT3&ew#Qt?ESX=Q zUr1U!e0{kp!^VgBixy+F&q9^IkF5){!z^==cxO1&TPn`45Y-)pzR z7lF$Uv~3PgKUi4WfEi5pzszpHN70B3N;=vF+?;O8e($W|pLEJS)wB1bSOw#x($h~x z8gpNpM!+>AEvz#=h<&M;?mMbg!fx`Ty%uFWb80@8iTr zg5V3)u%-6*eGJl7dm0UcE*(nLdtBhXW?)vnBsoWN@5Dtc$n znSRq)p{}n8o=plF8nhl@6r2seG-Nl6c@!6OA?Zou_+_pXEn~#tyB3hryLOiuod>+9 z<%K|T)*JP>FIOhl@=o6N%6;LgEKGYP=Yxqdj(YJ-?$pRv(U3v~>$Rh^kJcWZKGQB5 z?2-Az{!sPvE)Urlo%Bh+E8L@zQCSbL@4G8nogbf_3y6Cgv1H3|Fv`;W-1YgQ%wn9TS>R1h8uBIblWg-s-j6QE zpWGNx--7;fdf7;ekSsfdp;4iT5T@@1uM za#r(;_SaZLKYoZ+bdZr^`O1Qv+}eAK_w*O&%1RojPKDxvza6W1mCd7Y0eqG@Cn52^ ze#8ujn*}0<0|!B&N`BzAD6$b zF152Lm5ey=2Je+S_Q{CcmO44k6a2NRyOd2}wbu!kGRiXTx5sa0{Z6?C(+2U*z2P8_ z62BK25z)bYL_`dK&ulMO8?+~G7qdFgM9+m6L4Ov1u5sW(UEoRe?y_+;FRh*#E@305 z`8!g|`1kjnnUnIh9#)lZRHe;X_F5v_bTz7We%M^=Xd60ryU@iSQ^AYlpKTWM4`mM-Q&u}`UA3-%%CBX5{a$c%*?TiMGu z&sFzTmbHMS$k5{oV~zsIA>~?bVQEUtdADnamKZ0K+0tzcp));!M5+O4Z;v-kdkn6W zeYOZW*@+wNlB3h;OlV!q6_h=CaqmIp7BRY6O1{Ke>*-+r0s%4B$`cS&&T%!at1t+y zKMVT&!IsYqFB8z`A@66o>ogYWuDOzW3Pp31Ug=7c{HB6lNYGiK^GQ2PH{JF?nJ;Kx zw87PmlnB-8Yh0RU@A5On79Z|8Of^06?*4(y6_FsDSx!)4(wUcX#8{Xo%IBd9a+ z#V}*`5Gvrj1>$4v*PvjZ3B2y$8r94RvP+bwoUdM?w9j1&Nf-)P(O4ch;ZQnaqMAF; zp7&uyO1;AExc`EaL&TtvxcS{PIn6W|WJ}Xx^M^UfoGx%(akh5qRe68(DMc6~YEe8mT6e2qr{r)$R>F^XjAY*V*L z&X^*b>v;nnXKo4J-%y$I3h22na&YuWcC9 z!^&d}a)c3dM)fo62KkQ$Q=&Fp^E~q`MR=-$5{_6e-H1yuS6p}&_u5#s$HA1duX3ak z#a?JK7XH-7a>-UH-Gvlq%khYoG^y!E^+(R=!QQ+_DIKDeet~7TyHr#uAj|iH-d|u%K5j%6;S`k+ zeZh(BZeZ~}6GbBWddx9_8vS?Phj%k8MDgeiZ#)~yg9)sRHPH@;e5_Hu z1MjBg)8G5q`e>;Tk4D9<`b!nh94EO3nNK)$uZw1O2@U1X*ZD2V?OeggdZUX{NQj7( z$cc!U{$9ZdxrwWnhutpLut-C+LqCXqont*biQy&fjS``+hS%x@FEgpIVR76|rLD`T z1M&Piv9qN$XMJK*GO>kBin!_dLH`Bq8#PFw2eNxL!cdjP=jrax(Oht!->3N2i-kw( zp=v>rD(ltDH%Xs#f3mMpn)-6H(2Dqk2DUKd!~XERD6(b&@+U`bQE)1>5XINcL|wS0 zxY+wBjQ-Z;0Axrky{2QbYRocN*r`k?OR40rsj$ZjUAP--%V{;l@4oj{2}M4tN5Pp! z!vvK^4R*eCSx-75`E=7AM4H?;>1(&t1=4K3=oO6yj7Y?)znHbOd`n_BQ5FyZH@ouS zO@Y-7(NC?hd3l##_ucU_EOU2Cs?!ry!d#Y8t;e?nRkRZY}ZjX2FlCKU`vGw?R zs@&=0ZzKB^BY2)T@lIh6RrWl8Gy5Wk#EQ0a82qZUA}{ChD-j+@pjMG7%dM3VX4_zT z9T#mx&c6$kUp?7{{KEabi&BFV%CGGsR@HKK*9p?w9qlWCRe6;+K@wk|@Cu{$OeIGC$n$dgv zylW&4S*|g!lIX8UA-^cRSIte+WGai}VKfkR_kQ0_nR_)TBEeR-(x)nquJygHsCS<9 zL@4%AfO2c5$)1_HWmFHE1wRG_BjN+BNOT$ObDv%$M8v9OA<5=RTG<}sHhtARYk z(Y%&B!RC+sNo0CWNiMYcQS_Ktvm%cz6b=(hUp(48#iq!`!+V8ufA2h~c0!QMLIcU% zRuz;!L1`Rz#GD(yG{g9Dbb>4)r!d}7VO~~R4Ru{2mn}?8hs^tA?#QJhX)3iT&{N_s zESfaQ<>U|dHuTIKm~?;cP5w$rhjzc>&{(ONn@9vAw4dkP* zjjMPk!GNkErGuX|?l4_Wr9~ZkVxTukbG>S2-s;GO&ytPCilA&1t}o?)UBEKDE6DhA z!^wR&E2tIg-G!p-zt!{x$jQyjYi-)3|XYw7^chk&((^>3~T>xw%Li?jFM zO?u>|+ooL)qL*p520z>%AaBunMOZD2^kcU%ZxxS`^P?+T4AS9)6pCxo-mMvwZhbFK z+crV_rP%YYa+$Z7=LSpDN`>7QrtD6nbu_-$TFZ77bFA0=LW`bL-o-n~kk|WUMB+bc z6}Og|=pLap3%j)%91>SoE2Ss>EV>( zQtTUXkhLSp+>_bZ%I?-Jp%|tqaYy;{=h%CN&=Di8^&1d<={KZJhWk`srWe$Xg{nVF zmPqAFDE5=Ou9dJ-+$j0B-J(lWzlAAc`Tn!LG+ZK4XGgzHDm&EQ3iG~2w1U%YS>nFU z@;>qSD)rJsVmCofJ8Oy=ul1hGBU&8}25?){rEa=QF7!3919?^-I^F!wawd)y6*QA_ z#qVoHGoCHvUDD!r%gJyJ)GK2bb-# z7xN*^1t+xgE~Y}fiIWaHivC;jTKM#ZtC_rJufMu$P`$cawS4+6(Wkek_0ym9c^ycw z^e?Kq7?xeLo?3*Ekk|29BtFm&U22zsMt5{(lz78AMN*8rndiLc_)soJ6RM+2CrtA` z_B6V<=veIwZI18JQJq`fSJlN=plrqzi*Gs+)0TTz#_yPhKk7l9<`>a3aFO7q_w(&v zTWOzr@cCNeJ`{9PQGA*6`o6NM70gIH^so-9j4ct zc3bh0fsS%)FmF$j~fXQCzNzGwX{zS)OIxV z>ia%@xi9n~@9Bf0$LH?7t|021TvfRx$V>78I%{m|Q_ zQv1(N+|Er2B{nmojJEXd5Xb|kwv#!p_7C(@H;v?7B@T;=AEBC*v;rwPUI@+5S-7Fd z8f$);Ix5`URco1EG2*@%`U!_{d2W{FM-wu>NDn%0PCPOH_1i+T2gh7~@#D+~^1Px+U$wJcAaPp$FYm?-E%O4vdwDD9Q=yTq;~VHyo9@{X{xc)C75 zGgx9FeRktY`?{Mcw#S?eB@vsMVcL^1ewzKg`TTSrfi zPrJ(Z$G*5|e&qh)3tfDWv#hWwmskdrDh~ zNI2m5Yu^c|RLXGRpW%Y~G+bDEPm?rJ>CHNNSHDTrd0;7%w<6PvF(il=~J1i41s4mLQB3*@qC)R z=6CN{4*BVH6Us4?EUZ}~ssl%X+b>ST(v<3}$T8vUkbP{d<6>&Q0IKvQ>vOpT(5pm4 zmtb$I8AZ#H&Rm*ep(A!qrNgFn$ASYTs6nltx!n6k84^ve;P$xR9T07wvI@%gMt``X zbf8W^GTt1sO3b2O48g_)m|j;;5$pO^UKtgnCy&^RYcc9PovRg<>)XU2XmF+CVl>lT zo7zb2TMh5syTY;$Ju;;+wfYpGn{=!0dI|sWzNeX`y`?h6^t$Q1bVxInp}gWI{XHiQ zNWFDGX|a__dUdi~i9)m)9=qhKF7Fl86aIK#LXvt1Rgm@+e$*wpfQslm9p_%;iYI@# zl(5|*50!0V%?K_)mJGi~3(?$(x@r3~_T_?VL6>pf%LKus7B2p>(7ht8Wybf=r&!14 zgR`~nRZcd^CA(1$19u$(73 zi!-B4N_T(|pXtr8z42DB{Q$i%edDPZ_D2e2dR@*^w`}iymOb%7KKRaw!I@(*7S~Q3 zr*UzDNpa0_vQH5!s_Qn;68Wj`W%*pgD?}^)Vn&0@Sw`lNYu+;(XX&rpSI^2;sjJd{ z9!`EX`J$20m#>c8-30SxGIT6sba8=hfPOaUw)OqjlzAk?PGUi+*V9bXlGh?Wwd}Q! zFhSCIzs&g(YWMCNdQPBbna*P%p!{9F!AUpgV38vlt2}d|-ovouHOY3u49*YL{kMyqL!+?8V8FApv@j{oV5X-<0r8iDR=SN6M zH6k!yl@;R@kF(L%)F$Q+C7AG^u#l16w~eBvcV$wSpp7+V-O*grXrAqeoB*8 zW2M0_2G!Ka=cZ`u*px314qh)k$MD>TK{Ec6vjh}{2%tQ(cv01T?QW;(tX6{i)y04K zcJZC5-Y^9b5ii3(OT6wl4BBHi*-nb7gG;{(^SbD_a0}(UtX!_rqm2CzqegoblIEOA zY$BN>8j4iMbun7*525vfr`~N0dDw>Viiu2P$e&D%RWFoBKZ|q0N8~17H~PqTT5nX?b`;wPcCFNw+&bFW1(B8P+cKjJ?U6e{sSk=Egwx^&Z*{+;kW!XNfM+_I@Y1zH- zpr|C~PWK^m{I!F;*x=HT1M%^ilr66773P=KukLNU#Yed&sHw@^jWuFilX-FXArH z)za{+C%(u$yl#;74%FUGjK=p<-p3{D(GtNirZf2Rq5g{@8gZh+73rTeu6+a7 z_zb-;FV0DI>q(^bj}*MiVQzBDX{6ys?y0d`cSZNffLih|@&_J@;COk2JxnmuN)hI} zPvdh7m*ll_LGi2yoTSZ#2<8XqZ}hS4icRJ({785WCa>L(8dab*`o#ORo$B<-LZj2r z$Xko=E6`A|=qApS$-e1#9xa`Hv`52mPzU`pdr8IlpV zSYOsM=A_eIyN!K3J^gN4aE6mxb!}l*n6a`;p2I-%@Egh^|HzAh*WzN;t{~+3-yia! z3nYOXeel;8Vyct>c6BOV0Y23sk*ui`_SN8}Tl$H49Q~!_@$!4rK`Y`X&qq?f9Iwes z^YQt}#?>gI{In*?U<0O+jW?)N4isHI!#G%cq<6$C6L!z8_HCX_Bz??mZsl^>QH%34 zWNL+iw2xoD?zkk(Pr@@DB+!4uv$(NwoKEJEWj|y=Oq(?>Vz_q+hd+t5XLNot{s zJ~Phu@?hQfsxF=W3VC(tNn3x?qwJs_rclU!<1ZiVVu!xg9C*1TcKE78&oPqqxRb2X zUlK;%krk5Lxfrw0;cfW6v>DVXx(pl@%MV=(DlU^-|1!TggOrhIk3GCrl5UE2TofEL zd*wTPq2-R_qq^c1oLm^&*?w>USzz$(hiCk&`a(x5>RaeAu~zF&O3>^DT5!2`>hot| z3-c|8e)!PhmA8%@?b46j3qaLjPFKrC?H)3fAND{7NFDU8t@5$@aB_aFU&Q|`?4Td& zal<0}s}LGmspWItR02=;XML5Qu|pYm1Qc|u@vndV@aAoQnRxinc`M5!b~bZCU#Iqa zr5z+!HQ~7!MKc^!y78&v$S3ZVr0n-@pEg#UrAV7E9v(`2u*~$6t-!HG{`oLe+U(J4a4}IG` zGn4w4tj4rnH+5o|MB?r^TpJM5oYt$k4ZZ3my#yI@JY-tT)GiU+37voRIQC)u9(LZu zSJ9&3dOBT?9eA1>=LEISCq-Rn=uC)o12twn_o8c8zXxTxsNdAhnvTeCB%`Bx+0Jr+ zmb2+`gN2aDvJxVK?)v4x(fVcfFRARzme!UDN-?CYGCq|D-o_GVRBGlHDLm^9jh_=& zw3EfiDiB3o@-lW)^}Ja(BPxdqiwcxWX%OBkqL=}1$Ze=&ciUqVGvj~vDa)<*V1{z; zJ7qEoSK=TY*B&ra-{h9asMRSDFOaaRO8JZ^j1Op`SstB2)L@S3lg<`V2M-IpsuL^p zw73f!k(D|4%u|YA@&ae3TeBy6oOkAUchHLh`YPwx8=2HG@Mb z&`C3qJFLn|5-~K5FD9Y)=MJUFOA$M2Fz9+R8W#2=ZjG)v=y?$j4yKkq7$vj*pdRd1 z#87?S4Dzf7sYE0Vr=IFSjHL`VyDbPga>P73N@A8Y$3erj>i96$?m|9po+^pjredlt zNW+u`^Qv9f^n_Ma)m(6I>wWDCb%(j0&{+1+Cn1(#!O4kddXf!=)|XmKLRCJVn+~_V zI529%xX;k{t=p7^7JKVdS~nMKtDhC+Yy_{NVBzp=psLo9xSF*+UD8ozy&rFEMCV@* z=caW1;GSw?^zaQp)%-L~mCd$5ZO&IDFPU z)6~<;)J816N$DNg7oFSBz8Bkwd85&=GJ}tmlAY8R_BlT|^hCG*etVwjyr*T&u`~+5 zer_UHweh8m>kGd38|v~J^;IOegsR7hEe&B`h|Li}z6*ilLDAV?nNG?nuOg|=MalP+ zOWeHQ+#}w>Nl{b=@|(4KmG~Kptz$bqW9y*%rn&m7Y_>g#wR5mu@wfH8JDy*Wqy#s>}0pbIt>Un%5MMWKVfYTOzNVukkfXpbXY8JE<>r zirQEquV~_6Ei>hvyTa&nLy_BEtkrdig*la?;GnmpN+OTgxxz=Rdh0Uy3g`{z3q16s zgq_nzno{ViaZYTiG578pt^__qLugK2jCHs{#N$Xk!w$OpOsI*dnD?E$tyhKvj{c%s z(n%Eq@AN8RMQxID#G%Psl4y#3`s&MJ=7B{6aJ*8Nm~>c*M0{yt<4_x0WbBz~mMs4$ zXR?D;wBPs=Zyq{Tg$oQb!ZS5;HWxMp#@P485R>(U&0aqKuB<&6&U{q~Q_#biPaFAY zF;7W5BBSJX*@Jv+#26)&=xiRx`U$e2JF$JsC#edGys#;skB%N6M}a1oF}3?oO7T|4 zl*E%d-d}qbQ^!AX*D0o%;&@ND)L6P;{9 zuQ@&x0`+^gteJ(v6jk_5-TAd-3poGm8)YKoRR^mDK zB((ZQod|cBYZjx~HJ+SRZ3zkSBfyUP@yvVs4{sd@q|LdtBx~i zT>W6i`bMFOB?-g(*kO{xvg_t?NnL6h{TzlZUTZbSCbfF-w`dQ02qpQ7I(i|75C1t$69+!~2>`&o5!uiToJB%nf#Zv4D_tWam zkxMhjN%%f$xy#Ch(G5SPc#oFwGd}MFlGB)}w&-=+J1Maa6)V1BMRHpm$`E@+OsE^@ zuK}??Thca@Z_&vMOOvhsC{4AnZ(&)keelE8hszg^QNQXLb+xUuJk9QTmUQO?diwY{ z$zGtoczZ`Jmr!5as^{*afMpb8L8#>_Zxn}XO5K%@FG%=7chjT| zL+?Klzgc;Gw0ZfB^I(%(N3Cc(iOb=sDFZf2o=G}a6YPGqrqomKbdY2cVKl=N)5&EQ z#d8>y?e3jlCbMpJ6}EbGzIuYJ;CR9rj+n5%1v@X}s?emvD*-# zwL0SUNzo`vrqL}2$!VeywQ8ziftPX>@Zv4q?imW%&@{H2>gMVwFfWq_(`=fTF(d@hqFS{nUK{ljv!9>A3zqvG+v#?)JH6UUzXC9O9#E}pDOSF#Rd%^71;kpr zJO?p0rX}gPsflzOYh`>0E71tz?WK-0T~V4IKZ3aQprO+-^nK15pM1`{Oh?`yP=2-Y zty8v{tLDi*eOzf&(=*lts*hSFmd9>Cs1EIje8-WjVr6ia&V<2zu(Uh<8I$>aW5bg1 zma<#+w;zv6zX{g~&1Q}6e$f?v==h7W%mH4|RlB{9Xg0DO!-(^l_dO__JScFqFi(g5 z#UmH0q1b5B6ZY}n4rQ>RQ(UWp1v%N&9Q^MHQ<6XPQt?rtQWfB{*{eg}YUc7(YS0gt zP4jy4M(lO14DLSeGX2`1rwKGiukkdBA%xsU=q)>nQ;W{0pOi8@b5FIAl-J3LN#bxS zP#CELlLwL(-Ckf&CJtmb6B5?9ye8BsGfhrBnSir>n&=v zw?A*w5Y@D~?bmYbjMr6G$d3}Q&Oco)M8lzvYphhJC>@qA zdKY^(_~lxE_Gf+~BQPiPuX)_g0>);SEFe|zI_FbdL}CF32xB`700LOICJP+?b(REK-#-MZzQkG4gfOL7wwz=vW@+Vf zilySE@*Y);89J15+_4sZ;6P=ynJ;O=LjAck9XHDa8mhPA0{ELPe#UuJO?ygGGR0$z z<4|^&2FzYL%vBciooMkm4*JlvNO?kWgsj=H$Zuouc!BAeGuJ}ioF=*B6wx|W9V)A# zr1$($io*hT#6zb~k8N9^m+Rl2=5Ama*HBd2V(_6BUT4i!An0cy0633@VX$bh4G4_G zNFu>_2p)xmpd_&%8x#hh0u4hz@sd#Jrt{Ka|272d<|$`lCLfBFufF0_cdO79XRA%4 zyBU7r1gGU0%TMkGtjNsPaKDIsjx|1*KK^y8yw7D?OPWL?1ss?y2MDVNaMS+&q1_h4 zu4t^oRuKH;&ioo?dnDPwwm^QNU;aLy5{>aXBAwc6KO++Wfr4-l3>stu#YjTIU?>_1 z1=*m%UZ#@pD~fFU4=4Hmyi=3>I{$;AI}KDmktc5O~4*Zx=T(#omOwL!*?BiamZNn!|+*{4G-`}BiCGqS0GJb*V zx{dSx159*0?IC@(gR}|5FY>)V5tlp?(cT?hAm}dX3OJ6}G3h;csuZA#Ft*bLfItx_ z5C#snk;EdAa2p_gz$h3L1+2(82pm{_;7B+Oi^puzH5XiGNf3ztxco$Eh6C+&rQ(-D zr@1M=h+F_2ccym_GQJnjifQZpu>L%vyw>sV?F%N1pZrqy^!mz1MzTF*PLhp(B6i7R z5k@X4b^Q%8o1?sB;)0Qgb0v-73&zZWgRjnL9kn1bs8Y zA4ne&SD1gsp1`s&LmiM~@@97|V==pAnL--~%0N$NIKVJrY-bq&K?6G+6oQ8%@E{-* zv66T!41$59U|mZ@~gY5yp1101z-5 z0qlJs8w3Ok!XRvLSR@*VOb8xtjF|?d4i|zTUG1TtBK2DDYd-cf zSG!?7qBGx6Vy(t*N~ibcaNe^!m&UljGcH=-$U9f%IN?Vse$DLmr5ypL}!TjCV=m^CP4B|4&9;hNDRm(hSlg-)UBTH-OX zC%$7&vb=hNn4%tiTFBeFqfD*)_r|p;$Ucv0CYwu+mSTtxI(8G|0oiXkP-u#2W~3~~ z$G@!nM9ktxnS3wT9QXK@_mk<*+~-!y3c3qs8>#|=6c$RLcKeS4lXTA8B_+wf`4&9+ zhWx=-FP4MlK9QW#*L}DMQ_=1&%-Es#iHyEtN3A^WrK0sw&l`3DqOwIat9OQ9?BeiM5=gr4Htv@I2;itLo?v4iJZgyY+bYt+0*3d(56-O%gw=p&WR1$Y%`d8Qd51 z5EFeL>oguhx!}gHgaxVerh6~a#~kr|@QhYTMf={$7czLjQn-3W+bE@4g6ZW&`rGqY z;^V8aYzOL^-u5js8`h7=lnIf&j3Zg@!cexhD_cG0?ltsPmpA!rsDicci0so7olN@jCCP6IXv0 zdjJSl5&;Ao7HWe;VSpI40b!sJBuo<66|fi_9uMR#P)QJClXTgVU&NkfYm1IP2!U7Y zR2LODCOj@0+@8=Uy6`5pA-3HnxTL+Zfg^Y%_EvkPCwW2FNX+WVbJnkXZO^fokXw*v zC9kc$!vw!M6I|IoZpiPDZ!S*69LgrMI~r_uyBG8T8Cw#xb>L?-03awyC<=H|LSjH5 z3=)Hc;t*IQ6lw#(A@MLA93zPa!!gM3D^^U%FIKEyPQl&>8_jVm5}gR=cv~>l^ymW4 z*;;_ui1AN(ei1uY;qGXFpm(_v%>q+UWYgo5c zrRn!coFw)Ci1b}mim+3Wt}ZR|R|O*m+ceWn21|@r;}hgxXBsb2%zrW1_FVnDwH~vL z;h*eRTeqnV2s9=Cjrc@>UBcMTFaUzVpufyW`ScqAAD1C~2UC{Un4VnKMM4G4-v zpmE^u^_jE33N)`MU~8182~PPc!j)nkbHVw|yQ$11q0%^Ri;!EtRE5#k2cAJdmFR2+gifzL5JWBc+haF7Oc!x|BT-Vo!TSZeuOW zG@K=WSw44*g5U9o+HHlW3Rt%?P8?#$0XQU#?K}b?XuJ&sivo{ZM1v7xJAo;velT$5~&$A1t;vNct-{vY} zX~w~nDkTFSdj;lE^x8s+C9iDzM)D`MajI=*IfZwOBa1G`ht86tgqt*YJ8irj7akWlU*Dj&jT0hAKPc3J@t3>E_H zv``cpSpG0b1hDtw5H@(iqdyWYi3b4*Ga7<|ZPH38cl?yrEPz%Lplf5f!q`V0EBX92 z@&4#TLpS3xg^>nq(ko@uE+Zf0e4{12QqySH=)Ij_q_meOaxS+%f2@?ukb&o2xD`14h`g1#LtaNogAcE)u`;~7LT{O~?l3zf$Mov04Eqz2b4TZ?XWO(N?~YW=Zu2|B zgQ{&I*r5m@lrXlF3V*hvdZV z@S^PCUXWBrei4G-raKPcIY+wyJJ@sVZolu@El}ssCk>Dvy^;HJ{QPWROxu`C_0mg|xwP53fODjC8OjlfoRzm!3qy4*Z9Oz~C4tN)jjupfFe{?0W)z{8vd#R+JV{Z=q4CSQaYb7A(a!GF|O1 zSD2<{RG+6)x4ZzInmd@B|on|SMhsEcMc(YC8i@h-RJqz zuf`rOM-(id0@){;-exqA8dusMhf$HRd`jAO=#uN3abJg(M|Cf(_9S2|5XQ*mkh$SB zziZ{r<}UqKGwv78`z;DJ_@3wHuJlP+F39sAHXJArmiZjrhJ~-t#kT4Erii+oSln)_ zpM*62^v~GC5NZ$xCPxDeDz0Ji%D}db5!ti(&p)0zNpZBqh>5ITKE1bYFW3#! z4TfGZefy>-hiCa{Q6hi76hi(M_~ZwxkoI?t*}W91fyytw9PcakDd%G-Th0|3@G^eL zG^p{6N!$Ne#ao2LXG_GL=)5*BsbdQ&itNeCNKCYy_oH)86)QT8CzR#o+N3*+s%9Lk z8AWu#TWdlH@VJI~^^N}<5NU+5J=y?L&U-`yK|V~`Jy)@3Z(X^4&?9@GBSb`qK8BT zB2Ec$+18etxf~g;(JiQois=j_c^A*mg35gHWRM62)h^62+i1w+IB-u z@yKmO3+=v45f_8rif5-+lRjaJ95PATV-@nS=2Ieb1cX=O>R_W<@*S zP`p??%d|!G?-B(Bc9&~I08r(b*FJMR5V%u>vHflVAUGSOBn$;4@>m!Si$)-U>OCHW z29{kskR;eh!X?pYpj^ATqgno{A@+}2L`+m?ls0E0&!u!)zJ=g%Wya}qi14xj*Wu>A zC(O-$M<3dqYHTE{vq%>}um>GuI$XuYF|QWD$s!c^a+WqbSIjR~YCW>xLFL`m%<@Z} zDRF9Ju4jSbb;Erx20}Fg4pbv#kLL^z6N=X>Vq(3!BMh`#!tj20oyWb6uaW?=2xB{8 z00A42c5fHwudaGAtAv1VlR)32a<8|0|1~@2RsSj30{EUY$U#U!G>q z$;qRQIyualBYZ!ks1^R<57|iAzMbLAn`BNJ^nT%Y_(F!;Mccp=Zl|hd51o>XmagF9 z$$6n3moe%dtX|J3dZ)+wy>X6NPe_P>6K2Rj$H>oDsb46}tNlP=Trfn1AtNh0cO}h# z2l+(!rTA%r|VTo&NOPWQD5?Zv1uXjf!LUNa}N9e>c)W0tH*}epTU_g=( zC_)kmmjt2=L`d`TAUp^QB(1;#0YYQIAfO}r{o$I>iTnA+AFV}Ie~9s7#WLeOb?wIL z&8u8IANPDYlO1?u&%Kp`h@qQpY>6)T!gpU^K7@Sh7TzDd*Qw!9TnuAmf*Ed+iYAH|T)OVN zBNn{djEb<~Hw~>qe)hNyfIwg{6j0B`0S#R=1dful0b1QyG!UmK8!!xo1>^B}1mydq z{^f@M%g6OZ@5~SVqwK}A4&{;NvL)Iz8*Gks`~Lj6e$SMvb9Xf0cKZ-S=reIVNssy& z4FCv+(AUMlaX{@*5{m=6+z1#N3_^f0P#hcqR9k_E&A;-VU-p@PO#^3f7q1bo`+;*B z>$Gi^Wm&cU0WTGq$jhZ3tv;H0n+sEki51*AzvKe^y%*(G zd9%%<6@B6X+_+Z3^G9tmFFv8ERdwu=rUe5W>wfUWU z^Q}^=`?g>ZkzcJoPlyT+6VnUDD|dBUn@+AII_I=?qFwLrU0~=lW@GnCk><` zTH_`U+hKKf9k?#hB+AI=>FesuQkuqF4B@AARj!!ddcNOSV?^)NK6Q+w>K9cu;(m|G zfbwL4JKCn24#w0t(J_741kyO>Dyf66s2=ON4Y~KF7HLN}UwHX>H;JI^**r*TlWRg3 z<0qYr-^cB?bC~`c2;o$$O%PAC?KZW{PcMX+gp2g&p6mr)O#1#qPc)}M_-)%+W#r$_ zD*MM)q^n7Q`_)Nh-{FABB+3jt27LZ?ZW(~}lQYYV6ThFp^}8$ELIV8x`)ALNyYLu5`s>84 z-(h{f1q9l5p0~AiRdazvfS&O?7C|ZckJGny2fp*jpY7nUfp@CEga6}ow%q~mJc(mF za5D8@z=W&baW2R1pm!d8upK%KIJoHhHE+pgcL+RpXJF^s{@V?Fr2ESN;oATC?*H!4 zcfPQ`9X)#gU+BMieSLREcD|js-3SHnm;VLLPu^AB9s17q1Gl4(ZJ}=xwBv2T-GT3X znP59O1JB=={_9r@c4uU#;Cj0eL%wZBekQ-(oq?U2f&YAYA>XmQ zd=Vh}OP2aOsIApyrzmynIx_=Ng8zg1TcY|q#GhXr<&KLJ6(aguziDLn@6o7tpgC_t z+f;-8888TV^xdfi{q8Uk5it>8VDV1C-6}%?vjn-rPdCz^v$E3)XY=hjC@ckL^M*-h< zYT9-J?pDqRm?g;h{slEVr`&bO7B!o?yFdFu*pzmv?za0ev=eZ*8a%-4|7%lPf^PY- zsdD?XA3ti`w)=sU+yS^-#T#Ijpm_Vw_k$OpB=z0Ho^<`5(_GdqSRF7@>h7SotkKHdQ2l_Txtl$#y?( z?*!bfq69EYXfXZfxT;jx@?%r9@n=7Nlx%GGgII9~;BEyRfZ0E+yFZE|wwq-J%IAN@ z)xVHP0A>jiiT_OBIi)SLn}UHq)AyrXV7ng;I{|kq9stY|!~_4?k3!`wKQ{aLfA-_Y zF8+2uKJ5hDZBHLC`;&hDKl=)Qw*r7)c23K$DqDVRHqrm=$B!-a?S9Cs?f~3vLme>t zFN-ic{V-J9GP~Kc-i04ObgZ}gaeXJ?Zu{4O+5gw_Vxhj}$7a*{&wl*aa^CL8&7FX| zZ9oHNe_3hxUc3FVPyF31(D(wHa~KVxon2!9kkB>$7ZYx0UAae-=&z>epDFqMqdvp& w|3Q8KhiZ1SrT!C;YDWdo^e@2wHA{bWf#g6(i-<@Y_#?zgM3fACi-_p|0Hh|N#{d8T literal 0 HcmV?d00001