diff --git a/plugins/openmodeller/Makefile.am b/plugins/openmodeller/Makefile.am new file mode 100644 index 00000000000..41eedae6e06 --- /dev/null +++ b/plugins/openmodeller/Makefile.am @@ -0,0 +1,57 @@ +# Copyright (C) 2003 Gary Sherman +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# +# $Id$ + +plugindir = ${pkglibdir} +plugin_LTLIBRARIES = libopenmodellerplugin.la + +%.moc.cpp: %.h + $(MOC) -o $@ $< + +%.h: %.ui + $(UIC) -o $@ $< + +%.cpp: %.ui + $(UIC) -o $@ -impl $*.h $< + +libopenmodellerplugin_la_SOURCES = plugin.cpp \ + plugin.h \ + openmodellergui.cpp \ + openmodellergui.h \ + ../../src/qgsmaplayer.cpp\ + ../../src/qgsrasterlayer.cpp\ + $(openmodeller_UI)\ + $(openmodeller_MOC) + +openmodeller_MOC = plugin.moc.cpp \ + ../../src/qgsmaplayer.moc.cpp \ + ../../src/qgsrasterlayer.moc.cpp \ + openmodellergui.moc.cpp \ + openmodellerguibase.moc.cpp + +openmodeller_UI = openmodellerguibase.h \ + openmodellerguibase.cpp + +openmodeller_UIC = openmodellerguibase.ui + +# UI dependencies +openmodellerguibase.cpp: openmodellerguibase.h openmodellerguibase.ui + +BUILT_SOURCES = $(openmodeller_MOC) $(openmodeller_UI) + +AM_CXXFLAGS := $(CXXFLAGS) $(EXTRA_CXXFLAGS) $(QT_CXXFLAGS) $(DEBUG_QGIS) + +#-lom is libopenmodeller which should be in to /usr/lib/libom.so.0.0 +libopenmodellerplugin_la_LIBADD = $(QT_LDADD) -L/usr/lib/ -lom -lm +libopenmodellerplugin_la_LDFLAGS = -avoid-version -module + +EXTRA_DIST = $(openmodeller_UIC) icon_om.xpm + diff --git a/plugins/openmodeller/icon_om.xpm b/plugins/openmodeller/icon_om.xpm new file mode 100644 index 00000000000..6200a02b7c3 --- /dev/null +++ b/plugins/openmodeller/icon_om.xpm @@ -0,0 +1,32 @@ +/* XPM */ +static const char *icon_om[]={ +"22 22 7 1", +". c None", +"c c #000000", +"# c #0058c0", +"b c #0080ff", +"d c #58a8ff", +"a c #a8dcff", +"e c #c3c3c3", +"........#a#.a.........", +".....a#b.a#abbaa......", +"....a.ab.aaba#a#......", +"...#aaaa.a.ba#.b#a....", +"..aaba.aaabbaa#aaba...", +"..bbb#a##bba#ab#a##b..", +"..bccccabbccaabbbcca..", +"b.ccccccbacccbbacccda.", +"b#ccbbccabccccdcccca.e", +"#bccabccbbccbcccbccdbe", +"b.cc#bccbbccabcbbcca.e", +"a#ccbaccaacc#aabbcc#ae", +"a.ccb#ccaaccaabaaccdbe", +"b#cccccca#ccadab#cc##e", +".##ccccaaacca#a#bccaee", +".a#aabb#aa#b###aa#a#e.", +"..a#aaa#daa###bbb#aee.", +"...caaaa#baaaa#abdee..", +"....##bd#aaabddaaee...", +"....eaa#aaaa#abaee....", +"....eee##.#ba#eee.....", +".....eeeeeeeeeee......"}; diff --git a/plugins/openmodeller/openmodellergui.cpp b/plugins/openmodeller/openmodellergui.cpp new file mode 100644 index 00000000000..69788f5f772 --- /dev/null +++ b/plugins/openmodeller/openmodellergui.cpp @@ -0,0 +1,533 @@ +/*************************************************************************** + * Copyright (C) 2003 by Tim Sutton * + * tim@linfiniti.com * + * * + * Gyps - Species Distribution Modelling Toolkit * + * This toolkit provides data transformation and visualisation * + * tools for use in species distribution modelling tools such as GARP, * + * CSM, Bioclim etc. * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "openmodellergui.h" + +//qt includes +#include "qlineedit.h" +#include "qstring.h" +#include "qfiledialog.h" +#include "qmessagebox.h" +#include +#include +#include +#include +#include +#include +#include +// +//openmodeller includes +#include "control_interface.hh" +#include +#include +#include + +//standard includes +#include +#include +#include + +OpenModellerGui::OpenModellerGui() + : OpenModellerGuiBase() +{ + _log.info( "\n%s qgis openModeller plugin starting.\n\n", "" ); +} + +OpenModellerGui::OpenModellerGui( QWidget* parent , const char* name , bool modal , WFlags fl ) +: OpenModellerGuiBase( parent, name, modal, fl ) +{ + + _log.info( "\n%s qgis openModeller plugin starting.\n\n", "" ); +} +OpenModellerGui::~OpenModellerGui() +{ +} + +/** This is the page selected event which I am reimplementing to do some housekeeping + * between wizard pages. + * This routine is a slot that runs each time next is pressed */ +void OpenModellerGui::formSelected(const QString &thePageNameQString) +{ + std::cout << thePageNameQString << " has focus " << std::endl; + QString myQString; + if (thePageNameQString==tr("Step 3 of 8")) //we do this after leaving the file selection page + { + setNextEnabled(currentPage(),false); + if (leLocalitiesFileName->text() !="") + { + setNextEnabled(currentPage(),true); + } + } + if (thePageNameQString==tr("Step 4 of 8")) + { + if ( lstLayers->count()==0) + { + setNextEnabled(currentPage(),false); + } + else + { + setNextEnabled(currentPage(),true); + } + } + if (thePageNameQString==tr("Step 7 of 8")) + { + if ( leOutputFileName->text()=="") + { + setNextEnabled(currentPage(),false); + } + else + { + setNextEnabled(currentPage(),true); + } + } + else if (thePageNameQString==tr("Step 8 of 8")) + { + setFinishEnabled(currentPage(),true); + } +} + + +/** This method is used when you already have a valid model paramters text file + and want to run it without interacting with the user. + @see pbnRun method which is run when model inputs have been obtained via the wizard. */ +void OpenModellerGui::parseAndRun(QString theParametersFileNameQString) +{ + // + // Create a fileparser to read in the request file + // and a controlInterface to manage the model process + // + + //strdup is used to convert the qstring to a non const char * + FileParser myFileParser( strdup(theParametersFileNameQString)); + ControlInterface myController; + + // + // Parse the model paramter file... + // + + // Get the environmental variables (continuous and categorical) + char *myMaskFileNameCharArray = myFileParser.get( "Mask" ); + char *myCategoricalMapCharArray = "Categorical map"; + int myNumberOfCategoriesInt = myFileParser.count( myCategoricalMapCharArray ); + //The key name in the paramters file that indicates its value is a map layer + char *myLayerLabelCharArray = "Map"; + //find out the number of enviroinmental layers + int myNumberOfLayersInt = myFileParser.count( myLayerLabelCharArray ); + //Find out the total layer count including environmental and mask layers + int myTotalLayerCountInt = myNumberOfLayersInt + myNumberOfCategoriesInt; + //create a char array and populate it with all layer names + char *myLayersCollectionCharArray[myTotalLayerCountInt]; + myFileParser.getAll( myCategoricalMapCharArray, myLayersCollectionCharArray ); + myFileParser.getAll( myLayerLabelCharArray, myLayersCollectionCharArray + myNumberOfCategoriesInt ); + //get the coordinate system that point data should be transformed into + char *myCoordinateSystem = GeoTransform::cs_default; + // Get the details for the output Map + char *myOutputFleNameCharArray = myFileParser.get( "Output" ); + char *myOutputFormatCharArray = myFileParser.get( "Output format" ); + //scale is used to scale the model results e.g. from 0-1 to 0-255 - useful for image gen + char *myScaleCharArray = myFileParser.get( "Scale" ); + // find out which model algorithm is to be used e,g. bioclim, cartesian etc + char *myAlgorithmNameCharArray = myFileParser.get( "Algorithm" ); + //obtain any model parameters that are specified in the request file + char *myAlgorithmParametersCharArray= myFileParser.get( "Parameters" ); + // Obtain the Well Known Text string for the localities coordinate system + char *myLocalitiesCoordinateSystem = myFileParser.get( "WKT coord system" ); + // Get the name of the file containing localities + char *myLocalitiesFileCharArray = myFileParser.get( "Species file" ); + // Get the name of the taxon being modelled! + char *myTaxonNameCharArray = myFileParser.get( "Species" ); + + // + // Make sure the basic variables have been defined in the parameter file... + // + if ( ! myOutputFleNameCharArray ) + { + QMessageBox::warning( this,QString("Acme Wizard Error"),QString("The 'Output file name' was not specified!")); + return; + } + if ( ! myOutputFormatCharArray ) + { + QMessageBox::warning( this,"Acme Wizard Error","The 'Output format' was not specified!"); + return; + } + if ( ! myScaleCharArray ) + { + myScaleCharArray = "255.0"; + } + // + // Set up the output map builder + // + RasterFile map( myOutputFormatCharArray ); + // + // Set up the model controller + // + myController.setEnvironment( myCoordinateSystem, myNumberOfCategoriesInt, myTotalLayerCountInt, myLayersCollectionCharArray, myMaskFileNameCharArray ); + // Prepare the output map + + myController.setOutputMap( myOutputFleNameCharArray, map.header(), atof(myScaleCharArray) ); + // Set the model algorithm to be used by the controller + myController.setAlgorithm( myAlgorithmNameCharArray, myAlgorithmParametersCharArray ); + // Populate the occurences list from the localities file + myController.setOccurrences( myLocalitiesFileCharArray, myLocalitiesCoordinateSystem, myTaxonNameCharArray ); + + // + // Run the model + // + if ( ! myController.run() ) + { + QString myErrorQString; + QMessageBox::warning( this,"Acme Wizard Error",myErrorQString.sprintf("Error: %s\nModel aborted.", myController.error())); + } + else + { + //if all went ok, send notification to the parent app that we are finished + emit drawRasterLayer(QString( myOutputFleNameCharArray )); + } + +} //end of parseAndRun + +void OpenModellerGui::makeConfigFile() +{ + QFile myQFile( outputFileNameQString+".cfg"); + if ( myQFile.open( IO_WriteOnly ) ) { + QTextStream myQTextStream( &myQFile ); + //write the header to the file + myQTextStream << tr("#################################################################\n"); + myQTextStream << tr("##\n"); + myQTextStream << tr("## openModeller Configuration file\n"); + myQTextStream << tr("##\n"); + myQTextStream << tr("##Autogenerated using openModeller Plugin for QGIS (c) T.Sutton 2003\n"); + myQTextStream << tr("##\n"); + myQTextStream << tr("#################################################################\n"); + myQTextStream << tr("\n\n##\n"); + myQTextStream << tr("## Coordinate system and projection in WKT format\n"); + myQTextStream << tr("##\n\n"); + myQTextStream << tr("WKT Coord System = ") << coordinateSystemQString << "\n"; + + myQTextStream << tr("\n\n##\n"); + myQTextStream << tr("## Localities Data Configuration Options...\n"); + myQTextStream << tr("##\n\n"); + myQTextStream << tr("# Full path and file name of the file containing localities data.\n"); + myQTextStream << tr("Species file = ") << localitiesFileNameQString << "\n"; + myQTextStream << tr("# The taxon in the localities file to be modelled.\n"); + myQTextStream << tr("# (Defaults to the first taxon found.)\n"); + myQTextStream << tr("Species = ") << taxonNameQString << "\n"; + myQTextStream << tr("\n\n##\n"); + myQTextStream << tr("## Independent Variable Layers (map layers)\n"); + myQTextStream << tr("##\n\n"); + // Iterate through the items in the layers list + for ( QStringList::Iterator myIterator = layerNamesQStringList.begin(); myIterator != layerNamesQStringList.end(); ++myIterator) + { + myQTextStream << tr("Map = ") << *myIterator << "\n"; + } + myQTextStream << tr("# A layer that species the region of interest\n"); + myQTextStream << tr("Mask = ") << maskNameQString << "\n"; + + myQTextStream << tr("\n\n##\n"); + myQTextStream << tr("## Model Output Settings\n"); + myQTextStream << tr("##\n\n"); + // NOTE by Tim: not too sure what this next option does - will have to sak Mauro + // I think it just sets the ouput file extents etc + // I am hardcoding it to match the first layer in the collection for now + myQTextStream << tr("# File to be used as the output format.\n") ; + myQTextStream << tr("Output format = ") << layerNamesQStringList.front() << "\n"; + myQTextStream << tr("# Output file name (should end in .tif)\n"); + myQTextStream << tr("Output = ") << outputFileNameQString << ".tif\n"; + myQTextStream << tr("# Scale algorithm output (originally between 0 and 1) by this factor.\n"); + //NOTE I am hard coding the output scaling variable for now! + myQTextStream << tr("Scale = 240.0\n"); + myQTextStream << tr("\n\n##\n"); + myQTextStream << tr("## Model Type and Extra Model Parameters\n"); + myQTextStream << tr("##\n\n"); + myQTextStream << tr("# Name of the algorithm used to construct the model.\n"); + myQTextStream << tr("Algorithm = "); + if (modelNameQString=="") + { + // Default to bioclim if modelname has not been set + modelNameQString="Bioclim"; + } + myQTextStream << modelNameQString << "\n"; + // Iterate through the items in the extra parameters list + for ( QStringList::Iterator myIterator = extraParametersQStringList.begin(); myIterator != extraParametersQStringList.end(); ++myIterator) + { + myQTextStream << tr("Parameters = ") << *myIterator << "\n"; + } + + myQTextStream << tr("\n\n###########################################\n"); + myQTextStream << tr("## End of autogenerated configuration file.\n"); + myQTextStream << tr("###########################################\n"); + //for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) + // myQTextStream << *it << "\n"; + myQFile.close(); + } + +} + + + // + // What follow are the overridden methods from the base form... + // +/** The accept method overrides the qtwizard method of the same name and is run when the finish button is pressed */ +void OpenModellerGui::accept() +{ + std::cout << "cboModelAlgorithm .. current text : " << cboModelAlgorithm->currentText() << std::endl; + if (cboModelAlgorithm->currentText()==tr("Bioclimatic Envelope Model")) + { + modelNameQString="Bioclim"; + } + else if (cboModelAlgorithm->currentText()==tr("Cartesian Distance")) + { + modelNameQString="MinDistance"; + } + //pull all the form data into local class vars. + outputFileNameQString=leOutputFileName->text(); + localitiesFileNameQString=leLocalitiesFileName->text(); + //build up the map layers qstringlist + layerNamesQStringList.clear(); + for ( unsigned int myInt = 0; myInt < lstLayers->count(); myInt++ ) + { + QListBoxItem *myItem = lstLayers->item( myInt ); + layerNamesQStringList.append(myItem->text()); + } + // build up the model parameters qstringlist + extraParametersQStringList.clear(); + for ( unsigned int myInt = 0; myInt < lstParameters->count(); myInt++ ) + { + QListBoxItem *myItem = lstParameters->item( myInt ); + extraParametersQStringList.append(myItem->text()); + } + + maskNameQString=cboMaskLayer->currentText(); + taxonNameQString=cboTaxon->currentText(); + coordinateSystemQString=txtWKT->text(); + //strip linefeeds and escape carriage returns in WKT string + coordinateSystemQString=coordinateSystemQString.replace( QRegExp("\""), "\\\"" ); + coordinateSystemQString=coordinateSystemQString.replace( QRegExp("\n"), "" ); + makeConfigFile(); + parseAndRun(outputFileNameQString+".cfg"); + //close the dialog + done(1); +} + +void OpenModellerGui::cboModelAlgorithm_activated( const QString &theAlgorithmQString) +{ + if (theAlgorithmQString==tr("Bioclimatic Envelope Model")) + { + modelNameQString=="Bioclim"; + } + else if (theAlgorithmQString==tr("Cartesian Distance")) + { + modelNameQString=="MinDistance"; + } +} + + +void OpenModellerGui::pbnSelectOutputFile_clicked() +{ + std::cout << " OpenModellerGui::pbnSelectOutputFile_clicked() " << std::endl; + QString myOutputFileNameQString = QFileDialog::getSaveFileName( + ".", + "All Files (*.)", + this, + "save file dialog" + "Choose a filename to save under" ); + leOutputFileName->setText(myOutputFileNameQString); + if ( leOutputFileName->text()=="") + { + setNextEnabled(currentPage(),false); + } + else + { + setNextEnabled(currentPage(),true); + } +} + +void OpenModellerGui::pbnRemoveParameter_clicked() +{ + for ( unsigned int myInt = 0; myInt< lstParameters->count(); myInt++ ) + { + QListBoxItem *myItem = lstParameters->item( myInt ); + // if the item is selected... + if ( myItem->isSelected() ) + { + //remove the item if it is selected + lstParameters->removeItem(myInt); + } + } +} + + +void OpenModellerGui::pbnAddParameter_clicked() +{ + lstParameters->insertItem(leNewParameter->text()); + leNewParameter->setText(""); +} + + +void OpenModellerGui::pbnRemoveLayerFile_clicked() +{ + for ( unsigned int myInt = 0; myInt< lstLayers->count(); myInt++ ) + { + QListBoxItem *myItem = lstLayers->item( myInt ); + // if the item is selected... + if ( myItem->isSelected() ) + { + //remove the item if it is selected + lstLayers->removeItem(myInt); + //also remove the item from the mask layer combo + cboMaskLayer->removeItem(myInt); + } + } + //if user has removed last list entry, disable next button + if ( lstLayers->count()==0) + { + setNextEnabled(currentPage(),false); + } + +} + + +void OpenModellerGui::pbnSelectLayerFile_clicked() +{ + std::cout << " OpenModellerGui::pbnSelectLayerFile_clicked() " << std::endl; + QString myFileTypeQString; + QString myGDALFilterString="GDAL (*.tif; *.asc; *.bil;*.jpg;*.adf)"; + QString myFileNameQString = QFileDialog::getOpenFileName( + "" , //initial dir + myGDALFilterString, //filters to select + this , //parent dialog + "OpenFileDialog" , //QFileDialog qt object name + "Select localities text file" , //caption + &myFileTypeQString //the pointer to store selected filter + ); + std::cout << "Selected filetype filter is : " << myFileTypeQString << std::endl; + if (myFileNameQString==NULL || myFileNameQString=="") return; + //check if the file is an arc/info binary grid in which case we should only use the + //directory name in which the adf file occurs + if (myFileNameQString.endsWith(".adf")) + { + //try to find unix path separater first (search backwards from end of line) + if (myFileNameQString.findRev('/') != -1) + { + myFileNameQString=myFileNameQString.mid(0,myFileNameQString.findRev('/')+1); + } + else //no forward slash found so assume dos and look for backslash + { + //try looking for dos separaters + myFileNameQString=myFileNameQString.mid(0,myFileNameQString.findRev('\\')+1); + } + } + lstLayers->insertItem(myFileNameQString); + //also add the layer to the mask combo + cboMaskLayer->insertItem(myFileNameQString); + //enable the user to carry on to the next page... + setNextEnabled(currentPage(),true); +} + + +void OpenModellerGui::pbnSelectLocalitiesFile_clicked() +{ + std::cout << " OpenModellerGui::pbnSelectLocalitiesFile_clicked() " << std::endl; + QString myFileTypeQString; + QString myTextFileFilterString="Text File (*.txt)"; + QString myFileNameQString = QFileDialog::getOpenFileName( + "" , //initial dir + myTextFileFilterString, //filters to select + this , //parent dialog + "OpenFileDialog" , //QFileDialog qt object name + "Select localities text file" , //caption + &myFileTypeQString //the pointer to store selected filter + ); + std::cout << "Selected filetype filter is : " << myFileTypeQString << std::endl; + if (myFileNameQString==NULL || myFileNameQString=="") return; + + + // + // Now that we have the localities text file, we need to parse it and find + // all unique instances of taxon names and populate the taxon combo... + // + //first build a regex to match text at the beginning of the line + QRegExp myQRegExp( "^[^#][ a-zA-Z]*" ); //seconf caret means 'not' + QStringList myTaxonQStringList;; + QFile myQFile( myFileNameQString ); + if ( myQFile.open( IO_ReadOnly ) ) + { + //clear the existing entries in the taxon combo first + cboTaxon->clear(); + //now we parse the loc file, checking each line for its taxon + QTextStream myQTextStream( &myQFile ); + QString myCurrentLineQString; + while ( !myQTextStream.atEnd() ) + { + myCurrentLineQString = myQTextStream.readLine(); // line of text excluding '\n' + myQRegExp.search(myCurrentLineQString); + QStringList myMatchesQStringList = myQRegExp.capturedTexts(); + QStringList::Iterator myIterator = myMatchesQStringList.begin(); + QString myTaxonQString=*myIterator; + myTaxonQString=myTaxonQString.stripWhiteSpace(); + if (myTaxonQString != "") + { + //make sure there are only single spaces separating words. + myTaxonQString=myTaxonQString.replace( QRegExp(" {2,}"), " " ); + myTaxonQStringList.append(myTaxonQString); + } + } + myQFile.close(); + //sort the taxon list alpabetically + myTaxonQStringList.sort(); + //now find the uniqe entries in the qstringlist and + //add each entry to the taxon combo + QString myLastTaxon=""; + QStringList::Iterator myIterator= myTaxonQStringList.begin(); + while( myIterator!= myTaxonQStringList.end() ) + { + QString myCurrentTaxon=*myIterator; + if (myCurrentTaxon!=myLastTaxon) + { + cboTaxon->insertItem(myCurrentTaxon); + } + myLastTaxon=*myIterator; + ++myIterator; + } + } + else + { + QMessageBox::warning( this,QString("Acme Wizard Error"),QString("The localities file is not readable. Check you have the neccessary file permissions and try again.")); + return; + } + // if all that went ok, update the form field and the class var + leLocalitiesFileName->setText(myFileNameQString); + localitiesFileNameQString = myFileNameQString; + //enable the user to carry on to the next page... + setNextEnabled(currentPage(),true); +} //end of pbnSelectLocalitiesFile_clicked + +void OpenModellerGui::leLocalitiesFileName_textChanged( const QString &theFileNameQString ) +{ + // this should never run - I am changing the line edit control to read only so that + // file parsing for taxon names does not happen with every text change + localitiesFileNameQString = theFileNameQString; + //enable the user to carry on to the next page... + setNextEnabled(currentPage(),true); +} + +void OpenModellerGui::leLocalitiesFileName_returnPressed() +{ + // this should never run - I am changing the line edit control to read only so that + // file parsing for taxon names does not happen with every text change + localitiesFileNameQString = leLocalitiesFileName->text(); + //enable the user to carry on to the next page... + setNextEnabled(currentPage(),true); +} + + diff --git a/plugins/openmodeller/openmodellergui.h b/plugins/openmodeller/openmodellergui.h new file mode 100644 index 00000000000..e80c230162c --- /dev/null +++ b/plugins/openmodeller/openmodellergui.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2003 by Tim Sutton * + * tim@linfiniti.com * + * * + * Gyps - Species Distribution Modelling Toolkit * + * This toolkit provides data transformation and visualisation * + * tools for use in species distribution modelling tools such as GARP, * + * CSM, Bioclim etc. * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef OPENMODELLERGUI_H +#define OPENMODELLERGUI_H + +#include + +/** +@author Tim Sutton +*/ +class OpenModellerGui : public OpenModellerGuiBase +{ +Q_OBJECT +public: + OpenModellerGui(); + OpenModellerGui( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~OpenModellerGui(); + void OpenModellerGui::parseAndRun(QString theParametersFileNameQString); + void makeConfigFile(); + + // + // The following methods reimplement methods by the same name of the parent class + // + + void cboModelAlgorithm_activated( const QString & ); + /** This method overrides the virtual OpenModellerGuiBase method (slot) of the same name. */ + void formSelected(const QString &thePageNameQString); + void leLocalitiesFileName_textChanged( const QString &theFileNameQString ); + void pbnSelectOutputFile_clicked(); + void pbnRemoveParameter_clicked(); + void pbnAddParameter_clicked(); + void pbnRemoveLayerFile_clicked(); + void pbnSelectLayerFile_clicked(); + void pbnSelectLocalitiesFile_clicked(); + void leLocalitiesFileName_returnPressed(); + void accept(); + +private: + QString modelNameQString; + QString localitiesFileNameQString; + QString coordinateSystemQString; + QString taxonNameQString; + QStringList layerNamesQStringList; + QString maskNameQString; + QStringList extraParametersQStringList; + QString outputFileNameQString; + bool useTheseSettingsAgainFlag; +signals: + void drawRasterLayer(QString); +}; + +#endif diff --git a/plugins/openmodeller/openmodellerguibase.ui b/plugins/openmodeller/openmodellerguibase.ui new file mode 100644 index 00000000000..904f4fe57d5 --- /dev/null +++ b/plugins/openmodeller/openmodellerguibase.ui @@ -0,0 +1,747 @@ + +OpenModellerGuiBase +Tim Sutton + + + OpenModellerGuiBase + + + + 0 + 0 + 607 + 498 + + + + openModeller Wizard + + + image0 + + + + page + + + Step 1 of 8 + + + + unnamed + + + + pmAcmeLogo + + + image1 + + + true + + + + + + Bioclimatic Envelope Model + + + + + Cartesian Distance + + + + cboModelAlgorithm + + + + + lblSelectAlgorithm + + + <b>Select model algorithm:</b> + + + + + tbrAlgorithmDescription + + + <h1>Description:</h1> + +The openModeller wizard will assist you in carrying out a species distribution model using the openModeller toolkit developed by CRIA, Brazil. Select an option from the picklist below to determine which type of model you wish to carry out. + + + + + + + WizardPage + + + Step 2 of 8 + + + + unnamed + + + + lblSelectLocalitiesFile_4 + + + <b>Enter the WKT coordinate system definition:</b> + + + + + tbrLocalitiesFileDescription + + + <h1>Coordinate System:</h1> + +<p>You need to specify how the locality data should be transformed to the same coordinate system as the independent variable landscape and climate layers so that the two datasets can be overlayed properly. +</p> +<p>Specify the coordinate system using the WKT format (more information on the WKT format is available at the Open Gis Consortium <a href="http://www.opengis.org/docs/01-009.pdf">Website</a>).</p> + + + + + txtWKT + + + GEOGCS["1924 ellipsoid", +DATUM["Not_specified", +SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]], +AUTHORITY["EPSG","6022"]], +PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]], +UNIT["degree",0.0174532925199433, +AUTHORITY["EPSG","9108"]], +AUTHORITY["EPSG","4022"]] + + + WidgetWidth + + + + + pmAcmeLogo_2 + + + image1 + + + true + + + + + + + WizardPage + + + Step 3 of 8 + + + + unnamed + + + + pmAcmeLogo_3 + + + image1 + + + true + + + + + tbrParameterFileDescription + + + <h1>Locality Data:</h1> + +In order to carry out a distribution model, you need to have a text file containing distribution data for the species you are interested in. This data should be in the form: + +<pre> +#species subspecies longitude latitude altitude +furcata boliviana -68.85 -11.15 325 +furcata boliviana -67.38 -14.32 232 +furcata boliviana -67.55 -14.33 196 + +</pre> + +Use the ellipsis [...] button below to select an appropriate file. If the localities file contains data for more than one taxon, select which taxon you would like to run this model on using the picklist below. + + + + + leLocalitiesFileName + + + true + + + + + pbnSelectLocalitiesFile + + + + 30 + 32767 + + + + ... + + + + + lblSelectLocalitiesFile + + + <b>Select the file containing locality data:</b> + + + + + layout2 + + + + unnamed + + + + lblSelectLocalitiesFile_2 + + + + 140 + 0 + + + + <b>Taxon in file to use:</b> + + + + + spacer18 + + + Horizontal + + + MinimumExpanding + + + + 100 + 20 + + + + + + cboTaxon + + + + 240 + 0 + + + + + + + + + + WizardPage + + + Step 4 of 8 + + + + unnamed + + + + pmAcmeLogo_3_3 + + + image1 + + + true + + + + + tbrParameterFileDescription_2 + + + <h1>Environmental and Landscape Layers:</h1> + +Select the maps to be used as environmental continuous variables. Examples of this type of data could be average rainfall, average temperature, altitude etc. + + + + + pbnSelectLayerFile + + + + 30 + 32767 + + + + ... + + + + + lblSelectModelParameters + + + <b>Select file:</b> + + + + + lblSelectModelParameters_2 + + + <b>Remove selected file(s):</b> + + + + + pbnRemoveLayerFile + + + + 30 + 32767 + + + + X + + + + + lstLayers + + + + + + + WizardPage + + + Step 5 of 8 + + + + unnamed + + + + pmAcmeLogo_3_4 + + + image1 + + + true + + + + + tbrParameterFileDescription_3 + + + <h1>Select Mask Layer</h1> + +Select a file that will be used to mask areas from the model. + + + + + cboMaskLayer + + + + + spacer20 + + + Vertical + + + Expanding + + + + 21 + 121 + + + + + + + + WizardPage + + + Step 6 of 8 + + + + unnamed + + + + pmAcmeLogo_3_5 + + + image1 + + + true + + + + + tbrParameterFileDescription_4 + + + <h1>Algorithm Specific Parameters</h1> + +If you would like to specify any special parameters for the algorithm you have selected, use the form below. You will need to consult the algorithm documentation to find out what additional parameters can be specified. + + + + + lstParameters + + + + + pbnRemoveParameter + + + + 30 + 32767 + + + + X + + + + + pbnAddParameter + + + + 30 + 32767 + + + + + + + + + + lblSelectModelParameters_3 + + + <b>Parameter:</b> + + + + + leNewParameter + + + + 200 + 32767 + + + + + + lblSelectModelParameters_2_2 + + + + 200 + 0 + + + + <b>Remove selected parameter(s):</b> + + + + + + + WizardPage + + + Step 7 of 8 + + + + unnamed + + + + pmAcmeLogo_3_6 + + + image1 + + + true + + + + + tbrParameterFileDescription_5 + + + <h1>Output Destination:</h1> + +<p>Specify where the model should be saved to disk. Two files will be written - the parameters file that contains a record of all the choices you have made in this wizard, and a model results as a tiff image. You only need to specify the base name of the parameters file - the tiff image will be saved to a file with a similar name. </p> + +<p>For example choosing /tmp/acacia_saligna will create two output files : /tmp/acacia_saligna.cfg and /tmp/acacia_saligna.tif - the former containing the model parameters, and the latter the model outputs.</p> + + + + + leOutputFileName + + + + + pbnSelectOutputFile + + + + 30 + 32767 + + + + ... + + + + + lblSelectLocalitiesFile_3 + + + <b>Select the output parameters file name:</b> + + + + + + + WizardPage + + + Step 8 of 8 + + + + unnamed + + + + spacer10 + + + Horizontal + + + Expanding + + + + 108 + 21 + + + + + + progressBar1 + + + + + spacer9 + + + Horizontal + + + Expanding + + + + 108 + 21 + + + + + + textLabel3 + + + <b>Progress:</b> + + + + + cbxDefaultToLastChoices + + + Default to the choices I have made the next time I run this model. + + + + + pmAcmeLogo_3_2 + + + image1 + + + true + + + + + textEdit2 + + + <html><head><meta name="qrichtext" content="1" /></head><body style="font-size:12pt;font-family:Arial"> +<p style="margin-top:18px"><span style="font-size:23pt;font-weight:600">Run Model</span></p> +<p>Press the finish button to run the model. The results will be displayed in the main application window on completion, and saved to disk using the output filename prefix you have selected.</p> +</body></html> + + + + WidgetWidth + + + + + + + + 789c5592cd4ec3301084ef790a2b7b8b905b8a2a22211e01c411097198b55dc1a14582724088776767373fb0add7197f9e75b2c966488f0f7769d8741f679c5f4b2a2f784f43fd3c1ebf9e9e6fbfbb7eb74bf6bf4e97fd45d7e754d2fddba9f1daf626d97a504ac8fd585c6ac8717b385056cafd8831242831d612b251962bfefc94290492318bbc1088da802af09f20c3081434fe25020bc346b20a56c2cd96bc96b89889aa6d1451168bab85140b7358b2cc2988e6e2a160f25c1144b8401379757ff61ecab44a4a68a36a9bab892ebe38c70924ce800ddeb3720a621e9e05a7ca69ae26716ff4a28252c4491647708f3d27cf6941bc23f6ecb628c209d2e6beb1a3526db045b6a7cd24b394393c43ab81e5fdd8de4aa35673122ca479fbdd116025ad8964ab272dc0fa1db435a6b7fd73d3fd02a57dc0b9 + + + 789cecbd5973e3489635f8debfa2acf1d636c64f3ba98779a04451a4426b680d8dcd037680bb488aa2387f7eee72ee95083122b3baaa32cbba33dc14a113041d80c38fdfd52ffecf7ffdede9fae26ffff57ffe63360fe765fcb7b808a77ffbafe475387cff7ffedffffbfffb8fffdcdbdaffdbf65ee36f3bbb7b3b7fdbf9cfffeb3ffef366feb7f86f97e351ca207c21106cc91fc6e9f63a4e8ed671345ac7c5621dd79aeb383ea8e0d53a9e54fa9f7cabf457b9bedeee3aeecfd7f1bc5bf9fe721daf2af797a695fb4dd6f17b56e93fa85c4faf72becae7e3cafdcfc3caf9cbcaf88cd7f1acd27f81ebaf37e203c6d98de0edfa81e2aef6b773904411e3d348717d3b96ef9f4e81772279fef931f0617cc8f8589fc7ee41aa9f9f5e2aaeef46999cbf048ef4f8f6a1e0fd8358cfd78981b3483e3fcd1d2772bf5b8ae9fa1b72bd33c107f47d3ddf18388b65b29eeaf51dd4b7f5fca75dc3f1ae5cef09f05ebccdb8ac01a7712ce3a3cff7a0b11d4bff2d9d9f751a1fedef0438c578f51dcbf5b64e15d7f775fcba73e0ba9e7f700b8ce7911a0ee350c64b9f7fbdb193e8f8eb7835683ce4faba3a3f1bf4fca4bf4ee1785fce6f9fd7b5ffa31418cf6bd0054ef47c8327e02c96fbcb771437b6f5fc05fa6bece0f31278573fcf9f1dcbf5bcde093ea4f195e7d11903633c4e57c0f5784f9e871ddfd0ebcb9e81437dde69029cc632beb9f2ebb0b1a5e7ef05c0dbb8be57c121dd9f1c5fec2b6eece9e7a73a9f22ba1e1dbf7b60f0a13300aeebf5b6b7810f713ddf81639d2fbd1838d5f9323c73acd7a3cf2f6a6c299e360debf5f7f781771219afb403bc9be8fc3c00ded3f1cd71fec66122cffbf441704cd7afe3dd07aeeb78be7680237dde790f18cf7bb06f58cf7ffc283831be657360dc5fa6e393d0f5caf50def80f712799e651d785faf37d5f523a5f924c7671930e64f5a732ce71fed3bd6ef0f80f7f57e9353e0c3a42ee3aff797350e12797ee12b702391fb8f0e81c344eee754e6fbf6163d3ff97ef2ac980821b8f656915f67eb7874be8e1715f934afacbfd3f775fc565bc76165fd6e4e2bf2a1223ff3abcae715793aae7e5e91476905bf1595fbadc8d3c98f4afffd8a7c79addcff601dbf3eade3f63be44d84f5ac58973f277b9017903f5d95477bb4fec97c3dd1f9b547f24870bb05bcabf3bfd583bcd8d7cfdf6e0c63bd3f5e97279d1dacfffbba7eb76360acd7fd03e00cfc3ef2f55be5d11bd6cf7d9d4f6565fd1d346d7dc5fc7f595f4fdb3bebeb61ebcdb17c7f3cc4fab6a37c28dac0e04f7788f56e5be5616b0ebcaff2a0d704c67a909d0247b18c7739c6fab8abfc6da558bf202fdf8e7d7d94fbed5df87a25c7e7a1af4f72bea00dbcaf7cceb1be123fe5f8ce0fac37fbda5fa9c7c774bc7c9e627d223eeaf16dac3f75bd9ff6687d7d1aac6c3dd2f12ca7ebeb5316adaf4fe9fbfa7a54da7a52d7f5239e0137f47ee247ac0f87ba7e44afc091ae2f49457f1d5faee3fe73e5f38b755c56d68bb2c2afd72aae1c9f54f5cd4aff8b8abe1b1f57d68761a5bffbcaf1157dbb56d1477b157df4e8611dbf57d68fb872be97cafaf79e57faab5c4fadb2be4c2aeb715e19ff55b48ebbd0d769fd91f9bfd8034e22918f1de8e3a6cfad70fda45feaf5a9fcddaa6fe9faf57a030c7db3f96058d79bd76b60ac575dbdbf6dd25fe57cddd4b1f4d76c0043df5b5d38167ebfebfabe4de797fe56e786f57ccb33e06dbdfee51df08e5effeba563e167b7bdbe1e1f8f81edfab2f5f5b91b3b96fe17ca971dba1ec1f39663b9bec50b30d6f3f9cab19c7f1900efe8faf77a05bcabf7f3f2e458d6a3ae7e7f97ae4fced759002791acbfad0238d5fb69b51ccbf8adfa86311ecf90375b7a3dc717267ff4fb47a78ee5fb8b9d75f9f4fa1d7847af77feea58d7cf9963b9bff70018f6d1fb1c18faf22c772cc78f7781a19f16e7c0d0dfbb53c8c744afef756518fa760c9ceaf33c3e762cf7f73e76f92ae3793c5a97b7afa561cce703c85bc887c5e5ba3c5eb40debf1abc375f93cbd742cf7f7b6e558d6dba31d60e8e7e353c7f2f9b8065c5779bbb0ef433f9f198e757c8ee6c029ec55d89374ff72bdad117006fde3d0b1f25ff9b84ff359c6f7e89b611ddfb7d4b1dedf36b03def8663b9fef7047857fb5b4686319fea8ea5bff92df09e8ec7e4c4b1f4b7dc01367dc7ce0f7d67d2023ed0eb99ec38d6f9340536798af1a0f1d4cf618f933d26e337aa01c3fe997d074ef4f3e98b6319cfe62e70aacfeb2803cef47c85eaeffba6cf9ceaf372fbbefb029ce87cedec01633d6eab3c3cb0f5b8993ad6f572018cf5f9c8ec7daccf8b43c732beb30218f3b1b30bbc87f9fd6e187c6f3896ef2fb780f7c1df77c7329eafb7c0b0d78676fdd037473f1ccb780d4d3f85fddefc061c623c3bc0918ee7a8702cf37f6ae7833d3c7a752cf733bb014ef5f897b96319cfe90418fa6fcfb13eaf17f863c8be95e73d9b3ad6f3e1f9997d9ef681a11f76743eb87fe53802867fe5e8bb63e9ef489f7fdde4ddb161c8bb9396637d5ec7c0907fef6dc772fed79a63f547bc02839f9337e03d7d7e8b2760f8339aa163e56bc7b1f26d1718fe9971e9589edf0beedf9effa200867f6874e8589eeff00218fea2f4ccb18cd7c08e8f75becc478ef5f95c3a56fece8061dfbf587f993ebf12e36ffe8b7ccbb0eacf535caff9cbfa3130f4f1de83619d2f63f8bbe8f9ab7e1e3a56f9abf2ad61f2b93b01863e74dc722ce76bebfad4307de2edd5b18c7f730c8ce7bf300cfd62f6e658c67f1538d6e73503867d3785ffcbfc6fcd9563397e7a0c0cfb6d78e9589edf8bd9870dbdbee109f0a17e7f7eea58ce377a722ccf33c7f898fd361e3996f199bf03e3f98fb71c2bdf6f81a13f8c62c7f2fde1836379fe431b2ff88b46d786f5f9cd80697ec8f747378ee5f944f04f9a3ff12504ded1fe7be78ed53fb60f0c7990ec3996f3e58f8e65fcc35d60f88726b85eb237653e8cebc00d3dbe6bfe48e8abcd0e30f4b58ef92777a15fdae7982f8b08d8f4b513c7f23c471dc7f2fca73f80613f2fbac075e80b0bc73a5fdf1dcbf7670fc00d9d0f83d2b1ca833970a8c7cf8f1cab3c3871accfdb3e07ffc78f8e753c66c0897e7fda70aceb4d0c0c7f6c1a3996e75de27accbf39367fedb61e3f881ceb7a02ffaed9eb39ce67cf7f8ceb25fb5d3f7f702ce3d73f762ce317e1f9993f3037ff30fc095db51fdd5fd2e91ad6f5a17305bca7f824772ce77b37ffb2f98fef1ccbfc7bbb75aceb45007c007be60d18fe98e37be0867e7fd6722cdf9fc17f6dfaeddbcab1caf733c7b21ebc5c03633e4ce78e757df8068c78ccf0ddb17c7ff4080cfe8f13c7325e33bbff14c7370cebf379898033ac274f8ee5fb836dc7f2fc13e56f68fe98e41018f2228981e11f2e4e80e1cf4fba86f5fbe90b30e4c9e0deb13caf537dbeeedfea98bf1ef64ae71418cfb75d0386fedc0a1ccbf84e32c7babe3f0083df4bf8f7e979caf35ac2ff6ffaf56ce158ed975d60e8dbbd67c732dec74be008f3e30e18f6cee4d5b18cffa00e0c7e8e5b8ed5ffbf6718e3a77c8b4c7febdd3996e3875dc3783e3bc0885ff40be05d3d3e9b19d6fec31e30e219e19163f51ff681f1fce208d8fc877a3fb1e9efdd1130eca7cebe63d52f5bc0161fb9752cfd9d983f12fec571cfb18cff7b0adcd0f9f01a01836f478fc0d0c7e773c7f2fd17bb1ee8e3f307c7aacf14c031e6c31130eca7f1b663e5e30b30f8333e36accf63a8eb4becf276c7b18cd760010cf919bf03633d8d102f327f6cb10b7ca0c777d4fe4f4c7fee9c03c33eea5c00d7c1a763c7f2fd93ae638d575e0243df3d7e73acf26bcbb18cdfc915f0a13ebf95f587f5ad73020c7b68f9c3b17c7fb60d0c7d787ee558c6b77f080cfb683e06863dd4ffc0c2a744c733713e348021cf26db8e65bc12c39057b1c5d3b03e4d26c0905709aebf11697caaa3fa786af6467be058f97109dc803fabed58c6b71d0243bf6ce68e555f0c1ccbf8bcc15f4ee3abebe7c2b13cbfd71838d2f15b9c01dbf8dae7d02fa763c76a5fbd38d6f508f1405a8f347e66d767f169e5a3fbef47a1635defb780a14f267560c88ff20418fae2680f18ebcbb00f8c784068f1ca43c527cad7cce479e7c6b1f2e39b63f51f5c0343bf3fbe752ce3bf4a81317fdf1e8123f80b8e80631dafb708d8f4b30760ace7e343c3d09fec73e8eb43f5bf67361fa777c0263f43c7723f2f35c73a1fb780a15f45dbc075c46771bfa46fcbfdc575e0483f3f16be6d6fb9bebb003ed4fb7f1d03633ebd0d80631dbfd10c18f3e56d088cf56f84fe5d9ff8068cf56e78e858ce3fed0063bd7b7901463cf854f49fed6dd3cf5e07c0781eef7d608c77f25db1c79b0e1d6b3cee1b30d6d3b2e1583eef07c00d8d370597c091e2b65eef8ec9afa4add8e66b7fe958aebf2debc7f6aeadb7b503c516bf9a54e2d7ad73cc975db5b77bd57cacbb753cae7cbfa8c49bde2af957e9de3a8e2a9f1f237fe0603b94f9b9aac49ba695e3a3fd757c7abd8edf2bf1fcc9d63a7ee9548e3fad1c5f89ef053beb38abe05aab72ff95f8d5bb8ed7fe5ed650bedc56be5f8da757aeff44f9b66bf64947e58dfbff8fcd7fbe83fca96760f8133bf0f71e44fa7959f1ef66e64fb4fc2ef377c1dfd67d0786bc19c23f64fe8cf40e18f6661bf6baf9738e3ffc399abfa5ebabfb638e878e657cba0b60d85383efc0b8be91d9fbf037b475febabddeb3f83af4f38ee517413fefa5c0b0b7864b60d837a5aea71e7f2f618f98fd94de009bbf64ee58ed1dd87bb61e157b8e35bf05f178b3775a3abe91f9f74f3ff293d43f0ffdd9ec810ef43dd387dba69f425f2d1ac0909f7dd3f7b0de8df139ad3f1a0fef3ad67c399d0fae8f0d757e26e6ff2bf781b17ef54c1e5b7ed8cdba3c1d04ebf2299d413e407f0ae7c0c8d74987ebeb7164eb3be2f1c109d6bb2851fdae122faf55e2dd6185df2f93ca7a568927d72afd8d2af1f515e2177bbb07eaef3ca9ac1795fcd1b872bed7c70abf2bf932a34afe515c5d4f2aebf16b65bd7cabe497c695f5695eb9bf4925df68f2bd321e95787d2d5ec7fdcafa359855e40b9e87f9f3bbbabe7afcb9b5078c7863a6e7df317f5857c7d7e3bfaf1758ff707cd7e28566cf5b3c0cf6e1e00a18f677eb0ceb1de245ad7b60f0a977050cfd62f6b8befe653f7cfdd3f96df105cb9753ff89fbc373f78f237fe76c7d3dec98ff15fa64fb1bb0f98b2ddfd3f239cd9f0c7e9797ebeb61cfd647d883a5ad7ff01fceaed6d7bb01fc95c6df4e89f5ccfc8f97c0f03ff516ebebdf00fe195f6feaebeb5fe7c9d7378dd757fc2be5873f43fd47f0c778fc21378cfccf2930fc0b2d5bff20ef72cb87c4f59517ebeb5b6aeb1fecadd753ac77f6fc60efb93d77eb58ed09b3dfb0fe653affdd7e195a3e11ec93e10418f321fc5159ef9658dfa0af166febeb5f3c5d5fff3a95fc9c5e7b1d1f55d683e34abee071357fa8a2eff42bfad2b4a2bf2d2af9f069455f6c57d697b7caf9a615fdb157b99fb4929f9857d6dfc9cd3a9e55d6af7e455fac55f2a726f5caf92beb63ada2cfce2af94727c8d7a4f54bf525e47b59bcfa74e458f30db67dfd53f95d5b5f0f5bb85ecb4738c2f92cbe3dc3f59affa5ade3e7f943ed8f7c22cd772981113f6b9d38d6f54e9fc7473ed1c230e263c847b2f8c6db7760c43fdfe68e35fff211eb7703f94347ebebfbc9be63d557bbc0c8273aad3996eb5976d6e541f300f200f19be3d0b1da8397c0f0e7af7a8ed59e40be93c5fb66d61ffcf7ed3bc897509f67b3be2e6f9ab163cd276f03239f6665c743df6d19ce22e1eb0af948962fb2ba0746be51b374acf6bee72361bcaf8021dfde078ee57e8e26c0c82f6a3f01237ef1163bd6e769f94cfb7abef11218feedb17d8ef5bfdd84bc85bdd1ec1946be91d923a9deef911d8f7ca2f902f2d9f287ea8ed51fdb30f98de779be2ecfdfae81e1df7daf3996ef1f05c016bfb1e3910f333b74acf9592dc7eaff453e95c98f39f2a5ccfe7fc7fd9afe306a3b96fbedbf3896f9d3d2f1777bab83fc1f9a3f3abf909f63f948a7fa3c3ddf68716718f973278e35df60028cfc8595e527217f61f56a58bf3fbd70acfe5bfbfe9ecebfb9e5f7209f65b1ed58efdff291309e2fefc0f0afbf668e757e1d38d6fd2ef7c0b02796f639c633bb0686fffb05fb832c9e74a2fa91e70735b1dfc7f2814e918fe2e3b76f18fe26df0f84fc9053c3e0d3b563b9ff96e57fefe87a3c2f81619fb60cc3ffdd8c0c6b7fd39663cd0fb2fc72e49b8fb60d43bf6b3a96f178c9812d5f2801863f273b772cf3f5ddf2991a7afed13330e6639938d6fd4696ff83f85fb10286bedbc77e298b070d91ef64fec2577d9e751a7fcd9f51f9e3f9376fdf802dff62e958f97be058be3fb3cf113f5f59fe0ee4cdf4cdb1c6d73ef65bc9f74f4d1f3fd0e73fea1ac6785d38567bbf0e6cf93701b0e5dff41ceb7e988f7c1b19bff72930fcb5b3c8b11c3fb6eb853f7c68f603f4cb911d8f7c9b58d747cfb779b5fc8d2dbdfe85e57b409ebdbe3956ff7f04bca37c7eb3fd5e18ff690fd8f219a68ef5fe13c79a5f68e7db433ef1b663cd27b17c15f8672696ef62f93047c0b61fe2dab1e6ffbf3bd6fcc18f7c17e92ffbe658fd53763f98af43bb1ecb77b17c1ac41bc6967f027b2886ffc8eca13ef2892c1f252e1c6b3c4bf9e8f922ddae63cd57db0586fc7dcd1debf3b2fd1c18ef69080c797cfae6589edffcd0b1fa732d1f03fe9ff2deb1ee97fcc817d1fe52c76acfec3bd6fc10f38f419e67978e35debc742cf3bb350546fce2ddc603f905af5dc71affb6fd7ab0dfd26f8e75fdb0f35bfec0dcb1da8f0dc7f2bc0a7cdfecbd21eedff249d2b663791ec12d30ecd7680b18eb5574ea58c66ba1f3d3f33916a163b9df13cbaf40bca76ff91d98afbdccb1ae07cfc0d017de9a8e355e0fff9feb0b13c79a9f6df91421f2872f1cebfa720c0cff6376e558c633b5fc0fd8bbaf43c79a9f67fd99bd6ffd21fe3fb1cf216fc713c7fa3cce1cebfe5ecbd7807d9fa23fe28fae6f0f86e1dfab01231e17f4802dfe84f359fcbfd871acfa9ae56be0791d5bbe05f48bd5477e85fa2b6d7f26fca5c53530f2255ef61c6bfeda0a18f36f62fb9f32c48ff5fa3c3fa27fee58fd1d03c3f0b758fe83c57f2bf9107d9ccfe26df147fe83fa0f13c76a5f298e4d5eb66e80a12f9c3c03435f78b1fc04e80bc7ef8e653ebe1d39567f50088cf8efec1ed8f289bb8e355e87fc02cf4fc881313f26c887f0fce067c7727c027f8dadc7c99963f5bf993f1afe907ee258ee272c81c1e7e10018feed00e363fe9e08d767f1ca96ca83c4f481a5e523207fa11d38567fdc3330f483d5be63996ff30c18ebdd2406467ef574e658f713eafae6fef421f6bb593e6d0ffb6fcdff94bc3ad6fdb2b85ecf27580223bf76f0e858e3174360f8ab623b7f5dfb6bebe71ff903a78e359fec1118f1d979040cfda5a7f3c5e3f3fd6f8e353f08fdfbfedfc0b17c9ed97e61c4e37bb6ff17f18363e54766f2aadd05b6fcd91760c893b9c5bb21ff07a7c088e7c47bc0e05f72058cf991caf87fc493e35b60f03195f37fc46f932760c46f33d12fb7776cbfe47ba5be445af14fbd55fcf9a3ea7edcc63aae55eb6154f6d76515ff5dafe2ef9a54f627b674fc76b71b3bc287d74afca056d99f37aef80b938a3fb0568977a4957869bf121fa955ea69c49578ca5be5fc49355e53d93fddaaf80ba715ff6854f157169578c591fbef908faefae2f64188fdc20930fc6f5d9517ee2fea86c0b67f4efd59eebf29cddf03fda063fb8fe00f38d2f9eef67d0bf126b3efdb8561e56bd904c67a34367b14f2611400439eb73ff64f68be9ec52fac1e85d953b05f72cbf7877e7c8a7c79f3779d421f77ff62257ffec8ec15e8f703b30f909f9e213e6cfd77553f707dbb037dcef4ddac0f0cbe17a6df617d29a01f9b7fbf65fa1efc27a786e13fea98be74a0e7cb3fe2b9aa6f9e0343bea5b67f1aeb4117f2dbfc57c72530f493b6e92fd04f06c89734fd6484f886e92719f417cfafb4782ef24f469375f998b65c1eaabe3c5a978fe5deba7ccc23c79a2f5d5b978fc7cd75f9d6e961bd87be9be5ebeb77dfe2bf56afc1d66fd46b48df6c3dd6eb1b58bd06e413d5904f65f9569d50d75bb35fa24bacbfc85f1957e28f934abc7456dd6f5c5d6f2af5196a9578c4b4b29e1dc39fb8dbd8d7f857259edcc47ed2ddfd7dcd4fa8e68754f64b6795eb6956e2bf41455ec4957c95b812ef1857e4455ac98f29abf2a0f27952913f41357fe6b072feca7a3aaad65baadc7fe715eb6514697e83ca1bdfaf7c1a02c35f9163bdb5f9576c01c3bfd26a607d857ffd14f160e35f6786f514fed753ac97b6bfb30d7f96c56b5ad87fe7fec489635d2fcc9f87f5b26bfbe9cc7f67fe33e8dba7e62fda427ea0e5cf6cab3c68dbfe30dcef29ea0d793ce5637f99fac76d3f97d50fb2f5d9f6835d55d66b7c6eeb53fbb8b25ef77cbdd6fc59f3f7c05fd141fe8ec5a373f3c7d8fea6dcb1fa276cff15fc2f65b5de85f913d0ffa9ed3f41fce1d4ea01c17f31b80086be37f8d87fa2f707ff0bad27aa8f61bf8bf90306b6fe431e0ccd3f60ebe199635dff956fa1c52bda58dfbd9e86eddfc0faddb3fd0db6bff2c0e583eaf70bc79a1f3282bc40fe6186e3495f54f964f629e445ef06ebbfd50332fb13cfb31c01c3be09115ff77cd52dc80be403f52ddf1df6dcc0f2e3e1ef1d1c38d6fca819e401ecb3c1c3ba7c6859fe34fc4585ca0fcf874e51afc3e3e5c827a2fb95eb2b2d3f08cf27b3fa3f568fe30cf200f9a4a9d5df803e1e583e27e441aefab9ebdb710d38d6cf6b32bedb7b74bccc9f7e251e3eade4bba4157db3569107bd4a3c7c5a896fc715f91056d6ef5175fdaeacc75125df26ae7c3ea8d4bb0babf94515fd7c5ab99e41b5de5045ff7d37fd7a674be36b266fe901cbf556f22d07d57ca48a7ceb55f2b1e26afdbfcafdd4aaf5892ae37d64c76f6fc9fcaa55ea7dac56feb9ccff77938ffb5b321fdeacbf832ddd9f93acdfdfbb9d3fded6f882c5e7f7b5de4407f90107072a7f5e91ff74d0d0f85ed7ea891c6a3cfc14f606d90fd25f3b73acf9bdf78ee5fb27b0ef487ee9fa7feb588e3fde76acc7df39567fe20fc732df5fe78e359e7def58f575d44324fb45eeefe4bb63dd0f73ec58fa6b3d3bd67a0903c71a9fbb73acf59becfe516f653171acf277cbb1c62f878e35be766818f17de4cf91bda4f1d6dcb1d67f183a96eb5d7e73acfbc9771d6bbc3076acd76be30379f98e7c13cbcf580e1c6b3d87be638d2fdaf74d9f281d6b3e03f427b26fd4bff8cdb1d6e7881c6bff43c3dadfb2e658f505fb7c5bfb7b8f1d6b7fa163cdaf3f71acfb6f9f0d231e6afd219f78d975acf1bd91613d7f13f6b6d9a753ab8f83f8f364e158f703613e5a7ce965e858f7a30f1ccbf95e5686117fb6f3435f2a1f1d6b3ebfdd1fecb9972dc37a3d2f36fea8f7f772ea58fb7b72acf549ecfa918f57148e455ebdebf1db5be1b68e1feaf16ca5dbea5f84bebb7db023df5feafcd8ded9db55ff813e4ff62fa87eb804b6fc22f467f5798ebf39d6fc914bc7327e27c7c049a4f11fab3f84f9bc7a00ceb4bfb7c4b1c60f0f1d4b7f73e5afe70bcd3a86919ff1ec58e7c32930f4dd59a53ed10cf94b565f7466f948d0875f9a8e757ef7816d7f827d1ff1b3173b3ff4c9173b1ef1e397d2b1ee7fd901867e5b1e3996e7fd62f607fcc147b05fccdf98bf3956ff86f51f617edc3a96f57a1200c3be7f47fe13cd078dafa13ede76b8a37c45fda4ed6847d757e5cbce0e993cb29ee8f57bbe55fb16f810f201f5952cffaad977acfa761d38d6f9d17e702cfdad50ffd5fc57ab03c7ea5f7d76acfe20cbdfc57a3cb7fa7e58ef8ec68e757e205f8ce693ee377b712cfd4faf1c6bfe90e503231f6a923ad6fca6a963cdb73807c6fc5a5abe98e51bd8e7c8979a7dd49b92eb1d878e351f04f96bb65e15b87fb30fa6563f17ebcd34368cfece1c4b7fd32530ec9dfc036bfed5b363dd4f9e00c33f5f587e1be2e3af76ff88179685639d7fc8af33fdbff7e258e6c712f3cfea632e578e353e64c7a31ec064ea58eb27c17f4cf34ff31b53e050f589f677c7d2dfd10db0e5d70d1cabfc8d8051df6bf5e258f58f1dc390579e7fa7f37dd973acf5b1ce0d233fec0d18fe83a39563bd3fcbcfc37ab66838d67824f2ff4cbebe9e3956f9776218e743bd329a8f1a0ffaa817a6f2cc3f473cfac1b1ced77760d4a798d71d6bbced0018f96f2f8563b9fe49a5be58cbae1feb6561f984b03ffb53c75aafe60730e4e3b8eb58afefc39fadf936778e351ffbc4b1e67fa17e34cd5f8dbfd8fdc29fb1b47c44ec77cf178e65fe2c0d637fe0a0e358f55dbb3fccd7a98d0ffc0711e6a3d9ab31fc77965fd0ef39567d54f9b7b7b3aff2fa5dcfb7b74b06855c4f0a7cb0aff99efabcf6f6f6eb9aafb40b5cafab7f08fb15882faabf3e0087c8e77d03863edffc0e1c437f3c01b67cccc430f4cd7d60cbc73c70acfaf1b563950fe786919ffa040c7fd9c2f75b603d6e1b863f47f5913d5aaf95dfef8e359f0fe363eb73f3c6b1cc9f05c6c7f4cdd76f8e753db57c4ef0653a0046fc639238d6fe3a8e65bc57962f0afd72d6350cfd7ee658eb3b60fc2cdf713c77acfb498f1dab3fc4ae07eb7f8af1b3f5fbe5239f54eb810f1d6bbe95edd7433e647eea58fd9fdf1d6bbe14eaf559be48df30f2412633c72a4fef8163f8eb7e38d6f9b5079c80ffb963d5b7ae1d6b3dbc0218f5dd5ea68ee5fa8a0bc75acfc09e3ff24be25dc71a2f0f1d6b3e05eaff7afc15fb1b2dbfa4fce6588fef035b3d39c4cb885faa9f219fd6ecdff691638db755ead33791ef4a7cd27cc54abeeeca3e4fa1dfec03c33e5c2d1d2b7f0e0cebf37fb77a7bb0ef5e1786510f70e658ce7f62f50661dfbd751ccb784ef680212fdec6c056cfcce289b0c75e7a8e559ff07c60ccefd4b1eaa7478e351e8ff1b2fa8313afbf8cfcc267c79a6f5902233f65d077acf1fe6dc7eabfb47c65d867e90330e447993a56ffc4ae6319ffe91018f522fadf1d6b3ea2e54ba37e473e73acf3b7ef58e5d12370a4e391e0797b3df88ffa889a6f75098cfa88a3a663f51fbc01833f71e658e64b74ef58f553eb1ff94841e158ebbd287ff62dbf26be71acf5b88e0c23df260046bd96fcc930f6d363bfb0e567bd219f7a373ed07c73e45bef4575bd1fbdfe83fde450f333903f6dfea723e4139b7d7a5407863fe8a8128f691e01a7d08790af6cfe9465253ed3b2fc67f8538e2e1cebfe8cb163dd5f61f516e1ff987ce47fab3e76e458eb5f58be35f2c197b78e75fdba0386bc59341d6bfdc04760f833264f8651afb370acf68b5d3ff2c573dbaf08ff465ec9175fe48ed57f67f129e4431f5bbe37fc1f9307c7eaefdf72acf97316ef42fe53de75acfadd93633ddf2530f2cf53bb5fcbdf7d73acf6ef9e63793e2ff6fc505f64183ad67c01bb7fd8d3d9ad637dbf41dbb13e1feb0ff57512d4a7f4fdda1dc79acf68f7877cad6ce858e595e5cf23be137a7d78e5cb11c69ff8a6f57f02c7723dc177c7ca6f8cbfe997d1c7fb47747fe0be61e4c3e1febd7e0f9e97c5fbcb73c79a7f85f961f1a277e49fdb7ee525f2d70f7643f97e1bf9f0e64f3a42bd46b3ef57568f13f6d611e28de65f3dae39567bcede9f82fd01ef787f8af98b5edf1dab3fd0ea71c25f7474ee58fd1f13c7ca1f8b77c25f34e938d6fa7c1ff53ed57f8efdb8e63f5a8e1dabfd83fd0c26df9a35c76a0f5b7d51f8934603c76a0fed39d6fd10f6fe17f0af78310cffd1bb63b56ff71cabffc6fa87ff693474acf9e6c78eb59edb0d30fc93838163dd5ff3e858ed2ffbfe21f269ecfe21efa29a63ad976efb39b0df6158d9ef50c48e35fe69df87ff206b39d67ce595637d1e566f22c1fb39ec7e902f99db7e0decaf1dd8f3ccb4bf64ee58e59ff2d1f75344778651bf12fb3d886f72fe2871acfbe1ecf86dd417acd4378d32c3c8376f3a567dcaf0ae5e4f86f1f07a85183faf871a38d67a5cd80f63f1dd781b18f99a358befe37d30efa84f7ab017aa3f0ff534fdfd4e43c7eacf47fc9ef8aafe6dabaf6afee11bc772be23ecef30fff0e2dab1fad750afd3f4d185d5ebb0fd2a85638d7f593d55ec57698e1cabbd6df962c66fdb6f02ffdca4eb58eb277f7caef9fb565f04febaf78963cd0fc0fd99bc6c668eb51e9fbd3f09febbc9bb63ad4fde712ce72bac5e2afc77c59363adff9939d6fd7f962f017fdea8ef58f76f8c1cabbcdc77acfbe36d3f0dfcd16525bfaecc1c2bff6c7f8cd58f7d75acf9ef75c71a0fb3cfe10f1c068e35de3e71ace369e365f5422f1d4bffe1a163f5ffe37d53c46f7dbf8661d87fb19d0ff5ab0aabe78a7ab351d7b1ca4f7b3f15f215e2d4b1d61344be8bedf70932c75a3febdeb0f2296a03431f8e5f1d6b3dc38ffab4ba5f1ff98c8d3de807f63e2de4c38d6dff11ead3868f8e353f1dcfcfebbfd58051bfb6adcffbd0fc352733c7aadf3956be1ca13eaaf967565b8e75ff84e5d3c0dfbe1a39d6f825f2657c7fd3d2b1f20bf555cd1fb9fcee58e38375c390f70f8e75bf98d5b3857f72da77acf19c57c7ba9e593d5bf82bdf4e0debfdf66c3f14e4e76ad7b1fa4b2af9a393a563addf5b3a56fbf303eb7e7ebb9e06ce973896fb291e1deb7ecb9563f5afd8f9e1ef1cee3b567d7ae158f7b7597d0ef3e72f1cabfefbe058d707ab7784f85386e7eff669a5deef3c75accfdbee17f5e506e78e551fb6fb49b07fae523f24bd70acfaed896395a776fd998e4f68f57a618f46c78e95af989fe68f0d73c7aa1f633f9aed8f088f1dab3cc07c24f9abebc5b363b99ec0fab3fd62d89f67fa7370ee58eda3a1638defd9f9f6a10f58be19f259fb56bfb8aed753db712cdf0fb781f1bea1f0cab1ea83d84f66f66f1bf5a63c7f71ee58e325561f18fed6a34abef3eac4b1eaa756dfd7de6f62fbc910af58583eb4edaf6f3b96fb5b7abd64f89fed78f853172dc71a9fb37c39f84f5fee1dabff7ee258ed49ab470c7fea9b7d0e795c58fd65c8d3d58e63f5d714c0f0b74ecf1dab7db9e758df27f70318fed6bc526f797eed58fd831ff59635fff3c0b1fa6f478ed5be453d1c8b6794916395a7478ea5ff77ab978cf846669f437e664bc7aa6fbf18d6f9fc6af7077f6cffdab1ee87b3e78ffd7fa57d0e7f52d473acf2b5e558ebc123bf91e4affaa3301fcc5e0d1b8e55be61ffa4f96fc3c230ead562ffa1f135ec1b86bc5c3856fd19cfcbea4107a9619c1ff5ad4d9f0ecf1cab3e3d77acf698e5631e60bf22c6c3eb8fd9f991af59db76acf515c157cbbf0ccf1d6b7e17ea4ffbfb65ae0d431fb6facdf04fb56786513f6fea58fdc1562f0efa76cbf63bc25fb5ba74acf2daf647c25fd57971acfe00dbaf60f5361ac0f0ffae4e1d2b3ff1fe37f3ff1e2586e1ff3d71acf56df17e387f1fcdc0b1ae978f8e359ffb1618fedfd59d63b5af6cff27e46bf981959fa84f6dfedf59e258edd75dc7ba1fd7ea5399ff3773acfee46f8e35fe67ef138de0cfbf74acf923078ed5bf3c76acf94e36be88c7e41dc7eacf9a3ad6f7d3daf3b37afbb78ed57f6bcf137c5e58bd40f88b079963edcfe60ff27d737b1fa9edcf3c70acfcb27adc90d7239c9fe4b18c4f0df5c6cdfe0d3fb0eec7b4fdb1f03707f67e40e8d381d51bb7fdb05dc7aa8f5b7eb3ed8f2d1debf9f0fe42cf875e3ad67ce0d0b1da67a8874efcd6f5c2f2adb17f2f19021fa2bfae63ad577ee058f96eef470c35dfb8adf321363eafae0ca3de10ea719b3fab7d6118f5305f1c6bfec90ad8fc59bb8e555f5d02dbfeb08961e4db58bd71f88b9b8163f507d97e62f8839b678e95af95fdc4d39a63f5cf8e1d6b7d82efc0f0072f4f1ccbfdf4ec7a204f7bb963cd3fb3fa96f0072f168eb53ecfccb1fabf6cff33fcc1c59563e9af081cabbdf2b19f4af3e3b61c2b1f878e359f636a18f2d5f2e911df29868e757fc2c0b1f2ddeacf23de93d9fddb7eb2a661f8b7761cabbd62fbb5e04fcef71c6bbe426618fb7d71ffe6cf8a0f0d833fd78ed5bf8ceb23f92ce355b3fa78b06f93d0b1ce7fdcaff99fc38163dd7f8ef94ffab1cafbc030f4df3bc7babf0bf3cbea91d66e1d2bffecfea13f07178ef57a761dabffd0f6c735b03e7c033ec4fb3b315f89af2acf1f1dcbf504fb8ef5fdc0981f568f39bc74acf977ca57af8f7fb2036cfea88963959fd88f6dfea823ab778ff8cffb0330ecdb05ea0dbabf38762cf7d3c981e12f5e5e3bd67c8b17c79a6f60fdc33f3c8b1dab3cbc73acf9eb37c0f0172fdb8e35be6a9f433e2e7e38d67ce31218fee3b707c75aef3f752ce71bdaf7e12f2e52c7caa75dc76abf60ff89f33172acfe9d27c3a85f64ef0b40bc67b8e558ae3fdf76acf1f90418efaf4bf0be02b75f03c7ba9f7fea58f33df07c7c7fbfeddf877f39c67e1aaf0fd9320cf91838d67883d5a7847fb986f717783d8007c7ba9fc6ae17fee660ee58d763d443681ce8f96b5dc390bf378e355e8de7e9fee8ef8e959ff67dd38f4f1d2bbff61ceb78627e9abc8df07e09e29f3c9fc4f613a19e7cb8e558ae273873acfaa3ca83d4fccf27d86f44fc54fe7580e13f3eb2f717c0dfd4ba0306ff8e9e1dab3f7cdbb1c6c3edfbf0f71e4d1debfb2bec7d08f0f736b71d6b7db28963b5af513fd4fcb9f3a563b5e7ee1d6bfeac7d6ef153bcbfc0dfcf70ee58fd67f63e07f877177dc79aaf903856fe8d80e1cf2d2e1d6b7c2b74acf5abf0be06f3efcef71dcb78f4adbe84bdafe087638d17b48011df19b71dabfddb73ace7b3faaa88bf46b6ffd8de3f3f72acf927bb8e355e86e7ebf944f6be09f883e36b60f88b828563ad67f351ff5af557dc8ffb83f1fccdde0cef1debfcb5e3e11f0e668e553ed9f5dafb296e1dcbf8c6781ee62f8e268e553e62be9bbe5a6b3b56fbf6c5b1ceaf37e018e77b76acf5b7bf39d6fd47fa3c32f3f79c9c3a56ffd112d8fc3b63c79aff88fde0e6df692d1c2b3f23c71aaf42fd5c7f1fdad2b1e65f65c0f0afae0ac75a2fef1e18fed4f9d4b1cecf07c71a0f47bd72935fa36360c89f39de87e1efd7cb1cabff07f545cc3f5a868e75be750c43bfb47a26f097be7c77acfab28d07e223af78ff87bf8fcff7dbe37d354bc3c8ff5901439ef4fa8e55df3a01c67c0fad9e8af9475f1dcbf141e57d21710318fed19aede7b4f7875c3bd6f984f1377f69f0ec58df8f51023770fe77c73a7fa78e75bfb0d5933f047fee1cebfcc7f375fdaee358f5bbef8e753e58bd18c89fc8fa4ff4f3da1370aafb4b8ff57d1b5be6ff385d3a567dd0de6f827c9ca327c772fee6be63adc786fa33e6ff687d73acfedc4bc7727f475d60f82f4fce81e19f5ce58e355e72046cf9d575c75afff2deb1ea733d60c88f510bd8decf62f51be06f9c278e75bff43b30fc8b656018f185ae6379def33dc536bffb6dc3a88764f5b3111f48de0de3fd7477c03bc8ffb6f70b60bdce1a8ed53e19015b3e4dcdb1dc6f68e787ff21d872acfa4fec58d75feb1ff649f8e058c63bc6f337ff62923bd6f97a020c7f625477acfa91bdcf06f3797c030c7d28683a56ff845eefb6f9f78e7ac0fba847b70f0cfbfff8bb63cdffcc8161ef9fd8fb7060dfb7db8ea5ffe60fc71a6f7f03867dd0bc02b6f93707863f6cfee458ebd5de39567dc6ce8ff8d5ccbe8ff5b47fe658e7d30e30fc61f31f8eb5be8acef76df37fcdc686319fce1dabbd7b038c7855efd530e251b85ef377a70bc7aacfe3fd42b67e6695f70705565fcae6db03b0c58ffb8e55bf9839567d7b040c7f57cdde4704fd3bba70acf3a9050cfda0b6070cff56d4702c7c8aedfb11ce77ea58faafd978425f08568e757dc2fb8ccc3fd53e05b6f7c54d1cebfb03c6c0f0df1eaf80e1bf59be02c31f33bf71acf1cf4bc7fa7c7f00db7ab3abd8fc2bf347c77a7c1318fae4f4d0b1ae272530d697d2fab3f5a0ee58c7eb0518cfb377e858c7cbce6ff90185635d1f2e1dab3e89f171ff47020cfd2e9a3956ffed3e30e45f700c0cff467c0e1c63fd0a1d2bff757df2fd3d27df80e1af7bd1f57cd7f58b2930fc49af0d60abcfb10d6cf3f7c8b1c6eb1a8e757c26c0b047933e30f483dab9639d8f57c0665f5e02637d4c2e80631d9f99e23d7bbef333607b9f581dd8eaeded38d6fc9c16309e4f7ee758eddf1360acefb50bc71a2f7f0346fd8ac0fa4b12d52f75bcf7cd9ec87681a10f253d60f037ad3bd6f55e3f3f30f99aed01e37cc9237092e8fe1cedbf6ef2292981315ef9b563e92fd1f9141eeea6f27c6ee67fb5bfda5fedb7db5f6cf9abfdd57e6ffb8b2d7fb5bfdaef6dff285b6a412dfcb3efe1aff657fb63da3fcc96885afc67dfc55fedaff647b47f982d89f025fdb3efe3aff657fbd7b775b6d4b25a2eb3bfa895d47ab57e6d501bd646bfeaa136966f4c6a2f7ff6bdfcd5fe6affda5661cb5466fed736abcd6bafb545edadb6fcda47ed5d8e59d59a7ff6ddfcd5fe6affca5661cb66ae54db51edf8b36d5f6bd927fe3f27d2dab5536a6d6f1d425d6a67b56fb5736a17f473493f57b5ebdf73adb59bdaf7da6dedae764feda1f6587baafda83dd7b66adbb51de97f57ceda957ff7e8effddac19f3dbebfbc9f7aad41ed50feaed7ea412de03f21fd44d482e00fb707832448838c5a4effa64141bfa5418996ca4f6fc3b7fa4149cf851a1d310886c128180793e0259806b3604eed3558fcd963fdcf69eb6c09de7e275f7ed202489e5a3b78af9d042be287b244d81234690633578829c15170248cf956fb161c07ade0e4379f649b99129c52eb045d62cb7d70167c0bce6a3bc139f57d4c67dc0ddee9ef6e7021e73ba5a32fffecf1fd5513b61c0a5beac11535e54a8d7eaea905b5b33ffa8a821b9aef39b89206df3fb12595ffcf82db0ddf22b60477d4f8a87b62c743f0486c790a7ed0efb3e039d8fa1fca96ed7f8c2dc4971de96797da1eb1a34333fa2cd80f0e8433bb2e572e837a50af9d050d660b4b82e0f0b7ae34acd1443a09c3da5d18295b888fc7f47317c66142bd706f677c8ee082f8b21d1c846998fdd9e3fbab664c11b9c26cb90657f0270cfee82b0a6e483ea4c696300f0b9afd6861c1382cbf7e2becd133e873a37f07d486d446e13098536fff83d9128eff51b6849390ac7d620af3659f1ab3e58074a55362ce1d4d06952cf5704a3f339adfaab11197c25f5e67f81a2e88072c3fee880d4de2ca1d695bdf68be9d856f6112c6c2bb33d6f4828b704912e7207cfff7664bc0928578a26c0957a47d315baee95f962d51f887db81a48995d0c5a829578821c619d2ab36b2e5285c503be6e74bcfe1306c513b09db24594a912eaf61ebcf1eeb7f4eab7a90c3d37f982f1deaa54beb3af124fc169e53bb082fe9e722bc0aafc39bf07b781bde85f7e1835817edf02c7c649d2a7cfad575863fe8b8676a5b6157e4946a77a7c41f6249380b6724af62b282887de132380fb76b4fe14eb8fb678fefaf9aeb37e774bd7be17e784073ae1e3682ebf090c574adfe875f51c2b2250aa945511c857275a47f4549944619ad419d28fffaada8884ae27c23ea05af513f58448388644b34080b5a05c86e0907c1fd9f3dd6ff9c56654b348afe61f942a3de8926a450305bb82957cee9b79b602f7a89a6d1347c8866c4953d923817c141f02d9a0767d1eb2f9e63871e61975bb4104deb54ed21b18f1a611cc4c4970b620bd92eec4d88dea265f41eadfeecf1fd5593f59a751ed263a26674446c398ea89191df8a4e82b0d6f8c3af28615b9db8d226b684e1bbf0599aa0f370199d7efd56d4a975491b8ea36e3820b6904d4f3f244fd82e132b9fe4d39f3dd6ff9cf6353a199dd566ff185ba26fc17b34a1797b107e8bceb9314fc21bfaf786ed19664b74416c3961cd8a5a5bed9be8a736797445963df325e5652f5c929c599254fa1ebd909cba8dae4952dd47d7fc6f7443ed85fe7f27fafeefce96e836622ba124fda51fdd45f7e14174478c3960ad2c6a057f866ce9812d0f511ca6d163f414fd889ee9e789feff3b4bc2686bc37d6c936d3223a6ec908439645d4c6db1ff0d6ca1bbdfc5acdf533f71b45f6b4507bf9f2dc1b6706057f4ae6fca14fe0dd6cc2ecdef69548f1a62f5b32d629ee64ef4135b3fae055d6a1d624b1a9044215deb8218b6a73d0a43aec3873820b6d4c35b5ae6c2e83ddc092ee2e8d777ffe7b63826b6dc076cedd7a3324ee234ba8bb338894a42799c877f38d7e382f42e9627df23b260882bc696c7b88c09c7bdb8bfe15b03d6b5c242aeb92992b28c53d22a9b64f9b3d5ff3f5613c3fd0f79d6c71b63f8f1389efc8a2b3159f91cf308de459ebcf08c8e439629f437c995f0966739adfedfd9db2bb111d29c64f6bfc7d38d679cb1278cd6e090f4bb88a44c53d9a56c89c3f02eba6106d213ba8d1ac49639b185fbff37678bc8964130e4d9c4f2a4d608573ce3a22c7e255de821da6051ff6b5bbca0f9dee7d91e95613f18c66fc15022283f821ff4fb20ba8d3744a7e37761c43c6cd2b5d3f7e8ead3a819cfc54b56d273fb9fce9615c7e7e3667cf48b913d8e5bf149ad8cdbf1e967aec41d660bcf5ed694783e934d2f2d96ff8da6f02fef6984846c9713f1fbbe135b364618e26ff1797c41ebdb457c29d1c98ec4394f555eb12411364a9ff4fb3cee46cad27f73b6c457d2aed987c45eb05a9d34309aa7c413b61b1ee29b3ffc8abe335be0d76e90bc1099213114b6b2c85e8f37c45b982da4bf4dd48f1cdc05e7cc7792ff1a839168cd9f3dd6ff9cf6f3ac4ab3d87f5f238973470d6b886a5c3263a911476ec2fbf8217e20db82650b6b63d734c32f104f148d8cda49ed247edcd0f725f18498123f05d3da77b288dab536f54d7691447276a86d8b74620ded9c1a7b32396cf1efce961fd4aed7d942f3ad193fc75bf176bc13ffe11ebdf83b6b4f1c339501bc62cfb65a231231dd0ab6e2bdafdf0a7bc2116186c4f3356253927579f6bf852d3476fb222dfe1bd923c414b21bb0e6b3555f0f992917d4eaac89919e74c36c118f16d81206ec23fbaa8bc575e249c94c217d604a5cf9ce5a183391632aca16e50dc759d85b466ca1674efd9efe9bb3a511372492d78a0fb9f18a4e1cbf239e6c25b524f833640b8d5c53e40ab125ac2761d88803610bfd13d40232aabe7e2b8999e3117102d92fec0d78a69f9056aef47f0b5b922449892da7c9df1de393b94fba153f7b971fbbc81e3b315f58f01c3c2739b5825bd44fcaa4977cb1229381780c62d2ea03ee837a3bd0960c935132a6bf27c94b34214d807a233ded3bb53b896296c1069bf4dfa7916e23ded6da5970954c259a7fc5b3557cb63cc7beffd15794cc44ef42b68bc45dda512c96ff7d3227369f251bbcfcc922794b96c97bb24a56d1301a060be5bfc826ce78abfdf1196fff9af65bfb5bd426499ac92f2c98afad76c67ec4e498f8426b7c702cd2e3442c149eedefe0cf6ded3b71a5959ca0f58533edcf3d25a7acff0a4fc47fc6d9346cb3b034219e8cb9b1bf8cd952bb4b3ac413ceeffbce5e59eabdfb678fefaf5a988b0eb6107b6547a2f957a2f92353eb8ff7bb862562409c25f95db9426c2144767cce8c4e365896c9b768c04dd992ac4c56f2fd44ada8c5190a7ff658ff73da6fef06d3dcb1e4fcefe95532b61ab4be1f2717f07cf16cdf838cd905634ab60d934e7249ad979cb05e4cf2e1ea734fc935cb279654ea099088e4854434992dc3a0537b483aca157ec21c8ba61917704c26e8fe7b67be445d5a7f691d4e6e921be60acf2e8e522023abf8e3b3ab929958f59c835cd28a731665511abfcaf837f4ba366a62df8925600bb72f6c0982ff21bbd17f9b2dd128b915bedc25bfdb0f28799341f250fb963c92f1b222eeec8926b6ab3a9af285a3272211581bcb5d2f5bcbad489e6adf847bf81e5bf3629bb02e2631980fb6f05365bf0cc79cd9868916c98fbf7f4492e7642bd94e7692dd642fd9fb578ebd682b8bf830d98f766a75962e68929b951cc4bf9969bae1eaeb492339d496fedd2bfa57b6c4894650e4bae8d37443a6671a12e3dfa8ad9435c214ce1513b6c8de83dfb523a3d22b11d55bf2af7c0ebfbf7d654b2a7fd66dfb344b654f655aa4bf2b06c03b57821acd71d1c824f33109df58b2b0ab05b26657e2f2d4d8d2a0273163adac76174dd24f7b2878ff0b67b6c8f7582a71c6e4a964899d0a5b982f77608bf80be8d99e8937e63c7a4b7fb7dd920ed26172968e2403f85a5280af91551ba4e37492feb77686a6d37496ced3d774912e48af5fa66fe9327db74f6966e6611e7553c9a78c4ee4cc51203eb2f830eaa5bf3bab323d4a8fd3164746a21fd10fe61adb1fdc4b7a92b6d3d3b4f3fbfa91ac4ad1c6387e12dc7194d4d8423608fd7fba41b74d1acc166863c41a654bb0887624539433ab7f375bd2b3f45b7a1e9d704b2f3eb5cbf42abd4e6fd27fba2d97dea677e97dfa903ea64ff4f3837e7f4e37642c705b674bba5deb7dc44ed29d7437ddd34f6acd741ffffb3b7c64b5ab3021897091d639778b731e8386488833f88a852f9cf545da92b085e7bbb6daf7d4f3a3d243b2106becff17aeb4215934ab92d9d2111f59d7743d962dcc96e03cab510bb2dfa50164b484ca5e13f60561279658143c43d833ca3e9e76d4ce92eceff0ed645996276f599115c97b56325fb21e716645ffd3cf067c04e935f3649e0d892711e7867db04524ce41f6cb1dde38cb201bd319dee2ebb01d3d53a3eb14bbe753963d5f7f36c97e07df839e4513837bd2bc9abcac870b1d99da21c720b30df1e36c1616cc0f912f9fd892dc90bc8cc497f63bd892cdb3d76c91bd65cbec3d5b517bcf9ad951769c1d295bb216ff9b9d64ed6c43aeda97de3a5937bdcebad919b56fd97976915dd2df57f23fd719ae27bbc9be67b7d4eed2a7ec5eda03b5c7ec29fb913d7fed759d2dd9d6cf63f4d976b6e368561bfeea5a257b9ea44bb69bed49aee325c9983afd9ce97ead5a37dba77f1fb5b9954e9ce1df33e76356cf1ad9a14827b6594ec5bed79ccad3bc46567c87faa3954fad1a8955bc3253c21d6eac50fcd6a8f2e2ce1e67d634200b1b92add152bd9bf7354a166e1cb59320dec97fa777274f782de6394f528235fa77e20cb1251ad01c28a2419e325ba22ef3258844bb67a64469330a6cd6fd962729cff23cb8a6e397c992a39ccc96782b09c8da28392b1819ce29acf5765ee4bfa119285bc0b215c99563c989bec2ae827940bada8699b9812d8ca31db0250c7ec3939ff7f27e3ec887f9285be4e36c954fe8e7256bd2ff4df3a93086d842ed369fe5b3ec249fe7bfc8c0956b3acbeef345fe962f496a3c644ff97bbeca9bf4f7513ea0be24c69a1fe7adfc246f53afa72c5bb2133af291ced8c9bbf959fe2dff62abffb7761a6b4bf38bfc32bfda54bd4274a6465a4f9bd93238caafc98aa9918489b19f8566767e636c09b73863125a55977faf3de690b7f96d50cfef6ae7e18cf9203a18b14534ad657eaf6c614fbfec323b9458c55c73c4a42df387df784a8faa16ebde0c89cacdb5115f0a7ed2f27fa5e6e0465112e44ff98f7cc3aa53e9778bfb548d8867527cc83286d992f5f26dd658b2229d8ab6447425b97242dad835cb18166cc4a7266b36bf664bbe93ef66ef518bc6b8972cf3bd7c3f7aca0ff81a49e14fc283bc2e99f6b170e541f2039831bfcc6b564d4c23f8e12ab9091b49181db38c601f44d40d8bb4fdf55bc4963c39480e581eb32ea66b047b90a9b1261684bfb4c0f2c3a2c6bc28021aac281f17713ec9eb45926f17290f1bb1e558640bfd105b4e892fc49c62c3de818f4672a5c56c290a6602c98a4762cb2a7f27b9f190dde5249d8a326f15bde4217928fa799b7430624b31c8bbc5b01815e36252bca40f45459256d852fc77728e8b59312f5ee355b1303fb3acf57b125b67cd88640acb17d6c9780f0aeb64c956f1f6b1679fe505ef9e509b24b8d0595e2c69759c89fd3f0b9e9396da2fd4f74ef85890f62fb900f43db6e9f55f6a8136d1dede7f6d6d14ab702f5c702ea3b0a52ff1ffb9e63c05f751b7681647c571d1e2961f14c7926528adf8e5bee8a2ad3b0f6565bd66b911b5d4420973ec18a1cf8b53d595a2aefcbfe83ed10efbc744dfa7d53cfc85fc2e3a11cbbb84f31f39ef9173b88a6ed18d7a344ba3f0309f44c751963f45ac6692bce5ac4df6250441f18bfdcb245b38cb85f5c037b1dbf67874229230ba632dda29be7dfd56b21bedb07d2339669c4919c4ec6d0e798d601943d6d3c52feee4bcb848e664a55dd02a71cc6bbfb4693e282ea9a5c59535d192a4e547a4919d14bfd0ef8a9be27b714b7c59a4c294e2aeb8a79f87e2b17862394247fcc808b1d6456c221d8ced96e2998e3e26694647d1952c8aad62fbe76cc92ffe3b6cf9dcc0965b9ee5220778ee72507fc6f63a766dd1ac4fb6d381b3c5f4ab8ec4e2893b85ec574ebae213fe2eabfd33b106d63e7b87d922895f39bbc5d8223247d8c20ce5ccf1a02c7e913b52ec85fb51336ad2df29f5c4cf192d48e5ac25738558d2b2c61634da53b1ff8b9e4f4577eb0a5b48cbe2b92f59f85d7886114da126f63cafcbdcd866129d2c92761dff74361407f16bfc4a5c918a139c9dc9f999459d739a8995ade88434993a5b5b1ebb611be9205830138a9fca97a0276b057bb5dfe80aaec263594b5696811f5c151ba444b2cbf96d32727722e999f5fb11f54152ef8d7d64d186da17daca5a36240b9e99d2ccb7d1942f031673cc1662ce917244598276cfa9da3fed37295396422233e8bb34fb9bc553f15866195bf30f65ce9f107aca843d62e33fd00fd92f7416e1503e2b8b724d775d674bd9fb47d9528a172aea47fda4eff95f879c39a1b2e5832d74b681fac6e43889f5c3f3d5d51de9e550ad1cc90b68040d922ecf3c8fc3a814fb97bd9b224f44330b9734e7cfe043be633f5c308bb67f3a9ae370c1fb15794fa0e49651e335989f363f75d9e7d18ecc6d477a5898069f244339f9e98ca319ca6b7e32678f90c909c901937deeb0bc73fe5b3dadcc175e5bd97271aeb054da90c188ab7fe1359c15439eddd16d1c73f67f1c733e33cb3439f389ed14e6bf79c6b2bf9a7769c587e5c65c6fd997cf112bddefc87905c7ba73003e10fabbdc60b79473babbbeb245bc68a4b525d374256c5926efac77fef44e5ea31e295b2c51b6890ddbaca93253d8be679bc519c216b8b284f432c634d717e55bb921275afa7d2f57cc8c32e31eca8ce4c6a0181823882d4de3483160cd2cbb2b8fd42a223d8f25cd831c4bad3cfe195b482aacfe31b6a4322e658b1bcb14f322b3cda258bd6325e932655bf4aa8fb62bf35c7e2f49b32cd9f375c23e618dcf7c78cd4af163ca5ab6fce08bcc7668627ca6a4483668d918cd33e2ca63f98dda39fbd002fccd9c1109435762b16cd6f79939ce16c9192c7fa25d8435661ccdb2240e488759a9644176621d6cc959ff5289c27c61b6506b7d922cacefff24b65a5eba94ba178f846873aad171efc64ee4384b2bafcaeb52329e05fd24038dd9c26b81c8d694ef832d75668b78d649326db2f2cbef52c342d822f7291196f236599621f3856d999fdcc95d3ea5a38282431321694929b18539c26cb94773594252e2beca967c8366283ddf970fa47f913421bb87ad776244f9982f9931d913f188e48db281f05d765714e553be287fa8c5af7a195b3bc553f9c94aadb225fe07d9528aa7badc2e77ca5db6eb9925ea3b8607f94cf992e8717b2e5b24af523260459694fbe501cddf0bb3e925ef25a575ef99dabc945d8592f17fe136cb19b345d8267965611cf5cb9fe81ce561b81735499b4f25567dce7a8dfeadb54b34d2227bd413d17774b76d1b8dd943d226dfd9d4b7e4dc0b5b7a35e64b74acacd1cc169131dc982f2d8e2a58cd0a9225cc981e33487f0b37dab1bd80d926beb65b6da2d329ffe66c893b2379f70c499e52d892ef979fd8d3dbe85b4f667cc774bfec19cb45ceaec016fec3f6cc66b634b1b7a5c9f7c7d1a3acd18bc84abf64cd8a3ddc1bef2426cbfe8a4f05b66472bcb2e5842d086f27ae2b3d823fcc96b7f2ad97f4367af57b44bb5e41960ab3852405498f5bb2f8df8817c497529c2e1f6c219dedada03ff982d8b264eb453c034fc436b2757ece163a4ff98ff1a5473a6a76981df6fa41cc8d34308ec6ef7e64e7cbba2f6c61cf18b261842f98ebf4d31b84bdde309e73334d0b6c99d91e8be094fad2cfce548ffacc16f66fc5ef9b4692ee71241a39c90ed5be549a384b1ab442f2fef89275aa35b6a85e26f2267eed8d37f43ce1fdc2d2ee7b2fd13d7325afc741d808ebea5982b4218690763f4da6962146f32c9756681c8666fec64a29bda94815e2414c0c28ea455d742dde4d265e02915f79f05daa81b93484fea75118d2c57a1b663df53d17399588f4cc616deda8fc131ff1416fd3daf35dd707c97623a9982dd366ef95d832557b9de4c4c6386b6f214710a7c88667b65c96a1b3e5de2320e006e6f62362220f6506b66c66e2b224cbbef74ef3fd49e22777ea4d639d4bb8c0b2452d166292b425c91889bdf456c533e9672c591e992d3dbffa4d992fbd23ccfbe35eab7742ad9da4f149efb496c6bfa722cc11cde37ac09192467648768ac4e22ddb4524c7a1b1a5d7f988f733875473d3df7b5de2c95eef2cdca9ed644178563b0d5389c8cc7a90bec49c3bd39e543ab0ddc29249ce711894bd8dd96dbd8b2494380232cc79fea2129ee8e6bd4b8d8fa97ea1b282f9c4168ef292651227666ce8fbcad8121ef4aef577660b4997867abb48b76949b6c0356bf79cf5623962e67156b69074d9e879ebdd88c4f8110c7bdf7bb7a45f5d8b474df65eb21e443d699dbceff14e1248fc25566b9f794fbd0f34f6d9bbdbd0f7bd64aca82742d9c231a1830f6fc426b6f41e682c728ef024d3f0306af51ecbdb5e5444cc04f673a5979badfcde13f1e848fc60c69a54232cb9e8616bb2e441b527b1f6d917bc2a441323b6fce86df0e897496fabb7cd5cc9df33d1a9b2c7549b685e1261118d8c6c1a6522ce963ef4b67bdbe0ca63f1409c731d62235b767b7bc2968d7e9fde417cdfabff8a2f744ca377d8aff5fad9a1546e3d9358bc695bbcdbe8ac8fb8613f34fb51eb1f780d84c32c26b6ecf7a3ac163ee64fe5796d5ba2feb71fb9869c9b61924572c3c0168957524f61dadfe833e927f1433fed5dd22c63c6ddb30e2336c575d42a927ed6bbec67c49777bd66b55c992fe23b3b638d8f7ebb61b6e45f32248a15d7a188ee248a73a0ac112c8296e49579bda45e589cf573f5bdca6cb39aaab956f3ca3658b0fd8299c22d18f4cbb8c1f688583fb08f58030c32f551f47b7df9c3a3c7ab499f3fbb224e7105d9ebfe60335bc83a11d944dc12b6b0d6c73e32b6c5a3417f83573bd963b69016d6e88ff276799b2d0ba27a3e941c03cee0b9d8c496fe98ff3fbdc86e39d2012bff4898c31eb0934cac7b974f34abc59b4c97616cc93b65445cf9d1dfe071e9bff4a7c416d2c378cee72b61db53f6c116d2c948d37a74b63c890f401ab32b67a9f4a8e7e9bb1cde9c55198d74de47bf997bd19ff75ffb8b2a5b9251ffadf610bc0675a9744c338e54e1f3fc896584d668eb6326f4df453313d9227adb197b89b51282ed83e4efcbdac97228e87b6d07a982b4e4bffbcd2ca8edf48ffa47e2bf8ac294772285cbfef1a66ba619bc90bdcf671cb1a1b3a9652ad554996c5a9b98665f267b0173b17a6f4927db510f1756f0abb8d7ffa22b410bbb6379a4b113fd9b5b5ecfeb9144c7c11c5a8bfb238e8288c4d9e14c649ec7c6a74d518afe09f4abb276273606e95b2c8b38cedd637ab4fba7fd4ebfdb3feb77b221cd79cd41785639c3758fc45b91f23ab1a1f76f746135be02baeaa9ae12acd9250734f357ece5ed6f90d6bd73bd26d6e2243b85a734c994a2cb7a2247818a0dd56bfa17fc59ff927eaea85df7afc5d34b5c20fde9ae7f435647ca73953abb927f1fc59f4c9f73f71c37c9bba48b45e55b7f43ee58ff9634a8a257f4effaf7fd076af7f4db63ffb1f70eed4cac92fc9de3fbca0b62e2a360fd9f27f9dff762dc7fea7b6eeecf729053b15ea2bddf628b5fdd73b6d3dfea6ff7776a517f37e8f4f7e869ce8358e405adff9c611f3ed6b6c522a7295942cbe8efb35e261c89cd87261268e939616d9ed1a8187c18dc252e2fc2476e28ac18d0ef6928b341729bd90e0fc24d6bda01f150b395259a49768a5aa611b234883dfd7ab25bceb389ea2fa2c7d3bf1639d4b94d9c798ebecc389521aa79a98fcbfc5c512b5bf1b6b7ec5dffee5dd2bc548f3166a7f5ee5eb40d579f9e9875c31240ac7ab149d8aa286fd36611f51bfdc3416d101411494cc9d8891e06a1b065e7432be3ef275fa251c416a9c21c49d60a4b3c96456cafb0578127e926b60c228dbaaa9f4174c81e33ebd76c19c4836490b026d9bf1aa4836c90b34c0137b2fe4d7137280625b59e4b13b66f32650ecff4417f3028df0683c170f06555efcf5887d236180fc6fdc7c184ff755b86d9229c536d8d78f128f24ab86367c89bc50beb7abfc516b99f975a3498f67f275f3e7d6f56bb1bcc39aac8d928d4942d675c9b98abbc8a65ee3361f08a9c7cb560585b139daa764ac7ef73b6316b6fe659ae754bcf2253bb5e2a2648ceb1ecf9a3a7a6d608fddd186cd8213278435dfbbac6d224a3ea4a34a413cd971db80634786722c2d2cf544698a55eabb36f69b056c568d0541f98daf56b1e61925ccc11b68806478363d6f7581664a328d0380b69fc3bdab86ff1477d8952e487ea31d3cc126bfc3ff161f05ade96b7039776038eb7e4e2c17b408b651f64aa3eb3a83bf8e25f1f9c8a9646d7cb7738e8c4b9f8a273f37653db90f1d5bb235d8d189c0d99bb225f2ef91a8bee2051b60cbe64dc0fbac490b3412a5c391b7c1b9c832d5712bfa73670c93ab894999c61163f62dd5f7d62cbd597feafe9b8fbe27e70d37b27aedc6963b650034332b17f07df392e23ed412334dcc43340bf0f067937ef0e6e7f9b2dfd39b1e5aeb7f7f7b2853431deaf32b3dc7cf602f3ea1f2dc36de2ca23cff181ef9529de982bb059eae2b3270694e722890e44c210262b5b7a1b7cf2e745a957f361cbbe6f6c412d8579384836ad698f52cf97e3144dd535343e51abab7f2ab81a788dd9c10fb39859be982686d53f20ae3c0fd62c97c136f38158a15264992d79bd57ba64a3c1ce60979a8ce7607f70403a539bd9c247684e254733931bbe265ad7b3e84b76fca04ef603b2c8387f5133ced852e6d9c99cfcd8db58ce51fd3b57c6071249d1fa5eac3365c3c117ff3ab14564ab7ac3fa23780e587ec1cadfa889115be0bdce3553341ba617c901cb0e6b5fce74c86c19d606e7c36018f6bf0f23d6c42496b82d3963e9d0758841a97113acfa2a09ee48cfa2559f2d7da2cb97feb38bfc7d9842abba2b1efa37644689a4e941cf1aba7f7e583057c0197804f837e2e2a25ce4dd6139ecfd365bb8fdfeaa2f6b6c29b8c2a7c751485694d4d8b6e01c2f66ce075b86fd8fda8624fd393e4f7282b8c2955c76442edde93e13fe197eb24d35922d5a09d7a6be579b5c7cc14dd62182c570834d3a1c715d45ce05f38a8a78338464985f7dae10391cabc78a3dbda47f252a65343b2b2c982dc3350bb377c7d24498b2ca27f9cb901a716427a7bf87d3f2360a866e310ee7f9b017f5dbbd086cd18c32f62aef27d3388b49967db9f6d76c94369981e52d7b9ed226ffc64dbecbb19a4f9929f0044b0e026b6dee732b744e0fbf485ed2c4f84aa43e409cb3371a6c299463e1464d6c287994e9857125bdd426f6c895ea5a5fbeb32caf49fb22ae905461c644c38073e5394f4cb35c869fbcffca16b3ee0737c53dcdf907b2289ec0962f750a87cd61aad1c5e2496c1530859bda2503cf2b1a1e654fc3e3deb67245fd612257fa64172da8f7d6f0e4f7b1e5bfd74871df0a165cc5422218e2b1aa9d6a45168dbc7faec6822a547792d9c873fdcc22f41c0b513b5fe29c5c99fad3be26d943a6d584e72255ee7e0f5bf4b98bc656873ddfd7d8bdd42df9c216cde360b9631a99ea666151325bd6b499e129c71bd96ec9ebc38eedd350ee1409cfe8a1cb8be119fb59b391ce7f91412dd5c9cc8249bee4a724677a046b8de1a1f2a4bc55cb273ce4d57df0695cf1b6a25c7762f26a6f8dac1cf6127f590987dfc4d77125b533116f218b0a528335b8cdb245f541d1c234b3bec5319262580cfbcc89acff25e36d784e9fe4c530efe41dfe9bddf41c7397bc79f6513d0e3ff938b247b52a38fea1339e6df8fe53ef07c99784f952ed3f3b1f1e9ba430c6701bdc0c6e942dc34f75849923c216fd86e860d903b3657835bc1ede0cbfffcbd9f22a7b4f9aca04a962d145c48573ba3e3da9e1adc5496c978a4a12f104d7c517aca6335915c3bb4f7387b4bd4f6fae429d44b662849f41b0b5892da8834dda95c60469ed444445ae96feefe3d872fe61d5b36cf1789f787837b0e59ed7d638215dea8efd5fcc169634246726d98a33f3879f344966096b68f4b3e4881effae9995ea6ff81a9d1c3e7acc6687399336dd2ae2bc30e2c567b61417749df7ba675934b8e263ef09c9d6d7af7bb4882dac67ca7a23bb9f4f58ce315b747d08f34d19fbc32765a0f8838f354f857dc1c31fc3e7e18f6234dc2abe3c87e13649942d658b7225ef64c79ad5289990f7c34f991265a6528524c20d5b2205fbb8ee87bbc3bd62fc33b648b6a4b245729055be305f205b3ee54ba60f5f1a5b316fbd64b83f3ca09ffacfd8f2e1098e36c4aa7f5f0b67ac8b49258b86f8b974b7b1ec06138f57b0c69686ea5bc40cb6f457ac0158ec45629633f16bf29b4dd6f235a289bc9b47ad14aee893227be58c353fea7336fc92319bb3a7478e90188772c1d9c279519fab0f732eba65d0d38fc5c7215b789fd7602d3b85d8425a1ab12591884b30ec0c3b4cf361477cc771b433fab4579ee583ec980ca256792bac1139a3cc61c254af7e1470cc446a26b3876e9f24997a12a4721f4bd9cf9a18d8928b54915d9cbc2f4df7cdd3b18b201855f25f9257f160085bc4d770d81f25538b56f25d8f3668e6a358ad7a610bb221c94ebf1c25a3947e32e2cb17dfe1282fa3fe9370e9077b81cb68b8951d1783e299e6a948a7d1271f877a96d97fccb35d3ccc8f83c97077541a5baa5eb1512f936c2f96171271212b46228dae897d962dca0fcba3d4963d8efaa3c168485cf9095be2f168b41e3b09767e5e7daff6935c395abfcfa5b2de2dad60a5e441de6a3d16a934c9333c8d3fad06a371c8318d5b912792df489a5a48b2e636184afc300e429631b5c668cd4a089e3fded9c8b20b31778dcfb0fe56ffea131bbd4429db50a369fe146fa9a7482c914c3516d6263e1d3d2bc332e0e801cf866cc83b0a893dea3b0bf27dd6cbd77a9fcb5e96c3bc9daea213b530d88acf963ca3a3e36167f469cf1ff524734c751ccdf0e215daacf8af552ca21396518516604bdc93dd4a57b2b79f185d7e3efa79b428af476fa3e5e83deb651225b4772b45c745925e0c2a5e90d12a3be26a147cc7740ddd7c316a0a0725ff8cbdc31bd97244728bfa6786486451766f256f654896f55571c539c05fbe434c62bb9aed91d1f1a8353a9608cb1dcf64d6c6b2fbd1a74c06cdb487962439c49c57cffa95d823d4cbb0f27e86513bbb45be8c7c57bc60ab22639b8759333a1d7dd2e9f3b3417fd0f7bc31cd107b2a5e988baced8dba9bd8323afb1a991f7d4b37e6bd8fcee9b39fe5e10652355cf755cdd8ba30afae5a1ae1e0335b78a72a1d39d3a8a4666d713e1fef4b927a5bca099252a3b53141858c86e648910c6a7e660bcbaae44bde63f95dab72cb3ea936a2e739fe658b8434a94ff778c53b84598b917cc77d8eb8707687ea3efdab616db856576534170f2f7b834f9823fd5395156a85f30c1f7dd27ed41e90dc61f6f5269a0f4998994992e0ab5d61f9c9518b7d6f886e74794d57ab24ea8d3e790646df47b7f93e71e56e742fb9c09cab098fb95853455ec9dd51b6c0cf5664c3f2c7a8a93e2ecb711e6dd88d3a7ae44c30ea8de3eeca967b9acd83642911922bd6caaadf212ded87788c1f1131674d49fc5dc2169ae7a34f6fbf923dc2ef9a1da6be5db62c10439436aa54f7193d67b05b34bb05364fc1e7d148e5e89337b378613fb1b0907aee6d0f8fc59bf6a27c29c6a3ed8d6cd9f9ca16e2c4c63d55fad9e06ed367f2b6c167e50076232eb4c1833918ed7d3aeb3e5eb3a847dedb1acfb60f7b2e55aef0aa385893667823b0d6b83e0c1ab0d35127895bf225f385ed76f6d0caacf1dd2a16538912beb84f4f29f5fd271c799b6a6c5ef286c94ec8f7cb4abc7d74a0b987927d1fb015df3fcdc7f99859d37b1cd5872fa34f5e5be10a7b76bfc3d3c6d650ae6ce13e36b045b395d913c067ca750e73660acb2466cd67b6443f384379f01c9e8c96bc775fe232ac25aad57342f2a3227bd36b912d6ce31cd3a7c2459227f41b9f8bffdd6cb7b0078c64e291d69d60ceb02f58a38945b6892da4853dcbee95957a8439868e9c2ed19ed287d127c9da7b47c4456393fa8d77cb54e136ae5483cacee80ec876ff146d645f9ae8621c77e93f8e3fe9b9aacd8d43f10c3cb2c5cfd14afc4b671b479bd8f2b3ccaf4d95c46acb712c9f4e7b5fd844f37c269ea7f9c7bba2c016a9ce182ce235bb0c592760141fcbfb30822dfa764d7c348db04efa7f252f8b29e67c39d46c15abe8839d7c5fa2e1c3aec6a92566829d526689b05eb6ce168e52c3df8ac8a4b085ac70d28762b5983ff7fe112da419ff968d842dc37cd83f6509c36dfc2932607190713ae0f70b3d0485f24673b3f82cd5abffe85df2ef63ce432eaff37d1e2df6d496d7e34f3a8fb2a5bcb2da452cb7889b05df81584a4755b68c73b66d205b9a9c4117aaef59b25aca1fd970bc615f57ef8eed0ccd07d37d5d34af1ffa37c215ce58c936c816b2ff913ff9e0518e8f5807fd3efe64857394f1b30f18b6fa205f4ae630ef4fa9f80f49b670ed0ae1a0d8f4371f7e64e60ab1e5d3dc604f71f9265ee427f5222b5bf47fb897bf872db568bca13257af37dad53d2db54a46364b05b12467b2a7fe35ea97bbe38156fd647f0c69626bb9f4c2951ad7d0e5361e8c07e1283c4956e301b3456cec63ceee1aaff9566ce3970826f60d34b442aaf9b96a8daf9a18b34563d534f72137c43baa151f24e6fd69cc3dd345b25e5a9cbdc27b78d943dcabf17aba9e9d627b5378de105b0e992b853086b5b1ac416cf9648dea59992dca17624bf1992d5f7d62bacb5d794116c9624c7fd83689afc313ae63515e7fce2c66b610d37be60bd3382befea64d997926552f519f6ee5171f28dbf132c382aff714f7c57e30d198ce317b233982dbc63f85876d45ff58ad1b1f8ba384ff8c7572b1f599453cd983486a8ef56e3849f2d11f88cc1148b316a7ea466140f2b4f7a3ce5fe34eb8b1bfbd2cc2fa6df1f7fdab3a0b2473dd2c598f432b263c673660bf38525df26b6405a6c62cb4f7640dbe7e15abd08d5a1b47e88f82ab7982bcc16912ef47feb158a93d7a0563be7fdc9cc14e515ad71ea51bd966c92344e7b9567fbc115f1bb9e185b745706712c187e8d866f7fb0c5566ad6f99531aa0f7d1c5dce2dc78be328123da1a67960d1b158276b9a98ce296ef97ed88a8823e357b6f47b8ffc2fe1e3cf6ba0685289e862c213897a7685296a917fd5c478c7fc017fc6478c17a35bce41e61cabc173bec7b6f967b6687500e606dd5f11e66699455df1262fe967836c114d4c1217892d97cc16dc95441cc71b3c3bc416deb1c5dadb11fc6157bccb6bb8a53e6296235fd8c2958fb81a057ff31efb7f79fe2b5b1ed6ed76b99c2bd6c164be3f480ed863f6a0d9c36c6f5465cb78c95261986a3c1ffad8935823c80d1b7f5aafd50b307ceefd60ae70cbbb64f53f1503b0e57d135b52aff91237bff0e527ef751bcb91e15a3544d18bea9ce328d6b3bc055a352c614f19a4e335d99cd0e749013f31b79033a8f88775b4b04173b3c9bb1d2b73e79aabb77fbc5f5ef725eafe44ddef3afe92839c725c822b8e72ccfc4063d0cc169131d859f2e9de5aeccde5c6fa54fe92bf986c8953d9dd7598ae8d8aaebfbcee9376c4718d43f68db1d5cfbee2b0955e7eaeeb83bdc13967a1305b60f1e77c4dac09955f22e0c215a943c73398cf22e7da1b3cb3ad213eb84f0c136bc8d8c219980f9a5319e660cbd1a8f2b69c91e419cbae9326d76b719ec8f9f259763bdeb0e7a63f96bd299cdf25355a347725590eb7c6ed71bb18b2455ffd0ee7cfcb8e15adb6c23b8197a822f1a8fee2cff1109ef9e5470e2462fa62c5681eccd3a8f246ecf134158d0ada9568838cf8378d448e3fd5f0937a63efa372dc51cbbe180fe84ffffbb83b3e1b77d903b0912d7bce8d6fe3f3f1c5f892fe27d1b7b6863fa9db30be1a5ff3e7e927eb453c58fdf1cdf83be91729bf2b42a29566e5bf47e178ad42c3e8812c889947dae84fef72b09bdff55e852df5e8787c37be1fdf55d81248bda59a652d6ad6062a46ac82ebac31fee2c1193e285be23cd9171d45b40cd5706476d0faf9e9de1ef3316b52fdd3f113b51fe3278ecaf76ac30ee9858d649a9f8cd7740c664abeaf7398faed4a66f1d4a2227c8ee1d3e7a3353f92d9a2198964455f68fe2e7b70f32ffb8b982bf969d197ca63adf8ba14ab45ad92ec88bd70e34f969d544fb2ddc759500c4279ab77ea6c297eca168964aab7216be5a72c61902bb9c1833cde2e43f501c363ccdad5497634381f64c3adbcc3192ad5efa44fbd15cf5c8e44ea8e46ad25510c36b145e6fc0374ab77db77a236bb461b0795ba82e31d89303ed9ce2e966352b1e29eab861583f461fc69be92fca07ec77be3ceb8332a55b6e4dd613818325bd8bbbc892d21defe3d5e7b4e637d43eb4feb7624f78866fab76a5cd38a6d967baecac3c101a99f3f0f0752c395fe8cd73cfde38644d7594f28e13f6e6a4d30a9edded45ce1b8b28f41dec113069146c439b2c7255949a7d37cb355bf3dfe12b11823d791dbb8cd9a826667887439210b6be7737696e40bf642ce472bb2217b87c40ee7286531a94d824918ae45a3441b2a7475ee3d26fbccab58dee7dd7bec3df21c1c7ed264b43610b38a658b443ebf8b452d1284cef565c4b99290e849c7e2e155ff15cd6dd65b65ff54f37304c5e244e23123d6685c5f19aa958baafb27d36bbe22e6975b4fa81540fa5e2a25443668e4fd71d693bb460c5fedfcbcf9a94acb979dc6ac15b1e53d49269acf35600923f3f8913d6ad9e3679f582ad95b98f72a2956ee1d6bf2ff8f2a4f7abcd40a2fc573f1ac155df259cabb934942b1edd37f9c7cd2b8a52adfd324ef6db3cd3229c67b9372528efa93dea43f1a4ca86d62cbcd7c22ef670dbe68a7bde35a34f9c9deb0e4e8631f98cfe3eb20aced0792c9c7768bb285ec7ebc4567b2962730e1986566d554346fabd6d528cb47eee317b634643746a439231c0b477622e7f1125b7ad1e44bf5bdf1b10a30d65a584fe0a65a7ad6e41db8ac71acb385678f7a84648f25dbc96263105ba693305a9b6fb60f4a66c832994e669319c921f60e2c7b8f3ceb3ecf4fe85c2df3d0b284e1dfccef157ca9c3aaf68c6598e433b2dcb7b8b61d319aeb44928cfc6c89185bc44ec73e18cb13d30aacc3ca731ead546b531bce6ad3f077555e0eb2c986e73f79d5eaab6c83285b385299af4ccba2b9fd25e3cdf3ee39fb91e3edcfba475e2ae1490589cff35f658435d5ca6486bbf4a8c65bc64bd1e9a8dfde8adb6481da14f47fb26fe57ef2e9dec51b20f9ca6ce5b37c992cd1dea9fd942d2a47c65f748089d482f9d95e97895939b389d82301dbe791bc3727957d7a33e18de6b1f29ba6caf50aa3d17630fb54f3878ee1dc17f779c196af567eb35af8cc15b67144bad03acefe2bce09cc8afe97dc9d411ddca0366e8fde240eb1d42a56f2c49b9fd741678b441b24969ff38c96f8f60de7b7446bbe18d65f648dbd675d89335e942df013d03c5fd7c424727f5bfe500fadcd4cf33f7ddd0dc6592ce26f638d6cc6dfe31588651e6b5bcc99e4d3b85a4d62e15e57b20572e58ab2857eafe4ec8f27ca2cada26139c5fcbd382eea83b47f35d9b01b95d8c2bb8235d6722455f2a6bca70b9927a2076d608becbc92d8bc48159ac9b75c2d8fbfc572e1b3978b7b219b0319c21295679daccbbb4f584fcabb938aff70d42d5e9449937c1cf6b6b512a5d4a690ff1da693cfb9024fa2dfb12f60cc6c19778429e5a44ded74d2996cb45be879bc4c349e5f4ed62a352549fc42d2e5a7ef3c32e93210bf5c14f4fabca5237c977c478ee1dfd3bacc1ee57bc9afbf1fad65a3c7c807b7b7e84a5d8657b6f5ad312daa6f71fbff89fbaeeec495a6eb1fe37b2f7b9c662e11087018830306fbce440192504ebffeab5dd50d4292e74c78def59d5e0ee34310d0bb2beddaa5631ce04416a105b30c507d5b7f16f3eb5dcdb670dd59506181ad51428b688d5865a5b8035a042fd21d28a7f427abcc1de7ad249fa4f85f43e6ef06aacf584d5828a3053b4cac052a8d824595817a64a5ecdac45ab1407827717b5553e55c97dedf656ba1a70ea9facfb53c93fc453cb2aa6dd9791cbdb19593fa3dab9a93f7897afef6d19e7b0dec0d2fe668dd501c31d1952cacb1526659023fd5fb28368a6847be89de17abb2d0921ef90a5ac64efbd0012cf92ddbd93e6f9f6d073146152ddee3ae0f7b815aa3b7a22ba0b8c75be98a0af0b23bea08e02a24eccb9de553fc7249fe574e38015a06def02bb4f0bbdc979def1ded68e4bebc2fa7671c333169e7fe38c18cfbfee794d57a614f161cc9f3b445f21e8efcdff98f3d56e27d05339e2a1c88dd58ba5e45bb5145f6cab312ef8aa369664ace9f3eadea6e1076b9ec15e66a40ed0ad2535a6fc43eb62dee93f46be81a8aca367770b28bb6e4b1d284420bf7a9e85e7b2066eb6eddf915acd2115ac0a7fa295c31d9edf3485b15d639ad316b052df00c6195c42be49ca3c4246405ca8faf51a2f3e492fb53b361e85fc78c657ebd6f3ab6e1abbad5560658010b66e9380de725d0c2dc2e5167b5a546bf2a042752536944cb52d425f6d96354196dbdcad579d82744e22a0f9c4bf51f6841ee0a36a6012d97b048c8bd792bf2056d3cc2a1d36b71e4bb79afb450011d21d2e7d8e58d7db0315998896739975fa365b68f4338d7b5f2f87111cb7b5fa8cb7ba54916f3055742a07c2c136e391ae1df57500dc5b4073ae72ad122771c49959f19e5f607b87dd2738805547815be1ae7c010a79c487f08e277bd5367f32d4eea5a94efa4e015c0d75f32b26065f6eabb645d10e51e6e6d4f192d7adece4fa9d69d24cbcef295761498f64719d525e7b3f0b85c93d1d57f8516ecbaa3dd9c4a3e40f4e30fb51ab67bad5530afa9a1095a986542cfa3ac524734ed4f129c02478f4f1eda52a2996b9de912cb42cf41b6837051797f165db6a21b1deda86a14a3058fb5786cca202b4f0c59068e59f05eb2ce37e2125101afd916701de93c1f71ac702eecfa03fb9763ee926dd12861fe0bdb00ee20a6ff547d64e755f824eeb9e5b182eb527c388e939857a0f99965b4a027d9bbdcd0f55084afd0e23a58de9577bd8bec2fe216f5fa6b0a48de77f79ebeffa8cf06a318bfc25b66b40c3e67d24104462545ee3979657a8e3aba932a1eb35605c667b9bac41bbc047a141ec48af8152e909e0e24ac923d7bd184ef834e5dffc4af2932fa532836823dbcecccc1023609312d9e1462cb595f450b785bca3b7aa12fb0ab0ae88e4e1d56213dda07ab733c3f78fadc99afa2e47df591d0639710cf792dc205d7fd50d150bc77f669a0ff5b8b5bd0f3ce4811dde073f2220b85398584b23515a4abc7e4acb4dc86b3049c4fa8da167f5652a1b044150975fafd69f1e837ccb423b4d87c3bf1c470f2044a9745145b827adc827dec2cfc85f76a3f21bed65510d67d614feba83a3939f860c098f058105bd07e7ec3cef62b2c677f45205ab3d21ee7d1b82a7950a7c8ab68518ff8ea6f7697e48d79dec67bf3b7becdedafaeeffe0a2d53b78a96a3b5599073a796a7678695d1821ef7d39be996b5a96cd67c1425169e26cdfcb1aa9d1889e2bcbd5a5da2da667f2c914b3b5593ed3891e557a210284ee0efe8bad51df0a8e973a4b09eadfcc0af2932da3f9c536827acaec8463c33c3b08347d0d10cf4b74bef79843358e95e755621ed2242144f2c6a4f9d7956f531961b3cffe67473fa79fdd966e52247b2c3cc68813244192d63daef85d4358015a96bb01d608fa68e16ec7ee6086fa0ebc84d3d9fd623455fcc93669fab740ae13ddddb9296f08a9557f628fe955be965f6678856f81a30d32c233fd594c926cae6194d68714da55b7c982861680ea4d633aade077515ebcd8f35a3c59af889b7205f8bad076af6fe51ce0a3579e17bc16bc2eea6df322fa7f8628218c3af68aff9b9bff60b4c3b42d5d369fb84c843ef242c5a198dfec237fc783b767b400bd92acfbbf2db7ec7376975fd9edffb155ab07e89975f2ebf3f1b7e3a279345e2dfca0c39e8accb044ff1b64ee245e5d4e7a859a6e5608e5686939e767cccfaba8acd5255f401d7492f895d3827d6d19db8d35bbf36ab64b5a0cfb5a3635e617648055feba92e4bfc1a8a5b3672aa42ef4aaa336eea8edc9cd608f51ae788e7c939868e5649e29885a296551751bf6821ed4afe35ceec5224a1fc31dedb64c5e86f359e9868d3c0efdc4cfdfb6ddffadcf6fd074c1d936a225d6b19eb3ffd47f02dc18a415ddd1ff803f693ce594392ce866a7572c79adc7a768aca86b7b98b2c15ebb16bd066f687e4683ae89bf29ffc67e7da7ff15ffd17e7c999b2262b3cad1a5abcae3f222f4aea8caa4b8bb99340cab9d33e8e5b769f12a1d3df3f38133c416618b9004cf1f236aeed57ac973fa65dbfdbf7d9735cafaaf9aa76e3973b02ee76979e053b87d8c5bbf42e099b3bffddff20ebb2f5cffcb3ff420b3de3f9dfa165be38393b793bf1e705cf26cd652eb49aa76ecbaa7656704ef65ae615cafc103a03d7acd8fa84ce5d9ccb4e251f2caabbb28017dda78ec5f58ddbaaa7a1d0425644aa6e0a0b8f1293c03b3966be80832cde0c16e1e5643d25bce4b2043d35b49850d9c30256b8ab9fe72f82ff42f6b19ce9e9681f4cce7b28e8695e16b2c175b4884ae066bb68ad762bc7faf42ffc8b6d1f393da005f72ac72d27f66c060509aebe666c2990d1d0d384e87da8d5f2239dd7620f6a1fcde12f12b3fb970dfbe4caf9c072b7feb57f4d68b9f1bffb3f90af5a8e1037a0bfbd8e96e094d0a2f8c1881bc45e682556cb2ec72dde1cfc4661b248a46ed99b8235256f39c6b0834a9f69f0e95996877b0165ba4e83faa33c0a599bd23b45ae12b2c6afbc2e155a7cff3d980633fa3ef73bff8d162b09167f839660b9b3d7175347ba5368e70b56528d9a26b4484f8b9a38620b9b0c3a49d325a165098fe9b35854f6fe5eab4e788f9d325aace98aa2e17a4e2c58c90e90ca0afbfc50a63678b73a525b28dd1a9c60aee26307032dced47e409dc64d51d7ac769c1fa3453fde4137681e95ab933aaad7fd2c9ab3b6c74b2d4741af16dcb316789a6037fb17f8ce9905aec14c37c7d54f64b190d3a3c72c9616c73a0efa6d78b9759ed86ea562a24069acda7bbca08e423f9bd0e2e4a8af58cbcd3b850ae9aaef4c8114e7131929fa37f4b86ad93d6fbbebafeea42ab847caeb269798023bfa28c34b073f72bb964711f7d66612976fe19111e3c3ae0595783ad804dbc056ac4ab5f02f51a0649e4be9f1c9b6105ac8aa0856c8d3c3edc9b6bcfbedc009dcdf410bd6e62fe61fcdfce5f74dbc7429ee18e909589c59059f89bc2cae8c55d8af5c3958282d7b992e94afef5793d5049ac3d2c154478bd81c51e2961a20a217f0baaca9355d3cd695b183ddfa045d4ae8ec934899ebd02d8e8411633c9f94b2e48187085ddb1c410c337e57408a705caa68c17e063b796a4ad5627ec8fb929d0a4ab1d781a7c68c4ed10b574c4f8ea26a3ac827c355d77a8636d2fa65dba5d7f809169bd4ecc5af3cca503b6b74b48c80c0cd56a23b8516673709080bd5ea6d10966773812589b8a834d16ee934305f82881e91d144fbfc6d758eeaa2e476a54f1715bfda7d62cb579960e905cb57f981c9c255c552f64db11d092d818d89909c0923fc60115ab6ee36a8eca72055683c3c03e3853999a8e51ff5cf04b607408a6dc1cc3d414b5be125fb75947ff4bc79f087335d7c0fd33ba6273c7b9ae752092f892b816aee6df5d4d7ea703cf141a6a47c022de80a668d3c424b50611b894e9dcc1839a0452218c20a21a0ee89012daca7bb58235175824e2d608bb304c5aa8ba99d875bafa148211a953abf944a4d0556857dbaa38caac68aa005085bbf8331a3aaed6463ca713559334bb3a0b98bb7a5330a12956f6a572f3dccd2e98f79a6fe85428ba08e30598ed4dcd62a01c78deb999faaeb2013ab0486681d2dfea5f2bb182d88732c5796f3012d22cb0f6ab960468b435772027d3c6086ab27ac5e074def66b4581e59a237e1de63f7aa739f35249d05795e47b576e712cfbe99afeef668d9894dc1c2bf820ac720e8f89b23acf0773c2e1e1f16a7fcf87e029404a6bf618e98e56f023bb00927337f8d6c815ffc2e5a78d76c826ef03bd32878d1a7eaa097086c235166106f0c113f3c31ce13d732fdf489ae0e0af33cb97a893977dca75f34f646cd4bb6e59bc406ac1671a2b2c9b7d59ccf012d6c5b9c95abbb8077f13203bffe182d81272a78aa337724395f5d9f91493cc7bbb9645b44979efc3ce6b7f0acd29324287536002de853141f4d3423e037b11a173dd3b636171e8f7b32056781ed848b7dcf9e18a305f5c9325a801ed8353c2eeb1e938f070b03dbc267c46350b52db79cc9526891fe142cfc8432cbeab6ae0a49f7ba0beeb5923772b4c2c5b72674e23f3897586eadeeb0fbe44a8b7477e9a911523b9c085a8e3c31b12cbbd51dff88e0db593be74a32c8b030d5ea64f03330b51776e872f1133f91477716412927e62ce00906037f038f8cb03224dbe781af2f58099efe042d58736363fe56d4f28cae25cc6cc359caf97df2c0901983c02c67c410d157fab4a42ef6a97457942af6562baf36a3e5a04aac7f2a3d962167c4cc13ab3ebf2558e9c9863c9fddc1aec3798b9fb2d7cb1d2bc1cb9e716f2ec01284eee839f7713c125a329cd6e54717ae14732a9171cadc0c3a599f2e3dd5c9ea92bcb88fe0f5e8d61bf65085adb9941e17e4aa7912c3b955ab16897d10658ce909b0c2bfa96e2f7c95ad29b2e1d0210e46db47aefe5adc49c95844c4bffe0c2a99a44014210dce081b8214e87d49a7caaabf4e821af79eeef58ebd26bdc0eeda5d8b1d702e82076f1c3c040fe81ba9dde7c35b59233fd66a784b3531556a23d8e3654f8976775b96b792ec18b261ce55704668811d8877959325f84976827d2a1d8b70ce997f4a4e2128e5f251edb49f903dc6b5325a6c8afc6f6505df7edf13abbdce8b5f62e5929f9da7b681f325684156583859aae3751554789bf3a99eb22e1501f04b4e7f1cf2498d68d9abd7a3175229b03e296dc9ab79105cef6a7e838ef2b1a4fe8fcb168d54d985e5682178112b21351d9cc9a2d1bbfe5cd3c6dc8cff032da99b61a70537849ac439b357db6150aa872043857bf004701914007625ab72613707b5285fa9bf72f66f7ab2ed6ebbf89dd9389668b796d1e2269b17c6cb8d3d0f4fc313fc8e1a2bdbc80de63d566d4b88d98f13ee69a4652f5797acbe3a456e8373e82761437f0ba3c5b3bde0349c8139029dafd59d7311cebd31ad2eaa22d5fb6c8acd3954c1b83f057c2edd97afd5898ee20ac96b01279a17b3203fcfdd860bd7f6b6e1925625b31d7476978261efd54715f452eaf5d08495bf87253e20d91bf2c4a4bfc5b3082b26d0623bc2440bd7c1b7bf450bbfab9b701bdadbf3d0d926b266ae15866ea8ea69a82e82df1bee6051a41fff24d19c3eb22e67553defd0e34ec0016b9760f77fa7b5923abae888d46b7592d7423e0b4aa5743e5be878124588d9c76e11fa618d9f846c27bcf1551f8c93f995e2a430f31158c3b4a0d2558592b35afc845a2ff68bcebf226220bf2d581ee5c4d64354e9c8676f5314de430d11b1f1f6098a596184ef41e9539da9ff94555de94e4acd9759d5f455a6f3d96c3db0576e8ad7208c50747571bea155e32047c22390ae7ffa9a7397717b655803ba9eddae1b5678aa3bd44798610feb89d76c2f9c53fb3e5cdb77a207e534a8658589837d76e9712748708ae5d9fe08ff72d7f0c3769735b4cc457b085e1458c4e88347be0b513b7c37cf0e4b91ad1ffbb1db935c953747f545a6ad72eeec93a28eb95761e48419b2c0121171df8a6d7d7809f79a097bb255f6f4bc4bc2d3c84ff8d6735996efbd857958785714e9377683fdaf163614a3a5456ba7a640b7f4bc6b424e5ccd206bb470d5109e4f7b76a2d5ad1527b7d651848ab754d9640615f3652deeab7a066a4eac66b470d4fa8efbc2bf5a75192f01afa7e36eb0e0452b60032bf0a5f6f9a293d56ec11ac1e5475f5da9de13837b6ed6f34ce59264aa157970e5b8ba8a967dee4dd8988155e3b08a1ed2ea9273d7ae70a8c53e012d38898e33d4dcbf19292e01eb57cc99cb89b90f6ec7390b2bb67731e46ef982bbe007ce892cfb9ed61d21857e0f1b18fb61075881178325918a6004a735fed6841689fe8116ce0a135a3822a17fe31e8496d2fe777b6e2fec22cf8cfdbcfbdc7da24609b4386dc20eedf0a0a2be17f638afa5d0223e1c1490506b11341cc72d7e12f6bd053c3ef87ab8c77a19de8677e17df8e0bf07b3ff4bb42c2da065fd19fe0c5b9853bb48082d6d99a0209314ea68595d611bb256fb0f286faf6ec048d7f5f5a6696c6a66aecd5537f0ad7e0a5b50ef3a8a796b572668f107cebb3f60cbd4decf626f0b3fab9c130e1929d0ff01564025d36859ed76f1aa3bbf5a1c7d4ae82f966a09fb76899a0e27550bee962a67787916d00dd0229d2dcc5c44bcff4db0bba8292148878af4e6a0ce888c18b96e88ba0cf0eae6d7e1c09f86c3f0297c0e5fe8ba0dcd091365303032396ee11ec7f5347c3d7efce58055288094e5f6099a2d250d7c16610b1bb4b2c237648ab7134100472dc885bd4bdf2eec8e57eb02c56d1423d213ab820a8aa005f7daf5c3f12ef74ccf0c1e4395db15e68a35d251bb78677eab192de2e1c11661ef032b9a0f50470b1e27f8401f8cf87bb05dcbb75d14c4e4e34d7075ff976881fd98dad663f81eeec063422e4c587d928125cc54f2e3e107744bc0a5a44f58e9abecd988aa4faa092dc805ab1cd5b98a1ada9a2dbc74c2da5cc8f01c9e18fc1837576a713ce950e781b00eb776de74af0994e2c16053d53b1bd53de8a91ea3c55e2876ff23b82edc113c621e662a5d92cb8e5fba75152dba3f5f4da5b8aa9f0f8ac3857772b3992e33c7c7d40b859616ec367a1cdd24fc167e734eb6cf127f68c680b0dd345a966f9bf7b0c22572664a5d856d21d0a214f0139e1f4c08082f1bd072b599af13ba55ca8ac4367e62f289caf4b2e250f53eec8789baca9daa3deef0a53557f8ef1f9b82cff9855430353f4cd54372ec7cf2c35a9ce7aa7a623de6b0bcea0c98468b785acec21a953db15d165e8737e1f52ea09fdf652d1fc21feeb97b1e9d46a7cd5a957a794674127d624def3617b32fd45ebe5ef0b896d6fa248cc0fc03fb8535ddd8679255edd38aa61413bfba2957da940aaaf2aa965ae9a78616e1850f18316aa72bfb2033d61fddda9916cda0544d58594673b14a9221933c17ef9292d55b4cf99190cda50817f645660b91efefac1ce9f03ada6da7e0ae0061b08f9a67c5bc995b615896ab93b319142fc0efd4fdef4a5f853373f455ebbc528c7ebe2644fa8e1f2da205f3af0dd811a816ae87504e725fb6c3756a2df9351efadf0cd527cfdcfa553fac4421d152cf75042798f9946fa28fa718c0936dc3e4f0f08d22e22da640aa495a1c1baf53b1145241aca145f0c0dfe516a8a6686cc9921ee14dc12a456425a215dd6d01cc0005e235c12babe69bf995ac158b652e68d1d6c59b238b4c7f7dade2eb77561d2dd1a649552cda460d3370bf46cbc97049d10a90022f0c71c567e73001eeb80f839fd551686941ff57d0a2f42296d21bb8ac4d3510dd508596e0601d545e6ab4f819d59404a21d3c3177ee9273c239296119da3cbded1111b953e27eefc65a8581d0f2693f28b4c05e64923f3bded1f662f922fc76ee05503c79418b6489cb396dd1d0db0e340366a1fc3ec9c34dcd756d6244092d9966c349659f71f042efed00713922c0ed50ba4dc00fe3f7e55ca914bf2956fdf9aa1fd5ea2d32697b65a03397fb18c7ccf51aabe9c0a5194125b45cc90e579d59dbdd2db249b4b6c08ec423d5fbc0a2085a84a3c5b18a056e9762b7501c03062516e78e69c7335a12a9a2b0cd50f964b61795bd1f79c8164b366c7ffb055b99b96494abbedbdfa0e53fab29bf6567780ac80ff2bb728a7473a9358b3a82aea854eb8691ef0fdccc39c3a78a4c2e663422cf7550d66eb02dacdfb6e732d93a332c5543b62d359e4668400bce5d4481bb74d3d5a59e2002cd2b8a663ea2d02de5c47673e54b19849629a385bbee811655a5398a93092d1df4cda00b996c4b9bf968cce054ca10ab729d89198f03786f8ad7f928be12ebe50fa79dfa8c20e1da081b6dbaef3a51dd371de6cc5b7c5270442618d93329cf15db6bef753ad3a0d265b4bc97ce5f7aa417e805ac9255b80a39cb47f7e3ec72c31ea3a3ee9223f65be992d768410d118c2ec4254d68118c095a2477eb59a89df8161e6377274811bb72c855390beeab2fd55e10a34795ec5e94205bcc68793da0453dce2557eeff192de1f677ea8f51ea7ed99f7f400b760b7960ced2122dc8b96827a2cfc3aa77edd1014491046be3dacc8a24dbc235f01233b1fa2ceba9a0457b53caa61ce275d3add55bc257e855135a32b22fa9bdc4d443f8dca8572bb4946d4b9b2dc908710be78f2f75865857348f3375f6c26db1828bc5a78544383633c19805439149c99311e531b12de28921f2806d915947f5c9d684057a5ee1d59017a8b8d30a2b2fd273a996c1ef83a9ec888d1a91f23517eafbc076a28affb2bce757871ef964fd8e2b16fbb2e09e43c40a6ec39ce530810697784f6217568c177f4ddfd9375bd5624eb12cea3e7dce3f5bc8a1817182c7d8ddfa6bc96589b22a77b8e46ab7134a58c745f5d9436529aa9ce28496573f0ebb8c16e6bcc007537e18a1c5ed058d9323fe042d5f2bbbd61053cbe71ea125fab4a5034ffb5eaa9e60ed557a2aa79a6490e145b0f6e2d27e20ac5d232e90a8793ba82b37f24c4f6d510cee76550a3dfc37da23bbda3be2b2f6284f527f5a9ff03dcf9582c5b9b64fa5ab0ad05f6b2fb643f08e914963b5eb7356976b634ecbe688c56b714e896b33037ba9ae26e05d4c1e1cf71e966e7d5077d9c72dbcff956e8061d7ce249c3c64bbae50179a07ac6869aa6ececdf28db3c97ba682f5483654c97b4473e43584572f719b4caf8b2aa7c9f24ecd3c79034ae6cc345ba54a612244341235649077a1741e72253061c5237a0444e738d72deea9afde87bb7ae7613fe2ae12ec5edbf3634811e1df1bcb1a877de14d721fe3c6593b1d6472fdadbf0dbea1baeeaf57b784ad215b2433aad4ae2333eac2b260c1a648f60c310e6c0bb205bb1a1be78fd172ffbb6839d4ed9b16948cb97bf75c384ce28589a6957857d5b8c5fb493e3cfb257bb418c825ebd31358aaed9d09e345bc0b43e124d8fb648482ba4252e44af614d1cebeaaaf942ce8abd2df1bf8b015a8caa1dee2a6e04b91b7a8ee07eb728c16b90aa964d27e3c57f194ced7bd105a4ad921adeea597ccc4d20cfea5e5d46683a12b79f9c268596e5d64ebd8af925c85a1b3bf3af3e1721a1db3b9a4c2a4d1c2b353082bb61d55f822cb5b9e9035619dc7111002d4405d8227417e3a9fcdcc17ade60db440678555ea91bd7dd515c5ea7d800a3ef179e77aaf6197f0b2b377de25f02359628d96f096d0d2719e68ad192f603aba7e61db878c4054e1d6449ec68aa0053609b6e5e089fd7b943f1bfd095a687951cdc6f2b5de853b9e7cfea8764a4bfbeeba43b1dad50825abcf8ef4a66bb547e485780739d35bb0376a7b47676c247245d78adef58c96f56795d901b44846986fc5cad5a85c73af14b04d8f37cf8e6fbdf8a966552f806230f67556009cccd5d133c8750bbb6a3bb11eddb6d292e1f700afad1caf619a3caa9398908dd38067000ff55c53fa59b32d74bde417c2139b5f59cf8c7bed69011f07a9b4e5f669fb8429769a45ecbc636e9de0454d7a4cc8b6dc1f3fbe3f67056f35234bd41ee5379c4c0842a2061fdc5ecbf4548bb350e07de10487f5d0f5776751bd8f70f395f6fd08b6c5ed614e046aea88ce3df85d77bf40cb3a9ca0f2aff3cf55150bd4f2f512b4ecb1a2d0127ea9bdfabb68897efe215ae09335284c85efd1e3f62d8cc2881955f479eabc909e6755438b09feca216a557502d68ee05e71f2a16b68313992e5585fce53f1cdf19dcfd9c7a8e6bd916de9f0e404e82361d634b44702d113634b15943d312707b260f1ac5bdadbb7849b05c5fa8c1567190d51d12f3fba540ed902bd63afe24fd11cbb15880183b2fcba81166171012da2a02c889465d7e6cf095a102f7dfed8c574ade8d385f270c153199965c313e9de30f357d911b1271f845e472f41cbae5b450bc52d920530a0dfa566fb8ef7538390dc6a9a00fea8a66c8f440d827b75e7acca226418b21dd5fb709cce7514cef3528cc15186e133638b2c02725f7bb4002faee3aca1c0123e080fd9b7c225f207e1247a0eeca8a29e855a7ed80dbb92ffa2a533c7aadbcbf6dc1ad3f34fd1429fe0eb9fe365599b92e276a2d76814be73bde593cf7bcc08d535055ad56c15e6042abf5d47aec22061a51544c90d6869ebdaa2de25f8a2bd42e7396b872ca29ad6c8ea81a376aedd933d317842bbf2acea68f162dc4ed062dd6e1f6161082ddae339a120ec28af0d0e3ed0828c4134264f6812bdd38237447b14b14bf9750b56c4be20de8717aaac0a5742ebbea74ca503bb139df9741563519c57ea2a8c618d165acbbd92c421cbaefd54f619dd8a37e2ccb9f7f10c5adfeb8427d0290d7b5e3bfa181ad0b2cb4521c203b7f7557426b8f34a4d2702f7b77a9fe023f8e0b3fe95adc9a5db23bc18d1076c13aa2a649f1688f86139042d58f4db83a0052b88812664d12caf192db06d0a2f25b4708df37f8296cd2f19c65f2daf12b31f1449b0b8ae6189be356736e933732ad998053473d5ac75d525df764e567d9de342445dbd76be95219a0b6e9bf6c9683bc299cade0fab8d6c6afa67d0bed2fa8940cb9abb39d81f8377069fae1491eece918be6fd0babc2bb19f907e95d87fefe315a44c71bbb6dd775f3e82c3a8fbe4517d16574055f08677ab9b75732c85a955f62367cc74ff9ad8e16b624dc9fb28939dbf026519b30bbf68cb4a5460b9024af51b170029565471e7c52fd14c24bd4eb91358435c27df7b34fb0d075d5d00db643bf23a122b2042d9cbd226f4c7b5ac04bed7398ebda07f31917b003db71d4c55e8e56fec29a788be83a8881178596375a8497e806280a625814c9ab219716557660f403cc32e19729eba2adcc2bb2097e1c9fd65fc99fa265717ebaefc5b75fe3935967d6893f77b3d37c7135eb7d6d798223bf51a6f2ee6b7f2a769178412af07185f9bdb8dfc5609208d71e93503763f8fef2f92edff024d56b87b5124d1eb743d68cb012f1027278f734a0259e6d6526dbdbf6499db1c11e3f35b42c66ac5bbf44cc0eff6ad705b312f805b2d14176dc0d2cf902c41d98c510cfe385ff1c5dd2d7958e1eca593a95e96e89929eca8d69f6cbaddbb2efab572f5c03f42942bd4275a6e9ca23db0dc90dabe88527a4eea33a5b45789247638de21a5a46c2f692b59f89aa667621131cd7bc43ba97259c14441c5af35ef487911773165041aabd12c29544f9b2937d0368a19dcdac7afa2b6a28cf404b601fa325bc85bde1bacc066b77196cbddbb0d28b1baf624ba305154a85178516787df13fe7c464c9bc96d3e967ad778fae62b33c6bc64b5c9ab5c7d92ff0a4182d8a89c2fb1a3105888f718519103bd35344f58a0bcc9c42e79d3e88257fe2e3cd595cabcb43e5049566f228946521ffef311ac11b61bfa4092dbbed88e70ebee236ba66279935c9b095f5f45c9efdc0f3adb87669b9e88982f50303523a778fd0526067a2737f75652f632fc607b388ae64819f568ea4d8aa6d94bee546aba9b236007aaee7715d997e01ae01d012dc5b27d02e524c9c166b789d975437616fc4fbd27a1401ce0466b3489678b27cab2ad3470fba371835109906bcdccf5f04b3a5092dc1f951449d83198cca226a2260a6002fd5fb40bf6bd542ed4354efb0b3e39056e4d36bf417718c0cb2e022ba896ec41713dc483403a4c4499c78b78d6849638b56461e9e216841ad52ec0b3e94388fff98cfd58c16ef5df6ffbce19d29edd54afe2c2e5560d0f3380f182d2a22203bbe10ef19beb5db8e1b32fd8acd64a833d7a49d674b87081066bd56af009c8f951bb781a8ed53186d101ac00b53dcd955d8c07c79c34c44ee06874eafc93108fc157870e4c71dc72d14e5283d49a8d081fb824c157a20e9a87e883bb179acf9b21cdbb6f010fd1bb28c43d194943c1dcfc33e8aa4b0ebe153a1c31e3e1c3c509e7d61b1ea6a14d77c4fa913618eb5f5aa233542bde6c91152e2de76171126a3b7cd87176f77bb7327d73f9ddc355df3f0337c8b2bbe7b7c0baca0421b05fe4878f7e003b38a04cf8e6fca20fb4bd7d1bc2ff860c83f214688efe27b595e6d6a2978c36015e3c4c73e8e1f38c6e7855d4ebbf967f0e84fe24759510c3eb267921d4b77e12e0cad288e07f1307e8a9fe39720892bbb231ec56fa875c25f9325f842e73dfaeefd4dd577fb5bb4d0738d391aa931b36ab79b9c46f38377b63f4144b59b3356d82739bc00a971482db9dee3babcddb3e635664cf8db5a7304d6a3faeccb64e52e936502b410023b3c47772168c15abe34a205b3de382ee66b5aeaea84056fbba8a1a5ad2ae4ede5c876d02f0c5108c2cdf264129bf1fbea68bfd1599c40716cd78dcd559f2bffead56855aeb2efc3ba00c1bec75ff8d088f6ef51a3b51775ae0f90ceb382758422718c66c8355698fe64095a9ccb280c67e8e42a2f68a858bedb503108120f73b558fd4175f74a8c20ded31b2c44f53e8c964bce88495e807e4306793b464cc19ed2179adbbff94acee237cf92e846a3251862fdefd132374ed7642dcebd8698aebe3ef7f18c662b93dfbd9e7e237f8559c7685465bf79a3bc044250f5538dbfe9f85345a401ebe12e95460fdb97eaf3ae76f047e88466b4384b8d16d416b61342cba88e969df2540ef92246887097c5ba95aad550cada47050678e8885fc0aeb59cf8227ef7bfaf8fe22fb2850eebf3a571673d4584c3daf3c69e9333724af976a504c9aa66baca826c18baae6264926bf96f357ffe704db6d66f66a4d16bab5798fe64051cb5483756701a6cd1ff78e88584a5896b793abad71a68910edd528c7009b4c067a2e823aede0751be5694800eb837dadf5369e0c5d7ff7dbd5faf78e5535c73400b6a32e8b73fa8bac4377ffea8ffa5ecfabb8fb3bd28df7e3f6b54267e8a776ded19e3b43feccab52a25ab125b762ddc71d45058adbd8e16eb645d208b8bf3d6ed384bfce4663055836b428b6bea3d86b399227d432685ea5cdc315aa0877dd0762424a4c8b022bb4a68f91e9b75b4e0ff8a6d594fed078ea5477a6e161053460bf26b820f7b0914ba293daa19ffa018e72c397573ab66db9566e44879aaaa7b8d99cb8a1b57e7fafcc94a4ee06d0115c0898fb04be1056889b2e034a9296bd0bda6de3ad852f4d0f7fae44fc55a39229cf042d77ccd2fc0fe1596243267e0c024b36486fe452c7872559ee41fbe92b91f73cf572c7935d845b1296205e3fb2a57e677d6afbac144472c6ef054eb6b769d702e2de1ac275722a1feb867f7f167cb5ddfb47f8c7a7f8b35c41e93dcabd2e349f8fc070770090df67a5f3e3961ab7541f6658c79d38a2b4818d8333c6a1c5bba8f453b7e2a7b1ab53b3c137b5677dc75ceddb4875befce2b68990a03535483e2cb647d5c6f27dbf189d9a4f632d9c05228458bfdf4c565bbccf394bec4ed5058d096031e5a74862c5a729a6ca3f75d2d6e51b9ac11e7d14ccdf257487f842f5bcd72fde11e3ba1e8e43d0a1deeb1179fc867c4f8237f94d88993344c534c7682162c559d64c60bea87584d8c7d6877b1d5b1a566125d279eec6be539c549ad27e68f5e49106ca572ef27a8c7f0d40a4b3c31288dc7774943a7ce7fad5f2bbb2ebe218f9cfcd623cdaea138b6e54ae5e2a73ddf0ee8b395ee0aae93731e5318bdb46faaece0b0adf7a04c8dc69475ae1a2cb97692635e4df519a3e1ba8886f41d8f7dc8a31a522fb0dc7552eda4a5fb188868144bff44a276fb0e7de7f602a8a155b216dbdd1e2bec8909a2754f61b2aea1c5147514e724899929a63b08f6bce8f2ebd6b92a64ad74dd1dfc94e8dd9d274934776b5a95acd7c2ef1fce21859417a952c96f75d6f51fed31b12d17ce05f0b11d433b027543c2cd886c871d6c939a562ea3a507a4c0cb41d4222c93550b9d8de1c4b79abac1bc81b7c6ee8582979cf950f3f22c61b20033f19793b57eeb9564dead305d44430cd7c0313ea6aeb2327ff217e7ca7f751a4b3679f95bf63d615b34bda75d3660e6938d0aa5e289234638d405826a15391c49b4815d8edfe833fbe0ba3cd70ca41e527d3ec42cace77be8ace7531c7b198fb39df8352f9b15ae7957ae13fb2e18a13aafb41a1e243b508edb23cd511c88ce2f72c8ea3ac97a2571b23eee41e1a9d7dcc59ec48c48ae91ee6331c25db93ac90a8f8b4396013f511b641b13baf3fab423c28362fb70acd516e623a3a4b57ec76ff58e9e3f5914b7bcab29a536182b494b334590a5451c9334a03169d3de071398bc1ee004ddbfd2a728fd2888146af7e924a6771b275e9f1e79c8dffb81496b28b185672535cbfa272b41557291f4f79dc5843f410b2658b876b8481a198ebf5effdd973f6b4b44b2f90dce266eb758a1cfc3ba5d5dad3fc3886b81cb7dbd6ca16393aa7fcd75b17785960f56437877dbb210c5a04e507db6d85deda6a7cb54e6fb32a38ccf5e6100031349ad1f3cbc005a5083b3ededa31f58b7a8a6236e58f5dd11edd3b3b2ffb3f9d0553e5e2eeec7ec44464c724fb6e5c8235fb6457d6b3bf4a6ec512e791ec94045e7f671cecabf481e36abf55b70bf47cd2377f97ef2cfc5b2c6fb23fbd1e68e48d665015a789616a3659558d6daaa476a7fb290134334bcbbf447b6b76a257d5daba0bf6c929fb4a39be296c7f81e3b111e1577fe4affef4a75f4720c53bbcf2019925ff7943c272f5235a1a867e8a9ac15228b7f44cbab6f24a3e44d942a9d05e7928781a9b3dac938f9ad08e378fd8e8ac55e6fcf58fcb20273c80c480500591df03874b7d262a2bafa8cbabafbd653981ab0a637d816cbe43d794794efbc6fdefd9bb8c61343dd04b5634288358f5629144c254ee7cadce3f2adeec5076de93a732eb6139e7a255100b3fd7526fa706bccb666ad165d05525556ae8973d6d73eea518b19ebce3be1ee166a37922d07e744e7c7cba784730aac8277bcf73c9585b11e576ef2b1acf592ac7a7cb51b6688e1ca318b68b27c250b93ac2df43a2635dd8e3f59ee86f97513ad7b2faa8eb2245795347819c937c9340131d229bc8bc01166a52f420a7669f53ee103d71d2d6043f0413bf91eb31e29a2b8a0937f9c5cfecb2b49ae926b64a9c117f05bcad6ad820fce5c23fff6fabfe0897df93eaa6961cb5f7e1a7bb4403144ab8d3c8a6e1dad6747c5d7965355b272668c13e9ec5b32876fa02a6f8fec374d57b55787ea1ccfce35c11c212fa485de2dc4c1924f5bbe55fdbdfdac118e11b81b996c96706b5456f92853bd93ee5c731f5d73d7b1e46e99f17fee1ef9f1d199f6d590fb563ed6a364f890a738f640edbbed23a66a4b9c0f5e96e63f620640d394d6053a7aa07483c9704bcd0a4224c39c39b2ad75dd8e3f59cb07addc2d7590325ea463b7092df1cda1e6c76adb16452b85cf757cd817d88bea7dbc6bd461c4eb12b5ee60406899d0225f0991c53fda969be43b726b62e794ad23d4b0774868717b494d09f4bf5785b15f9b3fb11b46db94195ae9c9e1af9f5f64f5f768c1c93796eeeee50b6202eee4fd4eeb3a3a4bb6e9675ac94d335a54bd4d66a9a147036dca849a09f2c1eb5a365ba165293df82ae61dc9944fc4398bc9aec62d8b763c51a4cf9904c506d1ac17f69a9665cd973d5ada4a77cc144f483acf8004ffa826e25fbb0b77e9ce9d4beb15960faf80ab89cc6ec46397992f9c89e378499d218aedc033138af5493d52938e35e400515d52954ace9f700d74d4d45bfd27cbd9cf52417d50abae1e94b79d45da101745df3d4b2f410b663efa6b562fa2531d19aeea7d80164c29226b3289ef809074ce8aaa8c1fe0ee6ffa4f0e2b9de1b9f512b470761acc17031cceb4c659fdef758c96fa74d63d6a66e932581efe9dae4ebed5fd32f5ff2c991e4ba7768813798f96e7e82a6561aa749b56ce4d46cb52d70c65df329385b0834801358eda674b3b06a7b13a5f0df6e3b9875c75538656ad973fda4157613d65f5f885ea0c19487ca127561f6ebd1396afa9aa2552056cef27c22fdc7674d4a3169d4773774e8899235e036fcd6d33678d7bb5c81e2cd2520d659d8065bdc78ae3e660929175dad1b6db59ae557b7fc39d7f0b2c71156ab9e7c108ca07b87aef9faa144e4b7a3fb0fc583ab60e8add588d68e9ab3afe5eb385d6ddeece4b52173b153597ea7dbc2b6f93ee522f384b2e521f710f7262849585b092d320fd8b0cef61a5915fc0ae68b480bfe62f220bfc0170c7622bfd8b77ea6ffbf215f3f87971b9586ff7f797bffa1e5b089b6b7eb4d3740752724a6849d234cd6855f5131e7567d3a1ff2f0add05e26aec4b5881eab563c7f0ff3be76e635bfb4b8a976e1ccf95539fec3d6bc34d394e18ecfb6106d87182b1f2892e68513e98f86158ccea0502dcb67b7455d1b7680cdb226889082d1ad19217b416e55a3b5dc15ec55e7e238be76ed147c2d9b7752da266ffee51e6a4a06a0b5f55f5b3081e8bb4c4158c6f830956f47058692bbe8aafd47723ad44468e68cdc7b6b71ddb3bd18514d508ad779a36d4f4a2ef8216ce20335ad8b6147aaf8693b4e6117b1bb226ddb447ab4f68b9433e4c7899fe220d92b7e4ad8c9624a36d739bdea577c1677a9f3ef0fac9eb91d6201da6959e80f47977676f5999926d0a3880d628b27c037971df707be94bfd95fc195a82cb3f434bc9d6bc4676ac1463d29144b75a8105fb00753dff1a55b7f42da1ffd24a940fb4288e79a1e7e14661148213cbff32ea68e17d33967da277baeed167f66cbbee97a0dea23a6da73aafc0f35c0aa04556e9338d558d88adcb42d4c546d235c69def55b49c89cab2c42de015106ade74a716aeb48c9643b7fc76826bf26f6233bac2e4c6e434fd7497f5eaa4b554d3cc60ef5a4a8b20d86747e83db34b3c74a84e403952690e438dfb427892a2526c7b5ee53d15b4c017035aa426ef2f242bacb41e1bd44be21bc1ca21ca27b41425b42c1bd0b2f67ade209dd0cf01fd7ce7d865446b11f6d30f424b3f2d45c864759061065f003981115fd342b2cd62d3d24a3c957ef3ae2c4f75168fa215d994573f8eba71687bcc467e0d6a59a33f454bfa57bd600dd8b94cafac47a9de2f4de18ad0e7c67510a9b4572b21f4360c944fc4310bfee52e9c8b0d47ccf0921ad0b250ca8a83c3ac69ad67815dbf5eba35db125e1dea80a52cdc427b62c768619e9864c3f0e05263343522859376b4db868a193345afbfee345118e63a64d953622bb4901301e88ddfe3f7e414934efdebf4cd79afe73556e7dcefc9733211118aa7cb3d8e321d787c8c16d6f562bc8015298ade8216d404add1aee2eda4d73a4e41fca23aa958ef513421bd79d4d015927c937843a385e3960239318f15be9bd092dea437c94bfa5dea38de30fd41f75e442b61bf84fdec342b712aa26764dcf01ca8fae316d967f2e627841a8596ac12d566b3640c5c015971183fc421fb5f2170a2661efdb38ac569f6e9fd6ff08295cdb345b6cc565c0d37745420ab9adb0d6ed95260dfa35b8f7770fa16ced92721046dcee25a3ed579df57f5b46ae5a0c4cd6c7816ce8981efe2baf3285419a5379db3d255c81a5a54259e75c40ca5b31208a7fa182de0245358f4ec9c30ebf85c94f5755c354f1793f2245dba86200ae94498434798d062fa370e4f0576b799159d35f0c42487dd81321e96a8172dde78be750eb494a7cc63f248192da20879400b598e4a653ebd466c226a2ddc7162ed7bdbb9264efbb9163d022de90fd806e6f8c6d133d82ec153b844460c76a9296ec9d6d93a79491c70cb826db689236f84eecb64867b24b36c5b7ea7a26be9ffc2576667dbccc94ed30f8d16ac1a5adc6c170c230b2841e74ce6c556fce01b603b2723e85cc6b57ece3f45cb53f4b9fbdfa1658f1a3f0b848b65dfb1e223edb4b4d28b630dc9ee7c3a53e6f0fadb893bdff579fe2c9d98606284b3a8ce03e9708c621f38c5c8a351e43d42671818934e4d31207c4547262aa1a8e1d0eebc72b75eee655ed71b6721ad282b9dfe3ba53dc45927d422d0c52ffdfb36fd7e0b9db9f2a3736d925e857362df61aaafe8674b7f262db27e659d6e422de71794ca36f86a582709ca753134edab57bf4ef0f85982c02fcbb23c2b444d127d8de477d0fb94953ca5cc08e67edb79cada59275c6466d6a52f2b38c35453a7e3ac37f3eab4c6acc7d1fa2dfb3cb7d24da57b0f299ea128396ba852a03a892eadec36bb0d9e64f21cfd5c8353891d8edd5c43cb2d45e1d761c1fd9184306fa4f42b0873d13321ee2e2b559653337842de607707ee19e1e53ebace1eb24ef633197b93f83e1854f9fdd96336c886b49eb2e7ec25db795b59e82783ad4bcdecf5dfd1f2dfdaae7f8d9911585888b0abfe35ef6254c09f8116ec6628a63897d20fbe2aa4577c5bf3aaf60c2961be8cb44683aa9c174dd549410bba383673cc7507db3749c279f606ac30624ab77631913d50fd95b6648e093313ce29bcb1cad0d1598b2e34a88b8351e9ece3a33deb992c57052daa6f9e1f8b17b2ece804f06ff0e835b4a4cee7f6391b67932c0d467e1077d7efcb17e7147eaee523bb90956c5df6613bfebbb3761d2f0bce042d742ee4986c2ad3b3b34af52cf8c9b5f4a1778b257dbad2d72e4c61f2c46a9d2af43cd3f82ebaf136d885c00b16f861d8f5584dd549dc2e2cc2fbd4243b1447d79105ed0a7fa1792fdeb66c2d642e04ea38b05b746bee41ce3a29a320be8fef92cab9989d673be410383a7aa7d86822551cdddb1fdd64b593f46fd0f2146daef40e9ff5665dacff0d5ed2cbec22bbdcf01ec92a714b764db6c77198adc8f570f2b0658227eda604b9d6ba161d6af7aca6d8139d38e639b725ae8046fcaaa8777b84e7cebbec72b089f16cd0a0dc4ec0cb8a9e300b2e2bf51238b9d28131541faff86e13d898f552f86c4757a4b2c188d356b732e594fe2268c1bcca65588a8ae8b112aef790cdc16980ba12f286d155729a7df7af1bd092305a7ef0c48953eb76fd6edfc396ad13cc77604da6d2adb7cf8b379e2b7fb7998773c2c9d8eb227b05fe3a3a87ebccc5f4013b1b6861ebf2aafa87950231eae07983f6437e12dee59fb4f727a9994f53931112836b42eb3aba0e0641ad53279fd29ae533a0856fb522bc74290a4fc01af3fac71c615829d144825540cf0a0085881f4c162026afa8cd253d4f70b795de4d70c3bc0cdfc1a80472f27faeb7c89ab5673e76f7a6b4a3f365beda18a1bdbbb2fda0179f9f5a7f8798dccad7c8da56552cf20d7fee27c804f883cdfbee922b7cac3882bf834d5fbd4e8e23daacae38c677d636512a28eba537b7c679adc315b57ce14e5a0ece7fcc83b45ceee95844ef1c0597def7ed4e2b5b70e55eeb6d1ba21d4498be38460b2273b127b6bd8b4a68d13a92e326b430e3e683bccf854bb19a8c264c93f4ada1c2f481492a6073d28a31e30ed31fe0c721ebe55cb8f3b0749fe5247697136f65799899aa7a86092da833261fc987e557758530db34c06e15b440dd51759b20f24e467e92374c5a880915bc8baf335ba383f99260490e6455ef035ce54eeeb0ad788627e68d8096e427e36598bb79e9a48392b8d81665ad62ae612ebc11f20bc04295f515ada111206c4a9e4f8cae16d816b23639b9de692fa89dbe7f87167afd9c0b9ebffefabe7e7f7131ff0bfdb1dcb7de6a6809927bec027847fe33c5b90e9db4977bb44c9bd022d96354fe45cb67934bed9c39006ff0b4abddff1a2dd2b1652f9dcfdd2decd93ae51ac7054f832b9d3911c715d6a37fbbc6c4eae59e2dccf600192de7c85f161d48655da6ba8ac29902ae67ae8a722e70d597f90f92a513b4206b9e1052d23777d184161d6fd17b750fc5f33d5a587dc2f928a3c55924c89541d96bc23963c28ace79251f79588f5b828e8e5bc07214ace815f6c1e56d424b1eb1d7759d781945108199fccc36e04b7ac33861c498754f0cb7276b548865094ceec7878a4522962d9de4a5f83188e1d9e18bb5918048e4e050c9542cfc2a5ac2ccd7738ed01166b377475ea8a77cb3b49f37e42bfe0e2d8b733b243fcc3ff92ddfee34998ff2d47bceb34daf5cefff055ef2bc12e5e72df8ea14750ffc9be8ccb9a2052632eb58c9a4a9fade1125072852c822cfcddabea9f50a0e6d359700b408e78c3b8687d9c7ee96765b82b35926bb210777b8755ab0fac6e3be0aa43afa81cff5a7a8a6961f7d5fc95113e6052f07b458e3f2fec42bc6ebd53d04f8e2da88d4e6c97ad5d072c135936b7a77a0733a70861c7fc8f43ae66d976d576e305a723545683f470819b43cccc3ba669d424b1f5889f758515a29dc07dc94138b624c6d4c66799bd062e29e7987163cba2112164d3cb1c04c7f5024ff00eb93fe0806400b742c701f5edb72ff09770cc74a31291666bf67696e34ec4cb55b253f4d463a8320b608cc6aba4f9f63b2be37c8ff8287f635ab32e05ec85dcd86fed7229fad97f7f3dbfc2eff850679fe70cc35cb7f46673e76c1352dde0998dc267df37aee67f599a00ac65801c770acd8f1cb3d2b6bbc1cbb35e65c744f91f8be139955b1433d8751b3090eb7b6d75cbb5cb206e9821f7b0c6bc71ce94751112f3f3a3acc24af853e97325a544e6c5cd6ebcd1f65e19450b1540a8e5bdc8e459da35e2d9a416102ef1345ea5b9c29ee56f456040f9b79f9f185f145b11ffd1fe4c128da7fc33415cd62899ef3caa71b749427d6c73e979cb137929dccd931236f98761415611f7e5afa4332c9b837d9165e5fa2853092cee33bba255922ba551ee79c5120aca53fb2fbfc292fc554b2e3753ca4ab928841246f4d114ca53a99bf84f7d22da3bb6682a1aed980f16c8daad9f3df59bfe220e7ec658535dfffbfd7963952f9287fcbc7f9e44bc4947cfefc833cf653e73a3a23cbd27186fe8d6d23f7ca6cb1cbe034b1939a0f003f46ebf4a2b7725f67311457d26c60551a8c9677f6c7b2b5c5793553b427359feb70ebcd87d2b900fa265c911fec31b3005a8e2b88dc5786fecb1328c03aba4b53cd1882e718957856f9995ae7f9379c0ecee7e26dbd582ff28bfc92d6d5b2d6d113cec0064adf820760c5e7da0c23c71105236b579e28c73dbfd6aeafd102d56daeb3d3e2baca5d35ca5768517811857a8927683743b7c8ca1bb425a2986d90b02281163abb9327b62f1dc4214d9e185094dfa4efc9336e49a822b4c421a1852277c43fe17d3983cc38b1b9c75e7b5540e438ddc577e4fb0dad515ee929cf7f14a7d18d64cc345a1cc42efb55fccfe216bd8acfd369f1db4a1687852a75146cc7c50cbb1cd9d97c54cceb78394cb48cafdc35ea05d0b272de7982e78eabfa509564ed1cbb96df82afc2bd8938ed0da9324a848f1cef3c5b2fabea724f9197b2bff6c42a192126f9b0c2232b0f511472896eafd2eb5fc0ab835adfc682021378bfa295e176d627d38ddb5a1ef932eb041d62e1b7ec479604a38cd0b84a69854024abaa1da9efd17bb20410bdaed7f347b01bce8558c51577506f6a578fc940a83d81f6e85c907707f6f504d3b06d6777879c6279c684bde5f95c983d640331a848f2492cdec86dbd9e5dacb92acfb6c4bb0c6c646c91b542c4e05b88fa8b866947c596f0641576b4f2468c2e8b7ed22310c61e0a27b29a6c4be1d2da151e7df94590bb741b64034433e692ebefa51a43f0814917d04c8e43ae30beee3e838ff02ebc65db42d75cf5ab9273ee45e3be7cf6d528562976e90d2bf5b19dfc770e727d9dfe95e20e54108253dae5afe10c2bca10b9265b0aeba2bc9c4d5b784abd346da1be8c283b0a3996a55dcb110278e95fa1652c1e18aaff1ce71b8c94b1d69c5cbed53db1e01df8db585c694497ae2968610470d45e8e5b629b39c488892ca5c7ad237d286876aa68919888d032c9d2eda37daffa804da5f247d82e67378016b2bfa32cf4baf0b00e68a158ad5817f50a13323bc2f6c2edb94e93ae6e7777985db7bbdd45b6ed976ab8ab3bcc6c90890d6a06d7259fcbb792f37216555d952256ffbf4f7b7224dc7bd16dc1a90e0b5234c42df107aa259105460a6b806b55c851b44266b8112d2921254d6fe867064f0cbb3ebb470403c40015e5dd8c2e2e8ee90dedb1b12acc8d274a18e45d55b52a735b7278dc41804c32726137b9cb56b38f5ad2bff7b7fcaf961ffbf1768cb318f6821773059353da4db7455e141a2f9ebae6a2853dc05ca60ba5c5cb510b6b48be6d72e0a5fa2c1a2d7adeee7aa9ed0a343237e78496da7e8ba7d8f1c23b638e15338a65de09bc1ce728ca8f67d05d523a65870efd056bf84f8004e788270cac6ddec157403dc4990a1b73a5669721723f460b2aa2855118f908b9303052c4eb93ef9bdac41a281505a7f0b8c06729c7ee989d15deba4e50dacda2f2a5b9f4f0c98017d10dc65add5575558a36d723c078a4b845eb106b1f0868281a38c8f1756425236f918c10bff0bcaf916881034384ba263db15efa9ede2466b0459c026f0a1e18b263126b44473ac584d311fcb4d82accc28cf3cc03e32bba091fa29bec0168a9aa83155dbf153d5b9eca830d9033ce76b947af4d96f5bfd513fb97e5c745af98717571a73236ef523f57f3d4a7455fe345bdba16f68be47c704b56ee2a940a44614d10ad569f8527ec8c554c213d7f85b0538016dacdb5890bf43cb7d26fb9478b4cb746066abc7997dd7eb8755a6896f2fa44a609a99abe4c7e41aeeee84c73e7e84e117557c571d65ac46ac24a192de01084f32491cc31d9953b514fd51cec7a5ea3b8830f86c003fc2fe70a9db9b41fb023728a656c2f2bd7dcbc2e945a241bac6b28c2e315ce70035aee938be4826bdf14bd805fa2348bf8fc86d568424bf1908c98bb452b1901339ef863e854a1851c71f53ede8622fc7ef2425f3fb37b5a7666ab283e66df6a509494d7906d20df2c2b1e8b41312c9e8ae7e2250eb387b0c81e4423b9ca130b7ff004cb3e2a92d90e38c9bde2b5784dbdd4e3ba8bf5bfd3aac48aec99938e6459d1868eb2d31a53ebabc5dd1172ee21bb9febd37fd5c28c299ce691b158eb6e9af95cd0c2f57bda2d9c1d421e762ca72c5754f27a8608f9304ca4d2554ccd2b638419b018f50c723c6506fd78cf8d264f06750a7495284e72e9799c47616b62b686f4c01ccd3fe923f35c450bce0474aed0230ea4f793bba1c7f2bacb8c1fa085b37d17cc439ef3269e0bcf07cfeb5c54afdeb39526b16fdb9b79f040114fd71bd3cf2c7840b53e78f8155af64ba1c5f2aa517e312ade8a717e534c1085271ece7cee1fe69a09c7240dccdde2dd5b041fd9963b7951979159c223f1cae83ecf592d43133e8477016798939f8858c0fd026698d502fb6296b92c1483906d61cb322c3e8ab3e209d605b685e720913daca3457c34b062d2bea025edd1d102fb3271eddd6575f6dedfa2a5389f5e3567b1bc1ff19802bddaa7587b846fb42e0e6859e5c56571992c8b4b3d9d077581cdc58c2dcc821eafb80a67f0c3988f4b76057958894198458fbee59a27c69d5c6fdcd3fb6a3fa94cf28433c9f849bbdba9e95bc2b6f0234249a6cf18f11123a1daa2bca0920dcbaef01cdcd1bb541385d48414a0253a73ae2bb5fc0fa91f125a16dca9c57e24ae5d4fa72be71db49ebd585fb912fe9bacb95b63c76bdf0b3910778d4c217c33ac3d5aca1d01b6e6b31f9454f8dfaafa18d875db12dfa77e3111b4681e3e4efa6c535cd3feec160dfe4bf180685ae94c8ec4fb42a511513e3a4a9a6c4bfe99d9c140aa91ac4acc1c99bd7589e3fb325ac83e5978c4cc23a49c49ec42f8df14a78afdb52d2a96221d2277e66f72b79850b432109c643bc519db0676f13f895bd2dfe0b4ccff63023862d47581fa31e7fb29ae067a5aa78420352f2a648b7e9a724de74aa105b6e51dde9a4c905eee4fe42ff4c41827141b516cc168194bbccf7ded88fb27f5b9b5d19b748e4135783d3dcc2ae1f35ccdf629ed8385ea4c54f54f5603d4da01636780dae2d1ebe62aaa706f90fbdee21eaf32831e738297afe59c36508a186defadf25588c70a4cd455b830ad1cf942c41ec1b67552203b46d6c21f09afc55db74a715460233a672dbb58d81fbcf387875a7d51f91c5b53c6139df9c88b2986259fffd9866271daffad864ee3f8035d5c14755b6c4956d147fc50bc142fad796b5ebc641ed056470b1832dc6f7229b38ba2677428cb2cb0e826be2b2bafc2664556e1c0bec416aecd234bec4d92312c0662a05625c315fcf42c744b7395155940702be9763835789ec55f29c756d1e23efc3e83e5ebca25aa6bc13dce3f4cba81d2d166557c4bbe1717ebb7d6d28fed5d4b75cca75cfb3ff906b47896bbc66e11b46c9ff768515dbed567c14403a011f57cd6767f638f6cacaa9313aba13f2ed55e5167094dcb8b0d57d1f1ddd79d68251b4668196d5f9141066f40e6f6223bc61a12b9d3014fa7fce8b68dc9b1620b91a1206f9430c6e8411d3459a56505236b07b67579bed0315aea714bf601bef1660e6bd2b2101bd28e3030c18ee377424bd91b0f27e002637e3d1823ab3bd818541015c7b8efcd6b685973e54f4f868037f693d5be183374b2bfb41a32c8f147e114cea1f3aab56dd914593c6191c794d33d6bf70aef09c18c169f1968f0c1380307463d73848f6c0bb4c9168543b786d22c21c76f05e47f012ba9d7725a6eab9231a58bed2377a6f8017dcebe4df29bc0dcc1bfc99d4550f33bfe142dd1c9ef315764c5e7c93e035cd9c7b9bb4d922c2cac96d7f2d3493a61ff7a4b7ef4292a6c51a8f94cad008ff4e98597dc8f8eaea814790066253e3943e61f7f824d5b57df03b756b3f9d141251e0ae2851559366bbc1db66a4a08ad882c82d4f4b6f9b7acdd8ab3efc9369cd335b1fe04fcaed2ad9356daca082dafcc3d5b5afb8e3668cba0c3e0988f8308240a854fec2ee81d78e34e8037b07fe96b9d4e5a253f6f9d401b095c7b70d4dc35db4a641bce9df636588ced9ab70ffe3dbd2b57a8ca5b3e2cb764bd84310885a1562952f3ae31d3d4bb86aa29678f7906571cb6e43fc243b5e6d06a2b0fcca408fa0ecc14d6aa4325d1e43aa2d96aca893d099f9896036e65c2fdef6e2fcec9ba98c953936d893e22cc017b958e46f1dbf01b1087d827ec47a5574208cac3bcd56df5307712196dee64c679c09c16afdfaa4421ad5be8674a1d1fb18bb7f532e12b43a7127a65d548e7cfd132737e1f2b7a3529f221d353185908acb4ee90b163bcc0bfaea045f7d3b8b7e28f002d58506641bd9aa37efca5a1d318953af440f2ee67043857ccc3e7aacb72ec4c5b352c473df196708283a5055f8a2be2179c91e37a47e9752412854b1d46f42698a3924a172f3ca33a5a04c160472ab4085ec650122eb31ed195229d8db0c20ebc54e692e9d975f50cf2bed2280579b2ad9c15469d0a5a435b6f528e5d09533cdb94b35ab46f642e7d1c26d7c975eba1f5d080964ef2135177fa23bca7758416c2cb53f2d48c96d46cfd6cfdcc3fe15f45d7b05fa8ffc3178357d6c4416e3db61e51cd549548468baa6b4acffd475c3afba52a8fba3c508cf8861996b170c660f9aaf59622a6e844296b2016239c64f40839b2905927b94877c13fb32add5f30bbbe5edb5ad48fd0a13510cbd2bad3b6259c61b68142cbfe5d57683967b4bcfbfb7def3a78658e8a651063579fc5eba25a9185c15970d61a2aced5774c89b079d2fbf6b9112dc2d14426813b04801c891f24c3503ed15bf75082e0feae07b2703cc39efe25fdeea893db5fa105d642a3057515287710ba2fcbfd278ac7c97c4ed45a24b7a72708db4f612d46c033ae6e612b98eb806c862f53b9a473c3b5cb684157617c8f6c2933e787a23d1459c9f7e47beba9857975958ec3e415bb0f5645a3053e1158c5c04bcbcc3b4d68c907990da4d0a95f709c0ec6fe037964cfad178af33f8aebba27d67a6d8df61328469c1b4087cb0af10fd42f828f56294e0d6f95d6f796ecc31df7e70b036c089e59f2d3abd5f2f3176fb39f3fb165db922317163c040fc9b8354ebbffae1adefa92d3f5ab35bd9c79a7475a208492775a1ea3c5c7b9ea8db337a9eb87339ce1078f441ea3a5b48f8196d6b075d68a43f66464d64e70da549d644191f36c883c7aeb5b9a2ab4dc80c78eb578ab771abb93f552b253bcc6c2995f058817d8eb1b3aa5ba73eba2758995a5d98f6c4c5f1330e5fd1f81832595a3f2a30beea48fd9b908e7f2ba8114a008b6332c31f6c13a8e42ee965fc84fee96b7f01b782aad9ae6b9ce3082e5b9cad1d105962412c2f0cd507729a3051a5df0d3a19a1a905fc23b92abebd23b7c9ca5e5d77b0d6f05153fc14b192d6457082fad869c58eb7b3a975b33cec0dc32c91e510493208ff6d17a8c6b59a1d68fd68fccc11cf0e083fd2eba2ed46a9ad10206259db8035aaa0b1a5e5b867c449fe3aabe5161041a27e1ad3095192df78c969c9530b7c998d6c5bf4fa4f81bacc8323e17251668ebce981a53decd84189cb0f0dc850313ceb02b0efeb5baff4c78c66c29ade02c5ca4743fbabfd5b2c0352b66ad1a0b8e1efbaee518f3cc4cb3346d7d6bc5ad33daed4f3bc50569428bb1e0fc1421c5b2c1c644e51f1961ec71d44f70ffd2ad21906c196b639d25849971364eee937bf86f409544e5c76861e573e6bb4599374e4ccc3ec1bf7585b69cd38e82ec4650022c095ab0b711af238a376a27b2b1e5495a39d84fab96b75a4e2c1f39576be75c115a683f94a37c42899af8c0acf8e1fe0c67c478a360509df863d84a55fb2e9d1b0eac0bce728ef69fc07e6c464bbe2b26a9cf8bee6538c25ff1461a2dc575f2b3f64a5c63074c68b4080780aeea0bb4104e7ae0ca242fb49e7313b9b14cf5160013551d58c323940f9562bfa8c54e50c9457447318b4567f1ff47b49c4ee7251f98ce810c3dee8585257e7b3a612f2c435d6577a9d192abac82e1430fc95da366806a9b97c37b2334305a8a3b23306a137e292e424cd44d3323045a82b3cc820707ef1e71ce3a891a7210a8b5439705f92b559fe16913928f3ab62d4664cf8391111b09b2514a9722594b67afcafa1e7d46a95815414b386b59cc547917bb8578aa9cd38e82e014790fd44cc0fbe2aa7c57ad31bde65a35385aaf5a400baa7514b3cfe9ea7db0533673460bc528e52a02d0a22a2603f6c446c778a1e8a2829662cd3ecb207d3772a3c86f50a72c26c2bd075338ef180d7a62ad45b1cb5ed27eda3772e49dd279eac3a343b5057e122c53f53e05ba015a52ff97daff9e8fb9904ecd7294eff593e7e4d9308cb6d131cc96dd9ac79681ae64cd7cb3aad593d6d49bf02b47167caba31e7e87b76937dda53ba36162f79fa1655a56df5b245fcc488eb7def36e58c78bbff702981d7e55420be345fcb0e0946d8bf2c416fbea8ebb742e767dc99b49c50d78815df90a2d98ec86dd88c746754ee29c5d9f6b2da885d754cbf8dad6d8e7c866d189ac62782075d7d7bbbab4fbfbba9b17310ea2865a45f12873a9e736928da473c1b8055385bc484cc1441d66b438eab829e82c48bf4b851168e1489d70c216d94f6ca33e4fa387ccb5ee9787e617760bfbe684147040f2d2adb9474b7828ccbd571e52a277709c1895d3a4759dbb849407e3a7f1680c8acc181a43fade36da849327dc2bad59097a979e9321dfe7c17800d238b6505dc66475ded3f7bc3627231d607a059832a8fd4bf65967c7840750ee5861a4e0bf8ef162bcb6ece2051d04a22fa66623553b753ec105439c8f9c98d816e9e0075a5a14b9fcbb6dd15c14db3746ff7d5fe32d284e324c04d34b4f75758681eb0cc33962fc96aff342386d7192a2922668f14a5905e4a4c86bb895d3964fdcae20acb8832756d4625e61e2828d48ef4bce19810b6830d22e7addacacb728346ab10e3de7183d67c884593e67c22ea15c419ed0a5303acbbed5ea4114fb45958fcf7528dc718fd5c612dc1ca34598f1a8b38733e336b1e1890141aa963f2e33d712c79818efb03f51c6af029f25d94a78afc6877166d4f4ecd396bba413c594f90fb6c7156d9bfe320cefc003f1ae8d92ef09567bb6352e389a1ea91e76eed4e2ce93a7dc342eab68219b72655c1b37588481efc68ff6a9a0a57d525c17d7ed86f92ded697bd69eb76774cf070407f0e41899cc0bf006d9cea845d4e4295d83a7894885ed5d5732c8a8fd332bffa8ff84ae40b082d5262f2c47564faaaea2e95f454b7b51a4a23406a50b9908163ca4bee17893e02ca128ffdf6d4b5bf945bfd7612cebd43fd8875375fe53cc61a569f6bd35e49e612ce4b62ce975448d5f72625a0b9691b646de195509cc03ddbe163df822067db5575875bf44f1aaf884e7889b73c39c95659e59fed86ed0696fcbf3e4e97bd66d6f8aa5f1005524c583e79c5669f74432592e0a51a50462517b915b01ddf0b78e1e7b4b18bf452686b35d16ec80354255137aa9f4fbab5baa4e1add56066f0cf106c55c71db6e0dc90bcdd1bf024fa39e136b3bd2b3eeadd31e7dbd0b57924f50e9c1b5cbbdc3ac0661eabe2cb20e6dde756d3a9f5f68d719c9cf76e5cc6fcd0c8ae50923df092d3fe8bbc9b7ecf0996ef2ff6bf0c4dabbc207faa22e574f1e50cd240f2e2b76c9b0d8d14f5ab5fb78c58eacd0bdd43f09c1cf58b949b18987683e7b29f7cd1bedb64f2b688774151d44f67462e459a71d21624f7714b3576a8d51e25d8ada8b2828a53b8a84e976699f1e991963ed7f570d6726fdfa2f26e6b413d9f3f92b7f4e63ecc8749da6f08e1087c09ea0df45db8d76fa147dfa653f0e5107c51e88596cf831c59d460b7e4b28eaad3ea7d62ae5fac34ef39c0fc871aeda0d3cd076ceb6ce4cbd62d92e804ec596bf006b1231c7e1b67ec65e1bfd0dd70e6f103f6123d9eba3bfb78f764f71c54c140b7c37410bcf0c1a0ba706dc83325aa4fa4468216f5afa80e90b6ce253c433b04ad56b8f4fb90adfc379edf512337184532c1db4f85e8e76552f475f2a25a898903569f3ce0706dad9a65d51f9506881f77545df7de48c256691f5055adac610f932c429cc902104a097049e5ce1d3d7a4ee89b53bc52e77914160b4f411bde3fa8ab448f1fa928bf2d9cfffafa35f834c11f306e102ea7b14b3779271bbc2f488c05abee71cc5bdca894d34ab52d6bfa345942aff062d7abe8bdc577612c5de99ce87210ed13108569b3ed5785ccaa9cd90d1c209db3ac3ee09e7f988fc91293c39e461b19baacf2899697a6ce6ad03950a998ed833db8e1aac6dbbd73a6f9db3d8e39b3c02ac8ab03d6595d1c23647a105760538865789fb325a8e7c8c765fe90d5f6cde51a1dfe398992c480e87a5b89afbdfe0b53d085a504d84c7207fa558a48696e407763fe280ec85765447f243a21521d9d47224a2d5863852513b0dbbae650a0ad21aafb0b8c16e97d89ea27b0fbc6074c9e33b325dd97dbb615a2345f999f1d43e01f312f92fb22cd7ed3bba46fa77fbbe806252ad1bacfd40c898d4d182dc177258c945bb1421c91424ce40d077b024b93fa6275c7cb0f06bef5406250c55c597194a5b8d93ff155ae8ba7e7005e52fa6174edd598be38f8d689350f4ddcd865c73e198952cc54456fb91d660775db62c6dd458866d9bbc91b3d659fb89ce8d2eddea195968ec26a7e3d4ea627a988de490f6ab2bfc75e7729dd4bbc1e8737a699d174b2ce4e9982d4f9e12389898919c2c9365fb757fdb91a8ca06a7e84090c9f114e5a0e6d8c577b291475ccf30c12b97ea24f7c9fb5cc14c79c2d22dea88f13eefd01e739f38d921d1a240e73cf8e7de1b3c39077ce186d891f9903df1c48a546b45000bc04d6eb64bafb8fd8ebdabd79eedc57b3adb243fa3dad4e0f6275081c5f761b464f7e4b6b6854d4f68f9a85f53fb8c6c0ea1456710e28450725e04c85beb7ec8fabde86a5dc94e335ac80f634b889a0aedf2306f97a2017a5fae9cb577153e640fb0176c573b2d177985ec190ae4b56bbaa0c7b3f454566f224afeb0c919e7ef8c87f6e5bfa36537e06cf0eb9f3fd253b4fd60a45de3d4c454dccccc868c8c47634a3ed504d147eb9dfe7dd5be6e57e62ab5bfa31a4f68f901ebd2b6a1dbcbb6055880b5e838353e31ec4e79edd1c23b399c6d27f5fe16a0a5b040cd6f795e379d444194317f79b0ca811574161c94e73b926db0c52fe2df516f1cc23aa18e149c768eaa40e19be064bf7c7b2bac3751325add75f65172671aceb93e9dc18eb092d99a6bcf7d540610bf040dfa21ec79e1f5995cad1b327f8bcee5ceac3333daf47d9fd1ee2c501544f4cc2a14a12876d1ef1f58a8b5776a5ca2f4a7ec70d9e3a8b7a04ad9597556e17dfe897f150d1afb1d8bac51402b4d3ae90d452a3bd81ae3492befa1d3ab7e2fb26dfe012dfb0e1cb21d1961a238edec9fa9b309f3ce9696dd715abdac9375d29e316f39c643cb05528ab45debb14fdce4591864c22045660e88e10e675cdf55e72f2c42152d53992f69cd1a180ebf87167443a6136694d39e52583943fcd1d9b5de3b5efb99b072dd398a594ed79d00eaf2f0dd9dab34457d32eba2dec2760386f3cdab31f6092d7752ffe4dcdb1deae6e25d0997d1b90c1b5f85f16edc464138c37dc04a8182c416734bdea49fa0a3d0d289344664c1c6009550a3eec49dc41b135a8ef8499d0c911318e1d8f5d205acd48b7c6424c0b517ebd2c95b96f88d5e46cfc29df288ee814dad3fda8416f630d6deb878c5192c9ac58993bc70ce8882015a2ab2e818c2be52cbd2b596c2e6e544ab4e6d6a41eb1ade96fefff0c65071cc9ff227460b7d190dfbbed381f74688f11293f62e45f7b07a7bbd9701d0d7702f13f1cc1e2db74ac5ec3ef581ca4eb7fdd4517e74a7cf1d9dbbb4dbb94d2e5adfe8a44004f282be7ef2463b45daa9e5dadb8b62a794c9fa52ef278bb763dd0c596995b5fc376841a42fbaae9f5e3c69661837af4fdff8d468819d4c4cec2a3ef5ef12d320dc800dd3b9a79717d37a4897c1337cb7f8bcf3536bbec8b404ec78b24b66f12adfa53fb4ee9bb2863a9ff360bfa41e79475dd69137e5673ae934b2b23b83ed68b3dabeb67ce3035813b6a767430340b2dc9d61e7a9f38c284b50226c1dd6e1a7e7ebbcd0f5bf1a1f5e37a82930e908856d44c6b6239798c4ddc25e70cd95de13e31ce846f7633a499cf47bfa3d715a1622ba9605ab81e8b4c913eb8c929f744aae73af984437d26728913c45f01d64593b6f9d7167d279cf4d30286143a4722f5849669d0f5a67c92c1915b5da49e71c5e1a188f9d6fc54bde699f020586c3cc16e6c2741a3a013b840bec7ce367cba57d986137c2e669b62490d770afcbf88e5ec93ee692e9df60dd4053b973d5fed18e3ad79d9bcef7ce0ff3d43c313fe9e7341b9833736e2ecc253a22e9c4408f7dafae3bd9ba2d26e5c7e6ead29091ec09cacc866bfa73b43c45a7a59a7ef4db6a628b737d1fbad673c2c47df6943de1fc26ec98adbbc2829de9248216b392e14a0d51bde01c51173ccc74a2767d97cff2a4537f47ce052f40548a4e0744ee3c75018b4edf6ebb715ada362c2ecc75f1adf56e6e8c8fce7dcb0343057811ae81f2ec3cc9c52536a30591c49aae69582ccd6de7c5b44d875e53adfa69bac21156d17bbeef9ccfc48ec056325aa6c639ce019cc6a8509a3bd32b9e4c0fa8494cfa3cfb149d34548bc2344e042db94b68b986de1df683ca77b50dd3f4db2714c950fc0fb4908570142fec12d58dced9012df5473783f67dfbbef5187db41e32cfe89821f25ae0b4c03b0273f22bb4ecab9ad7c6157c1db22c0ed426b45dabdf2b2a28a6e8e99dac3a8e4dee6f79080b33ea74cd98364edaf94108c9902ee32fc7a420c96cb7a314f1c73b67051a7239c12677bd5b3caa28c54a5427196a59e65f784f4d68592c9a782dde2f278fcdccc36d773f91972d56a66976cd9ed937cee92495b842e1c0eb9a95dc8a7957bc12b2c4abf2901ba573fd2cebc023231bf30464549f1367bbb00382533df58af3c8aaf330386b568676fb98abb81d8b365738cb47b487d7c23710a6a6d82b328ff7e68331273f39cdcfcd9fe6a3499115c555df303b1336ccac31d1cda1f7062b82ff0bb61b5bc61eac24fa96528f1e8dce10634eebdcb8339f7879a6479eea1d6665317ade690710a6eab12b167a06bd5e91a27f43b487b93b5771a2a09485d804d3b01097236e001305bb39778bc07c365fccd7c4f316614376bd35e3be47a770cc51d8f737f08bc813bb81e5a07bfbc6d0acf9c3e44984a90f4f495525076c530829be2135c7a68914fcf9dd26cfb82ac4ed606f828b4016e50919617abcae39369788ca3159029e57d6698dd3b99a138ed87dc0ab97367840ad5b6f8dcc81785fe41f7a858fec7432602533d7786cd7fcd0bf430b79f6a3afd860cbf3d3205dcd3a7a9993d36857e1f9fbb4e7836d94152b154f74254fa54e579e2c6456b0677e644fb4a7ba12750055bc73ef1081e0feb43f6bf1a5e4a94b4b29c0ca1cacdd65daf31b3e5b2c3fc62452ce3c816333e6e987eab9b337c10a7b911eae454f0782e2ac78546047a713b321d36e9e73d524632f92a7908a1f09840027829596933d932ff0cdbc281e8bc74e617e43ec419faec3392ff81778971aabcdc14f6fcb9d802945ae3e9000af4d77054bd62bdb3047cbc3a2382400ffc41ba0471dbf418338fd615e365cfd551c45e884b4c9fa8cc09134afcd6b8e4982f65dfbc4786a6655d28e172ea68fe7464e011f33ba8d819726ad4a465940bb1931b7c4473ef281f05c8116e4ad90bdc2a422569ee87903d7c63320cbc595947b5d7d341baec9fc4eff872316c9506b0f5133748c47f37fa82716145fe1e5bf974f3e0c6c43924081542fd1eec50262ba158fbf7b920d694f49b4d2c50e637f85ad0d625e68be56afd11b6b7ce8aa88b63052f5f0d6dd069e067f4e9f00c9fe7663c2668fa312ce0ec09b0362b8bf6ae35c3903e4afe9fb93d30116801620acdbd07dd79d71dd24e75761614f4bdcc6f908c46f676453ceb27532e8ccd2ef71868c16a29660abb2424af90b1e5cda90ffa693ecd41be08434437cea7806cef378b049b92b1df4c80f537c43988067c51542f2d899f545272df0d4ad759af1d52fe2a8b0c94bc31a11529ecd67c3e1ea4bd05d7e8d16ae9cdc612f0359786eeecbb7d199dfb2c1ac6f7cb695d146e594abfd93fc46ba0665726bda370aed67691bc253c0865c8b65bc8b35ed36f03564b606bc4fc969d32902f53db28fc615f8392db7bbee36f44cff2d5a289258fd2d5abadbc42e7af68ece7ec57b11b4b0073f169bd1ade456ba8e394b7b1281a0bb8bbc9f099df296ae6b831b50434bb6ef22dc69c41c3258a89137f1c4f8d95c66e08055d6479700ec5e3857787983f744b8052ea0feb0c3e4a2d52dbeb3f6a30f765a38eb7e9153a1d7097d2fae7d229a542899b61f6162052df49bdff5f48c52bc3ef0be0429cc92ec4351cffb4291aa1b64eb2e0ba7f24ac0d14a06d99a5133c17ed51a47a8ad17d7c04afbb47dca8c961fdd9483c1c65ea86e81da8a5457321b7685227c9f6d12d71909650db57ca08573c81355d5a4fd89ca7fd780eed7d768a1e76b3307cd949a114f6eed704ed843bca4b022d3bda0acb1672c0403b0fba1186679ddc6f80353ce44c7996e87fe01660a913fda4ffbe6bc4b21c2ffa23a595ea7dbbf430b798d96ed811b8c88bbf5adf58da26e64aaf8c4ee76bb3d5a953eeaee6db1c479cc8c14f6f5bdb57385de73c425c51dea34d5eb934e7cc9d14a360d35519dc5023be5eb6ed2ee1db0058f4dd002268beaf1ec4a068e36f4352a245c61dc4abfe2ea0e3b5972c9e1173371bbf7920983c5229be2711466228bbe470be185a2b9b3e425d8ea4e61d55dafb0a2b48cbe42cb03a3ed67f7b13be80e693d759fd81b472e0a3b3b2882740e5523a9ac307b65980c0b173cc9ee73f7a5fbdafcc8eddb6060be7647d93dec0f63e587a8234945937e6bea065bc06e75dfd846ec10e1237b9c775af3e22cf37e8996b121ec35f0713a096ca6a8bd7255442a8ac26186cd94d84cba2659e7953e926ea3fd459d351828262973a1b59d62ef8e222173f9bf46cb53b4de9e867f8316da757638e37c5529ab2b9173e79ed152895bba1f84ada1f9900dd9bfa7efa9477e0fba36e8bc479da65bf3c4c0f6dd29f688da756a6eaf786751d8faa2e7809eefdc816e868f485fd4eb544c05ab60aa2cdb9baa1fe6a206a96ec1f631a9cd51da3ff237dc079842a45e582d1f6940ce73d1a9c97839c3445ffafd224871c5ba7ffc8016fa495e44b327c6cf71899d4f76e5aa7bddbd81ddc0c24ec52e87f7d5be47fcd1fa01b480e9c26c62610a0fbadfbb5ff8ec2df281e0739135a2d35dd7f5355280bd5ec324bd16797784c2b47dca2c4a44223bd817e8bd207a8127f4d52be99dec599b5c33e29abe785e0a295255d4d900353d897b22c365efb3f7851685d14a7e8a0e1a67b7d9da727592ae8e22979fc655af41ebe9dfd08215da7f81160f364579345dd41a833354958a5764833a0999978adfdc7ef347bcb7eed21bd466c0100b17ed1f59273351a544c6b57a65e5a9d6d8615ae757b32dcbfdcc0dafabb39db096eabbf0d2bc8ca2910cb57564142842e7089ff537c68a51a6f93559ef97faecbd05d002ab081f4b6a8f14c731cb1653aff13bea11bd65b0e17a816849f63976816716cb74d4e2cb0923bd55cf328674168353ff1d67bae63d4ad4223593debab74606195e54f7adfb660c8097dea6f76555a067d37eda817ddc73c81a3d895561ee0a7a559cc2e93554c08dcbe4698f164f6ae5f0c7f2ceafa37c7ec65dcfdbe385fe4396173512c4efe00b6b1624ec02f219c806305372e24d7a7eafd6f3b47fdcb048c98620fae9b3bd85488c545bd8f6192fbd3fc6caefea209f64bf8793cfbee81af7e2d6b035e4f8c322dcc49c773da3bfc5e02d80cddfabf848bdd4eba3eed0f592019dbed35e664c55dcdf150fa97ed26aaf4b752f737c2f1ada4a1bc2af4e8aabdcbf1db03a11e272a00596049d10ad6f841633f78a2567af869c21637bc7b6d2ecfd87fe41afe8b570f691d5c22cb9ad4427a2d58d1a24d7545e7a06aa02ca33e7ba03501376fd58d0e2f68a5f549b7bed5e073c44c5117b928a85e4c222c92147e6c81c6187c3d230aff8c67824ac7cb973e951bbb4cb0981bd5eafdf0587e5bafdde7ee79a0eebe537a3a5fd403bfd47f7198faf264d305a608d90c9fe2a83ac9ef3b67717e7625780146427025467ef7af7bd87831e6bda4b29e4daa365dbfbd9fb8522582f4c3af4e9b912d31b0f8a0ded19baad6cd6fbe3395ebfaf1a6ec5d3ebdd177aafe5d5639b4b11cab734850fc6f605b14bdcfec18cc96fc1d9ff6bef5a76d306a2e8be9fd1ec116d4802eaca9e19cfbd21e51d12bae395429a1a302f83d47fef9c1993aa9480db2aeaa2d6115240913d061fdfd7b9779057ddcfed4e2bc868415d16e55c77b167e2175dd70ddddc55f4f7d76478e4aa91ed788ebb7d37f7c475bd60f2dffa6075f20716a45b987b062509a2aab8ee2aa9aec3d9c62fa80f15cdbbb36d7faba1d8d729fae4745bdfe9067e67fb4cb4d3a18c8db13a73c77c95d786fdba331fc6122a4278626014145f26869fe94fc1dc3f3a1f4ee7f53bdb75d2b4fab0beb9055a16caa0a5dfeb73a7a017655df037fa425fea2b5dd447f3a6825d84026b243aaab511c840c31b73facab84c073c313ac35e44f1d3a68e894a362f16dab8a386b35b0df211b6e04aa8abb4cd5b2ca0e38fb06b711d3bb2466e4e60d5f9638837a00e93a5604c3d3aea49d18086c6960efc8a79e5cd13b868ed1e22a289eb42a00393bd4ee1f766ec0f6e874718f358d8fd1feaeb982d91a85746c6a7b2da626f096b83187ebf6e38bb4b94fd508228f35c30d130b6d5527dfa8ce73af203fbab715ae2b8e6fc233b0b207631839b99326d85272743d3886c0619b9055832f85e49af335b1700b5f711d802bed023a5d436d0137db5b982b1cb8b261e19b9589342b27683a6767fabb2f5c76bae7bcb17abaa630bcd4e9e2522db1f9574adfcc4165a4055e9bc30bfa62f6849272768f99ef3e35c9ce2ea354e899ce8905f600b56bf2ea94b6859e0f760b709d4836caeec1ed775f24a8cdbe53cb96915bd6df307ec4e31753b333935e41aca9ab8e185b4a117e3d1e7e37988d0cccbb2651bfaa595d3bd4c765eebeb7962bf222706b751c36130a4bd98570f48900cba412ec8c98ab8f5bad198947f17ada271ecc9caaab76ced5d5da0583415932622a6ebe089ca6a4437f4912a54254935fac5ab329fd60d1ad41401a03aaa8333785b6f63b0a516a5b003f09ca84d261a99dedb0aeabd9dc7bc990d5d44148e51f7df6abaa7a36a8603bfd827ca8371b077c92c97023a2de899f7f49ecee93ceead2aab6079e597fd32150c982ee892ae4edf13f618452ad93eadbaad8728f737e7f80c95467c1ab4b99b2ea6e59e94dce7010fb92fa51cc9113f3ce3b37d7fa0bac1e36d31eef99a8722f473221479bfa0abba1a3c02a2a0e4fe94e2c310537e442e04590fb025515837929a92650b7fe103bace036bfacaa1e8f1c498a6095d0bc933bfa14a80101c89bcc8f35ff7e5ffcfe0c5b229a3c50d63cef6e4a93eb571d097f95cf38aff6047cfe4a8b1d7a576b48e64f4717dc31bef857ae95faf7ecb1efb2cc0961d77587a7d56fc077bf7fe4b7813d6e69b2263ad3a3b4d575060e6eb743c794d646cc990212d32b664c89016195b3264488b8c2d1932a4c5db6f1fde7c0763ef106b + + + + + pbnSelectOutputFile + clicked() + OpenModellerGuiBase + pbnSelectOutputFile_clicked() + + + leOutputFileName + textChanged(const QString&) + OpenModellerGuiBase + leOutputFileName_textChanged(const QString&) + + + pbnRemoveParameter + clicked() + OpenModellerGuiBase + pbnRemoveParameter_clicked() + + + pbnAddParameter + clicked() + OpenModellerGuiBase + pbnAddParameter_clicked() + + + pbnRemoveLayerFile + clicked() + OpenModellerGuiBase + pbnRemoveLayerFile_clicked() + + + pbnSelectLayerFile + clicked() + OpenModellerGuiBase + pbnSelectLayerFile_clicked() + + + pbnSelectLocalitiesFile + clicked() + OpenModellerGuiBase + pbnSelectLocalitiesFile_clicked() + + + leLocalitiesFileName + returnPressed() + OpenModellerGuiBase + leLocalitiesFileName_returnPressed() + + + OpenModellerGuiBase + selected(const QString&) + OpenModellerGuiBase + formSelected(const QString&) + + + + openmodellerguibase.ui.h + + + pbRun_clicked() + pbnSelectOutputFile_clicked() + leOutputFileName_textChanged( const QString & ) + pbnRemoveParameter_clicked() + pbnAddParameter_clicked() + pbnRemoveLayerFile_clicked() + pbnSelectLayerFile_clicked() + pbnSelectLocalitiesFile_clicked() + leLocalitiesFileName_returnPressed() + formSelected( const QString & ) + + + init() + + + diff --git a/plugins/openmodeller/openmodellerguibase.ui.h b/plugins/openmodeller/openmodellerguibase.ui.h new file mode 100644 index 00000000000..2c2ec204c32 --- /dev/null +++ b/plugins/openmodeller/openmodellerguibase.ui.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you wish to add, delete or rename functions or slots use +** Qt Designer which will update this file, preserving your code. Create an +** init() function in place of a constructor, and a destroy() function in +** place of a destructor. +*****************************************************************************/ + + +void OpenModellerGuiBase::init() +{ + //hide some controls that have not yet been implemented + cbxDefaultToLastChoices->hide(); + textLabel3->hide(); + progressBar1->hide(); +} + +void OpenModellerGuiBase::pbRun_clicked() +{ + +} + + +void OpenModellerGuiBase::pbnSelectOutputFile_clicked() +{ + +} + + +void OpenModellerGuiBase::leOutputFileName_textChanged( const QString & ) +{ + +} + + +void OpenModellerGuiBase::pbnRemoveParameter_clicked() +{ + +} + + +void OpenModellerGuiBase::pbnAddParameter_clicked() +{ + +} + + +void OpenModellerGuiBase::pbnRemoveLayerFile_clicked() +{ + +} + + +void OpenModellerGuiBase::pbnSelectLayerFile_clicked() +{ + +} + + +void OpenModellerGuiBase::pbnSelectLocalitiesFile_clicked() +{ + +} + + +void OpenModellerGuiBase::leLocalitiesFileName_returnPressed() +{ + +} + + +void OpenModellerGuiBase::formSelected(const QString & ) +{ + +} diff --git a/plugins/openmodeller/plugin.cpp b/plugins/openmodeller/plugin.cpp new file mode 100644 index 00000000000..1f7d4376d7c --- /dev/null +++ b/plugins/openmodeller/plugin.cpp @@ -0,0 +1,180 @@ +/*************************************************************************** + plugin.cpp + Import tool for various worldmap analysis output files +Functions: + +------------------- +begin : Jan 21, 2004 +copyright : (C) 2004 by Tim Sutton +email : tim@linfiniti.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +/* $Id$ */ + +// includes + +#include "../../src/qgisapp.h" +#include "../../src/qgsmaplayer.h" +#include "../../src/qgsrasterlayer.h" +#include "plugin.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + +//non qt includes +#include +#include + +// xpm for creating the toolbar icon +#include "icon_om.xpm" +// +static const char *pluginVersion = "0.1"; +/** + * Constructor for the plugin. The plugin is passed a pointer to the main app + * and an interface object that provides access to exposed functions in QGIS. + * @param qgis Pointer to the QGIS main window + * @param _qI Pointer to the QGIS interface object + */ +Plugin::Plugin(QgisApp * theQGisApp, QgisIface * theQgisInterFace): + qgisMainWindowPointer(theQGisApp), qGisInterface(theQgisInterFace) +{ + /** Initialize the plugin and set the required attributes */ + pluginNameQString = "openModeller Wizard"; + pluginVersionQString = "Version 0.1"; + pluginDescriptionQString = "Plugin to run openModeller in QGIS."; + +} + +Plugin::~Plugin() +{ + +} + +/* Following functions return name, description, version, and type for the plugin */ +QString Plugin::name() +{ + return pluginNameQString; +} + +QString Plugin::version() +{ + return pluginVersionQString; + +} + +QString Plugin::description() +{ + return pluginDescriptionQString; + +} + +int Plugin::type() +{ + return QgisPlugin::UI; +} + +/* + * Initialize the GUI interface for the plugin + */ +void Plugin::initGui() +{ + // add a menu with 2 items + QPopupMenu *pluginMenu = new QPopupMenu(qgisMainWindowPointer); + + pluginMenu->insertItem(QIconSet(icon_om),"&WorldMap Results Importer", this, SLOT(run())); + + menuBarPointer = ((QMainWindow *) qgisMainWindowPointer)->menuBar(); + + menuIdInt = qGisInterface->addMenu("&Biodiversity", pluginMenu); + // Create the action for tool + QAction *myQActionPointer = new QAction("WorldMap Importer", QIconSet(icon_om), "&Wmi",0, this, "run"); + // Connect the action to the run + connect(myQActionPointer, SIGNAL(activated()), this, SLOT(run())); + // Add the toolbar + toolBarPointer = new QToolBar((QMainWindow *) qgisMainWindowPointer, "Biodiversity"); + toolBarPointer->setLabel("WorldMap Importer"); + // Add the zoom previous tool to the toolbar + myQActionPointer->addTo(toolBarPointer); + + +} + +// Slot called when the buffer menu item is activated +void Plugin::run() +{ + OpenModellerGui *myOpenModellerGui=new OpenModellerGui(qgisMainWindowPointer,"openModeller Wizard",true,0); + //listen for when the layer has been made so we can draw it + connect(myOpenModellerGui, SIGNAL(drawRasterLayer(QString)), this, SLOT(drawRasterLayer(QString))); + myOpenModellerGui->show(); +} +//!draw a raster layer in the qui - intended to respond to signal sent by diolog when it as finished creating +//layer +void Plugin::drawRasterLayer(QString theQString) +{ + std::cout << "DrawLayer slot called with " << theQString << std::endl; + qGisInterface->addRasterLayer(theQString); +} +// Unload the plugin by cleaning up the GUI +void Plugin::unload() +{ + // remove the GUI + menuBarPointer->removeItem(menuIdInt); + delete toolBarPointer; +} +/** + * Required extern functions needed for every plugin + * These functions can be called prior to creating an instance + * of the plugin class + */ +// Class factory to return a new instance of the plugin class +extern "C" QgisPlugin * classFactory(QgisApp * theQGisAppPointer, QgisIface * theQgisInterfacePointer) +{ + return new Plugin(theQGisAppPointer, theQgisInterfacePointer); +} + +// Return the name of the plugin - note that we do not user class members as +// the class may not yet be insantiated when this method is called. +extern "C" QString name() +{ + return QString("openModeller Wizard"); +} + +// Return the description +extern "C" QString description() +{ + return QString("This is a plugin to run openModeller in QGIS"); +} + +// Return the type (either UI or MapLayer plugin) +extern "C" int type() +{ + return QgisPlugin::UI; +} + +// Return the version number for the plugin +extern "C" QString version() +{ + return pluginVersion; +} + +// Delete ourself +extern "C" void unload(QgisPlugin * thePluginPointer) +{ + delete thePluginPointer; +} diff --git a/plugins/openmodeller/plugin.h b/plugins/openmodeller/plugin.h new file mode 100644 index 00000000000..4fc7358b410 --- /dev/null +++ b/plugins/openmodeller/plugin.h @@ -0,0 +1,96 @@ +/*************************************************************************** + qgsworldmapimporter.h + Functions: + Buffer + ------------------- + begin : Jan 21, 2004 + copyright : (C) 2004 by Tim Sutton + email : tim@linfiniti.com + + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + /* $Id$ */ +#ifndef PLUGIN +#define PLUGIN +#include "../qgisplugin.h" +#include + +#include "../../src/qgisapp.h" + +/** +* \class Plugin +* \brief OpenModeller plugin for QGIS +* +*/ +class Plugin:public QObject, public QgisPlugin +{ + Q_OBJECT public: + /** + * Constructor for a plugin. The QgisApp and QgisIface pointers are passed by + * QGIS when it attempts to instantiate the plugin. + * @param qgis Pointer to the QgisApp object + * @param qI Pointer to the QgisIface object. + */ + Plugin(QgisApp * , QgisIface * ); + /** + * Virtual function to return the name of the plugin. The name will be used when presenting a list + * of installable plugins to the user + */ + virtual QString name(); + /** + * Virtual function to return the version of the plugin. + */ + virtual QString version(); + /** + * Virtual function to return a description of the plugins functions + */ + virtual QString description(); + /** + * Return the plugin type + */ + virtual int type(); + //! init the gui + virtual void initGui(); + //! Destructor + virtual ~ Plugin(); + public slots: + //! Show the dialog box + void run(); + //!draw a raster layer in the qui + void drawRasterLayer(QString); + //! unload the plugin + void unload(); + //! show the help document + void help(); + private: + + + //! Name of the plugin + QString pluginNameQString; + //! Version + QString pluginVersionQString; + //! Descrption of the plugin + QString pluginDescriptionQString; + //! Plugin type as defined in QgisPlugin::PLUGINTYPE + int pluginType; + //! Id of the plugin's menu. Used for unloading + int menuIdInt; + //! Pointer to our toolbar + QToolBar *toolBarPointer; + //! Pointer to our menu + QMenuBar *menuBarPointer; + //! Pionter to QGIS main application object + QgisApp *qgisMainWindowPointer; + //! Pointer to the QGIS interface object + QgisIface *qGisInterface; +}; + +#endif diff --git a/plugins/openmodeller/portuguese.qm b/plugins/openmodeller/portuguese.qm new file mode 100644 index 00000000000..6bd22c41dfd Binary files /dev/null and b/plugins/openmodeller/portuguese.qm differ