diff --git a/docs/icgc.html b/docs/icgc.html
index 7d82f06..a3451b5 100644
--- a/docs/icgc.html
+++ b/docs/icgc.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/online-ca.html b/docs/online-ca.html
index bde4678..4b7830f 100644
--- a/docs/online-ca.html
+++ b/docs/online-ca.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/online-es.html b/docs/online-es.html
index 2100e2b..c39ab7b 100644
--- a/docs/online-es.html
+++ b/docs/online-es.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/online.html b/docs/online.html
index 7b27aae..60bc365 100644
--- a/docs/online.html
+++ b/docs/online.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/plugin_github.html b/docs/plugin_github.html
index 835701a..ee5a462 100644
--- a/docs/plugin_github.html
+++ b/docs/plugin_github.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/plugin_icgc.html b/docs/plugin_icgc.html
index c886a76..93e6ff8 100644
--- a/docs/plugin_icgc.html
+++ b/docs/plugin_icgc.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/plugin_issues.html b/docs/plugin_issues.html
index be0404e..0ea6862 100644
--- a/docs/plugin_issues.html
+++ b/docs/plugin_issues.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/docs/plugin_qgis.html b/docs/plugin_qgis.html
index 59818b3..6f477a6 100644
--- a/docs/plugin_qgis.html
+++ b/docs/plugin_qgis.html
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/geofinder3/geofinder.py b/geofinder3/geofinder.py
index d0ad8c2..482d0d3 100644
--- a/geofinder3/geofinder.py
+++ b/geofinder3/geofinder.py
@@ -245,24 +245,45 @@ def get_cadastral_ref(self, text):
return cadastral_ref
- def find_rectangle_coordinates(self, west, north, east, south, epsg):
+ def find_rectangle_coordinates(self, west, north, east, south, epsg, add_rect_if_empty=True, show_log=True):
""" Returns a list with a dictionary with the coordinates of the rectangle """
- print(u"Rectangle: %s %s %s %s EPSG:%s" % (west, north, east, south, epsg))
+ if show_log:
+ print(u"Rectangle: %s %s %s %s EPSG:%s" % (west, north, east, south, epsg))
+
+ # Find central point (exclude last result: "Point x, y")
+ central_x = west + (west-east) / 2.0
+ central_y = south + (north-south) / 2.0
dicts_list = [{
- 'nom':'Rectangle (%s %s %s %s)' % (west, north, east, south),
'west': float(west),
'north': float(north),
'east': float(east),
'south': float(south),
- 'epsg': int(epsg)
- }]
+ **point_dict
+ } for point_dict in self.find_point_coordinate(central_x, central_y, epsg, add_point_if_empty=False)]
+ # If not results, inject an entry with point
+ if not dicts_list and add_rect_if_empty:
+ dicts_list.append({
+ 'nom':'Rectangle (%s %s %s %s)' % (west, north, east, south),
+ 'idTipus': u'',
+ 'nomTipus': u'',
+ 'nomMunicipi': u'',
+ 'nomComarca': u'',
+ 'x': central_x,
+ 'y': central_y,
+ 'west': float(west),
+ 'north': float(north),
+ 'east': float(east),
+ 'south': float(south),
+ 'epsg': int(epsg)
+ })
return dicts_list
- def find_point_coordinate(self, x, y, epsg):
+ def find_point_coordinate(self, x, y, epsg, add_point_if_empty=True, show_log=True):
""" Returns a list of dictionaries with the sites found at the indicated point """
- print(u"Coordinate: %s %s EPSG:%s" % (x, y, epsg))
+ if show_log:
+ print(u"Coordinate: %s %s EPSG:%s" % (x, y, epsg))
# We convert the coordinates to ETRS89 UTM31N to do the query
nom = "Point: %s %s (EPSG:%s)" % (x, y, epsg),
@@ -292,13 +313,32 @@ def find_point_coordinate(self, x, y, epsg):
'y': y,
'epsg': epsg
} for label_adrecaInversa, res_dict in res_tuple_list if res_dict and label_adrecaInversa == 'adrecaInversa']
+ # If not results, inject an entry with point
+ if not dicts_list and add_point_if_empty:
+ dicts_list.append({
+ 'nom': "Punt %s %s" % (x, y),
+ 'idTipus': u'',
+ 'nomTipus': u'',
+ 'nomMunicipi': u'',
+ 'nomComarca': u'',
+ 'x': x,
+ 'y': y,
+ 'epsg': epsg
+ })
return dicts_list
def transform_point(self, x, y, source_epsg, destination_epsg):
+ # EN GDAL 3 al convertir una coordenada a WGS84 gira x<->y per evitar-ho canviar WGS84 oer CRS84!!
source_crs = osr.SpatialReference()
source_crs.ImportFromEPSG(int(source_epsg))
+ if source_epsg == 4326:
+ source_crs.SetWellKnownGeogCS("CRS84")
+
destination_crs = osr.SpatialReference()
destination_crs.ImportFromEPSG(int(destination_epsg))
+ if destination_epsg == 4326:
+ destination_crs.SetWellKnownGeogCS("CRS84")
+
ct = osr.CoordinateTransformation(source_crs, destination_crs)
destination_x, destination_y, _h = ct.TransformPoint(x, y)
return destination_x, destination_y
@@ -542,7 +582,7 @@ def find_placename(self, text):
def is_rectangle(self, dict_list):
""" Check if dict_list is of rectangle type """
- return len(dict_list) == 1 and dict_list[0]['nom'].startswith("Rectangle")
+ return len(dict_list) == 1 and dict_list[0].get("west", None)
def get_rectangle(self, dict_list):
""" Returns rectangle coordinates of dict_list type rectangle.
diff --git a/i18n/openicgc_ca.ts b/i18n/openicgc_ca.ts
index d78bb1c..872cd53 100644
--- a/i18n/openicgc_ca.ts
+++ b/i18n/openicgc_ca.ts
@@ -4,42 +4,42 @@
OpenICGC
-
+
Cerca espacial
-
+
Cercar
-
+
Mapes de fons
-
+
Esborrar mapes de fons
-
+
Transparència
-
+
Recarregar Open ICGC
-
+
Error, localització sense coordenades
-
+
-
+
Sèries temporals
-
+
Sobre Open ICGC
-
+
Ajuda
-
+
Seleccionar carpeta de descàrregues
-
+
Nom
-
+
Tipus
-
+
Municipi
-
+
Comarca
-
+
Municipis
-
+
Comarques
-
+
Províncies
-
+
Ortofoto color
-
+
[ST] Ortofoto color
-
+
Ortofoto infraroja
-
+
[ST] Ortofoto infraroja
-
+
Descàrregues
-
+
Obrir carpeta de descàrregues
-
+
Estil de pintat de les capes seleccionades
-
+
Desaturació de capa ràster
-
+
Referència %s
-
+
Descarregar àrea de mapa
-
+
Mida mínima de descàrrega no aconseguida (%d m costat)
-
+
Àrea màxima de descàrrega sobrepassada (%s m%s)
-
+
Canviar estil de geoPackage / base de dades
-
+
Error descarregant el fitxer o la selecció està fora de l'àrea de referència
-
+
Cal escriure algun text
-
+
-
+
-
+
-
+
Error, no s'ha trobat el producte %s per descarregar
-
+
Cercar topònims i adreces
-
+
Àrea
-
+
Comarca
-
+
Catalunya
-
+
Dades disponibles
-
+
Eina de descàrrega
-
+
Descarregar punt
-
+
-
+
-
+
Seleccionat:
-
+
Talls cartogràfics
-
+
Selecciona una àrea
-
+
Selecciona un municipi
-
+
Selecciona una comarca
-
+
Desconegut, servei no accessible
-
+
Llista de productes disponibles
-
+
-
+
Barra d'eines d'Open ICGC
-
+
Afegir ressaltat d'alçades
-
+
Ressaltat d'alçades
-
+
Atenció:
-
+
Alertes de la versió de QGIS
-
+
Descarregar plugin
-
+
Actualització
disponible: %s
-
+
Pots modificar la brillantor de la capa "Ressaltat d'alçades" per ajustar la visualització a la teva capa de fons
-
+
Tall %s
-
+
Repositori de connectors de QGIS
-
+
Repositori de codi
-
+
Reportar una incidència
-
+
Envia'ns un email
-
+
-
+
@@ -520,546 +520,546 @@ Do you want change the project coordinate system to EPSG 25831?
Vols canviar el sistema de coordenades del projecte a EPSG 25831?
-
+
Novetats
-
+
Web de l'Institut Cartogràfic i Geològic de Catalunya
-
+
Ortofoto color 25cm 1:2.500
-
+
Ortofoto color 50cm 1:5.000
-
+
Ortofoto color 2.5m 1:25.000
-
+
Ortofoto infraroja 25cm 1:2.500
-
+
Ortofoto infraroja 50cm 1:5.000
-
+
Ortofoto infraroja 2.5m 1:25.000
-
+
Mapa topogràfic 1:25.000
-
+
Mapa topogràfic 1:50.000
-
+
Mapa topogràfic 1:1.00.000
-
+
Mapa topogràfic 1:250.000
-
+
Mapa topogràfic 1:500.000
-
+
Mapa topogràfic 1:1.000.000
-
+
Mapa topogràfic 1:2.000.000
-
+
Cartografia topogràfica 1:1.000
-
+
Referencial topogràfic territorial
-
+
Mapa de cobertes del sòl
-
+
Model d'elevacions del terreny 2m
-
+
Model d'elevacions del terreny 5m
-
+
Mapa geològic 1:250.000
-
+
%s dades vectorials
-
+
%s dades ràster
-
+
Referencial topogràfic territorial 3D
-
+
NDVI color (sèrie temporal)
-
+
[ST] NDVI color
-
+
NDVI (sèrie temporal)
-
+
[ST] NDVI
-
+
El tipus de fitxer %s no està suportat per QGIS
Vols intentar obrir el fitxer descarregat amb un visor extern?
-
+
Ortofoto color %s (provisional)
-
+
Ortofoto color %s (rectificació sense correccions)
-
+
Ortofoto color %s (sèrie temporal)
-
+
Ortofoto color (sèrie anual)
-
+
Ortofoto color satèl·lit (sèrie mensual)
-
+
Ortofoto infraroja %s (provisional)
-
+
Ortofoto infraroja %s (rectificació sense correccions)
-
+
Ortofoto infraroja %s (sèrie temporal)
-
+
Ortofoto infraroja (sèrie anual)
-
+
Ortofoto infraroja satèl·lit (sèrie mensual)
-
+
Ombrejat de capa MET
-
+
L'àrea seleccionada és fora de Catalunya
-
+
S'ha de seleccionar una capa de MET
-
+
Es pot modificar l'angle del sol en la simbologia de la capa
-
+
[SA] Ortofoto color
-
+
[SM] Ortofoto color satèl·lit
-
+
[SA] Ortofoto infraroja
-
+
[SM] Ortofoto infraroja satèl·lit
-
+
Mapa geològic 1:50.000
-
+
Caps de municipi
-
+
Vegueries
-
+
Divisions administratives
-
+
Referencial topogràfic territorial %s (sèrie temporal)
-
+
[ST] Referencial topogràfic territorial
-
+
Divisions administratives (Piràmide ràster)
-
+
No s'ha pogut obrir l'arxiu descarregat
-
+
ràster
-
+
vector
-
+
Fototeca
-
+
Fotogrames
-
+
Foto: %s
-
+
Consulta fotos: %s
-
+
Cercar fotogrames
-
+
Coord %s %s
-
+
Existeix un cerca de fotogrames prèvia. Vols tancar-la?
-
+
Cercar fotogrames interactivament
-
+
Cercar fotogrames per coordenada
-
+
Eina de cerca de fotogrames
-
+
Selecciona un punt
-
+
Introdueix valors x y en el sistema de coordenades del projecte o afegeix el corresponent codi EPSG en el següent format:
"429393.19 4580194.65" o "429393.19 4580194.65 EPSG:25831" o "EPSG:25831 429393.19 4580194.65"
-
+
Codi de vol
-
+
Data de vol
-
+
Any de vol
-
+
Arxiu d'imatge
-
+
Amplada d'imatge
-
+
Alçada d'imatge
-
+
Canals d'imatge
-
+
Bits PPC d'imatge
-
+
Tipus de color
-
+
Passada
-
+
Càmera
-
+
Distància focal
-
+
Mida de píxel
-
+
Escala
-
+
Alçada de vol
-
+
Alçada mitja del terra
-
+
Tipus de vista
-
+
Nord
-
+
Est
-
+
Codi EPSG
-
+
Omega
-
+
Phi
-
+
Kappa
-
+
Fotograma dins la passada
-
+
Espanya
-
+
Topogràfic IGN
-
+
Ortofoto PNOA
-
+
Andorra
-
+
Andorra topogràfic 1:25.000 1989
-
+
Andorra topogràfic 1:50.000 1987
-
+
Andorra ortofoto 1:5.000 2003
-
+
Andorra ortofoto infraroja 1:5.000 2003
-
+
Andorra ortofoto 1:500-1.000 20cm 2003
-
+
Mon
-
+
Nasa blue marble
-
+
Mida mínima de descàrrega no aconseguida (%d px costat)
-
+
Àrea màxima de descàrrega sobrepassada (%s px%s)
-
+
Coordenades de l'àrea
-
+
-
+
Referencial topogràfic territorial volum
-
+
Polígons selecionats en una capa
-
+
Cal activar una capa vectorial amb un o més polígons seleccionats
-
+
-
+
El polígons tenen massa punts: %d màxim %d
-
+
Mapa topogràfic (piràmide topogràfica)
-
+
Mapa de cobertes del sòl (sèrie temporal)
-
+
[ST] Mapa de cobertes del sòl
-
+
Model d'elevacions del terreny %s
-
+
Format de coordenades incorrecte
-
+
Piràmide Instamaps
-
+
Cadastre
-
+
Mapa geològic 1:25.000 (GT I)
-
+
Mapa geològic per a la prevenció dels riscos geològics 1:25.000 (GT VI)
-
+
Reportar error de fotograma
-
-
- Descripció del problema:
-
-
-
+
Intentarem corregir-ho el més aviat possible
-
+
-
+
Cal seleccionar un fotograma
+
+
+
+ Mantenir escala
+
+
+
+
+ Anaglif
+
+
+
+
+ Estèreo invertit
+
+
+
+
+ Analògic
+
+
+
+
+ Fotograma anaglif central
+
+
+
+
+ [SA] Fotograma anaglif central
+
+
+
+
+ Fotograma rectificat central (sèrie anual)
+
+
+
+
+ [SA] Fotograma rectificat central
+
+
+
+
+ Fotograma central (sèrie anual)
+
+
+
+
+ [SA] Fotograma central
+
+
+
+
+ Fotograma anaglif central %s (sèrie anual)
+
+
+
+
+ Mostra només el fotograma més centrat en la vista mapa, pots apropar-te per obtenir una navegació contínua. L'any actual pot no tenir una cobertura completa
+
+
+
+
+ Foto: %s
+Codi de vol: %s
+Data: %s
+Resolució: %.2fm
+
+Descripció del problema:
+
+
+
+
+ Cercar fotogrames per nom
+
+
+
+
+ Nom de fotograma:
+
PhotoSearchSelectionDialog
-
+
Rang d'anys
-
+
Resolució
-
+
Totes
-
+
Molt alta (<15 cm/px)
-
+
Alta (aprox. 25 cm/px)
-
+
Mitja (aprox. 50 cm/px)
-
+
Baixa (> 60 cm/px)
-
+
Fotograma
-
+
Data
-
+
m/px
-
+
Informació
-
+
Any: %s
-
+
Fotogrames: %s
-
+
Descarregar
-
+
Sol·licitar certificat
-
+
Reportar error en fotograma
-
+
Visualitzar
-
+
Sol·licitar
certificat
-
+
Sol·licitar
escaneig
-
+
Sol·licitar escaneig
-
+
Ajustar
brillantor
-
+
Ajustar brillantor
-
+
No disponible o perdut
-
+
No publicable
-
+
Escaneig requerit
-
+
Disponible
-
+
Nota: La ubicació dels fotogrames és aproximada
-
+
+
+
+
+ Fotograma rectificat "al vol"
+
+
+
+
+ Fotograma anaglif "al vol"
+
+
+
+
+ Tipus de vista
+
+
+
+
+ Paral·laxi: %+d%%
+
+
+
+
+ Estèreo invertit
+
+
+
+
+ Fotograma orientació nominal
+
diff --git a/i18n/openicgc_es.ts b/i18n/openicgc_es.ts
index 0f6a0c8..af735fa 100644
--- a/i18n/openicgc_es.ts
+++ b/i18n/openicgc_es.ts
@@ -4,42 +4,42 @@
OpenICGC
-
+
Búsqueda espacial
-
+
Buscar
-
+
Mapas de fondo
-
+
Borrar mapas de fondo
-
+
Trasparencia
-
+
Recargar Open ICGC
-
+
Error, localización sin coordenadas
-
+
-
+
Series temporales
-
+
Acerca de Open ICGC
-
+
Ayuda
-
+
Selección de carpeta de descargas
-
+
Nombre
-
+
Tipo
-
+
Municipio
-
+
Comarca
-
+
Municipios
-
+
Comarcas
-
+
Provincias
-
+
Ortofoto color
-
+
[ST] Ortofoto color
-
+
Ortofoto infrarroja
-
+
[ST] Ortofoto infrarroja
-
+
Descargas
-
+
Abrir carpeta de descargas
-
+
Estilo de pintado de las capas seleccionadas
-
+
Desaturar capa raster
-
+
Referencia %s
-
+
Descargar área de mapa
-
+
Tamaño mínimo de descarga no alcanzado (%d m por lado)
-
+
Máxima área de descarga alcanzada (%s m%s)
-
+
Cambiar estilo de geoPackage / base de datos
-
+
Error descargando el fitchero o la selección está fuera del área de referencia
-
+
Debes escribir algun texto
-
+
-
+
-
+
-
+
Error, no se ha encontrado el producto %s a descargar
-
+
Buscar topónimos y direcciones
-
+
Área
-
+
Comarca
-
+
Cataluña
-
+
Datos disponibles
-
+
Herramienta de descarga
-
+
Descarga puntual
-
+
-
+
-
+
Seleccionado:
-
+
Cortes cartográficos
-
+
Selecciona un área
-
+
Selecciona un municipio
-
+
Selecciona una comarca
-
+
Desconocido, servicio no accesible
-
+
Lista de productos disponibles
-
+
-
+
Barra de herramientas de Open ICGC
-
+
Añadir resaltado de alturas
-
+
Resaltado de alturas
-
+
Atención:
-
+
Alertas de la versión de QGIS
-
+
Descargar plugin
-
+
Actualización
disponible: v%s
-
+
Puedes modificar el brillo de la capa "Resaltado de alturas" para ajustar la visualización a tu capa de fondo
-
+
Corte %s
-
+
Repositorio de conectores de QGIS
-
+
Repositorio de código
-
+
Reportar una incidencia
-
+
Envíanos un email
-
+
-
+
@@ -520,551 +520,551 @@ Do you want change the project coordinate system to EPSG 25831?
¿Quieres cambiar el sistema de coordenadas del projecto a EPSG 25831?
-
+
Novedades
-
+
Web del Instituto Cartográfico y Geológico de Cataluña
-
+
Ortofoto color 25cm 1:2.500
-
+
Ortofoto color 50cm 1:5.000
-
+
Ortofoto color 2.5m 1:25.000
-
+
Ortofoto infrarroja 25cm 1:2.500
-
+
Ortofoto infrarroja 50cm 1:5.000
-
+
Ortofoto infrarroja 2.5m 1:25.000
-
+
Mapa topográfico 1:25.000
-
+
Mapa topográfico 1:50.000
-
+
Mapa topográfico 1:100.000
-
+
Mapa topográfico 1:250.000
-
+
Mapa topográfico 1:500.000
-
+
Mapa topográfico 1:1.000.000
-
+
Mapa topográfico 1:2.000.000
-
+
Cartografía topográfica 1:1.000
-
+
Referencial topográfico territorial
-
+
Mapa de cubiertas del suelo
-
+
Modelo de elevaciones del terreno 2m
-
+
Modelo de elevaciones del terreno 5m
-
+
Mapa geológico 1:250.000
-
+
%s datos vectoriales
-
+
%s datos ráster
-
+
Mapa geológico para la prevención de los riesgos geológicos 1:25.000 (GT VI)
-
+
Referencial topográfico territorial 3D
-
+
NDVI color (serie temporal)
-
+
[ST] NDVI color
-
+
NDVI (serie temporal)
-
+
[ST] NDVI
-
+
El tipo de fichero %s no está soportado por QGIS
¿Quieres intentar abrir el fichero descargado en un visor externo?
-
+
Ortofoto color %s (provisional)
-
+
Ortofoto color %s (rectificación sin correcciones)
-
+
Ortofoto color %s (serie temporal)
-
+
Ortofoto color (serie anual)
-
+
Ortofoto color satélite (serie mensual)
-
+
Ortofoto infrarroja %s (provisional)
-
+
Ortofoto infrarroja %s (rectificación sin correcciones)
-
+
Ortofoto infrarroja %s (serie temporal)
-
+
Ortofoto infrarroja %s (serie anual)
-
+
Ortofoto infrarroja setélite (serie mensual)
-
+
Sombreado de capa MET
-
+
El área seleccionada se encuentra fuera de Cataluña
-
+
Se ha de seleccionar una capa MET
-
+
Se puede modificar el ángulo del sol desde la simbología de la capa
-
+
[SA] Ortofoto color
-
+
[SM] Ortofoto color satélite
-
+
[SA] Ortofoto infrarroja
-
+
[SM] Ortofoto infrarroja satélite
-
+
Mapa geológico 1:50.000
-
+
Capitales de municipio
-
+
Veguerías
-
+
Divisiones administrativas
-
+
Referencial topográfico territorial %s (Serie temporal)
-
+
[ST] Referencial topográfico territorial
-
+
Divisiones administrativas (pirámide raster)
-
+
No se ha podido abrir el archivo descargado
-
+
raster
-
+
vector
-
+
Fototeca
-
+
Fotogramas
-
+
Foto: %s
-
+
Consulta fotogramas: %s
-
+
Buscar fotogramas
-
+
Coord %s %s
-
+
Existe una búsqueda de fotogramas previa. ¿Quieres cerrarla?
-
+
Buscar fotogramas interactivamente
-
+
Buscar fotogramas por coordenada
-
+
Herramienta de búsqueda de fotogramas
-
+
Selecciona un punto
-
+
Introduce valores x y en el sistema de coordenadas del proyecto o añade el correspondiente código EPSG en el siguiente formato:
"429393.19 4580194.65" o "429393.19 4580194.65 EPSG:25831" o "EPSG:25831 429393.19 4580194.65"
-
+
Código de vuelo
-
+
Fecha de vuelo
-
+
Año de vuelo
-
+
Archivo de imagen
-
+
Anchura de imagen
-
+
Altura de imagen
-
+
Canales de imagen
-
+
Bits PPC de imagen
-
+
Tipo de color
-
+
Pasada
-
+
Cámara
-
+
Distancia focal
-
+
Tamaño de píxel
-
+
Escala
-
+
Altura de vuelo
-
+
Altura media en tierra
-
+
Tipo de vista
-
+
Norte
-
+
Este
-
+
Código EPSG
-
+
Omega
-
+
Phi
-
+
Kappa
-
+
Fotograma dentro de pasada
-
+
España
-
+
Topográfico IGN
-
+
Ortofoto PNOA
-
+
Andorra
-
+
Andorra topográfico 1:25.000 1989
-
+
Andorra topográfico 1:50.000 1987
-
+
Andorra ortofoto 1:5.000 2003
-
+
Andorra ortofoto infrarroja 1:5.000 2003
-
+
Andorra ortofoto 1:500-1.000 20cm 2008
-
+
Mundo
-
+
NASA blue marble
-
+
Tamaño mínimo de descarga no alcanzado (%d px por lado)
-
+
Máxima área de descarga alcanzada (%s px%s)
-
+
Coordenadas de área
-
+
"EPSG:25831 429393.19 4580194.65 429493.19 4580294.65"
-
+
Referencial topográfico territorial volumen
-
+
Polígonos seleccionados en una capa
-
+
Es necesario activar una capa vectorial com uno o más polígonos seleccionados
-
+
-
+
Los polígonos tienen demasiados puntos: %d máximo %d
-
+
Mapa topográfico (pirámide topográfica)
-
+
Mapa de cubiertas del suelo (serie temporal)
-
+
[ST] Mapa de cubiertas del suelo
-
+
Modelo de elevaciones del terreno %s
-
+
Formato de coordenadas incorrecto
-
+
Pirámide Instamaps
-
+
Catastro
-
+
Mapa geológico 1:25.000 (GT I)
-
+
Reportar error de fotograma
-
-
- Descripción del problema:
-
-
-
+
Intentaremos corregirlo lo antes posible
-
+
-
+
Se debe seleccionar un fotograma
+
+
+
+ Mantener escala
+
+
+
+
+ Anaglifo
+
+
+
+
+ Estéreo invertido
+
+
+
+
+ Analógico
+
+
+
+
+ Fotograma anaglifo central
+
+
+
+
+ [SA] Fotograma anaglifo central
+
+
+
+
+ Fotograma rectificado central (serie anual)
+
+
+
+
+ [SA] Fotograma rectificado central
+
+
+
+
+ Fotograma central (serie anual)
+
+
+
+
+ [SA] Fotograma central
+
+
+
+
+ Fotograma anaglifo central %s (serie anual)
+
+
+
+
+ Muestra solo el fotograma más centrado en la vista mapa, puedes acercarte para obtener una navegació contínua. El año actual puede no tener una cobertura completa
+
+
+
+
+ Foto: %s
+Código de vuelo: %s
+Fecha: %s
+Resolución: %.2fm
+
+Descripción del problema:
+
+
+
+
+ Buscar fotogramas por nombre
+
+
+
+
+ Nombre de fotograma:
+
PhotoSearchSelectionDialog
-
+
Rango de años
-
+
Resolución
-
+
Todas
-
+
Muy alta (<15 cm/px)
-
+
Alta (aprox. 25 cm/px)
-
+
Media (aprox. 50 cm/px)
-
+
Baja (> 50 cm/px)
-
+
Fotograma
-
+
Fecha
-
+
m/px
-
+
Información
-
+
Año: %s
-
+
Fotogramas: %s
-
+
Descargar
-
+
Solicitar certificado
-
+
Reportar error en fotograma
-
+
Visualizar
-
+
Solicitar
certificado
-
+
Solicitar
escaneo
-
+
Solicitar escaneo
-
+
Ajustar
brillo
-
+
Ajustar brillo
-
+
No disponible o perdido
-
+
No publicable
-
+
Escaneo requerido
-
+
Disponible
-
+
Nota: La ubicación de los fotogramas es aproximada
-
+
+
+
+
+ Fotograma rectificado "al vuelo"
+
+
+
+
+ Fotograma anaglifo "al vuelo"
+
+
+
+
+ Tipo de vista
+
+
+
+
+
+
+
+
+
+ Estéreo invertido
+
+
+
+
+ Fotograma orientación nominal
+
diff --git a/images/search_name.pdn b/images/search_name.pdn
new file mode 100644
index 0000000..22e7ffb
Binary files /dev/null and b/images/search_name.pdn differ
diff --git a/images/search_name.png b/images/search_name.png
new file mode 100644
index 0000000..26ce46b
Binary files /dev/null and b/images/search_name.png differ
diff --git a/metadata.txt b/metadata.txt
index f7d7d0f..96072d5 100644
--- a/metadata.txt
+++ b/metadata.txt
@@ -11,15 +11,15 @@ description=ICGC Open data access
description_ca=Accés a dades obertes ICGC
description_es=Acceso a datos abiertos ICGC
about=Plugin for accessing open data published by the Cartographic and Geological Institute of Catalonia (Catalan mapping agency).
- Includes spatial toponymic searches, streets, roads, coordinates in different reference systems, load of base data layers and download different vectorial and raster products.
+ Includes spatial toponymic searches, streets, roads, coordinates in different reference systems, acces to historical photo library and load of base data layers and download different vectorial and raster products.
This plugin uses suds-py3, wsse libraries and land registry geo services.
---
Plugin per accedir a dades obertes de l'Institut Cartogràfic i Geològic de Catalunya.
- Inclou cerques espacials de topònims, carrers, carreteres, coordenades en diferents sistemes de referència, càrrega de dades de capes base i descàrrega de diferents productes vectorials i ràster.
+ Inclou cerques espacials de topònims, carrers, carreteres, coordenades en diferents sistemes de referència, càrrega de dades de capes base, accés a la fototeca històrica i descàrrega de diferents productes vectorials i ràster.
Aquest plugin utilitza les llibreries suds-py3, wsse i serveis web del cadastre.
---
Plugin para acceder a datos abiertos del Instituto Cartográfico y Geológico de Cataluña.
- Incluye búsquedas espaciales de topónimos, calles, carreteras, coordenadas en diferentes sistemas de referencia, carga datos de capas base y descarga de diferentes productos vectoriales y raster.
+ Incluye búsquedas espaciales de topónimos, calles, carreteras, coordenadas en diferentes sistemas de referencia, carga datos de capas base, acceso a la fototeca histórica y descarga de diferentes productos vectoriales y raster.
Este plugin utiliza las llibrerías suds-py3, wsse y servicios web del catastro.
tags=ICGC,Catalunya,Cataluña,Catalonia,find,search,site,place,street,road,WMS
icon=icon.png
@@ -28,8 +28,14 @@ email=qgis.openicgc@icgc.cat
qgisMinimumVersion=2.99
qgisMaximumVersion=3.99
-version=1.1.0
-changelog=v1.1.0 (2022-02-14)
+version=1.1.1
+changelog=v1.1.1 (2022-04-19)
+ - Added photo library rectification "on the fly"
+ - Added photo library stereo anaglyph generation "on the fly"
+ - Added anaglyph central photo layer
+ - Improved point and rectangle searches
+
+ v1.1.0 (2022-02-14)
- Added access to ICGC historical photo library (visualization and downloads)
- Added download geological map GT I and GT VI product
- Fixed timeline bars to skip one year when click on it
diff --git a/openicgc.py b/openicgc.py
index af24b4e..a2eba4f 100644
--- a/openicgc.py
+++ b/openicgc.py
@@ -17,10 +17,10 @@
*******************************************************************************
"""
-# Add a additional library folder to pythonpath
+# Add a additional library folder to pythonpath (for external libraries)
import os
import sys
-sys.path.append(os.path.join(os.path.dirname(__file__), "lib")) # Per la suds que ha de ser global...
+sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
# Import base libraries
import re
@@ -45,6 +45,7 @@
# Initialize Qt resources from file resources_rc.py
from . import resources_rc
+# Detect import relative mode (for release) or global import mode (for debug)
is_import_relative = os.path.exists(os.path.join(os.path.dirname(__file__), "qlib3"))
if is_import_relative:
# Import basic plugin functionalities
@@ -94,7 +95,11 @@
set_html_font_size = lambda text, size=9: ('%s' % (size, text.replace("\n", "
").replace(" ", " ")))
# Constants
-PHOTOLIB_WFS = "https://fototeca-connector.icgc.cat/" #"http://sedockersec01.icgc.local:80" #"http://seuatdlinux01:5000" "http://localhost:5000"
+PHOTOLIB_WFS_MAX_FEATURES = 1000
+PHOTOLIB_WFS = "https://fototeca-connector.icgc.cat/"
+#PHOTOLIB_WFS = "http://sedockersec01.icgc.local/"
+#PHOTOLIB_WFS = "http://seuatdlinux01.icgc.local/"
+#PHOTOLIB_WFS = "http://localhost:5000/"
PHOTOLIB_WMS = PHOTOLIB_WFS
@@ -398,7 +403,8 @@ def __init__(self, iface):
# We created a GeoFinder object that will allow us to perform spatial searches
self.geofinder = GeoFinder()
self.geofinder_dialog = GeoFinderDialog(self.geofinder, title=self.tr("Spatial search"),
- columns_list=[self.tr("Name"), self.tr("Type"), self.tr("Municipality"), self.tr("Region")])
+ columns_list=[self.tr("Name"), self.tr("Type"), self.tr("Municipality"), self.tr("Region")],
+ keep_scale_text=self.tr("Keep scale"))
# Initialize reference to PhotoSearchSelectionDialog
self.photo_search_dialog = None
@@ -448,6 +454,9 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
self.combobox.setFixedSize(QSize(250,24))
self.combobox.setEditable(True)
self.combobox.setToolTip(self.TOOLTIP_HELP)
+ self.combobox.addItems(self.get_setting_value("last_searches", []))
+ self.combobox.setCurrentText("")
+ self.combobox.setMaxVisibleItems(20)
self.combobox.activated.connect(self.run) # Press intro and select combo value
# Gets available Topo5k files to simulate WMS-T service
@@ -480,7 +489,12 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
ortoxpres_color_list = [(str(year), layer_id, layer_name) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "ortoxpres" and color != "irc"]
ortoxpres_color_year, ortoxpres_color_layer_id, ortoxpres_color_layer_name = ortoxpres_color_list[-1] if ortoxpres_color_list else (None, None, None)
ortoxpres_infrared_list = [(str(year), layer_id, layer_name) for layer_id, layer_name, ortho_type, color, year in historic_ortho_list if ortho_type == "ortoxpres" and color == "irc"]
- ortoxpres_infrared_year, ortoxpres_infrared_layer_id, ortoxpres_infrared_layer_name = ortoxpres_infrared_list[-1] if ortoxpres_infrared_list else (None, None, None)
+ ortoxpres_infrared_year, ortoxpres_infrared_layer_id, ortoxpres_infrared_layer_name = ortoxpres_infrared_list[-1] if ortoxpres_infrared_list else (None, None, None)
+
+ # Gets anaglyph fotograms. Last year can not have full photograms coverage, we select previous year as default
+ photolib_wms_url = PHOTOLIB_WMS
+ photolib_time_series_list, photolib_current_time = self.layers.get_wms_t_time_series(photolib_wms_url, "anaglif_central")
+ photolib_current_time = str(int(photolib_current_time) - 1) if photolib_current_time else photolib_current_time
# Gets available download source data
fme_services_list = get_services()
@@ -497,8 +511,7 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
# Add new toolbar with plugin options (using pluginbase functions)
style = self.iface.mainWindow().style()
- self.toolbar = self.gui.configure_toolbar(self.tr("Open ICGC Toolbar") + (" lite" if self.lite else ""),
- [
+ self.toolbar = self.gui.configure_toolbar(self.tr("Open ICGC Toolbar") + (" lite" if self.lite else ""), [
self.tr("Find"), # Label text
self.combobox, # Editable combobox
(self.tr("Find place names and adresses"), self.run, QIcon(":/lib/qlib3/geofinderdialog/images/geofinder.png")), # Action button
@@ -511,7 +524,7 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
QIcon(":/lib/qlib3/base/images/cat_topo250k.png")),
(self.tr("Territorial topographic referential"), None, QIcon(":/lib/qlib3/base/images/cat_topo5k.png"), enable_http_files, [
(self.tr("Territorial topographic referential %s (temporal serie)") % topo5k_year,
- lambda _checked, topo5k_year=topo5k_year:self.add_wms_t_layer(self.tr("[TS] Territorial topographic referential"), None, topo5k_year, "default", "image/jpeg", topo5k_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, resampling_bilinear=True, set_current=True),
+ lambda _checked, topo5k_year=topo5k_year:self.add_wms_t_layer(self.tr("[TS] Territorial topographic referential"), None, topo5k_year, None, "default", "image/jpeg", topo5k_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, resampling_bilinear=True, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_topo5k.png"))
for topo5k_year, _url in topo5k_time_series_list]),
(self.tr("Topographic map 1:50,000"),
@@ -549,7 +562,7 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
lambda _checked:self.layers.add_wms_layer(self.tr("Geological map 1:250,000"), "https://geoserveis.icgc.cat/mgc250mv2(raster)/wms/service", ["0"], ["default"], "image/png", 25831, "referer=ICGC", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_geo250k.png")),
(self.tr("Land cover map (temporal serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[TS] Land cover map"), "https://geoserveis.icgc.cat/servei/catalunya/cobertes-sol/wms", "serie_temporal", "default", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[TS] Land cover map"), "https://geoserveis.icgc.cat/servei/catalunya/cobertes-sol/wms", "serie_temporal", None, "default", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_landcover.png")),
"---",
] + [(self.tr("Digital Terrain Model %s") % dtm_name,
@@ -559,10 +572,10 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
) for dtm_name, dtm_url in dtm_list] + [
"---",
(self.tr("NDVI color (temporal serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[TS] NDVI color"), "https://geoserveis.icgc.cat/servei/catalunya/ndvi/wms", "ndvi_serie_anual_color", "default", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[TS] NDVI color"), "https://geoserveis.icgc.cat/servei/catalunya/ndvi/wms", "ndvi_serie_anual_color", None, "default", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_landcover.png")),
(self.tr("NDVI (temporal serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[TS] NDVI"), None, ndvi_current_time, "default", "image/jpeg", ndvi_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[TS] NDVI"), None, ndvi_current_time, None, "default", "image/jpeg", ndvi_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_shadows.png"), enable_http_files),
"---",
(self.tr("Color orthophoto"), None, QIcon(":/lib/qlib3/base/images/cat_ortho5k.png"), [
@@ -577,16 +590,16 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
"---",
] + [
(self.tr("Color orthophoto %s (temporal serie)") % ortho_year,
- lambda _checked,layer_id=layer_id:self.add_wms_t_layer(self.tr("[TS] Color orthophoto"), ortho_wms_url, layer_id, "default", "image/jpeg", ortho_color_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked,layer_id=layer_id:self.add_wms_t_layer(self.tr("[TS] Color orthophoto"), ortho_wms_url, layer_id, None, "default", "image/jpeg", ortho_color_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png")) for ortho_year, layer_id in reversed(ortho_color_time_series_list)
] + [
"---",
(self.tr("Color orthophoto (annual serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[AS] Color orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/orto-territorial/wms", "ortofoto_color_serie_anual", "", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[AS] Color orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/orto-territorial/wms", "ortofoto_color_serie_anual", None, "", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png")),
]),
(self.tr("Satellite color orthophoto (monthly serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[MS] Satellite color orthophoto"), "https://geoserveis.icgc.cat/icgc_sentinel2/wms/service", "sen2rgb", "", "image/jpeg", None, 25831, "referer=ICGC", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[MS] Satellite color orthophoto"), "https://geoserveis.icgc.cat/icgc_sentinel2/wms/service", "sen2rgb", None, "", "image/jpeg", None, 25831, "referer=ICGC", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png")),
"---",
(self.tr("Infrared orthophoto"), None, QIcon(":/lib/qlib3/base/images/cat_ortho5ki.png"), [
@@ -601,17 +614,31 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
"---"
] + [
(self.tr("Infrared orthophoto %s (temporal serie)") % ortho_year,
- lambda _checked,layer_id=layer_id:self.add_wms_t_layer(self.tr("[TS] Infrared orthophoto"), ortho_wms_url, layer_id, "default", "image/jpeg", ortho_infrared_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked,layer_id=layer_id:self.add_wms_t_layer(self.tr("[TS] Infrared orthophoto"), ortho_wms_url, layer_id, None, "default", "image/jpeg", ortho_infrared_time_series_list, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5k.png")) for ortho_year, layer_id in reversed(ortho_infrared_time_series_list)
] + [
"---",
(self.tr("Infrared orthophoto (annual serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[AS] Infrared orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/orto-territorial/wms", "ortofoto_infraroig_serie_anual", "", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[AS] Infrared orthophoto"), "https://geoserveis.icgc.cat/servei/catalunya/orto-territorial/wms", "ortofoto_infraroig_serie_anual", None, "", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5kbw.png")),
]),
(self.tr("Satellite infrared orthophoto (monthly serie)"),
- lambda _checked:self.add_wms_t_layer(self.tr("[MS] Satellite infared orthophoto"), "https://geoserveis.icgc.cat/icgc_sentinel2/wms/service", "sen2irc", "default", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
+ lambda _checked:self.add_wms_t_layer(self.tr("[MS] Satellite infared orthophoto"), "https://geoserveis.icgc.cat/icgc_sentinel2/wms/service", "sen2irc", None, "default", "image/jpeg", None, 25831, "referer=ICGC&bgcolor=0x000000", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=True),
QIcon(":/lib/qlib3/base/images/cat_ortho5ki.png")),
+ "---",
+ (self.tr("Centered anaglyph photogram"), None, QIcon(":/lib/qlib3/photosearchselectiondialog/images/stereo_preview.png"), [
+ (self.tr("Centered anaglyph photogram %s (annual serie)") % anaglyph_year,
+ lambda _checked,anaglyph_year=anaglyph_year,anaglyph_layer=anaglyph_layer:self.add_wms_t_layer(self.tr("[AS] Centered anaglyph phootogram"), photolib_wms_url, anaglyph_layer, str(anaglyph_year), "central,100,false", "image/png", None, 25831, "referer=ICGC", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=False),
+ QIcon(":/lib/qlib3/photosearchselectiondialog/images/stereo_preview.png")) for anaglyph_year, anaglyph_layer in reversed(photolib_time_series_list)
+ ])
+ ] + ([
+ (self.tr("Centered rectified photogram (annual serie)"),
+ lambda _checked:self.add_wms_t_layer(self.tr("[AS] Centered rectified photogram"), photolib_wms_url, "ortoxpres_central", photolib_current_time, "central", "image/png", None, 25831, "referer=ICGC", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=False),
+ QIcon(":/lib/qlib3/photosearchselectiondialog/images/rectified_preview.png")),
+ (self.tr("Centered photogram (annual serie)"),
+ lambda _checked:self.add_wms_t_layer(self.tr("[AS] Centered photogram"), photolib_wms_url, "foto_central", photolib_current_time, "central", "image/png", None, 25831, "referer=ICGC", self.backgroup_map_group_name, only_one_map_on_group=False, set_current=False),
+ QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_preview.png")),
+ ] if self.debug_mode else []) + [
"---"
] + ([
(self.tr("Instamaps pyramid"),
@@ -655,7 +682,7 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
QIcon(":/lib/qlib3/base/images/world.png")),
]),
"---",
- ] if self.extra_countries else []) + [
+ ] if self.extra_countries or self.debug_mode else []) + [
(self.tr("Delete background maps"), lambda _checked:self.legend.empty_group_by_name(self.backgroup_map_group_name),
QIcon(":/lib/qlib3/base/images/wms_remove.png"), True, False, "delete_background")
]),
@@ -666,7 +693,8 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
] + ([
(self.tr("Search photograms"), (self.enable_search_photos, self.pair_photo_search_checks), QIcon(":/plugins/openicgc/images/search.png"), True, True, "photo_search", [
(self.tr("Search photograms interactively"), (self.enable_search_photos, self.pair_photo_search_checks), QIcon(":/plugins/openicgc/images/search.png"), True, True, "photo_search_2"),
- (self.tr("Search photograms by coordinates"), lambda _checked:self.search_photos(), QIcon(":/plugins/openicgc/images/search_coord.png"), True, False),
+ (self.tr("Search photograms by coordinates"), lambda _checked:self.search_photos_by_point(), QIcon(":/plugins/openicgc/images/search_coord.png"), True, False),
+ (self.tr("Search photograms by name"), lambda _checked:self.search_photos_by_name(), QIcon(":/plugins/openicgc/images/search_name.png"), True, False),
]),
(self.tr("Download tool"), self.disable_download_global_check, QIcon(":/plugins/openicgc/images/download_area.png"), True, True, "download",
download_vector_submenu + ["---"] + download_raster_submenu + [
@@ -682,6 +710,9 @@ def initGui(self, check_qgis_updates=True, check_icgc_updates=False):
(self.tr("Desaturate raster layer"),
lambda _checked:self.layers.set_saturation(self.iface.mapCanvas().currentLayer(), -100, True) if type(self.iface.mapCanvas().currentLayer()) is QgsRasterLayer else None,
QIcon(":/lib/qlib3/base/images/desaturate.png")),
+ (self.tr("Anaglyph"),
+ lambda _checked:self.tools.show_anaglyph_dialog(self.iface.mapCanvas().currentLayer(), self.tr("Anaglyph"), self.tr("Anaglyph"), self.tr("Inverted stereo")),
+ QIcon(":/lib/qlib3/photosearchselectiondialog/images/stereo_preview.png")),
(self.tr("Shading DTM layer"),
self.shading_dtm,
QIcon(":/lib/qlib3/base/images/cat_shadows.png")),
@@ -872,11 +903,14 @@ def pair_photo_search_checks(self, status):
def run(self, checked): # I add checked param, because the mapping of the signal triggered passes a parameter
""" Basic plugin call, which reads the text of the combobox and the search for the different web services available """
self.find(self.combobox.currentText())
+ # Save last searches in persistent app settings
+ searches_list = [self.combobox.itemText(i) for i in range(self.combobox.count())][-self.combobox.maxVisibleItems():]
+ self.set_setting_value("last_searches", searches_list)
- def add_wms_t_layer(self, layer_name, url, layer_id, style, image_format, time_series_list=None, epsg=None, extra_tags="", group_name="", group_pos=None, only_one_map_on_group=False, collapsed=True, visible=True, transparency=None, saturation=None, resampling_bilinear=False, resampling_cubic=False, set_current=False):
+ def add_wms_t_layer(self, layer_name, url, layer_id, time, style, image_format, time_series_list=None, epsg=None, extra_tags="", group_name="", group_pos=None, only_one_map_on_group=False, collapsed=True, visible=True, transparency=None, saturation=None, resampling_bilinear=False, resampling_cubic=False, set_current=False):
""" Add WMS-T layer and enable timeseries dialog """
# Add WMS-T
- layer = self.layers.add_wms_t_layer(layer_name, url, layer_id, style, image_format, time_series_list, epsg, extra_tags, group_name, group_pos, only_one_map_on_group, collapsed, visible, transparency, saturation, resampling_bilinear, resampling_cubic, set_current)
+ layer = self.layers.add_wms_t_layer(layer_name, url, layer_id, time, style, image_format, time_series_list, epsg, extra_tags, group_name, group_pos, only_one_map_on_group, collapsed, visible, transparency, saturation, resampling_bilinear, resampling_cubic, set_current)
if layer:
if type(layer) in [QgsRasterLayer, QgsVectorLayer]:
# Show timeseries dialog
@@ -885,6 +919,14 @@ def add_wms_t_layer(self, layer_name, url, layer_id, style, image_format, time_s
if self.time_series_action:
self.time_series_action.setEnabled(True)
self.time_series_action.setChecked(self.tools.time_series_dialog is not None and self.tools.time_series_dialog.isVisible())
+ # Show stereo anaglyph options
+ if layer_id.lower().startswith("anaglif"):
+ self.tools.show_anaglyph_dialog(layer, self.tr("Anaglyph"), self.tr("Anaglyph"), self.tr("Inverted stereo"))
+ # Show "on the fly" central photogram rendering layers warning
+ if layer_id.lower().endswith("_central"):
+ message = self.tr("This layer renders only the most centered photogram in the map view, you can zoom in for continuous navigation. Please note that current year may not have full photogram coverage")
+ self.iface.messageBar().pushMessage(layer_name, message, level=Qgis.Info, duration=10)
+
return layer
def find(self, user_text):
@@ -907,8 +949,6 @@ def find(self, user_text):
west, north, east, south, epsg = self.geofinder_dialog.get_rectangle()
# We resituate the map (implemented in parent PluginBase)
self.set_map_rectangle(west, north, east, south, epsg)
- if self.debug_mode:
- print("")
else:
# We get point coordinates
x, y, epsg = self.geofinder_dialog.get_point()
@@ -917,11 +957,12 @@ def find(self, user_text):
QMessageBox.warning(self.iface.mainWindow(), self.tr("Spatial search"),
self.tr("Error, location without coordinates"))
return
+ scale = self.geofinder_dialog.get_scale()
# We resituate the map (implemented in parent PluginBase)
- self.set_map_point(x, y, epsg)
- if self.debug_mode:
- print("")
-
+ self.set_map_point(x, y, epsg, scale)
+
+ if self.debug_mode:
+ print("")
def is_unsupported_file(self, pathname):
return self.is_file_type(pathname, ["dgn", "dwg"])
@@ -1386,10 +1427,6 @@ def get_menu_names(self, action_name, exclude_list):
names_list.append(subaction.text())
return names_list
- def check_qgis_version(self, version=31004):
- """ Checks QGIS old versions with plugin problems """
- return Qgis.QGIS_VERSION_INT >= version
-
def show_qgis_version_warnings(self):
""" Show QGIS old versions warnigs """
LogInfoDialog(
@@ -1573,29 +1610,45 @@ def enable_search_photos(self, checked=False):
self.gui.enable_tool(self.tool_photo_search)
self.iface.messageBar().pushMessage(self.tr("Photograms search tool"), self.tr("Select a point"), level=Qgis.Info, duration=5)
- def search_photos(self, x=None, y=None, photolib_wfs=PHOTOLIB_WFS, date_field="flight_date"):
- """ Search photos in photo library by selected point """
+ def search_photos_by_point(self):
+ """ Search photos in photo library by text point coordinates """
+ # Ask coordinates
title = self.tr("Search photograms")
- epsg = None
-
- # If no coordinate available, we request it
+ msg_text = self.tr('Enter an x y value in the project coordinate system or add the corresponding EPSG code in the following format:\n "429393.19 4580194.65" or "429393.19 4580194.65 EPSG:25831" or "EPSG:25831 429393.19 4580194.65"')
+ coord_text, ok_pressed = QInputDialog.getText(self.iface.mainWindow(), title,
+ set_html_font_size(msg_text), QLineEdit.Normal, "")
+ if not ok_pressed:
+ return
+ # Use GeoFinder static function to parse coordinate text
+ x, y, epsg = GeoFinder.get_point_coordinate(coord_text)
if not x or not y:
- msg_text = self.tr('Enter an x y value in the project coordinate system or add the corresponding EPSG code in the following format:\n "429393.19 4580194.65" or "429393.19 4580194.65 EPSG:25831" or "EPSG:25831 429393.19 4580194.65"')
- coord_text, ok_pressed = QInputDialog.getText(self.iface.mainWindow(), title,
- set_html_font_size(msg_text), QLineEdit.Normal, "")
- if not ok_pressed:
- return
- # Use GeoFinder static function to parse coordinate text
- x, y, epsg = GeoFinder.get_point_coordinate(coord_text)
- if not x or not y:
- QMessageBox.warning(self.iface.mainWindow(), title, "Incorrect coordinate format")
- return
+ QMessageBox.warning(self.iface.mainWindow(), title, "Incorrect coordinate format")
+ return
+ # Search photo coordinates
+ self.search_photos(x, y)
+
+ def search_photos_by_name(self):
+ """ Search photos in photo library by photo name """
+ # Ask photo name
+ title = self.tr("Search photograms")
+ msg_text = self.tr('Photogram name:') + " " * 50
+ photo_name, ok_pressed = QInputDialog.getText(self.iface.mainWindow(), title,
+ set_html_font_size(msg_text), QLineEdit.Normal, "")
+ if not ok_pressed or not photo_name:
+ return
+ # Search photo name
+ self.search_photos(name=photo_name.strip())
+
+ def search_photos(self, x=None, y=None, name=None, photolib_wfs=PHOTOLIB_WFS, date_field="flight_date"):
+ """ Search photos in photo library by selected point or photo name """
+ title = self.photo_search_label.replace(": %s", "")
+ epsg = None
# Check existence of old photo search
group_pos = 0
group = self.legend.get_group_by_name(self.photos_group_name)
if group and len(self.layers.get_group_layers(group)) > 0:
- if QMessageBox.question(self.iface.mainWindow(), self.photo_search_label.replace(": %s", ""),
+ if QMessageBox.question(self.iface.mainWindow(), title,
self.tr('It exists a previous photo search. Do you want close it?'), QMessageBox.Yes, QMessageBox.No) == QMessageBox.No:
return False
self.legend.empty_group(group)
@@ -1603,39 +1656,54 @@ def search_photos(self, x=None, y=None, photolib_wfs=PHOTOLIB_WFS, date_field="f
if not group:
# If not exists download group return -1
group_pos = self.legend.get_group_position_by_name(self.download_group_name) + 1
+
+ # Fix event problems betwen photo layer and photo dialog for QGIS versions < 3.10
+ # Needs create photo dialog previous to photo layer...
+ if not self.photo_search_dialog and not self.check_qgis_version(310000):
+ self.show_photo_search_dialog(None, [])
+ self.photo_search_dialog.hide()
- with WaitCursor():
- if not epsg:
- epsg = int(self.project.get_epsg())
- # Transform point coordinates to EPSG 4326
- point = QgsPointXY(x, y)
- if epsg != 4326:
- transformation = QgsCoordinateTransform(
- QgsCoordinateReferenceSystem("EPSG:%s" % epsg),
- QgsCoordinateReferenceSystem("EPSG:4326"),
- QgsProject.instance())
- point = transformation.transform(point)
+ if self.debug_mode:
+ print("Search photo: %s" % photolib_wfs)
- # Get municipality information of coordinate
- found_dict_list = self.find_point_secure(point.y(), point.x(), 4326) # En geogràfiques el topofinder vol lat, lon (y, x)
- municipality = found_dict_list[0]['nomMunicipi'] if found_dict_list else ""
- if municipality:
- layer_name = self.photo_search_label % municipality
- else:
- if x >= 100 and y >= 100:
- layer_name = self.photo_search_label % self.tr("Coord %s %s") % ("%.2f" % x,"%.2f" % y)
+ with WaitCursor():
+ photo_layer = None
+
+ # Search by coordinates
+ if x and y:
+ if not epsg:
+ epsg = int(self.project.get_epsg())
+
+ # Get municipality information of coordinate
+ found_dict_list = self.find_point_secure(x, y, epsg)
+ municipality = found_dict_list[0]['nomMunicipi'] if found_dict_list else ""
+ if municipality:
+ layer_name = self.photo_search_label % municipality
else:
- layer_name = self.photo_search_label % self.tr("Coord %s %s") % (x, y)
+ if x >= 100 and y >= 100:
+ layer_name = self.photo_search_label % self.tr("Coord %s %s") % ("%.2f" % x,"%.2f" % y)
+ else:
+ layer_name = self.photo_search_label % self.tr("Coord %s %s") % (x, y)
+
+ # Search point in photo library (EPSG 4326)
+ x, y = self.crs.transform_point(x, y, epsg, 4326)
+ photo_layer = self.layers.add_wfs_layer(layer_name, photolib_wfs,
+ ["icgc:fotogrames"], 4326,
+ filter="SELECT * FROM fotogrames WHERE ST_Intersects(msGeometry, ST_GeometryFromText('POINT(%f %f)'))" % (x, y),
+ extra_tags="referer=ICGC",
+ group_name=self.photos_group_name, group_pos=group_pos, only_one_map_on_group=False, only_one_visible_map_on_group=True,
+ collapsed=False, visible=True, transparency=None, set_current=True)
+
+ # Search by name
+ if name and len(name) > 7: # at least flight code...
+ layer_name = self.photo_search_label % name
+ photo_layer = self.layers.add_wfs_layer(layer_name, photolib_wfs,
+ ["icgc:fotogrames"], 4326,
+ filter="SELECT * FROM fotogrames WHERE name LIKE '%s'" % (name),
+ extra_tags="referer=ICGC",
+ group_name=self.photos_group_name, group_pos=group_pos, only_one_map_on_group=False, only_one_visible_map_on_group=True,
+ collapsed=False, visible=True, transparency=None, set_current=True)
- # Search point in photo library
- if self.debug_mode:
- print("Search photo: %s" % photolib_wfs)
- photo_layer = self.layers.add_wfs_layer(layer_name, photolib_wfs,
- ["icgc:fotogrames"], 4326,
- filter="SELECT * FROM fotogrames WHERE ST_Intersects(msGeometry, ST_GeometryFromText('POINT(%f %f)'))" % (point.x(), point.y()),
- extra_tags="referer=ICGC",
- group_name=self.photos_group_name, group_pos=group_pos, only_one_map_on_group=False, only_one_visible_map_on_group=True,
- collapsed=False, visible=True, transparency=None, set_current=True)
if not photo_layer:
return
# Translate field names
@@ -1665,6 +1733,7 @@ def search_photos(self, x=None, y=None, photolib_wfs=PHOTOLIB_WFS, date_field="f
"omega": self.tr("Omega"),
"phi": self.tr("Phi"),
"kappa": self.tr("Kappa"),
+ "analog": self.tr("Analog"),
})
# Get years of found photograms
self.search_photos_year_list = sorted(list(set([(f[date_field].date().year() if type(f[date_field]) == QDateTime \
@@ -1677,6 +1746,7 @@ def search_photos(self, x=None, y=None, photolib_wfs=PHOTOLIB_WFS, date_field="f
self.layers.set_categories_visible(photo_layer, self.search_photos_year_list[1:], False)
self.layers.enable_feature_count(photo_layer)
self.layers.zoom_to_full_extent(photo_layer)
+ self.layers.set_visible(photo_layer, False)
# Show photo search dialog
self.search_photos_year_list.reverse()
@@ -1684,30 +1754,56 @@ def search_photos(self, x=None, y=None, photolib_wfs=PHOTOLIB_WFS, date_field="f
# Map change selection feature event
photo_layer.selectionChanged.connect(self.on_change_photo_selection)
- photo_layer.willBeDeleted.connect(self.photo_search_dialog.reset)
+ if self.photo_search_dialog:
+ photo_layer.willBeDeleted.connect(self.photo_search_dialog.reset)
+
+ # Disable search tool
+ self.gui.enable_tool(None)
- # Disable search tool
- self.gui.enable_tool(None)
+ ## Show warning if max results
+ #if photo_layer and photo_layer.featureCount() == PHOTOLIB_WFS_MAX_FEATURES:
+ # QMessageBox.warning(self.iface.mainWindow(), title,
+ # self.tr("The maximum number of results (%d) has been reached.\nThe query may have more results than are displayed.") % PHOTOLIB_WFS_MAX_FEATURES)
- def photo_preview(self, photo_name, only_one=True, photolib_wms=PHOTOLIB_WMS):
+ def photo_preview(self, photo_name, rectified=False, stereo=False, only_one=True, photolib_wms=PHOTOLIB_WMS):
""" Load photogram raster layer """
if only_one:
- # Remove previous preview layers
- self.layers.remove_layer_by_id(self.photo_layer_id)
+ # Get previous photo_layer to update or create it
+ photo_layer = self.layers.get_by_id(self.photo_layer_id)
else:
+ photo_layer = None
# Disable previous preview layers
- self.legend.set_group_items_visible_by_name(self.photo_group_name, False)
+ self.legend.set_group_items_visible_by_name(self.photos_group_name, False)
self.layers.set_visible_by_id(self.photo_search_layer_id, True)
+ # Determine WMS layer to load
+ layer_name = "anaglif" if stereo else "ortoxpres" if rectified else "fotos"
+ if stereo:
+ photo_style = ",".join([photo_name, \
+ str(self.photo_search_dialog.get_parallax()), \
+ ("true" if self.photo_search_dialog.is_inverted_stereo() else "false") \
+ ])
+ else:
+ photo_style = photo_name
+
# We don't want change current selected layer
current_layer = self.layers.get_current_layer()
- # Load new preview layer at top (using WMS or UNC path to file)
+ # Show debug info
if self.debug_mode:
- print("Show photo: %s / %s" % (photolib_wms, photo_name))
- photo_layer = self.layers.add_wms_layer(self.photo_label % photo_name, photolib_wms,
- ["fotos"], [photo_name], "image/png", self.project.get_epsg(), extra_tags="referer=ICGC&bgcolor=0x000000",
- group_name=self.photos_group_name, group_pos=0, only_one_map_on_group=False, only_one_visible_map_on_group=False,
- collapsed=False, visible=True, transparency=None, set_current=False)
+ print("Show photo: %s %s" % (photolib_wms, photo_style))
+ photo_label = self.photo_label % photo_name
+ if photo_layer:
+ # Update current photo_layer
+ self.layers.update_wms_layer(photo_layer, wms_layer=layer_name, wms_style=photo_style)
+ photo_layer.setName(photo_label)
+ self.layers.set_visible(photo_layer)
+ self.legend.set_group_visible_by_name(self.photos_group_name)
+ else:
+ # Load new preview layer at top (using WMS or UNC path to file)
+ photo_layer = self.layers.add_wms_layer(photo_label, photolib_wms,
+ [layer_name], [photo_style], "image/png", self.project.get_epsg(), extra_tags="referer=ICGC&bgcolor=0x000000",
+ group_name=self.photos_group_name, group_pos=0, only_one_map_on_group=False, only_one_visible_map_on_group=False,
+ collapsed=False, visible=True, transparency=None, set_current=False)
# Restore previous selected layer
if current_layer:
self.layers.set_current_layer(current_layer)
@@ -1726,6 +1822,8 @@ def show_photo_search_dialog(self, layer, years_list, current_year=None, title=N
update_photo_selection_callback = lambda photo_id: self.layers.set_selection(layer, [photo_id] if photo_id else [])
show_info_callback = lambda photo_id: self.iface.openFeatureForm(layer, layer.getFeature(photo_id))
preview_callback = lambda photo_id: self.photo_preview(layer.getFeature(photo_id)['name'])
+ rectified_preview_callback = lambda photo_id: self.photo_preview(layer.getFeature(photo_id)['name'], rectified=True)
+ stereo_preview_callback = lambda photo_id: self.photo_preview(layer.getFeature(photo_id)['name'], stereo=True)
download_callback = lambda photo_id: self.photo_download_action.trigger()
request_certificate_callback = None #lambda photo_id: self.tools.send_email("qgis.openicgc@icgc.cat",
#"OpenICGC QGIS plugin. certificate %s" % layer.getFeature(photo_id)['name'],
@@ -1733,14 +1831,16 @@ def show_photo_search_dialog(self, layer, years_list, current_year=None, title=N
request_scan_callback = None #lambda photo_id: self.tools.send_email("qgis.openicgc@icgc.cat",
#"OpenICGC QGIS plugin. scan %s" % layer.getFeature(photo_id)['name'],
#self.tr("Scan request for photogram: %s") % layer.getFeature(photo_id)['name'])
- report_photo_bug_callback = lambda photo_id: self.report_photo_bug(layer.getFeature(photo_id)['name'], )
+ report_photo_bug_callback = lambda photo_id: self.report_photo_bug(layer.getFeature(photo_id)['name'], layer.getFeature(photo_id)['flight_code'], layer.getFeature(photo_id)['flight_date'], layer.getFeature(photo_id)['gsd'] )
if not self.photo_search_dialog:
self.photo_search_dialog = PhotoSearchSelectionDialog(layer,
years_list, current_year,
- update_photo_time_callback, update_photo_selection_callback, show_info_callback, preview_callback,
+ update_photo_time_callback, update_photo_selection_callback, show_info_callback,
+ preview_callback, rectified_preview_callback, stereo_preview_callback,
None, download_callback, request_certificate_callback, request_scan_callback, report_photo_bug_callback,
- parent=self.iface.mainWindow())
+ autoshow=True, parent=self.iface.mainWindow())
# Align dialog to right
+ self.photo_search_dialog.hide()
self.iface.addDockWidget(Qt.RightDockWidgetArea, self.photo_search_dialog)
# Map visibility event to refresh any control if necessary. This is implemented in
# change layer event that's why i send a change layer signal
@@ -1749,7 +1849,8 @@ def show_photo_search_dialog(self, layer, years_list, current_year=None, title=N
# Configure search result information
self.photo_search_dialog.set_info(layer,
years_list, current_year,
- update_photo_time_callback, update_photo_selection_callback, show_info_callback, preview_callback, None,
+ update_photo_time_callback, update_photo_selection_callback, show_info_callback,
+ preview_callback, rectified_preview_callback, stereo_preview_callback, None,
download_callback, request_certificate_callback, request_scan_callback, report_photo_bug_callback)
# Mostrem el diàleg
self.photo_search_dialog.show()
@@ -1764,8 +1865,11 @@ def update_photo_search_layer_year(self, photo_layer, current_year, range_year):
if photo_layer:
self.layers.set_categories_visible(photo_layer, set(self.search_photos_year_list) - set(year_range), False)
self.layers.set_categories_visible(photo_layer, year_range, True)
+ self.layers.set_current_layer(photo_layer) # click in categories of layer can unselect layer... we fix it
+ self.layers.set_visible(photo_layer) # force visibility of photo layer
+ self.legend.set_group_visible_by_name(self.photos_group_name) # force visibility of photo group
- def report_photo_bug(self, photo_name):
+ def report_photo_bug(self, photo_name, flight_code="", photo_date="", photo_resolution=0):
""" Report a photo bug """
# description, ok_pressed = QInputDialog.getMultiLineText(self.iface.mainWindow(), self.tr("Report photo bug"),
# set_html_font_size(self.tr("Looks like you found an error in photogram:\n%s\n\nWe will register the problem and try to fix it. Could you describe it briefly?") % photo_name))
@@ -1778,6 +1882,6 @@ def report_photo_bug(self, photo_name):
return
self.tools.send_email("qgis.openicgc@icgc.cat",
"Error en el fotograma %s" % photo_name, # Static text no translated
- self.tr("Problem description: "))
+ self.tr("Photo: %s\nFlight code: %s\nDate: %s\nResolution: %.2fm\n\nProblem description: ") % (photo_name, flight_code, photo_date, photo_resolution or 0))
QMessageBox.information(self.iface.mainWindow(), title,
self.tr("Thanks for reporting an error in photogram:\n%s\n\nWe try to fix it as soon as possible") % photo_name)
diff --git a/qlib3/base/aboutdialog.py b/qlib3/base/aboutdialog.py
index badfd63..6333e2f 100644
--- a/qlib3/base/aboutdialog.py
+++ b/qlib3/base/aboutdialog.py
@@ -1,102 +1,102 @@
-# -*- coding: utf-8 -*-
-"""
-*******************************************************************************
-Mòdul amb classe diàleg per mostrar informació bàsica del plugin i logo el ICGC
----
-Module with a dialog class to display basic information of plugin and ICGC logo
-
- -------------------
- begin : 2019-01-18
- author : Albert Adell
- email : albert.adell@icgc.cat
-*******************************************************************************
-"""
-
-import os
-import sys
-
-from PyQt5 import uic
-from PyQt5.QtCore import Qt
-from PyQt5.QtGui import QPalette, QColor, QFontMetrics, QPixmap
-from PyQt5.QtWidgets import QStyle, QDialogButtonBox, QDialog, QApplication
-
-ui_about, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_about.ui'))
-
-
-class AboutDialog(QDialog, ui_about):
- """ Classe diàleg per mostrar informació bàsica del plugin i logo el ICGC
- ---
- Class to display basic information of plugin and ICGC logo
- """
-
- def __init__(self, app_name, app_info, app_icon=None, app_pixmap=None, title="Sobre", autoshow=True, new_line=" ", parent=None):
- """ Inicialització del diàleg "about", cal informar de:
- - app_name: Títol del diàleg
- - app_icon: Icona del diàleg
- - app_info: Informació a mostrar
- - title: Títol de la finestra
- Opcionalment:
- - autoshow: Mostra el diàleg automàticament al crear-lo
- - new_line: Caràcters a substituir per un canvi de linia
- - parent: Especifica la finestra pare del diàleg
- ---
- Initialization of the "about" dialog, you need to report:
- - app_name: Title of the dialog
- - app_icon: Icon of the dialog
- - app_info: Information to show
- - title: Window title
- Optionally:
- - autoshow: Show the dialog automatically when you create it
- - new_line: Characters to be replaced by a change of line
- - parent: Specifies the parent window of the dialog
- """
- QDialog.__init__(self, parent)
- self.setupUi(self)
- self.ui = self # Per compatibilitat QGIS2/3
-
- # Canviem el títol i la icona
- if not title:
- title = self.windowTitle()
- self.setWindowTitle("%s %s" % (title, app_name))
- if app_icon and sys.platform == "win32":
- self.setWindowIcon(app_icon)
-
- # Escalem la imatge de logo mantenint proporcions
- self.label_banner.setScaledContents(False)
- self.label_banner.setAlignment(Qt.AlignCenter)
- if not app_pixmap:
- app_pixmap = QPixmap(self.label_banner.pixmap())
- self.pixmap_banner = app_pixmap
- self.resize_banner()
-
- # Carreguem la informació
- self.label_info.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
- self.label_info.setWordWrap(True);
- self.label_info.setText("\n" + app_info.replace(new_line, "\n"))
-
- # Mostrem el diàleg
- if autoshow:
- self.return_value = self.do_modal()
-
- def resizeEvent(self, newSize):
- """ Mapeja l'event de canvi de mida del diàlog
- ---
- Map dialog size change event
- """
- self.resize_banner()
-
- def resize_banner(self):
- """ Reescala el "banner" (logo ICGC) a la mida del diàleg
- ---
- Resize banner (logo ICGC) to dialog size
- """
- self.label_banner.setPixmap(self.pixmap_banner.scaled(self.label_banner.width(), self.label_banner.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
-
- def do_modal(self):
- """ Mostra el diàleg en mode modal
- ---
- Show dialog on modal mode
- """
- self.show()
- self.return_value = self.exec_()
- return self.return_value
+# -*- coding: utf-8 -*-
+"""
+*******************************************************************************
+Mòdul amb classe diàleg per mostrar informació bàsica del plugin i logo el ICGC
+---
+Module with a dialog class to display basic information of plugin and ICGC logo
+
+ -------------------
+ begin : 2019-01-18
+ author : Albert Adell
+ email : albert.adell@icgc.cat
+*******************************************************************************
+"""
+
+import os
+import sys
+
+from PyQt5 import uic
+from PyQt5.QtCore import Qt
+from PyQt5.QtGui import QPalette, QColor, QFontMetrics, QPixmap
+from PyQt5.QtWidgets import QStyle, QDialogButtonBox, QDialog, QApplication
+
+ui_about, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_about.ui'))
+
+
+class AboutDialog(QDialog, ui_about):
+ """ Classe diàleg per mostrar informació bàsica del plugin i logo el ICGC
+ ---
+ Class to display basic information of plugin and ICGC logo
+ """
+
+ def __init__(self, app_name, app_info, app_icon=None, app_pixmap=None, title="Sobre", autoshow=True, new_line=" ", parent=None):
+ """ Inicialització del diàleg "about", cal informar de:
+ - app_name: Títol del diàleg
+ - app_icon: Icona del diàleg
+ - app_info: Informació a mostrar
+ - title: Títol de la finestra
+ Opcionalment:
+ - autoshow: Mostra el diàleg automàticament al crear-lo
+ - new_line: Caràcters a substituir per un canvi de linia
+ - parent: Especifica la finestra pare del diàleg
+ ---
+ Initialization of the "about" dialog, you need to report:
+ - app_name: Title of the dialog
+ - app_icon: Icon of the dialog
+ - app_info: Information to show
+ - title: Window title
+ Optionally:
+ - autoshow: Show the dialog automatically when you create it
+ - new_line: Characters to be replaced by a change of line
+ - parent: Specifies the parent window of the dialog
+ """
+ QDialog.__init__(self, parent)
+ self.setupUi(self)
+ self.ui = self # Per compatibilitat QGIS2/3
+
+ # Canviem el títol i la icona
+ if not title:
+ title = self.windowTitle()
+ self.setWindowTitle("%s %s" % (title, app_name))
+ if app_icon and sys.platform == "win32":
+ self.setWindowIcon(app_icon)
+
+ # Escalem la imatge de logo mantenint proporcions
+ self.label_banner.setScaledContents(False)
+ self.label_banner.setAlignment(Qt.AlignCenter)
+ if not app_pixmap:
+ app_pixmap = QPixmap(self.label_banner.pixmap())
+ self.pixmap_banner = app_pixmap
+ self.resize_banner()
+
+ # Carreguem la informació
+ self.label_info.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
+ self.label_info.setWordWrap(True);
+ self.label_info.setText("\n" + app_info.replace(new_line, "\n"))
+
+ # Mostrem el diàleg
+ if autoshow:
+ self.return_value = self.do_modal()
+
+ def resizeEvent(self, newSize):
+ """ Mapeja l'event de canvi de mida del diàlog
+ ---
+ Map dialog size change event
+ """
+ self.resize_banner()
+
+ def resize_banner(self):
+ """ Reescala el "banner" (logo ICGC) a la mida del diàleg
+ ---
+ Resize banner (logo ICGC) to dialog size
+ """
+ self.label_banner.setPixmap(self.pixmap_banner.scaled(self.label_banner.width(), self.label_banner.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation))
+
+ def do_modal(self):
+ """ Mostra el diàleg en mode modal
+ ---
+ Show dialog on modal mode
+ """
+ self.show()
+ self.return_value = self.exec_()
+ return self.return_value
diff --git a/qlib3/base/anaglyphdialog.py b/qlib3/base/anaglyphdialog.py
new file mode 100644
index 0000000..fd688c3
--- /dev/null
+++ b/qlib3/base/anaglyphdialog.py
@@ -0,0 +1,139 @@
+# -*- coding: utf-8 -*-
+"""
+*******************************************************************************
+Mòdul amb classe diàleg gestionar series temporals de dades
+---
+Module with a dialog class to manage temporal series
+
+ -------------------
+ begin : 2019-01-18
+ author : Albert Adell
+ email : albert.adell@icgc.cat
+*******************************************************************************
+"""
+
+import os
+
+from PyQt5 import uic
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtCore import Qt, QPoint, QTimer
+from PyQt5.QtWidgets import QDockWidget, QSlider, QApplication, QStyleOptionSlider, QToolTip
+
+Ui_Anaglyph, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_anaglyph.ui'))
+
+
+
+
+class AnaglyphDialog(QDockWidget, Ui_Anaglyph):
+ """ Classe diàleg per mostrar opcions de visualitzar anaglif
+ ---
+ Class dialog to show anaglyph visualization options
+ """
+
+ def __init__(self, layer_name, update_callback=None, anaglyph_percent=100, inverted_stereo=False, \
+ title="", parallax_label="", inverted_stereo_label="", autoshow=True, parent=None):
+ """ Inicialització del diàleg "about", cal informar de:
+ - layer_name: capa a modificar
+ Opcionalment:
+ - update_callback: funció a cridar quan s'actualitzen les opcions
+ - anaglyph_percent: Valor inicial de l'anaglif
+ - inverted_stereo: Valor inicial de l'estèreo invertit
+ - title: Títol del diàleg
+ - parallax_label: Etiqueta anaglif
+ - inverted_stereo_label: Etiqueta estèreo invertit
+ - autoshow: Mostra el diàleg automàticament al crear-lo
+ - parent: Especifica la finestra pare del diàleg
+ ---
+ Initialization of the "about" dialog, you need to report:
+ - layer_name: layer to modify
+ Optionally:
+ - update_callback: callback function to call when options are modified
+ - anaglyph_percent: Anaglyph initial value
+ - inverted_stereo: Inverted stereo initial value
+ - title: Title of the dialog
+ - parallax_label: Anaglyph label
+ - inverted_stereo_label: Inverted stereo label
+ - autoshow: Show the dialog automatically when you create it
+ - parent: Specifies the parent window of the dialog
+ """
+ super().__init__(parent)
+ self.setupUi(self)
+
+ # Ens guardem la funció de callback si executar algun procés extern
+ self.update_callback = update_callback
+ # Configurem un temporizador per fer un refresc retardat a l'utilitzar el slider
+ self.parallax_timer = QTimer()
+ self.parallax_timer.timeout.connect(lambda:self.on_parallax_changed(delayed=0))
+
+ # Canviem el títol
+ if title:
+ self.setWindowTitle(title)
+ if layer_name:
+ self.update_title(layer_name)
+ # Canviem etiquetes si cal
+ if parallax_label:
+ self.update_parallax_label(anaglyph_percent, parallax_label)
+ if inverted_stereo_label:
+ self.checkBox_inverted_stereo.setText(inverted_stereo_label)
+ if inverted_stereo:
+ self.checkBox_inverted_stereo.setChecked(Qt.Checked if inverted_stereo else Qt.Unchecked)
+
+ # Mostrem el diàleg
+ if autoshow:
+ self.show()
+
+ def update_title(self, layer_name):
+ """ Actualitze el títol del diàleg amb el nom de la capa relacionada """
+ title = self.windowTitle().split(":")[0]
+ self.setWindowTitle("%s: %s" % (title, layer_name))
+
+ def update_parallax_label(self, value=None, label=None):
+ """ Actualitza el valor de la etiqueta de paral·laxi """
+ label_parts = self.label_parallax.text().split(": ")
+ if not label:
+ label = label_parts[0]
+ percent = ("%+d%%" % (value - 100)) if value is not None else label_parts[1]
+ self.label_parallax.setText("%s: %s" % (label, percent))
+
+ def set_callback(self, update_callback):
+ """ Actualitza la crida de refresc extern """
+ self.update_callback = update_callback
+
+ def set_enabled(self, enable=True):
+ """ Activa o desactiva tots els controls del diàleg """
+ self.label_parallax.setEnabled(enable)
+ self.horizontalSlider_parallax.setEnabled(enable)
+ self.checkBox_inverted_stereo.setEnabled(enable)
+ self.label_begin.setEnabled(enable)
+ self.label_end.setEnabled(enable)
+ # Canviem el color de la barra del slider i el títol del diàleg quan està desactivat
+ self.horizontalSlider_parallax.setStyleSheet("" if enable else "selection-background-color: gray")
+ self.setStyleSheet("" if enable else "color: gray")
+
+ def set_anaglyph(self, parallax, inverted_stereo):
+ """ Assigna valors a les opcions del diàleg """
+ self.horizontalSlider_parallax.setValue((parallax - 80) / 4)
+ self.checkBox_inverted_stereo.setChecked(Qt.Checked if inverted_stereo else Qt.Unchecked)
+
+ def get_parallax(self):
+ """ Retornem el valor de parallax enter entre 80 i 120 (tant per cent)"""
+ return self.horizontalSlider_parallax.value() * 4 + 80
+
+ def is_inverted_stereo(self):
+ """ Retornem el valor d'estèreo invertid """
+ return self.checkBox_inverted_stereo.checkState() == Qt.Checked
+
+ def on_inverted_stereo(self, inverted):
+ if self.update_callback:
+ self.update_callback(self.get_parallax(), inverted)
+
+ def on_parallax_changed(self, value=None, delayed=1000):
+ parallax = self.get_parallax()
+ self.update_parallax_label(parallax)
+ # Refresh visualization delayed (to avoid excessive refresh events)
+ if self.update_callback:
+ if delayed:
+ self.parallax_timer.start(delayed)
+ else:
+ self.parallax_timer.stop()
+ self.update_callback(parallax, self.is_inverted_stereo())
diff --git a/qlib3/base/errors.py b/qlib3/base/errors.py
index 37334c5..9a023b2 100644
--- a/qlib3/base/errors.py
+++ b/qlib3/base/errors.py
@@ -285,8 +285,9 @@ def qgis_handle_error(function):
def handle_error(*args, **kwargs):
try:
QgsMessageLog.logMessage(f"Procés '{function.__name__}' iniciat", 'Missatges', level=Qgis.Info)
- function(*args, **kwargs)
+ result = function(*args, **kwargs)
status_message = f"Procés '{function.__name__}' finalitzat amb èxit."
+ return result
except QgisError as e:
# Error controlat (InputError, ProcessError...)
title = 'Info' if e.level==Qgis.Info else ('Atenció' if e.level==Qgis.Warning else 'Error')
diff --git a/qlib3/base/loginfodialog.py b/qlib3/base/loginfodialog.py
index 49f1f3a..d69d67e 100644
--- a/qlib3/base/loginfodialog.py
+++ b/qlib3/base/loginfodialog.py
@@ -1,347 +1,347 @@
-# -*- coding: utf-8 -*-
-"""
-*******************************************************************************
-Mòdul amb una classe diàleg per mostrar informació multilinia
----
-Module with a dialog class to display multi-line information
-
- -------------------
- begin : 2019-01-18
- author : Albert Adell
- email : albert.adell@icgc.cat
-*******************************************************************************
-"""
-
-
-import os
-try:
- import win32clipboard as clipboard
- clipboard_available = True
-except:
- clipboard_available = False
-try:
- import utilities.email
- email_available = True
-except:
- email_available = False
-
-from PyQt5 import uic
-from PyQt5.QtCore import Qt
-from PyQt5.QtGui import QPalette, QColor, QFontMetrics, QFont
-from PyQt5.QtWidgets import QStyle, QDialogButtonBox, QDialog, QApplication, QFrame, QFileDialog, QMessageBox
-
-ui_loginfo, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_loginfo.ui'))
-
-
-class LogInfoDialog(QDialog, ui_loginfo):
- """ Classe diàleg per mostrar informació multilinia
- ---
- Dialog class to display multi-line information
- """
-
- mode_info = 0
- mode_warning = 1
- mode_error = 2
-
- buttons_none = 0
- buttons_ok = 1
- buttons_cancel = 2
- buttons_defcancel = 4
- buttons_okcancel = (buttons_ok | buttons_cancel)
- buttons_okcancel_defcancel = (buttons_ok | buttons_cancel | buttons_defcancel)
- buttons_yes = 8
- buttons_no = 16
- buttons_defno = 32
- buttons_yesno = (buttons_yes | buttons_no)
- buttons_yesno_defno = (buttons_yes | buttons_no | buttons_defno)
-
- def __init__(self, info_or_tupleinfolist,
- title=u"Informació de procés", mode=mode_info, buttons=buttons_ok,
- default_combo_selection=None,
- extrainfo_or_tupleextrainfolist=None, extrainfohtml_or_tupleextrainfohtmllist=None,
- email_button_text=None, email_subject=None, email_to=None, email_cc=None,
- save_button_text=None, copy_clipboard_button_text=None,
- autoshow=True, width=None, height=None, font_size=10, border=False, parent=None):
- """ Inicialització del diàleg, cal especificar paràmetre amb un text d'informació o amb una
- llista de tuples amb la informació. Opcionalment es pot especificar:
- - title: Títol del diàleg
- - mode: Mode del diàleg que canvia la icona a mostrar (mode_info, mode_warning, mode_error)
- - buttons: Màscara de botons a mostrar (buttons_ok, buttons_cancel, buttons_yes ...)
- - default_combo_selection: En cas de tenir una llista d'informacions, valor de la llista a mostrar per defecte
- - extrainfo_or_tupleextrainfolist: Informació addicional a mostrar (botó email + shift)
- - extrainfohtml_or_tupleextrainfohtmllist: Informació HTML addicional a mostrar (en emails)
- - email_button_text: Text del botó que serveix per enviar informes per email
- - email_subject: Asumpte del informes per email
- - email_to: Destinataris dels informes per email
- - email_cc: Destinataris en copia dels informes per email
- - save_button_text: Text del botó de guardar informació a fitxer
- - copy_clipboard_button_text: Text del botó per guardar informació al porta papers
- - autoshow: Mostra automàticament el diàleg al crear-lo
- - width: Amplada del diàleg
- - height: Alçada del diàleg
- - parent: Finestra pare del diàleg
- ---
- Initialization of the dialog, you need to specify a parameter with an information text or with a
- list of tuples with information. Optionally you can specify:
- - title: Dialog title
- - mode: Dialog mode that switches the icon to display (mode_info, mode_warning, mode_error)
- - buttons: Mask of buttons to show (buttons_ok, buttons_cancel, buttons_yes ...)
- - default_combo_selection: If you have a list of information, value of the list to be displayed by default
- - extrainfo_or_tupleextrainfolist: Additional information to show (email button + shift)
- - extrainfohtml_or_tupleextrainfohtmllist: Additional HTML information to show (in emails)
- - email_button_text: Text of the button used to send reports by email
- - email_subject: Subject of the reports by email
- - email_to: Receivers of the reports by email
- - email_cc: Receivers in copy of the reports by email
- - save_button_text: Text of the button to save information to file
- - copy_clipboard_button_text: Text of the button to save information to clipboard
- - autoshow: Automatically show the dialog when creating it
- - width: Dialog width
- - height: Dialog height
- - parent: Parent window of the dialog
- """
- QDialog.__init__(self, parent)
- self.setupUi(self)
- self.ui = self # Per compatibilitat QGIS2/3
-
- # Canviem el títol i la icona
- self.setWindowTitle(title)
- if mode == self.mode_error:
- icon = QStyle.SP_MessageBoxCritical
- elif mode == self.mode_warning:
- icon = QStyle.SP_MessageBoxWarning
- else:
- icon = QStyle.SP_MessageBoxInformation
- self.setWindowIcon(self.style().standardIcon(icon))
-
- # Canviem la mida
- if height or width:
- if not height:
- height = self.geometry().height()
- if not width:
- width = self.geometry().width()
- self.resize(width, height)
-
- # Canviem els botons que mostrem
- qt_buttons = 0
- if buttons & self.buttons_ok:
- qt_buttons |= QDialogButtonBox.Ok
- if buttons & self.buttons_cancel:
- qt_buttons |= QDialogButtonBox.Cancel
- if buttons & self.buttons_yes:
- qt_buttons |= QDialogButtonBox.Yes
- if buttons & self.buttons_no:
- qt_buttons |= QDialogButtonBox.No
- self.ui.buttonBox.setStandardButtons(qt_buttons)
- if buttons & self.buttons_defcancel:
- self.ui.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
- if buttons & self.buttons_defno:
- self.ui.buttonBox.button(QDialogButtonBox.No).setDefault(True)
-
- # Mostrem o no el botó de Save
- if save_button_text:
- self.ui.pushButton_save.setText(save_button_text)
- self.ui.pushButton_save.setMaximumWidth(QFontMetrics(self.ui.pushButton_save.font()).width(save_button_text) + 20)
- self.ui.pushButton_save.setEnabled(True)
- self.ui.pushButton_save.setVisible(True)
- else:
- self.ui.pushButton_save.setEnabled(False)
- self.ui.pushButton_save.setVisible(False)
-
- # Motrem el botó de copiar al portapapers
- if copy_clipboard_button_text:
- self.ui.pushButton_clipboard.setText(copy_clipboard_button_text)
- self.ui.pushButton_clipboard.setMaximumWidth(QFontMetrics(self.ui.pushButton_save.font()).width(copy_clipboard_button_text) + 20)
- self.ui.pushButton_clipboard.setEnabled(clipboard_available)
- self.ui.pushButton_clipboard.setVisible(True)
- else:
- self.ui.pushButton_clipboard.setEnabled(False)
- self.ui.pushButton_clipboard.setVisible(False)
-
- # Botó d'email
- if email_button_text:
- self.ui.pushButton_email.setText(email_button_text)
- self.ui.pushButton_email.setMaximumWidth(QFontMetrics(self.ui.pushButton_email.font()).width(email_button_text) + 20)
- self.ui.pushButton_email.setEnabled(email_available)
- self.ui.pushButton_email.setVisible(True)
- else:
- self.ui.pushButton_email.setEnabled(False)
- self.ui.pushButton_email.setVisible(False)
- self.email_subject = email_subject
- self.email_to = email_to
- self.email_cc = email_cc
-
- # Canviem el color i mida de la font de l'edit
- palette = self.ui.plainTextEdit.palette()
- palette.setColor(QPalette.Base, QColor('transparent'))
- self.ui.plainTextEdit.setPalette(palette)
- self.ui.plainTextEdit.setFont(QFont(self.ui.plainTextEdit.font().rawName(), font_size))
- if not border:
- self.ui.plainTextEdit.setFrameStyle(QFrame.NoFrame)
-
- # Carreguem les dades
- self.info_or_tupleinfolist = info_or_tupleinfolist
- self.extrainfo_or_tupleextrainfolist = extrainfo_or_tupleextrainfolist
- self.extrainfohtml_or_tupleextrainfohtmllist = extrainfohtml_or_tupleextrainfohtmllist
- if type(info_or_tupleinfolist) is list:
- self.index = 0
- self.tuple_list = info_or_tupleinfolist
- self.ui.comboBox.setVisible(True)
- self.ui.comboBox.setEnabled(len(info_or_tupleinfolist) > 1)
- if len(info_or_tupleinfolist) > 0 and len(info_or_tupleinfolist[0]) > 1:
- self.ui.comboBox.addItems([pair[0] for pair in info_or_tupleinfolist])
- combo_index = max(0, self.ui.comboBox.findText(default_combo_selection)) if default_combo_selection else 0
- self.ui.comboBox.setCurrentIndex(combo_index)
- self.ui.plainTextEdit.setPlainText(info_or_tupleinfolist[combo_index][1])
- elif type(info_or_tupleinfolist) is tuple:
- self.index = 0
- self.tuple_list = [info_or_tupleinfolist]
- self.ui.comboBox.setVisible(True)
- self.ui.comboBox.setEnabled(False)
- if len(info_or_tupleinfolist) > 0:
- self.ui.comboBox.addItem(info_or_tupleinfolist[0])
- self.ui.plainTextEdit.setPlainText(info_or_tupleinfolist[1])
- else:
- self.index = None
- self.tuple_list = None
- self.ui.comboBox.setVisible(False)
- self.ui.plainTextEdit.setPlainText(info_or_tupleinfolist)
-
- # Mostrem el diàleg
- self.setSizeGripEnabled(True) # Mostra la marca de resize (abaix a la dreta)
- if autoshow:
- self.return_value = self.do_modal()
-
- def update(self, index):
- """ En cas de tenir una llista d'informacions, mostra la informació associada a "index"
- ---
- In case you have a list of information, show the information associated with "index"
- """
- self.index = index
- self.ui.plainTextEdit.setPlainText(self.tuple_list[index][1])
-
- def get_report_info(self, html_format=False):
- """ Retorna un text amb la informació mostrada en el diàleg, pot ser en format
- text pla, HTML i es pot configurar els canvis de linia
- ---
- Returns a text with the information displayed in the dialog, it can be in
- plain text format, HTML, and you can configure line changes format
- """
- if self.index:
- if html_format and self.extrainfohtml_or_tupleextrainfohtmllist:
- report_info = self.extrainfohtml_or_tupleextrainfohtmllist[self.index][1]
- elif self.extrainfo_or_tupleextrainfolist:
- report_info = self.extrainfo_or_tupleextrainfolist[self.index][1]
- else:
- report_info = self.info_or_tupleinfolist[self.index][1]
- else:
- if html_format and self.extrainfohtml_or_tupleextrainfohtmllist:
- report_info = self.extrainfohtml_or_tupleextrainfohtmllist
- elif self.extrainfo_or_tupleextrainfolist:
- report_info = self.extrainfo_or_tupleextrainfolist
- else:
- report_info = self.info_or_tupleinfolist
-
- return report_info
-
- def save(self):
- """ Guarda la informació del diàleg en un fitxer
- ---
- Saves dialog information into a file
- """
- out_file, _file_type = QFileDialog.getSaveFileName(None, "Save log info", "log.txt", "Text files (*.txt)")
- if not out_file:
- return
- report_info = self.get_report_info(html_format=False)
- try:
- with open(out_file, 'w', encoding='utf-8') as file:
- file.write(report_info)
- except Exception as e:
- QMessageBox.warning(None, u"Save error", u"Error saving log\n%s" % e)
-
- def copy_to_clipboard(self):
- """ Guarda la informació del diàleg en el portapapers
- ---
- Saves dialog information into clipboard
- """
- if not clipboard_available:
- return
- clipboard.OpenClipboard()
- clipboard.EmptyClipboard()
- clipboard.SetClipboardText(self.ui.plainTextEdit.toPlainText())
- clipboard.CloseClipboard()
-
- def send_email(self):
- """ Envia la informació del diàleg per email
- ---
- Send dialog information by email
- """
- if not email_available:
- return
- if QApplication.keyboardModifiers() == Qt.ShiftModifier:
- return self.show_extra_info()
-
- email_info = self.get_report_info(html_format=True)
- try:
- email_object = utilities.email.eMail(self.email_to, self.email_cc, self.email_subject, htmlbody = email_info, attachment_files = [])
- email_object.open()
- except:
- QMessageBox.warning(None, u"Enviar informe", u"Error no es pot obrir el programa d'email per enviar l'informe")
-
- def show_extra_info(self):
- """ Mostra la informació addicional en el diàleg
- ---
- Show extra information on dialog
- """
- # Mostrem la informació extesa al diàleg
- extra_info = self.get_report_info()
- self.ui.plainTextEdit.clear();
- self.ui.plainTextEdit.appendPlainText(extra_info);
- # Fem el diàleg més gran
- extra_width = 400
- extra_height = 400
- self.resize(self.geometry().width() + extra_width, self.geometry().height() + extra_height)
- self.move(self.x() - extra_width / 2, self.y() - extra_height / 2)
-
- def do_modal(self):
- """ Mostra el diàleg en mode modal
- ---
- Show modal dialog
- """
- self.show()
- self.return_value = self.exec_()
- return self.return_value
-
- def accept(self):
- QDialog.accept(self)
-
- def reject(self):
- QDialog.reject(self)
-
- def is_ok(self):
- """ Retorna si s'ha premut el botó ok
- ---
- Return if ok button has been pressed
- """
- return self.return_value == 1
-
- def is_cancel(self):
- """ Retorna si s'ha premut el botó cancelar
- ---
- Return if cancel button has been pressed
- """
- return self.return_value == 0
-
- def is_yes(self):
- """ Retorna si s'ha premut el botó yes
- ---
- Return if yes button has been pressed
- """
- return self.return_value == 1
-
- def is_no(self):
- """ Retorna si s'ha premut el botó no
- ---
- Return if no button has been pressed
- """
- return self.return_value == 0
+# -*- coding: utf-8 -*-
+"""
+*******************************************************************************
+Mòdul amb una classe diàleg per mostrar informació multilinia
+---
+Module with a dialog class to display multi-line information
+
+ -------------------
+ begin : 2019-01-18
+ author : Albert Adell
+ email : albert.adell@icgc.cat
+*******************************************************************************
+"""
+
+
+import os
+try:
+ import win32clipboard as clipboard
+ clipboard_available = True
+except:
+ clipboard_available = False
+try:
+ import utilities.email
+ email_available = True
+except:
+ email_available = False
+
+from PyQt5 import uic
+from PyQt5.QtCore import Qt
+from PyQt5.QtGui import QPalette, QColor, QFontMetrics, QFont
+from PyQt5.QtWidgets import QStyle, QDialogButtonBox, QDialog, QApplication, QFrame, QFileDialog, QMessageBox
+
+ui_loginfo, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_loginfo.ui'))
+
+
+class LogInfoDialog(QDialog, ui_loginfo):
+ """ Classe diàleg per mostrar informació multilinia
+ ---
+ Dialog class to display multi-line information
+ """
+
+ mode_info = 0
+ mode_warning = 1
+ mode_error = 2
+
+ buttons_none = 0
+ buttons_ok = 1
+ buttons_cancel = 2
+ buttons_defcancel = 4
+ buttons_okcancel = (buttons_ok | buttons_cancel)
+ buttons_okcancel_defcancel = (buttons_ok | buttons_cancel | buttons_defcancel)
+ buttons_yes = 8
+ buttons_no = 16
+ buttons_defno = 32
+ buttons_yesno = (buttons_yes | buttons_no)
+ buttons_yesno_defno = (buttons_yes | buttons_no | buttons_defno)
+
+ def __init__(self, info_or_tupleinfolist,
+ title=u"Informació de procés", mode=mode_info, buttons=buttons_ok,
+ default_combo_selection=None,
+ extrainfo_or_tupleextrainfolist=None, extrainfohtml_or_tupleextrainfohtmllist=None,
+ email_button_text=None, email_subject=None, email_to=None, email_cc=None,
+ save_button_text=None, copy_clipboard_button_text=None,
+ autoshow=True, width=None, height=None, font_size=10, border=False, parent=None):
+ """ Inicialització del diàleg, cal especificar paràmetre amb un text d'informació o amb una
+ llista de tuples amb la informació. Opcionalment es pot especificar:
+ - title: Títol del diàleg
+ - mode: Mode del diàleg que canvia la icona a mostrar (mode_info, mode_warning, mode_error)
+ - buttons: Màscara de botons a mostrar (buttons_ok, buttons_cancel, buttons_yes ...)
+ - default_combo_selection: En cas de tenir una llista d'informacions, valor de la llista a mostrar per defecte
+ - extrainfo_or_tupleextrainfolist: Informació addicional a mostrar (botó email + shift)
+ - extrainfohtml_or_tupleextrainfohtmllist: Informació HTML addicional a mostrar (en emails)
+ - email_button_text: Text del botó que serveix per enviar informes per email
+ - email_subject: Asumpte del informes per email
+ - email_to: Destinataris dels informes per email
+ - email_cc: Destinataris en copia dels informes per email
+ - save_button_text: Text del botó de guardar informació a fitxer
+ - copy_clipboard_button_text: Text del botó per guardar informació al porta papers
+ - autoshow: Mostra automàticament el diàleg al crear-lo
+ - width: Amplada del diàleg
+ - height: Alçada del diàleg
+ - parent: Finestra pare del diàleg
+ ---
+ Initialization of the dialog, you need to specify a parameter with an information text or with a
+ list of tuples with information. Optionally you can specify:
+ - title: Dialog title
+ - mode: Dialog mode that switches the icon to display (mode_info, mode_warning, mode_error)
+ - buttons: Mask of buttons to show (buttons_ok, buttons_cancel, buttons_yes ...)
+ - default_combo_selection: If you have a list of information, value of the list to be displayed by default
+ - extrainfo_or_tupleextrainfolist: Additional information to show (email button + shift)
+ - extrainfohtml_or_tupleextrainfohtmllist: Additional HTML information to show (in emails)
+ - email_button_text: Text of the button used to send reports by email
+ - email_subject: Subject of the reports by email
+ - email_to: Receivers of the reports by email
+ - email_cc: Receivers in copy of the reports by email
+ - save_button_text: Text of the button to save information to file
+ - copy_clipboard_button_text: Text of the button to save information to clipboard
+ - autoshow: Automatically show the dialog when creating it
+ - width: Dialog width
+ - height: Dialog height
+ - parent: Parent window of the dialog
+ """
+ QDialog.__init__(self, parent)
+ self.setupUi(self)
+ self.ui = self # Per compatibilitat QGIS2/3
+
+ # Canviem el títol i la icona
+ self.setWindowTitle(title)
+ if mode == self.mode_error:
+ icon = QStyle.SP_MessageBoxCritical
+ elif mode == self.mode_warning:
+ icon = QStyle.SP_MessageBoxWarning
+ else:
+ icon = QStyle.SP_MessageBoxInformation
+ self.setWindowIcon(self.style().standardIcon(icon))
+
+ # Canviem la mida
+ if height or width:
+ if not height:
+ height = self.geometry().height()
+ if not width:
+ width = self.geometry().width()
+ self.resize(width, height)
+
+ # Canviem els botons que mostrem
+ qt_buttons = 0
+ if buttons & self.buttons_ok:
+ qt_buttons |= QDialogButtonBox.Ok
+ if buttons & self.buttons_cancel:
+ qt_buttons |= QDialogButtonBox.Cancel
+ if buttons & self.buttons_yes:
+ qt_buttons |= QDialogButtonBox.Yes
+ if buttons & self.buttons_no:
+ qt_buttons |= QDialogButtonBox.No
+ self.ui.buttonBox.setStandardButtons(qt_buttons)
+ if buttons & self.buttons_defcancel:
+ self.ui.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True)
+ if buttons & self.buttons_defno:
+ self.ui.buttonBox.button(QDialogButtonBox.No).setDefault(True)
+
+ # Mostrem o no el botó de Save
+ if save_button_text:
+ self.ui.pushButton_save.setText(save_button_text)
+ self.ui.pushButton_save.setMaximumWidth(QFontMetrics(self.ui.pushButton_save.font()).width(save_button_text) + 20)
+ self.ui.pushButton_save.setEnabled(True)
+ self.ui.pushButton_save.setVisible(True)
+ else:
+ self.ui.pushButton_save.setEnabled(False)
+ self.ui.pushButton_save.setVisible(False)
+
+ # Motrem el botó de copiar al portapapers
+ if copy_clipboard_button_text:
+ self.ui.pushButton_clipboard.setText(copy_clipboard_button_text)
+ self.ui.pushButton_clipboard.setMaximumWidth(QFontMetrics(self.ui.pushButton_save.font()).width(copy_clipboard_button_text) + 20)
+ self.ui.pushButton_clipboard.setEnabled(clipboard_available)
+ self.ui.pushButton_clipboard.setVisible(True)
+ else:
+ self.ui.pushButton_clipboard.setEnabled(False)
+ self.ui.pushButton_clipboard.setVisible(False)
+
+ # Botó d'email
+ if email_button_text:
+ self.ui.pushButton_email.setText(email_button_text)
+ self.ui.pushButton_email.setMaximumWidth(QFontMetrics(self.ui.pushButton_email.font()).width(email_button_text) + 20)
+ self.ui.pushButton_email.setEnabled(email_available)
+ self.ui.pushButton_email.setVisible(True)
+ else:
+ self.ui.pushButton_email.setEnabled(False)
+ self.ui.pushButton_email.setVisible(False)
+ self.email_subject = email_subject
+ self.email_to = email_to
+ self.email_cc = email_cc
+
+ # Canviem el color i mida de la font de l'edit
+ palette = self.ui.plainTextEdit.palette()
+ palette.setColor(QPalette.Base, QColor('transparent'))
+ self.ui.plainTextEdit.setPalette(palette)
+ self.ui.plainTextEdit.setFont(QFont(self.ui.plainTextEdit.font().rawName(), font_size))
+ if not border:
+ self.ui.plainTextEdit.setFrameStyle(QFrame.NoFrame)
+
+ # Carreguem les dades
+ self.info_or_tupleinfolist = info_or_tupleinfolist
+ self.extrainfo_or_tupleextrainfolist = extrainfo_or_tupleextrainfolist
+ self.extrainfohtml_or_tupleextrainfohtmllist = extrainfohtml_or_tupleextrainfohtmllist
+ if type(info_or_tupleinfolist) is list:
+ self.index = 0
+ self.tuple_list = info_or_tupleinfolist
+ self.ui.comboBox.setVisible(True)
+ self.ui.comboBox.setEnabled(len(info_or_tupleinfolist) > 1)
+ if len(info_or_tupleinfolist) > 0 and len(info_or_tupleinfolist[0]) > 1:
+ self.ui.comboBox.addItems([pair[0] for pair in info_or_tupleinfolist])
+ combo_index = max(0, self.ui.comboBox.findText(default_combo_selection)) if default_combo_selection else 0
+ self.ui.comboBox.setCurrentIndex(combo_index)
+ self.ui.plainTextEdit.setPlainText(info_or_tupleinfolist[combo_index][1])
+ elif type(info_or_tupleinfolist) is tuple:
+ self.index = 0
+ self.tuple_list = [info_or_tupleinfolist]
+ self.ui.comboBox.setVisible(True)
+ self.ui.comboBox.setEnabled(False)
+ if len(info_or_tupleinfolist) > 0:
+ self.ui.comboBox.addItem(info_or_tupleinfolist[0])
+ self.ui.plainTextEdit.setPlainText(info_or_tupleinfolist[1])
+ else:
+ self.index = None
+ self.tuple_list = None
+ self.ui.comboBox.setVisible(False)
+ self.ui.plainTextEdit.setPlainText(info_or_tupleinfolist)
+
+ # Mostrem el diàleg
+ self.setSizeGripEnabled(True) # Mostra la marca de resize (abaix a la dreta)
+ if autoshow:
+ self.return_value = self.do_modal()
+
+ def update(self, index):
+ """ En cas de tenir una llista d'informacions, mostra la informació associada a "index"
+ ---
+ In case you have a list of information, show the information associated with "index"
+ """
+ self.index = index
+ self.ui.plainTextEdit.setPlainText(self.tuple_list[index][1])
+
+ def get_report_info(self, html_format=False):
+ """ Retorna un text amb la informació mostrada en el diàleg, pot ser en format
+ text pla, HTML i es pot configurar els canvis de linia
+ ---
+ Returns a text with the information displayed in the dialog, it can be in
+ plain text format, HTML, and you can configure line changes format
+ """
+ if self.index:
+ if html_format and self.extrainfohtml_or_tupleextrainfohtmllist:
+ report_info = self.extrainfohtml_or_tupleextrainfohtmllist[self.index][1]
+ elif self.extrainfo_or_tupleextrainfolist:
+ report_info = self.extrainfo_or_tupleextrainfolist[self.index][1]
+ else:
+ report_info = self.info_or_tupleinfolist[self.index][1]
+ else:
+ if html_format and self.extrainfohtml_or_tupleextrainfohtmllist:
+ report_info = self.extrainfohtml_or_tupleextrainfohtmllist
+ elif self.extrainfo_or_tupleextrainfolist:
+ report_info = self.extrainfo_or_tupleextrainfolist
+ else:
+ report_info = self.info_or_tupleinfolist
+
+ return report_info
+
+ def save(self):
+ """ Guarda la informació del diàleg en un fitxer
+ ---
+ Saves dialog information into a file
+ """
+ out_file, _file_type = QFileDialog.getSaveFileName(None, "Save log info", "log.txt", "Text files (*.txt)")
+ if not out_file:
+ return
+ report_info = self.get_report_info(html_format=False)
+ try:
+ with open(out_file, 'w', encoding='utf-8') as file:
+ file.write(report_info)
+ except Exception as e:
+ QMessageBox.warning(None, u"Save error", u"Error saving log\n%s" % e)
+
+ def copy_to_clipboard(self):
+ """ Guarda la informació del diàleg en el portapapers
+ ---
+ Saves dialog information into clipboard
+ """
+ if not clipboard_available:
+ return
+ clipboard.OpenClipboard()
+ clipboard.EmptyClipboard()
+ clipboard.SetClipboardText(self.ui.plainTextEdit.toPlainText())
+ clipboard.CloseClipboard()
+
+ def send_email(self):
+ """ Envia la informació del diàleg per email
+ ---
+ Send dialog information by email
+ """
+ if not email_available:
+ return
+ if QApplication.keyboardModifiers() == Qt.ShiftModifier:
+ return self.show_extra_info()
+
+ email_info = self.get_report_info(html_format=True)
+ try:
+ email_object = utilities.email.eMail(self.email_to, self.email_cc, self.email_subject, htmlbody = email_info, attachment_files = [])
+ email_object.open()
+ except:
+ QMessageBox.warning(None, u"Enviar informe", u"Error no es pot obrir el programa d'email per enviar l'informe")
+
+ def show_extra_info(self):
+ """ Mostra la informació addicional en el diàleg
+ ---
+ Show extra information on dialog
+ """
+ # Mostrem la informació extesa al diàleg
+ extra_info = self.get_report_info()
+ self.ui.plainTextEdit.clear();
+ self.ui.plainTextEdit.appendPlainText(extra_info);
+ # Fem el diàleg més gran
+ extra_width = 400
+ extra_height = 400
+ self.resize(self.geometry().width() + extra_width, self.geometry().height() + extra_height)
+ self.move(self.x() - extra_width / 2, self.y() - extra_height / 2)
+
+ def do_modal(self):
+ """ Mostra el diàleg en mode modal
+ ---
+ Show modal dialog
+ """
+ self.show()
+ self.return_value = self.exec_()
+ return self.return_value
+
+ def accept(self):
+ QDialog.accept(self)
+
+ def reject(self):
+ QDialog.reject(self)
+
+ def is_ok(self):
+ """ Retorna si s'ha premut el botó ok
+ ---
+ Return if ok button has been pressed
+ """
+ return self.return_value == 1
+
+ def is_cancel(self):
+ """ Retorna si s'ha premut el botó cancelar
+ ---
+ Return if cancel button has been pressed
+ """
+ return self.return_value == 0
+
+ def is_yes(self):
+ """ Retorna si s'ha premut el botó yes
+ ---
+ Return if yes button has been pressed
+ """
+ return self.return_value == 1
+
+ def is_no(self):
+ """ Retorna si s'ha premut el botó no
+ ---
+ Return if no button has been pressed
+ """
+ return self.return_value == 0
diff --git a/qlib3/base/pluginbase.py b/qlib3/base/pluginbase.py
index 6c3115e..2edf470 100644
--- a/qlib3/base/pluginbase.py
+++ b/qlib3/base/pluginbase.py
@@ -32,8 +32,10 @@
from importlib import reload
import base64
import zipfile
-#import ogr
-from osgeo import ogr
+try:
+ import ogr, osr
+except:
+ from osgeo import ogr, osr
from PyQt5.QtCore import Qt, QSize, QSettings, QObject, QTranslator, qVersion, QCoreApplication, QVariant, QDateTime, QDate, QLocale, QUrl
from PyQt5.QtWidgets import QApplication, QAction, QToolBar, QLabel, QMessageBox, QMenu, QToolButton
@@ -42,13 +44,13 @@
from PyQt5.QtXml import QDomDocument
from qgis.gui import QgsProjectionSelectionDialog, QgsAttributeDialog
-from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsWkbTypes, QgsRectangle, QgsContrastEnhancement
+from qgis.core import QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsWkbTypes, QgsRectangle, QgsPointXY
from qgis.core import QgsRasterMinMaxOrigin, QgsDataSourceUri, QgsHueSaturationFilter, QgsRasterLayer, QgsVectorLayer, QgsLayerTreeGroup
-from qgis.core import QgsLayerTreeLayer, QgsLayerDefinition, QgsReadWriteContext, QgsLayoutItemMap
+from qgis.core import QgsLayerTreeLayer, QgsLayerDefinition, QgsReadWriteContext, QgsLayoutItemMap, QgsContrastEnhancement
from qgis.core import QgsRendererCategory, QgsCategorizedSymbolRenderer, QgsRendererRange, QgsGraduatedSymbolRenderer, QgsRenderContext, QgsRendererRangeLabelFormat
from qgis.core import QgsSymbol, QgsMarkerSymbol, QgsFillSymbol, QgsBilinearRasterResampler, QgsCubicRasterResampler, QgsSimpleLineSymbolLayer
from qgis.core import QgsEditorWidgetSetup, QgsPrintLayout, QgsSpatialIndex, QgsFeatureRequest, QgsMapLayer, QgsField, QgsVectorFileWriter
-from qgis.core import QgsLayoutExporter, QgsFields
+from qgis.core import QgsLayoutExporter, QgsFields, Qgis
from qgis.utils import plugins, reloadPlugin, showPluginHelp
from . import resources_rc
@@ -69,6 +71,10 @@
reload(timeseriesdialog)
from .timeseriesdialog import TimeSeriesDialog
+from . import anaglyphdialog
+reload(anaglyphdialog)
+from .anaglyphdialog import AnaglyphDialog
+
from . import stylesdialog
reload(stylesdialog)
from .stylesdialog import StylesDialog
@@ -230,7 +236,7 @@ def insert_at_GUI(self, menu_or_toolbar, position, names_callbacks):
if entry is None:
continue
# Recollim les dades de usuari
- eseparator, elabel, eaction, econtrol, name, callback, toggle_callback, icon, enabled, checkable, id, subentries_list = self.__parse_entry(entry)
+ eseparator, elabel, eaction, econtrol, name, callback, toggle_callback, icon, enabled, checkable, id, tooltip, subentries_list = self.__parse_entry(entry)
# Creem el menu o toolbar
if eseparator != None:
@@ -300,6 +306,7 @@ def insert_at_GUI(self, menu_or_toolbar, position, names_callbacks):
else:
# Submenú
submenu = QMenu()
+ submenu.setToolTipsVisible(True)
self.add_to_menu(submenu, subentries_list)
# Guardem el submenu (si no, si està buit, dóna problemes afegint-lo a un menú)
self.menus.append(submenu)
@@ -338,6 +345,11 @@ def insert_at_GUI(self, menu_or_toolbar, position, names_callbacks):
action.setEnabled(False)
if checkable:
action.setCheckable(True)
+ if tooltip:
+ if type(action) == QWidgetAction:
+ action.defaultWidget().defaultAction().setToolTip(tooltip)
+ else:
+ action.setToolTip(tooltip)
#Ens guardem els items de menu o toolbar, si no no apareix...
self.actions.append((menu_or_toolbar, action))
@@ -349,7 +361,7 @@ def __parse_entry(self, entry):
QAction --> Acció amb icona i funció a executar
Altres_tipus --> Suposem que és un control (combobox, lineedit, ...)
Tupla:
- (Nom, [funció | (funció_activació, funció_toggle)], [icona], [enabled], [checkable], [id], [submenu_llista])
+ (Nom, [funció | (funció_activació, funció_toggle)], [icona], [enabled], [checkable], [id], [tooltip], [submenu_llista])
---
Types of accepted menus / toolbars, lists of:
None or "---" or "" -> separator
@@ -399,6 +411,7 @@ def __parse_entry(self, entry):
enabled = True
checkable = False
id = None
+ tooltip = None
subentries_list = None
if type(entry) != tuple:
@@ -444,18 +457,24 @@ def __parse_entry(self, entry):
if len(entry) > 6:
if type(entry[6]) == list:
subentries_list = entry[6]
- # Si la entradano té callback (i no és un control) la desactivem
+ else:
+ tooltip = entry[6]
+ if len(entry) > 7:
+ if type(entry[7]) == list:
+ subentries_list = entry[6]
+
+ # Si la entrada no té callback (i no és un control) la desactivem
if self.disable_unmapped_gui and not separator and not label and not action and not control and not callback \
and not toggle_callback and not subentries_list:
enabled = False
- return separator, label, action, control, name, callback, toggle_callback, icon, enabled, checkable, id, subentries_list
+ return separator, label, action, control, name, callback, toggle_callback, icon, enabled, checkable, id, tooltip, subentries_list
def find_action(self, id, actions_list=None):
""" Cerca una acció a partir del seu objectName
---
Find a action by objectName
"""
- if not actions_list:
+ if actions_list == None:
actions_list = [action for menu_or_toolbar, action in self.actions]
for action in actions_list:
if action and action.objectName() == id:
@@ -1026,10 +1045,10 @@ def refresh_map(self, wait_refreshed=False):
---
Refresh the content of the map, if it is specified that you wait, the function does not return until the end event is received
"""
+ self.map_refreshed = False
self.iface.mapCanvas().refreshAllLayers()
if wait_refreshed:
# Espera a que es refresqui el mapa
- self.map_refreshed = False
while not self.map_refreshed:
QApplication.instance().processEvents()
@@ -1115,6 +1134,8 @@ def get_feature_attribute(self, layer, entity, field_name):
---
Returns the value of a field (column) of an layer entity (row) based on its id (id prefix is passed)
"""
+ if field_name.lower() in ('footprint', 'geometry', 'the_geom', 'geometria'):
+ return entity.geometry()
index = layer.dataProvider().fieldNameIndex(field_name)
if index < 0:
return None
@@ -1314,8 +1335,7 @@ def __get_attributes(self, layer_or_list_or_none, field_name_or_list, only_selec
if layer:
# Obtenim els elements seleccionats
if only_selection:
- selected_fids = set(layer.selectedFeatureIds())
- selected_features = [f for f in layer.getFeatures() if f.id() in selected_fids][:max_items]
+ selected_features = layer.getSelectedFeatures()
else:
selected_features = list(layer.getFeatures())[:max_items]
# Obtenim la selecció de la capa fields_name_or_list (acceptem llista o valor)
@@ -1468,24 +1488,12 @@ def set_selection(self, layer, values_list, field_name=None):
# Obtenim els camps de la capa
dp = layer.dataProvider()
- # CANVIS QGIS2
- ##fields_names = [f.name() for f in dp.fields().values()]
fields_names = [f.name() for f in dp.fields().toList()]
if field_name not in fields_names:
return False
- field_index = fields_names.index(field_name)
- fields_ids = list(dp.fields())
- field_id = fields_ids[field_index]
-
- # Obtenim la llista d'elements seleccionats
- selected_features = []
- for feature in layer.getFeatures():
- field_value = feature[field_index]
- if field_value in values_list:
- selected_features.append(feature.id())
-
- # Seleccionem els elements filtrats
- layer.selectByIds(selected_features)
+ # Seleccionem pel camp indicat
+ expression_filter = "\"%s\" IN ('%s')" % (field_name, "', '".join([str(v).replace("\\", "\\\\") for v in values_list]))
+ layer.selectByExpression(expression_filter)
return True
def zoom_to_selection_by_id(self, layer_idprefix, scale=None, pos=0):
@@ -1928,29 +1936,33 @@ def get_category_nodes(self, layer):
# if not show:
# self.set_visible(layer, False)
- def classification_ranges_by_id(self, layer_basename, class_attribute, ranges_list, color_list=None, border_color_list=None, transparency_list=None, width_list=None, pos=0):
+ def classification_ranges_by_id(self, layer_basename, class_attribute, ranges_list, color_list=None, border_color_list=None, transparency_list=None, width_list=None, pos=0, suffix=None):
""" Classifica els valors d'una capa per id segons la llista de rang de valors.
Addicionalment se li pot passar una llista de colors, transparencia o amplada a aplicar
(si és més curta que el nombre de valors, es repetiran colors utilitzant l'operador de mòdul)
+ suffix permet afegir un text al final de l'etiqueta de cada categoria (p.e.: unitats)
---
Classify the values of a layer by id according to the list of value ranges.
Additionally you can pass a list of colors to apply, transparency or width
(if it is shorter than the number of values, colors will be repeated using module operator)
+ suffix allows the user to append a text to each of the categories (e.g.: units)
"""
layer = self.get_by_id(layer_basename, pos)
if not layer:
return False
- self.classification_ranges(layer, class_attribute, ranges_list, color_list, border_color_list, transparency_list, width_list)
+ self.classification_ranges(layer, class_attribute, ranges_list, color_list, border_color_list, transparency_list, width_list, suffix)
return True
- def classification_ranges(self, layer, class_attribute, ranges_list, color_list=None, border_color_list=None, transparency_list=None, width_list=None):
+ def classification_ranges(self, layer, class_attribute, ranges_list, color_list=None, border_color_list=None, transparency_list=None, width_list=None, suffix=None):
""" Classifica els valors d'una capa segons la llista de rang de valors.
Addicionalment se li pot passar una llista de colors, transparencia o amplada a aplicar
(si és més curta que el nombre de valors, es repetiran colors utilitzant mòdul)
+ suffix permet afegir un text al final de l'etiqueta de cada categoria (p.e.: unitats)
---
Classify the values of a layer according to the list of value ranges.
Additionally you can pass a list of colors to apply, transparency or width
(if it is shorter than the number of values, colors will be repeated using module operator)
+ suffix allows the user to append a text to each of the categories (e.g.: units)
"""
# Afegim un categoria per cada data
renderers_list = []
@@ -1971,7 +1983,9 @@ def classification_ranges(self, layer, class_attribute, ranges_list, color_list=
symbol.setSize(width)
else:
symbol.setWidth(width)
- label = f"{begin_value} - {end_value}"
+ label = f"{begin_value} - {end_value}" if begin_value != end_value else str(end_value)
+ if suffix:
+ label += f" {suffix}"
renderers_list.append(QgsRendererRange(begin_value, end_value, symbol, label))
# Assignem la visualització per rangs a la capa
@@ -1986,7 +2000,7 @@ def classification_ranges(self, layer, class_attribute, ranges_list, color_list=
if not show:
self.set_visible(layer, False)
- def classify_by_id(self, layer_idprefix, class_attribute=None, values_list=None, color_list=None, border_color_list=None, expand=None, width=None, size=None, alpha=None, use_current_symbol=True, base_symbol=None, label_function=None, alpha_fill=None, sort=False, interpolate_colors=False, pos=0):
+ def classify_by_id(self, layer_idprefix, class_attribute=None, values_list=None, color_list=None, border_color_list=None, expand=None, width=None, size=None, opacity=None, use_current_symbol=True, base_symbol=None, label_function=None, alpha=None, sort=False, interpolate_colors=False, pos=0):
""" Classifica els valors d'una capa per id segons la llista de valors i un camp de la capa.
layer: capa a processar
class_attribute: si no s'especifica, assumim que es vol partir de la classificació anterior
@@ -1998,8 +2012,8 @@ def classify_by_id(self, layer_idprefix, class_attribute=None, values_list=None,
use_current_symbol: utilitza la simbolització actual canviant els colors
base_symbol: simbol base a utilitzar canviant els colors
label_function: genera una etiqueta a partir del valor de la categoria (p.e.: canvia representació de dates: lambda x: x.toPyDate())
- alpha: aplica transparència
- alpha_fill: aplica transparència només a l'emplenament (p.e.: ressalta el borde dels footprints amb transparència)
+ opacity: aplica opacitat a tot el símbol. Rang entre 0 (transparent) i 1 (opac)
+ alpha: aplica transparència al color de l'emplenament. Rang entre 0 (transparent) i 1 (opac)
expand: expandeix la llegenda de la capa
sort: ordena les categories
pos: index de la capa amb layer_idprefix a processar
@@ -2015,8 +2029,8 @@ def classify_by_id(self, layer_idprefix, class_attribute=None, values_list=None,
use_current_symbol: use current symbol changing colors
base_symbol: use this symbol changing colors
label_function: generate a label from a category value (e.g.: tune representation of dates: lambda x: x.toPyDate())
- alpha: set transparency
- alpha_fill: set transparency only to the fill (e.g.: highlight borders when footprints have transparency)
+ opacity: set opacity for the symbol. Range between 0 (fully transparent) and 1 (fully opaque)
+ alpha: set transparency only to the fill color. Range between 0 (fully transparent) and 1 (fully opaque)
expand: expand layer legend
sort: sort categories
pos: index of layer with layer_idprefix to process
@@ -2024,10 +2038,10 @@ def classify_by_id(self, layer_idprefix, class_attribute=None, values_list=None,
layer = self.get_by_id(layer_idprefix, pos)
if not layer:
return False
- self.classify(layer, class_attribute, values_list, color_list, border_color_list, expand, width, size, alpha, use_current_symbol, base_symbol, label_function, alpha_fill, sort, ininterpolate_colors)
+ self.classify(layer, class_attribute, values_list, color_list, border_color_list, expand, width, size, opacity, use_current_symbol, base_symbol, label_function, alpha, sort, ininterpolate_colors)
return True
- def classify(self, layer, class_attribute=None, values_list=None, color_list=None, border_color_list=None, expand=None, width=None, size=None, alpha=None, use_current_symbol=True, base_symbol=None, label_function=None, alpha_fill=None, sort=False, interpolate_colors=False):
+ def classify(self, layer, class_attribute=None, values_list=None, color_list=None, border_color_list=None, expand=None, width=None, size=None, opacity=None, use_current_symbol=True, base_symbol=None, label_function=None, alpha=None, sort=False, interpolate_colors=False):
""" Classifica els valors d'una capa segons la llista de valors i un camp de la capa.
layer: capa a processar
class_attribute: si no s'especifica, assumim que es vol partir de la classificació anterior
@@ -2040,8 +2054,8 @@ def classify(self, layer, class_attribute=None, values_list=None, color_list=Non
use_current_symbol: utilitza la simbolització actual canviant els colors
base_symbol: simbol base a utilitzar canviant els colors
label_function: genera una etiqueta a partir del valor de la categoria (p.e.: canvia representació de dates: lambda x: x.toPyDate())
- alpha: aplica transparència
- alpha_fill: aplica transparència només a l'emplenament (p.e.: ressalta el borde dels footprints amb transparència)
+ opacity: aplica opacitat al símbol. Rang entre 0 (transparent) i 1 (opac)
+ alpha: aplica transparència al color de l'emplenament. Rang entre 0 (transparent) i 1 (opac)
expand: expandeix la llegenda de la capa
sort: ordena les categories
---
@@ -2057,8 +2071,8 @@ def classify(self, layer, class_attribute=None, values_list=None, color_list=Non
use_current_symbol: use current symbol changing colors
base_symbol: use this symbol changing colors
label_function: generate a label from a category value (e.g.: tune representation of dates: lambda x: x.toPyDate())
- alpha: set transparency
- alpha_fill: set transparency only to the fill (e.g.: highlight borders when footprints have transparency)
+ opacity: set opacity for the symbol. Range between 0 (fully transparent) and 1 (fully opaque)
+ alpha: set transparency only to the fill color. Range between 0 (fully transparent) and 1 (fully opaque)
expand: expand layer legend
sort: sort categories
"""
@@ -2069,10 +2083,11 @@ def classify(self, layer, class_attribute=None, values_list=None, color_list=Non
if use_current_symbol:
# Prioritzem el símbol base de la capa. Si no està definit, agafem el de la primera categoria
renderer = layer.renderer()
- if len(renderer.symbols(QgsRenderContext())):
- base_symbol = renderer.symbols(QgsRenderContext())[0].clone()
- elif hasattr(renderer, 'sourceSymbol') and renderer.sourceSymbol():
- base_symbol = renderer.sourceSymbol().clone()
+ if renderer:
+ if len(renderer.symbols(QgsRenderContext())):
+ base_symbol = renderer.symbols(QgsRenderContext())[0].clone()
+ elif hasattr(renderer, 'sourceSymbol') and renderer.sourceSymbol():
+ base_symbol = renderer.sourceSymbol().clone()
# Recupera el renderer o crea un de nou
if hasattr(layer.renderer(), 'categories'):
@@ -2152,12 +2167,12 @@ def classify(self, layer, class_attribute=None, values_list=None, color_list=Non
if border_color:
# pinta les línies
symbol.symbolLayer(0).setStrokeColor(border_color)
- if alpha is not None:
+ if opacity is not None:
# aplica transparència al símbol sencer
- symbol.setOpacity(alpha)
- if alpha_fill is not None:
+ symbol.setOpacity(opacity)
+ if alpha is not None:
# aplica transparència a l'emplenament
- color.setAlpha(alpha_fill*100)
+ color.setAlphaF(alpha)
symbol.symbolLayer(0).setFillColor(color)
if width is not None:
if type(symbol) == QgsFillSymbol:
@@ -3573,7 +3588,7 @@ def add_remote_vector_files(self, remote_files_list, download_folder=None, group
# Retornem la última capa
return layers_list
- def add_wms_t_layer(self, layer_name, url, layer_id, style, image_format, time_series_list=None, epsg=None, extra_tags="", group_name="", group_pos=None, only_one_map_on_group=False, collapsed=True, visible=True, transparency=None, saturation=None, resampling_bilinear=False, resampling_cubic=False, set_current=False):
+ def add_wms_t_layer(self, layer_name, url, layer_id=None, default_time=None, style="default", image_format="image/png", time_series_list=None, epsg=None, extra_tags="", group_name="", group_pos=None, only_one_map_on_group=False, collapsed=True, visible=True, transparency=None, saturation=None, resampling_bilinear=False, resampling_cubic=False, set_current=False):
""" Afegeix una capa WMS-T a partir de la URL base i una capa amb informació temporal.
Veure add_wms_layer per la resta de paràmetres
---
@@ -3583,22 +3598,25 @@ def add_wms_t_layer(self, layer_name, url, layer_id, style, image_format, time_s
# Obtenim la llista de capes temporals i la registrem associada a la url
if time_series_list:
if url:
- default_time = dict([(layer_id, time_name) for (time_name, layer_id) in time_series_list])[layer_id]
+ if not default_time:
+ default_time = dict([(layer_id, time_name) for (time_name, layer_id) in time_series_list])[layer_id]
default_layer = layer_id
url_time = url
else:
- default_time = layer_id
+ if not default_time:
+ default_time = layer_id
default_layer = layer_id
url_time = dict(time_series_list)[default_layer]
else:
- time_series_list, default_time = self.get_wms_t_time_series(url, layer_id)
+ time_series_list, default_time2 = self.get_wms_t_time_series(url, layer_id)
if not time_series_list:
return None
+ default_time = default_time or default_time2
if not default_time:
default_time = time_series_list[-1][0]
default_layer = dict(time_series_list)[default_time]
is_question_mark = url.find("?") >= 0
- url_time = "%s%stime=%s&IgnoreGetMapUrl=1" % (url, "%26" if is_question_mark else "?", default_time)
+ url_time = "%s%stime=%s" % (url, "%26" if is_question_mark else "?", default_time)
# Obtenim el nom del temps per defecte i creem la capa
time_layer_name = "%s [%s]" % (layer_name, default_time)
@@ -3775,6 +3793,7 @@ def add_wms_layer(self, layer_name, url, layers_list, styles_list, image_format,
uri = "url=%s&crs=EPSG:%s&format=%s&styles=%s&layers=%s" % (url, epsg, image_format, "&styles=".join(styles_list), "&layers=".join(layers_list))
if extra_tags:
uri += "&%s" % extra_tags
+ uri += "&IgnoreGetMapUrl=1"
return self.add_raster_uri_layer(layer_name, uri, "wms", group_name, group_pos, only_one_map_on_group, only_one_visible_map_on_group, collapsed, visible, transparency, saturation, set_current)
@@ -3786,33 +3805,60 @@ def add_wms_url_query_layer(self, layer_name, url_query, group_name="", group_po
See add_wms_layer for options
"""
uri = "url=%s" % url_query.lower().replace("epsg:", "epsg:").replace("srs=", "crs=").replace("?", "&")
+ uri += "&IgnoreGetMapUrl=1"
return self.add_raster_uri_layer(layer_name, uri, "wms", group_name, group_pos, only_one_map_on_group, only_one_visible_map_on_group, collapsed, visible, transparency, saturation, set_current)
- def update_wms_layer(self, layer, wms_layer, wms_time=None):
+ def update_wms_layer(self, layer, wms_layer=None, wms_time=None, wms_style=None):
""" Actualitza la capa a llegir d'un servidor WMS
---
Update WMS layer to read
"""
- ##print("update wms layer", wms_layer, wms_time)
-
# Obtenim la capa actual carregada
url, current_layer, current_time = self.parse_wms_t_layer(layer)
+ current_style = None
if url and current_layer:
# Actualitzem la capa a WMS carregar (pot ser un canvi de capa (fals WMS-T) o un canvi de temps)
- new_uri = layer.dataProvider().dataSourceUri()
- new_uri = new_uri.replace("layers=%s" % current_layer, "layers=%s" % wms_layer)
+ if self.parent.check_qgis_version(31600):
+ # Incompatible with version 3.4 and 3.10 (not update value)
+ new_uri = layer.source()
+ else:
+ new_uri = layer.dataProvider().dataSourceUri()
+ if wms_layer:
+ new_uri = new_uri.replace("layers=%s" % current_layer, "layers=%s" % wms_layer)
if wms_time:
new_uri = new_uri.replace("time=%s" % (current_time), "time=%s" % (wms_time))
- layer.dataProvider().setDataSourceUri(new_uri)
+ if wms_style:
+ found = re.search(r"(styles=[^&]+)", new_uri, re.IGNORECASE)
+ if found:
+ current_style = found.groups()[0]
+ new_uri = new_uri.replace(current_style, "styles=%s" % wms_style)
+ else:
+ new_uri += "&styles=%s" % wms_style
else:
# Si tenim un fals WMS-T amb link a arxius raster, cal fer més refrescos...
new_uri = wms_layer
+
+ if self.parent.check_qgis_version(31600):
+ # Incompatible with version 3.4 and 3.10 (not updated)
+ layer.setDataSource(new_uri, layer.name(), "WMS", layer.dataProvider().ProviderOptions())
+ else:
layer.dataProvider().setDataSourceUri(new_uri)
layer.dataProvider().reloadData()
layer.reload()
+ layer.triggerRepaint()
- layer.triggerRepaint()
+ def is_anaglyph_layer(self, layer):
+ """ Retorna si una capa té informació WMS anaglif
+ ---
+ Returns layer is WMS anaglyph
+ """
+ uri = layer.source()
+ found = re.search(r"(styles=[^&]+)", uri.lower(), re.IGNORECASE)
+ if not found:
+ return False
+ anaglyph_params = found.groups()[0].split(",")
+ return len(anaglyph_params) == 3
def add_raster_uri_layer(self, layer_name, uri, provider, group_name="", group_pos=None, only_one_map_on_group=False, only_one_visible_map_on_group=True, collapsed=True, visible=True, transparency=None, saturation=None, set_current=False):
""" Afegeix una capa raster a partir d'un URI i proveidor de dades (wms, oracle ...). Retorna la capa.
@@ -3896,12 +3942,11 @@ def add_wfs_layer(self, layer_name, url, layers_list, epsg=None, filter=None, ex
if not epsg:
epsg = self.parent.project.get_epsg()
separator = "&" if url.find("?") >= 0 else "?"
- uri = "%s%sservice=WFS&version=%s&request=GetFeature&typename=%s&srsname=EPSG:%s" % (url, separator, version, ",".join(layers_list), epsg)
+ uri = "url=%s%sservice=WFS&version=%s&request=GetFeature&typename=%s&srsname=EPSG:%s" % (url, separator, version, ",".join(layers_list), epsg)
if extra_tags:
uri += "&%s" % extra_tags
ds_uri = QgsDataSourceUri()
ds_uri.setEncodedUri(uri)
- ds_uri.setParam('url', url)
# Apliquem un filtrat si cal
if filter:
ds_uri.setSql(filter)
@@ -4706,11 +4751,15 @@ def get_composition(self, report_pathname, atlas_layer=None, atlas_filter=None,
if os.path.splitext(report_pathname)[1].lower() != '.qpt':
report_pathname += '.qpt'
with open(report_pathname, "r") as template_file:
- template_content = template_file.read()
- document = QDomDocument()
- document.setContent(template_content)
+ report_content = template_file.read()
+ # Modifiquem els path relatius a paths absoluts a memòria
+ report_path = os.path.dirname(report_pathname).replace("\\", "/")
+ report_content = report_content.replace('"./', '"%s/' % report_path)
+ report_content = report_content.replace('"../', '"%s/../' % report_path)
# Creem l'objecte de l'informe
+ document = QDomDocument()
+ document.setContent(report_content)
layout = QgsPrintLayout(QgsProject.instance())
layout.loadFromTemplate(document, QgsReadWriteContext(), True)
@@ -5073,6 +5122,7 @@ def __init__(self, parent):
# Diàlegs auxiliars i gestió de time series
self.transparency_dialog = None
self.time_series_dialog = None
+ self.anaglyph_dialog = None
# Map change current layer event
self.iface.layerTreeView().currentLayerChanged.connect(self.on_change_current_layer)
@@ -5093,6 +5143,10 @@ def remove(self):
self.transparency_dialog.close()
self.iface.removeDockWidget(self.transparency_dialog)
self.transparency_dialog = None
+ if self.anaglyph_dialog:
+ self.anaglyph_dialog.close()
+ self.iface.removeDockWidget(self.anaglyph_dialog)
+ self.anaglyph_dialog = None
def add_shortcut_QGIS_options(self, description = "Eines QGIS", keyseq = "Ctrl+Alt+F12"):
""" Afegeix un shortcut per mostrar / ocultar els menús / toolbars de QGIS
@@ -5102,7 +5156,7 @@ def add_shortcut_QGIS_options(self, description = "Eines QGIS", keyseq = "Ctrl+A
#Creem un shortcut per activer les opcions per defecte de QGIS
self.parent.gui.add_shortcut(description, keyseq, self.toggle_QGIS_options)
- def toggle_QGIS_options(self, hide_not_remove = None):
+ def toggle_QGIS_options(self, hide_not_remove=None):
""" Mostra / Oculta els menús / toolbars de QGIS (canvia l'estat previ)
---
Show / Hide QGIS menus / toolbars (change previous state)
@@ -5233,18 +5287,23 @@ def add_tool_reload_plugins(self, tool_name = "&Recarregar plugins ICGC", toolba
(tool_name, lambda p = plugins_id_wildcard : self.parent.debug.reload_plugins(p), QIcon(":/lib/qlib3/base/images/python.png"))
])
- def add_tool_refresh_map_and_legend(self, tool_name, remove_refresh_map):
+ def add_tool_refresh_map_and_legend(self, tool_name, remove_refresh_map, id="ToolRefreshMapAndLegend"):
""" Afegeix o actualitza el botó de refresc per actualitzar també la llegenda
---
Add or refresh the refresh button to also update the legend
"""
- self.action_refresh_all = QAction(QIcon(":/lib/qlib3/base/images/refresh_all.png"), tool_name, self.iface.mainWindow())
- self.action_refresh_all.triggered.connect(self.parent.refresh_all)
- # Afegim el botó de la eina a la toolbar
- if remove_refresh_map:
- self.iface.mapNavToolToolBar().removeAction(self.iface.mapNavToolToolBar().actions()[-1])
- if self.action_refresh_all.text() not in [a.text() for a in self.iface.mapNavToolToolBar().actions()]:
+ self.action_refresh_all = self.parent.gui.find_action(id, self.iface.mapNavToolToolBar().actions())
+ # Si no existeix creem l'acció
+ if not self.action_refresh_all:
+ self.action_refresh_all = QAction(QIcon(":/lib/qlib3/base/images/refresh_all.png"), tool_name, self.iface.mainWindow())
+ self.action_refresh_all.setObjectName(id)
+ self.action_refresh_all.triggered.connect(self.parent.refresh_all)
+ # Afegim el botó de la eina a la toolbar
+ if remove_refresh_map:
+ self.iface.mapNavToolToolBar().removeAction(self.iface.mapNavToolToolBar().actions()[-1])
self.iface.mapNavToolToolBar().addAction(self.action_refresh_all)
+ # Registro l'acció perquè el destructor del plugin l'esborri automàticament al descarregar-lo
+ self.parent.gui.actions.append((self.iface.mapNavToolToolBar(), self.action_refresh_all))
def show_transparency_dialog(self, title=None, layer=None, transparency=None, show=True):
""" Mostra un diàleg simplificat per escollir la transparència d'una capa
@@ -5266,7 +5325,7 @@ def show_transparency_dialog(self, title=None, layer=None, transparency=None, sh
else:
self.transparency_dialog.hide()
- def toggle_transparency_dialog(self, title=None, layer=None, transparency=None, show=True):
+ def toggle_transparency_dialog(self, title=None, layer=None, transparency=None):
self.show_transparency_dialog(title, layer, transparency, not self.transparency_dialog.isVisible() if self.transparency_dialog else True)
def show_time_series_dialog(self, layer, title=None, current_prefix="", show=True):
@@ -5312,9 +5371,55 @@ def show_time_series_dialog(self, layer, title=None, current_prefix="", show=Tru
if self.time_series_dialog:
self.time_series_dialog.hide()
- def toggle_time_series_dialog(self, layer, title=None, current_prefix="", show=True):
+ def toggle_time_series_dialog(self, layer, title=None, current_prefix=""):
self.show_time_series_dialog(layer, title, current_prefix, not self.time_series_dialog.isVisible() if self.time_series_dialog else True)
+ def show_anaglyph_dialog(self, layer=None, title=None, parallax_label="", inverted_stereo_label="", show=True):
+ # Mostrem o ocultem el diàleg de sèries temporals
+ if show:
+ if not layer:
+ layer = self.parent.layers.get_current_layer()
+ # Obtenim els valors de paral·laxi
+ photo_id = "dummy"
+ parallax = 100
+ inverted_stereo = False
+ found = re.search(r"styles=([^&]+)", layer.dataProvider().uri().uri().lower())
+ if found:
+ anaglyph_params_list = found.groups()[0].split(",")
+ if len(anaglyph_params_list) == 3:
+ photo_id = anaglyph_params_list[0]
+ parallax = int(anaglyph_params_list[1])
+ inverted_stereo = anaglyph_params_list[2] == "true"
+ # Si no tenim el diàleg el creem i el mostrem
+ update_callback = lambda parallax, inverted_stereo: self.parent.layers.update_wms_layer(layer, wms_style=",".join([photo_id, str(parallax), "true" if inverted_stereo else "false"]))
+ if not self.anaglyph_dialog:
+ self.anaglyph_dialog = AnaglyphDialog(layer.name(), update_callback, parallax, inverted_stereo,
+ title, parallax_label, inverted_stereo_label, True, self.iface.mainWindow())
+ self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.anaglyph_dialog)
+ # Mapegem l'event de visibilitat per detectar quan tanquin el widget i poder refrescar
+ # algun botó si cal... en principi això està implementat en l'event de canvi de capa
+ # (que detecta si es tracta d'una capa WMS-T o no) per això emeto un un signal perquè
+ # s'executi
+ #self.anaglyph_dialog.visibilityChanged.connect(lambda dummy:self.iface.layerTreeView().currentLayerChanged.emit(self.iface.mapCanvas().currentLayer()))
+ else:
+ # Configurem el diàleg
+ if title:
+ self.anaglyph_dialog.setWindowTitle(title)
+ if layer:
+ self.anaglyph_dialog.update_title(layer.name())
+ self.anaglyph_dialog.set_callback(update_callback)
+ self.anaglyph_dialog.set_anaglyph(parallax, inverted_stereo)
+ # Mostrem el diàleg
+ self.anaglyph_dialog.show()
+ # Activem els controls
+ self.anaglyph_dialog.set_enabled(self.parent.layers.is_anaglyph_layer(layer))
+ else:
+ if self.anaglyph_dialog:
+ self.anaglyph_dialog.hide()
+
+ def toggle_anaglyph_dialog(self, layer, title=None, current_prefix=""):
+ self.show_anaglyph_dialog(layer, title, current_prefix, not self.anaglyph_dialog.isVisible() if self.anaglyph_dialog else True)
+
def on_change_current_layer(self, layer):
""" Activa o desactiva les opcions de sèries temporals / transparència segons la capa seleccionada
---
@@ -5330,6 +5435,12 @@ def on_change_current_layer(self, layer):
if self.transparency_dialog:
if self.transparency_dialog.isVisible():
self.show_transparency_dialog(layer=layer)
+ # Refresh anaglyph dialog
+ if self.anaglyph_dialog:
+ is_anaglyph = layer is not None and self.parent.layers.is_anaglyph_layer(layer)
+ self.anaglyph_dialog.set_enabled(is_anaglyph)
+ if is_anaglyph and self.anaglyph_dialog.isVisible():
+ self.show_anaglyph_dialog(layer=layer)
def on_layer_removed(self, layer):
if self.parent and self.parent.layers and self.parent.layers.time_series_dict:
@@ -5415,8 +5526,12 @@ def send_email(self, mail_to, subject="", body="", copy_to="", hidden_copy_to=""
Send email using system email client
"""
QDesktopServices.openUrl(
- QUrl("mailto:%s?subject=%s&body=%s&cc=%s&bcc=%s" % (
- mail_to, subject or " ", body or " ", copy_to or " ", hidden_copy_to or " "
+ QUrl("mailto:%s?subject=%s%s%s%s" % (
+ mail_to,
+ subject or " ",
+ ("&body=%s" % body) if body else "",
+ ("&cc=%s" % copy_to) if copy_to else "",
+ ("&bcc=%s" % hidden_copy) if hidden_copy_to else "",
), QUrl.TolerantMode))
@@ -5795,25 +5910,30 @@ def refresh_all(self):
self.layers.refresh_attributes_tables()
self.legend.refresh_legend()
- def set_map_point(self, x, y, epsg=None, scale=None):
+ def set_map_point(self, x, y, epsg=None, scale=5000):
""" Situa el mapa en les coordenades indicades a una determinada escala a partir d'un punt central.
Reprojecta la coordenada al sistema de projecte si cal
---
Locate the map in the coordinates indicated on a given scale from a central point.
Reproject the coordinate to the project reference system if necessary
"""
- print("Coordinate: %s %s EPSG:%s" % (x, y, epsg))
+ # Cal, transformem les coordenades al sistema del projecte
+ #print("Coordinate: %s %s EPSG:%s" % (x, y, epsg))
+ if epsg and epsg != int(self.project.get_epsg()):
+ x, y = self.crs.transform_point(x, y, epsg)
+ #print("Coordinate: %s %s EPSG:%s" % (x, y, self.project.get_epsg()))
- # Detectem si estem en geogràfiques o no i configurem la escala
- if not scale:
- scale = 0.01 if x < 100 else 1000
+ ## Detectem si estem en geogràfiques o no i configurem la escala
+ #if not scale:
+ # scale = 0.01 if x < 100 else 1000
- # Calculem el rectangle a visualitzar
- west = x-scale/2
- south = y-scale/2
- east = x+scale/2
- north = y+scale/2
- self.set_map_rectangle(west, north, east, south, epsg)
+ # Situem el centre del mapa i la escala
+ mc = self.iface.mapCanvas()
+ mc.setCenter(QgsPointXY(x, y))
+ if scale:
+ mc.zoomScale(scale)
+ else:
+ mc.refresh()
def set_map_rectangle(self, west, north, east, south, epsg=None):
""" Situa el mapa en les coordenades indicades pel rectangle.
@@ -5823,10 +5943,11 @@ def set_map_rectangle(self, west, north, east, south, epsg=None):
Reproject the coordinates to the project reference system if necessary
"""
# Cal, transformem les coordenades al sistema del projecte
+ #print("Rectangle: %s %s %s %s EPSG:%s" % west, north, east, south, epsg)
if epsg and epsg != int(self.project.get_epsg()):
west, north = self.crs.transform_point(west, north, epsg)
east, south = self.crs.transform_point(east, south, epsg)
- print("Rectangle: %s %s %s %s EPSG:%s" % (west, north, east, south, self.project.get_epsg()))
+ #print("Rectangle: %s %s %s %s EPSG:%s" % (west, north, east, south, self.project.get_epsg()))
# Resituem el mapa
rect = QgsRectangle(west, south, east, north) # minx, miny, maxx, maxy
@@ -5834,6 +5955,10 @@ def set_map_rectangle(self, west, north, east, south, epsg=None):
mc.setExtent(rect)
mc.refresh()
+ def check_qgis_version(self, version):
+ """ Checks QGIS version is greater than or equal to the one indicated (31004, 30400, 31600, ...) """
+ return Qgis.QGIS_VERSION_INT >= version
+
def get_settings(self, group_name=None):
self.settings.beginGroup(group_name or self.plugin_id)
settings_dict = dict([(key, self.settings.value(key, None)) for key in self.settings.childKeys()])
@@ -5862,3 +5987,26 @@ def set_setting_value(self, key, value, group_name=None):
else:
self.settings.setValue(key, value)
self.settings.endGroup();
+
+ #def get_setting_list(self, key, group_name=None):
+ # values_list = []
+ # self.settings.beginGroup(group_name or self.plugin_id)
+ # count = self.settings.beginReadArray(key)
+ # for i in range(count):
+ # self.settings.setArrayIndex(i)
+ # values_list.append(self.settings.value(key))
+ # self.settings.endArray()
+ # self.settings.endGroup();
+ # return values_list
+
+ #def set_setting_list(self, key, values_list, group_name=None):
+ # self.settings.beginGroup(group_name or self.plugin_id)
+ # if not values_list:
+ # self.settings.remove(key)
+ # else:
+ # self.settings.beginWriteArray(key, len(values_list))
+ # for i, value in enumerate(values_list):
+ # self.settings.setArrayIndex(i)
+ # self.settings.setValue(key, value)
+ # self.settings.endArray()
+ # self.settings.endGroup();
diff --git a/qlib3/base/timeseriesdialog.py b/qlib3/base/timeseriesdialog.py
index 49cedf5..ad55fdd 100644
--- a/qlib3/base/timeseriesdialog.py
+++ b/qlib3/base/timeseriesdialog.py
@@ -1,165 +1,122 @@
-# -*- coding: utf-8 -*-
-"""
-*******************************************************************************
-Mòdul amb classe diàleg gestionar series temporals de dades
----
-Module with a dialog class to manage temporal series
-
- -------------------
- begin : 2019-01-18
- author : Albert Adell
- email : albert.adell@icgc.cat
-*******************************************************************************
-"""
-
-import os
-
-from PyQt5 import uic
-from PyQt5.QtGui import QPainter, QPen, QFont
-from PyQt5.QtCore import Qt, QPoint
-from PyQt5.QtWidgets import QDockWidget, QSlider, QApplication, QStyleOptionSlider, QToolTip
-
-Ui_TimeSeries, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_timeseries.ui'))
-
-
-#class MySlider(QSlider):
-# def __init__(self, parent=None):
-# super().__init__(parent)
-# self.style = QApplication.style()
-# self.opt = QStyleOptionSlider()
-# self.tip_offset = QPoint(10, 10)
-# self.valueChanged.connect(self.show_tip)
-# #self.enterEvent = self.show_tip
-# #self.mouseReleaseEvent = self.show_tip
-
-# def paintEvent(self, event):
-# """Paint log scale ticks"""
-# super().paintEvent(event)
-# qp = QPainter(self)
-# pen = QPen()
-# pen.setWidth(2)
-# pen.setColor(Qt.black)
-
-# qp.setPen(pen)
-# font = QFont('Times', 10)
-# font_y_offset = font.pointSize()/2
-# qp.setFont(font)
-# size = self.size()
-# contents = self.contentsRect()
-# db_val_list = [10, 5, 0, -5, -10, -20, -30, -40, -50, -60, -90]
-# for val in db_val_list:
-# if val == 10:
-# y_val_fudge = 12
-# elif val == -90:
-# y_val_fudge = -12
-# ##db_scaled = db_to_int(val)
-# db_scaled = int(val)
-# y_val = contents.height() - translate(db_scaled, 0, 1023, 0, contents.height())
-# if val == -90:
-# qp.drawText(contents.x() - font.pointSize(), y_val + font_y_offset + y_val_fudge, '-oo')
-# else:
-# qp.drawText(contents.x() - font.pointSize(), y_val + font_y_offset + y_val_fudge,'{0:2}'.format(val))
-# qp.drawLine(contents.x() + font.pointSize(), y_val + y_val_fudge, contents.x() + contents.width(), y_val + y_val_fudge)
-
-# def show_tip(self, _):
-# #self.initStyleOption(self.opt)
-# #rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt, self.style.SC_SliderHandle, self)
-# rectHandle = self.style.subControlRect(self.style.CC_Slider, None, self.style.SC_SliderHandle, self)
-# pos_local = rectHandle.topLeft() + self.tip_offset
-# pos_global = self.mapToGlobal(pos_local)
-# QToolTip.showText(pos_global, str(self.value()), self)
-
-class TimeSeriesDialog(QDockWidget, Ui_TimeSeries):
- """ Classe diàleg per mostrar informació bàsica del plugin i logo el ICGC
- ---
- Class to display basic information of plugin and ICGC logo
- """
-
- layer = None
- time_series_list = []
-
- def __init__(self, time_series_list, current_time, layer_name, update_callback=None, title=None, current_label="", autoshow=True, parent=None):
- """ Inicialització del diàleg "about", cal informar de:
- - title: Títol del diàleg
- - layer: capa a modificar
- - time_series_list: Llista de dates disponibles
- Opcionalment:
- - autoshow: Mostra el diàleg automàticament al crear-lo
- - parent: Especifica la finestra pare del diàleg
- ---
- Initialization of the "about" dialog, you need to report:
- - title: Title of the dialog
- - layer: layer to modify
- - time_series_list: List of available dates
- Optionally:
- - autoshow: Show the dialog automatically when you create it
- - parent: Specifies the parent window of the dialog
- """
- super().__init__(parent)
- self.setupUi(self)
-
- # Etiqueta opcional pel valors seleccionat
- self.current_value_prefix = current_label
-
- # Canviem el títol i la icona
- if title:
- self.setWindowTitle(title)
- # Carreguem la sèrie temporal
- self.set_time_series(time_series_list, current_time, layer_name, update_callback)
-
- # Mostrem el diàleg
- if autoshow:
- self.show()
-
- def set_time_series(self, time_series_list, current_time, layer_name, update_callback):
- # Ens guardem la funció d'actualització de dades
- self.update_callback = update_callback
-
- # Actualitzem el títol amb el nom de la capa
- self.set_title(layer_name)
-
- self.time_series_list = time_series_list
- # Assignem les etiquetes
- self.label_begin.setText(time_series_list[0])
- self.label_end.setText(time_series_list[-1])
- self.label_current.setText(self.current_value_prefix + current_time)
- # Assignem el slider
- ##self.horizontalSlider = MySlider(self.horizontalSlider)
- self.horizontalSlider.setTickInterval(1)
- self.horizontalSlider.setMinimum(0)
- self.horizontalSlider.setMaximum(len(time_series_list) - 1)
- self.set_current_time(current_time)
-
- def set_title(self, layer_name):
- title = self.windowTitle().split(":")[0]
- self.setWindowTitle("%s: %s" % (title, layer_name))
-
- def set_current_time(self, current_time):
- # Canviem el valor quan és diferent de l'actual
- new_value = self.time_series_list.index(current_time)
- if self.horizontalSlider.value() != new_value:
- return self.horizontalSlider.setValue(new_value)
-
- def get_current_time(self):
- # Retornem el valor actual de la llista de time series
- return self.time_series_list[self.horizontalSlider.value()]
-
- def on_value_changed(self, value=None):
- # Modifiquem el label de temps actual
- # Si entra per event de soltar slider, no tindrem "value", per això no el faig servir
- self.label_current.setText(self.current_value_prefix + self.get_current_time())
-
- # Volem detectar només events de click o de soltar el slider
- if not self.horizontalSlider.isSliderDown():
- # Modifiquem la capa referenciada
- if self.update_callback:
- new_layer_name = self.update_callback(self.get_current_time())
- if new_layer_name:
- self.set_title(new_layer_name)
-
- def set_enabled(self, enable=True):
- # Activa o desactiva la barra temporal
- self.horizontalSlider.setEnabled(enable)
- self.label_begin.setEnabled(enable)
- self.label_end.setEnabled(enable)
- self.label_current.setEnabled(enable)
+# -*- coding: utf-8 -*-
+"""
+*******************************************************************************
+Mòdul amb classe diàleg gestionar series temporals de dades
+---
+Module with a dialog class to manage temporal series
+
+ -------------------
+ begin : 2019-01-18
+ author : Albert Adell
+ email : albert.adell@icgc.cat
+*******************************************************************************
+"""
+
+import os
+
+from PyQt5 import uic
+from PyQt5.QtGui import QPainter, QPen, QFont
+from PyQt5.QtCore import Qt, QPoint
+from PyQt5.QtWidgets import QDockWidget, QSlider, QApplication, QStyleOptionSlider, QToolTip
+
+Ui_TimeSeries, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_timeseries.ui'))
+
+
+class TimeSeriesDialog(QDockWidget, Ui_TimeSeries):
+ """ Classe diàleg per mostrar opcions de sèries temporals
+ ---
+ Class dialog to display temporal series options
+ """
+
+ layer = None
+ time_series_list = []
+
+ def __init__(self, time_series_list, current_time, layer_name, update_callback=None, title=None, current_label="", autoshow=True, parent=None):
+ """ Inicialització del diàleg "about", cal informar de:
+ - title: Títol del diàleg
+ - layer: capa a modificar
+ - time_series_list: Llista de dates disponibles
+ Opcionalment:
+ - autoshow: Mostra el diàleg automàticament al crear-lo
+ - parent: Especifica la finestra pare del diàleg
+ ---
+ Initialization of the "about" dialog, you need to report:
+ - title: Title of the dialog
+ - layer: layer to modify
+ - time_series_list: List of available dates
+ Optionally:
+ - autoshow: Show the dialog automatically when you create it
+ - parent: Specifies the parent window of the dialog
+ """
+ super().__init__(parent)
+ self.setupUi(self)
+
+ # Etiqueta opcional pel valors seleccionat
+ self.current_value_prefix = current_label
+
+ # Canviem el títol i la icona
+ if title:
+ self.setWindowTitle(title)
+ # Carreguem la sèrie temporal
+ self.set_time_series(time_series_list, current_time, layer_name, update_callback)
+
+ # Mostrem el diàleg
+ if autoshow:
+ self.show()
+
+ def set_time_series(self, time_series_list, current_time, layer_name, update_callback):
+ # Ens guardem la funció d'actualització de dades
+ self.update_callback = update_callback
+
+ # Actualitzem el títol amb el nom de la capa
+ self.set_title(layer_name)
+
+ self.time_series_list = time_series_list
+ # Assignem les etiquetes
+ self.label_begin.setText(time_series_list[0])
+ self.label_end.setText(time_series_list[-1])
+ self.label_current.setText(self.current_value_prefix + current_time)
+ # Assignem el slider
+ ##self.horizontalSlider = MySlider(self.horizontalSlider)
+ self.horizontalSlider.setTickInterval(1)
+ self.horizontalSlider.setMinimum(0)
+ self.horizontalSlider.setMaximum(len(time_series_list) - 1)
+ self.set_current_time(current_time)
+
+ def set_title(self, layer_name):
+ title = self.windowTitle().split(":")[0]
+ self.setWindowTitle("%s: %s" % (title, layer_name))
+
+ def set_current_time(self, current_time):
+ # Canviem el valor quan és diferent de l'actual
+ new_value = self.time_series_list.index(current_time)
+ if self.horizontalSlider.value() != new_value:
+ return self.horizontalSlider.setValue(new_value)
+
+ def get_current_time(self):
+ # Retornem el valor actual de la llista de time series
+ return self.time_series_list[self.horizontalSlider.value()]
+
+ def on_value_changed(self, value=None):
+ # Modifiquem el label de temps actual
+ # Si entra per event de soltar slider, no tindrem "value", per això no el faig servir
+ self.label_current.setText(self.current_value_prefix + self.get_current_time())
+
+ # Volem detectar només events de click o de soltar el slider
+ if not self.horizontalSlider.isSliderDown():
+ # Modifiquem la capa referenciada
+ if self.update_callback:
+ new_layer_name = self.update_callback(self.get_current_time())
+ if new_layer_name:
+ self.set_title(new_layer_name)
+
+ def set_enabled(self, enable=True):
+ # Activa o desactiva la barra temporal
+ self.horizontalSlider.setEnabled(enable)
+ self.label_begin.setEnabled(enable)
+ self.label_end.setEnabled(enable)
+ self.label_current.setEnabled(enable)
+ # Canviem el color de la barra del slider i el títol del diàleg quan està desactivat
+ self.horizontalSlider.setStyleSheet("" if enable else "selection-background-color: gray")
+ self.setStyleSheet("" if enable else "color: gray")
+
diff --git a/qlib3/base/ui_anaglyph.ui b/qlib3/base/ui_anaglyph.ui
new file mode 100644
index 0000000..02d7e44
--- /dev/null
+++ b/qlib3/base/ui_anaglyph.ui
@@ -0,0 +1,164 @@
+
+
+ DockWidget
+
+
+
+ 0
+ 0
+ 394
+ 100
+
+
+
+
+ 374
+ 100
+
+
+
+
+ 524287
+ 100
+
+
+
+ DockWidget
+
+
+
+ -
+
+
-
+
+
-
+
+
+ -20%
+
+
+
+ -
+
+
+
+ 0
+ 30
+
+
+
+ 0
+
+
+ 10
+
+
+ 1
+
+
+ 1
+
+
+ 5
+
+
+ 5
+
+
+ Qt::Horizontal
+
+
+ false
+
+
+ QSlider::TicksBelow
+
+
+
+ -
+
+
+ +20%
+
+
+
+
+
+ -
+
+
-
+
+
+ Parallax: +0%
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+ Inverted stereo
+
+
+
+
+
+
+
+
+
+
+
+
+
+ horizontalSlider_parallax
+ valueChanged(int)
+ DockWidget
+ on_parallax_changed()
+
+
+ 195
+ 53
+
+
+ 196
+ 49
+
+
+
+
+ horizontalSlider_parallax
+ sliderReleased()
+ DockWidget
+ on_parallax_changed()
+
+
+ 195
+ 53
+
+
+ 196
+ 49
+
+
+
+
+ checkBox_inverted_stereo
+ clicked()
+ DockWidget
+ on_inverted_stereo()
+
+
+ 290
+ 77
+
+
+ 196
+ 49
+
+
+
+
+
diff --git a/qlib3/base/ui_transparency.ui b/qlib3/base/ui_transparency.ui
index d2f3bb0..eec2ef9 100644
--- a/qlib3/base/ui_transparency.ui
+++ b/qlib3/base/ui_transparency.ui
@@ -29,6 +29,12 @@
-
+
+
+ 0
+ 30
+
+
0
diff --git a/qlib3/geofinderdialog/geofinderdialog.py b/qlib3/geofinderdialog/geofinderdialog.py
index c8093a1..28e3f25 100644
--- a/qlib3/geofinderdialog/geofinderdialog.py
+++ b/qlib3/geofinderdialog/geofinderdialog.py
@@ -44,12 +44,12 @@ class GeoFinderDialog(QDialog, ui_geofinder):
14:'river.png', 15:'river.png' #Curs fluvial, hidrografia
}
- def __init__(self, geofinder_instance, geofinder_dict_list=[], title=None, columns_list=[], auto_show=False, parent=None):
+ def __init__(self, geofinder_instance, geofinder_dict_list=[], title=None, columns_list=[], keep_scale_text=None, default_scale=1000, auto_show=False, parent=None):
""" Dialog initialization """
QDialog.__init__(self, parent)
# Set up the user interface from Designer.
- self.setupUi(title, columns_list)
+ self.setupUi(title, columns_list, keep_scale_text, default_scale)
# Set up values
self.geofinder = geofinder_instance
@@ -61,7 +61,7 @@ def __init__(self, geofinder_instance, geofinder_dict_list=[], title=None, colum
if auto_show:
self.do_modal()
- def setupUi(self, title, columns_list):
+ def setupUi(self, title, columns_list, keep_scale_text, default_scale):
""" Setup the components that form the dialog """
# We Initialize the UI by associating the items in the plugin class
@@ -86,6 +86,14 @@ def setupUi(self, title, columns_list):
for i, col_name in enumerate(columns_list):
self.tableWidget.horizontalHeaderItem(i).setText(col_name)
+ # Setup first scale text "keep scale"
+ if keep_scale_text:
+ self.comboBox_scale.setItemText(0, keep_scale_text)
+
+ # Initialize default scale value
+ pos = max(self.comboBox_scale.findText(str(default_scale)), 0)
+ self.comboBox_scale.setCurrentIndex(pos)
+
def set_data(self, topodata_list):
self.tableWidget.setRowCount(len(topodata_list))
@@ -121,19 +129,15 @@ def find(self, text, default_epsg):
finally:
QApplication.restoreOverrideCursor()
- # If we have a rectangle, we do not have to do anything, we get the coordinates and access
- if self.geofinder.is_rectangle(self.geofinder_dict_list):
- # Get rectangle coordinates
- self.selected = 0
- else:
- # We show the found places in a dialog
- self.set_data(self.geofinder_dict_list)
- if not self.do_modal():
- return False
- self.selected = self.get_selection_index()
- if self.selected < 0:
- return False
- print("Selected: %s" % self.geofinder_dict_list[self.selected]['nom'])
+ # We show the found places in a dialog
+ self.comboBox_scale.setEnabled(not self.geofinder.is_rectangle(self.geofinder_dict_list))
+ self.set_data(self.geofinder_dict_list)
+ if not self.do_modal():
+ return False
+ self.selected = self.get_selection_index()
+ if self.selected < 0:
+ return False
+ print("Selected: %s" % self.geofinder_dict_list[self.selected]['nom'])
return True
@@ -144,4 +148,8 @@ def get_rectangle(self):
return self.geofinder.get_rectangle(self.geofinder_dict_list)
def get_point(self):
- return self.geofinder.get_point(self.geofinder_dict_list, self.selected)
\ No newline at end of file
+ return self.geofinder.get_point(self.geofinder_dict_list, self.selected)
+
+ def get_scale(self):
+ scale = int(self.comboBox_scale.currentText()) if self.comboBox_scale.currentIndex() else None
+ return scale
\ No newline at end of file
diff --git a/qlib3/geofinderdialog/ui_geofinder.ui b/qlib3/geofinderdialog/ui_geofinder.ui
index 1e32bc6..6459234 100644
--- a/qlib3/geofinderdialog/ui_geofinder.ui
+++ b/qlib3/geofinderdialog/ui_geofinder.ui
@@ -24,41 +24,117 @@
-
-
-
-
- Name
-
-
-
-
- Type
-
-
-
-
- Municipality
-
-
-
-
- Region
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QDialogButtonBox::Cancel|QDialogButtonBox::Ok
-
-
- true
-
-
+
+
-
+
+
+
+ Name
+
+
+
+
+ Type
+
+
+
+
+ Municipality
+
+
+
+
+ Region
+
+
+
+
+ -
+
+
-
+
+
+
+ 120
+ 0
+
+
+
-
+
+ Keep scale
+
+
+ -
+
+ 500
+
+
+ -
+
+ 1000
+
+
+ -
+
+ 2500
+
+
+ -
+
+ 5000
+
+
+ -
+
+ 10000
+
+
+ -
+
+ 25000
+
+
+ -
+
+ 50000
+
+
+ -
+
+ 100000
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+ true
+
+
+
+ -
+
+
+
+ 120
+ 0
+
+
+
+
+
+
+
+
+
+
diff --git a/qlib3/photosearchselectiondialog/images/photo_digital_preview.png b/qlib3/photosearchselectiondialog/images/photo_digital_preview.png
new file mode 100644
index 0000000..53905e8
Binary files /dev/null and b/qlib3/photosearchselectiondialog/images/photo_digital_preview.png differ
diff --git a/qlib3/photosearchselectiondialog/images/rectified_preview.png b/qlib3/photosearchselectiondialog/images/rectified_preview.png
new file mode 100644
index 0000000..8c7e337
Binary files /dev/null and b/qlib3/photosearchselectiondialog/images/rectified_preview.png differ
diff --git a/qlib3/photosearchselectiondialog/images/stereo_preview.png b/qlib3/photosearchselectiondialog/images/stereo_preview.png
new file mode 100644
index 0000000..e8ee18d
Binary files /dev/null and b/qlib3/photosearchselectiondialog/images/stereo_preview.png differ
diff --git a/qlib3/photosearchselectiondialog/photosearchselectiondialog.py b/qlib3/photosearchselectiondialog/photosearchselectiondialog.py
index cca79bc..1f5150c 100644
--- a/qlib3/photosearchselectiondialog/photosearchselectiondialog.py
+++ b/qlib3/photosearchselectiondialog/photosearchselectiondialog.py
@@ -17,26 +17,34 @@
from PyQt5.QtCore import QDateTime
from PyQt5 import uic
from PyQt5.QtGui import QPainter, QPen, QFont, QIcon, QColor
-from PyQt5.QtCore import Qt, QPoint, QSize
-from PyQt5.QtWidgets import QDockWidget, QSlider, QApplication, QStyleOptionSlider, QToolTip, QTableWidgetItem, QHeaderView, QStyle
+from PyQt5.QtCore import Qt, QPoint, QSize, QTimer
+from PyQt5.QtWidgets import QDockWidget, QSlider, QApplication, QStyleOptionSlider, QToolTip, QTableWidgetItem, QHeaderView, QStyle, QMenu
from . import resources_rc
Ui_TimeSeries, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'ui_%s.ui' % os.path.basename(__file__).replace("dialog.py", "")))
+class PreviewType:
+ NOMINAL=0
+ RECTIFIED=1
+ STEREO=2
+
class PhotoSearchSelectionDialog(QDockWidget, Ui_TimeSeries):
""" Dialog class to show results of photo search and filter it """
photo_layer = None
time_series_list = []
photo_list = []
+ preview_type = PreviewType.NOMINAL
def __init__(self, photo_layer, time_series_list, current_time,
- update_callback=None, photo_selection_callback=None, show_info_callback=None, preview_callback=None, adjust_callback=None,
+ update_callback=None, photo_selection_callback=None, show_info_callback=None,
+ preview_callback=None, rectified_preview_callback=None, stereo_preview_callback=None, adjust_callback=None,
download_callback=None, request_certificate_callback=None, request_scan_callback=None, report_bug_callback=None,
name_field_name="name", gsd_field_name="gsd", date_field_name="flight_date", image_field_name="image_filename",
- publishable_field_name=None, available_field_name=None, autoshow=True, show_buttons_text=True, parent=None):
+ publishable_field_name=None, available_field_name=None, analog_field_name="analog",
+ autoshow=True, show_buttons_text=True, parent=None):
""" Initialize time range and refresh / action callbacks """
super().__init__(parent)
self.setupUi(self)
@@ -48,6 +56,7 @@ def __init__(self, photo_layer, time_series_list, current_time,
self.image_field_name = image_field_name
self.publishable_field_name = publishable_field_name
self.available_field_name = available_field_name
+ self.analog_field_name = analog_field_name
# Set table widget properties
self.tableWidget_photos.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) # col(0) és autoescalable
@@ -69,6 +78,24 @@ def __init__(self, photo_layer, time_series_list, current_time,
self.pushButton_request_certificate.setIcon(QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_certificate.png"))
self.pushButton_request_scan.setIcon(QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_scan.png"))
self.pushButton_adjust_brightness.setIcon(QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_brightness.png"))
+ # Add preview options (submenu) to preview button
+ preview_menu = QMenu(self);
+ if preview_callback:
+ photo_preview_action = preview_menu.addAction(self.tr("Photogram nominal orientation"))
+ photo_preview_action.setIcon(QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_preview.png"))
+ photo_preview_action.triggered.connect(lambda:self.update_preview_button(\
+ self.preview, photo_preview_action.text(), photo_preview_action.icon()))
+ if rectified_preview_callback:
+ rectified_preview_action = preview_menu.addAction(self.tr('Rectified photogram "on the fly"'))
+ rectified_preview_action.setIcon(QIcon(":/lib/qlib3/photosearchselectiondialog/images/rectified_preview.png"))
+ rectified_preview_action.triggered.connect(lambda:self.update_preview_button(\
+ self.rectified_preview, rectified_preview_action.text(), rectified_preview_action.icon()))
+ if stereo_preview_callback:
+ stereo_preview_action = preview_menu.addAction(self.tr('Anaglyph photogram "on the fly"'))
+ stereo_preview_action.setIcon(QIcon(":/lib/qlib3/photosearchselectiondialog/images/stereo_preview.png"))
+ stereo_preview_action.triggered.connect(lambda:self.update_preview_button(\
+ self.stereo_preview, stereo_preview_action.text(), stereo_preview_action.icon()))
+ self.pushButton_link_preview_type.setMenu(preview_menu);
# Translate dialog text
self.current_value_prefix = self.tr("Year: %s")
@@ -93,6 +120,7 @@ def __init__(self, photo_layer, time_series_list, current_time,
self.pushButton_show_info.setToolTip(self.tr("Information"))
self.pushButton_link_preview.setText((" " + self.tr("View")) if show_buttons_text else "")
self.pushButton_link_preview.setToolTip(self.tr("View"))
+ self.pushButton_link_preview_type.setToolTip(self.tr("View type"))
self.pushButton_adjust_brightness.setText((" " + self.tr("Adjust\nbrightness")) if show_buttons_text else "")
self.pushButton_adjust_brightness.setToolTip(self.tr("Adjust brightness"))
self.pushButton_download_hd.setText((" " + self.tr("Download")) if show_buttons_text else "")
@@ -101,6 +129,8 @@ def __init__(self, photo_layer, time_series_list, current_time,
self.pushButton_request_certificate.setToolTip(self.tr("Request certificate"))
self.pushButton_request_scan.setText((" " + self.tr("Request\nscan")) if show_buttons_text else "")
self.pushButton_request_scan.setToolTip(self.tr("Request scan"))
+ self.label_parallax.setText(self.tr("Parallax: %+d%%") % 0)
+ self.checkBox_inverted_stereo.setText(self.tr("Inverted stereo"))
# Configure small help in tooltip
self.tableWidget_photos.setToolTip(self.tr("""When photograms list is focused you can use\n"""
@@ -110,7 +140,8 @@ def __init__(self, photo_layer, time_series_list, current_time,
# Update time, photo information and callbacks
self.set_info(photo_layer, time_series_list, current_time,
- update_callback, photo_selection_callback, show_info_callback, preview_callback, adjust_callback,
+ update_callback, photo_selection_callback, show_info_callback,
+ preview_callback, rectified_preview_callback, stereo_preview_callback, adjust_callback,
download_callback, request_certificate_callback, request_scan_callback, report_bug_callback)
# Hide second time slider (date range slider)
@@ -120,13 +151,44 @@ def __init__(self, photo_layer, time_series_list, current_time,
# Hide resolution filter (not used for the moment)
self.label_quality.setVisible(False)
self.comboBox_quality.setVisible(False)
+ # Hide stereo options
+ self.label_parallax.setVisible(False)
+ self.horizontalSlider_parallax.setVisible(False)
+ self.checkBox_inverted_stereo.setVisible(False)
+
+ # Configure delayed stereo parallax change event
+ self.parallax_timer = QTimer()
+ self.parallax_timer.timeout.connect(lambda:self.on_parallax_changed(delayed=0))
# Show dialog
if autoshow:
self.show()
+ def show(self):
+ """ Show dialog and synchronize preview buttons size """
+ super().show()
+ # Fix preview type button size
+ self.pushButton_link_preview_type.setMinimumSize(self.pushButton_link_preview_type.minimumWidth(), self.pushButton_link_preview.height())
+
+ def update_preview_button(self, preview_callback, preview_text, preview_icon, preview=True):
+ """ Changes action, icon and tooltip to preview button """
+ # Remap view button function
+ self.pushButton_link_preview.clicked.disconnect()
+ self.pushButton_link_preview.clicked.connect(preview_callback)
+ self.pushButton_link_preview.setToolTip(preview_text)
+ self.pushButton_link_preview.setIcon(preview_icon)
+ # Enabled / Disable stereo options
+ stereo_visible = (preview_callback == self.stereo_preview)
+ self.label_parallax.setVisible(stereo_visible)
+ self.horizontalSlider_parallax.setVisible(stereo_visible)
+ self.checkBox_inverted_stereo.setVisible(stereo_visible)
+ # Execute current photo view
+ if preview:
+ preview_callback()
+
def set_info(self, photo_layer, time_series_list, current_time,
- update_callback, photo_selection_callback, show_info_callback, preview_callback, adjust_callback,
+ update_callback, photo_selection_callback, show_info_callback,
+ preview_callback, rectified_preview_callback, stereo_preview_callback, adjust_callback,
download_callback, request_certificate_callback, request_scan_callback, report_bug_callback):
""" Store time, photo information and callbacks """
self.photo_layer = photo_layer
@@ -134,6 +196,8 @@ def set_info(self, photo_layer, time_series_list, current_time,
self.photo_selection_callback = photo_selection_callback
self.show_info_callback = show_info_callback
self.preview_callback = preview_callback
+ self.rectified_preview_callback = rectified_preview_callback
+ self.stereo_preview_callback = stereo_preview_callback
self.adjust_callback = adjust_callback
self.download_callback = download_callback
self.request_certificate_callback = request_certificate_callback
@@ -154,7 +218,9 @@ def set_info(self, photo_layer, time_series_list, current_time,
# Update buttons
self.pushButton_report_bug.setVisible(self.report_bug_callback is not None)
self.pushButton_show_info.setVisible(self.show_info_callback is not None)
- self.pushButton_link_preview.setVisible(self.preview_callback is not None)
+ preview_count = (1 if self.preview_callback else 0) + (1 if self.rectified_preview_callback else 0) + (1 if self.stereo_preview_callback else 0)
+ self.pushButton_link_preview.setVisible(preview_count > 0)
+ self.pushButton_link_preview_type.setVisible(preview_count > 1)
self.pushButton_adjust_brightness.setVisible(self.adjust_callback is not None)
self.pushButton_download_hd.setVisible(self.download_callback is not None)
self.pushButton_request_certificate.setVisible(self.request_certificate_callback is not None)
@@ -173,15 +239,17 @@ def get_photo_info(self, feature):
return feature.id(), feature[self.name_field_name], year, datetime_text, feature[self.gsd_field_name], \
True if feature[self.image_field_name] else False, \
feature[self.publishable_field_name] if self.publishable_field_name else True, \
- feature[self.available_field_name] if self.available_field_name else True
+ feature[self.available_field_name] if self.available_field_name else True, \
+ feature[self.analog_field_name]
def reset(self, hide=True):
""" Reset all information, disable controls and hide dialog"""
# Delete information and disable controls
self.set_info(photo_layer=None, time_series_list=[], current_time=None,
update_callback=None, photo_selection_callback=None, show_info_callback=None,
- preview_callback=None, adjust_callback=None, download_callback=None,
- request_certificate_callback=None, request_scan_callback=None, report_bug_callback=None)
+ preview_callback=None, rectified_preview_callback=None, stereo_preview_callback=None,
+ adjust_callback=None, download_callback=None, request_certificate_callback=None, request_scan_callback=None,
+ report_bug_callback=None)
# Hide dialog
if hide:
self.hide()
@@ -193,6 +261,7 @@ def reset(self, hide=True):
UNAVAILABLE_PHOTO_COLOR = QColor(255, 200, 200)
# Icons for differents photo status
DEFAULT_PHOTO_ICON = QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_preview.png")
+ DIGITAL_PHOTO_ICON = QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_digital_preview.png")
UNPUBLISHABLE_PHOTO_ICON = QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_forbidden.png")
UNSCANNED_PHOTO_ICON = QIcon(":/lib/qlib3/photosearchselectiondialog/images/photo_scan.png")
UNAVAILABLE_PHOTO_ICON = QIcon(":/lib/qlib3/base/images/bug.png")
@@ -206,7 +275,7 @@ def update_photos(self):
# Update tableWidget with photo_list data
self.tableWidget_photos.blockSignals(True)
self.tableWidget_photos.setRowCount(0)
- for id, name, year, flight_datetime_text, gsd, image_available, publishable, available in self.photo_list:
+ for id, name, year, flight_datetime_text, gsd, image_available, publishable, available, analog in self.photo_list:
if year is not None and year in time_range_list and gsd is not None and gsd >= min_res and gsd < max_res:
if not available:
color = self.UNAVAILABLE_PHOTO_COLOR
@@ -220,6 +289,10 @@ def update_photos(self):
color = self.UNSCANNED_PHOTO_COLOR
icon = self.UNSCANNED_PHOTO_ICON
tooltip = self.tr("Scan required")
+ elif not analog:
+ color = self.DEFAULT_PHOTO_COLOR
+ icon = self.DIGITAL_PHOTO_ICON
+ tooltip = self.tr("Available")
else:
color = self.DEFAULT_PHOTO_COLOR
icon = self.DEFAULT_PHOTO_ICON
@@ -227,7 +300,7 @@ def update_photos(self):
row = self.tableWidget_photos.rowCount()
self.tableWidget_photos.insertRow(row)
item = QTableWidgetItem(name)
- item.setData(Qt.UserRole, (id, image_available, available, publishable))
+ item.setData(Qt.UserRole, (id, image_available, available, publishable, analog))
item.setBackground(color)
item.setToolTip(tooltip)
item.setIcon(icon)
@@ -259,6 +332,9 @@ def update_photos(self):
self.label_end_range.setEnabled(enable)
self.label_current.setEnabled(enable)
self.tableWidget_photos.setEnabled(enable)
+ self.label_parallax.setEnabled(enable)
+ self.horizontalSlider_parallax.setEnabled(enable)
+ self.checkBox_inverted_stereo.setEnabled(enable)
# Simulate update selection signal (and enable/disable selection dependent buttons)
self.on_photo_changed()
@@ -344,15 +420,13 @@ def on_range_clicked(self, enabled):
def on_value_changed(self, value=None):
""" Mapped event to update filtered photograms list when change current year """
- if not self.horizontalSlider.isSliderDown():
- self.update_filter()
+ self.update_filter(self.horizontalSlider.isSliderDown())
def on_range_value_changed(self, value=None):
""" Mapped event to update filtered photograms list when change current year range """
- if not self.horizontalSlider_range.isSliderDown():
- self.update_filter()
+ self.update_filter(self.horizontalSlider_range.isSliderDown())
- def update_filter(self):
+ def update_filter(self, only_label=False):
""" Update photograms list applying year and resolution filters """
# Update current years label
current_time, current_range = self.get_current_time_range()
@@ -360,6 +434,8 @@ def update_filter(self):
self.label_current.setText(self.current_value_prefix % ("%s - %s" % (str(current_time), str(current_range))))
else:
self.label_current.setText(self.current_value_prefix % str(current_time))
+ if only_label:
+ return
# Update photograms list
self.update_photos()
@@ -375,21 +451,21 @@ def on_quality_changed(self, index):
self.update_photos()
def get_selected_photo_id(self):
- photo_id, _image_available, _publishable, _available = self.get_selected_photo_info()
+ photo_id, _image_available, _publishable, _available, _analog = self.get_selected_photo_info()
return photo_id
def get_selected_photo_info(self):
""" Return current selected photogram id """
items_list = self.tableWidget_photos.selectedItems()
if not items_list:
- return None, None, None, None
+ return None, None, None, None, None
row = items_list[0].row()
item = self.tableWidget_photos.item(row, 0)
- photo_id, image_available, available, publishable = item.data(Qt.UserRole)
+ photo_id, image_available, available, publishable, analog = item.data(Qt.UserRole)
image_available = item.background() not in [self.UNSCANNED_PHOTO_COLOR, self.UNAVAILABLE_PHOTO_COLOR]
available = item.background() != self.UNAVAILABLE_PHOTO_COLOR
publishable = item.background() != self.UNPUBLISHABLE_PHOTO_COLOR
- return photo_id, image_available, publishable, available
+ return photo_id, image_available, publishable, available, analog
def get_selected_photo_name(self):
""" Return current selected photogram name """
@@ -408,7 +484,7 @@ def select_photo(self, photo_id, year):
if photo_id is not None:
# Search photo_id row
for i in range(self.tableWidget_photos.rowCount()):
- photo_id2, _image_available, _publishable, _available = self.tableWidget_photos.item(i, 0).data(Qt.UserRole)
+ photo_id2, _image_available, _publishable, _available, _analog = self.tableWidget_photos.item(i, 0).data(Qt.UserRole)
if photo_id2 == photo_id:
row = i
break
@@ -424,30 +500,64 @@ def select_photo(self, photo_id, year):
def on_photo_changed(self):
""" Mapped event to update photo layer selection when change selected photogram """
- photo_id, image_available, publishable, available = self.get_selected_photo_info()
+ # Select phootogram
+ photo_id, image_available, publishable, available, analog = self.get_selected_photo_info()
if self.photo_selection_callback:
self.photo_selection_callback(photo_id)
-
+ # Select year
+ current_time, current_range = self.get_current_time_range()
+ if self.update_callback and current_time:
+ new_layer_name = self.update_callback(current_time, current_range)
+
+ # Select "photo view" type for analog photograms (disable rectified modes)
+ if analog:
+ self.update_preview_button(self.preview,
+ self.pushButton_link_preview_type.menu().actions()[0].text(),
+ self.pushButton_link_preview_type.menu().actions()[0].icon(),
+ False)
+ # Enable or disable option for photogram
enable = photo_id is not None
+ nominal_preview = (self.preview_type == PreviewType.NOMINAL)
self.pushButton_report_bug.setEnabled(enable and image_available)
self.pushButton_show_info.setEnabled(enable)
self.pushButton_link_preview.setEnabled(enable and image_available)
+ self.pushButton_link_preview_type.setEnabled(enable and image_available)
+ self.pushButton_link_preview_type.menu().actions()[1].setEnabled(not analog)
+ self.pushButton_link_preview_type.menu().actions()[2].setEnabled(not analog)
self.pushButton_adjust_brightness.setEnabled(enable and image_available)
- self.pushButton_download_hd.setEnabled(enable and image_available and publishable)
+ self.pushButton_download_hd.setEnabled(enable and image_available and publishable and nominal_preview)
self.pushButton_request_certificate.setEnabled(enable and image_available and publishable)
self.pushButton_request_scan.setEnabled(enable and not image_available and available)
-
+
def show_info(self):
""" Mapped event to show photo information when push button """
photo_id = self.get_selected_photo_id()
if self.show_info_callback and photo_id:
self.show_info_callback(photo_id)
-
+
def preview(self):
""" Mapped event to load photo raster when push button """
photo_id = self.get_selected_photo_id()
if self.preview_callback and photo_id:
self.preview_callback(photo_id)
+ self.preview_type = PreviewType.NOMINAL
+ self.on_photo_changed()
+
+ def rectified_preview(self):
+ """ Mapped event to load rectified photo raster when push button """
+ photo_id = self.get_selected_photo_id()
+ if self.rectified_preview_callback and photo_id:
+ self.rectified_preview_callback(photo_id)
+ self.preview_type = PreviewType.RECTIFIED
+ self.on_photo_changed()
+
+ def stereo_preview(self):
+ """ Mapped event to load stereo photo raster when push button """
+ photo_id = self.get_selected_photo_id()
+ if self.stereo_preview_callback and photo_id:
+ self.stereo_preview_callback(photo_id)
+ self.preview_type = PreviewType.STEREO
+ self.on_photo_changed()
def adjust(self):
photo_id = self.get_selected_photo_id()
@@ -481,7 +591,7 @@ def report_bug(self):
def on_table_key_press(self, event):
""" Mapped table keyPress event to change current year with cursors and load preview photo raster """
if event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
- self.preview()
+ self.pushButton_link_preview.click()
self.tableWidget_photos.setFocus()
elif event.key() == Qt.Key_Left:
self.horizontalSlider.setValue(self.horizontalSlider.value() - 1)
@@ -500,3 +610,23 @@ def on_slider_key_press(self, event, widget):
self.tableWidget_photos.selectRow(rows_list[0].row()+1 if rows_list else 0)
else:
self.horizontalSlider.__class__.keyPressEvent(widget, event)
+
+ def on_parallax_changed(self, value=None, delayed=1000):
+ parallax = self.get_parallax() - 100
+ self.label_parallax.setText(self.tr("Parallax: %+d%%") % parallax)
+ # Refresh visualization delayed (to avoid excessive refresh events)
+ if delayed:
+ self.parallax_timer.start(delayed)
+ else:
+ self.parallax_timer.stop()
+ self.pushButton_link_preview.click()
+
+ def on_inverted_stereo(self, inverted):
+ # Refresh visualization
+ self.pushButton_link_preview.click()
+
+ def get_parallax(self):
+ return self.horizontalSlider_parallax.value() * 4 + 80
+
+ def is_inverted_stereo(self):
+ return self.checkBox_inverted_stereo.checkState() == Qt.Checked
diff --git a/qlib3/photosearchselectiondialog/resources.qrc b/qlib3/photosearchselectiondialog/resources.qrc
index 6761152..46697b6 100644
--- a/qlib3/photosearchselectiondialog/resources.qrc
+++ b/qlib3/photosearchselectiondialog/resources.qrc
@@ -2,9 +2,12 @@
images/photo_brightness.png
images/photo_certificate.png
+ images/photo_digital_preview.png
images/photo_download.png
images/photo_forbidden.png
images/photo_preview.png
images/photo_scan.png
+ images/rectified_preview.png
+ images/stereo_preview.png
diff --git a/qlib3/photosearchselectiondialog/resources_rc.py b/qlib3/photosearchselectiondialog/resources_rc.py
index 475c2a0..ad79d4b 100644
--- a/qlib3/photosearchselectiondialog/resources_rc.py
+++ b/qlib3/photosearchselectiondialog/resources_rc.py
@@ -9,6 +9,169 @@
from PyQt5 import QtCore
qt_resource_data = b"\
+\x00\x00\x04\xa2\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
+\xa8\x64\x00\x00\x04\x37\x49\x44\x41\x54\x78\x5e\xed\xd8\x5f\x48\
+\x5b\x57\x18\x00\xf0\x2f\x4d\xea\x70\x1b\x41\xfb\xa0\x18\xff\x83\
+\xd2\x07\x99\x06\xa7\xe0\x1c\x03\xf1\xdf\xfc\x03\x22\x41\x7d\x48\
+\x3b\x9b\x49\x27\xc8\x66\xa3\xe0\xc4\x32\xac\x1b\xab\x32\x32\x64\
+\x62\x98\x8a\x84\x61\xbb\xb0\x07\x1f\x02\x3e\xcc\xc2\x54\x1c\x6c\
+\x2b\x9d\x46\x6a\xa4\xce\x07\x5f\x26\x53\x41\x7c\xe8\xcc\xe8\x86\
+\xd1\xe4\xee\x3b\xf1\x9b\x25\xf1\x06\x93\xd4\x64\xd0\x7c\x3f\xb8\
+\xdc\x9c\xef\x9e\x7b\xcf\x39\xdf\xbd\xf7\xe4\xde\x0b\x8c\x31\xc6\
+\x18\x63\x8c\x31\xc6\x18\x63\xb1\x46\x49\xeb\xa0\xb5\xb5\xb5\x5d\
+\x95\x24\xe9\xd3\xcc\xcc\xcc\x92\x8a\x8a\x8a\x3f\x1c\x0e\xc7\x53\
+\xda\xf4\xbf\x68\x68\x68\xb8\x1a\x17\x17\x77\x2b\x3b\x3b\xfb\x83\
+\x84\x84\x04\xc7\xfe\xfe\x7e\x64\xfa\xd3\xde\xde\xfe\xaa\x56\xab\
+\xbd\xdd\xdd\xdd\xed\xc2\x46\xa4\xad\xad\x2d\xc9\x68\x34\xba\xca\
+\xcb\xcb\x3f\xa2\x2a\x51\x85\x27\x41\x51\x56\x56\x66\xec\xe9\xe9\
+\x71\xed\xed\xed\x49\x4e\xa7\x53\xea\xbf\x73\xc7\x55\x55\x55\x75\
+\x1f\x97\xd7\xa8\xda\xc5\x28\x2a\x2a\xaa\x6d\x6c\x6c\xfc\x7d\x65\
+\x65\x45\xf2\x78\x3c\xd8\xf6\x09\xf1\x7b\x74\x74\x54\xaa\xaf\xaf\
+\xbf\x46\x55\xa3\x26\x2f\x2f\xef\x5d\xb3\xd9\xec\xd3\x1f\x61\x73\
+\x73\x53\x6a\x6d\x6d\xfd\xb3\xb0\xb0\xd0\x40\x55\xc3\x67\x30\x18\
+\xde\xc0\x2c\xcf\x4e\x4d\x4d\x49\x6e\xb7\x9b\x9a\xf0\x75\x7c\x7c\
+\x2c\xe9\x74\xba\xb5\xe6\xe6\xe6\x90\x6f\xa7\x70\x75\x76\x76\xbe\
+\x82\x27\x64\x53\xb4\x2d\x47\xf4\x75\x66\x66\x46\xaa\xa9\xa9\xf9\
+\x15\xaf\x86\xb7\x69\xb7\xe0\xe1\x8e\xea\xd2\xd2\xd2\x91\xbe\xbe\
+\x3e\xf7\xc1\xc1\x01\x1d\x36\x30\xab\xd5\x2a\xe9\xf5\xfa\x37\x69\
+\xf7\x88\x2b\x28\x28\xc8\xb3\x58\x2c\xd4\x7a\x60\x87\x87\x87\x92\
+\xc9\x64\xf2\x60\xfd\x11\xbc\x2a\x52\x69\x77\x1f\x0a\x5a\x7b\xe1\
+\x7d\x7e\x79\x61\x61\xa1\x1e\x07\xff\x6d\x6f\x6f\xef\xeb\xb9\xb9\
+\xb9\xa0\x50\xf8\x54\x91\x65\xb7\xdb\x61\x60\x60\xa0\xbb\xab\xab\
+\xeb\x1e\x85\x22\x0a\x13\x7e\xa3\xa3\xa3\xe3\xab\x92\x92\x12\x8a\
+\x04\x86\x79\x80\xdd\xdd\x5d\x18\x1c\x1c\x7c\xb6\xbe\xbe\xfe\x59\
+\x7e\x7e\xfe\xc8\xe4\xe4\xe4\x11\x6d\xf6\x4d\x40\x52\x52\x52\x25\
+\x56\x98\xc3\x25\xa8\x81\xff\xc7\xe5\x72\x01\x5e\x76\x10\x1f\x1f\
+\x4f\x91\xc8\xc2\x33\xeb\xed\x1f\xce\xfe\x14\x09\xce\xc6\xc6\x06\
+\xe0\x04\x7e\x6d\x79\x79\xf9\x3b\x0a\x9d\x51\x39\x3f\x3f\xef\x9d\
+\x58\x5e\xc6\x05\x07\x2e\x89\x31\x9e\x0c\xf5\xc4\x25\x5a\xfb\x10\
+\xd9\x7d\x59\x17\x7f\xb2\x09\x88\x25\xfe\x29\x11\xb7\xc0\x1c\x3e\
+\xe1\x51\x11\xe0\xe8\xe8\x08\x56\x1f\x3f\x06\xfc\xcb\xa1\x48\x68\
+\x32\xb3\xb2\x40\xa3\xd1\x50\x29\x34\xde\xb6\x57\x57\xc3\x6e\x3b\
+\x0b\xdb\x4e\x49\x49\xa1\x12\x00\x3e\xc7\x88\x67\x9a\x2a\xfc\x39\
+\x7f\x12\x39\x27\x01\x62\x06\x35\xf4\xdf\x05\x6b\xb2\x16\xaf\x15\
+\x95\x37\x16\x2a\xf5\x6f\x0f\x61\xad\xaf\x1d\xd2\xd3\xd3\x29\x12\
+\x1c\xd1\x76\xef\x8d\xeb\xf0\xd6\x93\x47\x70\x59\xe6\xd2\x0d\xc6\
+\xe2\x3f\x6e\x30\x3e\xf8\x11\xf0\xb1\xdd\x5b\x0e\x2b\x01\xf9\x1f\
+\x7f\x0e\x4f\xf4\xfd\x62\x62\xf0\xc6\x42\x75\xc9\xf1\x33\x3c\xd0\
+\xfc\x0d\xd5\xd5\xd5\x14\x09\x8e\x38\xeb\x9f\xbc\x53\x0c\x5f\xa8\
+\xf1\xde\xa5\x58\xa8\x7e\x7a\xfa\x17\x3c\xbb\xfb\x35\xd4\x50\xdb\
+\x72\x09\x88\xca\x1c\x10\xee\x00\xa2\x21\xe6\x27\x41\x4e\x00\xad\
+\x63\x16\x27\x80\xd6\x31\x8b\x13\x40\xeb\x73\x88\x77\x88\xe8\x93\
+\x5e\xf0\x0f\x54\xf4\xfa\xbc\x23\xf8\x6f\x3f\xf3\x20\x74\x6b\xe8\
+\x4b\x98\x54\x69\xf0\x60\xe1\x7d\xf0\x49\xda\x5a\x83\x95\x81\x2e\
+\x48\x4e\x4e\xa6\xc8\x73\xe2\xf8\x72\x2f\x28\x82\xd8\xd6\xdf\xf9\
+\x21\xe4\xfc\xf2\x03\x84\xf7\x0c\x0a\xb0\xa4\x88\x83\xdb\xdf\x2f\
+\x9c\x3e\x0e\x87\xfc\x24\x28\x88\xf7\x7c\xf1\x41\xc1\x83\xeb\x70\
+\x24\x5e\xb9\x02\x6a\xb5\x9a\x4a\xcf\x89\x01\x9a\xcd\x66\x48\x4d\
+\x4d\x05\x9d\x4e\x27\x9b\x88\xd3\xb6\x3d\x1e\x8a\x84\x26\x31\x31\
+\xd1\xa7\x6d\xb9\x04\xf8\x13\x09\xc0\xbe\x45\x96\x78\x37\x1f\x1b\
+\x1b\x3b\xc6\xc1\x5f\xaf\xad\xad\x9d\xb2\xd9\x6c\xb4\x25\xb2\xec\
+\x76\xfb\x99\xef\x01\xfe\x22\x9e\x00\x1a\xbc\x2b\x2d\x2d\x4d\x2f\
+\x1a\xc4\x90\xa2\xae\xae\xee\x5e\x34\x92\x20\x97\x80\xa8\xfe\x0b\
+\x60\x1f\x60\x62\x62\xc2\x3d\x34\x34\x64\xd8\xde\xde\xf6\x7e\x96\
+\xc2\x4b\x5f\x2a\x2e\x2e\x7e\xdf\x62\xb1\xdc\xc7\x24\x78\xeb\x44\
+\x93\xcf\x8d\xa7\x54\x2a\x2b\xc7\xc7\xc7\xe7\xb0\x43\x14\xb9\x58\
+\x8b\x8b\x8b\x30\x3c\x3c\xfc\xde\xce\xce\x8e\x95\x42\xa7\xa6\xa7\
+\xa7\x95\xdf\xa0\x96\x96\x96\x56\xad\x56\x1b\x70\x72\x7c\x11\xe2\
+\x9b\xa0\x5e\xaf\x0f\x3c\x09\x36\x35\x35\xe5\xa8\x54\xaa\x9b\x54\
+\xbc\x70\x4e\xa7\x73\x69\x76\x76\xd6\x46\x45\x59\xd8\x87\x9b\xd8\
+\x87\x1c\x2a\x5e\xb8\x8c\x8c\x0c\x9b\xc9\x64\x5a\xa2\x22\x63\x8c\
+\x31\xc6\x18\x63\x8c\x31\xc6\x18\x63\xb1\x05\xe0\x5f\xd9\x8c\x8e\
+\xf4\x16\xcd\x28\x4c\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
+\x82\
+\x00\x00\x05\x36\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x16\xb7\x00\x00\x16\xb7\x01\x5a\x8b\
+\x7b\x20\x00\x00\x04\xcb\x49\x44\x41\x54\x78\x5e\xed\x9b\x59\xc8\
+\x75\x53\x18\x80\x3f\xf3\x4c\x64\xce\x10\x91\x39\xe5\x02\x17\x08\
+\x45\x11\x32\x24\xdc\x28\x12\x19\xae\x64\x2a\x53\x29\x37\x4a\x21\
+\x43\xe6\x12\x17\x72\x27\x94\xbf\x50\x8a\xa4\x94\x79\x0c\x91\x21\
+\x43\xc6\xcc\xe3\xf3\x9c\xbd\x97\x56\xbb\x7d\xce\xd9\x6b\xef\xf5\
+\x9f\x75\x74\xce\x53\x4f\x7b\x7f\xfb\xdf\xdf\xf9\xd6\x7a\xcf\x5e\
+\xd3\xbb\xf6\xbf\x52\x90\x03\xf0\x13\x7c\x0b\x77\xf0\xc2\xa2\x71\
+\x1b\xfe\x53\x7b\xb1\x17\x4a\xb0\x66\x7d\x2c\xc1\xba\xf5\x51\xe2\
+\xf3\x99\x52\x32\x00\x73\xc1\x32\x00\xf5\x71\x61\x59\x06\xa0\x3e\
+\x2e\x2c\x29\x01\xd8\x14\xff\x2f\x01\xdb\x0c\xd7\xa8\x4e\x27\xd3\
+\xb5\x42\x97\xe2\x77\xf8\x2a\x6e\xef\x85\x0c\x7c\x59\x1f\x25\x3e\
+\x1f\x82\xf5\xb9\x1d\x2d\xeb\x73\xb8\x36\x66\xe1\x05\x0c\x93\x96\
+\x77\x30\x47\x10\xfc\x96\x6e\xc2\xeb\x70\x1d\x2f\x0c\xc4\xca\xdf\
+\x8d\xa1\x9c\xba\x33\x66\xe1\x4c\xfc\x1b\x73\x07\x21\x17\x6d\x95\
+\x7f\x14\x3b\x35\x83\xae\x9c\x87\xf3\x18\x84\xb6\xca\x3f\x8e\xeb\
+\xe1\x54\x52\x23\x64\x10\xee\xc0\xf0\x7b\xef\xe2\x11\xf8\xd9\xe8\
+\xa7\xe9\xf8\x7b\xbb\xe3\xde\xb8\x0b\xda\x0c\x6c\xa7\x3f\xe2\xe7\
+\xf8\x36\xbe\x82\xbf\x61\x17\xac\xfc\x9d\x78\xce\xe8\xa7\x8a\x27\
+\xf0\x64\xec\xfa\x19\xc9\xb4\x3d\x09\xdb\xe2\x38\xac\xf4\x91\x78\
+\x1f\x1a\xa8\xf8\x9b\x6a\xf3\x67\x7c\x12\xcf\xc2\x4d\x70\x1c\x7e\
+\xee\x5d\x18\xff\x6e\xe7\x6f\x7e\x28\xcd\x20\xdc\x88\x6d\x9c\x8a\
+\x8e\x1c\x71\x21\x53\xfc\x16\xed\x24\x1d\x82\x9b\x1c\x84\xf1\xbd\
+\x33\xab\x7c\xc0\x20\xfc\x85\xfe\xf1\x0b\xbc\x10\xb1\x2b\x3e\x85\
+\x71\x01\x83\x3e\xee\xcf\xe3\x03\xf8\x50\x7d\x6d\x9a\x9f\xe2\x49\
+\x18\xb3\x13\xfa\xb4\xf8\xef\x33\xaf\x7c\xc0\xa4\x86\x7d\x40\xcc\
+\x89\xe8\x38\x1c\x57\xe0\x27\xbc\x07\xbd\x37\x5e\xfa\xee\x8b\xf1\
+\x7d\xd3\xbc\x15\xe3\xb1\x7d\x37\x3c\x16\x73\x0c\xa3\x59\x38\x1f\
+\xc3\x53\xa1\x7f\xe2\x2d\xb8\x0d\xb6\x91\x1a\x00\x7d\x0c\x37\xc0\
+\xb9\xc3\x4e\x2b\xee\x17\x3e\xc0\x03\x71\x12\x7d\x02\xa0\x8e\xf1\
+\xd9\x66\x79\x39\x38\x0c\xff\xc0\x50\x40\xdb\xf8\x16\x38\x8d\xbe\
+\x01\x50\x67\x91\x73\xc1\xe6\x68\x72\x33\x14\xec\x45\xdc\x18\xbb\
+\x30\x24\x00\x3e\x6d\x27\x60\x71\x9c\x18\x85\x42\xd9\x5b\x8f\x6b\
+\xef\x6d\x0c\x09\x80\x7e\x8c\x1b\x61\x31\xf6\x40\x3b\xba\x50\xa0\
+\xa3\x30\x85\xa1\x01\xd0\x2b\xb1\x18\xce\xee\x42\x41\x1e\xf1\x42\
+\x22\x39\x02\xf0\x15\x16\x19\x15\x9c\xa6\x3a\xbe\x5b\x08\xdb\xa3\
+\x95\x49\x25\x47\x00\xf4\x0c\xec\x85\x8b\x89\xbe\xd8\x01\x6d\x58\
+\x9d\xae\x3c\x8b\xaf\x57\xa7\x45\x38\xad\x3e\x26\x33\x24\x00\x2e\
+\x70\x02\x0f\xd7\xc7\x52\x1c\x8e\xbd\xe6\x05\x43\x02\xe0\x62\x24\
+\xf0\x74\x7d\x2c\x85\xcb\xea\x3d\xab\xd3\x34\xfa\x06\x60\x2d\x74\
+\x1e\x2e\x2e\x48\xde\xab\x4e\x8b\xe2\x88\x94\x8c\x6b\xea\x7d\xf0\
+\x7a\x9c\xb4\xf6\xfe\x05\x5d\x96\x3a\xc9\x91\xad\x30\x24\x32\x4d\
+\x62\xec\x55\x9d\x26\x63\x27\xf8\x5a\x75\x3a\x98\x0b\xd1\x84\xa8\
+\x38\x05\xbf\x06\x27\x8d\x0e\xae\x4a\x47\x43\xe8\x2a\x6c\xeb\x59\
+\x9b\xbe\x84\x01\xb3\x39\xe1\x7a\x08\x4a\x1f\x72\x8d\x02\x7a\x19\
+\x06\x2c\x6b\xdb\x3d\x4d\x57\xd9\x04\xdc\x9f\xef\x42\x7c\x9f\xf3\
+\xfe\x40\xb1\x9d\xdd\x06\x71\x99\x3a\xd7\xc9\x26\x60\x10\x8e\xc6\
+\x49\x4d\xc0\x76\xee\x93\x12\xfe\x88\xf7\xfe\x50\x9d\x8e\xd6\x01\
+\x3b\x56\xa7\xc9\xe4\x6c\x02\xe6\x05\xef\xad\x4e\x47\xf9\x01\xeb\
+\x14\x86\xe9\x36\x6c\x02\xd6\xa9\x37\xf6\x01\x3e\x46\x4e\x82\xba\
+\x2e\x7e\x9a\xe4\x6c\x02\xcd\xc4\x4c\x27\x86\x0c\x83\x6f\xd4\x47\
+\x9f\xa2\x78\x48\x2c\xc5\x9b\xf5\x31\x89\x21\x01\x70\xf6\x17\x30\
+\x2d\x55\x12\x47\xa2\x2f\xaa\xd3\x34\x86\x04\xc0\xfc\x7b\xc0\xb9\
+\x78\xc9\xbc\x9c\x49\xd1\x22\x18\xf9\xd0\x06\x4d\x89\xa5\x92\xab\
+\x0f\xd8\x1f\x8b\x60\x12\x34\x14\xe2\x23\x4c\x4d\x4e\xe4\x08\xc0\
+\x33\x58\x8c\xf5\xd1\x8a\x87\xc2\x98\x01\x4e\x21\x47\x00\x7a\xf5\
+\xfe\x39\x71\x1f\x2e\x14\xc6\x21\xf1\x74\xec\xca\xd0\x00\x94\x5e\
+\x85\xfe\x47\xbc\xc3\xf3\x2b\x1e\x83\x5d\x18\x12\x00\xf3\x8f\x5b\
+\xe3\x5c\xe0\xcc\x30\xde\x03\xfc\x1d\xcf\xc6\x69\xf4\x0d\x80\x8b\
+\xb3\x43\x71\xae\xf0\x5d\x81\xf7\x31\x2e\xe8\x83\xe8\xca\x71\x1c\
+\x7d\x02\xe0\x74\xfc\x14\x9c\x4b\xb6\x43\xf7\xf7\xe3\x02\x7f\x83\
+\x57\xe3\x96\xd8\x24\x35\x00\xe6\x20\x8f\xc3\xb9\xc0\x49\xd4\xb9\
+\x78\x39\xc6\x8b\x0e\xd7\x05\xee\xfc\x36\x0b\xef\x0b\x0b\x6e\x69\
+\x5d\x84\x07\xa3\x01\x71\xfc\x6e\xde\x37\x4e\x57\x78\xfb\x61\x8c\
+\x1d\xf0\xb5\x98\xb2\x17\x91\x05\x2b\x1f\xbf\x96\x62\xb2\xa4\xc9\
+\xf1\xe8\xfe\x60\x5c\x89\x3e\x86\x64\x4c\x33\xb9\x61\x30\xc2\x5e\
+\xe4\x4c\x5f\xd7\x69\x56\x5e\xaf\xc2\x36\xcc\x15\xd8\x19\xbe\x8c\
+\xf1\xfd\x5d\x74\xb5\x79\x03\xda\xac\xda\x30\x0b\x15\xef\x44\xcf\
+\x24\x08\x6d\x95\xef\xfa\x72\x82\xdf\x98\x59\x1b\xef\xff\x10\xe3\
+\xc2\xeb\xd7\xe8\xbb\x7d\xbe\x6d\xe2\x30\xda\x65\x6d\x31\xd3\x17\
+\xb7\x86\x54\xbe\x0d\x3f\xcf\x57\x5f\xdc\x45\x1e\x92\x55\x9a\x49\
+\x10\x72\x57\x3e\x37\xab\x3d\x08\x66\x8d\x57\x47\xe5\xfd\x8c\x5c\
+\xcb\xe8\x66\x10\x4c\x90\x64\x5b\xa2\xc7\xaf\xca\xe6\xaa\xfc\x21\
+\xf8\x3d\xfa\xea\x5c\xd8\x63\x18\x4a\x33\x08\xbe\x48\x95\x05\xf7\
+\x01\x8d\xe8\xfd\x98\xeb\xb1\x8f\xdf\x2b\xb8\xc4\x0b\x99\x30\x2f\
+\x61\x9e\xe2\xe6\xd1\x4f\x73\x4c\xdc\xa7\x5c\xe1\x85\x12\xd8\xb9\
+\x2d\x34\xcb\x00\xd4\xc7\x85\x65\x19\x80\xfa\xb8\xb0\x2c\x03\x50\
+\x1f\x4b\x60\xda\x2c\x10\x9f\x2f\x0c\x73\xf0\xdf\xe7\x57\x56\xfe\
+\x05\xdb\xb5\xa7\xd2\xe2\x7e\x5c\x73\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
\x00\x00\x1d\x71\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@@ -1665,516 +1828,10 @@
\xc8\x90\x21\x43\x86\x0c\x19\x32\x64\xc8\x90\x21\x43\x86\x0c\x19\
\x32\xfc\x76\x23\x8a\xfe\x1f\xdf\xac\xfa\xa7\xee\x82\x6f\x5e\x00\
\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
-\x00\x00\x12\x94\
+\x00\x00\x16\xda\
\x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
-\x09\x70\x48\x59\x73\x00\x00\x12\x73\x00\x00\x12\x73\x01\x8c\x22\
-\xb9\x07\x00\x00\x12\x29\x49\x44\x41\x54\x78\x5e\xed\x9d\x0b\x7c\
-\x14\x45\x9e\xc7\xab\x67\x7a\x66\x92\x4c\xde\x6f\x86\xf0\x0c\x04\
-\x79\x0a\x11\xe4\x21\xc8\x43\x5e\xc2\x82\xba\x80\xe0\xb2\xa2\xa7\
-\xe2\xde\xae\x77\xab\xa7\xa2\xb2\xee\xde\x80\xae\xae\x72\x28\x7e\
-\x4e\x94\x45\x56\x3e\xec\x67\x17\x4e\x11\xbc\x8f\x08\x08\xac\x3c\
-\x22\x1e\x2f\x21\x21\x80\x0b\x84\x04\x13\x20\x24\x64\x48\x42\x26\
-\x93\xd7\x64\x1e\x57\xff\xee\xea\x99\xee\x9e\xee\x49\x80\xee\x88\
-\x4c\x7d\xc3\xbf\xab\xea\x5f\x55\x3d\xa1\x7f\xff\xaa\xae\xee\xe9\
-\x99\x20\x0a\x85\x42\xa1\x50\x28\x14\x0a\x85\x42\xa1\x50\x28\x14\
-\x0a\x85\x42\xa1\x50\x28\x14\x0a\x85\x72\x9b\xc2\x90\x54\x13\xe6\
-\x6c\xdc\x68\x4c\xfa\xb6\x60\xdc\x85\x8a\x8a\x2c\xe2\x0a\x8b\xc5\
-\x6c\xb8\xf4\xc5\xfa\xfa\x7d\x08\x7d\xe6\x25\x2e\x45\x5e\xb1\xbf\
-\x99\x73\xf2\x6c\xc9\x48\xaf\x57\xda\x2c\x31\x3e\x1e\x1d\xcd\xdb\
-\xfe\x49\x71\x71\x71\x0b\x71\x29\xf2\xfc\x2b\xf6\x9c\xb3\xa5\x97\
-\x42\xfa\xa7\x24\x26\xa2\xc3\x7b\xcf\xe0\xfe\x3b\xc2\xf6\x7f\xe6\
-\x79\x7b\x4e\xe9\xe5\xd0\xfe\x69\x29\x29\xe8\x60\xe9\xf7\x9f\x14\
-\xef\x08\xdf\x1f\xf5\xea\x65\x79\x70\xe4\xc4\x79\xcd\xcd\xcd\xc4\
-\xa1\x8e\xd1\x68\x44\xdd\x6d\x59\x07\x3f\x78\x77\x69\x11\x71\xe9\
-\x8a\xa6\x01\xd0\x6f\xe8\xe8\xad\xa7\x4b\xca\xa7\x33\x4c\x7b\x77\
-\xeb\x47\x49\x71\x31\xa7\xaa\xbb\xa7\x0e\x41\x79\x79\x1e\xe2\x94\
-\x30\x6c\xdc\xd4\xc7\x4e\x17\xfd\xb0\xae\xb1\xb9\x95\x78\xc4\xf8\
-\x91\x89\x31\x54\x75\xe9\xd6\x75\x54\x71\xfe\xde\x12\xe2\x94\xd0\
-\x73\xe0\x88\xc7\x2a\x1c\x35\xeb\x5a\xdc\x4a\xbb\xf7\xa3\x18\xb3\
-\xa9\x2a\xbb\x4f\x8f\xe1\x85\x79\x3b\x4b\x89\x53\x82\xed\x8e\xdc\
-\xc7\x6a\x6b\x5d\xeb\x5a\x5a\x95\xfb\xc7\x5b\xa3\xaa\xc6\x8e\xba\
-\x77\xf8\x17\x9f\xae\x56\xec\x6f\xb1\x74\xc9\xf6\x44\x1b\x0e\xf8\
-\x0d\x86\xf4\xf6\x1e\x6e\x8b\x89\x45\x49\x49\xb1\x8f\x5f\x3e\x93\
-\xff\x57\xe2\xd2\x0d\x23\x49\x6f\x9a\x5f\x2f\x5e\x3a\x76\xc7\xae\
-\xbc\x37\x91\xd9\x82\x90\x01\xef\xb6\x9d\xd6\xd4\xea\x4d\xbf\x33\
-\x36\xce\x75\xa5\xbc\xec\x00\xd9\x95\x04\x53\x4c\xea\xae\xab\xae\
-\x66\xab\x52\x5f\x30\x9f\xd1\x68\x8d\x36\xa2\x4e\xce\xea\xcb\x9f\
-\x91\x2e\x12\x58\x6b\xea\x2e\xa7\xdb\xa3\xda\xdf\x83\x0c\x56\x9f\
-\xab\xc1\xd4\x50\x57\xb5\x9d\x74\x91\x60\xc2\xfd\x5d\xad\x3e\xd5\
-\xfe\x6e\x1f\xb2\x7a\x5d\x75\xa6\x1a\xc7\x25\xc5\xfe\xe6\xe4\xf4\
-\xd5\xad\x26\xcb\xdd\x4a\x7d\xd5\xcc\x83\x03\xc5\xe4\x67\x46\x35\
-\xd5\x55\x2d\x27\xbb\xd1\x0d\x03\x49\x6f\x9a\xe2\xf3\x17\xd2\x99\
-\x1b\xd8\x1d\xcc\x16\xd7\x6a\xea\x1a\x48\x31\x84\xa6\x96\xe6\x46\
-\x92\x55\xa5\xbe\xb1\x49\x71\xf6\x00\x2c\x16\x73\x32\xc9\xaa\x12\
-\x15\x15\xad\xda\xc6\x6c\x36\xb5\xd9\x3f\x3a\x26\x4a\xb5\x8d\xb7\
-\x15\x9f\x36\xfc\x7e\x52\x6a\x3f\xcd\x1e\x1f\x9e\x31\xf4\x47\xb3\
-\x53\xc0\xa4\xb9\x4f\xce\xd9\xbd\x73\xcf\x46\xbf\xd9\x4c\x3c\x3c\
-\xe1\x5e\xc0\x8f\x0f\x4c\xac\xc1\x7b\x71\xd7\xaa\xf9\x4f\x8e\xc8\
-\x8e\xaf\x25\x6e\x09\xf3\x5e\xfd\x72\xd4\xe6\xff\xbb\xf0\xae\xd7\
-\x64\x32\x32\xb2\xbd\x41\x7f\x2b\xeb\x77\xbf\xfe\xab\x09\x0b\x9f\
-\x7b\xa8\xf7\x3f\x89\x5b\xc2\x82\xe5\x05\xbf\xd9\xb0\xf5\xc0\x02\
-\x9f\x4a\xff\x78\xb3\xc1\xfd\x5f\xcf\x4d\x5f\xb8\x70\x72\x27\xc5\
-\xfe\xf3\xdf\x3a\xf2\x9b\x4f\x77\x7c\xa7\xda\x3f\x39\x8a\x75\xaf\
-\x7d\x75\xc2\xcf\x66\x8e\xec\xae\xf8\xfb\xbf\xf4\x97\xe3\xa3\xde\
-\xff\xf4\xd0\xbb\x2d\x7e\x83\x31\xdc\xa9\x51\x1e\x22\xd1\x2c\x8b\
-\x1a\x2f\x7f\x1f\xee\xf0\x69\x82\x66\x2f\xa0\x14\x00\xfd\x92\x8d\
-\xab\x9f\x9b\x3b\xd8\x44\x8a\x21\x18\x8c\x26\x34\x63\x7c\x7f\x47\
-\x5a\xbc\x21\xec\x28\xdf\x7f\xd2\x91\x76\xf6\xdc\xc5\x18\x52\x0c\
-\x62\x60\xd0\xc4\x11\x7d\x1c\xdd\x33\x63\xc2\xf6\xcf\x2b\xac\x4c\
-\x3b\x57\x72\x59\xb1\xff\xe4\x51\x7d\x1c\x5d\xd3\xc3\xf7\xdf\x7b\
-\xbc\x32\xad\xe4\xbc\x52\x7f\x23\x9a\x32\xba\x8f\xa3\x4b\x6a\x54\
-\xd8\xfe\xc7\x4a\x5c\x69\x05\x85\xe7\x70\x7f\xf5\x99\x60\xd1\xc7\
-\xc7\x06\xd5\xb9\xd1\x50\x52\xbc\x3d\x02\xe0\xfe\x9c\xf8\xc5\xdb\
-\x3e\x98\x2b\x9d\x12\x28\x8a\x64\x3e\xb0\x76\x4c\x55\xa3\x77\x22\
-\x29\x76\x58\x00\x68\xb6\x06\xa0\xfc\x34\xa1\x01\x10\xe1\xd0\x00\
-\x88\x70\x68\x00\x44\x38\x34\x00\x22\x1c\x1a\x00\x11\x8e\x66\x01\
-\xd0\xb3\x8b\xcd\x8d\x90\x8f\x94\x30\x3e\x1f\x8a\x4a\x48\x20\x05\
-\x4a\x5b\xc4\x59\xa3\xb9\xbb\xa2\x02\x31\x16\x13\x3e\x9e\xfa\xa3\
-\x59\x00\xac\x5e\xfe\xfa\x17\xbd\x7b\x66\x9d\x66\xb0\xf0\x8c\xdf\
-\x8f\x58\xaf\xe7\xf4\xb2\x67\x27\x1f\x21\xd5\x94\x36\x58\x30\x73\
-\xe8\xe7\x26\x5f\xab\x9b\x41\xf8\xd8\xe1\x81\x94\x14\x1f\xfd\x16\
-\xa9\xd2\x15\x4d\x6f\x34\x7c\xb8\x7e\x7d\xd2\xdf\x3e\xde\x70\x9f\
-\xdb\xd5\x84\x32\x7b\xf5\xd9\xbd\xf5\xe5\xec\x6c\xec\x9e\xc6\xd7\
-\x52\xda\x60\xfb\xb0\x67\xf6\xd6\xa4\xa7\xc6\xcf\xba\x78\xe1\xca\
-\xee\x93\xf9\x7b\xf2\x89\x5f\x57\x74\xbd\xd3\xe4\x2f\x5c\x0e\xb7\
-\x36\x69\x00\xb4\x8f\xed\xcc\x9d\x2f\x1e\x25\xf9\x0e\x83\x2e\x02\
-\x23\x1c\x1a\x00\x11\x0e\x0d\x80\x08\x87\x06\x40\x84\xa3\x79\x00\
-\xd8\xed\xf6\x28\xfb\x8a\x15\x89\xa4\x48\xb9\x4e\xec\xcb\x56\x66\
-\x92\x6c\x87\xa0\xe9\x55\xc0\xe4\x07\x1e\x7e\xe1\xdb\x83\xf9\xcf\
-\x5a\x4c\xa6\x78\xe4\x67\x5e\xaf\xf9\xea\x89\x3c\xec\xa6\x57\x01\
-\xed\xa0\xcc\xd1\xf0\x75\xee\x13\x1b\x5f\x36\x9b\x8c\x33\x5b\x5b\
-\x3d\xa7\x6c\xb6\x4e\xbf\x38\x79\x68\xf7\x49\x52\xad\x1b\x46\x92\
-\xde\x34\xbf\x7f\xfb\xbd\xde\xff\xf3\xd9\x96\x2f\x9b\x91\x31\xa1\
-\xd9\xe7\x8f\x6a\x71\xbb\x27\xb7\xb2\x09\xa7\x26\x0c\x4a\x89\x26\
-\x4d\x28\x61\x98\xbd\x64\xff\xec\x33\x97\xaa\x1f\x70\xb9\xbd\xa8\
-\xc9\xe3\x4f\xf7\xb6\x34\x8f\x6c\xbc\x56\xb5\x9a\x54\xeb\x86\x66\
-\xa7\x80\xa3\xf9\x27\x07\xbb\x5b\x82\x8f\x6e\xfb\x59\x13\x2a\x38\
-\x58\x68\x25\x45\x4a\x1b\x9c\x2a\x2a\xb3\x8a\x1f\x18\x6b\x74\xfb\
-\x06\x93\xac\xae\x68\x16\x00\xfc\x47\x26\xe4\x67\x14\xd1\x7b\x03\
-\x94\x5b\x12\x7a\x15\x10\xe1\xd0\x00\x88\x70\x68\x00\x44\x38\x9a\
-\x05\x40\x82\x35\xae\xd1\x2f\x3e\xe7\xc3\x5b\xc2\xd1\xf4\x02\xa0\
-\xbd\x44\x59\xcc\x78\x09\x15\x5c\x43\x45\x5b\x54\x3f\x4e\xa1\x29\
-\x9a\x05\xc0\xa6\xb5\xef\x6d\x33\x1b\xd8\xe3\x20\x3c\x58\x9c\x85\
-\x69\xfc\xd3\xb3\xf7\x29\x7e\xde\x8f\x12\xca\xcc\x31\x7d\xf7\x98\
-\x84\xa5\xb4\xcf\x87\xdc\x0d\x8d\x7f\xe2\x0a\x3a\xa3\xd9\x7d\x00\
-\x20\x39\xb6\xd3\xfa\x2e\x5d\x32\x2c\xbe\x56\xef\x41\x5b\x66\xea\
-\xbc\x25\x8f\x0e\x80\x29\xa0\x37\x5f\x4b\x09\xc7\xfd\xc3\x6d\x3b\
-\xf7\x9e\x6a\xdd\x7c\xa1\xac\xbc\xaa\x6f\x76\xd7\xbf\x5f\x3a\x77\
-\xec\x6d\x52\xa5\x2b\xf4\x79\x80\x5b\x07\xfa\x3c\x00\xa5\xe3\xa1\
-\x01\x10\xe1\xd0\x00\x88\x70\x68\x00\x44\x38\x9a\x07\xc0\x6f\x17\
-\xbf\x91\x31\xef\xb7\x8b\x33\x48\x91\x72\x9d\x2c\xf8\xf7\x17\xb3\
-\xed\xf6\x95\xb1\xa4\xa8\x3b\x9a\x5e\x05\xe4\x8e\x9e\x6c\x3f\x73\
-\xf6\xfc\x4b\x3e\xbf\x0f\x21\x8f\x6f\x59\x53\xde\xbf\x6d\xc3\x6e\
-\x7a\x15\xd0\x0e\x4e\xfc\x50\xbd\x6f\xc4\x53\x9f\x2e\x61\x59\x76\
-\x3c\xcb\x1a\xaf\x5a\xac\x51\xf7\x57\x9e\x2d\xd0\xfd\xaa\x40\xb3\
-\xfb\x00\xcf\xdb\x97\xdf\xf1\xe5\xf6\x9d\x9b\xdc\x06\xd6\xe4\x65\
-\x8c\x26\xaf\xdf\x3f\xae\xd6\x6d\x3e\x3d\xf5\xae\x4c\x0b\x69\x42\
-\x09\xc3\x2c\xfb\xbe\x39\xa5\x35\x0d\x53\xdc\x7e\x06\x35\x7b\xfd\
-\x31\xac\xdf\x37\xb2\xd9\xe9\x58\x45\xaa\x75\x43\xb3\x53\xc0\xc9\
-\x33\xa7\x07\x7a\xbd\xa2\x77\xb4\x59\x13\x3a\x57\x78\x26\x8a\x94\
-\x28\x6d\x50\x5c\x56\x19\x05\x37\x51\x05\xdc\x5e\x66\x20\xc9\xea\
-\x0a\x5d\x04\x46\x38\x34\x00\x22\x1c\x1a\x00\x11\x8e\x66\x57\x01\
-\xf4\x5b\xc2\x82\xbc\x74\x20\x76\xe9\x5e\xe7\x48\x64\x60\x94\xbf\
-\x16\x0e\xce\xf5\xdc\x47\xc1\xb9\x77\x4e\xe1\x2d\x74\x3f\xf7\x13\
-\x94\x43\x9c\xe7\xf1\xb9\xae\xa2\x77\xe6\xe4\x4c\x1b\x77\x67\x8f\
-\xaf\x88\x4b\x13\x34\x9b\x01\x12\x12\x62\xea\x25\xcf\x03\xf8\x7c\
-\xc8\x6c\x8d\xcc\x67\x42\x0d\x06\x06\x59\x53\x33\xb0\x65\x2a\x5a\
-\x6c\x1a\xa4\xb8\x1e\xd2\x74\x1b\xb6\xce\x28\x36\x3d\x0b\x1b\xa4\
-\xf2\x3c\xb6\x8c\x2c\x64\xb1\xc6\x69\xfb\xd6\x2d\x41\xb3\x00\xd8\
-\xf4\xd1\xfb\x3b\x2c\x26\xd3\x61\x78\x2f\x1b\xa2\x3a\x31\xc6\xe4\
-\x5c\xb9\x68\xfc\x37\xa4\x3a\xa2\x20\x8f\x44\x40\x8e\x2b\x87\x22\
-\xf2\xab\x35\x91\x21\xbe\x42\xd0\x12\x4d\xd7\x00\x19\x31\xad\xe3\
-\xee\xec\x9f\xf3\x9a\x2d\x35\xf5\xb5\x9e\x39\xb6\xae\x9d\xd3\xac\
-\x1d\xf2\x2d\x17\xb7\x24\x20\x18\xbe\xa6\xe7\xd3\x30\x06\x70\x79\
-\xbc\x09\x98\xe0\x13\x99\x4e\x68\x1a\x00\x65\x65\x65\xcd\x05\x79\
-\xdb\xec\xe5\xa7\x0f\xda\x8f\x7d\xfd\x75\x1d\x71\x47\x24\x41\xed\
-\xf8\xb3\xbb\xd4\x18\xac\xb3\xdc\x0f\xdf\x0d\x22\x98\xd8\x1f\x34\
-\x3d\xa0\x57\x01\x3a\xc0\x89\x15\x58\xc3\x49\x17\x73\x01\x24\x5f\
-\x1c\xad\x26\xb1\x5e\xb2\x07\xa1\x01\xf0\x63\x10\x38\xa1\x0b\x29\
-\x04\x03\x98\x5c\x70\x95\xe0\xd1\x10\x1a\x00\x3a\xa0\x76\x1a\xe7\
-\xa7\x7d\xfc\x83\x47\x3f\xef\x93\x4f\xf7\x42\x19\xff\x40\x5b\xa1\
-\x3d\x97\xea\x03\x0d\x80\x8e\x44\x32\xed\x87\x03\xb7\x83\xb6\x5c\
-\x7b\x21\xd5\x07\xcd\x03\xe0\x67\x8f\x3e\xdd\xf5\x17\x0b\xff\xa3\
-\x43\xde\xc8\xb8\x55\xe1\x46\xab\xea\x90\x05\x31\xe5\x95\x6d\x8f\
-\x6f\x98\x55\xa4\x7f\xb2\x4a\x1b\x34\x0d\x80\x1e\x03\x86\x2f\xdb\
-\xb9\x75\xe7\xb9\xcf\xff\x77\xcb\x09\x5b\xf6\x90\x0d\xc4\x1d\x71\
-\x08\x12\x83\x68\x21\x06\xb7\x49\xf0\xe5\x21\x5f\x26\xd3\x3b\x94\
-\x7d\x90\x8a\xda\xc9\x8d\xdb\xb3\xf6\x68\x16\x00\xff\xba\xd8\x3e\
-\xe0\x42\xf9\x95\x45\x1e\x53\x94\xb9\xc5\xc0\xa2\x8a\x5a\xe7\x23\
-\x4f\xaf\x38\x3c\x96\x54\x47\x14\x20\x16\x88\xa6\x88\x64\x36\x87\
-\x82\x7e\xd3\x7b\x7b\xd0\x2c\x00\x4a\xce\x5f\xea\x0b\x91\x1c\x80\
-\x65\x51\x79\x71\x69\xc7\x7c\xbe\xe9\x16\x03\xb4\x67\x54\xde\x07\
-\x08\x10\x52\x2d\x0b\x04\x2e\x8a\xf8\x2c\xd0\xc6\xde\x6e\x18\xba\
-\x08\xd4\x89\x70\x37\x74\x38\xc3\x7a\x73\x29\x9e\x2a\x24\xe5\x40\
-\x3d\xf6\x73\x3e\xbe\x9e\xdf\x68\x0f\x0d\x80\x1f\x0d\xa2\xa8\xea\
-\x0a\x9f\x04\x10\x69\xa6\x93\xfe\x34\x00\xf4\x40\x2c\x9c\x40\x40\
-\xc8\x40\x06\x04\x0e\x38\xf9\x14\x3c\x24\x0f\x5b\x2e\x34\x60\x23\
-\x54\xeb\x00\x0d\x00\x3d\x10\xe9\x2a\xac\xf4\x85\x32\xe0\x83\x15\
-\x3f\x34\x82\x20\x80\x04\x46\x3b\x4e\x7d\x30\xe7\x63\xb8\x76\x78\
-\xc3\xa7\xdc\x3f\xce\xf4\x40\xb3\x00\x48\x4b\x4e\xaa\x95\x7c\x27\
-\x50\x04\xff\xbd\x00\x4e\xdc\x00\x20\xaa\x78\x9a\x67\xf0\xac\x1f\
-\xf4\xf1\x2d\xf9\x2d\xef\x11\xda\x92\x54\xd8\x95\x4e\x11\xa0\x59\
-\x00\x6c\x58\xb5\xfc\xeb\xc4\xf8\xd8\x3c\xe4\xf5\x20\xe4\xf5\xa2\
-\xcc\xc4\xd8\xda\x8f\x5e\x9e\xb8\x8f\x54\x47\x18\x82\x88\xea\x08\
-\x7a\x4a\x45\xe7\xfd\x82\x71\xe8\x78\x17\x10\xd0\xf4\x14\x30\xb0\
-\x47\xea\xc4\x7e\x7d\xb2\x67\x0f\xcf\x1d\xf4\x72\xb7\xc1\xd9\x9d\
-\x53\x12\x58\xd5\xbf\xe9\x7b\xbb\x23\x16\x52\x6a\xc1\xf9\x21\xb4\
-\x4e\x4a\xb8\x3a\xad\xd0\x34\x00\xf2\xf2\xf2\x3c\xdf\x1f\xd8\xb5\
-\xf9\xd0\x3f\x3e\x5f\x76\x68\xd3\xa6\x26\xe2\x8e\x3c\xb8\x93\xb7\
-\x1c\xc1\xc7\x8f\x68\x79\x0b\xe9\x69\x43\x20\xe8\x53\xaa\xd5\x02\
-\xba\x08\xd4\x91\xd0\xb5\x40\xb0\xcc\x5f\xe4\xf1\x6d\xe0\x47\xfe\
-\x87\xa9\x79\x44\x7d\x74\x8a\x00\x1a\x00\x3a\xc0\x3f\xe7\x0b\x90\
-\x6b\xf9\x80\xf1\x65\x1f\xde\x0a\x79\x5e\x64\xc8\xc3\x8f\xb8\xad\
-\xb8\x0f\xe4\xf4\x81\x06\x80\x5e\x84\x2a\x19\x30\x26\xe4\xb6\x1f\
-\x98\x92\x4f\x30\x21\x58\xb4\x87\x06\x80\x0e\x08\x62\x29\x89\x26\
-\xaf\xe3\x47\x3e\x2e\xc1\x3f\xc5\xb5\x83\xbe\xd0\x00\xd0\x09\xb1\
-\xd0\x62\x03\x84\x94\xbf\x6b\x42\x4e\x01\x5c\xc2\x8f\x74\x25\xf3\
-\xc1\x46\x07\xb4\x0d\x00\x63\xca\x84\x38\xdb\x1d\x0d\xa6\xe4\xec\
-\x86\x61\x63\xa7\xae\x24\xde\x08\x04\xd4\x6c\x9b\xf6\xb5\x6a\x7f\
-\xbb\x1b\x41\xb3\x00\x78\xf4\x99\x57\x52\x8c\x09\xf1\xbb\x5c\x1e\
-\x7f\x8c\x87\x65\x63\x8e\x9d\x3c\xfb\xcc\xd2\x8d\x65\xe3\x49\x75\
-\x44\xd1\xd6\xa2\x2d\xa4\x5e\x98\xfa\xe5\xee\xc0\x8f\x7e\x41\xa0\
-\x59\x00\x38\xae\x3a\x26\xf8\x7d\xfe\xc0\xa7\x97\xfc\xac\x19\x1d\
-\xc9\x3b\xa2\xc7\xa7\x99\x6e\x79\x0c\x44\x2d\x10\x4e\xc9\x40\x4e\
-\x3e\xcf\x8b\x1b\x78\x48\x14\xf7\xe3\xde\x3b\xe0\xea\x00\xd8\x11\
-\x59\x00\xe2\x36\x46\x96\x85\x9c\xa6\x68\x16\x58\xb7\xc3\x87\x43\
-\x1f\xd9\x1a\xb5\xb4\xce\x63\xc5\xc7\x9a\x3f\xfc\xb0\xe5\x0f\x10\
-\x39\x4c\xc2\xd1\x12\x6e\xcf\xe2\x06\x7c\x4b\x00\x7c\xf8\xa2\x0d\
-\x0f\xa9\x8a\xfa\x58\x64\xea\x7e\x0f\x0e\x04\xa1\x83\x14\x90\x58\
-\xb8\xee\xe7\x5f\x23\xf8\x4a\x8a\xe0\xfd\x38\x2f\xff\x80\x0c\x75\
-\x15\x25\x75\x4d\xee\x7a\x6e\xed\xc0\xbd\x30\xde\xc0\x6b\x08\xdd\
-\x49\x2a\xd4\x0b\xa3\x1b\xca\x5c\x1e\xff\x72\x2d\x2d\x8d\xe8\xd9\
-\xfb\x07\x96\xfc\xe1\xe1\xdc\xd9\x9c\x0b\x36\x5a\x70\xbb\x7c\x3a\
-\x78\xe8\x67\x7d\x97\x1a\x3a\x0f\xe5\x3e\xe0\xc9\x01\xd3\x33\x97\
-\x15\x1f\x2a\xe1\x88\x03\xb2\xa3\xcf\xa5\x90\xe3\x53\x9e\x60\xfb\
-\x60\xee\x7a\x91\xee\x51\x8a\x7c\xaf\xe2\x32\xc9\xe3\x40\xa9\x77\
-\x54\xa0\x09\x99\x0d\x25\xd3\x86\xa4\x8e\x9c\x96\x9b\xe3\x80\x5a\
-\xcd\x4e\x01\xb7\x0b\x47\xe7\x9c\xb6\xb7\x5e\x3c\x82\x57\xdd\x70\
-\xbb\x06\x8f\x1d\x6e\x36\x00\x83\x71\x24\x98\xb8\x2c\xe4\xc5\x69\
-\x70\x1a\xe7\x8d\x4c\xf1\xd8\x42\xeb\x78\x4f\xa8\x4f\x6e\xe2\x52\
-\xf0\x75\x78\x03\xc4\x3e\x40\x9c\x47\xc8\xe9\xb8\x8c\xc6\xa7\xbb\
-\x24\xe2\x03\x34\x00\x14\x28\x98\x7b\xd6\xee\xbe\xf0\x1d\xbc\xa3\
-\x2d\x22\x78\x30\xd5\xe1\xdb\xf0\x62\x05\x91\x96\xe5\x23\x15\x10\
-\x8f\xd6\x70\xc8\xdb\x8b\x09\xfa\xc4\x7b\x81\x7c\x7d\x75\x05\x1a\
-\x97\xe6\x2a\x9e\x7e\x57\x0f\x89\xf8\x00\x0d\x00\x15\x8e\xe3\x20\
-\x68\x85\x20\xc0\x47\x10\x0e\xa2\x78\x14\x87\x9a\x30\x3e\x85\x69\
-\x5a\xda\x56\x5e\xe6\xdb\xc3\x8f\xdc\x2f\x2e\xcb\x7f\xe4\xf5\xea\
-\x06\x08\x79\xd7\xd5\x4a\x34\x36\xb5\xbe\x78\xc6\xd0\x9e\xa3\xa6\
-\xe5\xda\x24\xe2\x03\x34\x00\xc2\x70\x7c\xde\x59\x7b\xcb\x85\xa3\
-\xc8\xab\x70\x17\x46\x7a\xd3\x2e\x74\x44\xf2\x92\x71\x19\x05\xa0\
-\x3d\x16\x53\xb1\x4e\xdc\x8f\x6f\xa7\xb4\xff\xf0\xf0\xaf\xde\x50\
-\x5d\x89\xc6\xa4\x39\xb1\xf8\xd9\x8a\xe2\x03\xfa\x06\x80\xf1\xa7\
-\x1f\x5f\x85\x73\xcf\xd8\x7d\x97\x8e\x21\xee\x2b\xf0\xe0\xa8\x12\
-\xe3\x24\x11\x95\xa5\x86\xc7\xaa\x70\x6f\x1f\xc0\x29\x27\xb6\xcc\
-\x94\xf6\xc1\x3d\x5a\x0f\x79\xa8\x95\xd5\xb5\x6d\x78\x03\xff\xf0\
-\x3e\x1a\xab\xaf\xa0\xd1\x29\xce\xe2\xc9\xfd\x6d\xf7\xa8\x89\x0f\
-\x70\xbf\x83\x16\x28\x5d\x05\x18\x91\xdf\x03\x4f\x37\x93\xa2\x0c\
-\x06\xc5\x44\x99\xd1\xb0\x3e\xc9\x1f\xfd\xe3\x9d\x19\xeb\x88\x33\
-\x84\x2d\xdf\x96\x26\xfd\x6e\x6d\xe1\x9a\x73\x17\xab\x6c\xf2\x7b\
-\xe5\x06\x1c\x60\xc3\xfa\x76\xfd\x6e\xfd\x92\x99\x4b\xba\x26\x36\
-\xd7\x12\xb7\x84\x2d\xfb\x8a\x93\x16\xad\x3d\xb1\xa6\xb4\xa2\x5a\
-\xd6\x9f\x41\x2c\xee\x3f\xa8\x67\xf2\xb6\x43\xab\x1e\x7a\x83\x38\
-\x43\xd8\xb2\xef\x6c\xd2\x0b\x1f\x9f\x5a\x13\x3f\xf3\xd5\x6e\x8c\
-\xed\xae\xe0\xd5\x41\x00\xd8\x67\x5b\x3e\xa5\x36\x04\xf8\x9d\x02\
-\x97\x8b\x61\xda\x05\xc0\x6d\x02\xcd\x14\x5e\x03\x27\x8d\x35\x95\
-\xe8\x9e\xd4\xfa\x73\x53\x06\x74\x1a\x3d\xeb\x9e\x5e\x55\x7c\xbd\
-\x32\x6d\xbd\x5a\xbb\x51\x0a\x80\x76\xe1\x6d\x45\x83\xfb\xf5\x99\
-\x5d\xb0\xff\xab\xcd\xc4\x23\x21\xbd\xc7\xc0\x3d\x8e\x46\xf7\x78\
-\xee\xff\xa7\x00\xfc\x07\x6c\x71\x31\x6f\x5d\x2a\x29\x58\xcc\x7b\
-\xa4\xc4\x75\xca\xd9\xe3\xf2\x32\xaa\x77\x24\x19\x2c\x40\x4e\x56\
-\xc6\x9b\x67\x0a\xf6\xbf\x4a\x5c\x12\xb2\xfa\x0c\x2b\x2a\xaf\x75\
-\x72\x7f\xf5\x24\xf7\x57\xef\x20\x5f\x66\x2e\x17\x38\xca\x04\x94\
-\xf9\x51\x80\x57\xe7\xa6\xfd\x76\x8a\x0f\x68\x36\x47\x27\xc4\xc2\
-\xf7\x1b\xab\xa8\x14\x06\x86\x35\xa3\x38\x96\x19\x47\x8a\x21\x44\
-\x5b\x63\x55\xc5\xe7\xc0\xa3\xa7\xd2\xe9\xca\x26\xa5\x10\x2c\x51\
-\x31\xe1\x6f\x47\x1b\x0c\xa8\xca\x71\x4d\xf5\xcf\xda\xd4\x37\xb5\
-\x04\xea\xf2\x57\xbf\x80\x8c\x95\xf9\xf8\x74\x20\xbe\x3c\x10\xff\
-\x72\x20\x7e\xdb\xc7\x40\x98\x14\xc3\xb7\x14\x6a\xe5\xa9\x9c\xe0\
-\xbe\x60\xc1\x37\x26\xd5\xd9\x6e\xf1\x01\xcd\x02\xa0\x7f\x56\xe2\
-\x66\xb3\x89\xad\x02\x41\xe0\xa9\xd7\xf6\x18\xde\x20\xd6\xef\x41\
-\x3e\x6b\xc2\x26\xb2\x9b\x10\xae\x55\xd7\xac\xe2\xd6\xbe\xb2\xbe\
-\x42\x7f\xe4\xf1\xa0\xec\x4e\xa9\x3b\x48\xf3\x10\x9c\x75\xd7\x70\
-\x7f\x8c\xac\x6f\xa0\x7f\x6b\x2b\xea\xd5\xbb\xb3\x6a\xff\xe4\xb8\
-\xe8\x1d\xe2\xd7\xcf\xff\xe8\x45\x64\xbc\x52\x80\x5f\x16\xee\x13\
-\xc0\x81\x17\x56\xe6\xbc\xac\xca\x2b\x75\xa1\x8e\x37\xbc\x33\x92\
-\x4a\xfd\xbc\xa9\xed\x07\xca\xa2\xf6\x78\x13\xf4\x33\x9c\xf8\xe3\
-\xd2\x60\xe4\xdb\xda\x2d\x3e\xc0\x1d\x1b\xad\xe8\x37\x62\x72\xaf\
-\x8a\x1f\x4a\xff\xd0\xe4\x67\xb2\x88\x2b\x2c\x71\xd1\x66\x94\x9e\
-\x92\xb8\xec\xfb\xfc\xfd\x3b\x89\x4b\x09\xa6\x73\xf7\x41\xaf\xd7\
-\x34\xb6\x8c\x84\xff\xb0\x18\x13\x9e\x8a\x3b\xa5\x25\x6c\x28\x3a\
-\x71\xe8\x63\xe2\x52\x82\x19\x90\x3b\x76\x5d\xc9\xa5\xca\x2c\x79\
-\x7f\xb3\x91\x45\xdd\xbb\xa4\x6d\x38\x71\x64\x5f\xd8\xfe\x7d\x87\
-\x8c\x5e\x57\x5a\xee\x90\xf4\x1f\xf4\xeb\x77\x27\xb8\xd3\x06\x23\
-\x96\xd5\xf7\xed\x0e\x90\x9c\xbb\x17\x05\xc1\xaa\x08\x83\x9c\xdc\
-\x1d\x3e\x57\xd1\xa4\x7e\x99\x63\xae\x47\x7c\x40\xd3\x00\x88\x34\
-\xee\xfe\xcf\x6d\x7e\x77\x7a\x47\x04\x81\x9a\x50\x82\xf8\x0d\x45\
-\x0f\x0d\xcb\x18\x33\x65\xf0\xf5\x89\x0f\xd0\x00\xb8\x49\xee\xb6\
-\xe3\x20\xc0\x33\x81\xd1\xa8\x16\x04\x62\xf9\x84\x39\x44\x7e\xd8\
-\xd5\x25\x56\x07\x8b\x7f\xb5\x1c\x4d\xb2\x35\x17\x3d\x70\x57\xfa\
-\x0d\x89\x0f\xd0\x00\xd0\x00\x08\x82\x96\x54\xb5\x99\x40\x4d\x5c\
-\xfe\x7c\xce\xd7\x88\xeb\x05\x7f\x38\x69\x60\xe4\x97\xa3\x29\x9d\
-\x9b\x8b\x66\xdc\x84\xf8\xc0\x4f\xff\x4e\xcd\x2d\xc0\x91\xa5\xd3\
-\x19\xb3\xe3\x38\x5e\x18\x2a\x7d\x0e\x46\x2e\x24\xbf\x94\x0b\x8a\
-\x0c\x06\x25\x01\xa1\xbd\xd8\x27\x06\x8b\x5f\x05\xe2\xb7\x14\x4d\
-\xea\x1b\x7b\xef\xcd\x88\x0f\xd0\x00\xd0\x88\xef\x5e\x9b\xce\x98\
-\x1c\x85\x38\x08\xbc\x9c\x74\xea\x26\x88\x2e\xf7\xf3\x41\x01\x06\
-\xf5\x21\xab\x7e\x62\x20\xfe\xd4\xac\xe6\x73\x43\x52\x3c\xe3\x7f\
-\x3e\x6a\xd0\x55\x3c\xe7\x18\xb0\x09\x51\x73\xdd\xd0\x00\xd0\x90\
-\xa3\x38\x08\x58\x12\x04\x6d\x23\xd6\x2c\x18\x14\x52\xa4\x6d\x9c\
-\x55\x97\xb1\xf8\x4d\xc5\xd6\x2b\x05\x53\x9f\x7e\x70\xcc\x35\xec\
-\x84\x47\x84\x40\x43\xe6\x46\x83\xe0\x86\x3a\x51\xc2\x93\xfb\xfb\
-\x6d\x7e\x4f\xc6\x10\xbc\x26\x50\x1b\x5f\x30\x96\xe1\xd0\xcb\x53\
-\x31\xbc\x8f\xdf\xf2\xd3\xfe\xd4\xce\x0d\xe7\x6b\x0f\x6f\x7e\xf0\
-\x93\x35\xef\x55\x62\x77\x2b\x31\x38\xef\x80\x41\x53\x30\xf8\x36\
-\x31\x2e\x6d\x0f\x74\x06\xd0\x81\xc2\x3f\x4e\xbf\x8f\x81\x9b\x45\
-\x5e\xe1\x66\x91\xdc\x78\x61\x83\xa9\x92\xf1\x75\x20\x3f\x77\xce\
-\xcf\xac\x2f\x2d\xdb\xb1\xe6\x11\x2c\xbe\x13\x3b\xe1\xbb\x97\x60\
-\xf4\xc3\xaa\x13\x22\x47\x88\xa2\xeb\x46\x1e\x76\x14\x8d\xc0\xca\
-\x4c\xe8\xf7\xbb\x6d\xbb\x51\x27\x3c\x13\xc8\xde\x3b\x00\xa5\xda\
-\x3e\xf0\xd0\xca\xc0\xad\xf6\x27\x65\x38\xcb\xce\x6f\xfb\x70\xfe\
-\xee\x2f\x37\x5e\xc1\x4e\x18\xed\xf0\x2d\xec\x30\xfa\x5b\x48\x0a\
-\x26\x3c\x12\x44\x67\x80\x5b\x01\x2c\xc2\x9e\x7f\xbe\x39\x7d\xb4\
-\xb7\x1c\xde\x4a\x96\x3c\x5a\xa4\x22\xbe\x58\x33\x5e\xfc\x3a\x2c\
-\xfe\x7d\xe9\x4e\x3c\xf2\x57\x3e\x82\xc5\x57\x9a\xf6\x03\xa2\x03\
-\xd7\x23\xbc\x00\x9d\x01\x74\x06\xcf\x04\x03\xbb\x2d\xda\x55\x10\
-\xdb\x6d\x80\xd1\x60\x68\x6b\xbc\x81\x7e\x20\x09\x5c\xe7\x57\xa0\
-\x89\x19\x75\xe7\xaf\x1d\xfc\xdb\xac\xcd\x7f\xfd\x0b\x5c\xea\x81\
-\xd8\xb0\xba\x04\x03\xf1\x85\xbc\x60\x7e\xbc\xb9\xee\x00\xa0\x33\
-\x80\xfe\xd4\x0d\x36\x5f\x5e\x5c\x5f\x7a\x12\x2f\x09\xda\xd2\x27\
-\x28\xfe\x8c\xae\x4d\x57\x47\x26\x5e\x9b\x8f\xc5\x2f\xc5\x4e\x17\
-\xb6\x06\x6c\x8d\xd8\x9a\xb1\x09\xa7\x00\xb0\x1b\x16\x1f\xa0\x33\
-\x80\xce\xe0\x19\x20\x11\xd2\x87\xdf\xf8\xfc\x97\x87\x6b\xac\x2b\
-\x62\x7b\x0c\x64\x61\x26\x10\xc6\x3a\x07\x29\x40\xe2\x72\x54\xa2\
-\xb9\xbd\xdc\xe8\xed\xf9\x77\x47\x93\x1a\x00\x52\x79\x3e\xe0\xbb\
-\x51\xf1\x01\x1a\x00\x1a\x83\x05\x97\xff\xb5\xd4\x80\x38\xf3\x96\
-\x6f\x7f\xfc\x40\x85\x71\x65\x6c\x8f\x41\x38\x08\xc8\xa1\x27\x4f\
-\x04\x41\x23\x78\x4b\x77\x4e\xcf\x16\xb4\xfc\x97\xc3\x61\x85\xaf\
-\x26\x6a\xc0\x7f\x33\xc2\x0b\xd0\x00\xd0\x18\x1c\x00\xf8\x9f\x04\
-\x89\x48\xf3\xdf\xdb\xf5\xc4\x37\x17\xfd\xab\x62\xbb\x0f\xc4\x17\
-\x07\xfc\x19\x18\x1a\x34\xd4\x54\xa2\x59\xdd\x1a\xd1\xb2\x05\xa3\
-\xb8\x9b\x3a\x5a\x88\xdb\x1e\x68\x00\x68\x0c\x88\x47\xb2\x1c\x4a\
-\x42\x3e\xf6\xdf\x7b\x9e\xfc\xe6\xa2\xf7\xcf\xd6\x2e\xfd\x59\x83\
-\xd1\x88\x1a\xaa\x2b\xd0\x83\x5d\x5c\xe8\x9d\x7f\x19\xdd\xe1\x7a\
-\xd0\x00\xf8\x91\x78\xfc\xfd\xbd\x4f\x7d\x73\xc1\xbb\xca\x6b\x4d\
-\x61\x7f\x9e\x55\x8f\x56\x3c\x75\x2f\xd5\x22\xd2\x58\xf8\x61\xde\
-\x53\x4f\x7c\x90\x77\x9a\x14\x29\x14\x0a\x85\x42\xa1\x50\x28\x14\
-\x0a\x85\x42\xa1\x50\x28\x14\x0a\x85\x42\xd1\x1e\x84\xfe\x1f\x55\
-\x0b\x04\x29\x5c\xfb\x2b\x5e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
-\x42\x60\x82\
-\x00\x00\x07\x52\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
-\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
-\xa8\x64\x00\x00\x06\xe7\x49\x44\x41\x54\x78\x5e\xdd\x9b\xdb\x6f\
-\x14\x55\x1c\xc7\x7f\xe7\xec\xad\xdd\x5e\xd8\x5e\x2c\x5d\x4a\xb7\
-\x2d\x95\x4b\x03\x7d\x90\x82\xc6\x0b\x86\xad\x31\x98\x80\x18\x0c\
-\x60\xf4\xc1\x4b\xe2\x83\x41\x83\x0f\xea\x93\x7f\x82\x1a\x0d\x46\
-\x5f\xd0\x10\x4d\x34\xb1\x9a\xa0\x4d\x6b\xe0\x41\x5a\xc5\x88\x91\
-\xd6\x88\x20\xb4\x29\x6d\x29\xa6\x2c\xad\xb4\x85\x76\x2f\xdd\xcb\
-\xcc\xf1\xfc\x66\xcf\x94\x4e\xbb\xbb\xdd\xcb\xcc\x74\x97\x4f\x02\
-\x7b\xce\xaf\xdb\xb0\x9f\xef\x9c\xdb\x4c\x29\x81\x7b\x84\x89\x4b\
-\x1d\xa5\x55\x84\xbe\x09\x04\x0e\xf3\xee\xe6\x78\x95\x8c\x12\xc2\
-\xce\x10\x60\x27\x68\xcb\xa1\xbe\x78\x4d\xcb\x3d\x11\x80\xfc\xcf\
-\x77\x0d\x32\x81\xd3\x84\x10\x21\x9e\x00\xc6\x3a\x89\x14\x7d\x83\
-\xb6\x3e\xff\xaf\xa8\x28\x14\x7c\x00\x71\x79\xd2\x43\x08\x34\x89\
-\x52\x52\x18\xb0\x29\xfe\xe7\xa0\xad\xe5\x50\xaf\x28\x01\x15\xaf\
-\x05\x49\x26\xf2\x08\x01\x52\x35\x31\xe5\x3f\x75\xbe\xfb\xe3\x27\
-\x45\xa9\x70\x03\xc8\x54\x1e\xf1\x4d\xcd\x82\x6f\x7a\xce\x01\x12\
-\xeb\x18\xf9\xe9\xb3\x06\xac\x15\x64\x00\x39\xc8\x2b\xed\xea\x35\
-\x25\x2e\x4f\xad\xeb\x43\x6c\x17\xdc\x1a\xa0\x83\x3c\x78\x6a\x5c\
-\x4a\x3b\xc6\xa0\xcd\xa2\xb4\x0a\x04\x3d\xe5\x11\x4a\x20\x5a\x30\
-\x01\x04\xb9\x3c\xd5\x51\x5e\x50\x52\x10\x53\x00\xe5\xed\xfa\xcb\
-\xf3\xa3\x01\x0b\xe6\xfd\x22\x68\x94\xbc\x02\x3f\x22\xe6\x75\x00\
-\x86\xca\xc7\x19\xcc\xdb\x00\x4c\x90\xe7\x73\x80\x74\xe4\xe5\x1a\
-\x60\x86\x3c\x63\xfc\xea\x57\x94\xb6\xe5\xdd\x08\x30\x49\x7e\x94\
-\x32\xb6\x87\xba\xf7\x04\xf2\x2a\x80\xb8\x3c\x98\x21\xef\xa5\x5b\
-\x0f\x8e\x61\x3f\x6f\x02\x60\xc3\x9d\x9e\xb8\x3c\x31\x4d\x1e\xc9\
-\x8b\x35\x00\xe5\xa5\x70\xa4\xd7\x6c\x79\x64\xd5\x03\x58\x4d\x79\
-\x64\x55\x03\x58\x6d\x79\x64\xd5\x02\x60\x7d\x1d\x9e\xc0\xe0\x50\
-\x6f\x6c\xec\x46\x93\x74\xc7\x0f\xc4\x6e\x05\xeb\xda\x6a\x70\x6c\
-\x69\x04\x6b\x5d\x8d\x78\x97\x16\x8d\x7c\x39\x97\x5f\xbb\xb2\x7c\
-\x84\xcb\x3b\x93\xc8\x23\xab\x12\x80\xef\xd5\xa7\x9b\x88\x3f\xfc\
-\x93\xec\x0f\x26\xbc\xf2\xb6\x06\x37\x94\xed\x7b\x1c\x6c\x8d\xeb\
-\x44\xc5\x18\x79\xc4\xf4\xbb\xc1\x9b\x2f\xec\xdd\xc0\xa6\x67\x7f\
-\x66\x91\x88\xf2\x44\x26\x11\x32\x1f\x11\xa1\xbe\xcb\x00\xd1\x18\
-\xd8\xef\xaf\x57\xc4\x8d\x90\x47\x4c\x0d\x00\xe5\xe5\xb9\xb9\x5e\
-\x60\x72\xbd\x28\xa5\x24\x7a\xed\x06\xf8\x7d\xb7\xc0\x57\x55\xc9\
-\xc7\x2a\xd1\x5d\x1e\x31\x2d\x00\xe5\xca\xfb\xe7\x7a\xb8\xbc\x47\
-\x94\xd2\x82\x4c\x4e\x03\x91\x19\x94\xb5\x6c\x48\x43\x9e\x71\x79\
-\x48\x5b\x1e\x31\xe5\x20\xa4\xca\x33\x39\x33\x79\x95\xb2\x0b\x03\
-\x50\x1b\x0c\x88\x5e\x62\xb2\x91\x47\x0c\x1f\x01\xb9\xca\xab\x48\
-\x7c\x24\x14\x3f\xb8\x4d\xf4\xb4\xa0\xbc\xc5\x61\xdf\x6d\xdf\x7c\
-\xe0\xba\x28\xa5\x8d\xa1\x23\x40\x2f\x79\x24\x3a\xe6\x83\xd8\xf8\
-\xa4\xe8\xdd\x45\x95\x27\xcd\xfb\x33\x96\x47\x0c\x0b\x40\x4f\x79\
-\x95\xf0\xc0\x35\xd1\x8a\x93\xab\x3c\x62\xc8\x14\x40\x79\x3e\x68\
-\x7b\x6c\x9e\x5a\x8f\x6d\x5d\x0d\xd0\x92\x62\x90\x43\x61\x5e\x92\
-\xc4\x3b\xb2\x83\x96\x39\xa1\xa8\x75\xa3\xd2\xd6\x43\x1e\xd1\xfd\
-\x20\x14\x3a\x7d\xac\x89\xc4\x58\x2f\x3f\xc4\x78\x80\x2e\x1a\x60\
-\x92\xcc\xaf\xe0\x28\x04\x7a\xfb\x94\xed\x2d\x1b\x1c\x5b\x9b\xc1\
-\xf5\xf2\x7e\x6c\x8e\x50\xbb\xcd\x9b\xab\x3c\xa2\xeb\x08\x60\x97\
-\x3a\x3c\x64\x4d\x79\x8f\xa5\x72\x4d\x23\xee\xdb\x1a\x28\x01\x6b\
-\x4d\xa5\xb2\x90\xf1\xaf\x43\xe4\x2a\xff\xec\x3c\x94\x4c\x70\x6c\
-\xf4\x80\xa3\xa5\x69\x84\x4a\x92\x97\x6c\x79\x36\x67\x79\x44\xb7\
-\x00\x50\x5e\xa2\x96\x1e\x42\x09\x1f\xfe\xa9\xb1\xad\xbb\x8f\x9f\
-\xf9\x9b\x20\x74\x71\x48\x39\xed\xa5\x8b\x73\xd7\xf6\x11\x7b\x4d\
-\x85\x97\x6c\x3b\xac\x8b\x3c\xa2\xcb\x22\xb8\x20\x4f\x60\x45\x79\
-\x95\xff\x1c\x0e\x98\x7c\x6a\x17\x30\x9b\x55\x54\x52\x43\x4b\x9d\
-\xa3\xce\x4d\xeb\x75\x95\x47\x72\x0e\x20\x1b\x79\xf5\xc6\x26\x5a\
-\xe5\x82\x68\xfb\x43\xa2\x9a\x1c\x42\xe9\x75\x66\x75\x3c\x41\x76\
-\xbc\xa4\xab\x3c\x92\xd3\x14\xc8\x45\x1e\xa9\xc2\xb3\x7d\x6b\x33\
-\x44\x86\xae\x83\x7c\x3b\x5e\x5b\x0a\xca\x93\xd2\x32\xaf\xfb\xab\
-\xae\x51\x51\xd2\x95\xac\x03\xd0\x43\xbe\x01\xcf\xf6\x7c\xad\xc4\
-\x6d\x72\xfe\xaf\x41\xa5\xbe\x18\x55\xbe\xf6\xeb\xee\x11\x51\xd2\
-\x9d\xac\xa6\x80\x6e\xf2\x02\x5c\x10\x89\xc3\x2e\x7a\x71\x18\xbf\
-\x2b\xb6\xd8\xac\xaf\x19\x29\x8f\x64\x1c\x80\xde\xf2\x0a\x16\xaa\
-\xec\x0c\x2a\x28\x8f\xaf\xb1\x70\xf8\xf3\xf1\x7d\x0f\x6f\x51\x8a\
-\x06\x91\x51\x00\xc1\x9c\xe5\x9d\xcb\xe5\x05\x7c\x95\x57\x5e\x55\
-\x79\x9c\x19\xfc\x6f\x37\x01\x7a\xc6\xc8\x10\xd2\x0e\x00\xe5\xed\
-\x39\xcb\x57\x28\xed\x44\xc8\xe1\xc8\x12\x79\x15\x63\x43\x48\x2b\
-\x00\xa3\xe5\x41\x96\x21\x3a\x3e\x99\x40\x5e\xc5\xb8\x10\x56\x0c\
-\xc0\x70\x79\xce\xfc\xc5\xab\x12\x0b\x84\x58\x62\x79\x15\x63\x42\
-\x48\x19\x80\x19\xf2\xb1\xa9\xdb\xb1\xd9\xef\xcf\x60\x33\x8d\x2d\
-\x59\xff\x10\x92\x06\x60\x96\xfc\xf4\xa7\xdf\x02\xf3\x87\x32\x38\
-\x8f\xe8\x1b\x42\xc2\x00\xcc\x90\x67\x0c\x46\x66\xbe\xe8\x3a\xce\
-\x66\xfd\xe9\xdd\x0c\x68\xd0\x2f\x84\x65\x01\x98\x25\x1f\x91\x25\
-\x6f\xed\xf1\x93\x47\xf8\xca\xff\x81\x28\x67\x88\x3e\x21\xf0\x75\
-\xe7\x2e\x66\xca\x3b\x17\xdd\xd5\x8d\xef\x7b\xec\x7d\xfe\x41\xde\
-\x12\xdd\x0c\x61\x3e\x06\x72\x7b\x5d\xd7\xb9\x01\x51\xc8\x88\x85\
-\x00\xe4\xa1\x93\xf5\xb7\xef\x04\x7a\x83\xe1\xd8\x86\x68\x4c\xe2\
-\x87\x33\x02\xc5\x0e\x1b\x94\x3b\x8b\xc0\xca\x4f\x6a\x89\xd0\x43\
-\x5e\x65\xa5\x10\xf8\xf7\xbe\x0b\x84\x2c\x7f\x2a\xca\xa1\x32\xf8\
-\xdc\x3f\x9e\xed\x16\xdd\x8c\x50\x02\xe8\xeb\xfc\xc8\x63\xb5\x5a\
-\x7b\xa2\x31\x79\xd9\x95\x27\x7c\x38\x54\x96\x15\x83\xbb\xaa\x1c\
-\xec\xd6\xbb\x6b\x95\x9e\xf2\x2a\xa9\x42\x90\x18\xdd\x54\xdf\xfd\
-\xcb\x90\xe8\xea\x06\x3d\xfd\xe5\x7b\x25\x32\x23\xa7\x12\xc9\x23\
-\x8c\x7f\xf2\xa9\xd9\x20\x5c\x19\x9b\x80\x99\xb9\x90\x52\xcb\x46\
-\x9e\xda\xe8\xee\x54\xf2\x48\x5d\xd7\xaf\x6f\x67\xbf\x26\x64\x07\
-\xad\xa8\xb0\x1f\xe5\x57\xb9\x45\xf4\x93\x22\xc9\x0c\x46\x6f\x4e\
-\xc3\xf0\x8d\xa9\xac\xe4\xe9\xc6\x03\x9a\xdf\xd4\x48\x86\xd9\x21\
-\x50\x7e\xfa\x7e\x4e\xb4\x15\x94\x2b\x3e\x33\x07\x81\xe0\xbc\xa8\
-\x68\xb9\x13\x98\x57\xa6\x85\x11\xf2\x2a\x66\x86\x40\xb9\x8c\xe6\
-\xf7\x6c\x06\x86\xc7\xe1\x5c\xff\x00\xf4\xfc\x76\x11\x7e\xef\x1f\
-\x4c\x1a\x04\xae\x09\x2b\x30\x9c\x8d\xbc\x8a\x59\x21\x50\x7e\x95\
-\x16\x76\x02\x24\xcc\xef\xca\x54\x6e\xcd\xcc\xc2\xd9\x3f\x2e\x2b\
-\x23\x62\x31\x38\x4a\x70\x1d\x48\xc1\x30\xb1\x52\x6f\xb6\xf2\x2a\
-\x66\x84\xc0\xf7\x37\xa6\x79\xd6\x56\x53\xad\xbd\x5f\x8f\xf1\x2d\
-\xf1\xfc\x85\xa1\x65\x23\x61\x9a\x2f\x88\xb1\xc4\xcf\xf5\x75\x91\
-\x57\x31\x3a\x04\x9c\x02\x3d\xa2\xad\xe0\xae\xa9\x84\x0a\x57\xa9\
-\xe8\xc5\xc1\x10\xfe\xbe\xa2\xfd\xa9\x33\x8e\x82\xd9\xe5\xd3\x43\
-\x57\x79\x15\x0c\x61\xe2\x66\x40\xfb\x83\x41\x9d\xa0\x16\xb0\x9c\
-\x10\x6d\x05\xbe\xbe\x41\x5b\x6b\x33\x14\x17\x69\x9f\xd1\x4d\xf1\
-\xe9\xb0\x74\x14\x84\xc2\x51\xd1\x52\x30\x44\x5e\x65\x47\x7f\xbf\
-\xe6\x1f\xd3\x0b\xba\x7d\xff\xeb\xe7\xf9\xd5\xd4\x9c\xa2\x8a\x1c\
-\x76\x78\x74\x67\xcb\xb2\x91\x30\xaf\x15\x56\xb6\x46\x84\x01\x33\
-\x54\xde\x48\x94\x33\x2e\x25\xec\x08\x7f\x99\xc6\xb6\x0a\x86\xf0\
-\x48\x5b\x8b\x32\x1a\xd6\xbb\xab\xa1\xb9\xd1\x0d\x95\x4b\x02\xb1\
-\xf1\x93\x21\xca\x53\xab\xa5\x20\xe5\x91\x85\x1d\xa0\xef\x87\x63\
-\xed\x8c\x00\x8e\x84\xa2\x78\x65\x65\x9a\xeb\xaa\x86\x5d\xe5\xce\
-\x82\x95\x47\x16\xee\x72\x76\x3c\x73\xf4\x0c\x61\xb0\x97\x37\x35\
-\x23\x21\x19\x76\x9b\x65\xd8\x65\x2f\x6c\x79\x44\x73\x9b\xa7\x84\
-\x00\xf2\x03\x4b\xd7\x84\xa5\xf0\xaf\x5f\x89\x46\xa3\xed\xb4\xb5\
-\xb0\xe5\x11\xcd\x21\x68\x31\x7f\x76\x7e\xb2\x53\x02\xe9\x15\x2e\
-\xeb\xe5\x6f\x6b\xe2\xbb\x03\x6f\xb2\x41\x1e\xd9\x37\x33\x33\x91\
-\x63\x7b\x5e\x7c\x27\xf5\x7f\xdb\x2a\x08\x00\xfe\x07\x67\xd1\x50\
-\x78\x73\x48\xdf\xa1\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
-\x82\
-\x00\x00\x05\x36\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
-\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
-\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
-\x09\x70\x48\x59\x73\x00\x00\x16\xb7\x00\x00\x16\xb7\x01\x5a\x8b\
-\x7b\x20\x00\x00\x04\xcb\x49\x44\x41\x54\x78\x5e\xed\x9b\x59\xc8\
-\x75\x53\x18\x80\x3f\xf3\x4c\x64\xce\x10\x91\x39\xe5\x02\x17\x08\
-\x45\x11\x32\x24\xdc\x28\x12\x19\xae\x64\x2a\x53\x29\x37\x4a\x21\
-\x43\xe6\x12\x17\x72\x27\x94\xbf\x50\x8a\xa4\x94\x79\x0c\x91\x21\
-\x43\xc6\xcc\xe3\xf3\x9c\xbd\x97\x56\xbb\x7d\xce\xd9\x6b\xef\xf5\
-\x9f\x75\x74\xce\x53\x4f\x7b\x7f\xfb\xdf\xdf\xf9\xd6\x7a\xcf\x5e\
-\xd3\xbb\xf6\xbf\x52\x90\x03\xf0\x13\x7c\x0b\x77\xf0\xc2\xa2\x71\
-\x1b\xfe\x53\x7b\xb1\x17\x4a\xb0\x66\x7d\x2c\xc1\xba\xf5\x51\xe2\
-\xf3\x99\x52\x32\x00\x73\xc1\x32\x00\xf5\x71\x61\x59\x06\xa0\x3e\
-\x2e\x2c\x29\x01\xd8\x14\xff\x2f\x01\xdb\x0c\xd7\xa8\x4e\x27\xd3\
-\xb5\x42\x97\xe2\x77\xf8\x2a\x6e\xef\x85\x0c\x7c\x59\x1f\x25\x3e\
-\x1f\x82\xf5\xb9\x1d\x2d\xeb\x73\xb8\x36\x66\xe1\x05\x0c\x93\x96\
-\x77\x30\x47\x10\xfc\x96\x6e\xc2\xeb\x70\x1d\x2f\x0c\xc4\xca\xdf\
-\x8d\xa1\x9c\xba\x33\x66\xe1\x4c\xfc\x1b\x73\x07\x21\x17\x6d\x95\
-\x7f\x14\x3b\x35\x83\xae\x9c\x87\xf3\x18\x84\xb6\xca\x3f\x8e\xeb\
-\xe1\x54\x52\x23\x64\x10\xee\xc0\xf0\x7b\xef\xe2\x11\xf8\xd9\xe8\
-\xa7\xe9\xf8\x7b\xbb\xe3\xde\xb8\x0b\xda\x0c\x6c\xa7\x3f\xe2\xe7\
-\xf8\x36\xbe\x82\xbf\x61\x17\xac\xfc\x9d\x78\xce\xe8\xa7\x8a\x27\
-\xf0\x64\xec\xfa\x19\xc9\xb4\x3d\x09\xdb\xe2\x38\xac\xf4\x91\x78\
-\x1f\x1a\xa8\xf8\x9b\x6a\xf3\x67\x7c\x12\xcf\xc2\x4d\x70\x1c\x7e\
-\xee\x5d\x18\xff\x6e\xe7\x6f\x7e\x28\xcd\x20\xdc\x88\x6d\x9c\x8a\
-\x8e\x1c\x71\x21\x53\xfc\x16\xed\x24\x1d\x82\x9b\x1c\x84\xf1\xbd\
-\x33\xab\x7c\xc0\x20\xfc\x85\xfe\xf1\x0b\xbc\x10\xb1\x2b\x3e\x85\
-\x71\x01\x83\x3e\xee\xcf\xe3\x03\xf8\x50\x7d\x6d\x9a\x9f\xe2\x49\
-\x18\xb3\x13\xfa\xb4\xf8\xef\x33\xaf\x7c\xc0\xa4\x86\x7d\x40\xcc\
-\x89\xe8\x38\x1c\x57\xe0\x27\xbc\x07\xbd\x37\x5e\xfa\xee\x8b\xf1\
-\x7d\xd3\xbc\x15\xe3\xb1\x7d\x37\x3c\x16\x73\x0c\xa3\x59\x38\x1f\
-\xc3\x53\xa1\x7f\xe2\x2d\xb8\x0d\xb6\x91\x1a\x00\x7d\x0c\x37\xc0\
-\xb9\xc3\x4e\x2b\xee\x17\x3e\xc0\x03\x71\x12\x7d\x02\xa0\x8e\xf1\
-\xd9\x66\x79\x39\x38\x0c\xff\xc0\x50\x40\xdb\xf8\x16\x38\x8d\xbe\
-\x01\x50\x67\x91\x73\xc1\xe6\x68\x72\x33\x14\xec\x45\xdc\x18\xbb\
-\x30\x24\x00\x3e\x6d\x27\x60\x71\x9c\x18\x85\x42\xd9\x5b\x8f\x6b\
-\xef\x6d\x0c\x09\x80\x7e\x8c\x1b\x61\x31\xf6\x40\x3b\xba\x50\xa0\
-\xa3\x30\x85\xa1\x01\xd0\x2b\xb1\x18\xce\xee\x42\x41\x1e\xf1\x42\
-\x22\x39\x02\xf0\x15\x16\x19\x15\x9c\xa6\x3a\xbe\x5b\x08\xdb\xa3\
-\x95\x49\x25\x47\x00\xf4\x0c\xec\x85\x8b\x89\xbe\xd8\x01\x6d\x58\
-\x9d\xae\x3c\x8b\xaf\x57\xa7\x45\x38\xad\x3e\x26\x33\x24\x00\x2e\
-\x70\x02\x0f\xd7\xc7\x52\x1c\x8e\xbd\xe6\x05\x43\x02\xe0\x62\x24\
-\xf0\x74\x7d\x2c\x85\xcb\xea\x3d\xab\xd3\x34\xfa\x06\x60\x2d\x74\
-\x1e\x2e\x2e\x48\xde\xab\x4e\x8b\xe2\x88\x94\x8c\x6b\xea\x7d\xf0\
-\x7a\x9c\xb4\xf6\xfe\x05\x5d\x96\x3a\xc9\x91\xad\x30\x24\x32\x4d\
-\x62\xec\x55\x9d\x26\x63\x27\xf8\x5a\x75\x3a\x98\x0b\xd1\x84\xa8\
-\x38\x05\xbf\x06\x27\x8d\x0e\xae\x4a\x47\x43\xe8\x2a\x6c\xeb\x59\
-\x9b\xbe\x84\x01\xb3\x39\xe1\x7a\x08\x4a\x1f\x72\x8d\x02\x7a\x19\
-\x06\x2c\x6b\xdb\x3d\x4d\x57\xd9\x04\xdc\x9f\xef\x42\x7c\x9f\xf3\
-\xfe\x40\xb1\x9d\xdd\x06\x71\x99\x3a\xd7\xc9\x26\x60\x10\x8e\xc6\
-\x49\x4d\xc0\x76\xee\x93\x12\xfe\x88\xf7\xfe\x50\x9d\x8e\xd6\x01\
-\x3b\x56\xa7\xc9\xe4\x6c\x02\xe6\x05\xef\xad\x4e\x47\xf9\x01\xeb\
-\x14\x86\xe9\x36\x6c\x02\xd6\xa9\x37\xf6\x01\x3e\x46\x4e\x82\xba\
-\x2e\x7e\x9a\xe4\x6c\x02\xcd\xc4\x4c\x27\x86\x0c\x83\x6f\xd4\x47\
-\x9f\xa2\x78\x48\x2c\xc5\x9b\xf5\x31\x89\x21\x01\x70\xf6\x17\x30\
-\x2d\x55\x12\x47\xa2\x2f\xaa\xd3\x34\x86\x04\xc0\xfc\x7b\xc0\xb9\
-\x78\xc9\xbc\x9c\x49\xd1\x22\x18\xf9\xd0\x06\x4d\x89\xa5\x92\xab\
-\x0f\xd8\x1f\x8b\x60\x12\x34\x14\xe2\x23\x4c\x4d\x4e\xe4\x08\xc0\
-\x33\x58\x8c\xf5\xd1\x8a\x87\xc2\x98\x01\x4e\x21\x47\x00\x7a\xf5\
-\xfe\x39\x71\x1f\x2e\x14\xc6\x21\xf1\x74\xec\xca\xd0\x00\x94\x5e\
-\x85\xfe\x47\xbc\xc3\xf3\x2b\x1e\x83\x5d\x18\x12\x00\xf3\x8f\x5b\
-\xe3\x5c\xe0\xcc\x30\xde\x03\xfc\x1d\xcf\xc6\x69\xf4\x0d\x80\x8b\
-\xb3\x43\x71\xae\xf0\x5d\x81\xf7\x31\x2e\xe8\x83\xe8\xca\x71\x1c\
-\x7d\x02\xe0\x74\xfc\x14\x9c\x4b\xb6\x43\xf7\xf7\xe3\x02\x7f\x83\
-\x57\xe3\x96\xd8\x24\x35\x00\xe6\x20\x8f\xc3\xb9\xc0\x49\xd4\xb9\
-\x78\x39\xc6\x8b\x0e\xd7\x05\xee\xfc\x36\x0b\xef\x0b\x0b\x6e\x69\
-\x5d\x84\x07\xa3\x01\x71\xfc\x6e\xde\x37\x4e\x57\x78\xfb\x61\x8c\
-\x1d\xf0\xb5\x98\xb2\x17\x91\x05\x2b\x1f\xbf\x96\x62\xb2\xa4\xc9\
-\xf1\xe8\xfe\x60\x5c\x89\x3e\x86\x64\x4c\x33\xb9\x61\x30\xc2\x5e\
-\xe4\x4c\x5f\xd7\x69\x56\x5e\xaf\xc2\x36\xcc\x15\xd8\x19\xbe\x8c\
-\xf1\xfd\x5d\x74\xb5\x79\x03\xda\xac\xda\x30\x0b\x15\xef\x44\xcf\
-\x24\x08\x6d\x95\xef\xfa\x72\x82\xdf\x98\x59\x1b\xef\xff\x10\xe3\
-\xc2\xeb\xd7\xe8\xbb\x7d\xbe\x6d\xe2\x30\xda\x65\x6d\x31\xd3\x17\
-\xb7\x86\x54\xbe\x0d\x3f\xcf\x57\x5f\xdc\x45\x1e\x92\x55\x9a\x49\
-\x10\x72\x57\x3e\x37\xab\x3d\x08\x66\x8d\x57\x47\xe5\xfd\x8c\x5c\
-\xcb\xe8\x66\x10\x4c\x90\x64\x5b\xa2\xc7\xaf\xca\xe6\xaa\xfc\x21\
-\xf8\x3d\xfa\xea\x5c\xd8\x63\x18\x4a\x33\x08\xbe\x48\x95\x05\xf7\
-\x01\x8d\xe8\xfd\x98\xeb\xb1\x8f\xdf\x2b\xb8\xc4\x0b\x99\x30\x2f\
-\x61\x9e\xe2\xe6\xd1\x4f\x73\x4c\xdc\xa7\x5c\xe1\x85\x12\xd8\xb9\
-\x2d\x34\xcb\x00\xd4\xc7\x85\x65\x19\x80\xfa\xb8\xb0\x2c\x03\x50\
-\x1f\x4b\x60\xda\x2c\x10\x9f\x2f\x0c\x73\xf0\xdf\xe7\x57\x56\xfe\
-\x05\xdb\xb5\xa7\xd2\xe2\x7e\x5c\x73\x00\x00\x00\x00\x49\x45\x4e\
-\x44\xae\x42\x60\x82\
-\x00\x00\x16\xda\
-\x89\
-\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
-\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
+\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\
@@ -2539,6 +2196,1467 @@
\xe6\x82\xc2\xea\xa9\x94\x57\x04\x10\xa0\x24\x18\x65\xc5\x7f\xa5\
\x4b\x47\x8c\xfd\x2f\x03\x29\x07\x44\x48\xb3\xa2\x64\x00\x00\x00\
\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x21\xa6\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\
+\x9c\x18\x00\x00\x21\x3b\x49\x44\x41\x54\x78\x5e\xed\x5d\x09\x9c\
+\x14\xc5\xd5\x7f\xbb\x2c\x7b\x2f\x02\x2b\xb2\x80\x20\x88\x28\x8a\
+\x0a\x78\x1f\x31\x46\x41\xf0\xc2\x1b\x09\x78\x47\x8d\x89\xfa\x79\
+\xdf\xdf\xcf\x23\x44\xcd\xa1\xe6\x82\x78\x25\x26\x2a\x31\x0a\x2a\
+\x9e\x88\x31\x82\x28\x88\x80\x8a\x18\x45\x40\xce\x95\x73\x61\x59\
+\x96\x95\xbd\xaf\xef\xfd\x5f\x55\x75\xd7\xf4\xf4\xcc\xce\x76\xef\
+\x2e\xf9\x7e\x33\xff\x9e\xea\x7a\xf5\xea\x55\x57\xf5\x7b\xaf\xeb\
+\xe8\x99\xe9\x4e\x6b\x6e\x6e\xa6\x14\x92\x17\xe9\x3a\x4e\x21\x49\
+\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\x72\xa4\x1c\x20\
+\xc9\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\x72\xa4\x1c\
+\x20\xc9\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\x72\xa4\
+\x1c\x20\xc9\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\x72\
+\xa4\x1c\x20\xc9\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\
+\x72\xb4\xc9\x8f\x42\xab\xaa\xaa\xa8\xb8\xb8\x98\xea\x6a\x6b\xe9\
+\xfb\x8a\x0a\xda\xb1\x63\x07\x87\xb2\x1e\xe5\xe5\x3b\x7e\xb8\x75\
+\xeb\xb6\x13\xb7\x96\x6c\x19\x58\x57\x5b\xd7\xb7\xba\xa6\x3a\x2f\
+\x3d\x2d\xbd\x99\xd2\xb8\x50\x5a\x9a\xf2\xbe\x34\xe5\x83\x69\xe9\
+\x69\xcc\x46\x06\xb2\x34\x85\x98\x09\x49\xe1\x83\x04\x52\x8a\xa9\
+\xf9\x4a\x36\x52\x46\xc5\xde\xe3\x28\x29\x25\xe7\x0b\x56\x45\x33\
+\x76\xd8\x4b\xa4\x53\x88\xb5\x9e\x24\x96\x8f\xca\x53\x32\x9a\x27\
+\x32\x5a\x56\x3e\xa0\x8d\x8c\x4a\xcb\xc7\x2a\x43\xcd\x4d\xd4\xc4\
+\x91\x08\xf2\xa7\xa9\xa9\x29\x2d\x3b\x3b\xab\xa6\x73\x66\xe6\x86\
+\x3d\xf7\xec\xb1\xb6\x5b\xf7\x6e\x1f\xf7\xed\xdb\x6f\x4e\xd7\x6e\
+\xdd\xd7\x17\xe4\xe7\x53\x7e\x41\xbe\x88\x0e\xda\x7f\x10\x15\x14\
+\x74\x41\xc9\x50\x68\x33\x07\xf8\xee\xbb\xef\x44\xc9\x6b\x57\xaf\
+\xe9\x3b\xeb\xfd\xf7\x6e\xfc\x76\xc5\x8a\x09\x3b\x77\xee\xec\xd5\
+\xd8\xd4\x44\x19\x9d\x3a\x89\x31\x3a\xa5\x77\x12\x63\xc0\x00\xe9\
+\xca\x22\x9c\x64\x07\x00\x8b\xd3\xb2\x81\x2d\xb4\x95\x17\xc1\x07\
+\x2d\x4c\x15\xeb\x34\x28\xc9\x77\x64\xec\xb4\x4b\x2b\x52\xc5\x5e\
+\xd8\x86\x73\x8c\x26\x3c\xa6\x35\xdf\x49\x9b\x3c\x87\xa7\xd2\x92\
+\x83\x58\x58\x86\xdf\x84\x28\x82\x6f\x97\x01\xd1\xa4\xd3\x42\xb3\
+\xce\x10\x1a\x1b\x1b\xa5\xad\xf9\xf9\xf9\xe5\x03\xf7\x1b\x34\xfd\
+\xe4\x91\x23\x1f\x3b\xe0\x80\x03\xbe\xa9\xa9\xa9\xa5\xfd\x06\xed\
+\xf7\xdf\xe3\x00\x35\x35\x35\xb4\x69\xd3\x26\xfa\xf0\x83\xd9\x57\
+\x4c\x7f\xf5\x95\x87\xcb\xca\xca\x8a\x32\x3b\x77\xa6\x8c\x8c\x0c\
+\xa5\x78\x96\x11\x43\x88\xe2\x39\xf0\x47\x39\x80\xe6\xe1\x23\x72\
+\x48\x8b\x30\x58\x1c\x79\x1d\x20\x5d\xf3\x85\xa9\x62\x26\xe4\x58\
+\x2a\x03\x92\x6a\x93\xa2\x22\xa4\xca\x22\x25\xb4\x24\x90\x13\x01\
+\xa3\x05\x31\xa2\x18\x43\xcc\xa7\x63\xf0\x74\x1e\xb8\x92\xe0\xab\
+\x15\xb1\xe4\xa9\xb4\xca\x07\x8b\x0d\x2e\x2c\x9b\x2f\x84\xc3\xb7\
+\xcb\x08\x47\xe7\xb9\x34\x07\x49\x36\x8b\x23\xd4\xd6\xd5\x11\xf7\
+\x00\xbb\x4e\x19\x7d\xea\x43\xa3\x4f\x3d\xf5\xd7\x03\x07\xee\x47\
+\x39\xb9\xb9\x90\x08\x05\xd5\xff\x86\x44\x27\xbe\xc2\x5f\x9e\xfa\
+\xd2\xa3\x4f\x3f\xf9\xc4\xdf\x76\x96\xef\x2c\xca\xce\xce\x16\x5e\
+\x8b\xf0\x5a\x21\x02\x71\x33\x35\x62\xc8\xf8\xb0\x6d\x96\xd0\x70\
+\x86\x74\x76\x28\x0e\x42\x4b\x8e\x82\xca\x17\x32\x0a\x51\x72\xbe\
+\x82\x31\x0a\xfb\x21\x01\xd1\x74\x6e\x23\x74\xca\x17\x5a\xfe\xb4\
+\x97\x5e\xfc\xd5\xf3\xcf\x3e\xfb\x52\x5d\x5d\x5d\xb6\xce\x0e\x85\
+\xc0\x0e\xd0\x50\x5f\x2f\x9e\x89\xf0\xc4\xe4\x49\xbf\x7b\xf5\xe5\
+\x69\xb7\xa2\x91\x72\xd5\xef\x26\xb4\x42\xed\xbb\x05\x72\x45\x87\
+\x00\x2e\xaa\xbc\xbc\x3c\x9a\xf3\xc1\xac\x71\xbf\xf9\xd5\xc3\x2f\
+\xd4\x54\x57\x67\x60\xa8\x80\x2d\x82\x22\xf0\x10\x50\x5d\x5d\x4d\
+\x39\x39\xd9\xf4\xca\xb4\x69\x57\xfd\xf6\x57\x0f\xff\x25\x97\x1b\
+\x86\x06\xd6\xd5\xd5\x53\x43\x63\x83\x74\xcb\xaa\xab\x56\x57\x17\
+\xe8\x5c\xe9\xb2\xc0\xd3\x43\x80\xe4\xa5\xa1\xd3\xa3\x5a\x9e\x40\
+\xa2\x83\x47\xd7\x6d\xf8\xd0\x58\xe7\xac\x4c\xea\x9c\x91\xc9\x2c\
+\x4e\x78\x86\x80\xfa\xfa\x06\x71\xc0\x4e\x72\x15\xbb\xe5\x70\xec\
+\x6c\x6e\x9b\x1c\x03\x3c\x11\x57\x34\xce\x17\x93\x55\xb9\xfa\x91\
+\xc1\x90\xee\x96\x15\xc9\x13\x2f\xb9\xda\xd0\xed\xda\x5d\xb0\x6a\
+\x5f\x1d\x35\x36\x34\x48\x3d\xa2\x33\x7c\xb8\x0c\x57\x46\x99\x5c\
+\x4e\xd2\x76\x19\x0e\x8d\xac\x87\x5a\x1e\xaf\xa5\x5e\x9e\xea\x49\
+\x39\x2e\xd2\xc8\x43\x44\x56\x56\x16\x17\x4d\x67\xbe\x14\x54\x65\
+\x55\x61\xd1\x2d\x0c\x6b\x1f\x0b\xc3\x0d\xe4\xb3\x58\x1f\x28\x53\
+\xb1\xb3\x82\x2e\xbf\xe2\x27\xbf\xfe\x9f\x9b\x6e\xbe\x5b\xd9\x22\
+\x07\xd2\xad\x46\x60\x07\xc0\xb8\xbf\x79\xd3\xa6\xfe\xd7\xfd\xec\
+\xa7\x4b\x2a\x2a\x2a\xf6\x80\x12\xea\x79\x9c\x1a\xc0\x63\xd3\xd8\
+\x71\xe3\x28\x3f\x8f\x67\xab\xbc\x41\xc9\x38\x99\x25\x5f\x2c\xa6\
+\x99\x33\x66\x50\xa7\x8c\xce\x62\x10\x33\x07\x10\x70\x74\xee\x79\
+\xe7\xf3\xcc\x76\x7f\x39\x49\xc3\xe6\x49\x24\x4d\x7f\xe5\x15\x2a\
+\xdd\xb6\x8d\x3a\x77\xc6\x7c\xc2\x75\x80\x7a\xf6\xfa\x03\x0e\x1c\
+\x4c\xa3\x4f\x3d\x5d\xba\x47\x28\x0e\x05\x9b\x9a\x1a\xe9\xf3\x4f\
+\x3f\xa3\x8f\x3f\x9e\xcb\x65\xe0\x38\xca\x01\xe4\xa0\x7c\xae\x19\
+\xdc\xce\x33\xcf\x1c\x43\x7d\xf6\xde\x5b\xf3\x15\xb6\x97\x6e\xa7\
+\x37\xdf\x7c\x43\x56\x31\x8e\x13\x30\x1f\xfa\xa9\xab\xab\xa5\x43\
+\x87\x0e\xa3\x1f\x9e\xf8\x23\x36\x76\x67\xe1\xe1\x78\x68\xc3\xbc\
+\xb9\x1f\xd2\xa7\x8b\x16\xb1\x93\x2a\xbe\x32\x1a\x5f\x95\x0d\x8d\
+\x94\x9b\x97\x4b\xe7\x5f\x70\x21\xf5\x2c\xea\x09\xae\x34\x11\xf9\
+\x9b\x36\x6e\xa0\x69\x53\x5f\xa2\x9a\xea\x1a\x69\x1f\xb8\x52\x96\
+\x33\x51\xd7\x0f\x4e\xf8\x21\x9d\x70\xe2\x89\xd2\x9b\x82\x0f\xe7\
+\xc5\x05\x32\xe3\xed\xb7\xe8\x8b\xc5\x9f\x8b\xc3\x35\xb0\x33\x72\
+\x5e\xd3\xef\xff\x34\xf9\x84\x43\x87\x0e\x9d\x2f\x4e\x18\x00\x81\
+\x1d\x00\x46\x79\x7c\xf2\xa4\xa7\xde\x7c\xe3\xf5\x9f\xf2\x2c\x15\
+\x9a\x92\xab\xea\xf1\xa7\x9e\xa6\x03\x0f\x1a\xa2\xa5\x22\x71\xe7\
+\x6d\xb7\xd0\xc2\x05\x0b\xf8\xea\xcc\xd1\x0e\x80\x9e\xa4\x86\xce\
+\x18\x33\x86\x6e\xbb\xe3\x4e\x49\x7b\xb1\x70\xc1\x27\x34\xf1\xfe\
+\xfb\xe5\xa4\xcd\x52\x11\xb3\xea\xec\xec\x1c\xfa\xdd\x9f\x26\x51\
+\x51\x51\x91\x96\xb4\xc0\x6d\xb9\xeb\x8e\xdb\x69\xf5\xaa\x55\x94\
+\xc9\x57\x9a\xb1\x3f\x14\x7e\xde\x05\x63\x69\xc2\xc5\x17\x8b\x98\
+\x17\xb3\x67\xbd\xcf\xe7\x34\x99\x8f\x9d\x85\x43\x08\x1a\x1a\xea\
+\xa9\x6b\xd7\x6e\xf4\xd8\x1f\xfe\x88\xd9\xb8\x62\x5a\x80\x61\x6e\
+\xbc\xfe\x5a\xda\xb2\x79\x33\xf7\x80\x6c\x30\x6d\x4c\xac\x8c\xae\
+\xf9\xf9\x75\x74\xde\xf9\xe7\x6b\xc9\x48\xfc\xe3\xf9\xe7\xe8\x99\
+\xbf\x3c\xcd\x57\x2e\x7a\x45\x75\x85\xe3\x02\xea\xdb\xaf\x1f\xfd\
+\xf5\xef\xcf\xf9\x0e\xa5\xdb\x4b\x4b\xe9\xb2\x8b\x27\x10\x5f\x70\
+\xe2\xa4\xd5\x5c\xc7\x11\x47\x1d\x35\xfb\xde\xfb\x7f\x31\xa2\xa8\
+\x57\x2f\x2d\xd5\x3a\xa0\xc3\x0d\x04\x9e\xf5\xf7\x9e\xff\xf1\xbc\
+\xf1\xea\xea\x53\x33\xe2\x82\x2e\x5d\xe4\xca\x8a\x85\xde\x9c\xd7\
+\xd4\x28\xab\x5e\xb9\x12\x24\xe6\xde\xa1\xff\x80\x01\x3a\x15\x8d\
+\x5e\xbd\x7b\x4b\x77\x69\x3b\x6a\x23\x1f\x63\x8f\xae\x5d\xa9\xb0\
+\xb0\x50\x73\x3c\x60\xe7\x2a\x2a\xea\x25\x43\x11\x2c\x29\x25\x79\
+\x87\xb8\xcf\xde\x7d\x90\xf2\x05\xaf\xb7\x65\x18\x73\xea\xe2\x18\
+\x43\x4c\xb7\x6e\xdd\x7c\x8d\x0f\xa0\x6d\x7b\xf5\x2c\x92\x2b\xde\
+\x06\x7a\xb2\xbd\xe3\xd4\xd5\x7f\xc0\xbe\xdc\x4c\xa8\x5f\xb7\x8f\
+\x81\xba\x7a\xf4\xe8\x11\x73\x1e\xd5\x95\xdb\x51\x58\xb8\x27\xeb\
+\x50\xd5\x95\xc5\xba\xff\xcf\x97\x5f\x9e\xb4\x7c\xf9\xb2\xa3\x84\
+\x11\x00\x81\x1d\xe0\xe3\x79\x73\x4f\xdf\xb1\x63\x47\x81\xdd\x58\
+\x28\x0e\x27\x11\x0b\x30\xbe\x31\x86\x01\xc8\x46\x8f\xf2\x6c\xe0\
+\x78\x4a\x45\xaa\x90\x29\xda\x52\x5d\xb8\xff\x00\x38\xf2\x7a\x1f\
+\xb7\x8c\xe4\xe1\x0a\x96\x48\x95\xe1\x1d\x9c\x1b\xc3\x58\x2c\x98\
+\x3c\x55\x07\x43\x13\x2d\xd7\x15\x8d\xf8\xf5\xb0\x2e\xa4\x71\x0a\
+\xe8\x05\x6a\x6b\x6b\xd2\xe6\xcd\xfd\xe8\x3c\xcd\x6a\x35\x02\x3b\
+\xc0\x8a\xe5\xcb\x4e\xd4\x64\xab\xe0\x0c\xbb\xee\x79\x24\x84\x56\
+\x8a\x33\xb8\x84\x14\x52\x5d\x32\xac\x6a\x0c\x1b\x0f\x46\xbf\xb6\
+\xd3\x39\xcc\x58\x90\x6c\xaf\x0c\xa7\x5b\x28\xe6\x00\x72\x89\xca\
+\xb2\xa0\x2d\x8a\x0b\x70\xd9\xd2\x6f\x7e\xa4\x93\xad\x46\x60\x07\
+\xd8\xba\x75\xeb\x7e\xde\xb5\x3e\x26\x34\xf1\xd6\xff\xf0\xd8\xc8\
+\xe6\x03\xcd\x71\xcb\xc8\xdd\x43\x03\x6d\x41\x6c\x98\x42\xb4\x58\
+\x97\x31\xba\x94\x40\xd4\x42\x5d\x92\x87\x32\xba\x1e\x8e\x40\xe3\
+\xbc\x64\x62\x18\x03\x68\x8b\x1c\x1f\x7b\x55\xa1\xa4\xe3\xd7\x15\
+\xd9\xfd\x1b\xa8\x61\xc1\x1f\xe9\xac\x0b\x35\x69\x74\x81\x79\x47\
+\x69\xe9\xb6\xd8\xe3\x6e\x0b\x08\xec\x00\xbb\x76\xed\xea\x61\x2b\
+\x05\x0d\xc3\x0c\x7a\xd3\xa6\xcd\x9a\x13\x8d\x4d\x9b\x36\x5a\x06\
+\x55\xa7\x8e\x63\x14\x17\xaf\x13\xda\x0f\x25\x5b\xb6\xc8\x52\x4a\
+\x26\x7f\x9a\x87\xf1\x75\x67\xf9\x4e\xf9\xce\x21\x16\xb6\x70\xb9\
+\x74\x18\x80\x0d\xa2\xec\xa9\x0c\xbb\x91\xdb\x10\x0b\xeb\xd7\xaf\
+\xe7\x35\x75\x83\xf4\x52\xa6\x0c\xda\x87\x7a\xaa\x2a\xab\x44\xc6\
+\x8b\x3a\x9e\xb8\xf1\xc5\xe0\x18\x5b\x8a\x61\xe3\xae\x1c\x77\x47\
+\x63\x01\xdf\x9d\xa0\xbb\x57\xe6\x74\x75\x81\x89\x5e\xac\xe1\x01\
+\xab\xa2\xed\xdb\xb7\x47\x38\x23\xe8\xea\xea\xaa\xc0\xb7\x04\x03\
+\xaf\x02\xce\x18\x7d\x4a\x31\x37\xa8\x1f\x4e\x1c\xc6\x47\xc0\xb2\
+\x68\xbf\x41\x83\xe8\xc2\x71\xe3\x79\xc2\xd2\x55\x9d\x17\xf3\x71\
+\x42\x9f\x2e\x5a\x48\xef\xf0\x32\x46\xc9\xf3\x09\xf0\x99\x8b\x37\
+\x8b\x92\x3b\xc9\x6c\xf9\xc0\x21\x07\xcb\x9a\x5e\x17\x63\xcf\x2e\
+\xa5\x57\x5f\x9e\x46\x5b\x4b\xb6\x52\x06\x2f\x03\xe1\x04\xa6\x5c\
+\x7d\x5d\x3d\x1d\x34\x64\x08\x9d\x76\xc6\x19\x94\xc7\x4b\x4e\x5d\
+\x99\x2c\x8f\xb0\x72\x98\xfb\xe1\x87\xbc\xae\xef\x2c\x3c\x2e\x22\
+\x07\x84\x51\xb0\x9a\x38\xeb\x9c\x73\x64\xe2\x69\x3b\x55\x49\xc9\
+\x16\x7a\x7d\xfa\x74\x51\x32\xda\xe8\xea\x05\xcb\xc0\x3a\x1a\x36\
+\x6c\x38\x9d\x3c\xf2\x14\x99\xf4\x99\xba\xb0\x64\x9b\x33\x7b\xb6\
+\xac\x6c\xd0\x3e\xb0\x51\x0e\x1b\xce\x19\x37\x6d\xc6\x5e\x38\x8e\
+\x27\x9e\x7d\xe5\x48\x02\xce\x5f\xb7\x6e\x1d\x4d\x7b\xe9\x45\x5e\
+\x29\x54\xca\xca\x49\xea\xd2\x65\xb1\x12\xc0\x12\xf0\xa4\x11\x23\
+\xf5\xfd\x05\xce\xe0\x13\x80\x03\xf2\x8a\x8b\x16\x7f\xfe\x19\x2f\
+\x6f\xf5\x92\x13\x79\x72\xc8\xe6\xb2\x8f\xe6\x2f\x88\x31\x23\x8e\
+\x8f\x36\x73\x00\x00\xde\x08\x65\x61\x52\x97\xce\x5d\x9c\x71\x0c\
+\x39\x03\x3e\x43\xdc\xac\xb0\x79\x6a\x59\xa7\x20\x6b\x62\x3e\x16\
+\xb3\x18\x4a\x06\x8a\xc4\x77\x0a\xb8\x41\x03\x05\x49\x39\x7c\x70\
+\x0c\xee\xbc\x60\x00\x2c\x09\xe5\xa6\x8e\xca\xe0\xb2\x6a\xdd\x2c\
+\xab\x13\xc8\xe9\xe3\xc9\x9e\x13\xb8\xea\x9c\x1b\x41\xcc\x33\x67\
+\x6f\x6e\x04\x79\x8d\xaf\xc8\x66\xe9\x85\x9a\xb8\x2e\x39\x16\x94\
+\x8f\xad\x49\xc9\x61\xa9\xa9\x64\x39\x2d\x1f\x15\xc3\x19\x6b\xeb\
+\xf8\xbc\x78\x33\xc7\x41\x0c\xe7\xc8\xe2\xa5\x26\x96\xc2\x60\xab\
+\xe3\xe8\xf2\x0c\xdc\xd8\x11\x9e\x54\xa5\xf8\x4d\x9c\x4e\x67\xe5\
+\xc0\x01\x9d\x49\xa7\xe4\x09\xd5\xf1\x0e\x70\x3a\x3b\x40\x85\xc7\
+\x01\xc4\x30\x42\x6b\xc5\x23\xad\xf9\x8a\x56\x7c\x57\x46\xa5\x4d\
+\x9e\x7c\x84\x06\x38\x56\xde\xa0\x79\x9e\x7c\xcd\x33\xb4\xe4\xc9\
+\x8e\xf7\x86\x36\x79\x12\xe9\x74\x42\x30\x8a\x05\xa9\x08\xe6\x28\
+\x92\x77\xd8\xd4\xc7\x13\x47\xe5\xc9\xde\x35\xb0\x14\x97\x4c\x95\
+\x42\xbe\x44\x92\x23\xb1\xca\x36\x79\x42\x39\x72\xae\x8c\x24\x2c\
+\x1a\x0e\xb0\x30\x90\x03\x04\x9e\x03\xe8\x16\xc5\x40\xbc\x3c\x17\
+\xfa\xf4\xdc\x63\xc9\xb9\x28\x52\xe0\xf0\x2d\x26\x93\x26\x85\xd8\
+\xca\x61\x28\x0e\xc4\x23\x8e\xcd\x41\x2b\xca\xe5\xfb\x40\xe5\x41\
+\x16\x91\x2a\x67\xf8\x8a\x54\xf9\x0e\x20\xe2\x90\x16\x5f\x43\x38\
+\x36\xdb\x87\xf6\x2b\xe7\x8f\x44\xe5\x5a\x87\xe0\x3d\xc0\xa8\x91\
+\xc5\x15\x15\x15\xd2\x03\x00\xea\x6a\x56\x01\x40\x97\x55\xdf\x50\
+\xcf\xed\x56\xb3\x68\xb9\x26\x39\x32\xf9\x2e\xcf\xe6\x83\x50\x34\
+\x36\x97\x96\x02\xec\xad\x8a\x87\x9d\x2a\xa3\xe7\x12\x3a\xad\x76\
+\x2a\x0d\x5a\x52\x7a\xa7\x72\x18\x0e\x01\x98\x84\xa5\x03\xc7\x30\
+\x18\xd2\xd2\xe4\x16\xaf\x3a\xae\xe5\x04\xf8\x70\x02\x49\xac\xcd\
+\x31\x6e\xe3\x7c\x85\x23\x1f\x11\xc0\x5e\xe4\x0c\xcf\xa6\x25\x5f\
+\x22\xde\x99\x3c\x2d\xaf\x48\x8e\xd1\xd5\x73\xdd\x19\xdc\x06\xb4\
+\xc5\xcd\xf7\xca\x37\x97\xcd\xfd\x24\x58\x0f\x10\xd2\x01\x30\x04\
+\xa8\x1b\x41\xca\x80\x2a\xc6\x3c\xa0\x77\xdf\x01\x74\xca\x59\x17\
+\x51\xf7\x1e\x45\x5a\xcd\xbc\x57\x84\xd2\x67\xa4\x25\x18\x8e\x54\
+\x14\xf8\x14\x79\x1f\x9d\x1f\x8b\xef\x07\x57\x32\x31\xb4\xee\xd8\
+\xed\x23\xfb\xc9\x7b\x2f\x50\xe5\xae\x4a\x5a\xbd\x66\x35\xf1\x70\
+\x1b\x71\x47\xf4\xbf\xc2\x01\xbc\xab\x00\x20\x2b\xb7\x80\xc6\x5c\
+\x78\x25\x1d\xfd\xa3\xb3\xa9\xb9\x13\x26\x47\x29\x04\x45\x6e\x67\
+\xdc\xca\xe6\xc9\x64\xd5\x56\xfa\xfc\xf3\x2f\xe8\xe5\xe7\x26\x51\
+\x4d\x65\x85\xe4\x69\xc3\x83\xe2\x98\x02\x3b\x40\xf0\x39\x80\x07\
+\x68\x4c\x6e\x41\x57\x3a\xed\xbc\x2b\xe8\xa8\x11\x17\xb2\xf1\x83\
+\x7d\x3b\x95\x82\x8b\xaa\xfa\x0c\xaa\x6a\xc8\xa0\xba\xcc\x5e\x74\
+\xc8\xb1\x67\xd0\xdd\x8f\x4d\xa3\x3e\xfd\x07\x6b\xc3\x2b\x04\xbb\
+\x7c\x5d\x04\xef\x01\x4e\x19\x51\xbc\xd3\x99\x03\xa8\x31\xf8\xf8\
+\xd1\xe3\xe8\x9c\x4b\x6e\x52\x02\x1a\x7b\x04\xfb\x9a\x7a\xb7\x02\
+\x3a\x31\x3d\xda\xee\x44\x65\x6d\x33\x35\x34\x45\xb6\x63\xc5\x7f\
+\x16\xd0\x5f\x7f\x7b\xb3\xd0\x68\xa7\xd8\x0f\x43\xc0\x82\x45\x1d\
+\xdb\x03\x28\xb7\xc1\x5e\x07\x6e\xc8\x81\x43\x8f\x11\xae\x41\x7a\
+\x5a\xb3\x7c\x29\xf3\xff\x2d\xe0\x8c\xfc\xf8\x1d\x1d\x3a\x77\xc2\
+\x8f\x5b\x94\x2e\x0d\x32\xb3\x72\xe4\x3e\x80\xba\x70\x11\xcc\x3e\
+\x18\x02\xf7\x00\xa7\x71\x0f\x80\xfb\x00\xb8\xdd\x6a\xae\x96\xab\
+\xef\xfc\x23\x1d\x70\xe8\xd1\x42\xa3\x59\xe0\xaa\x7d\x0a\x6d\x85\
+\x75\xdf\xfe\x87\x26\x3d\x70\xb5\xe8\x5c\x5f\xfd\x70\x80\xb2\x79\
+\x1d\xdd\x03\x00\xae\xeb\x18\xca\x76\x26\xdc\xe5\x4a\x19\xbf\x3d\
+\xd0\x56\x57\x3f\xd0\x66\x93\xc0\x14\x76\x27\x82\xbb\x41\xf0\x39\
+\x80\xf1\x42\x74\x41\x52\x7f\x58\x5f\x4c\x21\x11\x98\x21\x5b\xa9\
+\xdf\xa2\x03\x22\xdc\x10\xc0\x15\x9b\xba\xc3\x34\x22\x85\xd6\x42\
+\x1b\x5e\xf6\xe1\x10\x78\x12\x78\xea\xc8\x93\xdd\x1b\x41\x60\xf0\
+\xa4\xe4\xa7\x77\x61\x12\x18\xb9\x12\xe8\x08\xec\x2c\x2f\xa3\xd9\
+\x33\x5f\xa1\xef\xd6\x7e\x4b\x25\x9b\xd6\x53\xc9\xe6\xf5\x54\xb8\
+\x67\x4f\xea\xce\x61\xff\x83\x86\xd1\xa8\x31\xe3\x29\xbf\xcb\x1e\
+\x5a\x3a\x3c\xa6\x3d\x37\x49\xea\xc9\xcd\x2f\xa0\xfe\x03\x07\xd3\
+\x88\xd3\xc7\xea\x9c\xf6\xc7\xda\x15\x5f\xd2\x9f\xee\xbf\x4a\x7e\
+\x13\x81\xe9\x9f\x4c\x01\x79\x19\xf8\xf1\xc2\xcf\x3a\xf6\x4e\xe0\
+\xe8\x11\x27\x45\xde\x0a\xe6\x70\x15\xaf\x02\x0e\x1c\x76\xac\xa4\
+\x3b\x02\x25\x9b\x37\xd0\x23\xf7\x5d\x47\x73\x67\xbd\xa9\x39\xb1\
+\x31\xf6\xd2\xeb\xe9\xe6\x7b\xff\xe0\xfc\x70\x23\x08\x16\xce\xfd\
+\x37\x3d\xfe\xc8\xdd\xb4\xfc\xeb\xcf\x35\x87\xe8\xe0\xe1\xc7\xd2\
+\x33\xaf\xce\xd7\xa9\xf6\x87\x71\x00\xb3\xf2\x82\xfd\x38\x94\xcd\
+\x5f\x14\xcc\x01\xc2\x4d\x02\xe1\x7c\xd8\x29\xb2\x43\xf1\xc1\xbb\
+\xd3\xe9\xd2\x31\x87\x25\x64\x7c\xe0\xe5\xe7\x27\xd3\xf8\xd1\x07\
+\xd3\xaa\xe5\x5f\x69\x4e\xe2\xd8\x55\xb1\x93\x7e\x73\xef\xb5\x74\
+\xc3\x65\xa3\x22\x8c\x0f\xc8\x17\x36\x1d\x0d\xe7\xa2\x45\x1c\x4e\
+\xf3\xe1\x97\x81\xd2\x18\xbb\x41\xed\x8f\x6f\x97\x7d\x49\xf7\xde\
+\x34\x81\xca\xcb\xb6\x69\x8e\xc2\x91\xc7\x8f\xa4\xb3\xc7\x5d\x4d\
+\x17\x5d\x75\x1b\x1d\x7f\xd2\x19\xd4\xad\x70\x2f\x9d\xa3\x50\xbc\
+\x66\x39\x3d\x70\xeb\xa5\x54\x53\x53\xad\x39\x2d\xe3\xed\x57\x9e\
+\xa5\xb1\x23\x07\xd3\xf4\x17\x9e\xd0\x9c\x48\x98\x0b\xa0\x23\xa1\
+\x6a\x94\x2b\x5f\xfb\x42\xf0\x36\x84\x5f\x05\x08\x2d\x7b\x5a\xf1\
+\xd5\x22\x49\xb7\x37\x1e\xba\xf3\x4a\xaa\xaf\xab\xd5\x29\xa2\x81\
+\x07\x1c\x42\x4f\x4f\x9b\x47\x93\xa7\xfc\x9b\xee\xf9\xd5\xd3\x74\
+\xc3\x3d\x8f\xd0\xef\x9e\x79\x9b\xa6\xcf\x59\x4d\xe3\x2e\xbf\x51\
+\x4b\x29\xac\x5c\xb6\x84\x7e\x3f\x31\xf2\x76\xb5\x1f\xd6\xac\xfc\
+\x86\x6e\xbb\xfa\x6c\xfa\xe5\x1d\x57\x50\x59\xe9\x16\xcd\x8d\x46\
+\xd0\x21\x34\x28\x4c\x7d\x96\xfa\xdd\x38\x00\x42\x0f\x01\xaa\x72\
+\xe5\x89\xa5\x5b\x36\x20\xd1\xae\x78\x63\xea\x33\x11\xdd\x30\xae\
+\xf2\xdf\x3e\xf9\x1a\x0d\x3d\xe2\x78\xcd\x71\x91\x9b\x97\x4f\xb7\
+\xdc\xf7\x07\x3a\x77\xfc\x35\x9a\xa3\xf0\xfa\x4b\x7f\xa1\x9d\x3b\
+\xb6\xeb\x54\x34\xe6\xcd\x7a\x9b\x87\x8b\x21\x51\xc3\xcb\xd5\x37\
+\xfd\x82\xee\x98\xf8\xb8\x4e\x29\xec\x96\x21\xc0\x55\xbc\xc4\x86\
+\x0a\x82\xd0\x43\x80\x54\xee\xee\xda\x1d\x53\x9f\xfd\xa3\xa6\x14\
+\x7e\x7e\xdb\xc3\xb4\xf7\x3e\x03\x75\xca\x1f\x77\x3d\xf4\x24\xed\
+\xd5\xcb\xfa\x61\x26\xb7\xf5\x8d\x69\xcf\x68\x3a\x1a\xf3\x66\xbf\
+\xad\x29\x85\xd3\xcf\xbb\x8c\x66\x2e\x2a\xa1\xab\x6e\xb8\x4f\x73\
+\x5c\x74\x74\x0f\x00\x98\xab\x5f\x22\xa9\x3e\x78\x1b\x42\x38\x80\
+\x6e\x05\x07\xd3\x86\x78\xff\x6a\x69\x0b\x7c\xbd\x64\x21\xad\x5e\
+\xe1\x4e\xe2\xfa\xf4\x1b\xc8\x63\xfe\x95\x3a\x15\x1f\xa3\xce\xfc\
+\xb1\xa6\x14\x3e\xfb\x78\x96\xa6\xa2\x91\x9b\x57\x20\xf1\x90\xa1\
+\x47\xf3\xb0\xf2\x3e\xdd\xff\xe8\xb3\xbc\xa4\x8c\x9c\x4f\x18\x74\
+\xfc\x10\x00\x1d\x9b\xab\x5e\xd7\x1d\xa2\x09\x21\xe6\x00\xd8\xe9\
+\xd8\xdb\xa0\x76\xc2\xa7\x1e\xa3\x9d\x7c\xda\x05\x9a\x6a\x19\xa7\
+\x8c\x89\x74\x80\x4f\xe7\xcf\x92\x9f\x72\xf9\xe1\xa4\x53\xcf\xa3\
+\x89\x7f\xf8\x27\xfd\xed\xb5\x05\x3c\xb1\x1c\xa1\xb9\xfe\xd8\x3d\
+\xab\x00\xb5\x53\x36\x80\xee\x83\xeb\x3d\x54\x0f\xa0\x2a\xd6\x0d\
+\x09\xd1\x88\x44\xf1\x19\x1b\xcd\xc6\x21\x87\x25\x7e\xcf\x61\xf0\
+\xc1\x87\x51\x56\xb6\xfb\xff\x09\xfc\x96\xcf\xbb\xa4\x33\xc0\x71\
+\x47\x9f\x35\x5e\xa7\xe2\x23\x8c\xf2\x83\xc2\x55\x77\xf8\xda\x83\
+\x3b\x00\x6a\x36\x01\x51\xd8\x96\x24\x80\xf5\xc5\xab\x34\xa5\x30\
+\x60\xe0\x81\x9a\x4a\x0c\xfd\x06\xec\xaf\x29\x85\x4d\xeb\xd7\x6a\
+\x2a\x38\x76\xc7\x1c\x00\x4a\x97\x5a\xf5\x2e\x4c\x13\x82\x0f\x01\
+\x12\xd4\xe6\xb6\x20\x44\x4b\x5a\x00\x1e\x83\x52\xb2\xe9\x3b\x9d\
+\x52\xc0\x0f\x4e\x5b\x83\x28\x07\xd8\x10\xfb\x2f\x69\x89\xa2\xbd\
+\xe7\x3d\x5e\xc0\xe1\x44\xdd\x88\x45\xf7\xc2\xc5\x2e\x10\xc2\xf7\
+\x00\x12\xa1\x21\x08\x2a\xdd\x1e\xf0\xbb\x5a\xf3\xf2\xd5\x64\x2d\
+\x51\xe0\xbb\x01\x1b\xdb\xb7\xc5\xfe\x1f\x63\xc2\x70\x9c\xbf\x63\
+\x21\x3a\xd7\x71\x98\x26\x84\xe8\x01\x54\x13\x4c\xe5\xa6\x41\xed\
+\x85\xca\xca\xef\x35\xa5\x90\x93\x9b\xef\xdc\x0f\x4f\x14\xd9\xf2\
+\x34\x0e\x17\xb1\x26\x81\xad\x41\xc7\xaf\x02\xb8\x3e\x5d\xa7\x44\
+\x21\xab\x0f\x31\x09\x04\x74\x63\x74\x23\x42\xb6\x25\x2e\xaa\xab\
+\x76\x69\x4a\xc1\x2c\xd5\x5a\x03\xaf\x03\xe0\xf1\x2f\x61\xd1\xd1\
+\x43\x00\x20\x7a\xc6\x8e\x75\xaf\x74\x1e\x5c\xf3\xc1\x7b\x00\x5d\
+\xa7\x6a\x87\xea\x86\x9a\x79\x66\xdd\x5e\xa8\xaa\xf4\x38\x40\x2b\
+\xbb\x7f\x20\x27\x27\x4f\x53\x0a\xf5\xf5\x6d\xd0\x03\x84\x50\x7e\
+\x20\x88\xe2\xa1\x6f\xd7\xf8\xc6\x16\x41\x10\xa2\x07\x50\x8d\x70\
+\x54\xe0\x34\xa8\x7d\x60\xff\x27\x1e\x68\x0c\xf1\x6c\x3c\x83\xac\
+\xac\x36\x78\xd6\x62\x18\xed\x07\xc0\xaa\x6f\x16\x4b\x95\xaa\x56\
+\x6d\xfc\x10\x6d\x08\x37\x04\xa0\x21\x52\xb7\x71\x02\xec\xda\x07\
+\x18\xf3\x6d\xe0\xaf\xe1\xad\x45\x95\xcf\x3c\x22\x2c\x3a\x7a\x08\
+\x28\x2d\x59\xaf\x95\xae\x8d\x1f\x52\xe9\x21\x86\x00\x6f\xc5\xed\
+\x68\x7d\x46\x4e\x6e\xf8\xee\x3b\x6a\x22\x29\x0f\x96\x08\x87\x68\
+\x3d\xb4\x2f\xe4\x3f\x01\x9a\x16\x70\x22\x4c\x13\x42\xf5\x00\x72\
+\xf2\x1c\x74\x04\x9f\xd4\x39\x6d\x0f\xef\xa4\xaf\xa2\xbc\x4c\x53\
+\x89\xc3\x5b\xa6\x6b\xb7\x3d\x35\x95\x38\xa2\x56\x1e\x61\xb4\x1f\
+\x18\x6e\xd7\x1f\x56\xef\xc1\x7b\x00\x69\x84\xdb\x10\xa7\x51\xed\
+\x84\x1e\x3d\x7b\x6b\x4a\x01\x5f\x8a\x94\x95\x6e\xd5\xa9\xc4\xb0\
+\xf1\xbb\x35\x9a\x52\xc0\x3f\x98\x5b\x0b\x3c\x59\xc4\x46\xc7\xaf\
+\x02\x5c\x9d\x23\xe6\xbd\xf0\x82\x22\x78\x0f\xa0\xeb\x44\x03\xb4\
+\xfd\x39\xb4\x9f\x32\x30\x04\xe4\x17\x74\xd5\x29\x85\x6d\x25\xb1\
+\x1f\xf8\xe4\x87\x4d\xeb\x23\x1d\xa0\x4f\xdf\x7d\x35\x95\x38\xbc\
+\x3d\x80\x32\x40\xc7\x41\x5d\x64\xa6\x56\xad\xf8\x10\x4d\x08\x35\
+\x07\x50\xcd\x50\x71\x47\x8c\x85\x3d\x8a\x22\x9f\xbc\xb9\x74\xc9\
+\x42\x4d\xb5\x8c\xed\xdb\x4a\x68\xab\xf5\x83\x15\x3c\xb3\x78\xc0\
+\xa0\x83\x74\x2a\x71\x58\x8f\x9a\x10\x74\xf4\x1c\x40\xbe\x7d\x14\
+\xb5\x6b\xfd\xcb\x27\x78\x1b\x42\xcd\x01\xa4\x5e\xa9\x5b\x35\x61\
+\xcd\x8a\xaf\xb8\x4b\x6c\xbf\x7b\x01\x47\x1e\x17\xf9\xd5\xec\x57\
+\x5f\x2c\xd0\x54\xcb\xf8\xe4\xc3\x99\x9a\x52\x38\xea\xf8\x91\x81\
+\x7e\x21\xec\x1d\x02\x76\xc7\xd7\xc1\xce\xc5\xa7\x3e\x7a\x17\x0c\
+\xc1\x7b\x00\x67\x93\x84\xec\x2a\x76\x6c\xa3\x86\xfa\xd6\x2f\xcf\
+\x12\x85\xf7\xbb\xf9\x59\x33\xa6\xe1\x51\xa9\x3a\x15\x1f\xf3\xe7\
+\xbc\xa3\x29\x05\xaf\x33\x25\x8a\xa8\x21\xa0\x83\x7b\x00\xa5\x79\
+\x89\x74\xac\xd3\x01\x11\x6e\x0e\x20\xc1\x6e\x10\x76\x92\x6a\x17\
+\x1c\xf7\xa3\xd3\xa9\x4b\x57\xf7\xe7\xef\xb5\xb5\xd5\xf2\x27\x8d\
+\x96\x30\x6f\xf6\x0c\x9a\xf5\xce\xcb\x3a\x45\x94\xd1\x39\x93\xce\
+\xbc\xe0\x72\x9d\x6a\x1d\x76\xb7\x03\xa8\xda\x8c\xce\xdd\x38\x28\
+\x42\x0c\x01\xa8\xd4\x6e\x48\xf0\x46\x24\x0a\x3c\x17\xf7\xc2\x4b\
+\xaf\xd7\x29\x85\xc9\xbf\xbe\x83\x3e\x5f\x30\x47\xa7\xa2\xb1\x79\
+\x63\x31\x4d\xfe\x4d\xe4\xa3\xe8\x7f\x7c\xf9\x8d\xb4\x47\xb7\x40\
+\xff\xa3\x88\x1a\x02\x76\x0b\x44\xf5\x6d\xa3\xfb\x50\x3d\x80\x38\
+\x9e\x6e\x08\xe8\x8e\xb8\x1a\x2e\xb8\xe4\xba\xa8\xaf\x75\xaf\x9d\
+\x70\x12\x4d\x79\xfa\x11\x2a\x2f\x2b\xd5\x1c\xe2\x09\xdf\x46\x7a\
+\xf7\xf5\x17\xe8\xa2\xd3\x0e\xa5\xb5\x2b\x97\x6a\x2e\x51\xdf\x01\
+\xfb\xd3\xe5\xd7\xdd\xa3\x53\xb1\x81\x9f\x9f\xcd\x9f\x33\x93\xe6\
+\xbe\xff\x56\x44\x58\xf9\xcd\x12\x2d\xe1\x62\xc1\x47\xff\x12\x79\
+\x3b\xac\x5b\xbd\x5c\xe7\xb6\x2d\x30\xe7\x70\x4c\x6e\x8c\x1f\x42\
+\xed\x81\xff\x1a\x76\xc2\xb1\x47\x15\x97\x97\x97\xeb\xff\x06\xaa\
+\x6e\x11\x4f\xc6\x7c\x7c\xfa\x62\xca\xca\x09\x7f\x87\x2d\x1e\xf0\
+\xb3\xed\x5b\xaf\x1e\xa3\x53\x91\xe8\xda\xbd\x87\xac\xcd\x2b\xca\
+\xfd\x7f\xf6\x8d\xff\x0f\xf8\xfd\x84\xdc\xc6\xcc\xd7\xfe\x41\x0f\
+\xdc\x7a\x89\x4e\x05\x43\x76\x4e\x1e\x7d\xb8\x34\xf2\x0b\xac\xb6\
+\xc0\x33\x8f\xde\x46\x0b\xe7\xcc\x90\xa1\xc8\x18\x9f\xe3\xb2\x2f\
+\x97\x2e\xef\xe0\xbf\x86\xc1\x6f\x74\x50\x7e\xa8\xb6\x8e\xc0\x0f\
+\x46\x9c\x49\x0f\x3c\x36\x85\xba\xec\xd1\x5d\x73\x5c\xe0\xdf\x42\
+\x7e\xc6\x1f\xb0\xdf\x41\xf4\xe4\x4b\x1f\xb5\x68\x7c\x60\xfd\xba\
+\x95\x9a\x0a\x8e\x9a\xea\xca\x56\xdf\xa8\x4a\x04\x66\x05\x20\xba\
+\xd6\xba\xc7\x27\x28\x02\x3b\x80\x74\xf9\x7a\x73\x1a\x10\xa2\x21\
+\xad\xc5\x69\xe7\x5e\x4c\x2f\xfe\xeb\x6b\x1a\x7f\xe5\x2d\x54\xd8\
+\x23\xf6\xeb\x52\xf6\xd9\x77\x30\x5d\x73\xcb\x2f\xe9\xf9\xb7\x16\
+\xd3\xf0\xa3\x4e\xd0\xdc\xf8\x38\xf4\xf0\xe3\x34\x15\x1c\x83\x0f\
+\x39\x22\xe6\x4f\xc9\x43\x01\x3a\xd6\xc1\xd1\x3d\x42\x40\x04\x1e\
+\x02\x7e\x70\xf4\x91\xce\x10\x80\x11\x00\xc3\x00\x9e\x16\xfe\xe4\
+\xeb\x4b\xda\x7d\x08\xf0\x03\xfe\x33\x50\x56\x5a\x22\x01\x2f\x8b\
+\xc2\x3f\x86\x10\x0e\x3c\xe4\x70\x2d\xd1\x3a\x84\x79\x15\x1b\x90\
+\xd1\x19\x4f\x2a\x6f\x7b\x3c\xfd\x9b\x9b\x69\xd1\x47\xef\xa8\xd5\
+\x08\xec\x2f\xf6\x6b\x2e\xfb\xcf\xb2\x6f\x3b\xf6\xef\xe1\xc7\x1f\
+\x7d\x44\x71\xf9\x0e\x3d\x07\xd0\x4b\x23\xcc\x01\x76\x97\x03\x24\
+\x0b\xc4\x01\x3e\xc4\x1c\x40\x3f\x66\x5e\xf5\x03\x65\x5f\x05\x74\
+\x80\x70\x73\x00\xd9\x71\x03\xb8\x21\x66\x4b\xa1\xfd\x01\xbb\x5b\
+\xc6\x57\x66\x08\x88\xe0\x73\x00\x5d\xb9\xaa\x9b\xf7\x92\x08\xd1\
+\x92\x14\x12\x83\xa8\x5a\x94\x2d\x7b\x37\x1d\x0c\x21\x57\x01\x52\
+\xbb\x22\xb1\xa5\x1c\xa0\xdd\x61\x5e\x27\x23\x9a\x86\xee\xb5\x0d\
+\x82\x22\x5c\x0f\xe0\x34\x40\x35\x02\x8d\xab\xab\x4d\xfc\xe1\x0b\
+\x29\xb4\x0e\x8d\x0d\xf5\xb4\x74\xc9\x7c\x75\xdf\x85\x75\x6e\x2e\
+\x38\xd8\x22\x28\x42\xf5\x00\xaa\x62\xed\x08\xbc\xe1\x56\xed\x9c\
+\x99\x53\x55\x7e\x0a\x6d\x8e\x39\x33\x5e\x90\x7b\x1c\xd0\xb5\xb2\
+\xbd\x50\x1c\x49\x22\x10\x42\xf5\x00\xca\x0b\x55\x0a\x1f\x3c\x36\
+\xf6\xdd\x57\xff\x4e\x8b\xe6\x24\xf6\xdc\x9e\x14\x12\xc7\xae\x8a\
+\x1d\x34\x7d\xca\x24\xf5\x56\x51\xad\x73\xd1\x3d\x6c\x80\x64\x40\
+\x04\x5e\x06\x1e\x7d\xf8\xf0\xe2\xf2\xf2\x1d\xfd\x32\xcc\x77\xea\
+\xbc\x14\x94\xae\x89\x3f\x39\x79\x5d\xe8\xf8\x11\xe7\xd0\x09\xa3\
+\x2f\xa0\xcc\x4c\xf7\x9d\x01\x11\x5f\xa4\x45\x24\x50\x2c\x32\x1d\
+\x05\x8f\x7c\x3c\x38\xff\x4f\x68\xc7\x3a\xbc\xf0\x7e\x4b\x98\x08\
+\xa0\x7b\xfc\x30\xc5\xd0\x2e\x5c\x1a\x6f\x2c\xc7\xd3\x4c\x5e\x7c\
+\xea\x61\x79\x4e\x30\x60\x5f\xf5\x88\xf8\x53\xb6\x6c\xe5\xea\x8e\
+\xbd\x0f\x70\xf4\xe1\xc3\x9c\xfb\x00\xd0\xab\x9c\x3e\x2b\x41\xa9\
+\x41\xdd\xa7\x46\xe3\x9d\xe3\x5b\x79\xfa\x23\x3c\xcd\x51\x7b\xc3\
+\x77\x09\x8e\x34\x01\x08\xdb\xcd\xb3\x11\x65\x5c\x9d\x54\x91\x4f\
+\x81\x04\x80\xff\x22\xa8\xf3\xe3\xf2\x72\x1a\xae\xae\x0c\x85\xdf\
+\x26\xea\x37\x79\x3b\x4c\xe7\x9a\x8c\x88\x4c\xbe\xce\x75\xf2\x1c\
+\x42\xd1\x3a\x53\x45\xea\xb1\xf5\x78\x14\x9f\x72\x30\x97\xaf\xc5\
+\x0c\x87\x1d\x60\x4d\x07\x3b\xc0\x61\x43\x8b\x77\xc0\x01\x32\xf4\
+\x97\x41\xea\xc3\x30\xb4\x4e\x49\x64\x78\x9a\xd6\x91\x6d\x4c\xc7\
+\x80\xbe\x69\x27\xa5\xe0\xe5\x45\x64\x02\x2e\x23\x2a\xab\x95\x88\
+\xd4\x8e\x47\x57\x3a\xa9\x22\xde\x5b\xd9\x5e\x9e\x36\x94\x6f\x5a\
+\x68\x9d\x74\x72\xf4\xce\x98\xc7\x95\x71\xf3\x2d\x5e\xd9\xb2\x55\
+\x6b\x3b\xf6\x46\x90\xd4\x2b\x0d\x40\x33\x78\x53\xa4\xcb\xe3\x2b\
+\x03\xce\x65\x82\xe2\x21\x17\x42\x42\x58\x79\x2e\xed\x0d\xbc\x93\
+\x20\x69\xd9\x14\xcb\xe1\x21\xe0\x85\x4d\x08\x3a\x8d\x3c\xde\x49\
+\x08\xbb\x99\xe3\xe0\x98\xf1\xea\x93\xc8\xd4\xa8\x79\x8a\xef\x1f\
+\xd4\x21\x5d\x1a\x3b\xd9\x40\x6b\xbe\x1b\xf0\x3b\x40\xc9\x90\x48\
+\x02\x6f\x2e\x0f\x71\x30\x04\xee\x01\x8e\x1a\x8e\x1e\xa0\x8c\x7b\
+\x00\xbc\xd1\x13\xe0\x2b\x32\x3d\x4d\x5e\xb0\xd8\xc8\x63\x30\x5e\
+\x8a\x28\x3c\x7d\x09\xa2\x9e\x9c\xdc\x5c\x79\xc4\xa9\x80\xf9\xa6\
+\x1c\xbe\xbe\xc5\xb3\xfb\xd4\xbb\x71\x85\xc9\xc0\xf3\xf0\x9b\xe4\
+\xbe\x3e\xde\xa0\x89\x13\x36\xf2\x2a\x42\x5d\x35\x52\xd6\xbc\x5f\
+\x50\xa0\x4f\x07\x2f\xa9\x54\xa2\x6e\x1e\x8e\x8d\xa5\x6a\x0d\x97\
+\xf3\xfe\xd5\x0c\xc7\x41\x3d\xea\xad\x9c\x9a\x29\x40\x22\x8d\x6a\
+\xf0\x32\x47\x64\xd8\x55\x89\x9c\x7a\x21\xa6\xa9\x17\x84\x2a\x91\
+\x26\x6f\x4d\x83\x3e\x54\x5d\x4a\x00\x65\xf0\xbb\x49\xfc\x2d\x0d\
+\xbd\x27\x18\xfa\x30\xb2\x43\x54\x5d\xe5\xbe\xa6\xd6\xd4\xa1\xea\
+\x4e\xa3\x9c\xec\x1c\x45\x6b\x59\x2d\x50\xb6\x7c\xf5\xba\x8e\x1d\
+\x02\x8e\x1c\x7e\x28\xcf\x01\x76\x44\x7c\x19\x54\x5b\x5b\x47\x43\
+\x87\x0f\xa7\xab\x7e\x7a\x8d\xf3\xbe\x7d\xe8\x0b\xca\xc5\xeb\x55\
+\x9f\xfb\xfb\x33\x7c\x0e\xe9\x62\x30\xa5\x47\x65\x64\x38\xd1\x35\
+\x3f\xbf\x8e\x86\x1c\x7c\xb0\x76\x10\x75\xb2\x3b\xca\xca\xe8\xa9\
+\x27\xfe\x4c\x6b\xd7\xae\xa5\x4c\x76\x04\x03\x18\xb2\xa6\xb6\x96\
+\x8e\x3d\xee\x78\x1a\x3f\xe1\x62\xca\xce\xcd\x56\x45\x78\x6b\x68\
+\x6c\xa0\x0f\x3f\xf8\x80\x5e\x9e\xfa\x92\xbc\x3a\xd6\xd4\x04\xe0\
+\x2d\x1c\xb9\xb9\x39\xf4\xb3\x6b\xaf\xa7\x7d\x07\x46\x3e\x59\x6c\
+\x6b\x49\x09\x3d\xf1\xe7\xc9\xf2\x0a\x59\x79\x55\x9c\x06\xb4\x83\
+\x37\x8d\x8e\x1c\x35\x8a\xce\x3e\xe7\x5c\x99\xd4\x6a\xd5\xcb\x97\
+\x5f\x33\x67\xbc\x4d\x33\xde\x7a\x8b\x32\xb3\xd4\xdb\x4d\x0d\x30\
+\x2f\xe8\x5e\xd8\x9d\xae\xbd\xfe\x06\xea\xdd\xa7\x8f\xd3\x0a\x88\
+\x7c\x57\x5c\x4c\x7f\x9e\xf4\x47\x79\xff\xb1\xe8\xcf\x1c\x91\x6d\
+\x51\x57\x57\x4f\xe7\x9e\x7f\x3e\x8d\x3a\xf5\x34\x69\x87\xa9\x0b\
+\x8e\x34\x6d\xea\x8b\x34\xfb\xfd\x7f\xab\xb7\x87\x81\xaf\xeb\xe3\
+\x62\x65\x2b\xd6\x74\xb0\x03\x1c\x73\xf8\xf0\x55\xdb\x4a\xb7\x0d\
+\xc4\xb2\xc4\x18\x19\x27\xf3\xda\x9b\x33\x68\xf0\x41\xfe\x3f\xb7\
+\xbe\xe6\xca\x9f\xd0\x7b\xef\xbd\x4b\x79\xe6\x6f\x5e\x5c\xb0\x72\
+\xd7\x2e\xba\xe4\xb2\x2b\x68\xe2\x43\x0f\x2b\x9e\x07\xf3\xe6\x7e\
+\x44\x57\x5d\x71\x99\x5c\x9d\x66\xa6\xdd\xc4\x57\x71\x7e\x7e\x01\
+\xbd\x3e\x63\x26\xf5\xec\x19\xf9\xeb\x20\x83\x09\x17\x8e\xa5\x2f\
+\x16\x7f\xae\x5f\x21\xab\x78\xbb\x76\x55\xd2\x8d\x37\xdf\x4c\xd7\
+\xdf\xe0\xff\xa0\xc8\xb7\xde\x78\x9d\x6e\xbb\xf9\x26\x76\x12\xf7\
+\x6f\xe4\x30\x72\xaf\x5e\xbd\xe8\x8d\x77\xde\x8d\xe0\x1b\x20\xff\
+\xec\x33\x4e\xa3\x75\xec\xa4\xea\x5d\xc5\x0c\x56\x69\x65\x65\x25\
+\xfd\xe2\xc1\x87\xe8\xa2\x4b\x2e\x55\x3c\x0f\xfe\xf2\xd4\x13\xf4\
+\xf0\x2f\x27\xea\xf7\x1e\x2b\xe0\x07\xae\xfb\x1f\x30\x98\x66\xfc\
+\xeb\xdf\x9a\x13\x09\x5c\x10\xa3\x47\x9c\x44\x65\x65\xdb\x65\x39\
+\x28\x96\x63\xfb\xb1\x0d\xcb\xbe\x5d\xfb\x5d\xc7\xce\x01\xba\xec\
+\xb1\x47\x09\xde\x11\x0c\x07\x82\x0f\xc1\x01\x0a\x0a\xba\x50\x11\
+\x2b\x2b\x16\x7a\xf5\xe9\x2d\x5d\xb0\x94\x11\x0f\xc6\x3b\x71\x9b\
+\xa8\xff\x80\xfe\x5a\x22\x1a\x45\x45\xbd\x28\x9b\xbb\x4b\xc8\xc9\
+\x19\x73\xc0\x31\xf0\x72\xea\x6e\x78\x41\x75\x0c\xf4\xea\xdd\x5b\
+\xcd\xce\xb1\x29\x25\x31\xb7\x39\xf2\x45\xce\x1e\xf4\xdd\x67\x1f\
+\xe9\x96\xf1\x8e\x60\xd5\x42\xf5\x12\xe8\xee\x85\x85\xbe\xc6\x07\
+\x30\x64\xe0\x9c\x51\x17\x8b\x4b\x40\x5d\xf0\xd5\xde\xdc\x86\x58\
+\xe8\xb7\x4f\x7f\x96\x51\xbd\x9d\x6c\x5c\xa6\x91\x7b\xaf\x3d\xf7\
+\x8c\xfd\x77\xb5\x82\x2e\x5d\xa4\x2d\x4a\x87\xaa\x9e\xc6\xc6\x26\
+\xbc\xa4\xda\xff\xd5\xe6\x09\x20\xb0\x03\xf0\xc9\xad\xc2\xad\x49\
+\xb4\xc4\x9c\x40\x93\x34\x28\xf6\xff\x02\xe0\x30\x2c\xca\x90\xd6\
+\xbb\x27\x01\x7e\x0c\x40\x29\x66\x12\x04\x59\x13\xe0\x10\xf1\xca\
+\x61\x9c\x65\x49\x55\x9f\x15\xe2\xd6\x65\x19\xd1\x04\x1c\x03\x73\
+\x1a\x71\xc0\x18\x70\x9c\x5a\x07\x53\xb8\x21\x9e\x2e\x50\x06\x1b\
+\xe4\x75\x19\x44\x30\x68\x2c\xa0\x0d\xaa\x0e\xd5\x2e\x10\x0d\xf5\
+\x75\xd4\xb3\xa8\x68\xbd\x16\x69\x35\x02\x3b\xc0\xd0\x61\xc3\x3e\
+\x90\x66\x4b\x6b\x54\xa3\xd4\x2e\x1e\xd0\x6c\x73\x02\x2a\x65\x78\
+\xf1\x60\xcb\xcb\x66\x18\xf1\xa0\x0a\x88\xac\x04\xbd\xb5\x54\xd0\
+\x91\xd4\xe5\x44\x3c\x7e\x11\x9d\xef\x94\xe4\x8d\x53\x2d\x95\x93\
+\x63\x6b\x59\x93\x14\x1a\xfb\xd8\x70\xdb\xa5\xe4\xea\x78\x08\x1a\
+\x36\xfc\xb0\xd9\x92\x08\x80\xc0\x0e\x70\xf2\xc8\x53\x66\xf6\xe8\
+\xb1\xd7\x4e\xe7\x26\x88\x6e\x38\x6e\x07\xc7\x82\x4c\x78\x70\x02\
+\xd8\xe4\x24\xe0\xd5\xcd\x72\xa3\x23\x16\xd4\x58\x67\x9d\xb4\xaa\
+\x46\x66\x82\x72\x5b\x34\x06\x30\xd1\x34\xca\x32\xe5\xb1\x74\x53\
+\x93\x2e\x7f\x48\x5d\xde\x32\x1c\xd0\x9d\x7b\x57\x0d\x36\xd0\x93\
+\x43\x4e\xda\x66\xca\x73\x90\x59\x7e\x0c\xa0\x1d\x52\x44\x82\xd4\
+\x06\x65\x70\x3d\x7a\xc2\xe2\x03\x94\x51\xb9\xea\xf8\xe8\x45\x78\
+\x65\xd5\x34\x72\xd4\xe8\xe9\xc2\x0e\x80\xc0\x0e\xc0\x63\x6c\x09\
+\xcf\x8c\xa7\x54\xe9\x25\x0b\x96\x7d\xbc\x2c\xa4\xd5\xab\x62\xff\
+\xa0\x72\xd5\xca\x95\xec\x20\xa2\x2d\x9c\x83\x9c\x34\x1c\x66\xe9\
+\xd7\xb1\x9f\xe1\x8f\x32\x58\x16\x61\x36\x6f\x94\x05\x63\x6c\xdb\
+\xba\x95\x36\x6c\xf0\x7f\x38\x35\x14\xb3\x76\xcd\x6a\x36\xa8\x9a\
+\x61\xeb\x82\x52\x76\xc5\xf2\xd8\x3f\xd7\x5e\xfa\xf5\xd7\x54\xcf\
+\xb3\x70\x51\x32\xca\x48\xfb\xd2\x69\xcb\x96\x2d\x54\xb6\xdd\xff\
+\x57\xc6\xdf\x7f\xff\x3d\x15\xaf\x2b\xb6\x9c\x87\x99\x1c\xd0\x95\
+\xaf\xfc\xf6\x5b\x25\xe4\x83\xa5\x4b\xbf\x96\xa1\x45\x84\xa5\x0c\
+\xd7\xc5\xc7\xd8\xb4\x61\xa3\x2c\x53\xfd\xb0\x65\xcb\x66\x09\xc6\
+\x89\xab\xaa\xaa\xe9\xe8\x63\x8e\x79\xef\xa0\x83\x86\x2c\x16\x46\
+\x00\xf8\xae\x02\x32\xf4\x6c\x3b\x1e\x2a\x78\x96\xbb\x79\xd3\xc6\
+\x3e\x63\xcf\x3d\xe7\xcb\xd2\xd2\x6d\x85\x58\x9a\xe0\xa5\xd1\x03\
+\x06\xec\x4b\x13\x2e\xbe\x84\xba\x75\xef\x2e\x0a\xc1\xcc\x1d\xbd\
+\xc4\x82\xf9\xf3\xe9\xed\xb7\xde\x90\x49\x93\x80\xf9\xa8\xc5\x28\
+\x6d\xec\xb8\x71\x74\xe8\xd0\x61\xce\x95\x86\x72\x58\x92\xbd\x30\
+\xe5\x79\x2a\xdd\xb6\x8d\x15\xcc\xe5\xb8\x80\x69\x19\xea\x1a\x7c\
+\xe0\x10\x3a\xff\x82\xb1\x3c\x39\x2a\x90\xab\x1b\x99\x98\x95\xcf\
+\xf9\x60\x36\x7d\x30\xeb\xfd\x88\xef\x21\x90\x87\x31\x14\x86\x1a\
+\x37\x7e\x82\xcc\xb6\xcd\xb1\x40\x6c\x64\x67\x7a\xe1\xf9\xe7\xe9\
+\xfb\x5d\xdf\x2b\x05\x1b\xb5\x70\x5e\x2d\x2f\x03\x0f\x3b\xfc\x08\
+\x3a\x73\xcc\x59\x72\x2f\x83\x27\x3b\xd2\xbe\x9a\xda\x6a\x7a\xf7\
+\x9d\x77\xe8\x13\x3e\x37\x9c\x3f\x0a\x49\x31\xde\xa9\xab\x33\x87\
+\x2e\xbe\xe4\x32\xda\xa7\xbf\x3b\xc9\x45\xfe\x9a\x55\xab\xf8\xbc\
+\x9e\x93\xe3\xe2\x7c\x55\x19\x55\x61\x2d\x9f\xd7\x09\x3f\x3c\x91\
+\x46\x8d\x3e\xd5\x79\x59\x34\xea\xaa\xac\xdc\x45\xaf\xbd\xf2\x0a\
+\x7d\xf1\xc5\x62\xe1\x43\xa7\x5c\xb6\xe1\x85\xa9\x2f\x1f\xcb\x43\
+\xc0\x67\xf9\xb8\x17\x91\x00\x1a\x74\x3d\x06\x81\x1d\xa0\x9c\x3d\
+\x1f\x33\xe3\xa9\x2f\xfe\xf3\xa2\x9b\x6f\xb8\xfe\x1f\xa0\xd1\x95\
+\xe3\xd1\x2d\x58\x37\x9b\x7f\xd0\xa0\xf1\xa8\x02\x5d\x5b\x6e\x5e\
+\x9e\xa4\xed\xa3\xab\xfc\x66\xf6\x66\x7b\x22\xcb\x12\x10\x62\x7e\
+\x76\x76\x8e\x76\x1a\x4f\xc3\xb9\x1c\x14\x88\x31\x50\xdd\x74\x12\
+\xae\x1c\xab\x13\x5f\xb5\x39\xf6\x13\xc1\x74\x36\x22\x38\x81\xaa\
+\x4b\xd7\xa1\x81\x72\xb8\xa1\x83\x2f\xb7\xa4\x26\xab\x3a\x1c\x1e\
+\x57\x65\x7d\x7d\x83\xd4\x6b\x32\x55\x5d\x19\x5c\x2e\x5b\x68\x2f\
+\xe0\x04\x52\x17\xca\x58\x07\x85\x2c\xf4\x25\xc6\xb7\xca\x19\x91\
+\xea\xea\x2a\x31\xb0\xd1\x8d\xb0\x79\x22\x9c\x91\x91\xc9\xfa\xc8\
+\x92\x61\xb3\xa2\x62\x27\xdd\x7e\xd7\xdd\xf7\xdf\x7e\xe7\x3d\x13\
+\xe1\x1c\x5d\x0b\x12\x7b\x68\x56\x5b\x39\x40\x84\xc0\x83\x0f\x4e\
+\x7c\xf0\xf7\x8f\x3d\x7a\x0f\x2f\x47\xf8\xa4\xf4\xb8\xc7\x12\x46\
+\x48\x62\x39\xa6\x62\x2a\xbe\x4d\x5b\x60\x39\x97\xe7\x0a\x44\xb8\
+\x8d\xcb\xf6\x81\x5d\xc6\x0f\xe0\xea\x2b\xd5\x82\x92\x55\x79\x5e\
+\x38\x1c\x21\xa2\xf3\x01\x6f\x96\x53\x83\x95\xa1\x48\x4b\x88\xe1\
+\x66\xbb\xbd\x87\xde\xb9\xc6\xb7\x76\xe0\x55\x54\x54\xd0\x8f\x27\
+\x4c\xf8\x67\xf7\xc2\xbd\x2e\x79\xe8\xc1\x07\x95\x90\x82\x4d\xfb\
+\x22\xa8\x03\x80\x61\x33\x4d\xda\xf0\xd2\xee\xbc\xf3\xf6\xfb\xfe\
+\xfe\xcc\x5f\xff\x17\x5d\x2c\x6e\xda\x48\x96\xfa\x38\x50\x57\x8f\
+\x50\x56\x9e\x4d\x6b\x48\xc2\xe3\x08\x56\x04\x78\x1d\xc2\x8a\xe2\
+\xa0\x65\x09\x85\xf8\x7a\x74\x72\x2d\xb1\x08\x97\xf2\x08\x38\x7b\
+\xaf\x88\xde\xd9\xb4\xec\x2d\x9b\xd8\x79\x18\xde\xd0\x13\x9d\x7d\
+\xee\x79\xcf\xe5\xe6\x15\x5c\x37\x79\xd2\x24\xf3\xa0\x24\x48\x98\
+\x60\xe0\x4d\x0b\x5a\xeb\x00\x20\x4c\x40\x9f\x6e\xc7\x5e\x3a\xed\
+\x8e\x3b\x6e\x3f\xf7\xfd\xf7\xfe\x35\x71\xc3\x86\xf5\x7d\x3b\xb3\
+\x13\xc0\x19\xc4\x50\xea\xe3\xc0\x75\x04\xc0\xce\xb7\x69\x0b\x11\
+\xbd\x02\xa0\x53\x1e\x41\xaf\x94\x00\x2c\x9c\xa2\x4f\x56\x8b\x88\
+\x56\x8d\x20\xc2\xd8\x80\x93\x74\xf9\x42\x79\x74\xab\x78\x6a\x67\
+\xd3\x06\xb1\x0c\x8f\xe1\x00\x73\x9e\xc2\xc2\xc2\x1d\x67\x9e\x75\
+\xce\xaf\x1f\x79\xe4\xd1\xa7\x74\xae\x09\xb8\x79\x60\x6e\x20\x18\
+\xda\xce\x47\x10\xb4\xc6\x01\xb0\x43\x40\x9f\x0e\x43\x23\xb6\x03\
+\x78\x26\x18\xd9\xf4\xd3\xcf\x38\x7d\xcf\xbc\xdc\x9c\x4b\x57\x2c\
+\x5f\x76\x7e\x69\x69\x69\x5f\xfc\xc1\x02\x93\x2a\x8c\x77\x66\x82\
+\x07\xc4\x75\x02\xec\xed\x6c\x40\xd2\x7e\x26\x66\x9e\x87\x89\x33\
+\xd2\x47\x91\x7d\x78\x28\x83\x79\x8f\xa6\x54\x17\xa9\x3f\x95\xe2\
+\x7d\x24\xdb\xf2\x85\x96\x8d\x8f\x79\x8a\xba\xa9\xd6\x40\x9d\x78\
+\x48\xed\x5e\x58\xb8\x75\xd0\xa0\xfd\x67\x14\x74\xe9\xfa\xb7\x29\
+\x53\xa6\x14\x43\x84\x03\x0a\x20\x18\x83\x63\x49\x61\x62\x3b\xd8\
+\xb2\x09\x3b\x00\xce\x15\xc1\x18\x1e\x0b\x6e\xcc\xc4\x4c\x88\xe5\
+\x08\x08\x52\xb6\x5f\xbf\x7e\xf9\xc7\x1e\x7b\xcc\xe1\x3c\xa9\x3a\
+\x64\xf3\xe6\xcd\xfb\xd7\xd6\x56\xef\xcd\xcb\x96\x1c\xce\x54\x15\
+\x32\xa1\x3e\xde\x84\xcb\x32\x70\xcc\x6e\xf1\x6c\x88\x0b\xc4\xc8\
+\x73\xd1\xa2\x80\x07\xd1\x7a\x89\x00\x67\xb3\x29\xfd\x85\x34\x37\
+\xa2\xa7\x70\xc8\x68\x07\xe0\xbd\x23\xca\x47\x4c\xcb\xce\xc9\xae\
+\xcd\xcc\xca\xdc\xdc\xb3\xa8\xd7\xca\xa6\xc6\xa6\xaf\x57\xae\x5a\
+\xf5\xd9\x97\x4b\xbe\xc4\x23\xce\x20\x65\x0c\x6e\xd3\xc6\xd8\x0d\
+\x3a\xe0\x6f\x4d\x08\x26\x0d\x59\xa9\x81\x1d\x40\xd7\xa4\xd0\x92\
+\x03\xd8\xc6\xc7\x3a\x07\x83\x3b\x68\xf0\x4c\xf0\x3a\x80\xe3\x04\
+\x2d\x04\x20\x56\x0c\xf8\xf1\x00\x6f\xda\x8b\x58\xf9\x2d\x95\xf3\
+\x22\x5a\x31\x0a\xb1\xf8\x06\xde\x7c\x93\xb6\xf9\x36\xcf\xcb\x6f\
+\x29\x18\xa3\x7b\x8d\x6f\x0c\x8e\x18\x73\x03\x13\xc0\x43\xbe\xc0\
+\xeb\x00\x30\x56\x22\xb0\x95\x07\xba\xb5\x21\x51\xa7\x40\x88\xe7\
+\x44\x7e\x7c\x23\x1f\xaf\x5c\x5b\x86\xa0\x75\xc5\x92\x6f\x2d\xdf\
+\x2f\x00\x5e\xda\x2f\x8e\x42\x22\x3d\x00\x82\xe9\xfa\x4d\x6f\x60\
+\xae\x7e\x7b\x08\x30\xf2\x76\xc3\x81\x58\x27\x02\x78\x63\xc0\x2b\
+\x03\xd8\x34\xd0\x52\xda\x8b\x96\xf2\x63\x21\x5a\x39\x2e\xfc\xf2\
+\xbc\x3c\x3b\x0d\xda\x04\x83\x58\x69\x3b\xe0\x2a\x07\x0c\x6d\x82\
+\x9d\xf6\xeb\xfe\xed\x21\xc0\xc8\xa5\x25\x3a\x04\x20\xc2\xce\x18\
+\xd7\x38\x82\x31\xba\x1d\x8c\x9c\x1d\x7b\x69\x6f\x00\xbc\xb4\x89\
+\x6d\x3e\xe0\x95\x31\xf0\xa6\x81\x44\x64\x82\xc0\xab\xa4\x68\xa5\
+\xc5\x96\xb1\xf9\xa0\x4d\x00\xec\xd8\xa6\x61\x2c\xc0\xf0\x0d\xcf\
+\x4b\x1b\xc3\x22\x98\xa1\xc0\x74\xf9\x76\x30\xe5\x02\x2f\x03\x8d\
+\x23\x98\x60\x78\x76\xdc\x9a\x00\xd8\x34\xe0\xe5\x7b\xf3\xbc\x69\
+\x3f\x78\xe5\x6c\xc4\xe2\xc7\x42\xb4\x62\x5c\x5e\xbc\x3c\x03\xa4\
+\x6d\x9e\x49\x1b\x5e\xbc\xd8\x18\x18\x40\x1c\x2f\xd8\xce\x60\x62\
+\xe3\x10\xb6\x9c\xa0\xb5\x0e\x00\x98\x84\x51\xae\x1d\x00\x3b\xf6\
+\xf2\x6d\xda\xc4\x86\x06\x12\xc9\xb7\xd3\x80\x37\xdf\x86\x37\x6d\
+\x23\x5e\x9e\x1f\xa2\x15\xa3\xe0\xc7\xb7\x79\x7e\x74\xa2\x31\x00\
+\xda\x2f\xdf\x4b\xb7\x94\x67\xf3\x1c\x04\x71\x00\x20\x51\x45\x1b\
+\xbe\x37\xb6\xe1\x97\x17\x4f\x0e\xf0\x2b\xe3\x87\x78\xf9\x2d\x95\
+\xf5\x22\x5a\x31\x0a\xb1\xf8\x06\x76\x7e\x2c\xda\xc0\x9b\xef\x27\
+\x03\x18\xbe\x37\xf6\xc2\xe6\xfb\xca\x04\x75\x80\x44\x60\x0a\xe1\
+\x80\xb1\x0e\xd0\x5a\xbe\x8d\xb6\x92\x09\x0b\x5f\xc5\xfa\x20\x11\
+\xb9\x58\x32\xf1\xf8\x38\xc7\x44\xdb\x10\x85\xf6\x74\x80\x30\xe8\
+\xf0\x0a\xff\x4b\x10\xd8\x90\x41\x91\x90\x03\xa4\x90\x3c\xc0\x0c\
+\x3e\x85\x24\x46\xca\x01\x92\x1c\x29\x07\x48\x72\xa4\x1c\x20\xc9\
+\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\x72\xa4\x1c\x20\
+\xc9\x91\x72\x80\x24\x47\xca\x01\x92\x1c\x29\x07\x48\x6a\x10\xfd\
+\x1f\xc7\xc9\xb8\x91\x66\xc8\x02\x22\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x1f\x16\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x0e\xc2\x00\x00\x0e\xc2\x01\x15\x28\
+\x4a\x80\x00\x00\x1e\xab\x49\x44\x41\x54\x78\x5e\xed\x9b\x49\x90\
+\x64\xd7\x75\x9e\x4f\xce\xf3\x54\x99\x59\x99\x35\x74\x55\x4f\xe8\
+\x19\x00\x01\xb0\x31\xb4\x6c\x02\x16\x85\x16\x6c\x85\xb4\xd3\x4a\
+\x0e\xda\x1b\x71\xe1\xf0\xc4\x85\x6d\xda\x0b\x63\xe5\xf0\x82\xc6\
+\xca\x2b\xaf\x1c\x1e\xc2\x11\x0e\x30\x6c\x53\x96\x2c\x3b\xcc\x20\
+\xd5\x04\x21\x00\xc4\xd0\xdd\x40\xa3\xa7\xea\xa9\xe6\x21\xab\x2a\
+\x2b\xe7\x97\xb3\xbf\xff\x16\x68\x8b\x44\xa2\x49\x84\x37\x5a\xe0\
+\x22\x12\x55\x95\xf9\xf2\xbd\x7b\xcf\xf9\xcf\x7f\xfe\xff\xbe\xd7\
+\xf6\xd5\xf8\x6a\x7c\x35\xbe\x1a\x5f\x66\x8c\x46\xa3\xd8\x78\x3c\
+\x0e\x7d\xf6\xe7\x5f\x8a\xc1\x7c\xc2\xbc\xa2\x9f\xfd\xf9\xa5\x86\
+\xef\xb3\x9f\xbf\x6a\xf8\xfe\xe8\xdf\xbc\x1e\x1b\x87\x33\x7f\xb7\
+\xdd\x6a\x65\xc3\xe1\xb0\xb5\x3d\xcf\x1e\x54\xb6\xed\x5c\x69\xc6\
+\x22\xb1\x88\x0d\xc7\x43\x0b\xf8\xfc\x56\xad\xd6\x2d\x97\xcb\x9b\
+\xdf\xef\xb7\x56\xab\x65\xc1\x60\xd0\xfc\xc1\x10\x17\x1a\x70\x9a\
+\xb1\xb5\xda\x6d\xeb\x79\x3d\xf3\xdb\xc8\xe2\xf1\xa4\xbd\x7d\xe3\
+\xae\xdd\x5c\xa9\xd8\x33\x27\xe7\xed\xe5\x8b\x4f\x59\xaf\x37\xb0\
+\xee\xb0\x6f\x31\xce\x69\x23\xbf\xed\xec\x55\xed\x4f\xde\x7e\xdf\
+\x5a\x5d\xcf\x2e\xbf\x74\xd1\xce\x1d\x3f\x66\x57\x6f\x2c\xd9\x5b\
+\x1f\x5e\x35\xaf\xd7\x33\x2e\x64\xc1\x38\x67\xeb\x8e\x7c\xfe\x40\
+\xf8\xa0\xba\xbd\xf7\xaf\x3f\xfc\xf0\xc3\x8e\xbb\xd8\xaf\x31\x7e\
+\x65\x00\xfe\xf3\x1b\xdf\x89\x8d\x62\x85\xaf\x77\x7b\x9d\xef\x25\
+\x13\x89\x17\x6a\x8d\x96\xa5\x93\x71\xeb\x30\xa1\xe5\xfd\x7d\x3b\
+\xb3\x70\xcc\xe2\x81\x80\x8d\xfa\x3d\xd0\x31\xb4\x7a\xcb\xb3\x04\
+\x0b\xf3\xfb\x7c\x36\x1c\x0c\xdc\x7b\x23\x2e\x33\x1e\x8f\x2c\x1a\
+\x09\x5b\x80\x09\xfb\x78\xf9\xfd\x84\xa4\xdb\xb5\x1f\x7d\x78\xd3\
+\xae\xdd\x5b\xb5\xe7\xce\x1c\xb5\x57\x5f\x7c\x86\x63\xcd\x9a\x1d\
+\xcf\x7c\x01\xbf\x0d\x86\x63\x1b\x71\x8e\xef\xff\xf0\xa7\x56\xeb\
+\x74\xec\x6b\x67\x4e\xda\xcb\xcf\x3d\x63\x1f\x7d\xba\x64\x7f\xf6\
+\xde\x07\x42\x23\xc7\xf9\x2c\x1c\x0f\x59\x24\x14\x24\xf8\x6d\x1b\
+\x8f\xc6\x6f\xa7\x92\xe1\x7f\x90\x89\x17\x3e\x79\xf3\xcd\x37\x89\
+\xd0\xe3\x47\xe0\xb3\x9f\x13\xc7\xdb\xff\xeb\xdf\x4f\xf7\x7d\xf1\
+\x3f\xec\xf7\xbb\xff\x2a\xe4\x0f\x9d\xf1\xfa\x3d\x5f\x36\x9d\x64\
+\x62\x23\x5b\x25\x33\x8f\x76\x2b\x36\x24\xb3\x89\x60\xc4\x06\xbd\
+\x3e\x21\x67\x71\x64\x3c\xc4\x64\x84\x80\x00\x8b\xd0\xef\x42\xcc\
+\x88\x80\xf8\x08\x54\x80\x9f\x44\xc3\xc6\xc3\xa1\x79\x5e\xd7\x02\
+\xc1\xb0\xad\x6e\xef\x58\x07\x54\x3c\x7d\xea\x98\x0b\x8e\x71\x4c\
+\xbd\xd5\xb6\x54\x22\x6e\x89\x44\x8c\xeb\x0d\x6d\x6d\x7b\xcf\x86\
+\x04\x73\xb1\x3c\x6d\xd1\x60\xc0\x3e\xbc\x79\xdf\xc6\x1c\xea\xe7\
+\x1a\x9c\xcd\x62\xa1\xa8\xf5\x41\x4e\x34\x16\x3a\x12\xf2\x07\xfe\
+\x6a\xaf\xdf\xd9\x3b\xb6\x78\xf2\x01\xa3\xff\xd9\x72\x26\x0e\x4e\
+\x31\x79\xfc\xf8\xbf\xfe\xdb\xec\xb8\xef\xfb\x87\xf1\x44\xe2\xbb\
+\x60\x6b\xae\xdd\xed\xb2\x02\x9f\x83\x74\xb7\xdb\xb3\x26\x99\xae\
+\xed\xb7\x2c\x36\xe4\x60\x32\xd1\x17\xc8\x29\x01\x8e\x65\xa2\x23\
+\x97\x1d\x4d\x6e\x34\x1a\x5b\x8f\x2c\xf6\x07\x7d\xe0\xed\xd9\xfa\
+\xce\x8e\xfb\x5d\x41\x50\x2c\x04\xe3\x62\x26\xed\x02\xa8\x85\x36\
+\x9a\xad\xc3\xe0\x05\x09\x1e\xdf\x0f\x12\xb4\x73\x27\x16\xed\xe9\
+\x13\x47\xb9\xd0\x98\xc0\xb4\xdc\x39\xf5\x5d\xae\x66\xfe\x31\x48\
+\xeb\x69\x12\x01\xf3\x01\x7a\x90\xe7\xf3\x3a\xbd\xb3\xad\x76\xef\
+\x5f\x8c\x7c\x83\x6f\xbd\xf8\xe2\x8b\x31\xad\xe7\x8b\xc6\x44\x04\
+\xbc\xfe\xfa\xeb\xc1\xf9\xa9\xe8\x3f\x66\x22\x7f\xbf\xd1\x69\xe7\
+\xb4\x40\x65\x32\x16\x0d\xbb\x9f\xcc\x9d\x8c\x79\xae\x56\xf3\xf1\
+\x94\xe5\x32\x09\x3e\x8b\x90\x71\x26\x03\x86\x59\x07\x01\x6a\x5a\
+\x8a\x52\x21\x6a\x16\x08\x85\xad\x37\x1c\xf0\x19\x7f\x11\xa0\x6e\
+\x1f\xd4\xc4\xe2\x2c\xd0\x67\xdb\x7b\xfb\xb6\x53\x03\xba\x5c\x77\
+\x6e\xa6\xc8\xc2\x83\x7c\x7f\x68\xbd\x7e\xdf\xe2\xb1\x28\x0b\xf5\
+\x39\x2e\x51\xa6\x5a\x94\xcc\x88\x8b\x0f\x07\x63\xbb\xfd\x68\xd5\
+\x05\x41\xc3\x1f\xf2\x5b\xbf\x4f\xa9\x81\x90\x46\xbd\xab\xf7\x7d\
+\xb1\x48\x28\xdb\x1f\x0c\x9f\xf7\x85\x7d\xdd\x17\xbe\xfe\xc2\xcf\
+\x6e\xde\xbc\x39\x91\x13\x26\x22\xe0\xe2\x62\xec\xf7\x2a\x95\xfd\
+\x7f\xb2\x5d\xa9\xa4\x43\xbe\x80\xc5\x80\x70\x84\x45\x04\xfc\x41\
+\x26\xd3\x71\x13\x9c\x2f\x16\xed\xe9\x85\x45\x9b\x82\xf0\xe0\x06\
+\x0b\x13\x98\x68\x38\xc4\xe4\xfa\xd6\x1f\x0d\x2c\x96\x48\x81\x80\
+\x80\x85\x63\x61\x16\xdc\xe3\xfb\x21\xab\x77\x5a\xc0\x9a\x60\xc5\
+\x13\xd6\x04\x15\x95\x86\x47\x46\x3b\xf6\xea\xd7\xcf\xd8\x37\x9f\
+\x3f\x6f\xd9\x68\xc0\xc6\x03\x0f\x04\x04\xac\xb2\xbb\x07\xd1\x76\
+\x6d\xc0\x71\x7e\xf8\x23\x9b\x8a\xd9\x5c\x36\x6b\x01\xb2\xdd\xaa\
+\xd5\x5d\x60\x15\x9c\x40\x18\x3e\x01\x2d\x5d\xd0\x35\x24\xfa\xa9\
+\x74\xc4\x52\x99\x28\x41\xf1\x59\x36\x1d\x2b\xfa\x86\xf6\x8f\x16\
+\x16\x16\xbe\xb0\x43\x7c\x2e\x00\xb4\x93\x38\xe0\x3d\x0e\x04\xa3\
+\x51\x16\xbe\xbe\xb5\x65\x9b\xfb\x55\xdb\xd8\xde\x36\xd0\x60\xb5\
+\x66\x17\x48\x1f\x42\x1c\xbc\xb9\x85\xf5\xc9\x88\xb2\xd2\x65\xc2\
+\x7e\x58\xc1\x47\x96\xa2\x2c\x7c\x08\x54\x95\x8e\x41\xdf\x03\xca\
+\x3e\x8b\x05\x40\x0f\x59\xd2\x77\x62\x91\xa8\xe5\xf3\x39\x02\x47\
+\x07\x19\xf4\x6c\x3a\x9b\xb4\x60\x88\x60\x07\x7d\x76\x50\xdd\x83\
+\x64\xfb\xb6\xbc\xb2\x61\xad\xa6\xc7\xb1\x11\x38\x03\xc2\xe3\x9a\
+\xc9\x64\x4c\x57\x60\xd1\x41\x37\x87\x51\x9f\x6e\x12\x8c\xda\xb1\
+\x99\x92\x08\xd0\x3c\xbe\xc7\xc7\x90\x27\xe5\x52\xef\x80\xd8\x40\
+\x64\x79\x79\x19\xe0\x8c\xe3\x9f\x2d\xf1\x17\xc6\x24\x04\x8c\x5a\
+\x30\xfd\x10\xc8\x06\x55\x54\xe3\xbe\x35\xbd\x86\xd5\x61\xfd\x46\
+\xb3\xed\x88\x48\x10\x1e\xb3\xb0\xde\x00\x22\x23\xf2\xb5\x7a\x13\
+\x08\x0e\xc8\x16\x93\x84\x07\x44\x4b\x9a\x1c\x24\x6e\xed\x76\xc7\
+\xd5\xb1\xa0\xaf\x92\xe8\x72\x9e\x16\x81\x6c\xf3\x1a\x50\x42\xa5\
+\x42\x9a\xbf\x09\x6a\xaf\xc3\xab\x47\x10\x42\x96\x8c\x85\x28\x8f\
+\x90\x45\x29\xaf\x28\xf0\x6e\x72\x0e\x5d\x6b\x7e\x6e\xd6\x8e\x2f\
+\x1c\xb1\x7c\x2e\x45\x40\x40\x59\x34\x64\x8b\x33\xd3\x76\xac\x54\
+\xb2\x48\x38\xea\xba\x46\xdf\x83\x6f\x5a\x74\x1f\x7e\x57\xa7\x21\
+\x2a\x56\xa9\x54\x58\x3f\x7d\x7a\xc2\xf8\x5c\x00\xc4\x21\xe1\x68\
+\xcc\x42\x2c\xb0\x59\xaf\x5a\x0c\x42\x2a\x26\x32\x56\x86\xa8\xb2\
+\x09\xa0\xa5\xa0\xf8\x46\x90\x61\xc0\xe2\x64\x66\x24\xc8\xf3\xea\
+\x32\xf9\x1e\xd1\xf7\x51\x26\x09\xd8\xdb\x05\x84\xac\x89\x30\xab\
+\x07\x4d\xfb\xf0\xd3\xbb\xf6\xd6\xd5\x1b\x0e\xde\xef\x5d\xbf\x69\
+\x3f\xf9\xe8\xba\xbd\xfd\xc1\x75\x17\x90\x01\xc1\xda\x27\xd3\x6b\
+\x3b\x55\xab\xd6\x5b\x16\xa6\x33\x28\x98\x0f\x37\xb6\xed\x1d\x7a\
+\xfe\xf2\xe6\xae\x2d\xad\x6e\x51\x5a\x90\x2d\x81\xb8\x7a\xeb\x3e\
+\xc9\xf1\x59\x02\x4e\x52\x6b\x55\x49\x7a\xdd\x81\xd3\x21\xe2\xa8\
+\x68\x24\x64\x09\x5e\xd1\x70\x50\x58\x71\xeb\x82\xcf\xba\xee\x97\
+\x5f\x1a\x13\x49\xf0\xb5\x57\x5e\xba\xe4\x0b\xfa\x2f\x77\xbc\x0e\
+\x17\xf5\xb9\x8b\x28\xda\x3a\x99\xa2\x1a\x16\xec\x85\x02\x26\xb4\
+\xb5\x7f\x60\x19\x16\x7c\xe0\xd8\xdb\x20\x2f\x32\xc0\xab\x07\x61\
+\xc5\x98\x40\x1f\x76\xdf\x42\x2f\x5c\x5d\x7a\x64\xdb\xd5\x03\x9b\
+\xc9\x67\x6d\x69\x79\xd3\xb6\x20\xbf\xed\xdd\x03\xdb\xa9\xd6\x6c\
+\x75\xb7\x66\xf7\x37\x2a\x70\x42\x43\x44\xef\xb8\xe4\xdd\x4f\x96\
+\xec\xe6\x83\x55\x5b\xdd\xd9\x25\x20\x7e\xab\x1c\xd4\xe0\x1b\xf1\
+\xf1\xd8\xe9\x90\xc5\xf2\x94\x9d\x3e\x7a\xc4\x0a\xb9\xac\xcd\x97\
+\x8a\x76\x00\x0a\x25\x9a\x7a\x04\x43\xdf\xd7\x71\x7a\x31\x5f\x6f\
+\x30\x18\xbf\x41\x19\x48\x89\x7d\x6e\x4c\x2a\x01\x45\xcb\x41\xd9\
+\x63\xf1\x1d\xd8\x98\x60\xbb\xba\x16\xfc\xd7\xb6\x2b\xf6\x60\x7d\
+\xc7\x95\xc1\x3e\xec\x9c\xa0\xd6\x35\xc9\x7c\x26\x65\xe9\x54\x92\
+\xbf\x23\xd6\x67\xf1\x61\x60\xaf\x20\xfc\xf0\xa3\x8f\xed\x5d\x7a\
+\xf6\x01\x65\xd5\xf5\xfa\xb6\x44\x5d\xfb\x20\xd6\x1e\xac\xad\x32\
+\xaa\x35\x3b\xbc\xda\xe6\xef\x8d\xad\x41\x6b\xd5\xe2\x88\xab\x0b\
+\xb4\x6a\x59\x19\x7f\x40\x70\x58\x04\x0b\xdc\x27\x70\x55\x3b\x42\
+\x29\x9c\x39\x79\xdc\x66\x8b\x79\x2b\xe5\x33\x56\x98\x4a\x5b\x88\
+\x20\xe5\x52\x09\xd7\xa1\xa6\xd2\x69\x7b\xe9\x6b\x90\x6a\x26\x69\
+\xa1\x68\xd0\x4c\x1d\xf4\x0b\xc6\xc4\x00\x6c\xd5\x6a\xd6\xa2\xcd\
+\x05\x81\x73\x8c\xda\x12\x51\x0d\x86\xcc\x26\x10\xb6\x8f\x96\x56\
+\xc8\x68\x95\x09\x79\x96\x4f\x41\x66\x51\x68\x8f\x5a\x6e\xb4\x3d\
+\xeb\x50\x06\x3e\x26\x9e\x62\x22\x22\xbd\x0e\xd9\x4f\x52\x4e\x52\
+\x85\x52\x80\x0a\xec\xc8\x3f\xb6\xe3\xb3\x05\x87\xa2\x10\xf5\x1d\
+\xa4\xd7\x0b\x39\x7e\xde\xcf\x86\x09\x1e\x81\x49\xa7\x53\x76\xf1\
+\xdc\x71\x4b\x49\x39\x32\x9f\x29\x02\xfb\xb5\xd3\xc7\xc9\x34\x12\
+\x9b\x37\xc4\x2f\x85\x99\x05\x1b\x87\x13\x56\x6b\xb4\xe1\x90\x1e\
+\x1a\xc4\x67\x33\x85\x0c\x9c\x01\xfc\xe3\x31\x3b\x75\x64\xd6\xca\
+\x53\x19\xa7\x51\xec\xd1\xe1\xba\x26\x8d\x89\x25\xf0\xbb\xbf\x75\
+\xe9\xd2\xdd\x8d\x8d\xcb\x12\x28\x52\x62\x6a\x39\x8a\x95\x60\xb8\
+\xba\xb5\x63\xe7\x16\x4b\x96\x4d\x06\x9d\x70\x09\x12\xf9\x30\x2d\
+\xf2\xde\xda\x8e\xa5\xb9\x70\x3c\x1a\x75\xac\x2d\x04\xed\xd7\x1a\
+\x76\x64\x3a\xcf\xfb\x71\x9b\x2b\x66\x60\xea\xa2\x05\x11\x2e\x0b\
+\xa5\x69\x6a\xb6\xe3\xfa\xba\x48\x2f\x8a\x94\x55\x2a\x02\x04\xf8\
+\xdc\x13\x47\x39\x37\x0a\x90\xfa\x56\xc9\xbc\xfc\xec\x79\xfb\x6b\
+\x2f\x3c\xc5\x7b\x09\xcb\xf0\x2a\xe6\xd2\x76\x1f\x14\x45\x22\x71\
+\x5a\x1d\xf5\x4f\xc6\x9b\x10\x6a\xab\xde\x20\xb0\x33\xb6\x50\xce\
+\xdb\x5c\x21\xeb\x4a\xf2\xd1\x56\xc5\xda\xa8\xaf\xfe\xcc\xe8\x8d\
+\xe5\xeb\x93\x4b\x60\x62\x00\x9e\xba\x70\xfa\xd2\x4e\xad\x79\x59\
+\xb5\x1f\x27\x2b\x41\x52\x14\x80\x5c\x6a\x9c\x14\x3e\xb7\x02\x3d\
+\x39\x25\x42\x04\x6f\x3e\x88\x2e\xce\x71\x6b\x95\xaa\xa5\xe1\x02\
+\xd5\x5f\x90\x76\xa7\xda\x57\x41\xcb\x07\x84\x79\xaf\x5c\x98\x02\
+\xae\x53\xb4\xb1\x84\xc5\x59\xb4\xd4\xe2\x0c\xef\xbd\x72\xf1\x69\
+\xab\x53\x02\x51\x16\xf3\x57\x9e\xbd\x60\x19\xb2\x2f\x74\x28\xe8\
+\x27\x66\x0a\x36\x53\x2a\x1c\x22\x87\x7a\x96\x48\x0a\x73\xad\x23\
+\xe5\x22\x7a\xa4\xce\xf7\x0e\x78\x9f\x52\x62\x0e\x3a\x86\x58\xc0\
+\x13\x69\xce\x15\xb4\x4f\xef\xaf\x58\x13\x02\x9e\x2d\x64\xbd\xf3\
+\xc3\xfc\x1b\x57\xae\x5f\xff\xf5\x03\x30\x7d\x6c\xf6\x52\xdb\xeb\
+\x39\x04\x14\xa8\x6d\xd7\xc6\xc8\xa8\x7a\xb8\x20\xde\x43\xd8\x24\
+\xc2\x01\x57\x3f\x63\x67\x58\xe8\x04\xfc\x94\x3e\x48\xc1\x01\x5d\
+\xfe\x8e\x52\x3a\x87\x68\x80\x40\xe9\xf9\x2a\x68\xc7\xd0\x2c\x42\
+\xe7\x09\xf1\x53\x5e\x41\x59\x15\x89\x0a\xbe\xaa\x7b\xf5\xf7\x80\
+\xae\xe7\x82\xc7\x04\x23\x31\x54\x27\x48\x21\x11\x71\x90\x14\xa4\
+\x06\x46\x20\x4f\x32\xdb\x63\x81\x29\x50\x27\x79\x2c\x5f\x11\xe4\
+\x5a\x41\x9c\x67\xb7\xdf\x45\x9c\x45\xed\x99\xb3\x27\xed\xc2\xc9\
+\xa3\xde\x99\xa3\x67\xdf\xf8\x77\x3f\xf8\xc1\xaf\x4f\x82\x27\xe6\
+\xe6\x1c\xa9\xa9\x85\x39\xf7\x46\x05\x68\x72\x9f\xdc\x5f\xb6\xab\
+\xf7\x1f\x59\x05\xb8\x75\x21\xc7\x01\x0b\xd1\x22\x98\xad\x95\xf3\
+\x29\x26\x0c\xfb\x23\x6a\x3c\x20\x59\xc7\xf6\x2a\xcb\x03\x48\xac\
+\xcf\xb1\x5a\xb4\x6c\xb0\x26\x2f\xf2\x53\x30\x22\x20\x43\xd7\x88\
+\x84\xe5\x1c\xbb\xc8\xe7\x06\xdf\x6d\x22\x82\x3a\xd0\x0d\x2d\x0e\
+\x57\xa9\x60\x44\x59\xb8\x6b\x77\x9c\x47\x9a\xe3\x83\x9b\x4b\x74\
+\x90\xaa\xb5\xf9\xee\xed\x65\x65\xba\x6f\x09\xca\xa6\x23\x05\x1a\
+\x66\x2e\xc5\x29\x3b\x75\x74\xde\x05\x79\x73\x67\xdf\x1e\x3d\xfa\
+\x62\x12\x98\x88\x80\x6f\xfe\xe6\x4b\x97\x06\x9d\xde\xe5\x31\x3d\
+\x5f\x28\x88\x52\xd3\xa4\xda\x36\x2b\x7b\xb4\xaa\xba\xab\xf1\xd9\
+\xe9\x02\x75\x08\x49\x01\x77\xa9\x2f\x72\x62\x9b\xcd\x06\x02\x26\
+\x48\xbd\x2a\x18\x7e\x57\x0e\x0a\x8e\x34\x88\x02\xe9\xc4\x91\xb2\
+\xcf\xfb\xb2\xc7\x0a\x90\xc8\xb2\x4b\xbb\x95\xb0\x51\x50\x05\xf5\
+\x36\x76\xb8\x8b\xc2\xf3\x28\xa3\xbb\xd4\xfb\x87\x37\xee\xb8\x96\
+\x2b\x19\xfd\xdf\xae\xbc\x63\xef\x7c\x72\xdb\x56\x37\x76\xec\xd3\
+\x07\x0f\xed\xc1\xda\xa6\x15\xd3\x09\x3e\x0b\xeb\x52\x70\xd4\x16\
+\x89\x7a\x64\x4b\x6b\x1b\xd8\xec\x47\xf6\xd1\xad\x7b\xde\x47\xf7\
+\x1e\x7d\x61\x1b\x9c\x18\x80\xe2\x6c\xfe\x52\x3c\x9e\xb8\xac\x89\
+\x97\x73\x19\x8b\x61\x4a\x06\x44\x3b\x2c\xa1\xc1\x2b\xe0\x0b\x59\
+\xa3\x87\xce\x8f\xe6\x2d\x92\xcc\xdb\xb8\x4b\x57\x80\x0f\x76\x6b\
+\x1d\x90\x93\xb1\x7c\x22\x69\x51\xcc\x51\xab\xb9\x6b\xad\x5e\x13\
+\x8b\x0c\x34\x09\x8c\x60\xad\x49\x3a\xf4\xa0\xf1\xa5\xe5\x13\x2c\
+\x4a\xfa\xa2\x83\x90\xa9\xb7\xba\xf6\xf1\xd2\x9a\xfd\xe4\xea\x2d\
+\xbb\x76\xf7\x81\xfd\xec\xe3\xdb\xf6\xc9\xbd\x65\x0c\x53\xd5\x0a\
+\xf8\x80\x59\x32\x7b\x7b\x79\xd5\xd6\x2b\xbb\x8e\x37\x98\x0a\x2a\
+\xd1\x73\xc9\x59\xa3\x15\x6f\xd3\x9d\x54\x3c\xd7\xa8\xff\xca\x41\
+\xdd\x7d\x26\x1d\x40\x8b\xf8\x72\x3a\x40\xed\x63\x26\x3b\x05\x73\
+\x97\x2c\x93\x4a\x03\x53\x1c\x16\x93\x17\xeb\xa7\x63\x31\x10\x10\
+\xb2\x0e\xd9\xf6\xbc\xa6\xf9\x81\x9d\xca\x83\x7c\xd2\xfb\xd1\xfd\
+\x64\x4d\x8e\xcd\xcf\xec\xc4\x17\x11\xf4\xbd\x24\xae\x32\x2b\xaf\
+\xaf\x52\x08\xf2\xbe\xcc\x93\xc8\x4e\xfa\x3d\x4a\xab\x2c\x63\xae\
+\xce\x1c\x5d\x70\x7c\xd0\x23\x18\x43\xda\xa1\x6c\xb4\x50\xe3\x47\
+\x37\x88\xd8\xc4\x35\xa7\xe7\xcb\x2c\x12\x1e\x60\x9e\x3d\x8c\x51\
+\x08\x45\x7a\x77\x65\xdb\xee\x3c\xdc\xb4\x0a\xf6\xfc\x1e\xaa\x51\
+\xd7\x12\x6f\x49\x14\xa8\x14\x1f\x37\x26\x06\xe0\xb9\x13\xa7\x10\
+\x17\x19\x3b\x7b\xf2\x24\xd9\x27\x7b\x94\x82\x7c\x40\x03\x68\xc2\
+\x32\xee\x02\x05\x02\x24\xed\x7d\x80\x74\xf5\x87\xe2\xe6\x91\xd5\
+\xba\x87\x57\x87\x8a\x9d\x65\x25\x2b\xd1\x78\x06\xd6\x4e\xb9\x1d\
+\x22\x6d\x8a\x68\x2f\xc1\x07\x12\x02\x4c\x3a\x02\x41\x4a\xbc\xb4\
+\x3b\x1d\xb7\x51\xa2\x76\x18\x80\xe0\xb4\xb3\x23\xce\x91\xa2\x94\
+\xb4\xd5\x42\x12\xf1\x28\x08\xe9\x39\xc9\x7b\x6c\xae\xe4\x08\x4e\
+\x7b\x01\xe2\x17\x17\x6c\x02\x2a\x92\xfe\xf9\x5e\x02\xba\x1f\x69\
+\x2e\x29\x3e\x46\x87\x4c\xf4\x40\xff\x77\x4c\x0c\x40\x2e\x9b\xb2\
+\xa9\x64\x84\x36\xd7\x87\xb8\x70\x78\x5c\x58\x17\x68\x7a\x43\xa7\
+\xd9\xfd\x11\xec\x2c\x4c\x2b\x2e\x18\x0d\xc9\x2e\x25\x91\x4b\x4d\
+\xd9\x91\x99\x59\x68\x50\xa4\x87\x8d\x25\x20\xc1\x40\x04\x54\xd0\
+\x01\x48\x57\xb7\x87\x14\x67\x65\x62\x6f\xf1\x46\x98\x12\x51\x7b\
+\x8c\x20\x97\xb5\x77\x30\x82\x13\xae\x23\x97\x1f\x52\xdb\x09\x82\
+\xf3\xc4\xe2\xbc\x9d\x3a\x26\x44\x24\x9c\x59\xda\x84\xf4\x04\xeb\
+\xfd\x5a\xd3\x71\x8b\x5a\x9e\xec\xaf\x10\x24\x2d\xa2\x45\xf7\xf9\
+\x5b\x64\x29\xe2\x49\x81\xd4\x8b\x67\x8e\xdb\x6b\xcf\x3f\x69\xaf\
+\xbc\xf2\x8a\x5b\xd7\xa4\x31\x31\x00\xd5\x83\x86\xb5\xda\x3d\x6b\
+\xbb\x3a\xa3\xaf\x27\xd2\x36\x62\x21\x71\x26\x9d\x4c\x26\xad\x58\
+\x9c\xb6\xe9\xa9\x29\x8b\x53\xeb\x7e\x16\xd7\xa6\xba\xa6\x72\xd3\
+\xb6\x58\x9a\xb5\x2e\x93\x90\x73\x53\x09\x68\x52\x9a\xa8\x32\x2a\
+\x7f\xa0\x6e\xa0\x40\xba\x6d\x2f\x55\x3e\xc2\x47\x22\x2a\x40\x06\
+\xeb\xd2\xf2\xf8\x02\x71\xc7\xdf\xf8\xc6\x45\xfb\x1d\x5e\xbf\xf1\
+\xb5\xd3\xd4\x7a\x0b\x47\xd9\x46\x68\x6d\xda\x0f\xde\x7a\xdf\xfe\
+\xcb\x8f\xdf\x63\x6e\x9e\x5b\xb8\xce\x2d\xd3\xe4\xb6\xde\x84\x2e\
+\x4d\x9e\xeb\x5f\x3c\x7b\xc2\xfe\xfa\xf3\x4f\xd9\x6f\x3c\x79\xda\
+\xce\x51\x56\xaf\x1c\xfd\x62\x2d\x3c\x31\x00\x5b\x1d\x32\x3f\x82\
+\x98\x90\x98\x22\xb0\x30\x6d\xa8\x4d\xcd\x8f\x40\x43\x07\xed\x0e\
+\x88\x2d\x4a\x76\xa3\x58\xd6\xae\x22\xdf\x15\xa3\x8f\xc9\x26\xad\
+\x8a\x33\x36\x39\x4e\x1b\x23\x62\x6e\xd5\xa1\x3a\x80\xda\x59\x1f\
+\x2e\x10\x44\xab\xf8\x02\x45\xc5\x6d\x8e\x32\x71\x65\x4d\xc8\x78\
+\x86\x89\xbf\xf2\xc2\x93\x08\xa6\x34\xa2\x2a\x86\x71\xd2\x7e\x01\
+\xf5\xee\x20\xdd\xb3\x3d\x12\x53\xa9\xd6\x9d\xfc\xe5\xc4\xee\x98\
+\x0b\xc7\xe7\xec\xe5\xa7\xcf\x3a\x4f\xa2\x21\x05\xf8\xd2\xf9\xd3\
+\x6e\x7f\x20\x19\x8b\xbb\xd2\x7b\xdc\x98\x18\x80\x44\x0c\x73\x91\
+\xc8\xd2\x57\x03\xb6\x51\x39\xb0\xa5\xa5\x87\x4e\xd9\x29\x53\x61\
+\x26\xde\xa3\x57\x6b\x1f\x60\x17\x35\x16\x0c\xb2\x90\x70\x9c\xbe\
+\x1e\x3a\x74\x80\x64\x38\x0c\xac\xb5\x9b\x33\xa2\xb5\x49\xa5\xf5\
+\x5c\x9b\x83\x1c\x29\x25\x91\x5a\x10\x22\x94\x70\x51\xc6\x24\x5c\
+\x82\x04\x52\x46\x4a\xa2\xc6\x47\x20\x43\x04\x4b\x25\xb4\x07\xe4\
+\x13\x74\x20\x79\x09\x91\x5d\x31\x2b\x4b\x0e\x61\x22\x75\x67\x8b\
+\x39\x3b\xb3\x38\x63\xbf\x77\xe9\x59\x7b\xee\xe4\x82\xcd\x4d\xe7\
+\x1c\x22\x84\x34\xb5\x4f\x21\x49\x9c\xa3\xeb\x3d\x6e\x4c\x0c\xc0\
+\xb0\xd7\xb2\x41\xad\xc2\x04\xc7\x98\xa2\x9e\x6d\x13\xf9\x31\x0b\
+\xd3\x22\x73\xf4\xdc\xa9\x4c\xd6\xed\xc0\x8a\x74\xe4\xff\x25\x47\
+\x6b\xe8\xfe\x0e\x7f\x6f\xd5\x0f\x50\x82\x43\xc7\x0f\x9a\x90\x08\
+\x8f\x96\x6e\xeb\xbb\x08\x92\x9d\x8a\xd5\xf0\x13\xda\x52\xd0\x3e\
+\x5f\x97\x89\x4a\xcb\x93\x60\x5e\x94\x04\x88\x08\x41\x84\x7d\xd8\
+\xff\xd6\xc3\x47\xf6\x1f\xff\xe4\xc7\xb8\xc8\x26\x7a\x43\x04\x09\
+\xc9\x51\x0a\x1e\x2a\xb4\x43\xa0\xc5\xee\x9b\x58\x71\x11\xb3\x9c\
+\xe7\x8b\xe7\x9f\x70\xf2\x5c\x81\x11\x01\x6b\xdf\x41\x08\x13\xf2\
+\x1e\x37\x26\x06\xe0\xfe\xea\xb2\x35\xa8\x2d\x49\xde\x6a\x6d\xcf\
+\x3c\x32\x37\x7b\x74\xd1\x8e\x9e\x3c\xc1\x64\x82\xbc\x0f\x31\x2a\
+\x53\x84\x48\xf0\x34\x5f\x8f\xd6\x66\x0e\x6e\x49\x24\xb0\xb2\x24\
+\xa1\xa3\x95\x49\xec\xd4\xdb\x1d\x26\xe5\x43\x97\x17\x71\x7a\x69\
+\x08\x74\x48\x19\x74\xb0\xb7\x7b\xd6\x07\x1d\x62\xf3\x21\xd7\xea\
+\x43\x76\x0d\xf5\x6f\x16\x9d\x4b\x67\xec\xe2\x85\x93\xb6\x38\x5b\
+\xa4\x44\x0e\x33\x29\xd2\x93\x76\x10\xc3\xcb\xf5\x69\x3f\xf1\xde\
+\xfa\xb6\xad\xed\xd7\x6d\x63\xf7\xc0\x4e\x2d\xcc\xd8\xdf\x7c\xed\
+\x65\x9b\xa3\x74\xa4\x38\x74\xfc\x50\x11\x7e\xcc\x98\x18\x80\x08\
+\x0c\x9a\x41\x59\xa5\x52\x88\x9a\x6c\x11\x47\x37\x87\xd0\x81\xb9\
+\x13\x39\x52\x4a\xdd\x03\x6d\xf5\xf0\x6e\xbf\x63\x7b\x7b\xbb\xc0\
+\xf6\x50\xe9\x89\x03\x72\x68\x7b\x6d\x8a\x06\xd5\xce\x28\x19\x71\
+\x83\x3c\xc1\xb1\xf9\x39\x9b\xc6\xbf\x47\x68\x89\x55\x08\x4f\x9e\
+\x61\x75\x6b\xcf\xb1\xfe\x80\xf3\x29\xab\x6b\x38\x4d\x0f\x31\xb4\
+\xb7\x5d\xe5\x67\xdb\xce\x2e\xcc\xdb\x73\x67\x8f\xdb\x33\x4f\x2c\
+\x20\xb0\x10\x4c\x8e\xe5\x98\x34\xe7\x15\xc1\xaa\x34\xae\xdd\x5b\
+\xb1\xff\xf1\xb3\x6b\xf6\x67\xd7\x6f\x59\x83\x80\x28\xf3\xda\x8c\
+\x3d\xa4\xc8\x5f\x3d\xbe\x80\x03\x32\xd6\x69\xa3\xe0\xf0\xfc\x3e\
+\x6a\x4a\x66\xc4\xed\xec\xec\xd5\x81\x27\x19\x20\xb2\x41\x4c\x4a\
+\x18\x93\x13\xa1\xce\xc4\x7c\x22\x29\xd5\x9f\x2c\xd2\x3e\x13\xd1\
+\x56\x38\x20\x02\xa2\x5d\x7e\xc7\xa3\xb3\x60\x67\xa8\x58\xc4\xda\
+\xde\xbe\xbd\x85\x9c\xbd\xb9\xb2\x6e\x6f\x5d\xbf\x6d\xff\xfb\x83\
+\x1b\xb6\x8a\x9b\x7c\xb8\xb3\x43\xb7\x21\x90\x10\x6f\x0f\x84\xb4\
+\x41\xc2\x14\xc9\x38\x33\x5b\xb2\x67\xa9\x73\x95\x9f\x10\xa0\xc5\
+\x6b\xaf\x41\x9b\x2a\x52\x84\x9a\x9f\x38\x62\x07\xf4\xe8\x3e\x43\
+\x50\x9d\x85\x20\x28\x01\x93\x57\xf8\xff\xc6\xc4\x8f\x77\x5b\xfb\
+\xd6\x01\xf6\x20\xcf\xe2\x31\xf9\x7d\x69\xe6\x91\x25\x0c\x0f\x4f\
+\x50\xae\xdd\xbb\x63\x77\x57\x1f\x59\xd6\xf9\x7e\x9f\xc5\x33\x79\
+\x5a\x62\xd4\x0e\xba\x04\x0d\x35\x38\xa2\x38\xea\x68\x86\x83\x7a\
+\x9d\x32\x18\x40\x6a\xaa\x06\x72\xc2\xab\xd1\x6c\xba\xcc\x37\x09\
+\x92\xca\x44\x5b\xe6\xf2\x18\x3f\xbd\x7a\xd3\xdd\x55\x2a\x96\xf2\
+\x96\xd2\x0e\x31\x0b\x72\xa5\x21\x74\xf1\x7b\x39\x97\x75\x41\x48\
+\x27\x29\x2f\xe6\x78\xc8\x6d\x42\x57\xd8\x4e\xcd\x15\xad\x0c\x42\
+\x5a\x04\x62\x0f\x1e\x92\xbe\x90\xb0\x72\xad\xf8\xf1\x1c\x38\x39\
+\x00\x82\xe4\x68\x24\x6b\x1a\x26\x10\x1c\x12\x8c\x5a\x03\x13\x94\
+\x2c\x94\x6c\x7e\x66\x1e\x83\x94\x43\x22\x27\xad\x52\xab\x5a\x28\
+\x4a\xa4\xfb\x07\xee\x7b\x31\x8e\x47\xc5\x22\x56\x68\x73\x4c\x5c\
+\x1e\x22\x10\x8a\xb2\xb0\x18\x3c\xa1\xc9\x8c\x58\xec\x3e\xe5\x62\
+\x96\x42\x0c\x4d\xc7\x13\x36\x4d\xc9\x64\x59\x44\x93\x12\x68\x23\
+\x28\x12\x98\xaf\x99\x23\x65\x9b\x3b\x52\xb2\x45\x5e\x0b\xe5\x69\
+\x54\x67\xda\x09\xa6\x32\x02\xed\xb7\x9f\x3d\x67\x4f\x1e\x9f\x81\
+\x90\xb9\x2e\xc1\x57\xc6\x15\x90\x59\x5a\xa7\xba\xd4\x3d\xcc\x13\
+\x71\x3e\x1c\x7c\x2e\x4d\xf2\xb8\x31\x91\x22\x17\x4f\xce\x5d\x4a\
+\x45\xb3\x97\xc3\x4c\x52\xfa\x7f\xc0\x09\x6b\xb5\x9a\x6b\x69\x4d\
+\xd8\x3b\x16\x22\xeb\x31\xc9\xda\x01\xb5\x99\x75\x9e\xbe\xdd\x63\
+\x71\x30\xfc\x83\xed\x4d\xf8\x23\x6a\x73\x53\x59\x57\xab\x2a\xdb\
+\x36\xc2\x45\x37\x4a\xe5\xfc\x7e\x7a\xed\xa6\x6d\x23\x78\xf4\x99\
+\xa4\xb0\xf6\x07\xe4\x2a\x0b\xc0\xfb\xc8\xec\x0c\x82\x2a\xe5\x64\
+\xb7\xb3\xd9\x04\x51\x59\xd6\x5e\x40\x06\x93\xe5\xca\x4a\x84\x8c\
+\x4c\xcf\x17\x93\x76\x04\x73\x94\x82\x70\xb9\x34\xd7\x6e\x38\xd4\
+\xe8\x3a\x33\x85\x3c\x56\xb9\x6b\x4b\xab\xeb\xf6\xa7\xef\xbc\xef\
+\xfd\xcf\x8d\xf7\xbf\xdc\x8e\xd0\xd3\xcf\x9c\xbe\x84\xcf\xb8\x1c\
+\xa5\xc6\xa3\xd1\xa4\x75\xe8\xf7\x31\x7a\xf4\x10\xf6\x6d\x23\x7d\
+\x13\xf4\xd8\x78\x34\x84\x20\xa1\xd6\x21\x9d\x0d\x3c\xf7\xf6\xfe\
+\xbe\xad\xec\x6c\xb8\x00\x2d\x14\x0a\x4e\x8a\xba\xc5\x7b\xda\x19\
+\x1a\xda\x16\x4c\x3d\xe2\x3f\xdd\xd4\xf4\x68\xad\x32\x54\xd3\xb9\
+\x34\x92\x3b\x66\x47\xf2\x19\x3b\x09\xf4\x57\xb6\xb6\xed\xfe\x66\
+\xc5\xf5\x6f\xdd\x18\xd5\xf2\xf7\x10\x3d\x2b\x68\x91\x36\x84\x52\
+\x2e\xa1\x40\xa7\x8b\x4e\x23\x44\x40\x53\x81\xc0\x9f\x41\x2e\x9f\
+\x82\x2c\x75\x2b\x6d\x6d\x67\x8f\x8e\xe3\x61\x8e\xd6\xec\xea\xed\
+\x7b\xc8\x67\xd0\xe6\xf3\x79\xa5\x70\xff\x8d\xeb\x5f\x26\x00\x8b\
+\xc7\x8f\x5e\x0a\x87\x22\x97\xd3\x98\x90\xb8\x36\x45\x99\x90\x87\
+\xb2\x73\xdb\xdc\x83\xb6\x4d\xa5\x0b\x6e\x33\xa2\x42\xed\x76\xe8\
+\xc7\x2d\x11\x26\x67\xc2\x15\x20\x67\x0f\x2c\x4e\xe0\x84\x8a\x3e\
+\x02\x40\x7b\xfe\x4d\x14\xe5\x8d\x07\xcb\x26\x1f\xa1\x16\x17\x81\
+\xa0\x4a\x53\x69\x7b\x12\x76\x3f\xc2\xcf\x0c\xd7\x51\x07\x11\xab\
+\xdf\xc6\xc7\x37\x51\x8a\xdb\x7b\xea\xf1\x5d\xbb\xbb\xbc\x46\x5b\
+\xde\xb0\x55\x34\x84\xee\x18\xab\xb7\xe7\xb2\x19\xa7\x1e\x65\xa2\
+\xa4\x37\x24\x96\x3c\x32\xde\xc4\x9d\x6a\xfb\xde\x91\x36\xd0\xd7\
+\x1d\x67\xc4\x93\xe7\xf7\x97\x08\xc0\xe4\x2d\xb1\x89\x1c\x50\x76\
+\xdb\x60\x87\x85\x34\x86\xc4\x74\xb1\x04\x8b\xef\xd0\xff\x77\x59\
+\xa0\xf6\xf9\xe3\xc0\x2d\x09\xfc\xce\x9d\x39\x67\x53\x4c\x48\xd0\
+\xb5\xc0\x08\xa6\x4e\x21\x51\x93\x4c\x2e\x44\x3b\x1c\xb2\xf8\x0e\
+\x4c\x7f\xc3\x6a\xad\x06\xf6\xb5\x6b\x59\xea\xb9\x98\x8e\xbb\x7a\
+\x8d\x86\xb5\xdb\x13\x83\xe4\x10\x3a\x2c\xa6\x90\x4e\x5a\x46\xdb\
+\xea\x64\x13\x06\xb4\xd5\xf5\x0d\xc3\x6e\xd9\x85\xd9\x82\x85\x7c\
+\x23\x7b\xb8\xb2\x6a\x3f\x7a\xef\x7d\xfb\xef\x57\xfe\xdc\x6e\xd1\
+\xff\x03\xa1\x08\xe5\xc3\x11\x5c\x67\xbb\x5a\x45\x63\x44\xed\x68\
+\x29\x63\xb3\xb9\x04\xb6\x3d\x62\x8b\xe5\x1c\x65\xf6\x59\xef\xfc\
+\x82\x31\x31\x00\xcf\x5d\x38\x63\x39\x26\xa6\x76\x92\xa5\xf6\x3a\
+\x90\x62\x8d\x4c\x4f\x15\x66\xac\x06\xa4\x2b\xf5\x1d\xd7\xb7\xf7\
+\x71\x71\xab\x5b\xab\x16\xa2\x5d\x5c\xbb\xf3\xc0\x02\x03\xa0\x0b\
+\xf4\xb7\x1a\x55\xc4\x49\x85\x5a\x6e\xf0\x39\x99\x43\x08\x15\x52\
+\x09\x24\x74\x0b\x61\x33\xef\x4a\x43\xdb\xee\x12\x32\x60\x94\x60\
+\xf9\x11\x4a\x63\xb2\x19\xb6\xd3\x73\x33\xf6\xfc\x85\x53\x76\x02\
+\x22\xd4\xb3\x04\x12\x32\xc7\x91\xb9\xe7\xcb\x05\x44\x16\x9c\x24\
+\xe4\x91\x80\xf7\x3e\xb9\x65\x37\x1e\xae\x1b\x17\xb7\x26\x24\x30\
+\x24\x40\x12\x60\xf9\x44\xc6\x4a\x74\x8c\xe3\xb3\xd3\xce\x53\x04\
+\xf9\xce\xe3\xc6\xc4\x00\xec\xa2\xaa\xca\x2c\x56\x8f\xc1\x74\x7a\
+\x1d\x77\x0b\xac\x98\xcb\xd9\xd2\x0a\xad\x0f\xa8\x96\x11\x47\x83\
+\x71\xc0\xf2\xa9\x3c\xda\x60\xd7\x3e\xba\xb3\x84\x78\xd2\x1d\xe4\
+\x00\xa5\x72\x28\x6a\x2e\x2c\x2e\xda\xc3\xb5\x5d\x5b\x5a\xdf\x72\
+\x0f\x34\xcc\x4d\xe5\x6c\x06\x07\x59\x4a\x47\x80\x70\x96\x3a\x1e\
+\xe1\x33\xf6\x5d\x2f\x1f\xd2\xab\xda\xc0\x5d\x6d\x5b\xfa\xfe\xe4\
+\xdc\xb4\xbb\xc9\x21\x02\xaf\xb5\x3c\xea\x7f\x68\x27\x4a\x53\x76\
+\xaa\x4c\x8b\x94\x8d\xf6\x61\x70\x58\xf0\xc7\x4b\x4b\xf6\xc7\x3f\
+\x79\xd7\xed\x12\x95\x40\x96\x07\x12\x96\x0f\xf6\x48\x5c\x00\xd2\
+\x8c\xd9\x3e\xe8\xdb\x6e\xd4\xec\xd1\x63\x6e\x0c\x4c\xe4\x80\x27\
+\xce\x1e\xbd\x04\xb9\x5d\xae\xd6\xd0\xdb\xd4\xb9\x02\x20\xf8\x16\
+\x58\x44\xa1\x38\x8b\x3e\xaf\x59\x52\x04\x89\xdb\x1a\x74\x1b\x76\
+\x72\xb6\x6c\x33\xb9\x3c\x8b\x41\x3e\xd3\x96\xa6\x80\xf2\x7c\xb1\
+\x64\x6f\x5f\xbd\xe1\x9c\x5f\x29\x87\xac\xc5\x9b\xcf\x17\x72\xae\
+\x6f\xcf\x4c\x97\xe0\x90\xc3\x9d\x23\xf9\x8d\xa5\xf5\x1d\x77\xdb\
+\xbd\x10\x47\x57\x50\xe3\x7e\x7a\xb8\xcc\xd4\x32\xe8\x51\x17\x58\
+\x98\x86\xed\xf9\x5e\x9a\x5a\x0f\x13\x4c\x05\xd9\xf3\x28\x4d\xb2\
+\x5b\x85\x53\xd6\x36\xf7\x31\x53\x61\x44\xd6\xd0\xd2\x9c\x43\x4a\
+\x70\x8b\xae\xe0\xee\x5c\x85\xc2\xde\x94\xcd\x7c\x39\x0e\x48\xd0\
+\x76\x76\x1b\xfb\x44\xd2\x6f\x7b\xb5\x03\x04\x4d\x83\xec\xc8\x04\
+\xfb\x9d\x22\x4c\xd1\x19\x76\x61\xf5\x9d\x7d\x7c\x02\x93\x39\x52\
+\x42\x88\xd0\x9a\xca\xf0\x40\x11\xf2\x3b\x0d\xcc\x0f\x50\x65\xba\
+\xc1\x81\x1d\xb1\xe9\x29\xdd\xd1\x09\x99\x87\x0c\xec\xd2\x53\x37\
+\x77\x2b\x4e\x1d\xfa\xfd\x21\x6a\xb7\x85\xae\xa7\xcd\x7d\xe6\x1f\
+\xf4\xe8\x8c\x5e\xf2\x10\xda\x15\x52\x93\x57\xb0\xf6\x20\xd0\x47\
+\x74\x9b\x2a\x76\x3c\x42\x7b\xce\x53\x6a\x59\xbe\x97\x42\x7b\x8c\
+\x90\xde\xf7\xd6\x29\xb9\x06\x9a\x80\x6b\x74\xdc\x6e\xd0\x08\xb4\
+\xa5\x40\x5d\xca\x1e\xb3\x1d\x30\x39\x00\x19\xe0\x37\x44\xd1\xe4\
+\x20\xb3\x2c\xa6\x64\x75\x6b\x03\x58\xf7\x69\x75\x7b\x4e\xd5\xe5\
+\xa9\xb1\xb8\xa4\x2d\x90\xeb\xa0\xf8\x76\xf1\xe8\x31\xf4\xfe\x0c\
+\x99\xce\xd3\xcf\x7b\x74\x8c\xb5\x6d\xb2\x4a\xb0\x12\x89\x08\x24\
+\x99\xb5\x1b\x95\x6d\xfb\xf3\xe5\x87\x76\x7b\x77\xdb\x3e\xc1\x5e\
+\xaf\x6e\xae\x5b\x85\xf2\xa9\xe2\x22\xdb\xa0\x26\x92\xce\x59\xad\
+\x0f\x1e\x9c\x5c\x3e\xdc\x2b\x10\x07\x64\x53\x71\x82\x54\xb7\xbb\
+\xa0\x64\xeb\x40\xb7\xe1\xb5\xf7\xe8\xb7\x24\x88\x90\x0b\x4c\xa0\
+\xfa\xf4\xf2\xe8\x34\x3b\xbb\x70\xce\x06\x6e\x94\x1e\x9e\xe2\xbd\
+\x2c\x73\xd2\x31\x8f\x1b\x13\x03\x10\x0c\x24\xec\x89\xb9\x45\x8c\
+\x4d\x9a\x3e\x7b\xc2\x6a\xc0\xff\xc6\xfa\x5d\xe7\xca\xf4\x15\x7d\
+\x29\xca\x24\x16\xcb\x25\x3b\x3e\x77\xc4\xed\xcb\xd7\x74\xaf\x80\
+\x85\xec\x40\x7c\xb7\x70\x93\xbb\x12\x4e\x30\xb8\x08\xef\x00\x14\
+\xd5\x1a\x0d\xdb\x41\x39\xd6\x9b\xc8\x63\x3a\xbc\xcc\x13\xb0\x80\
+\xa4\xe8\x02\x91\xa4\xdd\x7d\xb4\x6a\xf7\xb6\x2b\xf6\xa8\xda\x01\
+\xba\x03\x7a\xfa\xbe\x73\x80\xe2\x05\xdd\xfa\x76\x37\x53\x11\x3c\
+\x3a\x9f\x36\x48\x73\xa0\x4b\xa8\xc9\xd3\x51\xa6\x09\xfa\x3c\x64\
+\xdd\xeb\x0e\x21\x48\xe6\x01\x4a\xf2\x88\xb1\x74\x32\x6a\x0b\xf9\
+\x29\x3b\xfa\x98\xbb\xa3\x13\x03\xb0\xc6\x02\xee\x3d\x78\x68\x77\
+\x1e\xde\xb3\xfd\xea\xae\x7b\x0a\x63\x6b\xab\x6a\xd7\x1e\xdc\x71\
+\x75\xe6\xf7\x63\x86\xa8\x3f\x0f\x38\x6b\xe7\x67\x71\x0e\x66\x07\
+\xe2\x0d\xb2\x30\x85\x63\x8c\xf8\xb5\xdf\x27\x43\x12\xa2\xce\x87\
+\x7c\xbf\xef\x1e\x5c\x98\x8a\xc4\xad\x0c\x4b\x7b\xc0\x53\x37\x55\
+\xb4\x55\x1e\x05\x49\x12\x7d\xc3\x51\xdf\x29\xc6\x9d\x1d\xc4\x10\
+\x72\x76\xe8\x0b\x51\x5a\x25\xb7\xeb\xa4\x5b\x6f\xca\x7a\x9c\xac\
+\x0a\x15\xe2\x91\x01\xb0\x97\x5a\x9c\x81\x97\x9e\x3a\x76\xc4\xed\
+\x05\xe4\x28\x0b\xed\x14\xef\x35\x3c\x6b\x70\xbd\x19\x82\x12\xa3\
+\x93\x3d\xee\xee\xf0\x44\x7c\xbc\xf6\x8d\x97\x2e\xf1\xc5\xcb\x09\
+\x44\x85\xbb\x29\x4c\x1a\xc4\x03\x7a\xe4\xe4\x34\xfa\x5c\x77\x81\
+\xb5\x85\xd5\xa4\xd6\x44\x38\x45\xfa\x2f\xdd\x0c\x66\xef\x39\x19\
+\x5a\xc0\x1c\x69\xf3\xc4\xc7\x22\xf4\x60\xa4\x26\x7e\xb2\x5c\xb6\
+\x34\xa2\xaa\x0d\x31\x69\x93\x43\xb6\x35\xae\x07\x19\x52\x59\x6d\
+\x23\xa3\x32\x3b\x76\x20\x83\x84\xe2\xd3\xad\x2d\x8f\x16\x9b\x4b\
+\xa5\x68\xbd\x45\x82\x8c\x86\x84\x17\x52\xa8\x46\x11\x6c\x96\xda\
+\xce\x66\xf3\x96\x83\x5b\x64\x8e\x74\xcf\xf0\x00\xd2\xf3\x13\xd4\
+\x31\x8a\xac\x8a\x94\xce\xc4\xe3\x4e\x83\xec\xd5\xda\x5e\xc3\x3b\
+\x78\xe3\xca\x95\x2f\x41\x82\xba\x03\x3c\x84\x6d\xd5\xaa\xc2\x2c\
+\xa2\x4b\x1f\x3f\x52\x2c\x3a\xf9\xfa\x60\x7d\xd3\x3d\xcf\x93\x8c\
+\xfa\xcd\x37\x44\xb3\xcb\x00\xc1\xd8\x82\x66\x3a\x91\xa2\x15\xea\
+\x49\x32\x1f\x50\xef\xb2\x40\xc1\x35\x64\xfb\x74\x82\xbb\xcb\xeb\
+\x76\x7f\x79\xc3\x1e\x6e\xee\xb9\x3a\xe7\x7f\x6e\x67\xa8\x4b\x80\
+\xb4\x63\x9c\xc2\x18\xb5\xf5\x00\x14\xc1\xd5\x82\x3d\x82\xbb\x81\
+\xfa\x5b\xde\x58\xb3\x1d\xbe\x9f\x84\x77\xb4\x19\x3b\x43\xc9\x65\
+\x59\xb8\xe0\x6f\x7d\xba\x14\x5c\x73\xfb\xe1\x2a\xe4\xaa\x27\x4c\
+\x47\x10\x24\x3c\x02\x32\xc7\x2c\x2d\x9b\x4a\xbb\x67\x8a\x1e\x37\
+\x26\x22\xe0\xb9\xf3\xa7\x2e\xed\xb7\xda\x97\x45\x46\xee\xc4\x5d\
+\xcf\x4d\x56\x7b\x7d\x5b\xe8\x6b\x3d\xc8\x30\xad\x96\x06\x27\xf8\
+\xd4\xc3\x91\xc2\x92\xa3\xba\x5f\x40\xa9\xda\xf5\x3b\xf7\x09\x84\
+\xcf\x22\xd1\xa0\x95\xa6\x33\xee\x7e\x3f\x78\xb5\x31\x48\x92\xb1\
+\x72\x37\x44\xb4\x78\x0e\x16\x37\x54\x51\x89\x6b\x9c\xb7\x02\x21\
+\xaa\x35\xea\x2e\x93\x7a\x79\x9f\xac\x17\x21\x51\x3d\x5f\x08\x16\
+\x1d\xbb\xeb\x5e\xa2\x0c\x91\xf6\x0b\x37\xd1\xfe\xda\x2a\x97\x0f\
+\xe8\x13\x3c\xb9\x43\xcd\x41\x5b\x72\xda\x7c\xc9\xc2\x01\x94\x89\
+\x37\x4b\x1b\xfc\xc1\x95\x2b\xbf\xbe\x17\x38\x79\xfa\xe8\x25\xd4\
+\xdf\xe5\x06\x42\x48\x34\xa6\xfd\x15\xf9\x76\x6d\x80\xea\x06\xc5\
+\x2e\xae\x6f\xaf\x56\xb7\x59\x50\x91\x47\x80\x68\xd4\xf0\xe1\xd2\
+\xdf\xf7\x57\x36\x6d\x1d\xed\x20\x05\xa9\xdb\x55\x32\x24\xf2\xfe\
+\x6a\x89\x5d\x26\x2e\x22\x95\x5e\x97\x03\xd4\x53\xa7\xba\xc6\x2e\
+\xe5\xe5\x75\x06\x4e\x48\x95\x31\x46\xba\x47\x20\xe7\x38\x0b\xd2\
+\xca\x74\x01\xed\x07\x4c\x73\xac\xb2\x5b\xe5\xd8\x1b\x8f\x36\xdd\
+\x3e\x65\x02\xd4\xb8\xad\x79\x39\x4a\x38\x27\x84\x48\x2a\x60\xc4\
+\x92\x74\xae\x1c\x88\x39\xbc\x49\x62\x5e\xc2\xa2\x5f\x18\x00\x21\
+\xf7\x17\x06\xcc\x1b\xf9\xe6\x6b\x2f\xff\xbd\x78\x2c\xfc\x3d\xed\
+\xce\xaa\x8e\xf5\x7c\x80\xab\x65\x4c\x8b\x76\x60\x64\x70\xf4\x64\
+\x47\x0e\x88\x3d\xff\xe4\x19\x47\x50\x7a\x4c\xa6\x09\x12\xb6\x76\
+\x6b\xb6\x5f\x6f\xf2\x39\xd6\x94\xf0\x29\x23\x29\xda\xd1\x7c\x21\
+\x0b\x63\xa7\x9c\xdc\xed\x13\x4c\x3d\xf2\xa2\x36\xb9\x42\xb0\xf6\
+\xb5\xd5\xee\x87\xd9\xc9\xf6\xab\x2f\x3e\xe9\xcc\x4c\x03\xa7\x99\
+\x80\x6c\x47\x94\x83\x5a\xe2\xe1\x4d\x54\x5c\x64\x32\x85\xfa\x0d\
+\xdb\xdd\xb5\x2d\xdb\xc0\x30\xcd\x63\xbb\xe5\x0e\xf5\xc8\x8e\xb6\
+\xdf\x14\x8c\x75\x50\x71\x6c\xae\x6c\x21\xff\x18\x7d\x92\xae\xc2\
+\x16\xb3\x7f\xeb\xf5\xd7\xc7\x04\xe4\x73\x0f\x4a\x7d\x2e\x00\xe3\
+\xf1\x38\xfe\xea\xef\xbc\xf2\x77\xa2\xc1\xd0\xf7\xc4\xb2\xd2\x22\
+\x09\x08\xa5\xe5\xa1\xf8\xe6\x8f\x92\xa9\x2a\xfa\x3c\x68\xc7\xca\
+\x73\x28\xc3\xb8\xdd\xa2\xb6\xb5\x2d\xf6\xe9\xca\x0a\x8b\x45\x9d\
+\xc1\x09\x5a\xa8\xa0\xad\x47\xeb\x4e\xcd\xce\x42\x92\x68\x72\xb1\
+\xa4\x9c\x21\x08\xba\x57\x6d\xd8\x98\xd6\xa6\x2d\xb4\x78\x98\x5a\
+\x45\x69\xd6\x09\xca\x6e\xab\x67\x27\x66\xf2\x76\x7a\xa1\xec\xee\
+\xf8\xea\x39\xc5\x3e\x01\xd0\xe6\xa9\x9e\x5a\xd3\x53\x68\x05\x48\
+\xd6\xed\x16\xf1\x5d\x21\xe7\xda\xd2\xb2\x65\x49\x4c\x9f\xcf\x5a\
+\x90\x67\x29\x93\xb5\x0d\xd0\x19\x96\x2e\xc1\x0b\xcc\x14\xd2\xd5\
+\x5c\x70\x66\xee\xf7\xbf\xf3\x1d\x21\x42\x4f\x91\xff\xc2\xf8\x5c\
+\x00\x34\x7e\xf3\xb5\x6f\xfc\x6e\x22\x12\xfe\x4f\xc8\xe1\xa4\x76\
+\x56\x23\x91\x18\x52\xb5\x69\xcf\x9e\x7d\xc2\x16\xa7\xb3\x76\x67\
+\x79\xcb\x8e\x62\x5a\x9c\xe4\xdc\xab\x42\x3a\x3d\xf4\x7a\xd7\x76\
+\xea\x75\x9b\x49\x65\xe0\x86\x18\x13\x88\x61\x6b\x6b\x9c\xcd\x0f\
+\x22\xf4\x64\xe7\xc8\xfa\x10\x5f\x30\x86\x32\x2b\x4e\x39\x19\x2b\
+\x02\xd5\xf3\x47\x01\x24\xf5\xfa\xfa\x1a\xe7\xda\xb3\xed\x7a\xdb\
+\xc9\xee\x08\x7c\x71\x12\x43\x73\xfe\xd4\x31\xda\x4b\xd7\xaa\x94\
+\x5d\x0b\xee\x51\x67\xc8\x6a\x6f\x50\x67\xe6\x18\xa1\xed\xbd\x4f\
+\xef\x39\xd1\x13\x8f\xe0\x50\x39\xd7\x8a\x9e\x16\x83\x68\x67\x41\
+\xdd\xb1\xd2\xd4\xfa\x7c\xe9\xec\xe9\xdf\xfe\xd6\xb7\x5a\x6e\x71\
+\xbf\x34\x26\x72\xc0\xb7\xfe\xe0\x6f\xdf\xbb\xff\xe0\xfe\x41\xd8\
+\x1f\x7c\xc6\xeb\x0f\x52\x29\xa2\x2a\x22\x12\x33\x47\x53\x53\xd8\
+\xdc\xb1\x5b\xd4\x9d\x95\x75\xdb\xaa\xee\x63\x8b\xe3\x36\x45\x3b\
+\xd3\xcd\xc8\x5c\x7e\xda\x82\xf1\xa4\xdd\x7b\xb8\x8c\x3f\x6f\x59\
+\x85\x96\xa7\xef\xe9\x69\x71\x89\x96\xb9\x6c\x82\x5a\x3e\x94\xc3\
+\x5a\xd4\x1e\x82\x49\x19\x8e\x22\xbf\xb3\x04\xef\x58\x79\x9a\xe3\
+\xa8\x77\x82\xe3\x91\xd1\x5b\x5c\xe3\xc1\xd6\xbe\xd5\xd1\x18\x72\
+\x9d\x43\x50\x26\x13\xa5\x87\xa9\x25\x94\x74\x9f\x50\xf0\x5f\xd9\
+\x02\x25\x08\x24\xb5\x6c\x75\x1d\xde\x1b\x97\x73\x99\xa5\x44\x3c\
+\xfa\xcf\xad\xf0\xee\xb5\x37\xdf\x9c\xfc\xac\xf0\xc4\x00\x5c\xb9\
+\x72\x65\x7c\xfe\x5c\xe1\xd3\xee\xc0\x5f\xed\x0d\x47\x4f\x06\xc7\
+\xa3\x0c\x76\xd5\xd7\x25\x8b\x7e\x7f\xd8\x59\x59\xed\xd0\xa4\x80\
+\xf6\x6c\x79\xd6\x7c\xea\xd3\x4c\xa6\xdd\xa6\xc7\xd7\x59\x14\x7c\
+\xd0\xf6\xda\x6e\x5f\x5e\xc8\x4f\x02\xf1\x1c\x8b\x8f\x45\xe3\xb8\
+\xca\xc3\xcd\x0c\x37\x59\x3e\xd3\xad\x2f\x4d\xba\x09\x89\xae\x6f\
+\x22\xb9\x3b\x0d\x67\x9b\xd5\xdf\xf5\xb4\x67\x87\xc0\x6b\xc3\xb5\
+\xc1\xf9\x2a\xf5\x96\x3d\x44\x21\x4a\x87\x1c\x50\x62\x6d\x6a\x5f\
+\xe5\x97\xa2\x04\x96\xd6\xb6\x6d\x65\x07\xa5\x09\x7f\xe0\x4f\x46\
+\x38\xd2\x0f\xbc\x4e\xe7\x9f\x6d\xb7\x02\x7f\xf4\xdd\xef\xfe\x87\
+\x89\x04\xa8\x31\xb1\x04\x7e\x3e\x5e\x7d\xf5\xd5\x04\xcd\xea\x72\
+\x2e\x93\xfc\x97\xe8\xae\x53\xf9\x7c\xda\x57\xce\x97\x40\xa4\x47\
+\xef\xee\xe3\x0b\xd0\xeb\x4c\x7e\x6f\xbf\xea\xb6\xc8\x76\xa9\xbd\
+\x6d\x5a\x99\xfc\xfd\x54\x86\x6c\xa3\xef\xb5\x4b\x1c\x24\x9b\x47\
+\xc8\x6c\x11\x51\xa3\x9d\x62\x26\xe6\xb6\xb8\x7b\x9d\xb6\x6b\x5d\
+\x75\x6a\x5f\x3b\xc0\x22\x57\xb7\xb1\xc2\x4f\x3d\x67\xb4\x81\xef\
+\xd7\xb3\x85\x32\x40\x1e\xd7\x54\x39\x8d\x28\x99\x3e\x79\xf3\x08\
+\x48\xd0\x7a\x56\x00\x7d\x27\x67\xa6\x9d\xeb\xec\x60\xa9\x9b\xbd\
+\xee\x08\xf4\xbc\xb3\xba\x57\xf9\xa7\x0f\xc3\x5b\xef\xdd\x7c\xf3\
+\xe6\x63\xff\xd1\xc4\x44\x04\xfc\x7c\xe8\x1f\x1b\xfc\x56\xae\x70\
+\x7f\x34\x53\xfe\xd1\x4c\xb1\x70\x21\x97\xca\x2c\xd4\x6b\x35\xdf\
+\x1a\x99\x92\x4d\x16\x44\xa5\xfc\xf4\x4f\x62\xe2\x61\x14\x61\x3e\
+\x8b\x88\x19\xe2\xe7\xf1\x08\xb4\x48\xed\x14\x95\xd1\x0b\xaa\x45\
+\xc9\x57\x65\xf9\x87\xef\x7e\x48\xd9\xec\x91\xf9\xa0\x7b\xaa\x4c\
+\x01\xe8\x53\x22\xd2\xfb\x6a\x65\xa5\xe2\xa1\x65\xd6\x76\xdc\x2c\
+\xe7\xd6\x93\x64\xda\x38\xbd\xfb\x68\xc3\xed\x19\x4c\xd3\x5e\xe7\
+\xb2\x31\xb8\x24\x46\xa6\xcd\xdd\x3a\x57\xeb\x6d\x13\x20\x6d\x81\
+\xd1\x7a\x7e\x74\xfa\xe8\xfc\x1f\x56\x0e\x86\x1f\x5f\x79\x73\x72\
+\xeb\xfb\x8b\xe3\xb1\x08\xf8\x0b\xc3\xf7\xed\x6f\x7f\x3b\x46\xad\
+\xbe\x36\xee\xb6\xfa\xda\xa2\xde\x6a\x57\x1d\xac\xf5\xb4\x46\x21\
+\x1c\xb7\xa7\x9f\x58\xa0\x56\x77\xad\x81\x20\x39\x56\x2a\xa0\x00\
+\xfd\xb5\xb0\x7f\x94\x09\xf3\x59\x8a\xe3\x86\x4c\xe5\x8f\xaf\x7c\
+\x64\xdb\xba\xb3\x1b\x18\xda\x42\xb9\x60\x17\x4f\x1f\x03\xbe\x71\
+\x6b\xf3\x5e\xa3\x3d\xb0\x70\x3c\x68\x0b\xb3\x05\x77\x41\x65\x26\
+\xa2\xcf\xda\xa0\x6a\xfb\xc0\xfd\x33\x99\x03\x5a\x71\x1d\xcb\xbb\
+\x30\xc7\x77\x9f\xb9\x68\x9f\xde\xbe\x6e\x07\x5c\x4f\x6a\x72\x21\
+\x9b\xb2\xdd\xce\x28\x54\x6b\xf6\xfe\xf4\xfb\xdf\xff\xbe\xe0\x32\
+\xb1\xe6\xff\xbf\x07\x6d\x32\xca\xeb\x2f\xdd\xbf\x1a\x83\x83\x1e\
+\xaf\x79\xbf\x1a\x5f\x8d\xaf\xc6\x57\xe3\xab\xf1\xcb\xc3\xec\xff\
+\x00\xa0\xa1\xea\x83\x3e\xf3\xbe\x33\x00\x00\x00\x00\x49\x45\x4e\
+\x44\xae\x42\x60\x82\
+\x00\x00\x07\x52\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x40\x00\x00\x00\x40\x08\x06\x00\x00\x00\xaa\x69\x71\xde\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7\x6f\
+\xa8\x64\x00\x00\x06\xe7\x49\x44\x41\x54\x78\x5e\xdd\x9b\xdb\x6f\
+\x14\x55\x1c\xc7\x7f\xe7\xec\xad\xdd\x5e\xd8\x5e\x2c\x5d\x4a\xb7\
+\x2d\x95\x4b\x03\x7d\x90\x82\xc6\x0b\x86\xad\x31\x98\x80\x18\x0c\
+\x60\xf4\xc1\x4b\xe2\x83\x41\x83\x0f\xea\x93\x7f\x82\x1a\x0d\x46\
+\x5f\xd0\x10\x4d\x34\xb1\x9a\xa0\x4d\x6b\xe0\x41\x5a\xc5\x88\x91\
+\xd6\x88\x20\xb4\x29\x6d\x29\xa6\x2c\xad\xb4\x85\x76\x2f\xdd\xcb\
+\xcc\xf1\xfc\x66\xcf\x94\x4e\xbb\xbb\xdd\xcb\xcc\x74\x97\x4f\x02\
+\x7b\xce\xaf\xdb\xb0\x9f\xef\x9c\xdb\x4c\x29\x81\x7b\x84\x89\x4b\
+\x1d\xa5\x55\x84\xbe\x09\x04\x0e\xf3\xee\xe6\x78\x95\x8c\x12\xc2\
+\xce\x10\x60\x27\x68\xcb\xa1\xbe\x78\x4d\xcb\x3d\x11\x80\xfc\xcf\
+\x77\x0d\x32\x81\xd3\x84\x10\x21\x9e\x00\xc6\x3a\x89\x14\x7d\x83\
+\xb6\x3e\xff\xaf\xa8\x28\x14\x7c\x00\x71\x79\xd2\x43\x08\x34\x89\
+\x52\x52\x18\xb0\x29\xfe\xe7\xa0\xad\xe5\x50\xaf\x28\x01\x15\xaf\
+\x05\x49\x26\xf2\x08\x01\x52\x35\x31\xe5\x3f\x75\xbe\xfb\xe3\x27\
+\x45\xa9\x70\x03\xc8\x54\x1e\xf1\x4d\xcd\x82\x6f\x7a\xce\x01\x12\
+\xeb\x18\xf9\xe9\xb3\x06\xac\x15\x64\x00\x39\xc8\x2b\xed\xea\x35\
+\x25\x2e\x4f\xad\xeb\x43\x6c\x17\xdc\x1a\xa0\x83\x3c\x78\x6a\x5c\
+\x4a\x3b\xc6\xa0\xcd\xa2\xb4\x0a\x04\x3d\xe5\x11\x4a\x20\x5a\x30\
+\x01\x04\xb9\x3c\xd5\x51\x5e\x50\x52\x10\x53\x00\xe5\xed\xfa\xcb\
+\xf3\xa3\x01\x0b\xe6\xfd\x22\x68\x94\xbc\x02\x3f\x22\xe6\x75\x00\
+\x86\xca\xc7\x19\xcc\xdb\x00\x4c\x90\xe7\x73\x80\x74\xe4\xe5\x1a\
+\x60\x86\x3c\x63\xfc\xea\x57\x94\xb6\xe5\xdd\x08\x30\x49\x7e\x94\
+\x32\xb6\x87\xba\xf7\x04\xf2\x2a\x80\xb8\x3c\x98\x21\xef\xa5\x5b\
+\x0f\x8e\x61\x3f\x6f\x02\x60\xc3\x9d\x9e\xb8\x3c\x31\x4d\x1e\xc9\
+\x8b\x35\x00\xe5\xa5\x70\xa4\xd7\x6c\x79\x64\xd5\x03\x58\x4d\x79\
+\x64\x55\x03\x58\x6d\x79\x64\xd5\x02\x60\x7d\x1d\x9e\xc0\xe0\x50\
+\x6f\x6c\xec\x46\x93\x74\xc7\x0f\xc4\x6e\x05\xeb\xda\x6a\x70\x6c\
+\x69\x04\x6b\x5d\x8d\x78\x97\x16\x8d\x7c\x39\x97\x5f\xbb\xb2\x7c\
+\x84\xcb\x3b\x93\xc8\x23\xab\x12\x80\xef\xd5\xa7\x9b\x88\x3f\xfc\
+\x93\xec\x0f\x26\xbc\xf2\xb6\x06\x37\x94\xed\x7b\x1c\x6c\x8d\xeb\
+\x44\xc5\x18\x79\xc4\xf4\xbb\xc1\x9b\x2f\xec\xdd\xc0\xa6\x67\x7f\
+\x66\x91\x88\xf2\x44\x26\x11\x32\x1f\x11\xa1\xbe\xcb\x00\xd1\x18\
+\xd8\xef\xaf\x57\xc4\x8d\x90\x47\x4c\x0d\x00\xe5\xe5\xb9\xb9\x5e\
+\x60\x72\xbd\x28\xa5\x24\x7a\xed\x06\xf8\x7d\xb7\xc0\x57\x55\xc9\
+\xc7\x2a\xd1\x5d\x1e\x31\x2d\x00\xe5\xca\xfb\xe7\x7a\xb8\xbc\x47\
+\x94\xd2\x82\x4c\x4e\x03\x91\x19\x94\xb5\x6c\x48\x43\x9e\x71\x79\
+\x48\x5b\x1e\x31\xe5\x20\xa4\xca\x33\x39\x33\x79\x95\xb2\x0b\x03\
+\x50\x1b\x0c\x88\x5e\x62\xb2\x91\x47\x0c\x1f\x01\xb9\xca\xab\x48\
+\x7c\x24\x14\x3f\xb8\x4d\xf4\xb4\xa0\xbc\xc5\x61\xdf\x6d\xdf\x7c\
+\xe0\xba\x28\xa5\x8d\xa1\x23\x40\x2f\x79\x24\x3a\xe6\x83\xd8\xf8\
+\xa4\xe8\xdd\x45\x95\x27\xcd\xfb\x33\x96\x47\x0c\x0b\x40\x4f\x79\
+\x95\xf0\xc0\x35\xd1\x8a\x93\xab\x3c\x62\xc8\x14\x40\x79\x3e\x68\
+\x7b\x6c\x9e\x5a\x8f\x6d\x5d\x0d\xd0\x92\x62\x90\x43\x61\x5e\x92\
+\xc4\x3b\xb2\x83\x96\x39\xa1\xa8\x75\xa3\xd2\xd6\x43\x1e\xd1\xfd\
+\x20\x14\x3a\x7d\xac\x89\xc4\x58\x2f\x3f\xc4\x78\x80\x2e\x1a\x60\
+\x92\xcc\xaf\xe0\x28\x04\x7a\xfb\x94\xed\x2d\x1b\x1c\x5b\x9b\xc1\
+\xf5\xf2\x7e\x6c\x8e\x50\xbb\xcd\x9b\xab\x3c\xa2\xeb\x08\x60\x97\
+\x3a\x3c\x64\x4d\x79\x8f\xa5\x72\x4d\x23\xee\xdb\x1a\x28\x01\x6b\
+\x4d\xa5\xb2\x90\xf1\xaf\x43\xe4\x2a\xff\xec\x3c\x94\x4c\x70\x6c\
+\xf4\x80\xa3\xa5\x69\x84\x4a\x92\x97\x6c\x79\x36\x67\x79\x44\xb7\
+\x00\x50\x5e\xa2\x96\x1e\x42\x09\x1f\xfe\xa9\xb1\xad\xbb\x8f\x9f\
+\xf9\x9b\x20\x74\x71\x48\x39\xed\xa5\x8b\x73\xd7\xf6\x11\x7b\x4d\
+\x85\x97\x6c\x3b\xac\x8b\x3c\xa2\xcb\x22\xb8\x20\x4f\x60\x45\x79\
+\x95\xff\x1c\x0e\x98\x7c\x6a\x17\x30\x9b\x55\x54\x52\x43\x4b\x9d\
+\xa3\xce\x4d\xeb\x75\x95\x47\x72\x0e\x20\x1b\x79\xf5\xc6\x26\x5a\
+\xe5\x82\x68\xfb\x43\xa2\x9a\x1c\x42\xe9\x75\x66\x75\x3c\x41\x76\
+\xbc\xa4\xab\x3c\x92\xd3\x14\xc8\x45\x1e\xa9\xc2\xb3\x7d\x6b\x33\
+\x44\x86\xae\x83\x7c\x3b\x5e\x5b\x0a\xca\x93\xd2\x32\xaf\xfb\xab\
+\xae\x51\x51\xd2\x95\xac\x03\xd0\x43\xbe\x01\xcf\xf6\x7c\xad\xc4\
+\x6d\x72\xfe\xaf\x41\xa5\xbe\x18\x55\xbe\xf6\xeb\xee\x11\x51\xd2\
+\x9d\xac\xa6\x80\x6e\xf2\x02\x5c\x10\x89\xc3\x2e\x7a\x71\x18\xbf\
+\x2b\xb6\xd8\xac\xaf\x19\x29\x8f\x64\x1c\x80\xde\xf2\x0a\x16\xaa\
+\xec\x0c\x2a\x28\x8f\xaf\xb1\x70\xf8\xf3\xf1\x7d\x0f\x6f\x51\x8a\
+\x06\x91\x51\x00\xc1\x9c\xe5\x9d\xcb\xe5\x05\x7c\x95\x57\x5e\x55\
+\x79\x9c\x19\xfc\x6f\x37\x01\x7a\xc6\xc8\x10\xd2\x0e\x00\xe5\xed\
+\x39\xcb\x57\x28\xed\x44\xc8\xe1\xc8\x12\x79\x15\x63\x43\x48\x2b\
+\x00\xa3\xe5\x41\x96\x21\x3a\x3e\x99\x40\x5e\xc5\xb8\x10\x56\x0c\
+\xc0\x70\x79\xce\xfc\xc5\xab\x12\x0b\x84\x58\x62\x79\x15\x63\x42\
+\x48\x19\x80\x19\xf2\xb1\xa9\xdb\xb1\xd9\xef\xcf\x60\x33\x8d\x2d\
+\x59\xff\x10\x92\x06\x60\x96\xfc\xf4\xa7\xdf\x02\xf3\x87\x32\x38\
+\x8f\xe8\x1b\x42\xc2\x00\xcc\x90\x67\x0c\x46\x66\xbe\xe8\x3a\xce\
+\x66\xfd\xe9\xdd\x0c\x68\xd0\x2f\x84\x65\x01\x98\x25\x1f\x91\x25\
+\x6f\xed\xf1\x93\x47\xf8\xca\xff\x81\x28\x67\x88\x3e\x21\xf0\x75\
+\xe7\x2e\x66\xca\x3b\x17\xdd\xd5\x8d\xef\x7b\xec\x7d\xfe\x41\xde\
+\x12\xdd\x0c\x61\x3e\x06\x72\x7b\x5d\xd7\xb9\x01\x51\xc8\x88\x85\
+\x00\xe4\xa1\x93\xf5\xb7\xef\x04\x7a\x83\xe1\xd8\x86\x68\x4c\xe2\
+\x87\x33\x02\xc5\x0e\x1b\x94\x3b\x8b\xc0\xca\x4f\x6a\x89\xd0\x43\
+\x5e\x65\xa5\x10\xf8\xf7\xbe\x0b\x84\x2c\x7f\x2a\xca\xa1\x32\xf8\
+\xdc\x3f\x9e\xed\x16\xdd\x8c\x50\x02\xe8\xeb\xfc\xc8\x63\xb5\x5a\
+\x7b\xa2\x31\x79\xd9\x95\x27\x7c\x38\x54\x96\x15\x83\xbb\xaa\x1c\
+\xec\xd6\xbb\x6b\x95\x9e\xf2\x2a\xa9\x42\x90\x18\xdd\x54\xdf\xfd\
+\xcb\x90\xe8\xea\x06\x3d\xfd\xe5\x7b\x25\x32\x23\xa7\x12\xc9\x23\
+\x8c\x7f\xf2\xa9\xd9\x20\x5c\x19\x9b\x80\x99\xb9\x90\x52\xcb\x46\
+\x9e\xda\xe8\xee\x54\xf2\x48\x5d\xd7\xaf\x6f\x67\xbf\x26\x64\x07\
+\xad\xa8\xb0\x1f\xe5\x57\xb9\x45\xf4\x93\x22\xc9\x0c\x46\x6f\x4e\
+\xc3\xf0\x8d\xa9\xac\xe4\xe9\xc6\x03\x9a\xdf\xd4\x48\x86\xd9\x21\
+\x50\x7e\xfa\x7e\x4e\xb4\x15\x94\x2b\x3e\x33\x07\x81\xe0\xbc\xa8\
+\x68\xb9\x13\x98\x57\xa6\x85\x11\xf2\x2a\x66\x86\x40\xb9\x8c\xe6\
+\xf7\x6c\x06\x86\xc7\xe1\x5c\xff\x00\xf4\xfc\x76\x11\x7e\xef\x1f\
+\x4c\x1a\x04\xae\x09\x2b\x30\x9c\x8d\xbc\x8a\x59\x21\x50\x7e\x95\
+\x16\x76\x02\x24\xcc\xef\xca\x54\x6e\xcd\xcc\xc2\xd9\x3f\x2e\x2b\
+\x23\x62\x31\x38\x4a\x70\x1d\x48\xc1\x30\xb1\x52\x6f\xb6\xf2\x2a\
+\x66\x84\xc0\xf7\x37\xa6\x79\xd6\x56\x53\xad\xbd\x5f\x8f\xf1\x2d\
+\xf1\xfc\x85\xa1\x65\x23\x61\x9a\x2f\x88\xb1\xc4\xcf\xf5\x75\x91\
+\x57\x31\x3a\x04\x9c\x02\x3d\xa2\xad\xe0\xae\xa9\x84\x0a\x57\xa9\
+\xe8\xc5\xc1\x10\xfe\xbe\xa2\xfd\xa9\x33\x8e\x82\xd9\xe5\xd3\x43\
+\x57\x79\x15\x0c\x61\xe2\x66\x40\xfb\x83\x41\x9d\xa0\x16\xb0\x9c\
+\x10\x6d\x05\xbe\xbe\x41\x5b\x6b\x33\x14\x17\x69\x9f\xd1\x4d\xf1\
+\xe9\xb0\x74\x14\x84\xc2\x51\xd1\x52\x30\x44\x5e\x65\x47\x7f\xbf\
+\xe6\x1f\xd3\x0b\xba\x7d\xff\xeb\xe7\xf9\xd5\xd4\x9c\xa2\x8a\x1c\
+\x76\x78\x74\x67\xcb\xb2\x91\x30\xaf\x15\x56\xb6\x46\x84\x01\x33\
+\x54\xde\x48\x94\x33\x2e\x25\xec\x08\x7f\x99\xc6\xb6\x0a\x86\xf0\
+\x48\x5b\x8b\x32\x1a\xd6\xbb\xab\xa1\xb9\xd1\x0d\x95\x4b\x02\xb1\
+\xf1\x93\x21\xca\x53\xab\xa5\x20\xe5\x91\x85\x1d\xa0\xef\x87\x63\
+\xed\x8c\x00\x8e\x84\xa2\x78\x65\x65\x9a\xeb\xaa\x86\x5d\xe5\xce\
+\x82\x95\x47\x16\xee\x72\x76\x3c\x73\xf4\x0c\x61\xb0\x97\x37\x35\
+\x23\x21\x19\x76\x9b\x65\xd8\x65\x2f\x6c\x79\x44\x73\x9b\xa7\x84\
+\x00\xf2\x03\x4b\xd7\x84\xa5\xf0\xaf\x5f\x89\x46\xa3\xed\xb4\xb5\
+\xb0\xe5\x11\xcd\x21\x68\x31\x7f\x76\x7e\xb2\x53\x02\xe9\x15\x2e\
+\xeb\xe5\x6f\x6b\xe2\xbb\x03\x6f\xb2\x41\x1e\xd9\x37\x33\x33\x91\
+\x63\x7b\x5e\x7c\x27\xf5\x7f\xdb\x2a\x08\x00\xfe\x07\x67\xd1\x50\
+\x78\x73\x48\xdf\xa1\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\
+\x82\
+\x00\x00\x12\x94\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3\x3e\x61\xcb\
+\x00\x00\x00\x01\x73\x52\x47\x42\x00\xae\xce\x1c\xe9\x00\x00\x00\
+\x04\x67\x41\x4d\x41\x00\x00\xb1\x8f\x0b\xfc\x61\x05\x00\x00\x00\
+\x09\x70\x48\x59\x73\x00\x00\x12\x73\x00\x00\x12\x73\x01\x8c\x22\
+\xb9\x07\x00\x00\x12\x29\x49\x44\x41\x54\x78\x5e\xed\x9d\x0b\x7c\
+\x14\x45\x9e\xc7\xab\x67\x7a\x66\x92\x4c\xde\x6f\x86\xf0\x0c\x04\
+\x79\x0a\x11\xe4\x21\xc8\x43\x5e\xc2\x82\xba\x80\xe0\xb2\xa2\xa7\
+\xe2\xde\xae\x77\xab\xa7\xa2\xb2\xee\xde\x80\xae\xae\x72\x28\x7e\
+\x4e\x94\x45\x56\x3e\xec\x67\x17\x4e\x11\xbc\x8f\x08\x08\xac\x3c\
+\x22\x1e\x2f\x21\x21\x80\x0b\x84\x04\x13\x20\x24\x64\x48\x42\x26\
+\x93\xd7\x64\x1e\x57\xff\xee\xea\x99\xee\x9e\xee\x49\x80\xee\x88\
+\x4c\x7d\xc3\xbf\xab\xea\x5f\x55\x3d\xa1\x7f\xff\xaa\xae\xee\xe9\
+\x99\x20\x0a\x85\x42\xa1\x50\x28\x14\x0a\x85\x42\xa1\x50\x28\x14\
+\x0a\x85\x42\xa1\x50\x28\x14\x0a\x85\x72\x9b\xc2\x90\x54\x13\xe6\
+\x6c\xdc\x68\x4c\xfa\xb6\x60\xdc\x85\x8a\x8a\x2c\xe2\x0a\x8b\xc5\
+\x6c\xb8\xf4\xc5\xfa\xfa\x7d\x08\x7d\xe6\x25\x2e\x45\x5e\xb1\xbf\
+\x99\x73\xf2\x6c\xc9\x48\xaf\x57\xda\x2c\x31\x3e\x1e\x1d\xcd\xdb\
+\xfe\x49\x71\x71\x71\x0b\x71\x29\xf2\xfc\x2b\xf6\x9c\xb3\xa5\x97\
+\x42\xfa\xa7\x24\x26\xa2\xc3\x7b\xcf\xe0\xfe\x3b\xc2\xf6\x7f\xe6\
+\x79\x7b\x4e\xe9\xe5\xd0\xfe\x69\x29\x29\xe8\x60\xe9\xf7\x9f\x14\
+\xef\x08\xdf\x1f\xf5\xea\x65\x79\x70\xe4\xc4\x79\xcd\xcd\xcd\xc4\
+\xa1\x8e\xd1\x68\x44\xdd\x6d\x59\x07\x3f\x78\x77\x69\x11\x71\xe9\
+\x8a\xa6\x01\xd0\x6f\xe8\xe8\xad\xa7\x4b\xca\xa7\x33\x4c\x7b\x77\
+\xeb\x47\x49\x71\x31\xa7\xaa\xbb\xa7\x0e\x41\x79\x79\x1e\xe2\x94\
+\x30\x6c\xdc\xd4\xc7\x4e\x17\xfd\xb0\xae\xb1\xb9\x95\x78\xc4\xf8\
+\x91\x89\x31\x54\x75\xe9\xd6\x75\x54\x71\xfe\xde\x12\xe2\x94\xd0\
+\x73\xe0\x88\xc7\x2a\x1c\x35\xeb\x5a\xdc\x4a\xbb\xf7\xa3\x18\xb3\
+\xa9\x2a\xbb\x4f\x8f\xe1\x85\x79\x3b\x4b\x89\x53\x82\xed\x8e\xdc\
+\xc7\x6a\x6b\x5d\xeb\x5a\x5a\x95\xfb\xc7\x5b\xa3\xaa\xc6\x8e\xba\
+\x77\xf8\x17\x9f\xae\x56\xec\x6f\xb1\x74\xc9\xf6\x44\x1b\x0e\xf8\
+\x0d\x86\xf4\xf6\x1e\x6e\x8b\x89\x45\x49\x49\xb1\x8f\x5f\x3e\x93\
+\xff\x57\xe2\xd2\x0d\x23\x49\x6f\x9a\x5f\x2f\x5e\x3a\x76\xc7\xae\
+\xbc\x37\x91\xd9\x82\x90\x01\xef\xb6\x9d\xd6\xd4\xea\x4d\xbf\x33\
+\x36\xce\x75\xa5\xbc\xec\x00\xd9\x95\x04\x53\x4c\xea\xae\xab\xae\
+\x66\xab\x52\x5f\x30\x9f\xd1\x68\x8d\x36\xa2\x4e\xce\xea\xcb\x9f\
+\x91\x2e\x12\x58\x6b\xea\x2e\xa7\xdb\xa3\xda\xdf\x83\x0c\x56\x9f\
+\xab\xc1\xd4\x50\x57\xb5\x9d\x74\x91\x60\xc2\xfd\x5d\xad\x3e\xd5\
+\xfe\x6e\x1f\xb2\x7a\x5d\x75\xa6\x1a\xc7\x25\xc5\xfe\xe6\xe4\xf4\
+\xd5\xad\x26\xcb\xdd\x4a\x7d\xd5\xcc\x83\x03\xc5\xe4\x67\x46\x35\
+\xd5\x55\x2d\x27\xbb\xd1\x0d\x03\x49\x6f\x9a\xe2\xf3\x17\xd2\x99\
+\x1b\xd8\x1d\xcc\x16\xd7\x6a\xea\x1a\x48\x31\x84\xa6\x96\xe6\x46\
+\x92\x55\xa5\xbe\xb1\x49\x71\xf6\x00\x2c\x16\x73\x32\xc9\xaa\x12\
+\x15\x15\xad\xda\xc6\x6c\x36\xb5\xd9\x3f\x3a\x26\x4a\xb5\x8d\xb7\
+\x15\x9f\x36\xfc\x7e\x52\x6a\x3f\xcd\x1e\x1f\x9e\x31\xf4\x47\xb3\
+\x53\xc0\xa4\xb9\x4f\xce\xd9\xbd\x73\xcf\x46\xbf\xd9\x4c\x3c\x3c\
+\xe1\x5e\xc0\x8f\x0f\x4c\xac\xc1\x7b\x71\xd7\xaa\xf9\x4f\x8e\xc8\
+\x8e\xaf\x25\x6e\x09\xf3\x5e\xfd\x72\xd4\xe6\xff\xbb\xf0\xae\xd7\
+\x64\x32\x32\xb2\xbd\x41\x7f\x2b\xeb\x77\xbf\xfe\xab\x09\x0b\x9f\
+\x7b\xa8\xf7\x3f\x89\x5b\xc2\x82\xe5\x05\xbf\xd9\xb0\xf5\xc0\x02\
+\x9f\x4a\xff\x78\xb3\xc1\xfd\x5f\xcf\x4d\x5f\xb8\x70\x72\x27\xc5\
+\xfe\xf3\xdf\x3a\xf2\x9b\x4f\x77\x7c\xa7\xda\x3f\x39\x8a\x75\xaf\
+\x7d\x75\xc2\xcf\x66\x8e\xec\xae\xf8\xfb\xbf\xf4\x97\xe3\xa3\xde\
+\xff\xf4\xd0\xbb\x2d\x7e\x83\x31\xdc\xa9\x51\x1e\x22\xd1\x2c\x8b\
+\x1a\x2f\x7f\x1f\xee\xf0\x69\x82\x66\x2f\xa0\x14\x00\xfd\x92\x8d\
+\xab\x9f\x9b\x3b\xd8\x44\x8a\x21\x18\x8c\x26\x34\x63\x7c\x7f\x47\
+\x5a\xbc\x21\xec\x28\xdf\x7f\xd2\x91\x76\xf6\xdc\xc5\x18\x52\x0c\
+\x62\x60\xd0\xc4\x11\x7d\x1c\xdd\x33\x63\xc2\xf6\xcf\x2b\xac\x4c\
+\x3b\x57\x72\x59\xb1\xff\xe4\x51\x7d\x1c\x5d\xd3\xc3\xf7\xdf\x7b\
+\xbc\x32\xad\xe4\xbc\x52\x7f\x23\x9a\x32\xba\x8f\xa3\x4b\x6a\x54\
+\xd8\xfe\xc7\x4a\x5c\x69\x05\x85\xe7\x70\x7f\xf5\x99\x60\xd1\xc7\
+\xc7\x06\xd5\xb9\xd1\x50\x52\xbc\x3d\x02\xe0\xfe\x9c\xf8\xc5\xdb\
+\x3e\x98\x2b\x9d\x12\x28\x8a\x64\x3e\xb0\x76\x4c\x55\xa3\x77\x22\
+\x29\x76\x58\x00\x68\xb6\x06\xa0\xfc\x34\xa1\x01\x10\xe1\xd0\x00\
+\x88\x70\x68\x00\x44\x38\x34\x00\x22\x1c\x1a\x00\x11\x8e\x66\x01\
+\xd0\xb3\x8b\xcd\x8d\x90\x8f\x94\x30\x3e\x1f\x8a\x4a\x48\x20\x05\
+\x4a\x5b\xc4\x59\xa3\xb9\xbb\xa2\x02\x31\x16\x13\x3e\x9e\xfa\xa3\
+\x59\x00\xac\x5e\xfe\xfa\x17\xbd\x7b\x66\x9d\x66\xb0\xf0\x8c\xdf\
+\x8f\x58\xaf\xe7\xf4\xb2\x67\x27\x1f\x21\xd5\x94\x36\x58\x30\x73\
+\xe8\xe7\x26\x5f\xab\x9b\x41\xf8\xd8\xe1\x81\x94\x14\x1f\xfd\x16\
+\xa9\xd2\x15\x4d\x6f\x34\x7c\xb8\x7e\x7d\xd2\xdf\x3e\xde\x70\x9f\
+\xdb\xd5\x84\x32\x7b\xf5\xd9\xbd\xf5\xe5\xec\x6c\xec\x9e\xc6\xd7\
+\x52\xda\x60\xfb\xb0\x67\xf6\xd6\xa4\xa7\xc6\xcf\xba\x78\xe1\xca\
+\xee\x93\xf9\x7b\xf2\x89\x5f\x57\x74\xbd\xd3\xe4\x2f\x5c\x0e\xb7\
+\x36\x69\x00\xb4\x8f\xed\xcc\x9d\x2f\x1e\x25\xf9\x0e\x83\x2e\x02\
+\x23\x1c\x1a\x00\x11\x0e\x0d\x80\x08\x87\x06\x40\x84\xa3\x79\x00\
+\xd8\xed\xf6\x28\xfb\x8a\x15\x89\xa4\x48\xb9\x4e\xec\xcb\x56\x66\
+\x92\x6c\x87\xa0\xe9\x55\xc0\xe4\x07\x1e\x7e\xe1\xdb\x83\xf9\xcf\
+\x5a\x4c\xa6\x78\xe4\x67\x5e\xaf\xf9\xea\x89\x3c\xec\xa6\x57\x01\
+\xed\xa0\xcc\xd1\xf0\x75\xee\x13\x1b\x5f\x36\x9b\x8c\x33\x5b\x5b\
+\x3d\xa7\x6c\xb6\x4e\xbf\x38\x79\x68\xf7\x49\x52\xad\x1b\x46\x92\
+\xde\x34\xbf\x7f\xfb\xbd\xde\xff\xf3\xd9\x96\x2f\x9b\x91\x31\xa1\
+\xd9\xe7\x8f\x6a\x71\xbb\x27\xb7\xb2\x09\xa7\x26\x0c\x4a\x89\x26\
+\x4d\x28\x61\x98\xbd\x64\xff\xec\x33\x97\xaa\x1f\x70\xb9\xbd\xa8\
+\xc9\xe3\x4f\xf7\xb6\x34\x8f\x6c\xbc\x56\xb5\x9a\x54\xeb\x86\x66\
+\xa7\x80\xa3\xf9\x27\x07\xbb\x5b\x82\x8f\x6e\xfb\x59\x13\x2a\x38\
+\x58\x68\x25\x45\x4a\x1b\x9c\x2a\x2a\xb3\x8a\x1f\x18\x6b\x74\xfb\
+\x06\x93\xac\xae\x68\x16\x00\xfc\x47\x26\xe4\x67\x14\xd1\x7b\x03\
+\x94\x5b\x12\x7a\x15\x10\xe1\xd0\x00\x88\x70\x68\x00\x44\x38\x9a\
+\x05\x40\x82\x35\xae\xd1\x2f\x3e\xe7\xc3\x5b\xc2\xd1\xf4\x02\xa0\
+\xbd\x44\x59\xcc\x78\x09\x15\x5c\x43\x45\x5b\x54\x3f\x4e\xa1\x29\
+\x9a\x05\xc0\xa6\xb5\xef\x6d\x33\x1b\xd8\xe3\x20\x3c\x58\x9c\x85\
+\x69\xfc\xd3\xb3\xf7\x29\x7e\xde\x8f\x12\xca\xcc\x31\x7d\xf7\x98\
+\x84\xa5\xb4\xcf\x87\xdc\x0d\x8d\x7f\xe2\x0a\x3a\xa3\xd9\x7d\x00\
+\x20\x39\xb6\xd3\xfa\x2e\x5d\x32\x2c\xbe\x56\xef\x41\x5b\x66\xea\
+\xbc\x25\x8f\x0e\x80\x29\xa0\x37\x5f\x4b\x09\xc7\xfd\xc3\x6d\x3b\
+\xf7\x9e\x6a\xdd\x7c\xa1\xac\xbc\xaa\x6f\x76\xd7\xbf\x5f\x3a\x77\
+\xec\x6d\x52\xa5\x2b\xf4\x79\x80\x5b\x07\xfa\x3c\x00\xa5\xe3\xa1\
+\x01\x10\xe1\xd0\x00\x88\x70\x68\x00\x44\x38\x9a\x07\xc0\x6f\x17\
+\xbf\x91\x31\xef\xb7\x8b\x33\x48\x91\x72\x9d\x2c\xf8\xf7\x17\xb3\
+\xed\xf6\x95\xb1\xa4\xa8\x3b\x9a\x5e\x05\xe4\x8e\x9e\x6c\x3f\x73\
+\xf6\xfc\x4b\x3e\xbf\x0f\x21\x8f\x6f\x59\x53\xde\xbf\x6d\xc3\x6e\
+\x7a\x15\xd0\x0e\x4e\xfc\x50\xbd\x6f\xc4\x53\x9f\x2e\x61\x59\x76\
+\x3c\xcb\x1a\xaf\x5a\xac\x51\xf7\x57\x9e\x2d\xd0\xfd\xaa\x40\xb3\
+\xfb\x00\xcf\xdb\x97\xdf\xf1\xe5\xf6\x9d\x9b\xdc\x06\xd6\xe4\x65\
+\x8c\x26\xaf\xdf\x3f\xae\xd6\x6d\x3e\x3d\xf5\xae\x4c\x0b\x69\x42\
+\x09\xc3\x2c\xfb\xbe\x39\xa5\x35\x0d\x53\xdc\x7e\x06\x35\x7b\xfd\
+\x31\xac\xdf\x37\xb2\xd9\xe9\x58\x45\xaa\x75\x43\xb3\x53\xc0\xc9\
+\x33\xa7\x07\x7a\xbd\xa2\x77\xb4\x59\x13\x3a\x57\x78\x26\x8a\x94\
+\x28\x6d\x50\x5c\x56\x19\x05\x37\x51\x05\xdc\x5e\x66\x20\xc9\xea\
+\x0a\x5d\x04\x46\x38\x34\x00\x22\x1c\x1a\x00\x11\x8e\x66\x57\x01\
+\xf4\x5b\xc2\x82\xbc\x74\x20\x76\xe9\x5e\xe7\x48\x64\x60\x94\xbf\
+\x16\x0e\xce\xf5\xdc\x47\xc1\xb9\x77\x4e\xe1\x2d\x74\x3f\xf7\x13\
+\x94\x43\x9c\xe7\xf1\xb9\xae\xa2\x77\xe6\xe4\x4c\x1b\x77\x67\x8f\
+\xaf\x88\x4b\x13\x34\x9b\x01\x12\x12\x62\xea\x25\xcf\x03\xf8\x7c\
+\xc8\x6c\x8d\xcc\x67\x42\x0d\x06\x06\x59\x53\x33\xb0\x65\x2a\x5a\
+\x6c\x1a\xa4\xb8\x1e\xd2\x74\x1b\xb6\xce\x28\x36\x3d\x0b\x1b\xa4\
+\xf2\x3c\xb6\x8c\x2c\x64\xb1\xc6\x69\xfb\xd6\x2d\x41\xb3\x00\xd8\
+\xf4\xd1\xfb\x3b\x2c\x26\xd3\x61\x78\x2f\x1b\xa2\x3a\x31\xc6\xe4\
+\x5c\xb9\x68\xfc\x37\xa4\x3a\xa2\x20\x8f\x44\x40\x8e\x2b\x87\x22\
+\xf2\xab\x35\x91\x21\xbe\x42\xd0\x12\x4d\xd7\x00\x19\x31\xad\xe3\
+\xee\xec\x9f\xf3\x9a\x2d\x35\xf5\xb5\x9e\x39\xb6\xae\x9d\xd3\xac\
+\x1d\xf2\x2d\x17\xb7\x24\x20\x18\xbe\xa6\xe7\xd3\x30\x06\x70\x79\
+\xbc\x09\x98\xe0\x13\x99\x4e\x68\x1a\x00\x65\x65\x65\xcd\x05\x79\
+\xdb\xec\xe5\xa7\x0f\xda\x8f\x7d\xfd\x75\x1d\x71\x47\x24\x41\xed\
+\xf8\xb3\xbb\xd4\x18\xac\xb3\xdc\x0f\xdf\x0d\x22\x98\xd8\x1f\x34\
+\x3d\xa0\x57\x01\x3a\xc0\x89\x15\x58\xc3\x49\x17\x73\x01\x24\x5f\
+\x1c\xad\x26\xb1\x5e\xb2\x07\xa1\x01\xf0\x63\x10\x38\xa1\x0b\x29\
+\x04\x03\x98\x5c\x70\x95\xe0\xd1\x10\x1a\x00\x3a\xa0\x76\x1a\xe7\
+\xa7\x7d\xfc\x83\x47\x3f\xef\x93\x4f\xf7\x42\x19\xff\x40\x5b\xa1\
+\x3d\x97\xea\x03\x0d\x80\x8e\x44\x32\xed\x87\x03\xb7\x83\xb6\x5c\
+\x7b\x21\xd5\x07\xcd\x03\xe0\x67\x8f\x3e\xdd\xf5\x17\x0b\xff\xa3\
+\x43\xde\xc8\xb8\x55\xe1\x46\xab\xea\x90\x05\x31\xe5\x95\x6d\x8f\
+\x6f\x98\x55\xa4\x7f\xb2\x4a\x1b\x34\x0d\x80\x1e\x03\x86\x2f\xdb\
+\xb9\x75\xe7\xb9\xcf\xff\x77\xcb\x09\x5b\xf6\x90\x0d\xc4\x1d\x71\
+\x08\x12\x83\x68\x21\x06\xb7\x49\xf0\xe5\x21\x5f\x26\xd3\x3b\x94\
+\x7d\x90\x8a\xda\xc9\x8d\xdb\xb3\xf6\x68\x16\x00\xff\xba\xd8\x3e\
+\xe0\x42\xf9\x95\x45\x1e\x53\x94\xb9\xc5\xc0\xa2\x8a\x5a\xe7\x23\
+\x4f\xaf\x38\x3c\x96\x54\x47\x14\x20\x16\x88\xa6\x88\x64\x36\x87\
+\x82\x7e\xd3\x7b\x7b\xd0\x2c\x00\x4a\xce\x5f\xea\x0b\x91\x1c\x80\
+\x65\x51\x79\x71\x69\xc7\x7c\xbe\xe9\x16\x03\xb4\x67\x54\xde\x07\
+\x08\x10\x52\x2d\x0b\x04\x2e\x8a\xf8\x2c\xd0\xc6\xde\x6e\x18\xba\
+\x08\xd4\x89\x70\x37\x74\x38\xc3\x7a\x73\x29\x9e\x2a\x24\xe5\x40\
+\x3d\xf6\x73\x3e\xbe\x9e\xdf\x68\x0f\x0d\x80\x1f\x0d\xa2\xa8\xea\
+\x0a\x9f\x04\x10\x69\xa6\x93\xfe\x34\x00\xf4\x40\x2c\x9c\x40\x40\
+\xc8\x40\x06\x04\x0e\x38\xf9\x14\x3c\x24\x0f\x5b\x2e\x34\x60\x23\
+\x54\xeb\x00\x0d\x00\x3d\x10\xe9\x2a\xac\xf4\x85\x32\xe0\x83\x15\
+\x3f\x34\x82\x20\x80\x04\x46\x3b\x4e\x7d\x30\xe7\x63\xb8\x76\x78\
+\xc3\xa7\xdc\x3f\xce\xf4\x40\xb3\x00\x48\x4b\x4e\xaa\x95\x7c\x27\
+\x50\x04\xff\xbd\x00\x4e\xdc\x00\x20\xaa\x78\x9a\x67\xf0\xac\x1f\
+\xf4\xf1\x2d\xf9\x2d\xef\x11\xda\x92\x54\xd8\x95\x4e\x11\xa0\x59\
+\x00\x6c\x58\xb5\xfc\xeb\xc4\xf8\xd8\x3c\xe4\xf5\x20\xe4\xf5\xa2\
+\xcc\xc4\xd8\xda\x8f\x5e\x9e\xb8\x8f\x54\x47\x18\x82\x88\xea\x08\
+\x7a\x4a\x45\xe7\xfd\x82\x71\xe8\x78\x17\x10\xd0\xf4\x14\x30\xb0\
+\x47\xea\xc4\x7e\x7d\xb2\x67\x0f\xcf\x1d\xf4\x72\xb7\xc1\xd9\x9d\
+\x53\x12\x58\xd5\xbf\xe9\x7b\xbb\x23\x16\x52\x6a\xc1\xf9\x21\xb4\
+\x4e\x4a\xb8\x3a\xad\xd0\x34\x00\xf2\xf2\xf2\x3c\xdf\x1f\xd8\xb5\
+\xf9\xd0\x3f\x3e\x5f\x76\x68\xd3\xa6\x26\xe2\x8e\x3c\xb8\x93\xb7\
+\x1c\xc1\xc7\x8f\x68\x79\x0b\xe9\x69\x43\x20\xe8\x53\xaa\xd5\x02\
+\xba\x08\xd4\x91\xd0\xb5\x40\xb0\xcc\x5f\xe4\xf1\x6d\xe0\x47\xfe\
+\x87\xa9\x79\x44\x7d\x74\x8a\x00\x1a\x00\x3a\xc0\x3f\xe7\x0b\x90\
+\x6b\xf9\x80\xf1\x65\x1f\xde\x0a\x79\x5e\x64\xc8\xc3\x8f\xb8\xad\
+\xb8\x0f\xe4\xf4\x81\x06\x80\x5e\x84\x2a\x19\x30\x26\xe4\xb6\x1f\
+\x98\x92\x4f\x30\x21\x58\xb4\x87\x06\x80\x0e\x08\x62\x29\x89\x26\
+\xaf\xe3\x47\x3e\x2e\xc1\x3f\xc5\xb5\x83\xbe\xd0\x00\xd0\x09\xb1\
+\xd0\x62\x03\x84\x94\xbf\x6b\x42\x4e\x01\x5c\xc2\x8f\x74\x25\xf3\
+\xc1\x46\x07\xb4\x0d\x00\x63\xca\x84\x38\xdb\x1d\x0d\xa6\xe4\xec\
+\x86\x61\x63\xa7\xae\x24\xde\x08\x04\xd4\x6c\x9b\xf6\xb5\x6a\x7f\
+\xbb\x1b\x41\xb3\x00\x78\xf4\x99\x57\x52\x8c\x09\xf1\xbb\x5c\x1e\
+\x7f\x8c\x87\x65\x63\x8e\x9d\x3c\xfb\xcc\xd2\x8d\x65\xe3\x49\x75\
+\x44\xd1\xd6\xa2\x2d\xa4\x5e\x98\xfa\xe5\xee\xc0\x8f\x7e\x41\xa0\
+\x59\x00\x38\xae\x3a\x26\xf8\x7d\xfe\xc0\xa7\x97\xfc\xac\x19\x1d\
+\xc9\x3b\xa2\xc7\xa7\x99\x6e\x79\x0c\x44\x2d\x10\x4e\xc9\x40\x4e\
+\x3e\xcf\x8b\x1b\x78\x48\x14\xf7\xe3\xde\x3b\xe0\xea\x00\xd8\x11\
+\x59\x00\xe2\x36\x46\x96\x85\x9c\xa6\x68\x16\x58\xb7\xc3\x87\x43\
+\x1f\xd9\x1a\xb5\xb4\xce\x63\xc5\xc7\x9a\x3f\xfc\xb0\xe5\x0f\x10\
+\x39\x4c\xc2\xd1\x12\x6e\xcf\xe2\x06\x7c\x4b\x00\x7c\xf8\xa2\x0d\
+\x0f\xa9\x8a\xfa\x58\x64\xea\x7e\x0f\x0e\x04\xa1\x83\x14\x90\x58\
+\xb8\xee\xe7\x5f\x23\xf8\x4a\x8a\xe0\xfd\x38\x2f\xff\x80\x0c\x75\
+\x15\x25\x75\x4d\xee\x7a\x6e\xed\xc0\xbd\x30\xde\xc0\x6b\x08\xdd\
+\x49\x2a\xd4\x0b\xa3\x1b\xca\x5c\x1e\xff\x72\x2d\x2d\x8d\xe8\xd9\
+\xfb\x07\x96\xfc\xe1\xe1\xdc\xd9\x9c\x0b\x36\x5a\x70\xbb\x7c\x3a\
+\x78\xe8\x67\x7d\x97\x1a\x3a\x0f\xe5\x3e\xe0\xc9\x01\xd3\x33\x97\
+\x15\x1f\x2a\xe1\x88\x03\xb2\xa3\xcf\xa5\x90\xe3\x53\x9e\x60\xfb\
+\x60\xee\x7a\x91\xee\x51\x8a\x7c\xaf\xe2\x32\xc9\xe3\x40\xa9\x77\
+\x54\xa0\x09\x99\x0d\x25\xd3\x86\xa4\x8e\x9c\x96\x9b\xe3\x80\x5a\
+\xcd\x4e\x01\xb7\x0b\x47\xe7\x9c\xb6\xb7\x5e\x3c\x82\x57\xdd\x70\
+\xbb\x06\x8f\x1d\x6e\x36\x00\x83\x71\x24\x98\xb8\x2c\xe4\xc5\x69\
+\x70\x1a\xe7\x8d\x4c\xf1\xd8\x42\xeb\x78\x4f\xa8\x4f\x6e\xe2\x52\
+\xf0\x75\x78\x03\xc4\x3e\x40\x9c\x47\xc8\xe9\xb8\x8c\xc6\xa7\xbb\
+\x24\xe2\x03\x34\x00\x14\x28\x98\x7b\xd6\xee\xbe\xf0\x1d\xbc\xa3\
+\x2d\x22\x78\x30\xd5\xe1\xdb\xf0\x62\x05\x91\x96\xe5\x23\x15\x10\
+\x8f\xd6\x70\xc8\xdb\x8b\x09\xfa\xc4\x7b\x81\x7c\x7d\x75\x05\x1a\
+\x97\xe6\x2a\x9e\x7e\x57\x0f\x89\xf8\x00\x0d\x00\x15\x8e\xe3\x20\
+\x68\x85\x20\xc0\x47\x10\x0e\xa2\x78\x14\x87\x9a\x30\x3e\x85\x69\
+\x5a\xda\x56\x5e\xe6\xdb\xc3\x8f\xdc\x2f\x2e\xcb\x7f\xe4\xf5\xea\
+\x06\x08\x79\xd7\xd5\x4a\x34\x36\xb5\xbe\x78\xc6\xd0\x9e\xa3\xa6\
+\xe5\xda\x24\xe2\x03\x34\x00\xc2\x70\x7c\xde\x59\x7b\xcb\x85\xa3\
+\xc8\xab\x70\x17\x46\x7a\xd3\x2e\x74\x44\xf2\x92\x71\x19\x05\xa0\
+\x3d\x16\x53\xb1\x4e\xdc\x8f\x6f\xa7\xb4\xff\xf0\xf0\xaf\xde\x50\
+\x5d\x89\xc6\xa4\x39\xb1\xf8\xd9\x8a\xe2\x03\xfa\x06\x80\xf1\xa7\
+\x1f\x5f\x85\x73\xcf\xd8\x7d\x97\x8e\x21\xee\x2b\xf0\xe0\xa8\x12\
+\xe3\x24\x11\x95\xa5\x86\xc7\xaa\x70\x6f\x1f\xc0\x29\x27\xb6\xcc\
+\x94\xf6\xc1\x3d\x5a\x0f\x79\xa8\x95\xd5\xb5\x6d\x78\x03\xff\xf0\
+\x3e\x1a\xab\xaf\xa0\xd1\x29\xce\xe2\xc9\xfd\x6d\xf7\xa8\x89\x0f\
+\x70\xbf\x83\x16\x28\x5d\x05\x18\x91\xdf\x03\x4f\x37\x93\xa2\x0c\
+\x06\xc5\x44\x99\xd1\xb0\x3e\xc9\x1f\xfd\xe3\x9d\x19\xeb\x88\x33\
+\x84\x2d\xdf\x96\x26\xfd\x6e\x6d\xe1\x9a\x73\x17\xab\x6c\xf2\x7b\
+\xe5\x06\x1c\x60\xc3\xfa\x76\xfd\x6e\xfd\x92\x99\x4b\xba\x26\x36\
+\xd7\x12\xb7\x84\x2d\xfb\x8a\x93\x16\xad\x3d\xb1\xa6\xb4\xa2\x5a\
+\xd6\x9f\x41\x2c\xee\x3f\xa8\x67\xf2\xb6\x43\xab\x1e\x7a\x83\x38\
+\x43\xd8\xb2\xef\x6c\xd2\x0b\x1f\x9f\x5a\x13\x3f\xf3\xd5\x6e\x8c\
+\xed\xae\xe0\xd5\x41\x00\xd8\x67\x5b\x3e\xa5\x36\x04\xf8\x9d\x02\
+\x97\x8b\x61\xda\x05\xc0\x6d\x02\xcd\x14\x5e\x03\x27\x8d\x35\x95\
+\xe8\x9e\xd4\xfa\x73\x53\x06\x74\x1a\x3d\xeb\x9e\x5e\x55\x7c\xbd\
+\x32\x6d\xbd\x5a\xbb\x51\x0a\x80\x76\xe1\x6d\x45\x83\xfb\xf5\x99\
+\x5d\xb0\xff\xab\xcd\xc4\x23\x21\xbd\xc7\xc0\x3d\x8e\x46\xf7\x78\
+\xee\xff\xa7\x00\xfc\x07\x6c\x71\x31\x6f\x5d\x2a\x29\x58\xcc\x7b\
+\xa4\xc4\x75\xca\xd9\xe3\xf2\x32\xaa\x77\x24\x19\x2c\x40\x4e\x56\
+\xc6\x9b\x67\x0a\xf6\xbf\x4a\x5c\x12\xb2\xfa\x0c\x2b\x2a\xaf\x75\
+\x72\x7f\xf5\x24\xf7\x57\xef\x20\x5f\x66\x2e\x17\x38\xca\x04\x94\
+\xf9\x51\x80\x57\xe7\xa6\xfd\x76\x8a\x0f\x68\x36\x47\x27\xc4\xc2\
+\xf7\x1b\xab\xa8\x14\x06\x86\x35\xa3\x38\x96\x19\x47\x8a\x21\x44\
+\x5b\x63\x55\xc5\xe7\xc0\xa3\xa7\xd2\xe9\xca\x26\xa5\x10\x2c\x51\
+\x31\xe1\x6f\x47\x1b\x0c\xa8\xca\x71\x4d\xf5\xcf\xda\xd4\x37\xb5\
+\x04\xea\xf2\x57\xbf\x80\x8c\x95\xf9\xf8\x74\x20\xbe\x3c\x10\xff\
+\x72\x20\x7e\xdb\xc7\x40\x98\x14\xc3\xb7\x14\x6a\xe5\xa9\x9c\xe0\
+\xbe\x60\xc1\x37\x26\xd5\xd9\x6e\xf1\x01\xcd\x02\xa0\x7f\x56\xe2\
+\x66\xb3\x89\xad\x02\x41\xe0\xa9\xd7\xf6\x18\xde\x20\xd6\xef\x41\
+\x3e\x6b\xc2\x26\xb2\x9b\x10\xae\x55\xd7\xac\xe2\xd6\xbe\xb2\xbe\
+\x42\x7f\xe4\xf1\xa0\xec\x4e\xa9\x3b\x48\xf3\x10\x9c\x75\xd7\x70\
+\x7f\x8c\xac\x6f\xa0\x7f\x6b\x2b\xea\xd5\xbb\xb3\x6a\xff\xe4\xb8\
+\xe8\x1d\xe2\xd7\xcf\xff\xe8\x45\x64\xbc\x52\x80\x5f\x16\xee\x13\
+\xc0\x81\x17\x56\xe6\xbc\xac\xca\x2b\x75\xa1\x8e\x37\xbc\x33\x92\
+\x4a\xfd\xbc\xa9\xed\x07\xca\xa2\xf6\x78\x13\xf4\x33\x9c\xf8\xe3\
+\xd2\x60\xe4\xdb\xda\x2d\x3e\xc0\x1d\x1b\xad\xe8\x37\x62\x72\xaf\
+\x8a\x1f\x4a\xff\xd0\xe4\x67\xb2\x88\x2b\x2c\x71\xd1\x66\x94\x9e\
+\x92\xb8\xec\xfb\xfc\xfd\x3b\x89\x4b\x09\xa6\x73\xf7\x41\xaf\xd7\
+\x34\xb6\x8c\x84\xff\xb0\x18\x13\x9e\x8a\x3b\xa5\x25\x6c\x28\x3a\
+\x71\xe8\x63\xe2\x52\x82\x19\x90\x3b\x76\x5d\xc9\xa5\xca\x2c\x79\
+\x7f\xb3\x91\x45\xdd\xbb\xa4\x6d\x38\x71\x64\x5f\xd8\xfe\x7d\x87\
+\x8c\x5e\x57\x5a\xee\x90\xf4\x1f\xf4\xeb\x77\x27\xb8\xd3\x06\x23\
+\x96\xd5\xf7\xed\x0e\x90\x9c\xbb\x17\x05\xc1\xaa\x08\x83\x9c\xdc\
+\x1d\x3e\x57\xd1\xa4\x7e\x99\x63\xae\x47\x7c\x40\xd3\x00\x88\x34\
+\xee\xfe\xcf\x6d\x7e\x77\x7a\x47\x04\x81\x9a\x50\x82\xf8\x0d\x45\
+\x0f\x0d\xcb\x18\x33\x65\xf0\xf5\x89\x0f\xd0\x00\xb8\x49\xee\xb6\
+\xe3\x20\xc0\x33\x81\xd1\xa8\x16\x04\x62\xf9\x84\x39\x44\x7e\xd8\
+\xd5\x25\x56\x07\x8b\x7f\xb5\x1c\x4d\xb2\x35\x17\x3d\x70\x57\xfa\
+\x0d\x89\x0f\xd0\x00\xd0\x00\x08\x82\x96\x54\xb5\x99\x40\x4d\x5c\
+\xfe\x7c\xce\xd7\x88\xeb\x05\x7f\x38\x69\x60\xe4\x97\xa3\x29\x9d\
+\x9b\x8b\x66\xdc\x84\xf8\xc0\x4f\xff\x4e\xcd\x2d\xc0\x91\xa5\xd3\
+\x19\xb3\xe3\x38\x5e\x18\x2a\x7d\x0e\x46\x2e\x24\xbf\x94\x0b\x8a\
+\x0c\x06\x25\x01\xa1\xbd\xd8\x27\x06\x8b\x5f\x05\xe2\xb7\x14\x4d\
+\xea\x1b\x7b\xef\xcd\x88\x0f\xd0\x00\xd0\x88\xef\x5e\x9b\xce\x98\
+\x1c\x85\x38\x08\xbc\x9c\x74\xea\x26\x88\x2e\xf7\xf3\x41\x01\x06\
+\xf5\x21\xab\x7e\x62\x20\xfe\xd4\xac\xe6\x73\x43\x52\x3c\xe3\x7f\
+\x3e\x6a\xd0\x55\x3c\xe7\x18\xb0\x09\x51\x73\xdd\xd0\x00\xd0\x90\
+\xa3\x38\x08\x58\x12\x04\x6d\x23\xd6\x2c\x18\x14\x52\xa4\x6d\x9c\
+\x55\x97\xb1\xf8\x4d\xc5\xd6\x2b\x05\x53\x9f\x7e\x70\xcc\x35\xec\
+\x84\x47\x84\x40\x43\xe6\x46\x83\xe0\x86\x3a\x51\xc2\x93\xfb\xfb\
+\x6d\x7e\x4f\xc6\x10\xbc\x26\x50\x1b\x5f\x30\x96\xe1\xd0\xcb\x53\
+\x31\xbc\x8f\xdf\xf2\xd3\xfe\xd4\xce\x0d\xe7\x6b\x0f\x6f\x7e\xf0\
+\x93\x35\xef\x55\x62\x77\x2b\x31\x38\xef\x80\x41\x53\x30\xf8\x36\
+\x31\x2e\x6d\x0f\x74\x06\xd0\x81\xc2\x3f\x4e\xbf\x8f\x81\x9b\x45\
+\x5e\xe1\x66\x91\xdc\x78\x61\x83\xa9\x92\xf1\x75\x20\x3f\x77\xce\
+\xcf\xac\x2f\x2d\xdb\xb1\xe6\x11\x2c\xbe\x13\x3b\xe1\xbb\x97\x60\
+\xf4\xc3\xaa\x13\x22\x47\x88\xa2\xeb\x46\x1e\x76\x14\x8d\xc0\xca\
+\x4c\xe8\xf7\xbb\x6d\xbb\x51\x27\x3c\x13\xc8\xde\x3b\x00\xa5\xda\
+\x3e\xf0\xd0\xca\xc0\xad\xf6\x27\x65\x38\xcb\xce\x6f\xfb\x70\xfe\
+\xee\x2f\x37\x5e\xc1\x4e\x18\xed\xf0\x2d\xec\x30\xfa\x5b\x48\x0a\
+\x26\x3c\x12\x44\x67\x80\x5b\x01\x2c\xc2\x9e\x7f\xbe\x39\x7d\xb4\
+\xb7\x1c\xde\x4a\x96\x3c\x5a\xa4\x22\xbe\x58\x33\x5e\xfc\x3a\x2c\
+\xfe\x7d\xe9\x4e\x3c\xf2\x57\x3e\x82\xc5\x57\x9a\xf6\x03\xa2\x03\
+\xd7\x23\xbc\x00\x9d\x01\x74\x06\xcf\x04\x03\xbb\x2d\xda\x55\x10\
+\xdb\x6d\x80\xd1\x60\x68\x6b\xbc\x81\x7e\x20\x09\x5c\xe7\x57\xa0\
+\x89\x19\x75\xe7\xaf\x1d\xfc\xdb\xac\xcd\x7f\xfd\x0b\x5c\xea\x81\
+\xd8\xb0\xba\x04\x03\xf1\x85\xbc\x60\x7e\xbc\xb9\xee\x00\xa0\x33\
+\x80\xfe\xd4\x0d\x36\x5f\x5e\x5c\x5f\x7a\x12\x2f\x09\xda\xd2\x27\
+\x28\xfe\x8c\xae\x4d\x57\x47\x26\x5e\x9b\x8f\xc5\x2f\xc5\x4e\x17\
+\xb6\x06\x6c\x8d\xd8\x9a\xb1\x09\xa7\x00\xb0\x1b\x16\x1f\xa0\x33\
+\x80\xce\xe0\x19\x20\x11\xd2\x87\xdf\xf8\xfc\x97\x87\x6b\xac\x2b\
+\x62\x7b\x0c\x64\x61\x26\x10\xc6\x3a\x07\x29\x40\xe2\x72\x54\xa2\
+\xb9\xbd\xdc\xe8\xed\xf9\x77\x47\x93\x1a\x00\x52\x79\x3e\xe0\xbb\
+\x51\xf1\x01\x1a\x00\x1a\x83\x05\x97\xff\xb5\xd4\x80\x38\xf3\x96\
+\x6f\x7f\xfc\x40\x85\x71\x65\x6c\x8f\x41\x38\x08\xc8\xa1\x27\x4f\
+\x04\x41\x23\x78\x4b\x77\x4e\xcf\x16\xb4\xfc\x97\xc3\x61\x85\xaf\
+\x26\x6a\xc0\x7f\x33\xc2\x0b\xd0\x00\xd0\x18\x1c\x00\xf8\x9f\x04\
+\x89\x48\xf3\xdf\xdb\xf5\xc4\x37\x17\xfd\xab\x62\xbb\x0f\xc4\x17\
+\x07\xfc\x19\x18\x1a\x34\xd4\x54\xa2\x59\xdd\x1a\xd1\xb2\x05\xa3\
+\xb8\x9b\x3a\x5a\x88\xdb\x1e\x68\x00\x68\x0c\x88\x47\xb2\x1c\x4a\
+\x42\x3e\xf6\xdf\x7b\x9e\xfc\xe6\xa2\xf7\xcf\xd6\x2e\xfd\x59\x83\
+\xd1\x88\x1a\xaa\x2b\xd0\x83\x5d\x5c\xe8\x9d\x7f\x19\xdd\xe1\x7a\
+\xd0\x00\xf8\x91\x78\xfc\xfd\xbd\x4f\x7d\x73\xc1\xbb\xca\x6b\x4d\
+\x61\x7f\x9e\x55\x8f\x56\x3c\x75\x2f\xd5\x22\xd2\x58\xf8\x61\xde\
+\x53\x4f\x7c\x90\x77\x9a\x14\x29\x14\x0a\x85\x42\xa1\x50\x28\x14\
+\x0a\x85\x42\xa1\x50\x28\x14\x0a\x85\x42\xd1\x1e\x84\xfe\x1f\x55\
+\x0b\x04\x29\x5c\xfb\x2b\x5e\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
+\x42\x60\x82\
"
qt_resource_name = b"\
@@ -2559,6 +3677,16 @@
\x07\x03\x7d\xc3\
\x00\x69\
\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
+\x00\x12\
+\x0b\xae\x6d\xe7\
+\x00\x73\
+\x00\x74\x00\x65\x00\x72\x00\x65\x00\x6f\x00\x5f\x00\x70\x00\x72\x00\x65\x00\x76\x00\x69\x00\x65\x00\x77\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
+\x00\x14\
+\x00\xf4\xcc\xc7\
+\x00\x70\
+\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x62\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x6e\x00\x65\x00\x73\x00\x73\x00\x2e\
+\x00\x70\x00\x6e\x00\x67\
\x00\x11\
\x04\xde\x94\x07\
\x00\x70\
@@ -2568,26 +3696,31 @@
\x07\xd7\xe7\xc7\
\x00\x70\
\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x73\x00\x63\x00\x61\x00\x6e\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x12\
-\x03\xa7\x30\x47\
+\x00\x13\
+\x0b\xca\x9e\xc7\
\x00\x70\
-\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x6c\x00\x6f\x00\x61\x00\x64\x00\x2e\x00\x70\x00\x6e\
-\x00\x67\
+\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x66\x00\x6f\x00\x72\x00\x62\x00\x69\x00\x64\x00\x64\x00\x65\x00\x6e\x00\x2e\x00\x70\
+\x00\x6e\x00\x67\
+\x00\x19\
+\x0f\x4c\xca\x07\
+\x00\x70\
+\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x64\x00\x69\x00\x67\x00\x69\x00\x74\x00\x61\x00\x6c\x00\x5f\x00\x70\x00\x72\x00\x65\
+\x00\x76\x00\x69\x00\x65\x00\x77\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x15\
+\x01\xbd\xb5\xe7\
+\x00\x72\
+\x00\x65\x00\x63\x00\x74\x00\x69\x00\x66\x00\x69\x00\x65\x00\x64\x00\x5f\x00\x70\x00\x72\x00\x65\x00\x76\x00\x69\x00\x65\x00\x77\
+\x00\x2e\x00\x70\x00\x6e\x00\x67\
\x00\x15\
\x01\x31\x18\xe7\
\x00\x70\
\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x63\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x63\x00\x61\x00\x74\x00\x65\
\x00\x2e\x00\x70\x00\x6e\x00\x67\
-\x00\x14\
-\x00\xf4\xcc\xc7\
-\x00\x70\
-\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x62\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x6e\x00\x65\x00\x73\x00\x73\x00\x2e\
-\x00\x70\x00\x6e\x00\x67\
-\x00\x13\
-\x0b\xca\x9e\xc7\
+\x00\x12\
+\x03\xa7\x30\x47\
\x00\x70\
-\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x66\x00\x6f\x00\x72\x00\x62\x00\x69\x00\x64\x00\x64\x00\x65\x00\x6e\x00\x2e\x00\x70\
-\x00\x6e\x00\x67\
+\x00\x68\x00\x6f\x00\x74\x00\x6f\x00\x5f\x00\x64\x00\x6f\x00\x77\x00\x6e\x00\x6c\x00\x6f\x00\x61\x00\x64\x00\x2e\x00\x70\x00\x6e\
+\x00\x67\
"
qt_resource_struct_v1 = b"\
@@ -2595,13 +3728,16 @@
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x02\
\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x01\x00\x00\x00\x04\
-\x00\x00\x00\x56\x00\x02\x00\x00\x00\x06\x00\x00\x00\x05\
-\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x81\x23\
-\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x79\xcd\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x67\x35\
+\x00\x00\x00\x56\x00\x02\x00\x00\x00\x09\x00\x00\x00\x05\
+\x00\x00\x00\x92\x00\x00\x00\x00\x00\x01\x00\x00\x04\xa6\
+\x00\x00\x01\x9e\x00\x00\x00\x00\x00\x01\x00\x00\xc8\xb7\
+\x00\x00\x01\x6e\x00\x00\x00\x00\x00\x01\x00\x00\xa9\x9d\
+\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\xd0\x0d\
+\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x09\xe0\
+\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x27\x55\
\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
-\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x75\
-\x00\x00\x01\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x86\x5d\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x71\x15\
+\x00\x00\x01\x36\x00\x00\x00\x00\x00\x01\x00\x00\x87\xf3\
"
qt_resource_struct_v2 = b"\
@@ -2613,20 +3749,26 @@
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x1c\x00\x02\x00\x00\x00\x01\x00\x00\x00\x04\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x00\x56\x00\x02\x00\x00\x00\x06\x00\x00\x00\x05\
+\x00\x00\x00\x56\x00\x02\x00\x00\x00\x09\x00\x00\x00\x05\
\x00\x00\x00\x00\x00\x00\x00\x00\
-\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x81\x23\
+\x00\x00\x00\x92\x00\x00\x00\x00\x00\x01\x00\x00\x04\xa6\
\x00\x00\x01\x7c\xb6\x3f\x9d\xc6\
-\x00\x00\x00\xdc\x00\x00\x00\x00\x00\x01\x00\x00\x79\xcd\
+\x00\x00\x01\x9e\x00\x00\x00\x00\x00\x01\x00\x00\xc8\xb7\
\x00\x00\x01\x7b\x7c\xa8\xd4\xb4\
-\x00\x00\x00\xb2\x00\x00\x00\x00\x00\x01\x00\x00\x67\x35\
+\x00\x00\x01\x6e\x00\x00\x00\x00\x00\x01\x00\x00\xa9\x9d\
+\x00\x00\x01\x7f\x92\x7b\x65\x66\
+\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\xd0\x0d\
\x00\x00\x01\x7c\x0d\x03\xa8\x3e\
-\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x09\xe0\
\x00\x00\x01\x7b\x7c\xa8\xd4\xd5\
-\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x75\
+\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x27\x55\
\x00\x00\x01\x7c\x0c\xff\x7e\xca\
-\x00\x00\x01\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x86\x5d\
+\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x7f\x92\x7b\x65\x69\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x71\x15\
\x00\x00\x01\x7c\xc1\x61\xb4\x86\
+\x00\x00\x01\x36\x00\x00\x00\x00\x00\x01\x00\x00\x87\xf3\
+\x00\x00\x01\x7f\xbc\x1f\xde\x32\
"
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
diff --git a/qlib3/photosearchselectiondialog/ui_photosearchselection.ui b/qlib3/photosearchselectiondialog/ui_photosearchselection.ui
index 0d7b9ea..56b10ea 100644
--- a/qlib3/photosearchselectiondialog/ui_photosearchselection.ui
+++ b/qlib3/photosearchselectiondialog/ui_photosearchselection.ui
@@ -6,14 +6,20 @@
0
0
- 656
- 373
+ 400
+ 500
+
+
+ 0
+ 0
+
+
- 300
- 300
+ 400
+ 326
@@ -26,6 +32,18 @@
Photo library search
+
+
+ 0
+ 0
+
+
+
+
+ 400
+ 300
+
+
11
@@ -432,26 +450,70 @@
-
-
-
-
- 0
- 0
-
-
-
- Preview
-
-
- Preview
-
-
-
- 32
- 32
-
+
+
+ 1
-
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Preview
+
+
+ Preview
+
+
+
+ 32
+ 32
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 18
+ 16777215
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ 32
+ 32
+
+
+
+
+
-
@@ -531,6 +593,67 @@
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
+ 0
+
+
-
+
+
+ Parallax: +0%
+
+
+
+ -
+
+
+
+ 0
+ 25
+
+
+
+ 0
+
+
+ 10
+
+
+ 1
+
+
+ 1
+
+
+ 5
+
+
+ 5
+
+
+ Qt::Horizontal
+
+
+ false
+
+
+ QSlider::TicksAbove
+
+
+
+ -
+
+
+ Inverted stereo
+
+
+
+
+
@@ -762,5 +885,53 @@
+
+ horizontalSlider_parallax
+ sliderReleased()
+ DockWidget
+ on_parallax_changed()
+
+
+ 315
+ 651
+
+
+ 345
+ 338
+
+
+
+
+ horizontalSlider_parallax
+ valueChanged(int)
+ DockWidget
+ on_parallax_changed()
+
+
+ 315
+ 651
+
+
+ 345
+ 338
+
+
+
+
+ checkBox_inverted_stereo
+ clicked(bool)
+ DockWidget
+ on_inverted_stereo(bool)
+
+
+ 620
+ 650
+
+
+ 345
+ 338
+
+
+
diff --git a/resources.qrc b/resources.qrc
index 8630a5b..a9a0687 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -11,5 +11,6 @@
images/download_all.png
images/search.png
images/search_coord.png
+ images/search_name.png
diff --git a/resources3/http.py b/resources3/http.py
index f877308..31d38a9 100644
--- a/resources3/http.py
+++ b/resources3/http.py
@@ -1,221 +1,221 @@
-# -*- coding: utf-8 -*-
-"""
-*******************************************************************************
-Module with functions to recover data to make WMS connections to ICGC resources
-
- -------------------
- begin : 2019-03-27
- author : Albert Adell
- email : albert.adell@icgc.cat
-*******************************************************************************
-"""
-
-import urllib
-import urllib.request
-import html
-import socket
-import re
-import os
-
-
-styles_list = [ # (regex_file_pattern, qml_style)
- (r".+-caps-municipi-.+", "divisions-administratives-caps-municipi-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
- (r".+-municipis-.+", "divisions-administratives-municipis-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
- (r".+-comarques-.+", "divisions-administratives-comarques-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
- (r".+-vegueries-.+", "divisions-administratives-vegueries-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
- (r".+-provincies-.+", "divisions-administratives-provincies-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
- (r".+-catalunya-.+", "divisions-administratives-catalunya-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
- ]
-
-def get_http_dir(url, timeout_seconds=0.5, retries=3):
- """ Obté el codi HTML d'una pàgina web amb fitxers
- Retorna: string
- ---
- Gets HTML code of web page with files
- Returns: string
- """
- # Llegeixo la pàgina HTTP que informa dels arxius disponibles
- remaining_retries = retries
- while remaining_retries:
- try:
- response = None
- response = urllib.request.urlopen(url, timeout=timeout_seconds)
- remaining_retries = 0
- except socket.timeout:
- remaining_retries -= 1
- #print("retries", remaining_retries)
- except:
- remaining_retries -= 1
- #print("retries", remaining_retries)
- if response:
- response_data = response.read()
- response_data = response_data.decode('utf-8')
- else:
- response_data = ""
- return response_data
-
-def get_http_files(url, file_regex_pattern, replace_list=[]):
- """ Obté una llista de fitxer d'una pàgina web a partir d'una expressió regular
- Retorna: llista de resultats de la expressió regular
- ---
- Gets file list of web page from a regular expression
- Returns: list of regex matches
- """
- # LLegeixo les dades HTML del directori HTTP
- response_data = get_http_dir(url)
- if not response_data:
- return []
- # Reemplacem els textos indicats
- for search, replace in replace_list:
- response_data = response_data.replace(search, replace)
- # Obtinc la informació de fitxers a partri de la regex
- http_file_regex_pattern = r'' % file_regex_pattern
- files_list = re.findall(http_file_regex_pattern, response_data)
- return files_list
-
-def get_dtms(dtm_urlbase_list=[
- ("2m 2008-2011", "https://datacloud.icgc.cat/datacloud/met2_ETRS89/mosaic"),
- ("5m 2020", "https://datacloud.icgc.cat/datacloud/met5_ETRS89/mosaic")],
- dtm_http_file_pattern=r'(met\w+\.\w+)'):
- """ Obté les URLs dels arxius de MET disponibles de l'ICGC
- Retorna: [(dtm_name, dtm_url)]
- ---
- Gets ICGC's available DTM urls
- Returns: [(dtm_name, dtm_url)]
- """
- dtm_list = []
- for dtm_name, dtm_urlbase in dtm_urlbase_list:
- # Llegeixo la pàgina HTTP que informa dels arxius disponibles
- # Cerquem links a arxius MET i ens quedem el més recent
- files_list = get_http_files(dtm_urlbase, dtm_http_file_pattern)
- if not files_list:
- continue
-
- dtm_file = sorted(files_list, reverse=True)[0]
- dtm_url = "%s/%s" % (dtm_urlbase, dtm_file)
- dtm_list.append((dtm_name, dtm_url))
-
- return dtm_list
-
-def get_sheets(sheets_urlbase="https://datacloud.icgc.cat/datacloud/talls_ETRS89/json_unzip",
- sheet_http_file_pattern=r'(tall(\w+)etrs\w+\.json)'):
- """ Obté les URLs dels arxius de talls disponibles de l'ICGC
- Retorna: [(sheet_name, sheet_url)]
- ---
- Gets ICGC's available sheets urls
- Returns: [(sheet_name, sheet_url)]
- """
- # Llegeixo la pàgina HTTP que informa dels arxius disponibles
- # Cerquem links a arxius json
- sheets_info_list = get_http_files(sheets_urlbase, sheet_http_file_pattern)
- if not sheets_info_list:
- return []
- sheets_info_list.sort(key=lambda sheet_infoi:int(sheet_infoi[1][:-1]) if sheet_infoi[1][:-1].isdigit() and sheet_infoi[1][-1] == "m" else 9999999)
-
- # Ajustem els noms i generem les urls completes
- sheets_list = []
- for sheet_file, sheet_name in sheets_info_list:
- if sheet_name[:-1].isdigit() and sheet_name[-1] == 'm':
- sheet_name = sheet_name.replace("m", ".000")
- sheet_url = "%s/%s" % (sheets_urlbase, sheet_file)
- sheets_list.append((sheet_name, sheet_url))
-
- return sheets_list
-
-def get_delimitations_old(delimitations_urlbase="https://datacloud.icgc.cat/datacloud/bm5m_ETRS89/json_unzip/",
- delimitation_http_file_pattern=r'(bm5mv\d+js\dt[cp][cmp][\d_]+\.json)',
- delimitation_type_patterns_list=[("Caps de Municipi", "bm5mv\d+js\dtcm[\d_]+\.json"), ("Municipis", "bm5mv\d+js\dtpm[\d_]+\.json"),
- ("Comarques", "bm5mv\d+js\dtpc[\d_]+\.json"), ("Províncies", "bm5mv\d+js\dtpp[\d_]+\.json")]):
- """ Obté les URLs dels arxius de talls disponibles de l'ICGC
- Retorna: [(sheet_name, sheet_url)]
- ---
- Gets ICGC's available sheets urls
- Returns: [(sheet_name, sheet_url)]
- """
- # Llegeixo la pàgina HTTP que informa dels arxius disponibles
- delimitations_info_list = get_http_files(delimitations_urlbase, delimitation_http_file_pattern)
-
- # Cerquem links a arxius json
- delimitations_list = []
- for delimitation_name, delimitation_type_pattern in delimitation_type_patterns_list:
- for delimitation_file in delimitations_info_list:
- # Cerquem el fitxer que quadri amb cada plantilla de tipus
- if re.match(delimitation_type_pattern, delimitation_file):
- delimitation_url = "%s/%s" % (delimitations_urlbase, delimitation_file)
- delimitations_list.append((delimitation_name, delimitation_url))
- break
-
- return delimitations_list
-
-def get_delimitations(delimitations_urlbase="https://datacloud.icgc.cat/datacloud/divisions-administratives/json_unzip/",
- delimitation_http_file_pattern=r'(divisions-administratives-v\d+r\d+\-(\D+)(?:-(\d+))*-(\d{8})\.json)'):
- """ Obté les URLs dels arxius de talls disponibles de l'ICGC
- Retorna: [(sheet_name, sheet_url)]
- ---
- Gets ICGC's available sheets urls
- Returns: [(sheet_name, sheet_url)]
- """
- # Llegeixo la pàgina HTTP que informa dels arxius disponibles (canvio "caps-municipi" per parsejar-lo més fàcil...)
- delimitations_info_list = get_http_files(delimitations_urlbase, delimitation_http_file_pattern)
- delimitations_info_list.sort(key=lambda d:d[0], reverse=True)
- # Cerquem links a arxius json (només ens quedem els de la data més nova)
- delimitations_dict = {}
- last_name = None
- last_scale = None
- for filename, name, scale, date in delimitations_info_list:
- # Ens quedem el primer (el de data més nova -> sort reverse)
- if last_name != name or last_scale != scale:
- delimitations_dict[name] = delimitations_dict.get(name, []) + [(int(scale) if scale else None, "%s/%s" % (delimitations_urlbase, filename))]
- last_name = name
- last_scale = scale
-
- # Ordenem els arxius...
- order_dict = {
- "caps-municipi": 1,
- "municipis": 2,
- "comarques": 3,
- "vegueries": 4,
- "provincies": 5,
- "catalunya": 6
- }
- #delimitations_list = sorted(list(delimitations_dict.items()), key=lambda d: order_dict.get(d[0], 0) * 1000000 + d[1][0]) # index(name) * 1000000 + scale
- delimitations_list = sorted(list(delimitations_dict.items()), key=lambda d: order_dict[d[0]])
- delimitations_list = [(name, sorted(scale_list, key=lambda s: s[0])) for name, scale_list in delimitations_list]
- return delimitations_list
-
-def get_ndvis(urlbase="https://datacloud.icgc.cat/datacloud/ndvi/tif/",
- http_file_pattern=r'(ndvi-v\d+r\d+-(\d+)\.tif)'):
- """ Obté les URLs dels arxius NDVI disponibles de l'ICGC
- Retorna: [(year, ndvi_url)]
- ---
- Gets ICGC's available NDVI file urls
- Returns: [(year, ndvi_url)]
- """
- # Llegeixo la pàgina HTTP que informa dels arxius disponibles
- # Cerquem links a arxius json
- info_list = get_http_files(urlbase, http_file_pattern)
- file_tuple_list = [(year, "%s/%s" % (urlbase, filename)) for filename, year in info_list]
- file_tuple_list.sort(key=lambda f : f[0]) # Ordenem per any
- return file_tuple_list
-
-def get_topographic_5k(urlbase="https://datacloud.icgc.cat/datacloud/topografia-territorial/tif_unzip",
- http_file_pattern=r'(topografia-territorial-v\d+r\d+-(\d+)\.tif)'):
- """ Obté les URLs dels arxius de topografia 1:5.000 disponibles de l'ICGC
- Retorna: [(year, ndvi_url)]
- ---
- Gets ICGC's available topography 1:5,000 file urls
- Returns: [(year, ndvi_url)]
- """
- info_list = get_http_files(urlbase, http_file_pattern)
- file_tuple_list = [(year, "%s/%s" % (urlbase, filename)) for filename, year in info_list]
- file_tuple_list.sort(key=lambda f : f[0]) # Ordenem per any
- return file_tuple_list
-
-def get_regex_styles():
- """ Retorna la llista d'estils disponibles amb el path al seu QML """
- final_styles_list = [
- (style_regex,
- # Injectem el path dels arxiu .qml
- os.path.join(os.path.dirname(__file__), "symbols", style_qml) if style_qml else None
- ) for style_regex, style_qml in styles_list]
- return final_styles_list
+# -*- coding: utf-8 -*-
+"""
+*******************************************************************************
+Module with functions to recover data to make WMS connections to ICGC resources
+
+ -------------------
+ begin : 2019-03-27
+ author : Albert Adell
+ email : albert.adell@icgc.cat
+*******************************************************************************
+"""
+
+import urllib
+import urllib.request
+import html
+import socket
+import re
+import os
+
+
+styles_list = [ # (regex_file_pattern, qml_style)
+ (r".+-caps-municipi-.+", "divisions-administratives-caps-municipi-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
+ (r".+-municipis-.+", "divisions-administratives-municipis-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
+ (r".+-comarques-.+", "divisions-administratives-comarques-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
+ (r".+-vegueries-.+", "divisions-administratives-vegueries-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
+ (r".+-provincies-.+", "divisions-administratives-provincies-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
+ (r".+-catalunya-.+", "divisions-administratives-catalunya-ref.qml"), # ct1mv22sh0f4483707eaxt1 (Textos)
+ ]
+
+def get_http_dir(url, timeout_seconds=0.5, retries=3):
+ """ Obté el codi HTML d'una pàgina web amb fitxers
+ Retorna: string
+ ---
+ Gets HTML code of web page with files
+ Returns: string
+ """
+ # Llegeixo la pàgina HTTP que informa dels arxius disponibles
+ remaining_retries = retries
+ while remaining_retries:
+ try:
+ response = None
+ response = urllib.request.urlopen(url, timeout=timeout_seconds)
+ remaining_retries = 0
+ except socket.timeout:
+ remaining_retries -= 1
+ #print("retries", remaining_retries)
+ except:
+ remaining_retries -= 1
+ #print("retries", remaining_retries)
+ if response:
+ response_data = response.read()
+ response_data = response_data.decode('utf-8')
+ else:
+ response_data = ""
+ return response_data
+
+def get_http_files(url, file_regex_pattern, replace_list=[]):
+ """ Obté una llista de fitxer d'una pàgina web a partir d'una expressió regular
+ Retorna: llista de resultats de la expressió regular
+ ---
+ Gets file list of web page from a regular expression
+ Returns: list of regex matches
+ """
+ # LLegeixo les dades HTML del directori HTTP
+ response_data = get_http_dir(url)
+ if not response_data:
+ return []
+ # Reemplacem els textos indicats
+ for search, replace in replace_list:
+ response_data = response_data.replace(search, replace)
+ # Obtinc la informació de fitxers a partri de la regex
+ http_file_regex_pattern = r'' % file_regex_pattern
+ files_list = re.findall(http_file_regex_pattern, response_data)
+ return files_list
+
+def get_dtms(dtm_urlbase_list=[
+ ("2m 2008-2011", "https://datacloud.icgc.cat/datacloud/met2_ETRS89/mosaic"),
+ ("5m 2020", "https://datacloud.icgc.cat/datacloud/met5_ETRS89/mosaic")],
+ dtm_http_file_pattern=r'(met\w+\.\w+)'):
+ """ Obté les URLs dels arxius de MET disponibles de l'ICGC
+ Retorna: [(dtm_name, dtm_url)]
+ ---
+ Gets ICGC's available DTM urls
+ Returns: [(dtm_name, dtm_url)]
+ """
+ dtm_list = []
+ for dtm_name, dtm_urlbase in dtm_urlbase_list:
+ # Llegeixo la pàgina HTTP que informa dels arxius disponibles
+ # Cerquem links a arxius MET i ens quedem el més recent
+ files_list = get_http_files(dtm_urlbase, dtm_http_file_pattern)
+ if not files_list:
+ continue
+
+ dtm_file = sorted(files_list, reverse=True)[0]
+ dtm_url = "%s/%s" % (dtm_urlbase, dtm_file)
+ dtm_list.append((dtm_name, dtm_url))
+
+ return dtm_list
+
+def get_sheets(sheets_urlbase="https://datacloud.icgc.cat/datacloud/talls_ETRS89/json_unzip",
+ sheet_http_file_pattern=r'(tall(\w+)etrs\w+\.json)'):
+ """ Obté les URLs dels arxius de talls disponibles de l'ICGC
+ Retorna: [(sheet_name, sheet_url)]
+ ---
+ Gets ICGC's available sheets urls
+ Returns: [(sheet_name, sheet_url)]
+ """
+ # Llegeixo la pàgina HTTP que informa dels arxius disponibles
+ # Cerquem links a arxius json
+ sheets_info_list = get_http_files(sheets_urlbase, sheet_http_file_pattern)
+ if not sheets_info_list:
+ return []
+ sheets_info_list.sort(key=lambda sheet_infoi:int(sheet_infoi[1][:-1]) if sheet_infoi[1][:-1].isdigit() and sheet_infoi[1][-1] == "m" else 9999999)
+
+ # Ajustem els noms i generem les urls completes
+ sheets_list = []
+ for sheet_file, sheet_name in sheets_info_list:
+ if sheet_name[:-1].isdigit() and sheet_name[-1] == 'm':
+ sheet_name = sheet_name.replace("m", ".000")
+ sheet_url = "%s/%s" % (sheets_urlbase, sheet_file)
+ sheets_list.append((sheet_name, sheet_url))
+
+ return sheets_list
+
+def get_delimitations_old(delimitations_urlbase="https://datacloud.icgc.cat/datacloud/bm5m_ETRS89/json_unzip/",
+ delimitation_http_file_pattern=r'(bm5mv\d+js\dt[cp][cmp][\d_]+\.json)',
+ delimitation_type_patterns_list=[("Caps de Municipi", "bm5mv\d+js\dtcm[\d_]+\.json"), ("Municipis", "bm5mv\d+js\dtpm[\d_]+\.json"),
+ ("Comarques", "bm5mv\d+js\dtpc[\d_]+\.json"), ("Províncies", "bm5mv\d+js\dtpp[\d_]+\.json")]):
+ """ Obté les URLs dels arxius de talls disponibles de l'ICGC
+ Retorna: [(sheet_name, sheet_url)]
+ ---
+ Gets ICGC's available sheets urls
+ Returns: [(sheet_name, sheet_url)]
+ """
+ # Llegeixo la pàgina HTTP que informa dels arxius disponibles
+ delimitations_info_list = get_http_files(delimitations_urlbase, delimitation_http_file_pattern)
+
+ # Cerquem links a arxius json
+ delimitations_list = []
+ for delimitation_name, delimitation_type_pattern in delimitation_type_patterns_list:
+ for delimitation_file in delimitations_info_list:
+ # Cerquem el fitxer que quadri amb cada plantilla de tipus
+ if re.match(delimitation_type_pattern, delimitation_file):
+ delimitation_url = "%s/%s" % (delimitations_urlbase, delimitation_file)
+ delimitations_list.append((delimitation_name, delimitation_url))
+ break
+
+ return delimitations_list
+
+def get_delimitations(delimitations_urlbase="https://datacloud.icgc.cat/datacloud/divisions-administratives/json_unzip/",
+ delimitation_http_file_pattern=r'(divisions-administratives-v\d+r\d+\-(\D+)(?:-(\d+))*-(\d{8})\.json)'):
+ """ Obté les URLs dels arxius de talls disponibles de l'ICGC
+ Retorna: [(sheet_name, sheet_url)]
+ ---
+ Gets ICGC's available sheets urls
+ Returns: [(sheet_name, sheet_url)]
+ """
+ # Llegeixo la pàgina HTTP que informa dels arxius disponibles (canvio "caps-municipi" per parsejar-lo més fàcil...)
+ delimitations_info_list = get_http_files(delimitations_urlbase, delimitation_http_file_pattern)
+ delimitations_info_list.sort(key=lambda d:d[0], reverse=True)
+ # Cerquem links a arxius json (només ens quedem els de la data més nova)
+ delimitations_dict = {}
+ last_name = None
+ last_scale = None
+ for filename, name, scale, date in delimitations_info_list:
+ # Ens quedem el primer (el de data més nova -> sort reverse)
+ if last_name != name or last_scale != scale:
+ delimitations_dict[name] = delimitations_dict.get(name, []) + [(int(scale) if scale else None, "%s/%s" % (delimitations_urlbase, filename))]
+ last_name = name
+ last_scale = scale
+
+ # Ordenem els arxius...
+ order_dict = {
+ "caps-municipi": 1,
+ "municipis": 2,
+ "comarques": 3,
+ "vegueries": 4,
+ "provincies": 5,
+ "catalunya": 6
+ }
+ #delimitations_list = sorted(list(delimitations_dict.items()), key=lambda d: order_dict.get(d[0], 0) * 1000000 + d[1][0]) # index(name) * 1000000 + scale
+ delimitations_list = sorted(list(delimitations_dict.items()), key=lambda d: order_dict[d[0]])
+ delimitations_list = [(name, sorted(scale_list, key=lambda s: s[0])) for name, scale_list in delimitations_list]
+ return delimitations_list
+
+def get_ndvis(urlbase="https://datacloud.icgc.cat/datacloud/ndvi/tif/",
+ http_file_pattern=r'(ndvi-v\d+r\d+-(\d+)\.tif)'):
+ """ Obté les URLs dels arxius NDVI disponibles de l'ICGC
+ Retorna: [(year, ndvi_url)]
+ ---
+ Gets ICGC's available NDVI file urls
+ Returns: [(year, ndvi_url)]
+ """
+ # Llegeixo la pàgina HTTP que informa dels arxius disponibles
+ # Cerquem links a arxius json
+ info_list = get_http_files(urlbase, http_file_pattern)
+ file_tuple_list = [(year, "%s/%s" % (urlbase, filename)) for filename, year in info_list]
+ file_tuple_list.sort(key=lambda f : f[0]) # Ordenem per any
+ return file_tuple_list
+
+def get_topographic_5k(urlbase="https://datacloud.icgc.cat/datacloud/topografia-territorial/tif_unzip",
+ http_file_pattern=r'(topografia-territorial-v\d+r\d+-(\d+)\.tif)'):
+ """ Obté les URLs dels arxius de topografia 1:5.000 disponibles de l'ICGC
+ Retorna: [(year, ndvi_url)]
+ ---
+ Gets ICGC's available topography 1:5,000 file urls
+ Returns: [(year, ndvi_url)]
+ """
+ info_list = get_http_files(urlbase, http_file_pattern)
+ file_tuple_list = [(year, "%s/%s" % (urlbase, filename)) for filename, year in info_list]
+ file_tuple_list.sort(key=lambda f : f[0]) # Ordenem per any
+ return file_tuple_list
+
+def get_regex_styles():
+ """ Retorna la llista d'estils disponibles amb el path al seu QML """
+ final_styles_list = [
+ (style_regex,
+ # Injectem el path dels arxiu .qml
+ os.path.join(os.path.dirname(__file__), "symbols", style_qml) if style_qml else None
+ ) for style_regex, style_qml in styles_list]
+ return final_styles_list