From 2105bb96a08102ec996ffba74a7262acca8d714b Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 24 Sep 2026 10:07:14 +0200 Subject: [PATCH] Version initiale --- .gitignore | 11 + README.md | 208 ++++++++++++ deploy.ps1 | 107 +++++++ docs/capture-desktop.png | Bin 0 -> 111953 bytes docs/parametres.png | Bin 0 -> 323450 bytes docs/schema_parametres.py | 424 +++++++++++++++++++++++++ i18n.py | 283 +++++++++++++++++ images/parameters_en.png | Bin 0 -> 285057 bytes locale/en/LC_MESSAGES/yarrowpattern.mo | Bin 0 -> 3540 bytes locale/fr/LC_MESSAGES/yarrowpattern.mo | Bin 0 -> 3803 bytes pattern_core.py | 358 +++++++++++++++++++++ po/en.po | 156 +++++++++ po/fr.po | 157 +++++++++ po/yarrowpattern.pot | 137 ++++++++ test_pattern.py | 311 ++++++++++++++++++ tests/data/shapes.svg | 15 + y_pattern.inx | 91 ++++++ y_pattern.py | 193 +++++++++++ 18 files changed, 2451 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 deploy.ps1 create mode 100644 docs/capture-desktop.png create mode 100644 docs/parametres.png create mode 100644 docs/schema_parametres.py create mode 100644 i18n.py create mode 100644 images/parameters_en.png create mode 100644 locale/en/LC_MESSAGES/yarrowpattern.mo create mode 100644 locale/fr/LC_MESSAGES/yarrowpattern.mo create mode 100644 pattern_core.py create mode 100644 po/en.po create mode 100644 po/fr.po create mode 100644 po/yarrowpattern.pot create mode 100644 test_pattern.py create mode 100644 tests/data/shapes.svg create mode 100644 y_pattern.inx create mode 100644 y_pattern.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d5c4b8c --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# Cache Python et outils +__pycache__/ +*.pyc +.pytest_cache/ +.venv/ + +# Archives de distribution +*.zip + +# SVG intermediaires du schema (regeneres par docs/schema_parametres.py) +docs/*.svg diff --git a/README.md b/README.md new file mode 100644 index 0000000..570a7fb --- /dev/null +++ b/README.md @@ -0,0 +1,208 @@ +# Remplissage motif Y fléché — extension Inkscape + + + + + + +
+Une forme courbe percée d'un trou et un cercle, remplis par l'extension d'un réseau de Y fléchés découpé au contour + + +Extension Inkscape 1.x qui remplit la surface d'une forme fermée avec un motif +géométrique de « Y fléchés » : un réseau triangulaire de Y identiques (bras à 0°, +120° et 240°), chaque bras se terminant par un chevron dont les barbes sont +parallèles aux deux autres bras. La pointe de chaque flèche vient se loger dans le +« V » arrière du Y voisin, ce qui produit l'effet de chevrons imbriqués. + +
+ +## Table des matières + +- [Fonctionnalités](#fonctionnalités) +- [Installation](#installation) +- [Utilisation](#utilisation) +- [Paramètres](#paramètres) +- [Structure du projet](#structure-du-projet) +- [Développement](#développement) + +## Fonctionnalités + +- Remplissage de `path`, `rect`, `circle`, `ellipse`, `polygon` (les groupes + sélectionnés sont explorés ; `line` et `polyline` sont ignorées) +- Deux modes au bord de la forme : **découpe géométrique** des traits sur le + contour, ou **motifs entiers uniquement** avec marge réglable +- Gestion des trous : les sous-chemins internes sont exclus (règle pair-impair) +- Proportions réglables : période, longueur des bras et des barbes (en % de la + période), rotation, épaisseur et couleur du trait +- Ancrage du réseau sur l'origine du document (motif continu d'une forme à + l'autre) ou au centre de chaque forme +- Un chemin par motif, sans attribut `transform` sur les chemins : SVG directement + exploitable par les logiciels de découpe laser +- Motifs ordonnés en serpentin, ligne par ligne, pour limiter les déplacements à vide +- Index spatial des arêtes du contour : plusieurs milliers de motifs en une fraction + de seconde +- Interface traduite en français et en anglais, selon la langue d'Inkscape + (anglais pour toute autre langue) +- Script de déploiement PowerShell (installation, mise à jour, désinstallation) + +## Installation + +Aucune dépendance externe : l'extension utilise `inkex`, fourni avec Inkscape. + +### Windows — script de déploiement + +Inkscape fermé, depuis le dossier du projet : + +```powershell +.\deploy.ps1 # copie vers %APPDATA%\inkscape\extensions\yArrowPattern +.\deploy.ps1 -Uninstall # retire le sous-dossier de l'extension +.\deploy.ps1 -Force # passe outre le contrôle « Inkscape ouvert » +``` + +### Installation manuelle + +Copier `y_pattern.inx`, `y_pattern.py`, `pattern_core.py` et les dossiers `locale/` +et `images/` dans un sous-dossier (par exemple `yArrowPattern`) du dossier des extensions +utilisateur, puis redémarrer Inkscape : + +- Windows : `%APPDATA%\inkscape\extensions` +- Linux : `~/.config/inkscape/extensions` +- macOS : `~/Library/Application Support/org.inkscape.Inkscape/config/inkscape/extensions` + +## Utilisation + +1. Sélectionner une ou plusieurs formes fermées. +2. **Extensions → AlexDesign → Remplissage motif Y fléché…** + (*Y Arrow Pattern Fill…* avec une interface en anglais) +3. Régler les paramètres, puis **Appliquer**. L'onglet **Schéma** illustre chaque + paramètre. + +Le résultat est placé dans un groupe « Motif Y fléché » juste au-dessus de la forme. + +Conseils : + +- motif trop serré ou trop lâche → ajuster la **période** ; les proportions + restent identiques +- traits qui se touchent → réduire l'épaisseur ou la longueur des bras (l'écart + entre une pointe et le Y suivant vaut `100 % − bras`) +- en mode « motifs entiers », la demi-épaisseur du trait est ajoutée à la marge + pour que rien ne déborde du contour +- en mode découpe, les extrémités coupées en biais peuvent dépasser du contour + d'au plus une demi-épaisseur de trait + +## Paramètres + +![Schéma des paramètres : période, bras, barbes, épaisseur, rotation, bord de la forme et ancrage du réseau](docs/parametres.png) + +| Paramètre | Défaut | Rôle | +| ---------------------------- | ------- | ------------------------------------------------------------- | +| Période | 10.0 | Distance entre les centres de deux Y voisins | +| Longueur des bras | 83 % | En pourcentage de la période | +| Longueur des barbes | 33 % | En pourcentage de la période ; 0 donne des Y simples | +| Rotation du motif | 0° | Sens anti-horaire | +| Épaisseur du trait | 0.5 | Largeur du trait | +| Unité | mm | Unité de la période, de l'épaisseur et de la marge | +| Couleur du trait | #b3b3b3 | Couleur et opacité | +| Bord de la forme | Découpe | Découpe au contour, ou motifs entiers uniquement | +| Marge au contour | 0.0 | Mode « motifs entiers » seulement | +| Ancrage du réseau | Document| Origine du document, ou centre de chaque forme | +| Finesse d'échantillonnage | 0.2 | Précision de l'aplatissement des courbes de Bézier | +| Conserver la forme d'origine | oui | Sinon la forme source est supprimée | + +Les valeurs par défaut (83 % / 33 %) reproduisent les proportions du motif +d'origine. + +## Structure du projet + +```text +y_pattern.inx Description de la boîte de dialogue Inkscape +y_pattern.py Extension : lecture de la sélection, aplatissement des + chemins, écriture des motifs dans le SVG +pattern_core.py Noyau géométrique sans dépendance à inkex +deploy.ps1 Déploiement / désinstallation sous Windows +test_pattern.py Tests pytest +i18n.py Chaîne de traduction : extraction, mise à jour, compilation +po/ Catalogues source : modèle .pot, en.po, fr.po +locale/ Catalogues compilés (.mo) chargés par Inkscape +images/ Schéma anglais de l'onglet « Diagram » (déployé) +tests/data/shapes.svg Formes d'exemple (rectangle, cercle, courbe, forme trouée) +docs/ Images du README, SVG des schémas et leur générateur + (non déployés) +``` + +API de `pattern_core.py` (utilisable seule, hors Inkscape) : + +| Fonction | Rôle | +| ----------------------------------------------- | -------------------------------------------------------- | +| `motif_polylines(cx, cy, arm, barb, angle)` | Polylignes d'un Y fléché | +| `lattice_centers(bbox, period, angle, reach)` | Centres du réseau triangulaire, en ordre serpentin | +| `EdgeIndex(rings)` | Index spatial du contour : appartenance, intersections | +| `clip_polyline(polyline, index)` | Morceaux d'une polyligne intérieurs au contour | +| `motif_fits(polylines, index, clearance)` | Motif entier intérieur, à distance minimale du bord | +| `fill_pattern(rings, period, …)` | Remplissage complet, renvoie une liste de motifs | +| `polylines_to_d(polylines)` | Données `d` d'un chemin SVG | +| `parse_color(value)` | Décode la couleur RGBA transmise par Inkscape | + +## Développement + +```powershell +python -m venv .venv +.venv\Scripts\activate # Linux/macOS : source .venv/bin/activate +pip install pytest +python -m pytest test_pattern.py -q +``` + +Résultat attendu : **23 passés, 3 ignorés** (tests de bout en bout sautés quand +`inkex` n'est pas importable). Pour les exécuter : + +```powershell +pip install lxml tinycss2 cssselect2 cssselect +$env:PYTHONPATH = 'C:\Program Files\Inkscape\share\inkscape\extensions' +python -m pytest test_pattern.py -q # 26 passés +``` + +Les tests couvrent la géométrie du motif (barbes parallèles aux bras, voisins à une +période), la couverture du réseau, l'absence de croisement entre motifs voisins aux +proportions par défaut, la découpe (y compris à travers un trou), la marge du mode +« motifs entiers » et la continuité du motif entre deux formes adjacentes. + +### Traductions + +Les textes source du `.inx` et des appels `_()` de `y_pattern.py` sont en anglais ; +Inkscape les traduit avec le catalogue `yarrowpattern` (attribut +`translationdomain` du `.inx`) trouvé dans `locale//LC_MESSAGES/`. +`i18n.py` n'a besoin que de Python (ni `xgettext` ni `msgfmt`) : + +```powershell +python i18n.py # tout : extract + update + compile +python i18n.py extract # po/yarrowpattern.pot depuis le .inx et le .py +python i18n.py update # reporte les nouveaux textes dans po/en.po et po/fr.po +python i18n.py compile # po/*.po -> locale/*/LC_MESSAGES/yarrowpattern.mo +``` + +Après modification d'un texte d'interface : lancer `python i18n.py`, compléter les +`msgstr` vides de `po/fr.po` (liste affichée par la commande), relancer +`python i18n.py`, puis redéployer. `po/en.po` est rempli automatiquement avec les +textes source. Ajouter une langue : l'ajouter à `LANGUAGES` dans `i18n.py`. +Le test `test_translations_up_to_date_and_complete` échoue si un catalogue est +incomplet ou si un `.mo` n'a pas été recompilé. + +### Schéma des paramètres + +Le schéma existe en deux versions, produites à partir de `pattern_core` (même +géométrie que l'extension) : + +- `docs/parametres.png` : version française du README (1400 px) ; +- `images/parameters_en.png` : version anglaise, textes agrandis, affichée à + 900 × 694 px dans l'onglet **Schéma** / **Diagram** de la boîte de dialogue. + Inkscape ne traduit pas le chemin d'une `` : cet onglet montre la version + anglaise quelle que soit la langue. + +```powershell +python docs/schema_parametres.py # les deux versions (ou : fr, en) +``` + +Le script écrit les SVG dans `docs/` puis les exporte en PNG avec +`C:\Program Files\Inkscape\bin\inkscape.com`. Il faut passer par `inkscape.com` : la +commande `inkscape` installée par Chocolatey rend la main avant la fin de l'export. diff --git a/deploy.ps1 b/deploy.ps1 new file mode 100644 index 0000000..89d46f1 --- /dev/null +++ b/deploy.ps1 @@ -0,0 +1,107 @@ +<# +.SYNOPSIS + Déploie l'extension « Remplissage motif Y fléché » dans Inkscape. + +.DESCRIPTION + Copie y_pattern.inx, y_pattern.py, pattern_core.py, le schéma de l'onglet + « Diagram » (images\parameters_en.png) et les traductions + compilées (locale\\LC_MESSAGES\yarrowpattern.mo) dans un + sous-dossier dédié du répertoire des extensions utilisateur d'Inkscape + (Inkscape explore récursivement ce répertoire). Refuse de s'exécuter si + Inkscape est ouvert : les extensions ne sont chargées qu'au démarrage. + +.PARAMETER ExtensionsDir + Répertoire des extensions Inkscape. Par défaut : %APPDATA%\inkscape\extensions + +.PARAMETER FolderName + Nom du sous-dossier de l'extension. Par défaut : yArrowPattern + +.PARAMETER Uninstall + Supprime le sous-dossier de l'extension au lieu de le créer. + +.PARAMETER Force + Déploie même si Inkscape est en cours d'exécution. + +.EXAMPLE + .\deploy.ps1 + .\deploy.ps1 -Uninstall + .\deploy.ps1 -FolderName 'motif-y' +#> + +[CmdletBinding()] +param( + [string] $ExtensionsDir = (Join-Path $env:APPDATA 'inkscape\extensions'), + [string] $FolderName = 'yArrowPattern', + [switch] $Uninstall, + [switch] $Force +) + +$ErrorActionPreference = 'Stop' + +$files = @('y_pattern.inx', 'y_pattern.py', 'pattern_core.py', 'images\parameters_en.png') +$localeDir = 'locale' +$source = $PSScriptRoot +$destination = Join-Path $ExtensionsDir $FolderName + +# --- Inkscape doit être fermé : les extensions sont lues au démarrage --------- +$running = Get-Process -Name 'inkscape' -ErrorAction SilentlyContinue +if ($running -and -not $Force) { + Write-Error "Inkscape est ouvert. Fermez-le puis relancez le script (ou utilisez -Force)." + exit 1 +} + +# --- Désinstallation --------------------------------------------------------- +if ($Uninstall) { + if (Test-Path -LiteralPath $destination) { + Remove-Item -LiteralPath $destination -Recurse -Force + Write-Host "Supprimé : $destination" -ForegroundColor Green + } + else { + Write-Host "Rien à supprimer : $destination n'existe pas." -ForegroundColor Yellow + } + exit 0 +} + +# --- Vérification des sources ------------------------------------------------ +$missing = $files | Where-Object { -not (Test-Path -LiteralPath (Join-Path $source $_)) } +if (-not (Test-Path -LiteralPath (Join-Path $source $localeDir))) { + $missing = @($missing) + "$localeDir\ (lancer : python i18n.py)" +} +if ($missing) { + Write-Error "Fichier(s) introuvable(s) dans $source : $($missing -join ', ')" + exit 1 +} + +# --- Copie ------------------------------------------------------------------- +if (-not (Test-Path -LiteralPath $destination)) { + New-Item -ItemType Directory -Path $destination -Force | Out-Null + Write-Host "Dossier créé : $destination" +} + +foreach ($file in $files) { + $from = Join-Path $source $file + $to = Join-Path $destination $file + $action = if (Test-Path -LiteralPath $to) { 'remplacé' } else { 'copié ' } + New-Item -ItemType Directory -Path (Split-Path $to) -Force | Out-Null + Copy-Item -LiteralPath $from -Destination $to -Force + Write-Host " $action $file" +} + +# Traductions : le dossier est remplacé en entier (langue retirée => supprimée) +$localeTo = Join-Path $destination $localeDir +if (Test-Path -LiteralPath $localeTo) { + Remove-Item -LiteralPath $localeTo -Recurse -Force +} +Copy-Item -LiteralPath (Join-Path $source $localeDir) -Destination $localeTo -Recurse +$languages = Get-ChildItem -LiteralPath $localeTo -Directory | ForEach-Object Name +Write-Host " copié $localeDir\ ($($languages -join ', '))" + +# Le cache Python d'une version précédente peut masquer les fichiers copiés +$pycache = Join-Path $destination '__pycache__' +if (Test-Path -LiteralPath $pycache) { + Remove-Item -LiteralPath $pycache -Recurse -Force +} + +Write-Host "" +Write-Host "Extension déployée dans $destination" -ForegroundColor Green +Write-Host "Redémarrez Inkscape, puis : Extensions > AlexDesign > Remplissage motif Y fléché..." diff --git a/docs/capture-desktop.png b/docs/capture-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..db6a526694e0df7803a731f07b6e545161d4ee51 GIT binary patch literal 111953 zcmeFZ_dnJB{|A05yNt*dg(zk3jFXv$P)N39M7C^>k-d^6*`$<&%&cREGK4Zr>~pq)^%Muyw3Cacs?HY^%SXn>nb%B8x;zLqQ0h~dK-lzg?~Mo zML`CCw3ziK!ylB+8u#2#C@wVe&yhyopeXpCtnO+C?suH5-90T_tx%qxoz+Qj#&b5P_b9iLfzo9P zZnf5mi`6TO+}sfYv1cvP$&QQvCYARij4TbkDDyV z16BX`!52e%<$o{YX83aS%>Q1JKxuj8>Hl8R{-gw@@xPZmXfimFJ2Uvlmx+xr*;L4?im=k<9g!% zRZ70F#+FZAeUY4!s%l-qyLXg&dV2XEKB(&HB~1-7GBSouOzipGC@FfJ@DW?=>3l`c z$|}A-+*l|aei-s&Y;5@Vw_~xM&dz~}i3}X4Pg^{E_$&ADzgnwiMT+aDhKkCu>({Sq z>+6So|9<=Vix)W`KAbpr?%a7{;j1n#qF=v#)6vm6a!2NHWO(@OnKLMlogIx^x2hkW z>}~8jd4zC8L$j{ezV+tCix$0*_p`oGYFI`eqQVN=!Z)#H3y?b|Ji{gi+gkj%o_*!Y71Zwj-MC+DJ zfB)QHnz%TM6DOW1Tf{zpUYdVicy)!M^0k#vJ$p)OYV+5x*UKFI{S_XFv4({{QRYsd zF#Xout?Z%yB8wtl`@D#U@oU?W=cOI_`S}Z9PSrIJ53^-tWUQ^N1-^azc5;xDlk*bY zzZ0H7f%J{Kn{R)dm6m3{ckf<%R~O?cd{k7F<3rnzH~B(}inxr8O%mw1_zldDRVkj3 zJR{P(M#6#W|M_#;{eF{Xyu-tXl=k-a&9p{FM(0ma!Kczl>~Wj2Q(M1XKTi!ZF)6v+OA<($21$3YvlL^qRHJcXxuNV6{H@1_;8}S)8Ot?M-8eYU=85Y)3A5-c+}= z+KEP-}ix^my?}+gqoT;<|kcivimy(iN+uC}PoXi|{g7qjD z7guwSkdTo7n8Lq>UOa|0vTeFT{phqbjt37OoDmmiU}a@(7d{{OMki!$ZqCt{>s`vJ zl@(4Aaq(lQ-*av;f2S*8E1h_qTCL^-r z*2rOu^kad!&J;o0ix)05j`U%e6;8_va36)jOAl}=)IT1pZn@VtG<1INbKc9L-d^*) z$4;lHqob&@i!0Qxxs>z`GE$M&*40hT%vhd3vA@6H)Ye8$Lqnr5j{fiA*^!5T9D>LD z8Q1%Y zQ@g{vGdLJ!gX2Isyt_OSZ`l^Vt5f6?ZdwGNSMMv!_uG{(JQf!hUpOMc&dRqkIf=qx zFnc&$7%-Bo9z)TlLQ6A_&&xYk-w@7H7|{ZR{xT zCtZ{_k*%(-X6xwafZoAWb}{KX2`MRS00|jcQ%_IP1Pv=cvg~Y~$ROO;3kays9vZy8 zW`9pLr>4v_vVwnTWW;i@|3c1=g70ocjdJn3;>yal)i<{o%W2=>Gch}?QPI%}iHRXl zX;4QwRj+l|R(pQ_qzMXAlJUR1{$l)XZ7oMhNl8R(tYjHvN^ zkIXGCk0o6vMO8h06{UqfyjkYpgaBTts&_V@2^E%XIfym`a7G*+oq=Ahc55fdM?R6^J;tJsXEFB8Qu>?|`d zQ}J-C-)}ueOEC(`al)yZC^rq=iw!vKIsXQ%Rq=>R=rDJi>7`nsYo)7>I# zieX-Q$`#Y%EB(m~{8~A$U#s@=C3c9|?4)t7+Gtr2GCEf0=E&e1+k0&TNe zxuM|BD*B8am$gsCm=ny?cB5YP4bMfxSEErP^4+DPm_dmIjEHnit8eT^p`1g41 zlkjlMmWY!qqW4LZm6gpOKJ@;-NB(y*a*kZf?K>kY%SuT}i9EHT;j2FGiQa61DqpXx z*RNUb7MZG9vTI#}`aUBe(O>MWWNv;&US6JLL_%6R_rr$|Km5zfJ_SFP?)Kc7DY1n4 zL|4`^>)M&3U{to;7%~x=@%O6(L# zTiog6dAEQ4nV|=q^+vw{7EQ;<=y>|Aa6ntO<%R&VSWIhlV6wVjPS5HZ9p#`3J!)6Z z2H)Um$AjYH;y~zRmjngRCUzi42zGdAXo$s>hnp=QIR-~&76%IUaPyfb+1aCi|9)UA z@yesJvZOpTwMGur(Avs)J&(clQ)xnK>M?S1@)!n;4N=QtP?d*(6brgn00{qF&&JG}xDgc3I zmoF>7({1YLpoAgm?CMHyk{KDXPX!R9-|5|e9WO8M`On>}w_mbORRd|srw>*Kl@_Y=wvFFW} zMo>j-ZCRN_8X7}*(;OZW9E^-=pM6GMJ$+?pJz>;NW7UiRm02Y1PJM~ziqFqKzqh}? zV=KhXZD*#bNlisX1rHtpIPw%DV|G;)3n?k-c_AV7YuBz-3V!{moVRfmdhp`k5wl;W z0!d91=*fL2-oWUBi)ra;2`^p@&nX%fGQk1^?p<}p0Jt+YHlBpeLrY6rRbAaQFu=I7 zvVy?Mw{Q6$J$iK6Po6u+s1=&t_C;A)*}Xq+GuJkI&^#9|T+?1EF0H(J#r%vefpEUP z=c=_e*{fHtVmNIKG$=SYI7l4mBT3@rHzI5^$`bi8%1{%#;eV{}{raVG{T5SsPpUNY z++5QS@7u0`H(H`qFNu88AlVehnEkFSEp0}sBmnQFVg%Uy_U+qGpFIn9o9~{QZjBBj zvJC$kX&&gJM$w%VrLwZh)4)E93nMGHAclpJ;Wxes@69Hgt*z9oD(Bs{`1<_9%gc`i zpw0M5pE=ogM#sb?_QQuu#x)+)pFe*N&ICMPz%P-RaN!hT9EV%b;a4=bmj$WtI0P3T=JsAp6 zgGY}ZrQ>Acv#qJuXi@4DeTku)mHwm=Q=+E4ZxnF%?%kWIQq(`*XdZL+|JZ|+o}4Gm zwGJE7k;}5OD%=T^#@C~=Ot=$R2x*4;Y=o^JT2oU~L2y3q!`i|84b&A_PS*yMlmqkE z+uJ+L&Hh_F9*^ftQDNTOJ}@&s^T=U&a%m~J)_(A5db-sXS+TA_DE8|_aVC_IF(9#5 zK1y5Zy-iI=>jMJ9CMr)6QCISAXP13A)#WhyV1+U%DGA74%V)QF)uLa&epxK^X0Pq; zO5>MSS84hA-!sV65)s|@9(S`kFA#CbSkwQiWr}V@EA3Z$-ps0(siP!V0d>j4x zD$w{no=w_mJeuHjg0V28%GNF6X+XvVJTlMKIMrNr9s$&KUV2?t?@ujlgUq*Xb!%W< zSqBCN!ghj#kNRy7+}&F&D4JYcj7kx=xxX^{830M;C_wBxNy*9K$nb-@MTR)+?~`ZG zo|&$Or>4q1awtL{;ZM3Q+R{dzVVaTu@ncw?F%9sXm%zS${$!$#jmxwX${vGKkI5914Z9IH@Wc;_%t~fY2gzrj)z{MtwQP%vu1J^a+T(_)9JyRyX;}EB_Osj6!otuL!K3oa7j?hg zv9me{4wag8g}R;iP9lun90yHNV#|o5%GL-*#nhB@dU~3Uiz{B-rrW%oj_YMgibel| zsKZBsiLr4^p;6`izds9M};{C`#wfWaCR%rMjFf^_x`0Cu{Py6Py@w-DEORU5FoKRgAwf}h& z@3^R|WCYJ~>yUoLae_^f?StWVvPTidu<&QG%r#IOEY_cW`XtuO%_kWB>eQ)I?$zeD z*4AMzGu%3W$3A?x+1JG1+S&>S{|g}62ezf<R5t;c|qk6D3QaJ%j3loEW z%SXXum5KJ4wJDwT8pp$M09iF7VCePhR88O2<10(l_FRrRJoA@ZulmcQ-bg za@3-WZTq+%9Zq9|`FWwETUg~a{83%EYZrv(x<)uyotYpKr1@^8MW{tHSxmP?a&X^N zTqFe>=w{$RW-G#oe`(2s;VRa z1J)`lbJa$=Ub--UC@ds(K*orpr2J9TTu&yyA@5m$i>xUr!BRlS9{yNq*_~*MsHi*K ziDdCrCF%9M$A?vrm`V&-C4JJAuFmD{W6yaB&J6dm1UeAI?mW6t@H zj*iZryA1s|c&7pY2w2H13`HHIE% zzU;2@6Uf++prH2lDm(Y;P$ocj0RaI}(`)PNqL)lXAGALeDtt7O^4H8-|Hb;>%mlSh z`y2Z-Jyd;;? zX@1>HY5(?(;gn2tbhOLXf)2;w<8CvM;GTqrS^)cDQSgyyYHp^E&ZbLvi0HA^i29^+zf2L=*{PIT3V=iCI5E7OYu z1%n_KaOZSywu-aM;}Af!Ut&)0{uM}I4I2nMGC5ps@3lMTxt>YHlb2d|HP!8oM`vYa zabCZs+V9WC&YqB#7E@Iv!+Y-BSxL!(V)HOv0a8a-&g5^iEbnhOc6FUbO|GuSzZSPS zlh}d$TSLPY5ET&F4wf4vsD%W36`PM3-<>7NfJ5;L4SjSy;n(mmw}iy0?Ck8lrP3a? zqLE*}?swGfa$mf79Jqg#&$d9Bp&*P>6kea#eRr)TFPd5B4v(Kt{cMK^$Smh6Dwmjn zo$BPOTj2NBVK7cI1gr8zfy!5Hb>YGV8RtpV{rmT|_4Ed&4qxBCpdQO+b$N+|0mw_eU(v zK~l#97CE8YYyD}3g{L#jDrq+7yZ)BvXs6B-Nsp6lZ#(_^o<~7LBZaRAog|#*^cPw* z;rviH2!35%(~L3xetuIcQ$d|ECr&XQ?wrcL^;YHjbt*tQ#a7>#Kq^2u$V^-O)dvrF zL4}YNBuj`ihmyRU2jG>QhNFRSc#x2uJ~nlD>Cz<;UYvQTd zMvKPVRvnl3+jDMA=E^!$J8H`k!ynNT6J9^L?wDfGD3TV%9tZMh@!-nX3&nTG(KM-@h0Bo)RM^3!3cBEuPuEh0LAb?Sc9gl9Ss`Y_Vi$!XD2!hUkx9cEYH@7zoeU1B`?4Y)-GqBenaB z1qQ|DM_?D^@T6ZmJ5L-T5Ll!=E-fxD>c9xT${C;`vHJ~p52=b&;NL`5G`=?^r)FTn zZ&Pq%W0Tb3)~#DrPB^i~F-_1#K%b5Q3qaHFui#eNsIjl}94tvPt?LCbz z`d}8{8qM4cN;y!6Fe06-tQ?QLJO`8@Fx{tDf)Ql2Hr2d070#8VeI5>S4?j;tew&qz zjpanW|K4N>?HUXK1f76{ews7rA%(Hv4X}Qs%fM73B3Lf$ z)Bj9-nTbo8@FD<8c{EaCl7<;KCfPf_X=81De}ZrY`(a3?GQBxz0J1rN+6|i^2(a~{jdwcmyzpBL0pKTxDrkrM& zL&%S@fc5%pp;d@5cdR39&nj*2J>!TsI9FP zk-r3mA%r}fdahDHfFeMq_3c5k85kkw1q6a)W2vE__a4aWpxcaos`4W6VtJ&}vg6sg zy~9;Zyh)7*YerZCOb90WsNN}yoWn3$uDF4MyOu=4;ZUu&I1KL-SFg4?E~h3YCgwY= z)*qfWb7So4~E?WF9c*LU}NOS%N$~#|rKieX)#J2y>f%(mWRtaXI(% zXI4N6O789wAmxW#<@6>os&rJlbt}%+h!}W9Bk%UmuMx|wmnHDzR4~KA-T>%h(e+Al zZ!Xozd2h|a%f~xq6qh-OjT3(M35Kr@AuH>Q{CW$+-pB+Y3@C~@h)!NRzidPwe&>ak z%g9{5Z~WV9kDR2bvvX;GTlh+?kISuFG!>3xQQ@3E6u_ig0S|h@e2t_^RP9GQ(_G;` zih7-wXEFHEWDlsbs^^h^+fq06_pi-Mzk8slK)di9_vUB1WDwYJWj#4K!(;Xvgh+s@p+nnyHPEHVU+PwjUCQ{>S_iGZ&H=Ha9jp=9w1%K`N)mSX? z+^*0Uj3S%>PgjpHAT3>=lb%0+f~*bLa9(pMHj^_mKYnSbN>E5jOY;D_gWlbQAQy?u z%-r1E{PUoHhaJ2SZZ`28J7>_sBPF!*q8oF3u7@F=xc?1@DK;ZsP9++eW@Kp!B;6;} zeh!ubF*@mbC|C+A1q0mBQ$(*~=pN00gtoOmn3JDRF;d~sT;VV>`TO@1g#ChMgADn^ zAk{;XOcXC$3v|h~<;sca`h%6`D8`G$Zu7TtRZvHdg=F2v9k18D85Px3?|)Ei-StZG z0s)@dvIk(*PVucv^v(w@kvVd;g`^}T5gBwx13}%V(vSS>0As0Ucj=$FU$?&Nv_z?d zqBuciw}}=%nKWiY|++Uw=MFv8Qql#*X7W4td!>v1)?tLP; z@#0b=(87el#Xlb^ynKCUkbQWs*V6z-<(gqpCef076^F%|66dz3x19#w+Z6lZT)n)# zA1}xNXB(>bmm{o&qs@_i0UC#nfx%F=e`LNdFf|Dc5RMV1wl~8?jDP~Mgi|2xe_8FF z?sOwLS4*;4KqOQ|gels6K?JJ6C%?_%PQieT>+gvC!?=#bsp)BMTSOYtLK8t4oaDUy6sbzv~dE z$eoh`Zbm|6K~YiL&hm&$kHW6`_TqqshK8-DFAynEEX_eTLXa&2jP~~S%=gP47MGSX zJn}t^Zr@e-<)2$G=T7msFe(|mn5xb0iO7nvI-B@}YtP11qe(_jz}v?3pqIPl)JDWG zJ#%O`K1yLMUaZ1tA`S#zsa+!I*ek&bKV6hNv1EvgPFF0$acI!Kji3N`I+$ z9;S@N?AIiu8y4I2a6&bbfqRGYI{d3OkD0?}U}q=(GMo7YDfsS8{<6tz1+m-d^35uw z?e=7}zR^q-LB1XMnCt87Ijz?t{%!h$oQ;i*wQjjp^PeB?Ma0Fa!w{?)0a7r9)Rpvv zUkE@>I?u7k%n!s;rXGJbjst`qu_Lz~?R7p_)TfR!GV-mO%E`+G#l`Ilz0tCzHql`- zl2TI2g^qL%HESysnL`hwL7V!JBCfXlHUO8W(#!%i?<+=J`c+Eym{5OsAPhEJ6YL?a z9~3;|VJ*V}2IX`e%72;`v)8QI)21pR0+OFO$ma&19#HCkFbIO7m;3(x;+q2;4mTCa zpV0tl|Adw<_36vH#hN-gM0w)ai6Tr0KNbw@7s6(7T8cOl;=u&5*md?gD9KG-T_$Uo zsGs2OxU5Yo$>V+}B1om4ux}6kx5xWT)qYXyqI!Ue{$rHfi;6&PV0FG2In{+ee}2lg zeAuIsOV*W_u=N&=pd18#!6Ofk{`~fX;UTjyh=jwvZy;S_d^_01vaRB?nWLjnMZmfl z9u6Ihdv$)smHeXmVI+iMfvv4|?oo(V^<)R{=p?Hw&G`6udv|x3;aK2Wu}H4xSGlIr zLVPQ<$-3v55szFPGwlZ6|6tebQTytjKaoJWo4$Uff+y_#<6aC}%)*)o$hazeiDxCZ zkM69D9R~*l;C#$Q9{Q9(P(BebgFv=hX);0JHZ=YPy6*hgO{I%^o)&b{&QxjI0{z0K zA6n?xzTB(L0QtIh_cp#2X&dVE*>3Lad{KyI+KJxG6s;vtkK=cCc0ealQ^_Tp6JrHa z0uYJY4`o}xRkzYFhr$w4-Ti1B1cv$O*qGD12~}Q5NhL&rG5l{acL6y7=v!7)1`lJc zX5x_M?_g0If*SyiG*V$55;S<7cb%E3d4z<8!(lHW<3YL%aC-zh9yI2=llAEneZw|o zv5Ja{YBS~KX?*DM2w5N9{?bQTK-2mc%X+&T3>hK3@Jk<%cZ0)biJ>8h#-S&6aY@nPIvLn7ys zZh?x~`uxJ3HK5(o$oYgJI-WiKPu43N2v!Ca{Gz@*$_jm%ST54BNd%tsSQHDAP#AU5 zbe!BuAVdj(dDIkKkd~A@3vJAIccm5dHxjVMfb~Z*ojaS;Jw<1pbL0aY`EXjUFaEn@ z;b{C6t&I1^gPIX=;XfFErbnn|s#AR=IBd7DZ!?REEQDUMFOSvqEHF=ejiOQ#y$yo; z;K#A_jG0{Exp3l`%j2UW=%^D#zbNxHoBVj&+|lvw&g#gpHX02~N5|J}Hr|{t-i3Cz z4d3+j@wuO$nVF@@op9#NnclU7p&^4&4Dk>Q%+=f2i2Pl!nJhNvx)53cRD1$jD?u} zSfLmp7NGjbIL(~+^}Rq<_2;HshWITmIS&r#v5aLM55(j*)>KTof80a3b`QStm6_wi zNF-E4tPXwv*(-!50ilgymyS~jj@*9-$YpZObE5Tc5jO706A}ptyj0t(n|us{YoIAp z*f38e>gWv&zyS*i55F2dQQ5UQ!2=f6=7c$#IB}aWb4(l?9!@@OI5t`>iVY1V1r8`; z)6H=+Q}MLEzCIYyC;dKxA3DGYHL{WHSCX2lL39yE?M4$9$SoP%JyM-vHm-NRjAXi^-n*~aNQCV>$4D)p7i z_M#qg{?MDWad;C2BDfy8S!c}F+*^K?+PJJwtKCeK(Q!V(y(kBLQO0NMJW?^pI0EaN z@zg%(Bv~7@SG1i)qNtAdfxQmRYUbVBj3$_(@r$qQ)^Wl%&Y48AeH?bM2xE4l6I#{j zp4Ekg2ym(`e|@roS%dhi;1h!Xr>-6o4DIE^DJoq(y&O0}@G~{EwAx^-(6O^02ag4& z#s(Ri4tX&^B~<=^9WYO7km{Qw8ThmG3r0qNf=>da-HdFd?`mD;9nTcG=D{}dw>@bm zN8j1o*#%dd3hv*Yp8p#?G$hl={1WN_#E!EK6T~;G<@URdzkmOx7+zXlUT-+I>$z}T zS8L58U~V-JU*ox|B(-^bc>glyZVv_wa@(KMxr>9J6Aa-MX8^)meu??B;Vj5q{aBDk z(9~~T&F^5j66ATNS|Mn3%geD-7E=(R35T`@Njk#*Aa)vNYZw+w+?M@zb8UYxb%MA* z^B-GCoPb9zaXH=N1d@MXAgVJH4N-{BE1H^uWtUIGWCk~Ma_SFdq5egKvsJ(sCNM+= zsA`JI{e1pz2918H?jsug@sbh}=D;Kjs+`Y``>rZ9t5$yjMuwm^csE~e2-lHtabcPV$D?oUR3C_- zH+S_3KNCM5>vW>R=?P$R89vR=&Q9%Oi3%{$`utDx<Lx^)A&toSb&K|4dE> zCSAOHALzD0sdcRFxsMqV5LFXMy58&I|7=1b=UUwAOZj^eTH(-#f{u}o$k&?|wPlP= zTLO@=_}zZeWXXR}6pfsUiF|P!1YJtJ*6Xwdl5#8y2J8^fC+D%WK!{^V(6F*PN7ydH zSahe!dJzwI!JHYMtAKMJ6cps_;lWh)ciU%aT+sBl1z7PJ#Fu8hU+|SLCcwET5Z-%) z@4tBdd=eDr=F!h?>wxdew4HX{&MRPStHW$QdwfF(({@mT|ylp~-e4n9rI6J#vadrJv_r$jsg3S;M0u?Hzv-4&jK0*+76ue1< z;^ut(NCVb)aaq}ty9f6j2!!35G}~rMT6%F=_XO{jo*r?o00APy88Nvqv*BX%AD}>B}JjWy}KNU#3bajDh38J zIk^*G0EtgQBr&U~o_KTN_Dc8kF4~kh+-24$O(dK?eflILV<^~VjiBFwLty*pk;E${ zkPbkM07aAn<(Igi0cvIgc6NlR zaP!}V8Hvo>RFNYv8jv@G5cN0KQ>xffn=WP0bUoD{-L=_Bz1HQ7+puaR$bSCJ0^zm~ z9|BTOr6IP8rZC269^02|G+(J?;$V`ByBf?zFqj^$AfPJko+|0BFM5S z^CfPpKHyH&Gc$|tQ9L+7TqPc&(-i%yyDUQfSyJSj20_*PJ`xkooQrjx31QSu=n8Kqt1#e|F3qFaGP_iX>6zZ{@#~^csY5-2W2E;D6 zzP|n&E`sbBq@W=#c7LiV6u5v}P3CD(+^E^5kcsHE*2st_G=p(%N~{hzgf;}b_EOGM z2vGw-S$sQ|1DryTu$f6TC*W~IpR8`AZer+D*c4%`-VhKFKq5W&XTHRORrfx7tm7A} zg~b$@i=l7{0LrAcE<9q#to{+}=%|lV=mb-SscA$s!>tV?Jv~xpW}7}t~Kxt6A-WzZeDUv#_)w4}ZLAY--9G`9z=cY;MjP7MB)e6b_oxmr2SE$L1=ajd~Gq z^XsE-J!j9KZx`WW?ZH6L2lT4S9aK~#%p_z?0TMj~J+o_TM;9s}d=8YMtuch$!rnd_ zsGv}_8ec557tWsm^u}sDEtiMOA#+M^tO41vsZ}m>uPtK;@9-tp>o{xES$C)P+56Wg zq!$Xl7btMnl<08!==IEunHd06R$19LFBZpwHkIip0yn!mT`qihcw%m`_wRO){CEct&)fP|v_qOXh&CKqGZ@Evcz0b+vMyzf?M3ZTOs)a3IzTAf=87jBGo4Ofv zWbil!L4=SGJf3v@+`blsyz#U<0M@?(BN6bab`+Uijl^Q$o(L2K^whH=B6KM!DGp3W zA@AaX-*e$W2XLr_od_DF-lV5bp$A;586yfo$qdxe(BMV6WJbao=&^S&53w< z{8I}G12b?fl#GpQZJ(LF(~Sbm)>tua`h_3&*xecI`pRq|V+~ycjG)wv_&eR{SZzR< zNmxbW3+%;tY#ZmnF~r}2I76eonwlDddCMOD@UhZ4pF3|&)zCQq=~L;5 z{EOS~R9o5;Ocs0KJJ-~DwU^Aal{jTOD>A3t3@h(Z;P1Gg00cZp5@>H#j>9g!VxVBT0zK8*tJKq zuCih8@!5S6+;AP@1eYQQBE3M|O&g*%mAS<6l_+-;Ng(i-UZRU`wAtF(DZ6h?=!`BZ z%L3z-ueu+ar3r5(R(gV-x-La*mZmdR?k)hm{{U6x3*vo40SI=ltu@om^uUx8JRM@2 z_5F`K;1G7j{RN)pX--i5z;dx0nlp41x_;xv8e-gmqxkgOYFOrF z4R5k&=KB(Rh==33xBs`O1f1=@J3G>!V9^oz-Tlw)#$KD8pa_+~$m$M+WOs`9oRN}Z z>cR?{2}_EH#1{!Ghle*pstcmE2Gx%)nEFkTHj`9CKqNLc7Et$_Xad<+L4aqPo6 zVL?G9NQA+>0va7L)f_(Y-6ewT6$EiUnAWj@i9$c>Tn@LeHmNT@gR2VDM8YZ&i2t5Z zhHxo1fFRfOya#g{_H@ED0I(8-bj_icqY&{-LQ*oa;)kuozjWo{?nEDZri}!lSBE{zfa6Oir%G^zUXN z6*YBZvBmW9KOkmMtMxEdYQ8*UaPCA^0J962zd46*HEY~Zvs`?36J5xrLf&ch5Z~9= zr*ZS<(uPaKe(Ch|eMHpNl3yo*kdtGz|APmw`&tJs7ho|2$fby5FU%uJQsmSkGihh( zm&2`hkTi&Wo8d#%Bfoh9qO?ArlU2u%@-%w=;}4QoKrjs!zY*Q%0Ml31;oZB3RbDz? zHjtOM{Q05&-fTfBQ)i~I4_-kS%>{BYat$u3hPjh@8KXcvr!>;=6|MCgjs1Zm-_fu;e{8)AXjWcvTiRe2fdb95fXTTL1n8R-Rw;HiJ}^l4~}^pP!V z3soR1zml|n`sx*UkUhtDJmKiRvblR)=rzdJfMgdUX0{|ILi#46kWQWY?^%tsQP{`0WPcBBG)emnp__3a8FZfonDK+eIJR;ARE&CgH* ztB0F{)J2e$I_vJm;^*h@0@soJHoK&O3bz(pGC`Qa= zF?Oj(4Vi>3eu(|=xYEk);&x|o@eq;V-57zpQ~)0+C@8Mj8M478xRZ1&6rYW00E1k- zc;oln@5$dCiO7{Ncw}mJ_SE_nsRW8}6hk=@7}%Rf6C(jJ=N8Gy%JQ5M(e5VOCJ|^ z%&p2CbD6kJI>$AN6E>}Vl3wExIoy+%rsnM}i)sK`8n3X!0-lfs3!{2J7szuDRPWtm zm2wz<0_uci=a5T!eaOtxQcQVI;Ym%`gYkn^9)AAHbOp_0$Ya9it^?smBxQbKVJifb zOB~0lO?}OBy1(}Hw1Joa8bjbUokX>Zu{6Agvzrrl!M-AQ3n({?ZF%C=n3e}8)Bqdc zAOBJNRzEAp(VP8W5eNW-ZxTi#3Z$R1D3nOY88WCA&)k7sn%7YUh1|5@|pPw8xIrCR8EAs`?J?fjFW?ybX z%`TJ~0;FIchR8&T=c*})Y``R49j`399owb4(cc9VeI2ODO!=Uxy<5AJjd8W#z5co7 z*>f+?3_b^)sq!CI@J}ShN{`bO4r}x$!#r36>vS^RbNr#(M{Ll0tUtk*9c&W&kPFz{ z+ZXJ>^hLa|L@mWgAnb|@jD1d^g&lQ<}4$KUyIFK1_l|Caj=mlCYy zzxsBH#T^J?;5Gx~vkn!#opOEx>T?G5YNj(q+|agYm5tcyfC%sixmKH3JgGeL6) zZ|=+6LcRZG0WN^%_UoGh&wi}8nP*_WFx+UV-RzbdvUaHn`dGFCmL ztSmZbr@dVRJa9_n;tAwLX>%L^0#M1xjTkNXPyD|RrijtkXF{$cIe>WaQq~Q*>sEbu z7;zbn-_cYlho*QmVQ5YY2267p>Fzp_&b1Y&xqRCK7SLMZ7KwldHm*5RrK4?M~OV#DoyGb03pp;sYm)(rSb zjTr?R$31XdE5iQ7FNd&5ei-bQq)7tqP9<`>CD;OAuzTMcVeai z`8t&DF|)Epo|f}4hq3O!M1*_=LTz*oOguHi3k%ocenLUV&^*2;f*B92+xzbwKp7tL zU{g|95&62$?megiL)DM%<7@d7M8UKGz++J7^EkB?3u^oHH(@M?NGp~=z^(pM4k6Rn z92R=zox2!*yrY8^-e!ohi@#zEn5+Nt1YiM4uxa*qq%GXNg!-O!TU$G@jSIs8eJ9A) z>lDhsz`%Uqy&lr+D5a$tu4Ruyf_43$zrR^S^8sL9dZ z8S)U~+RqBFv_9iU@TEt3kmn^L^bIu}5J6}b{6mi5ym^7lNnMc5u+7Vade{p#9xsH; z0wAu$>Ti;FdkRF+wqvyNsCQ+D@#@z4Ou%IM?XYl@<7Mjct3NXp{mD}9-TRjX2WZAs ze53KdZig(jFmWaxE%Yk>8gPdYTE&I+-8YTP4ME2YO74@w?TiOo+b4O{Ct;miAXD%2 z*~UctsUlGU20s$QC3dpT;JUg(wdN|TywRAWa98G{0g5jjFfP<1V zc#fVD$bAGr0(O&y-13SQTT)UoZeCv1-Zy=A>top}IhJtMlXHB0JQ%JQ3oQMrspLtx zEXd1CGV>*F`Gw_wV=Xax*w)LE{Jr+H<5zJ3#~xuthiqLaV8e zc3^<3tcU@2ib}0=D}6!z66)Eti^9TfU|2la+w;mT0vELwE>|JgYE9JAa>g0*d`hXh z0Hz@6uX6dHV&J>k5G`C!Vb9JE_fOd>E?zp{0yxZNs)@9A z`==2_Rkn;q|7jVLmpAo|jXA(7`Dwk5+!R4*otz%t-qyBZis!28a-t*l^vX(;?6Gg( zzQHM`?5hxm3}7nI2XUJiTFn(Lq;X{8j4TO+Od@muCQXL~xTFT%W@q8x`y`UB_+U_S zl$DhgWc1+5UAks_8k#s3aSskK^WaJa_3IvDc5}GeawTnG55|+FeIC04`ou&Zo-rv& zrY{H&dyF7^xSJ<5v1;FEE_ z49HU>S@vAAKFBZ8NPDS$zGdy?QupINavBl#SP0CT2fpY1oUruV)!_-gBNN|Yc5-8o znh41VBt3rwj))OLMbdjnkR1uA7XJBba$gygV<*$){hBwU&4ZlWG zhAPMO2F;tDUf7t=ynF_;QB;J{)qVa|Q+a=PwI>p+=cJG*b#?WPbB%D7>>oY%TE7qK zzm#6c8B{OoOt#G_CMG1$H&pg8@v9#O!UTIjzC<4{_FtCX*X9!zrUh@q;pq zQav#vBaT*a4+S>gi#G5IrzRU#7UV=F>38*L_9R6C^^p+F)MyD@`6#`JShx0 z`PHEzyc2E%DijgNdBnv_MX5*{gIrPcKFx4}0nbzFh{ZVIdf{T?h zQne|v+;KUk-hbcu{_S_VR$@j@PEPKN{gDg>AcZ%ogqs=^CFb%d9z0SHA-}|^L&*EV z(heJuiDx{E8QXwgmeK$K7=9?mIgSV_35$d+-Rx1wId1=^Y-=4 zb+hpyz{}vB9Bxk3IH7B2EI%9`$3&%EXL z*O8BE;<@1WvaBEf+uhOCS~ybKhc&~hml-SkzZ)=*j2;jN0i!5$7Nn3OM7q3RX#tJo zLxBIjvsz&fR!n4kBCUWG37<_&O#)PR-WN+wpe(->xO~X%XM}6CN-02BoyZ zMdy--Klm;gmPKq@aVqsQv!Qt1U%=Q0FiDOk;!D4hd;+l;HWwcR(^dLi1|&pz_@$E> z#HFOZRFzn!e7YLXsq*k4E5EgcMcm0|J>HI3>%`x1CG@O>J74JyefX<5PKBQap?pdN zWX*~waDOW>8X6Sv%NJxzV2P(7GH6#2(u@97T8bprxG!HeoLvWFx3N7Ub>;^90Y;^_ zZ613T*)Yt^VW{$1^%Izs3nO$G9v(%q6D;|k{E@5!XYj@EiLQ)V zCAN@}YX*MSj?m$`D%RGWj*kEEVJS>Nf)XkhKCRl#Di4>JmrrtVbhae99ivyJ_FNfl z1oR3S$p#L%-QRSuilybrBO#(he4g)Y6Zdn9dNBS-m zf3%?e=FtOPiA3I?t*xQg`oSkJK|j-c_IKvTy$s$;rwK)8H#f`f=$M#C&#zkkJ9-;; zpWwHfiCxkY55C_=qF693ksY9g119Rf?=J7V6C=xaimJqC+m7O<(Yqz0|Gupav50mb zj~^sQR=}wiWcqHqL%g`8WNY=~zb`oo8aB_hA}u}pvXtK02sY%vUVsyYs2jOuWzS`; zEiFU3Ql)1G?waWt`7g^WtXmEF!Id86j1UWaRY~W@J4o-0Vte=^(^)$CBI~@?=}Tkf zGJDz}diEQ==_P+Njiu9XWOJ>LCuyQVni;7jq?|AWxTnA(^R(uJ1`sAltJ-~5%syy; zAci<$$C)l&0h8aY)?uUqNwFGMIu^PeVigxQH_f<^CWc)nB=T$CuEEyTDFhsD-z~Er zjC-ebiOCX44?|DWd(+BIp|%Hi4yRr@k|_0uLfqnKp;1Y|p%3Kk=e*wDN~b${vXR$H zj~qtY>Dt=fA3d~ue0(hOULx}$_uy7^vYAKLhuSnZ(@MuN5%_H&w{G&%TeNkX>FDXT zMv{}!sB59ow>p1*L7--P_uMUCt!tWU*m{5Vx_8%9{@X5oVi?YIb(~ry{KQmCS=R)p zzoMd|X+xm2tb@cZcCC%FIcLsl0}z=mPE6Lk0rhCO4EePM6nxpN@#1QUr-odXS zNlk=E!&{fOmxF{2q{a;9j8aPHyWicUm$Sfo&9T9iK(%`*uFw7-vfcwO$F~0;zY-;+ zg^-p~veMAfuu03xD5Sb8L?NlDu9ip=BJCtpNTnjJtDVv^lJ?%(dtKM>eU#^Zp6~zf z<#j)==f1f*uk$>QvMYXQ}t`k?TW(l4<0Q8k$i=&9BBUH^MAg|c ze(X#RlUYB1E`!7{8yfU)Z*(_$CBz_ED=seIf4oe1H}JHt9wuh(4OzLK*b|KRRa7~G zpM;}QdLTUi0pTPbMIRTOd-n<-(t5|=9`xs0p4+y5?Gjf=>4^Y0$*O&+)qR{kb*XlK zD!1ftR1Lpi$S)u_U;ZD)2j21Ot476*mjC?Y2CKReIR6c1f9jL17o%W0pspSj!)>^O z6dQ>zBO;o!In;8z_~a>+(WOiKIXakeMjBqcc&{KP^&T38ldbO$Y$jSfVQvovDKtK& zUGkJYd-qGJ8=X0GnzNygk)`CGro7~%oLtaJ=t-9f9-is3*Vy&%M(oP~QR2t@5LOdu zyL$^~#NiRcrWsPmyD#j}U4o~^(CEp^uQ_ID5@i3SF--~nTFM}4A7GeKkp5GmqoI+F zvJ}&rVF;EH96b5RC8k(G=SaOCk;@X8rd9yXF9$APzI1^KgE4djvsIo|FgQ>9nURWd^p4$Uz1{Yw zo+gMY;r7W*rVoe@T>s;xoqcE1{EQEO`^LHP^4qg~D6h5Xd69449BdtoL>^IAZQ5pW zu@#=AKYIP=p|G>&!v~o!pvfSz_WARekPLJMl_jvkuiht)9m~l1 zJ%0N~6a>l^_35q#j+IP!JJBi1CP%~NofDj5qbPOs=u!KA`Yp{~R@G3BzGtZz>gR1{k7xoP zI#USany@5|9t_|>3|7)j{}CgdIKmjSPGwZ^Iylg~7n2V#r>S}8XFuQRdJcO9{LcWj z$ufj46R}3ia1iY>H5FrFUwzC>VAn3SFs2>5!f{{{9}o;>x^~JaI-tY!q3-Yx2$(0m zN>nRB&ip0zJh;n5ULnDzH2wjTn~XZqP!0chd113SFZIyQYQpT9}u0_ zMaeLSySYZ2PA74)atQqMU|_<2)7jLdUpoyPdKn{sm(H{4o*w=~$G5mVP26_h%ggYx zF}C6B_%d+#asp?=IeaCYMU<`99jo0-7)#rJVo;BEJ7k;r3RU{Ju~?t;oja@+HK_#! zJg9}C0CcxVPY?P)8bFKMn=P%a1;$2kE3vcy$6dM-IM!QzCqcHiT&U^ejHX%bOP^oRpG+uNWBA(@vVz+26}AL{dSBSk$E!ctD*AUZ3`@XI;V_$nZ#& z4c)WJ1Gf3|h%!-R-~GsuY3gW~4I^f;1C`$GLO#Q~lm--3pm}KG;ZFA~M#%yD!4@`d zZtktn5AI{X$DO>mcuG{(1>#gBqahZ;-x#$BtU0s+*is^upW!S*g{3(SEZ%l(3zQ);m0dCV4!P#G-|P)_GdGeE(3{wnl0aExqxs&NPl?s&{uFPQmx z&t_Lt@Jia1s_@@q<|YxbrQ zpa8Y@qzyXR0`Dh&es_`Yu`MyEY(5ewkrlA(^ywhw<1)s%s3M30cXGJ%X!nHVAI8CW zZM}In>EziNaCuF1H?)U7dc;+A%kHXCMT`O2$=T<2&YHIqD{g*y zC_Iu312CsdkJ4rpekiP)b8z%?qC*HmY85|T$k?;iXVPx6OGrc&S&P3(ve5XqBl4jh z#hxZWaEK?m+syBmv4eGhZEDHslu?>vry>%QiLZZot$A8OIV6FLT?F#qEO021x=U%RD%_f*Ku+5eE_qQ zqb6VT*C+#tTcll-V!Z!)Z;{vqulx7#A~_hUUGc}zF|SwQ*_uj^ zSu%Ic(vuDKQC4QA>enF6A^Hx);El-nl_`;zfa{{~jDX5bbPTv$bPUi3L}XU*%iNSL zy1h&L-OHEr^L2vG6>2Y8YIzI zX@E2MjLA+(PQMpcW}|6SsB4Jj?*iwcQtX*8DjywuH4f3V7ozWE@{zPQ05wB6yy#xZ z9|2=6T&}LI6RMgmYG)0I#EI$8;OpIYIKtogrm}*7RIqZdm9qR9`Dm-WyydaLa<;#B z20zhjgm=;HjyF##qVO11AMQD?1}27(DZTYHNpFu_Bj^)kOgQ*&US+6Z2j&sncFnDB zl)87xzyw*Nq0_qK-QU_nQ|_=TMgHbe6c%>&W$sqQ3oE-3#0y%Yj7K8-{ft4D;AMy$ zE20I}oZho|8*|u6_|9z4oCw~0w*$2k?M!LUNEq9#N#TYYsZZGJD41MIGD zMo{jh-BYxC%8!cK=Wvvm<#fH_iHe`~46IGCwl2@UzZRnOH)Jvw1#I(_WBGRUKOI#1er_h@ZbwBjlCt|Mp zgtoP`Wc>KSvvhQH&@V1dN-t4*uf6@eh)b{vCQnR)h}$JVy8opD|5VdQ^)2!D;!1A3 zUHtFY)1~7W(0=gX;)uMQ+&+|i5%;5_B*6McTd3^vg0w&cu^{r6b^knoDj7hAqf>PB z<|dw`F*V&gQ?xL(S;)vTiQY9n6Z-V&ZAB~7X56gx>(@7|LAGcfDz2@FrSS9flXVpi zlQ_>J^z9N6h@+v=tU=3%qxtry?{aN#$R2(?`m7g^xK1I>L(#UM69kcBtI~}>3k5?< ziYC5&WA&@q>o7U&92m$aF81^w*Q!;y6LwV5>d`H#svSS0dUtAA&uu+upzBvMz8sJ% zu!FAw8CwccC^9;jSzFYAD`n^AK0VroYb^T1yz3U69vKii`)8^Nc(a0kwFl=2EPZ!< zy890X`^?1bE08^6`K6B`V^#{{Zyp?mRMp6imQD3SEt4bN3)$Ik9}qnfArNLr*7*wj zk$&`fQUd}0RDRu-HHY>>`X}sj%|HqH%A9<+f+XHpI1B_} zLS6)052<3>6=orV=I(NfzuyS}lMmHlCO$rX6%Zm3%>ZSO0UDLzT*IhJ?C$93VP`n0 z#>U@Lbw#e^N?y*4>BLW37EhTahWQqG;6sV@tieaGcb zGu-L)(xRf9AwD$o6W2!vc9xz^L)F1dfkJ|Xcw+HM){$I#l+8?HKTCRRQ-~Nu3<|La z2qj8C`_<7L_>HrNhm%jyYRZu#M?pH+Xshy}+rl;sV#=yeOg!Q__6^SUng$;e<8~gu zu>!!@=L#+Lo!$bq1KscI{Wy{{GBW#zhThs#mov@o8{{BZTihDz>+6mm*;rv<6ZYoK zBAnw8HoJfRya1p5Ee<<;*UzX`njU#a;tQ($85X|`FI~Dn+LP9QB%*|K(QQ1;d`L4Q z89p@SeRC~h*BF)IICG_alpkg9ZXwR+*4=Vjc>}_sCc~YBf+`2G8~#jtc8xtp5gGlb zHig&x*E_?eXuZTNR2$#$PO}*NK;sSg0w7_OGNMXJT%sCHAm~GgfWY09n@?r-CgWPm zb<2x9HL5@MCSC93HoKQ_Kr{;_^xIv znP4usI62EAy9aHRQC`QYYg<`0b~XwdRLxUnj8?zX-B{!4-Tp*NL&Mdw;(ZYRL%7-x zZI0S!WVANo-5X_A9#_|f&d$onQTgTnZZLcGzB3A%_rrJO4wz|UOzMlJn|HBas!8Ia z&W!M4B^R8t?91>dzsY!O9nRRU7}Ua*!Ny{YMHP&Ou&&oVFo@o*n@9qqT^RIUtwWkt5nzQ=18`qLsU56 zU%q<1W9_3Wbv-flNlfUXuJ_fYeLL%B+E{R2U;c%MsF+w2kdZy=>TL7wEYUq>ilbuT z(txs;HwTA?;@Sce2WuZ*grj&Z%hHt@9^jP>hsN~%D(`}?R!trszhVSmJ}?V<<;#!d z3uYG(^(d;-iYKH_Z|bXEKtY)$2sqy29ZML?XkWdz$yZ;gt7!0ud1+VJ!^zpZZqBtFotgc|8?*N-Oc+wg zK~$R(Kf!{iNI#CU5S5vR&c?91JUQmMvZWAZ%cqwNR2JQ5d=IG+%OQ{o|0E9&Hk8He zNHv?gW2H|}oS%rG;e7$11##;`s`VPNh}5f|P*worZHa^lkr3vxzf&ha;GF6m!9kf~ubzPm+?+KGX>B z8ek}riZI+$ed4U#`K?VKEqf8cip+&ONV)xV9?@j4 zNr(*(?aIJfIBgUOa<$}eoN;5Eaa_>!LP|q#-HNnZBSwW6`Tpl_JYj&xT3u$e>kP>k zL3_Slk{VK7`t2LsSWNxHm+pMLT>I^_m6^63`M6cmZl9O_pKC%^={WpY;ETU?m~(E{ z`Pz3ut3w$r1uC{&^woaG-0ItqN9kwDbNX~uWHcQS^m;-GY1qiR1NEjj)J5N4tG+;5|UNzwVYaA5cjszG*e&+}f3nz*?5 zTaDY1;s_zaS(qDdR!X5rru}4#uAYw3!Qw(%i*Z##RL~H%;JIZ@W$)_O(bU}Y%1>Vo z!JrV$X8`0~0+*fpMXuFOa!kUjkvl#g&}?1~Ty1v&b7uk&s;qwaBrMZ2ZxyGZQzuzRQUfU5&w<%08Z_QD)o=&D z%#*p?dg1@{B%qAPb|od8`Y&?#(Gl$Z&?oR~iy&yAy-}->on_g)Qy8X@=a*M=Ed%og*uyS7W00KG@IVEXTBDrakn@>DXRf0vW(dFaf z|6b@e**j$EUTw}}*DivLABE5f*98M>9Va`*r-7Ae)3 z0k+wVWFTa8!_0Q6Bo4V1896!g5k}{gEcZtpJZq&7w2B5PD5C0_JeiASvCQQ5u^JOx+x*QmW zpRE&3t+Bf7L{nThGGggm42+)M@}cA8;0B$4$M}K$=L% z8!=p8+$wa8Y*NTp$*Rrf$;)HhQUpB-doE46RQm6W>JIc`-3)vboV>jGr}$5vI_v=^ zfIyire_Z}P;?V}$&_juhgCif@<2mBpRdv`_8+3C(x!}V3s*l#qIXXegC@EZ5U)25j zZ}}W^;OI=Bcnn1#es<;taq5zA1u8#`-QMf+7l}AwdJSSSrZDlWfZ_lB| zt57#skGHq9$WE-D?|E`l9i6XYP0+{cHVqI-1Q{kjAu4ILr=(cjQy>ipFT^ z@$uoE0LFPVv@}R@#-jIQ5F6KA+uKrq?1_&fPnRKdUBHM>d`%>E;or5mxfpB<4uHWG zG0$wJ&{;-`B2K};ablg>9pN)sm6dEWQzOkesKVBYgr8gZwr=iiA;kZQXS4&N(tf;A zzD;m{?uY(D@BQAHIh+jtx#A^*h@EeZS$O@_ip)FtgIy@W8z?gf>V+sHf|Bq(`=8xG zLgS9zn~m*;$EE1>DK$-H1qHv#%Jo}%H-OMmlp)hPS=_%Op0EtU`xNz(CuCtVfcDJ?9@z+2xM=(v9O++`8Gqv9nMr)m0l(_*o7 zU|iQb%9tP+IBxE+rx_cFOC#LN*?8ss$Dsr#1O|J;fo`v{C6AI)@Q zZ}0m-<++`WKq<7>go7q5ZR%LvEd+5t%Lhk+MmE;GVhgThU(X0PyQ?pSXAKEx1G}+x zV5cifBT$Np9iA84!Et>lDr(6Yw^tRrFPQ&C<;Eso|8FFy7Wjai`M(#q7i%vtyS}b2 z#AErgWwOr`-8SSHN#V!%-O6qr=m()22Fpfbh{pds#uW^(`XpAbVZb)X77}JsfX1Dy zxn#{V;tD8Mk!T=4URuRt`QtS^;^nfGzXa?N<%aIlSkoSorz_X5x8z`_yEh||1OFxq1c3hFp9?{}5xg$0sjrVmXcBSPvIQQ=2d>U<|ceEuR0YT{EUtD3OOXxbZH z;T(#dm{`o)6)ZZ^5of$!LgKKcaUc_bWA|}06O*e(?roMGW3x!G_2dukhP*h0A1OOb zKJmD7`?i#%Y2o=FGZpja&VA6qqf@Kt3EOU%zn#je+eN&az7Ep?{M7_ab`7i7b*wELJ1T7|L+8Mk_8b52&qYea