From e02c3cd4c5d50683c89d88347cdfe6111fc49983 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Metivier <jean-philippe.metivier@unicaen.fr> Date: Mon, 7 Apr 2025 14:50:18 +0200 Subject: [PATCH] =?UTF-8?q?Simplification=20des=20donn=C3=A9es=20agents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/autoload/synchro.local.php.dist | 33 -- config/autoload/synchro.local.php.save | 35 --- documentation/docs/connecteurs.md | 285 ++++++++++++++++++ documentation/docs/indicateurs.md | 8 +- documentation/docs/install.md | 96 +++++- .../config/merged/agent-quotite.config.php | 32 -- module/Agent/src/Entity/Db/Agent.php | 51 ---- module/Agent/src/Entity/Db/AgentEchelon.php | 34 --- module/Agent/src/Entity/Db/AgentQuotite.php | 51 ---- .../Db/Mapping/Agent.Entity.Db.Agent.dcm.xml | 2 - .../Agent.Entity.Db.AgentEchelon.dcm.xml | 24 -- .../Agent.Entity.Db.AgentQuotite.dcm.xml | 25 -- .../Agent/src/Service/Agent/AgentService.php | 2 - .../AgentQuotite/AgentQuotiteService.php | 46 --- .../AgentQuotiteServiceAwareTrait.php | 20 -- .../AgentQuotiteServiceFactory.php | 27 -- .../src/View/Helper/partial/agent-grade.phtml | 16 +- .../Db/MacroContent/AgentMacroTrait.php | 45 --- public/img/logo-universite.png | Bin 2959 -> 19369 bytes 19 files changed, 385 insertions(+), 447 deletions(-) create mode 100644 documentation/docs/connecteurs.md delete mode 100644 module/Agent/config/merged/agent-quotite.config.php delete mode 100644 module/Agent/src/Entity/Db/AgentEchelon.php delete mode 100644 module/Agent/src/Entity/Db/AgentQuotite.php delete mode 100644 module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentEchelon.dcm.xml delete mode 100644 module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentQuotite.dcm.xml delete mode 100644 module/Agent/src/Service/AgentQuotite/AgentQuotiteService.php delete mode 100644 module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceAwareTrait.php delete mode 100644 module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceFactory.php diff --git a/config/autoload/synchro.local.php.dist b/config/autoload/synchro.local.php.dist index 878b9d37..9908d43f 100644 --- a/config/autoload/synchro.local.php.dist +++ b/config/autoload/synchro.local.php.dist @@ -223,39 +223,6 @@ return [ ], 'id' => 'id', ], - 'AGENT_ECHELON' => [ - 'order' => 5200, - 'source' => 'OCTOPUS', - 'orm_source' => 'orm_octopus', - 'orm_destination' => 'orm_default', - 'table_source' => 'V_EMC2_AGENT_ECHELON', - 'table_destination' => 'agent_carriere_echelon', - 'correspondance' => [ - 'id' => 'id', - 'agent_id' => 'agent_id', - 'echelon' => 'echelon', - 'date_debut' => 'd_debut', - 'date_fin' => 'd_fin', - ], - 'id' => 'id', - ], - 'AGENT_QUOTITE' => [ - 'order' => 5300, - 'source' => 'OCTOPUS', - 'orm_source' => 'orm_octopus', - 'orm_destination' => 'orm_default', - 'table_source' => 'V_EMC2_AGENT_QUOTITE', - 'table_destination' => 'agent_carriere_quotite', - 'correspondance' => [ - 'id' => 'id', - 'agent_id' => 'agent_id', - 'quotite' => 'quotite', - 'date_debut' => 'd_debut', - 'date_fin' => 'd_fin', - 'modalite' => 'modalite_de_service', - ], - 'id' => 'id', - ], 'AGENT_POSTE' => [ 'order' => 5500, 'source' => 'OCTOPUS', diff --git a/config/autoload/synchro.local.php.save b/config/autoload/synchro.local.php.save index 3205a368..1695e40c 100644 --- a/config/autoload/synchro.local.php.save +++ b/config/autoload/synchro.local.php.save @@ -227,24 +227,6 @@ return [ 'id' => 'ID', 'separator' => 'STRUCTURE_ID' ], - 'AGENT_QUOTITE' => [ - 'order' => 5300, - 'source' => 'OCTOPUS', - 'orm_source' => 'orm_octopus', - 'orm_destination' => 'orm_default', - 'table_source' => 'V_MESFORMATIONS_AGENT_QUOTITE', - 'table_destination' => 'agent_carriere_quotite', - 'correspondance' => [ - 'ID_ORIG' => 'id', - 'AGENT_ID' => 'agent_id', - 'QUOTITE' => 'quotite', - 'DATE_DEBUT' => 'd_debut', - 'DATE_FIN' => 'd_fin', - //'MODALITE' => 'modalite_de_service', - ], - 'id' => 'ID_ORIG', - 'separator' => 'QUOTITE' - ], 'AGENT_STATUT' => [ 'order' => 5400, 'source' => 'OCTOPUS', @@ -276,23 +258,6 @@ return [ 'id' => 'ID_ORIG', 'separator' => 'STRUCTURE_ID', ], - 'AGENT_ECHELON' => [ - 'order' => 5200, - 'source' => 'OCTOPUS', - 'orm_source' => 'orm_octopus', - 'orm_destination' => 'orm_default', - 'table_source' => 'V_MESFORMATIONS_AGENT_ECHELON', - 'table_destination' => 'agent_carriere_echelon', - 'correspondance' => [ - 'ID_ORIG' => 'id', - 'AGENT_ID' => 'agent_id', - 'ECHELON' => 'echelon', - 'DATE_DEBUT' => 'd_debut', - 'DATE_FIN' => 'd_fin', - ], - 'id' => 'ID_ORIG', - 'separator' => 'ECHELON' - ], 'AGENT_VALIDATEUR' => [ 'order' => 5200, 'source' => 'OCTOPUS', diff --git a/documentation/docs/connecteurs.md b/documentation/docs/connecteurs.md new file mode 100644 index 00000000..86e85b57 --- /dev/null +++ b/documentation/docs/connecteurs.md @@ -0,0 +1,285 @@ +Connecteurs +==== + +**Mes Formations** est alimentée via des synchronisations exploitant des données exposées dans le SI de l'établissement qui l'instale. +Ces données sont présentés : +- soient depuis le SIRH (SIHAM, HARPEGE, ...) +- soient depuis un concentrateur de données (par exemple *OCTOPUS* à Caen) + +Nous aborderons tout d'abord la composition des vues puis le moyen de déclencher ces synchronisations et finalement comment adapter les vues et la configuration de la synchronisation. + +---- + +Vues +===== + +## Données liées aux référentiels RH + +1. CORRESPONDANCE_TYPE +1. CORRESPONDANCE +2. CORPS +3. GRADE +4. EMPLOITYPE + + +## Données liées aux structures + +On retrouve dans cette catégorie les vues : +1. V_MESFORMATIONS_STRUCTURE_TYPE +1. V_MESFORMATIONS_STRUCTURE + +### La vue listant les types de structures V_MESFORMATIONS_STRUCTURE_TYPE + +Cette vue présente directement la liste des types de structures + +| Nom de la colonne | Type | Obligatoire | Commentaire | +|-------------------|---------------|-------------|---------------| +| ID | integer | Oui | Clef primaire | +| CODE | varchar(64) | Oui | | +| LIBELLE | varchar(256) | Oui | | +| DESCRIPTION | text | Non | | + +Exemple depuis l'instance de démonstration. +```csv +'id';'code';'libelle';'description' +1,"ETAB","Établissement","Établissement" +2,"COMP","Composante","Composante" +3,"SREC","Structure de recherche","Structure de recherche" +... +``` + +### La vue listant les types de structures V_MESFORMATIONS_STRUCTURE + +Cette vue présente la liste des structures + +| Nom de la colonne | Type | Obligatoire | Commentaire | +|-------------------|---------------|-------------|----------------------------------------------------| +| ID | integer | Oui | Clef primaire | +| CODE | varchar(64) | Oui | | +| LIBELLE_COURT | varchar(256) | Oui | | +| LIBELLE_LONG | varchar(2048) | Oui | | +| SIGLE | varchar(64) | Non | | +| TYPE_ID | integer | Oui | Clef étrangère vers V_MESFORMATIONS_STRUCTURE_TYPE | +| EMAIL_GENERIQUE | varchar(2048) | Non | | +| DATE_OUVERTURE | DateTime | Oui | | +| DATE_FERMETURE | DateTime | Non | | +| PARENT_ID | integer | Non | Clef étrangère vers V_MESFORMATIONS_STRUCTURE | +| NIV2_ID | integer | Non | Clef étrangère vers V_MESFORMATIONS_STRUCTURE | + +**N.B.**: +Dans cette vue vous pouvez limiter le liste des structures que vous voulez présenter. +Attention toutefois a bien remonter les structures référencées par les colonnes parent_id et niv2_id + +## Données liées aux référentiels Agent·es + +1. AGENT +3. AGENT_AFFECTATION +7. AGENT_GRADE +7. AGENT_STATUT + +2. STRUCTURE_RESPONSABLE +3. STRUCTURE_GESTIONNAIRE +3. AGENT_VALIDEUR + +Configuration de la biliothèque +=== + +## L'accés aux bases de données sources + +Les bases de données sources doivent être déclaré comme ORM pour cela, il est nécessaire de les déclarer comme fichier de configuration local (non synchronisé dans le dépôt). +Dans la suite je présente la configuration faite à Caen exploitant deux bases de données sources : +1. OCTOPUS qui est un concentrateur de données +2. UNIFORMSUP qui regroupe des informations sur les étapes et diplômes + +**Ajout de l'ORM pour OCTOPUS** + +Dans cet exemple, octopus est une base de donnée pgsql (penser à installer le drivers associé). + +Fichier 'config/autoload/database-octopus.local.php' +```php +<?php +use Doctrine\DBAL\Driver\PDO\PgSQL\Driver; +use Doctrine\ORM\Mapping\Driver\XmlDriver; +use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; + +return [ + 'doctrine' => [ + 'driver' => [ + 'orm_octopus' => [ + 'class' => MappingDriverChain::class, + 'drivers' => [ + 'Application\Entity\Db' => 'orm_octopus_xml_driver', + ], + ], + 'orm_octopus_xml_driver' => [ + 'class' => XmlDriver::class, + 'cache' => 'apc', + 'paths' => [ + __DIR__ . '/../src/Application/Entity/Db/Mapping', + ], + ], + ], + 'connection' => [ + 'orm_octopus' => [ + 'driverClass' => OCI8::class, + 'params' => [ + 'host' => #####, + 'user' => #####, + 'password' => #####, + 'charset' => 'AL32UTF8', + 'port' => ####, + 'service' => ####, + 'servicename' => ####, + ], + ], + ], + + + 'entitymanager' => [ + 'orm_octopus' => [ + 'connection' => 'orm_octopus', + 'configuration' => 'orm_octopus', + ], + ], + + 'configuration' => [ + 'orm_octopus' => [ + 'metadata_cache' => 'array', + 'query_cache' => 'array', + 'result_cache' => 'array', + 'hydration_cache' => 'array', + 'generate_proxies' => true, + 'driver' => 'orm_octopus', + ], + ], + ], + +]; + + +``` +**Ajout de l'ORM pour UNIFORMSUP** + +Dans cet exemple, uniformsup est une base de donnée oracle (penser à installer le drivers OCI8). + +Fichier 'config/autoload/database-uniform.local.php' +```php +<?php +use Doctrine\DBAL\Driver\OCI8\Driver as OCI8; +use Doctrine\ORM\Mapping\Driver\XmlDriver; +use Doctrine\Persistence\Mapping\Driver\MappingDriverChain; + +return [ + 'doctrine' => [ + 'driver' => [ + 'orm_uniform' => [ + 'class' => MappingDriverChain::class, + 'drivers' => [ + 'Application\Entity\Db' => 'orm_octopus_xml_driver', + ], + ], + 'orm_uniform_xml_driver' => [ + 'class' => XmlDriver::class, + 'cache' => 'apc', + 'paths' => [ + __DIR__ . '/../src/Application/Entity/Db/Mapping', + ], + ], + ], + 'connection' => [ + 'orm_uniform' => [ + 'driverClass' => OCI8::class, + 'params' => [ + 'host' => #####, + 'user' => #####, + 'password' => #####, + 'charset' => 'AL32UTF8', + 'port' => ####, + 'service' => ####, + 'servicename' => ####, + ], + ], + ], + + + 'entitymanager' => [ + 'orm_uniform' => [ + 'connection' => 'orm_uniform', + 'configuration' => 'orm_uniform', + ], + ], + 'configuration' => [ + 'orm_uniform' => [ + 'metadata_cache' => 'array', + 'query_cache' => 'array', + 'result_cache' => 'array', + 'hydration_cache' => 'array', + 'generate_proxies' => true, + 'driver' => 'orm_uniform', + ], + ], + ], +]; + +``` + +## Configurer une synchronisation + +Le fichier configurant les synchronisations est composé de deux blocs : +1. data_sources la liste des ORM utilisables +2. la liste des synchronisation (les tables de correspondance) + +La liste des ORM utilisables est un simple table référencant les ORM précédemment définis. + +Le synchronisation on la structure suivante : +```php + 'NOM_DE_LA_SYNCHRONISATION' => [ + 'order' => ORDRE DE PRIORITE, + 'source' => LIBELLE DE LA SOURCE (sera copié tel que en base de donnée dans la colonne SOURCE_ID), + 'orm_source' => ORM SOURCE (clef définie précédemment orm_octopus ou orm_uniform) + 'orm_destination' => 'orm_default', + 'table_source' => NOM DE LA TABLE OU VUE SOURCE, + 'table_destination' => NOM De LA TABLE DESTINATION + 'correspondance' => [ + LIBELLE DE LA COLONNE 1 SOURCE => LIBELLE DE LA COLONNE 1 DESTINATION, + LIBELLE DE LA COLONNE 2 SOURCE => LIBELLE DE LA COLONNE 2 DESTINATION + ], + 'id' => COLONNE A UTILISEE COMME CLEF PRIMAIRE DANS LA SOURCE, +], +``` + +Les synchronisations utilisées à Caen sont fourni comme exemple : +1. La synchronisation de l'instance de démonstration `config/autoload/synchro.local.php.demo` +2. La synchronisation des instances de préproduction et production `config/autoload/synchro.local.php.octopus` + +## Lancer une synchronisation + +La synchronisation est lancé en ligne de commande il est possible de lancer l'ensemble des synchronisations ou une synchronisation + +```bash +/var/www/html$ php public/index.php synchroniser-all +/var/www/html$ php public/index.php synchroniser --name=NOM_DE_LA_SYNCHRONISATION +``` + +Cette même commande peut être lancer via un cron ou un service pour rendre récurrent/automatique celle-ci. + +## Astuces + +Les synchronisations peuvent être accélérées par un spérateur divisant le volume de données en des morceaux plus petits. + +```php + 'NOM_DE_LA_SYNCHRONISATION' => [ + 'order' => ORDRE DE PRIORITE, + 'source' => LIBELLE DE LA SOURCE (sera copié tel que en base de donnée dans la colonne SOURCE_ID), + 'orm_source' => ORM SOURCE (clef définie précédemment orm_octopus ou orm_uniform) + 'orm_destination' => 'orm_default', + 'table_source' => NOM DE LA TABLE OU VUE SOURCE, + 'table_destination' => NOM De LA TABLE DESTINATION + 'correspondance' => [ + LIBELLE DE LA COLONNE 1 SOURCE => LIBELLE DE LA COLONNE 1 DESTINATION, + LIBELLE DE LA COLONNE 2 SOURCE => LIBELLE DE LA COLONNE 2 DESTINATION + ], + 'id' => COLONNE A UTILISEE COMME CLEF PRIMAIRE DANS LA SOURCE, + 'separator' => COLONNE SOURCE QUI DIVISERA LES DONNEES, +], +``` diff --git a/documentation/docs/indicateurs.md b/documentation/docs/indicateurs.md index 0450beec..174d1d69 100644 --- a/documentation/docs/indicateurs.md +++ b/documentation/docs/indicateurs.md @@ -24,4 +24,10 @@ L'exemple suivant rafraichit les indicateurs le lundi à 8:00. 0 8 * * 1 /usr/bin/php/var/www/html/vendor/laminas indicateur-refresh ``` -**N.B.:** Ici la supposition faite est que php est installé dans le répertoire par défaut et que Mes Formations est installé dans le repertoire `/var/www/html`. \ No newline at end of file +**N.B.:** Ici la supposition faite est que php est installé dans le répertoire par défaut et que Mes Formations est installé dans le repertoire `/var/www/html`. + +# Indicateurs partagés + +--- + + diff --git a/documentation/docs/install.md b/documentation/docs/install.md index c019eefb..64fa9d6f 100644 --- a/documentation/docs/install.md +++ b/documentation/docs/install.md @@ -1,4 +1,92 @@ -* Cloner le projet -* Déplacer et configurer les fichiers locaux -* Installer les biliothèque -* Lancer une synchro +# Documentation pour l'installation et la configuration du projet + +## Clonage du projet + +Clonez le projet dans le répertoire `/var/www/html/` : + +```bash +git clone https://git.unicaen.fr/open-source/mes-formations.git /var/www/html/ +``` + +**Note :** À partir de cette étape, toutes les commandes et chemins supposent que vous êtes dans le répertoire +/var/www/html/. + +## Mise à jour avec Composer + +Rendez-vous dans le répertoire du projet et exécutez la commande suivante pour mettre à jour les dépendances : + +```bash +composer update +``` + +**Note :** Attention à la configuration de votre proxy + +## Configuration + +La configuration à la charge de l'établissement est contenue dans les fichiers `local.dist` contenu dans le répertoire +`./config/autoload`. +Ces configurations doivent être adaptées aux besoins spécifiques de l'établissement, et l'extension `.dist` doit être +retirée. + +Liste des fichiers distants : + +- `database.local.php.dist` +- `local.php.dist` +- `synchro.local.php` +- `unicaen-app.local.php.dist` +- `unicaen-authentification.local.php.dist` +- `unicaen-evenement.local.php.dist` +- `unicaen-fichier.local.php.dist` +- `unicaen-ldap.local.php.dist` +- `unicaen-mail.local.php.dist` + +## Installation sur le serveur + +Lancez la commande suivante pour exécuter le processus d'installation : + +```bash +./vendor/bin/laminas bddadmin:install +``` + +Après l'installation, vérifiez que les données ont été correctement insérées par la mise à jour. + +## Création des répertoires nécessaires + +Créez les répertoires suivants si ce n'est pas déjà fait : + +```bash +mkdir -p ./data/DoctrineORMModule/Proxy +mkdir -p ./upload +``` + +Assurez-vous que ces répertoires ont les permissions appropriées. + +## Configuration des paramètres PHP + +Vérifiez que les paramètres suivants dans PHP sont correctement configurés à 0 : + + session.cookie_lifetime + session.gc_maxlifetime + +Pour vérifier, consultez la configuration PHP : + +php -i | grep session.cookie_lifetime +php -i | grep session.gc_maxlifetime + +Modification des paramètres + +Si les valeurs ne sont pas correctes, modifiez le fichier /etc/php/8.2/fpm/php.ini et assurez-vous que les lignes +suivantes sont définies : + +session.cookie_lifetime = 0 +session.gc_maxlifetime = 0 + +Redémarrez le service PHP-FPM pour appliquer les modifications : + +systemctl restart php-fpm + +## Mise en place de la synchronisation et execution de celle-ci + +Configurez le fichier de synchronisation selon les besoins du projet et les fichiers de base de données sources comme +décrit dans [la documentation sur les connecteurs](connecteurs.md). +Pour lancer la synchronisation suivez les dernières étapes de la documentation associée. diff --git a/module/Agent/config/merged/agent-quotite.config.php b/module/Agent/config/merged/agent-quotite.config.php deleted file mode 100644 index 86595034..00000000 --- a/module/Agent/config/merged/agent-quotite.config.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace Agent; - -use Agent\Service\AgentQuotite\AgentQuotiteService; -use Agent\Service\AgentQuotite\AgentQuotiteServiceFactory; - -return [ - - 'service_manager' => [ - 'factories' => [ - AgentQuotiteService::class => AgentQuotiteServiceFactory::class, - ], - ], - 'controllers' => [ - 'factories' => [ - ], - ], - 'form_elements' => [ - 'factories' => [ - ], - ], - 'hydrators' => [ - 'factories' => [ - ], - ], - 'view_helpers' => [ - 'invokables' => [ - ], - ], - -]; diff --git a/module/Agent/src/Entity/Db/Agent.php b/module/Agent/src/Entity/Db/Agent.php index 5a94523d..1b53e8b1 100644 --- a/module/Agent/src/Entity/Db/Agent.php +++ b/module/Agent/src/Entity/Db/Agent.php @@ -54,9 +54,7 @@ class Agent implements private ?string $email = null; private Collection $affectations; - private Collection $echelons; private Collection $grades; - private Collection $quotites; private Collection $statuts; private Collection $validateurs; @@ -78,7 +76,6 @@ class Agent implements $this->statuts = new ArrayCollection(); $this->missionsSpecifiques = new ArrayCollection(); $this->fichiers = new ArrayCollection(); - $this->echelons = new ArrayCollection(); $this->grades = new ArrayCollection(); $this->structuresForcees = new ArrayCollection(); @@ -200,30 +197,6 @@ class Agent implements return $libelle; } - /** @return AgentEchelon[] */ - public function getEchelons(?DateTime $date = null, bool $histo = false): array - { - $echelons = $this->echelons->toArray(); - if ($histo === false) $echelons = array_filter($echelons, function (AgentEchelon $ae) { - return !$ae->isDeleted(); - }); - if ($date !== null) $echelons = array_filter($echelons, function (AgentEchelon $ae) use ($date) { - return ($ae->estEnCours($date)); - }); - - usort($echelons, function (AgentEchelon $a, AgentEchelon $b) { - return $a->getDateDebut() <=> $b->getDateDebut(); - }); - return $echelons; - } - - /** @return AgentEchelon[] */ - public function getEchelonsActifs(?DateTime $date = null): array - { - if ($date === null) $date = (new DateTime()); - return $this->getEchelons($date); - } - /** @return AgentGrade[] */ public function getGrades(?DateTime $date = null, bool $histo = false): array { @@ -248,30 +221,6 @@ class Agent implements return $this->getGrades($date); } - /** @return AgentQuotite[] */ - public function getQuotites(?DateTime $date = null, bool $histo = false): array - { - $quotites = $this->quotites->toArray(); - if ($histo === false) $quotites = array_filter($quotites, function (AgentQuotite $q) { - return !$q->isDeleted(); - }); - if ($date !== null) $quotites = array_filter($quotites, function (AgentQuotite $q) use ($date) { - return ($q->estEnCours($date)); - }); - - usort($quotites, function (AgentQuotite $a, AgentQuotite $b) { - return $a->getDateDebut() <=> $b->getDateDebut(); - }); - return $quotites; - } - - /** @return AgentQuotite[] */ - public function getQuotitesActives(?DateTime $date = null): array - { - if ($date === null) $date = (new DateTime()); - return $this->getQuotites($date); - } - /** @return AgentStatut[] */ public function getStatuts(?DateTime $date = null, bool $histo = false): array { diff --git a/module/Agent/src/Entity/Db/AgentEchelon.php b/module/Agent/src/Entity/Db/AgentEchelon.php deleted file mode 100644 index f0eb4e3c..00000000 --- a/module/Agent/src/Entity/Db/AgentEchelon.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -namespace Agent\Entity\Db; - -use Application\Entity\Db\Interfaces\HasPeriodeInterface; -use Application\Entity\Db\Traits\HasPeriodeTrait; -use UnicaenSynchro\Entity\Db\IsSynchronisableInterface; -use UnicaenSynchro\Entity\Db\IsSynchronisableTrait; - -class AgentEchelon implements HasPeriodeInterface, IsSynchronisableInterface -{ - use IsSynchronisableTrait; - use HasPeriodeTrait; - - private ?string $id = null; - private ?Agent $agent = null; - private ?int $echelon = null; - - public function getId(): ?string - { - return $this->id; - } - - public function getAgent(): ?Agent - { - return $this->agent; - } - - public function getEchelon(): ?int - { - return $this->echelon; - } - -} \ No newline at end of file diff --git a/module/Agent/src/Entity/Db/AgentQuotite.php b/module/Agent/src/Entity/Db/AgentQuotite.php deleted file mode 100644 index 6c95f2ac..00000000 --- a/module/Agent/src/Entity/Db/AgentQuotite.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -namespace Agent\Entity\Db; - -use Application\Entity\Db\Interfaces\HasPeriodeInterface; -use Application\Entity\Db\Traits\HasPeriodeTrait; -use UnicaenSynchro\Entity\Db\IsSynchronisableInterface; -use UnicaenSynchro\Entity\Db\IsSynchronisableTrait; - -class AgentQuotite implements HasPeriodeInterface, IsSynchronisableInterface -{ - use HasPeriodeTrait; - use IsSynchronisableTrait; - - private ?string $id = null; - private ?Agent $agent = null; - private ?int $quotite = null; - private ?string $modaliteDeService = null; - - public function getId(): ?string - { - return $this->id; - } - - public function getAgent(): Agent - { - return $this->agent; - } - - public function setAgent(Agent $agent): AgentQuotite - { - $this->agent = $agent; - return $this; - } - - public function getQuotite(): ?int - { - return $this->quotite; - } - - public function setQuotite(?int $quotite): void - { - $this->quotite = $quotite; - } - - public function getModaliteDeService(): ?string - { - return $this->modaliteDeService; - } - -} \ No newline at end of file diff --git a/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.Agent.dcm.xml b/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.Agent.dcm.xml index 5787ae2f..0fd68513 100644 --- a/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.Agent.dcm.xml +++ b/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.Agent.dcm.xml @@ -15,9 +15,7 @@ <field name="login" column="login" length="256"/> <field name="email" column="email" length="1024"/> - <one-to-many target-entity="Agent\Entity\Db\AgentQuotite" mapped-by="agent" field="quotites"/> <one-to-many target-entity="Agent\Entity\Db\AgentAffectation" mapped-by="agent" field="affectations"/> - <one-to-many target-entity="Agent\Entity\Db\AgentEchelon" mapped-by="agent" field="echelons"/> <one-to-many target-entity="Agent\Entity\Db\AgentGrade" mapped-by="agent" field="grades"/> <one-to-many target-entity="Agent\Entity\Db\AgentStatut" mapped-by="agent" field="statuts"/> <one-to-many field="validateurs" target-entity="Agent\Entity\Db\AgentValidateur" mapped-by="agent"/> diff --git a/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentEchelon.dcm.xml b/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentEchelon.dcm.xml deleted file mode 100644 index 3269d0c3..00000000 --- a/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentEchelon.dcm.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - <entity name="Agent\Entity\Db\AgentEchelon" table="agent_carriere_echelon"> - - <id name="id" type="string" column="id"/> - - <many-to-one target-entity="Agent\Entity\Db\Agent" field="agent"> - <join-column name="agent_id" referenced-column-name="c_individu"/> - </many-to-one> - - <field name="echelon" type="integer" column="echelon"/> - <field name="dateDebut" type="datetime" column="d_debut"/> - <field name="dateFin" type="datetime" column="d_fin" nullable="true"/> - - <!-- DB IMPORT ############################# --> - <field name="createdOn" column="created_on" type="datetime"/> - <field name="updatedOn" column="updated_on" type="datetime"/> - <field name="deletedOn" column="deleted_on" type="datetime"/> - <field name="sourceId" column="source_id" length="128"/> - - </entity> -</doctrine-mapping> diff --git a/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentQuotite.dcm.xml b/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentQuotite.dcm.xml deleted file mode 100644 index 461e7894..00000000 --- a/module/Agent/src/Entity/Db/Mapping/Agent.Entity.Db.AgentQuotite.dcm.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping https://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> - <entity name="Agent\Entity\Db\AgentQuotite" table="agent_carriere_quotite"> - - <id name="id" type="string" column="id"/> - - <many-to-one target-entity="Agent\Entity\Db\Agent" field="agent"> - <join-column name="agent_id" referenced-column-name="c_individu"/> - </many-to-one> - - <field name="dateDebut" type="datetime" column="d_debut"/> - <field name="dateFin" type="datetime" column="d_fin"/> - <field name="quotite" type="integer" column="quotite"/> - <field name="modaliteDeService" length="1024" column="modalite_de_service"/> - - <!-- DB IMPORT ############################# --> - <field name="createdOn" column="created_on" type="datetime"/> - <field name="updatedOn" column="updated_on" type="datetime"/> - <field name="deletedOn" column="deleted_on" type="datetime"/> - <field name="sourceId" column="source_id" length="128"/> - - </entity> -</doctrine-mapping> diff --git a/module/Agent/src/Service/Agent/AgentService.php b/module/Agent/src/Service/Agent/AgentService.php index ef739346..16c61927 100644 --- a/module/Agent/src/Service/Agent/AgentService.php +++ b/module/Agent/src/Service/Agent/AgentService.php @@ -49,8 +49,6 @@ class AgentService //affectations ->addSelect('affectation')->leftJoin('agent.affectations', 'affectation') ->addSelect('affectation_structure')->leftJoin('affectation.structure', 'affectation_structure') - //quotite de l'agent - ->addSelect('quotite')->leftJoin('agent.quotites', 'quotite') ->addSelect('utilisateur')->leftJoin('agent.utilisateur', 'utilisateur') ->andWhere('agent.deletedOn IS NULL'); diff --git a/module/Agent/src/Service/AgentQuotite/AgentQuotiteService.php b/module/Agent/src/Service/AgentQuotite/AgentQuotiteService.php deleted file mode 100644 index 42462257..00000000 --- a/module/Agent/src/Service/AgentQuotite/AgentQuotiteService.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php - -namespace Agent\Service\AgentQuotite; - -use Agent\Entity\Db\Agent; -use Agent\Entity\Db\AgentQuotite; -use Doctrine\ORM\QueryBuilder; -use DoctrineModule\Persistence\ProvidesObjectManager; - -class AgentQuotiteService -{ - use ProvidesObjectManager; - - /** GESTION ENTITE ************************************************************************************************/ - // Complétement importées et jamais modifiées - - /** REQUETAGE *****************************************************************************************************/ - - public function createQueryBuilder(): QueryBuilder - { - $qb = $this->getObjectManager()->getRepository(AgentQuotite::class)->createQueryBuilder('agentquotite') - ->join('agentquotite.agent', 'agent')->addSelect('agent') - ->andWhere('agentquotite.deletedOn IS NULL'); - return $qb; - } - - /** - * @param Agent $agent - * @param bool $actif - * @return array - */ - public function getAgentQuotitesByAgent(Agent $agent, bool $actif = true): array - { - $qb = $this->createQueryBuilder() - ->andWhere('agentquotite.agent = :agent') - ->andWhere('agentquotite.deletedOn IS NULL') - ->setParameter('agent', $agent); - - if ($actif === true) $qb = AgentQuotite::decorateWithActif($qb, 'agentquotite'); - - $result = $qb->getQuery()->getResult(); - return $result; - } - - -} \ No newline at end of file diff --git a/module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceAwareTrait.php b/module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceAwareTrait.php deleted file mode 100644 index 00edcd87..00000000 --- a/module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceAwareTrait.php +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -namespace Agent\Service\AgentQuotite; - -trait AgentQuotiteServiceAwareTrait { - - private AgentQuotiteService $agentQuotiteService; - - public function getAgentQuotiteService(): AgentQuotiteService - { - return $this->agentQuotiteService; - } - - public function setAgentQuotiteService(AgentQuotiteService $agentQuotiteService): void - { - $this->agentQuotiteService = $agentQuotiteService; - } - - -} \ No newline at end of file diff --git a/module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceFactory.php b/module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceFactory.php deleted file mode 100644 index 8f186583..00000000 --- a/module/Agent/src/Service/AgentQuotite/AgentQuotiteServiceFactory.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -namespace Agent\Service\AgentQuotite; - -use Doctrine\ORM\EntityManager; -use Interop\Container\ContainerInterface; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; - -class AgentQuotiteServiceFactory { - - /** - * @throws ContainerExceptionInterface - * @throws NotFoundExceptionInterface - */ - public function __invoke(ContainerInterface $container) : AgentQuotiteService - { - /** - * @var EntityManager $entityManager - */ - $entityManager = $container->get('doctrine.entitymanager.orm_default'); - - $service = new AgentQuotiteService(); - $service->setObjectManager($entityManager); - return $service; - } -} \ No newline at end of file diff --git a/module/Agent/src/View/Helper/partial/agent-grade.phtml b/module/Agent/src/View/Helper/partial/agent-grade.phtml index 4bec9d24..3d102784 100644 --- a/module/Agent/src/View/Helper/partial/agent-grade.phtml +++ b/module/Agent/src/View/Helper/partial/agent-grade.phtml @@ -8,13 +8,8 @@ */ use Agent\Entity\Db\AgentGrade; -use Agent\Entity\Db\AgentEchelon; -$debug = false; - -/** @var AgentEchelon[] $echelons */ -$echelons = ($options['echelons']) ?? []; -$echelons = array_filter($echelons, function (AgentEchelon $a) { return $a->getEchelon() !== 0 ;}); +$debug = false; //todo parametre !!! $displayStructure = (isset($options['structure']) and $options['structure'] !== false); $displayPeriode = (isset($options['periode']) and $options['periode'] !== false); @@ -103,15 +98,6 @@ $displayCorrespondance = (isset($options['correspondance']) and $options['corres <?php endif; ?> </dd> - <?php if (!empty($echelons)) : ?> - <dt class="col-md-3"> Échelon</dt> - <dd class="col-md-9"> - <?php foreach ($echelons as $echelon) : ?> - <?php echo $echelon->getEchelon(); ?> (date de passage : <?php echo $echelon->getDateDebut()->format('d/m/Y'); ?>) - <?php endforeach; ?> - </dd> - <?php endif; ?> - <dt class="col-md-3"> Emploi Type</dt> <dd class="col-md-9"> <?php if ($grade->getEmploiType()) : ?> diff --git a/module/Application/src/Application/Entity/Db/MacroContent/AgentMacroTrait.php b/module/Application/src/Application/Entity/Db/MacroContent/AgentMacroTrait.php index 41db5d4c..be9cddbf 100644 --- a/module/Application/src/Application/Entity/Db/MacroContent/AgentMacroTrait.php +++ b/module/Application/src/Application/Entity/Db/MacroContent/AgentMacroTrait.php @@ -2,8 +2,6 @@ namespace Application\Entity\Db\MacroContent; -use Agent\Entity\Db\AgentEchelon; -use Agent\Entity\Db\AgentQuotite; /** * Trait AgentMacroTrait @@ -138,31 +136,6 @@ trait AgentMacroTrait return $texte; } - public function toStringModaliteDeService() : string - { - $agent = $this; - $quotites = $agent->getQuotitesActives(); - if (empty($quotites)) { - $quotite = new AgentQuotite(); - $quotite->setAgent($agent); - $quotite->setQuotite(100); - $quotites[] = $quotite; - } - - $array = []; - foreach ($quotites as $quotite) { - $modalite = $quotite->getModaliteDeService(); - $pourcentage = $quotite->getQuotite()??100; - if ($modalite === null) { - $array[] = $pourcentage."% "; - } else { - $array[] = "$modalite (". $pourcentage. "%)"; - } - } - $texte = implode("<br>",$array); - return $texte; - } - public function toStringQuotiteAffectation() : string { $agent = $this; @@ -317,24 +290,6 @@ trait AgentMacroTrait return $this->toStringModaliteDeService(); } - public function toStringEchelon() : string - { - $agent = $this; - $echelons = $agent->getEchelonsActifs(); - - $texte = implode("<br>", array_map(function (AgentEchelon $a) { return $a->getEchelon();}, $echelons)); - return $texte; - } - - public function toStringEchelonPassage() : string - { - $agent = $this; - $echelons = $agent->getEchelonsActifs(); - - $texte = implode("<br>", array_map(function (AgentEchelon $a) { return $a->getDateDebutToString();}, $echelons)); - return $texte; - } - /** @noinspection PhpUnused */ public function getDateNaissanceAsString() : string { diff --git a/public/img/logo-universite.png b/public/img/logo-universite.png index a399add5324b2c393bb1e3d40e4d89fdfc63eaba..484c89e851839f33647ff63c8711b3cb249cb969 100644 GIT binary patch literal 19369 zcmeAS@N?(olHy`uVBq!ia0y~yU>0CtU~J)FVPIh3nZd`!z#vmm6%tVrlvu7%P?VpR znUkteQdy9ykXn(M#=uZ<YwhgtqFBpKuKx|Y<e2tI^5wXkf55x{`mvoQi<THw9o3k) z%ZAM%EpKwenScBL%YByrr@b;tIC$mGr#V0Mx810D-kvr8|E<55Z&v)T`FphOI)A*K zx#_;TFE!Uy&!=wta=mx%`OC+7^WPUde*JvezPiV+Upuak|M1{<{Ds+HKmW4vu={@g zx!yjxE8jjl=WVT#dsShZu}^Q0bLC(8`|V$AF5f>pou6y<79oAEd+#4K?XAC-&f@rg z`Gucy@8{2Z9i#E*jgxUr_xGUhIwz*T+*`Z-+h?ZQ$S2$9pXpy6|LwO_ZDh^;`0y6_ zYexI8b;#HK;+|gj!)DL^`}K8&74j4R|LUG|=a1Rk>;IpxsXAAec0D=G^|SWkcS*aq zA1`>AaPsh8-Or&v>^~OojPG5awR>($&CN{q_{*lxJ5L$v?RvV)I`97b%f4+Af4{Z9 zzvnOiF5Oh*{vV#M;49Ou_qB+HtvFKjE7$2k@_#$A^82^n{a&_uPo<^a*S>bkyq`~} z|GcaJ|KxN__w3hm#3o<Zt$rY`@~nY~<=>N`EJx;s-?<d~VEg*;A8(f*Q3~x$*mXK) zX2SNzl}9|@DQ`d2Tl`?xk?+e}=4ihD$}p{?T%GMPli-G%txq;>KKlES%<Blwfb=JJ zF7_P_-Y50hUM6$goc(C^_1!y{@2FnuZ&zK*V<y-kV)QknGeAAUQ0>$5BVK%8MS^@Z zpR#P4c_rw);_*2}=Ty0$RB@_K3n|iEIxVb<*YsLQvF_GuVbz~?8yZ(W4U5WM`}Ljg zbJw})rR(0;82#Z;?lbwMvAECdmr8BgoXlsDX>)VGJq?dIaOBkLHM?%Tx;>LO=*^DH z=XSr@b^Bd=jP=7Kll|<TUb*a7-+xPc)%|_{9IxEb&id!(b$#mh6(3h>K7A|bS1?J$ zSn1hf<wvf93JdoprLFG1s9n@GGk4x1k9m%2M~~?&?+`q+W3K=4y~p1v7u9R$sa@SK zYW_cbqA}Oq|L#wC7XFsoKHnv`^ZB#h8^Ntn!O|=C*|N`{y>@|-<aXEC?~=xA;+|=) zNuB-khXsSiX@!H6o_&7taL%kxH@3;jU5T|Sl=y3rTe$JegmVuMZM(ZiTqgQ>=9BuS z-t_(9zb5we@=S>Tu5yQWD*NOKE9bvDebaO*>po76JA2FzA3xgv+cQ4Z>X_r!cVQC! zclW(Af6x5-S)ccUkeDdVo!3v_kN@ivp`UJgFYf>0+m6-Qbv1u)pLU#j{q<3na)$fY zp5{ghHROc7Yvf^yYLkl;3V3^YPOkdAC(gbMn%kS-FEu~pye(8Z>es`A&puC1{&{vv znfl2emQ&vsTTkDVUbKJar57o0vN`69f4_X|-uKz_TR)fUUq7_(-e1*O&ur(+kN<l* z_3zgwy=(!+QHK5((!=eIcSaXWB!^fpOtY7Kw&sA-=WSDFuKfNj_rSAkrGLM#8a+QQ zSRc7|D|@EZBe`mwV<%jb4VeTKfAu+iDE0NQS2LcK%(Z*#%u9cKEAk&sxSIH3dQdWZ zxX$#YuC3RDd{SDsvD-%9>bceY<ZNS4LuO>9&VBdQ%deF-FitYNw=%6-O0dI2xFEGj zt?mBK8L|nbZ(MFMRrSq0{;16R>eCMod~%LEGUm1vy*Zi7l%cnMYWMS?@Wm&)=ji7$ z{ZzOY_tNLt<>WmxAAQ?-ztxe!%VRF%S+Vn4kKerXQq!{C5aE`X;JB(<F(!J?#Asn> z*@yf7Mr7$fIph3%g23dEGHolN^wzgq=3PB==doh$BZXKFxto^{f14>E&5<N}Z(Zkk zJFC^DVvD1`Ejl{+x&N*i^;{C~CzLXZdVg#RDYjG0s`~wRJ;QasO@)1@{>b*+SI)GW ze{<$cw`8p{;r>gfPn7n(`Frd2nY{@!jGjleyRMw<Fmb_d$LZ`}S8?!tYVv%ab1gDg zfU#-El<wvw7CTjnKCh^m{pj6^i@sI|R(yzi_j=0JV$Og-4uKaMw^dfgOfuH#^7NkW zu4~-)_7j&1pUlfoZByoaUOrJo^?aq#L`6BdUs3^bQ(L8OhI}sK$(pky=jfj&cA6cN zgI5U`ZPTb*cFRLk%c*sD)osITX~)+{f8e^iMJ7N}?$Wxsj~dP>TU-t7W4;nrv$}b0 z;1|YcDLTi452lEFUTVwVxX3VY#xe6%WzW|n?rzn;(<6MW{f>X{(#=XN7v|pbUl6AG zCs0bMWcs%7K9?<RojL}*CCRsXYC2`bl4j@3*|+hF@#pE=7QC~#bE;3~@XRZ7U+?oc zu%^j~k@vurZ#S3cB`phj+*n+?>^ReU163~}QOQ3kn_}Ggc*+A@dEVz7G0YBnrBz^` zm9pu`x#X-j&rDac*Ihi<k#~Is=QF|6heT5r*-t9c5l*|Vl*E7Kk(Q(G;|0gc5B@jy z>dKquu;t*iuBw=$N;^-i=J9w`e0mv+Y~TVWf0YC64^8eF@kUPAX}59JlBx5PO`Yak z=i8~)@VemcjaJo_lboe5JUGkF+woe<C&k?8rs(FNyB-(*iT(eo`me6?LkjzW(x-dN zXLME-P5h9wJE53M>B!B6Ioj6eGR*IDoz9Ic&l1syxyWpw(#&1^l=D!tx(c%#bMG|9 zMETW1=LMDWb?T4Qa2)TOFtdOyQzAU?dR1=3biqYZ3$5=wIQg}~ySCNEws-b|BZodO z*cP{$aTDX-b-!%3_N*-kzy3Tg%0PjSg_AER%D{nBulGU?%hTqw1@-Hn=sM3SV^;EJ zo-`?C%8M8kqslGQrUfzyIY=Mae&xKUrpY|tyXS6%nMgliVDvn2R%^o2ox(HcNH;48 zDm6)%C9pD93DhK*t(>5CMc72uarN9M6EDX+zqa_;+NQn=wQXmcl}n%G?skuyo~62b zBliTUlOb1@Hu7FzvRg5$=hdyvWg-?oyLN3`{rE}wsm3L?m9BOrVHXQ7{AAnvOlxjS zzWUo$t6F9pSL?5Gd(=4j$DhdAPF_g?C(E`(9@xt|=}?lW6yMZ8Pg^zH5`~MsLmeJ# zuuNW|mcw|hq^ULUY_R@|;4B_4j`r5W)0VhIeL55<U~}c-Eq1HW%FKyng6joiBLt0J zDD<>l6_-5zCWrZ_r?mLYz|^!mciJC+5^b3($jdx0z@INvS~`+p+9OYe{5^6j@*bW{ z6jjSPr`I4=)xeZ+h&OSE<NukqdUrPcQI@mUy`z7FvA}#1;}_;j*DtIH-o0X)m8$>R zj%^+uF?{|L<ql3ToaVH%Qel&1PW3vT@Mp1ecQ~G63t;mJ*!kt;-3Mktb3U4g7pbqQ zHM^3iuJ5?lEljp+Th>3b5Bs=9*Rd|*T3V?y?|`J-*FPo#?%@TAtkJE<nAb<YdhXM6 zV-?%u7s`k3E!^mqDx3KCT#cvMt0Kc+H5c?2i`r;=*Iub!#jdiY&#F#5@mac-PUHO$ z)lx04Jm&9}OWO1T!u2P;sE8?1U~DhmF@MorhfkFyt!tFBWB<<kez8YvUXOFpavr<e zK2?iN8D?r{)+q6sg{DuAyk4Gr!!b#IL*M6Bf=*B6O%JV#H5FP{_Il4Wk((h$#RXIM zt<t#iXLcW#!Nz(^&X;1EOT-p!inye`tUCDp`uN$OFW)!X7O7pjeb&`ahYbHXRZO%J zee6*wdgALnv!?QMM;4V#Npg`$v$kH%XnyY^quh%(S0+sGYT%x`r|Z*`{FP0&Uig;^ z?{-gr{J23s?4%Osf{DdT1#MXL4@;>Caq}ITFp*Q%!t>9S+SS5q^4BSMp13U7yZlD5 zLh$zx$q7!vHTKFs%mR*1JvhN}LM*%cg*XSMP3~_xRUD#>U9N63UL#_r?8U9`k^A0f zWy1T*DUAWT6Rf+|dfA9SJ=Dmn)#EGY^oDogu7v$FFH8tH!Jwxl%5D-OCp@e5$M35L z{*;~nn$j!L$a3mjdWz9LZnyl{z7@L3kN=7`z28{GDe0;t>?UTFb!YX_iHz4<?7BM^ z%kWR$G|`l?QNxdgtNZTS!+yU{r|_jHC~~fy<5A{%z*a#>OjdU{KmQljeTjDi>O)Q~ z$=IZlXw1W3p?<QvYG2>3`x<KehqtcwJlML~rXpOzgkN>#j;U8(+&TB4wfRiKp}(_t z$NJ4)s!}GQBGM)!yHk=|Q7CJ|R?%z?_Cuy`{SGBDt=juHm0MPIx+KFMHlEWbLp9x> zSerD&EdOAjZs7jpy^7XK?ubR5)81Tjn6mn~>nt<oFAKdVu3E7=k5MAP`D{nC&QiJL zC<~qL9EQTVDtfCJ)#OAnjvO*u#&GC&f)_Kl?k<rBiJ^%`52|?YYuendPAGLSy5Z~; zY1i>Z>=To4hJoekwPDu`3YA_)PqE%0`bw!d=-WldQ|^2l8ebIH9sU^k?{wdxEw+sl z${nt57dFTg6=aN63e%XvI^o2zMQ0ZGtc>8+b-1aJx`bWHKBdhz>!{FzYV{|R1G!UL z96z3DH;9Y#PACX{Ve~+1tEiGs$7!KG!fUVGI@A%Ue}d@)SNQrX>Ji>+tHPgbpK$1a z^|`M5r)$y@Ib6@0FLAEe(X;fucHFGZI(%L%bIx)Ui>#c<@I}hZT3u51s%k?hyC%zm zM+g2eJX`5@{MHZ054L)IXZ#<icL{8qaYQ?UV^90GO%HA_UYe3PVg3p8G#+NB+*8FS z!dCW&A{NMSSv0Fm<2r8KuCTFL>gFs@{gaa_#9Y)pwG_|QR;*!LZ_8w`q+t_x?>Q^> zwh+O;H6>GoJ+>!C+!b4vy&~N};;`Glruxp*xg95_J*<zraA?+x^fcS0NsgI2tM=t? zZHo?MKBz2UT*24t#$}z$^3Ky|(W<k_7mas&vK!_K$sJ?in(p)Z-J<<IXPu9-g`6z1 zz8;yHm#V`Z$aDEo%JM%98QPcjH+$}wCH`bZrl4c;)}&}NyVa%LUcHY#OX;|9xJRoL zGB|Oh+%H|RnD=68Y2XS!_Lgbu?pkPxU#(!ey8jCM%Xzc6z6<UXv=vIUKGxEGKqYCf zl-w>q6WeJmTbCYKDVyipWBgdOuk+H5JKNmUGOx`mo-goMYU6jsNaF=OCX3~B<6pHY zRqga_QVKe)aE0lbw2jh6xeF%SIG=jX%dqC&TKb^ujKVe1{q3dBe;1qZi#j(1%KgYL zvat%|)iR4Z%Mg1g+2#Aim5i%5u}Uu#ae4A;^{S()KUXZ1csEg%Rc*SwWTQ;vrZj=o zUMrVQvt2r6qe0~pg-U;!hGVmw4z}rVGA*6x8?nXj$d7K`h~B1?(U%i`w1t^{=I&m0 zJfhHe(!JPp*G&<x@3%_Y@7LTsUGMU=$x~+j)H{2n=KoX+W;2!Zaj$xA?q6;Ec~bg* z@pP$^-g6dKpN#Z8xc=6eJ7JfU&+qHn9Pha~{>%0==84~eAC~^P+$|C^*?x)4DyDXh zgt&OoHI6QppIWWlIUM_HZ#{ae)qkn=?cpu_R&5*PIirqPH>f?m@aJ;g(bUz><sV)? zkKDs(rJXMxDk2wY=)a#o^mSKb@{C`{ioG-&j`dGD`{Q5r&ufR2at?UR5K~>$(yYrU z>7&riROoT|?m`vb)|dmQ+JBlPEH>Viu-Jc|TlujEd%xMo@FxZ=_-Qsvz|{1PZE@}- zo%sTd(a!DJbDyQGndP%YJ%{6hQtTGh#bzfMTsvA+AL{mWIysdwBv$docbxn^=fk9P zFO(HTr5oy>M9wOjopnJ&wtZ3UpCsFo-GA$TAHVzTeBS>ZxBuLHD_=f){+)Fu4;bGa zXK(3epQ68B-FRE2+=PE$neV+bum90d{>H$bm4B&GrDU9JQiJ%!7QxEY+hTSLD%5_i z@8g(MKVyxo_awEIg|n`_J)|@FMn<Q~`s&w_8p~!`Jq>((dgY9(u0n}r@8X{sF1({w z*t5wopjCJ2POFv}=Dw(!^*67(UUgeFt9$M*B^$npvo<%JS~KH<R0EgOv9o-k={#p= zSchKGnAz)<**(3N{Xku7{4?GIei66SSNuJq(Vr|k<JylyM>FD!SI!NWnew{eMV8|| z-d%AUes`qg3sk!Lihs3}ds4~tY3&@5Gu-N__hJK&>`7}=N%BgS*71s0YEvt{^T0gi zXxG<Mi5Wi|{r`WHwb^m{UHbd*my6h|RLgxdj%<0p@*Z>MMhDT=e$^?OS(YDNEjhwW z6>lAg>a&~YD>UWquHTy~1e~R~ggE_gddD)YIVM-WdWntAw)IhJ%-;^HznY^hc~v6( z&C^+eQL4^C9Phr|dK1*YOd;LXyMsmM&8=HP*-M^0GCQWcFUC%z`O?ncYo9D<Tve`F zUaMU6_S4Ol_oerP`b8XtI(K$COWRw#ev>cFyhes|amR^NF*hyV&`npDo_W5_<KuRV zRa17j-ARc(VPEa+u<OpnpBJ{7CfFz*I<O)>&L(J+-xsad{F47uG^TGcmDoD{&vEH9 z_vg5z?q&G2_A%?HvlI4nrJT&RGL`o^UcMoUFEelJp&5xS@i(?6Kf1^=JJB-t;{TkO zmG^pCrxzK&;OS49x6ofiCC|Rn)FRO3goJqki|kGpqfk@klP7-|vVQ;gBW26Qm;28A zOTOpzCjQ>f!pD1gxhHN3bPx<ME1p|@h^y9O#hgop%DqwX*KAK(>i-T_3;8ei>gM8e zu|9fA*_Zwv{I|+3L^f6IiRFtn;n3M!pPw0g+%9jpwd3`S@Ut8*S<W)>q!vwF-{g3v z;m3pEb$1pn*%OuS7_jHv$Nh&CxE5K@O3!6^<UiSY@7s!_7nPHq=}!10&f1hvuRr0- zETw+W%+#9!KN?=?rp*7gqwsIxYFn|aT}B-{-xMufdir+A+nA={9{YzXC-P3UZ#h1> zf_ra8sY0Vh&_pfvX&3xX9Xb5xV33IJQif%Tn{T;YN$8t4p*OY9;iUz~kKFv*9G%J& z-UU7K7W2IA$5?(_`M$H0)V2pab?RoXm-%tEo;%@c-@9c0hDWvMzOKD%x#h@-^&<J# zIvF^OkFcJvY<|f8T<ey^p)(oBg#{vdu5N4z(6duejaj8F?QuB4ZPm<d^J7<6D;}xX zRCfL2mj^dgJwzTZj$#j&PyKS&{ZP%+$*%1g519i)SIbqiCNE!ofYajUggU26iJ%R9 z{9jkDy{@QyYwK@S?^i3&a$YZ->;6^kqVCRPyb)1rC1wV#FfG|LVR_lfQ2R>Ot#YT> zuEkuGZ2Kv~;ZuI4kv((SwV<<XT(Ze?D(5`x+!NY+vgNk>3$}tKn)01Dt}IS0c+>yu zm&K7ibB_Bxx7hTWdwb?dJt4)}GlMRRc{q0ql+LX^(Qa~3EN}VU(zaEe$unA$oMi*2 zxu0A8a)IOY-*e8+`tfB)=(_$NeZEJu&nik;2mR^fY2co^-Js^-$<41P+g4aCy?4<* zz^paWd*ZDRW(!)m4RgKnc2qgO5Zx>}mErM|HUA{~%&+pXvE?q_!qa*^<yA&Yu66E{ z1v}M>8Xc|H{MoQ`b?R!R*V4{2XLabG-1ewA!pElgW6aurO^U{ajy>I9E|$ePiRJEW z7wq~qebUDnZaulzo=NRoSerQKR>0}in{|2@%+0y>NO8}c0;4OAe={zxi1L4xFp=@% z%WWRX&)2DnG$r5v@Fwh&!E=u_9W9o1lS4gImf7x*sXh54H;m=uQ|p6w{4T7Y#C6N^ zt(^|blrnX$uM@Y3_sW^R*ga!b_SRjY<xl)IowoX$e-&hilyHBmyf$mPmF%|Mn$(00 zi@9^!CciNVHxhiS=-^gtv+ir5heNTQ$JRy5rtb;Aw`8;OlBBlEt(*^b$NFBKqV;g8 zumJP2uggzsKVG=-jq2xh!aP>3-D}_6a+>1)^?VqU)STIs{4<SsJLex<vBp{8$u2X; zSQgEE`;$rs_EfZaz7}BaY`VZ~x%`&u6pp1kuTGwISwq@iucl%0(w+-%c1iEu8llEf z{piZM1y4AOSo5~rz4~mPSVU*(lrS&Ghi3({G&fqk6!6G=BCfE!SHtxF0k2Pvvu3pl z-c+3Dd{L1(KrM;0m`_ymY?Alxxb;?Dd`GrrZ>kJvE8V>7ppACJX`9IW51!c)3Y`nm zy4;UV_IMIl{PoS6&yG8@nveU-nuz2E-c2aEIiub*?(x3%+#Rp-IBkFXz7%NN&6u>| z`S0CqYQnFI&z--2@7l|c+ah*7^Lw!?>eKCgW=%CQHXiK3C3_aee7|&`_3iFCqRo4v z*g0;wxZI2Q*L1G?`B~>LSxh%>&-z&Jd2ae_&#IO4=QWA&pGkZt*W~|i58uv-#gjN5 zmL<JAxx@Nyb5()Od2X$;2TOfd`A0uHvDooSjv6=jf-9*Du4SyXN^$?RLfz12OY4?k z>GJD}6)ev@b}Zn%<YDk|1?S1K$y?5IrW{&Zl$6LLtCDDFw$$$o*Y{_0|1OnSKPB?c zx@7+AtScu@pYHy1edCUVDLzrZk8!w%{n_^0aNb|JJ)5l9Cb3vW)g7>Pke;w2+u6l! z>!Z&dQdJAHPcs|4`1u|X{4X(|ck99@Znhci_fjX>mbSE%d0aYV)4bB^uybh|^Nu6c zX&g;%Z>(jPu77#cdSmeaM+?>+y)?<A;iMj?{jDOd;(&sLDZY~8oT=`z4Y$ADe3-UY z;dteFc_XhB@A<aI%W}7VeYfe3(-{MGku`@~Bh?jGeP29d)!%*zQ>#fHv%)pG-)lZ| z^!2jVH}UgabRlskpZ|B!xgCOU+2rC|RCWnH-mN?{;KeIL<?o!w@3_=4e!JrFg>PX? zXU2_~O%n<gPH-RHIPsw2l!hc__QIvSxl?qU`y?LdzDr*sb#jyFS>prNA6EN#Fsi(< z$ktM-T659irNWK(o$1lted-qenzyU{bhG*eHP0m|-q<9P_V%d^gD01SqjQ$n^3Rdh z56<?6#9Vv2J+i$-BY>mmO_WHd_9n;w3lghd@oix_+}ZQ(!qZDDth?qgF4|mruWcr8 zg<3=B&v}{!&YLFJT;8ZCJ}b(=Kt;vz<6^%BU$jgoh8(rZpW$oq@Y<6A?x#$a21cbC zt&+lWI+msfZci+-(z05$?GX2*v_&~VmkRlr?(s}Nuwt>1;Qs?xRO0o2r7Yk4VY~Rw zhRw^`yw4Wc{5t$|#@5#>9W$PHMqTz?RKS16VvG8dWy*&|r$4Kidd(qclgae1E1x37 zAMNS!oAIjuO?Ga>#Hr6uyFXl1@<N3F={eiW?k`QAT)yPT`_t}1j7rJHP1)8>Ce1q? zvicP+vYo!QDSqA@muHHRffEmxcXzfWy_@H%oKW*pMKEc#b7Jgr?&U}L3MTtU9h)X( z_^NEKTAXU~_n<Fxu1@oQXc?f@8m$nz%vM?K@Y^13@pn~I^%NeouUQf9v9$c%%cHtR zj^eJK)uqi0M?><bWp3v<K6{#(zzU_m+MCyWzOh)R*)K24({tZP#+hMzS9PEE%5uF> zv)Lq*IiW-8W3ZLVf3IUJbS2*}_PnKDWX1bNJL9(Jo$4J0vBkggGUTm)r=<zI{7!4j z|9n^cv&@2uGaF|4#6Am(W&8f^@8L76biXC0pVVKTH_`gmK0_;s)|bxj7k=z>Sfc$w zH8J&BV%NXC{E5XXB2sx1zVTGPZcyy}<G1{oc+IbpqX9yb7=NiV#6>@dTP8X8oyYP9 zMqWeRfa{7=c^Dm+ep^-S<Jjvl=jpXTDK^24$NYSX&IcVV^_|<g{QeiKO+oKI-mJT` zI#hqbwZ2z{Gh~^zE1g@Qvj6M(u&#QKxeFUsI*14_nxip&a@)E4f#DYwSOa4oXr7yK z;c2dM>jdwB-J%bx0&g?z4>#_-+U_T0JJ+1cY~|(tpz43RE>Zo;)w`d47IkNLEfHGz z=Ud>jm%9IcE<RKIbiVzmJ+VKR_Z!KF|GT;P%yaGkPXeF4p8Ee^;InMAKfm2)$_u}~ zZ+EKZ{KfiDEBFr>-H$FfdA~PN<z5&w&sFwwj{@#IKF>Ah#AJ=F%f8udv5#%pbai^@ zajy5PYhx~0Ea#Z-b@AR>?Y#IK*`MwI&xq-Hzk9J80|TQ<rn7T^r?WF`4w8YPV$R$N z8@&z(h_vm$wn#~o{ivgik;M*?m@`j;M4JK>uW`98|FZ08l92PHpc>};F7nHo6@Kuo z<2v`x+{$9cQSSEtj|<NIzhAxZ<q<W_sOkwzQr~^ueK57)sm|Vui%v@AmN^Hf#NK}& zSZx=d8BzN(V*Rh3_UDsKw0cU`dHGJ8e!)Uu_hzHbYmy$9U9cCj@0hFMsr+$rg}Rs0 z>9Xzfj|6{yoSA=FZmIb5ZR>9xd)yLSBh%(HQy}=##AUB!9&ghBdV+K3@&g{pZm-Uo z1Q#i5J$X{7A=Obbd)A({TIa)01;`0k-fXcJs=Q_M=6~J#+Bu=Kd(T#iJxjbA6<~Ti zxuU-1D#Nw;iBET_W&iwsJ1gx@*0cHff0z#S1_ZU;<axuuz`&H`?e4<xzrFv=eg*~x z&H|6fVg?3oVGw3ym^DX&fq{X&#M9T6{Ur+%zp%l(njMQ67!(*hT^vIyZoR#mzCh&a z!S;{Oy(X%~2;^v(Epl@V(Mezp+^F59>*gca*_mV#A!NGIW%0!yUOlsBNHp(tIm%bo zt01w|Rc8f9Ss>$7HKyNn4;B@azngdS?#;6AKR-S-sy+YaT>Y~%XDm&17PEN<*-1Su zEHVAQTIFQJ1QkhvNlX5i#C~*7FWY9K658rMBfgwLX2SDH%RXh@jjw$<<9N}%1h2dC zyEo<CoDzJtYxb4)qWSlwJVO(MmoaZ(i+{Fr$>*I5-bMV9+5L3m9Bqrm@7A~9+@Evm zq?VfJBt}I~BLx*twicLGD$GukQXD)c@o=C^LfwK}fuz7Bm?U-+kQ5*pZ=|52ny$jF z%fjrm)S&TRO@^UKmGH}>?4mpF#v8RT#=PJ&Q3&a(xG}r%i>Z=St<9UW6~Dq_TzVF( zUuO<CI5;=MVa1P+2GTRqTugpd{E(^GyhtgD^Z91&{HuTe22b0e%*!EaFK3`6RcZ6) z==0M0a6gwl&hmN*FSq}nf25#%DdWPRBh7*rcRWsf`Zq>WuuwSKc-g%T_djjheYqh( z^U=YM6@3*eS~`C8I9txE%seb^Fk{N@D{vW&?;RC$<nG)*uw(hon{%@qR+xNDa0zj@ znUe3K^C;)r*&lzc=SIGZV0K#C*)A&hvGM4Y6^|F%C?{#{-O-aOx%}sx%XhZ2wRnm0 zySbDeao*|b()I95N>Pty{$s}S^^6OHjyhM)i`9Brp|Sk$AG_+0-uwD2ziOT-7nc_B z`nO?Y`kKSXJ~_MF+ig9eb?M2PZ^ic~U4M1|u$hf$^{cNtI>O$iFgtnPo^f{5j9u1m zbvJcwNeug4`Fhg3=j$a79mtP=%$<2GATC|N^c_gu>ZgWf9hPqe@Aw6GuW|bRIisw{ z^6kSrew!!dzKp3VsC~2YdlJ{-$iuQZ4lA|@7P4%Y<QLsH|FO%F1Cx$1U%90HY|3lH zrsFpc#b!IKxFVQn6SA+&P$@}a`&1J-hJR<G4rYdh=$vc_IH`Q7VnttvMtem=UyS68 zMf$>PBeF_Pec&i&^G}!gZ_RfqDRX~%%CV2ji((?(kJ$aWUa_L7<3_u<a96v1f&Y^a ze|KoCUu!dMw{%X_V&mx*PZJzOj+expv-r1p&9rZM37PWK|AxARxJd9{6%^bVV{3Eu zfVtiO-%Qs(=@egXGkdI3_kOCga;j+X%<fegR+lO=rU-5fX8OpGFOnmD{V{*$;cqFE zM7`NsPN^&PJqdffFwpJDi%=z{?G-c5|7N{&Oz}(f%lf&J2PfyeTxYBhq6hM*yUUYb z39pwleLE6xxO59kP14DR07<u&j{&lRh6c~C%ggJ25UcC|+*s$6W|4a*v3H*P?5@s^ zi!n#@Gm`>MK6OYO{a+Y&&i;%$_rBKUn|XilSj@vQb^5oM1jUe}D;?hbu9On)E;wNz zx2iqVCunhDXRYJuh6z*NiRNt;NOAC3m2buzkz}Y5c(2*xMpD`*)nd<!)51y?u5}ek z6qEmG8qegLaayWmp(|@$m+F~Bz2YB28IICc7dxM+-kPQ<b3EEL=Dv(wf?#o@R95E6 zwk_YXa~)PF&NrNOu_wK1@8%unO49YeeJ)iB@_CY}X3+Uk$4h#**xeT=&%FuV(yng* zNK(yU>iHi{B3rL)vb%e8mTc2PyXN$Y&gnB`K3bYBkiPrU&3s$R*F`mbJO50N-Z}TE zYs7VFn{zB`M!l?=k8f>OwY}N-Z_Uex2O3tev48M<^5OT5gsK1gAD_Q-`2hbHX1fHD z!!M2o^qu*nc=dCo#^WD}GO_t56dUJtR~MH~OZ_0cEJbF2<(jJZnt$e2|1@}PdNkOE zb&a2V-Jyk%^E>$;>^<>tyX%)*+os&!IWav_%JR7VkId%mpG~uWhzlF#9IxIJ{(VIz zciBRD_KUhZ-im*6IQDV*=jJNsd5?S)j>bGQ{~+u8UE}t0UhBT#<a4%jrFUpQHa#VC z%z!P!DW9#dC*M;-p!e>7DT^02hbH9zuj}5t!~EE$V}^aFcg~946!E{u!MXWmtw_Fz z#g#p$mPUrMo_Y4nVedD_gQ+%WD|<Tk9$PPYHsjhep1O&lTQ7&)>yi1#aQGGP&iV15 zquNwUvkhd{J^BAb>zkPFBhPtH%yZ5K{%PSg_OUeHFyFq@LSp}%uiGojT>f9LJ~pe^ z==mp((@E>nHP3&xIsAh)J?ORLl0%h~t=RAH?I{tyeXOhfsoEy#^yB{)K21tU_~RsZ zKC6<SJ-<3F?s2uufq9Wf4wttdNz6Id%sJ(R^H;n7D`jRG%4JEd;Mp_(eQ~1L#|=eW z&$Q+o`q$|8=JZvWx+7&aQ@(Eh=Kb%$vOjl^=ka#D`m7Sq>@9ib<C)W0=R~F##xRFU zd){dM$`pKO{?$)T!TE0Ad6M&&TlYWt6M64xLY-9L^|^Bm&qTiLT5Vp>=d(Z1<@A#K z1zPQ&0_CDN_PF1iEUfiz_CJ%mk`q5`p3U)l;$Zi+A<-dZdZo>Ap}q(5mS=0F?e%U{ zUd`g+@cEb^*6&nzHn~x=?}WiSqrRuzHumT3UrO)pv%MwccJ=R9!`c}#bL{puWg0R! zZxr(X&-HuW|L%W{)lrH47rL+8rbq}}eHz$S6o0Px{+an)+fo;LEjwRn_ifWWj<A&` zd$z?FmMIzjP}=Q&C;Q~F!=>Sj?kQ`cq83))GQDru_}i*5_gtdrSK0l2@}GT~PR~5| z&aH(pFm~O;U3;GWFXc0re0+0mDRc0V^(kDwJ2`KgRD3N+O`4w}_4|3q_y4go^cnp+ zC3~W;{{DY7@=o%pH*31GGCt<{`Q=2;S1V9eVqVnr<oB7MLUmyaW?x-hn32#m(Qx_} zoevXqWv(9h@Z3WE;`uK{aa+G{mOL%|NB7y4yRTX=zZd?+BVCZgTD$-Lqvf4-_V=G^ z-2Y^zAadXPPV55JcCDFdM^<#QR~S}An^pP77vwzJ{_y>&)l(P#worXG#rI~-)c^C( zUFWQAGWPz~SNd&Qkx$(9oWNrR8||x@oj(3u=&*g&_k^`B>lB?teWW+%KKanied*=X zmo+m#?+HJ?j`@Dh)a~=*Pd=7h6S{Wp!>7AH6*KFLCajz;vQ<++^|1I;uQa3co1+=0 z-ELuQ<eK{XXDkzAp^E9mshoxPuI3$l_hpfA?u^6jHm6S?<m!!#nfBQ-<In4vq1rR@ z{B#cauYSE^vye{5*S8r?`DMwnw?46MmN<Ol0q@(Ra}Lk__lB3_XsNd&6B8R7Q<BpA z4TTAk`K<GQcCJg<rM9Sc(XWREQt8*T-@mXu_jH<r$Dh{C%J%|2uB~GH7|>%mYoq1s z4Oa2S-Q`j%W@MiC6#cSx&(!|rhaZIXQs#!Xoqd+{PiTkv_xyWLs{g&w?h5tke0k!X z%rU_?XMY(!-?81neAVwung*^v4xSA#z2f$zM`G6mX{OIxAA9O~X7lAUyA=dK$a(7R zCQ>86PDUV}Rk=tvFTw2p<3hPdg=(KwjU^8D-&}I9L_IuY_P*;Z${+dGtrzFN&}eUH zb>ZKoO%FCb6?IYGVrBo(rD{#c(@$E{S<iPoG*)vlSukzCnv76I=lg#N%DD@<mNiZk z_38gud2DCaj`q3I66HFZC1(}BlNPG^Vk9H5o>gl`)F++jE7IE(n<ZF$o{8nHuimn` z^g-~`r1*P%JLJyBn3i}PS$zCuuBtDu-JuWD+2osF9FBc6zwqAd9dpv;4E8jwP`f+x z)YhEMrx=U9-3r`$<{t`Xy|wJZWS{dNBaeODT%ow!v?VE3;IC27Usmh1In_eO!ul)4 zw*24r^U$=_bAGqa>bPO9E4S}*^Xbaz?l;<{+AbJ=T$^`RE%U!qZ_f748Oxooh4<|? zv^ad@@1<MfaaU#jJ!U-IutM#&@ibrM<1&Jemt`%CoBmqdLPK|L_5K}-{H%Fz@-7@$ z_~+t*vbmB!jOK~W_<!(-SBC$(C$7&nPq=v|nN$9=&GvPlw4zr`UAwi(e(hh0vr`VF z>zOZRdfe_BXSvSCZZo@0iiE(`#mwJRR+QULUDx<iT`XhwtfGR1uHT;}xZPdk)b4TL zxpznJM((A9jkhl(3v13*o^fRIoMU`jR!LuK*?MznoORg3?_$S}?rOf$yH)$e?>#0T zdf%L=YgGMmrXY6e9l0rtfr53e(|M9-e?ENR&wG(Ke=h~7UVg#zc8T7T&N<Wm-9Hdh z+Z26QtHA%+(LJY^s)iSe+a~!)zB-*?WbeIX?V_SjTAz*k?pwNTefh32==ZI|ZH$4k zQJ+5_5Lvh_bh^m})xdw>x>m%;-E88qb+!@9NU5%^a^<U6-r!rvcRD&<#@hD0c};eu zU738=Y}VyJtfNKW)c&}{@%CWur+dxal~<YD83Sd@xaXy|{Z^e9x*#`un!9Rnp1*-0 z&+c`G+pIsEXr?{+n!3OHZIb_8%NyI-_MDvf#s9&sWiflCCH80bq_!-Z`LOYD!wSA? zmgN~zHX3!I8`g4%8rfcO_<C(q0<$o$uBC`T;XO7E-_Ln+szpZC>85}GZCqB>Gxx^) z!rn*Hf9sg4H^ef2U%=DBwW+cv)2TQAy!MT2Z=HYlJhsn&(Dv|#gShSM3)aUsbbppB z$(Yq&tk=J7&itn`A8-3tO}Y0*y2fP3pQ+#FLO%Xn6eDMKWX3Yzlj{^_6)Kpg&w2Fk zgml+K^%+uDt0N?4e7=)EU+UD~KStm6JnCgQ&XnwZaoBj{a=Eh^-=5Z#t$L7OlEKgS zeBA@1XJR@0ry5phY&Be#8M~>Wp|P=Hhxw-T-Rw=?XTN?Z@@AT^`Tg+e1v1Yh&+$cm z{cG42_~y9l#IqAZngXn&_@|Zdullhj>6G&vxkFC<tYV)WPyTEC^+3|cQ~I0MWutSO z`F5LF=!Lczo!`28**RVlzj-&W#mxF@)4xf%nd@6gRN~ana#I)=x~x6d*r<6)I*cRK zKsN4CpK)>S$>rq_cptRQnRa;gh0{A`p0(7ku#1~JE1HF^<&^Ua&t<<i^K~?;{&U$W z7q{(PW$*ODJicPxC*MmRTkdb_blt<lp_+65Ky#;XMf%kL^+FZWRd1QTCItRCeA=yY z&1a=`XICDczy0RqVy-Job~7&2;_V0sbtwBQtG{v&lScqIAE>(B`?~#1`{u)5F$bso zewaFU&$TKc{pTgTo2GbM+_}A}Gluz8L&sOvQ}3RORh?hps(k<8%}}GM)vUsn<#%st zo&Q=l|6`0$O@`$uk6%wO&M$j>`I3@>!Y9G3IZ1Vk7&lfa-#_@9l`rf3x+}&<_Bi|( zk!9xHDC*oU^ZfMxJzH7#KPzQ>TEJ`C=jd8#x58-4b`GA7nwE24H&uVPFey#8pPwn2 zVUYCFi#NN6&!)UMLUNDU<kt_Es!iNlp2o8N)8aMSyWTxl>NjO;VVu|!@IU&dY5w=X zgqr1U`@0{98$FFa7}BF3oO|+gv2orL-?p^MtU|$HTN#Fj+h&FMo%-PWD!@N>ed@+F zu3zU}^4wmw`2JD$3s%Wn?`Vi!;EIrX!Jp^*>sh5~S<Z*OpEi6wwaCXj#Uj1PvcA98 zJ%@8T+r4c4{?}*E@cAtGv;TeI^@bDfD=K&A+?rgk`{T^zUA=YU+mr17%}xBnH1CPR zp}!&g9CeXS=6}xfelZJ+v?>;TUSN9N!1~&kazmTv)*45JZZ)eHO*npLRZv@~&%(Z_ zXDJsK{qb)6__q1FcCX_euVsJcCvb)SKa*Rcdb^W*=E?a<wcTRu)o=9P_*<T<zI$~$ zduSo!MbjU1PSkFkF8b<ycK50qC)rt7mAy;XT<G@e7Q6P06F2^9wNy*5@X589`!Ysq zvE~~?*1LTdK35dVZN0ld>-z#NErlo+>zkdo&py_f$LDi#uU1)+_OEoA|B}fwg?2<6 zD;#THwD9oh9d6Nw)>?L-JQ)5mPV<9V$~V8B)RL9AY*%z~au{t9-}NZl%IsRvI-Y&* zd%dT=c~+nrEVTYauBgO+pT&BQdn-*YY&iLxHMagm?8ogtO?LF?HeYwRufV+M471Wv zO+%?W70v%oSNrxJb!>bd{Em~wMfY#gn$-3KKc-9nlzdUuSa*P1T3~MT{#nw^r(c|! z)#zWa{J0PEqAS1H&9j-rS(eQ>&flziK3{IN@V8?Ncz>tJ*f&o%?z6YJHv7cf8!84z zT}6MmeLSSI>}*ZN+~5b=GcIT^oBk;*p-XBTzfYlLeDxI*1+Ue`J$cglkKXWzddOeU z|G^S$xkV?$=4b6S<s?7xEU6C@PuRVY`nKOFgZrz&w#QvFWEpJd7v?0+F3l8L^Jw;A zxgMS=85#Wh4qaHYEvw4$w@*kY8;gu+@~qQ08Yc>dbIvc)jQ*I^qbd{YYW-`1%`DZN z({YB&ZA>hV-i#4?t(Bw}zL7WDy(BXvM*fq9uw`@ajn;07=?k-rkN#|Yy}@Ze>pk^j z%Owx6$(%YbaZI32;Np(oiU-|1*FAr}ah+0HA@lCbQ?qSPg>5i;JNcLU9P!6zl7*Nv zj=sxrcfXdxIscR5d1K9Ik?HZfLNE5kHSaBc7idwp<ITagGiNN02AzAzS?9c;jn5_i zgHr#;6WiB2|C@N&D=KgM71u*X$Bd@k4?4ZBBt3iA$Gub6aqN3g`0vo>#?(^X58J*y z{}eIt``y3G>N3Cg?z*7<<IVljo~LuzX4l0ZaFKf)7`N`XEZ_6#z56_Um=~S6^-+0U zpXpO3H$$!ErE|hkcUL8xV-(z9wTg3p$3@rYmu=3bz46mGTVlJl=3IKsv38$FsrS~E z*BZ`CPnshsey*eH|NPU=HX+~3y|Y#><t+Z8aBb5z%@5n&9o%(r+wm|_)2|m291f)P zrPThq(EUEpTle$Nmh(SaG<`g>_dZb0OWNQb#jF(h++fjywJ*N&eY<|=hRm5)mUk0k zlna`xLz{Q%T)S*_dB!pOB;AjjgxHRBOG=kTo;b9I@5FDhKgVlqrl*-6KQ4HfFKKlI zFZaIlx_5-Kb;Cad?_ReiAa(csYtP;^)xCMhY0405nU#FsbA`N)?xv{ItepAZHPoi9 zIg{sA5Gk9yr+eP|;LSP7-yWY>ec&Ny{?#p$?t2C;=H`%aThF9d-L7@#CUdvZb%8RU zirwoq0xNa>zO4Ko+<ig%v(=nASHE1mZvQvQR%KG}X`4$@0-o8&bXl{k>)N&6?t6Mc z=2vL8aK<v_*x+}5JFZ@`uH3Ei^lQR`+S@s6PHVc}eD?XK#d&RxhW)8qr)&_H{u%v+ z&BZh4)Lqt!e+#vhS8sXzCF<Lms(H-CFN)W5Z&!^v<h^s1%2QLNjjC5aY*#9sa=9yd z^N+J8CG1OOm4)B^Je$qIyoll3vvn=}&!j)5%q+1A=3?$PV0Wm`^ZoL(y<V+CPyYHE znfZO)cI)-y?78;-^nUX@oBQXYM#JdO1wG#~A4{K2>EFiY@`>-+$^_$-k8clg9~9G; z-h6md&+RZv`%2>p%Z1*YD|I~6K5ueKb`tMp-p6|u<^AN0bUAWdvMG&6T6LSR=D!yg zuQh12#7fLR(cI^2p?h(|N|(2rbxtyWexXuger!{5Qgof~8ovBVU)H-!+hldUpz`AU z8NV(0kF8PqWpQ}NyPoG0j%<6WS3TK4fon0hzoF9kdyC7TxUO4sshWTFyqn^AuYT?N zB;R(~@O^IHVNaXc?!k&XXPgh)a<W=;uf+ND-kaw0CpfJ!uQl3#e5081&bhpw@6CE9 zb9nQb_aCn{X!J<28BP|=nfKWA1anWa^>?$vs%iiHw7;GI{n~WO%NUuQu3d?@4d#5` zX?8;(_EJ=_^yVGY7Z<PVyx(Rm;oU#!?aSVZ2^SBR>)Y|^J<nKHn7cvwfzNVIaiht% zh4#z}`Dn6sj&JN-N14-~|IGfKWR}Zt+i1e!;vUf(rWcNS%`rZs%e;Phspf?}yf069 z?hz}#_4f0MgkR^R{<LkDIQrJ++?pH3Ta(Ry6&7q@{3u$+H|P1bvx%ppjT#tr9`3g} zyxHdbpBwGZ4qMK-xAA&#$KO47?A{#KzH`!Jnb`%GN5>7PU79obhvfNU?!^`6-Is39 zw6$E}Rh65wCM#mwo~ADsbgHWK_P*?S?0PRn&3I;bevJCA3$5?o9Pw-X_A@l*^o%pz zK95B2Jzl(}tRnhCBkzq4-y5^!a>U-u+;d~!!_s>xQu#)`FVFbxR=+e)_vN{3Z$hSB zUsYT&@%qez?KMY}7HH;1c9-60zPl;v-0M9DQkH$tlV38`!T4H=tyx;~wj}9oI<L9z z`p%3i|1~MU+3xxJ4C@8YcIuoi3JouCyBp8{y!L6_)Nldq+bzC79Pi$b|HxY$=@UHb z;xsW!o9*i#MfB$0EL-Y)ZMsgX-P*=yTl}A7EuApyV(rw;4_VJV%uY~To9UiA)BNtG zdH*8!f09V$-uC0$d;K3>M@y?WXucJ$)d^#Bak|#fa{o?fAz$QM?W*6=tknhCZ*Gac zd}=@S(-J@UI6KlXI?f^d!7#?p)<SrWVP)XTL`hSIxi1nkJyvlgM{qa@|9ZA_$xEO0 zzq6~eK1ZDMxfk>AxNvHSPj$Vtz$BHmHH?X(lT|c9{_DE3<(A&eQw6hw>UdZCaz{mR zXhnPfSk=Qn!}VJ4Z|`0In1k0d2An?qQ@8!;>CAK2--UQuO8c+hRg;mGXp%lzXnp<8 ztDo-lJ$vWn+4)J1h{+J7sSFb5I*6HTSyG}LnV~2lFloyweaS-%dRr8DI6R|nT2vL; z7O)EI@Gv_~nihTN=bKZ}rS<=(sETzmDtdn4tKHGC^!~qkp~Jc&%ubW?lCqCok^UBa zZ(9Nnhv(Hd#(YmJo-O5#Kadb4*3YQ8GRoGE|6P8<oy&J}7)_mgb(yB_=HIdO-UPWf z*&9W!DxG^?G%a<;qmpl_y4<H4CUj-1rC*mey3wGqYNgESCkIUC7fWrA3hC_$^_gVk zVK`^r!3u^Qz3e)A>lIX{ZhxZn^xpG|d0n<&HNPz0dNkj`Lo41h^wizM0(SkjU#ntV zw7K^OZtU_5Y5`3|-1vB*XW^c63RyZ9>lIW?^NMfwl_&Y{6%XIs+WJhiWl2_m_xc&Z z>yC5CnahE^^7y>ry{w49jVjDeL832DOl{QsWi;{On#4d!fk~^*Zj`z7V8^+h2b$Y9 zO#rEW8I`5nW|pk6K5`>yusrSc$M!9W)kY_~RGFP7wOz<x`oA=d#edV%qe%`PLA=*5 z3VrAV$-Me0_ni6fj57tdB4k33nXgn$EwQ@2q5tRu(H51Z^IfI*k&^V&BeSneN}6$) zT_;H|z*$%K=7oKaK~}%vl}l$5o_VZkOX1s_ljgl~slT>m0S|{}<Yvj^Cd)n>c1L(< zUrW&4mf*c@xohL~KcfGi^4@z`yDw4iLSNdN^T%?I^=&CV&R{TCdPnzmqqyLnM4k&R z_jn%7VA`j;amLJ=lQBVCmWsx1y5YX_ye6}gs!{Ll9qlWZC>`InK%BiuMOq}`?D}GH z<(Y>ru^lsCDBWI=GIe{f)y(3`mQ=&#ai>1poHwXDICEm}@2BsK-Hc~_^hrOdb=dmy z+`TvSofpgRJil`4%~qY;AB#M%@Au6zVvybRLe8$pQYYT8c%R<uPjctqSMF%ci1@nN zvRRLzCv|$&W47X2zHGU(Pi-WNZ`oQ*{;U1Xdai%x*@q^1eX@M3UmaLFN5E!9j=bfU zeO2l#kAE0{-(c~0QkCHp<;<Y`jCaLpucg%tr%LWQ?6fb5Q#aF*-7G12Tk2*mJGH*} zi}MqD!v(Y!?VNLv*YFVIg4jjj0{O*U{b`1OH`|<!`_p>%^r}Bx@tWUFj(>ENyIroN z{8N0ck)LR-(>D(1eSd%Jo_lmp;<fZ~3%%#Bram(GZn^oh;P(Rk#}PLkh-7b4XSO^L z{c~zP>qM=W`{hdOOFW*YA1#`-{M6McA=h=dmc8Hpxz|(L+~Tz9{fSwVFQ3btDHW)e z`rYkS`O3VNv)Hz6c3tKFs_V+`%IP<HSEg~+EH(GsJFQUnVzKO}w?70U->sc>C9?9& zPLtQQAB$eS2)R5Xdxh`ZslN<DGmovkQ70*I^!KH$r&lGksfr1RKik?|7t5wvp3r=8 z!>fmRX>qD$xk>S_{3Ml?s^*!kbX^&e<@u^*&b1l8=h%Dbo=l2A<Mr3#+P;Xdlm8lS z-QmQ1Nc?Gt$odQO^*7C0obHspZ^r#+rvK$FmM@uF)co?S^G3gCpH@%VJ$th7?N|OU z=a;%(wV9X9>HeV~Y~uEhk8dnLb^gL!>CJW<=N+H<=HPG9pSw*JLZ%$P)8JsU=G?BY z^BO$W6y81D!;^e_lcDt{<=JU9e?AK3X$J26+b{dW{SEV_ZIw2~pTz9XemqvPrQCAW zz0b~x{YF!M7sbTCD?W7gkLI-!^G)XSpX}%pe-Zgzz%%uu+SaZIJ#6!q=O1(Yl3Kp& z(yDhh1!nSwGduS<UU%UOzL?%_Ds#Z`OY-HZZF>&~+Z<t@*nU#+i&skZCS$wPtJmF8 zF4a8#A@oqReOvd>*s$Ul;fhZhlV5+jbuIp~c|_I!M=g7lO2qzFbgi|O2$6d4D01t@ ziKyGlRxZ4MZD#tk-?kmiO5J}Nt}J1D{v-a?g%g$Ew5nGA)jwTrwj}TT&LjWACaf>} zd}Vgzoo1=HLVE@V-YU>q0FAf%-!hx8p3i-6U;gYU^Q%S%XWdr%Yrm0e2^Y}X@mcxY zBkMx-TJAmfo>v$=y7f@0Zt_B{Wzye2s-N?!p7@T_?ehLJT2HMuOxVd8<EYb7y6k?- zy*J0KwmjudGi=*fBRnJ7@OeRcYmIySqrASXf;TdKSr0Df9Xa^MQQzt!PebdT^Ys;N zzkeDfy^{Q6@yJ?py~3&=TuDJk+TTs6((YD$QpLKl{K%~J{ie@#1&iNBT?xv5(K#n= z<>8?4<!Z~HUHAR&`)cx)C09DG=m-B^I_+sh(slOzOMHWxgXOQze*O8%%azX>e};Mc zuAZRH5o8;twf`5J`?-ygua;dg=RIR+UFx{XtZ1Ee&6%qW1`7K=pYAw(Y;mNn;`W9L z>qSY~0dGp@No-slm$_tWku6jF#k7^XrDuG8`JkG8d6<vGgsOFo{y(#_wsx%S_c+V_ zrqw(++I64mrX5X8hnCL>3DA7!CtYUqTP*SH_9b%})*dz8_<Ud2xy-|PT7^sRB=fA# zu2Jy}ZuY<ar?ru{=jGwp#>#xIFqf(QZSz8RTReL9CEy*;KIOYp#c!DAz9`9Cz2N?O z#)VC@W_`1%;XT~7=~?^bHlCA<_FkO!M=AG)va8nSlQz@L)-dafyqI_P#DO1oCFUf) zsgs#o_|Ec=`uer6VI%yk^FPN;Gt|$0@%)c<?u~VSG_NTi%`T9Cy^QzoYDPuf>2(!1 zR%_^Ho_n^m%6V2{P?)#H#A%s{-wOjzy@?mJzZ@N2sbcO48gFLhYhAdbUg7xLsJWA8 zoY0x~RPNm)!+XhE%}KHwispVcRx?n|eG!}48^7*c?#B7=UP^rIJ8E&yKw-(#^usS1 z19>K2TE)7p-(vdd6yLIS<|?66%IdqLHMdXcY-GLz8f;GK?s<It*_PP5;4ykHi`<hO z?^aYttq>?a6ud|FvDX*&$h{luRHUcBiMrAdFtghB(WgBUm(H`4pR1CzKHjnWiRkvA zccIVNPbt(y+_f#}no#@s^KIj8joQnUckFN|X4*67n!+)2o5^NZGb3xKsqy$qe`{e> zWE5oIJ<m1rea{xfy_@6Q)^AaKFOqn=J6cnG)teh?$Bc~j%kG&GzWL5FzB`j2=3QJV zc`x&P?YXCFM$7L_xPFPLBzaf*&q_W&=}(gw6&W+Pe#?#6t8&ognz?0XMbe9ArJTw_ z?Wgy6d-{u?E1R6{(b@hoTyp-^taJR_2G6^M8(I%)Uwl(N;fBiEqGB<5Ndciu`yJn0 zqu$@yqIh$?Wo@6O>y1y3!cMi`lIXqMUcB4JIU{uK&&q@@#?JFQ4^7(AUNm`!Q17gC zx7I&(yd0tz%rkw%u83ux?dB2^;Px(f8+^lSXMk{R_K^s;j9G8y{k^68L-yvT#?=?@ zJU{cy%VfHFpjWZ(ESB3zL5#ZEH^uV`kNiyC7PT>IuYW+#^nG2?n&Mr19v%#TxM<zA zu&oNKb#Eyjb6l+*EIikE_W5b2HT~Kr#dJ#v1TFr(Q)GKkUSL9vknibKae=}r#(48j z2J?T<xyh2D_j|F)^+lc=x;(qqMjpH#@WyLr(w5`XV)glDlYB0#J+w4_+g~$X!1nwj zuAj%MSr=**rt-Ca54l*ccUtP9|CY+I;NzS}u5q4^teJW#U=`y+t-^Ws)4O)O%bN6A zXtv5e-A!GdMhd4i6jB^KL|5)~O;{-@Flo`2tsF%cKtr=jj;+6@bi%Q^`#{44n=2=S zj1^SYE7&j`xpq$9@93wEJfWT8LMyoAH(#9UwZexlW$&KrA8Ys5u(gETGt-(qeaR`$ z?gKxBEl)VDN(wVv`9^me2bWq%rrC8RBZVbJX2+E@W(2%H^*-8#ttCX_?4^AP-9-_n z-pD-j%rASGUGClz@Sg3ljuNwz)|Kn4bD6@K=RY&>uaf7A4+-3PeEk&euVuE&G-?y3 zte>?-@pMtdsZCwBAEX4dR@`D?dh`@zO2W=rS(hJAFS>qUa^(Et^w9eH$(9#A<}Y_` zt*K*na^>xCt(o`LDDFh!-q*``f9_B^wfe@?BGVlC8ILxtS~n+qru&byS<8cF$r~z! z1iXG$yJP;m;QxDHFXye?=u|i1=(;J^3I_i~+tPOK-<Rcb|Gr-*i%V6)`cwyxz|uR( zn_>>x3rFQIy_2U~w)Bpo;MX^+cg>rBd{@_uqr7kY!q?@x+`oS=(>d;RqUQRe5$hNi zYHf+VHGzH8E8o}I|K?q;s$RldxzFjHlgRF%b=<X0mt&6m-I;q$@)Z}i#NqchCYD+@ z{-2Okp}cC!EuGvGH`Yww*zz&6{q8!^Pd{rXN3m{ozcnFT@@U=0=llC2E!TdpUK9Ub z@?T}l`I({tNw1AG-xky-gn6IX7L=#q&%S)-nTc!s<*Pp0X01%MoBu&_zCkPJo-lnY zyGLql=9Av%_ji1Vo%XcytID(M(wj81D_9jB(|0ZB-L3L%aZ`SQ-?{8}^Ua=|&$Pc% z6!OPwXY&oMYbEcCxz#VvpL=7@+Z+9lC64*-5h_eAboJwJp0-#oGdJ+;!-G203xjV> zxF`DgCohNSjft7g^PYd-_-xMkLY)(pd+j}>KQS(UvSChAxqkc~ubpZ<{y&U;l2ep_ ze!I58|JDZW%~6MB@_eMXZD&-}Ew6Eze?+_}yhr|8;~(?>uirXXJl{Lfc$3xk+Sd4s zt^Hk5aTli+eS8|EdA)zJ&_9vsrnBC^Z`h)E{-clB=lFwrs+_~p>zSRR@|f9{@kXDz zIOp~QU;l>x8<NB953gANEnlgA-S5wSJv-Bl=FEL@Zt9-%S6y}2UkW+(x3^dLuZaG$ zo!?I#uUj+M?2Y<Hc^Qer@|W9Wo!FV3e!Z(w+<W_%i1=n!bC*4A+j`O^56JDA`n{^Z zd&g0Z#W#BnSIkkJ_*o~3M|`ub^vBcr_vie`zGaz^ICW9bI`CN8+Kn;JCXbhFNqk>W zuqOS{F=K^C)n!?%wN>+zf)18GEz#?h_$Q`bV6^u}>(<E0S7#j6S@v=Mk$aVSr+B|~ z{b<yCX!mY0tL=?G-c0Z4S)VoMe-ad)DRJ@J1(`gJSN*>#^n7l2ao<!@vUrvMJh3w5 zRPNcsU;IC)ZolZ$$MfP;u~zufqX#3(o`r2YYjMB#kIf^N4E?fi69PQ9DTiLFw|({R z#e`GmyPlf(Po2L$*!Hu=BIls{>&;UN-k8SEKH+yu<EwAr>DMzla#wiHog6hOao+Qw zSmT<e3RN@Jt$|JPZ{<xkOgmHjSN~YqKaGc$`+u9Obmw2pTG_agbK+%v-@CJK*%i%u zwlX~EY5twAw_CeBk6xHltt_>_BRx9r<R{yPsdGgt)s>=+cP!V^db-Pap0m(zk#f^n z_f*<k_WA7SsoyLs{aN|nsal)kr)^HojX9`T^2i{rE9TNpLwU_@U7n#!xfkD5Zx5SV zmLQUA(Qvvr?(@+t&)@WzA9=h(>ErX7QyYW$t|h6I7nm7;wo|p3Gr8DKQ^S09A-na5 zIA(QzV+p}xOZI0U<N6sFy5)MuJqS=sF+CsnXRc{OY{q=|{Y8gwG&=5?eSF*Y#p2yv zw_HB6+T3&K_Uf)s`_Xbi(dYEavkRW~Ju}FAptbC&On$S(8LQq`w|ATMU+VY&6m@Lf zov^}CvoOPz8D<GG&t11{kYB58Uf>=(nZ;N6UiZ0Ua(hm(3f8(Dxj6at&xY0Acbe*7 zYCWB{{;x{hb4x#-Zx-7(P5bgVY1s$0=cbz~7;bbezp2vy^Lu*8QIidc4l7h<6)Ik~ zn0T%6<+Uf*_nh<(lPYqUmz{Suzq0>f$>~SSFV43AWTtOuv14!Rh1QFfTYv6k_P?O^ z{!^1w+2i~(PfY)vT=^ySaz{tbF{_;84|yKDsToaI|KWQiTBi5t_sUM^;y?G|4>YU( z6nlDFOHK6ef$!%3j_mDuwz6Z_=e{>*8)c@I8T?YTKT~~nD^IG%<;ocweIBf3i?ho< zKJ80N`Y)F+sev&|S5Jw)DVFo`?fv)<qTMt7vlnQ-Ew)j<r~UYb*+#Fl^)Ao<oQpT^ z%ROJ)^W;m!`l!0)`r+X>*1nwTFTCnrnPq9_%sIJ1lNn!3aNc}wwNCrV(yPo<FW>mI ze9zI}H3ylZHn7dTVYD`L%b~~<)io!U*Bmr@c6pZAmULMw@j~uLKiax~B%iUpHSu)V zu2)uV)?rfSGhY8)sh+}F{yF{F@eIZ6QoaY_qCf5(uBf{Dv^iWrYoVW@ZJDUIw^?__ z+x>S;9y|FxNXp~g;<8&!z37=%t*6WeF9!`vU(2@S87FIPj&o1+pKx`9<=z*^9k;Ch zaQ>BOOSr%)hR>VUO_{u>X~HTeX*R=-OJS#0O0A!!6510Kc53CXA2Z-<f?-Q-c`z30 z(spbLv>q9ZaV``_vLEU=&=4KwGUJfESy3$UA6+`H@4sVSnRmSFsm@cQ@>NUb?EU^W v-c-!(<We0b&(syiwA4I<K)w}u`Ja(ZjrnrV>sEIL1_lOCS3j3^P6<r_5HKx} literal 2959 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 Mr>mdKI;Vst0NG)|JOBUy -- GitLab