Converti le script en plugin #1

This commit is contained in:
Djedouas 2021-03-01 14:32:10 +01:00
parent 3093f80066
commit 691817794f
28 changed files with 2205 additions and 119 deletions

View File

@ -1,119 +0,0 @@
# 🄯 Association Linux-Alpes
# Contributeurs : Jean-Christophe Becquet (APITUX), Jacky Volpes, Arnaud Champollion
# mercredi 13 janvier 2021
# licence GPL version 3 ou supérieure
# ce script fait partie du projet CaliÉc
# voir http://www.linux-alpes.org/caliec/
import shutil
import tempfile
from pathlib import Path
from processing.tools import dataobjects
def main():
# Paramètres du projet
tempdir = tempfile.TemporaryDirectory()
styles_url = 'https://forge.chapril.org/linux_alpes/caliec/raw/branch/master/styles/'
lambert93 = QgsCoordinateReferenceSystem("EPSG:2154")
wgs = QgsCoordinateReferenceSystem("EPSG:4326")
wgspm = QgsCoordinateReferenceSystem("EPSG:3857")
scr = wgspm
project = QgsProject.instance()
project.setCrs(scr)
options = QgsVectorFileWriter.SaveVectorOptions()
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
options.driverName = "GPKG"
context = dataobjects.createContext()
context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)
# Correspondances des noms des couches et des styles:
# "NOM_DE_LA_COUCHE_OSM": ("nom_du_style", "nom_du_layer")
# Commenter les couches non désirées
# L'ordre impacte directement l'ordre final des couches
names = {
#"OUTPUT_OTHER_RELATIONS": (None, "Autres"),
"OUTPUT_MULTIPOLYGONS": ("multipolygon", "Surfaces"),
#"OUTPUT_MULTILINESTRINGS": (None, "Multilignes"),
"OUTPUT_LINES": ("linestring", "Lignes"),
"OUTPUT_POINTS": ("point", "Points"),
}
# Vérif de l'échelle
if iface.mapCanvas().scale() > 10000:
if QMessageBox.warning(iface.mainWindow(), "Zone étendue",
"La zone est étendue et le téléchargement risque de prendre longtemps",
QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Cancel:
return
# Paramétrage du dossier de travail
settings = QSettings()
dir = QFileDialog.getExistingDirectory(iface.mainWindow(),
"Sélectionnez un dossier de travail",
settings.value("caliec/workingDir"))
if dir == "":
return
settings.setValue("caliec/workingDir", dir)
workDir = Path(dir)
# Construction de la requête overpass
try:
url = processing.run("quickosm:buildqueryextent", {"EXTENT": iface.mapCanvas().extent()})["OUTPUT_URL"]
except QgsProcessingException:
QMessageBox.warning(iface.mainWindow(), "Attention", "Vous n'avez pas installé l'extension QuickOSM")
return
# Barre de chargement animée
qApp.setOverrideCursor(Qt.WaitCursor)
message_bar = iface.messageBar()
progress_bar = QProgressBar()
progress_bar.setMaximum(0)
widget = message_bar.createMessage("Chargement", "Récupération des data en ligne")
widget.layout().addWidget(progress_bar)
message_bar.pushWidget(widget)
# Téléchargement du fichier osm et création des couches
osmfile = str(Path(tempdir.name) / "osm.xml")
processing.run("native:filedownloader", {"URL": url, "OUTPUT": osmfile})
layers = processing.run("quickosm:openosmfile", {"FILE": osmfile})
for osm_name, style_layer_names in names.items():
style_name, layer_name = style_layer_names
# On explose les champs
layer = processing.run("native:explodehstorefield", parameters={"INPUT": layers[osm_name], "FIELD": "other_tags", "OUTPUT": "memory:"}, context=context)["OUTPUT"]
# On enregistre le layer dans le gpkg
options.layerName = layer_name
code, error = QgsVectorFileWriter.writeAsVectorFormat(layer, str(workDir / "data.gpkg"), options)
if code != 0:
QMessageBox.warning(None, 'Erreur', f"Erreur à l'export de la couche {layer_name} : \n\n{error}")
return
new_layer = QgsVectorLayer(str(workDir / f"data.gpkg|layername={layer_name}"), layer_name)
# Les layers suivants seront enregistrés dans le gpkg déjà existant
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
# On charge le style
if style_name is not None:
stylefile = str((Path(tempdir.name) / style_name).with_suffix('.qml'))
processing.run("native:filedownloader", {"URL": styles_url + f"{style_name}.qml", "OUTPUT": stylefile})
new_layer.loadNamedStyle(stylefile)
# On charge le nouveau layer
project.addMapLayer(new_layer)
try:
project.removeMapLayer(project.mapLayersByName("OpenStreetMap")[0])
except IndexError:
pass
iface.mapCanvas().refreshAllLayers()
project.write(str(workDir / 'orient.qgs'))
try:
main()
finally:
iface.messageBar().popWidget()
qApp.restoreOverrideCursor()

36
orientation/__init__.py Normal file
View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
Orientation
A QGIS plugin
Réaliser des cartes dorientation
Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
-------------------
begin : 2021-03-01
copyright : (C) 2021 by Association Linux-Alpes
email : caliec@linux-alpes.org
git sha : $Format:%H$
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
This script initializes the plugin, making it known to QGIS.
"""
# noinspection PyPep8Naming
def classFactory(iface): # pylint: disable=invalid-name
"""Load Orientation class from file Orientation.
:param iface: A QGIS interface instance.
:type iface: QgsInterface
"""
#
from .orientation import Orientation
return Orientation(iface)

11
orientation/i18n/fr.ts Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0" language="fr" sourcelanguage="en">
<context>
<name>@default</name>
<message>
<location filename="test_translations.py" line="48"/>
<source>Good morning</source>
<translation>Bonjour</translation>
</message>
</context>
</TS>

BIN
orientation/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

46
orientation/metadata.txt Normal file
View File

@ -0,0 +1,46 @@
# This file contains metadata for your plugin.
# This file should be included when you package your plugin.# Mandatory items:
[general]
name=CaLiÉc
qgisMinimumVersion=3.0
description=Réaliser des cartes dorientation
version=1.0
author=Association Linux-Alpes
email=caliec@linux-alpes.org
about=Permettre la production de supports pour lenseignement en géographie et EPS (course dorientation) à lécole primaire. En effet la représentation de lespace y est travaillée sur des zones peu étendues, et la symbologie doit être adaptée à lâge des élèves.
tracker=https://forge.chapril.org/linux_alpes/caliec/issues
repository=https://forge.chapril.org/linux_alpes/caliec/
# End of mandatory metadata
# Recommended items:
hasProcessingProvider=no
# Uncomment the following line and add your changelog:
# changelog=
# Tags are comma separated with spaces allowed
tags=python, osm
homepage=http://www.linux-alpes.org/caliec/
category=Plugins
icon=icon.png
# experimental flag
experimental=False
# deprecated flag (applies to the whole plugin, not just a single version)
deprecated=False
# Since QGIS 3.8, a comma separated list of plugins to be installed
# (or upgraded) can be specified.
plugin_dependencies=QuickOSM
Category of the plugin: Raster, Vector, Database or Web
# category=
# If the plugin can run on QGIS Server.
server=False

302
orientation/orientation.py Normal file
View File

@ -0,0 +1,302 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
Orientation
A QGIS plugin
Réaliser des cartes dorientation
Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
-------------------
begin : 2021-03-01
git sha : $Format:%H$
copyright : (C) 2021 by Association Linux-Alpes
email : caliec@linux-alpes.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
"""
from qgis.PyQt.QtCore import Qt, QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction, qApp, QFileDialog, QProgressBar, QMessageBox
from qgis.core import QgsCoordinateReferenceSystem, QgsProject, QgsVectorFileWriter, QgsVectorLayer, QgsFeatureRequest
from processing import QgsProcessingException
# Initialize Qt resources from file resources.py
from .resources import *
import processing
import os.path
import shutil
import tempfile
from pathlib import Path
from processing.tools import dataobjects
class Orientation:
"""QGIS Plugin Implementation."""
def __init__(self, iface):
"""Constructor.
:param iface: An interface instance that will be passed to this class
which provides the hook by which you can manipulate the QGIS
application at run time.
:type iface: QgsInterface
"""
# Save reference to the QGIS interface
self.iface = iface
# initialize plugin directory
self.plugin_dir = os.path.dirname(__file__)
# initialize locale
locale = QSettings().value('locale/userLocale')[0:2]
locale_path = os.path.join(
self.plugin_dir,
'i18n',
'Orientation_{}.qm'.format(locale))
if os.path.exists(locale_path):
self.translator = QTranslator()
self.translator.load(locale_path)
QCoreApplication.installTranslator(self.translator)
# Declare instance attributes
self.actions = []
self.menu = self.tr(u'&CaLiÉc')
# Check if plugin was started the first time in current QGIS session
# Must be set in initGui() to survive plugin reloads
self.first_start = None
# noinspection PyMethodMayBeStatic
def tr(self, message):
"""Get the translation for a string using Qt translation API.
We implement this ourselves since we do not inherit QObject.
:param message: String for translation.
:type message: str, QString
:returns: Translated version of message.
:rtype: QString
"""
# noinspection PyTypeChecker,PyArgumentList,PyCallByClass
return QCoreApplication.translate('Orientation', message)
def add_action(
self,
icon_path,
text,
callback,
enabled_flag=True,
add_to_menu=True,
add_to_toolbar=True,
status_tip=None,
whats_this=None,
parent=None):
"""Add a toolbar icon to the toolbar.
:param icon_path: Path to the icon for this action. Can be a resource
path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
:type icon_path: str
:param text: Text that should be shown in menu items for this action.
:type text: str
:param callback: Function to be called when the action is triggered.
:type callback: function
:param enabled_flag: A flag indicating if the action should be enabled
by default. Defaults to True.
:type enabled_flag: bool
:param add_to_menu: Flag indicating whether the action should also
be added to the menu. Defaults to True.
:type add_to_menu: bool
:param add_to_toolbar: Flag indicating whether the action should also
be added to the toolbar. Defaults to True.
:type add_to_toolbar: bool
:param status_tip: Optional text to show in a popup when mouse pointer
hovers over the action.
:type status_tip: str
:param parent: Parent widget for the new action. Defaults None.
:type parent: QWidget
:param whats_this: Optional text to show in the status bar when the
mouse pointer hovers over the action.
:returns: The action that was created. Note that the action is also
added to self.actions list.
:rtype: QAction
"""
icon = QIcon(icon_path)
action = QAction(icon, text, parent)
action.triggered.connect(callback)
action.setEnabled(enabled_flag)
if status_tip is not None:
action.setStatusTip(status_tip)
if whats_this is not None:
action.setWhatsThis(whats_this)
if add_to_toolbar:
# Adds plugin icon to Plugins toolbar
self.iface.addToolBarIcon(action)
if add_to_menu:
self.iface.addPluginToMenu(
self.menu,
action)
self.actions.append(action)
return action
def initGui(self):
"""Create the menu entries and toolbar icons inside the QGIS GUI."""
icon_path = ':/plugins/caliec/icon.png'
self.add_action(
icon_path,
text=self.tr(u'Créer le projet'),
callback=self.run,
parent=self.iface.mainWindow())
# will be set False in run()
self.first_start = True
def unload(self):
"""Removes the plugin menu item and icon from QGIS GUI."""
for action in self.actions:
self.iface.removePluginMenu(
self.tr(u'&CaLiÉc'),
action)
self.iface.removeToolBarIcon(action)
def run(self):
try:
self.main()
finally:
self.iface.messageBar().popWidget()
qApp.restoreOverrideCursor()
def main(self):
# Paramètres du projet
tempdir = tempfile.TemporaryDirectory()
styles_url = 'https://forge.chapril.org/linux_alpes/caliec/raw/branch/master/styles/'
lambert93 = QgsCoordinateReferenceSystem("EPSG:2154")
wgs = QgsCoordinateReferenceSystem("EPSG:4326")
wgspm = QgsCoordinateReferenceSystem("EPSG:3857")
scr = wgspm
project = QgsProject.instance()
project.setCrs(scr)
options = QgsVectorFileWriter.SaveVectorOptions()
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteFile
options.driverName = "GPKG"
context = dataobjects.createContext()
context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck)
# Correspondances des noms des couches et des styles:
# "NOM_DE_LA_COUCHE_OSM": ("nom_du_style", "nom_du_layer")
# Commenter les couches non désirées
# L'ordre impacte directement l'ordre final des couches
names = {
#"OUTPUT_OTHER_RELATIONS": (None, "Autres"),
"OUTPUT_MULTIPOLYGONS": ("multipolygon", "Surfaces"),
#"OUTPUT_MULTILINESTRINGS": (None, "Multilignes"),
"OUTPUT_LINES": ("linestring", "Lignes"),
"OUTPUT_POINTS": ("point", "Points"),
}
# Vérif de l'échelle
if self.iface.mapCanvas().scale() > 10000:
if QMessageBox.warning(self.iface.mainWindow(), "Zone étendue",
"La zone est étendue et le téléchargement risque de prendre longtemps",
QMessageBox.Ok | QMessageBox.Cancel) == QMessageBox.Cancel:
return
# Paramétrage du dossier de travail
settings = QSettings()
dir = QFileDialog.getExistingDirectory(self.iface.mainWindow(),
"Sélectionnez un dossier de travail",
settings.value("caliec/workingDir"))
if dir == "":
return
settings.setValue("caliec/workingDir", dir)
workDir = Path(dir)
# Construction de la requête overpass
try:
url = processing.run("quickosm:buildqueryextent",
parameters={"EXTENT": self.iface.mapCanvas().extent()})["OUTPUT_URL"]
except QgsProcessingException:
QMessageBox.warning(self.iface.mainWindow(), "Attention", "Vous n'avez pas installé l'extension QuickOSM")
return
# Barre de chargement animée
qApp.setOverrideCursor(Qt.WaitCursor)
message_bar = self.iface.messageBar()
progress_bar = QProgressBar()
progress_bar.setMaximum(0)
widget = message_bar.createMessage("Chargement", "Récupération des data en ligne")
widget.layout().addWidget(progress_bar)
message_bar.pushWidget(widget)
# Téléchargement du fichier osm et création des couches
osmfile = str(Path(tempdir.name) / "osm.xml")
processing.run("native:filedownloader", {"URL": url, "OUTPUT": osmfile})
layers = processing.run("quickosm:openosmfile", {"FILE": osmfile})
for osm_name, style_layer_names in names.items():
style_name, layer_name = style_layer_names
# On explose les champs
layer = processing.run("native:explodehstorefield",
parameters={"INPUT": layers[osm_name],
"FIELD": "other_tags", "OUTPUT": "memory:"},
context=context)["OUTPUT"]
# On enregistre le layer dans le gpkg
options.layerName = layer_name
code, error = QgsVectorFileWriter.writeAsVectorFormat(layer, str(workDir / "data.gpkg"), options)
if code != 0:
QMessageBox.warning(None, 'Erreur', f"Erreur à l'export de la couche {layer_name} : \n\n{error}")
return
new_layer = QgsVectorLayer(str(workDir / f"data.gpkg|layername={layer_name}"), layer_name)
# Les layers suivants seront enregistrés dans le gpkg déjà existant
options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
# On charge le style
if style_name is not None:
stylefile = str((Path(tempdir.name) / style_name).with_suffix('.qml'))
processing.run("native:filedownloader",
parameters={"URL": styles_url + f"{style_name}.qml", "OUTPUT": stylefile})
new_layer.loadNamedStyle(stylefile)
# On charge le nouveau layer
project.addMapLayer(new_layer)
try:
project.removeMapLayer(project.mapLayersByName("OpenStreetMap")[0])
except IndexError:
pass
self.iface.mapCanvas().refreshAllLayers()
project.write(str(workDir / 'orient.qgs'))

774
orientation/resources.py Normal file
View File

@ -0,0 +1,774 @@
# -*- coding: utf-8 -*-
# Resource object code
#
# Created by: The Resource Compiler for PyQt5 (Qt v5.15.2)
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore
qt_resource_data = b"\
\x00\x00\x2c\x6f\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
\x00\x00\x68\x00\x00\x00\x75\x08\x06\x00\x00\x00\xa2\x54\xa4\xe4\
\x00\x00\x00\x06\x62\x4b\x47\x44\x00\xff\x00\xff\x00\xff\xa0\xbd\
\xa7\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\
\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\x07\x74\x49\x4d\x45\x07\
\xe5\x03\x01\x0c\x25\x29\xd6\x1a\x8c\xcb\x00\x00\x20\x00\x49\x44\
\x41\x54\x78\xda\xed\x5d\x77\x78\x14\xc5\xdf\xff\xcc\x5e\xca\xa5\
\x57\x08\x09\xa1\x06\x88\x04\x41\x08\x45\x3a\x0a\x88\x20\xd5\x50\
\x14\x44\x40\xf9\x59\x29\x22\x22\x22\x8a\xa2\x40\x00\x51\x10\x50\
\xa9\x2a\x88\x8a\x09\x22\x55\x40\x42\x8d\x84\x00\x09\xcd\x84\x12\
\x20\x60\x20\x80\x94\x40\x48\xcf\x25\x77\xf3\xfe\x71\x5b\x66\xf7\
\x76\xf7\xf6\x02\xfe\x5e\xdf\xf7\x71\xf3\xdc\x93\xdd\xd9\x99\xd9\
\xa9\xdf\xfa\x99\x19\x42\x29\xc5\xbf\xd7\x3f\xf7\xe2\xfe\x6d\x82\
\x7f\x78\x07\x09\x33\x48\xef\xbf\x91\x38\xc2\x65\x34\x6e\x55\xd3\
\xb8\x92\xaf\xab\xf9\xff\x9d\xe5\x56\x4b\xa3\x57\x1f\xe1\x9e\xfc\
\xb7\x49\x1c\xa5\x14\x84\x90\xff\x77\xdf\xfa\xbb\x2e\xf2\x2f\x0f\
\xfa\x67\x5f\x6e\xca\x51\x26\x3c\xeb\x75\x9c\x32\xbe\xda\x7b\x65\
\x38\x1b\x66\x34\x7f\xa3\xf1\x8d\xc6\xd1\xca\x5f\x99\x87\x32\x2f\
\x67\xcf\xae\x96\x45\xeb\x3b\xaa\x71\x6d\x36\x9b\x4b\x95\x73\xb5\
\x11\x5d\x69\x5c\xbd\xb8\xae\x54\xca\x48\xd9\x1f\x64\x87\xff\x9d\
\xdf\xf9\x97\xc4\xfd\x5f\x12\xb3\xf5\x24\x14\x23\xef\xb5\xf2\xd2\
\x4b\xaf\xc7\xe0\x5d\x7d\xef\xca\x60\x63\x25\x28\x23\xf9\xdf\xef\
\xf7\xaa\x5a\x16\x37\x23\xb4\xd9\x15\x69\x49\xed\x5e\xf8\xaf\x75\
\xaf\x97\x2e\x25\x25\x85\x26\x27\x27\x6b\x7e\x3b\x3a\x3a\x1a\x71\
\x71\x71\x44\x29\xad\x09\x79\x7c\xfb\xed\xb7\xf4\xfa\xf5\xeb\xaa\
\x69\x9b\x36\x6d\x8a\xbe\x7d\xfb\x12\x35\x69\x4f\x59\x3e\xb5\xbc\
\x95\x64\x57\x8f\x97\xeb\xd5\x57\xd9\xf6\xb2\x7e\x60\xe5\xf1\x7f\
\xe2\x6f\xfa\xf4\xe9\x14\x00\xf5\xf3\xf3\xa3\x01\x01\x01\xb2\x9f\
\x9f\x9f\x1f\xf5\xf6\xf6\xa6\x19\x19\x19\x54\x2b\x7d\x6c\x6c\x2c\
\xe5\x38\x4e\x96\xce\xdf\xdf\x9f\x12\x42\xe8\xf0\xe1\xc3\xe9\x3f\
\xbd\xfe\x6e\x7a\xd2\xcc\x83\x60\x86\x6a\x12\x50\x55\x66\x69\xf2\
\xfe\x64\xd4\xa9\x53\x47\x16\x66\xb1\x58\xd0\xa7\x6f\x1f\xf4\xec\
\xd9\x13\x07\x0e\x1c\xa0\x75\xea\xd4\x21\x6a\x65\x89\x89\x89\xc1\
\xde\x3d\x7b\x61\x32\x99\x00\x00\xf9\xf9\xf9\x68\xd5\xba\x95\x4b\
\x52\xa8\xd1\x70\xe5\xbd\x2b\x75\x55\xcb\x9f\xd3\xa3\xad\xf7\xab\
\xe4\xa9\x7d\x50\x18\x19\xce\xf2\x56\xbe\xf7\xf7\xf7\x47\x60\x60\
\x20\x02\x83\xec\xbf\xa0\xa0\x20\x54\x0f\xab\x8e\x29\xef\x4c\xc1\
\xd5\xab\x57\xb1\x78\xf1\x62\xcd\xb2\x9b\x4c\x26\x04\x05\x05\x89\
\x69\x03\x02\x02\xc0\x11\xce\xb0\x82\xeb\xac\xa1\xd5\x78\xab\xb3\
\x34\x02\x89\xd4\xca\x47\x78\xcf\x09\x91\xd8\x04\x6a\x3c\x42\xed\
\xbd\x1a\x5f\x71\x96\x5e\x2f\x1f\x36\x5c\xad\x93\x08\x21\x10\xfe\
\x28\xa5\x20\x20\x18\x30\x60\x00\x06\x0d\x1a\x84\xa5\x4b\x97\x22\
\x33\x33\x93\xea\xa6\xe7\xff\xd4\x06\x82\xd6\xf7\xf5\xea\xe7\x2c\
\x4c\xaf\xfd\xb4\xbe\xaf\x4c\xcf\x29\x6d\x43\x42\x81\x9c\xd9\xc1\
\xd8\x9f\x5a\x1a\xf6\x9e\x7d\xef\xec\xa7\x66\xa7\x12\x47\x18\xf3\
\xb7\x6a\xf5\x2a\xdc\xb9\x73\x07\x9c\x89\xc3\x9a\xef\xd6\xa0\x49\
\x93\x26\x18\x3b\x76\x2c\x2a\x2a\x2a\x74\xd3\xeb\xd9\xe9\xb4\xca\
\xaa\x55\x3f\xbd\x30\x23\xed\xa7\x65\x9b\x63\xdf\x73\x0f\x42\x74\
\xbc\x5f\x91\xd9\xf8\x87\xa4\xff\x3b\x76\xec\xc0\xaa\xd5\xab\x00\
\x0a\x78\x9a\x3d\x31\x7e\xdc\x78\x1c\x3e\x7c\x18\x9f\x7d\xf6\x19\
\xd5\xcf\xe2\xef\x15\xdf\x1f\x64\xbb\x89\x1d\x64\x84\xf4\x18\x25\
\x51\xce\xe2\xe9\x3d\xeb\x91\x02\x19\x89\x23\x04\x15\x96\x0a\xcc\
\x98\x31\x03\xe7\xce\x9f\x03\x00\x0c\x1b\x36\x0c\x4f\x74\x7f\x02\
\x33\x66\xcc\x40\x7a\x7a\x3a\x55\xa3\xf1\x7a\xbc\xc0\x08\x29\xbf\
\xdf\x5f\x55\xf2\xe7\x9c\x49\x6c\x46\x94\x4b\x3d\xa5\x4e\xad\x91\
\xb5\x98\xa9\xf2\x9d\x33\x12\x95\x9f\x9f\x8f\x99\x33\x67\x02\x14\
\x20\x1c\x41\x7c\x7c\x3c\x00\x60\xda\xb4\x69\xea\xd2\x16\x88\xcb\
\xba\x9c\x11\x65\x5d\x4d\xd9\xd4\x12\x1c\xf4\x4c\x63\x6a\x69\x38\
\x67\x3c\xc6\x19\xfd\x74\x96\xc6\x15\x5e\xe3\x74\xca\x53\x9e\x0f\
\x31\xf1\x12\x12\x12\x70\xf0\xe0\x41\x80\x02\x4d\x9a\x34\xc1\xf2\
\xe5\xcb\xb1\x77\xef\x5e\xec\xdc\xb9\x93\xaa\x76\x30\xd5\xd6\xe2\
\x9d\xf9\x9b\x9c\xdd\xbb\xda\x56\x46\xda\x9a\xd3\x1b\xe5\x5a\xa2\
\xaf\x2b\xf1\xb5\x24\x16\xad\xb8\xae\x88\xf8\xd5\xaa\x55\x43\xcb\
\x96\x2d\xd1\xbb\x4f\x6f\x9c\x3e\x7d\x1a\x84\x23\x18\x36\x74\x18\
\xfa\xf6\xed\x8b\xe7\x9f\x7f\x1e\x07\x0f\x1e\xa4\x46\x49\x9c\x1a\
\xb9\x73\x26\xfa\xab\x91\x2d\x3d\x31\x5a\xab\x1d\xb4\xda\x09\x80\
\xa3\x98\x6d\x44\x04\x66\xc5\x4e\xbd\xf4\x5a\x8d\xa0\x25\x56\x1a\
\xe2\x41\x54\x7a\xef\xee\xee\x8e\x89\x13\x27\xe2\xde\xbd\x7b\xf8\
\xea\xab\xaf\x00\x0a\x70\x1c\x87\x49\x6f\x4d\x42\x5e\x5e\x1e\x3e\
\xff\xfc\x73\x47\x31\xbb\x8a\x8d\xef\x6a\x3d\xd5\x78\x9c\x96\xfa\
\xa1\x36\x48\x45\x1e\x54\x55\x05\xf4\x7e\xde\xdf\x97\x14\x47\x20\
\x23\x53\x3d\x7b\xf6\xc4\xf8\xf1\xe3\xb1\xf2\xeb\x95\x22\xa9\x7b\
\xf4\xd1\x47\x31\x76\xec\x58\x6c\xdc\xb8\x11\x67\xcf\x9e\x75\x94\
\x02\xff\x6e\x2f\xe8\x7d\xb6\x8f\x6c\x06\x69\xe9\x1d\x6a\x74\xd5\
\x08\xbf\x71\x46\x8b\xf5\x78\x8f\x11\x3d\x48\xe0\x43\x6c\x65\x3e\
\xfd\xf4\x53\xb4\x6d\xdb\x16\x13\xde\x9c\x00\x4b\x85\x05\x00\xf0\
\xc9\xdc\x4f\xf0\xd4\x53\x4f\xa1\xa4\xa4\xc4\x10\x0f\x32\xc2\x3f\
\xb5\xd2\x68\x59\xfe\x8d\xf0\x1d\x67\xdf\xe0\xd4\xa4\x29\x35\x89\
\x4a\x4d\x0a\xd1\xb2\x00\x3b\x93\xde\xb4\x68\xbd\xde\xf4\x17\xa5\
\x30\xe2\x18\xee\xee\xee\x8e\xc9\x93\x27\x23\x23\x23\x03\x53\xde\
\x9d\x02\x4a\x29\x3c\x3d\x3c\x31\xe5\x9d\x29\x70\x73\x73\x73\x48\
\xaf\xc7\x83\x5c\xe5\x2f\x6a\xe4\x5f\x49\xda\xd4\x2c\x11\xce\xc8\
\xb9\x10\xe6\x66\x84\x79\xeb\x3d\x6b\xd9\xad\xb4\xf2\x35\x9a\x5e\
\x93\x0c\x30\x33\xa0\xa0\xa0\x00\xef\xbd\xf7\x1e\x2c\x16\x0b\x8a\
\x8b\x8b\xe1\xe1\xe1\x81\x2f\xbe\xf8\x02\x7d\xfb\xf4\xc5\xe3\x8f\
\x3d\x8e\x76\x6d\xdb\x61\xec\x98\xb1\xd8\xbb\x6f\xaf\x26\x99\x53\
\x36\x9e\xd1\x72\x6b\xb9\x24\x8c\xb4\xa1\x2b\xed\xe4\xa6\xa7\xd3\
\x38\xb3\x52\x1b\xd1\x88\x8d\xc4\xd3\xd2\x9b\x1c\xa6\xbd\xa2\x75\
\x8b\x8a\x8a\xb0\x68\xd1\x22\x69\x7e\x10\x80\x52\x60\xfe\x82\xf9\
\x78\xec\xb1\xc7\x00\x00\xaf\xbf\xfe\x3a\x8e\x1d\x3b\xa6\x6b\x45\
\xb8\xdf\x3a\xaa\x51\x8d\x07\x81\xed\x00\x00\x37\xb5\x4c\x5d\x75\
\x5c\x19\x0d\xd7\x9a\x41\xca\xf0\xdb\xb7\x6f\xcf\xd9\xb6\x6d\xdb\
\x3b\xbb\x76\xed\xc2\xb6\x6d\xdb\xe4\x69\x99\x7a\xf8\x06\x04\x63\
\xdc\x47\x2b\xe0\x1f\x18\x02\x4f\x2f\x6f\x98\xbd\x7d\x71\x29\xeb\
\x24\x3e\x7f\x77\x24\x12\x12\x12\x30\x64\xc8\x10\x34\x68\xd8\x00\
\xab\x56\xad\x92\x66\x09\x93\x7e\xe3\xc6\x8d\x18\x34\x68\x10\xed\
\xd6\xad\x1b\xfa\xf7\xef\x8f\x88\x88\x08\xa2\x55\x1f\x23\xb3\x5f\
\x2d\xdc\x88\xc0\xa4\x96\x8f\x18\x26\x8c\x52\x9b\xcd\x06\x9b\xcd\
\x26\x7b\x56\xbb\xaf\xca\x7b\xad\x34\xc2\xb3\xf0\xff\xf8\xf1\xe3\
\x74\xe0\xc0\x81\x34\x24\x24\x84\xf2\xc4\x88\x9a\x4c\x6e\x14\x00\
\xcd\xbe\x90\x4d\xa9\x8d\x52\x6a\xa5\x94\xda\x28\x7d\x7a\xc0\xd3\
\x34\xb8\x7a\x04\x4d\x4c\x2b\xa4\x9b\x4f\xd9\xe8\xe6\x4c\x1b\xdd\
\x72\x8a\xd2\xcd\x99\x36\xda\xb1\xe7\x10\xea\xef\xef\x4f\x53\x52\
\x52\x28\xb5\x52\x6a\xb3\xda\xc4\x74\xd4\x4a\x69\xde\xed\x3c\x1a\
\x1a\x12\x2a\xe6\x2d\x38\x04\x7b\xf6\xec\x49\x93\x92\x92\xa8\xd1\
\x3a\x2a\xeb\xa6\x8c\xa3\x97\x5e\xed\x59\x2d\x3e\xe7\x4c\xa9\x74\
\x85\x86\xba\x4a\x77\x09\x21\xb0\x5a\xad\x38\x76\xec\x18\x9d\x34\
\x69\x12\xed\xdc\xb9\x33\xd6\xaf\x5f\x0f\xb8\x79\xa1\xef\xf0\xf1\
\x98\xf6\xe5\x66\xc4\xbd\xf8\xb6\xd2\x5e\xa3\x62\xc2\xb1\xe7\x57\
\x78\xef\x0e\x8a\xee\xdd\xc5\x90\x97\xa6\xa2\xb4\xcc\x82\x59\xb3\
\x66\xc1\x6a\xb3\xda\xbf\xab\x92\xae\xc3\x93\x83\x31\xeb\x9b\x3d\
\x18\xfc\xf2\x54\xf8\x06\x85\xe1\xb7\xdf\x76\xa2\x4f\x9f\x3e\x18\
\x35\x6a\x14\x3d\x70\xe0\x00\xad\xac\xac\x74\x49\x34\xd6\xe3\xd7\
\xce\x78\xb9\x56\xfb\xbb\x29\x7d\xea\x6a\xff\x9d\x39\xe4\xb4\x70\
\x63\x7a\x95\xb2\xd9\x6c\x38\x74\xe8\x10\x9d\x3d\x7b\x36\xb6\x6f\
\xdf\x0e\x80\xa0\x6d\xf7\xa7\xd1\x63\xe0\x68\xc4\xb4\xe8\x08\x4f\
\x6f\x1f\x00\x14\xd9\xa7\xed\xfc\xe3\xfd\x69\xef\xc3\xcf\xcf\x4f\
\x4c\x7f\xfc\xc4\x71\x59\x17\x65\xa4\xed\xc7\xac\x71\x03\x40\xa9\
\x0d\x53\x17\x6d\xc0\x90\x57\xa6\x22\x61\xe9\x4c\x3c\x37\xfc\x39\
\x04\x04\x04\xc8\xbe\x5d\x5e\x5e\x8e\xa2\xe2\x22\x98\x4c\x26\x34\
\x7d\xf4\x71\x34\x7b\xf4\x71\x0c\x7d\xed\x03\x9c\xcf\x4c\xc7\xee\
\x4d\xab\xf0\x53\xe2\x8f\xf8\xee\xbb\xef\xd0\xbe\x7d\x7b\x1a\x1f\
\x1f\x8f\x76\xed\xda\x11\x77\x77\x77\x55\xfe\xe2\xac\xad\x8c\xb4\
\xad\x96\x0d\x50\xc6\x83\x9c\xfd\x77\xc6\xe8\x8c\x9a\x7f\x00\xa0\
\xa2\xa2\x02\xb3\x66\xcd\xa2\x33\x67\xce\x84\xcd\x66\x43\xdd\xe8\
\x47\x30\x7c\xdc\x0c\xb4\xee\xfc\x14\x08\xc7\x31\xfa\x28\x81\xc9\
\xcd\x1d\x9e\x66\x6f\xfc\xb2\x61\x93\x43\x3e\xc1\xd5\xc2\xed\xf1\
\x28\xc5\xf6\x84\x25\x28\x2e\xcc\x07\x00\x6c\xf9\x7e\x11\xa6\x7e\
\xbe\x1e\xd9\xa7\x8f\x61\xe3\xa6\x2d\x9a\x86\x7c\x37\x0f\x4f\x3e\
\x3d\xe0\xee\xe1\x89\x98\xd8\x0e\x68\xdc\xa2\x3d\x7a\x0e\x7e\x05\
\x2b\xe6\xbc\x81\xd4\xd4\x43\xe8\xd6\xad\x1b\x46\x8c\x18\x41\x17\
\x2e\x5c\x48\x7c\x7d\x7d\xab\xd4\x56\x46\xe3\xab\x52\x9d\xbf\x1b\
\x17\xa7\xd4\xa9\x36\x6f\xde\x4c\xe7\xcd\x9b\x87\x94\x94\x83\xa8\
\x59\xb7\x21\x86\xbc\xf2\x3e\x1e\xeb\x3d\x0c\x1c\x67\x92\xc8\x10\
\x65\x71\x07\xa5\x28\x2f\x2b\x55\x6f\x62\x8e\x83\xb7\x6f\x00\xce\
\x9f\x4a\xc7\xd4\x51\x8f\xa3\xbc\xb4\xd8\x3e\xea\xdc\x3d\xb0\xe8\
\x97\x13\x08\xab\x59\x0f\xe5\x65\x25\x9a\x65\x73\xf7\xf0\x84\xd9\
\xec\x0d\x08\x0d\x43\x25\x12\x4a\xa9\x0d\xc7\x52\x76\xe2\x9b\x79\
\x93\x70\x25\xfb\x0c\xa2\xa3\x1b\xe1\x93\x4f\x3e\x41\xaf\x5e\xbd\
\x08\xab\x5b\xb9\x22\x20\x55\xc9\x2a\xa1\xf4\x1a\x1a\x01\x43\xb8\
\x02\x1a\x61\xc9\xca\xd4\xa9\x53\xe9\xa2\x45\x8b\x60\xf6\xf6\xc3\
\xa8\xb7\xe6\xe2\xf1\xbe\xcf\xc3\xd3\x6c\x16\x5b\x85\x82\xf2\x2e\
\x01\xd6\xa6\x43\x44\x01\xd9\xf1\x1d\x50\x59\x51\x81\xd7\xfb\x35\
\xc1\xf5\xcb\x17\x64\xdf\x6b\xdb\x6d\x00\xde\x9c\xbd\x1a\xde\x3e\
\x7e\x50\xf6\xbc\x3c\x2f\x75\x6b\x92\x70\x95\x95\x96\xe0\x58\xca\
\x6f\x58\x31\x67\x02\xf2\xfe\xca\xc5\xe0\xc1\x83\xb1\x6c\xd9\x32\
\x12\x10\x10\xa0\x2b\xd5\x19\x51\xf6\x9d\xb5\xa1\x68\x8b\x33\xe2\
\x6b\xd7\x73\x30\x39\x73\x3e\x5d\xbb\x76\x8d\x4e\x9e\x3c\x99\x2e\
\x5e\xbc\x18\x61\x91\x51\x78\x79\xea\x22\x3c\x39\xe8\x25\x78\x9a\
\xbd\x00\xca\x88\xbe\xe2\x3d\x91\xd8\x3f\x05\x28\xb5\x1b\x49\xed\
\xf2\x16\x91\xe2\x82\xe0\xf4\xf1\x14\x87\xce\x01\x80\xb4\xfd\x5b\
\x71\xea\xe8\xef\x4c\x7c\x7b\x3e\x94\x32\xb8\x04\x4a\x00\x3e\x4c\
\xb8\x27\xc2\x3d\xec\xe1\x9e\x66\x1f\xb4\xef\x1e\x87\x09\x33\xbf\
\x45\x58\x64\x3d\x24\x26\x26\x62\xe2\xc4\x89\x34\x27\x27\x87\x1a\
\x15\x9c\x5c\x31\x44\x3b\x84\x39\xac\x47\xd1\x00\xd8\x39\x93\xf9\
\xb5\xde\x9f\x39\x73\x86\xf6\xeb\xd7\x0f\x17\x2e\x5c\xc0\xe3\x7d\
\x87\xe3\xe5\xa9\x8b\xe1\xeb\x17\x68\x1f\xa9\x02\x03\x60\x47\x38\
\x91\x00\x21\x8e\x36\x52\xf9\x0c\xb3\xd9\xac\xf8\xf0\x95\x9e\x38\
\x91\xba\x4b\x75\xd6\x3e\xd4\xbc\x1d\xe6\xae\x39\x00\x42\x38\xd9\
\x1c\x22\x2a\x79\x4a\xff\xf9\x70\x02\x10\x2a\xa5\xa0\xa0\x28\x2b\
\x29\x42\xe2\xf2\x78\xfc\xf2\xcd\x3c\x84\x86\x86\x20\x31\x31\x11\
\x5d\xba\x74\x21\x46\x49\x9b\xb3\x38\x6a\x6d\x49\x6c\x36\x9b\x4b\
\xb0\x29\x57\xae\xf3\xe7\xcf\xd3\xae\x5d\xbb\xe2\xaf\x1b\x37\x11\
\xf7\xe2\xdb\x18\x3e\xf6\x63\x70\x26\x4e\x9b\x9e\xa8\x0a\xd0\x14\
\x94\x4a\x6c\x82\x4d\x77\x3e\xf3\x28\x26\x0d\x6d\x0b\x9b\xcd\xaa\
\x99\xc3\xdc\x35\x07\x10\x13\xdb\x5e\xce\xdb\x78\x8b\x03\xa0\xc8\
\x57\xef\xfb\x4c\xba\x2d\x3f\x2c\xc6\xd7\x73\x27\xc2\xdb\xdb\x0b\
\xfb\xf7\xef\x47\x8b\x16\x2d\xc8\xdf\xd1\x7e\xa2\xcb\xdb\xa8\xdf\
\xc7\x15\xb2\x76\xe0\xc0\x01\xda\xa1\x43\x07\xdc\xb8\x79\x0b\x2f\
\xbf\xbb\x10\xcf\x8f\x9b\x01\xc2\x99\xec\xe4\x84\x27\x1f\x94\x27\
\x33\x2c\x89\xa1\x90\x9e\xed\xfc\x91\x6f\x26\x26\x1e\x05\x81\xb5\
\xb2\x12\x3b\xd7\xaf\x94\x3a\x87\x98\xa4\x8a\xb9\x79\x8a\xf7\xdb\
\x13\x97\xc2\x8e\xa0\x15\x35\x26\x86\xcc\x49\x24\x4e\x8c\x23\x3e\
\x0b\xdf\xe7\xe3\x11\x22\x76\x6a\xef\x67\x5f\xc3\xdb\x9f\xae\x85\
\x0d\x1c\x7a\xf7\xee\x8d\x9f\x7e\xfa\x89\xea\x19\x41\x9d\xf9\xbe\
\xb4\xde\x8b\xd6\x6c\x35\x32\x67\xc4\x56\xa5\x05\x4a\x3c\x71\xe2\
\x04\x1d\x34\x68\x10\x0a\x8b\x4b\xf1\x66\xfc\x6a\xf4\x7a\xe6\x55\
\x80\xb3\xdb\xca\x08\x11\x95\x77\xfb\xe8\x25\xfc\x28\x26\x14\x20\
\x14\x84\x0f\xa7\x44\x78\x6f\x8f\x40\x08\xb5\xa7\xe5\x7f\x7b\x36\
\xaf\xc1\x9e\x4d\xdf\xf1\xe2\x9c\x19\x08\xef\x21\x96\x23\xac\xd5\
\x50\xb1\x93\x0e\xee\x5c\x8f\xac\x3f\x0e\x09\x22\x91\x9d\x74\x31\
\xdf\xa5\xfc\xb7\x89\x60\x25\x27\x10\xcb\x69\x6f\x30\xa1\xcc\x10\
\xe3\x98\xdc\xdc\xd1\xf1\xc9\xc1\xf8\xe0\xab\xad\x28\x2a\xb5\xe0\
\x85\x17\x5e\x80\x60\x81\x50\x7a\x05\xd4\xdc\x0d\xca\x38\x5a\xef\
\x65\x33\xc8\x99\x95\x55\x4d\xc2\x50\x93\xe3\x2f\x5d\xba\x44\xc7\
\x8c\x19\x83\xbc\xbc\x3b\x18\xf7\xf1\x0a\x74\xea\xf5\x2c\x6f\x53\
\xe2\x47\x29\xc3\xe0\xed\xa3\x59\x12\x10\xa4\x11\x0c\x10\x7e\xa6\
\x40\xe8\x4f\x30\x23\xdb\x46\xb1\x73\xfd\xd7\xb0\x94\xf3\xe2\x77\
\x64\x5f\x20\xa0\x89\x58\x0e\x73\x68\x3d\x04\x3d\xd4\xcd\x2e\xa6\
\x97\x97\x62\xc5\xec\x09\xb0\x59\x2b\x79\x61\x03\xe2\x6c\x11\x66\
\x27\x71\x98\x45\x6c\x79\x20\x96\x93\x32\x61\x94\x02\x31\xb1\x9d\
\x30\xfa\xed\x4f\x61\x72\x37\xe3\xd5\x57\x5f\xc5\xb5\x6b\xd7\xa8\
\x96\x4b\x45\xcd\xa5\xaf\x25\x8c\xb1\x6d\xcf\x19\x75\x50\x39\x73\
\xec\x51\x4a\x71\xeb\xd6\xad\xc4\x7e\xfd\xfa\x21\x35\x35\x15\x23\
\x27\xce\x41\xe7\x5e\xcf\x0a\x91\x20\xb5\x34\xe1\x85\x66\xca\x77\
\x0e\x9f\xa7\x20\x20\x08\xef\xf8\x74\x44\x80\x2a\x32\x79\x9c\x4a\
\x4f\xc6\xb9\x8c\xc3\xbc\x32\xe3\x0f\x3c\x12\x2f\x67\x66\x84\xa0\
\x7e\xff\x78\x78\x04\xd6\x04\x00\x9c\xcb\x38\x82\xe3\x07\x93\x18\
\x71\x5d\xe0\x3d\x54\x51\x36\xca\x0b\x08\x94\x17\x1a\xa8\x58\x3e\
\x71\xc6\x8b\x82\x85\xfd\xae\xfb\x80\x51\x98\x10\xbf\x0a\x39\x97\
\x2f\xa3\x6d\xdb\xb6\x38\x77\xee\x1c\x55\x03\x3f\x2a\x85\x00\xa3\
\x3f\xce\x99\x98\xe8\x0c\xa7\xcc\x7e\x70\xdc\xb8\x71\x83\x4f\x9d\
\x3a\x85\x3e\xcf\x8d\xc3\x80\x11\x6f\xca\xb5\x1b\x81\xb4\x30\x0c\
\x9f\x30\xe4\x46\xe0\xc0\x22\xa9\x11\x1b\x4b\x22\x3b\xe0\x21\xbf\
\x3f\x7f\x3d\x17\x36\x2b\xcf\x7b\xa2\x46\x03\x1e\x41\x4a\xda\x0b\
\xdf\xc8\x66\x88\x7c\x6c\xac\x84\xfe\x59\x3a\x93\xff\x26\x15\xfb\
\x92\x10\xa9\x5b\x84\xb2\x50\xc6\x75\x21\x06\x12\x69\x9c\x11\x9e\
\x1c\x52\x46\x8e\x68\xd7\x6d\x00\xfe\xf3\xce\x02\xe4\xe6\xe6\x62\
\xc4\x88\x11\xb0\x58\x2c\x9a\xa0\x11\x67\xfe\x33\xe5\x8c\xe2\xf4\
\x3c\x84\xce\x18\x1f\x1b\x27\x29\x29\x89\x6e\xda\xb4\x09\xad\x3a\
\xf7\xc6\xc0\x17\x27\x83\x70\x1c\xe4\x68\x68\x5e\xcf\xe0\xc9\x19\
\xab\x8b\x10\x2a\xb0\x6c\x22\xea\x42\x84\xef\x39\xc2\x93\x3b\x41\
\xb5\xbc\x71\xf5\x92\x5d\xbf\x01\x00\xce\x03\x88\xec\xaf\x21\x8a\
\x11\x54\x6b\x39\x44\xe4\x45\xd9\x67\x8e\x21\xe7\x42\xa6\xa8\x5b\
\x89\xdf\x26\x52\x99\xec\xcf\x50\xe8\x5b\x52\x2d\x64\xf1\x14\xe5\
\xed\xda\x6f\x04\x5a\xb4\xef\x81\xf4\xf4\x74\x24\x24\x24\x50\x35\
\x67\xa0\x91\x7b\x55\x4c\xc2\xfd\x5e\xbb\x77\xef\xa6\xfd\xfb\xf7\
\x47\x40\x68\x38\xc6\xcf\x58\x89\xe0\xb0\x9a\x62\x1d\x29\x91\xeb\
\x9f\x6c\x18\xd4\xc2\x98\xf8\xb2\x30\x00\x16\x4b\x19\x16\x4d\x1b\
\x2d\x9a\x74\x50\xb3\x0f\x10\xf0\xb0\x26\x18\xc4\x2b\xb4\x3e\xc2\
\xdb\x8d\xb2\xdb\xff\x2c\xe5\xf8\x79\xc5\x1c\x54\x56\x56\x40\xa6\
\xa7\xea\x95\x53\x11\x07\x44\xc6\x3e\x65\x61\xde\x7e\x01\x78\x6f\
\xf1\x06\x34\x68\xd2\x0a\xe3\xc7\x8f\xc7\x9a\x35\x6b\xe8\x83\x30\
\xf9\x70\x46\xa4\x35\xbd\xab\xb2\xb2\x12\x1f\x7e\xf8\x21\xca\xcb\
\x2d\x18\xf9\xe6\x6c\x04\x85\xd6\x80\x20\x0d\x08\x02\x1b\x61\xc1\
\x1a\x22\xb9\xa7\x8c\x80\xa0\x1d\x87\x0d\x3b\x76\x60\x07\x32\xd3\
\xf6\x4b\xbc\x27\xea\x45\xa7\x0a\x55\x44\xe7\xd7\x01\x7e\xa9\x49\
\xea\xae\x0d\x48\xf9\x6d\x9d\x44\xae\xc4\x6f\x4b\xdf\x92\x87\xc9\
\xff\xb3\xec\x8a\x32\x61\xc2\x97\x3d\x3d\xbd\xf1\xca\x7b\x5f\xa0\
\xa0\xb0\x10\x53\xa6\x4c\x41\x59\x59\x99\x4b\x1e\x5c\xa7\x1d\xe4\
\x6a\x8f\x53\x4a\xb1\x6d\xdb\x36\x9a\x9a\x9a\x8a\x87\x5b\x77\x46\
\xbb\x6e\x4f\x8b\xc4\x5d\x26\x42\x0b\x34\x1d\xac\x88\x4b\x64\x16\
\x1d\x30\x80\x0e\x91\xf4\x13\x29\x1d\xb5\x59\xb1\x2d\x61\x89\xf4\
\xf1\xa8\x97\x80\x90\x36\xda\xda\x26\xdf\x90\x3e\x11\x31\xa8\xf1\
\xe8\x08\x51\xa2\xdb\xb4\x66\x21\xec\x2b\xdb\x15\x49\xf9\x6f\x29\
\x2d\x4d\xca\xff\x02\x0f\x23\x0a\x3e\x26\x58\x1f\xa2\x62\x62\xd1\
\xb9\xd7\xb3\xb8\x76\xed\x1a\x96\x2c\x59\x42\xb5\xec\x6e\x46\x3b\
\x8c\x33\xda\xc3\x6a\x61\x37\x6f\xde\xbc\x33\x71\xe2\x44\x84\xd7\
\x6e\x88\xf7\x16\x6d\x80\xc9\xdd\x5d\x66\x4a\x51\x4e\x08\x09\x17\
\x40\x55\xa1\x6e\x4a\x63\x36\x1b\xf3\xd4\xb1\xdf\x71\x32\x75\xb7\
\xfd\xc1\x23\x18\x68\xf0\x12\xaf\x9c\x12\x95\x09\xc4\x18\x27\x39\
\x37\x34\x18\xb2\x10\x9e\x81\x91\x76\xeb\x46\x46\x1a\xd2\xf6\x6f\
\x55\xc5\x90\xa8\xcd\x43\x47\x28\x1e\x71\xa8\x9b\xac\xf1\x39\x0e\
\x23\x26\xc4\xe3\xa1\xe6\xed\x31\x6b\xd6\x2c\xa8\xd9\xec\x5c\xe9\
\x30\x4e\x4d\xd1\x54\x53\xa4\x94\xe2\x21\x00\xcc\x9a\x35\x2b\x28\
\x3b\x3b\x1b\x3d\x06\xfd\x07\x3e\x7e\x41\x3c\xd3\xa4\xbc\x78\x0c\
\x10\xe1\x9e\x52\x89\xdc\xf1\xba\x08\xc4\x30\x86\x66\x88\xe1\xf2\
\x74\x94\x52\xec\xff\xf5\x47\xc9\x6a\x10\xd6\x15\xf0\x0c\x85\x48\
\x47\x89\x16\xfc\xc7\x9e\xa7\x9b\xd9\x1f\xa1\xcd\xfb\x8b\xe1\x7b\
\xb7\x7c\x2f\xd5\x83\x4a\x92\x1f\xd8\x30\x56\x59\x02\x43\x72\x99\
\xb2\x52\x5e\x0d\x00\x43\xca\x09\x28\x42\x6b\xd4\xc2\xc0\xd1\x6f\
\x23\x2f\x2f\x0f\x4b\x97\x2e\x75\x09\x53\xe8\xb0\x04\x52\x4f\xcb\
\x55\x7b\x16\xae\x8b\x17\x2f\xd2\x6f\xbf\xfd\x16\x61\x91\xf5\xd1\
\xeb\x99\x57\x45\xc7\x99\x38\xaa\xa8\x24\xc2\x52\x71\xee\x50\x85\
\xf1\x9a\x8a\x4a\x20\x11\x63\xf0\x0a\x2a\x23\xa4\x9f\x3d\x71\x10\
\xbb\x37\xae\x96\x24\xb7\xe8\x71\x72\x4e\x4d\x35\x87\xa6\xd8\x29\
\x91\xdd\xde\x02\xe7\xe1\x03\x00\x38\xb2\x77\x33\x2e\x9e\x3d\x21\
\xcd\x69\xd6\x1d\x00\x07\xb3\x1d\xa3\x83\xa9\xcc\x52\x2a\x95\x9c\
\x32\xd2\x44\x9b\xc7\xfa\x22\xa6\x65\x27\xcc\x9d\x3b\x17\xa9\xa9\
\xa9\xd4\x48\x9b\xaa\x02\x17\xd5\xb4\x5a\x2d\xd1\x8f\xfd\x7d\xf3\
\xcd\x37\x28\x2a\x2a\x42\x8f\x81\xa3\xe1\xe5\xe5\xcb\x00\x0a\x89\
\x64\x32\x11\xf5\x0b\x29\x5c\x14\x4f\x09\x23\x80\x13\xe9\x99\x10\
\x39\x5f\xb0\x5a\x2b\xf1\xd5\xc7\xaf\xa1\x92\x47\x8c\xa2\xc6\x13\
\x76\xab\x81\xc8\xb5\xd5\xe8\x12\xab\x6c\xd9\xf3\x31\x87\xd4\x45\
\xf5\xd8\xc1\xa2\x44\xb7\x64\xc6\xeb\xb0\x5a\x2b\xe5\x65\x13\xef\
\xa5\xb5\x48\x90\x85\x13\x49\x75\x50\xb3\xb7\x89\xf5\x01\x08\x31\
\xa1\xef\x73\xe3\x00\x00\x0b\x17\x2e\xac\xd2\xda\x2a\x42\x88\x64\
\x8b\x73\xe5\x57\x56\x56\x86\xb5\x6b\xd7\xc2\xcb\xc7\x0f\x5d\x7a\
\x0f\xe5\x21\xb5\x8c\xb6\x4f\x25\xeb\x00\xd5\xb8\x67\xe3\x53\x9d\
\xfb\x33\xc7\x53\x70\x39\xfb\x0c\x2f\xb9\x05\x02\xcd\x3e\x82\x23\
\x87\x97\xf7\x12\x85\x82\x44\xf1\x24\xb7\x46\xbb\x91\x70\xf3\x0a\
\x04\x00\x64\x9d\x3c\x84\xa3\xc9\xdb\xa4\x39\xae\x52\x06\xaa\x28\
\x8f\x20\x79\x8a\x96\x0d\x26\x8e\x78\x0f\x2a\x5a\x40\x9a\xb7\xeb\
\x8e\x90\xb0\x9a\x48\x4a\x4a\xc2\xd5\xab\x57\xa9\xd1\xa5\x39\x4e\
\x97\x9f\x38\xbb\x92\x92\x92\xe8\xc5\x8b\x17\xf1\xf2\xd4\x45\xa8\
\x1e\x51\x57\x26\xb1\x29\xef\xd5\x9e\xf5\xc2\xc0\xdc\x53\x6a\xc3\
\xba\x15\x73\x60\xb3\xf2\xe8\x9a\xa8\x17\x01\x9f\xba\x72\x0e\xad\
\xee\x18\x15\xf3\x62\x7f\x01\x0d\x3a\xa3\x4e\xef\x0f\xc4\x28\x89\
\xcb\xe3\x51\x59\x51\x29\xfb\x2e\x55\x29\x97\x20\x4d\x52\x22\x59\
\x12\xf4\xea\x2c\x50\x5e\x5f\xff\x40\x3c\xfb\xda\x07\xb8\x7b\xf7\
\x2e\x12\x12\x12\xaa\x04\xf2\xe4\x5c\x9d\x72\x56\xab\x15\x5b\xb6\
\x6c\x81\x97\x8f\x1f\x5a\x76\xe8\xc9\xaf\xb8\x96\x7b\x26\xd9\xff\
\x5a\xf7\x4a\x37\x83\xf0\x4c\x98\xe7\xbf\xae\x5c\xc4\x89\x83\x3b\
\x79\xde\xe3\x09\xd4\x1d\x2a\x58\x37\x21\x57\xb4\x8c\xf5\x10\x21\
\x1c\x6a\xb4\x1b\x05\xce\xdd\xcb\x2e\xd1\x9d\x4a\xc7\xf9\x53\x69\
\x9a\x65\xa1\x32\x23\xaa\xbc\x6c\x6a\xf1\xa1\xe2\x99\xed\x31\xf0\
\x3f\x08\xae\x5e\xd3\x01\x80\x69\xd4\x85\xc3\x19\x5d\x95\x2c\x5c\
\x47\x8e\x1c\xa1\x09\x09\x09\x88\x89\xed\x88\xc0\xd0\x30\xd9\x88\
\x97\x46\x22\x15\xd5\x1a\xc9\x9c\xc5\xba\x0b\xd8\x78\xd4\x2e\x2c\
\xc8\xee\xed\x3a\xcb\x86\x55\x9f\x4a\xdf\x8e\xe8\x05\xf8\xd4\x73\
\x64\x38\x54\x03\x2c\x47\xa9\xa3\xc2\x4b\x00\x37\xaf\x40\x84\xb7\
\x7f\x91\xd7\xad\x6c\xd8\xbc\x66\x21\x2c\x96\x32\xd1\xe5\x41\x40\
\x15\xb3\x9b\x2a\x5c\x1d\xd2\x2c\xa3\x4c\x79\xa5\x77\x54\x74\x61\
\x50\x42\xc1\x71\x1c\xda\x3f\x11\x87\x94\x94\x14\x64\x65\x65\x51\
\x2d\x12\xa7\x29\x66\x6b\x39\x8a\xd4\xa6\x1e\xa5\x14\xeb\xd6\xad\
\x43\x41\x41\x01\xba\xf4\x1e\xa6\xb2\xfa\x40\xa1\xc5\xb0\x23\x9b\
\x10\xb0\x0e\x64\x56\xeb\x90\x44\x07\x22\xe6\xf1\xfb\x6f\x89\x48\
\x5a\xff\x8d\xe4\x8c\x6b\x3c\x51\x52\xeb\x1d\x9d\x9e\x8e\x12\x96\
\x6c\xd0\x88\xfe\x6b\x10\x02\x44\x76\x7b\x13\x26\x4f\x5f\xd1\xba\
\xb0\xed\xa7\xaf\x14\x95\xa0\x0a\x39\x8e\xfd\x51\x99\x26\x44\x14\
\x75\x27\x62\xfd\x24\x60\x4a\x97\xde\x43\x51\x5e\x5e\x8e\x29\x53\
\xa6\x68\xba\x6c\xb4\x3a\x8b\x53\x43\x9d\x68\x2d\x0f\xa1\x94\xe2\
\xe8\xd1\xa3\xe0\x4c\x26\x44\x3f\xd2\x56\x43\x1b\x25\x8e\x46\x34\
\x71\x34\x13\x47\xc3\x17\x25\x72\x8f\x04\x08\xac\x56\x1b\x92\x7f\
\x5d\x0b\xab\xc0\x7b\x6a\x0d\x04\xfc\x63\xf4\xb0\x49\x2a\x2a\x10\
\x61\xbd\x08\x32\xb0\x89\x39\xa4\x1e\x02\x1b\xd9\xc1\xf5\xd6\xca\
\x0a\xec\xdb\xfa\x03\xac\x95\x95\x2a\xa4\x4a\x4d\xd3\x56\x01\x98\
\x50\xaa\x6b\x50\x8c\xac\xd7\x18\x7e\x81\xa1\x48\x4f\x4f\x47\x65\
\x65\xa5\x21\xcf\xaa\xd8\x41\xae\x2c\x3e\xca\xcf\xcf\xef\x7e\xe2\
\xc4\x09\x54\x8f\xa8\x83\xf0\x5a\x51\x8c\x92\xc8\x90\x29\xc1\x73\
\x29\x69\x6f\x7c\x3f\x51\xd1\x73\x49\x21\x91\x34\x41\xb7\x25\x4c\
\xfa\xb3\x27\x53\x25\x20\x88\x47\x10\xd0\xf4\x43\x55\xcc\x9c\x13\
\x40\x99\xe3\x8f\x57\xb8\x08\xc7\x21\x7a\xf8\x4a\xd1\xba\x70\xf1\
\xcc\x71\x1c\xd9\xb7\x45\x2c\x9f\x40\xaa\x64\xf5\x21\x6c\x7d\x28\
\x53\x07\x61\x5c\x31\x64\x9a\xca\xeb\xe7\xe3\x17\x80\xa8\x98\x58\
\xdc\xb8\x71\x03\x67\xce\x9c\xa1\x46\x36\xb4\x10\xa5\x38\x67\xbe\
\x72\xf6\x39\x2b\x2b\x2b\xa9\xb0\xb0\x10\x0d\x1f\x6e\x2d\x99\xda\
\x19\x97\x01\x3b\x6a\x08\xe3\x31\x15\x31\x00\x82\xb7\x94\xc8\xb1\
\x00\x84\xc5\x26\x00\xd8\xf9\xf3\x0a\xc9\x6a\x10\xd1\x0b\x30\x87\
\x49\xc4\x44\xb3\xa3\x88\x73\x31\x8e\x89\xe3\xe1\x1f\x86\xb0\x47\
\x9f\x17\x1b\xe2\xb7\x75\xcb\x41\x6d\x54\x3e\xe3\xa8\x04\xfb\x82\
\x5a\xfd\x04\xd7\x88\xc2\x24\xcf\x0a\x4e\x02\x55\x68\xf4\x70\x6b\
\x54\x56\x56\xe2\xc4\x89\x13\x86\xb6\x9f\x11\x5d\xde\xae\xe8\x3f\
\xa9\xa9\xa9\xe0\x38\x0e\x31\xb1\x1d\x15\xa3\x92\x91\xa8\xa0\xf4\
\x50\x0a\x8c\x57\xc2\x1c\x08\xfc\x49\xed\xdd\x5f\xb9\x97\x90\xb2\
\xf3\x67\x01\xfd\x61\x37\x8a\xca\x34\x77\x01\x13\x05\xb9\xd7\x4c\
\x4d\xcb\x07\xd5\xf8\xd9\xdf\x85\x77\x7c\x09\x26\xb3\x1d\xef\x7d\
\xf2\xf0\x1e\x64\x9f\x39\x2e\xd6\x83\x30\x75\x12\x85\x04\x28\xea\
\xa9\xbc\x67\xe2\x10\xc5\x7d\xe3\x16\x76\x64\x51\x6a\x6a\xaa\x6b\
\x1e\x55\x57\x76\xca\xc8\xc8\xc8\x40\x60\x68\x0d\x34\x89\xed\xe4\
\xa8\xb4\x38\x53\x76\xf4\xe2\xf3\xcf\x96\xf2\x32\x7c\xf6\xce\x70\
\x94\x97\xf2\x70\xdd\x88\x9e\x40\x60\x53\x15\x1b\xa8\xd2\x35\x41\
\x35\x4c\x71\xfa\xce\x26\x73\x48\x5d\xd1\xd2\x5d\x59\x61\xc1\xfc\
\x77\x47\xa0\xb4\xb8\x48\xbf\xbc\x30\x52\x3f\x38\xa4\xad\xdd\xa0\
\x09\xdc\xdc\x3d\x90\x91\x91\xe1\xba\x25\x41\x49\x03\xb5\xfe\xe7\
\xe6\xe6\x22\x20\xa8\x1a\x6a\xd4\xaa\x2f\xf1\x2c\xd6\xa9\x23\xf3\
\xe1\x48\xfe\x7e\x56\x13\x67\x9f\xa9\xcc\x20\x49\x71\xfe\x54\x3a\
\x83\x35\x08\x04\xea\x3e\x27\xa7\x4c\x5a\x54\x4b\x55\xd1\x56\x9b\
\x45\x4c\x38\xb1\x4b\x5c\xd5\x5b\x0f\x85\xbb\x5f\x75\x00\xc0\x95\
\xec\xd3\x38\x76\x70\xa7\xc2\x28\x4a\xe5\xcf\xb2\x01\x22\x0d\x14\
\xaa\xf1\x2c\x24\x09\x08\xae\x0e\x4f\xb3\x37\x6e\xde\xbc\x09\x8b\
\xc5\xa2\x89\xea\x51\x9d\x41\xce\xd6\xad\x08\x57\x56\x56\x16\x6a\
\xd4\x8e\x82\xd9\xc7\x4f\x66\x2f\x53\x2c\xd4\x61\x3c\x96\x92\x0d\
\x8b\xf2\xcf\x14\x4a\x9b\x9d\x84\x39\x5b\xb7\x62\xb6\x84\x35\xa8\
\x3f\xd2\x6e\x77\xd3\xed\x1d\xe8\x20\x1f\x05\xd1\x9a\xa8\x3c\x4b\
\xe1\xfe\xf5\xdb\xa1\x4e\xaf\xf7\xc4\x54\xeb\x57\xce\x41\x45\x65\
\x05\xe4\x8a\x9c\xdc\x5f\xe5\x28\x5f\x53\xd9\xc4\x61\x50\xcb\xa2\
\x50\xe4\xe1\x69\x46\x4c\xcb\x8e\xb8\x76\xed\x1a\x8a\x8a\x8a\x5e\
\xd6\x82\x14\x28\xf9\x3f\x67\xa4\x63\x00\xe0\xd6\xad\x5b\xe9\xb7\
\x6f\xdf\x46\x78\xad\x28\x9e\xd4\x12\x99\x77\x91\xf5\xe1\x8b\x8c\
\x94\x3a\x3e\x13\x07\xf1\xd7\x9e\xfe\x4a\xf6\x69\x1c\xfd\x7d\xbb\
\x3d\x0f\x93\x17\x50\x7f\x94\xe3\xcc\x74\xb0\xb1\xb1\x33\x95\x28\
\x8c\xa5\x6c\xa3\x2a\x5a\x8f\x69\x4d\x02\x0e\x35\xda\x8e\x82\x9b\
\x4f\x88\xdd\xba\x90\x99\x6e\xf7\xda\x2a\xfc\xdd\x54\xf1\x5f\xf6\
\x1e\x8e\xfe\x71\xb6\xae\xc2\xff\x16\xed\x7b\xa0\xb8\xb8\x18\x57\
\xae\x5c\x59\x66\x74\x69\x0f\x67\xd4\x39\x77\xeb\xd6\xad\x96\x56\
\xab\x15\xfe\x41\xa1\x72\x85\x4e\xd9\x06\x50\x1b\xe4\xea\x23\x0c\
\x4c\x1b\x6e\x4f\x5c\x26\xa5\xaf\xd1\x1d\xf0\xae\xc5\x98\xf3\x21\
\xb7\x5e\xeb\x4a\x73\x0a\x3e\x45\x15\xd6\x05\xa5\x2f\x81\x50\x98\
\xcc\x7e\x08\x6b\xf3\x9c\x18\x6d\xc7\xba\x65\xa0\xb0\x39\x96\x57\
\xc5\x6a\xe2\x30\xc1\xa1\xfd\x3e\x34\x2c\x52\x70\x74\x1a\x77\x79\
\x1b\x5d\xbe\x78\xf7\xee\x5d\xd8\x6c\x36\x78\xf9\xf8\x49\x75\x15\
\x49\x97\x9c\x2f\xcb\x58\x13\x91\x80\x7f\x20\x0a\xbe\xce\xeb\x40\
\x47\x92\xb7\x4a\xfe\x1e\x62\x02\x1a\xbf\xa5\xde\x11\x1a\xd6\x6b\
\x85\x04\x2d\x75\xac\x43\xa3\x29\xc8\x14\x95\x90\x3d\xb5\xba\xbd\
\x09\x93\xd9\x1f\x00\x70\x68\xd7\x46\x1c\xd8\xb1\x4e\x06\x00\x22\
\x6a\xb2\x89\x92\xb3\x31\x14\x54\xe6\x07\xe4\xbf\x29\xb4\xdd\x9d\
\x3b\x77\x5c\xc3\x24\x18\xd9\x2f\xbb\xa0\xa0\x00\x94\x52\x98\xcd\
\x3e\x12\xbe\x4c\x1c\x84\x54\x74\x06\x2b\x59\x13\x15\xbc\xa4\x44\
\xee\xaa\x11\xd2\x53\x6a\xc5\xa6\xd5\x0b\x50\x5a\x5c\x60\x8f\x10\
\xda\x0e\x08\x88\x61\x1a\x97\xca\x05\x01\x55\xf6\x43\xf4\xad\x0b\
\x44\x21\x38\xa8\xb0\x2f\x73\x48\x5d\x84\x34\xed\x0d\x00\xb0\xd9\
\xac\x58\xfb\xd5\x47\xa8\xa8\xb0\xc8\xa8\x03\x25\x94\x31\xe9\x30\
\x20\x13\x38\x4a\xfd\x84\x01\xfd\x8b\xa0\x12\x2f\x6f\x00\x10\xdb\
\xd2\x08\xe5\xe2\xf4\xe0\xbe\x6c\x58\x7e\x7e\x3e\x6c\x36\x1b\xcc\
\xde\x3e\xfc\xc8\x22\x8c\x05\x47\xb2\x3e\x39\x68\x1c\x44\x7a\x2f\
\x23\xd7\x7c\xdc\x73\x7f\x1c\x41\x46\xda\x3e\x49\x72\x6b\xb5\xd8\
\x3e\x8b\x1c\x86\x28\xd5\x46\xfc\xa8\x7a\x3b\x89\x86\x85\x5b\x3b\
\xa8\xd1\xb3\x5f\xc2\x33\xa8\x36\x00\x20\xf7\xd2\x59\x1c\xde\xb3\
\x49\x51\x0c\xc2\xe0\x4f\x89\x28\x00\x50\x85\xcd\x56\x8c\xc3\xbc\
\x07\x00\x2f\x6f\x5f\x91\x1a\x19\xa5\x5c\x9c\xde\xac\x51\x35\x41\
\x48\x70\x4c\x69\xc6\x50\x01\x7f\x00\x05\xfe\x80\x4a\xf1\xa8\x04\
\xe5\x25\x42\x3c\xd8\x25\x37\x2a\x2c\x81\xa9\x3b\x4c\xe2\x3d\x44\
\x21\x0e\x81\x38\x2a\xa6\x84\x81\xd5\xa8\x5a\xb9\x59\xda\xa3\x30\
\xaa\x51\x85\x5a\x40\xed\x96\xee\x5a\xdd\xdf\x12\xeb\xbb\xfe\x9b\
\x4f\x60\xad\xac\xe0\x27\x24\x5b\x57\x86\x32\xf0\xb6\x38\xc2\x08\
\x2d\x6c\xfd\xec\x02\x03\x65\x56\x57\x40\x77\x7f\x1f\xe5\x8c\xe2\
\xf4\x66\x0d\xfb\xdf\xcf\xcf\x0f\x1c\xc7\xc1\x52\x56\xca\x80\xf7\
\x58\x22\x4d\x24\xd1\x5a\x34\xc7\x0b\xbb\x7f\x10\xde\x44\x2f\x2c\
\x1f\xb1\xc7\xbf\x71\xf5\x92\x34\x7b\x40\x80\xda\x83\xe5\x8d\xa7\
\x89\xf1\xa1\xba\x4a\xaa\x43\x90\x03\x42\x51\x83\xce\x81\x20\xf4\
\x91\xfe\x30\x99\xed\xab\xc2\x2f\x9d\x39\x81\x3f\xb3\xfe\x10\x21\
\xc8\xac\x70\x28\x50\x06\xc8\x56\x60\x40\x34\x57\x51\x66\xb9\x8a\
\x40\xe7\x84\xf5\xb2\xfe\xfe\xfe\x86\xb6\x9b\xd1\xf4\x07\xa9\xcd\
\x9e\xa0\xa0\x20\x70\x1c\x87\x92\xe2\x02\x66\x96\xf0\x30\x0f\x7e\
\x43\x0c\xbb\xaa\x21\xc9\xce\xc4\x01\xe1\x23\xd1\xe7\xf2\xb2\x52\
\x7c\xf2\xd6\xb3\x28\x2d\x2e\xe4\x51\xa2\xbd\xed\x56\x03\x96\xd7\
\xa8\x69\xed\x72\x70\x9d\x36\x2e\x8e\x35\x43\xc9\x10\x88\x4a\x67\
\x1f\x64\x46\x50\xcf\xe0\xda\x08\xef\x30\xda\x6e\xe9\xb6\x56\xe2\
\xc7\x2f\xa7\xa3\xf0\xde\x1d\x86\x8f\xb2\x94\x82\xca\x28\x85\x40\
\x21\xc4\x59\x24\xe8\x47\x7c\x1b\x08\x75\x0d\x0e\x0e\x76\xba\x3b\
\xb0\xaa\xa9\x47\xcf\x80\x17\x10\x10\x00\x8e\xe3\x50\x5e\x52\x22\
\x71\x3e\x95\xb8\x54\xd5\x9f\xad\x90\xa0\x08\x41\x66\xfa\x7e\x9c\
\xcb\x38\x22\x8d\xe2\xa8\xd1\x8e\x0d\x4e\xb4\xd8\x87\xdc\x3a\xad\
\x6e\x45\x70\xd6\xb1\x6a\x1d\x6c\xaf\x4f\x44\xa7\x57\x40\x38\xfb\
\x4a\xee\xb4\xfd\x5b\x71\xe0\xb7\x75\x72\x1d\x4a\x09\xac\x77\x08\
\x23\x0a\xc1\xc6\xfe\x5f\x80\x2c\x0b\x0b\x90\x8d\x6c\x74\xc8\x19\
\xdd\x2f\x2d\x34\x34\x14\x26\x93\x09\x85\x05\x79\xe2\xca\x37\x01\
\x1b\x06\x76\x8f\x69\x51\x8f\x64\x71\x66\x8e\xf9\x6f\xfd\x61\x31\
\x83\x12\x7d\x11\x08\x79\x54\x85\x92\x29\x78\x86\xaa\x17\x55\x0b\
\x76\x45\x1d\x95\x5b\xc0\xd1\x8c\xa3\x02\x30\xf1\xaa\xde\x10\x75\
\xfb\x4c\x97\xf4\xa2\xc4\x65\xa8\xb0\x94\x31\x58\x3a\xca\xc0\x97\
\xa9\x43\x5d\x55\xeb\x4d\x81\xbb\xb7\xff\x02\x60\xdf\xca\xd3\xe8\
\x7e\x72\x9c\x11\x93\x37\x21\x04\xe1\xe1\xe1\x24\x24\x24\x04\x57\
\xff\x3c\x2f\x5b\xe0\x4b\x20\x87\x2a\x49\x03\x46\x6e\xce\x11\xfd\
\xa5\x14\xc8\xfa\xe3\x30\x8e\x1e\xd8\x21\x61\xac\x1f\x9a\x68\xc7\
\x1c\xb0\x30\x2a\xd6\x41\x06\x69\x79\x8a\xc3\x6c\xa2\x5a\x52\x9b\
\x7c\xc6\xaa\xce\x22\xe2\x80\x35\x16\xa9\x42\x64\xd7\x37\xe0\x55\
\xad\x81\xe8\x2f\x3a\xbc\x67\x13\x03\x45\x66\x2d\x11\xd2\xea\x0d\
\xc2\x68\xb1\x72\x2f\xb1\xbd\x2c\xe9\xbf\x6f\x87\x8f\x8f\x0f\xea\
\xd6\xad\x3b\xd7\xe8\x7e\x72\x9c\xd1\x1d\xd5\x01\x20\x32\x32\x12\
\x79\x37\x72\x61\xb5\x55\x3a\x0a\xd4\x0a\xe4\x25\x81\x72\xa4\x52\
\x11\xe0\xb7\x7f\xeb\x0f\x92\xe4\x56\xbd\x0b\x60\xae\x21\x5f\x38\
\x44\x95\xca\x14\xdb\x09\xce\x18\xbd\x51\x97\x83\xfe\xcf\xe4\xe9\
\x83\xd0\xe6\x4f\x8b\xb9\xed\xdd\xb2\x86\x41\xa2\xb2\xc2\xb5\x04\
\xcb\x54\x2e\x06\x63\x7f\x36\x9b\x15\x17\x32\xd3\x11\x1c\x1c\x0c\
\x6f\x6f\xef\x29\xce\xa8\x96\x83\xc3\xce\x19\xe2\x84\x10\x82\xe8\
\xe8\x68\xdc\xfe\xeb\x0a\xae\x64\x9f\xe1\xad\x08\x44\xd2\x89\x58\
\x6f\xbc\x8c\xb1\x83\x89\x4b\x70\x64\xef\x16\xec\xd9\xfc\x9d\xe4\
\xef\x79\x68\x02\x83\x42\xa7\x72\x05\x95\xb2\x18\x01\xa2\x62\x56\
\x61\xe3\x4b\xab\xd5\xa9\xad\xd2\xa0\x91\x95\x68\xd9\xa6\x00\x10\
\x44\x3e\xfe\x06\xdc\xbc\xec\x12\x5d\x7a\xf2\x36\x9c\x39\x9e\x22\
\xce\x3e\xa2\x10\x62\x88\xda\x4c\x25\x52\xbb\xdc\xb9\x79\x1d\x05\
\xf9\xb7\x51\xab\x56\x2d\x78\x79\x79\xc1\xe8\x66\xbe\x1c\x8b\xc7\
\x66\xd7\x50\xaa\xc9\xe7\xd1\xd1\xd1\xb8\x7b\xeb\x2f\x7e\x51\x2e\
\x15\x77\x15\x90\x3b\xb4\xd8\x31\x2c\x2c\x16\x14\x46\x91\x0d\x6b\
\x97\x7c\x84\x92\x22\xde\x6a\x10\x39\x00\x08\x6c\x06\xa8\x5a\xc6\
\x09\xe3\x72\x26\x2a\xa0\x0e\x3e\xdc\x66\x01\x32\x3e\x06\x2e\xac\
\x14\xa3\x5c\xff\x7d\x39\x2e\x6d\xfd\x10\x95\x25\xf9\x8e\xfc\x46\
\x6b\xa2\x39\x2a\x4f\xf0\x0c\xaa\x89\xea\xad\x87\x8a\x6d\x30\xff\
\xdd\x11\x28\x29\x2e\x10\x17\x52\x52\xc2\xa8\xa1\x02\x76\x5d\x14\
\x94\xa8\xcc\xf5\x7e\x35\xe7\x1c\x2a\x2c\xe5\x88\x8e\x8e\xd6\xdd\
\x80\x49\x39\xa3\x38\x67\x1b\xf8\xb1\xf7\xb1\xb1\xb1\xb0\xd9\xac\
\x38\x97\x91\xc6\xec\xc6\x41\x65\xee\x6a\x02\x22\xe3\xed\xe2\xaa\
\x34\x10\x9c\xcf\x4c\xb3\x7b\x2d\x01\xc0\x3d\x00\x68\x3a\x4d\x5c\
\xbb\xe3\x60\xc8\x54\xb3\xb7\x81\x31\xe2\x59\xf2\x81\xdc\x4d\xc0\
\xee\x27\x80\xac\x85\x40\xf9\x2d\x69\xcd\x52\x69\x3e\x72\x7e\x9d\
\x81\xf4\xd9\xad\x70\x3d\xe5\x6b\x54\x96\xde\x53\xe8\xab\xda\xcb\
\x55\xe4\x33\x89\x22\xa2\xf3\x6b\xf0\xaa\x16\x05\x00\xb8\x91\x7b\
\x09\x69\xc9\xbf\x32\x40\x11\x88\x7c\x55\xdc\x7c\x83\x51\xd4\x29\
\x95\xda\xe3\xc2\xa9\x74\xb1\x0d\x9d\xed\x03\x2b\xdb\x96\xd9\x95\
\xdd\xe6\x5b\xb5\x6a\xf5\x8a\xaf\xaf\x2f\x32\x8e\xec\x15\x69\x30\
\x81\x1c\x4f\x46\x19\x37\xb6\x48\xa9\x08\x05\x60\x43\xe2\xb2\x59\
\x52\x47\xd4\x1b\x0e\x78\xd5\x74\x5c\x41\xa0\xe4\x5d\x0a\x6d\x1f\
\x96\xbb\xc0\xd9\xcf\x81\x9d\x1d\x80\x43\x2f\x02\xf7\x32\xc5\xca\
\x36\x6e\xd1\x01\x8f\xb4\xed\x66\xdf\x98\x09\x14\x65\xb7\x2f\x22\
\xeb\xfb\x97\x70\x78\x7a\x34\x2e\x6e\x78\x07\xe5\xf7\xae\xca\x75\
\x1f\x19\x44\x0c\x8e\xab\xb4\x00\xf8\xd6\x6c\x8a\x5a\x4f\x4c\x16\
\xbf\xb1\x6e\xc5\x6c\x58\x2b\x2d\x00\x03\x11\x93\xb7\x83\x84\x91\
\x23\x8c\x24\x99\x71\x64\x1f\xdc\xdc\xdc\xd0\xa9\x53\x27\x55\x00\
\xbd\x56\xfb\xbb\xe4\xf2\x0e\x0c\x0c\x5c\xde\xa8\x51\x23\xdc\xbc\
\x96\x83\xfc\xbc\x9b\x92\x79\x94\x4a\xb4\x96\x30\x1b\x55\x88\x3c\
\x89\x12\x5c\xbf\x9c\x8d\x13\xa9\x49\x92\x85\xa9\xde\x08\xb9\x54\
\x25\x73\xa4\x29\xf5\x21\x02\x50\x0b\x90\xb3\x16\xd8\xd1\x0a\xc8\
\x9c\x01\x94\xfd\x25\x36\x9a\x6f\x40\x30\x5e\x98\x34\x0f\xb3\x57\
\xed\xc5\xc7\x2b\x7e\xc3\x84\xf8\x55\xbc\x5b\xc4\x9e\xbe\xa2\xf0\
\x26\xae\x24\xcd\x43\xfa\xac\x16\xc8\xd9\x31\x17\x56\x4b\x89\x8a\
\xff\x00\x9a\xfe\x84\x6a\xb1\x03\xe1\xee\x6b\x77\xb3\xe4\x9c\xcb\
\xc0\xe9\xe3\x29\x92\x6d\x4e\xac\x27\xd3\x0e\x54\x1e\x5e\x5e\x56\
\x82\x9c\xf3\x99\xf0\xf7\xf7\x47\xa3\x46\x8d\x88\x51\x9e\xaf\x09\
\x1a\xd1\xd2\x85\x38\x8e\x43\xc7\x8e\x1d\x61\xad\xac\xc0\x1f\x87\
\xf7\x48\xe0\x08\x96\x07\x89\xc8\x4c\x29\xbc\xb2\xa2\x1c\x6b\x97\
\x7c\x0c\x4b\x79\x99\x84\x35\xf0\x8d\x52\xe1\x2d\x2a\x9a\xa9\xe5\
\x2e\x70\xe1\x6b\x60\xcf\x93\x40\xfa\x58\xa0\xe2\x9e\xe4\x36\x8a\
\xac\x8f\x57\xa6\x2e\xc6\x37\xbb\x72\x10\xf7\xc2\x5b\x30\xb9\xb9\
\x81\x10\x0e\x8f\xf7\x1d\x8e\xe5\xdb\xcf\x63\xd2\x27\xdf\xa3\x6e\
\xa3\x66\x62\xfc\x8a\xa2\x5b\xb8\xb4\xe9\x5d\xa4\xcd\x68\x86\x2b\
\xbb\xe6\xa3\xec\xee\x15\xa8\x7a\x0f\x15\xd2\x98\xbb\x4f\x30\x6a\
\xb4\x7b\x41\xcc\x67\xe3\xea\xf9\xa0\xd4\xea\x58\x7f\xfe\x3f\x85\
\xfc\x39\xe7\xfc\x29\xe4\xdd\xb8\x8a\x0e\x1d\x3a\xc0\x6c\x36\xbb\
\x04\x1a\x91\x1d\x74\xab\x75\x6a\x21\x1b\x76\xe0\xc0\x01\xda\xab\
\x57\x2f\x34\x6e\xd9\x05\xd3\xbe\xdc\x22\x4a\x5f\x44\xdc\xe3\x40\
\xf2\x2b\x08\x61\xbf\x6f\x4f\xc4\xbc\x49\xcf\x4a\x7a\x4f\xc7\x75\
\x40\x48\x2b\x4d\x03\x00\x00\xa0\x38\x07\xb8\xf2\x8b\x9d\xf9\x33\
\xb3\x05\xb0\x6f\x92\xf4\xcc\xab\xd3\x10\x13\xdb\x91\xf7\xb1\x50\
\xc9\xff\xa3\x70\xca\x54\x58\xca\x70\xea\xe8\xef\xd8\xf2\xfd\x62\
\xa4\xed\xff\x55\xc6\xe4\xdc\xbc\x02\x51\xa3\xfd\x0b\x08\x6b\x33\
\x1c\x7e\xb5\x63\xe5\xcb\x56\xc4\x7b\x7b\x7e\x96\x82\xbf\x70\x68\
\x5a\x03\xd8\x2c\xc5\x30\xb9\xb9\x63\xd4\xc4\xb9\xe8\x3f\x72\x82\
\xc4\x77\x1d\x90\xfc\xd2\xca\xbf\x95\x73\xde\xc4\x6f\x89\x4b\x70\
\xec\xd8\x31\x34\x6e\xdc\x98\x18\x39\x1d\x52\xf8\xcf\x19\xd9\x6c\
\x9b\x0d\x6b\xd6\xac\x19\xe9\xda\xb5\x2b\xce\x67\xa6\xa3\xb8\xf0\
\x9e\xc8\xb4\x1d\xdc\xde\x8c\xb0\xb0\x6f\xcb\xf7\x52\xeb\xd6\x79\
\x56\x42\xea\xc8\xf8\x0c\x5f\x3f\x6b\x39\x90\xbb\x05\x48\x1d\x05\
\x64\xce\x94\x75\x4e\x58\xcd\x7a\x18\xf2\xf2\x7b\x78\x67\x7e\x22\
\x5a\x75\xea\x05\x2f\x6f\x3f\x99\x47\x8c\xa8\x20\x49\x3d\x3c\xbd\
\xd0\xbc\x5d\x0f\x4c\x9c\xf3\x1d\x9e\x1b\x3b\x1d\x75\x1a\x3e\x2c\
\x13\x26\x72\x77\x2f\x40\xe6\xb2\x38\x5c\x4d\x5e\x82\xca\xb2\x02\
\xc6\x50\x2b\x5f\x0a\xee\xee\x17\x26\x7a\x5d\xad\x95\x15\xd8\xb5\
\xe1\x5b\x54\x94\x97\x29\x70\x74\x8c\x13\x50\x14\xf9\x6d\x38\x79\
\x78\x37\x1e\x7e\xf8\x61\x19\x79\x33\xb2\xa1\xba\x0c\x59\xea\xcc\
\xf4\x2d\x84\xf9\xfb\xfb\xe3\x85\x17\x5e\x40\x7e\xde\x0d\x69\xad\
\x27\xb3\x24\x83\x5d\x1f\x47\x88\x7d\x97\x8f\x63\x29\xbc\xd5\xc0\
\xe4\x03\x44\xbf\x01\x98\x3c\x14\xfc\x07\x40\x65\x21\x70\x76\x21\
\x90\xd4\x09\x38\x34\x0a\xc8\xff\x43\xfc\x6e\xbd\xe8\x47\xf0\xca\
\x7b\x5f\x60\xd1\x2f\xc7\xf1\xfc\xf8\x99\x08\xad\x5e\x53\x6e\x16\
\x63\x8d\x07\x84\x88\xd8\x68\x76\x73\x0c\x5f\xff\x20\x3c\xf3\xea\
\x34\xcc\x4f\x48\xc3\xa4\x4f\x7e\x44\xc3\xa6\x6d\x40\x78\x09\xb2\
\xfc\x4e\x0e\xce\xaf\x7d\x1d\x47\xa6\x37\xc6\x85\xf5\x6f\xa1\x2c\
\xff\x8a\x83\x1e\x46\x40\x10\x35\xf0\x53\x78\x55\x6f\x64\xe7\x45\
\xe7\x33\x90\xba\x6b\x23\x83\xd7\x96\x9b\xea\x84\x76\xd9\xbd\x71\
\x15\x72\xce\x65\xe2\x99\x67\x9e\x81\x72\xa7\x46\x23\x6d\x5f\xa5\
\x2d\x31\x4b\x4a\x4a\x50\xb7\x6e\x5d\x5a\x5c\x52\x8e\x95\x49\x97\
\xe0\xe7\x1f\xac\xea\xa2\xa6\xa0\xf8\xec\x9d\xe1\xd8\xff\xeb\x8f\
\x7c\x4b\x3f\x0f\xc4\x7e\x2e\x77\x63\xdb\x2c\xc0\xf9\x2f\x81\x0b\
\x2b\x80\xb2\x1b\xb2\xef\xf8\xf8\x05\x62\xfc\x8c\x95\x78\xb4\x6b\
\x7f\x98\x4c\x6e\xea\xbe\x39\x25\x78\x9e\x18\x8b\x63\xb3\x5a\x91\
\x95\x71\x04\x9f\x4d\x7e\x0e\x37\xae\x5e\x92\x3b\xc9\x3c\x7c\x10\
\xd6\xfa\x3c\x22\x3b\xa4\x00\x00\x0b\xf0\x49\x44\x41\x54\x59\x44\
\xc5\x7d\x0a\x37\xef\x40\xd9\xbb\x2b\xbb\x17\x20\xfb\xe7\x89\x00\
\x80\x06\x4d\x5a\x62\x7e\x42\x9a\xfc\xe0\x28\xc6\xe5\x5d\x61\x29\
\xc3\x98\x7e\x4d\x70\x2f\xef\x3a\x32\x32\x32\x10\x15\x15\xe5\xf2\
\xc6\x09\x9a\x1b\x59\xe8\x1d\xba\xe4\xe5\xe5\x85\x61\xc3\x86\xa1\
\xa4\xb8\x00\xfb\xb6\xfe\x20\x07\xb8\x30\x05\xbd\xfa\x67\x16\xd2\
\x93\xb7\x49\x56\x83\xba\xc3\xa5\xf7\x96\x7b\x40\xce\x0f\xc0\xbe\
\xde\x3c\x29\x93\x3a\xa7\x7a\x44\x1d\xbc\x3c\x75\x21\x16\x6f\x38\
\x89\x76\x4f\xc4\x81\x33\xb9\x31\xae\x1d\x06\x1f\xad\xb0\x97\x52\
\x15\xc3\x00\x85\xe4\x0a\x91\xad\x59\xe0\x4c\x78\xe8\x91\xb6\x98\
\x9f\x78\x04\x93\xe6\xfd\x88\xfa\x0f\x35\x17\xbf\x61\xb3\x14\xe3\
\x7a\xca\xd7\x48\x8f\x8f\x45\xee\xde\x45\x28\xcb\xcb\x91\xc8\x6c\
\xab\xa1\x30\xf1\xd6\x85\x8b\x67\x4f\x20\xeb\xe4\x21\x07\xe7\xaf\
\xd0\x5f\x27\x0f\xef\xc6\x8d\xab\x7f\xa2\x6b\xd7\xae\xa8\x57\xaf\
\x1e\x31\x7c\x90\x95\xcc\x6b\x52\xc5\x0d\xe7\x2e\x5c\xb8\x40\x9b\
\x37\x6f\x0e\xff\x90\x70\x2c\xfa\xe5\x04\xcc\x66\x1f\x09\x07\x46\
\xed\x58\x83\x09\x83\x5b\xe1\x92\xb0\x58\x37\xbc\x27\xd0\x7e\x0d\
\x50\x9e\x07\x5c\x5e\x07\x9c\xfb\xd2\x81\xf9\x37\x7c\xb8\x35\xfa\
\x3c\x37\x0e\x6d\xbb\x0d\x80\xb7\x8f\x9f\x7c\x23\x3f\xaa\xc0\x8e\
\x50\xc7\x45\x76\xac\xb5\x48\xeb\x59\xc9\xcb\x85\xf0\x0a\x4b\x39\
\x4e\x1e\xde\x83\x6d\x6b\xbf\xe2\x95\x51\xa9\x5d\x4c\x66\x3f\xd4\
\x68\x3b\x12\xb5\x7b\xbc\x03\xcf\xa0\x48\x64\xff\x32\x19\x57\x92\
\xe6\xd9\xad\x2b\xcd\xda\x62\xda\x97\x9b\x11\x10\x5c\x4d\x26\x57\
\xd8\xa8\x0d\xef\x8f\xee\x8e\x8c\x23\x7b\x91\x9c\x9c\x8c\x4e\x9d\
\x3a\x55\x69\xdb\x11\xd5\x1d\x17\x8d\x9c\x29\x60\xb3\xd9\xd0\xab\
\x57\x2f\xba\x7b\xf7\x1e\xbc\xff\xc5\x46\xb4\xea\xd2\x5b\x36\xd5\
\xcf\x65\xa6\x61\xd2\xd0\xb6\x76\xa3\xa8\x9b\x9f\xbd\x73\x04\x3e\
\x73\xf7\x04\x40\xa5\x4d\xc3\x83\xab\x45\xa0\x5d\xf7\xa7\x11\xf7\
\xe2\x64\x54\x0b\xaf\xa5\xda\x90\xf2\x0d\x8d\x88\x8c\x8c\xea\xc5\
\xb7\x0b\x78\x92\x10\x41\x59\x90\x21\xdb\xf1\xbc\x98\x5f\x74\xef\
\x0e\x76\x24\x2e\xc3\xee\x8d\xab\x70\xf5\xcf\x73\x72\x92\x1b\xd1\
\x14\xe1\x1d\xff\x03\x9f\x9a\xcd\x90\xb9\xa4\x1f\xac\x65\x76\x07\
\xdc\xc4\x39\x6b\xf0\x78\xdf\xe7\x64\x92\x5b\xce\x85\x53\x78\x73\
\x70\x4b\x74\xea\xd8\x01\xdb\xb7\x6f\x97\xed\xbb\xed\x4a\x7b\xdf\
\xd7\xb6\xcc\xd7\xaf\x5f\xa7\xed\xdb\xb7\x87\xd5\xe4\x8d\x4f\xd7\
\xa6\xc2\xcb\xc7\x5f\x5c\xb6\x1e\xff\x46\x1c\x0e\xed\xde\xc8\xd3\
\xc4\x08\xc0\x23\x10\xb8\x77\x46\xc6\x0c\xc2\x6b\x37\x40\x9f\x61\
\x63\xd1\x6d\xc0\x28\x78\xfb\xfa\x8b\x08\x54\x56\x5a\x56\x6e\x87\
\x49\xe1\x08\x10\x55\xdb\x0c\x83\x95\x94\xd9\x91\x2d\xe2\xee\xe5\
\x52\xb4\x43\x1e\x96\xf2\x32\xa4\xed\xdb\x8a\x84\x65\x33\xf1\xe7\
\xb9\x0c\x50\x2a\x0d\x64\xcf\xe0\xda\xe0\x4c\x1e\x28\xbd\x65\xdf\
\xcc\x36\xb2\xde\x43\xf8\x62\x53\x06\x38\x93\x1b\x08\x80\xbc\x1b\
\x57\x31\x6f\xf2\x30\x5c\xbd\xf0\x07\x8e\x1e\x3d\x8a\x7a\xf5\xea\
\x91\xaa\xee\xdb\xc3\xb9\xc2\x7b\x94\xef\xc2\xc3\xc3\xc9\x07\x1f\
\x7c\x80\x2b\xd9\xa7\xb1\xe0\xdd\x91\xa2\x82\x97\x7b\xe9\x2c\xd2\
\xf7\xff\x2a\x25\x2c\xbd\x06\xdc\x3b\x2d\x76\x8e\x97\x8f\x1f\x26\
\x7d\xf2\x23\x96\xfd\x9a\x85\x7e\xcf\xbf\x01\x1f\x3f\x7f\xd1\x66\
\x25\x43\x52\x51\x2a\xc2\xb3\xc4\xbd\x43\x55\x7a\x43\x82\x40\x51\
\x99\x4f\x8e\xb0\xb0\x5c\xca\x98\x5f\x64\x9e\x59\x30\x52\x98\x24\
\x8d\x79\x78\x9a\xd1\xbe\xc7\x20\x2c\x5c\x7f\x1c\xf3\xd6\x1e\x44\
\x8d\xc8\xfa\x62\xaa\xf2\x3b\x97\xc5\xce\x11\x10\x40\xe9\xc9\xdb\
\x78\xa8\x15\xc5\x2f\xdf\xce\xc3\xa9\xf4\x64\xbc\xf6\xda\x6b\xa8\
\x5f\xbf\x3e\x51\x9b\x21\x46\x4e\x53\x71\xd8\x2f\x4e\x0b\x40\xa2\
\xf7\x6e\xe0\xc0\x81\xa4\x71\xe3\xc6\x48\x4f\xde\x86\xcc\xf4\xfd\
\xb0\xd9\x28\x92\x7e\xf9\xc6\xbe\xab\x94\xe2\x0a\x09\x8b\xc4\x8b\
\x6f\xcf\xc3\xc2\xf5\xc7\xd1\xf9\xa9\x67\xf9\x2d\xcb\x18\x90\xa1\
\x12\x08\xea\x60\x86\x11\x48\x11\x95\x91\x3c\x29\x3d\x91\x66\x06\
\xd3\xd3\x54\xe1\xd6\x96\x6d\x5b\xa1\xe1\x9d\xa5\x90\x56\x78\x47\
\x37\x7d\x14\xf3\x13\xd3\xf0\xda\xb4\xaf\x10\x15\x13\xab\xda\xa8\
\x3b\x12\x97\xc1\x66\xa3\xb8\x76\xf9\x3c\xf6\x6c\xfa\x0e\xc1\xc1\
\xc1\x18\x33\x66\x0c\x5c\x69\x5f\x55\xbc\xb6\x72\x5d\xa4\xde\x39\
\x0c\x5a\x5b\x30\x27\x25\x25\xd1\x7e\xfd\xfa\x21\x30\x34\x02\xaf\
\xbc\xff\x05\x16\x4f\xfb\x0f\xee\xdc\xba\xc6\xa7\xe7\xd0\xa8\x59\
\x1b\x74\x1f\x30\x0a\x5d\x7a\x0f\x13\xb1\x61\x50\x57\xd8\x19\x92\
\xa6\xdc\xf1\x97\x35\x2e\xda\x5d\x1c\x54\xd8\xdf\x4d\x3c\x3a\x4d\
\xda\x0c\x50\xce\xaf\xd4\x9f\x59\xc9\xc1\x9e\x17\x65\xbe\x23\xb7\
\x3e\x09\x75\xb6\x56\x56\xe0\xf0\xde\x2d\xd8\xb5\xf1\x5b\x1c\x4f\
\xd9\x29\x6e\xb0\xe1\xe1\x69\xc6\xe7\x3f\x1f\xc3\xa2\xf7\x47\xe3\
\xaf\x9c\x33\x58\xb0\x60\x01\x46\x8e\x1c\x49\xaa\x72\xae\x05\x3b\
\x8b\x4c\xd3\xa7\x4f\xd7\x75\x1a\x19\x39\x18\x22\x2a\x2a\xea\x23\
\xab\xd5\x3a\x7d\xeb\xe6\x0d\xa8\x28\x2f\x43\xe1\xbd\x3c\x14\xdd\
\xbb\x0b\xbf\x80\x60\x3c\x39\xf8\x25\x4c\x9c\xb3\x06\xd1\x8f\xb4\
\x85\xbb\x87\xa7\xdd\x6f\xc2\xba\x86\x15\x40\x0e\x22\x3a\xb9\xa8\
\x08\xcb\xa5\x0c\xf7\x27\xbc\x9f\x88\x30\x07\x3a\xc9\x5c\xd6\x7c\
\x27\x50\x30\x5b\x28\xb2\xab\x29\xa8\xdc\x81\x08\xb6\xc3\xc1\x3a\
\x0d\xf9\xef\xf0\x1b\x68\x8b\xbb\x40\x12\x13\x6a\x45\x35\x46\x97\
\xa7\x86\x22\x20\xa4\x3a\x2e\x9e\x3d\x8e\xd2\xe2\x42\x04\x84\x54\
\x47\x85\xa5\x1c\x29\x3b\xd7\x61\xec\xd8\xb1\x98\x3c\x79\x32\xd1\
\x73\xca\x39\x9b\x14\xe2\x4f\xed\x68\x00\x67\xb6\x39\x65\x4f\x13\
\x42\x50\x51\x51\x81\x21\x43\x86\xd0\x2d\x5b\xb7\xa2\xf3\x53\x43\
\xd1\xbe\x7b\x1c\x1e\x6e\xd5\x19\x3e\xfe\x41\x8c\x74\xe7\x6c\x3f\
\x29\xc7\xed\xc7\xa5\xed\xc6\x01\xa8\x1c\x0d\xc0\x36\xb2\x73\x0d\
\x55\x1e\xae\x8a\x3f\x25\xda\x80\x7c\x76\x5d\xba\x90\xbe\xac\xb4\
\x18\xb9\x17\xcf\xe0\xd0\x9e\x4d\x58\xb7\x62\x36\x5a\x34\x6f\x8e\
\x7d\xfb\xf6\x89\x07\x71\x68\x91\x30\xa3\xc2\x19\xe7\x8a\x1d\x4e\
\x8f\x2f\xb9\xbb\xbb\x63\xc9\x92\x25\x88\x08\x0f\xc7\xfe\xad\x3f\
\xa2\xf0\xde\x1d\xf8\x04\x04\x3b\x80\x37\xa8\x83\x22\xc9\xb8\xcd\
\x45\x96\xa0\x58\x32\x41\x18\xd4\x37\x51\xb8\xd1\x85\x19\xa1\x70\
\x41\x4b\x70\x63\xf6\x99\x48\x9b\x3b\x29\xc0\x23\x72\xb7\xbd\x34\
\xc3\xa8\xca\x2a\x3b\x4a\x24\xf8\xaf\x97\xb7\x2f\xca\x4a\x8a\xf1\
\xcb\x37\xf3\xe0\xed\xe5\x85\xef\xbe\xfb\x0e\x7e\x7e\x7e\x0f\xe4\
\x1c\xf4\x2a\xef\xd5\xa3\xe5\x92\x08\x0b\x0b\x23\xf3\xe7\xcf\x47\
\x78\x78\x0d\x7c\xbf\x68\x1a\xae\x64\x9f\x96\x76\xce\x95\x81\x49\
\x04\xa9\x8c\x97\xd2\x44\x48\x30\x65\x9c\x5c\x8c\xd9\x9e\x2a\xdc\
\x19\x80\x43\x18\xa1\x2c\x26\x97\x07\x16\x12\x16\x48\x28\xad\x35\
\x25\x32\x74\xb8\x54\x0e\x36\x9c\xf0\xab\xb5\xd9\xf2\x08\x52\x1a\
\xdb\x8d\xd9\x67\x8e\x63\xc5\x9c\x09\xf0\xf6\x32\x63\xd5\xaa\x55\
\x88\x89\x89\x21\x5a\xee\x9a\xaa\xfc\x44\x77\x83\x9e\x62\xaa\x77\
\xce\x9d\xda\x29\x1f\xc7\x8f\x1f\xa7\x4f\x3e\xf9\x24\x0a\x8b\x4a\
\x30\x21\x7e\x15\x3a\xf4\x18\xc4\xc0\x84\xa9\xe2\x9e\x71\x35\xb3\
\x67\x39\x10\xa8\xc4\x17\xb5\x4d\x05\x39\xaa\x42\x7c\x99\xa8\xad\
\x2c\x8f\xca\xe2\x23\x36\x0e\x9f\xfe\xec\x89\x14\xcc\x18\xd3\x0f\
\x96\xb2\x62\x6c\xd8\xb0\x01\x3d\x7b\xf6\x24\xca\x36\x73\x26\x60\
\x39\x6b\x6f\xcd\x83\x6e\x95\x7c\xc6\xe8\x01\xe1\x00\xd0\xa2\x45\
\x0b\xb2\x60\xc1\x02\x58\xca\x4b\x31\x7f\xca\xf3\xc8\x3a\xc9\x83\
\x4c\x88\x62\x17\x12\x66\x55\x22\x51\xec\x43\x20\xdf\xac\x8f\x71\
\x80\x41\xc5\xe9\x2a\x5b\x51\x2d\xdf\x76\x46\x2b\xbe\xe4\x50\x03\
\xb3\xd2\x9c\xd1\x84\x89\x7c\x71\x1a\x91\x2d\x73\xa4\xb8\x71\xf5\
\x22\x66\x8e\x7b\x1a\x85\xf7\xee\x60\xca\x94\x29\xb2\xce\xd1\x83\
\x50\xbb\xda\xde\x44\xb9\xe9\xb6\x9e\xd8\xe7\xec\x3d\xdb\xfb\x36\
\x9b\x0d\xeb\xd6\xad\xa3\x6f\xbc\xf1\x06\xca\x2a\x28\x46\xbe\x39\
\x1b\xdd\xfa\x8f\x04\x67\x32\x39\x0c\x4e\x46\xb8\x85\xfe\x69\x1b\
\x2a\xef\x65\x72\x03\x33\x03\x54\x8f\x3b\xa1\xec\xc2\x51\x1d\x88\
\x0f\xd1\xfc\x3e\x05\x70\xe0\xb7\x75\x58\x31\x7b\x02\x2c\xa5\x05\
\x58\xb9\x72\x25\xe2\xe2\xe2\x88\x87\x87\x87\xa1\x83\xe2\x5d\x6d\
\x67\xdd\xd3\x4f\x1e\xc4\x95\x91\x91\x41\xfb\xf7\xef\x8f\x9c\x9c\
\xcb\xe8\x36\x60\x24\x5e\x9a\xf2\xb9\xb8\xd2\x4c\xb9\x8c\x91\x10\
\xe5\x4e\x87\x0a\xca\xe7\x2c\x8e\x0a\xc5\x72\x10\xf8\xd4\xa8\xa0\
\x32\x7f\x8d\x6f\x95\x97\x95\x62\xdd\x8a\x39\xf8\x79\xe5\x1c\x04\
\xf8\xfb\xe1\xa7\x9f\x7e\x42\xf7\xee\xdd\xc9\xdf\xd9\x7e\x9c\x2b\
\x27\x3f\x6a\xd1\x49\xbd\x74\x4d\x9b\x36\x25\x4b\x96\x2c\x41\xc3\
\x86\x0d\xb0\x6b\xc3\xb7\x58\x3e\xfb\x0d\xd1\xff\x42\x18\x93\x8c\
\x68\xea\xa1\x44\x75\x0f\x20\x89\xa6\x2b\xd6\xe8\xf0\x9b\x9f\xcb\
\xac\x00\xac\xc9\x48\xdc\x84\x1c\x8a\xfd\x9d\xe4\x0b\x7c\x09\x18\
\x4b\x84\x28\x0a\x43\x84\x56\x15\xe6\xdf\xc1\xd2\x99\x63\xb1\x6e\
\x79\x3c\xea\xd4\xae\x85\x2f\xbf\xfc\x52\xec\x1c\x23\x67\xc6\x56\
\xe5\x24\x4d\xd9\x0c\xd2\x3b\x45\x57\x6b\x8f\x4d\x3d\xf9\x5e\x79\
\x5f\x5c\x5c\x8c\xc9\x93\x27\xd3\xa5\x4b\x97\xda\x51\x38\x6f\x7d\
\x82\x2e\xbd\x87\xd9\x95\x57\xca\x9f\x4a\xe2\xe0\xd3\xa7\x8c\x25\
\x88\x48\x67\x26\x50\xc6\x3a\xa0\xa4\x66\x4a\xd8\xb0\x08\xcd\x25\
\xe2\x52\x4d\x87\x77\xec\xf9\x40\x90\x77\x6e\x79\x79\x09\x4e\xa4\
\xee\xc2\xca\xb9\x6f\xe2\x46\xee\x25\xf4\xef\xdf\x1f\xcb\x97\x2f\
\x5f\x57\xad\x5a\xb5\x21\x5a\x75\x75\x76\xef\xec\x9d\x83\x35\x5b\
\xef\xe4\x2d\x2d\xfa\xa8\x25\xcd\xe9\x9d\xe3\x46\x29\xc5\x0f\x3f\
\xfc\x40\x27\x4d\x9a\x84\x9b\xb7\x6e\xa1\x76\xfd\xc6\x98\x10\xbf\
\x1a\x0d\x9a\xb4\x94\xcd\x10\x61\xbd\x91\xba\x24\x04\x11\x30\x29\
\x8c\x72\x42\x94\x65\x70\x3c\x37\x50\x3a\xd9\x97\xf5\x15\xa9\x7d\
\x03\xa2\xc9\xe7\xc6\xd5\x3f\x31\xfb\x8d\x81\xb8\x94\x75\x12\x6e\
\x6e\x26\xac\x5e\xbd\x5a\xc6\x6f\xf4\x4e\x29\xd3\x6b\x3f\x67\x6d\
\x2b\x0b\xfb\xbb\x4f\x81\x54\x63\x82\xd9\xd9\xd9\x74\xc2\x84\x09\
\xd8\xbe\x7d\x3b\xbc\x7c\xfc\xd1\x77\xf8\x78\x74\x7c\x72\x30\x6a\
\x37\x68\x52\xa5\x13\x14\xa9\x2e\x5b\x77\x72\xc8\x97\xc3\x16\x0b\
\x14\xb7\xae\x5f\xc6\x81\x1d\x89\xd8\xfc\xfd\x42\xdc\xcb\xbb\x81\
\x36\x6d\xda\x60\xc1\x82\x05\x68\xdd\xba\x35\x79\x90\x27\x3c\x1a\
\x76\xd8\x55\xa9\x51\x0c\x8e\x02\xad\xb4\x56\xab\x15\x07\x0f\x1e\
\xa4\xf1\xf1\xf1\xd8\xb9\x73\x27\xdc\xdc\x3d\xd0\xee\x89\x38\xf4\
\x88\x1b\x8d\x98\xd8\x8e\x76\xd2\xe7\xd0\x88\x54\x8d\x0e\x89\x16\
\x6a\xe2\xe0\x30\x52\xef\x0c\xb5\xb7\x56\x6b\x25\x2e\x9c\x4a\xc7\
\xee\x8d\xab\xb1\xff\xd7\x1f\x51\x52\x54\x80\x36\x6d\xda\x20\x3e\
\x3e\x1e\x1d\x3b\x76\x24\x9e\x9e\x9e\x2e\xd5\x5d\x4b\xdf\x71\xb5\
\xcd\xfe\xeb\x33\x48\x59\x28\xab\xd5\x8a\xb5\x6b\xd7\xd2\x39\x73\
\xe6\xe0\xd4\xa9\x53\x00\x21\xa8\xdb\xa8\x29\x46\x4f\xfe\x0c\x0d\
\x9b\xb4\x86\xb7\xaf\xbf\x8e\xfd\xae\xca\x25\x10\xc5\xbb\xf2\xd2\
\x62\x5c\xce\x3e\x8d\x55\xf3\xdf\x41\x66\x7a\x32\xa8\xcd\x86\x5a\
\xb5\x6a\x61\xe2\xc4\x89\x18\x33\x66\x8c\xae\x27\xf4\xbf\x3e\x83\
\x8c\x30\x37\x35\x29\xc4\x08\x23\x54\xcb\x97\x4d\x6b\xb1\x58\xb0\
\x7e\xfd\x7a\x9a\x90\x90\x80\xe4\xe4\x64\xe4\xe7\xe7\xc3\x2f\x20\
\x18\x2d\x3a\xf4\x40\x4c\x6c\x27\x34\x68\xd2\x12\x75\x1a\x3e\x0c\
\xb3\x97\x8f\x6c\xce\xc8\x4f\x71\x54\x18\x43\x45\xcb\xb6\xe4\x8c\
\xab\xb0\x58\x70\xe5\xe2\x19\x64\x9d\x3c\x84\x73\x99\x69\x38\x7e\
\xe0\x37\xe4\xdd\xbc\x0a\x6f\x6f\x6f\xb4\x6f\xdf\x1e\x71\x71\x71\
\x18\x3e\x7c\x38\xf1\xf5\xf5\x75\xda\x2e\x6a\xef\x5c\x39\x0a\xda\
\x90\x00\xf1\xbf\x31\x83\x9c\xcd\xae\x5b\xb7\x6e\xa5\x6f\xd9\xb2\
\xa5\x65\x52\x52\x12\xb6\x6f\xdf\x8e\x82\x82\x02\x10\x8e\x43\x40\
\x50\x35\x84\x45\xd6\x43\x78\xed\x06\x88\xac\x17\x8d\x6a\x35\x6a\
\x23\xb8\x7a\x04\xbc\x7c\xfc\x60\xf6\xf6\x15\xdd\xe6\xa5\xc5\x85\
\x28\x29\x2a\x40\x79\x69\x09\xee\xde\xfe\x0b\x37\x72\x2f\xe2\x7a\
\xee\x45\xe4\x5e\x3c\x83\x5b\xd7\x2e\xe3\x6e\xde\x0d\xd8\xac\x95\
\xf0\xf2\xf2\x42\xb7\x6e\xdd\xd0\xbd\x7b\x77\xc4\xc5\xc5\xa1\x66\
\xcd\x9a\x84\xe3\x38\x97\x49\xf6\x83\xa6\x2a\x9a\x52\x9c\x1a\xad\
\xd4\x92\x50\xb4\xc4\x6f\x67\x52\x8c\xd6\x48\x54\x8b\x53\x56\x56\
\x86\xb4\xb4\x34\x7a\xf0\xe0\x41\x1c\x39\x72\x04\x69\x69\x69\xb8\
\x7d\xfb\x36\x4a\x4b\xa5\xa3\xa3\xcd\x5e\x3e\xf0\xf4\xf2\x81\xa7\
\xd9\x1b\x66\x6f\x1f\x7b\xba\xd2\x62\x94\x95\x14\xc3\x52\x5e\x8a\
\xb2\x92\x22\x31\x4f\xb3\xd9\x8c\xa0\xa0\x20\xb4\x68\xd1\x02\x1d\
\x3b\x76\x44\xab\x56\xad\xd0\xb6\x6d\x5b\xd9\x19\xdd\x7a\x87\xc7\
\x3b\xe3\x21\x55\x89\xa3\xd7\x76\x55\x96\xe2\x1e\xc4\xa1\xae\x55\
\x49\x53\x52\x52\x82\x3b\x77\xee\xd0\x6b\xd7\xae\x21\x2b\x2b\x0b\
\x97\x2f\x5f\x46\x6e\x6e\x2e\x0a\x0a\x0a\x50\x58\x58\x28\xee\x86\
\x12\x10\x10\x80\xc0\xc0\x40\xf8\xf8\xf8\x20\x22\x22\x02\xf5\xeb\
\xd7\x47\xfd\xfa\xf5\x51\xa7\x4e\x1d\x04\x06\x06\x12\x3f\x3f\x3f\
\xfc\x5f\xb8\x34\x3b\xc8\x88\x44\x52\x55\x79\xff\x41\xd9\xfd\x5c\
\x71\x7a\x19\x91\xa6\x8c\x94\xdb\x48\xf9\x1e\x74\xfe\xff\x38\x1e\
\xf4\xef\xa5\xb0\xc5\x69\x1d\x56\xab\xd7\xbb\xce\x40\xf6\x46\xc0\
\x10\x7a\xe9\x8d\x40\x92\x8c\xa6\x77\x56\x3f\x67\xe5\x77\xb5\x7d\
\x8c\xd4\xdf\x95\xef\xff\x3b\x83\xfe\xe1\x97\xdb\xbf\x1d\xf4\xcf\
\xbe\xfe\x96\x19\xf4\xdf\xd4\x1f\xfe\xbf\x7f\x9f\x38\xa3\xa9\x46\
\x80\x8c\x55\xb5\x26\xe8\x69\xe7\x46\x74\x12\x57\xca\xab\xa7\x7b\
\x3c\xc8\xfc\xd5\x0e\x26\x71\x35\x7f\xb6\x8c\xaa\x3b\x2e\xea\x89\
\xd8\x46\x3e\xe2\x8a\xd8\xeb\x4c\x91\x75\x96\xde\xe8\xce\x85\xce\
\x44\x60\x36\xdc\xc8\xa9\xcc\x7a\xdf\xd6\x7a\x6f\x34\x7f\x59\x5e\
\x7f\xb7\xcb\xfb\xdf\xeb\xfe\xae\xff\x01\x23\xea\xed\xde\xc5\xed\
\x5c\x00\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
"
qt_resource_name = b"\
\x00\x07\
\x07\x3b\xe0\xb3\
\x00\x70\
\x00\x6c\x00\x75\x00\x67\x00\x69\x00\x6e\x00\x73\
\x00\x06\
\x06\x98\x2f\xb3\
\x00\x63\
\x00\x61\x00\x6c\x00\x69\x00\x65\x00\x63\
\x00\x08\
\x0a\x61\x5a\xa7\
\x00\x69\
\x00\x63\x00\x6f\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
"
qt_resource_struct_v1 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
\x00\x00\x00\x26\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
"
qt_resource_struct_v2 = b"\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x26\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x77\xed\xcb\x53\xaa\
"
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
if qt_version < [5, 8, 0]:
rcc_version = 1
qt_resource_struct = qt_resource_struct_v1
else:
rcc_version = 2
qt_resource_struct = qt_resource_struct_v2
def qInitResources():
QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
def qCleanupResources():
QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
qInitResources()

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/plugins/caliec" >
<file>icon.png</file>
</qresource>
</RCC>

80
pb_tool.cfg Normal file
View File

@ -0,0 +1,80 @@
#/***************************************************************************
# Orientation
#
# Configuration file for plugin builder tool (pb_tool)
# Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
# -------------------
# begin : 2021-03-01
# copyright : (C) 2021 by Association Linux-Alpes
# email : caliec@linux-alpes.org
# ***************************************************************************/
#
#/***************************************************************************
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU General Public License as published by *
# * the Free Software Foundation; either version 2 of the License, or *
# * (at your option) any later version. *
# * *
# ***************************************************************************/
#
#
# You can install pb_tool using:
# pip install http://geoapt.net/files/pb_tool.zip
#
# Consider doing your development (and install of pb_tool) in a virtualenv.
#
# For details on setting up and using pb_tool, see:
# http://g-sherman.github.io/plugin_build_tool/
#
# Issues and pull requests here:
# https://github.com/g-sherman/plugin_build_tool:
#
# Sane defaults for your plugin generated by the Plugin Builder are
# already set below.
#
# As you add Python source files and UI files to your plugin, add
# them to the appropriate [files] section below.
[plugin]
# Name of the plugin. This is the name of the directory that will
# be created
name: caliec
# Full path to where you want your plugin directory copied. If empty,
# the QGIS default path will be used. Don't include the plugin name in
# the path.
plugin_path:
[files]
# Python files that should be deployed with the plugin
python_files: __init__.py caliec.py
# The main dialog file that is loaded (not compiled)
main_dialog:
# Other ui files for dialogs you create (these will be compiled)
compiled_ui_files:
# Resource file(s) that will be compiled
resource_files: resources.qrc
# Other files required for the plugin
extras: metadata.txt icon.png
# Other directories to be deployed with the plugin.
# These must be subdirectories under the plugin directory
extra_dirs:
# ISO code(s) for any locales (translations), separated by spaces.
# Corresponding .ts files must exist in the i18n directory
locales:
[help]
# the built help directory that should be deployed with the plugin
dir: help/build/html
# the name of the directory to target in the deployed plugin
target: help

111
plugin_upload.py Executable file
View File

@ -0,0 +1,111 @@
#!/usr/bin/env python
# coding=utf-8
"""This script uploads a plugin package to the plugin repository.
Authors: A. Pasotti, V. Picavet
git sha : $TemplateVCSFormat
"""
import sys
import getpass
import xmlrpc.client
from optparse import OptionParser
standard_library.install_aliases()
# Configuration
PROTOCOL = 'https'
SERVER = 'plugins.qgis.org'
PORT = '443'
ENDPOINT = '/plugins/RPC2/'
VERBOSE = False
def main(parameters, arguments):
"""Main entry point.
:param parameters: Command line parameters.
:param arguments: Command line arguments.
"""
address = "{protocol}://{username}:{password}@{server}:{port}{endpoint}".format(
protocol=PROTOCOL,
username=parameters.username,
password=parameters.password,
server=parameters.server,
port=parameters.port,
endpoint=ENDPOINT)
print("Connecting to: %s" % hide_password(address))
server = xmlrpc.client.ServerProxy(address, verbose=VERBOSE)
try:
with open(arguments[0], 'rb') as handle:
plugin_id, version_id = server.plugin.upload(
xmlrpc.client.Binary(handle.read()))
print("Plugin ID: %s" % plugin_id)
print("Version ID: %s" % version_id)
except xmlrpc.client.ProtocolError as err:
print("A protocol error occurred")
print("URL: %s" % hide_password(err.url, 0))
print("HTTP/HTTPS headers: %s" % err.headers)
print("Error code: %d" % err.errcode)
print("Error message: %s" % err.errmsg)
except xmlrpc.client.Fault as err:
print("A fault occurred")
print("Fault code: %d" % err.faultCode)
print("Fault string: %s" % err.faultString)
def hide_password(url, start=6):
"""Returns the http url with password part replaced with '*'.
:param url: URL to upload the plugin to.
:type url: str
:param start: Position of start of password.
:type start: int
"""
start_position = url.find(':', start) + 1
end_position = url.find('@')
return "%s%s%s" % (
url[:start_position],
'*' * (end_position - start_position),
url[end_position:])
if __name__ == "__main__":
parser = OptionParser(usage="%prog [options] plugin.zip")
parser.add_option(
"-w", "--password", dest="password",
help="Password for plugin site", metavar="******")
parser.add_option(
"-u", "--username", dest="username",
help="Username of plugin site", metavar="user")
parser.add_option(
"-p", "--port", dest="port",
help="Server port to connect to", metavar="80")
parser.add_option(
"-s", "--server", dest="server",
help="Specify server name", metavar="plugins.qgis.org")
options, args = parser.parse_args()
if len(args) != 1:
print("Please specify zip file.\n")
parser.print_help()
sys.exit(1)
if not options.server:
options.server = SERVER
if not options.port:
options.port = PORT
if not options.username:
# interactive mode
username = getpass.getuser()
print("Please enter user name [%s] :" % username, end=' ')
res = input()
if res != "":
options.username = res
else:
options.username = username
if not options.password:
# interactive mode
options.password = getpass.getpass()
main(options, args)

281
pylintrc Normal file
View File

@ -0,0 +1,281 @@
[MASTER]
# Specify a configuration file.
#rcfile=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Profiled execution.
profile=no
# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS
# Pickle collected data for later comparisons.
persistent=yes
# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=
[MESSAGES CONTROL]
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time. See also the "--disable" option for examples.
#enable=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once).You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
# see http://stackoverflow.com/questions/21487025/pylint-locally-defined-disables-still-give-warnings-how-to-suppress-them
disable=locally-disabled,C0103
[REPORTS]
# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text
# Put messages in a separate file for each module / package specified on the
# command line instead of printing them on stdout. Reports (if any) will be
# written in a file name "pylint_global.[txt|html]".
files-output=no
# Tells whether to display a full report or only the messages
reports=yes
# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Add a comment according to your evaluation note. This is used by the global
# evaluation report (RP0004).
comment=no
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details
#msg-template=
[BASIC]
# Required attributes for module, separated by a comma
required-attributes=
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,apply,input
# Regular expression which should only match correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression which should only match correct module level names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression which should only match correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Regular expression which should only match correct function names
function-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct method names
method-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct instance attribute names
attr-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct argument names
argument-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct variable names
variable-rgx=[a-z_][a-z0-9_]{2,30}$
# Regular expression which should only match correct attribute names in class
# bodies
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
# Regular expression which should only match correct list comprehension /
# generator expression variable names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata
# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=__.*__
# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO
[TYPECHECK]
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set).
ignored-classes=SQLObject
# When zope mode is activated, add a predefined set of Zope acquired attributes
# to generated-members.
zope=no
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E0201 when accessed. Python regular
# expressions are accepted.
generated-members=REQUEST,acl_users,aq_parent
[VARIABLES]
# Tells whether we should check for unused import in __init__ files.
init-import=no
# A regular expression matching the beginning of the name of dummy variables
# (i.e. not used).
dummy-variables-rgx=_$|dummy
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=80
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# List of optional constructs for which whitespace checking is disabled
no-space-check=trailing-comma,dict-separator
# Maximum number of lines in a module
max-module-lines=1000
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
[SIMILARITIES]
# Minimum lines number of a similarity.
min-similarity-lines=4
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=
[DESIGN]
# Maximum number of arguments for function / method
max-args=5
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=7
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
[CLASSES]
# List of interface methods to ignore, separated by a comma. This is used for
# instance to not check methods defines in Zope's Interface base class.
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

2
test/__init__.py Normal file
View File

@ -0,0 +1,2 @@
# import qgis libs so that ve set the correct sip api version
import qgis # pylint: disable=W0611 # NOQA

BIN
test/__init__.pyc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

205
test/qgis_interface.py Normal file
View File

@ -0,0 +1,205 @@
# coding=utf-8
"""QGIS plugin implementation.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
.. note:: This source code was copied from the 'postgis viewer' application
with original authors:
Copyright (c) 2010 by Ivan Mincik, ivan.mincik@gista.sk
Copyright (c) 2011 German Carrillo, geotux_tuxman@linuxmail.org
Copyright (c) 2014 Tim Sutton, tim@linfiniti.com
"""
__author__ = 'tim@linfiniti.com'
__revision__ = '$Format:%H$'
__date__ = '10/01/2011'
__copyright__ = (
'Copyright (c) 2010 by Ivan Mincik, ivan.mincik@gista.sk and '
'Copyright (c) 2011 German Carrillo, geotux_tuxman@linuxmail.org'
'Copyright (c) 2014 Tim Sutton, tim@linfiniti.com'
)
import logging
from qgis.PyQt.QtCore import QObject, pyqtSlot, pyqtSignal
from qgis.core import QgsMapLayerRegistry
from qgis.gui import QgsMapCanvasLayer
LOGGER = logging.getLogger('QGIS')
#noinspection PyMethodMayBeStatic,PyPep8Naming
class QgisInterface(QObject):
"""Class to expose QGIS objects and functions to plugins.
This class is here for enabling us to run unit tests only,
so most methods are simply stubs.
"""
currentLayerChanged = pyqtSignal(QgsMapCanvasLayer)
def __init__(self, canvas):
"""Constructor
:param canvas:
"""
QObject.__init__(self)
self.canvas = canvas
# Set up slots so we can mimic the behaviour of QGIS when layers
# are added.
LOGGER.debug('Initialising canvas...')
# noinspection PyArgumentList
QgsMapLayerRegistry.instance().layersAdded.connect(self.addLayers)
# noinspection PyArgumentList
QgsMapLayerRegistry.instance().layerWasAdded.connect(self.addLayer)
# noinspection PyArgumentList
QgsMapLayerRegistry.instance().removeAll.connect(self.removeAllLayers)
# For processing module
self.destCrs = None
@pyqtSlot('QStringList')
def addLayers(self, layers):
"""Handle layers being added to the registry so they show up in canvas.
:param layers: list<QgsMapLayer> list of map layers that were added
.. note:: The QgsInterface api does not include this method,
it is added here as a helper to facilitate testing.
"""
#LOGGER.debug('addLayers called on qgis_interface')
#LOGGER.debug('Number of layers being added: %s' % len(layers))
#LOGGER.debug('Layer Count Before: %s' % len(self.canvas.layers()))
current_layers = self.canvas.layers()
final_layers = []
for layer in current_layers:
final_layers.append(QgsMapCanvasLayer(layer))
for layer in layers:
final_layers.append(QgsMapCanvasLayer(layer))
self.canvas.setLayerSet(final_layers)
#LOGGER.debug('Layer Count After: %s' % len(self.canvas.layers()))
@pyqtSlot('QgsMapLayer')
def addLayer(self, layer):
"""Handle a layer being added to the registry so it shows up in canvas.
:param layer: list<QgsMapLayer> list of map layers that were added
.. note: The QgsInterface api does not include this method, it is added
here as a helper to facilitate testing.
.. note: The addLayer method was deprecated in QGIS 1.8 so you should
not need this method much.
"""
pass
@pyqtSlot()
def removeAllLayers(self):
"""Remove layers from the canvas before they get deleted."""
self.canvas.setLayerSet([])
def newProject(self):
"""Create new project."""
# noinspection PyArgumentList
QgsMapLayerRegistry.instance().removeAllMapLayers()
# ---------------- API Mock for QgsInterface follows -------------------
def zoomFull(self):
"""Zoom to the map full extent."""
pass
def zoomToPrevious(self):
"""Zoom to previous view extent."""
pass
def zoomToNext(self):
"""Zoom to next view extent."""
pass
def zoomToActiveLayer(self):
"""Zoom to extent of active layer."""
pass
def addVectorLayer(self, path, base_name, provider_key):
"""Add a vector layer.
:param path: Path to layer.
:type path: str
:param base_name: Base name for layer.
:type base_name: str
:param provider_key: Provider key e.g. 'ogr'
:type provider_key: str
"""
pass
def addRasterLayer(self, path, base_name):
"""Add a raster layer given a raster layer file name
:param path: Path to layer.
:type path: str
:param base_name: Base name for layer.
:type base_name: str
"""
pass
def activeLayer(self):
"""Get pointer to the active layer (layer selected in the legend)."""
# noinspection PyArgumentList
layers = QgsMapLayerRegistry.instance().mapLayers()
for item in layers:
return layers[item]
def addToolBarIcon(self, action):
"""Add an icon to the plugins toolbar.
:param action: Action to add to the toolbar.
:type action: QAction
"""
pass
def removeToolBarIcon(self, action):
"""Remove an action (icon) from the plugin toolbar.
:param action: Action to add to the toolbar.
:type action: QAction
"""
pass
def addToolBar(self, name):
"""Add toolbar with specified name.
:param name: Name for the toolbar.
:type name: str
"""
pass
def mapCanvas(self):
"""Return a pointer to the map canvas."""
return self.canvas
def mainWindow(self):
"""Return a pointer to the main window.
In case of QGIS it returns an instance of QgisApp.
"""
pass
def addDockWidget(self, area, dock_widget):
"""Add a dock widget to the main window.
:param area: Where in the ui the dock should be placed.
:type area:
:param dock_widget: A dock widget to add to the UI.
:type dock_widget: QDockWidget
"""
pass
def legendInterface(self):
"""Get the legend."""
return self.canvas

64
test/test_init.py Normal file
View File

@ -0,0 +1,64 @@
# coding=utf-8
"""Tests QGIS plugin init."""
__author__ = 'Tim Sutton <tim@linfiniti.com>'
__revision__ = '$Format:%H$'
__date__ = '17/10/2010'
__license__ = "GPL"
__copyright__ = 'Copyright 2012, Australia Indonesia Facility for '
__copyright__ += 'Disaster Reduction'
import os
import unittest
import logging
import configparser
LOGGER = logging.getLogger('QGIS')
class TestInit(unittest.TestCase):
"""Test that the plugin init is usable for QGIS.
Based heavily on the validator class by Alessandro
Passoti available here:
http://github.com/qgis/qgis-django/blob/master/qgis-app/
plugins/validator.py
"""
def test_read_init(self):
"""Test that the plugin __init__ will validate on plugins.qgis.org."""
# You should update this list according to the latest in
# https://github.com/qgis/qgis-django/blob/master/qgis-app/
# plugins/validator.py
required_metadata = [
'name',
'description',
'version',
'qgisMinimumVersion',
'email',
'author']
file_path = os.path.abspath(os.path.join(
os.path.dirname(__file__), os.pardir,
'metadata.txt'))
LOGGER.info(file_path)
metadata = []
parser = configparser.ConfigParser()
parser.optionxform = str
parser.read(file_path)
message = 'Cannot find a section named "general" in %s' % file_path
assert parser.has_section('general'), message
metadata.extend(parser.items('general'))
for expectation in required_metadata:
message = ('Cannot find metadata "%s" in metadata source (%s).' % (
expectation, file_path))
self.assertIn(expectation, dict(metadata), message)
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1,60 @@
# coding=utf-8
"""Tests for QGIS functionality.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'tim@linfiniti.com'
__date__ = '20/01/2011'
__copyright__ = ('Copyright 2012, Australia Indonesia Facility for '
'Disaster Reduction')
import os
import unittest
from qgis.core import (
QgsProviderRegistry,
QgsCoordinateReferenceSystem,
QgsRasterLayer)
from .utilities import get_qgis_app
QGIS_APP = get_qgis_app()
class QGISTest(unittest.TestCase):
"""Test the QGIS Environment"""
def test_qgis_environment(self):
"""QGIS environment has the expected providers"""
r = QgsProviderRegistry.instance()
self.assertIn('gdal', r.providerList())
self.assertIn('ogr', r.providerList())
self.assertIn('postgres', r.providerList())
def test_projection(self):
"""Test that QGIS properly parses a wkt string.
"""
crs = QgsCoordinateReferenceSystem()
wkt = (
'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",'
'SPHEROID["WGS_1984",6378137.0,298.257223563]],'
'PRIMEM["Greenwich",0.0],UNIT["Degree",'
'0.0174532925199433]]')
crs.createFromWkt(wkt)
auth_id = crs.authid()
expected_auth_id = 'EPSG:4326'
self.assertEqual(auth_id, expected_auth_id)
# now test for a loaded layer
path = os.path.join(os.path.dirname(__file__), 'tenbytenraster.asc')
title = 'TestRaster'
layer = QgsRasterLayer(path, title)
auth_id = layer.crs().authid()
self.assertEqual(auth_id, expected_auth_id)
if __name__ == '__main__':
unittest.main()

44
test/test_resources.py Normal file
View File

@ -0,0 +1,44 @@
# coding=utf-8
"""Resources test.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'caliec@linux-alpes.org'
__date__ = '2021-03-01'
__copyright__ = 'Copyright 2021, Association Linux-Alpes'
import unittest
from qgis.PyQt.QtGui import QIcon
class OrientationDialogTest(unittest.TestCase):
"""Test rerources work."""
def setUp(self):
"""Runs before each test."""
pass
def tearDown(self):
"""Runs after each test."""
pass
def test_icon_png(self):
"""Test we can click OK."""
path = ':/plugins/Orientation/icon.png'
icon = QIcon(path)
self.assertFalse(icon.isNull())
if __name__ == "__main__":
suite = unittest.makeSuite(OrientationResourcesTest)
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

55
test/test_translations.py Normal file
View File

@ -0,0 +1,55 @@
# coding=utf-8
"""Safe Translations Test.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
from .utilities import get_qgis_app
__author__ = 'ismailsunni@yahoo.co.id'
__date__ = '12/10/2011'
__copyright__ = ('Copyright 2012, Australia Indonesia Facility for '
'Disaster Reduction')
import unittest
import os
from qgis.PyQt.QtCore import QCoreApplication, QTranslator
QGIS_APP = get_qgis_app()
class SafeTranslationsTest(unittest.TestCase):
"""Test translations work."""
def setUp(self):
"""Runs before each test."""
if 'LANG' in iter(os.environ.keys()):
os.environ.__delitem__('LANG')
def tearDown(self):
"""Runs after each test."""
if 'LANG' in iter(os.environ.keys()):
os.environ.__delitem__('LANG')
def test_qgis_translations(self):
"""Test that translations work."""
parent_path = os.path.join(__file__, os.path.pardir, os.path.pardir)
dir_path = os.path.abspath(parent_path)
file_path = os.path.join(
dir_path, 'i18n', 'fr.qm')
translator = QTranslator()
translator.load(file_path)
QCoreApplication.installTranslator(translator)
expected_message = 'Bonjour'
real_message = QCoreApplication.translate("@default", 'Good morning')
self.assertEqual(real_message, expected_message)
if __name__ == "__main__":
suite = unittest.makeSuite(SafeTranslationsTest)
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)

61
test/utilities.py Normal file
View File

@ -0,0 +1,61 @@
# coding=utf-8
"""Common functionality used by regression tests."""
import sys
import logging
LOGGER = logging.getLogger('QGIS')
QGIS_APP = None # Static variable used to hold hand to running QGIS app
CANVAS = None
PARENT = None
IFACE = None
def get_qgis_app():
""" Start one QGIS application to test against.
:returns: Handle to QGIS app, canvas, iface and parent. If there are any
errors the tuple members will be returned as None.
:rtype: (QgsApplication, CANVAS, IFACE, PARENT)
If QGIS is already running the handle to that app will be returned.
"""
try:
from qgis.PyQt import QtGui, QtCore
from qgis.core import QgsApplication
from qgis.gui import QgsMapCanvas
from .qgis_interface import QgisInterface
except ImportError:
return None, None, None, None
global QGIS_APP # pylint: disable=W0603
if QGIS_APP is None:
gui_flag = True # All test will run qgis in gui mode
#noinspection PyPep8Naming
QGIS_APP = QgsApplication(sys.argv, gui_flag)
# Make sure QGIS_PREFIX_PATH is set in your env if needed!
QGIS_APP.initQgis()
s = QGIS_APP.showSettings()
LOGGER.debug(s)
global PARENT # pylint: disable=W0603
if PARENT is None:
#noinspection PyPep8Naming
PARENT = QtGui.QWidget()
global CANVAS # pylint: disable=W0603
if CANVAS is None:
#noinspection PyPep8Naming
CANVAS = QgsMapCanvas(PARENT)
CANVAS.resize(QtCore.QSize(400, 400))
global IFACE # pylint: disable=W0603
if IFACE is None:
# QgisInterface is a stub implementation of the QGIS plugin interface
#noinspection PyPep8Naming
IFACE = QgisInterface(CANVAS)
return QGIS_APP, CANVAS, IFACE, PARENT

View File

@ -0,0 +1,12 @@
#!/bin/bash
LRELEASE=$1
LOCALES=$2
for LOCALE in ${LOCALES}
do
echo "Processing: ${LOCALE}.ts"
# Note we don't use pylupdate with qt .pro file approach as it is flakey
# about what is made available.
$LRELEASE i18n/${LOCALE}.ts
done

View File

@ -0,0 +1,56 @@
#!/bin/bash
LOCALES=$*
# Get newest .py files so we don't update strings unnecessarily
CHANGED_FILES=0
PYTHON_FILES=`find . -regex ".*\(ui\|py\)$" -type f`
for PYTHON_FILE in $PYTHON_FILES
do
CHANGED=$(stat -c %Y $PYTHON_FILE)
if [ ${CHANGED} -gt ${CHANGED_FILES} ]
then
CHANGED_FILES=${CHANGED}
fi
done
# Qt translation stuff
# for .ts file
UPDATE=false
for LOCALE in ${LOCALES}
do
TRANSLATION_FILE="i18n/$LOCALE.ts"
if [ ! -f ${TRANSLATION_FILE} ]
then
# Force translation string collection as we have a new language file
touch ${TRANSLATION_FILE}
UPDATE=true
break
fi
MODIFICATION_TIME=$(stat -c %Y ${TRANSLATION_FILE})
if [ ${CHANGED_FILES} -gt ${MODIFICATION_TIME} ]
then
# Force translation string collection as a .py file has been updated
UPDATE=true
break
fi
done
if [ ${UPDATE} == true ]
# retrieve all python files
then
echo ${PYTHON_FILES}
# update .ts
echo "Please provide translations by editing the translation files below:"
for LOCALE in ${LOCALES}
do
echo "i18n/"${LOCALE}".ts"
# Note we don't use pylupdate with qt .pro file approach as it is flakey
# about what is made available.
pylupdate4 -noobsolete ${PYTHON_FILES} -ts i18n/${LOCALE}.ts
done
else
echo "No need to edit any translation files (.ts) because no python files"
echo "has been updated since the last update translation. "
fi