diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..968267997 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +* +!bin/ +!mapserver/ +!qgisserver/ +!tilegeneration/ +!print/print-apps/ +!geoportal/vars*.yaml +!geoportal/CONST_vars.yaml +!geoportal/CONST_config-schema.yaml +!geoportal/geoportailv3_geoportal/static +!geoportal/geoportailv3_geoportal/locale diff --git a/.editorconfig b/.editorconfig index 5b1d828a0..6da856443 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,5 +11,11 @@ trim_trailing_whitespace = true [*.js] indent_size = 2 +[*.yaml] +indent_size = 2 + +[*.yml] +indent_size = 2 + [Makefile] indent_style = tab diff --git a/.gitignore b/.gitignore index 4891a6adf..cffde1f2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,25 +1,17 @@ -*~ *.pyc *.pyo __pycache__/ /.env -/geoportal/.venv/ -/geoportal/dist/ -/geoportal/build/ -/geoportal/geoportailv3_geoportal/static-ngeo/build/ -/geoportal/geoportailv3_geoportal.egg-info/ -/geoportal/geoportailv3_geoportal/locale/*/LC_MESSAGES/*.mo -/geoportal/c2cgeoportal/ -/geoportal/node_modules/ +/docker-compose.override.yaml +/upgrade +/.upgrade.yaml +/.UPGRADE* /geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-client.pot /geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-server.pot /geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-tooltips.pot /geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-legends.pot /geoportal/geoportailv3_geoportal/locale/ngeo.pot -/.build/ -/node_modules/ -/geoportailv3/ -/apache/ -/print/WEB-INF/ -/geoportailv3.egg-info/ -/geoportal/jsapi/node_modules/ + +# Generated with dev mode +/geoportal/geoportailv3_geoportal/static/apihelp/index.html +lidar/data diff --git a/.prospector.yaml b/.prospector.yaml new file mode 100644 index 000000000..5d708c6ba --- /dev/null +++ b/.prospector.yaml @@ -0,0 +1,22 @@ +--- +strictness: veryhigh + +pep8: + options: + max-line-length: 110 + disable: + - E203 + +pylint: + options: + max-line-length: 110 + disable: + - too-many-locals + - too-many-statements + - too-many-branches + +mccabe: + run: false + +mypy: + run: true diff --git a/CONST_CHANGELOG.txt b/CONST_CHANGELOG.txt new file mode 100644 index 000000000..a94b139ce --- /dev/null +++ b/CONST_CHANGELOG.txt @@ -0,0 +1,67 @@ +This file includes migration steps for each release of c2cgeoportal. + + +Version 2.5.0 +============= + +Information +----------- + +1. Basic authentication is disabled by default from this version onward. + To enable basic auth see: + https://camptocamp.github.io/c2cgeoportal/2.5/integrator/security.html#basic-auth + +2. We change the secret name from `GITHUB_GOPASS_CI_TOKEN` to `GOPASS_CI_GITHUB_TOKEN` because we can't + anymore create create secret started with `GITHUB_`. + +3. Layers which have any errors are not added to the theme anymore. + +4. If a WMS version is given in an OGC server URL, it will be used for the GetCapabilities request + Supported versions: 1.1.1 and 1.3.0 + +Changes to apply +---------------- + +1. Now we need to have PyYAML python package installed in the home, + see the documentation for more information: + https://camptocamp.github.io/c2cgeoportal/2.5/integrator/requirements.html + +2. The configuration vars `vars/functionalities/anonymous` and `vars/functionalities/registered` should + be moved to the new roles `anonymous` and `registered` that will be created once the database has been upgraded. + +3. The 'INSTANCE' configuration variable is removed, it should be in the '.env' files, and also the + environment makefiles, these contents should also be moved to the '.env' files. In a multi-organisation + project you can have a chain of multiple '.env' files see the build configuration documentation. + +4. A new PostgreSQL extension is required, install it by running in psql: + `CREATE EXTENSION IF NOT EXISTS hstore;` + +5. The static files will be moved, therefore you should replace: + `request.static_url('geoportailv3_geoportal:static/` by: + `request.static_url('/etc/geomapfish/static/`. + +6. Optional, change your mapfiles according the documentation: + https://camptocamp.github.io/c2cgeoportal/2.5/administrator/mapfile.html + + +Version 2.4.2 +============= + +Information +----------- + +1. The SVG inclusion through Webpack has changed, See ngeo SVG example for more information: + https://camptocamp.github.io/ngeo/master/examples/svg.html + +2. The WMTS capabilities is now generated on runtime. + +3. If not already done the 'edit' and 'routing' interfaces and their relations will be removed from the + database, If you don't want that, you should rename the interfaces before applying the alembic scripts. + +4. If not already done the 'api' and 'iframe_api' will be created. After the database upgrade you can run + the following request to fill e.-g. the api's interfaces with the desktop interface: + + INSERT INTO main.interface_layer (interface_id, layer_id) + SELECT , layer_id FROM main.interface_layer WHERE interface_id = ; + INSERT INTO main.interface_theme (interface_id, theme_id) + SELECT , theme_id FROM main.interface_theme WHERE interface_id = ; diff --git a/CONST_create_template/.dockerignore b/CONST_create_template/.dockerignore new file mode 100644 index 000000000..968267997 --- /dev/null +++ b/CONST_create_template/.dockerignore @@ -0,0 +1,11 @@ +* +!bin/ +!mapserver/ +!qgisserver/ +!tilegeneration/ +!print/print-apps/ +!geoportal/vars*.yaml +!geoportal/CONST_vars.yaml +!geoportal/CONST_config-schema.yaml +!geoportal/geoportailv3_geoportal/static +!geoportal/geoportailv3_geoportal/locale diff --git a/CONST_create_template/.editorconfig b/CONST_create_template/.editorconfig new file mode 100644 index 000000000..6da856443 --- /dev/null +++ b/CONST_create_template/.editorconfig @@ -0,0 +1,21 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.js] +indent_size = 2 + +[*.yaml] +indent_size = 2 + +[*.yml] +indent_size = 2 + +[Makefile] +indent_style = tab diff --git a/CONST_create_template/.github/workflows/ci.yaml b/CONST_create_template/.github/workflows/ci.yaml new file mode 100644 index 000000000..694fd7a0a --- /dev/null +++ b/CONST_create_template/.github/workflows/ci.yaml @@ -0,0 +1,56 @@ +--- +name: Continuous integration + +on: + push: + +env: + PROJECT: geoportailv3 + # Requires CI_GPG_PRIVATE_KEY and GOPASS_CI_GITHUB_TOKEN secrets. + # OPENSHIFT_PROJECT: gs-gmf-geoportailv3 + # HELM_RELEASE_NAMES: # List of branch that should be deployed on helm + PATH: /bin:/usr/bin:/usr/local/bin:/home/runner/.local/bin + SUMMON_PROVIDER: /usr/local/bin/gopass + +jobs: + config: + runs-on: ubuntu-18.04 + name: Config + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v1 + + - name: Build config + run: ./build --config + + - uses: camptocamp/initialise-gopass-summon-action@v1 + with: + ci-gpg-private-key: ${{secrets.CI_GPG_PRIVATE_KEY}} + github-gopass-ci-token: ${{secrets.GOPASS_CI_GITHUB_TOKEN}} + if: "env.HELM_RELEASE_NAMES != ''" + - run: scripts/publish-docker --image=config --no-trigger + if: "env.HELM_RELEASE_NAMES != ''" + - run: scripts/publish-docker --image=config --service=github + if: "env.HELM_RELEASE_NAMES != ''" + + geoportal: + runs-on: ubuntu-18.04 + name: Geoportal + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v1 + + - name: Build geoportal + run: ./build --geoportal + + - uses: camptocamp/initialise-gopass-summon-action@v1 + with: + ci-gpg-private-key: ${{secrets.CI_GPG_PRIVATE_KEY}} + github-gopass-ci-token: ${{secrets.GOPASS_CI_GITHUB_TOKEN}} + if: "env.HELM_RELEASE_NAMES != ''" + - run: scripts/publish-docker --image=geoportal --no-trigger + if: "env.HELM_RELEASE_NAMES != ''" + - run: scripts/publish-docker --image=geoportal --service=github + if: "env.HELM_RELEASE_NAMES != ''" diff --git a/CONST_create_template/.gitignore b/CONST_create_template/.gitignore new file mode 100644 index 000000000..d3bb74deb --- /dev/null +++ b/CONST_create_template/.gitignore @@ -0,0 +1,13 @@ +*.pyc +*.pyo +__pycache__/ +/.env +/docker-compose.override.yaml +/upgrade +/.upgrade.yaml +/.UPGRADE* +/geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-client.pot +/env.personal + +# Generated with dev mode +/geoportal/geoportailv3_geoportal/static/apihelp/index.html diff --git a/CONST_create_template/.prospector.yaml b/CONST_create_template/.prospector.yaml new file mode 100644 index 000000000..5d708c6ba --- /dev/null +++ b/CONST_create_template/.prospector.yaml @@ -0,0 +1,22 @@ +--- +strictness: veryhigh + +pep8: + options: + max-line-length: 110 + disable: + - E203 + +pylint: + options: + max-line-length: 110 + disable: + - too-many-locals + - too-many-statements + - too-many-branches + +mccabe: + run: false + +mypy: + run: true diff --git a/CONST_create_template/Dockerfile b/CONST_create_template/Dockerfile new file mode 100644 index 000000000..7a7665b99 --- /dev/null +++ b/CONST_create_template/Dockerfile @@ -0,0 +1,66 @@ +FROM camptocamp/geomapfish-tools:2.5.0.139 as builder + +ENV LANGUAGES="en fr de" +ENV VARS_FILE=vars.yaml +ENV CONFIG_VARS sqlalchemy.url sqlalchemy.pool_recycle sqlalchemy.pool_size sqlalchemy.max_overflow \ + sqlalchemy.use_batch_mode sqlalchemy_slave.url sqlalchemy_slave.pool_recycle sqlalchemy_slave.pool_size \ + sqlalchemy_slave.max_overflow sqlalchemy_slave.use_batch_mode schema schema_static enable_admin_interface \ + default_locale_name servers layers available_locale_names cache admin_interface getitfixed functionalities \ + raster shortener hide_capabilities tinyowsproxy resourceproxy print_url print_get_redirect \ + checker check_collector default_max_age package srid \ + reset_password fulltextsearch global_headers headers authorized_referers hooks stats db_chooser \ + dbsessions urllogin host_forward_host smtp c2c.base_path welcome_email \ + lingua_extractor interfaces_config interfaces devserver_url api authentication intranet metrics pdfreport + +COPY . /tmp/config/ + +RUN \ + for lang in ${LANGUAGES}; \ + do \ + node /usr/bin/compile-catalog \ + /opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal/locale/${lang}/LC_MESSAGES/ngeo.po \ + /opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal/locale/${lang}/LC_MESSAGES/gmf.po \ + /tmp/config/geoportal/geoportailv3_geoportal/locale/${lang}/LC_MESSAGES/geoportailv3_geoportal-client.po \ + > /tmp/config/geoportal/geoportailv3_geoportal/static/${lang}.json; \ + done && \ + rm -rf /tmp/config/geoportal/geoportailv3_geoportal/locale + +RUN \ + cd /tmp/config/geoportal/ && \ + c2c-template --vars ${VARS_FILE} \ + --get-config geoportailv3_geoportal/config.yaml \ + ${CONFIG_VARS} && \ + pykwalify --data-file geoportailv3_geoportal/config.yaml \ + --schema-file CONST_config-schema.yaml && \ + rm CONST_* vars.yaml + +############################################################################### + +FROM camptocamp/geomapfish-config:2.5.0.139 + +ARG PGSCHEMA +ENV PGSCHEMA=$PGSCHEMA + +COPY --from=builder /tmp/config/ /tmp/config/ + +RUN \ + if [ -e /tmp/config/mapserver ]; then mv /tmp/config/mapserver /etc/; fi && \ + if [ -e /tmp/config/tilegeneration ]; then mv /tmp/config/tilegeneration /etc/; fi && \ + if [ -e /tmp/config/qgisserver ]; then mv /tmp/config/qgisserver /etc/qgisserver; fi && \ + mkdir --parent /usr/local/tomcat/webapps/ROOT/ && \ + if [ -e /tmp/config/print ]; then mv /tmp/config/print/print-apps /usr/local/tomcat/webapps/ROOT/; fi && \ + mv /tmp/config/geoportal/geoportailv3_geoportal/ /etc/geomapfish/ && \ + chmod g+w -R /etc /usr/local/tomcat/webapps && \ + adduser www-data root && \ + sed 's#bind :80#bind *:443 ssl crt /etc/haproxy_dev/localhost.pem#g' /etc/haproxy/haproxy.cfg.tmpl \ + > /etc/haproxy_dev/haproxy.cfg.tmpl && \ + echo ' http-request set-header X-Forwarded-Proto https' >> /etc/haproxy_dev/haproxy.cfg.tmpl + +VOLUME /etc/geomapfish \ + /etc/mapserver \ + /etc/qgisserver \ + /etc/tilegeneration \ + /usr/local/tomcat/webapps/ROOT/print-apps \ + /etc/gunicorn \ + /etc/haproxy_dev \ + /etc/haproxy diff --git a/CONST_create_template/README.rst b/CONST_create_template/README.rst new file mode 100644 index 000000000..b676a9f41 --- /dev/null +++ b/CONST_create_template/README.rst @@ -0,0 +1,29 @@ +geoportailv3 project +=================== + +Read the `Documentation `_ + +Checkout +-------- + +.. code:: + + git clone git@github.com:camptocamp/geoportailv3.git + + cd geoportailv3 + +Build +----- + +.. code:: + + ./build + +Run +--- + +.. code:: + + docker-compose up -d + +.. Feel free to add project-specific things. diff --git a/CONST_create_template/build b/CONST_create_template/build new file mode 100755 index 000000000..5cff2f0ca --- /dev/null +++ b/CONST_create_template/build @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 + +import argparse +import os +import os.path +import platform +import re +import stat +import subprocess +import sys +import urllib.request + +import yaml + + +def call(verbose, arguments, **kwargs): + if verbose: + print_args = [a.replace(" ", "\\ ") for a in arguments] + print_args = [a.replace('"', '\\"') for a in print_args] + print_args = [a.replace("'", "\\'") for a in print_args] + print(" ".join(print_args)) + subprocess.check_call(arguments, **kwargs) + + +def load_env(env_files): + """ + Parse env files and return environment as dict + """ + env = {} + if os.path.exists('env.personal'): + env_files.append('env.personal') + for env_file in env_files: + with open(env_file) as f: + for line in f: + if line and line[0] != "#": + try: + index = line.index("=") + env[line[:index].strip()] = line[index + 1 :].strip() + except ValueError: + # Ignore lines that don't have a '=' + pass + return env + + +def main(): + parser = argparse.ArgumentParser(description="Build the project") + parser.add_argument("--verbose", help="Display the docker build commands") + parser.add_argument("--config", action="store_true", help="Build only the configuration image") + parser.add_argument("--geoportal", action="store_true", help="Build only the geoportal image") + parser.add_argument("--upgrade", help="Start upgrading the project to version") + parser.add_argument("env", nargs="*", help="The environment config") + args = parser.parse_args() + + if args.upgrade: + major_version = args.upgrade + match = re.match(r"^([0-9]+\.[0-9]+)\.[0-9]+$", args.upgrade) + if match is not None: + major_version = match.group(1) + match = re.match(r"^([0-9]+\.[0-9]+)\.[0-9a-z]+\.[0-9]+$", args.upgrade) + if match is not None: + major_version = match.group(1) + full_version = args.upgrade if args.upgrade != "master" else "latest" + with open("upgrade", "w") as f: + result = urllib.request.urlopen( + "https://raw.githubusercontent.com/camptocamp/c2cgeoportal/{}/scripts/upgrade".format( + major_version + ) + ) + if result.code != 200: + print("ERROR:") + print(result.read()) + sys.exit(1) + f.write(result.read().decode()) + os.chmod("upgrade", os.stat("upgrade").st_mode | stat.S_IXUSR) + try: + if platform.system() == "Windows": + subprocess.check_call(["python", "upgrade", full_version]) + else: + subprocess.check_call(["./upgrade", full_version]) + except subprocess.CalledProcessError: + sys.exit(1) + sys.exit(0) + + with open("project.yaml") as project_file: + project_env = yaml.load(project_file, Loader=yaml.SafeLoader)["env"] + if len(args.env) != project_env["required_args"]: + print(project_env["help"]) + sys.exit(1) + env_files = [e.format(*args.env) for e in project_env["files"]] + print("Use env files: {}".format(", ".join(env_files))) + for env_file in env_files: + if not os.path.exists(env_file): + print("Error: the env file '{}' does not exist.".format(env_file)) + sys.exit(1) + env = load_env(env_files) + + base = env["DOCKER_BASE"] if "DOCKER_BASE" in env else "camptocamp/geoportailv3" + tag = ":" + env["DOCKER_TAG"] if "DOCKER_TAG" in env else "" + schema = env["PGSCHEMA"] + + default = not (args.config or args.geoportal) + + docker_build = ["docker", "build"] + if os.environ.get("CI", "FALSE").upper() != "TRUE": + docker_build.append("--pull") + + if default or args.config: + call( + args.verbose, + docker_build + + [ + "--tag={}-config{}".format(base, tag), + "--build-arg=PGSCHEMA=" + schema, + ".", + ], + ) + if default or args.geoportal: + git_hash = subprocess.check_output(["git", "rev-parse", "HEAD"]).strip().decode() + call( + args.verbose, + docker_build + + [ + "--tag={}-geoportal{}".format(base, tag), + "--build-arg=PGSCHEMA=" + schema, + "--build-arg=GIT_HASH=" + git_hash, + "geoportal", + ], + ) + call( + args.verbose, + docker_build + + [ + "--target=builder", + "--tag={}-geoportal-dev{}".format(base, tag), + "geoportal", + ], + ) + + with open(".env", "w") as dest: + for file_ in env_files: + with open(file_) as src: + dest.write(src.read() + "\n") + dest.write("# Used env files: {}\n".format(" ".join(env_files))) + + +if __name__ == "__main__": + main() diff --git a/CONST_create_template/docker-compose-lib.yaml b/CONST_create_template/docker-compose-lib.yaml new file mode 100644 index 000000000..7d11f7302 --- /dev/null +++ b/CONST_create_template/docker-compose-lib.yaml @@ -0,0 +1,302 @@ +--- + +version: '2.0' + +services: + config: + image: ${DOCKER_BASE}-config:${DOCKER_TAG} + user: www-data + environment: + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - VISIBLE_ENTRY_POINT + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - GEOPORTAL_INTERNAL_URL + - GEOPORTAL_INTERNAL_HOST + - GEOPORTAL_INTERNAL_PORT + - TILECLOUDCHAIN_INTERNAL_URL + - TILECLOUDCHAIN_INTERNAL_HOST + - TILECLOUDCHAIN_INTERNAL_PORT + - MAPSERVER_URL + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - TILEGENERATION_SQS_QUEUE + - TILEGENERATION_S3_BUCKET + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + + print: + image: camptocamp/mapfish_print:3.22 + user: www-data + restart: unless-stopped + environment: + - CATALINA_OPTS + - PGOPTIONS + + mapserver: + image: camptocamp/mapserver:7.4 + user: www-data + restart: unless-stopped + entrypoint: [] + environment: + - PGOPTIONS + + qgisserver: + image: camptocamp/geomapfish-qgisserver:gmf2.5-qgis${QGIS_VERSION} + user: www-data + restart: unless-stopped + environment: + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - CPL_VSIL_CURL_USE_CACHE + - CPL_VSIL_CURL_CACHE_SIZE + - CPL_VSIL_CURL_USE_HEAD + - GDAL_DISABLE_READDIR_ON_OPEN + - QGIS_SERVER_LOG_LEVEL=2 + - LOG_LEVEL=INFO + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - OTHER_LOG_LEVEL + + tinyows: + image: camptocamp/tinyows:master + user: www-data + restart: unless-stopped + + redis: + image: redis:5 + user: www-data + restart: unless-stopped + command: + - redis-server + - --save + - '' + - --appendonly + - 'no' + - --maxmemory + - 512mb + - --maxmemory-policy + - volatile-lru + - --tcp-keepalive + - '30' + + tilecloudchain: + image: camptocamp/tilecloud-chain:1.13 + user: www-data + restart: unless-stopped + environment: + - GUNICORN_PARAMS + - VISIBLE_ENTRY_POINT + - C2C_REDIS_URL + - TILEGENERATION_CONFIGFILE=/etc/tilegeneration/config.yaml + - C2C_BASE_PATH=/tiles/c2c + - C2C_BROADCAST_PREFIX=broadcast_tilecloudchain_ + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_SECRET + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + + tilegeneration_slave: + image: camptocamp/tilecloud-chain:1.13 + user: www-data + restart: unless-stopped + entrypoint: + - generate_tiles + - --role=slave + - --daemon + environment: + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + + geoportal: + image: ${DOCKER_BASE}-geoportal:${DOCKER_TAG} + user: www-data + restart: unless-stopped + environment: + - VISIBLE_ENTRY_POINT + - PACKAGE=geoportailv3 + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - GUNICORN_PARAMS + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - AUTHTKT_TIMEOUT + - AUTHTKT_REISSUE_TIME + - AUTHTKT_MAXAGE + - AUTHTKT_SECRET + - AUTHTKT_COOKIENAME + - AUTHTKT_HTTP_ONLY + - AUTHTKT_SECURE + - AUTHTKT_SAMESITE + - BASICAUTH + - TINYOWS_URL + - MAPSERVER_URL + - QGISSERVER_URL + - PRINT_URL + - DEVSERVER_HOST + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SECRET + - LOG_LEVEL + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - GUNICORN_LOG_LEVEL + - OTHER_LOG_LEVEL + - DOGPILECACHE_LOG_LEVEL + - LOG_TYPE + + tools: + image: camptocamp/geomapfish-tools:2.5.0.139 + restart: unless-stopped + environment: + - PGSCHEMA + # From geoportal + - VISIBLE_ENTRY_POINT + - PACKAGE=geoportailv3 + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - GUNICORN_PARAMS + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - AUTHTKT_TIMEOUT + - AUTHTKT_REISSUE_TIME + - AUTHTKT_MAXAGE + - AUTHTKT_SECRET + - AUTHTKT_COOKIENAME + - AUTHTKT_HTTP_ONLY + - AUTHTKT_SECURE + - AUTHTKT_SAMESITE + - BASICAUTH + - TINYOWS_URL + - MAPSERVER_URL + - QGISSERVER_URL + - PRINT_URL + - DEVSERVER_HOST + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SECRET + - LOG_LEVEL + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - GUNICORN_LOG_LEVEL + - OTHER_LOG_LEVEL + - DOGPILECACHE_LOG_LEVEL + - LOG_TYPE + + alembic: + image: ${DOCKER_BASE}-geoportal:${DOCKER_TAG} + user: www-data + entrypoint: [] + command: + - alembic + - --name=static + - upgrade + - head + environment: + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - LOG_TYPE + + front: + image: haproxy:1.9 + restart: unless-stopped + volumes: + - /dev/log:/dev/log:rw + command: + - haproxy + - -f + - /etc/${FRONT_CONFIG} + ports: + - ${DOCKER_PORT}:${FRONT_INNER_PORT} + + webpack_dev_server: + image: ${DOCKER_BASE}-geoportal-dev:${DOCKER_TAG} + volumes: + - ./geoportal/geoportailv3_geoportal/static-ngeo:/app/geoportailv3_geoportal/static-ngeo + environment: + - VISIBLE_ENTRY_POINT + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT diff --git a/CONST_create_template/docker-compose.override.sample.yaml b/CONST_create_template/docker-compose.override.sample.yaml new file mode 100644 index 000000000..17045bb85 --- /dev/null +++ b/CONST_create_template/docker-compose.override.sample.yaml @@ -0,0 +1,54 @@ +--- +# This file can be renamed as `docker-compose.override.yaml` and uncomment the desired lines for +# development. The file `docker-compose.override.yaml` is ignored by Git by default. + +# yamllint disable rule:line-length + +version: '2.0' + +services: + geoportal: + user: root + volumes: + # For Python project development. + - ./geoportal/geoportailv3_geoportal:/app/geoportailv3_geoportal + # For Python c2cgeportal development. + # - ./../c2cgeoportal/commons/c2cgeoportal_commons:/opt/c2cgeoportal/commons/c2cgeoportal_commons + # - ./../c2cgeoportal/geoportal/c2cgeoportal_geoportal:/opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal + # - ./../c2cgeoportal/admin/c2cgeoportal_admin:/opt/c2cgeoportal/admin/c2cgeoportal_admin + environment: + - GUNICORN_CMD_ARGS=--reload + - C2CWSGIUTILS_CONFIG=/app/development.ini + # - PRINT_URL=http://print:8080/print/ + ports: + - 5678:5678 # For remote debugging using Visual Studio Code + + # Also uncomment the PRINT_URL in geoportal + # print: + # extends: + # file: docker-compose-lib.yaml + # service: print + # volumes_from: + # - config:ro + + qgisserver: + # volumes: + # - './../c2cgeoportal/docker/qgisserver/geomapfish_qgisserver/:/var/www/plugins/geomapfish_qgisserver/' + # - './../c2cgeoportal/commons/c2cgeoportal_commons:/opt/c2cgeoportal/commons/c2cgeoportal_commons/' + environment: + - QGIS_SERVER_LOG_LEVEL=0 + + # For Javascript project development. + # The debug application will be availavble at ``https:////dev/.html``. + webpack_dev_server: + # Uncomment these lines when you want to debug respectively the project js, ngeo js and/or the gmf contrib js. + # Adapt the path for ngeo / gmf contrib to point where you have checkouted the code. + # volumes: + # - ./geoportal/geoportailv3_geoportal/static-ngeo:/app/geoportailv3_geoportal/static-ngeo + # - ./../ngeo/src:/usr/lib/node_modules/ngeo/src + # - ./../ngeo/contribs:/usr/lib/node_modules/ngeo/contribs + volumes_from: + - config:rw + extends: + file: docker-compose-lib.yaml + service: webpack_dev_server diff --git a/CONST_create_template/docker-compose.yaml b/CONST_create_template/docker-compose.yaml new file mode 100644 index 000000000..e8176caa4 --- /dev/null +++ b/CONST_create_template/docker-compose.yaml @@ -0,0 +1,98 @@ +--- + +# The project Docker compose file for development. + +version: '2.0' + +services: + config: + extends: + file: docker-compose-lib.yaml + service: config + + ## print: + ## extends: + ## file: docker-compose-lib.yaml + ## service: print + ## volumes_from: + ## - config:ro + + mapserver: + extends: + file: docker-compose-lib.yaml + service: mapserver + volumes_from: + - config:ro + volumes: + - /var/sig:/var/sig:ro + + ## qgisserver: + ## extends: + ## file: docker-compose-lib.yaml + ## service: qgisserver + ## volumes_from: + ## - config:ro + ## environment: + ## # Single QGIS project files + ## - QGIS_PROJECT_FILE=/etc/qgisserver/project.qgz + ## - GEOMAPFISH_OGCSERVER= + ## # Multiple QGIS project files + ## - QGIS_PROJECT_FILE= + ## - GEOMAPFISH_ACCESSCONTROL_CONFIG=/etc/qgisserver/accesscontrol_config.yaml + + tinyows: + extends: + file: docker-compose-lib.yaml + service: tinyows + volumes_from: + - config:ro + + redis: + extends: + file: docker-compose-lib.yaml + service: redis + + tilecloudchain: + extends: + file: docker-compose-lib.yaml + service: tilecloudchain + volumes_from: + - config:ro + + tilegeneration_slave: + extends: + file: docker-compose-lib.yaml + service: tilegeneration_slave + volumes_from: + - config:ro + + geoportal: + extends: + file: docker-compose-lib.yaml + service: geoportal + volumes_from: + - config:ro + volumes: + - /var/sig:/var/sig:ro + + alembic: + extends: + file: docker-compose-lib.yaml + service: alembic + + front: + extends: + file: docker-compose-lib.yaml + service: front + volumes_from: + - config:ro + + # Rich image for project development with e.-g. vim, tree, awscli, psql, ... + tools: + volumes_from: + - config:rw + volumes: + - .:/src + extends: + file: docker-compose-lib.yaml + service: tools diff --git a/CONST_create_template/env.default b/CONST_create_template/env.default new file mode 100644 index 000000000..9af37dbee --- /dev/null +++ b/CONST_create_template/env.default @@ -0,0 +1,49 @@ +# Default values for c2cgeoportal +COMPOSE_PROJECT_NAME=geoportailv3 +DOCKER_PORT=8484 +DOCKER_BASE=camptocamp/geoportailv3 +DOCKER_TAG=latest +VISIBLE_WEB_HOST=localhost:8484 +VISIBLE_WEB_PROTOCOL=https +VISIBLE_ENTRY_POINT=/ +AUTHTKT_TIMEOUT=86400 +AUTHTKT_REISSUE_TIME=9000 +AUTHTKT_MAXAGE=86400 +AUTHTKT_SECRET=aed4ma7pah7Riph9paMoow3raeB5ooSa2ayee4fooQuohT7Etinohshah7eib4Re +AUTHTKT_COOKIENAME=auth_tkt_geoportailv3 +AUTHTKT_HTTP_ONLY=True +AUTHTKT_SECURE=True +AUTHTKT_SAMESITE=Lax +BASICAUTH=False +GEOPORTAL_INTERNAL_URL=http://geoportal:8080 +# For internal print +GEOPORTAL_INTERNAL_HOST=geoportal +GEOPORTAL_INTERNAL_PORT=8080 +TILECLOUDCHAIN_INTERNAL_URL=http://tilecloudchain:8080 +# For internal print +TILECLOUDCHAIN_INTERNAL_HOST=tilecloudchain +TILECLOUDCHAIN_INTERNAL_PORT=8080 +MAPSERVER_URL=http://mapserver:8080/ +TINYOWS_URL=http://tinyows:8080/ +QGISSERVER_URL=http://qgisserver:8080/ +QGIS_VERSION=3.10 +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_DB=0 +GUNICORN_PARAMS=--bind=:8080 --worker-class=gthread --threads=10 --workers=5 --timeout=60 --max-requests=1000 --max-requests-jitter=100 --config=/etc/gunicorn/config.py --worker-tmp-dir=/dev/shm +DEVSERVER_HOST=webpack_dev_server:8080 +C2C_REDIS_URL=redis://redis:6379/0 +PGOPTIONS=-c statement_timeout=30000 +CATALINA_OPTS=-Xmx1024m +C2C_BROADCAST_PREFIX=broadcast_geoportal_ +LOG_LEVEL=INFO +C2CGEOPORTAL_LOG_LEVEL=INFO +SQL_LOG_LEVEL=WARN +GUNICORN_LOG_LEVEL=WARN +OTHER_LOG_LEVEL=WARN +DOGPILECACHE_LOG_LEVEL=WARN +LOG_TYPE=console +CPL_VSIL_CURL_USE_CACHE=TRUE +CPL_VSIL_CURL_CACHE_SIZE=128000000 +CPL_VSIL_CURL_USE_HEAD=FALSE +GDAL_DISABLE_READDIR_ON_OPEN=TRUE diff --git a/CONST_create_template/env.project b/CONST_create_template/env.project new file mode 100644 index 000000000..8cec478eb --- /dev/null +++ b/CONST_create_template/env.project @@ -0,0 +1,39 @@ +# Custom project values + +# Database +PGDATABASE=gmf_geoportailv3 +PGSCHEMA=main +PGSCHEMA_STATIC=main_static +# To use the mutualised database. +PGHOST=pg-gs.camptocamp.com +PGHOST_SLAVE=pg-gs.camptocamp.com +PGPORT=30100 +PGPORT_SLAVE=30101 +PGUSER= +PGPASSWORD= +# Should be set to 'prefer' to be able to connect to a local database +PGSSLMODE=require +# To use a database on the host +# PGHOST=172.17.0.1 +# PGHOST_SLAVE=172.17.0.1 +# PGPORT=5432 +# PGUSER=www-data +# PGPASSWORD=www-data +# PGSSLMODE=prefer + +# Use the mutualised print, ask Camptocamp to configure your project. +PRINT_URL=https://mutualized-print.apps.openshift-ch-1.camptocamp.com/print/geoportailv3/ +# To use the internal print: +# PRINT_URL=http://print:8080/print/ + +TILEGENERATION_SQS_QUEUE= +TILEGENERATION_S3_BUCKET= + +# For production +# FRONT_INNER_PORT=80 +# FRONT_CONFIG=haproxy +# For development (front in https) +FRONT_INNER_PORT=443 +FRONT_CONFIG=haproxy_dev + +C2C_SECRET=c2crulez diff --git a/CONST_create_template/geoportal/.dockerignore b/CONST_create_template/geoportal/.dockerignore new file mode 100644 index 000000000..09c6f06dc --- /dev/null +++ b/CONST_create_template/geoportal/.dockerignore @@ -0,0 +1,5 @@ +Dockerfile +vars*.yaml +CONST_vars.yaml +CONST_config-schema.yaml +geoportailv3_geoportal/static diff --git a/CONST_create_template/geoportal/.eslintrc b/CONST_create_template/geoportal/.eslintrc new file mode 100644 index 000000000..8f145b91c --- /dev/null +++ b/CONST_create_template/geoportal/.eslintrc @@ -0,0 +1,19 @@ +extends: + - openlayers +globals: + 'geoportailv3': false +env: + jquery: true +parserOptions: + ecmaVersion: 2017 +rules: + no-console: 0 + comma-dangle: 0 + import/no-unresolved: 0 + valid-jsdoc: 0 + max-len: + - error + - code: 110 + ignoreComments: true + prettier/prettier: 0 + sort-imports-es6-autofix/sort-imports-es6: 0 diff --git a/CONST_create_template/geoportal/Dockerfile b/CONST_create_template/geoportal/Dockerfile new file mode 100644 index 000000000..826dad630 --- /dev/null +++ b/CONST_create_template/geoportal/Dockerfile @@ -0,0 +1,66 @@ +FROM camptocamp/geomapfish-tools:2.5.0.139 as builder +LABEL maintainer Camptocamp "info@camptocamp.com" + +WORKDIR /app +COPY webpack.*.js Makefile CONST_Makefile /app/ +COPY geoportailv3_geoportal/static-ngeo /app/geoportailv3_geoportal/static-ngeo +RUN make apps + +COPY . /app + +RUN make checks +RUN make build +RUN mv webpack.apps.js webpack.apps.js.tmpl + +ENTRYPOINT [ "/usr/bin/eval-templates" ] +CMD [ "webpack-dev-server", "--mode=development", "--debug", "--watch", "--no-inline" ] + +############################################################################### + +FROM camptocamp/geomapfish:2.5 as runner + +COPY requirements.txt /tmp/requirements.txt +RUN \ + python3 -m pip install --disable-pip-version-check --no-cache-dir --requirement=/tmp/requirements.txt && \ + rm --recursive --force /tmp/* /var/tmp/* /root/.cache/* + +WORKDIR /app +COPY . /app +COPY --from=builder /app/geoportailv3_geoportal/locale/ /app/geoportailv3_geoportal/locale/ +COPY --from=builder /usr/lib/node_modules/ngeo/dist/* /etc/static-ngeo/ +COPY --from=builder /etc/static-ngeo/* /etc/static-ngeo/ +COPY --from=builder /app/alembic.ini /app/alembic.yaml ./ +RUN chmod go+w /etc/static-ngeo/ \ + /app/geoportailv3_geoportal/locale/ \ + /app/geoportailv3_geoportal/locale/*/LC_MESSAGES/geoportailv3_geoportal-client.po + +RUN pip install --disable-pip-version-check --no-cache-dir --editable=/app/ && \ + python3 -m compileall -q /usr/local/lib/python3.7 \ + -x '/usr/local/lib/python3.7/dist-packages/(pydevd|ptvsd|pipenv)/' && \ + python3 -m compileall -q /app/geoportailv3_geoportal -x /app/geoportailv3_geoportal/static.* + +ARG GIT_HASH +RUN c2cwsgiutils_genversion.py ${GIT_HASH} + +ARG PGSCHEMA +ENV PGSCHEMA=${PGSCHEMA} + +ENTRYPOINT [ "/usr/bin/eval-templates" ] +CMD ["c2cwsgiutils_run"] + +ENV VISIBLE_ENTRY_POINT=/ \ + AUTHTKT_TIMEOUT=86400 \ + AUTHTKT_REISSUE_TIME=9000 \ + AUTHTKT_MAXAGE=86400 \ + AUTHTKT_COOKIENAME=auth_tkt \ + AUTHTKT_HTTP_ONLY=True \ + AUTHTKT_SECURE=True \ + AUTHTKT_SAMESITE=Lax \ + BASICAUTH=False \ + LOG_LEVEL=INFO \ + C2CGEOPORTAL_LOG_LEVEL=INFO \ + C2CWSGIUTILS_LOG_LEVEL=INFO \ + GUNICORN_LOG_LEVEL=INFO \ + SQL_LOG_LEVEL=WARN \ + DOGPILECACHE_LOG_LEVEL=INFO \ + OTHER_LOG_LEVEL=WARN diff --git a/CONST_create_template/geoportal/Makefile b/CONST_create_template/geoportal/Makefile new file mode 100644 index 000000000..cbea249f1 --- /dev/null +++ b/CONST_create_template/geoportal/Makefile @@ -0,0 +1,6 @@ +# Language provided by the application +LANGUAGES ?= en fr de +NGEO_INTERFACES ?= desktop mobile iframe_api +NGEO_API ?= TRUE + +include CONST_Makefile diff --git a/CONST_create_template/geoportal/alembic.ini b/CONST_create_template/geoportal/alembic.ini new file mode 100644 index 000000000..3a7abb3b3 --- /dev/null +++ b/CONST_create_template/geoportal/alembic.ini @@ -0,0 +1,57 @@ +[DEFAULT] +app.cfg = %(here)s/alembic.yaml +script_location = /opt/alembic +version_table = alembic_version + +[main] +type = main +version_locations = /opt/alembic/main/ + +[static] +type = static +version_locations = /opt/alembic/static/ + +[getitfixed] +script_location = getitfixed:alembic +version_locations = getitfixed:alembic/versions/ + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console, json +handlers = %(LOG_TYPE)s + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[handler_json] +class = c2cwsgiutils.pyramid_logging.JsonLogHandler +args = (sys.stdout,) +level = NOTSET + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/CONST_create_template/geoportal/alembic.yaml b/CONST_create_template/geoportal/alembic.yaml new file mode 100644 index 000000000..b7aa77944 --- /dev/null +++ b/CONST_create_template/geoportal/alembic.yaml @@ -0,0 +1,19 @@ +--- +vars: + schema: '{PGSCHEMA}' + schema_static: '{PGSCHEMA_STATIC}' + sqlalchemy.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE}?sslmode={PGSSLMODE} + srid: 2056 +environment: + - name: PGHOST + - name: PGPORT + default: '5432' + - name: PGUSER + - name: PGPASSWORD + - name: PGDATABASE + - name: PGSSLMODE + default: prefer + - name: PGSCHEMA + default: main + - name: PGSCHEMA_STATIC + default: main_static diff --git a/CONST_create_template/geoportal/development.ini b/CONST_create_template/geoportal/development.ini new file mode 100644 index 000000000..404a00a47 --- /dev/null +++ b/CONST_create_template/geoportal/development.ini @@ -0,0 +1,102 @@ +[app:app] +use = egg:geoportailv3_geoportal +filter-with = proxy-prefix +pyramid.reload_templates = true +pyramid.debug_authorization = false +pyramid.debug_notfound = true +pyramid.debug_routematch = false +pyramid.debug_templates = true +pyramid.includes = + pyramid_debugtoolbar +debugtoolbar.hosts = 0.0.0.0/0 +mako.directories = geoportailv3_geoportal:templates + c2cgeoportal_geoportal:templates +authtkt_secret = %(AUTHTKT_SECRET)s +authtkt_cookie_name = %(AUTHTKT_COOKIENAME)s +authtkt_timeout = %(AUTHTKT_TIMEOUT)s +authtkt_max_age = %(AUTHTKT_MAXAGE)s +authtkt_reissue_time = %(AUTHTKT_REISSUE_TIME)s +authtkt_http_only = %(AUTHTKT_HTTP_ONLY)s +authtkt_secure = %(AUTHTKT_SECURE)s +authtkt_samesite = %(AUTHTKT_SAMESITE)s +basicauth = %(BASICAUTH)s + +app.cfg = /etc/geomapfish/config.yaml + +[filter:proxy-prefix] +use = egg:PasteDeploy#prefix +prefix = %(VISIBLE_ENTRY_POINT)s + +[pipeline:main] +pipeline = + app + +### +# logging configuration +# https://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/logging.html +### + +[loggers] +keys = root, sqlalchemy, gunicorn, c2cgeoportal_commons, c2cgeoportal_geoportal, c2cgeoportal_admin, geoportailv3_geoportal, c2cwsgiutils, dogpilecache + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = %(OTHER_LOG_LEVEL)s +handlers = console + +[logger_c2cgeoportal_commons] +level = %(C2CGEOPORTAL_LOG_LEVEL)s +handlers = +qualname = c2cgeoportal_commons + +[logger_c2cgeoportal_geoportal] +level = %(C2CGEOPORTAL_LOG_LEVEL)s +handlers = +qualname = c2cgeoportal_geoportal + +[logger_c2cgeoportal_admin] +level = %(C2CGEOPORTAL_LOG_LEVEL)s +handlers = +qualname = c2cgeoportal_admin + +[logger_geoportailv3_geoportal] +level = %(LOG_LEVEL)s +handlers = +qualname = geoportailv3_geoportal + +[logger_c2cwsgiutils] +level = %(C2CWSGIUTILS_LOG_LEVEL)s +handlers = +qualname = c2cwsgiutils + +[logger_gunicorn] +level = %(GUNICORN_LOG_LEVEL)s +handlers = +qualname = gunicorn + +[logger_sqlalchemy] +level = %(SQL_LOG_LEVEL)s +handlers = +qualname = sqlalchemy.engine +# "level = INFO" logs SQL queries. +# "level = DEBUG" logs SQL queries and results. +# "level = WARN" logs neither. (Recommended for production systems.) + +[logger_dogpilecache] +level = %(DOGPILECACHE_LOG_LEVEL)s +handlers = +qualname = dogpile.cache + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/__init__.py b/CONST_create_template/geoportal/geoportailv3_geoportal/__init__.py new file mode 100644 index 000000000..21d5cad1b --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/__init__.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- + +import distutils.core +from pyramid.config import Configurator +from c2cgeoportal_geoportal import locale_negotiator, add_interface, INTERFACE_TYPE_NGEO +from c2cgeoportal_geoportal.lib.authentication import create_authentication +from geoportailv3_geoportal.resources import Root + + +def main(global_config, **settings): + """ + This function returns a Pyramid WSGI application. + """ + del global_config # Unused + + config = Configurator( + root_factory=Root, settings=settings, + locale_negotiator=locale_negotiator, + authentication_policy=create_authentication(settings) + ) + + # Workaround to not have the error: distutils.errors.DistutilsArgError: no commands supplied + distutils.core._setup_stop_after = 'config' + config.include('c2cgeoportal_geoportal') + distutils.core._setup_stop_after = None + + config.add_translation_dirs('geoportailv3_geoportal:locale/') + + # Scan view decorator for adding routes + config.scan() + + # Add the interfaces + for interface in config.get_settings().get("interfaces", []): + add_interface( + config, + interface['name'], + interface.get('type', INTERFACE_TYPE_NGEO), + default=interface.get('default', False) + ) + + try: + import ptvsd + ptvsd.enable_attach(address=('172.17.0.1', 5678)) + # ptvsd.wait_for_attach() + except ModuleNotFoundError as e: + pass + + return config.make_wsgi_app() diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/locale/de/LC_MESSAGES/geoportailv3_geoportal-client.po b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/de/LC_MESSAGES/geoportailv3_geoportal-client.po new file mode 100644 index 000000000..f0b65abaa --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/de/LC_MESSAGES/geoportailv3_geoportal-client.po @@ -0,0 +1,297 @@ +# +# Translators: +# Stéphane Brunner , 2019 +# Renata Müller , 2021 +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Last-Translator: Renata Müller , 2021\n" +"Language-Team: German (https://www.transifex.com/camptocamp/teams/36764/de/)\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: contribs/gmf/apps/desktop/Controller.js:126 +#: contribs/gmf/apps/desktop_alt/Controller.js:169 +#: contribs/gmf/apps/oeedit/Controller.js:222 +msgid "Add a layer" +msgstr "Ebene hinzufügen" + +#: contribs/gmf/apps/desktop/Controller.js:125 +#: contribs/gmf/apps/desktop_alt/Controller.js:168 +#: contribs/gmf/apps/oeedit/Controller.js:221 +msgid "Add a sub theme" +msgstr "Unterthema hinzufügen" + +#: contribs/gmf/apps/desktop/Controller.js:124 +#: contribs/gmf/apps/desktop_alt/Controller.js:167 +#: contribs/gmf/apps/oeedit/Controller.js:220 +msgid "Add a theme" +msgstr "Thema hinzufügen" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:4 +msgid "Alternative Desktop Application" +msgstr "Alternative Desktop-Applikation" + +#: contribs/gmf/apps/mobile_alt/index.html.ejs:4 +msgid "Alternative Mobile Application" +msgstr "Alternative Mobile-Applikation" + +#: contribs/gmf/apps/mobile/index.html.ejs:185 +msgid "Area" +msgstr "Fläche" + +#: contribs/gmf/apps/mobile/index.html.ejs:111 +#: contribs/gmf/apps/mobile/index.html.ejs:147 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:108 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:145 +msgid "Back" +msgstr "Zurück" + +#: contribs/gmf/apps/mobile/index.html.ejs:118 +#: contribs/gmf/apps/mobile/index.html.ejs:132 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:115 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:130 +msgid "Background" +msgstr "Hintergrund" + +#: contribs/gmf/apps/mobile/index.html.ejs:102 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:99 +msgid "Close" +msgstr "Schliessen" + +#: contribs/gmf/apps/mobile/index.html.ejs:167 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:165 +msgid "Coordinate" +msgstr "Koordinate" + +#: contribs/gmf/apps/mobile/index.html.ejs:112 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:109 +msgid "Data" +msgstr "Daten" + +#: contribs/gmf/apps/desktop/index.html.ejs:4 +msgid "Desktop Application" +msgstr "Desktop-Applikation" + +#: contribs/gmf/apps/desktop/index.html.ejs:206 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:224 +msgid "" +"Draw a line on the map to display the corresponding elevation profile.\n" +" Use double-click to finish the drawing." +msgstr "" +"Zeichnen sie eine Linie auf die Karte, um das entsprechende Höhenprofil " +"anzuzeigen. Schliessen sie mit einem Doppelklick ab." + +#: contribs/gmf/apps/desktop/index.html.ejs:146 +#: contribs/gmf/apps/desktop/index.html.ejs:73 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:163 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:70 +msgid "Draw and Measure" +msgstr "Zeichnen & Messen" + +#: contribs/gmf/apps/desktop/index.html.ejs:200 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:217 +msgid "Draw profile line" +msgstr "Profil-Linie zeichnen" + +#: contribs/gmf/apps/desktop/index.html.ejs:173 +#: contribs/gmf/apps/desktop/index.html.ejs:83 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:190 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:81 +msgid "Editing" +msgstr "Editieren" + +#: contribs/gmf/apps/desktop/contextualdata.html:43 +#: contribs/gmf/apps/iframe_api/contextualdata.html:43 +#: contribs/gmf/apps/oeedit/contextualdata.html:43 +msgid "Elevation (Aster)" +msgstr "Höhe (Aster)" + +#: contribs/gmf/apps/desktop/contextualdata.html:35 +#: contribs/gmf/apps/iframe_api/contextualdata.html:35 +#: contribs/gmf/apps/oeedit/contextualdata.html:35 +msgid "Elevation (SRTM)" +msgstr "Höhe (SRTM)" + +#: contribs/gmf/apps/desktop/index.html.ejs:159 +#: contribs/gmf/apps/desktop/index.html.ejs:77 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:176 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:74 +msgid "Filter" +msgstr "Filter" + +#: contribs/gmf/apps/iframe_api/index.html.ejs:4 +msgid "Iframe API Application" +msgstr "Iframe-API-Applikation" + +#: contribs/gmf/apps/desktop/index.html.ejs:226 +#: contribs/gmf/apps/desktop/index.html.ejs:99 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:101 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:257 +msgid "Import Layer" +msgstr "Ebene importieren" + +#: contribs/gmf/apps/desktop/index.html.ejs:178 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:195 +msgid "In order to use the editing tool, you must log in first." +msgstr "Sie müssen eingeloggt sein, um das Editier-Werkzeug zu verwenden." + +#: contribs/gmf/apps/desktop_alt/Controller.js:166 +msgid "Learning [merged]" +msgstr "Lernen [kombiniert]" + +#: contribs/gmf/apps/mobile/index.html.ejs:176 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:174 +msgid "Length" +msgstr "Länge" + +#: contribs/gmf/apps/desktop/index.html.ejs:127 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:133 +msgid "Loading themes, please wait..." +msgstr "Die Themen werden geladen, bitte warten..." + +#: contribs/gmf/apps/desktop/index.html.ejs:41 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:37 +#: contribs/gmf/apps/oeedit/index.html.ejs:32 +msgid "Loading..." +msgstr "Laden..." + +#: contribs/gmf/apps/desktop/index.html.ejs:117 +#: contribs/gmf/apps/desktop/index.html.ejs:65 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:123 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:62 +#: contribs/gmf/apps/mobile/index.html.ejs:155 +#: contribs/gmf/apps/mobile/index.html.ejs:190 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:153 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:179 +msgid "Login" +msgstr "Anmelden" + +#: contribs/gmf/apps/mobile/index.html.ejs:154 +#: contribs/gmf/apps/mobile/index.html.ejs:159 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:152 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:157 +msgid "Measure tools" +msgstr "Messwerkzeuge" + +#: contribs/gmf/apps/mobile/index.html.ejs:4 +msgid "Mobile Application" +msgstr "Mobile-Applikation" + +#: contribs/gmf/apps/desktop_alt/Controller.js:165 +msgid "OSM_time (merged)" +msgstr "OSM Zeitlayer (kombiniert)" + +#: contribs/gmf/apps/desktop_alt/Controller.js:164 +msgid "OSM_time_merged" +msgstr "OSM Zeitlayer kombiniert" + +#: contribs/gmf/apps/oeedit/index.html.ejs:62 +#: contribs/gmf/apps/oeedit/index.html.ejs:80 +msgid "Object Editing" +msgstr "Objektbasierte Editierung" + +#: contribs/gmf/apps/oeedit/index.html.ejs:4 +msgid "ObjectEditing - Edit Application" +msgstr "Objektbasierte Editierung - Bearbeitung" + +#: contribs/gmf/apps/desktop/index.html.ejs:134 +#: contribs/gmf/apps/desktop/index.html.ejs:69 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:140 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:66 +msgid "Print" +msgstr "Drucken" + +#: contribs/gmf/apps/desktop/index.html.ejs:192 +#: contribs/gmf/apps/desktop/index.html.ejs:88 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:209 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:86 +msgid "Profile" +msgstr "Profil" + +#: contribs/gmf/apps/oeedit/index.html.ejs:58 +#: contribs/gmf/apps/oeedit/index.html.ejs:71 +msgid "Query" +msgstr "Abfrage" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:105 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:268 +msgid "Routing" +msgstr "Routing" + +#: contribs/gmf/apps/desktop/index.html.ejs:217 +#: contribs/gmf/apps/desktop/index.html.ejs:92 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:248 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:94 +msgid "Selection" +msgstr "Auswahl" + +#: contribs/gmf/apps/desktop/index.html.ejs:105 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:111 +msgid "Share this map" +msgstr "Diese Karte teilen" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:235 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:90 +msgid "Street View" +msgstr "Street View" + +#: contribs/gmf/apps/desktop/contextualdata.html:11 +#: contribs/gmf/apps/iframe_api/contextualdata.html:11 +#: contribs/gmf/apps/oeedit/contextualdata.html:11 +msgid "Swiss grid (LV03)" +msgstr "Swiss Grid (LV03)" + +#: contribs/gmf/apps/desktop/contextualdata.html:3 +#: contribs/gmf/apps/iframe_api/contextualdata.html:3 +#: contribs/gmf/apps/oeedit/contextualdata.html:3 +msgid "Swiss grid (LV95)" +msgstr "Swiss grid (LV95)" + +#: contribs/gmf/apps/desktop/index.html.ejs:40 +#: contribs/gmf/apps/oeedit/index.html.ejs:31 +msgid "Theme:" +msgstr "Thema:" + +#: contribs/gmf/apps/desktop/index.html.ejs:45 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:41 +#: contribs/gmf/apps/mobile/index.html.ejs:121 +#: contribs/gmf/apps/mobile/index.html.ejs:139 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:118 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:137 +#: contribs/gmf/apps/oeedit/index.html.ejs:36 +msgid "Themes" +msgstr "Themen" + +#: contribs/gmf/apps/mobile/index.html.ejs:148 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:146 +msgid "Tools" +msgstr "Werkzeuge" + +#: contribs/gmf/apps/desktop/contextualdata.html:19 +#: contribs/gmf/apps/iframe_api/contextualdata.html:19 +#: contribs/gmf/apps/oeedit/contextualdata.html:19 +msgid "Wgs Coord." +msgstr "WGS84-Koord." + +#: contribs/gmf/apps/desktop/contextualdata.html:27 +#: contribs/gmf/apps/iframe_api/contextualdata.html:27 +#: contribs/gmf/apps/oeedit/contextualdata.html:27 +msgid "Wgs Coord. DMS" +msgstr "WGS84-Koord. Grad, Min., Sek." + +#: contribs/gmf/apps/mobile/index.html.ejs:103 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:100 +msgid "" +"You're using the mobile application. Check out the standard application." +msgstr "" +"Sie verwenden die mobile Applikation. Wechsel zur Standard-Applikation." + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:153 +msgid "debug" +msgstr "debug" diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/locale/en/LC_MESSAGES/geoportailv3_geoportal-client.po b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/en/LC_MESSAGES/geoportailv3_geoportal-client.po new file mode 100644 index 000000000..2d9149bc1 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/en/LC_MESSAGES/geoportailv3_geoportal-client.po @@ -0,0 +1,6 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/locale/fr/LC_MESSAGES/geoportailv3_geoportal-client.po b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/fr/LC_MESSAGES/geoportailv3_geoportal-client.po new file mode 100644 index 000000000..1dbc751d0 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/fr/LC_MESSAGES/geoportailv3_geoportal-client.po @@ -0,0 +1,296 @@ +# +# Translators: +# Stéphane Brunner , 2020 +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Last-Translator: Stéphane Brunner , 2020\n" +"Language-Team: French (https://www.transifex.com/camptocamp/teams/36764/fr/)\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: contribs/gmf/apps/desktop/Controller.js:126 +#: contribs/gmf/apps/desktop_alt/Controller.js:169 +#: contribs/gmf/apps/oeedit/Controller.js:222 +msgid "Add a layer" +msgstr "Ajouter une couche" + +#: contribs/gmf/apps/desktop/Controller.js:125 +#: contribs/gmf/apps/desktop_alt/Controller.js:168 +#: contribs/gmf/apps/oeedit/Controller.js:221 +msgid "Add a sub theme" +msgstr "Ajouter un sous thème" + +#: contribs/gmf/apps/desktop/Controller.js:124 +#: contribs/gmf/apps/desktop_alt/Controller.js:167 +#: contribs/gmf/apps/oeedit/Controller.js:220 +msgid "Add a theme" +msgstr "Ajouter un theme" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:4 +msgid "Alternative Desktop Application" +msgstr "Application bureau alternative" + +#: contribs/gmf/apps/mobile_alt/index.html.ejs:4 +msgid "Alternative Mobile Application" +msgstr "Application mobile alternative" + +#: contribs/gmf/apps/mobile/index.html.ejs:185 +msgid "Area" +msgstr "Surface" + +#: contribs/gmf/apps/mobile/index.html.ejs:111 +#: contribs/gmf/apps/mobile/index.html.ejs:147 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:108 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:145 +msgid "Back" +msgstr "Retour" + +#: contribs/gmf/apps/mobile/index.html.ejs:118 +#: contribs/gmf/apps/mobile/index.html.ejs:132 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:115 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:130 +msgid "Background" +msgstr "Fond de plan" + +#: contribs/gmf/apps/mobile/index.html.ejs:102 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:99 +msgid "Close" +msgstr "Fermer" + +#: contribs/gmf/apps/mobile/index.html.ejs:167 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:165 +msgid "Coordinate" +msgstr "Coordonnée" + +#: contribs/gmf/apps/mobile/index.html.ejs:112 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:109 +msgid "Data" +msgstr "Donnée" + +#: contribs/gmf/apps/desktop/index.html.ejs:4 +msgid "Desktop Application" +msgstr "Application bureau" + +#: contribs/gmf/apps/desktop/index.html.ejs:206 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:224 +msgid "" +"Draw a line on the map to display the corresponding elevation profile.\n" +" Use double-click to finish the drawing." +msgstr "" +"Dessine une ligne sur la carte pour afficher le profile d'altitude correspondant\n" +"Double cliquer pour terminer la saisie." + +#: contribs/gmf/apps/desktop/index.html.ejs:146 +#: contribs/gmf/apps/desktop/index.html.ejs:73 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:163 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:70 +msgid "Draw and Measure" +msgstr "Mesure et dessin" + +#: contribs/gmf/apps/desktop/index.html.ejs:200 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:217 +msgid "Draw profile line" +msgstr "Dessiner une ligne de profil" + +#: contribs/gmf/apps/desktop/index.html.ejs:173 +#: contribs/gmf/apps/desktop/index.html.ejs:83 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:190 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:81 +msgid "Editing" +msgstr "Edition" + +#: contribs/gmf/apps/desktop/contextualdata.html:43 +#: contribs/gmf/apps/iframe_api/contextualdata.html:43 +#: contribs/gmf/apps/oeedit/contextualdata.html:43 +msgid "Elevation (Aster)" +msgstr "Altitude (Aster)" + +#: contribs/gmf/apps/desktop/contextualdata.html:35 +#: contribs/gmf/apps/iframe_api/contextualdata.html:35 +#: contribs/gmf/apps/oeedit/contextualdata.html:35 +msgid "Elevation (SRTM)" +msgstr "Altitude (SRTM)" + +#: contribs/gmf/apps/desktop/index.html.ejs:159 +#: contribs/gmf/apps/desktop/index.html.ejs:77 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:176 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:74 +msgid "Filter" +msgstr "Filtre" + +#: contribs/gmf/apps/iframe_api/index.html.ejs:4 +msgid "Iframe API Application" +msgstr "Application iframe API" + +#: contribs/gmf/apps/desktop/index.html.ejs:226 +#: contribs/gmf/apps/desktop/index.html.ejs:99 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:101 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:257 +msgid "Import Layer" +msgstr "Importer une couche" + +#: contribs/gmf/apps/desktop/index.html.ejs:178 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:195 +msgid "In order to use the editing tool, you must log in first." +msgstr "Pour utiliser l'interface d’édition vous devez être connecté." + +#: contribs/gmf/apps/desktop_alt/Controller.js:166 +msgid "Learning [merged]" +msgstr "Formation [merged]" + +#: contribs/gmf/apps/mobile/index.html.ejs:176 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:174 +msgid "Length" +msgstr "Longueur" + +#: contribs/gmf/apps/desktop/index.html.ejs:127 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:133 +msgid "Loading themes, please wait..." +msgstr "Chargement des thèmes, veuillez patienter..." + +#: contribs/gmf/apps/desktop/index.html.ejs:41 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:37 +#: contribs/gmf/apps/oeedit/index.html.ejs:32 +msgid "Loading..." +msgstr "Chargement..." + +#: contribs/gmf/apps/desktop/index.html.ejs:117 +#: contribs/gmf/apps/desktop/index.html.ejs:65 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:123 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:62 +#: contribs/gmf/apps/mobile/index.html.ejs:155 +#: contribs/gmf/apps/mobile/index.html.ejs:190 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:153 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:179 +msgid "Login" +msgstr "Connection" + +#: contribs/gmf/apps/mobile/index.html.ejs:154 +#: contribs/gmf/apps/mobile/index.html.ejs:159 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:152 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:157 +msgid "Measure tools" +msgstr "Outil de mesure" + +#: contribs/gmf/apps/mobile/index.html.ejs:4 +msgid "Mobile Application" +msgstr "Application mobile" + +#: contribs/gmf/apps/desktop_alt/Controller.js:165 +msgid "OSM_time (merged)" +msgstr "Temps OSM (merger)" + +#: contribs/gmf/apps/desktop_alt/Controller.js:164 +msgid "OSM_time_merged" +msgstr "Temps OSM (merger)" + +#: contribs/gmf/apps/oeedit/index.html.ejs:62 +#: contribs/gmf/apps/oeedit/index.html.ejs:80 +msgid "Object Editing" +msgstr "Edition objet" + +#: contribs/gmf/apps/oeedit/index.html.ejs:4 +msgid "ObjectEditing - Edit Application" +msgstr "Edition objet - Application d'édition" + +#: contribs/gmf/apps/desktop/index.html.ejs:134 +#: contribs/gmf/apps/desktop/index.html.ejs:69 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:140 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:66 +msgid "Print" +msgstr "Impression" + +#: contribs/gmf/apps/desktop/index.html.ejs:192 +#: contribs/gmf/apps/desktop/index.html.ejs:88 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:209 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:86 +msgid "Profile" +msgstr "Profil" + +#: contribs/gmf/apps/oeedit/index.html.ejs:58 +#: contribs/gmf/apps/oeedit/index.html.ejs:71 +msgid "Query" +msgstr "Interrogation" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:105 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:268 +msgid "Routing" +msgstr "Trajet" + +#: contribs/gmf/apps/desktop/index.html.ejs:217 +#: contribs/gmf/apps/desktop/index.html.ejs:92 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:248 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:94 +msgid "Selection" +msgstr "Sélection" + +#: contribs/gmf/apps/desktop/index.html.ejs:105 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:111 +msgid "Share this map" +msgstr "Partager cette carte" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:235 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:90 +msgid "Street View" +msgstr "Street View" + +#: contribs/gmf/apps/desktop/contextualdata.html:11 +#: contribs/gmf/apps/iframe_api/contextualdata.html:11 +#: contribs/gmf/apps/oeedit/contextualdata.html:11 +msgid "Swiss grid (LV03)" +msgstr "Grille suisse (LV03)" + +#: contribs/gmf/apps/desktop/contextualdata.html:3 +#: contribs/gmf/apps/iframe_api/contextualdata.html:3 +#: contribs/gmf/apps/oeedit/contextualdata.html:3 +msgid "Swiss grid (LV95)" +msgstr "Grille suisse (LV95)" + +#: contribs/gmf/apps/desktop/index.html.ejs:40 +#: contribs/gmf/apps/oeedit/index.html.ejs:31 +msgid "Theme:" +msgstr "Theme:" + +#: contribs/gmf/apps/desktop/index.html.ejs:45 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:41 +#: contribs/gmf/apps/mobile/index.html.ejs:121 +#: contribs/gmf/apps/mobile/index.html.ejs:139 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:118 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:137 +#: contribs/gmf/apps/oeedit/index.html.ejs:36 +msgid "Themes" +msgstr "Themes" + +#: contribs/gmf/apps/mobile/index.html.ejs:148 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:146 +msgid "Tools" +msgstr "Outils" + +#: contribs/gmf/apps/desktop/contextualdata.html:19 +#: contribs/gmf/apps/iframe_api/contextualdata.html:19 +#: contribs/gmf/apps/oeedit/contextualdata.html:19 +msgid "Wgs Coord." +msgstr "Coordonnées WGS" + +#: contribs/gmf/apps/desktop/contextualdata.html:27 +#: contribs/gmf/apps/iframe_api/contextualdata.html:27 +#: contribs/gmf/apps/oeedit/contextualdata.html:27 +msgid "Wgs Coord. DMS" +msgstr "Coordonnées WGS D.M.S." + +#: contribs/gmf/apps/mobile/index.html.ejs:103 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:100 +msgid "" +"You're using the mobile application. Check out the standard application." +msgstr "" +"Vous utilisez l'application mobile. Allez sur l'application standard." + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:153 +msgid "debug" +msgstr "Debug" diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/locale/it/LC_MESSAGES/geoportailv3_geoportal-client.po b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/it/LC_MESSAGES/geoportailv3_geoportal-client.po new file mode 100644 index 000000000..07347ae20 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/locale/it/LC_MESSAGES/geoportailv3_geoportal-client.po @@ -0,0 +1,292 @@ +# +# Translators: +# Giovanni Degiorgi , 2020 +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Last-Translator: Giovanni Degiorgi , 2020\n" +"Language-Team: Italian (https://www.transifex.com/camptocamp/teams/36764/it/)\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: contribs/gmf/apps/desktop/Controller.js:126 +#: contribs/gmf/apps/desktop_alt/Controller.js:169 +#: contribs/gmf/apps/oeedit/Controller.js:222 +msgid "Add a layer" +msgstr "Aggiungi Layer" + +#: contribs/gmf/apps/desktop/Controller.js:125 +#: contribs/gmf/apps/desktop_alt/Controller.js:168 +#: contribs/gmf/apps/oeedit/Controller.js:221 +msgid "Add a sub theme" +msgstr "" + +#: contribs/gmf/apps/desktop/Controller.js:124 +#: contribs/gmf/apps/desktop_alt/Controller.js:167 +#: contribs/gmf/apps/oeedit/Controller.js:220 +msgid "Add a theme" +msgstr "" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:4 +msgid "Alternative Desktop Application" +msgstr "" + +#: contribs/gmf/apps/mobile_alt/index.html.ejs:4 +msgid "Alternative Mobile Application" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:185 +msgid "Area" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:111 +#: contribs/gmf/apps/mobile/index.html.ejs:147 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:108 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:145 +msgid "Back" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:118 +#: contribs/gmf/apps/mobile/index.html.ejs:132 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:115 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:130 +msgid "Background" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:102 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:99 +msgid "Close" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:167 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:165 +msgid "Coordinate" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:112 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:109 +msgid "Data" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:4 +msgid "Desktop Application" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:206 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:224 +msgid "" +"Draw a line on the map to display the corresponding elevation profile.\n" +" Use double-click to finish the drawing." +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:146 +#: contribs/gmf/apps/desktop/index.html.ejs:73 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:163 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:70 +msgid "Draw and Measure" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:200 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:217 +msgid "Draw profile line" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:173 +#: contribs/gmf/apps/desktop/index.html.ejs:83 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:190 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:81 +msgid "Editing" +msgstr "" + +#: contribs/gmf/apps/desktop/contextualdata.html:43 +#: contribs/gmf/apps/iframe_api/contextualdata.html:43 +#: contribs/gmf/apps/oeedit/contextualdata.html:43 +msgid "Elevation (Aster)" +msgstr "" + +#: contribs/gmf/apps/desktop/contextualdata.html:35 +#: contribs/gmf/apps/iframe_api/contextualdata.html:35 +#: contribs/gmf/apps/oeedit/contextualdata.html:35 +msgid "Elevation (SRTM)" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:159 +#: contribs/gmf/apps/desktop/index.html.ejs:77 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:176 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:74 +msgid "Filter" +msgstr "" + +#: contribs/gmf/apps/iframe_api/index.html.ejs:4 +msgid "Iframe API Application" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:226 +#: contribs/gmf/apps/desktop/index.html.ejs:99 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:101 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:257 +msgid "Import Layer" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:178 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:195 +msgid "In order to use the editing tool, you must log in first." +msgstr "" + +#: contribs/gmf/apps/desktop_alt/Controller.js:166 +msgid "Learning [merged]" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:176 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:174 +msgid "Length" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:127 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:133 +msgid "Loading themes, please wait..." +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:41 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:37 +#: contribs/gmf/apps/oeedit/index.html.ejs:32 +msgid "Loading..." +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:117 +#: contribs/gmf/apps/desktop/index.html.ejs:65 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:123 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:62 +#: contribs/gmf/apps/mobile/index.html.ejs:155 +#: contribs/gmf/apps/mobile/index.html.ejs:190 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:153 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:179 +msgid "Login" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:154 +#: contribs/gmf/apps/mobile/index.html.ejs:159 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:152 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:157 +msgid "Measure tools" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:4 +msgid "Mobile Application" +msgstr "" + +#: contribs/gmf/apps/desktop_alt/Controller.js:165 +msgid "OSM_time (merged)" +msgstr "" + +#: contribs/gmf/apps/desktop_alt/Controller.js:164 +msgid "OSM_time_merged" +msgstr "" + +#: contribs/gmf/apps/oeedit/index.html.ejs:62 +#: contribs/gmf/apps/oeedit/index.html.ejs:80 +msgid "Object Editing" +msgstr "" + +#: contribs/gmf/apps/oeedit/index.html.ejs:4 +msgid "ObjectEditing - Edit Application" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:134 +#: contribs/gmf/apps/desktop/index.html.ejs:69 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:140 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:66 +msgid "Print" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:192 +#: contribs/gmf/apps/desktop/index.html.ejs:88 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:209 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:86 +msgid "Profile" +msgstr "" + +#: contribs/gmf/apps/oeedit/index.html.ejs:58 +#: contribs/gmf/apps/oeedit/index.html.ejs:71 +msgid "Query" +msgstr "" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:105 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:268 +msgid "Routing" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:217 +#: contribs/gmf/apps/desktop/index.html.ejs:92 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:248 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:94 +msgid "Selection" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:105 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:111 +msgid "Share this map" +msgstr "" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:235 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:90 +msgid "Street View" +msgstr "" + +#: contribs/gmf/apps/desktop/contextualdata.html:11 +#: contribs/gmf/apps/iframe_api/contextualdata.html:11 +#: contribs/gmf/apps/oeedit/contextualdata.html:11 +msgid "Swiss grid (LV03)" +msgstr "" + +#: contribs/gmf/apps/desktop/contextualdata.html:3 +#: contribs/gmf/apps/iframe_api/contextualdata.html:3 +#: contribs/gmf/apps/oeedit/contextualdata.html:3 +msgid "Swiss grid (LV95)" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:40 +#: contribs/gmf/apps/oeedit/index.html.ejs:31 +msgid "Theme:" +msgstr "" + +#: contribs/gmf/apps/desktop/index.html.ejs:45 +#: contribs/gmf/apps/desktop_alt/index.html.ejs:41 +#: contribs/gmf/apps/mobile/index.html.ejs:121 +#: contribs/gmf/apps/mobile/index.html.ejs:139 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:118 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:137 +#: contribs/gmf/apps/oeedit/index.html.ejs:36 +msgid "Themes" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:148 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:146 +msgid "Tools" +msgstr "" + +#: contribs/gmf/apps/desktop/contextualdata.html:19 +#: contribs/gmf/apps/iframe_api/contextualdata.html:19 +#: contribs/gmf/apps/oeedit/contextualdata.html:19 +msgid "Wgs Coord." +msgstr "" + +#: contribs/gmf/apps/desktop/contextualdata.html:27 +#: contribs/gmf/apps/iframe_api/contextualdata.html:27 +#: contribs/gmf/apps/oeedit/contextualdata.html:27 +msgid "Wgs Coord. DMS" +msgstr "" + +#: contribs/gmf/apps/mobile/index.html.ejs:103 +#: contribs/gmf/apps/mobile_alt/index.html.ejs:100 +msgid "" +"You're using the mobile application. Check out the standard application." +msgstr "" + +#: contribs/gmf/apps/desktop_alt/index.html.ejs:153 +msgid "debug" +msgstr "" diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/models.py b/CONST_create_template/geoportal/geoportailv3_geoportal/models.py new file mode 100644 index 000000000..b29892274 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/models.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +import logging + +from pyramid.i18n import TranslationStringFactory + +from c2cgeoportal_commons.models.main import * # noqa + +_ = TranslationStringFactory("geoportailv3-server") +LOG = logging.getLogger(__name__) diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/resources.py b/CONST_create_template/geoportal/geoportailv3_geoportal/resources.py new file mode 100644 index 000000000..c68279b13 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/resources.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +from pyramid.security import ALL_PERMISSIONS, Allow + + +class Root: + __acl__ = [(Allow, "role_admin", ALL_PERMISSIONS)] + + def __init__(self, request): + self.request = request diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/api/api.css b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/api/api.css new file mode 100644 index 000000000..06e091840 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/api/api.css @@ -0,0 +1,437 @@ +.ol-box { + box-sizing: border-box; + border-radius: 2px; + border: 2px solid blue; +} + +.ol-mouse-position { + top: 8px; + right: 8px; + position: absolute; +} + +.ol-scale-line { + background: rgba(0,60,136,0.3); + border-radius: 4px; + bottom: 8px; + left: 8px; + padding: 2px; + position: absolute; +} +.ol-scale-line-inner { + border: 1px solid #eee; + border-top: none; + color: #eee; + font-size: 10px; + text-align: center; + margin: 1px; + will-change: contents, width; +} +.ol-overlay-container { + will-change: left,right,top,bottom; +} + +.ol-unsupported { + display: none; +} +.ol-viewport, .ol-unselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0,0,0,0); +} +.ol-selectable { + -webkit-touch-callout: default; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} +.ol-grabbing { + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; +} +.ol-grab { + cursor: move; + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; +} +.ol-control { + position: absolute; + background-color: rgba(255,255,255,0.4); + border-radius: 4px; + padding: 2px; +} +.ol-control:hover { + background-color: rgba(255,255,255,0.6); +} +.ol-zoom { + top: .5em; + left: .5em; +} +.ol-rotate { + top: .5em; + right: .5em; + transition: opacity .25s linear, visibility 0s linear; +} +.ol-rotate.ol-hidden { + opacity: 0; + visibility: hidden; + transition: opacity .25s linear, visibility 0s linear .25s; +} +.ol-zoom-extent { + top: 4.643em; + left: .5em; +} +.ol-full-screen { + right: .5em; + top: .5em; +} +@media print { + .ol-control { + display: none; + } +} + +.ol-control button { + display: block; + margin: 1px; + padding: 0; + color: white; + font-size: 1.14em; + font-weight: bold; + text-decoration: none; + text-align: center; + height: 1.375em; + width: 1.375em; + line-height: .4em; + background-color: rgba(0,60,136,0.5); + border: none; + border-radius: 2px; +} +.ol-control button::-moz-focus-inner { + border: none; + padding: 0; +} +.ol-zoom-extent button { + line-height: 1.4em; +} +.ol-compass { + display: block; + font-weight: normal; + font-size: 1.2em; + will-change: transform; +} +.ol-touch .ol-control button { + font-size: 1.5em; +} +.ol-touch .ol-zoom-extent { + top: 5.5em; +} +.ol-control button:hover, +.ol-control button:focus { + text-decoration: none; + background-color: rgba(0,60,136,0.7); +} +.ol-zoom .ol-zoom-in { + border-radius: 2px 2px 0 0; +} +.ol-zoom .ol-zoom-out { + border-radius: 0 0 2px 2px; +} + + +.ol-attribution { + text-align: right; + bottom: .5em; + right: .5em; + max-width: calc(100% - 1.3em); +} + +.ol-attribution ul { + margin: 0; + padding: 0 .5em; + font-size: .7rem; + line-height: 1.375em; + color: #000; + text-shadow: 0 0 2px #fff; +} +.ol-attribution li { + display: inline; + list-style: none; + line-height: inherit; +} +.ol-attribution li:not(:last-child):after { + content: " "; +} +.ol-attribution img { + max-height: 2em; + max-width: inherit; + vertical-align: middle; +} +.ol-attribution ul, .ol-attribution button { + display: inline-block; +} +.ol-attribution.ol-collapsed ul { + display: none; +} +.ol-attribution:not(.ol-collapsed) { + background: rgba(255,255,255,0.8); +} +.ol-attribution.ol-uncollapsible { + bottom: 0; + right: 0; + border-radius: 4px 0 0; + height: 1.1em; + line-height: 1em; +} +.ol-attribution.ol-uncollapsible img { + margin-top: -.2em; + max-height: 1.6em; +} +.ol-attribution.ol-uncollapsible button { + display: none; +} + +.ol-zoomslider { + top: 4.5em; + left: .5em; + height: 200px; +} +.ol-zoomslider button { + position: relative; + height: 10px; +} + +.ol-touch .ol-zoomslider { + top: 5.5em; +} + +.ol-overviewmap { + left: 0.5em; + bottom: 0.5em; +} +.ol-overviewmap.ol-uncollapsible { + bottom: 0; + left: 0; + border-radius: 0 4px 0 0; +} +.ol-overviewmap .ol-overviewmap-map, +.ol-overviewmap button { + display: inline-block; +} +.ol-overviewmap .ol-overviewmap-map { + border: 1px solid #7b98bc; + height: 150px; + margin: 2px; + width: 150px; +} +.ol-overviewmap:not(.ol-collapsed) button{ + bottom: 1px; + left: 2px; + position: absolute; +} +.ol-overviewmap.ol-collapsed .ol-overviewmap-map, +.ol-overviewmap.ol-uncollapsible button { + display: none; +} +.ol-overviewmap:not(.ol-collapsed) { + background: rgba(255,255,255,0.8); +} +.ol-overviewmap-box { + border: 2px dotted rgba(0,60,136,0.7); +} + +.ol-overviewmap .ol-overviewmap-box:hover { + cursor: move; +} + + +.ol-popup { + position: absolute; + background-color: white; + -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2)); + filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2)); + padding: 15px; + border-radius: 5px; + border: 1px solid #ccc; + bottom: 12px; + left: -50px; + min-width: 280px; +} +.ol-popup:after, .ol-popup:before { + top: 100%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} +.ol-popup:after { + border-top-color: white; + border-width: 10px; + left: 48px; + margin-left: -10px; +} +.ol-popup:before { + border-top-color: #ccc; + border-width: 11px; + left: 48px; + margin-left: -11px; +} +.ol-popup-closer { + cursor: pointer; + text-decoration: none; + position: absolute; + top: 2px; + right: 8px; +} +.ol-popup-closer:after { + content: "✖"; +} + +.layer-switcher.shown.ol-control { + background-color: transparent; +} + +.layer-switcher.shown.ol-control:hover { + background-color: transparent; +} + +.layer-switcher { + position: absolute; + top: 3.5em; + right: 0.5em; + text-align: left; +} + +.layer-switcher.shown { + bottom: 3em; +} + +.layer-switcher .panel { + padding: 0 1em 0 0; + margin: 0; + border: 4px solid #eee; + border-radius: 4px; + background-color: white; + display: none; + max-height: 100%; + overflow-y: auto; +} + +.layer-switcher.shown .panel { + display: block; +} + +.layer-switcher button { + float: right; + width: 38px; + height: 38px; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAACE1BMVEX///8A//8AgICA//8AVVVAQID///8rVVVJtttgv98nTmJ2xNgkW1ttyNsmWWZmzNZYxM4gWGgeU2JmzNNr0N1Rwc0eU2VXxdEhV2JqytQeVmMhVmNoydUfVGUgVGQfVGQfVmVqy9hqy9dWw9AfVWRpydVry9YhVmMgVGNUw9BrytchVWRexdGw294gVWQgVmUhVWPd4N6HoaZsy9cfVmQgVGRrytZsy9cgVWQgVWMgVWRsy9YfVWNsy9YgVWVty9YgVWVry9UgVWRsy9Zsy9UfVWRsy9YgVWVty9YgVWRty9Vsy9aM09sgVWRTws/AzM0gVWRtzNYgVWRuy9Zsy9cgVWRGcHxty9bb5ORbxdEgVWRty9bn6OZTws9mydRfxtLX3Nva5eRix9NFcXxOd4JPeINQeIMiVmVUws9Vws9Vw9BXw9BYxNBaxNBbxNBcxdJexdElWWgmWmhjyNRlx9IqXGtoipNpytVqytVryNNrytZsjZUuX210k5t1y9R2zNR3y9V4lp57zth9zdaAnKOGoaeK0NiNpquV09mesrag1tuitbmj1tuj19uktrqr2d2svcCu2d2xwMO63N+7x8nA3uDC3uDFz9DK4eHL4eLN4eIyYnDX5OM5Z3Tb397e4uDf4uHf5uXi5ePi5+Xj5+Xk5+Xm5+Xm6OY6aHXQ19fT4+NfhI1Ww89gx9Nhx9Nsy9ZWw9Dpj2abAAAAWnRSTlMAAQICAwQEBgcIDQ0ODhQZGiAiIyYpKywvNTs+QklPUlNUWWJjaGt0dnd+hIWFh4mNjZCSm6CpsbW2t7nDzNDT1dje5efr7PHy9PT29/j4+Pn5+vr8/f39/f6DPtKwAAABTklEQVR4Xr3QVWPbMBSAUTVFZmZmhhSXMjNvkhwqMzMzMzPDeD+xASvObKePPa+ffHVl8PlsnE0+qPpBuQjVJjno6pZpSKXYl7/bZyFaQxhf98hHDKEppwdWIW1frFnrxSOWHFfWesSEWC6R/P4zOFrix3TzDFLlXRTR8c0fEEJ1/itpo7SVO9Jdr1DVxZ0USyjZsEY5vZfiiAC0UoTGOrm9PZLuRl8X+Dq1HQtoFbJZbv61i+Poblh/97TC7n0neCcK0ETNUrz1/xPHf+DNAW9Ac6t8O8WH3Vp98f5lCaYKAOFZMLyHL4Y0fe319idMNgMMp+zWVSybUed/+/h7I4wRAG1W6XDy4XmjR9HnzvDRZXUAYDFOhC1S/Hh+fIXxen+eO+AKqbs+wAo30zDTDvDxKoJN88sjUzDFAvBzEUGFsnADoIvAJzoh2BZ8sner+Ke/vwECuQAAAABJRU5ErkJggg==') /*logo.png*/; + background-repeat: no-repeat; + background-position: 2px; + background-color: white; + border: none; +} + +.layer-switcher.shown button { + display: none; +} + +.layer-switcher button:focus, .layer-switcher button:hover { + background-color: white; +} + +.layer-switcher ul { + padding-left: 1em; + list-style: none; +} + +.layer-switcher li.group { + padding-top: 5px; +} + +.layer-switcher li.group > label { + font-weight: bold; +} + +.layer-switcher li.layer { + display: table; +} + +.layer-switcher li.layer label, .layer-switcher li.layer input { + display: table-cell; + vertical-align: sub; +} + +.layer-switcher label.disabled { + opacity:0.4; +} + +.layer-switcher input { + margin: 4px; +} + +.layer-switcher.touch ::-webkit-scrollbar { + width: 4px; +} + +.layer-switcher.touch ::-webkit-scrollbar-track { + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); + border-radius: 10px; +} + +.layer-switcher.touch ::-webkit-scrollbar-thumb { + border-radius: 10px; + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.5); +} + +.layer-switcher .group.layer-switcher-fold > label:before { + content: ''; + border: solid black; + border-width: 0 3px 3px 0; + display: inline-block; + padding: 2px; + margin-right: 2px; + margin-bottom: 2px; +} + +.layer-switcher .group.layer-switcher-fold.layer-switcher-close > label:before { + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); +} + +.layer-switcher .group.layer-switcher-fold.layer-switcher-open > label:before { + transform: rotate(45deg); + -webkit-transform: rotate(45deg); +} + +.layer-switcher .group.layer-switcher-fold.layer-switcher-close > ul { + overflow: hidden; + height: 0; +} + +.api-search-input { + width: 100%; +} + +.api-search-results { + max-height: 400px; + overflow: hidden; + overflow-y: auto; + margin: 0; + padding: 0; + list-style: none; + background-color: #fff; +} + +.api-search-results .autocomplete-result { + cursor: pointer; + padding: 4px; +} diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/api/index.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/api/index.js new file mode 100644 index 000000000..c88bbe022 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/api/index.js @@ -0,0 +1,37 @@ +/* eslint-disable */ +import Map from 'api/Map.js'; +import config from 'api/constants.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; + + +// The URL to the themes service. +config.themesUrl = '{FULL_ENTRY_POINT}themes?version=2&background=background&interface=api'; + +// The URL to the locale service. +config.localeUrl = '{FULL_ENTRY_POINT}locale.json'; + +// The URL to the search service. +config.searchUrl = '{FULL_ENTRY_POINT}search?interface=api&limit=15'; + +// The projection of the map +config.projection = EPSG2056; + +// The resolutions list. +config.resolutions = [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05]; + +// The extent restriction, must be in the same projection as `config.projection`. +// the format is `[minx, miny, maxx, maxy]`for example: `[420000, 30000, 660000, 350000]` +// the default is ǹo restriction. +config.extent = undefined; + +// The name of the GeoMapFish layer to use as background. May be a single value +// (WMTS) or a comma-separated list of layer names (WMS). +config.backgroundLayer = 'OSM map'; + +// end of configuration + +const lib = { + Map +}; + +export default lib; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllerdesktop.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllerdesktop.js new file mode 100644 index 000000000..1820815e1 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllerdesktop.js @@ -0,0 +1,153 @@ +// The MIT License (MIT) +// +// Copyright (c) 2016-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +/** + * Application entry point. + * + * This file includes `import`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import './sass/desktop.scss'; +import './sass/vars_desktop.scss'; + +import angular from 'angular'; +import gmfControllersAbstractDesktopController, {AbstractDesktopController} + from 'gmf/controllers/AbstractDesktopController.js'; +import geoportailv3Base from '../geoportailv3module.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; +import EPSG21781 from '@geoblocks/proj/src/EPSG_21781.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. ' + + 'Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. ' + + 'Sie werden weitergeleitet.'); + window.location.href = 'https://geomapfish.org/'; +} + + +/** + * @private + */ +class Controller extends AbstractDesktopController { + /** + * @param {angular.IScope} $scope Scope. + * @param {angular.auto.IInjectorService} $injector Main injector. + * @ngInject + */ + constructor($scope, $injector) { + super({ + srid: 2056, + mapViewConfig: { + center: [2632464, 1185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05], + constrainResolution: true, + extent: [2485071.54, 175346.36, 2828515.78, 1299941.84], + } + }, $scope, $injector); + + /** + * @type {string[]} + */ + this.searchCoordinatesProjections = [EPSG21781, EPSG2056, 'EPSG:4326']; + + /** + * @type {number[]} + */ + this.scaleSelectorValues = [1000000, 500000, 200000, 100000, 50000, 20000, 10000, 5000, 2000, 1000, 500, 200]; + + /** + * @type {string[]} + */ + this.elevationLayers = ['aster', 'srtm']; + + /** + * @type {Object} + */ + this.elevationLayersConfig = {}; + + /** + * @type {string} + */ + this.selectedElevationLayer = this.elevationLayers[0]; + + /** + * @type {Object} + */ + this.profileLinesconfiguration = { + 'aster': {color: '#0000A0'}, + 'srtm': {color: '#00A000'}, + }; + + /** + * @type {Array} + */ + this.mousePositionProjections = [{ + code: EPSG2056, + label: 'CH1903+ / LV95', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: EPSG21781, + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + // Allow angular-gettext-tools to collect the strings to translate + /** @type {angular.gettext.gettextCatalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + gettextCatalog.getString('Add a theme'); + gettextCatalog.getString('Add a sub theme'); + gettextCatalog.getString('Add a layer'); + } +} + +/** + * @hidden + */ +const module = angular.module('Appdesktop', [ + geoportailv3Base.name, + gmfControllersAbstractDesktopController.name, +]); + + +module.value('gmfContextualdatacontentTemplateUrl', 'gmf/contextualdata'); +module.run( + /** + * @ngInject + * @param {angular.ITemplateCacheService} $templateCache + */ + ($templateCache) => { + // @ts-ignore: webpack + $templateCache.put('gmf/contextualdata', require('./contextualdata.html')); + } +); + +module.controller('DesktopController', Controller); + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllerdesktop_alt.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllerdesktop_alt.js new file mode 100644 index 000000000..80ea4c3c4 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllerdesktop_alt.js @@ -0,0 +1,204 @@ +// The MIT License (MIT) +// +// Copyright (c) 2016-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +/** + * Application entry point. + * + * This file includes `import`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import './sass/desktop_alt.scss'; +import './sass/vars_desktop_alt.scss'; + +import angular from 'angular'; +import gmfControllersAbstractDesktopController, {AbstractDesktopController} + from 'gmf/controllers/AbstractDesktopController.js'; +import geoportailv3Base from '../geoportailv3module.js'; +import gmfImportModule from 'gmf/import/module.js'; +import gmfFloorModule from 'gmf/floor/module.js'; +import ngeoGooglestreetviewModule from 'ngeo/googlestreetview/module.js'; +import {isEventUsinCtrlKey} from 'ngeo/utils.js'; +import ngeoRoutingModule from 'ngeo/routing/module.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; +import EPSG21781 from '@geoblocks/proj/src/EPSG_21781.js'; +import ngeoStatemanagerWfsPermalink from 'ngeo/statemanager/WfsPermalink.js'; +import Style from 'ol/style/Style.js'; +import Circle from 'ol/style/Circle.js'; +import Fill from 'ol/style/Fill.js'; +import Stroke from 'ol/style/Stroke.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. ' + + 'Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. ' + + 'Sie werden weitergeleitet.'); + window.location.href = 'https://geomapfish.org/'; +} + + +/** + * @private + */ +class Controller extends AbstractDesktopController { + /** + * @param {angular.IScope} $scope Scope. + * @param {angular.auto.IInjectorService} $injector Main injector. + * @ngInject + */ + constructor($scope, $injector) { + super({ + maxTilesLoading: Infinity, + srid: 2056, + mapViewConfig: { + center: [2632464, 1185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05], + constrainResolution: false, + } + }, $scope, $injector); + + if (this.dimensions.FLOOR == undefined) { + this.dimensions.FLOOR = '*'; + } + + /** + * @type {Array} + */ + this.searchCoordinatesProjections = [EPSG21781, EPSG2056, 'EPSG:4326']; + + /** + * @type {number} + */ + this.searchDelay = 500; + + /** + * @type {boolean} + */ + this.showInfobar = true; + + /** + * @type {string[]} + */ + this.elevationLayers = ['srtm-partial']; + + /** + * @type {Object} + */ + this.elevationLayersConfig = {}; + + /** + * @type {Object} + */ + this.profileLinesconfiguration = { + 'srtm-partial': {} + }; + + /** + * @type {Array} + */ + this.mousePositionProjections = [{ + code: 'EPSG:2056', + label: 'CH1903+ / LV95', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:21781', + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + /** + * @type {import('gmf/query/gridComponent.js').GridMergeTabs} + */ + this.gridMergeTabs = { + 'OSM_time_merged': ['osm_time', 'osm_time2'], + 'transport (merged)': ['fuel', 'parking'], + 'Learning [merged]': ['information', 'bus_stop'] + }; + + const radius = 5; + const fill = new Fill({color: [255, 255, 255, 0.6]}); + const stroke = new Stroke({color: [255, 0, 0, 1], width: 2}); + const image = new Circle({fill, radius, stroke}); + const defaultSearchStyle = new Style({ + fill, + image, + stroke + }); + + /** + * @type {Object} Map of styles for search overlay. + * @export + */ + this.searchStyles = { + 'default': defaultSearchStyle + }; + + // Allow angular-gettext-tools to collect the strings to translate + /** @type {angular.gettext.gettextCatalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + gettextCatalog.getString('OSM_time_merged'); + gettextCatalog.getString('OSM_time (merged)'); + gettextCatalog.getString('Learning [merged]'); + gettextCatalog.getString('Add a theme'); + gettextCatalog.getString('Add a sub theme'); + gettextCatalog.getString('Add a layer'); + + /** + * @type {string} + */ + this.bgOpacityOptions = 'orthophoto'; + } + + /** + * @param {JQueryEventObject} event keydown event. + */ + onKeydown(event) { + if (event && isEventUsinCtrlKey(event) && event.key === 'p') { + this.printPanelActive = true; + event.preventDefault(); + } + } +} + +/** + * @hidden + */ +const module = angular.module('Appdesktop_alt', [ + geoportailv3Base.name, + gmfControllersAbstractDesktopController.name, + gmfImportModule.name, + gmfFloorModule.name, + ngeoRoutingModule.name, + ngeoGooglestreetviewModule.name, + ngeoStatemanagerWfsPermalink.name, +]); + +module.controller('AlternativeDesktopController', Controller); + + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controlleriframe_api.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controlleriframe_api.js new file mode 100644 index 000000000..cb615ce35 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controlleriframe_api.js @@ -0,0 +1,84 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +/** + * Application entry point. + * + * This file includes `import`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import 'gmf/controllers/iframe_api.scss'; +import 'gmf/controllers/vars_desktop.scss'; + +import angular from 'angular'; +import gmfControllersAbstractAPIController, {AbstractAPIController} + from 'gmf/controllers/AbstractAPIController.js'; +import geoportailv3Base from '../geoportailv3module.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; +import EPSG21781 from '@geoblocks/proj/src/EPSG_21781.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. ' + + 'Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. ' + + 'Sie werden weitergeleitet.'); + window.location.href = 'https://geomapfish.org/'; +} + + +/** + * @private + */ +class Controller extends AbstractAPIController { + /** + * @param {angular.IScope} $scope Scope. + * @param {angular.auto.IInjectorService} $injector Main injector. + * @ngInject + */ + constructor($scope, $injector) { + super({ + srid: 2056, + mapViewConfig: { + center: [2632464, 1185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + this.EPSG2056 = EPSG2056; + this.EPSG21781 = EPSG21781; + } +} + +/** + * @hidden + */ +const module = angular.module('Appiframe_api', [ + geoportailv3Base.name, + gmfControllersAbstractAPIController.name, +]); + +module.controller('IframeAPIController', Controller); + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllermobile.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllermobile.js new file mode 100644 index 000000000..efcbc59af --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllermobile.js @@ -0,0 +1,95 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +/** + * Application entry point. + * + * This file includes `import`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import './sass/vars_mobile.scss'; +import './sass/mobile.scss'; + +import angular from 'angular'; +import gmfControllersAbstractMobileController, {AbstractMobileController} + from 'gmf/controllers/AbstractMobileController.js'; +import geoportailv3Base from '../geoportailv3module.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; +import EPSG21781 from '@geoblocks/proj/src/EPSG_21781.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. ' + + 'Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. ' + + 'Sie werden weitergeleitet.'); + window.location.href = 'https://geomapfish.org/'; +} + + +/** + * @private + */ +class Controller extends AbstractMobileController { + /** + * @param {angular.IScope} $scope Scope. + * @param {angular.auto.IInjectorService} $injector Main injector. + * @ngInject + */ + constructor($scope, $injector) { + super({ + autorotate: false, + srid: 2056, + mapViewConfig: { + center: [2632464, 1185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {Array} + */ + this.elevationLayersConfig = [ + {name: 'aster', unit: 'm'}, + {name: 'srtm', unit: 'm'} + ]; + + /** + * @type {string[]} + */ + this.searchCoordinatesProjections = [EPSG21781, EPSG2056, 'EPSG:4326']; + } +} + +/** + * @hidden + */ +const module = angular.module('Appmobile', [ + geoportailv3Base.name, + gmfControllersAbstractMobileController.name, +]); + +module.controller('MobileController', Controller); + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllermobile_alt.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllermobile_alt.js new file mode 100644 index 000000000..2f6dfb0e2 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controllermobile_alt.js @@ -0,0 +1,102 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +/** + * Application entry point. + * + * This file includes `import`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import './sass/vars_mobile_alt.scss'; +import './sass/mobile_alt.scss'; + +import angular from 'angular'; +import gmfControllersAbstractMobileController, {AbstractMobileController} + from 'gmf/controllers/AbstractMobileController.js'; +import geoportailv3Base from '../geoportailv3module.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; +import EPSG21781 from '@geoblocks/proj/src/EPSG_21781.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. ' + + 'Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. ' + + 'Sie werden weitergeleitet.'); + window.location.href = 'https://geomapfish.org/'; +} + + +/** + * @private + */ +class Controller extends AbstractMobileController { + /** + * @param {angular.IScope} $scope Scope. + * @param {angular.auto.IInjectorService} $injector Main injector. + * @ngInject + */ + constructor($scope, $injector) { + super({ + autorotate: true, + mapPixelRatio: 1, + maxTilesLoading: 64, + srid: 2056, + mapViewConfig: { + center: [2632464, 1185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {Array} + */ + this.elevationLayersConfig = [ + {name: 'aster', unit: 'm'}, + {name: 'srtm', unit: 'm'} + ]; + + /** + * @type {number} + */ + this.searchDelay = 50; + + /** + * @type {string[]} + */ + this.searchCoordinatesProjections = [EPSG21781, EPSG2056, 'EPSG:4326']; + } +} + +/** + * @hidden + */ +const module = angular.module('Appmobile_alt', [ + geoportailv3Base.name, + gmfControllersAbstractMobileController.name, +]); + +module.controller('AlternativeMobileController', Controller); + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controlleroeedit.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controlleroeedit.js new file mode 100644 index 000000000..8bc996959 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/Controlleroeedit.js @@ -0,0 +1,252 @@ +// The MIT License (MIT) +// +// Copyright (c) 2016-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +/** + * Application entry point. + * + * This file includes `import`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import './sass/vars_oeedit.scss'; +import './sass/oeedit.scss'; + +import angular from 'angular'; +import gmfControllersAbstractDesktopController, {AbstractDesktopController} + from 'gmf/controllers/AbstractDesktopController.js'; +import geoportailv3Base from '../geoportailv3module.js'; +import gmfObjecteditingModule from 'gmf/objectediting/module.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import EPSG2056 from '@geoblocks/proj/src/EPSG_2056.js'; +import EPSG21781 from '@geoblocks/proj/src/EPSG_21781.js'; +import olCollection from 'ol/Collection.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olSourceVector from 'ol/source/Vector.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. ' + + 'Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. ' + + 'Sie werden weitergeleitet.'); + window.location.href = 'https://geomapfish.org/'; +} + + +/** + * @private + */ +class Controller extends AbstractDesktopController { + /** + * @param {angular.IScope} $scope Scope. + * @param {angular.auto.IInjectorService} $injector Main injector. + * @param {angular.ITimeoutService} $timeout Angular timeout service. + * @ngInject + */ + constructor($scope, $injector, $timeout) { + super({ + srid: 2056, + mapViewConfig: { + center: [2632464, 1185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {boolean} + */ + this.oeEditActive = false; + + /** + * The ngeo ToolActivate manager service. + * @type {import('ngeo/misc/ToolActivateMgr.js').ToolActivateMgr} + */ + const ngeoToolActivateMgr = $injector.get('ngeoToolActivateMgr'); + + ngeoToolActivateMgr.unregisterGroup('mapTools'); + + const oeEditToolActivate = new ngeoMiscToolActivate(this, 'oeEditActive'); + ngeoToolActivateMgr.registerTool('mapTools', oeEditToolActivate, true); + + const queryToolActivate = new ngeoMiscToolActivate(this, 'queryActive'); + ngeoToolActivateMgr.registerTool('mapTools', queryToolActivate, false); + + // Set edit tool as default active one + $timeout(() => { + this.oeEditActive = true; + }); + + /** + * @type {import("ol/source/Vector.js").default<*>} + * @private + */ + this.vectorSource_ = new olSourceVector({ + wrapX: false + }); + + /** + * @type {import("ol/layer/Vector.js").default} + * @private + */ + this.vectorLayer_ = new olLayerVector({ + source: this.vectorSource_ + }); + + /** + * @type {import("ol/Collection.js").default>} + */ + this.sketchFeatures = new olCollection(); + + /** + * @type {import("ol/layer/Vector.js").default} + * @private + */ + this.sketchLayer_ = new olLayerVector({ + source: new olSourceVector({ + features: this.sketchFeatures, + wrapX: false + }) + }); + + /** + * @type {import("gmf/theme/Themes.js").ThemesService} gmfObjectEditingManager The gmf theme service + */ + const gmfThemes = $injector.get('gmfThemes'); + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + // Add layer vector after + this.map.addLayer(this.vectorLayer_); + this.map.addLayer(this.sketchLayer_); + } + }); + + /** + * @type {import("gmf/objectediting/Manager.js").ObjecteditingManagerService} gmfObjectEditingManager + * The gmf ObjectEditing manager service. + */ + const gmfObjectEditingManager = $injector.get('gmfObjectEditingManager'); + + /** + * @type {string|undefined} + */ + this.oeGeomType = gmfObjectEditingManager.getGeomType(); + + /** + * @type {number|undefined} + */ + this.oeLayerNodeId = gmfObjectEditingManager.getLayerNodeId(); + + /** + * @type {?import("ol/Feature.js").default} + */ + this.oeFeature = null; + + gmfObjectEditingManager.getFeature().then((feature) => { + this.oeFeature = feature; + if (feature) { + this.vectorSource_.addFeature(feature); + } + }); + + /** + * @type {string[]} + */ + this.searchCoordinatesProjections = [EPSG21781, EPSG2056, 'EPSG:4326']; + + /** + * @type {number[]} + */ + this.scaleSelectorValues = [250000, 100000, 50000, 20000, 10000, 5000, 2000, 1000, 500, 250, 100, 50]; + + /** + * @type {string[]} + */ + this.elevationLayers = ['aster', 'srtm']; + + /** + * @type {string} + */ + this.selectedElevationLayer = this.elevationLayers[0]; + + /** + * @type {Object} + */ + this.profileLinesconfiguration = { + 'aster': {color: '#0000A0'}, + 'srtm': {color: '#00A000'} + }; + + /** + * @type {Array} + */ + this.mousePositionProjections = [{ + code: EPSG2056, + label: 'CH1903+ / LV95', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: EPSG21781, + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + // Allow angular-gettext-tools to collect the strings to translate + /** @type {angular.gettext.gettextCatalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + gettextCatalog.getString('Add a theme'); + gettextCatalog.getString('Add a sub theme'); + gettextCatalog.getString('Add a layer'); + } +} + +/** + * @hidden + */ +const module = angular.module('Appoeedit', [ + geoportailv3Base.name, + gmfControllersAbstractDesktopController.name, + gmfObjecteditingModule.name, +]); + +module.value('gmfContextualdatacontentTemplateUrl', 'gmf/contextualdata'); +module.run( + /** + * @ngInject + * @param {angular.ITemplateCacheService} $templateCache + */ + ($templateCache) => { + // @ts-ignore: webpack + $templateCache.put('gmf/contextualdata', require('./contextualdata.html')); + }); + +module.value('gmfPermalinkOptions', /** @type {import('gmf/permalink/Permalink.js').PermalinkOptions} */ ({ + pointRecenterZoom: 10 +})); + +module.controller('OEEditController', Controller); + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/contextualdata.html b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/contextualdata.html new file mode 100644 index 000000000..59246b9d0 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/contextualdata.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Swiss grid (LV95) + + {{coord_2056|ngeoNumberCoordinates:0:'{x} / {y}'}} +
+ Swiss grid (LV03) + + {{coord_21781|ngeoNumberCoordinates:0:'{x} / {y}'}} +
+ Wgs Coord. + + {{coord_4326|ngeoNumberCoordinates:2:'{y} / {x}'}} +
+ Wgs Coord. DMS + + {{coord_4326|ngeoDMSCoordinates:0:'{y} {x}'}} +
+ Elevation (SRTM) + + {{srtm | number}} [m] +
+ Elevation (Aster) + + {{aster | number}} [m] +
+Google StreetView diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/desktop.html.ejs b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/desktop.html.ejs new file mode 100644 index 000000000..a67d4b493 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/desktop.html.ejs @@ -0,0 +1,346 @@ + + + + GeoMapFish + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + + +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + +
+
+ +
+ +
+
+
+ +
+
+
+ + + + + + + + +
+
+
+ + + +
+
+
+
+
+ {{'Login' | translate}} + × +
+ +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + + {{'Loading themes, please wait...' | translate}} +
+
+
+
+
+
+ {{'Print' | translate}} + × +
+ + +
+
+
+
+
+ {{'Draw and Measure'|translate}} + × +
+ + +
+
+
+
+
+ {{'Filter'|translate}} + × +
+ + +
+
+
+
+
+ {{'Editing'|translate}} + × +
+
+
+ {{'In order to use the editing tool, you must log in first.' | translate}} +
+ + +
+
+
+
+
+
+ {{'Profile'|translate}} + × +
+
+

+ +

+

+ + Draw a line on the map to display the corresponding elevation profile. + Use double-click to finish the drawing. + +

+
+
+
+
+
+
+ {{'Selection'|translate}} + × +
+ +
+
+
+
+
+ {{'Import Layer'|translate}} + × +
+ + +
+
+
+
+
+ + + + +
+ + +
+
+ + + +
+
+ + +
+ + +
+ + + + + + + +
+ + + +
+
+ + +
+ + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/desktop_alt.html.ejs b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/desktop_alt.html.ejs new file mode 100644 index 000000000..faa889321 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/desktop_alt.html.ejs @@ -0,0 +1,407 @@ + + + + GeoMapFish + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + + +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + +
+
+ +
+ +
+
+
+
+ +
+ + +
+
+
+
+
+ + + + + + + + + + +
+
+
+ + + +
+
+
+
+
+ {{'Login' | translate}} + × +
+ + +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + + {{'Loading themes, please wait...' | translate}} +
+
+
+
+
+
+ {{'Print' | translate}} + × +
+ + +
+ +
+
+
+
+
+
+
+
+ {{'Draw and Measure'|translate}} + × +
+ + +
+
+
+
+
+ {{'Filter'|translate}} + × +
+ + +
+
+
+
+
+ {{'Editing'|translate}} + × +
+
+
+ {{'In order to use the editing tool, you must log in first.' | translate}} +
+ + +
+
+
+
+
+
+ {{'Profile'|translate}} + × +
+
+

+ +

+

+ + Draw a line on the map to display the corresponding elevation profile. + Use double-click to finish the drawing. + +

+
+
+
+
+
+
+ {{'Street View'|translate}} + × +
+ + +
+
+
+
+
+ {{'Selection'|translate}} + × +
+ +
+
+
+
+
+ {{'Import Layer'|translate}} + × +
+ + +
+
+
+
+
+ {{'Routing'|translate}} + × +
+ + +
+
+
+
+
+ + + + +
+ +
+
+ + + +
+
+ + +
+
+ + + + + + + + + +
+ + + + + + + + +
+
+ + + + + +
+ + + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/iframe_api.html.ejs b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/iframe_api.html.ejs new file mode 100644 index 000000000..f19714d8b --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/iframe_api.html.ejs @@ -0,0 +1,83 @@ + + + + GeoMapFish + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + + +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + +
+
+
+
+ +
+
+ + + +
+
+ + +
+ + +
+ + + + +
+ + +
+ + + +
+ + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/background-layer-button.png b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/background-layer-button.png new file mode 100644 index 000000000..46767ce30 Binary files /dev/null and b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/background-layer-button.png differ diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/favicon.ico b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/favicon.ico new file mode 100644 index 000000000..2eb150037 Binary files /dev/null and b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/favicon.ico differ diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/logo.png b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/logo.png new file mode 100644 index 000000000..a07d43d5b Binary files /dev/null and b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/logo.png differ diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/logo.svg b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/logo.svg new file mode 100644 index 000000000..e211bc9e7 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/image/logo.svg @@ -0,0 +1,104 @@ + + + +image/svg+xml diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/mobile.html.ejs b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/mobile.html.ejs new file mode 100644 index 000000000..e8ab8846c --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/mobile.html.ejs @@ -0,0 +1,202 @@ + + + + GeoMapFish + + + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + + + +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + +
+
+ + + + + + + + + + +
+
+
+
+
+
+ + + + +
+
+
+ + +
+ + +
+
+ + + + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/mobile_alt.html.ejs b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/mobile_alt.html.ejs new file mode 100644 index 000000000..80a6628b8 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/mobile_alt.html.ejs @@ -0,0 +1,191 @@ + + + + GeoMapFish + + + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + + +
+ + <%=require('gmf/icons/spinner.svg?viewbox&height=1em')%> + +
+
+ + + + + + + + + +
+
+
+
+ + + + +
+
+
+ + +
+ + +
+
+ + + + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/oeedit.html.ejs b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/oeedit.html.ejs new file mode 100644 index 000000000..e97a918ee --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/oeedit.html.ejs @@ -0,0 +1,182 @@ + + + + GeoMapFish + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + + +
+ +
+ +
+
+
+ +
+
+
+ + +
+
+
+
+
+
+ {{'Query' | translate}} + × +
+ Query +
+
+
+
+
+ {{'Object Editing' | translate}} + × +
+ + +
+
+
+
+
+
+ + +
+
+ + + +
+
+ + +
+ + +
+ + + + + + + +
+ + + +
+
+ + +
+ + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/desktop.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/desktop.scss new file mode 100644 index 000000000..7f141fbd0 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/desktop.scss @@ -0,0 +1,17 @@ +header { + .logo { + background-image: url('../image/logo.png'); + span { + left: 19.5rem; + position: absolute; + bottom: 0.2rem; + } + span::before { + content: "by Camptocamp"; + } + } +} + +.offset-info-icon { + position: absolute; +} diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/desktop_alt.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/desktop_alt.scss new file mode 100644 index 000000000..9303b6d21 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/desktop_alt.scss @@ -0,0 +1,39 @@ +header { + .logo { + background-image: url('../image/logo.svg'); + span { + left: 18.5rem; + position: absolute; + bottom: 0.2rem; + } + span::before { + content: "by Camptocamp"; + } + } +} + +.gmf-theme-selector li { + flex-direction: column; + span.gmf-text { + width: auto; + } +} +.gmf-theme-selector .gmf-thumb { + height: 3rem; +} + +.gmf-layertree-node .gmf-layertree-legend { + border: none; + background-color: transparent; +} + +div .ngeo-displaywindow { + $displaywindow-min-height: 15rem; + left: $app-margin + $left-panel-width + $displaywindow-min-height / 2; + right: initial; + top: $topbar-height + $app-margin + 3 * $map-tools-size; +} + +.offset-info-icon { + position: absolute; +} diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/mobile.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/mobile.scss new file mode 100644 index 000000000..e1eff6553 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/mobile.scss @@ -0,0 +1,8 @@ +gmf-displayquerywindow { + position: inherit; + + .spinner-window { + position: inherit; + right: 65px; + } + } diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/mobile_alt.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/mobile_alt.scss new file mode 100644 index 000000000..a7b06610b --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/mobile_alt.scss @@ -0,0 +1,18 @@ +#themes .gmf-theme-selector { + display: flex; + flex-wrap: wrap; + + li { + flex-direction: column; + flex-basis: 50%; + } +} + +gmf-displayquerywindow { + position: inherit; + + .spinner-window { + position: inherit; + right: 65px; + } +} diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/oeedit.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/oeedit.scss new file mode 100644 index 000000000..26702abb5 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/oeedit.scss @@ -0,0 +1,26 @@ +header { + .logo { + background-image: url('../image/logo.png'); + span { + left: 19.5rem; + position: absolute; + bottom: 0.2rem; + } + span::before { + content: "by Camptocamp"; + } + } +} + +.gmf-displayquerywindow { + width: 22.50rem; + max-width: 22.50rem; +} + +.gmf-displayquerywindow .details { + overflow-x: auto; +} + +::-webkit-scrollbar { + height: $half-app-margin; +} diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_desktop.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_desktop.scss new file mode 100644 index 000000000..8337712ea --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_desktop.scss @@ -0,0 +1 @@ +// diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_desktop_alt.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_desktop_alt.scss new file mode 100644 index 000000000..ef864fad9 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_desktop_alt.scss @@ -0,0 +1,5 @@ +$brand-primary: #9FB6CC; +$brand-secondary: #D3DBE3; + +$theme-selector-columns: 3; +$theme-selector-column-width: 8rem; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_mobile.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_mobile.scss new file mode 100644 index 000000000..8337712ea --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_mobile.scss @@ -0,0 +1 @@ +// diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_mobile_alt.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_mobile_alt.scss new file mode 100644 index 000000000..8337712ea --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_mobile_alt.scss @@ -0,0 +1 @@ +// diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_oeedit.scss b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_oeedit.scss new file mode 100644 index 000000000..8337712ea --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/sass/vars_oeedit.scss @@ -0,0 +1 @@ +// diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/geoportailv3module.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/geoportailv3module.js new file mode 100644 index 000000000..e6c7e4911 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static-ngeo/js/geoportailv3module.js @@ -0,0 +1,22 @@ +/** + * This file provides the "geoportailv3" namespace, which is the + * application's main namespace. And it defines the application's Angular + * module. + */ +import {decodeQueryString} from 'ngeo/utils.js'; +import angular from 'angular'; + +/** + * @type {!angular.IModule} + */ +const module = angular.module('geoportailv3', []); + +module.config(['$compileProvider', function($compileProvider) { + if (!('debug' in decodeQueryString(window.location.search))) { + // Disable the debug info + $compileProvider.debugInfoEnabled(false); + } +}]); + + +export default module; diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/data.txt b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/data.txt new file mode 100644 index 000000000..a2ae02a0b --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/data.txt @@ -0,0 +1,6 @@ +id point title description icon iconSize iconOffset +1 1216300,2553000 Information Office de l'information
Tél: 032 000 00 00
Email: info@example.com
Internet: Cliquer ici http://dev.openlayers.org/releases/OpenLayers-2.13.1/img/marker.png 21,25 -10.5,-25 +2 1215600,2554250 Ma première station Diesel pas cher http://dev.openlayers.org/releases/OpenLayers-2.13.1/img/marker-blue.png 21,25 -10.5,-25 +3 1215864,2552556 Mon parking C'est celui-là le meilleur. http://dev.openlayers.org/releases/OpenLayers-2.13.1/img/marker-gold.png 21,25 -10.5,-25 +4 1217126,2554489 Mon parking Ce parking est
le meillleur. http://dev.openlayers.org/releases/OpenLayers-2.13.1/img/marker-gold.png 21,25 -10.5,-25 +5 1217326,2554089 Ma deuxième station Sans-plomb pas cher. http://dev.openlayers.org/releases/OpenLayers-2.13.1/img/marker-blue.png 21,25 -10.5,-25 diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/github.css b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/github.css new file mode 100644 index 000000000..088f06575 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/github.css @@ -0,0 +1,88 @@ +/** + * GitHub theme + * + * @author Craig Campbell + * @version 1.0.4 + */ +pre { + border: 1px solid #ccc; + word-wrap: break-word; + padding: 6px 10px; + line-height: 19px; + margin-bottom: 20px; +} + +code { + border: 1px solid #eaeaea; + margin: 0px 2px; + padding: 0px 5px; + font-size: 12px; +} + +pre code { + border: 0px; + padding: 0px; + margin: 0px; + -moz-border-radius: 0px; + -webkit-border-radius: 0px; + border-radius: 0px; +} + +pre, code { + font-family: Consolas, 'Liberation Mono', Courier, monospace; + color: #333; + background: #f8f8f8; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} + +pre, pre code { + font-size: 13px; +} + +pre .comment { + color: #998; +} + +pre .support { + color: #0086B3; +} + +pre .tag, pre .tag-name { + color: navy; +} + +pre .keyword, pre .css-property, pre .vendor-prefix, pre .sass, pre .class, pre .id, pre .css-value, pre .entity.function, pre .storage.function { + font-weight: bold; +} + +pre .css-property, pre .css-value, pre .vendor-prefix, pre .support.namespace { + color: #333; +} + +pre .constant.numeric, pre .keyword.unit, pre .hex-color { + font-weight: normal; + color: #099; +} + +pre .entity.class { + color: #458; +} + +pre .entity.id, pre .entity.function { + color: #900; +} + +pre .attribute, pre .variable { + color: teal; +} + +pre .string, pre .support.value { + font-weight: normal; + color: #d14; +} + +pre .regexp { + color: #009926; +} diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/essence.png b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/essence.png new file mode 100644 index 000000000..18877a8ac Binary files /dev/null and b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/essence.png differ diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/info.png b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/info.png new file mode 100644 index 000000000..7fc771ff0 Binary files /dev/null and b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/info.png differ diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/parking.png b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/parking.png new file mode 100644 index 000000000..222e735de Binary files /dev/null and b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/img/parking.png differ diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/index.html.tmpl b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/index.html.tmpl new file mode 100644 index 000000000..4318e110f --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/index.html.tmpl @@ -0,0 +1,236 @@ + + + + + API description + + + + + + + +
+

Simple API Help

+

+ This page describes how to use the Simple API. The Simple API + provides a JavaScript API for inserting simple maps into web pages. +

+

Basis

+

To use the API you should add the following HTML:

+

+<link href="https://geomapfish-demo-2-5.camptocamp.com/api.css" rel="stylesheet">
+<script src="https://geomapfish-demo-2-5.camptocamp.com/api.js?version=2"></script>
+<script>
+window.onload = function() {
+    // add the code here
+};
+</script>
+            
+

To put a new map in the page you'll have to put a div element with a + certain id where you want your map to be: +

<div id='map1' style='width:700px;height:400px;'></div>
+ +
+

A map

+
+
+const map1 = new geoportailv3.Map({
+    div: 'map1', // id of the div element to put the map in
+    zoom: 4,
+    center: [2544500, 1210100]
+});
+                    
+
+ +
+

A map with a marker on its center

+
+
+const map2 = new geoportailv3.Map({
+    div: 'map2',
+    zoom: 7,
+    backgroundLayers: ['OSM map'],
+    center: [2544500, 1210100]
+});
+map2.addMarker();
+                    
+
+ +
+

A map with several custom markers

+
+
+const map3 = new geoportailv3.Map({
+    div: 'map3',
+    zoom: 7,
+    center: [2544500, 1210100]
+});
+map3.addMarker({
+    position: [2544410, 1210100],
+    size: [14, 14],
+    icon: '../static/${CACHE_VERSION}/apihelp/img/info.png'
+});
+map3.addMarker({
+    position: [2544450, 1210000],
+    size: [18, 18],
+    icon: '../static/${CACHE_VERSION}/apihelp/img/essence.png'
+});
+map3.addMarker({
+    position: [2544310, 1210200],
+    size: [14, 14],
+    icon: '../static/${CACHE_VERSION}/apihelp/img/parking.png'
+});
+                    
+
+ +
+

A map with a subset of overlays

+
+
+const map4 = new geoportailv3.Map({
+    div: 'map4',
+    zoom: 0,
+    center: [2590000, 1170000],
+    layers: ['ch.astra.hauptstrassennetz', 'polygon', 'point']
+});
+                    
+
+ +
+

A map with some additional controls

+
+
+const map5 = new geoportailv3.Map({
+    div: 'map5',
+    zoom: 3,
+    center: [2544500, 1210100],
+    layers: ['osm_open'],
+    addLayerSwitcher: true,
+    addMiniMap: true,
+    miniMapExpanded: true,
+    showCoords: true
+});
+                    
+
+ +
+

Recenter the map to given coordinates

+ + +
+
+
+const map6 = new geoportailv3.Map({
+    div: 'map6',
+    addMiniMap: true,
+    miniMapExpanded: false
+});
+const button1 = document.getElementById('button1');
+button1.onclick = function() {
+    map6.recenter([2543500, 1202154], 7);
+}
+const button2 = document.getElementById('button2');
+button2.onclick = function() {
+    map6.recenter([2564500, 1216100], 9);
+}
+                    
+
+ +
+

Recenter the map on objects

+
+
+const map7 = new geoportailv3.Map({
+    div: 'map7',
+    layers: ['polygon']
+});
+map7.recenterOnObjects(
+    /* the layer name */
+    'polygon',
+    /* the ids of the objects */
+    ['94', '125'],
+    /* whether to highlight the objects or not */
+    true
+);
+                    
+
+ +
+

Load data from a text file

+ See data.txt. +
+
+
+const map8 = new geoportailv3.Map({
+    div: 'map8'
+});
+map8.addCustomLayer('text', 'My custom txt layer', '../static/${CACHE_VERSION}/apihelp/data.txt', {
+  success: function() {
+    map8.selectObject(2);
+  }
+});
+                    
+
+ +
+

Search input

+
+
+
+const map9 = new geoportailv3.Map({
+    div: 'map9',
+    zoom: 3,
+    center: [2544500, 1210100],
+    searchDiv: 'map9search'
+});
+                    
+
+ + +
+ + + diff --git a/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/rainbow-custom.min.js b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/rainbow-custom.min.js new file mode 100644 index 000000000..7c33d1cd3 --- /dev/null +++ b/CONST_create_template/geoportal/geoportailv3_geoportal/static/apihelp/rainbow-custom.min.js @@ -0,0 +1,11 @@ +/* Rainbow v1.1.8 rainbowco.de | included languages: generic, javascript, html */ +window.Rainbow=function(){function q(a){var b,c=a.getAttribute&&a.getAttribute("data-language")||0;if(!c){a=a.attributes;for(b=0;b=e[d][c])delete e[d][c],delete j[d][c];if(a>=c&&ac&&b'+b+""}function s(a,b,c,h){var f=a.exec(c);if(f){++t;!b.name&&"string"==typeof b.matches[0]&&(b.name=b.matches[0],delete b.matches[0]);var k=f[0],i=f.index,u=f[0].length+i,g=function(){function f(){s(a,b,c,h)}t%100>0?f():setTimeout(f,0)};if(C(i,u))g();else{var m=v(b.matches),l=function(a,c,h){if(a>=c.length)h(k);else{var d=f[c[a]];if(d){var e=b.matches[c[a]],i=e.language,g=e.name&&e.matches? +e.matches:e,j=function(b,d,e){var i;i=0;var g;for(g=1;g/g,">").replace(/&(?![\w\#]+;)/g, +"&"),b,c)}function o(a,b,c){if(b { + promises.push(new Promise((resolve) => { + fs.readFile(input, 'utf-8', (error, content) => { + resolve(error ? undefined : {input, content}); + }); + })); + }); + + const messages = []; + Promise.all(promises).then((contents) => { + contents = contents.filter(content => content !== undefined); + contents.forEach(({input, content}) => extractor.parse(input, content)); + for (const msgstr in extractor.strings) { + if (extractor.strings.hasOwnProperty(msgstr)) { + const msg = extractor.strings[msgstr]; + const contexts = Object.keys(msg).sort(); + const ref = msg[contexts]['references'].join(', '); + messages.push([ref, msgstr]); + } + } + process.stdout.write(JSON.stringify(messages)); + }); +} + +// If running this module directly then call the main function. +if (require.main === module) { + options.parse(process.argv); + main(options.args); +} + +module.exports = main; diff --git a/CONST_create_template/geoportal/tsconfig.json b/CONST_create_template/geoportal/tsconfig.json new file mode 100644 index 000000000..9d41fde6a --- /dev/null +++ b/CONST_create_template/geoportal/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "module": "system", + "lib": ["es2017", "dom"], + }, + "include": [ + "geoportailv3_geoportal/static-ngeo/js/**/*.js", + ], +} diff --git a/CONST_create_template/geoportal/vars.yaml b/CONST_create_template/geoportal/vars.yaml new file mode 100644 index 000000000..107399c7a --- /dev/null +++ b/CONST_create_template/geoportal/vars.yaml @@ -0,0 +1,224 @@ +--- + +extends: CONST_vars.yaml + +vars: + + srid: 2056 + + # The application's default language. This is the language used by + # the application if no specific language is specified in the URLs. + # This also defines the language used for the text search. + default_locale_name: fr + + # The set of languages supported by the applications. + available_locale_names: + - en + - fr + - de + + # All the application interfaces used to create the apache rewrite rules + interfaces: + - name: desktop + default: True + - name: mobile + - name: iframe_api + + interfaces_config: + default: + constants: + defaultTheme: Demo + defaultLang: '{default_locale_name}' + ngeoWfsPermalinkOptions: + wfsTypes: + - featureType: fuel + label: display_name + - featureType: osm_scale + label: display_name + desktop_alt: + constants: + ngeoWfsPermalinkOptions: + wfsTypes: + - featureType: osm_hospitals + label: name + - featureType: osm_firestations + label: name + defaultFeatureNS: http://www.qgis.org/gml + defaultFeaturePrefix: feature + routes: + ngeoPermalinkOgcserverUrl: + name: mapserverproxy + params: + ogcserver: QGIS server + + admin_interface: + # Default values for the admin interface's maps. + map: + baseLayers: + - type_: "OSM" + view: + projection: 'EPSG:3857' + center: [829170, 5933942] + zoom: 7 + fitSource: false + fitMaxZoom: 14 + focusOnly: false + + functionalities: + # Functionalities that are made available to Mako templates. + available_in_templates: + - default_basemap + + layers: + geometry_validation: True + + fulltextsearch: + languages: + fr: french + en: english + de: german + + # proxies: + # http: https://someproxy + + shortener: + # Used to send a confirmation email + email_from: info@example.com + email_subject: "Geoportal URL" + email_body: | + Hello, + + Somebody sent you the following link: + {short_url} + + With the message: + {message} + + Sincerely yours + The GeoMapFish team + + smtp: + # Used to send email from various feature + host: smtp.example.com + ssl: true + user: + password: + starttls: false + + reset_password: + # Used to send a reset password email + email_from: info@camptocamp.com + email_subject: New password generated for GeoMapFish + email_body: | + Hello {user}, + + You have asked for a new password, + the newly generated password is: {password} + + Sincerely yours + The GeoMapFish team + + welcome_email: + # Used to send a welcome email for new user + email_from: info@camptocamp.com + email_subject: Welcome to GeoMapFish + email_body: | + Hello {user}, + + You have a new account on GeoMapFish: https://geomapfish-demo-2-5.camptocamp.com + Your user name is: {user} + Your password is: {password} + + Sincerely yours + The GeoMapFish team + + # Checker configuration + checker: + fulltextsearch: + search: text to search + # print: + # spec: + # layout: "1 A4 portrait" + # outputFormat: "pdf" + # attributes: + # title: "" + # comments: "" + # datasource: [] + # map: + # projection: "EPSG:2056" + # dpi: 254 + # rotation: 0 + # center: [2600000, 1200000] + # scale: 100000 + # longitudeFirst: true + # layers: [] + # legend: {} + phantomjs: + disable: [apihelp] + + check_collector: + hosts: [] + # - display: Child: + # url: {web_protocol}://{host}/child/wsgi + +update_paths: + - admin_interface.available_functionalities + - admin_interface.available_metadata + - admin_interface.functionalities + - admin_interface.available_in_templates + - api + - authorized_referers + - cache.std.arguments + - cache.obj + - check_collector.disabled + - check_collector.hosts + - checker.fulltextsearch + - checker.lang + - checker.phantomjs + - checker.print + - checker.routes + - checker.themes + - content_security_policy.main + - content_security_policy.admin + - content_security_policy.apihelp + - fulltextsearch + - functionalities.available_in_templates + - global_headers + - headers.index + - headers.api + - headers.profile + - headers.raster + - headers.error + - headers.themes + - headers.config + - headers.print + - headers.fulltextsearch + - headers.mapserver + - headers.tinyows + - headers.layers + - headers.shortener + - headers.login + - interfaces_config.default.constants.ngeoWfsPermalinkOptions + - interfaces_config.default.dynamic_constants + - interfaces_config.default.static + - interfaces_config.default.routes + - interfaces_config.desktop.constants + - interfaces_config.desktop.routes + - interfaces_config.desktop_alt.constants + - interfaces_config.desktop_alt.routes + - interfaces_config.mobile.constants + - interfaces_config.mobile_alt.constants + - interfaces_config.iframe_api.constants + - interfaces_config.oeedit.routes + - interfaces_theme + - resourceproxy + - servers + - shortener.allowed_hosts + - sqlalchemy + - sqlalchemy_slave + - tinyowsproxy + +no_interpreted: + - reset_password.email_body + - shortener.email_body + - welcome_email.email_body diff --git a/CONST_create_template/geoportal/webpack.api.js b/CONST_create_template/geoportal/webpack.api.js new file mode 100644 index 000000000..b675d387e --- /dev/null +++ b/CONST_create_template/geoportal/webpack.api.js @@ -0,0 +1,71 @@ +const path = require('path'); +const TerserPlugin = require('terser-webpack-plugin'); + +const destDir = '/etc/static-ngeo/'; + +const babelPresets = [[require.resolve('@babel/preset-env'), { + targets: { + browsers: ['> 0.5% in CH', '> 0.5% in FR', 'Firefox ESR', 'ie 11'], + }, + modules: false, + loose: true +}]]; + +module.exports = (env, argv) => { + const library = argv.library ? argv.library : 'geoportailv3'; + return { + entry: path.resolve(__dirname, 'geoportailv3_geoportal/static-ngeo/api/index.js'), + devtool: 'source-map', + mode: 'production', + module: { + rules: [{ + test: /\.js$/, + use: { + loader: 'babel-loader', + options: { + presets: babelPresets, + babelrc: false, + comments: false, + plugins: [ + require.resolve('@babel/plugin-syntax-object-rest-spread'), + require.resolve('@babel/plugin-transform-spread'), + require.resolve('@camptocamp/babel-plugin-angularjs-annotate'), + ] + } + } + }] + }, + output: { + filename: 'api.js', + path: destDir, + libraryTarget: 'umd', + globalObject: 'this', + libraryExport: 'default', + library: library + }, + optimization: { + minimizer: [ + new TerserPlugin({ + parallel: true, + sourceMap: true, + terserOptions: { + compress: false + } + }) + ] + }, + resolve: { + modules: [ + '/usr/lib/node_modules', + '/usr/lib/node_modules/ol/node_modules', + '/usr/lib/node_modules/proj4/node_modules', + ], + alias: { + api: '/usr/lib/node_modules/ngeo/api/src', + } + }, + resolveLoader: { + modules: ['/usr/lib/node_modules'], + } + }; +}; diff --git a/CONST_create_template/geoportal/webpack.apps.js b/CONST_create_template/geoportal/webpack.apps.js new file mode 100644 index 000000000..ceb7551c7 --- /dev/null +++ b/CONST_create_template/geoportal/webpack.apps.js @@ -0,0 +1,89 @@ +const path = require('path'); +const ls = require('ngeo/buildtools/ls.js'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); + +const plugins = []; +const entry = {}; + +// The dev mode will be used for builds on local machine outside docker +const nodeEnv = process.env['NODE_ENV'] || 'development'; +const dev = nodeEnv == 'development' + +for (const filename of ls(path.resolve(__dirname, 'geoportailv3_geoportal/static-ngeo/js/apps/*.html.ejs'))) { + const name = filename.file.substr(0, filename.file.length - '.html.ejs'.length); + entry[name] = 'geoportailv3/apps/Controller' + name + '.js'; + plugins.push( + new HtmlWebpackPlugin({ + template: filename.full, + inject: false, + chunksSortMode: 'manual', + filename: name + '.html', + chunks: [name], + vars: { + entry_point: '${VISIBLE_ENTRY_POINT}', + version: '2.5.0.139', + cache_version: '${CACHE_VERSION}', + }, + }) + ); +} + +const babelPresets = [[require.resolve('@babel/preset-env'), { + targets: { + browsers: ['> 0.5% in CH', '> 0.5% in FR', 'Firefox ESR', 'ie 11'], + }, + modules: false, + loose: true, +}]] + +// Transform code to ES2015 and annotate injectable functions with an $inject array. +const projectRule = { + test: /geoportailv3_geoportal\/static-ngeo\/js\/.*\.js$/, + use: { + loader: 'babel-loader', + options: { + presets: babelPresets, + babelrc: false, + comments: false, + plugins: [ + require.resolve('@babel/plugin-syntax-object-rest-spread'), + require.resolve('@babel/plugin-transform-spread'), + require.resolve('@camptocamp/babel-plugin-angularjs-annotate'), + ], + } + }, +}; + +const rules = [ + projectRule, +]; + +const noDevServer = process.env['NO_DEV_SERVER'] == 'TRUE'; +const devServer = dev && !noDevServer; + +console.log("Use dev mode: " + dev) +console.log("Use dev server mode: " + devServer) + +module.exports = { + output: { + path: '/etc/static-ngeo/', + publicPath: devServer ? '${VISIBLE_ENTRY_POINT}dev/' : '.__ENTRY_POINT__static-ngeo/' + }, + devServer: { + publicPath: '${VISIBLE_WEB_PROTOCOL}://${VISIBLE_WEB_HOST}${VISIBLE_ENTRY_POINT}dev/', + port: 8080, + host: 'webpack_dev_server', + hot: true, + }, + entry: entry, + module: { + rules + }, + plugins: plugins, + resolve: { + modules: ['/usr/lib/node_modules'], + alias: { + geoportailv3: path.resolve(__dirname, 'geoportailv3_geoportal/static-ngeo/js'), + }, + }, +}; diff --git a/CONST_create_template/geoportal/webpack.commons.js b/CONST_create_template/geoportal/webpack.commons.js new file mode 100644 index 000000000..7b5d7b66d --- /dev/null +++ b/CONST_create_template/geoportal/webpack.commons.js @@ -0,0 +1,21 @@ +const commons = require('ngeo/buildtools/webpack.commons.js'); +const SassPlugin = require('ngeo/buildtools/webpack.plugin.js'); + +const config = commons({ + DllReferencePluginOptions: { + context: '/usr/lib/', + } +}); + +for (const plugin of config.plugins) { + if (plugin instanceof SassPlugin) { + plugin.options.preReplacements = [ + [new RegExp('\\${VISIBLE_ENTRY_POINT}', 'g'), 'visible-entry-point'], + ]; + plugin.options.postReplacements = [ + [new RegExp('visible-entry-point', 'g'), '${VISIBLE_ENTRY_POINT}'], + ]; + } +} + +module.exports = () => config; diff --git a/CONST_create_template/geoportal/webpack.config.js b/CONST_create_template/geoportal/webpack.config.js new file mode 100644 index 000000000..ef801de07 --- /dev/null +++ b/CONST_create_template/geoportal/webpack.config.js @@ -0,0 +1,22 @@ +const webpackMerge = require('webpack-merge'); +const apps = require('./webpack.apps.js'); +const commons = require('./webpack.commons.js'); + +let config = commons(); + +const nodeEnv = process.env['NODE_ENV'] || 'development'; +switch (nodeEnv) { + case 'development': + config = webpackMerge(config, require('ngeo/buildtools/webpack.dev')()); + break; + case 'production': + config = webpackMerge(config, require('ngeo/buildtools/webpack.prod')()); + break; + default: + console.log(`The 'NODE_ENV' environment variable is set to an invalid value: ${process.env.NODE_ENV}.`); + process.exit(2); +} + +config = webpackMerge(config, apps); + +module.exports = config; diff --git a/CONST_create_template/mapserver/data/Readme.txt b/CONST_create_template/mapserver/data/Readme.txt new file mode 100644 index 000000000..64d3aead5 --- /dev/null +++ b/CONST_create_template/mapserver/data/Readme.txt @@ -0,0 +1,69 @@ +TM_WORLD_BORDERS-0.1.ZIP + +Provided by Bjorn Sandvik, thematicmapping.org + +Use this dataset with care, as several of the borders are disputed. + +The original shapefile (world_borders.zip, 3.2 MB) was downloaded from the Mapping Hacks website: +https://www.mappinghacks.com/data/ + +The dataset was derived by Schuyler Erle from public domain sources. +Sean Gilles did some clean up and made some enhancements. + + +COLUMN TYPE DESCRIPTION + +Shape Polygon Country/area border as polygon(s) +FIPS String(2) FIPS 10-4 Country Code +ISO2 String(2) ISO 3166-1 Alpha-2 Country Code +ISO3 String(3) ISO 3166-1 Alpha-3 Country Code +UN Short Integer(3) ISO 3166-1 Numeric-3 Country Code +NAME String(50) Name of country/area +AREA Long Integer(7) Land area, FAO Statistics (2002) +POP2005 Double(10,0) Population, World Polulation Prospects (2005) +REGION Short Integer(3) Macro geographical (continental region), UN Statistics +SUBREGION Short Integer(3) Geogrpahical sub-region, UN Statistics +LON FLOAT (7,3) Longitude +LAT FLOAT (6,3) Latitude + + +CHANGELOG VERSION 0.3 - 30 July 2008 + +- Corrected spelling mistake (United Arab Emirates) +- Corrected population number for Japan +- Adjusted long/lat values for India, Italy and United Kingdom + + +CHANGELOG VERSION 0.2 - 1 April 2008 + +- Made new ZIP archieves. No change in dataset. + + +CHANGELOG VERSION 0.1 - 13 March 2008 + +- Polygons representing each country were merged into one feature +- land Islands was extracted from Finland +- Hong Kong was extracted from China +- Holy See (Vatican City) was added +- Gaza Strip and West Bank was merged into "Occupied Palestinean Territory" +- Saint-Barthelemy was extracted from Netherlands Antilles +- Saint-Martin (Frensh part) was extracted from Guadeloupe +- Svalbard and Jan Mayen was merged into "Svalbard and Jan Mayen Islands" +- Timor-Leste was extracted from Indonesia +- Juan De Nova Island was merged with "French Southern & Antarctic Land" +- Baker Island, Howland Island, Jarvis Island, Johnston Atoll, Midway Islands + and Wake Island was merged into "United States Minor Outlying Islands" +- Glorioso Islands, Parcel Islands, Spartly Islands was removed + (almost uninhabited and missing ISO-3611-1 code) + +- Added ISO-3166-1 codes (alpha-2, alpha-3, numeric-3). Source: + https://www.cia.gov/library/publications/the-world-factbook/appendix/appendix-d.html + https://unstats.un.org/unsd/methods/m49/m49alpha.htm + https://www.fysh.org/~katie/development/geography.txt +- AREA column has been replaced with data from UNdata: + Land area, 1000 hectares, 2002, FAO Statistics +- POPULATION column (POP2005) has been replaced with data from UNdata: + Population, 2005, Medium variant, World Population Prospects: The 2006 Revision +- Added region and sub-region codes from UN Statistics Division. Source: + https://unstats.un.org/unsd/methods/m49/m49regin.htm +- Added LAT, LONG values for each country diff --git a/CONST_create_template/mapserver/data/TM_EUROPE_BORDERS-0.3.sql b/CONST_create_template/mapserver/data/TM_EUROPE_BORDERS-0.3.sql new file mode 100644 index 000000000..dd1cb2b20 --- /dev/null +++ b/CONST_create_template/mapserver/data/TM_EUROPE_BORDERS-0.3.sql @@ -0,0 +1,70 @@ +SET CLIENT_ENCODING TO UTF8; +SET STANDARD_CONFORMING_STRINGS TO ON; +SELECT DropGeometryColumn('data','europe_borders','geom'); +DROP TABLE "data"."europe_borders"; +BEGIN; +CREATE TABLE "data"."europe_borders" (gid serial, +"fips" varchar(2), +"iso2" varchar(2), +"iso3" varchar(3), +"un" int4, +"name" varchar(50), +"area" numeric, +"pop2005" numeric, +"region" int4, +"subregion" int4, +"lon" numeric, +"lat" numeric); +ALTER TABLE "data"."europe_borders" ADD PRIMARY KEY (gid); +SELECT AddGeometryColumn('data','europe_borders','geom','4326','MULTIPOLYGON',2); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('AL','AL','ALB','8','Albania','2740','3153731','150','39','20.068','41.143','0106000020E61000000100000001030000000100000051010000AE0E80B8AB6F33408D0B0742B2824440FD14C78157733340A7E9B303AE874440A9DDAF027C833340514F1F813FA04440ABE7A4F78D833340F92F1004C8A04440D0D03FC1C5823340FBE769C020A34440D53DB2B96A8233407C6308008EA344407AABAE4335813340A8716F7EC3A444402B69C537147E3340AB5FE97C78A64440D0420246977B3340AC5626FC52A74440A7E9B303AE773340FED2A23EC9A744407E9065C1C4733340520ABABDA4A74440FF93BF7B47713340D7A6B1BD16B44440A304FD851E853340295C8FC2F5C8444051C1E10511913340AB984A3FE1CA4440CF488446B0953340530438BD8BCD444079AEEFC341963340D4EE5701BED14440BF9B6ED921923340677FA0DCB6D744404DD6A8876894334000CADFBDA3D8444024809BC58B9533407D5D86FF74D9444052465C001A993340FD4AE7C3B3E244407E8AE3C0AB993340543A58FFE7E444400473F4F8BD993340D47FD6FCF8E54440D3C1FA3F87993340FDDB65BFEEE6444057B3CEF8BE983340FD4D2844C0E7444001857AFA08983340D38558FD11E84440DA58897956863340419B1C3EE9EA4440276893C3277D3340A7ECF483BAEC4440D63730B951783340FC1A498270ED44400282397AFC7233402AE44A3D0BEE44404DDC2A88816E33405376FA415DEE44407F15E0BBCD6B3340FF9600FC53EE444083F755B95069334052499D8026EE4440CF6A813D265E334019ABCDFFABEC444056BC9179E45733402CD505BCCCF444407D93A641D15833407E54C37E4FFA44407F8461C0925F3340AA656B7D91084540C6FB71FBE55F3340698B6B7C26094540F92F1004C86033407BA2EBC20F0A4540BA6587F887613340BEF8A23D5E0A45405055A18158623340FD4AE7C3B30A454050C422861D663340AA9ECC3FFA0C4540AB5FE97C78663340FD9FC37C790D4540A4FB3905F96533407D96E7C1DD0D45407C992842EA6233407AA52C431C0F45407E8D2441B85E33405401F73C7F104540000341800C553340AA622AFD8413454052B5DD04DF4C33407E1B62BCE61545407D93A641D148334002BB9A3C65174540D63730B951483340FD4D2844C01745404DD9E907754933407B6649809A184540000341800C853340AB5CA8FC6B394540D5AF743E3C9B3340000341800C454540A5F5B704E09B3340FC1A4982704545402CD505BCCC9C334055FB743C66464540AB59677C5F9C3340D0D38041D24745407F15E0BBCD9B3340552E54FEB548454051BEA085049C3340D00F2384474945402DCC423BA79D33405182FE428F4A4540008BFCFA21A233407DCC07043A4D4540D4B5F63E55A533407AA52C431C4F4540514F1F813FA83340FE9C82FC6C504540FD9FC37C79B5334027F6D03E56544540D13FC1C58AB6334029232E008D544540CC5D4BC807B93340A7ECF483BA544540D925AAB706BA3340D3BEB9BF7A5445407E18213CDAC03340276BD44334524540D13C80457EC13340FDD8243FE25145407E1B62BCE6C53340D3BEB9BF7A4C45402AE44A3D0BC63340FCDEA63FFB4B45407B116DC7D4C53340AA622AFD844B454029ED0DBE30C53340FBE769C0204B4540D82B2CB81FC433407E1EA33CF34A454081069B3A8FC23340286211C30E4B4540D04543C6A3C03340A7E67283A14A45400000000000C0334028F04E3E3D4A454084F1D3B837BF3340295FD04202464540FF08C38025BF3340527FBDC282454540A77A32FFE8C333407B6649809A4045402AE44A3D0BC63340520ABABDA43F45404ED026874FCA3340A7AD11C1383E454050C763062ACB3340D3FA5B02F03D4540AD50A4FB39CD3340FD9FC37C793D454081069B3A8FD233407D5A457F683C4540FE99417C60EB334029266F8099414540D4BB783F6EEF3340D4B837BF61424540FB230C03960C34402638F581E44745402DCC423BA70D3440D38558FD1148454004763579CA0E34407EC9C6832D484540FE9C82FC6C103440D38558FD11484540A52E19C7481234405C7347FFCB474540295C8FC2F5183440A7ECF483BA444540FC8F4C874E1B3440D3F4D901D74345408200193A76283440508BC1C3B44145404DD9E9077529344001C11C3D7E41454050C763062A2B3440D3F71A82E3404540A8E0F08288383440A5BC56427737454027F911BF62393440D6AC33BE2F364540027FF8F9EF3D3440556D37C1372F4540D1CDFE40B93D34405628D2FD9C2E454052B5DD04DF3C3440FE47A643A72D45402CD505BCCC3C3440D388997D1E2D454083FA96395D3E3440FC1D8A027D2A454058AD4CF8A53E34407BA2EBC20F2A4540AA656B7D91403440D3C1FA3F8729454052B81E85EB41344027F911BF622945403B014D840D5B344017BA1281EA274540286211C30E633440FDDB65BFEE26454082FDD7B969733440D2C77C40A02345404FCDE50643753440FBE769C020234540EBFD463B6E783440C576F700DD214540AC53E57B46823440FD9FC37C791D4540D6AC33BE2F86344054FEB5BC721B4540FA298E03AF86344029E78BBD171B4540FC17080264983440A8E33103950545407F8461C0929F34407E9065C1C4FB4440A86E2EFEB69F34402B14E97E4EFB444084F1D3B8379F3440D106600322FA444052499D80269E3440A8E0F08288F84440D44334BA839C34407D21E4BCFFF74440FC1708026498344028F38FBE49F74440FA298E03AF9634407E8D2441B8F644404FCDE506439534402AE44A3D0BF64440A8716F7EC3943440A968ACFD9DF5444022895E46B194344052431B800DF44440195932C7F29634406AFAEC80EBF04440C806D2C5A69134403D7D04FEF0EF4440ABEAE5779A88344054FEB5BC72E34440A304FD851E853440D5B2B5BE48E0444027F6D03E56843440556D37C137DF4440D2C77C40A0833440276893C327DD4440D1CABDC0AC883440FE0E45813ED14440AC5626FC527734407AA52C431CC744404FCDE50643753440FE99417C60C3444029ED0DBE307534402635B401D8C24440FD9FC37C79753440A6B915C26AC244407E1B62BCE6753440A9A10DC006C24440514F1F813F783440286552431BC0444057B3CEF8BE783440A86E2EFEB6BF4440276BD443348234402635B401D8BA4440A86E2EFEB68F344051888043A8B444407D21E4BCFF8F3440D00CE2033BB444407A17EFC7ED8F3440282CF180B2B344402CD505BCCC8C3440FD4D2844C0AF4440D6AC33BE2F863440FED5E3BED5AC4440AA656B7D9180344029232E008DAC44404ED367075C7F344001BEDBBC71AC44405340DAFF007F34402BDEC83CF2AB444052499D80267E3440D4B837BF61AA4440A777F17EDC7E3440FCE1E7BF07A94440D04543C6A3803440813FFCFCF7A64440543A58FFE7843440FB20CB82899F444052431B800D943440FED5E3BED59444406D8D08C6C199344027BD6F7CED8B4440A7E9B303AEA734407C6308008E8B4440AA622AFD84AB3440A7B05241458B4440A5F5B704E0BB3440A7ECF483BA74444011AB3FC230BC34405CE509849D744440FD1186014BBE3440FE0B0401327444407E18213CDAC03440D57954FCDF7344405055A18158C234407E9065C1C4734440FC1A498270CD3440514CDE00337344405437177FDBCF3440FD14C78157734440276BD44334D2344027F6D03E5674444059A7CAF78CD434407D96E7C1DD754440266E15C440D734407E5704FF5B774440D82E6D382CD93440FD4D2844C0774440800F5EBBB4F13440FE47A643A7754440000341800CF534407B9FAA420375444001857AFA08F8344056F5F23B4D7444407D93A641D1F8344081423D7D04744440641EF98381FB34409BE7887C97724440A5F5B704E0FB3440D4B837BF617244402BDEC83CF2FB3440D1066003227244406BF12900C6FB3440F984ECBC8D6D4440A5F5B704E0FB3440527FBDC282654440D4B5F63E5505354000C79E3D975B4440D236FE4465073540A7E67283A15A4440717500C45D0935400B992B836A5944402BDEC83CF20B3540FED2A23EC9574440505260014C0D35405628D2FD9C564440A8E33103950D3540D6AC33BE2F5644407D96E7C1DD0D3540A7ECF483BA544440D1CDFE40B90D3540A86E2EFEB64F4440A8E33103950D3540D009A1832E4F44407E1EA33CF30A3540527C7C42764844402383DC45980A3540AA9B8BBFED47444057B08D78B2F3344027F6D03E563C44407C992842EAF2344081423D7D043C44407BA2EBC20FF234407E9065C1C43B44405437177FDBEF344054FEB5BC723B444050C763062AEB344029E78BBD173B4440D925AAB706EA3440A7B05241453B4440D82E6D382CE934407C6308008E3B4440D4B5F63E55D534407F4B00FE293B4440E2EA0088BBCA34400BF148BC3C374440D3C1FA3F87C934408081204086324440276BD44334C23440AA9B8BBFED27444082035ABA82BD34407F8461C092274440F92CCF83BBBB3440A9A44E401327444054C554FA09B7344052431B800D244440D13FC1C58AB63440D2C77C40A023444079AEEFC341B63440286211C30E234440A4FB3905F9B53440823CBB7CEB21444051BB5F05F8B63440D1CABDC0AC204440A8E0F08288B834407F8461C0921F4440D1CABDC0ACB83440D1031F83151D4440ABEAE5779AB8344029232E008D1C4440D44334BA83AC3440AA9ECC3FFA0C444051BEA08504AC344029232E008D0C44404ED026874FAA344052431B800D0C4440514F1F813FA83440282CF180B20B4440D828EB37139F34407C992842EA0A44405534D6FECE9A3440FA264D83A2094440D4B5F63E55953440FCE1E7BF07094440FD1186014B8E34405401F73C7F084440257A19C5727B3440A7B393C151084440FF058200197A3440527C7C427608444032C85D842976344001C11C3D7E094440514CDE0033733440D00F238447094440D5B2B5BE48703440552E54FEB508444051BEA085046C3440D4BB783F6E074440A5F8F884EC503440FF08C38025FF4340AA656B7D91503440508E0244C1FE434050C422861D5634405376FA415DF64340D13FC1C58A563440D47FD6FCF8F5434058AD4CF8A55E3440FF05820019F24340D1CABDC0AC683440520DFB3DB1EC4340D3C1FA3F876934402BDEC83CF2EB43404ED026874F6A3440FBE769C020EB4340FF058200196A3440D3C1FA3F87E94340D3C1FA3F87693440FE9C82FC6CE84340514F1F813F683440813FFCFCF7E643402BDB87BCE5663440FD1186014BE64340A7E67283A1623440253B3602F1E44340FA264D83A2613440A8716F7EC3E44340D5B2B5BE486034402CD505BCCCE44340FF08C380255F3440AA9ECC3FFAE44340705B5B785E4E3440E9BAF083F3E74340D63A71395E4D34402638F581E4E74340257A19C5724B34402920ED7F80E743402383DC45984A3440266E15C440E74340FF058200194A3440D4F19881CAE64340267156444D4C34405534D6FECEE24340AB5CA8FC6B5134407E8D2441B8DE4340008BFCFA215234407E1B62BCE6DD4340A6EF3504C7513440A6B6D4415EDD4340FF93BF7B47513440253B3602F1DC4340AA656B7D915034407F87A2409FDC434057B3CEF8BE383440D2FD9C82FCD2434056BC9179E4373440FFCF61BEBCD243400282397AFC3234408081204086D24340D13C80457E3134405307793D98D24340A96BED7DAA2A3440D5AF743E3CD34340FE0B040132243440FCDEA63FFBD343407B14AE47E11A3440FFCC203EB0D54340FE0E45813E19344079AEEFC341D6434001857AFA08183440FDDB65BFEED64340008E3D7B2E173440556D37C137D74340AD4D637B2D083440FE0E45813ED94340FB95CE8767053440D00F238447D9434082FDD7B969033440D47C957CECD84340F702B34291023440637FD93D79D843407E8D2441B8FE33402638F581E4D74340A8E3310395FD3340FED2A23EC9D743402CD505BCCCFC3340D38558FD11D84340AA622AFD84FB3340D6A9F23D23D94340FE99417C60FB3340FA264D83A2D943407F15E0BBCDFB3340533D997FF4E1434052B5DD04DFFC33405340DAFF00EF43407D21E4BCFFEF33407D21E4BCFFF74340A8E3310395DD3340A7ECF483BA04444055BFD2F9F0DC3340D1031F83150544407E8AE3C0ABD93340A7AD11C138064440AC5626FC52D73340D2C43BC093064440FD14C78157D333405340DAFF00074440037976F9D6C333407AABAE4335094440800F5EBBB4C13340D28BDAFD2A0A4440CF4E0647C9BF33407C6308008E0B4440A4FE7A8505BB334029ED0DBE300D44407D96E7C1DD9D334029E78BBD171344402DCF83BBB3823340F92F1004C8184440A777F17EDC7E3340D673D2FBC61944405628D2FD9C7633402BDEC83CF21B4440A77A32FFE8733340A8716F7EC31C44402CD8463CD9713340FFCC203EB01D4440FA298E03AF663340D3F4D901D7234440CE548847E2493340FC1A498270354440A774B0FECF4933407E1B62BCE635444080812040864A3340A7AD11C138364440FA264D83A25133407EC9C6832D3844402BDB87BCE5563340AC5626FC52374440286552431B5833407AA52C431C3744400282397AFC6233407E54C37E4F32444024809BC58B6533402AE109BDFE304440D13FC1C58A6633407F4E417E363044402DD2C43BC06733407C60C77F812E44407C9C69C2F6673340530438BD8B2D4440D63730B951683340D7A6B1BD162C4440D4B837BF616A3340276BD443342A4440D5AF743E3C6B33402CD8463CD9294440FB230C03966C3340D4EE5701BE2944405340DAFF006F3340508BC1C3B42944404DA3C9C51870334046B3B27DC829444081069B3A8F723340253E7782FD294440D482177D05753340C02500FF942A4440A8E0F082887833407E9065C1C42B444080812040867A3340FED5E3BED52C44407E1EA33CF37A3340295FD042022E44402CD505BCCC7C33402638F581E437444052B5DD04DF7C3340FE9C82FC6C38444022895E46B1743340D0D38041D2474440ABE7A4F78D733340A8E0F08288484440D0420246976B3340A774B0FECF49444028F04E3E3D6A3340533D997FF4494440D4B5F63E55653340D4B837BF614A444052431B800D6433405055A181584A4440AB5FE97C78563340D009A1832E4F44407009C03FA54E334040683D7C995244404DD9E90775593340D38558FD11584440257A19C5725B3340A8AAD0402C594440A5F5B704E05B334029266F8099594440A7E9B303AE673340D47C957CEC684440A774B0FECF6933402BDB87BCE56E4440CA1649BBD1733340666A12BC21714440FA298E03AF763340D47C957CEC70444056BC9179E47733407E18213CDA70444057B3CEF8BE7833402AE109BDFE7044402383DC45987A3340AB5CA8FC6B714440FD9FC37C79853340D00CE2033B744440A968ACFD9D853340520DFB3DB1744440D6AC33BE2F863340FDDB65BFEE764440A4FB3905F98533402638F581E47744407B116DC7D48533402B172AFF5A784440D0D03FC1C58233407AA86DC3287C4440FA264D83A281334082397AFCDE7C44402AE44A3D0B763340D3F71A82E3804440AE0E80B8AB6F33408D0B0742B2824440'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('BK','BA','BIH','70','Bosnia and Herzegovina','5120','3915238','150','39','17.786','44.169','0106000020E6100000010000000103000000010000008F0100009599D2FA5BA631404AD40B3ECD714540BDE2A9471A943140D712F241CF78454029E78BBD17AB31407E1EA33CF37A4540AD50A4FB39AD31402B14E97E4E7B45405340DAFF00AF31407F15E0BBCD7B45404E2844C021B0314092B1DAFCBF7C4540FD1186014BAE3140A9A44E40137F4540562B137EA9AB3140D106600322824540A3073E062BAA3140F92CCF83BB83454057B3CEF8BEA83140000341800C854540FF9600FC53A631402541B8020A8745407F87A2409FA431407EC9C6832D884540257497C459A131402CD8463CD98945402BDB87BCE5963140D1031F83158D4540AC53E57B469231405376FA415D8E4540FF08C380258F3140A9A44E40138F454028F38FBE496F3140813FFCFCF796454084F1D3B8374F3140A7E67283A1A24540267156444D4C31402BDEC83CF2A34540A3073E062B4A3140295FD04202A6454052465C001A493140AC5626FC52A74540D540F33977473140FA264D83A2A9454051BB5F05F84631405307793D98AA4540D446753A90413140000341800CB545402CD8463CD94131408048BF7D1DB64540286211C30E433140A777F17EDCB6454029ED0DBE304531405437177FDBB74540A968ACFD9D453140D3F71A82E3B84540FB95CE8767453140AB5CA8FC6BB945407A1A3048FA4431402CD8463CD9B945400282397AFC4231402635B401D8BA4540D4BB783F6E3F31402BDEC83CF2BB4540D82E6D382C39314029ED0DBE30BD4540CC5D4BC807293140A86E2EFEB6BF4540FC1A4982701D3140D3F71A82E3C04540D82E6D382C193140D4EE5701BEC14540AC53E57B46123140FE99417C60C3454028F38FBE490F3140D7A6B1BD16C44540A5F5B704E00B314029ED0DBE30C54540533D997FF4F93040D482177D05CB454022895E46B1F430407DCC07043ACD45407D21E4BCFFEF30407F8461C092CF45404DD6A88768D4304082397AFCDEDC454079AEEFC341B63040D673D2FBC6E94540000341800CB53040562B137EA9EB4540ABE7A4F78DB3304082397AFCDEEC45405055A18158B23040A8E3310395ED4540AB5FE97C78A63040D00CE2033BF44540D3BEB9BF7AA43040505260014CF54540D3C1FA3F87893040D4EE5701BE0146408109DCBA9B873040AC53E57B46024640D82B2CB81F8430405534D6FECE0246407AABAE43358130407E1EA33CF3024640FA298E03AF76304053793BC269034640FB928D075B703040D7A6B1BD16044640AD50A4FB396D3040A7ECF483BA044640D4B837BF616A3040530438BD8B0546405534D6FECE5A30402A1DACFF730A46407F129F3BC15630402BDEC83CF20B46404DD6A88768543040D4B5F63E550D46402DCF83BBB35230407AA52C431C0F464081069B3A8F523040520ABABDA40F4640D6A9F23D2351304027F911BF6211464084F1D3B8374F3040D482177D05134640D63A71395E4D3040A8A78FC01F1446402DD2C43BC04730402829B000A6164640037976F9D6433040514F1F813F184640CA1649BBD13F3040D009A1832E19464055BFD2F9F03C304027F911BF621946402BDB87BCE5363040D00F2384471946400282397AFC3230402AE109BDFE184640D7A6B1BD162C30407B6649809A184640295C8FC2F5283040D1CABDC0AC1846402577D84466263040D3F71A82E31846404FCDE50643253040A8AAD0402C1946407F87A2409F243040D3C1FA3F8719464022895E46B1243040D1066003221A4640D6A9F23D233130407EC9C6832D2846402DCF83BBB33230407E5182FE422D4640008BFCFA21223040A7AD11C1383E4640FB928D075B203040D0D38041D23F46404DDC2A88811E3040D3F71A82E3404640FB230C03961C30407D5D86FF744146400282397AFC123040A77A32FFE8434640A8E0F0828808304001C11C3D7E4946402DCF83BBB3023040813FFCFCF74E4640AB59677C5FEC2F407D93A641D1584640F4346090F4E92F4029266F8099594640772CB64945E32F40FD4AE7C3B35A4640CBD8D0CDFEE02F407E1EA33CF35A4640257A19C572DB2F407F4B00FE295B46407D21E4BCFFBF2F407C992842EA5A46405AA148F773BA2F40286211C30E5B4640CDC98B4CC0B72F40514CDE00335B4640A968ACFD9DB52F4054FEB5BC725B4640295C8FC2F5882F40FD14C78157634640020D36751E852F4027F6D03E5664464051BEA085047C2F40A777F17EDC66464083F755B950792F407D21E4BCFF6746402C6684B707792F40AA656B7D916846404ED026874F7A2F4001C11C3D7E69464006F52D73BA7C2F4028F04E3E3D6A4640A774B0FECF892F408048BF7D1D76464006F2ECF2AD872F40556D37C137874640FB20CB8289872F40AB5CA8FC6B894640DBA4A2B1F6872F4080812040868A46407A17EFC7ED8F2F40A7ECF483BA944640D0D03FC1C5922F40295FD04202964640F71F990E9D962F402541B8020A9746407B14AE47E19A2F40D38558FD11984640C8EA56CF499F2F40FCE1E7BF0799464024809BC58BA52F40AC53E57B469A4640CADE52CE17AB2F40FBE769C0209B4640A4703D0AD7C32F40D3BEB9BF7A9C464058AA0B7899D92F4029ED0DBE309D4640DF8C9AAF92DF2F407E5182FE429D4640A77A32FFE80330402BDEC83CF29B46407E1B62BCE6053040AA622AFD849B4640FE0E45813E0930405055A181589A464051BEA085041C3040272F3201BF904640D1CDFE40B91D30407F8461C0928F4640FC1D8A027D323040FFCC203EB0854640CF488446B03530407D5A457F68844640FC17080264383040D2C77C40A0834640FA9B5088803F3040823CBB7CEB814640ABE7A4F78D43304080457EFD108146404C50C3B7B04A3040B6F81400E37F46405EF23FF9BB5730408048BF7D1D804640F4177AC4E85930409A5C8C817580464055151A88655B30403C86C77E168146406667D13B155C30403868AF3E1E82464062307F85CC5D30400457790261854640F41ABB44F56A3040B9196EC0E78F4640533D997FF4793040FED2A23EC99746407288B83995803040C8940F41D59A464053CE177B2F8230406ABE4A3E769B46407F129F3BC1863040A7ECF483BA9C46409E961FB8CA8730407E1EA33CF39C4640C5C551B9898A30404B04AA7F109D4640C37FBA810297304022DE3AFF769D464005C3B986199A304022DE3AFF769D4640B188618731A130409C508880439C46407E8AE3C0ABA930407C992842EA9A464004763579CAAE304028F04E3E3D9A46407D21E4BCFFCF30407D21E4BCFF974640286211C30ED330407D21E4BCFF9746401F4B1FBAA0D63040AB59677C5F98464097C62FBC92D830405019FF3EE398464032923D42CDD83040F5D896016799464035289A07B0D830400C570740DC9946402EFF21FDF6E9304072C45A7C0AA2464083F755B950093140D1031F83159D46404ED026874F0A3140514CDE00339B464050C763062A0B3140D4B837BF619A46402CD505BCCC0C3140D673D2FBC6994640276BD44334123140286552431B984640D63A71395E2D3140D482177D059346404FCAA486363031407E1EA33CF3924640A4FE7A85053B3140D0D03FC1C5924640A8E33103953D3140D482177D05934640FF08C380253F314000C79E3D97934640D63730B951483140D2C43BC09396464050C763062A7B3140F92F1004C890464051BEA085047C31407AA52C431C8F4640A5F5B704E07B3140A7AD11C1388E46404DDC2A88817E3140FCE42840148E46408881AE7D0185314081423D7D048E4640D1CABDC0AC983140D3FA5B02F08D4640D04543C6A3B03140A86E2EFEB68F46407BA2EBC20FC2314029E78BBD178B464029ED0DBE30D531407AA52C431C874640FF05820019DA3140FF9600FC53864640276893C327DD3140D6AC33BE2F86464023861DC6A4DF3140A9DA6E826F86464058AA0B7899E93140552E54FEB5884640A777F17EDCEE3140AC53E57B468A464055C2137AFD113240A6B6D4415E8D4640AB59677C5F1C3240D482177D058B46407E8D2441B81E3240A96BED7DAA8A4640257497C45921324080812040868A4640CF4BC5C6BC2A32407BA2EBC20F8A46407D96E7C1DD2D3240533D997FF489464081069B3A8F3232402A1DACFF738A46407F87A2409F343240AB984A3FE18A4640AB5FE97C78363240FE99417C608B4640D0D38041D2373240FE0B0401328C4640A7E9B303AE373240D1031F83158D4640AB5FE97C7836324027327381CB8D46407B116DC7D4353240FA298E03AF8E464050C422861D363240FED2A23EC98F4640D540F339773732407B6649809A904640562B137EA93B324027F911BF62914640247D5A457F403240D673D2FBC6914640000341800C45324001C11C3D7E914640FC8F4C874E6B3240D3FA5B02F08D46405055A18158A23240A96BED7DAA8A4640FC8F4C874ECB3240520ABABDA47F4640F92CCF83BBCB32407E8D2441B87E46407B9FAA4203CD3240A4C2D8429079464000917EFB3ACC32407B6649809A78464028F04E3E3DCA32407EC9C6832D784640D0D38041D2C732402B172AFF5A7846402AE44A3D0BC63240D3F71A82E3784640ABE7A4F78DC33240295C8FC2F578464056B950F9D7C232407EC9C6832D7846407F87A2409FC432407DCC07043A7546400473F4F8BDC932407F4B00FE29734640FC8F4C874ECB32405182FE428F724640A968ACFD9DD532407AA52C431C6F4640D236FE4465D7324000C45DBD8A6E464058AA0B7899D93240D6AC33BE2F6E4640D2393FC571DC32407E1B62BCE66D4640000341800CF5324029ED0DBE306D464056BC9179E4F732407E5182FE426D46408109DCBA9B0733408048BF7D1D6E4640A3073E062B0A334079AEEFC3416E46405340DAFF001F3340FE99417C60734640A4FE7A85052B3340D3FA5B02F0754640D63A71395E2D3340A7AD11C13876464029EACC3D24303340D6AC33BE2F764640800C1D3BA84C3340A5BF97C283744640D4BB783F6E4F334056F5F23B4D744640D828EB37135F3340A774B0FECF714640226FB9FAB16133409F3BC1FEEB6E464055C2137AFD613340AB5FE97C786E4640A8E0F082885833402A1DACFF7362464025CFF57D38583340A165DD3F166246402AE44A3D0B563340520ABABDA45F4640D5B2B5BE48503340276BD443345A46409E0B23BDA8313340E04BE141B34746401615713AC9223340836C59BE2E434640B5705985CD203340EC3026FDBD424640D0420246971F33408F352383DC414640A4FE7A85051B33407F4E417E36304640CF4BC5C6BC1A3340530438BD8B2D464022895E46B1203340C861307F85284640257497C4592133407EC9C6832D2846408200193A76283340543A58FFE72446408599B67F65293340ECA529029C244640FA980F08742A33407D5A457F68244640DEE8633E203C3340B1DD3D40F7214640FC1A4982703D3340823CBB7CEB214640AD8905BEA25B3340EAB12D03CE1A4640AB59677C5F7C334002BB9A3C650F46407D93A641D1983340A86E2EFEB6074640419E5DBEF59D3340C7A013420707464058AD4CF8A59E3340FA298E03AF064640F1F3DF83D79E334021AE9CBD3306464025CCB4FD2B9F3340E690D442C9024640D2C43BC0939E3340A6B915C26A0246409FAD8383BD9D33402B86AB03200246402654707841883340B8AD2D3C2FFB4540C4AF58C345863340F2ED5D83BEFA4540BA6B09F9A08333408F8AFF3BA2FA454000917EFB3A7C3340FFCF61BEBCFA45401B4AED45B46D334094DE37BEF6FA4540CF4E0647C95F334000C79E3D97FB45402DCC423BA75D334052431B800DFC4540D7A6B1BD165C3340520DFB3DB1FC45407E1EA33CF35A33402A1A6B7F67FD4540029CDEC5FB593340D9092FC1A9FD454023861DC6A44F334051853FC39BFF454003603C83864E3340F511F8C3CFFF4540A64412BD8C3E3340AEB6627FD9014640505260014C3D3340A774B0FECF014640D787F546AD3C3340187B2FBE68014640D787F546AD3C33401E3526C45C0046408411FB0450403340B8AD2D3C2FFB4540027FF8F9EF5D3340295FD04202EE45407D21E4BCFF6F3340A9DA6E826FE645407E8AE3C0AB7933407C992842EAE245402CD505BCCC7C3340508BC1C3B4E1454052499D80267E3340527C7C4276E045407F8461C0927F3340508E0244C1DE45404FCAA48636803340D3FA5B02F0DD4540AB5CA8FC6B81334081423D7D04DC4540FC1D8A027D823340FA264D83A2D94540A7E67283A1823340AA656B7D91D84540D0D03FC1C58233405340DAFF00D74540A9DA6E826F7E3340A7B0524145CB4540A4FE7A85057B3340D6A9F23D23C94540ABEAE5779A6833405534D6FECECA454058AA0B7899493340FE47A643A7C54540CC07043A933A3340B7EC10FFB0C1454083F755B950393340FF05820019C24540D6AC33BE2F363340D0D03FC1C5C245400282397AFC023340D009A1832EC74540800F5EBBB4013340FF08C38025C74540D2C77C40A0F3324029266F8099C14540286211C30EF332407AABAE4335C1454056B950F9D7F23240D1CABDC0ACC045402B6C06B820F3324051853FC39BBF454022895E46B1F43240A96BED7DAABA4540543A58FFE7F43240D28BDAFD2ABA45407B116DC7D4F53240823CBB7CEBB94540FF05820019FA3240253E7782FDB945400188BB7A15FD3240823CBB7CEBB9454023861DC6A4FF324029266F8099B945407C992842EA023340D47C957CECB845407E1B62BCE6053340FD4D2844C0B7454054C554FA09073340FDDB65BFEEB645407C9C69C2F6173340FB20CB8289A745408109DCBA9B1733405628D2FD9CA64540FE0B04013214334029266F8099A14540FC1D8A027D123340FD4D2844C09F4540D446753A901133402BDB87BCE59E45407E18213CDA103340D2C43BC0939E45402B69C537140E33405531957EC29D4540E7E26F7B820C33404A438D42929D454084F41439440433402829B000A69E45400ADB4FC6F8F432407DCC07043AA5454027F6D03E56F43240A8E3310395A5454057B08D78B2F33240A9DA6E826FA6454084F4143944F43240FB20CB8289A745401956F146E6F532406BF46A80D2A84540E69315C3D5F532406094A0BFD0A94540A304FD851EF53240D106600322AA4540257A19C572EB3240D1CDFE40B9AD4540ADC266800BEA324047551344DDAD4540ABEAE5779AE832407D96E7C1DDAD454082FDD7B969E33240A968ACFD9DAD45407AC7293A92DF3240C097C28366AD454082397AFCDED63240EE2422FC8BAC4540543A58FFE7B432405473B9C150A14540514CDE0033B33240552E54FEB5A04540A7E67283A1B23240A7B393C151A04540D4B5F63E55A532402635B401D8924540CE5147C7D5A43240A774B0FECF914540A304FD851EA532407E18213CDA904540D13FC1C58AA63240520ABABDA48F4540AC5626FC52A73240508E0244C18E4540FC17080264A83240F92CCF83BB8B454057B3CEF8BEA83240AC53E57B468A4540FC17080264A832407AABAE4335894540A6F27684D3A63240FCE42840148645402577D84466A63240FE47A643A7854540CF488446B0A53240505260014C85454052431B800DA43240A8716F7EC3844540800F5EBBB4A132407D5A457F688445404DD6A88768943240F92CCF83BB834540D63A71395E8D32407C992842EA82454052465C001A893240276BD4433482454079AEEFC341863240A4C2D84290814540AC53E57B46823240D38558FD1180454028F38FBE497F3240508E0244C17E4540A5F5B704E07B32407D5A457F687C4540A4FE7A85057B324054FEB5BC727B454080812040867A3240A6B915C26A7A454027F6D03E56743240A96BED7DAA6A45407F87A2409F7432407E8AE3C0AB694540000341800C753240FE0E45813E6945402DCC423BA77D3240FF0582001962454052431B800D843240A8E33103955D4540A8716F7EC38432407E5182FE425D45407F129F3BC1863240A7ECF483BA5C454052465C001A89324001BEDBBC715C45402BDEC83CF28B324054707841445C4540276893C3278D324052431B800D5C4540A777F17EDC8E32407C6308008E5B4540D4BB783F6E8F32407F4B00FE295B4540CF4E0647C98F3240D0D03FC1C55A4540ABE7A4F78D93324082397AFCDE544540037976F9D6933240D3F4D901D7534540286211C30E9332405055A181585245407BA2EBC20F92324027F911BF625145407E18213CDA903240552E54FEB55045402CD505BCCC8C324028F38FBE494F454027F911BF62893240D6AC33BE2F4E45407F129F3BC1763240D3F71A82E34845407F87A2409F743240FE9C82FC6C4845404DD9E90775693240A968ACFD9D4D45405531957EC26532402829B000A64E45402CD505BCCC5C32407F4E417E3650454057B3CEF8BE583240A8E0F082885045407B116DC7D45532405401F73C7F504540CF4E0647C94F324028F38FBE494F4540FC1A4982704D3240813FFCFCF74E45400473F4F8BD4932402829B000A64E45402BDB87BCE5463240D4F19881CA4E4540A8716F7EC3443240FF08C380254F4540037976F9D643324002BB9A3C654F4540FE99417C603B3240276BD443345245407D93A641D1383240286211C30E53454052465C001A293240295C8FC2F5584540A86E2EFEB6FF31407D5D86FF74614540257A19C572FB31407E54C37E4F6245405531957EC2F53140F92CCF83BB63454055C2137AFDE131407E18213CDA684540FE9C82FC6CE03140AB5CA8FC6B694540295C8FC2F5D83140FE47A643A76D4540FC17080264D831402AE44A3D0B6E4540AC5626FC52D7314002BB9A3C656F45407AA86DC328CC3140282CF180B2734540D2C43BC093BE314027327381CB75454054C554FA09B731402829B000A67645402DCF83BBB3B23140FA298E03AF764540A301BC0512B03140D47FD6FCF875454084F1D3B837AF3140A968ACFD9D7545409599D2FA5BA631404AD40B3ECD714540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('BU','BG','BGR','100','Bulgaria','11063','7744591','150','151','25.231','42.761','0106000020E6100000010000000103000000010000003402000051C1E10511E13B40A3C85A43A96B4540A304FD851EE53B407E8D2441B8664540A7052FFA0AE63B40A5BF97C28364454079AEEFC341E63B407784D38217634540A4FB3905F9E53B4080812040865A4540268A90BA9DE53B40D05E7D3CF45945407F87A2409FE43B40D4EE5701BE594540FD14C78157E33B40D4EE5701BE594540F54A598638CE3B40A7E67283A15A454072DEFFC709C73B40A7B05241455B4540FE0B040132C43B4053793BC2695B4540FD2D01F8A7BC3B40514CDE00335B45402383DC4598BA3B402635B401D85A454052B81E85EBA13B40CCB56801DA504540219221C7D6833B40556D37C137474540FA264D83A2813B4052499D8026464540CD57C9C7EE7E3B40FB230C0396444540FD14C78157733B40A1A17F828B3D454074D2FBC6D7723B40000341800C3D4540D0D03FC1C5723B407AA86DC3283C4540A016838769733B4053793BC2693B454072DEFFC709773B4050E3DEFC86394540287E8CB96B813B40D009A1832E374540D0D03FC1C5823B40D009A1832E374540D2C77C40A0833B40A5BC564277374540AAF3A8F8BF873B40295C8FC2F538454074CFBA46CB8D3B40FA7E6ABC743945407D96E7C1DD9D3B40FE0E45813E3945407D96E7C1DDAD3B40A1A17F828B354540A20DC00644B43B40514CDE0033334540F44D9A0645B33B40D2FD9C82FC324540AAF06778B3B23B405182FE428F3245407C992842EAB23B40FA264D83A2314540FE0B040132B43B40556D37C1372F45404FCAA48636C03B4029266F80992145409F1F46088FC23B40A741D13C801F4540D0D38041D2C73B40D1031F83151D4540257A19C572DB3B407B9FAA420315454053CE177B2FE63B4052465C001A114540FB928D075BF03B40768A5583300D45407C9C69C2F6F73B40D00F238447094540A20A7F8637FF3B40CCEEC9C34205454051C1E10511013C40D00CE2033B044540CF488446B0053C40FD4D2844C0FF44407BC1A73979053C40508E0244C1FE4440FD14C78157033C40D1CDFE40B9FD4440C90391459AF83B40211D1EC2F8FD444029780AB952E73B40F9F36DC152FF444076C6F7C5A5DE3B40A3CB9BC3B5004540505260014CDD3B40A3CB9BC3B5004540CF488446B0D53B40514F1F813F00454076C075C58CD43B407EC9C6832D00454022895E46B1B43B402026E1421EFD4440FD14C78157A33B40F6083543AAFA4440A5F8F884ECA03B40A9A10DC006FA4440A019C40776983B40FD4D2844C0F74440D15B3CBCE7943B40D0D6C1C1DEF444407F87A2409F943B40FA7B293C68F44440D2C77C40A0933B40FE0B040132F44440FC1D8A027D923B40A8A78FC01FF4444051C1E10511913B40FE0B040132F44440A11342075D8E3B4029232E008DF44440A5F8F884EC703B40000341800CFD4440228C9FC6BD693B40D009A1832EFF4440295C8FC2F5683B40A5BC564277FF4440A304FD851E653B407903CC7C07014540A417B5FB55643B40A3957B8159014540FA9B5088805F3B402026E1421E054540A8E33103955D3B407F8461C0920745402A7288B8395D3B407C9C69C2F6074540FB230C03965C3B40A7B393C1510845404FCAA48636503B40A29BFD81720B454049827005144E3B40787B1002F20B4540D255BABBCE4A3B4051888043A80C45407E8AE3C0AB493B40D0D6C1C1DE0C4540F450DB8651483B40D1031F83150D4540D34CF73AA93B3B40FCE42840140E454073DBBE47FD113B40F8FF71C2840B4540A4FE7A85050B3B40D2FD9C82FC0A45401F9E25C808083B40A6B915C26A0A454040868E1D54F63A408D2958E36C004540FA9B508880EF3A40D3F71A82E3004540F54A598638EE3A40D3F71A82E3004540F6419605139F3A4029232E008DFC4440A7E67283A1923A40514F1F813FF84440E06932E36D913A407F15E0BBCDF74440A702EE79FE903A40A0A70183A4F74440D55DD905838F3A40E9B7AF03E7F64440C495B37746933A40C1E3DBBB06F34440FC3905F9D9903A40FB20CB8289EF4440CD57C9C7EE8E3A407B9FAA4203ED444054C8957A168C3A40D0D03FC1C5EA444027840EBA848B3A405055A18158EA4440D255BABBCE8A3A40253E7782FDE94440228C9FC6BD893A4079758E01D9E94440266E15C440873A40D4EE5701BEE944404ED026874F7A3A404E5E64027EE94440AAF3A8F8BF773A404E5E64027EE944405055A18158723A4029266F8099E94440FE0B040132643A40FA7E6ABC74E94440FD304278B4613A40A3957B8159E94440D04543C6A3603A407AABAE4335E944407A17EFC7ED5F3A40CCB56801DAE844407E8AE3C0AB593A40A1A17F828BE54440A019C40776583A409FAA4203B1E4444072DEFFC709573A40CDE847C329E34440A60EF27A30553A40FC17080264E044407A1A3048FA543A40D158FB3BDBDF4440000341800C553A407978CF81E5DE4440FB95CE8767553A40F981AB3C81DE4440AAF3A8F8BF573A402026E1421EDD444014083BC5AA593A40EB1B98DC28DC4440A708707A175B3A40A29BFD8172DB4440C6BFCFB8705C3A40B1E07EC003DB4440A514747B494F3A40A0A4C00298DA4440FC8F4C874E4B3A40A7E67283A1DA444051BB5F05F8463A4028BA2EFCE0DA4440219221C7D6433A40D2C77C40A0DB44406E6DE179A93C3A40C4B5DAC35EDE44403A048E041A3C3A40E90FCD3CB9DE4440C1E3DBBB06393A40BA490C022BDF4440FC1A4982702D3A40FD4D2844C0DF444051BEA085042C3A404C70EA03C9DF4440228C9FC6BD293A407F8461C092DF4440A9DDAF027C233A40A4C519C39CDE444022895E46B1143A40F92CCF83BBDB4440286211C30E133A40FBE769C020DB4440A5F8F884EC103A40D00F238447D94440FC3905F9D9103A404C70EA03C9D74440F25F200890113A40A5BF97C283D44440A41AF67B62193A40A19E3E027FD0444051DA1B7C611A3A402250FD8348D0444049827005141E3A40527C7C4276D044407AABAE4335213A40221ADD41ECD04440FC1D8A027D223A40221ADD41ECD044404985B18520233A40F702B34291D044404DDC2A88812E3A40A1A17F828BC54440F6419605132F3A40A7ECF483BAC44440AAF06778B3323A40514F1F813FB84440219221C7D6233A40A73B4F3C67AD444052B5DD04DFFC394052465C001AA94440268DD13AAAFA3940D3F71A82E3A84440D0D38041D2E73940D0D38041D2A74440209BE447FCE239407F8461C092A74440F25F200890E13940A0A70183A4A744407BBE66B96CD0394021205F4205AB44407DAF21382EA73940D1CABDC0ACA84440257497C459913940FE0E45813EA94440A20A7F86378F3940295C8FC2F5A84440A9F6E978CC8C39402123A0C211A84440A5F8F884EC803940000341800CA54440F450DB86515839402123A0C211A04440A4FB3905F95539402638F581E49F4440295C8FC2F54839407AA52C431C9F4440FE2AC0779B4739407AA52C431C9F4440A9DA6E826F3E3940A8380EBC5AA04440505260014C3D3940F702B34291A04440FC3905F9D9303940FB230C0396A644407F8461C0922F3940A9A44E4013A74440228C9FC6BD2939404D672783A3A84440DEC66647AA0F3940003961C268AE44403813D385580939400B992B836AAF4440D236FE4465E73840A7ECF483BAB4444050C422861DE63840A7ECF483BAB44440A6EF3504C7D13840D3F4D901D7B34440FF93BF7B47D13840AA622AFD84B344407D21E4BCFFCF3840FE9C82FC6CB0444084F1D3B837CF3840D1031F8315AD444059A7CAF78CC43840D4BB783F6EAF44402CD505BCCC9C3840A9A44E4013B74440A5F5B704E09B3840AC5626FC52B74440FA980F08749A38407D21E4BCFFB74440FF93BF7B479138402829B000A6BE4440247D5A457F903840FE9C82FC6CC04440AC5626FC527738402829B000A6C6444004763579CA4E3840D3FA5B02F0C54440295FD042024E3840A7AD11C138C644407A1A3048FA443840295C8FC2F5C84440ABE7A4F78D433840FCE1E7BF07C944402AE109BDFE403840295C8FC2F5C84440A777F17EDC3E3840D1CABDC0ACC844407AA52C431C3738402541B8020AC74440CE6DC2BD32333840168733BF9AC54440514F1F813F2838407E5182FE42C54440D925AAB7061A38407C60C77F81C64440295C8FC2F518384000C45DBD8AC6444056BC9179E417384055FB743C66C6444059A7CAF78C1438407E5182FE42C54440D04543C6A3103840FBE769C020C3444029EACC3D24103840A96BED7DAAC2444029EACC3D24103840276BD44334C244402AE109BDFE1038408048BF7D1DBE44402383DC4598FA3740527C7C4276B844404DD9E90775F93740FC17080264B844407C992842EAE237402CD8463CD9B94440A5F5B704E0CB37402638F581E4B744407B9FAA4203BD374056F5F23B4DB44440D0D03FC1C5A23740FC17080264B04440D446753A90A13740A7B393C151B0444052465C001A993740272F3201BFB044400188BB7A158D3740D106600322B24440533D997FF48937402635B401D8B24440F92F1004C87037407D5A457F68B44440257A19C5724B3740FCDEA63FFBB34440CC5D4BC8074937407F15E0BBCDB3444050C422861D4637407F4B00FE29B34440D5AF743E3C3B3740A7B393C151B04440FA980F08743A37407D21E4BCFFAF4440533D997FF4393740813FFCFCF7AE44407E1EA33CF33A37407DCC07043AAD4440CF4BC5C6BC3A3740A8716F7EC3AC4440A3073E062B3A374027F6D03E56AC444051BB5F05F8363740FBE769C020AB4440A9DDAF027C333740D106600322AA4440247D5A457F303740A4C2D84290A94440FD1186014B2E37405473B9C150A944407E8D2441B81E374080457EFD10A94440AD4D637B2D183740FCE1E7BF07A944400473F4F8BDF936407E1EA33CF3AA4440BD0166BE83EF36406F1283C0CAAB4440FF93BF7B47F13640A8A78FC01FAC44407F87A2409FF4364029ED0DBE30AD4440A4FB3905F9F536407E1B62BCE6AD444051BB5F05F8F63640A777F17EDCAE4440D540F33977F736402638F581E4AF444024809BC58BF53640AA9ECC3FFABC4440D2C77C40A0F336407F87A2409FCC4440D2C77C40A0F3364029EACC3D24D04440037976F9D6F336407AABAE4335D14440CE5147C7D5F43640D106600322D24440800C1D3BA8FC36407DCC07043AD544407C992842EA023740FE9C82FC6CD84440A8716F7EC304374029266F8099D944408109DCBA9B073740F92CCF83BBDB444001857AFA08083740D00CE2033BDC4440FC170802640837407DCC07043ADD4440A7E9B303AE0737402AE44A3D0BDE44407E9065C1C4033740A4C2D84290E14440D734EF3845033740533D997FF4E14440FC1D8A027D02374028F04E3E3DE244407A17EFC7EDFF36405307793D98E24440037CB779E3F836405534D6FECEE24440A7E9B303AEF73640D482177D05E3444079AEEFC341F63640562B137EA9E34440FF93BF7B47F1364002BB9A3C65E7444079AEEFC341E63640A8E0F08288F04440D4B5F63E55E536405473B9C150F14440F92F1004C8E03640520ABABDA4F744404FCAA48636E03640A8E0F08288F84440D82B2CB81FD4364054FEB5BC72034540FF93BF7B47D136407C6308008E0345407F8461C092AF36402B172AFF5A08454051BEA085049C36407DCC07043A0D4540FB95CE8767853640D482177D0513454059A7CAF78C8436402B14E97E4E134540FC170802646836407E9065C1C423454082035ABA825D36407D5D86FF74294540D82E6D382C6936407C992842EA2A4540A968ACFD9D753640AB5FE97C782E45407A1A3048FA84364029E78BBD17334540CF488446B0853640A9DDAF027C33454083F755B950893640D6AC33BE2F3645400473F4F8BD8936407E8D2441B8364540A777F17EDC8E3640D4B5F63E553D4540D828EB37138F364055FB743C663E4540800C1D3BA88C36405473B9C150414540FE99417C608B3640253E7782FD4145405531957EC2853640FCDEA63FFB434540037CB779E3783640A7B393C151484540A6F27684D37636407D93A641D1484540FC1D8A027D723640A7ECF483BA4C4540552E54FEB5703640D5B2B5BE486845407E18213CDA703640F92F1004C86845407AABAE4335713640A8AAD0402C694540D0D03FC1C5723640A774B0FECF694540D2C77C40A0833640FD4D2844C06F4540D4B5F63E55853640D5B2B5BE487045402577D84466863640527C7C4276704540A4FB3905F9953640AC53E57B467245402383DC45989A3640FD4AE7C3B3724540FC1A4982709D36408081204086724540A7E9B303AEA73640D00F238447714540D3C1FA3F87A93640272F3201BF704540F92CCF83BBBB3640FDD8243FE2714540027FF8F9EFBD3640D106600322724540A777F17EDCBE3640D4B837BF61724540D236FE4465F736407B9FAA42038D4540A8E3310395FD3640FCE1E7BF0791454083FA96395DFE3640D106600322924540FF93BF7B47013740D1CABDC0AC984540F92F1004C8F036407E1EA33CF39A4540D63730B951E836407E5182FE429D4540FB20CB8289E73640530438BD8B9D4540D3C1FA3F87D93640A8A78FC01FA44540037CB779E3D83640D3BEB9BF7AA445408200193A76D8364082397AFCDEA44540FC17080264D83640D4B5F63E55A545405531957EC2D53640508BC1C3B4A945404FCDE50643D53640FF05820019AA4540514CDE0033D33640286211C30EAB454084F4143944C4364027F911BF62B14540286211C30EC3364029266F8099B1454027F911BF62B93640514CDE0033B345407C9C69C2F6B73640FE99417C60B34540FC8F4C874EAB36407DCC07043AB54540F92F1004C8A03640FF08C38025B7454055BFD2F9F08C36402BDEC83CF2BB454029E78BBD178B3640D3BEB9BF7ABC454083F755B950893640530438BD8BBD4540D925AAB7066A36405534D6FECEDA4540286552431B68364082397AFCDEDC4540295FD042025E36402CD8463CD9E94540CF4BC5C6BC6A3640D3F71A82E3004640D0420246976B36407AABAE43350146404DD9E9077589364002BB9A3C6507464082035ABA828D36407EC9C6832D084640D63A71395E9D36402541B8020A0F4640FC1A4982709D36407F8461C0920F46404DDC2A88819E36405531957EC2154640AB5FE97C78A63640FBE769C0201B4640266E15C440A7364054FEB5BC721B4640276893C327AD3640A8716F7EC31C46408A592F8672AE364073309B00C31C4640A86E2EFEB6AF364081423D7D041C4640D53DB2B96AB236407F4B00FE291B4640D63730B951E8364000C45DBD8A0E46402BDEC83CF2EB36407E1B62BCE60D464055C2137AFDF13640A6B6D4415E0D4640ABE7A4F78DF336407E5182FE420D464068976F7D58FF36402D776682E10C4640A5F8F884EC003740A7ECF483BA0C4640A968ACFD9D053740D57954FCDF0B4640D3C1FA3F870937405534D6FECE0A4640FC8F4C874E0B3740D4EE5701BE0946407F15E0BBCD0B37407E18213CDA084640FE99417C600B3740FD4D2844C00746407E1EA33CF30A3740266E15C440074640D63730B951083740D1CDFE40B9054640D593F947DF0037406473D53C47024640CD57C9C7EEFE3640A774B0FECF0146402CD505BCCCFC364001C11C3D7E014640257A19C572FB36407D5D86FF74014640C1C41F459DF536404A438D429201464026FF93BF7BEB3640D097DEFE5C004640AD4D637B2DE836405437177FDBFF4540FC1D8A027DE23640AB5FE97C78FE45407AABAE4335E13640FE47A643A7FD4540B894F3C5DED7364079758E01D9F345401F2C634337D73640E04BE141B3F145403D80457EFDD83640B3075A8121EF4540B7442E3883DB3640D28E1B7E37ED45407B9FAA4203DD3640FB230C0396EC4540A301BC0512E03640D3F4D901D7EB45407A1A3048FAE43640D482177D05EB4540FB20CB8289F73640AA656B7D91E84540CFF57D38481037403C4D66BCADE64540FD1186014B1237403C4D66BCADE64540ABE7A4F78D233740A5BC564277E745405531957EC2253740D0D38041D2E745402463B5F97F293740944DB9C2BBE8454056B950F9D7323740A6B915C26AEA454016FC36C47839374020B75F3E59EB454006D671FC5041374082751C3F54EC4540655419C6DD443740B0AD9FFEB3EC4540ABEAE5779A483740543A58FFE7EC4540FD6662BA106B37404E64E60297ED4540A3957B81596D3740103FFF3D78ED45405055A18158723740253B3602F1EC45404417D4B7CC813740657094BC3AEB45404DA3C9C5188437409259BDC3EDEA454018EAB0C22D873740438CD7BCAAE945403E0801F9128A37403A596ABDDFE8454055C2137AFD91374028F38FBE49E74540D925AAB7069A3740A7AD11C138E645402CD505BCCC9C37407E1B62BCE6E545407AABAE4335A137405531957EC2E54540D6AC33BE2FC63740543A58FFE7E445402CD505BCCCFC3740266E15C440DF454078B7B24467113840ABCE6A813DDC45405BD1E638B71D3840CB85CABF96D945409EB30584D62738404913EF004FD845402B69C537142E3840520ABABDA4D745407F8461C0922F384051853FC39BD745407BA2EBC20F323840A86E2EFEB6D7454027F911BF62393840514F1F813FD845402CD8463CD9413840D3F71A82E3D8454083F755B950493840D00F238447D9454004763579CA4E3840D00F238447D94540C1559E40D85138406DACC43C2BD94540D0D38041D25738407E18213CDAD8454028F04E3E3D5A3840FCE1E7BF07D94540AB59677C5F5C384055F833BC59D94540D63A71395E5D3840A4C2D84290D945402DD2C43BC0673840A8A78FC01FDC4540D5B2B5BE4870384079AEEFC341DE454029ED0DBE30753840AC5626FC52DF454028F38FBE497F38405473B9C150E14540FA264D83A2813840A4C2D84290E14540AC5626FC52873840AB5CA8FC6BE145407D21E4BCFF8F3840A8AAD0402CE14540D82E6D382C9938405401F73C7FE045407B9FAA42039D38402638F581E4DF45406C938AC6DAAF38401EFCC401F4DB45407F87A2409FB438407C6308008EDB4540CC5D4BC807B9384053793BC269DB454050C763062ACB3840D5AF743E3CDB4540FA264D83A2E138407F4B00FE29DB454088F37002D30539401EF98381E7DA454050E3DEFC86393940CBBE2B82FFD74540286211C30E433940D4F19881CAD645402881CD3978463940FCE4284014D64540247D5A457F503940A9DDAF027CD34540A8FC6B79E556394050E3DEFC86D14540A1100187505939404D672783A3D0454073D87DC7F05C39407C9C69C2F6CF4540A301BC0512603940F60B76C3B6CF45403B3AAE46766139400169FF03ACCF4540FB95CE87676539404C70EA03C9CF454080812040866A39407C9C69C2F6CF454071CADC7C236E394018EDF1423AD04540151BF33AE270394098689082A7D04540272F3201BF76394018B49080D1D145402A6F47382D88394051DA1B7C61D24540A8FFACF9F19B3940F50EB743C3D44540467D923B6CAE3940B1169F0260D84540ED0BE8853BBB3940F1F3DF83D7D84540E6B2D1393FBD3940745DF8C1F9D84540AAF06778B3C23940D4EE5701BED94540D252793BC2C53940CCF10A444FDA45404DD9E90775C93940A7B0524145DB4540CE5147C7D5E0394082AB3C81B0E3454052B81E85EBE13940A73B4F3C67E54540B9C4910722E339405891D10149E64540249C16BCE8E339402829B000A6E64540A60BB1FA23F03940A8A78FC01FEC45409F1F46088FF23940D1031F8315ED45407B116DC7D4153A40A4C2D84290F94540FB230C03961C3A40787B1002F2FB4540A5F8F884EC203A4052D7DAFB54FD4540D15B3CBCE7243A4079AEEFC341FE4540505260014C4D3A40787B1002F2034640A6EF3504C7613A40A1A17F828B054640FE0B040132643A404D6A6803B0054640171230BABC693A402D414640850546400B0BEE073C703A407590D7834905464080812040867A3A404C3448C153064640FC36C478CDAB3A407AABAE4335094640257A19C572CB3A40FE0B0401320C4640266E15C440D73A40D4F19881CA0E464056BC9179E4E33A404337FB03E51046407B116DC7D4E93A40B119E0826C114640FFB0A54753093B4072361D01DC124640D2393FC5711C3B40A9A10DC006124640FA980F08742A3B404D672783A3104640FA42C879FF2F3B4027BD6F7CED0F46404985B18520333B40A0A70183A40F4640CC5D4BC807393B40FB78E8BB5B0F464052B5DD04DF3C3B407F8461C0920F4640A60BB1FA23403B40CBBE2B82FF0F4640AD31E884D0453B407C992842EA104640D236FE4465473B40527FBDC2820D4640FE2AC0779B473B40D1031F83150D464051DA1B7C614A3B40A7B05241450B4640A9F6E978CC4C3B40CCF10A444F0A4640FB95CE8767653B407784D382170346402577D84466663B40A2D11DC4CE024640CF4BC5C6BC6A3B40A7E67283A1024640259694BBCF793B40FC1D8A027D0246402A7288B8399D3B4021205F42050346407F8461C0929F3B40234DBC033C0346407AABAE4335A13B4022179CC1DF034640A6EF3504C7A13B40A3923A014D0446404DD6A88768A43B40276893C327054640D13FC1C58AA63B40527FBDC2820546407C9C69C2F6A73B40FC1A498270054640F54718062CA93B407DCC07043A054640F25CDF8783AC3B40A5BF97C283044640505260014CAD3B40FE0B0401320446402098A3C7EFAD3B40D3F4D901D7034640A514747B49AF3B40F6083543AA02464041102043C7B23B40D009A1832EFF45407A1A3048FAB43B40D1031F8315FD454053CE177B2FB63B40F9F6AE415FFC4540AAF3A8F8BFB73B407E9065C1C4FB4540A708707A17BB3B4021205F4205FB4540F25CDF8783BC3B402635B401D8FA4540A514747B49BF3B40D0D03FC1C5FA4540A11342075DCE3B4053793BC269FB454073DBBE47FDD13B40D2C77C40A0FB454052D7DAFB54D53B4052431B800DFC45404ED026874FDA3B402026E1421EFD4540F54A598638DE3B40211D1EC2F8FD4540FF05820019EA3B40F702B3429100464052D158FB3BEB3B40A3CB9BC3B50046409F1C058882ED3B40A8380EBC5A004640A9F92AF9D8F13B405376FA415DFE4540D2C77C40A0F33B40505260014CFD45404DD6A88768F43B40A5BF97C283FC4540A60EF27A30F53B404C6DA983BCFA454052D7DAFB54F53B40F511F8C3CFF945407CB8E4B853F63B40286552431BF84540D1CDFE40B9FD3B407F8461C092EF4540A514747B49FF3B40211D1EC2F8ED4540247D5A457F003C40CCEEC9C342ED4540FE2AC0779B073C4053793BC269EB454054C8957A160C3C40A73E90BC73EA45407BA2EBC20F223C40A4C519C39CE64540D2C43BC0932E3C40A5BF97C283E44540267156444D3C3C405182FE428FE2454073DBBE47FD413C4079758E01D9E14540D236FE4465673C40D200DE0209E045407AA86DC3287C3C40266E15C440DF45409696917A4F953C40F60B76C3B6DF4540C90050C58D933C4028B7ED7BD4DD454052B81E85EB913C402250FD8348D84540A7E67283A1923C40D15B3CBCE7CC4540D0D03FC1C5923C4050E09D7C7ACC4540F644D7851F943C4079B130444ECB4540FB3C4679E6953C40768D96033DCA45401F9E25C808983C40FE0E45813EC94540F54718062C993C40A8E0F08288C8454080812040869A3C40FB78E8BB5BC74540A708707A179B3C404E61A5828AC6454052D158FB3B9B3C40F705F4C29DC5454052D158FB3B9B3C4051888043A8C44540A4FE7A85059B3C40A8A78FC01FC44540A3073E062B9A3C40D2FD9C82FCC2454075CC79C6BE983C40F8F9EFC16BC14540D449B6BA9C963C4051DD5CFC6DBF4540259012BBB68F3C40F6083543AABA454074CFBA46CB8D3C40A41AF67B62B94540268DD13AAA8A3C40D200DE0209B84540D13FC1C58A863C40F981AB3C81B64540CF4BC5C6BC7A3C405055A18158B2454052431B800D743C405473B9C150B14540A9DA6E826F6E3C4079758E01D9B1454050E3DEFC86693C404C6DA983BCB24540FE2AC0779B673C40A7B0524145B34540000341800C653C40FE0B040132B44540A6EF3504C7613C40D15B3CBCE7B445407BBE66B96C603C402026E1421EB54540F3599E0777573C40CCB8A981E6B5454076C075C58C543C40778192020BB64540A7ECF483BA4C3C40211D1EC2F8B5454072DEFFC709273C40D3F4D901D7B34540A4FB3905F9253C40282CF180B2B3454052B81E85EB213C40CBBBEA01F3B24540A20A7F86371F3C40202922C32AB2454073D53C47E4173C40F9F36DC152AF4540FB3C4679E6153C40CDE506431DAE454076C075C58C143C409FAA4203B1AC45405055A18158123C405473B9C150A9454052499D80260E3C404F5B238271A44540276893C3270D3C40A29BFD8172A3454052431B800D043C40D15B3CBCE79C454052B81E85EBF13B40A73B4F3C67954540C90050C58DE33B40505260014C854540D0D03FC1C5E23B407AA86DC3288445407C992842EAE23B40F511F8C3CF8145407BC1A73979E53B40A298BC016676454029780AB952E73B408081204086724540F3599E0777E73B4029266F8099714540A6F27684D3E63B40527FBDC2826D454051C1E10511E13B40A3C85A43A96B4540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('CY','CY','CYP','196','Cyprus','924','836321','142','145','33.219','35.043','0106000020E610000001000000010300000001000000BB000000F56393FC88D340402F35423F53AD4140A7B0524145DB4040D3F71A82E3B041402638F581E4DF40402635B401D8B24140D3F71A82E3E040407F4B00FE29B34140514CDE0033E34040A9DDAF027CB34140AC5626FC52E74040D5AF743E3CB341407E5182FE42ED404000C79E3D97B341402920ED7F80EF404081423D7D04B44140A8A78FC01FFC4040D0D38041D2B741402A1A6B7F67254140A8E0F08288C841407F4E417E362841407E8AE3C0ABC9414029E78BBD172B414054FEB5BC72CB4140D3F4D901D72B4140520DFB3DB1CC41402CD505BCCC2C4140FFCC203EB0CD41408048BF7D1D2E4140FF9600FC53CE41402CD8463CD93141405437177FDBCF4140FF9600FC53464140FF08C38025D7414028F38FBE49474140A5BC564277D741402A1DACFF734A414029EACC3D24D841407C6308008E4B41402B172AFF5AD8414000C79E3D974B4140AA9B8BBFEDD74140D47C957CEC484140D4B837BF61D2414001C11C3D7E314140A5BF97C283C441402BDEC83CF2234140000341800CBD41407AABAE4335214140D3F4D901D7BB4140FED5E3BED51C41407E54C37E4FBA41407E5704FF5B0F41402B14E97E4EB34140A7E67283A1FA4040D200DE0209A8414027F911BF62F94040AC5626FC52A74140FC17080264F84040FF9600FC53A64140D3FA5B02F0F540407C992842EAA2414029232E008DF44040FC17080264A041402BDEC83CF2F340405340DAFF009F414054FEB5BC72F34040D2C77C40A09B4140D5AF743E3CF3404055F833BC5999414053793BC269F34040000341800C954140AA622AFD84F34040520DFB3DB194414051888043A8FC4040A7B05241458B4140A77A32FFE8034140D3FA5B02F085414029232E008D044140505260014C854140813FFCFCF7064140A7E67283A18241407B6649809A0841405401F73C7F804140FDD8243FE20941407E8D2441B87E4140D1066003220A4140FF9600FC537E41407F4B00FE290B4140FE99417C607B4140A96BED7DAA0A41405534D6FECE7A41407B6649809A0841407C992842EA7A4140D200DE020908414029E78BBD177B414001BEDBBC710441407D5A457F687C4140FD14C781570341407E5182FE427D4140D0D03FC1C5024140FC1A4982707D4140000341800CFD4040A968ACFD9D7D41405055A18158FA404029ED0DBE307D4140813FFCFCF7F640407F87A2409F7C4140543A58FFE7F44040D7A6B1BD167C414000C79E3D97F3404053793BC2697B414029E78BBD17F340402635B401D87A4140FFCF61BEBCF240407E54C37E4F7A41405473B9C150F1404052465C001A794140D47C957CECF040407E18213CDA7841407AA52C431CEF4040D200DE02097841405628D2FD9CEE40402638F581E4774140D3FA5B02F0ED40402638F581E4774140FB230C0396EC404000CADFBDA37841402635B401D8EA4040D1066003227A4140AC53E57B46EA40405534D6FECE7A4140514F1F813FE84040D2C77C40A07B4140276893C327E54040FE0B0401327C41407E8AE3C0ABE14040A5BF97C2837C4140AB984A3FE1DA4040520DFB3DB17C4140AC53E57B46DA40407F87A2409F7C4140A86E2EFEB6D74040A77A32FFE87B41407E8D2441B8D6404000C79E3D977B4140FC1A498270D540407C992842EA7A4140A7ECF483BAD440407E54C37E4F7A41407F4B00FE29D340407B6649809A784140FD4AE7C3B3D24040FD4D2844C0774140253E7782FDD140407D96E7C1DD754140D4EE5701BED14040FED5E3BED5744140AB5CA8FC6BD14040514CDE00337341402AE109BDFED040405437177FDB6F4140FA264D83A2D140407E8D2441B86E41407E8AE3C0ABD14040D6AC33BE2F6E4140AB5CA8FC6BD1404027327381CB6D4140FE47A643A7CD40402AE109BDFE6841402CD505BCCCCC4040A8E0F08288684140FF05820019C2404056F5F23B4D644140A86E2EFEB6AF4040276893C3275D4140508E0244C1AE4040FED5E3BED55C4140D673D2FBC6A94040562B137EA95B41407B6649809AA84040A9DDAF027C5B414001F73C7FDAA240406BF46A80D25A41407F15E0BBCD9B4040D3C1FA3F8759414000C79E3D97934040823CBB7CEB59414052465C001A914040A774B0FECF594140813FFCFCF78E4040AB5CA8FC6B594140FC1A4982708D40402AE109BDFE584140A8E0F08288884040AC5626FC52574140520ABABDA4874040FDDB65BFEE564140D3F4D901D7834040FE0B040132544140EFA83121E6804040548B8862F2504140EFA83121E6804040771211FE454C4140AEBCE47FF2834040B22E6EA301484140CFF753E3A57D4040B9FE5D9F394941406876DD5B91784040B22E6EA3014841406876DD5B91784040D38558FD114C4140EC51B81E857540400D7217618A5041405BD3BCE314734040E509849D62534140295FD042026E40407E5182FE42554140D4B837BF616A4040FC1A4982705541402A1DACFF73624040D7A6B1BD16544140AB5CA8FC6B6140407F15E0BBCD5341407F4E417E36604040286211C30E53414028F38FBE495F4040A96BED7DAA5241407E8D2441B85E40405182FE428F524140FE99417C605B4040533D997FF451414027F911BF62594040276BD443345241407F15E0BBCD534040562B137EA9534140D106600322524040A8A78FC01F544140813FFCFCF73E4040FDD8243FE259414056F5F23B4D3C4040A7B05241455B41407AA86DC3283440405437177FDB5F4140F92CCF83BB334040286552431B604140D57954FCDF2B4040FCE42840146E4140AA622AFD842B4040FDDB65BFEE6E414027F911BF622940407D5A457F68744140FE99417C60234040A7ECF483BA84414029E78BBD17234040A968ACFD9D8541405307793D982240407D21E4BCFF8741402A1DACFF73224040D3C1FA3F87894140A7E67283A1224040A96BED7DAA8A4140D5AF743E3C234040FCDEA63FFB8B4140D7A6B1BD1624404001BEDBBC718C4140A6B6D4415E254040AB59677C5F8C4140D6AC33BE2F264040D3F4D901D78B41405340DAFF00274040D0D03FC1C58A41407D21E4BCFF2740402CD8463CD9894140A774B0FECF294040FC17080264884140282CF180B22B4040813FFCFCF7864140D4B5F63E552D4040D3FA5B02F0854140266E15C4402F4040D1031F8315854140D0D38041D22F4040253B3602F1844140527C7C4276304040FED5E3BED58441407C992842EA324040000341800C8541405531957EC2354040527FBDC282854140D4F19881CA36404027327381CB85414029EACC3D24384040A9DA6E826F8641407C992842EA3A4040514F1F813F884140FDDB65BFEE3E404052431B800D8C41402920ED7F803F4040A8716F7EC38C4140514F1F813F404040D47FD6FCF88D4140A9A10DC00642404027F911BF629141402635B401D8424040FC1D8A027D924140FD1186014B464040A7AD11C138964140A777F17EDC464040D6AC33BE2F964140FC17080264484040A968ACFD9D954140520ABABDA44F40407F8461C092974140FE99417C605340407F4E417E3698414029232E008D5440402B172AFF5A9841407D5A457F685C4040FF08C380259741408081204086624040AA9ECC3FFA9441402920ED7F80674040D2FD9C82FC924140FCE1E7BF07694040A6B915C26A9241407E54C37E4F6A4040276BD44334924140A9DDAF027C6B4040D4B837BF619241407D96E7C1DD6D4040A7B05241459341402AE109BDFE704040A8716F7EC3944140A96BED7DAA724040D1CDFE40B995414054FEB5BC72734040FD1186014B964140D7A6B1BD16744040813FFCFCF7964140FED5E3BED574404029EACC3D24984140A6B6D4415E75404029266F80999941406155BDFC4E7740400A302C7FBEA141407F4E417E36784040823CBB7CEBA94140D7F7E12021764040CB67791EDCAD4140336B2920ED7540404643C6A354B24140F1D8CF6229784040B0CBF09F6EB241402B172AFF5A804040D4F19881CAAE41405534D6FECEA24040A9DDAF027CAB4140A6B6D4415EAD4040AC53E57B46AA414028F38FBE49AF40407BA2EBC20FAA41405473B9C150B14040A9A10DC006AA41407E8D2441B8B64040253E7782FDA94140A77A32FFE8BB4040253E7782FDA94140D1031F8315BD4040D106600322AA41407E18213CDAD04040FED5E3BED5AC4140F56393FC88D340402F35423F53AD4140'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('DA','DK','DNK','208','Denmark','4243','5416945','150','154','9.264','56.058','0106000020E61000001200000001030000000100000048000000E0AD65321C072740386BD443346A4B40C0D8D0CDFE20274078ABAE4335694B40405C8FC2F548274030172AFF5A704B4000E92972884827403014E97E4E734B40C0CABDC0AC482740282CF180B2734B40C0921CB0AB492740F8DEA63FFB734B4020A7B1BD164C274058431B800D744B40609BC6F65A502740282CF180B2734B40002C9D0FCF6A2740C800DE0209704B40C000193A76782740001B4982706D4B40204E7CB5A3B027406082FE428F624B4020A26131EAB22740B0A10DC006624B40802634492CB927402820ED7F805F4B4080D9E90775B9274078A52C431C5F4B408038BA4A77B72740584F1F813F584B40A08EC70C54B62740B8BC564277574B4040CAA48636B0274000CD203EB0554B40801EA33CF3AA27408887A2409F544B4040B81E85EB912740883CBB7CEB514B40E07F828B158D2740A0A10DC006524B40006684B7077927405007793D98524B4060B81E85EB7127401015C78157534B40802CB64945632740B87A32FFE8534B40E0A4A2B1F647274028D505BCCC544B40C050A4FB392D2740383B3602F1544B404018080264282740603A58FFE7544B40E0622AFD840B2740D08BDAFD2A524B4080B81E85EBF12640A86E2EFEB64F4B40C06DFC89CAEE2640905704FF5B4F4B408088450C3BEC2640606D37C1374F4B40E00E45813EE9264030F38FBE494F4B4000AE65321CE72640D8BB783F6E4F4B4000AAF23D23C12640D0D03FC1C5524B404015C78157B3264038F6D03E56544B40C05CA8FC6BA12640B05FE97C78564B40C0FA96395D8E2640A8C2D84290594B40C0B628B34186264078812040865A4B40209F20B1DD7D264028E78BBD175B4B40C03E3C4B9061264088397AFCDE5C4B4020356090F4492640009700FC535E4B40E0B2B5BE48402640608E0244C15E4B40E0D03FC1C53226403041B8020A5F4B4040CAA4863610264000301004C8604B408032384A5E0D264050465C001A614B4040068200190A264000274D83A2614B40E01A498270FD2540F80B040132644B40407A19C572FB2540A8716F7EC3644B40E0353FFED2FA2540A80DDC813A654B4080BFD2F9F00C2640604F1F813F684B4060BB5F05F8062640583D997FF4714B40403F373465072640A86BED7DAA724B406069C537140E2640B0BF97C283744B40809BC6F65A102640D8031F8315754B40C068ACFD9D15264060499D8026764B4000EC6AF2941D2640A8E9B303AE774B4040A7CAF78C242640089D82FC6C784B4060B5DD04DF3C2640488BC1C3B4794B40A0116DC7D445264010068200197A4B40000C040132542640301DACFF737A4B4060D636C5E3622640F02422FC8B7A4B404054FEB5BC7A264090812040867A4B40C07F828B158D2640A0C2D84290794B4000C87C40A0932640602E54FEB5784B40C0C1FA3F87A9264010CD203EB0754B4000A7B1BD16AC264030ED0DBE30754B402069C53714AE264058888043A8744B4020F86EF3C6B12640104BE7C3B3724B4020999EB0C4B32640E08BDAFD2A724B40A0737E8AE3B82640E0A9F23D23714B40E0F0D8CF62C9264088A52C431C6F4B40207497C459D1264050FB743C666E4B40E0AD65321C072740386BD443346A4B400103000000010000003C000000E0E5E8F17B13284028F04E3E3D724B402009C380251F284088A2EBC20F724B4020CBBDC0AC282840D0B837BF61724B402023DA8EA92B2840D0B837BF61724B4000013274EC30284028F04E3E3D724B40E00241800C352840583D997FF4714B4040E2AC889A38284038266F8099714B40606893C3273D2840D87C957CEC704B40000473F4F8452840D009A1832E6F4B40C0DB114E0B562840002DCF83BB6B4B40A0129F3BC156284058793BC2696B4B40C08EC70C54562840D082177D056B4B40E0B5F63E5555284010D061BEBC6A4B4080C1E1051151284078A2EBC20F6A4B40C05A99F04B3D2840606D37C137674B40C0D24ECDE53628404876FA415D664B40A032384A5E2D2840B0E3310395654B40606552431B282840889FAA4203654B40405A80B6D524284008240C0396644B40607156444D1C2840804B00FE29634B40A05FE97C78F6274088992842EA5A4B40607D5A457FF02740D8C1FA3F87594B40E07F828B15ED2740A06E2EFEB6574B40A0D58F4DF2EB27408860C77F81564B40402C9D0FCFEA2740603A58FFE7544B40C0622AFD84EB274090992842EA524B40E07F828B15ED2740806649809A504B4060A4897780EF2740285FD042024E4B40E0A16131EAF22740F0E769C0204B4B4000E5D4CE30F52740D8EE5701BE494B4020295C8FC2F5274030E109BDFE484B40200341800CF52740886649809A484B4060CAA48636F02740909C69C2F6474B4060B60F79CBED27403038F581E4474B4040B08D78B2E3274010CADFBDA3484B4040FEF0F3DFDB27405873B9C150494B4020E2AC889AD82740D8EE5701BE494B4020E3A7716FBE2740089A417C60534B40405FD04202BE2740281A6B7F67554B40C05CA8FC6BC12740E000DE0209584B4000CBBDC0ACC82740E0EE5701BE594B40A059677C5FCC274010DFA63FFB5B4B40A08EC70C54B6274038E78BBD17634B400083DC45989A274058793BC2696B4B40801B62BCE6952740A8A78FC01F6C4B40809BC6F65A90274060888043A86C4B4080B950F9D7822740281A6B7F676D4B40C0D8D0CDFE802740D87FD6FCF86D4B40002C9D0FCF6A27403038F581E4774B40E050A4FB396D2740A0E0F08288784B40A0D24ECDE5762740D88BDAFD2A7A4B4080BEA085047C2740D8D03FC1C57A4B40A094490D6D802740E0FD9C82FC7A4B40E0CABDC0AC88274038E78BBD177B4B404045B9347EB12740C8B837BF617A4B4060CEA62380B32740405FB35C367A4B4080CA15DEE5BA2740F803029D49794B40E0E2A7716FFE2740282CF180B2734B4000E8154F3D0A284008D061BEBC724B40E0E5E8F17B13284028F04E3E3D724B400103000000010000000D00000020EC6AF294DD2440002DCF83BB6B4B40607D5A457FD02440D0A9F23D23694B40C03BFBCA83CC244008C11C3D7E694B404009C380257F2440F82CCF83BB734B40404278B4717C2440080C040132744B40A00F5EBBB4612440A8E67283A17A4B402038A110015F2440A87A32FFE87B4B40201286014B5E24407887A2409F7C4B40E0656B7D9160244028ED0DBE307D4B40406BD44334922440D0D38041D2774B40E0A7E331039D24402829B000A6764B40800F5EBBB4E12440D0C43BC0936E4B4020EC6AF294DD2440002DCF83BB6B4B4001030000000100000021000000E01A4982701D294060793BC2697B4B40E01A4982701D2940E0FD9C82FC7A4B4000F52D73BA1C29405807793D987A4B4080E2AC889A18294010C11C3D7E794B4000D34ECDE5162940100F45813E794B40A0D03FC1C5122940385C8FC2F5784B40C089592F860A29408818213CDA784B408018213CDA002940100F45813E794B40E0AA24B20FF228405855A181587A4B4080035ABA82ED28406082FE428F7A4B40206002B7EECE2840B8B05241457B4B40E0A9F23D23C12840B8B05241457B4B40A02634492CB92840804B00FE297B4B40807F828B15AD284000D061BEBC7A4B40C06E2EFEB69F2840908AE3C0AB794B400052D66F269E2840885D86FF74794B40406E15C4408728400048A643A7754B40005FD042025E2840D8CABDC0AC704B4020999EB0C453284010E2E7BF07714B40C050A4FB394D2840B85CA8FC6B714B40A09885764E3B2840F82CCF83BB734B4060B08D78B2432840E873D2FBC6794B4020809BC58B452840301DACFF737A4B400007B474055B28406831957EC27D4B40C06E2EFEB69F2840B8BF97C283844B40E0B837BF61CA284080A86DC328844B404021CB8289E7284050FEB5BC72834B40C0FDD7B969032940A8A10DC006824B40C02975C9380E29405073B9C150814B4000301004C81029408018213CDA804B4040EFAB72A1122940604F1F813F804B4080BEA085041C294000BEDBBC717C4B40E01A4982701D294060793BC2697B4B4001030000000100000011000000A014AE47E13A254000274D83A2794B40A05CA8FC6B21254050465C001A794B4040240C03961C254080ABAE4335794B40C02634492C19254030266F8099794B4020CBBDC0AC082540605260014C7D4B40002A8E03AF0625408896E7C1DD7D4B40E0EA56CF49FF2440904E417E36804B40E0EA56CF49FF24408893A641D1804B40A0069B3A8F02254078ABAE4335814B4000965D30B83E2540B868ACFD9D854B4060DF6B088E432540580438BD8B854B40C0F755B95059254030F38FBE497F4B404054FEB5BC5A25403829B000A67E4B4080D9E907755925408896E7C1DD7D4B40C009DCBA9B57254028ED0DBE307D4B4020B6F63E555525407887A2409F7C4B40A014AE47E13A254000274D83A2794B400103000000010000003700000040295C8FC295234038266F8099894B4040AD4CF8A5EE234028266F8099814B40E0264D83A2F12340D0A9F23D23814B40200000000000244020BA1281EA7D4B40A03579CA6A022440301A6B7F677D4B40C068ACFD9D15244028172AFF5A784B40A05FE97C78162440D800DE0209784B4080FDD7B969232440A8A4C00298724B40605A80B6D5242440E0D90242EB714B40809E077767252440A05016BEBE704B4080D6A8876824244008BE4D7FF66F4B40C0069B3A8F222440786F0C01C06F4B4080D026874FFA234008E52840146E4B40400341800CF52340901B62BCE66D4B4000931CB0ABE92340A89509BFD46D4B4020BC783F6EDF23408048BF7D1D6E4B404083DC4598DA234050FB743C666E4B40C06BED7DAACA2340908461C0926F4B40002DCF83BB9B234000E869C020734B40C05DDA7058922340F8DEA63FFB734B40200AF5F411902340B0BF97C283744B4040AD4CF8A58E234030ED0DBE30754B40E0622AFD848B234028DB87BCE5764B4080F4143944842340286211C30E7B4B4060D6A88768842340605260014C7D4B40609E077767852340B0E33103957D4B40E0D38041D2872340507FBDC2827D4B40200AF5F41190234050431B800D7C4B40A0FDD7B969A32340B0AAD0402C794B4020E9297288A82340B0656B7D91784B40A03BFBCA83AC2340E0B2B5BE48784B40C0F1D3B837AF2340B0B393C151784B4040CAA48636B02340886649809A784B40A017EFC7EDAF234030E109BDFE784B40C0035ABA82AD2340D00CE2033B7C4B40E0A6B1BD16AC2340B09ECC3FFA7C4B40606684B707992340A85CA8FC6B814B40E08EC70C54962340883CBB7CEB814B4020301004C8902340303E7782FD814B4000FEF0F3DF7B2340B0C2D84290814B4060861DC6A46F234078ABAE4335814B4000FBAF73D3662340080F45813E814B4020895E46B164234060F833BC59814B4040F52D73BA5C2340603D997FF4814B4020D9E907755923405055A18158824B40A0B08D78B2432340285FD04202864B4080B950F9D7422340109700FC53864B40C079008BFC422340508E0244C1864B40403F3734654723403020ED7F80874B40C0ED974F56542340D8CABDC0AC884B4020B937BF616A23406055A181588A4B40C020B248136F23405082FE428F8A4B40A082C30B228223405034D6FECE8A4B40C0AF743E3C8B23406055A181588A4B4040295C8FC295234038266F8099894B400103000000010000002900000080DF6B088E832540A8DDAF027C634B40E076BF0AF06D254040D505BCCC5C4B40C05758703F68254088397AFCDE5C4B40A01A3048FA642540D8B5F63E555D4B40C094490D6D60254060FB743C665E4B4060AA0B78995925405001F73C7F604B4020861DC6A44F2540808D2441B8664B4040B60F79CB4D2540904B00FE296B4B40206893C3275D254060F5F23B4D744B40406C06B82063254030E44A3D0B764B40C02634492C7925403835B401D87A4B40E017080264882540F80241800C7D4B40C0D58F4DF28B2540301A6B7F677D4B40E08FDB2F9F942540D0FA5B02F07D4B40C07C410B09982540F89600FC537E4B4080D026874F9A2540B077F17EDC7E4B40E0E5E8F17BB325406031957EC2854B40C0116DC7D4C52540381A6B7F678D4B40C05758703FC82540B05FE97C788E4B40604E7CB5A3D02540D8EE5701BE914B4000EFAB72A1D22540D0B837BF61924B40A01D71C806DA2540D87954FCDF934B40C05A99F04BDD254028F6D03E56944B400009C38025DF2540A8BF97C283944B4080DF6B088EE32540600DFB3DB1944B40000473F4F8E525408087A2409F944B40205C8FC2F5E8254088A86DC328944B40A01EA33CF3EA2540906308008E934B408091088D60EB2540584CDE0033934B40A01EA33CF3EA2540001E8A027D924B40C06E2EFEB6DF2540A8622AFD848B4B4020F52D73BADC2540508BC1C3B4894B40206BD44334D22540D0C77C40A0834B404023DA8EA9CB254030EACC3D24804B40C06BED7DAACA2540B06E2EFEB67F4B402051BD35B0C52540D8C43BC0937E4B4000D9D0CDFEC025408896E7C1DD7D4B40E085048C2EB72540D87954FCDF7B4B40A0035ABA82AD2540302F3201BF784B40E0A16131EA92254090423D7D046C4B4080DF6B088E832540A8DDAF027C634B400103000000010000002400000060A148F7731A2E40905704FF5B7F4B4040295C8FC2152E40B85626FC527F4B40C0069B3A8FE22D40588BC1C3B4814B4080DF6B088EC32D40302CF180B2834B4040E3A7716F7E2D4030172AFF5A884B40A0978A8D79752D406073B9C150894B4080BEA085045C2D40B0716F7EC38C4B400007B474055B2D40000341800C8D4B40A0116DC7D4652D40B0622AFD849B4B40E0A7E331037D2D40101B498270A54B40C051D66F267E2D40B89509BFD4A54B40000D36751E852D40903FFCFCF7A64B4000AE65321C872D4080A52C431CA74B40E0E7154F3D8A2D4080A52C431CA74B40C0737E8AE3982D40E8A6B1BD16A44B40804278B4719C2D400815C78157A34B40C0E1934E24A02D40381DACFF73A24B40C0703D0AD7A32D4030F911BF62A14B404048FAB48AA62D40C8F71A82E3A04B40A032384A5EAD2D40E08558FD11A04B4000B728B341C62D40B8B6D4415E9D4B40C0955D30B8FE2D40909C69C2F6974B40C08B868C47212E4038D505BCCC944B406051BD35B0252E4000BEDBBC71944B4060DC2A88812E2E40D87954FCDF934B400038A110013F2E40286211C30E934B4020895E46B1442E40301DACFF73924B40E05758703F482E40D8EE5701BE914B40C0A6B1BD164C2E40A0E0F08288904B40C0CCCCCCCC4C2E4050793BC2698B4B40E0D58F4DF24B2E405082FE428F8A4B4000D34ECDE5362E402014E97E4E834B40E0311F10E8342E40B8E67283A1824B40206E15C440272E4030EACC3D24804B4000BC783F6E1F2E40F020CB82897F4B4060A148F7731A2E40905704FF5B7F4B40010300000001000000110000008032384A5EED2040D8D03FC1C5AA4B40C0D38041D2E7204008D061BEBCAA4B408018213CDAE02040B8622AFD84AB4B4080BEA08504DC204038232E008DAC4B40A0FA96395DCE2040B0656B7D91B04B40E0AD65321CC72040881EA33CF3B24B4080129F3BC1B6204010D9243FE2B94B408000193A76B820404807793D98BA4B4080C763062ABB204028E78BBD17BB4B40E079008BFCC22040282CF180B2BB4B40603F373465C72040B87A32FFE8BB4B4080035ABA82CD2040D0F4D901D7BB4B40806BED7DAAEA2040D0C43BC093B64B40E0A6B1BD16EC2040E0FA5B02F0B54B40A05DDA7058F22040E0F4D901D7AB4B40207497C459F12040286211C30EAB4B408032384A5EED2040D8D03FC1C5AA4B400103000000010000006500000040EC6AF2947D2540D0CDFE40B9BD4B40A0716F7EC3942540B0DA6E826FAE4B40206552431BA82540286E15C440A74B40C091088D60AB2540B068ACFD9DA54B4000B0743E3CAB2540386893C327A54B40A00F5EBBB4A12540C053E57B469A4B40C08C9AAF929F25405837177FDB974B40606BD44334922540F817080264904B4000301004C8902540A8E9B303AE8F4B408020B248138F2540A8A44E40138F4B402007B474057B2540786649809A884B40C038BA4A77772540584F1F813F884B4020E6E8F17B732540809C69C2F6874B4080716F7EC3542540104E2844C0874B40E0A9F23D2341254008D3A23EC9874B40804B3B35973B2540104E2844C0874B4040EFAB72A1322540D0BB783F6E874B40E0DE52CE172B2540508E0244C1864B40A020B248130F2540909065C1C4834B4020356090F4092540582B137EA9834B40A077F17EDCFE2440302CF180B2834B40602975C9384E24405034D6FECE8A4B4020CDE506434524406040DAFF008F4B40A07F828B154D244060853FC39B8F4B40A020B248134F2440504F1F813F904B40602975C9384E244030E109BDFE904B4000CDCCCCCC4C244030266F8099914B4020F52D73BA3C244028DB87BCE5964B408038BA4A773724405837177FDB974B40401E8A027D322440D08558FD11984B40C079008BFC022440282F3201BF984B40E0AF743E3CCB23408015E0BBCDA34B40C0DE52CE17CB2340F8230C0396A44B4000FBAF73D3C6234020E78BBD17AB4B40E0B628B341C623409015E0BBCDAB4B400009C380259F23402838F581E4B74B40200F45813E892340889065C1C4BB4B40C0E4D4CE30752340500DFB3DB1BC4B40E0955D30B85E2340B877F17EDCBE4B40609885764E5B234038F38FBE49BF4B40005DC136E25923403838F581E4BF4B4020B1A6B2285C2340607C7C4276C04B40E0EA56CF497F2340306893C327C54B40C0B2B5BE48A0234000E5284014C64B40E00373F4F8A5234028E44A3D0BC64B4000E8154F3DAA2340E0CDFE40B9C54B40E091088D60AB2340E088997D1EC54B400023DA8EA9AB2340A0622AFD84C34B40C0CCCCCCCCAC2340B0984A3FE1C24B4060573F36C9AF2340A0B915C26AC24B40A05FE97C78B6234030266F8099C14B404054FEB5BCBA2340D00F238447C14B40A0F4143944C42340302F3201BFC04B4020B937BF61CA2340602E54FEB5C04B4060D367075CCF2340302F3201BFC04B4060BC9179E4D72340F80E45813EC14B402009C38025DF2340783CBB7CEBC14B40A01D8CD8270024405840852348C54B4080116DC7D4252440386E15C440C74B40002FDE8FDB3F2440582E54FEB5C84B4000A7B1BD164C244010C11C3D7EC94B40E0ED974F5654244080A2EBC20FCA4B400007B474055B24406034D6FECECA4B40E0CCCCCCCC6C244048888043A8CC4B4000EE974F56942440808D2441B8CE4B40206684B70799244008DC65BFEECE4B4000C53BC0939E2440803FFCFCF7CE4B404021CB8289A72440109700FC53CE4B408059677C5FCC2440089A417C60CB4B4020861DC6A4CF2440881EA33CF3CA4B40E04D637B2DF8244070A86DC328C44B40401E8A027DF22440783CBB7CEBC14B400021CB8289E724400048A643A7BD4B4040634337FBE32440785182FE42BD4B400007B47405DB2440B87A32FFE8BB4B40A04D637B2DD8244060FEB5BC72BB4B40200341800CD52440583D997FF4B94B4020295C8FC2D52440000F45813EB94B40A085048C2ED7244008CADFBDA3B84B40205DC136E2D9244028EACC3D24B84B40A021E4BCFFDF2440D000DE0209B84B40E009F5F411F02440889C69C2F6B74B40000341800CF52440E08558FD11B84B404015C7815733254030327381CBBD4B40C08EC70C5436254080AEEFC341BE4B40C0C98B4CC03725403841B8020ABF4B4040A148F7733A2540001E8A027DC24B40C0B0A6B2283C254080C9C6832DC84B40C06ABB09BE392540D8F4D901D7CB4B4000D34ECDE5362540D888997D1ECD4B4000321F10E8342540D8CDFE40B9CD4B4080E2AC889A3825405040DAFF00CF4B4080D026874F3A2540D009A1832ECF4B4000A8E331033D2540306E15C440CF4B40A0D8D0CDFE40254008DC65BFEECE4B40005A80B6D54425408048BF7D1DCE4B4020013274EC502540B0622AFD84CB4B40C05417F03253254078992842EACA4B40606893C3277D2540888461C092BF4B40E0C43BC0937E2540B877F17EDCBE4B4040EC6AF2947D2540D0CDFE40B9BD4B400103000000010000001A000000E0CABDC0AC282940E0C43BC093C64B40C0F4143944242940009700FC53C64B4000965D30B81E2940A85FE97C78C64B40A014AE47E11A2940D0F19881CAC64B4080BC9179E4172940386E15C440C74B40C076BF0AF00D29405073B9C150C94B408091088D600B294028D8463CD9C94B40205C8FC2F5082940D0D03FC1C5CA4B40000473F4F80529400848A643A7CD4B4040C422861D06294038E44A3D0BCE4B40E0AD65321C07294058FB743C66CE4B40008E3D7B2E0B2940B82E35423FCF4B40C06ABB09BE192940D8C1FA3F87D14B40205FD042021E294030F04E3E3DD24B40206552431B282940505260014CD54B40A02975C9382E2940E009A1832ED74B40C08EC70C5436294050465C001AD94B40C02FF7C951382940D87C957CECD84B40207A19C5723B2940D88558FD11D84B4020D270CADC4C2940A814ADDC0BD24B40C0978A8D7955294008DC65BFEECE4B4040D026874F5A294048888043A8CC4B40A09885764E5B294008DFA63FFBCB4B40007A19C5725B2940F8C69E3D97CB4B40A01D71C8065A29401015C78157CB4B40E0CABDC0AC282940E0C43BC093C64B400103000000010000002000000060B950F9D7422540D8F19881CAEE4B4040F2ECF2AD47254010C45DBD8AEE4B40A050A4FB394D254010C45DBD8AEE4B40007497C459512540E876137CD3EE4B4020C87C40A053254010BB9A3C65EF4B4040321F10E854254088C9C6832DF04B4000DDD1FF72552540086F0F4240F24B40E0978A8D79552540D88558FD11F04B4080716F7EC3542540E009A1832EEF4B4080D026874F3A2540608BC1C3B4E14B40E05626FC52372540100F45813EE14B404015C78157332540385C8FC2F5E04B40A0C3094CA72D2540385C8FC2F5E04B40C0D24ECDE5162540B05CA8FC6BE14B402045B9347E11254028266F8099E14B402069C537140E2540A8A10DC006E24B40C00C1D3BA80C2540B86BED7DAAE24B40200473F4F80525403829B000A6E64B40200473F4F8052540D0BB783F6EE74B4000180802640825405870784144FC4B4000A7B1BD160C2540A068ACFD9DFD4B4020321F10E8142540B8A44E4013FF4B40802FF7C951182540A8BC564277FF4B40407156444D1C2540F84D2844C0FF4B40C021E4BCFF1F25403820ED7F80FF4B400009C380251F25403829B000A6FE4B40001B4982701D2540D87FD6FCF8FD4B4020A8E331031D2540B0A78FC01FFC4B402038A110011F2540603D997FF4F94B40E01A4982703D2540084E2844C0EF4B40E0BB783F6E3F2540586D37C137EF4B4060B950F9D7422540D8F19881CAEE4B400103000000010000001A010000803579CA6A2229405840DAFF00FF4B4040D367075C0F2940A0C2D84290F94B40807F828B150D2940B0656B7D91F84B4000CBBDC0AC082940A85FE97C78F64B4000A5A2B1F607294010CD203EB0F54B40C074B0FECF09294058888043A8F44B40801A2FDD241E2940D8703C9F01EF4B40C053E57B462229406031957EC2ED4B4020C422861D26294028232E008DEC4B4020FBAF73D3262940E00CE2033BEC4B40207497C45931294070AEEFC341E64B40E01D8A027D322940580438BD8BE54B40E05417F032332940286BD44334E24B402015C78157332940B0656B7D91E04B40C0DE52CE172B29408848BF7D1DDE4B40C0A16131EA3229409081204086DA4B402015C78157332940D006600322DA4B40C0B3E73235312940D0C1FA3F87D94B4000BC783F6E1F2940B0B6D4415ED54B4080AA0B7899192940A8A78FC01FD44B4000321F10E81429403814E97E4ED34B40A059677C5F0C294040D8463CD9D14B40C05CA8FC6B0129408893A641D1D04B4020E3A7716FFE28400848A643A7CD4B4020CEFE40B9FD2840585260014CCD4B40A0BEA08504FC2840E0031F8315CD4B40C02634492CF92840809FAA4203CD4B40809E077767E52840C8B5F63E55CD4B4080B08D78B2E32840001B498270CD4B40C082C30B22E22840D8CDFE40B9CD4B402009C38025DF28406028D2FD9CCE4B40201B498270DD2840E0F19881CACE4B4060BC9179E4D7284038DB87BCE5CE4B40C06DFC89CACE284008DC65BFEECE4B404018080264C8284000C45DBD8ACE4B40C079008BFCC2284010E5284014CE4B40A09BC6F65AB02840A87A32FFE8CB4B4040BB6070CDAD284098F3C5DE8BCB4B4040356090F4892840B8E9B303AEC74B40800F5EBBB4812840888D2441B8C64B40206893C3277D2840B0E3310395C54B40C0F0D8CF62692840E0B2B5BE48C04B4020D6A88768642840608E0244C1BE4B40E082C30B22622840D0CDFE40B9BD4B40A00F5EBBB4612840785182FE42BD4B40C03E3C4B9061284008C79E3D97BB4B40A0C64ACCB36228404807793D98BA4B4040634337FB63284010D9243FE2B94B40402A8E03AF662840E07C957CECB84B40A074B0FECF692840306552431BB84B40E0D03FC1C5722840508E0244C1B64B404020990E9D762840109700FC53B64B406000193A76982840F8C69E3D97B34B40C017EFC7EDAF284058793BC269B34B4080D026874FBA2840206211C30EB34B406018213CDAC028405007793D98B24B40A03BFBCA83CC284000301004C8B04B40404278B471DC2840081286014BAE4B4000EB56CF49DF28406831957EC2AD4B4080FDD7B969E3284008240C0396AC4B40803F373465E72840286211C30EAB4B40C05758703FE828408854C37E4FAA4B4060BFD2F9F0EC284008A0C37C79A54B40C059677C5FEC284058888043A8A44B40200473F4F8E52840009A417C60A34B40A079008BFCE22840B8984A3FE1A24B40C01D71C806DA284000C11C3D7EA14B40C05417F032D32840382F3201BFA04B40A01EA33CF3AA284008E52840149E4B402048FAB48AA628408096E7C1DD9D4B40803E3C4B90A1284038327381CB9D4B40C05FE97C78962840A89509BFD49D4B40E0622AFD848B2840E0FA5B02F09D4B4080B5DD04DF7C2840109700FC539E4B40206552431B68284038ED0DBE309D4B40201077F52A5A2840E00CE2033B9C4B40401E8A027D122840E8AC33BE2F964B40C07F828B150D284008CD203EB0954B4040F2ECF2AD07284050888043A8944B40202A8E03AF06284058F5F23B4D944B406048FAB48A062840A87A32FFE8934B40202A8E03AF062840B8622AFD84934B4000D48041D2072840E0AF743E3C934B40000F45813E092840D882177D05934B40C0CDFE40B91D284008E2E7BF07914B40A03E3C4B90212840602E54FEB5904B400077D844662628405001F73C7F904B40803BFBCA832C28405001F73C7F904B4000B4E73235312840B8656B7D91904B40C014AE47E13A284030E109BDFE904B4080B950F9D742284050465C001A914B40C03BFBCA834C2840D0CABDC0AC904B4040B3CEF8BE582840B86E2EFEB68F4B40E02CCF83BB5B2840A85626FC528F4B4000F52D73BA5C28406040DAFF008F4B40A0B5DD04DF5C28405828D2FD9C8E4B40A0737E8AE358284010CADFBDA3804B4080E2AC889A58284080C9C6832D804B4080BC9179E45728405837177FDB7F4B40E0B5F63E55552840D8BB783F6E7F4B40E0B3E73235512840B8A44E40137F4B40405A80B6D524284008DFA63FFB7B4B40000341800C152840382CF180B27B4B4000FBAF73D306284038DEC83CF27B4B40401B498270FD274028F6D03E567C4B40E0311F10E8F42740D0B5F63E557D4B40406552431BE827405837177FDB7F4B404077D84466E62740D000DE0209804B4080F4143944E42740604F1F813F804B4000BC783F6EDF2740009D82FC6C804B40A07A32FFE8D32740806649809A804B40C0AA24B20FD22740009D82FC6C804B40C01EA33CF3CA274020DB87BCE57E4B40E089592F86CA27409060C77F817E4B40002C9D0FCFCA2740E8AC33BE2F7E4B406015FF7744CD2740E8C039234A7D4B40E04D637B2DB82740E073D2FBC6814B40A02975C938AE2740D8FD9C82FC824B40E0DB114E0B762740104E2844C0874B4040013274EC902740205C8FC2F5904B40A000193A7698274038DEC83CF2934B40607A19C5727B2740805D86FF74994B4020AD33BE2F76274078A2EBC20F9A4B4080A48977806F2740281DACFF739A4B40E09E758D96632740A8C62FBC929A4B40009F20B1DD5D2740D8066003229A4B4060C1E10511512740909C69C2F6974B4040D9E90775392740909C69C2F6974B4060C763062A1B2740009D82FC6C984B40E0DB114E0B162740E0CABDC0AC984B4000931CB0AB09274028266F8099994B402018080264E82640504CDE00339B4B40E006B47405DB2640D0C77C40A09B4B4080978A8D79D52640D0C77C40A09B4B4080BFD2F9F0CC2640784B00FE299B4B40E0C77C40A0B32640E073D2FBC6994B40609E077767A526400818080264984B4020F52D73BA9C264080C9C6832D984B404023DA8EA98B2640E0CABDC0AC984B402077D84466862640D0F71A82E3984B40A03E3C4B90812640D8A9F23D23994B40001286014B7E264098C2D84290994B40E0A7E331037D2640D08BDAFD2A9A4B40E0E1934E24602640109A417C60AB4B4020861DC6A46F2640E0B837BF61B24B40A0F1D3B8376F264030E78BBD17B34B40005858703F682640905D86FF74B94B40A059677C5F4C264010CADFBDA3C84B4020356090F4492640903CBB7CEBC94B40E0C3094CA72D264000D6E3BED5D44B40002C9D0FCF2A26405831957EC2D54B404048FAB48A2626409048BF7D1DD64B4000A8E33103FD254000CADFBDA3D84B40A0069B3A8FC22540A8B6D4415EDD4B4000EB56CF49BF25405031957EC2DD4B40A03E3C4B90C12540009700FC53DE4B40C0B628B341C625408060C77F81DE4B40A091088D60CB25406828D2FD9CDE4B40C00F5EBBB4E12540E0C43BC093DE4B4000A5A2B1F6E72540A85FE97C78DE4B40E053E57B46422640B859677C5FDC4B4080BB5F05F84626400015C78157DB4B40C02975C9384E26406007793D98DA4B40E08EC70C54562640503D997FF4D94B406018213CDA60264000C11C3D7ED94B4060BB5F05F866264058F833BC59D94B40E0A6B1BD166C2640885D86FF74D94B4020573F36C9AF2640B8E9B303AEDF4B40A0F755B950F92640002DCF83BBEB4B400052D66F26FE2640603A58FFE7EC4B404000000000002740A0E3310395ED4B40802CB649450327405040DAFF00EF4B40000473F4F8052740B8656B7D91F04B40606552431B082740E08BDAFD2AF24B400018080264082740D0FD9C82FCF24B4020CDE50643052740709FAA4203F54B4000634337FB032740A868ACFD9DF54B40202DCF83BBFB2640A8A44E4013F74B40000341800CF52640A09B8BBFEDF74B4040301004C8F02640504F1F813FF84B40200473F4F8E5264010CADFBDA3F84B40A03579CA6AC2264080ABAE4335F94B40C04D637B2DB8264010C11C3D7EF94B4060C1E1051191264028F6D03E56FC4B40C0FA96395D8E264008D6E3BED5FC4B40C059677C5F8C2640B8B6D4415EFD4B40E0D58F4DF28B264010DC65BFEEFE4B40A0E1934E24A02640A8E3310395FD4B406045B9347ED12640286211C30EFB4B40A05FE97C783627405837177FDBF74B40400C040132542740B8E0F08288F84B4020931CB0AB692740608BC1C3B4F94B40E06ABB09BE7927406034D6FECEFA4B40C05A99F04B7D2740504CDE0033FB4B40A05CA8FC6B81274058FEB5BC72FB4B40C0AD65321C872740A8DDAF027CFB4B400023DA8EA98B2740804B00FE29FB4B40A0AD4CF8A58E2740B86BED7DAAFA4B40809BC6F65A902740E006600322FA4B4060DC2A88818E2740B05CA8FC6BF94B400054FEB5BC7A2740D0FA5B02F0F54B40E085048C2E572740283E7782FDF14B40A05626FC52572740884E417E36E84B4040D367075C6F2740580438BD8BE54B4020BFB9BF7A742740D8CDFE40B9E54B40C085048C2E77274000CD203EB0E54B40006684B707792740607FBDC282E54B4040EC6AF2947D2740B059677C5FE44B4000A5A2B1F687274048465C001AE14B4040D9E90775992740809C69C2F6D74B4080AA0B78999927400021CB8289D74B40C044F5D6C0962740500DFB3DB1D44B4080B08D78B2A327405876FA415DD64B40000D36751EA527405828D2FD9CD64B40202A8E03AFA62740805704FF5BD74B40C01D71C806AA2740E8DF12807FDA4B408017EFC7EDAF274030D8463CD9E14B40802975C938CE27408060C77F81F64B4080A4897780CF2740588E0244C1F64B40E04B546F0DD427406040DAFF00F74B40A0AA0B7899D9274028DB87BCE5F64B4000D00D4DD9E12740009700FC53F64B4020B0743E3CEB2740381A6B7F67F54B4080F755B950F927407815E0BBCDF34B40007156444DFC27400015C78157F34B40E0BB783F6EFF2740081E8A027DF24B4000261B0FB6002840A874B0FECFF14B4000AB24B20F122840606D37C137E74B4080716F7EC3142840580438BD8BE54B40204278B4711C284080C9C6832DE04B40206893C3271D28406040DAFF00DF4B4080B5DD04DF1C2840A8AD11C138DE4B4000FEF0F3DF1B2840081B498270DD4B40A01D71C8061A2840B8ECF483BADC4B40C05626FC52172840D80CE2033BDC4B40A017EFC7ED0F2840906308008EDB4B406032384A5E0D2840A8DDAF027CDB4B40A01A3048FA042840906308008EDB4B4040013274ECF02740E0F4D901D7DB4B40E08C9AAF92DF27403029B000A6D64B400009C38025DF2740E0C77C40A0D34B40E05A99F04B1D2840E0C77C40A0D34B40C06E2EFEB61F2840E00CE2033BD44B4080F1D3B8372F284028F911BF62D94B40400AF5F411302840E082177D05DB4B4080F1D3B8372F2840D8BEB9BF7ADC4B4080DC2A88812E284028ED0DBE30DD4B4060BFD2F9F02C2840E0C43BC093DE4B40203C1405FA24284060469561DCE14B40C068ACFD9D152840F847A643A7F54B40A0ED974F56142840081286014BF64B400021CB8289072840E0B837BF61FA4B40E0703D0AD70328406034D6FECEFA4B40C0B5F63E55F52740281DACFF73FA4B40E051D66F26DE274028266F8099F94B40200473F4F8C52740A09B8BBFEDF74B40A0656B7D91C02740D0D38041D2F74B40604B3B3597BB2740909C69C2F6F74B40000341800CB527409093A641D1F84B40401E8A027DB227405873B9C150F94B4060C1E10511B12740903CBB7CEBF94B40A05DDA7058B22740084BE7C3B3FA4B40A07C410B09B82740082DCF83BBFB4B40609885764EBB2740B0A78FC01FFC4B400020990E9DD6274028F38FBE49FF4B40A02634492C592840905182FE420D4C406048FAB48A6628405076FA415D0E4C4000CDCCCCCC8C2840D8B2B5BE48104C40C0716F7EC39428405001F73C7F104C4060A148F7739A2840587C7C4276104C40C021E4BCFF9F2840D8B2B5BE48104C4000931CB0ABA928403038F581E40F4C40206E15C440072940E8AF743E3C0B4C40E0B3E732351129406055A181580A4C4060AA0B789939294030327381CB054C4080B5DD04DF3C2940B0B6D4415E054C40805A99F04B3D2940080341800C054C40404278B4713C294038F6D03E56044C40000AF5F411302940806649809A004C40C0DE52CE172B2940B89B8BBFEDFF4B4060809BC58B252940A8BC564277FF4B40803579CA6A2229405840DAFF00FF4B400103000000010000000A000000A00F5EBBB42127409096E7C1DD554C4000A8E331031D274010CD203EB0554C40C038BA4A771727409096E7C1DD554C40803E3C4B90012740A874B0FECF594C40C00F5EBBB40127405807793D985A4C4020CDE50643052740E0FD9C82FC5A4C406048FAB48A462740A8BF97C2835C4C40A015E0BBCD4B274008240C03965C4C4020A7B1BD164C274088A86DC3285C4C40A00F5EBBB42127409096E7C1DD554C400103000000010000002800000080D9E90775D92140B0E3310395754C40A0C2137AFDC12140B8AD11C138664C4000931CB0ABA921400009C380255F4C40C0E7154F3D8A214008301004C8584C4000CBBDC0AC882140886649809A584C40201B4982707D2140789C69C2F6574C40A02FF7C951782140084E2844C0574C4060A48977804F2140101286014B564C4040C422861D462140100F45813E594C40C0716F7EC3342140503A58FFE75C4C4040261B0FB62021405076FA415D5E4C40A0BEA085041C2140D8C43BC0935E4C40C01B62BCE615214008C45DBD8A5E4C40600C1D3BA80C2140A868ACFD9D5D4C4020068200190A2140B0E33103955D4C40406E15C44007214008CD203EB05D4C4060809BC58B052140801B62BCE65D4C4020895E46B104214058499D80265E4C40A01A3048FA04214010DC65BFEE5E4C40C009DCBA9B172140580438BD8B654C4000F05014E83B214010759142596A4C40C0622AFD844B2140A0C2D84290714C40E0CCCCCCCC4C214030D8463CD9714C4040013274EC5021401006820019724C40A05FE97C78562140B053E57B46724C40605A80B6D5642140306BD44334724C408038BA4A77772140301DACFF73724C4040D026874F7A21409081204086724C40E0656B7D91A02140E0F4D901D7734C40A03579CA6AA2214058431B800D744C40C0AD65321CA72140D0031F8315754C40A0C3094CA7AD2140004E2844C0774C40E0311F10E8B42140B874B0FECF794C4000AD33BE2FB6214008068200197A4C40A04D637B2DB82140C053E57B467A4C400007B47405BB21408054C37E4F7A4C40800C1D3BA8CC2140C053E57B467A4C40A05DDA7058D2214038F911BF62794C4080D9E90775D92140F8E4284014764C4080D9E90775D92140B0E3310395754C4001030000000100000028020000E0AFAE0AD4F22340E009A1832E894C40E0EA56CF493F24406055A18158824C40E0AF743E3C4B2440305C8FC2F5804C40604E7CB5A35024400818080264804C4040FEF0F3DF5B2440306E15C4407F4C40209CDF30D168244058FB743C667E4C4020861DC6A46F2440D87FD6FCF87D4C40E0311F10E87424406031957EC27D4C40209F20B1DD7D244000CD203EB07D4C4060D5592DB09F244098B7955E9B7D4C4040E6E8F17B932440B0B05241457B4C40407D5A457F90244000D9243FE2794C40C091088D608B2440D8C43BC093764C40A074B0FECF892440301A6B7F67754C40C0F0D8CF62892440F02CCF83BB734C408017EFC7ED8F2440808AE3C0AB694C40401E8A027D9224406028D2FD9C664C4020A26131EA92244088AEEFC341664C40407156444D9C2440004E2844C05F4C4040C763062A7B2440D87954FCDF5B4C40E0264D83A2512440D00CE2033B5C4C40A020B248134F244088A86DC3285C4C40804B3B3597BB2340D0AF743E3C534C4060116DC7D4C52340C88BDAFD2A524C4020CEFE40B9DD2340D006600322524C40E0CF0D4DD9012440A859677C5F544C400021CB8289272440D0D38041D2574C400054FEB5BC5A2440E0A9F23D23594C40C0CF0D4DD9A1244050465C001A594C40A032384A5EAD244030E109BDFE584C4080B81E85EBB12440B0B393C151584C4000321F10E8B4244010BB9A3C65574C4020E2AC889AB8244030327381CB554C40A0F755B950B92440000341800C554C40401077F52ABA24405082FE428F524C40401077F52ABA2440D873D2FBC6514C40A009DCBA9BB724409018213CDA504C40C088433690AE2440002EE57CB14F4C40A0435376FAA92440B8984A3FE14E4C4080A6B4FE96A824403029B000A64E4C40C0E1934E24A024408845459C4E4E4C40801074B4AA9D2440408908FF224E4C40E0AA24B20F92244090397AFCDE4C4C40E0D58F4DF28B2440A07A32FFE84B4C40E0CDFE40B97D244038F911BF62494C40000AF5F411702440C8F19881CA464C40C015E0BBCD6B244030232E008D444C4000E2934E24602440F8DEA63FFB3B4C4000AD33BE2F76244020232E008D3C4C4000999EB0C47324405828D2FD9C3E4C4000D13FC1C5722440D8F71A82E3404C4040EFAB72A1722440503A58FFE7444C40801B62BCE6752440F89600FC53464C40A02634492C792440B077F17EDC464C4040C64E78099E2440C071361D014A4C40003561FBC9A82440B87D737FF5484C40E0B8382A37A92440881E15FF77484C40C038BA4A77B72440889C69C2F6474C4020E2AC889AB82440500ABABDA4474C4000F52D73BABC2440D876137CD3464C40C0ED974F56D4244000C79E3D97434C40601D71C806DA244038E78BBD17434C40A0A7CAF78C04254028F911BF62414C4080A48977800F254078457EFD10414C40C0622AFD842B2540885D86FF74414C40202C9D0FCF4A2540D8D03FC1C5424C40C0D38041D287254088A86DC328444C40E0A16131EA922540B859677C5F444C4040CAA48636B02540286211C30E434C4000999EB0C4B32540B86BED7DAA424C40A0B3CEF8BEB82540B0A10DC006424C40E0955D30B8BE2540D8A9F23D23414C40C0D58F4DF2EB2540285C8FC2F5384C40807F828B15ED2540584F1F813F384C40E0C98B4CC0D7254008DFA63FFB2B4C40604E7CB5A3D0254080A2EBC20F2A4C40001B4982707D2540B09ECC3FFA144C40406684B707592540D000DE0209184C40C0CDFE40B95D2540884E417E36184C40C0BB783F6E5F25408018213CDA184C40603579CA6A622540B0B915C26A1A4C40A053E57B46622540904B00FE291B4C40A03E3C4B90612540E87954FCDF1B4C4040E3A7716F5E254068F5F23B4D1C4C40A08EC70C54562540809FAA42031D4C40A0622AFD844B2540B0B6D4415E1D4C4080116DC7D4452540B0B6D4415E1D4C4020B3B5BE4840254088CC07043A1D4C40207156444D3C2540A89ECC3FFA1C4C40A0737E8AE33825408887A2409F1C4C40C076BF0AF02D254080812040861A4C40407156444D1C25403829B000A6164C40C02634492C192540585260014C154C406000193A76182540D0BEB9BF7A144C40405DC136E21925409015E0BBCD134C40002DCF83BB1B2540504CDE0033134C40601A3048FA24254030E109BDFE104C40C0D38041D2272540004E2844C00F4C40E0298E03AF26254000DC65BFEE0E4C4080A7CAF78C24254080AEEFC3410E4C4020965D30B81E2540905182FE420D4C40607A19C5721B2540583A58FFE70C4C40C038BA4A7717254058888043A80C4C40E05DDA7058122540F8230C03960C4C40A059677C5F0C25408087A2409F0C4C40E0D38041D2072540583A58FFE70C4C4000F2ECF2ADC72440B0ECF483BA144C40C0716F7EC3B4244028E109BDFE184C40C038BA4A77B72440B0C2D84290194C40A014AE47E1DA244068F5F23B4D1C4C40806E2EFEB6DF2440805A457F681C4C40C0069B3A8FE2244030DEC83CF21B4C40E0978A8D79F52440E00CE2033B1C4C40A0F4143944042540803CBB7CEB214C40C0703D0AD7032540A86BED7DAA224C40E0D8D0CDFE00254028E78BBD17234C404051BD35B0E52440A8B6D4415E254C40E07F828B15CD244080CC07043A254C40A0F545425B7E244090D558C2DA164C40A0129F3BC1762440D0B5F63E55154C4060CAA4863670244060793BC269134C40A0AD4CF8A56E2440084BE7C3B3124C400069C537146E244000D9243FE2114C4080C1E10511712440886649809A104C40E07A32FFE8732440386552431B104C4060D026874F7A2440206E15C4400F4C4000A8E331037D2440888D2441B80E4C40A079008BFC822440D80CE2033B0C4C40400473F4F8852440306BD443340A4C40A0F1D3B8378F2440B0B915C26A024C4000D9D0CDFE802440B89509BFD4F54B40402FDE8FDB7F2440709FAA4203F54B4080B950F9D7622440B8E67283A1EA4B408018213CDA602440303E7782FDE94B4000CEFE40B95D2440B0C2D84290E94B4020E2AC889A58244040D8463CD9E94B40A07F828B154D2440B8984A3FE1EA4B4020931CB0AB4924403814E97E4EEB4B40E0D38041D2472440B87A32FFE8EB4B406077D84466462440F8230C0396EC4B40400D36751E452440D07FD6FCF8ED4B4060B08D78B24324403029B000A6EE4B40A018213CDA4024401009C38025EF4B40E05A99F04B3D2440908461C092EF4B4000DC114E0B362440E0B2B5BE48F04B40E009F5F411302440607C7C4276F04B40E0BB783F6E1F2440607C7C4276F04B4040D9E90775192440583ACAC16CF04B40C022F8DF4A062440682E1B9DF3EF4B4060C554FA09F72340908461C092EF4B40001286014BBE234040D505BCCCEC4B4020C763062ABB234038F6D03E56EC4B4060BEA08504BC2340E0C77C40A0EB4B40E0BB783F6EBF2340D8AF743E3CEB4B4080B08D78B2C3234090992842EAEA4B40009CDF30D1C82340B06BED7DAAEA4B408000193A76D8234078A2EBC20FEA4B4000931CB0ABE9234020266F8099E94B402000000000002440F08AE07F2BE94B40E08FDB2F9F142440A8656B7D91E84B4080737E8AE3182440604F1F813FE84B40A038BA4A77172440D800DE0209E04B40207156444DFC234028F04E3E3DDA4B40C074B0FECFA92340D8FA5B02F0D54B40E08C9AAF929F2340F8CC203EB0D54B406054FEB5BC9A234030327381CBD54B4040BB7D5699792340B071A8DF85D74B4020C879FF1F772340F85DBC1FB7D74B404068AED3487323401890680245D84B40C0E1934E2460234088A2EBC20FDA4B40C07C410B0958234008D061BEBCDA4B40800C1D3BA84C2340306211C30EDB4B4020AE65321C472340306211C30EDB4B40C05A99F04B1D234008D061BEBCDA4B4040AA0B78991923405855A18158DA4B402007B474051B2340788AE3C0ABD94B40009F20B1DD1D2340B0AAD0402CD94B4060C2137AFD212340E0F71A82E3D84B40000473F4F8252340382F3201BFD84B402023DA8EA92B2340382F3201BFD84B40002DCF83BB3B2340285C8FC2F5D84B40403F373465472340D0CABDC0ACD84B40A02975C9384E23403838F581E4D74B40809BC58B85712340E8E49A0299D34B40A0FDD7B969A32340301A6B7F67CD4B4000E929728868234010DFA63FFBC34B4080A48977802F234000C45DBD8AB64B40C050A4FB392D2340D87FD6FCF8B54B40E0CCCCCCCC2C2340E0031F8315B54B40C02975C9382E2340B8BF97C283B44B40006BD4433432234058793BC269B34B40400341800C352340A8984A3FE1B24B404022FDF675382340F81D8A027DB24B40005517F032332340089D82FC6CB04B4040274D83A231234010D3A23EC9AF4B408045B9347E3123405840DAFF00AF4B40E01D8A027D52234040D505BCCCA44B4000295C8FC255234028DEC83CF2A34B40A0B3CEF8BE582340B0DDAF027CA34B40C051D66F265E234088992842EAA24B4040DF6B088E632340A8B915C26AA24B4040356090F4692340283E7782FDA14B4020A7B1BD166C2340A05CA8FC6BA14B40C00C1D3BA86C234088457EFD10A14B40C059677C5F6C2340885704FF5B9F4B40E088450C3B6C234008DC65BFEE9E4B4080622AFD846B2340D0C43BC0939E4B40A0656B7D9160234080ABAE4335994B40E0CDFE40B95D234010CADFBDA3984B4060D026874F5A2340A8B393C151984B40406BD44334522340B06E2EFEB6974B4060BB5F05F84623400009C38025974B4060A7CAF78C442340386E15C440974B40001B4982703D2340507C7C4276984B40C0129F3BC13623408893A641D1984B40A0FA96395D2E2340582E54FEB5984B402021CB82892723400818080264984B40C05CA8FC6B212340909C69C2F6974B406083DC4598FA224058FEB5BC72934B40C07F828B15ED2240587C7C4276904B40C0DE52CE17EB22406037177FDB8F4B40A03BFBCA83EC224080A52C431C8F4B40C0703D0AD7032340A8DA6E826F864B40C0737E8AE318234080A86DC328844B4080116DC7D44523400806820019824B4020CAA48636702340B85626FC527F4B40E0AA24B20F72234078A52C431C7F4B40E0BEB9BF7A7423403829B000A67E4B40A05626FC527723406831957EC27D4B40401286014B7E23405873B9C150794B40206E15C44087234050793BC269734B40200F45813E89234088A2EBC20F724B40A0E1934E24802340582B137EA96B4B40E0C43BC0937E2340D082177D056B4B40407156444D7C2340B0B915C26A6A4B4080D9E90775792340603D997FF4694B40E04B546F0D742340883CBB7CEB694B40A05CA8FC6B412340080341800C6D4B4000CEFE40B93D234010A0C37C796D4B4060A148F7733A2340283E7782FD714B4040D6A887684423400815C78157734B40C04E95EF19492340A8622AFD84734B4000B0743E3C4B2340E8A6B1BD16744B40C015E0BBCD4B2340B89ECC3FFA744B40E0921CB0AB492340500438BD8B754B4060BB5F05F846234030E44A3D0B764B40A0B08D78B2432340B8DA6E826F764B40E06ABB09BE392340E076137CD3764B40000C040132342340B877F17EDC764B4040861DC6A42F23402829B000A6764B40E05CA8FC6B0123401009C380256F4B40208A592F86EA22401015C781576B4B40A0D38041D2E72240A0984A3FE16A4B4060809BC58BE52240C053E57B466A4B404006BAF605E42240F88A6EBDA6694B40E0ED974F56D42240B06BED7DAA6A4B40205C8FC2F5C8224090992842EA6A4B4000D00D4DD9C12240386BD443346A4B4060B5DD04DFBC22405073B9C150694B4020F52D73BABC224088457EFD10694B40E0C98B4CC0B722408021E4BCFF674B4080A4897780AF22403820ED7F80674B40E0CF0D4DD9812240F020CB8289674B40604278B4717C22406001F73C7F684B408009DCBA9B772240E0C1FA3F87694B40A0716F7EC3742240D0D03FC1C56A4B408009DCBA9B772240E00CE2033B6C4B40A0D03FC1C5722240805182FE426D4B40C05FE97C78562240908D2441B86E4B40C0CF0D4DD9E12140B07A32FFE8734B40A0C554FA09D72140D80CE2033B744B40602F3201BFAE214090DBDAC2F3744B40E017080264A82140B89ECC3FFA744B40E05DDA7058922140F8DEA63FFB734B40002A8E03AF862140306211C30E734B40C03579CA6A8221402835B401D8724B40609BC6F65A70214088A2EBC20F724B4080C422861D662140B853E57B46724B40A0EA56CF495F2140306211C30E734B40C070033E3F5421404816A243E0744B40C0F1D3B8374F214008CD203EB07D4B40201077F52A5A21405828D2FD9C8E4B4020BC783F6E1F2140583A58FFE78C4B40C06E2EFEB61F2140A8A78FC01F8C4B402009C380251F2140A8B05241458B4B4080B5DD04DF1C2140A86BED7DAA8A4B40E082C30B22022140B09B8BBFED874B40209F20B1DDFD2040A86E2EFEB6874B4080AA0B7899F92040C800DE0209884B4000AD33BE2FF62040F89C82FC6C884B40207497C459F12040B85CA8FC6B894B4020861DC6A4EF2040B8984A3FE18A4B4000356090F4E920406037177FDB8F4B40806BED7DAAEA2040602E54FEB5904B40204E7CB5A3F020406831957EC2954B4020274D83A2F120409060C77F81964B4000E6E8F17BF32040606D37C137974B40C05626FC52F72040507C7C4276984B40C01D71C806FA2040305C8FC2F5984B40A02CB64945032140E00F238447994B4020CEFE40B91D21408018213CDA984B40A0B950F9D7222140282F3201BF984B408015E0BBCD2B214030EACC3D24984B4080A48977802F2140004E2844C0974B40E0C3B46FEE2F2140F021533E04974B40E050A4FB392D2140D8C43BC093964B40C03579CA6A222140B0E3310395954B40008D9AAF921F2140D0031F8315954B40604B3B35971B2140809065C1C4934B4000FEF0F3DF1B2140804B00FE29934B40C0FDD7B969232140301DACFF73924B40C079C6BE642B214028207BBDFB914B4080CF9F36AA432140109CFA40F2904B4000931CB0AB49214008301004C8904B40005FD042025E2140205C8FC2F5904B4000261B0FB6602140885D86FF74914B40A0C2137AFD612140286BD44334924B40803579CA6A62214038E78BBD17934B4000D9D0CDFE602140A8BF97C283944B4040EFAB72A1522140A8A10DC0069A4B4040013274EC50214058465C001AA14B40E0B3E732355121405828D2FD9CA64B40E05417F03253214038EACC3D24A84B40E07A32FFE853214008E2E7BF07A94B40206211C30E5321404882FE428FAA4B40E0298E03AF462140886308008EB34B4000BC783F6E3F2140808D2441B8B64B40A0AA0B7899392140600ABABDA4B74B4000A26131EA322140507C7C4276B84B40C076BF0AF02D2140682E54FEB5B84B40401E8A027D12214008C11C3D7EB94B4020295C8FC2F520400006820019BA4B4020861DC6A4EF2040D806600322BA4B4000B728B341E6204038D8463CD9B94B40C08B868C47E1204010D9243FE2B94B40401B4982709D2040E076137CD3C64B4060DF6B088E832040B877F17EDCBE4B4020B6F63E5535204010D6E3BED5C44B40C06DFC89CA2E2040E0CDFE40B9C54B40800C1D3BA82C204078AEEFC341C64B40800C1D3BA82C20403041B8020AC74B4060573F36C92F2040089D82FC6CC84B40206893C3273D204030DEC83CF2CB4B40C018213CDA40204088CC07043ACD4B40803F373465472040889C69C2F6CF4B40207A19C5725B2040781EA33CF3DA4B40C05A99F04B5D204038232E008DDC4B404038A110015F204078A52C431CDF4B40405FD042025E2040C8CABDC0ACE04B40C0E4D4CE30552040F8230C0396EC4B4020DC2A88814E204028E78BBD17F34B40E00E45813E492040D08558FD11F84B40605A80B6D54420406034D6FECEFA4B40C018213CDA402040301A6B7F67FD4B40A0656B7D91402040B09509BFD4FD4B40E0A9F23D2341204058499D8026FE4B40A079008BFC422040109700FC53FE4B40803F37346547204020E44A3D0BFE4B4080622AFD844B2040100341800CFD4B40E076BF0AF04D204008DFA63FFBFB4B4080F1D3B8374F2040F814C78157FB4B4060C1E1051151204080A2EBC20FFA4B4020A26131EA522040D0CABDC0ACF84B4000DC114E0B562040B89509BFD4F54B4080B3CEF8BE582040B0984A3FE1F24B40C05A99F04B5D204048FEB5BC72EB4B40009F20B1DD5D2040E8B2B5BE48E84B4020BC783F6E5F2040B0E9B303AEE74B40406C06B820632040D0BB783F6EE74B402021CB8289672040B0E9B303AEE74B4000C4094CA78D2040B8984A3FE1EA4B4060116DC7D4A52040A0E3310395ED4B40E074B0FECFC92040E08BDAFD2AF24B40A091088D60CB2040B0984A3FE1F24B4020CDE50643C52040D0AC33BE2FF64B40A053E57B46A2204030F911BF62014C40A053E57B46A22040386BD44334024C4000B3B5BE48A02040D07FD6FCF8054C408021E4BCFF9F2040B8DA6E826F064C4000EB56CF499F2040D8F19881CA064C40C051D66F269E20405040DAFF00074C40E06BED7DAA8A204038266F8099094C4060069B3A8F8220406007793D980A4C40E0EEAB72A1722040E07954FCDF0B4C40002C9D0FCF4A2040A8AD11C1380E4C40E05758703F482040081286014B0E4C402077D84466462040D8AC33BE2F0E4C40E05758703F482040D088997D1E0D4C4020B937BF614A20406055A181580A4C40601EA33CF34A204058465C001A094C40601EA33CF34A204000CADFBDA3084C40405C8FC2F54820402838F581E4FF4B4020CBBDC0AC4820400821CB8289FF4B40A0F4143944442040306E15C440FF4B40E0A9F23D2341204028F38FBE49FF4B40E0A7E331033D204050853FC39BFF4B4060D026874F3A2040306552431B004C408038BA4A77372040C053E57B46024C4000999EB0C4332040002A8E03AF064C40004C546F0D342040E0A9F23D23094C40C0DB114E0B36204078A52C431C0F4C40A077F17EDC3E2040600DFB3DB12C4C40401B4982703D204008274D83A2394C4000240C03963C204038DEC83CF2434C40209F20B1DD3D204060FB743C66464C40A077F17EDC3E2040D809A1832E474C408017EFC7ED4F2040F0264D83A2514C400090DB2F9F542040E0C77C40A0534C40605DC136E259204008A0C37C79554C4060B08D78B26320405001F73C7F584C4000DF52CE176B20405807793D985A4C40A00C1D3BA86C20406834D6FECE5A4C40406002B7EE6E2040901EA33CF35A4C4000B4E732357120406834D6FECE5A4C40C0D03FC1C57220405807793D985A4C40E0B5F63E55752040B0A10DC0065A4C40E06ABB09BE792040E000DE0209584C40C05DDA7058722040D088997D1E554C40C088450C3B6C2040282CF180B2534C4000931CB0AB69204008D061BEBC524C400018080264682040808AE3C0AB514C4000F1D8CF6269204058F833BC59514C40E02EDE8FDB7F2040001B4982704D4C40E020CB8289A7204030F04E3E3D4A4C4020A5A2B1F6C7204088812040864A4C40C0C3094CA7CD2040E0B837BF614A4C4000321F10E8D42040A8A10DC0064A4C4080C1E10511F12040E0D38041D2474C40A074B0FECF092140507FBDC282454C4080F1D3B8372F21405001F73C7F404C408018213CDA402140905182FE423D4C40A03579CA6A422140789FAA42033D4C4060634337FB43214010D6E3BED53C4C4020B0743E3C4B2140B0BF97C2833C4C4080FA96395D4E2140B0BF97C2833C4C4020321F10E8742140C8CDFE40B93D4C406083DC45987A214080AEEFC3413E4C40009F20B1DD7D214080A52C431C3F4C4000C53BC0937E21406037177FDB3F4C4000C5573B8A83214040D13C8045464C40C023F3C81F8421404876FA415D464C40002A8E03AF86214020DB87BCE5464C4020A5A2B1F6872140606D37C137474C40C05758703F8821403820ED7F80474C40603F373465872140604F1F813F484C40405A80B6D584214000301004C8484C40E0978A8D79752140D08BDAFD2A4A4C4080BFD2F9F06C2140D0D03FC1C54A4C40A074B0FECF692140D8AF743E3C4B4C4020240C03965C21406028D2FD9C4E4C40007156444D5C21405040DAFF004F4C40E0F42D73BA5C2140885704FF5B4F4C40C050A4FB39AD2140D8C77C40A05B4C4040013274ECB02140A8B6D4415E5D4C40C06ABB09BEB92140386552431B604C400038A11001BF214028266F8099614C4020F2ECF2ADE721405040DAFF00674C4040D367075CEF2140F808C38025674C40E0703D0AD723224000BB9A3C65674C402050C3B7B02622401018247D5A674C40C01B62BCE63522408096E7C1DD654C40406684B70739224010A0C37C79654C40A01D71C8063A2240286893C327654C404069C537144E224010068200195A4C40E0E7154F3D4A2240488BC1C3B4594C40A01A3048FA442240302F3201BF584C40207156444D1C2240682E54FEB5504C40809885764E1B22400018080264504C4000AD33BE2F162240E0031F83154D4C4000AD33BE2F162240580DFB3DB14C4C408009DCBA9B17224010C79E3D974B4C40404278B4711C2240A8AAD0402C494C40005FD042021E2240A8656B7D91484C40C018213CDA202240C88558FD11484C4060809BC58B2522405837177FDB474C40E0921CB0AB292240386552431B484C4080AD4CF8A52E22408893A641D1484C40A017EFC7ED2F2240D0A9F23D23494C40C07A32FFE8332240004BE7C3B34A4C402015C78157332240B0622AFD844B4C40A05DDA7058322240E87954FCDF4B4C40A0B81E85EB3122409087A2409F4C4C4020A26131EA322240B8B6D4415E4D4C40E0E4D4CE30352240D87FD6FCF84D4C4080129F3BC136224050499D80264E4C402007B474055B2240884E417E36504C40C0D58F4DF26B224010E2E7BF07514C40E0C77C40A073224070ABAE4335514C40E0BB783F6E7F224080457EFD10514C40E059677C5F8C224008CADFBDA3504C40603AE63C638F22408081E7DEC34F4C402077BCC96F912240306E15C4404F4C4040AF5C6F9B912240000FB743C34E4C40E03BF71E2E912240C052CF82504E4C40809BC6F65A902240E0B5F63E554D4C4000D68F4DF28B2240E0031F83154D4C4040F2ECF2AD872240580DFB3DB14C4C406018213CDA802240B06BED7DAA4A4C408094490D6D802240C053E57B464A4C40605C8FC2F5882240A8BC564277474C4040DC2A88818E22408848BF7D1D464C408021E4BCFF9F2240B8B0524145434C40603579CA6AA22240584CDE0033434C4020895E46B1A42240B8B0524145434C40405FD04202BE224090CC07043A454C404038A11001BF2240507FBDC282454C4020BC783F6EBF2240801B62BCE6454C40E0656B7D91C02240F020CB8289474C4020261B0FB6C02240A8B393C151484C40E09E20B1DDBD22408893A641D1484C40C02634492CB9224000E2E7BF07494C4080CAA48636B022404801F73C7F484C40E08D959867A5224088D5AD9E93564C40C0703D0AD7A32240506D37C137574C4000FEF0F3DF9B224030266F8099594C406083DC45989A224008D9243FE2594C40E0D24ECDE596224020F04E3E3D5A4C40C07A32FFE89322408854C37E4F5A4C4040A48977808F2240C8066003225A4C40A0035ABA828D2240383E7782FD594C4000D68F4DF28B2240D8EE5701BE594C404018080264882240205C8FC2F5584C40A09E0777678522405001F73C7F584C4000BC783F6E5F2240C8CDFE40B9554C4040240C03965C224010CD203EB0554C4080B3CEF8BE582240385FD04202564C40C0D24ECDE556224080AEEFC341564C40E00241800C552240D0F19881CA564C40C0BEB9BF7A54224028F04E3E3D724C40A04BC8073D5B2240A88FF98040754C402090DB2F9F942240D0BB783F6E7F4C40001077F52A9A22401000000000804C4040E3A7716F9E2240584F1F813F804C4060C763062ABB2240B0C2D84290814C4020F86EF3C6D122406055A18158824C40205DC136E2D922405082FE428F824C406020B24813EF2240081E8A027D824C40A0716F7EC3F42240A8B915C26A824C4020CBBDC0AC08234070A2EBC20F824C40E0AF743E3C0B2340283E7782FD814C40001077F52A1A2340E07C957CEC804C40401286014B1E2340786649809A804C4000EB56CF495F2340303B3602F1844C40206E15C440872340E876137CD3864C40A00C1D3BA88C234000DC65BFEE864C40A05A99F04B9D2340B05FE97C78864C40200341800CB52340A09509BFD4854C40E08B868C47E1234000DC65BFEE864C40A0703D0AD7E323403841B8020A874C40206E15C440E72340B8BC564277874C40C03BF9F4D8EE234060DF878384884C40E0AFAE0AD4F22340E009A1832E894C400103000000010000001D00000060F414394464264010D3A23EC9A74C40E0E8297288282640E000DE0209A04C40209F20B1DD1D2640E876137CD39E4C40A088450C3B0C2640281A6B7F679D4C4000965D30B8FE2540F8230C03969C4C4000D34ECDE5F62540A859677C5F9C4C40C03BFBCA83EC2540B05FE97C789E4C406077D84466E62540B8BC5642779F4C400052D66F26DE2540E000DE0209A04C40A02FF7C951D82540286552431BA04C4020301004C8D0254000D3A23EC99F4C40002C9D0FCFCA2540B05626FC529F4C40A01A3048FAC42540C8BB783F6E9F4C408021E4BCFFBF2540B86E2EFEB69F4C408014AE47E1BA2540E0B2B5BE48A04C4000295C8FC2B5254028F911BF62A14C40E0978A8D79B52540788AE3C0ABA14C4060E2AC889AB82540306BD44334A24C40E0DB114E0BD6254008C45DBD8AA64C40E0C98B4CC0D72540588E0244C1A64C40A050A4FB390D264030E109BDFEA84C4020356090F4492640B8B915C26AAA4C4040BFD2F9F04C2640281DACFF73AA4C40E051D66F265E2640903CBB7CEBA94C4020261B0FB6602640E873D2FBC6A94C40C053E57B4662264028266F8099A94C4060DF6B088E6326405873B9C150A94C40205A80B6D5642640904E417E36A84C4060F414394464264010D3A23EC9A74C40010300000001000000C0000000401B498270DD24408015E0BBCDCB4C40E0F42D73BADC2440D806600322CA4C404009C38025DF2440D8C43BC093C64C40E094490D6DE02440580438BD8BC54C40A0B08D78B2E32440100C040132C44C4060809BC58BE52440D0C77C40A0C34C40E0A4A2B1F6E7244038E78BBD17C34C40C0FA96395D0E2540A89ECC3FFAB44C40A068ACFD9D152540101B4982709D4C4020F86EF3C611254058888043A89C4C4020573F36C90F2540A859677C5F9C4C40E0FAAF73D3062540B0DDAF027C9B4C40206552431BE82440600ABABDA4974C4000C74ACCB3E224406028D2FD9C964C40606684B707D92440B0A78FC01F944C40C04B546F0DD424405055A18158924C40C09EAEEE58AC244048CBF3E0EE7E4C40401B4982707D2440082A8E03AF7E4C40A0716F7EC3742440A877F17EDC7E4C40A017EFC7ED6F2440B0A44E40137F4C4080B950F9D762244030172AFF5A804C4080B60F79CB4D2440904B00FE29834C40E05A99F04B3D2440D8B5F63E55854C40809BC6F65A10244030085740A18A4C40806BED7DAA0A244078094E7D208B4C40E00373F4F8052440D09A1F7F698B4C40A0FDD7B969032440000072C2848B4C4080F2052D24002440B0BFB33D7A8B4C400000000000002340D8FA5B02F0854C40400C040132942240786649809A804C4020068200198A224008D3A23EC97F4C40A0C64ACCB38222403020ED7F807F4C40A0B5DD04DF7C2240D0BB783F6E7F4C40C0C98B4CC0772240600ABABDA47F4C40407497C45971224090C9C6832D804C40A05758703F68224008C11C3D7E814C4060B5DD04DF5C2240306211C30E834C402045B9347E512240B0BF97C283844C4020A5A2B1F647224008A0C37C79854C40A02B103D293B2240608E0244C1864C4040F52D73BA3C224050499D8026864C4000EC6AF2943D2240789FAA4203854C40609885764E3B2240E0BEB9BF7A844C40A0C554FA0937224078A86DC328844C4020999EB0C4132240D8C1FA3F87814C4000301004C810224008C11C3D7E814C40C02975C9380E2240F8264D83A2814C40C076BF0AF00D2240283E7782FD814C40A0AD4CF8A50E2240D8B837BF61824C400069C537140E2240004BE7C3B3824C40A01EA33CF30A224000E869C020834C40409E0777670522403814E97E4E834C40E0B2B5BE48002240604CDE0033834C4060809BC58BC52140B0E9B303AE7F4C40C0B94C4D82A7214068942EFD4B7C4C4000CDCCCCCC8C214028D8463CD9794C40C05758703F88214098C2D84290794C40A0069B3A8F822140888AE3C0AB794C4040E2AC889A782140281DACFF737A4C4020A26131EA7221405882FE428F7A4C40E0F42D73BA5C214028266F8099794C4040B3CEF8BE582140080F45813E794C40A038BA4A7757214030E109BDFE784C4020A8E331033D214050F833BC59714C4080BEA085043C214000D3A23EC96F4C40207156444D3C2140B05FE97C786E4C4040FEF0F3DF3B214010CD203EB06D4C40C02634492C3921408887A2409F6C4C4060C554FA0937214060431B800D6C4C40400D36751E252140C8F71A82E3684C4040261B0FB620214028EACC3D24684C40C0955D30B81E2140889C69C2F6674C4020013274EC10214038DB87BCE5664C40203F373465072140B85FE97C78664C40C0656B7D9100214038E44A3D0B664C40402DCF83BBFB2040001B498270654C4040D9E90775F9204090397AFCDE644C406009DCBA9BF7204080A86DC328644C408085048C2EF72040D8F4D901D7634C40E07F828B15ED20405873B9C150594C40E08C2958E3D4204078C493DDCC564C40806FD23428E22040E893A30051564C408071E316F3E32040801211FE45564C40C00A80F10CFA2040B8046EDDCD554C40203F37346507214008A0C37C79554C4040356090F4092140B8E3310395554C40805DDA705812214080AEEFC341564C40A01D71C8061A2140A85626FC52574C4000634337FB23214088C9C6832D584C40205C8FC2F5282140E0B2B5BE48584C40E0622AFD842B2140804E417E36584C40A06DFC89CA2E2140D0D38041D2574C40604E7CB5A33021400809C38025574C40A0D24ECDE5362140682E54FEB5504C4000EFAB72A13221408096E7C1DD4D4C4060B81E85EB312140A8E33103954D4C4000B1A6B2281C21405882FE428F4A4C40A0F755B95019214088812040864A4C40C0E4D4CE301521405834D6FECE4A4C40407D5A457F10214050FEB5BC724B4C40C059677C5F0C2140100C0401324C4C40A0716F7EC3F420408093A641D1504C40A0402D060FEB2040708EACFC32524C404025E7C41EEA204088F3A96395524C4020FFCC203EE82040D8067C7E18534C40002EAD86C4E520400866DAFE95534C40C026158DB5DF204080E123624A544C40E06E1118EBCB2040D040498105564C40E0230C0396BC2040002A8E03AF564C4000BC783F6E7F2040B05CA8FC6B594C400007B474057B204090812040865A4C40401077F52A7A2040E0AF743E3C5B4C4080E2AC889A782040009700FC535E4C40802FF7C951782040582E54FEB5604C4060B3CEF8BE782040B0B915C26A624C40606684B707792040B0B0524145634C40E09E20B1DD7D2040306E15C440674C40206C06B8208320406073B9C150694C40006E15C4408720404807793D986A4C40A0716F7EC39420409048BF7D1D6E4C40C059677C5FAC2040B07A32FFE8734C4060C2137AFDC1204000E2E7BF07794C40402A8E03AFE6204008CADFBDA3804C404021CB828927214058F5F23B4D8C4C40A0E4D4CE30352140F8298E03AF8E4C4080BEA085043C2140808461C0928F4C40E08C9AAF923F2140B89B8BBFED8F4C4000D00D4DD9412140D800DE0209904C40403F373465472140909C69C2F68F4C408020B248134F2140808461C0928F4C40A0035ABA826D2140B0E33103958D4C4080D9E90775792140D0031F83158D4C40C05758703F882140283B3602F18C4C40E0B0A6B2289C2140605260014C8D4C406045B9347EB121408896E7C1DD8D4C40A074B0FECFC92140905704FF5B8F4C40C09BDF30D1082240602B137EA9934C40009CDF30D12822405807793D98924C4000EFAB72A152224028266F8099914C4040D6A88768642240B05CA8FC6B914C40A0B5DD04DF7C2240E0C1FA3F87914C40A0D38041D2872240E073D2FBC6914C4060895E46B1C42240E0AF743E3C934C4000F2ECF2ADC722401015C78157934C40A09BC6F65AD02240D8A6B1BD16944C40801EA33CF3EA224000C45DBD8A964C40E01D8A027DF22240306E15C440974C40209F20B1DDFD224030172AFF5A984C4020321F10E8142340009A417C609B4C4040BC9179E4172340D0F4D901D79B4C40200F45813E292340A077F17EDC9E4C40A03BFBCA834C2340E076137CD3A64C4020B937BF616A2340808D2441B8AE4C4000013274EC702340A8656B7D91B04C40E05FE97C787623405007793D98B24C4080BB5F05F8862340084E2844C0B74C402023DA8EA98B2340D87C957CECB84C4020AD33BE2F962340884B00FE29BB4C4020B728B341E62340004BE7C3B3CA4C402023DA8EA9EB23403814E97E4ECB4C4000B4E73235F1234050FEB5BC72CB4C402000000000002440B8DDAF027CCB4C40C08EC70C541624401015C78157CB4C4000B6F63E55352440B8DDAF027CCB4C40A0CF0D4DD9412440806308008ECB4C40201E8A027D5224408015E0BBCDCB4C4000F52D73BA5C244080A86DC328CC4C4060573F36C96F2440E0031F8315CD4C40C0CABDC0AC882440B05FE97C78CE4C4000EE974F56942440B8BC564277CF4C40A01D71C8069A2440D88558FD11D04C4080C1E10511D12440A8AD11C138D64C40206552431BE82440E00F238447D94C40E00C36751E05254008D6E3BED5DC4C40A05417F03213254058FB743C66DE4C400020990E9D162540588E0244C1DE4C40C0EA56CF491F254000BB9A3C65DF4C402021CB8289272540808461C092DF4C40801B62BCE6352540386E15C440DF4C4000E8154F3D4A254058FB743C66DE4C40E081035ABA4A2540E80F3FFF3DDE4C40E0E2A7716F3E2540306893C327DD4C4000A5A2B1F6272540E0FD9C82FCDA4C40E077F17EDC1E2540903CBB7CEBD94C4080035ABA820D25402820ED7F80D74C40A0B950F9D7022540D8B5F63E55D54C40A08EC70C54F62440A86BED7DAAD24C40C059677C5FEC2440607C7C4276D04C40009CDF30D1E82440580ABABDA4CF4C40000D36751EE52440908D2441B8CE4C40E0E1934E24E0244088CC07043ACD4C40401B498270DD24408015E0BBCDCB4C40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('EI','IE','IRL','372','Ireland','6889','4143294','150','154','-8.152','53.177','0106000020E6100000050000000103000000010000000E00000060E81038125023C000BEDBBC719C4A4060A69883A05323C028F6D03E569C4A40204487C0916023C0A8BF97C2839C4A4000020F0C206423C008240C03969C4A4080F62345646823C0100341800C9D4A40207024D0606B23C06831957EC29D4A4080C404357C7323C0E073D2FBC6A14A40A0402D060F7323C07854C37E4FA24A400035423F535723C048431B800DA44A4080EA1F44325423C0D8A6B1BD16A44A40403CF6B3585223C0D8F4D901D7A34A4040A9D903AD4823C0604F1F813FA04A404085CD00174C23C0100341800C9D4A4060E81038125023C000BEDBBC719C4A400103000000010000001F00000060A2258FA7ED23C0E0B837BF61024B40001D588E90E123C0B06E2EFEB6FF4A40E0D9E4F049DF23C028DB87BCE5FE4A40A044A0FA07D923C0908AE3C0ABF94A40A044A0FA07D923C080457EFD10F94A4060EE92382BDA23C080AEEFC341F64A4000EE79FEB4E123C008C11C3D7EF14A4020581CCEFCE223C088457EFD10F14A406008AA46AFE623C0009D82FC6CF04A40A03AAB05F6E823C0884E417E36F04A400067614F3BEC23C0306552431BF04A4080E15CC30CF523C0A8656B7D91F04A40A02094F7711C24C0805A457F68F44A40409A94826E1F24C0D0CDFE40B9F54A4000D12170242024C0D8AC33BE2FF64A4000D12170242024C0608E0244C1F64A400055DB4DF04D24C03835B401D8FA4A40E004508C2C5924C0C8FD9C82FCFA4A40804C3107418724C010DFA63FFBFB4A4060A01683878924C038D505BCCCFC4A404083BEF4F68724C0306893C327FD4A4080677A89B16424C090457EFD10014B40E0C75EEFFE6024C0D8A9F23D23014B408052B3075A5124C0A8AAD0402C014B4000000000004024C0904E417E36004B40204ED2FC313D24C00000000000004B40E0DBF3FC692324C0D0D03FC1C5024B404091D101492024C0A8984A3FE1024B4060AF5B04C6F223C06034D6FECE024B4080643909A5EF23C0B86BED7DAA024B4060A2258FA7ED23C0E0B837BF61024B400103000000010000000C000000004D4A41B7DF20C0D8F71A82E3784B4000581CCEFCE220C09093A641D1784B4000F0880AD5E520C030E109BDFE784B4080D00836AEE720C05873B9C150794B40607AFB73D1E820C0488BC1C3B4794B4080F6234564E820C020F04E3E3D7A4B408008AA46AFE620C05807793D987A4B40E0DBF3FC69E320C06082FE428F7A4B40004487C091E020C0B053E57B467A4B40609A94826EDF20C030D8463CD9794B4040747973B8DE20C028F911BF62794B40004D4A41B7DF20C0D8F71A82E3784B400103000000010000001200000060A01683870921C060793BC2697B4B4040A2258FA70D21C0109A417C607B4B40E0A57F492A1B21C0D8C77C40A07B4B40607D3CF4DD1D21C0082DCF83BB7B4B40401E6CB1DB1F21C0B8A78FC01F7C4B40E0C75EEFFE2021C0A8BF97C2837C4B40004487C0912021C0D8C43BC0937E4B400049D74CBE1921C088457EFD10814B40005B5D4E091821C0E0C1FA3F87814B406077BAF3C41321C0A8A10DC006824B40A0355B79C90F21C0303E7782FD814B40E0942BBCCB0D21C0E073D2FBC6814B408002284696FC20C0B8E9B303AE7F4B40C0A57F492AFB20C0B85626FC527F4B40205B5D4E09F820C0503A58FFE77C4B40A0C0C8CB9AF820C028F6D03E567C4B40A061F88898FA20C088A86DC3287C4B4060A01683870921C060793BC2697B4B40010300000001000000B9030000C0D0217024A01DC0B0A10DC0067A4B40C015A4198BC61DC0285C8FC2F5704B4040F2CEA10CD51DC030327381CB6D4B4000EFC8586DEE1DC0806F9A3E3B6A4B40000F27309D361EC000274D83A2614B400021AD31E8F41EC0801EA33CF35A4B4080D9CBB6D3461FC0B8E33103955D4B404067614F3B4C1FC0385FD042025E4B400016DBA4A2511FC060499D80265E4B4040C972124A5F1FC0801B62BCE65D4B40C0B392567CB31FC008D9243FE2594B40400778D2C2B51FC0905D86FF74594B4000B29C84D2A71FC0881B62BCE6554B40C0D0217024A01FC0080341800C554B4000F4FBFECD6B1FC0080F45813E514B40C000FBE8D4651FC000E2E7BF07514B40408FC2F5281C1FC0604F1F813F504B40403201BF46021FC0E0A6B1BD164C4B4000583A1F9E551FC028DB87BCE5464B40C0B2976DA7CD1FC0B8A78FC01F444B40005B5D4E091820C0D87C957CEC404B4080AB1F9BE45720C0A0261763603B4B40600569C6A25120C0A8656B7D91384B40C0A8C0C9365020C028EACC3D24384B40001D588E902120C0B06E2EFEB62F4B4060022846961C20C028DB87BCE52E4B40206420CF2E1720C078AEEFC3412E4B40E082A5BA800F20C0E0CDFE40B92D4B4080415F7AFBC31FC0089700FC53264B40803BDD79E2991FC00048A643A7254B40003AB01C21831FC0789FAA4203254B40404487C091801FC0F8230C0396244B40005EBC1FB77F1FC080A86DC328244B4080AE42CA4F7A1FC00818080264204B40800CFFE9067A1FC0A8E33103951D4B40801E85EB51781FC0600DFB3DB11C4B4040CDC7B5A1721FC0A87A32FFE81B4B4040B29C84D2671FC0804B00FE291B4B40402502D53F481FC010C11C3D7E194B40C039B01C21431FC010C11C3D7E194B4040AC1A84B9FD1EC000274D83A2194B4080C2F5285CCF1EC0903CBB7CEB194B40407138F3ABC91EC0903CBB7CEB194B40C0976C3CD8821EC0E0CDFE40B9154B40409A94826E7F1EC0605260014C154B40404E5E64027E1EC080397AFCDE144B4040F850A2257F1EC0B07A32FFE8134B4000B4C9E1937E1EC0306211C30E134B4000F3C98AE17A1EC0104BE7C3B3124B40001C261AA4701EC028F04E3E3D124B4040A46B26DF3C1EC0584F1F813F104B40805A626534521DC0B05FE97C780E4B4040E6CAA0DA401DC068FB743C660E4B408000FBE8D4251DC060853FC39B0F4B40406BB6F2921F1DC09021E4BCFF0F4B400094128255951CC008D6E3BED51C4B40400E2C47C8901CC0A8B393C151204B4080963AC8EB911CC0282F3201BF204B40C0AD47E17A941CC0E8A9F23D23214B408077BAF3C4B31CC0789FAA4203254B404078EC67B1A41CC028E78BBD172B4B40001C5DA5BB3B1CC0D0BEB9BF7A344B4040BC732843251CC0301A6B7F67354B40806BB6F2921F1CC0F89FC37C79354B40803BDD79E2191CC0B8B6D4415E354B40C000FBE8D4E51BC060793BC269334B4040C3F01131B51BC0B8E0F08288304B40008E90813CAB1BC0D0D38041D22F4B4000880E8123811BC0000C0401322C4B40C0F2C98AE17A1BC0F899417C602B4B4080AAED26F8661BC0B0B6D4415E254B408054E0641B681BC040D505BCCC244B408079E2395BF01AC02020ED7F80174B4000C972124A9F1AC030172AFF5A084B40C0BF9657AE871AC038327381CB054B400000000000801AC0809FAA4203054B4000F3C98AE17A1AC0A0716F7EC3044B40808B683BA66E1AC0301A6B7F67054B40003883BF5F6C1AC000CD203EB0054B4040EB51B81E451AC09060C77F81064B4000D7A3703DCA19C0A8BC564277074B40000F27309D7619C0A0ECF483BA0C4B4040B16A10E67619C0D088997D1E0D4B4000CB9F6F0B7619C0587FBDC2820D4B4000DD2571567419C0881B62BCE60D4B40001C261AA47019C0101286014B0E4B400052B81E856B19C05828D2FD9C0E4B4080A23EC91D6619C0D8F19881CA0E4B4040E5CFB7055B19C0D8F19881CA0E4B40401059A4892719C0881B62BCE60D4B404039B5334C1D19C0D0CDFE40B90D4B4080A3703D0A1719C0101B4982700D4B4080963AC8EB1119C0080341800C0D4B40C065F7E4611119C040102043C70C4B4000941282551519C0B0BF97C2830C4B4040EA1F44321419C000DFA63FFB0B4B40400F27309DF618C0B0C2D84290094B40C08B683BA6AE18C0A8ECF483BA044B404061DF4E22A218C0A87A32FFE8034B4000508BC1C39418C0602B137EA9034B40402DB1321A8918C078423D7D04044B40007E37DDB28318C08815E0BBCD034B40C0F3FBFECD6B18C038172AFF5A004B40C0633E20D06918C0B89B8BBFEDFF4A4040A01683876918C0B0BC564277FF4A40C051B81E856B18C05840DAFF00FF4A40C02DAC1BEF6E18C06828D2FD9CFE4A40401C5DA5BB7B18C028327381CBFD4A40C010548D5E8D18C038D505BCCCFC4A40002C7FBE2D9818C000BEDBBC71FC4A40C0630795B89E18C000BEDBBC71FC4A408066666666A618C0A8BF97C283FC4A4000A0168387E918C0B0DA6E826FFE4A40401059A4892719C0B0656B7D91004B40009A94826E3F19C080ABAE4335014B40405A6265345219C0888AE3C0AB014B40407365506D6019C028D8463CD9014B4040AAED26F86619C0E073D2FBC6014B40C0953FDF166C19C0A0C2D84290014B40007233DC806F19C080ABAE4335014B4080D11C59F98519C088A2EBC20FFA4A40407B0F971C8719C0D0C1FA3F87F94A4080D11C59F98519C0201A6B7F67F54A408085E63A8D8419C0805A457F68F44A4000B4C9E1937E19C0904B00FE29F34A40806F0B96EA7219C0808AE3C0ABF14A408054E0641B6819C0202F3201BFF04A40007B14AE476119C090C9C6832DF04A40C0332E1C085919C050853FC39BEF4A400011548D5E4D19C0306E15C440EF4A4000BA4BE2AC2819C0D0C43BC093EE4A4080EB51B81E0519C0084BE7C3B3EA4A40800778D2C2F518C0000C040132E44A4080A46B26DFFC18C0A8E0F08288E04A4080A1293BFD0019C0202C634337DD4A4040880E81230119C0E8A6B1BD16DC4A4000BB0CFFE9F618C0E80CFE7E31D74A40008940F50FF218C0E0FA5B02F0D54A4000662FDB4EDB18C060F833BC59D14A40C091EA3BBF9818C0906308008ECB4A40C069C020E99318C02814E97E4ECB4A4040560DC2DC7E18C0E0FD9C82FCCA4A4040B29C84D26718C0A8E67283A1CA4A40C0402D060F5318C038EACC3D24C84A4040C2F5285C4F18C0D8AC33BE2FC64A40005D8AABCA4E18C0D088997D1EC54A40C0643909A54F18C03014E97E4EC34A40400E2C47C85018C0B8984A3FE1C24A40C0D571FC509918C0B05CA8FC6BB14A4000698EACFCA218C030E109BDFEB04A4080A23EC91DE618C0485260014CAD4A408000FBE8D4E518C0789FAA4203AD4A400061DF4E22E218C08015E0BBCDAB4A40C0C0C8CB9AB818C0885704FF5BA74A4080819197357118C0A8B393C151A04A4080B4C4CA682418C0D0C43BC0938E4A40802407EC6A2218C0A8E33103958D4A400011548D5E0D18C0285C8FC2F5784A40807B0F971C4718C0D876137CD36E4A408047E17A146E18C0B8622AFD846B4A40C01E85EB517818C088812040866A4A4000F3C98AE17A18C008068200196A4A4040ABE80FCD8C18C05028D2FD9C664A4000508BC1C39418C038D505BCCC644A40008A3BDEE49718C0F82CCF83BB634A4080DD205A2B9A18C088A2EBC20F624A404024D060539718C08860C77F815E4A40C07D37DDB2C318C088457EFD10594A4000CFF41263C918C0604F1F813F584A4000662FDB4EDB18C0001B498270554A4040C972124ADF18C0A0BF97C283544A4080CEF9298EE318C05055A18158524A40801281EA1FE418C010CADFBDA3504A40C01C588E90E118C0D809A1832E4F4A40407D3CF4DDDD18C0009700FC534E4A40002C7FBE2DD818C0A868ACFD9D4D4A40009CC1DF2FD618C028ED0DBE304D4A404055DB4DF0CD18C08854C37E4F4A4A4040ABE80FCDCC18C0804E417E36484A40006F10AD15CD18C0B0A44E4013474A40C0A8C0C936D018C09048BF7D1D464A40002C7FBE2DD818C0603A58FFE7444A40C0F3FBFECDEB18C0386BD44334424A4080726A6798FA18C030172AFF5A404A4080CDC7B5A17219C0B053E57B46324A4000E048A0C1D619C038EACC3D24304A40007D3CF4DDDD19C028172AFF5A304A404066666666E619C0A89B8BBFED2F4A4040560DC2DCFE19C0B8E33103952D4A40000AD7A370FD19C0080341800C2D4A40805EB7088CA519C000240C0396244A400061DF4E22A219C0B059677C5F244A40407B0F971C8719C0B8DDAF027C234A40C0573A1F9E5519C030EACC3D24204A404016DBA4A25119C05837177FDB1F4A4040CFF412634919C0588E0244C11E4A40407B0F971C4719C05076FA415D1E4A40C06E10AD154D19C0503A58FFE71C4A404016DBA4A25119C058431B800D1C4A4040C8409E5D6E19C080A52C431C174A40C0C51858C77119C0908D2441B8164A40C07492AD2E7719C05828D2FD9C164A40000AD7A3707D19C010C45DBD8A164A40C0C41D6FF28B19C02829B000A6164A40008A3BDEE49719C0903FFCFCF7164A40C03BDD79E29919C0805704FF5B174A40007D3CF4DDDD19C0602E54FEB5184A4040AC1A84B97D1AC0886649809A184A4040F6234564281BC0809065C1C41B4A40C0D11C59F9451BC0809C69C2F6174A40400E2C47C8501BC0385FD04202164A4000508BC1C3541BC0D0CDFE40B9154A4080583508737B1BC088397AFCDE144A40408FC2F5289C1BC0505260014C154A4040AAED26F8A61BC0203E7782FD194A40C0A7C5E061AA1BC0D8D03FC1C51A4A4000EC4CA1F3EA1BC058793BC269234A4080726A6798FA1BC0100C040132244A4040B27F9E06FC1BC060C77F8120244A4040560DC2DCFE1BC01015C78157234A40804E5E6402FE1BC0A8984A3FE1224A40C01B446B45FB1BC02063997E89224A40C05D85949FF41BC0B874B0FECF214A4080BC732843E51BC0801B62BCE61D4A4000BF9B6ED9E11BC0905A457F681C4A40805EB7088CE51BC0587FBDC282154A4080F0A1444BFE1BC0B8A10DC006124A40006CB1DB67051CC0A05CA8FC6B114A4040BC732843251CC020E109BDFE104A40C04C310741671CC06001F73C7F104A40403883BF5F6C1CC0682E54FEB5104A40C0E175FD826D1CC0B8AAD0402C114A40C01281EA1FA41CC0D0AF743E3C134A404049D74CBE791DC0B8AAD0402C114A40400AD7A370BD1DC028EACC3D24104A40800E2C47C8501EC000D6E3BED50C4A4080B6F1272A7B1EC0D8B2B5BE48084A4040F6234564681EC0D08558FD11084A4040EB51B81E451EC0808461C092074A408081919735311EC0606D37C137074A4000D0EFFB372F1EC0C8F19881CA064A40C08B683BA62E1EC078AEEFC341064A40C0A3703D0A571EC0A85626FC52FF4940C07F643A745A1EC000DC65BFEEFE4940803BDD79E2D91EC090C9C6832DF849408008AA46AFE61EC0C800DE0209F84940409A94826E3F1FC0A8E0F08288F84940006CB1DB67451FC0D8CABDC0ACF84940008196AE604B1FC0E0F71A82E3F8494000A69883A0531FC030F911BF62F94940C073D2FBC6671FC008E2E7BF07FD494040B29C84D2671FC0E082177D05FB49404054E0641B681FC030F911BF62F9494000A8C5E0616A1FC030172AFF5AF84940C0BA46CB818E1FC0603D997FF4F14940E0DF66F1620920C03835B401D8EA4940203883BF5F2C20C000D3A23EC9E7494000D462F0305520C0381A6B7F67E54940402C7FBE2D5820C0D8B5F63E55E54940E016D68D777720C09096E7C1DDE54940C07C3F355E7A20C0E839CD02EDE6494000E7E104A67B20C0006405BF0DE74940204E5FCFD77C20C078B2463D44E74940A0AA0837197D20C058551344DDE74940402A70B20D7420C0B8B915C26AEA494080D68A36C77120C0084BE7C3B3EA49404024EEB1F46920C038E78BBD17EB494060D349B6BA5C20C07887A2409FEC4940C03BDD79E25920C0A8B6D4415EED4940E0F3FBFECD6B20C078ABAE4335F1494060AF5B04C69220C040D8463CD9F14940E076A1B94EBB20C0206BD44334F24940A0415F7AFBC320C0C053E57B46F249404049473998C520C0308D43FD2EF24940606EF7729FD420C05073B9C150F1494000E8F7FD9BD720C0D0A9F23D23F1494080DC0C37E0DB20C0582E54FEB5F049408019C5724BDB20C01006103E94F04940C07F643A74DA20C00818080264F0494000F1BA7EC1D620C0604F1F813FF04940001A170E84CC20C0C88558FD11F0494060C1C3B46FBE20C080C9C6832DF04940006420CF2EB720C0C88558FD11F049406092037635B120C05837177FDBEF4940E08B683BA6AE20C0808461C092EF4940207024D060AB20C0883FFCFCF7EE4940001F82AAD19B20C048A19E3E02E9494040C2DB83109820C04816A243E0E64940E0D57267269820C02084F23E8EE64940205B5D4E099820C030F911BF62E14940607D3CF4DD9D20C0885704FF5BDF49404091D10149A020C000C45DBD8ADE49402055DB4DF0AD20C0B8BF97C283DC494080CDC7B5A1B220C0D8A6B1BD16DC494000FA7DFFE6D520C0B0B915C26ADA4940003883BF5F0C21C0306893C327D5494000D462F0301521C0E0FD9C82FCD2494080F964C5701D21C0D8A9F23D23D1494000DCF3FC696321C0B85CA8FC6BC9494060E28E37F96521C0D00F238447C94940C0B7054B757921C0E0EE5701BEC94940A0415F7AFBC321C0786649809AC8494020A8A78FC0F721C0580ABABDA4C74940C0B7054B753922C050499D8026C649404077BAF3C45322C0C053E57B46C249404077BAF3C47322C0D87FD6FCF8BD4940C09AADBCE47722C0487FBDC282BD4940406EF7729FB422C0D00CE2033BBC4940800BEBC6BBBB22C0B0A78FC01FBC494000EE79FEB4C122C05870784144BC4940407AFB73D1E822C030DEC83CF2C3494080D9CBB6D34623C078ABAE4335C14940403674B33F6823C088A86DC328BC4940403674B33F6823C09015E0BBCDBB4940E0D6A3703D6A23C0B8622AFD84BB4940E0FECD8B136F23C0F0E769C020BB494060ED60C43E8923C030D8463CD9B94940C0C0C8CB9A9823C0100F45813EB9494060FEB5BC729D23C01869A9BC1DB9494000E5B67D8FA223C008E2E7BF07B949402061DF4E22A223C030232E008DBC4940E0FB8C0B079A23C0588E0244C1BE4940E0EA387EA88C23C0604F1F813FC04940A03E1EFAEE6E23C0B0B0524145C3494060D00836AE6723C0909065C1C4C34940C09CBCC8045C23C000D6E3BED5C449400035423F535723C0505260014CC54940C08B683BA64E23C088AEEFC341C64940E0EA387EA84C23C0F8C35DBD8AC6494080E81038123023C0B0DDAF027CCB494000FFCD8B132F23C000E5284014CE494080D349B6BA5C23C028F04E3E3DCA4940608940F50F9223C0B0AD11C138C64940804F72874D9C23C010A0C37C79C5494040A9D903ADA823C0D888997D1EC549404085CD0017AC23C038ED0DBE30C54940C08B683BA6AE23C0B0B6D4415EC54940805B76887FB023C00848A643A7C54940805B76887FB023C08048BF7D1DC64940803E1EFAEE8E23C008D061BEBCCA494080CA8635957D23C0B8ECF483BACC494080D45E44DB3923C0286BD44334D249404047C7D5C83623C07057E88365D24940C03BDD79E21923C06070784144D44940E09DEE3CF10C23C008240C0396D4494060D00836AE0723C0503A58FFE7D4494060DF4DB7ECF022C0D8C43BC093D649400067614F3BEC22C00009C38025D74940A04C310741E722C0C88558FD11D84940A055F48766E622C0009D82FC6CD84940003201BF46E222C0D8AF743E3CDB4940A04C310741E722C0B8716F7EC3DC4940A049F086341223C01000000000E0494000529ACDE31823C080A86DC328DC4940E0AE42CA4F1A23C08815E0BBCDDB4940E0C75EEFFE4023C0B0E3BF4010D8494040A2410A9E4223C0E8783E03EAD7494060C405A0515223C050F52B9D0FD74940C0893DB48F5523C0C84961DEE3D649408047E17A148E23C0F80B040132D44940E093F947DF9C23C0382CF180B2D34940804F72874DDC23C0B8E0F08288D04940804F72874DDC23C0D08558FD11D0494080F964C570DD23C0500ABABDA4CF494040272F3201DF23C0C05626FC52CF4940A0677A89B1E423C0E0C43BC093CE4940202FC03E3A0D24C0000C040132CC494040807D74EA1224C0B07A32FFE8CB4940006DE34F541624C0E07954FCDFCB4940204F594DD74324C028DEC83CF2CB494000E5B67D8F4224C05076FA415DCE494020560DC2DC1E24C0C8B837BF61D24940A03BDD79E2F923C0588E0244C1D64940408B4F0130F623C0B06BED7DAADA4940600BEBC6BBFB23C0881EA33CF3DA4940803DEC8502FE23C0504CDE0033DB494040272F3201FF23C0C8C77C40A0DB494060F0A1444BFE23C0D8A6B1BD16DC4940402A70B20DF423C0E0B5F63E55DD4940800569C6A2F123C0B868ACFD9DDD4940A0643909A5CF23C038E109BDFEE0494060A2258FA78D23C08060C77F81E64940E0B1834A5C2F23C0F8298E03AFEE494060C745B5882823C0905704FF5BEF494060D00836AE2723C0500ABABDA4EF4940401B2B31CF2A23C0E0D38041D2EF4940607AFB73D14823C030F38FBE49EF4940007365506D6023C0A0AD11C138EE494020414640856B23C0A868ACFD9DED494000F73C7FDAE023C0009700FC53E64940E0AE42CA4F1A24C0104BE7C3B3E2494060EA1F44323424C0E8B2B5BE48E0494080CA8635955D24C0F8230C0396E44940000E130D525824C0789C69C2F6E74940C0B7054B755924C008E2E7BF07E94940C0AE42CA4F5A24C010C11C3D7EE94940A0295778975B24C030D8463CD9E94940C02616F88A6624C06070784144EC4940402DB1321A6924C000BEDBBC71EC4940E019170E846C24C0A8BF97C283EC4940E0CA9F6F0B7624C0D00CE2033BEC494080CA8635957D24C0602B137EA9EB4940409A94826E7F24C0109A417C60EB4940204FCB0F5CAD24C0002D5DC136E44940E0D362F030B524C0D87954FCDFEB494080C1C3B46FBE24C04801F73C7FF04940E0997B48F88624C0B05FE97C78FE4940204D4A41B77F24C080A52C431CFF4940609A94826E3F24C0B8B0524145034A40202A70B20D3424C038DEC83CF2034A40E08B683BA62E24C06070784144044A40A046AF06281D24C0283B3602F1044A40E004508C2CF923C060FB743C66064A4080EE92382B9A23C0A86E2EFEB60F4A40A0415F7AFB8323C0E082177D05134A406008AA46AF8623C0A8B0524145134A40609A94826E9F23C0A8622AFD84134A40E0A8C0C936B023C060FEB5BC72134A4060747973B8BE23C0009A417C60134A4060E28E37F9C523C0A8B0524145134A4000E5B67D8FE223C08081204086124A4040ABE80FCD0C24C0A05CA8FC6B114A40A0295778971B24C08093A641D1104A40A0643909A52F24C0D8D38041D20F4A4040A35703945E24C0D8CDFE40B90D4A4020ABE80FCD8C24C08096E7C1DD0D4A40A03AAB05F6A824C08860C77F810E4A40C076A1B94EBB24C0001286014B0E4A40E0DBF3FC69C324C0585260014C0D4A40606BB6F292DF24C08815E0BBCD0B4A4000DCF3FC69E324C0D8F4D901D70B4A40C0A23EC91DE624C090423D7D040C4A4000D9B27C5DEE24C0100341800C0D4A40C02C98F8A3F024C06031957EC20D4A4080FCA5457DF224C0B0E0F08288104A40A0402D060FF324C0B0E67283A1124A4000FFCD8B13EF24C05828D2FD9C164A402055DB4DF0ED24C06040DAFF00174A4020B4AB90F2EB24C0B05626FC52174A40202C7FBE2DB824C0301A6B7F671D4A4060D00836AE8724C038F04E3E3D224A404091D101498024C000D061BEBC224A4080C745B5886824C008DFA63FFB234A4000F1BA7EC15624C030D505BCCC244A4080F3E2C4575324C000D6E3BED5244A40E09FFD48115124C000240C0396244A40E079E2395B5024C0B0A78FC01F244A40E079E2395B5024C0206211C30E234A40805B76887F5024C05007793D98224A40A01D537765E723C0B0E33103951D4A4000D3307C44E423C000A0C37C791D4A40006420CF2ED723C0081B4982701D4A40C085E63A8DC423C0081B4982701D4A4080C1C3B46F7E23C00009C380251F4A40E076A1B94E7B23C0C05626FC521F4A40E09CBCC8047C23C0B06E2EFEB61F4A40204D4A41B77F23C01018080264204A400053CC41D08923C0B874B0FECF214A40E079E2395B9023C0603D997FF4214A40A0402D060F9323C028D8463CD9214A4040B4AB90F2AB23C0580DFB3DB1244A400055DB4DF0AD23C0886649809A304A40A02616F88A8623C0C8CABDC0AC384A40A04F72874D5C23C0F8264D83A2414A40A03BDD79E25923C030327381CB454A408044A0FA075923C050499D8026464A4080643909A54F23C0580ABABDA4474A4060A2258FA74D23C0A89B8BBFED474A40E0A02FBDFD4123C09018213CDA484A40600BEBC6BB3B23C080457EFD10494A4080D349B6BABC22C0306BD443344A4A4000F3C98AE1BA22C0B0A10DC0064A4A4000859675FFB822C0280B98C0AD494A40609F724C16B722C008F73C7FDA484A402053CC41D0A922C050465C001A494A40C0963AC8EB7122C0B0984A3FE14A4A4020A8A78FC0F721C0582E54FEB5504A4000581CCEFCA221C020ED0DBE30554A4080CDC7B5A1B221C0A8B393C151584A40C0389CF9D5E421C08887A2409F5C4A4000D9B27C5D0E22C0587FBDC2825D4A40C09FFD48111122C060431B800D5C4A40001D588E902122C028EACC3D24584A40A0BA46CB812E22C0301A6B7F67554A400061DF4E224222C05873B9C150514A40408E90813C4B22C0B06E2EFEB64F4A4080643909A54F22C0386E15C4404F4A400076A6D0795522C0F8DB65BFEE4E4A40C09CBCC8045C22C0E076137CD34E4A40800BEBC6BB7B22C08060C77F814E4A40E0CA9F6F0BF622C0883FFCFCF74E4A40800BEBC6BB1B23C0888AE3C0AB514A40E0DBF3FC696323C0D0031F83154D4A40804C3107416723C0A8BF97C2834C4A40607AFB73D16823C070A86DC3284C4A400053CC41D06923C0382CF180B24B4A400053CC41D06923C0E8AF743E3C4B4A40608C81751C6723C0301DACFF734A4A406083BEF4F66723C0283E7782FD494A4060975302626A23C0D073D2FBC6494A40206420CF2E9723C000D3A23EC9474A40C02FD978B0C523C0B8DA6E826F464A40E09DEE3CF1CC23C068FB743C66464A40E0AE42CA4FDA23C0908D2441B8464A4080F964C570DD23C0A077F17EDC464A40609A94826EDF23C01009C38025474A4080F0A1444BDE23C00021CB8289474A4020508BC1C3D423C080457EFD10494A4060FCA5457DD223C0D00F238447494A408049F08634B223C0F899417C604B4A40A0677A89B1A423C0D8C77C40A04B4A40406BB6F2929F23C080423D7D044C4A40000E130D527823C0E873D2FBC6514A40409DD5027B7423C05055A18158524A40206AA2CF472123C0B8BC5642775F4A40E091EA3BBFF822C0A85FE97C78664A40A0643909A5CF22C0785D86FF74714A4080E49D4319CA22C05828D2FD9C764A4040B4AB90F2EB22C03029B000A6764A40E082A5BA80EF22C0908D2441B8764A408052B3075AF122C03841B8020A774A4080FCA5457DF222C0D0BB783F6E774A404033333333F322C0B09B8BBFED774A40403CF6B358F222C00018080264784A40C0355B79C98F22C008D9243FE2914A4080C745B5888822C0F8E769C020934A40C07C23BA678522C0E8AF743E3C934A4040AE2990D98122C0884B00FE29934A40200F27309D7622C08854C37E4F924A40E0F84B8BFA6422C0B8B393C151904A4020529ACDE35822C0D0C43BC0938E4A40A03E1EFAEE4E22C000CD203EB08D4A40C0BD874B8E2322C05040DAFF008F4A4020755776C10022C0984737C2A2924A40A023D5777E1122C0A0A78FC01F944A40408B4F01301622C038232E008D944A40E0E7F7FD9B1722C0583A58FFE7944A40006DE34F541622C0D8B5F63E55954A4020333333331322C0101B498270954A40206DE34F54F621C0583A58FFE7944A40608B4F0130F621C0A859677C5F944A4080E15CC30CF521C028DEC83CF2934A4000DCF3FC69E321C008D9243FE2914A406091D10149E021C0283E7782FD914A4060A3570394DE21C06055A18158924A4020AE2990D9E121C0B074B0FECFA14A40201268B0A9EB21C0386BD44334A24A40800E2C47C81022C0D0D03FC1C5A24A40406EF7729F1422C0D0D03FC1C5A24A4020A8A78FC01722C0B8E67283A1A24A40804F72874D1C22C0D08BDAFD2AA24A4080C404357C3322C000E2E7BF07A14A40E0F97DFFE65522C010D3A23EC99F4A4060FFE6C5896722C0F020CB82899F4A402047C8409E7522C0D8BB783F6E9F4A40C08827BB999922C0B85626FC529F4A404015A930B6E022C0C8FA5B02F09D4A40C0B4C4CA68E422C0B09509BFD49D4A40609DD5027BF422C0A8716F7EC39C4A4040747973B8FE22C030232E008D9C4A402035423F533723C0D8CDFE40B99D4A40C02094F7713C23C0B8AD11C1389E4A40609A94826E3F23C010DC65BFEE9E4A40E0D02170244023C000BB9A3C659F4A40606BB6F2923F23C0507C7C4276A04A40E0DE347D763823C0F81186014BA64A40402FC03E3A2D23C0E0F71A82E3A84A4060E49D43192A23C0F02F1004C8A84A4060D00836AE2723C0D87C957CECA84A40A02FD978B02523C0D00F238447A94A4080CA8635951D23C0801EA33CF3AA4A4080D349B6BA1C23C050793BC269AB4A40608FC2F5281C23C0A0E0F08288B04A40207365506D2023C078457EFD10B14A40E0F3FBFECD4B23C0B05CA8FC6BB14A40E0B1834A5C4F23C028F911BF62B14A406077BAF3C45323C08818213CDAB04A40609544F6416623C080AEEFC341AE4A40403674B33F6823C0587FBDC282AD4A40607138F3AB6923C0E07954FCDFAB4A406085CD00176C23C0306211C30EAB4A4060E5CFB7057B23C0B09B8BBFEDA74A406086FF74037D23C0600ABABDA4A74A4000D0EFFB378F23C0D0CDFE40B9A54A4060AF5B04C69223C00848A643A7A54A40E0942BBCCBCD23C0E8B2B5BE48A84A4000D0EFFB37CF23C0786649809AA84A4000FFCD8B13CF23C070ABAE4335A94A4020CA6C9049C623C000A93121E6AC4A4000698D4127C423C03892CB7F48AD4A40E0F50A0BEEAF23C0E009A1832EAF4A40000BD28C45A323C0F820CB8289AF4A404030F2B2269E23C08821E4BCFFAF4A400049D74CBE9923C0A0E0F08288B04A4080EA1F44329423C010C11C3D7EB14A4080D68A36C79123C08054C37E4FB24A4080FCA5457D9223C0D8D03FC1C5B24A40202C7FBE2D9823C0503A58FFE7B44A4060D349B6BA9C23C0301A6B7F67B54A40004487C091A023C0301A6B7F67B54A40E0DBF3FC69C323C0B859677C5FB44A40C0620D17B9D723C0B0E6C75F5AB24A4080E9094B3CD823C0406EA301BCB14A402081785DBFD823C058CB811E6AB14A40809CBE9EAFD923C0908DB27E33B14A4000CEE0EF17EB23C060853FC39BAF4A40004C18CDCAEE23C060853FC39BAF4A408008AA46AF0624C0587C7C4276B04A40E0FB8C0B075A24C0000C040132B44A40A0321AF9BC5A24C0600DFB3DB1B44A40A04C3107416724C080CC07043AC54A40C02FD978B06524C0B068ACFD9DC54A4000DAE4F0495F24C0B8DA6E826FC64A4060FCA5457D1224C080397AFCDECC4A406091D101490024C0507FBDC282CD4A408046AF0628FD23C0A868ACFD9DCD4A40204487C091C023C0E8AC33BE2FCE4A4000D671FC509923C028F6D03E56CC4A4020594E42E99323C0E0A6B1BD16CC4A4000F60A0BEE8F23C080423D7D04CC4A40607AFB73D16823C088A86DC328CC4A4060E28E37F96523C06070784144CC4A40A0415F7AFB6323C08087A2409FCC4A40A029C93A1C6523C0D8A6954220CD4A40408C81751C8723C0F80241800CCD4A40803E1EFAEE8E23C0E088997D1ECD4A4000D671FC509923C0301A6B7F67CD4A40E08EA9BBB2A323C0E8AC33BE2FCE4A402049D74CBEB923C0D8B2B5BE48D04A4000D0EFFB37CF23C05055A18158D24A4080C404357CD323C0A8984A3FE1D24A4060EA1F4432D423C0B0B0524145D34A40E0D571FC50D923C06001F73C7FD84A4080E8103812D023C050465C001AE14A40608E90813CCB23C030266F8099E14A4080EA1F4432B423C0001E8A027DE24A408052B3075AB123C05807793D98E24A4060F0A1444B5E23C0B859677C5FE44A40A0389CF9D54423C06070784144E44A4000E5B67D8F4223C038DEC83CF2E34A40004D4A41B73F23C0809065C1C4E34A40E00D130D523823C0382CF180B2E34A40E09DEE3CF12C23C0905A457F68E44A40C0976C3CD82223C028327381CBE54A40C0BD874B8E2323C0009700FC53E64A404024EEB1F42923C0A85FE97C78E64A40205E9ECE152D23C02029B000A6E64A40E09CBCC8043C23C0B89B8BBFEDE74A4060CA8635953D23C0A8B393C151E84A40C07F643A743A23C090992842EAEA4A40E0DE347D763823C0E0AF743E3CEB4A40202A70B20D3423C0302CF180B2EB4A4060A2258FA72D23C0A87A32FFE8EB4A404083BEF4F62723C05870784144EC4A40409A94826E1F23C038E44A3D0BEE4A40C0A02FBDFD2123C0B8A10DC006F24A4040A5660FB42223C08081204086F24A4060EB51B81E6523C0E0D03FC1C5F24A4080C404357C7323C0B06BED7DAAF24A40A01D5377658723C0081E8A027DF24A40004A09C1AA8A23C0D8B837BF61F24A40E09DEE3CF18C23C0D08BDAFD2AF24A40803E1EFAEE8E23C010D9243FE2F14A40E0963AC8EB9123C058465C001AF14A4000CB9F6F0B9623C0B0E0F08288F04A4060A5660FB4A223C03020ED7F80EF4A40004C18CDCAAE23C0803FFCFCF7EE4A40E0CDE0EF17CB23C0901B62BCE6ED4A40C0963AC8EBD123C06031957EC2ED4A40606BB6F292DF23C0082A8E03AFEE4A40001D588E90E123C0803FFCFCF7EE4A4040A5660FB4E223C0885704FF5BEF4A4060F3E2C457D323C0D0C1FA3F87F94A40C09FFD4811D123C0D073D2FBC6F94A4000FDBE7FF3CA23C088A2EBC20FFA4A4000892650C4BA23C03823F59ECAF94A40E0620CACE3B823C03823F59ECAF94A4000E5B67D8FA223C05801F73C7FF84A40004D4A41B79F23C0E0B2B5BE48F84A4060A35703949E23C03838F581E4F74A4060CA8635959D23C030DB87BCE5F64A40E0D9E4F0499F23C010C45DBD8AF64A40E0FFFFFFFF9F23C0D8AC33BE2FF64A4060022846969C23C0303B3602F1F44A4080E5CFB7059B23C0F8230C0396F44A40E00D130D529823C0805A457F68F44A402076A6D0799523C0E0BEB9BF7AF44A40E0963AC8EB9123C0D8031F8315F54A4080D68A36C79123C010CD203EB0F54A4080F3E2C4579323C0B8656B7D91F84A4000D462F0309523C0885D86FF74F94A40605DA27A6BA823C050BC033C69FD4A4020BA2EFCE0B423C06082C5E1CCFF4A4080E7DEC325DF23C008D3A23EC9074B40204487C091E023C0D8AC33BE2F0E4B40E0AE42CA4FDA23C06037177FDB0F4B4060AAEE91CDE523C0C8C16C020C174B40E0C534D3BDE623C05810AE8042174B40804A22FB200324C078423D7D041C4B408008AA46AF0624C0E0A6B1BD161C4B40607AFB73D10824C08815E0BBCD1B4B40401B2B31CF2A24C0E082177D05134B4080677A89B12424C0D88558FD11104B4000C85EEFFE2024C0E00CE2033B0C4B4000C85EEFFE2024C0002DCF83BB0B4B40203201BF462224C00815C781570B4B40403674B33F2824C0386211C30E0B4B402067614F3B2C24C0386211C30E0B4B40408B4F01303624C0009A417C600B4B40600BEBC6BB3B24C0002DCF83BB0B4B40004D4A41B73F24C038F6D03E560C4B40206AA2CF474124C0500DFB3DB10C4B40E0A02FBDFD4124C0089700FC530E4B40C0B7054B753924C0001B4982701D4B400053CC41D02924C0E07C957CEC204B4000C85EEFFE2024C0101E8A027D224B40E085E63A8D0424C08860C77F81264B40001D588E900124C0D0C43BC093264B4000560DC2DCFE23C08860C77F81264B40805EB7088CC523C030F911BF62214B4080677A89B1C423C088457EFD10214B400053CC41D0C923C0D0BB783F6E1F4B40A0643909A5CF23C0901B62BCE61D4B40A044A0FA07D923C028F6D03E561C4B40608FC2F528DC23C0100C0401321C4B4000E5B67D8FE223C030DEC83CF21B4B406008AA46AFE623C008DFA63FFB1B4B40E0FCBE7FF3EA23C0F8BDDBBC711C4B40E09DEE3CF1EC23C030D505BCCC1C4B40E0CFEFFB37EF23C0A068ACFD9D1D4B406092037635F123C08096E7C1DD1D4B40402A70B20DF423C08048BF7D1D1E4B40206420CF2EF723C0E0FA5B02F01D4B4040A8A78FC0F723C010A0C37C791D4B402035423F53F723C090397AFCDE1C4B402076A6D079F523C030DEC83CF21B4B4060AF5B04C6F223C02814E97E4E1B4B4020ABE80FCDEC23C078992842EA1A4B40006420CF2ED723C0001E8A027D1A4B4000F4FBFECDCB23C0001E8A027D1A4B40402DB1321AC923C0A8E67283A11A4B40408C81751CC723C0901EA33CF31A4B40A03DEC8502BE23C090397AFCDE1C4B4080EA1F4432B423C0101E8A027D224B40600569C6A2B123C04837177FDB274B40403CF6B358B223C00018080264284B408049F08634B223C0D87C957CEC284B408052B3075AB123C06073B9C150294B40C0355B79C9AF23C0788AE3C0AB294B40E010548D5EAD23C0503D997FF4294B40E0A57F492A9B23C008D061BEBC2A4B40C09AADBCE49723C02035B401D82A4B40001D588E908123C0B0A10DC0062A4B40E0A57F492A7B23C0788AE3C0AB294B40E0EA387EA82C23C0E000DE0209284B4040747973B8FE22C0D88558FD11284B402067614F3BAC22C0B8656B7D91284B40A0436E861B8822C008E5284014264B40001A170E846C22C0904B00FE29234B40207024D0606B22C0C8D03FC1C5224B40C07C23BA676522C0109700FC531E4B40205E9ECE154D22C0588E0244C1164B40E0FD2AC0774322C0205D177E70144B4080EB51B81E4522C0305FD04202164B40000BD28C454322C0608BC1C3B4194B4040272F32011F22C08015E0BBCD234B40E093F947DF1C22C0D8A6B1BD16244B40000E130D521822C028232E008D244B4000D462F0301522C0A8ECF483BA244B4000E275FD820D22C0580DFB3DB1244B40004D4A41B7DF21C060F5F23B4D244B40804F72874DDC21C0080C040132244B40408B4F0130D621C0E07954FCDF234B4020594E42E9D321C0E0C77C40A0234B40E0D9E4F0497F21C0588BC1C3B4214B4060F964C5703D21C0E07C957CEC204B4000508BC1C3F420C0881EA33CF3224B40C023D5777EF120C0386211C30E234B40C02FD978B00521C0D00F238447294B404024EEB1F40921C0E0EE5701BE294B4000FFCD8B130F21C0D0066003222A4B40E0FCBE7FF32A21C060FEB5BC722B4B40803E1EFAEE2E21C0B0DDAF027C2B4B402076A6D0793521C0A0B05241452B4B40E0F63C7FDA4021C0B0E67283A12A4B40207024D0604B21C0D0B837BF612A4B40E0D362F0305521C0E8AF743E3C2B4B40006DE34F545621C0F82CCF83BB2B4B40400F27309D5621C0000C0401322C4B40608B4F01305621C0B8ECF483BA2C4B4040AF5B04C65221C000A0C37C792D4B40E010548D5E4D21C05076FA415D2E4B4060C1C3B46FDE20C0D80F238447394B404068757286CA20C000E869C0203B4B406088467710C320C080B1BE81C93B4B40203CF6B358B220C080A86DC3283C4B40E06915FDA19120C000240C03963C4B4080ED60C43E8920C0081E8A027D424B40203674B33F8820C028E78BBD17434B40C0997B48F86620C068F833BC59494B40C0A3703D0A5720C0302CF180B24B4B40207365506D6020C060465C001A514B404083BEF4F6C720C0B89B8BBFED4F4B4060A35703941E21C09060C77F814E4B40408E90813C2B21C020E44A3D0B4E4B40E0F63C7FDA4021C0B8A44E40134F4B40608FC2F5285C21C00818080264504B4060B29C84D26721C0386BD44334524B40E0D9E4F0497F21C0881EA33CF3524B4060A69883A09321C080A86DC328544B40E0D362F0309521C010BEDBBC71544B4000FC8C0B079A21C0A8E0F08288584B40C0B7054B759921C038E109BDFE584B4040A8A78FC09721C058F833BC59594B404086FF74037D21C010D6E3BED55C4B40E0DE347D767821C0A8B6D4415E5D4B40400F27309D5621C0100F45813E614B4000DAE4F0493F21C0001E8A027D624B40A02094F7713C21C0A8E67283A1624B4060920376351121C0885A457F68644B4000E275FD820D21C000BEDBBC71644B40E076A1B94EFB20C0B0E3310395654B4060D349B6BABC20C0101E8A027D6A4B4000D462F030B520C050FEB5BC726B4B40E0ED79FEB4A120C0B05626FC526F4B40E0F63C7FDAA020C0A86E2EFEB66F4B4040AE2990D9A120C090C9C6832D704B4000F4FBFECDAB20C00815C78157734B4040A2258FA7AD20C0682B137EA9734B4080DF4DB7ECB020C0D0F4D901D7734B40409DD5027BB420C0E07954FCDF734B4060C1C3B46FBE20C008C79E3D97734B4000D3307C44C420C0A8B0524145734B40C0BD874B8EC320C0306BD44334724B4040AE2990D9C120C0000F45813E714B40000BD28C45C320C0F02F1004C8704B40A02FD978B0C520C000CADFBDA3704B40608E90813CCB20C038E109BDFE704B40E0FFFFFFFFDF20C05034D6FECE724B402053CC41D0E920C0B89ECC3FFA744B40204A09C1AAEA20C0881B62BCE6754B40207024D060EB20C0206552431B784B40A0CCCCCCCCCC20C0F8C01C3D7E774B402055A2EC2DC520C0D8B5BDDD92784B40C0E6FF5547CE20C0A82F849CF7794B40C086A757CADA20C0B88009DCBA7B4B404097530262EA20C0905704FF5B7F4B402053CC41D0E920C0E0D38041D27F4B40E0E4B67D8FA220C0D8FA5B02F08D4B406086FF74035D20C0D88BDAFD2A924B40007024D0600B20C0386E15C440974B40803EE60302ED1FC0C0FEEBDCB49B4B400019541B9CC81FC080E7DEC325994B40C0F9D4B14A991FC0C010AB3FC2964B40C09C2E8B897D1FC0604FE61F7D994B404042226DE36F1FC0384A5E9D639C4B40809658198D2C1FC0D888997D1E9F4B4040D593F9472F1FC0F8D8CF62299C4B40C0C1C073EF411FC040EF8D21009A4B4000CFBD874B3E1FC078546EA296964B4000E17CEA58151FC0F021E17B7F974B40C03C9D2B4AD91EC03074B33F50944B4080E1CD1ABCCF1EC0702A1900AA924B40408EAB915DC91EC0D040D7BE80904B4080A59C2FF6CE1EC040CBBA7F2C8E4B40C0963AC8EBD11EC020232E008D8C4B40400E2C47C8D01EC060431B800D8C4B4040CFF41263C91EC0B07A32FFE88B4B40C0D11C59F9C51EC0080C0401328C4B40C0F3FBFECDAB1EC0D88BDAFD2A924B40C051B81E85AB1EC000D061BEBC924B400021AD31E8B41EC000A0C37C79954B40C08096AE60CB1EC058793BC2699B4B4040FCA5457DD21EC090423D7D049C4B40002C7FBE2DD81EC0E00CE2033B9C4B40007D3CF4DDDD1EC0B0A78FC01F9C4B40001D588E90E11EC0002DCF83BB9B4B4000698EACFCE21EC0A0E67283A19A4B40C02407EC6AE21EC0C87C957CEC984B400088D51F61D81EC0D070033E3F964B40405184D4EDDC1EC00009FCE1E7954B40C01B0A9FADF31EC048BC75FEED964B4000CAFB389A031FC0F863CC5D4B984B408019E25817271FC038029CDEC5994B40802DC901BB2A1FC02899805F239B4B40009A94826E0F1FC0E86FB4E3869D4B40407CEC2E50F21EC0806C04E2759F4B40C08096AE60CB1EC0D8C1FA3F87A14B408047E17A14AE1EC05834D6FECEA24B40C07A14AE47A11EC000E869C020A34B404001F6D1A98B1EC09054C37E4FA24B40007E37DDB2831EC0808AE3C0ABA14B404039B5334C1D1EC0F817080264904B40C03BDD79E2191EC0E0BB783F6E8F4B400022A81ABD1A1EC0089700FC538E4B4000C972124A1F1EC050707841448C4B40401059A489271EC028E78BBD178B4B4000E275FD822D1EC088992842EA8A4B4000880E8123411EC0B0E67283A18A4B4040ABE80FCD4C1EC0808AE3C0AB894B408078EC67B1641EC0D8D38041D2874B400017D68D77771EC038DB87BCE5864B404001F6D1A98B1EC0603A58FFE7844B40C058350873BB1EC0B053E57B467A4B40401C5DA5BBBB1EC0A074B0FECF794B404049D74CBEB91EC028F911BF62794B40804C310741A71EC010068200197A4B4000A69883A0931EC0D882177D057B4B40002EAC1BEF6E1EC0D8CDFE40B97D4B4000B3976DA74D1EC010CADFBDA3804B4000880E8123411EC0B0C2D84290814B40403E05C078161EC0D0C77C40A0834B400016DBA4A2111EC0D8F4D901D7834B4080D9CBB6D3061EC0E00CE2033B844B4000FED2A23EE91DC0080341800C854B4040A5660FB4E21DC0E0031F8315854B4080A3703D0AD71DC0001B498270854B4040C2F5285CCF1DC008E5284014864B40807138F3ABC91DC0A877F17EDC864B40C0698995D1C81DC0F8BA9A3C65874B4040B06F2711D11DC028172AFF5A904B40C0BFCDE2C5D21DC068F833BC59914B40C0FECD8B130F1EC05840DAFF00974B40C03BDD79E2191EC05837177FDB974B400084B9DDCB2D1EC0D0F71A82E3984B40806F0B96EA321EC0888AE3C0AB994B4000DD257156341EC0D8066003229A4B404077BAF3C4331EC0F8CF61BEBC9A4B40C01B261AA4301EC0909065C1C49B4B400067614F3B0C1EC000E869C020A34B40800E2C47C8901DC0386893C327A54B4040EC4CA1F36A1DC0104BE7C3B3AA4B4000CEC29E76981DC0D8B2B5BE48B04B40400455A357931DC0B0656B7D91B04B408085E63A8D841DC0E0CABDC0ACB04B4040560DC2DC7E1DC0806649809AB04B40400F27309DF61CC0000341800CAD4B4000DCF3FC69C31CC008D061BEBCAA4B40C0F2C98AE1BA1CC0E08BDAFD2AAA4B4040C3F01131351CC0E0D03FC1C5A24B40C0402D060FD31BC0B09B8BBFED9F4B4040880E8123C11BC0A877F17EDC9E4B40C00CFFE906BA1BC0E0AC33BE2F9E4B4080F0A1444BBE1BC0B0A78FC01F9C4B40806CE8667FD01BC030E78BBD179B4B4000282A1BD6441CC0009700FC53964B4000A69883A0931CC02814E97E4E934B40C0688EACFCA21CC0A06BED7DAA924B40809CBCC804BC1CC0D8F71A82E3904B4000D7A3703DCA1CC00021CB82898F4B40000BEC3191021DC07021C84109894B40801803EB384E1DC038327381CB854B40C0D0217024A01DC0B0A10DC0067A4B40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('EN','EE','EST','233','Estonia','4239','1344312','150','154','25.793','58.674','0106000020E61000000600000001030000000100000017000000B0ED26F8A6FD374038D505BCCC0C4D4070DA1B7C61FA3740A8BF97C2830C4D404081CD3978F63740180ED940BA0C4D40C07A32FFE8F33740885182FE420D4D40F0D90242EBF13740801B62BCE60D4D4080B471C45AF037403829B000A60E4D4060D4997B48F03740F80B76C3B60F4D4050672783A3F037405819FF3EE3104D40307E8CB96BF13740D0D90242EB114D4020085740A1F237403035B401D8124D4000A986FD9EF43740F8FF71C284134D4060C554FA09F73740D064FF3C0D144D40108DD13AAAFA3740782DE8BD31144D4070C6F7C5A5FE374088008BFCFA134D4000274D83A2013840886308008E134D40E02B2CB81F043840D082177D05134D40C06D50FBAD05384040D13C8045124D40109700FC53063840B0C2D84290114D40A05FE97C78063840A89E3E027F104D4070431B800D0438403829B000A60E4D40001E8A027D0238408896E7C1DD0D4D40109D82FC6C003840F8EDEBC0390D4D40B0ED26F8A6FD374038D505BCCC0C4D4001030000000100000064000000B0ED26F8A6FD3640B0BF97C2834C4D40306E15C440173740584F1F813F484D400015C78157433740A841D13C803F4D40701B62BCE6453740D0DC43C2F73E4D40E025AAB7064A374060EFE2FDB83D4D40D0F92AF9D851374020E78BBD173B4D40A024253D0C55374030266F8099394D4030ED0DBE305537402802D53F88384D40F05A0A48FB533740E0A623809B374D40D0BEB9BF7A443740D8DC43C2F7364D402000000000403740A8A44E4013374D4060766C04E2393740A059D93EE4374D403093533BC3343740A87D737FF5384D40C0F06778B3323740A0C2D84290394D4070E09D7C7A24374008301004C8384D4070B08D78B213374028C0B0FCF9344D40009D82FC6C10374030F911BF62314D40B05626FC5207374038327381CB2D4D40B0EF3504C7C13640608E0244C11E4D40F0E506431DA6364008A0C37C791D4D40F03B1405FA943640B877F17EDC1E4D4050CDE506438536406040DAFF001F4D40D0F6E978CC7C36406040DAFF001F4D4090C3B64599793640D8DC43C2F71E4D408018213CDA603640A84412BD8C1C4D405069C537145E364028C9737D1F1C4D40E0548847E24936402023A0C211184D40F040F339774736408842AF3F89174D4040809BC58B453640A877F17EDC164D4060D6A88768443640601C40BFEF154D40000C04013244364030C0B0FCF9144D40703A58FFE7443640D8DF844204144D4040E44A3D0B463640904B00FE29134D40102A8E03AF46364030F04E3E3D124D40909065C1C4433640D0031F83150D4D40306211C30E433640E0DF8442040C4D40209221C7D6333640B0AD11C138FE4C4020F911BF6219364070A52C431CF74C40D0D03FC1C5123640D0B5F63E55F54C40407288B8390D3640605B238271F44C40808AE3C0AB093640E0915CFE43F44C40E0488446B0053640605B238271F44C40A0E67283A1023640E0D6C1C1DEF44C4040EACC3D24003640A0B6D4415EF54C40F0FD0E4581FE3540D0E506431DF64C4020205F4205FB354028085740A1FA4C40507B4B395FFC354030C0B0FCF9FC4C408024253D0C153640A074B0FECF094D40E0DC43C2F7163640001E8A027D0A4D40108C9FC6BD19364000BB0CFFE90A4D40D0F6E978CC1C3640606DA983BC0A4D40002A8E03AF263640B083F57F0E0B4D40903F6EBF7C32364028266F8099114D40C0E7A4F78D33364008A304FD85124D40F03DB2B96A323640089A417C60134D4060D4997B48303640D8DF844204144D40405260014C2D3640087C293C68144D4030ED0DBE30253640B0923A014D144D40900F5EBBB42136408045F0BF95144D40D02B2CB81F1436408096E7C1DD154D40E046753A90113640E097DEFE5C164D40E03DB2B96AE23540E0B2B5BE48204D4070C6F7C5A5DE354030266F8099214D40A030293E3ED93540B84DD53DB2234D40908636001BD8354038232E008D244D405058E20165D73540507FBDC282254D4020857AFA08D83540081286014B264D40E058FB3BDBDF3540F8FF71C2842B4D4040085740A1E23540787B1002F22B4D4050CE177B2FE6354030179CC1DF2B4D4000A986FD9EF43540A07A32FFE82B4D4060B81E85EB013640F8EDEBC0392D4D4010274D83A201364008E52840142E4D40E041960513FF354008B58AFED0304D40B06BED7DAAEA35404882FE428F3A4D40D05D4BC807E93540B8B05241453B4D40C0FC6B79E5E63540B07A32FFE83B4D4000301004C8E03540600DFB3DB13C4D4060499D8026DE354000EEEBC0393D4D40503D997FF4D9354030FC523F6F3E4D40F03B1405FAD4354010CADFBDA3404D40D0F3A8F8BFD7354090457EFD10414D40C0F6E978CCEC3540A88CB80034424D4050C8957A16FC35400806820019424D4040EACC3D24003640883CBB7CEB414D40D0F6E978CC1C36405840DAFF003F4D40209D82FC6C3036406031957EC2454D40E0D03FC1C5323640109700FC53464D40809065C1C4533640C8D90242EB494D40009D82FC6C803640D8031F83154D4D40C04E0647C99F3640887B1002F24B4D4020895E46B1C43640F8D5E3BED54C4D403083DC4598C6364058A7AE7C964D4D40408FE046CACE364030DB87BCE54E4D4050B950F9D7D23640D8DC43C2F74E4D40A02AA73D25DF364030C632FD124F4D40B0F3A8F8BFE736403841B8020A4F4D40F055BABBCEEA3640B877F17EDC4E4D40B0A4C00298FA3640303B3602F14C4D40B0ED26F8A6FD3640B0BF97C2834C4D400103000000010000001A000000001B4982705D37406016BEBED6434D40C0073E062B3A37408815E0BBCD434D4000C710001C373740C80CE2033B444D4050780AB952173740B853E57B464A4D40206BD4433412374080B130444E4B4D40C0656B7D91103740E064FF3C0D4C4D40F0BB783F6E0F3740603A58FFE74C4D40308FE046CA0E37409096E7C1DD4D4D4000A6457D920F374030DB87BCE54E4D40D046753A9011374010A6457D924F4D40907A32FFE823374000EEEBC039554D40009700FC5326374028327381CB554D40705B2382712C37407860C77F81564D40309012BBB62F374050137D3ECA564D40B016838769333740F8DB65BFEE564D405058E20165373740588E0244C1564D40D0191879593F37406879C9FFE4554D4010A0C37C794537408024253D0C554D4080ABAE433551374078B130444E534D40C0F27684D35637405855A18158524D4030956247E358374060103CBEBD514D40B004FD851E6537408839ECBE63484D4060CE177B2F6637400821CB8289474D4020A0C37C796537408860C77F81464D4050D4997B48603740C80CE2033B444D40001B4982705D37406016BEBED6434D400103000000010000001B00000060BB5F05F8463740A8B05241457B4D40E04A5986382E3740D082177D057B4D4090073E062B2A3740204DBC033C7B4D4070C554FA09273740E0C77C40A07B4D40003C1405FA243740D8915CFE437C4D40A036AB3E5723374000C18EFF027D4D40709FAA42031D3740988CB80034824D40307B4B395F1C3740D0E847C329834D40C080B4FF011E3740807B1002F2834D40F09C82FC6C203740D8BEB9BF7A844D40C034EF3845233740583A58FFE7844D40D049B6BA9C26374030ED0DBE30854D4040FC523F6F2E3740381A6B7F67854D40806FB6B93131374028F6B4C35F854D40C01683876953374038D505BCCC844D40D0DC43C2F7563740A8BF97C283844D40702766BD185A37403044F98216844D40A00C1D3BA85C3740906308008E834D40408FE046CA5E3740801EA33CF3824D40206C06B820633740706649809A804D40B00DC00644643740786F0C01C07F4D4070D6A88768643740002A8E03AF7E4D40504CDE00336337409853573ECB7D4D40F046753A9061374028C0B0FCF97C4D4020AF08FEB75E3740A84412BD8C7C4D40D04BC5C6BC4A3740D89A1F7F697B4D4060BB5F05F8463740A8B05241457B4D400103000000010000005A0000002039D384EDBF36401000000000804D400088BB7A15CD3640580ABABDA47F4D40F0D38041D2D73640E0B2B5BE48804D40407B4B395FDC3640804E417E36804D40C080B4FF01EE3640A0CEDC43C27D4D40209221C7D6F33640F8B1497EC47B4D4040C763062A0B3740283B3602F16C4D40207156444D0C37402844F982166C4D40E0420246970B3740B083F57F0E6B4D4040809BC58B05374008E2E7BF07694D40307497C4590137408854C37E4F6A4D40401D1EC2F8F5364070A86DC3286C4D40F0D03FC1C5F236402844F982166C4D40D03DB2B96AE23640B0E67283A16A4D40300516C094DD3640D0C1FA3F87694D40A0336ABE4ADE36408093A641D1684D40B0F92AF9D8E13640A8E0F08288684D4040FF93BF7BE336406070EA03C9674D40406C06B820E3364000D6E3BED5644D40D03DB2B96AE236408015E0BBCD634D4050465C001AD93640C882177D05634D407018213CDAD03640F8BA0CFFE9624D40C059677C5FCC3640C882177D05634D408093A641D1C8364080B130444E634D40F08D3D7B2EC7364060431B800D644D4040BB5F05F8C63640D088997D1E654D40B0E0F08288C83640881B62BCE6654D40A01EA33CF3CA364020FC523F6F664D4070B60F79CBCD3640A077F17EDC664D40C0F06778B3D2364000BE4D7FF6674D40B00DC00644D43640382F3201BF684D40B0E7A4F78DD3364000C11C3D7E694D408021E4BCFFCF3640D073D2FBC6694D40207156444DCC364030266F8099694D40D049B6BA9CC6364008301004C8684D40A014747B49BF364080A52C431C674D40D07344BE4BBD364020FC523F6F664D40B0EAE5779AB8364060431B800D644D40A0E7A4F78DB336406001F73C7F604D4080B5A33847B13640B84A94BDA55E4D4010874F3A91B03640300516C0945D4D40A0336ABE4AAE3640082DCF83BB5B4D40300ED940BAAC3640881EA33CF35A4D40606DA983BCAA364008F12C41465A4D4020A0C37C79A53640D8949D7E50594D40C04E0647C99F3640D89D60FF75584D409019C40776983640A08636001B584D40C04F38BBB5903640B059D93EE4574D4070A86DC3288C3640F8BD4D7FF6574D40206552431B8836407887140324584D4060A7CAF78C843640D89D60FF75584D4020369204E17A3640A0C2D84290594D40D070033E3F78364080A2EBC20F5A4D4000C710001C77364078992842EA5A4D40206F47382D7836405864E602975B4D40F0B48AFED0783640C8EE5701BE614D40704CDE0033733640A0B915C26A6A4D4020C4CF7F0F72364028D236FE446B4D4080A99F37156D364000A0C37C796D4D40300B98C0AD67364008A6457D926F4D40C07A32FFE8633640301ADD41EC704D4030111AC1C6613640E0C1FA3F87714D4080C6F7C5A55E3640603D997FF4714D4030E44A3D0B563640286BD44334724D4040DB87BCE546364070758E01D9714D402099D53BDC3E3640D89D60FF75704D40706DA983BC3A36407839ECBE63704D40E03A71395E2D3640E873D2FBC6714D4040F04E3E3D2A3640D88BDAFD2A724D40C0B2B5BE48103640B8AD11C138764D40A0ED26F8A60D3640508E0244C1764D40C0622AFD840B3640885704FF5B774D405034D6FECE0A364028D5777E51784D40C0F5B704E00B3640887E5182FE784D40D03A71395E0D3640B0C2D84290794D40F04543C6A310364010D9243FE2794D40301ADD41EC3036406031074147794D4040EACC3D24603640B074B0FECF794D40A00A7F86376F3640282CF180B27B4D40E0D38041D2773640788A5583307D4D40F0D6C1C1DE7C36405040DAFF007F4D4030E44A3D0B86364038BA2EFCE0824D40C01683876993364000301004C8884D40309BE447FCB23640E0C43BC093864D40B0F92AF9D8B1364080698A00A7854D4070D2FBC6D7B23640D0A3E2FF8E824D40407CEE04FBB33640E0EE5701BE814D40F070033E3FB83640607C7C4276804D4020179CC1DFBB364088C9C6832D804D402039D384EDBF36401000000000804D40010300000001000000D501000040D2C43BC0C73940B09E3E027FD04D4080BD344580DF3940D8A96400A8CC4D4020369204E1FA3940787E5182FED04D4040BC9179E4073A40000C76C3B6CF4D4060C763062A0B3A400079E8BB5BCF4D40E05A0A48FB133A40D0D6C1C1DECC4D402015C78157433A40501F813FFCCA4D4010B2497EC4633A403838F581E4C74D4070D7DAFB54753A40805182FE42C54D4000369204E17A3A4038F6D03E56C44D40F061BEBC007F3A40782DE8BD31C44D40B05FE97C78863A4060888043A8C44D40208C9FC6BD893A40809FAA4203C54D40F04E0647C98F3A4030327381CBC54D40A0069B3A8F923A40F81186014BC64D40D05A0A48FB933A4088A52C431CC74D4070129F3BC1963A40F8A5457D92C74D40902AA73D259F3A40F8F36DC152C74D407061A5828AA63A4030145B41D3C64D4020C18EFF02AD3A4008E5284014C64D40102E01F8A7BC3A4028BA2EFCE0C24D4010335184D4C53A406001F73C7FC04D4090ABAE4335D13A40A8A17F828BBD4D40D0C1FA3F87D93A402844F98216BC4D4010917EFB3ADC3A40D0C77C40A0BB4D40C08CB80034E23A40D8D03FC1C5BA4D4040179CC1DFEB3A40608BC1C3B4B94D40E0DC43C2F7F63A40A87D737FF5B84D40A008707A17FB3A40F8B48AFED0B84D40C0E0F08288083B4058672783A3B84D402077D84466163B40886649809AB84D4070DD5CFC6D2F3B4080ABAE4335B94D401045D7851F643B40F8F9EFC16BB94D40E03A71395E6D3B4020F911BF62B94D40F046753A90713B407830293E3EB94D40D0EEC9C342753B40787E5182FEB84D40E04CF73AA97B3B40D070033E3FB84D40A0069B3A8F823B40E0A623809BB74D40300516C0948D3B40B877F17EDCB64D4060465C001AD93B40E064FF3C0DB44D40207E8CB96BE13B40882DE8BD31B44D4050ED0DBE30E53B40007C293C68B44D40F057C9C7EEEE3B40A03B4F3C67B54D40802DE8BD31F43B4038FC523F6FB64D4060DA1B7C61FA3B408039ECBE63B84D40F04A598638FE3B40E873D2FBC6B94D40409012BBB6FF3B405807793D98BA4D4050431B800D043C40D0EEC9C342BD4D4090129F3BC1063C4078724D81CCBC4D4020FF93BF7B133C4030C3F17C06BA4D40D0DF8442041C3C40D0D38041D2B74D405064E602972B3C4088992842EAB24D4090336ABE4A2E3C4080758E01D9B14D4020274D83A2313C40B08636001BB04D4060C2137AFD313C4028F38FBE49AF4D40D046753A90313C408860C77F81AE4D40907C26FBE72D3C4068AF22A303AA4D405094BDA59C2B3C40387AFCDEA6A74D40602E71E481283C404047567E19A64D40A0C937DBDC243C4048CEFBFF38A54D4060185B0872183C401866136058A44D40209CC1DF2F0E3C40287D21E4BCA34D401040C05AB5073C40E0FD2AC077A34D408009A359D9023C4048E38920CEA34D40900CC85EEFFE3B4030CC7B9C69A44D4040745E6397F83B4098B1DAFCBFA44D40F079A9D898F33B4080033E3F8CA44D40B0CCCD37A2EB3B40786000E143A34D40E0635B069CE93B4018336DFFCAA24D40F07B2AA73DE13B40A8CB2901319D4D40009700FC53D63B4080B130444E934D40009C508880CF3B40E088997D1E8D4D40C0ED26F8A6CD3B4000BB0CFFE98A4D407034D6FECECA3B40A88636001B884D40408C9FC6BDC93B40A841D13C80874D4060E09D7C7AB43B40204A7B832F7E4D40C09E3E027FB03B4020D8B8FE5D7D4D40A093A641D1983B40E08E1B7E37774D4050D505BCCC8C3B40802DE8BD31744D40E0CABDC0AC883B4028FF93BF7B734D40A01342075D7E3B405819FF3EE3704D409024253D0C753B40C888997D1E6D4D40909E3E027F703B40D8D03FC1C56A4D4080BD3445806F3B40E08BDAFD2A6A4D40E0CDFE40B96D3B409018213CDA684D4090A99F37156D3B4038EACC3D24684D40C0923A014D6C3B40D0C43BC093664D40C0FFACF9F16B3B40603A58FFE7644D40C0FFACF9F16B3B40D0DF844204644D4030FF93BF7B733B4028BD6F7CED574D4080D87DC7F07C3B40D873D2FBC6494D40400516C0947D3B4088457EFD10494D405079AD84EE7E3B40180B98C0AD474D4060CAA48636803B4088AEEFC341464D40E0BEB9BF7A843B40080F45813E414D4020A0C37C79853B4010D3A23EC93F4D40E05D4BC807893B40508BC1C3B4394D4020369204E18A3B4028C0B0FCF9344D4070C763062A8B3B40A8B915C26A324D4050E78BBD178B3B405070EA03C92F4D40E04BC5C6BC8A3B40D861BEBC002F4D40F025AAB7068A3B40001286014B2E4D40C07D737FF5883B4000CD203EB02D4D40F049B6BA9C863B40B04412BD8C2C4D40107976F9D6833B40F8FF71C2842B4D40802AA73D257F3B40882766BD182A4D40507B4B395F7C3B4090457EFD10294D40102BC0779B773B4050137D3ECA264D40D0DC43C2F7763B408848BF7D1D264D40A0FC6B79E5763B4028F6D03E56244D4070CC79C6BE783B4028C0B0FCF91C4D4030F911BF62793B40009A417C601B4D40003F5585067A3B40806CCB80B31A4D4010205F42057B3B4088A2EBC20F1A4D40D04334BA838C3B40E0C1FA3F87114D408096E7C1DD8D3B40887E5182FE104D40A018213CDA903B405822C2BF08104D40D0BEB9BF7A943B40A08FF980400F4D40802766BD189A3B4010E52840140E4D4050C8957A169C3B40D8CDFE40B90D4D40B001BC0512A03B40889FAA42030D4D400045D7851FA43B40A0923A014D0C4D402077D84466A63B40D864FF3C0D0C4D40308C9FC6BDA93B40E0E847C3290B4D40507B4B395FAC3B40902766BD180A4D40E03A71395EAD3B4010C11C3D7E094D4080336ABE4AAE3B408821E4BCFF074D405070EA03C9AF3B40806308008EFB4C40A0FB3905F9C53B4028FF93BF7BF34C40007CB779E3C83B40A883F57F0EF34C4050499D8026CE3B4080A2EBC20FF24C4070D367075CCF3B40E873D2FBC6F14C402094BF7B47D13B4020473A0323F14C4060C2137AFDD13B4000301004C8F04C40D0F06778B3D23B40E058FB3BDBEF4C4030085740A1D23B4008F46DC152EF4C40406BD44334D23B40E076137CD3EE4C4080B471C45AD03B409048BF7D1DEE4C40D05D4BC807C93B40F8230C0396EC4C4000301004C8C03B40D09A1F7F69EB4C4010CA518028BC3B40801EA33CF3EA4C4020B2497EC4B33B40301DACFF73EA4C40705B238271AC3B40B853E57B46EA4C402094BF7B47A13B4088A2EBC20FEA4C40909065C1C4933B40C8949D7E50E94C40106893C3278D3B40E0F71A82E3E84C40202DCF83BB8B3B40D8CABDC0ACE84C4070BC9179E4673B40280B98C0ADD74C40E049B6BA9C663B4058137D3ECAD64C4050465C001A593B40602EC6C03ACC4C407093A641D1583B40A0C85A43A9CB4C407093A641D1583B4000E869C020CB4C4050465C001A593B40B8E67283A1CA4C4090BAF3C4735A3B40F82F1004C8C84C4020240C03965C3B4010E5284014C64C40809FAA42035D3B4078698A00A7C54C40D02E35423F5F3B4090C3D2C08FC44C40D0BB783F6E4F3B40E0DF844204C44C40F09600FC53163B40F0BD4D7FF6C74C4000A986FD9E143B4028EACC3D24C84C4050C2137AFD113B4008CADFBDA3C84C40507288B8390D3B4080B130444ECB4C40802766BD180A3B40B8716F7EC3CC4C40406F47382D083B40A83B4F3C67CD4C40A0716F7EC3043B4088AEEFC341CE4C40D061BEBC00FF3A40782AA73D25CF4C40F050DB8651F83A404870EA03C9CF4C4000BE4D7FF6E73A4010E2E7BF07D14C40B0FB3905F9E53A4028473A0323D14C403075C93846E23A4058465C001AD14C4080BD344580DF3A40A8CB9BC3B5D04C4020085740A1B23A40888AE3C0ABC94C40901F46088FA23A40802AA73D25C74C4090B471C45AA03A406061A5828AC64C4000AF08FEB79E3A406831957EC2C54C40C01C0588829D3A40D00CE2033BC44C40F0D6C1C1DE9C3A4000B2497EC4C34C40A0F5B704E09B3A4058FEB5BC72C34C4070D026874F9A3A4088B130444EC34C40503D997FF4893A403835B401D8C24C4050E44A3D0B863A40901EA33CF3C24C4070992842EA823A408036AB3E57C34C4060CAA48636503A40F81A498270CD4C4000240C03964C3A4088AEEFC341CE4C4060AA0B7899493A40D88E1B7E37CF4C40F0AC33BE2F463A40786649809AD04C4040F6D03E56343A40A07D737FF5D84C40B07D737FF5083A4028F911BF62E94C40E03DB2B96AF23940485260014CED4C4080A2EBC20FE23940500438BD8BED4C40E0E506431DD6394060499D8026EE4C40106893C327CD3940E076137CD3EE4C4070DD5CFC6D9F3940585260014CF54C40F031AEB8389E3940600438BD8BF54C40B0052FFA0A76394028F38FBE49FF4C40E064FF3C0D74394030BD6F7CEDFF4C40A083F57F0E733940382F3201BF004D40D0D90242EB713940A86BED7DAA024D4060672783A370394060FEB5BC72034D4020861DC6A46F394008B2497EC4034D40A0FFACF9F16B394020232E008D044D40A08D2441B84E3940B8B915C26A0A4D40507288B8394D3940A8E67283A10A4D40D0622AFD844B3940A8D11DC4CE0A4D40D0C1FA3F87493940D8D03FC1C50A4D40F03FC1C58A463940301DACFF730A4D4030F6D03E5644394030D8463CD9094D402015C781574339408818213CDA084D4060B08D78B2433940E058FB3BDB074D40603D997FF449394030E44A3D0B064D40307A19C5724B3940485260014C054D4060BEA085044C3940D0D6C1C1DE044D40E0D6C1C1DE4C394060FEB5BC72034D4050BFD2F9F04C3940A8B915C26A024D4030D505BCCC4C3940A874B0FECF014D40109A417C604B3940285C8FC2F5004D40D02E6D382C4939400018080264004D40B014747B493F39402041B8020AFF4C4030840EBA843B394038C632FD12FF4C40B010018750393940600ABABDA4FF4C4050C554FA09373940382F3201BF004D40201D1EC2F835394038266F8099014D408024253D0C3539405064E60297034D40802DE8BD31343940789FAA4203054D40506C06B82033394068FB743C66064D4090B5A33847313940E0A623809B074D40A080B4FF012E394030E109BDFE084D4040840EBA842B3940D0C1FA3F87094D40208C9FC6BD293940488BC1C3B4094D40E0C77C40A0233940A074B0FECF094D40F058FB3BDB1F394058103CBEBD094D40D040F33977173940B0AAD0402C094D40C0D90242EB113940A8380EBC5A084D4000A6457D920F3940D0D38041D2074D40B074B0FECF09394038FC523F6F064D4070431B800D0439408824253D0C054D40A010018750B93840B0622AFD84FB4C40F09B5088808F38407854C37E4FFA4C40D0CDFE40B98D3840A88CB80034FA4C40A01EA33CF38A3840B074B0FECFF94C40507CEE04FB733840D85B3CBCE7F44C40705E64027E71384000B2497EC4F34C40401ADD41EC70384088B130444EF34C40D0EB884336703840F8F02C4146F24C4000429605136F384020F911BF62F14C40901C0588826D3840F802B34291F04C406064E602976B384028BD6F7CEDEF4C4050C554FA0967384060DD5CFC6DEF4C4070BD3445805F3840D88E1B7E37EF4C40C083F57F0E5338405058E20165EF4C40F0E47E87A2503840B8E68EFE97EF4C406061A5828A56384078AEEFC341F64C403002D53F88583840C870033E3FF84C403083DC45985A3840A88CB80034FA4C4070BFD2F9F05C3840D8DF844204FC4C40109221C7D663384030172AFF5A004D40F049B6BA9C66384088A2EBC20F024D4040D9E9077569384008B2497EC4034D4070A99F37156D384080CC07043A054D4000429605136F3840881B62BCE6054D40E05B3CBCE774384058103CBEBD094D40E050DB8651783840F80B76C3B60F4D4080CC79C6BE7838405819FF3EE3104D40B0EAE5779A783840D082177D05134D40409E25C80878384088008BFCFA134D40309221C7D67338405858E20165174D40506F47382D783840A0C519C39C1E4D40507F2F8507793840580ABABDA41F4D40308DD13AAA7A3840089D82FC6C204D40002E01F8A77C384050465C001A214D4080BD3445807F3840F8C01C3D7E214D40B0F27684D386384038E78BBD17234D4000369204E18A3840885A457F68244D4070499D80268E3840305FD04202264D4060D367075C8F38408878CF81E5264D40D04E0647C98F3840D08558FD11284D40A00A7F86378F384000E2E7BF07294D40D031AEB8388E384000D9243FE2294D403083DC45988A384018D236FE442B4D4050A7CAF78C84384038ED0DBE302D4D4010A0C37C79753840F89C82FC6C304D40A09BFD81726B3840485E64027E314D40D05A0A48FB633840B8A10DC006324D40B0F6E978CC5C3840C88BDAFD2A324D40002F6D382C593840B8A10DC006324D40901B62BCE655384050103CBEBD314D4030FF93BF7B533840000F45813E314D4050BFD2F9F04C384008E52840142E4D40102DCF83BB4B3840286893C3272D4D40A0FE7A85054B3840A883F57F0E2B4D4040E78BBD174B3840303E7782FD294D40D04BC5C6BC4A38408893A641D1284D40D0C1FA3F874938402838F581E4274D4040BC9179E447384078A52C431C274D40E061BEBC003F3840C89A1F7F69234D4070D87DC7F03C3840486DA983BC224D40307156444D1C384050EFE2FDB81D4D40408C9FC6BD19384080AEEFC3411E4D40B0F3A8F8BF1738407078CF81E51E4D4050DC2A88810E3840F8F02C4146224D4060BFD2F9F00C3840D882177D05234D40E0D03FC1C5023840A0AD11C138264D40104B598638FE37404858E20165274D40004818062CF93740009D82FC6C284D40306C06B820F33740E00F238447294D40B001BC0512F03740608BC1C3B4294D40B0E7A4F78DD33740B03B4F3C672D4D40106552431BC8374000D6E3BED52C4D40E0B5F63E55C53740805A457F682C4D4010A304FD85BA3740A8BC5642772F4D4000B8CB7EDDAD3740B05FE97C78364D40705E64027EA13740D082177D05434D403098A3C7EF9D37408036AB3E57434D40009700FC53863740A8BC564277474D40E0B2B5BE4880374038D8463CD9494D404099D53BDC7E3740C8B56801DA584D40C0FB3905F985374058499D80265E4D400021CB828987374008DC65BFEE5E4D40603D997FF4893740B841D13C805F4D40A00C1D3BA88C3740E08E1B7E375F4D40A0EF3504C791374058499D80265E4D40E0B5F63E5595374030B7ED7BD45D4D40C074B0FECF993740A8CEDC43C25D4D40308C9FC6BDB9374000F46DC1525F4D403069C53714DE37400006820019624D409021E4BCFFDF374058DA1B7C61624D40107A19C572DB374098C85A43A9634D40909065C1C4D33740785182FE42654D4060499D8026CE3740B0AD11C138664D402083DC4598CA37408860C77F81664D40C040F33977973740D0D6C1C1DE644D40F04CF73AA97B3740300B98C0AD674D406064E602976B3740B84DD53DB2734D4000A304FD856A3740B04412BD8C744D4070DA1B7C616A3740A068ACFD9D754D40901342075D6E3740E070033E3F784D4020C4CF7F0F7237408839ECBE63784D40B0073E062B7A37408021E4BCFF774D4070B81E85EB813740F0BD4D7FF6774D4050B08D78B29337408830293E3E794D40C049B6BA9C96374008ACC77DAB794D40E034EF3845A33740602EC6C03A7C4D40B0F06778B3A23740788A5583307D4D40A018213CDAA03740D88558FD11804D4010A6457D929F3740283E7782FD814D40A080B4FF019E3740506DA983BC824D40208E3D7B2E973740A8BF97C283844D40101E8A027D92374080698A00A7854D40D0BB783F6E8F374000E5284014864D40B0656B7D9190374080CC07043A854D40108BFCFA21923740A8BF97C283844D40503D997FF499374008BB0CFFE9824D40D0DF8442049C3740F8F02C4146824D40900C1D3BA89C37406073B9C150814D40C0FE7A85059B3740A8E0F08288804D4010FC523F6F8E374028FC523F6F7E4D40F0C77C40A0833740280516C0947D4D404058E20165773740D07FD6FCF87D4D40409221C7D673374080AEEFC3417E4D4030861DC6A46F3740580ABABDA47F4D40E0548847E269374008274D83A2814D40504F1F813F68374058DA1B7C61824D40A0ED26F8A66D3740A84A94BDA5864D40A077F17EDC6E374008A6457D92874D40A018213CDA703740504F1F813F884D4030840EBA847B3740989BFD81728B4D4090AF21382E773740A09E3E027F984D405061A5828A763740F87E6ABC74994D4020145B41D3763740A8B915C26A9A4D40B019C40776783740584CDE00339B4D40F038D384ED7F374058732B84D59C4D40C0D03FC1C582374000EEEBC0399D4D400088BB7A159D3740F8298E03AF9E4D40D0E506431DB63740380516C0949D4D40A0073E062BBA3740A03B4F3C679D4D4090A99F3715BD3740B053573ECB9D4D4020AF08FEB7BE374098C519C39C9E4D406082700514BE3740F820CB82899F4D40F05CDF8783BC3740D8B2B5BE48A04D40308C9FC6BDB9374000D9243FE2A14D4050ECA17DACB83740606DA983BCA24D40506DA983BCBA3740E09A1F7F69A34D40B080B4FF01BE3740A8C85A43A9A34D4040895E46B1D43740D0031F8315A54D40209A417C60DB3740B859677C5FA44D400045D7851FE43740601F813FFCA24D40B0F3A8F8BFE73740B86BED7DAAA24D4040861DC6A4EF37403835B401D8A24D4060BB5F05F806384008D6E3BED5A44D40D0AC33BE2F063840280516C094AD4D40A004FD851E05384028FC523F6FAE4D40901A3048FA043840B041D13C80AF4D4010335184D40538403002D53F88B04D40F040F33977073840C8949D7E50B14D40E0C1FA3F87093840283E7782FDB14D40F0D6C1C1DE0C384000F12C4146B24D40E04543C6A3103840A8B915C26AB24D40A0716F7EC3143840306BD44334B24D40801EA33CF31A384058F833BC59B14D4010861DC6A41F3840C8EB884336B04D40901B62BCE6253840101286014BAE4D40407288B8392D384000240C0396AC4D405070EA03C92F3840D064FF3C0DAC4D40109BE447FC32384030179CC1DFAB4D40A0B8E4B85336384080A86DC328AC4D4020274D83A25138408060C77F81B64D40F034EF384553384038F38FBE49B74D40C083F57F0E533840001E8A027DBA4D40C00DC00644543840E09A1F7F69BB4D40B0F27684D3563840807B1002F2BB4D40308C9FC6BD5938408893180456BC4D400088BB7A155D384000A986FD9EBC4D408024253D0C65384078724D81CCBC4D40F04718062C6938408845F0BF95BC4D4030F911BF6289384010A304FD85BA4D40407F2F8507B93840483D997FF4B94D40E04BC5C6BCCA38405073B9C150C14D40F040F33977C738405007793D98C24D4040DB87BCE5C63840F8FF71C284C34D4010809BC58BC53840885704FF5BC74D40B0F27684D3C63840584F1F813FC84D4020F04E3E3DCA3840A8E0F08288C84D40605260014CCD3840B08636001BC84D40407156444DDC384028B7ED7BD4C54D40B01342075DDE384038ED0DBE30C54D40306C06B820E33840881EA33CF3C24D4010B58AFED0E83840E07C957CECC04D40803C2D3F70ED38408893A641D1C04D4050BFD2F9F00C3940E0C1FA3F87C14D40308C9FC6BD1939407836AB3E57C34D40307A19C5721B394030C9737D1FC44D40A00A7F86371F39405870784144C44D402021CB828927394048431B800DC44D40F08AFCFA21423940B074B0FECFC14D400018080264483940A8AAD0402CC14D4010274D83A2513940D858FB3BDBBF4D40C0F5B704E05B394050137D3ECABE4D4050E09D7C7A643940304A7B832FBE4D40B0982EC4EA67394028923D42CDBE4D40C0ED26F8A67D3940D8D38041D2C74D40002E01F8A77C3940F02F1004C8C84D40406F47382D783940E0FD9C82FCD24D40B0EAE5779A783940D864FF3C0DD44D40F05E7D3CF4793940E0D6C1C1DED44D40C06A813D267E394008C18EFF02D54D40F040F33977973940485260014CCD4D4020F911BF62993940F8230C0396CC4D4080A86DC3289C3940801EA33CF3CA4D4040111AC1C6A139408093A641D1C84D4070C075C58CA43940B0380EBC5AC84D40D0D38041D2A739405022C2BF08C84D40E04334BA83AC39405022C2BF08C84D40C016838769B33940382F3201BFC84D40D052793BC2B53940C8949D7E50C94D4010C710001CB73940E08BDAFD2ACA4D4010C710001CB739408836AB3E57CB4D40D049B6BA9CB6394008F7AE415FCC4D40A00EF27A30B5394030ED0DBE30CD4D40505E64027EB13940A0C519C39CCE4D40B001BC0512B0394048DD5CFC6DCF4D4070B130444EAB3940A8C85A43A9D34D40200ED940BAAC394058E09D7C7AD44D40C061BEBC00AF39405025034015D54D4030111AC1C6B13940600438BD8BD54D40A0A17F828BB53940D0B5F63E55D54D400051DB8651B8394050732B84D5D44D40D0BEB9BF7AC43940B0A10DC006D24D40209700FC53C6394068F833BC59D14D4040D2C43BC0C73940B09E3E027FD04D40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('AU','AT','AUT','40','Austria','8245','8291979','150','155','14.912','47.683','0106000020E61000000100000001030000000100000054020000F52B9D0FCFAA2B40D482177D05634840AC5626FC52B72B40A7E67283A16248404DD6A88768C42B40D4EE5701BE6148407B14AE47E1FA2B40D57954FCDF5B484057B08D78B2032C407C992842EA5A4840782634492C192C405376FA415D5648404ED026874F1A2C40295FD042025648407B14AE47E11A2C40530438BD8B5548407B14AE47E11A2C407B9FAA4203554840FD1186014B5E2C4056F5F23B4D4C48404DDC2A88818E2C405182FE428F4A4840D0D38041D2C72C40D3F4D901D74B484059A7CAF78CE42C40556D37C1374F484056B950F9D7022D40FE9C82FC6C504840CDC98B4CC0372D405401F73C7F5048407B14AE47E13A2D40FC170802645048402B69C537144E2D40295FD042024E4840030AF5F411502D405531957EC24D4840F415A4198B662D4064CA87A06A4A484008E9297288682D40FD4AE7C3B34A4840A774B0FECF692D4029E78BBD174B48407A17EFC7ED6F2D40D1031F83154D4840F92F1004C8702D40530438BD8B4D4840257497C459712D405055A181585248404DDC2A88816E2D407C6308008E534840A376BF0AF06D2D4029232E008D54484005F86EF3C6712D40520ABABDA4574840DD989EB0C4732D40AA656B7D915848407E1B62BCE6752D40AB5CA8FC6B5948407D21E4BCFF9F2D4081423D7D04644840800F5EBBB4A12D4027F6D03E56644840B14E95EF19A92D402CD505BCCC644840A088450C3BAC2D402CD505BCCC644840DCA16131EAB22D4051888043A86448405A9E077767C52D40FE0B0401326448407E1EA33CF3EA2D40D1CDFE40B9654840772FF7C951F82D407F4E417E36784840A8716F7EC3F42D4029232E008D7C4840A8716F7EC3F42D40D1031F83157D48409F8EC70C54F62D402AE44A3D0B7E484008E3A7716FFE2D40295C8FC2F58048407B116DC7D4052E40533D997FF4814840AD50A4FB390D2E40A6B915C26A824840030AF5F411102E40D4B837BF61824840753E3C4B90212E40FDD8243FE28148404FCAA48636502E407C9C69C2F67F48404ED026874F9A2E40A9DA6E826F7E4840F4311F10E8B42E40D6AC33BE2F7E48402E54FEB5BCBA2E407E1B62BCE67D4840295C8FC2F5C82E407F87A2409F7C4840266E15C440E72E40D4EE5701BE7948407A1A3048FA042F40D47FD6FCF8754840A774B0FECF092F40530438BD8B75484056BC9179E4172F40A8716F7EC3744840842C0B26FE202F40AB59677C5F744840AA622AFD842B2F4029E78BBD17734840DC9E20B1DD5D2F40FA298E03AF6E4840AA656B7D91602F407C60C77F816E4840B151D66F267E2F407E1B62BCE66D48400C5A48C0E8B22F40F5A276BF0A6E4840CEC3094CA7ED2F405340DAFF0067484024809BC58B053040A9DDAF027C634840FA9B5088800F30405473B9C150614840A8716F7EC31430407B6649809A604840FA980F08741A304000000000006048404FCDE50643553040AB9509BFD45D4840A777F17EDC5E3040D3FA5B02F05D4840FB928D075B603040295FD042025E48407C992842EA62304079AEEFC3415E484029ED0DBE306530402829B000A65E4840266E15C4406730407AA52C431C5F48400473F4F8BD693040D38558FD116048407E1EA33CF36A3040D3F71A82E3604840FD1186014B6E3040A8A78FC01F644840D2C77C40A0733040556D37C137674840A304FD851E753040AA9B8BBFED67484079AEEFC341763040286552431B68484058AA0B7899893040D200DE020968484050C763062A8B3040AA9B8BBFED674840A304FD851EA5304029ED0DBE3065484056BC9179E4A73040FED5E3BED56448405534D6FECEAA304081423D7D04644840D6AC33BE2FB63040FB20CB82895F4840FC17080264C83040D00CE2033B5C4840A774B0FECFC9304052431B800D5C48407E9065C1C4D33040D2C77C40A05B4840FA298E03AFD63040F92CCF83BB5B484055BFD2F9F0DC304001BEDBBC715C484084F1D3B837DF30402CD505BCCC5C48404FCAA48636E03040D1031F83155D4840A7E67283A1E23040A6B6D4415E5D4840FF9600FC53E6304001BEDBBC715C48400473F4F8BDE93040FFCF61BEBC5A484050C763062AEB3040A9A10DC0065A4840AA622AFD84EB3040FA264D83A25948405A10CAFB38F23040C310397D3D4F4840D13C80457EF1304027F911BF62494840CD57C9C7EEEE3040FE0B040132444840D63730B951E83040D3F71A82E3404840027FF8F9EFDD3040FE0B0401323C4840505260014CDD30407F15E0BBCD3B484029E78BBD17DB3040D3C1FA3F873948407AA52C431CD730407EC9C6832D30484054C554FA09D73040520ABABDA42F48408109DCBA9BD73040508E0244C12E4840FC17080264D830407E1B62BCE62D4840295C8FC2F5D83040530438BD8B2D4840562B137EA9EB304027F6D03E56244840D63A71395EED3040D57954FCDF2348406C5B94D920F33040BFD7101C9723484082FDD7B969F330402AE109BDFE204840FE0B040132F43040A9A44E40131F48407E8AE3C0ABF93040286552431B1848407EE200FA7DFF30409C8C2AC3B8154840A4FB3905F9053140D5AF743E3C1348401D5A643BDF073140E469F981AB1248400E2C47C8400A3140BD6DA6423C12484092AE997CB31131408FA50F5D50114840A8716F7EC31431402B14E97E4E0B48407D96E7C1DD1D3140253B3602F10448402383DC45982A314029266F8099014840A968ACFD9D2531400000000000004840562B137EA91B314027F6D03E56FC4740FA9B5088800F3140514F1F813FF04740027FF8F9EF0D314001BEDBBC71EC47402B69C537140E31405376FA415DE647405340DAFF000F3140000341800CE54740D446753A901131405055A18158E247405055A181581231407E5182FE42DD474056B60F79CB0D31405534D6FECEDA474059A7CAF78CF43040D47C957CECD84740D82E6D382CE93040FE9C82FC6CD84740286211C30ED33040FB20CB8289D74740A8716F7EC3C43040520ABABDA4D74740286211C30EC33040A86E2EFEB6D7474052B81E85EBC13040AA9B8BBFEDD74740A7ECF483BABC3040508BC1C3B4D9474051BEA08504BC3040A9A10DC006DA4740A96BED7DAABA3040A7B0524145DB47400473F4F8BDB93040D388997D1EDD4740D82E6D382CB93040527FBDC282DD4740266E15C440B730402AE44A3D0BDE47402DCF83BBB3A230405473B9C150E14740A7ECF483BA9C3040A8AAD0402CE14740A86E2EFEB68F30407E18213CDAE04740FD1186014B8E3040F92F1004C8E04740FD14C7815773304055F833BC59D94740505260014C6D3040D3FA5B02F0D547407B9FAA42036D3040530438BD8BD54740027FF8F9EF6D30407E5182FE42D54740D0D03FC1C572304001BEDBBC71D44740D731AEB8387E3040D0D03FC1C5D24740266E15C440973040A8E0F08288D0474028F04E3E3D9A3040527C7C4276D047407A17EFC7ED9F304027F911BF62D14740D13C80457EA1304027F911BF62D147400282397AFCA23040FE0E45813ED1474029ED0DBE30A53040D3F71A82E3D0474050C422861DA630407B6649809AD04740533D997FF4A930405340DAFF00CF4740D5AF743E3CAB3040FD1186014BCE47407F129F3BC1B63040A968ACFD9DC5474059A7CAF78CB43040FD4AE7C3B3C24740F92CCF83BBA730403BC8EBC1A4BA4740A7E9B303AE973040A9DA6E826FB64740D0420246977B3040527FBDC282B54740A8E0F08288783040D1CDFE40B9B5474024809BC58B753040FE47A643A7B54740D3BEB9BF7A743040FD9FC37C79B5474057B08D78B2733040276893C327B54740FD14C781577330407F87A2409FB44740FD14C78157733040A8A78FC01FB44740CE5147C7D5743040556D37C137AF4740D1CDFE40B97D304027F6D03E56A447407D96E7C1DD7D3040D3F4D901D7A34740A3073E062B7A30407D5D86FF74A14740FE0E45813E7930407AABAE4335A14740286552431B7830402AE109BDFEA047402CD8463CD971304028F38FBE499F4740562B137EA96B30402B14E97E4E9B4740562B137EA96B3040D0D03FC1C59A474051BEA085046C30405055A181589A4740037976F9D6733040286211C30E934740A8716F7EC37430405534D6FECE924740D6AC33BE2F763040FFCF61BEBC924740FB20CB82897730405534D6FECE924740AB5CA8FC6B8130407E8D2441B88E47402DCF83BBB3823040D00F2384478147402DCF83BBB38230407E18213CDA804740A6EF3504C78130407B6649809A804740D4BB783F6E7F3040D5B2B5BE48804740D5AF743E3C7B3040D38558FD1180474052B81E85EB7130407B6649809A80474058AA0B78996930402AE109BDFE8047407D93A641D1583040D00F23844781474082035ABA824D30407D5D86FF74814740A6F27684D3463040AB5FE97C787E4740A5F8F884EC403040A96BED7DAA7A47407E9065C1C423304000CADFBDA370474056B950F9D72230402B172AFF5A7047407F87A2409F1C3040AC5626FC526F47405797530262023040D89DEE3CF16A474006F52D73BAFC2F402635B401D86A4740021077F52AFA2F40FD4AE7C3B36A47404CE2AC889AF82F40D4B837BF616A47404CE2AC889AF82F402CD8463CD9694740A56ABB09BEF92F40A8AAD0402C6147402D5DC136E2F92F4029EACC3D24604740FB230C0396BC2F4029232E008D5C4740286211C30EB32F40FB230C03965C4740D4B837BF61AA2F4001BEDBBC715C4740DBA7E331039D2F40FCDEA63FFB5B4740D3BEB9BF7A342F402638F581E45747407A17EFC7EDCF2E40AA622AFD84534740313F373465472E40A8A78FC01F5447407E1B62BCE6352E40A8A78FC01F54474008E6E8F17B332E40FCDEA63FFB5347401D1F2DCE18262E402711E15F04534740CBD8D0CDFE202E4054FEB5BC725347407638BA4A77172E40A9DDAF027C534740D1CDFE40B9BD2D40D576137CD34E47402383DC4598BA2D40D6AC33BE2F4E4740AA622AFD84AB2D40A4C2D84290494740C9E7154F3DAA2D40A8E0F082884847402577D84466A62D40505260014C454740D6A9F23D23A12D40FA264D83A2414740DF8C9AAF929F2D40D00F23844741474054C554FA09172D407AA86DC328344740A8716F7EC3F42C40FFCC203EB0354740FA264D83A2512C40FE9C82FC6C3847402D6002B7EE4E2C40AA656B7D91384740A27F828B154D2C407D93A641D138474082FDD7B969432C40A96BED7DAA3A4740AA656B7D91402C40D57954FCDF3B4740DBA7E331033D2C407B9FAA42033D474058AA0B7899392C40A8E33103953D47409F91088D602B2C4000C45DBD8A3E4740DC9BDF30D1282C40FA298E03AF3E4740A86E2EFEB6DF2B40A9A10DC00642474004013274ECB02B405182FE428F4247407632384A5E8D2B405055A18158424740B936548CF36F2B40605B3FFD67434740A3737E8AE3382B4052499D8026464740D1CDFE40B91D2B40FF08C380254747402383DC45981A2B40266E15C440474740304B3B3597DB2A40D38558FD11484740A4703D0AD7832A40AA9B8BBFED47474006F2ECF2ADA72940D1CABDC0AC5047402F51BD35B0A52940D47C957CEC504740FD14C781579329405182FE428F524740DE921CB0AB8929402B14E97E4E534740D8B628B341862940FD14C78157534740800F5EBBB4812940D2FD9C82FC524740C075C58CF07E29401EC022BF7E524740FB230C03967C2940FF05820019524740021077F52A7A2940533D997FF451474054C554FA097729407BA2EBC20F524740A8716F7EC374294028F04E3E3D52474081069B3A8F62294001BEDBBC71544740782975C9382E294027F6D03E5654474004FEF0F3DF1B2940520DFB3DB1544740BD546CCCEBF82840AF777FBC57574740753E3C4B90E12840FE9C82FC6C584740DAAA24B20FD22840533D997FF4594740CBD58F4DF2CB2840A96BED7DAA5A4740DAAD65321CC7284000C79E3D975B4740CCCF0D4DD9C128407B9FAA42035D47405AA148F7739A2840562B137EA96B4740CCD24ECDE5762840D673D2FBC6714740D6A9F23D23612840FCDEA63FFB73474052B5DD04DF5C284001BEDBBC71744740DAAA24B20F522840D4F19881CA7647402F51BD35B04528407E9065C1C47B4740AB5CA8FC6B4128407F4E417E36804740D6A9F23D23412840FE0E45813E81474055C2137AFD412840508BC1C3B481474022895E46B14428402A1DACFF7382474005FBAF73D3462840A96BED7DAA824740782975C9384E2840FBE769C020834740A777F17EDC5E2840282CF180B2834740A08B868C47612840D3F4D901D78347402F51BD35B065284027F6D03E56844740D1CABDC0AC6828407B9FAA420385474007EFAB72A1722840D38558FD11884740D6AC33BE2F762840FE0E45813E8947409F8EC70C547628405055A181588A4740DD989EB0C473284029E78BBD178B47403145B9347E7128402B14E97E4E8B47407E18213CDA602840A8A78FC01F8C4740D1CDFE40B95D2840D7A6B1BD168C4740C24F1C40BF47284078279F1EDB8A47403048FAB48A26284051853FC39B87474008E9297288882740505260014C7D4740A379008BFC822740D388997D1E7D47402C6684B707792740276893C3277D4740D2C77C40A0732740FC1A4982707D47407632384A5E6D2740266E15C4407F4740A774B0FECF692740D0D38041D27F4740CCCF0D4DD941274029266F80998147400307B474053B27407E8AE3C0AB814740CDC98B4CC0F72640A774B0FECF814740D4BB783F6E5F2640FE0B0401327C4740CDC98B4CC0572640F92CCF83BB7B4740FE0B0401325426407F4B00FE297B4740314278B4713C26402541B8020A774740782634492C39264055FB743C66764740DCA16131EA322640D388997D1E7547403145B9347E3126402CD505BCCC7447405A9BC6F65A302640AB59677C5F744740247D5A457F302640D3F4D901D773474007EFAB72A1322640FC1D8A027D724740276BD443343226405473B9C1507147403145B9347E3126407E18213CDA704740020D36751E25264029266F80996947402C634337FB2326407AABAE4335694740DE921CB0AB09264029E78BBD17634740FB20CB8289072640AB984A3FE16247403048FAB48AC62540FD4AE7C3B3624740CADE52CE17AB2540A7ECF483BA644740D4B5F63E55952540D2C43BC093664740313F3734658725405473B9C150694740B05758703F882540D673D2FBC6694740313F373465872540D0D03FC1C56A47407923F3C81F842540FE99417C606B4740CBD8D0CDFE602540520ABABDA46F4740D2C43BC0935E2540D0D38041D26F474004FEF0F3DF5B25407C9C69C2F66F47409E978A8D795525407C9C69C2F66F474082035ABA824D254051853FC39B6F4740295C8FC2F5482540556D37C1376F4740286211C30E33254027327381CB6D474055C2137AFD212540520DFB3DB16C4740FF08C380251F25407F87A2409F6C4740A777F17EDCFE2440FD9FC37C796D4740DE8FDB2F9FF424402829B000A66E4740DCA16131EAF22440813FFCFCF76E47400C76C3B645F12440C022BF7E886F4740B22D03CE52FA2440F0C341429477474058AA0B7899F92440D200DE0209784740D9B0A6B228DC2440D47FD6FCF87D4740AD50A4FB39CD244029EACC3D24804740B05758703FC82440527C7C42768047405A9E077767C524402B172AFF5A804740CCD24ECDE5B62440520ABABDA47F4740000341800CB524407E5704FF5B7F474051C1E10511B1244079AEEFC3417E474024809BC58BA524407E54C37E4F7A47409F94490D6DA024402920ED7F80774740AB5FE97C787624405401F73C7F704740FC1D8A027D7224407D21E4BCFF6F4740AC5626FC52572440D1CDFE40B96D47407632384A5E4D2440276893C3276D474010B056ED9A482440395FECBDF86C4740D0D38041D2472440253B3602F16C4740A777F17EDC3E2440A8716F7EC36C4740A27C410B09382440FED5E3BED56C4740B151D66F261E24402BDB87BCE56E4740DD955D30B8DE2340FED5E3BED5744740AC53E57B46C22340CCEB884336784740AA656B7D91C023402502D53F88784740C8EA56CF49BF23407A6CCB80B37A4740FF08C38025BF2340234DBC033C7B4740D5B2B5BE48C023404D2EC6C03A7C4740A379008BFCC22340A1A17F828B7D4740313F373465C723407C2AA73D257F4740FE0E45813EC923404F22C2BF08804740D1CABDC0ACC82340A19E3E027F804740D5B2B5BE48C0234028BA2EFCE082474007EC6AF294BD234021205F42058347405A9BC6F65A702340A9DA6E826F864740A4703D0AD7432340266E15C4408747405F7B6649803223408AABCABE2B884740000341800C352340FE9C82FC6C8847408200193A763823402AE109BDFE884740D6A9F23D23412340286211C30E8B4740020D36751E4523407AA86DC3288C47402F51BD35B04523407E5182FE428D474059A7CAF78C442340552E54FEB5904740A777F17EDC3E2340A7B052414593474055C2137AFD212340556D37C1379F4740A051BAF42F11234011A8FE4124A34740D3BEB9BF7A142340AB59677C5FA44740286211C30E332340D4B5F63E55AD47407E1B62BCE6352340FCE4284014AE47402383DC45983A23402541B8020AAF47404ACE893DB43F2340FFB1101D02AF47409F94490D6D4023405340DAFF00AF4740772CB649454323407AA52C431CAF474008E92972884823407E5704FF5BAF4740A27F828B154D2340FD4D2844C0AF4740D3BEB9BF7A5423407D93A641D1B0474054C554FA09572340FA264D83A2B147404CE2AC889A5823405182FE428FB2474057B3CEF8BE582340D482177D05B3474058AD4CF8A54E23407E54C37E4FBA47407632384A5E4D2340A96BED7DAABA4740D5AF743E3C4B23407C992842EABA4740782634492C39234081423D7D04BC47404FCAA486363023402BDEC83CF2BB4740782975C9382E2340FE0B040132BC474081069B3A8F222340A777F17EDCBE4740F52EDE8FDB1F23407F8461C092BF4740D2C43BC0931E23407C9C69C2F6BF4740C03FA54A941D2340B7EF517FBDC0474074B7EBA529222340950B957F2DC5474014CD0358E42723401024EF1CCAC447406B28B517D13623401763601DC7C34740E597C118913823401763601DC7C34740A94BC631924D23401763601DC7C34740AFEE586C936223401763601DC7C34740857CD0B359752340CE52B29C84C447402C6684B707792340295FD04202C64740314278B4717C2340FED2A23EC9C74740A86E2EFEB67F234080457EFD10C94740FA298E03AF8623402635B401D8CA4740D7A6B1BD168C2340282CF180B2CB47402F4E7CB5A3902340D7A6B1BD16CC4740DC9E20B1DD9D2340A8A78FC01FCC4740AA656B7D91A02340FCDEA63FFBCB4740295C8FC2F5E82340D1031F8315C54740CBDB114E0B16244002BB9A3C65BF4740AB5FE97C787624407D93A641D1B04740A185048C2E772440D0D38041D2AF4740AB5FE97C787624407E5704FF5BAF4740AB59677C5F6C2440D00F238447A9474057B3CEF8BE5824407F4B00FE29A34740FA264D83A2712440D5AF743E3CA34740A8716F7EC3742440A7B0524145A34740A185048C2E77244053793BC269A34740753BFBCA838C2440AA9ECC3FFAA44740D1CABDC0ACA82440A5BC564277A74740800C1D3BA8AC24407D21E4BCFFA747402B69C53714AE2440A7B393C151A8474051BEA08504DC2440FD4AE7C3B3B24740AF5DDA7058F22440FD4D2844C0B74740D0D03FC1C5F22440D5B2B5BE48B84740247D5A457FF02440AA9ECC3FFABC47404FCAA48636F02440527FBDC282BD47404ED367075CEF24407E1B62BCE6BD4740A96BED7DAAEA2440A777F17EDCBE4740D4BB783F6EDF2440F92CCF83BBC347402383DC4598DA24402CD8463CD9C94740D9B0A6B228DC2440276BD44334CA4740FD1186014BDE2440A6B915C26ACA47402B6C06B820E32440FFCF61BEBCCA474052B81E85EBF12440282CF180B2CB4740A8716F7EC3F424407E9065C1C4CB4740A185048C2EF7244000C79E3D97CB4740A27C410B09F824407F4B00FE29CB474056BC9179E4F724405307793D98CA47404CDF6B088E232540276893C327C54740800F5EBBB46125402BDB87BCE5C64740FA264D83A2D125407E54C37E4FC24740D9B3E73235F12540D2C77C40A0B34740FC1D8A027DF22540A7B0524145B34740F4311F10E8F4254029E78BBD17B347408109DCBA9BF725407E1EA33CF3B2474084F4143944042640A96BED7DAAB2474058AD4CF8A50E26405307793D98B2474004013274EC302640FD4AE7C3B3B2474058AA0B78993926405534D6FECEB24740CDC98B4CC09726402BDB87BCE5B64740C9E7154F3DEA2640A4C2D84290C14740CEC64ACCB3022740A8AAD0402CC1474004FEF0F3DF1B2740253E7782FDC1474050C422861D2627405182FE428FC24740D0D38041D22727405534D6FECEC24740F52B9D0FCF2A2740A9DDAF027CC34740D1CDFE40B95D27402635B401D8CA474054C554FA09D727405628D2FD9CCE4740772CB64945032840AA9B8BBFEDCF4740DD955D30B81E2840D4BB783F6ECF4740A3737E8AE3382840FA298E03AFCE4740FC17080264482840A7AD11C138CE474007B64AB038642840D3F4D901D7CD47403126FDBD146628404A07EBFF1CCE47409BAC510FD1682840912C6002B7CE4740DE921CB0AB692840D009A1832ECF4740D4B837BF616A2840D5B2B5BE48D0474077F69507E96928400C570740DCD1474051BB5F05F86628407AA86DC328D44740295C8FC2F5E82840FD9FC37C79D5474059A7CAF78C0429405473B9C150D147403048FAB48A06294080457EFD10D14740FE0E45813E092940D47C957CECD04740A182C30B22222940D28BDAFD2AD247409E7B0F971C2729402A1DACFF73D24740FA264D83A2312940FC1A498270D54740DE8FDB2F9F3429408048BF7D1DD647407F129F3BC1362940FF9600FC53D64740F4311F10E8542940A7E9B303AED74740DAAA24B20F72294051853FC39BD747404CE2AC889A7829407F8461C092D74740AF5A99F04B7D2940D009A1832ED747402F51BD35B0A52940A7B393C151D0474008E9297288A82940520ABABDA4CF4740C7F0D8CF62A92940556D37C137CF4740D0D38041D2A729402BDB87BCE5CE4740CBD8D0CDFEA02940813FFCFCF7CE4740B151D66F269E29402BDB87BCE5CE4740A56ABB09BE992940AB5FE97C78CE4740FD14C7815793294054FEB5BC72CB4740FC1D8A027D922940D2FD9C82FCCA4740FE0B040132942940D28BDAFD2ACA4740257A19C5729B2940AC5626FC52C74740D2C43BC0939E2940FA298E03AFC64740D0B69A75C6E72940B071FDBB3EBD4740A27F828B15ED294082397AFCDEBC474081069B3A8F022A40D7A6B1BD16BC4740040473F4F8052A4052431B800DBC474008E9297288082A40FE0B040132BC4740A56ABB09BE192A40556D37C137BF474050C763062A1B2A40FB20CB8289BF4740D9B0A6B2281C2A400000000000C04740FD14C78157332A40A9A10DC006D24740B05417F032332A405182FE428FD24740295C8FC2F5282A4051853FC39BD747402577D84466262A402B172AFF5AD84740DC9E20B1DD1D2A40D4B837BF61DA4740FA264D83A2112A4001BEDBBC71DC4740753BFBCA830C2A402CD505BCCCDC4740A774B0FECF092A40FED5E3BED5DC4740266E15C440072A40520DFB3DB1DC4740800F5EBBB4012A40D57954FCDFDB4740D1CDFE40B9FD294053793BC269DB4740257A19C572FB2940514CDE0033DB4740772FF7C951F829407F4B00FE29DB4740A3737E8AE3D82940A9DDAF027CDB4740F6285C8FC2D5294000C79E3D97DB4740DCA16131EAD229405470784144DC4740AF5DDA7058D22940A7ECF483BADC474007EFAB72A1D22940D4B5F63E55DD4740B05417F032D32940AB9509BFD4DD4740D6A9F23D23E1294001BEDBBC71E447402F51BD35B0E52940FD9FC37C79E5474059A4897780EF294002BB9A3C65E74740AF5DDA7058F22940286552431BE8474059A7CAF78C042A40D4B5F63E55ED47402D6002B7EEEE2940D7A6B1BD16F44740AB5FE97C78D629405307793D98FA4740E1B54B1B0EBB29406155BDFC4EFF4740F4346090F4B9294000000000000048407638BA4A77B72940A4C2D84290014840F4311F10E8B42940AC53E57B46024840CDCCCCCCCCAC2940D3F4D901D7034840314278B4719C29405376FA415D0648407E1B62BCE695294051853FC39B074840C7F0D8CF62892940D1066003220A4840266E15C4408729407C992842EA0A4840AC53E57B46822940527FBDC2820D4840800F5EBBB4812940D47FD6FCF80D484081069B3A8F822940813FFCFCF70E484084F41439448429405437177FDB0F484024809BC58B852940D5B2B5BE48104840295C8FC2F5882940D3F71A82E3104840D9B0A6B228BC2940508BC1C3B41948407D21E4BCFFBF294028F04E3E3D1A4840B14E95EF19092A407AABAE43352148407920B248134F2A402A1A6B7F672548407923F3C81F842A4079AEEFC34126484058AD4CF8A58E2A40D4F19881CA2648409E978A8D79952A407E5704FF5B274840D5B2B5BE48A02A40FE9C82FC6C284840AA622AFD84AB2A407BA2EBC20F2A4840C9E7154F3DCA2A40A777F17EDC2E4840F71F990E9DD62A40D3C1FA3F8731484056BC9179E4D72A40823CBB7CEB31484057B3CEF8BED82A40D4B837BF61324840FF08C38025DF2A40A7AD11C138364840A08B868C47E12A40A86E2EFEB6374840FF05820019EA2A40508BC1C3B4414840D4B837BF61EA2A40AC53E57B46424840020D36751EE52A40FFCC203EB04548402B6C06B820E32A40AB5FE97C78464840A777F17EDCDE2A4028F38FBE49474840DD955D30B8DE2A40D0D38041D2474840A182C30B22E22A40FC17080264484840FA298E03AFE62A407D93A641D1484840CEC64ACCB3022B40A7E67283A14A4840D0D38041D2072B407C992842EA4A484056B60F79CB0D2B40AB984A3FE14A4840DE8FDB2F9F342B40552E54FEB5484840CEC3094CA74D2B40FDDB65BFEE464840F92F1004C8502B40FD1186014B4648409E978A8D79552B40A8716F7EC34448404DD9E90775592B40D00CE2033B444840D1CDFE40B95D2B407E9065C1C4434840BB0D6ABFB5732B40129F3BC1FE4148407B14AE47E19A2B40D4B837BF614A4840D9B0A6B2289C2B40D0D03FC1C54A48404FCDE50643A52B405340DAFF004F48403048FAB48AA62B40D200DE0209504840313F373465A72B40D673D2FBC6514840266E15C440A72B407E54C37E4F524840D6A9F23D23A12B40AB5FE97C785E4840F52B9D0FCFAA2B40D482177D05634840'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('EZ','CZ','CZE','203','Czech Republic','7727','10191762','150','151','15.338','49.743','0106000020E61000000100000001030000000100000008020000F415A4198B662D4064CA87A06A4A4840030AF5F411502D405531957EC24D48402B69C537144E2D40295FD042024E48407B14AE47E13A2D40FC17080264504840CDC98B4CC0372D405401F73C7F50484056B950F9D7022D40FE9C82FC6C50484059A7CAF78CE42C40556D37C1374F4840D0D38041D2C72C40D3F4D901D74B48404DDC2A88818E2C405182FE428F4A4840FD1186014B5E2C4056F5F23B4D4C48407B14AE47E11A2C407B9FAA42035548407B14AE47E11A2C40530438BD8B5548404ED026874F1A2C40295FD04202564840782634492C192C405376FA415D56484057B08D78B2032C407C992842EA5A48407B14AE47E1FA2B40D57954FCDF5B48404DD6A88768C42B40D4EE5701BE614840AC5626FC52B72B40A7E67283A1624840F52B9D0FCFAA2B40D482177D05634840C9E7154F3DAA2B40514CDE0033634840753E3C4B90A12B40D2C77C40A0634840F52EDE8FDB9F2B402BDEC83CF2634840CAE1934E24A02B40A5BF97C283644840800F5EBBB4A12B40FD9FC37C79654840753E3C4B90A12B40295FD04202664840F6251B0FB6A02B40A9DA6E826F6648400307B474059B2B40FED2A23EC9674840AF5DDA7058922B405055A181586A48407920B248138F2B40D2FD9C82FC6A4840F4346090F4892B40FD14C781576B4840DBA4A2B1F6872B40D2C77C40A06B4840FA298E03AF862B40FCDEA63FFB6B48407B116DC7D4852B407D5A457F686C484082FDD7B969832B40D388997D1E6D4840800F5EBBB4812B40D47FD6FCF86D4840DC9E20B1DD7D2B40A9A44E40136F4840D9B0A6B2287C2B40AA9B8BBFED6F48405B9885764E7B2B407E18213CDA704840782634492C792B40D6A9F23D237148407F129F3BC1762B4052465C001A714840DCA16131EA722B40AA656B7D917048405A9BC6F65A702B40FE9C82FC6C704840D4B837BF616A2B40D1CABDC0AC704840CCCF0D4DD9612B40FE9C82FC6C7048400307B474055B2B40A8AAD0402C714840D4B5F63E55552B408081204086724840DCA16131EA522B40FFCF61BEBC72484023861DC6A44F2B40FD14C78157734840AB59677C5F4C2B40FCDEA63FFB734840B05758703F482B407B9FAA4203754840D5B2B5BE48402B407F4E417E367848407D21E4BCFF3F2B40D00F238447794840A08B868C47412B407E8AE3C0AB794840F6251B0FB6402B40A9A10DC0067A48407E1B62BCE6352B40508BC1C3B4794840286211C30E332B402CD8463CD97948402E573F36C92F2B40FC1D8A027D7A484058AD4CF8A52E2B402635B401D87A484055BFD2F9F02C2B40282CF180B27B4840FE0E45813E292B4054707841447C48406ADC9BDF30212B40E318C91EA17C48407A1A3048FA042B40D3BEB9BF7A7C48406A882AFC19CE2A40865451BCCA804840D5AF743E3CCB2A4052499D8026864840D4B837BF61CA2A40A9DA6E826F8648404FCDE50643A52A40FB230C03968C48407E18213CDAA02A407DCC07043A8D48404CE2AC889A582A402A1A6B7F679548407A17EFC7ED0F2A40FED5E3BED5A448402D6002B7EEEE2940FC1D8A027DAA4840FF05820019EA2940286211C30EAB48407923F3C81FE4294054FEB5BC72AB4840286552431BC829407D5A457F68AC48402F51BD35B0C529407D5A457F68AC484022895E46B1C42940FE0B040132AC484022895E46B1C429407F15E0BBCDAB48404FCDE50643C52940A9DDAF027CAB4840FE0E45813EC92940D4B837BF61AA4840B05758703FC82940FF05820019AA48403048FAB48AC62940533D997FF4A9484084F4143944C42940823CBB7CEBA94840CCCF0D4DD9C12940253E7782FDA94840257A19C5729B2940D5AF743E3CAB4840AC5626FC52972940A9DDAF027CAB4840FC1D8A027D92294052431B800DAC484083F755B95059294055FB743C66B64840DAAA24B20F322940AA622AFD84C34840B05758703F282940FD4D2844C0C7484051BEA085041C2940FDDB65BFEECE4840753BFBCA830C294029ED0DBE30D54840DBA4A2B1F6072940813FFCFCF7D64840FA298E03AF062940556D37C137D7484059A7CAF78C0429407E5704FF5BD74840DD989EB0C4F32840FE9C82FC6CD84840FE0E45813EE92840FCE1E7BF07D948404ED367075CEF2840A8A78FC01FE448405A9BC6F65AF0284001BEDBBC71E44840A27C410B09182940AB984A3FE1F24840AD4D637B2D182940A8A78FC01FF44840AC5626FC5217294029ED0DBE30F54840F71F990E9D162940527FBDC282F54840267156444DFC28402CD505BCCCFC48407B14AE47E1FA28407B9FAA4203FD4840D9B3E73235F12840D6AC33BE2FFE484004FEF0F3DFDB2840556D37C137FF4840FC1A4982709D2840FCE4284014064940DBA4A2B1F6872840527C7C427608494000AAB8718B6928403BC5AA41980D494081069B3A8F6228407E18213CDA104940772CB649456328407E8AE3C0AB11494059A7CAF78C642840A6B915C26A124940CADE52CE176B284029232E008D1449409F91088D606B2840AA9ECC3FFA144940F52B9D0FCF6A2840FFCC203EB0154940FF08C380253F28407E5704FF5B274940DC9E20B1DD3D284051853FC39B2749403F027FF8F92F2840BD70E7C2482949402E54FEB5BC5A2840552E54FEB5284940267156444D5C28405401F73C7F28494084F4143944642840FF08C3802527494083FA96395D8E2840AB59677C5F1C49403145B9347E9128407C6308008E1B49405A9E077767A528402A1DACFF731A4940FA298E03AFA62840A7AD11C1381E4940D7A6B1BD16CC28407F8461C092274940A3737E8AE3F82840FD4D2844C02F4940D8B628B3410629407BA2EBC20F324940D3C1FA3F87092940A6B915C26A32494006F52D73BA3C2940A7ECF483BA344940FF08C380253F2940A7ECF483BA344940CDC98B4CC0572940A7ECF483BA344940AD4D637B2D782940D576137CD3364940295FD042027E2940520ABABDA4374940C7F0D8CF628929407E18213CDA3849407632384A5E8D294080457EFD10394940772CB64945A32940D28BDAFD2A3A4940DE921CB0ABA92940A774B0FECF394940D6AC33BE2FB629407B6649809A384940D5AF743E3CCB294000C45DBD8A364940800C1D3BA8CC2940FF9600FC53364940A968ACFD9DD52940D1031F8315354940F6251B0FB6E0294027F6D03E56344940FA298E03AFE629407F87A2409F344940519FE40E9BF82940530438BD8B35494004FEF0F3DFFB29407E1B62BCE6354940040473F4F8052A405437177FDB374940DE921CB0AB092A407B6649809A384940D1CABDC0AC282A40FD4D2844C03F4940DC9E20B1DD5D2A40514F1F813F404940CCCF0D4DD9612A40527C7C4276404940286552431B682A40D28BDAFD2A4249407E1EA33CF36A2A40286211C30E434940DAAA24B20F722A40FE47A643A745494007EFAB72A1722A40295FD0420246494007EFAB72A1722A40A9DA6E826F46494005F86EF3C6712A407AA52C431C47494005F86EF3C6712A402920ED7F80474940D0D03FC1C5722A40D5B2B5BE48484940F437A110017F2A402B14E97E4E4B4940AA656B7D91802A40AA622AFD844B4940800F5EBBB4C12A40AA656B7D91504940D2C77C40A0D32A405376FA415D4E4940C9E4D4CE30D52A4052499D80264E4940DF8C9AAF92DF2A40FD9FC37C794D4940F52B9D0FCFEA2A4082397AFCDE4C494082035ABA82ED2A40FED5E3BED54C494052B81E85EBF12A40FD9FC37C794D4940C7F0D8CF62092B40FA264D83A2514940D4B837BF610A2B40823CBB7CEB514940FF058200190A2B40AC53E57B46524940DBA4A2B1F6072B405534D6FECE52494024809BC58B052B40A7B0524145534940000341800C152B40D5B2B5BE48584940FF058200192A2B405534D6FECE5A49407A1A3048FA442B4001BEDBBC715C49407F129F3BC1562B40543A58FFE75C494056BC9179E4772B40530438BD8B5D4940B05758703FC82B40A6B915C26A624940782975C938CE2B40A7ECF483BA6449407920B24813CF2B40000341800C654940782634492CF92B4029EACC3D24684940AF5A99F04BFD2B402B172AFF5A68494023861DC6A44F2C40A77A32FFE86B4940D4BB783F6E9F2C40D47C957CEC704940FB230C0396BC2C40A7E9B303AE7749404FCDE50643A52C402AE109BDFE78494057B08D78B2A32C407AABAE43357949402B6C06B820832C40A9DA6E826F7E494081069B3A8F822C40508E0244C17E494056B950F9D7822C407AA52C431C7F4940DBA4A2B1F6872C407AABAE4335814940276BD44334922C402CD505BCCC8449400307B474059B2C40D2C43BC093864940D2C43BC0939E2C40A777F17EDC864940F92CCF83BBFB2C40520DFB3DB184494082FDD7B969232D40552E54FEB580494005F86EF3C6312D405531957EC27D4940800F5EBBB4412D40A7AD11C138764940772CB64945432D40F92F1004C8704940314278B4713C2D40FCE42840146E4940DBA7E331033D2D405531957EC26D4940FD1186014B3E2D40527FBDC2826D4940CEC3094CA74D2D4001BEDBBC716C494059A48977806F2D40D1066003226A49402E54FEB5BC7A2D407D5D86FF7469494008E9297288882D40272F3201BF68494082035ABA828D2D40272F3201BF6849405AA148F7739A2D407D93A641D1684940F92CCF83BB9B2D40FCE1E7BF076949402577D84466A62D40A968ACFD9D6D4940286552431BA82D40D576137CD36E49402D6002B7EEEE2D40D47FD6FCF86D49407E18213CDA002E402BDB87BCE56E4940CEC64ACCB3022E405340DAFF006F49404CDF6B088E032E407E5704FF5B6F4940A774B0FECF092E407E8AE3C0AB794940DF89592F860A2E40A9DDAF027C7B4940DF89592F860A2E40D57954FCDF7B4940DAAD65321C072E402A1A6B7F677D49405A9E077767052E40D47FD6FCF87D49402383DC45985A2E40FDD8243FE28149402383DC45987A2E40813FFCFCF77E494055BFD2F9F08C2E402CD505BCCC7C4940A185048C2E972E40D1066003227A4940F71F990E9D962E40AB5CA8FC6B79494056B60F79CB8D2E407EC9C6832D784940F722DA8EA98B2E4051853FC39B774940D5AF743E3C8B2E40D009A1832E774940A96BED7DAA8A2E40D3FA5B02F0754940753BFBCA838C2E407F87A2409F744940247D5A457F902E405055A1815872494051C1E10511912E40A9A10DC006724940257A19C5729B2E405628D2FD9C6E4940F437A110019F2E407D96E7C1DD6D4940FC17080264A82E402A1A6B7F676D4940CBDB114E0BB62E4056F5F23B4D6C494083F755B950B92E402BDEC83CF26B49405AA148F773BA2E40282CF180B26B4940AF5A99F04BBD2E402A1DACFF736A49403546EBA86AC22E407E9065C1C46349407A1D71C806FA2E40520DFB3DB1644940F71F990E9D362F407C992842EA624940B05417F032932F40266E15C4405F49402D5A80B6D5E42F40514F1F813F58494079AEEFC34106304000CADFBDA3504940AC53E57B4612304055F833BC59514940D731AEB8381E3040B62BF4C132544940514CDE0033233040FCDEA63FFB5349402CD505BCCC3C3040AB9509BFD4554940FD14C7815753304029ED0DBE305549405531957EC2553040AA9ECC3FFA544940FB20CB82895730407F87A2409F5449407E8D2441B85E30402A1DACFF735249407D96E7C1DD6D3040D388997D1E4D4940A9DA6E826F6E304082397AFCDE4C4940A6EF3504C77130407E1EA33CF34A4940A7E67283A1723040D4B837BF614A49400282397AFC723040508BC1C3B44949402DCF83BBB37230405473B9C150494940286552431B6830407E1EA33CF3424940FD1186014B5E3040D0D38041D23F4940D2393FC5715C3040FB20CB82893F4940FF058200195A3040FB20CB82893F494057B3CEF8BE58304051853FC39B3F49405628D2FD9C5630402638F581E43F4940800F5EBBB4513040D1CABDC0AC4049407F8461C0924F3040A8E0F082884049407F129F3BC1363040A4C2D8429039494024809BC58B353040FCE1E7BF07394940FE0B040132343040D200DE0209384940A77A32FFE8333040556D37C13737494052431B800D343040A777F17EDC36494022895E46B134304079AEEFC341364940A7E9B303AE3730407F87A2409F3449408200193A763830407D5A457F68344940D82B2CB81F443040FDD8243FE2314940A8E33103954D3040FC1708026430494084F1D3B8375F3040A7AD11C1382E49402AE109BDFE703040A8E0F08288284940FB95CE8767753040A777F17EDC2649407F15E0BBCD8B3040D4B5F63E551D49402CD505BCCC8C30402CD505BCCC1C4940FF08C380258F304053793BC2691B4940552E54FEB5903040FDD8243FE21949402AE109BDFE903040D4F19881CA164940D5B2B5BE48903040D1031F8315154940FF93BF7B4791304029232E008D144940AB5FE97C78963040823CBB7CEB114940505260014C9D3040AC5626FC520F4940FD14C78157A33040295FD042020E494027F6D03E56A430407D96E7C1DD0D4940FE0B040132B43040FB230C03960C49407F129F3BC1B63040D3BEB9BF7A0C494056BC9179E4B73040A5BF97C2830C49407E8AE3C0ABB93040A8716F7EC30C494027F911BF62C93040253E7782FD11494053D0ED258DCD3040EA5DBC1FB7154940D2C43BC093CE304055FB743C66164940F92F1004C8D03040FB20CB828917494001857AFA08D83040FA264D83A219494058AA0B7899D93040A9A10DC0061A494057B3CEF8BEE8304001BEDBBC711C4940CE548847E2E93040D3BEB9BF7A1C49407C9C69C2F6F73040A5BF97C2831C4940AA656B7D910031407E9065C1C41B4940CC5D4BC807F93040A7E9B303AE2749407D21E4BCFFEF304000C79E3D972B4940D2C43BC093DE3040D57954FCDF3349402B69C53714DE304029232E008D344940D731AEB838DE304082397AFCDE3449407E8D2441B8DE30407DCC07043A354940514CDE0033E330407D21E4BCFF374940A77A32FFE8E33040514F1F813F3849402AE44A3D0BE630402B172AFF5A384940D82E6D382CE9304027F6D03E563849402AE109BDFEF03040A7E9B303AE37494004763579CA0E314029232E008D344940D731AEB8381E3140D0D03FC1C532494057B08D78B2333140D2C43BC0932E4940FB95CE8767353140AB9509BFD42D4940FF058200193A3140FE0B0401322C4940ABEAE5779A4831402AE109BDFE2849407E18213CDA6031407E9065C1C4234940A777F17EDC6E31405307793D982249407E8D2441B89E3140253E7782FD214940276BD44334A23140253E7782FD214940286552431BA831405182FE428F224940D4B837BF61AA31407F4B00FE292349407AABAE4335B13140D47FD6FCF8254940A6EF3504C7B1314079AEEFC34126494052B81E85EBB1314002BB9A3C65274940FA264D83A2B131405401F73C7F284940800F5EBBB4B13140D3F71A82E3284940276BD44334B231407AABAE4335294940FE0B040132B4314027F911BF62294940CC5D4BC807B93140D47C957CEC284940CE548847E2B93140272F3201BF284940F92F1004C8C031408048BF7D1D264940D734EF3845C331402AE44A3D0B1E4940FD14C78157C33140FFCC203EB01D4940D2C77C40A0C3314029E78BBD171B4940ABE7A4F78DC33140FD4AE7C3B31A4940514CDE0033C331407E54C37E4F1A49407C992842EAB231402541B8020A17494051C1E10511B13140D4F19881CA1649402BDB87BCE5A63140295FD04202164940276BD44334A23140295FD042021649407F8461C0929F31408048BF7D1D164940D63A71395E9D3140FCE4284014164940AA622AFD849B3140AB9509BFD41549400473F4F8BD9931407B9FAA4203154940FE0E45813E993140520DFB3DB1144940CC5D4BC8079931405470784144144940A774B0FECF993140282CF180B2134940257A19C5729B31407C992842EA124940FC17080264A83140AB9509BFD40D494050C422861DD63140D576137CD3FE484001857AFA08D831407C60C77F81FE4840295FD04202DE3140A8E3310395FD484055C2137AFDE13140000341800CFD4840D734EF3845E331407B9FAA4203FD4840CE548847E2E93140AA9ECC3FFAFC48407AA86DC328EC3140000341800CFD4840A777F17EDCEE31402A1A6B7F67FD4840D53DB2B96A023240AB5CA8FC6B014940D4635B069C0D324092EA3BBF28074940286552431B18324082397AFCDE04494029ED0DBE304532405307793D98FA48407E8AE3C0AB5932407EC9C6832DF84840A7ECF483BA8C3240FCE4284014F64840D1CDFE40B98D324052499D8026F6484004763579CA8E3240D47FD6FCF8F548407E9065C1C4933240000341800CF5484027F6D03E569432402CD505BCCCF44840A8716F7EC39432407AA86DC328F4484007F0164850943240A7B393C151E848405055A18158A23240A9DA6E826FDE48404DD9E90775C9324028F38FBE49D748404ED367075CCF3240FF9600FC53D64840CF4E0647C9CF32402AE44A3D0BD648402BDB87BCE5D632407AA86DC328CC4840CC5D4BC807D93240FDDB65BFEEC64840A3073E062BDA32407C6308008EC34840CFD90242EBD93240A7AD11C138C248407E1EA33CF3CA3240D673D2FBC6C14840D0D38041D2A73240A8E0F08288C04840A8716F7EC3943240A86E2EFEB6BF4840FA264D83A29132402920ED7F80BF48407A17EFC7ED8F3240556D37C137BF4840276893C3278D3240FF9600FC53BE4840AB59677C5F8C3240FE47A643A7BD484000917EFB3A8C32407DCC07043ABD4840AB59677C5F8C3240FD14C78157BB48407F15E0BBCD8B32405182FE428FBA484080812040868A3240A9A10DC006BA4840286211C30E633240D2FD9C82FCAA4840D6A9F23D23613240AC53E57B46AA4840257497C4595132407E5704FF5BA7484058AD4CF8A54E32402BDB87BCE5A6484001857AFA084832402829B000A6A64840A304FD851E45324055FB743C66A64840D236FE44653732407B9FAA4203A54840AB5FE97C7836324082397AFCDEA448404FCDE50643353240AB59677C5FA44840295FD042022E3240AA9B8BBFED9F48407B9FAA42032D324028F38FBE499F4840A7ECF483BA2C3240FDDB65BFEE9E4840FB230C03962C32407C992842EA9A48404DD9E90775293240FD1186014B964840D1CABDC0AC283240276893C32795484056BC9179E427324001BEDBBC719448406ADC9BDF30253240C3F5285C8F9248405628D2FD9C26324000CADFBDA39048407F129F3BC1263240AA9B8BBFED8F48407B116DC7D4253240D4F19881CA8E484084F1D3B8371F32405307793D988A484059130B7C45133240E8A562635E854840FE0E45813EE93140FCE42840147E4840FB20CB8289D73140D576137CD3764840FD14C78157C331407B6649809A70484052B81E85EBC131407F4E417E36704840FF9600FC53B63140A8E33103956D4840FC1A498270AD3140000341800C6D4840A7E9B303AEA73140000341800C6D48404FCDE50643A53140000341800C6D4840552E54FEB5803140FE99417C606B484050C763062A6B3140A774B0FECF694840D236FE44656731405473B9C150694840A77A32FFE86331405473B9C150694840D0D03FC1C562314027F911BF62694840FB928D075B603140823CBB7CEB69484022895E46B1543140FED5E3BED56C4840552E54FEB5403140A5BC5642776F4840FC1A4982703D3140A86E2EFEB66F48407E1EA33CF33A3140FD4D2844C06F484022A81ABD1A303140ABD1AB014A6F4840276893C3271D3140A7E67283A16A4840267156444D1C31407E54C37E4F6A4840FC8F4C874E0B3140FFCF61BEBC624840533D997FF4093140533D997FF46148405531957EC2053140D009A1832E5F48407B9FAA4203FD3040266E15C4405748405A10CAFB38F23040C310397D3D4F4840AA622AFD84EB3040FA264D83A259484050C763062AEB3040A9A10DC0065A48400473F4F8BDE93040FFCF61BEBC5A4840FF9600FC53E6304001BEDBBC715C4840A7E67283A1E23040A6B6D4415E5D48404FCAA48636E03040D1031F83155D484084F1D3B837DF30402CD505BCCC5C484055BFD2F9F0DC304001BEDBBC715C4840FA298E03AFD63040F92CCF83BB5B48407E9065C1C4D33040D2C77C40A05B4840A774B0FECFC9304052431B800D5C4840FC17080264C83040D00CE2033B5C4840D6AC33BE2FB63040FB20CB82895F48405534D6FECEAA304081423D7D0464484056BC9179E4A73040FED5E3BED5644840A304FD851EA5304029ED0DBE3065484050C763062A8B3040AA9B8BBFED67484058AA0B7899893040D200DE020968484079AEEFC341763040286552431B684840A304FD851E753040AA9B8BBFED674840D2C77C40A0733040556D37C137674840FD1186014B6E3040A8A78FC01F6448407E1EA33CF36A3040D3F71A82E36048400473F4F8BD693040D38558FD11604840266E15C4406730407AA52C431C5F484029ED0DBE306530402829B000A65E48407C992842EA62304079AEEFC3415E4840FB928D075B603040295FD042025E4840A777F17EDC5E3040D3FA5B02F05D48404FCDE50643553040AB9509BFD45D4840FA980F08741A30400000000000604840A8716F7EC31430407B6649809A604840FA9B5088800F30405473B9C15061484024809BC58B053040A9DDAF027C634840CEC3094CA7ED2F405340DAFF006748400C5A48C0E8B22F40F5A276BF0A6E4840B151D66F267E2F407E1B62BCE66D4840AA656B7D91602F407C60C77F816E4840DC9E20B1DD5D2F40FA298E03AF6E4840AA622AFD842B2F4029E78BBD17734840842C0B26FE202F40AB59677C5F74484056BC9179E4172F40A8716F7EC3744840A774B0FECF092F40530438BD8B7548407A1A3048FA042F40D47FD6FCF8754840266E15C440E72E40D4EE5701BE794840295C8FC2F5C82E407F87A2409F7C48402E54FEB5BCBA2E407E1B62BCE67D4840F4311F10E8B42E40D6AC33BE2F7E48404ED026874F9A2E40A9DA6E826F7E48404FCAA48636502E407C9C69C2F67F4840753E3C4B90212E40FDD8243FE2814840030AF5F411102E40D4B837BF61824840AD50A4FB390D2E40A6B915C26A8248407B116DC7D4052E40533D997FF481484008E3A7716FFE2D40295C8FC2F58048409F8EC70C54F62D402AE44A3D0B7E4840A8716F7EC3F42D40D1031F83157D4840A8716F7EC3F42D4029232E008D7C4840772FF7C951F82D407F4E417E367848407E1EA33CF3EA2D40D1CDFE40B96548405A9E077767C52D40FE0B040132644840DCA16131EAB22D4051888043A8644840A088450C3BAC2D402CD505BCCC644840B14E95EF19A92D402CD505BCCC644840800F5EBBB4A12D4027F6D03E566448407D21E4BCFF9F2D4081423D7D046448407E1B62BCE6752D40AB5CA8FC6B594840DD989EB0C4732D40AA656B7D9158484005F86EF3C6712D40520ABABDA4574840A376BF0AF06D2D4029232E008D5448404DDC2A88816E2D407C6308008E534840257497C459712D405055A18158524840F92F1004C8702D40530438BD8B4D48407A17EFC7ED6F2D40D1031F83154D4840A774B0FECF692D4029E78BBD174B484008E9297288682D40FD4AE7C3B34A4840F415A4198B662D4064CA87A06A4A4840'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('FR','FR','FRA','250','France','55010','60990544','150','155','2.55','46.565','0106000020E61000000A00000001030000000100000007000000A0B3CEF8BEF82240608E0244C14E4540805A99F04BFD2240905182FE424D4540E085048C2EF72240B05FE97C784E4540C08FDB2F9FF422406040DAFF004F4540A02975C938EE2240302F3201BF504540E0B837BF61EA22405855A18158524540A0B3CEF8BEF82240608E0244C14E4540010300000001000000BA00000040895E46B1E4224028DB87BCE5564540A09E077767E52240F8E769C0205345400021CB8289E72240D0CABDC0AC50454020EFAB72A1F2224080812040864A4540A0716F7EC3F42240E0EE5701BE49454040B950F9D702234090C9C6832D484540000D36751E05234028EACC3D2448454060116DC7D4052340786649809A484540200473F4F8052340B8AAD0402C494540605A80B6D5042340283E7782FD494540A03E3C4B90012340F82CCF83BB4B454000C53BC093FE2240583A58FFE74C4540C0E1934E240023408887A2409F4C454020B937BF610A2340D80F23844749454080CAA48636102340F81186014B464540607497C459112340B8B6D4415E454540002FDE8FDB1F234080992842EA22454020965D30B81E2340786649809A184540804278B4711C234038172AFF5A104540A09885764E1B2340E0F19881CA0E45406038BA4A77172340D0031F83150D4540A09E077767E52240B09B8BBFEDFF4440205DC136E2D9224028D505BCCCFC4440001E8A027DD22240D806600322FA444040861DC6A4CF2240B0E9B303AEF744406077F4BF5CCB2240B846CB811EF04440E0DE52CE17CB2240B0DA6E826FEE444000A7B1BD16CC2240583A58FFE7EC44402069C53714CE2240906308008EEB44408020B24813CF2240B0A10DC006EA4440406002B7EECE22409018213CDAE84440C088450C3BCC2240805D86FF74D9444060634337FBC3224030F6D03E56D44440E053E57B46C2224058FEB5BC72D34440202DCF83BBBB2240D8EE5701BED144406023F3C81FA42240D088997D1ECD4440C0DE52CE178B2240A8E67283A1C2444020FEF0F3DF7B224030D8463CD9B9444000965D30B87E22408060C77F81B64440A0D8D0CDFE80224010C45DBD8AB64440E082C30B22822240D8AC33BE2FB64440E082C30B22822240B8E3310395B54440805CA8FC6B812240D088997D1EB54440E0BB783F6E7F224038F6D03E56B4444060B81E85EB712240D009A1832EAF444060CAA4863670224038DB87BCE5AE444060B60F79CB6D2240E0F19881CAAE4440E0EA56CF495F22406028D2FD9CAE444040240C03965C2240082A8E03AFAE44402054FEB5BC5A224008DC65BFEEAE444080B08D78B2432240381DACFF73B24440609885764E3B224038F38FBE49B74440C0716F7EC3F42140889FAA4203BD444000EFAB72A1F2214028ED0DBE30BD4440C0CF0D4DD9E121402829B000A6BE444000295C8FC2D52140909C69C2F6BF4440C0978A8D7995214088A52C431CC74440E04B546F0D942140D0BB783F6EC74440C0989EB0C4932140889C69C2F6C74440206BD443349221408860C77F81CE4440A01B62BCE6952140B8656B7D91D04440A0D24ECDE5962140285C8FC2F5D0444060A148F7739A214000C11C3D7ED1444000F52D73BA9C214008274D83A2D144400009C380259F2140D0C1FA3F87D14440C021E4BCFF9F214050465C001AD1444000D00D4DD9A121409018213CDAD0444040D6A88768A42140285C8FC2F5D04440A0EA56CF49BF21406834D6FECED24440C018213CDAC0214028E78BBD17D34440C07A32FFE8D32140E0C43BC093D6444080129F3BC1D62140686D37C137D7444000CA8B4CC0D7214058853FC39BD7444000CA8B4CC0D72140D08558FD11D84440E0D24ECDE5D621405001F73C7FD84440000341800CD52140302F3201BFD84440401E8A027DD221408818213CDAD84440A0C2137AFDC1214068F833BC59D94440E01F990E9DB6214038F911BF62D9444000E6E8F17BB32140B05CA8FC6BD9444060DC2A8881AE2140888AE3C0ABD94440E07C410B0998214078992842EADA444020C87C40A0732140B8B6D4415EDD4440405C8FC2F568214078ABAE4335E14440A077F17EDC7E2140084E2844C0E74440A07A32FFE893214080CC07043AED444060C763062A9B2140A8984A3FE1F24440C014AE47E19A214060793BC269F34440801D71C8069A2140D8F4D901D7F344408045B9347E912140109700FC53F644406017EFC7ED8F21406028D2FD9CF644408015E0BBCD8B21402841B8020AF74440202FDE8FDB7F2140A8BC564277F74440E0A7E331037D21403820ED7F80F7444080C763062A7B214028F38FBE49F74440605DC136E279214010DC65BFEEF6444080B3CEF8BE782140E0FA5B02F0F54440E085048C2E7721401048A643A7F54440A0F1D3B8376F214030D505BCCCF4444020068200196A214008240C0396F44440C08EC70C545621405870784144F4444000AAF23D2341214050431B800DF4444080A48977802F2140101E8A027DFA4440A032384A5E2D2140A8B0524145FB444080B60F79CB2D2140582B137EA9FB444040861DC6A42F2140B87A32FFE8FB4440401077F52A3A21405070784144FC4440200D36751E45214030DEC83CF2FB4440402C9D0FCF4A214060431B800DFC444000BFB9BF7A5421406031957EC2FD444020295C8FC25521407848BF7D1DFE4440C0DB114E0B5621408860C77F81FE444020274D83A251214080457EFD1001454080C763062A7B214080CC07043A054540201B4982707D2140305FD04202064540201B4982707D2140E0C43BC09306454040BEA085047C2140B0BC564277074540E0F42D73BA5C2140A868ACFD9D0D4540C0AD65321C47214000BB9A3C650F4540C038BA4A7737214028E109BDFE104540A00C1D3BA82C2140D0CDFE40B9154540C023F3C81F242140A859677C5F1C454040240C03963C21401018080264204540A088450C3B4C214090457EFD10214540A05A99F04B5D2140483D997FF4214540A0EA56CF495F2140286BD4433422454020B3B5BE486021405807793D982245408021E4BCFF5F2140F0E769C0202345404009C380255F2140B8622AFD84234540A0FDD7B96943214008E869C0202B4540A09885764E3B214000240C03962C4540A0D24ECDE5362140383B3602F12C4540207D5A457F302140A89ECC3FFA2C454000DF52CE172B214030D505BCCC2C454040FBAF73D326214058465C001A314540E08FDB2F9F542140A85CA8FC6B4145408076BF0AF06D2140A8E0F082884845404045B9347E712140D8C1FA3F8749454080C422861DC62140F817080264504540207156444D1C2240808D2441B8564540C09E20B1DD1D2240904E417E365845404009C380251F2240B0656B7D91584540801EA33CF32A2240D8FD9C82FC5A4540800C1D3BA82C2240B0B05241455B4540609885764E3B2240805182FE425D4540206893C3273D224010A0C37C795D4540E0D58F4DF24B22408096E7C1DD5D454080DC2A88814E22408096E7C1DD5D454000261B0FB680224058707841445C4540C0069B3A8F82224090423D7D045C454000356090F489224000D9243FE259454040DC2A88818E22400818080264584540207497C4599122406828D2FD9C564540C0A16131EA922240009700FC5356454040321F10E8942240E8AC33BE2F564540805FE97C78962240A85FE97C78564540C0BB783F6E9F224038172AFF5A584540603579CA6AA2224028E109BDFE58454080FDD7B969A3224038F911BF6259454060AD4CF8A5AE2240D87FD6FCF85D454060D367075CAF2240A8DA6E826F5E454040573F36C9AF2240908461C0925F454080035ABA82AD224030ED0DBE30654540C00C1D3BA8AC2240D8AC33BE2F664540004F95EF19A922406037177FDB67454020895E46B1A422407893A641D1684540C0BB783F6E9F2240306BD443346A4540001286014B9E22404882FE428F6A4540E0CDFE40B99D2240D882177D056B454080DC2A8881AE224038F38FBE497F4540207D5A457FB02240286552431B804540201E8A027DB22240B8B393C151804540E0716F7EC3B422405801F73C7F80454080F4143944C4224050465C001A81454000AD33BE2FD622405873B9C150814540A02634492CD9224050F833BC59814540E06BED7DAAEA2240002A8E03AF7E454000D68F4DF2EB224080AEEFC3417E45406083DC4598FA2240504F1F813F684540A0A148F773FA2240A8A44E401367454060E2AC889AF82240B068ACFD9D654540000AF5F411F02240381DACFF7362454080AD4CF8A5EE2240D8C1FA3F87614540605C8FC2F5E8224008DFA63FFB5B454060809BC58BE52240909C69C2F657454040895E46B1E4224028DB87BCE55645400103000000010000001A00000000EE3D5C721CF3BFE00F238447E9464000D0B8702064F3BF30F38FBE49E74640001A62BCE6D5F3BFE0FA5B02F0ED464000992B836A03F4BFD8D38041D2EF464000624337FB83F4BFB87A32FFE8F3464000E2B19FC592F4BF080C040132F44640008E8B6A1111F5BFB0AD11C138F64640001E4E603A6DF5BF00D3A23EC9F7464000B48D3F51D9F5BF08274D83A2F9464000D026874FFAF5BFA8E67283A1FA464000A7CAF78C04F6BF906308008EFB4640004E27D9EA72F6BFD87FD6FCF8054740001D4E603A6DF6BFB85FE97C780647400060E97C7856F6BF00C45DBD8A06474000D38041D227F6BF109700FC53064740007497C459D1F5BFD8CDFE40B905474000D76CE525BFF5BF607FBDC2820547400027EE78935FF4BFB0BC564277FF4640002FA2ED98BAF3BFA8DDAF027CFB46400005465ED6C4F2BFE082177D05F34640003E4162BBBBF2BFD006600322F24640002EA2ED98BAF2BF38266F8099F1464000BB0A293FE9F2BFB8BF97C283EC464000EFE2FDB8FDF2BF281DACFF73EA4640002FD978B005F3BF303E7782FDE9464000EE3D5C721CF3BFE00F238447E946400103000000010000001600000000F5BA45602CF4BF80423D7D0414474000A439B2F28BF4BFB07A32FFE813474000361FD786CAF4BF58431B800D144740005412D90719F5BF08240C039614474000ED3D5C721CF8BFE0066003221A474000C93B873254F8BFD0D03FC1C51A4740004487C09180F8BF886308008E1B4740002B4833168DF8BFE87954FCDF1B4740001A62BCE6D5F8BFA877F17EDC1E474000B58D3F51D9F8BF885704FF5B1F47400093533BC3D4F8BF104E2844C01F47400015E5D2F8C5F8BFF8FFFFFFFF1F474000E8C072840CF8BF682E54FEB520474000F2052D24E0F7BF8018213CDA20474000D0EFFB37AFF7BF8018213CDA2047400003ECA35397F7BF202F3201BF20474000292504ABAAF4BF68F833BC5919474000BF64E3C116F4BF600438BD8B154740008F8B6A1111F4BFE088997D1E154740008F8B6A1111F4BF08240C039614474000662FDB4E1BF4BF000C04013214474000F5BA45602CF4BF80423D7D0414474001030000000100000011000000006BED7DAA2A02C0382F3201BF58474000CB9F6F0B3602C0D8CABDC0AC58474000FED2A23EE902C058F833BC5959474080285C8FC2F502C0D873D2FBC659474080B7E7F9D30603C0E0D03FC1C55A474080F2CEA10C1503C0E07954FCDF5B474080AD47E17A1403C080397AFCDE5C474080F61E2E390E03C030ED0DBE305D474080A59D9ACBED02C09048BF7D1D5E47408047AAEFFCE202C0A8AD11C1385E47408094128255D502C060499D80265E474080AF743E3CAB02C0507FBDC2825D474080DAC69FA86C02C010DFA63FFB5B4740008718AF793502C0E08BDAFD2A5A474000D0EFFB372F02C008D9243FE259474080C422861D2602C0E0A9F23D23594740006BED7DAA2A02C0382F3201BF5847400103000000010000001800000000E370E6579301C0386BD4433482474000809BC58B2501C0383E7782FD794740005512D9071901C09093A641D1784740003656629E1501C06037177FDB7747408045B41D531701C00048A643A7754740801C588E902101C0000C040132744740005C8FC2F52801C028DEC83CF2734740006DE34F547601C010C11C3D7E79474080CEC29E769801C0D882177D057B474000F4FBFECDAB01C0109A417C607B474000D21C59F9C501C0886308008E7B474080AF3DB324E001C000C79E3D977B474080E4D4CE30F501C0109A417C607B474080CC9541B50102C0109A417C607B474080B2976DA70D02C0A8DDAF027C7B474000DE205A2B1A02C0B0A78FC01F7C4740009DF3531C4702C0B8E67283A1824740809735B1C03702C0B0622AFD8483474080B2976DA70D02C0B87A32FFE883474000B16A10E6F601C0D8A6B1BD1684474000D349B6BADC01C0B87A32FFE88347408015A4198BC601C0582B137EA983474000A0168387A901C0386211C30E83474000E370E6579301C0386BD443348247400103000000010000001800000000C745B5888808C0286E15C440A74740804C310741A708C0000341800CA54740001477BCC9AF08C010D6E3BED5A44740005C5837DEDD08C0B89509BFD4A54740004D689258F208C048499D8026A6474080A8C0C9365009C0E876137CD3A6474080C3EBFA055B09C0B877F17EDCA6474000986C3CD88209C0608E0244C1A6474080B4C4CA68A409C0B8DA6E826FA647400058FE7C5BB009C08060C77F81A6474000EB1A2D07BA09C0888D2441B8A6474000698995D1C809C0286E15C440A747408066666666E609C028172AFF5AA8474080425A63D0E909C008301004C8A8474080F2CEA10C150AC0588E0244C1AE4740007ADD2230160AC030F38FBE49AF47408015DBA4A2110AC030EACC3D24B047400064027E8D040AC0303E7782FDB1474000AC1A84B9FD09C0C053E57B46B24740804C689258F209C0D806600322B2474000CC9541B58108C030E109BDFEA8474000AC1A84B97D08C0886649809AA8474080880E81238108C038EACC3D24A8474000C745B5888808C0286E15C440A747400103000000010000000D000000C01E85EB513814C0D0066003223A484040B29C84D26714C0786649809A38484080137CD3F48914C0306BD443343A484080137CD3F48914C0A86BED7DAA3A4840009544F6418614C0D0FD9C82FC3A484000963FDF166C14C0B0716F7EC33C4840807B0F971C4714C05831957EC23D4840403201BF464214C0B89509BFD43D4840C01E85EB513814C008A0C37C793D4840008940F50F3214C0386893C3273D48408047E17A142E14C010DFA63FFB3B484000C3F011313514C0081E8A027D3A4840C01E85EB513814C0D0066003223A48400103000000010000000A00000080758D96039D0CC038DB87BCE56648400018080264A80CC038DB87BCE566484000A0168387A90CC0B05626FC52674840802CB64945A30CC0600ABABDA46748400022A81ABD9A0CC07821E4BCFF674840008F8B6A11910CC0C800DE0209684840002FD978B0850CC02038F581E467484000CC9541B5810CC03020ED7F8067484080FB6EBA65870CC01009C3802567484080758D96039D0CC038DB87BCE56648400103000000010000008E0600008095128255550440602B137EA98B494080E17A14AEC70440B8BC5642777F49408068CA4E3FC804409060C77F8176494000FF092E56340540607C7C4276684940806E1ADB6B410640682E54FEB56049408074B169A5F00640A053C900505B494000D0EFFB372F0740303E7782FD59494080A27A6B608B074038DB87BCE55E494080CFEFFB37AF0740305C8FC2F56049408016DBA4A2110840381DACFF73624940005C8FC2F5280840B8E67283A162494000130B7C45370840C882893F8A6249408094128255550840B0DDAF027C6349400077C4211B680840E07954FCDF63494000EB245B5DEE0840D8B5F63E5565494000809BC58B25094080CC07043A65494080EEAB72A1320940D088997D1E6549400082C8224D3C0940603A58FFE76449400089450C3B4C094060F5F23B4D644940007597C459510940B87A32FFE86349400050CAA486760940F8B7AF03E760494000BD783F6E7F0940788461C0925F494000F3CEA10C950940E0031F83155D494080F9821612F00940507FBDC2825549400009E1D1C6F10940A8BF97C28354494080736A67983A0A40E0B5F63E55454940000BD7A3703D0A40483A58FFE7444940805A99F04B5D0A40B0B052414543494000CFF9298E630A40881EA33CF342494000FA821612F00A40D8BB783F6E3F4940809BFD8172FB0A40905704FF5B3F49400085EB51B89E0B4080ABAE43354149400090F98040A70B40805D86FF74414940803C1405FA240C40B0B915C26A42494000D449B6BADC0C40B0BC5642773F4940009C1BD313F60C4000CD04C3B93E49400083C8224D3C0D4038E78BBD173B4940804FCDE506430D40D08E8D40BC3A494080AC510FD1480D40B8B915C26A3A4940803BDD79E2590D408818213CDA384940805A99F04B5D0D40089D82FC6C384940006BB6F2925F0D40B8BC56427737494080C9A99D616A0D406007793D9832494000F0AB72A1320E40585260014C2D494000416491261E0F40B0622AFD842B494000272F3201DF0F40100C0401322C494040EBC726F921104018A88C7F9F2D4940406E15C440271040607FBDC2822D4940005C8FC2F5A81040D00CE2033B244940809DF3531CC7104068FB743C661E49408093179980AF1040B0C2D8429011494000022D5DC1961040D00F2384470149404048A5D8D1981040702DCC423BFD4840009AD2FA5BB21040707C98BD6CFD4840C07A19C572BB1040A89ECC3FFAFC4840C06A2C616DDC1040A096033DD4FA484040FCAA5CA8EC1040484CDE0033FB4840C06F422102FE104050FEB5BC72FB484080490ED8D5441140A8A78FC01FFC4840406E15C440A7114008C11C3D7EF94840003448C153B81140E8BE47FDF5F8484040E9297288C811400818080264F8484040B6F63E55D5114028EACC3D24F84840808713984EDB114078C9C6832DF84840C03C0FEECE0A1240D80F238447F9484080E7FC14C7B112400021CB8289FF4840407D410B09B81240584F1F813F004940009DF3531CC71240A8B6D4415E05494080F8872D3DCA124078A52C431C074940C03788D68AC61240A89B8BBFED07494040A243E048C01240886649809A084940C0656B7D91C0124050465C001A0949404051BD35B0C51240B86BED7DAA0A494040931CB0ABC91240D0C77C40A00B49408032384A5E0D134060F833BC591149408053E57B4642134088CC07043A15494000FBAF73D3461340281A6B7F67154940C0499BAA7B541340A8E331039515494000A5A2B1F68713408815E0BBCD134940000C040132941340603D997FF4114940406AC020E9931340A85CA8FC6B114940C0CCCCCCCC8C1340F82F1004C810494000E9297288881340B0E0F082881049404051BD35B085134078C9C6832D10494040643E20D0691340D00CE2033B0C49400007B474055B13408818213CDA08494040E9297288481340B0A44E4013FF4840407F69519F741340B05626FC52E7484080704221027E134030E44A3D0BE64840C094490D6DA01340E0031F8315E54840802A8E03AFA61340A89ECC3FFAE4484000EFAB72A1B21340080341800CE54840C0CDFE40B9BD134088CC07043AE54840403F373465C71340A0E3310395E54840809CC1DF2FD61340002A8E03AFE6484080F9821612F013405040DAFF00E7484000240C0396FC1340908D2441B8E64840406211C30E53154058431B800DD44840003BE466B8911540C88B4CC0AFCF4840404E637B2D9815400021CB8289CF4840805C8FC2F5A815408860C77F81CE484040A8FC6B79B51540F8CC203EB0CD484040A243E048C0154040D505BCCCCC484040809BC58BE51540885182FE42C5484040CCD1E3F7E6154008D6E3BED5C4484080313D6189E71540B059677C5FC4484000DE57E542E51540A87A32FFE8C34840C03106D671DC1540D0D03FC1C5C2484040438CD7BCDA1540A853E57B46C24840403E3C4B90E11540D8A9F23D23C1484040D6A88768E4154000301004C8C04840405C8FC2F5E81540B8E0F08288C04840807E6E68CA0E1640D8A9F23D23C1484040EB56CF491F1640B05CA8FC6BC14840C08C9AAF925F1640089A417C60C34840409DF3531C87164000240C0396C448404020B24813CF1640607FBDC282C5484040B0743E3C2B17408096E7C1DDC54840805E0CE5443B1740C8707500C4C54840C02BBB60703D1740B09ECC3FFAC44840001A355F253F174048888043A8C4484080438CD7BC5A1740B874B0FECFC148404015E0BBCD6B174030EACC3D24C048404020B75F3EE91740B85CA8FC6BB9484000BFD2F9F0EC174028F911BF62B9484040F52D73BA5C1840283E7782FDB9484040378DEDB5601840D006600322BA4840C084F068E3781840B8A78FC01FBC4840C014AE47E17A1840B859677C5FBC4840002CBB60707D1840507FBDC282BD484000704221027E18405076FA415DBE48408019355F257F1840F8298E03AFBE4840402FDE8FDB9F18405001F73C7FC048404020B75F3EA91840806649809AC0484000B0743E3CEB184090457EFD10C1484040A8FC6B79F5184030E109BDFEC0484080D906EE40FD184028508BC1C3C04840C0EC832C0B361940889FAA4203BD484040CAA4863650194058431B800DBC4840805E46B1DC72194030923D42CDBA484000DE57E542A5194080397AFCDEBC48400006820019AA1940583A58FFE7BC4840008D9AAF92DF1940306211C30EBB4840C0E8297288081A40D0CABDC0ACB84840C0D8D0CDFE201A401009C38025B7484000C2FA3F87291A408860C77F81B64840C0F1D3B8372F1A40F8CC203EB0B5484040D9D0CDFE601A40B85FE97C78AE484000BC783F6EBF1A40805704FF5B9F4840C0DBF81395DD1A406001F73C7F98484040ED7E15E0DB1A4090C9C6832D984840008813984EDB1A4008D3A23EC9974840C0B0A6B228DC1A40D0BB783F6E974840C01A3048FAE41A40D87FD6FCF8954840C05C8FC2F5E81A40001B498270954840005A677C5FEC1A40805182FE42954840803D0AD7A3F01A40286893C32795484080921CB0AB491B40302CF180B29348400026396057531B40F8C69E3D979348400007B474055B1B40D8F4D901D7934840C094490D6D601B405870784144944840C0F9821612701B4010E528401496484040E7FC14C7711B4058FB743C6696484040E7FC14C7711B40508E0244C1964840809BC6F65A701B402841B8020A9748408052B81E856B1B400821CB828997484080C422861D661B400818080264984840805A99F04B5D1B40B8A10DC0069A4840C03106D6715C1B40D8B837BF619A484040DBF813955D1B4010D061BEBC9A4840C0EA56CF495F1B40306211C30E9B4840C0703D0AD7631B40806308008E9B484040A8C5E0616A1B40B87A32FFE89B484080AD4CF8A5AE1B40D80CE2033B9C48408084F068E3B81B4050707841449C484000240C0396BC1B40A8A78FC01F9C4840406AC020E9131C408021E4BCFF97484000F52D73BA5C1C40A8B393C151904840C08713984E9B1C403820ED7F808F4840402A8E03AF261D40A8AD11C1388E4840806BED7DAA2A1D405076FA415D8E4840803D0AD7A3701D40286BD44334924840004D689258721D40F81D8A027D924840807C410B09781D4030232E008D94484000EF7211DF791D4090A8177C9A95484040C64FE3DE7C1D408096E7C1DD95484040A243E048801D40285FD04202964840008B6D52D1881D40E0AC33BE2F96484080313D6189A71D403829B000A696484080E7FC14C7B11D40082A8E03AF9648400015AE47E1BA1D408860C77F8196484000EFAB72A1F21D40809FAA42039548404008AF5DDA801E408818213CDA884840808D959867851E4028172AFF5A88484080530438BD9B1E40C0B0E07EC085484040BFD2F9F0AC1E40201A6B7F67854840C05417F032F31E4008A0C37C79854840004F95EF19491F40D8FA5B02F0854840403E4162BBBB1F4080AEEFC34186484040AAF23D23C11F4080AEEFC341864840E0ED974F56142040A05CA8FC6B8148402083DC45981A2040D8CABDC0AC80484060861DC6A44F2040A89ECC3FFA7C4840A0B0E07EC0732040785A2904727B4840C0C1FA3F87692040F8CF61BEBC7A4840803E3C4B9061204040D8463CD9794840406E15C440472040A8E67283A172484040809BC58B452040B0A10DC006724840001286014B3E2040888D2441B86E484060AA0B789939204030F6D03E566C4840A000193A76382040E0C77C40A06B4840A05FE97C78362040000F45813E694840E0E4D4CE30352040A8E0F08288684840A0F1D3B8372F2040A877F17EDC664840005612D907D91F40600DFB3DB15C4840C00C36751E851F40789FAA420355484040A8FC6B79351F40588BC1C3B4494840005D8DEC4AFB1E40B037F8C264364840004D689258F21E40D082177D05334840004D689258F21E4040D8463CD93148408084F068E3F81E403820ED7F802F484000D95C35CF011F40D8EB8843362C4840C007AF5DDA001F4038E78BBD172B4840C0BEA08504FC1E408054C37E4F2A484080F30016F9C51E40009A417C60234840C052CF82506E1E4038BF9A030415484040E1B19FC5521E40B06E2EFEB60F484000301004C8501E40C05626FC520F484000836C59BE4E1E4018BDC5C37B0E4840C03F373465471E4048793BC2690B4840003888D68A461E4088992842EA0A484080E3A25A44441E40A8E9B303AE0748404051BCCADA461E40804EB340BB05484000F1D8CF62491E40B8716F7EC3044840C088450C3B4C1E40805A457F68044840801B62BCE6551E40B8DDAF027C034840C0DC257156741E40F82F1004C800484040F357C85C791E40F8FFFFFFFFFF4740402CBB60707D1E40606D37C137FF474040BC783F6E7F1E40B8AD11C138FE4740C019355F257F1E40100341800CFD4740806893C3277D1E4050431B800DFC4740409CC1DF2F561E40D8C77C40A0F34740C0934E24983A1E40B8DA6E826FEE4740C08713984E1B1E4090397AFCDEE44740C0DE52CE170B1E40B0A10DC006DA474000D57B2AA70D1E40A89B8BBFEDD74740C069C020E9131E40500438BD8BD547400060E97C78161E4030ED0DBE30D5474080DBF813951D1E40F8230C0396D447404020B75F3E291E40D0F4D901D7D3474000D6AD9E933E1E40D806600322D24740C0490ED8D5441E4008C11C3D7ED14740C0AB1F9BE4571E408096E7C1DDCD4740C0ED7E15E05B1E40100341800CCD474040A837A3E65B1E4008B8CB7EDDCB4740402235ED625A1E4040959A3DD0CA4740C05512D907591E40A8984A3FE1CA4740C0490ED8D5441E40084BE7C3B3CA4740C0934E24983A1E40B0B915C26ACA4740403BE2900D341E40E073D2FBC6C94740C07823F3C82F1E401018080264C84740809CC1DF2F161E40500ABABDA4C747408032384A5E0D1E40386E15C440C74740004C361E6C011E40A85FE97C78C6474040D5AD9E93FE1D4060499D8026C64740406893C327FD1D4008CD203EB0C54740C053E57B46021E40D88558FD11C04740C0C54FE3DEFC1D40805704FF5BBF474080861DC6A4CF1D4078A86DC328BC4740009CFD8172BB1D40801EA33CF3BA4740C0C1FA3F87A91D4020E109BDFEB84740C0D47B2AA78D1D40908461C092B7474080E17A14AE871D40885704FF5BB7474080AD4CF8A56E1D403020ED7F80B7474040FA5E43706C1D4040747ADE8DB74740402FDE8FDB5F1D4028EACC3D24B84740405512D907591D40584F1F813FB84740403E4162BB3B1D4030172AFF5AB84740C0FF04172B1A1D40885704FF5BB74740404C361E6C011D40285FD04202B6474000C64FE3DEFC1C408096E7C1DDB54740C0D24ECDE5F61C40285FD04202B64740C021E4BCFFBF1C40786649809AB84740C0300BED9CB61C4088457EFD10B9474000ECDD1FEF951C4020786000E1BF4740009A999999191C4008E2E7BF07C14740008FC70C54F61B40580ABABDA4BF474000931CB0AB891B40B06E2EFEB6AF474000B728B341861B40F8298E03AFAE4740000D36751E851B408848BF7D1DAE474000B728B341861B4008CD203EB0AD4740406BBB09BEB91B40D0FA5B02F0AD4740C059677C5FEC1B40081286014BAE47408007AF5DDA001C40808D2441B8AE4740808A7269FCE21B40B0B6D4415EA5474080ED7E15E05B1B40A0AD11C138964740009A999999591B40801B62BCE69547400007B474055B1B4000A0C37C7995474080E506431D661B40A0990B5C1E954740C059677C5F2C1B40302F3201BF9047408088450C3BCC1A4090C9C6832D88474000310BED9CB61A40B059677C5F8447408020B248138F1A40B0E0F0828880474080490ED8D5841A40480ABABDA47F4740003E4162BB7B1A4030F38FBE497F474040634337FB431A40081B4982707D474080977153031D1A40B859677C5F7C47404046B41D53D71940A86BED7DAA72474040931CB0ABC9194050FEB5BC726B4740C0573A1F9ED51940A8BF97C28364474040AE47E17AD4194038DEC83CF263474080861DC6A4CF1940F0E769C020634740402CBB6070BD194008E2E7BF076147408038BA4A77771940D80CE2033B5C47400052B81E856B194060FEB5BC725B4740C08A7269FC621940306211C30E5B4740C0C77C40A013194010BB9A3C65574740800D36751E85184038DEC83CF24B474000B950F9D7821840B8622AFD844B4740C053E57B46821840E0FD9C82FC4A4740004A0ED8D5841840A8E67283A14A4740C078E750868A1840D0031F8315454740805512D907591840D8C1FA3F87394740808B6D52D1481840D8C43BC09336474040E7FC14C7711840F8BDDBBC7134474000AC1F9BE4971840D0EE5701BE314740008813984E9B1840805D86FF74314740C0D8D0CDFEA01840D8B2B5BE48304740C082C30B22A218405837177FDB2F47408046EBA86AA21840785704FF5B2F4740409F20B1DD9D1840A85FE97C782E474040D8D5E4297B1840A89B8BBFED27474040295C8FC275184080A52C431C274740C03E73D6A76C1840C8F59A1E14264740C084F068E37818409054C37E4F224740002EE3A6067A184040D8463CD9214740007D410B0978184060F833BC5921474000EA245B5D6E1840081808026420474040AE47E17A541840788461C0921F474080F8872D3D4A1840889C69C2F61F4740001286014B3E1840E08558FD112047408085EB51B81E184038DB87BCE51E474000F1D8CF62091840E0FA5B02F01D474000BFD2F9F0EC1740885A457F681C474000EB56CF49DF1740504CDE00331B4740009F20B1DDDD17406034D6FECE1A4740005B99F04BDD1740A853E57B461A474040E3A7716FDE174028D8463CD91947404082C8224DFC17406834D6FECE12474080D5AD9E937E1840781EA33CF3124740408B6D52D1881840F8E769C02013474040ED7E15E09B1840682B137EA9134740401286014BBE18408896E7C1DD154740800F5EBBB4C11840E8AC33BE2F164740407A19C572FB184030DEC83CF21B47404060E97C78161940D8C1FA3F8721474000FE45D098F91840D8C7B5A162284740C0C1FA3F87E91840D87C957CEC28474080CCD1E3F7E61840D00F238447294740C051B81E85EB184008D061BEBC2A474000AB24B20FF21840B8A78FC01F2C4740802634492CF91840081B4982702D47400082C8224DFC184028327381CB2D4740C0AD4CF8A52E1940281DACFF7332474080D5AD9E933E1940089A417C6033474040CAA48636501940E0A6B1BD1634474080DAFD2AC0F71940303E7782FD394740C078E750860A1A405007793D983A474000AE47E17A141A40C8D03FC1C53A4740808B6D52D1881A4050793BC2693B474040861DC6A4CF1A40386BD443343A474080D576137CF31A40D80F23844739474080A8C5E0612A1B40808461C09237474040D576137C331B4088A52C431C374740008FC70C54361B40508E0244C1364740003E4162BB3B1B40A8E331039535474040C64FE3DE3C1B40286893C3273547404065FD66623A1B4058103CBEBD334740805417F032331B40089D82FC6C304740808C9AAF921F1B40885182FE42154740002FDE8FDB1F1B4038D505BCCC144740C0C64ACCB3221B40781EA33CF312474080CCD1E3F7261B40306BD443341247400078F17EDC7E1B40A8B05241450B4740C07A19C572BB1B40B0A44E4013074740C0F30016F9051C40B89B8BBFEDFF4640C08A6D52D1081C40808461C092FF4640C0EA56CF491F1C40F8E769C020FB464080EDB5A0F7261C4038F38FBE49F74640C0230C0396FC1B4058F833BC59F14640C05417F032F31B40584F1F813FF04640C059677C5FEC1B40600ABABDA4EF464080D6A88768E41B40586D37C137EF4640803788D68AC61B408096E7C1DDED4640409BC6F65AB01B40E0031F8315ED464080E07F2BD9A11B40A8ECF483BAEC464080583A1F9E951B4000D6E3BED5EC46408021E4BCFF7F1B40A8E3310395ED464040944E24987A1B40580438BD8BED464080B628B341461B4058793BC269EB46400082C8224D3C1B40B0B915C26AEA464080944E24983A1B4000D9243FE2E946400091EF52EA321B40E07FD6FCF8E5464040F1113125321B40F07B9BFEECE3464000D8D5E4293B1B40385FD04202DE4640C06893C3273D1B40386893C327DD464000105EBBB4411B40785A457F68DC4640C0368DEDB5E01B40885A457F68CC464040A8FC6B79F51B405070784144C44640C0BB783F6EFF1B406055A18158C2464080B950F9D7021C4088A2EBC20FC246408093347F4C5B1C40A8629CBF09BD46400060E97C78961C4070A52C431CB746404046EBA86AA21C40B0B393C151B04640C0E3A25A44841C40B0C2D84290A14640C0B950F9D7821C4028E109BDFEA046400022E4BCFF7F1C4008CADFBDA3A046400054E57B46421C4030232E008D9C464000B2A19BFDC11B40883FFCFCF7964640C07E6E68CA4E1B40884B00FE29934640C0634337FB431B4088423D7D04944640C05FE97C78161B40507FBDC282954640C0DE52CE170B1B40480438BD8B95464040F8872D3DCA1A40E8AF743E3C934640404C361E6CC11A4088992842EA924640003BE2900DB41A40A8B915C26A9246408090F469158D1A4038EACC3D24904640C0D3F20357891A40F0D5C743DF8F46404054E57B46821A4020F38FBE498F464080240C03967C1A40D0C43BC0938E4640C0798D5DA27A1A4000068200198E464040809BC58BA51A40E088997D1E85464080C64FE3DEFC1A40F8CC203EB075464040AAF23D23011B40281A6B7F67754640C05DC136E2191B40B87A32FFE873464000977153035D1B402838F581E46F464040EA245B5D6E1B4010DC65BFEE6E46404038BF61A2911B408048BF7D1D6E464000416491269E1B40D87FD6FCF86D4640C015E0BBCDAB1B40109700FC536E4640C077F17EDCBE1B400821CB82896F4640C0DE52CE17CB1B40885704FF5B6F4640404B3B3597DB1B40D876137CD36E464040DE57E542E51B40A8DA6E826F6E464080B950F9D7021C40286893C3276D4640C0F8872D3D0A1C409087A2409F6C46400095490D6D201C40B8B915C26A6A464000977153031D1C40B05626FC525F46408015E0BBCDEB1B40B0E0F0828858464000E17F2BD9E11B40600ABABDA4574640C0D47B2AA7CD1B40E0031F83155546400020B75F3E691B4080CC07043A45464080068200196A1B40B853E57B4642464080B1A19BFD811B40804E417E3630464080634337FB831B40D0D38041D22F464040D48041D2E71B40B059677C5F24464080F2052D24201C4058853FC39B1F4640009AD024B1641D40E0F71A82E310464080643E20D0691D40F82F1004C810464080BFD2F9F0AC1D40E08558FD1110464040A3755435B11D40884E417E36104640C0DBF81395DD1D40E0EE5701BE11464080716F7EC3141E40F8DEA63FFB13464040A8FC6B79751E40A8A44E401317464040C422861DA61E409096E7C1DD154640003F3C4B90A11E4080812040861246400083C30B22A21E40A8C2D8429011464040809BC58BA51E40F82F1004C810464040BFD2F9F0AC1E40A86E2EFEB60F4640409279E40FD61E40606A6803B00B4640C0B5F63E55D51E40D08BDAFD2A0A464000D253E410D11E40080F45813E094640C0703D0AD7A31E4078457EFD1001464000D9D0CDFEA01E40D0CABDC0AC004640C099D024B1641E40B0DDAF027CFB454080A9F23D23011E40E0C1FA3F87F14540C014AE47E1FA1D408018213CDAF04540402634492CF91D4038172AFF5AF04540C07C410B09F81D4030F38FBE49EF4540402634492CF91D404876FA415DEE454040D5AD9E93FE1D40B0ECF483BAEC454040CDCCCCCC0C1E4050465C001AE9454000F52D73BA1C1E40303B3602F1E44540400C040132141E4080CC07043AE5454080A4A2B1F6071E40381A6B7F67E5454000573F36C9EF1D40000C040132E4454000733106D6C11D40F07B7F83F6E045404008AF5DDAC01D406073B9C150E145400015AE47E1BA1D40301DACFF73E24540C0DAFD2AC0B71D4008D061BEBCE24540C090EF52EAB21D40801EA33CF3E24540C069C53714AE1D40B0984A3FE1E24540C005820019AA1D40B0E67283A1E2454080F52D73BA9C1D40905D86FF74E145408090F469158D1D40D8D38041D2DF45408023DA8EA98B1D40D0BB783F6EDF45408023DA8EA98B1D40783FFCFCF7DE454000471FF301911D40D0A6954220DD454000B728B341461D403035B401D8DA454040490ED8D5041D40D08BDAFD2ADA4540407F69519FF41C40785D86FF74D945404046EBA86AA21C4078397AFCDED44540003206D6719C1C40D00CE2033BD44540004C6DA9834C1C40000F45813EC945404038BF61A2911B40F8D2A23EC9B7454080F0D8CF62891B40B0BC564277B7454080C64ACCB3621B40081286014BB645404040321D3A2D1B408848BF7D1DB645404023DA8EA98B1A40E0D38041D2A74540C0CCCCCCCC8C1A4008D6E3BED5A4454000C64FE3DEBC1A40A8716F7EC3A4454080B1A19BFDC11A4030232E008DA4454000931CB0ABC91A4078423D7D04A445400091F46915CD1A40B0B0524145A34540C04C6DA983CC1A4000D061BEBCA245400079E75086CA1A408054C37E4FA2454080D253E410911A40A8E9B303AE9745404022DFA5D4651A4000CADFBDA3984540C0B0A6B2281C1A40804E417E36984540002FDE8FDB9F194088397AFCDE944540C0BB783F6EBF1840507C7C4276904540C096766A2EB71840E08558FD11904540009BC6F65AB018400821CB82898F4540406CED7DAAAA1840E0F19881CA8E454040DB2F9FACA818406076FA415D8E45408022DFA5D4A51840805182FE428D4540C0D8D0CDFEA01840806649809A8845404020B75F3EA91840A85FE97C78864540C090F469158D18400809C38025874540808EC70C54761840484F1F813F884540005EBC1FB73F1840B09ECC3FFA8C4540001E8A027DD217400009C380258F4540401A355F25BF1740D0C77C40A08B4540805EBC1FB7BF1740804B00FE298B4540C07C410B09B81740084BE7C3B38A45400082C8224D7C1740500ABABDA4874540C090EF52EA721740905704FF5B87454080438CD7BC5A1740B8E9B303AE87454080D253E410511740D08558FD11884540402FDE8FDB1F17406082FE428F8A4540C0438CD7BC1A1740B0B05241458B454040A148F7731A1740909065C1C48B4540C0B0A6B2281C174090397AFCDE8C45408046EBA86A221740001B4982708D454080A8C5E0612A17408096E7C1DD8D4540400D36751E451740808D2441B88E4540005C94D92043174000BB9A3C658F45408057CA32C4C11640A00854FF20984540C0D36531B1B91640C87328435598454040573F36C9AF1640A8E0F0828898454040AE47E17A141640B0984A3FE19A454040643E20D0A91540F82CCF83BB9B45404009DCBA9B971540D87954FCDF9B4540008E95986785154058431B800D9C454040FE092E56741540905A457F689C45408040321D3A6D1540B89ECC3FFA9C454000323D6189671540B0E33103959D454000323D61896715408848BF7D1D9E454040963FDF166C1540B06E2EFEB69F45408045B9347E711540587C7C4276A04540C07C410B0978154090457EFD10A14540406893C3277D154000D9243FE2A14540C077F17EDC7E1540B8B915C26AA24540C077F17EDC7E154058793BC269A34540007F69519F741540B8A10DC006AA4540404D68925872154090992842EAAA4540C01A3048FA641540080341800CAD45408009DCBA9B57154080AEEFC341AE454080356090F449154008DC65BFEEAE4540C09F1B9AB24315403841B8020AAF4540806ABB09BE391540D8F19881CAAE454000022D5DC1161540B068ACFD9DAD454000E9297288081540F8230C0396AC45408000000000001540080C040132AC454040D6A88768E4144048FEB5BC72AB454080FF04172BDA14400815C78157AB454080C64ACCB362144000E869C020AB4540C0D7D5E4293B1440282CF180B2AB454040D48041D2271440E0BEB9BF7AAC4540808C9AAF921F1440A89ECC3FFAAC4540007E71A94A2B144060F4DC4257B045404047E5266A29144008C765DCD4B04540C09541B5C1291440B8A1629CBFB14540C00D315EF32A14402023A0C211B24540C07B4963B42E144070DC627E6EB24540401A33897A41144010BA84436FB34540C0D7A19A924C1440A032FE7DC6B3454080861DC6A44F1440607347FFCBB3454080B1A4DC7D5E1440E8F42EDE8FB345404038BF61A2911440905182FE42B545408007B474059B1440381A6B7F67B5454040AAF23D23C11440F820CB8289B7454000963FDF16EC144060793BC269BB45404069C53714EE1440D8F4D901D7BB4540C059677C5FEC1440508E0244C1BE454000DC2F9FACE814403820ED7F80BF454080F2052D24201440286E15C440C74540000ADCBA9B17144030DB87BCE5C6454000583A1F9E15144068FB743C66C64540C0DE52CE170B1440D806600322C2454040356090F4091440B0C2D84290C1454000D253E410111440D8C43BC093BE45408046B41D53171440D87FD6FCF8BD454080F52D73BA1C14406831957EC2BD4540C0E9245B5D2E1440580438BD8BBD4540C0285C8FC2351440100341800CBD45400015AE47E13A144028F6D03E56BC4540C0921D1B81281440C85B59A2B3BA4540C0E92807B3291440503A1F9E25BA454040819719362A14409002999D45B94540C0C1FA3F87291440B89597FC4FB8454000DC2F9FAC28144018C0948103B8454040FED64E94241440C09BE09BA6B74540405FED28CE11144070E5EC9DD1B64540C0726A6798FA134070EBE0606FB6454000BEA4315AF7134060BE2EC37FB6454080300DC347F4134020F98381E7B64540C0716F7EC3D4134060FB743C66B645404070422102BE134008BB9A3C65B74540005517F032B31340B06E2EFEB6B745400040321D3AAD1340004E2844C0B7454000AAF23D2381134078AEEFC341B6454000068200196A1340583A58FFE7B4454040861BF0F951134058888043A8B44540C098A1F1445013400894F8DC09B445404084F3A963551340A8AD8383BDB345400015ADDC0B5C134088185A9D9CB345404053E8BCC65E1340488C497F2FB345408000FF942A611340C016F4DE18B24540809E2287885B1340F8AB72A1F2B14540C0CCCEA2774A134018FD135CACB2454000C425C79D4213402005888219B34540C02764E76D2C134020F9F5436CB4454000C74ACCB3221340E830D12005B545404000000000001340A8AD11C138B64540406BBB09BEF91240B877F17EDCB6454000310BED9CF61240B06E2EFEB6B7454000310BED9CF6124030EACC3D24B8454080DAFD2AC0F71240E873D2FBC6B945404000000000001340109700FC53BE45400008AF5DDA00134000BB9A3C65BF4540C0A9F23D23011340E07C957CECC045408019355F25FF12409054C37E4FC2454040240C0396FC1240484CDE0033C3454000E5D4CE30F51240B8716F7EC3C44540C09E20B1DDDD124028172AFF5AC8454040B3CEF8BED8124038E109BDFEC8454040B81E85EBD1124038266F8099C94540C0F0D8CF62C91240503D997FF4C94540C0DB2F9FACE81240B8E0F08288B8454040EA245B5DEE1240E076137CD3B6454040E7FC14C7F1124028E44A3D0BB64540C038BA4A77F71240081B498270B54540C056410C74ED124090F0BDBF41B3454040BEA4315AF7124088C954C1A8B24540408A778027FD1240583ACAC16CB245400021B248130F134038E97DE36BB1454080DD26DC2B131340E8F4A0A014B1454080AB21718F15134068790261A7B0454000726DA81817134078A983BC1EB0454040999B6F4417134018C30E63D2AF454040B3D0CE6916134018C3633F8BAF4540405FED28CE1113403020425C39AF4540C0D5ABC8E8001340305019FF3EAF4540C03106D6719C124030E44A3D0BAE4540802EE3A6067A1240B0AD11C138AE454000045ABA826D1240089700FC53AE454080D38041D2671240B05FE97C78AE4540C01B62BCE6551240805704FF5BAF4540C0DE52CE174B124000CADFBDA3B0454000F9872D3D4A124008274D83A2B145404088450C3B4C124088A2EBC20FB2454080DBF813955D124078A86DC328B4454080D6A88768641240081B498270B545400076C4211B68124060FB743C66B6454000323D6189671240B877F17EDCB6454000F0DDE68D631240888461C092B74540005B99F04B5D1240904E417E36B84540C01B62BCE6551240302F3201BFB84540805B94D92043124028266F8099B94540C0D6A88768241240B86BED7DAABA454040B728B341061240E0AF743E3CBB454000DE57E542E5114008E869C020BB454000CAA48636D01140901EA33CF3BA4540800F5EBBB4C1114000D061BEBCBA454040F9821612B011400806820019BA454080D47B2AA74D11408881204086BA4540808B6D52D1481140B86BED7DAABA45404051BD35B0451140D882177D05BB454000A01B9AB2431140A8DDAF027CBB4540000D36751E451140B059677C5FBC4540808B6D52D14811402841B8020ABF454040FBAF73D3461140889C69C2F6BF4540808D9598674511406001F73C7FC0454000C64FE3DE3C1140B0C2D84290C14540401A3048FA241140682E54FEB5C04540804C361E6C011140606D37C137BF4540006893C327FD1040803FFCFCF7BE4540C0B35C363AF7104028AE9CBD33BE4540800D315EF32A1140D0D03FC1C5BA4540C0298E03AF261140001E8A027DBA4540C0B81E85EBD1104080992842EABA4540805B94D920C3104008E869C020BB454040C422861DA6104050F5F23B4DBC454040B728B34186104010DC65BFEEBE4540005EBC1FB77F104008D3A23EC9BF454040BC783F6E7F1040E0CABDC0ACC04540C00F5EBBB481104088457EFD10C145404023DA8EA98B1040F8E1E7BF07C1454080D47B2AA78D1040785D86FF74C14540803AE7A7388E1040B0B915C26AC24540C032384A5E8D10401015C78157C345404047E6913F881040580DFB3DB1C4454040B950F9D7821040587FBDC282C54540007D410B09781040D0C43BC093C6454000AD4CF8A56E10403841B8020AC74540C0C64ACCB3621040D0BB783F6EC74540405EBC1FB73F1040286552431BC8454040D576137C331040809C69C2F6C7454080DAFD2AC0B70F4088CC07043AC5454000F855B950590F40386211C30EC34540807C789620430F40D8B837BF61C24540005EBC1FB7BF0E4078397AFCDEBC454080E17A14AEC70D40500DFB3DB1B44540006CB6F2925F0C40E07C957CECA845400009E1D1C6710B40B0ECF483BAA44540003F6EBF7C520B40383B3602F1A44540004F5E64023E0B40600DFB3DB1A445408047E17A14AE0A40603D997FF4A1454080890E8123810A40C8CABDC0ACA04540808DCC237F100A40C888997D1E9D454080D8D0CDFE200940D873D2FBC6914540804C72C0AEA60840D8F71A82E3884540800D3B8C499F0840605260014C85454080D349B6BA5C0840D8066003227A4540803F37346507084000301004C870454080CB9F6F0BB6074008240C03966C454000DF4DB7ECB0074088A86DC3286C45408047E17A14AE0740E8AF743E3C6B45408068CA4E3FC80740809C69C2F66745400095128255D50740286E15C440674540805512D90719084048499D80266645408097A3C7EF4D084088CC07043A5D454000C97C40A0530840903FFCFCF74E4540001C62BCE65508409096E7C1DD4D454000DF57E54265084038DB87BCE546454000EA245B5D6E0840D87FD6FCF8454540809CFD81727B0840E0031F8315454540806E10AD158D084060888043A844454080B6F1272ABB0840302CF180B243454080BF9B6ED9E1084050FEB5BC7243454000E5D4CE30F50840904B00FE2943454000416491261E0940281DACFF73424540803C1405FA240940080682001942454080E17A14AE47094090CC07043A3D454000DE57E54265094008E2E7BF0739454080C57762D66B094028594E42E937454000E4A7716F5E0940084E2844C03745408006871744440940B0BC56427737454000F855B950D9084000DC65BFEE36454000C64FE3DEBC08403841B8020A37454080A9F7544E9B0840504F1F813F38454000DF57E5426508403835B401D83A454000C09B6ED9610840B8A78FC01F3C454080D349B6BA5C0840A8716F7EC33C45408099999999990740507FBDC2823D45400089450C3BCC054010CD203EB0354540806116DA396D054050793BC26933454000B1A19BFD41054070ABAE4335314540006E1ADB6B410540A0656B7D9130454000DF57E542650540D0CDFE40B92D454000518BC1C3540540909065C1C42B4540001B62BCE65504405882FE428F2A4540804391EEE7340440B06BED7DAA2A454080378DEDB5E00340B87A32FFE82B454000B1A19BFDC1034088CC07043A2D4540001C2B31CF8A034090C9C6832D30454000986C3CD8820340682E54FEB53045400018080264A80240587FBDC28235454080541B9C883E0240D085CABF963745400090F98040270240789C69C2F6374540009A9999991902403038F581E437454080CB9F6F0B360140D8FA5B02F03545400021E9D32A1A0140381A6B7F6735454080C845B588080140D80CE2033B34454000346ABE4AFE0040D0FD9C82FC32454000E1844204FC00406055A1815832454080B5FB5580EF004080457EFD10314540005EBC1FB7BF00406028D2FD9C2E454080BC783F6E7F004000CD203EB02D454080E04DB7EC300040E0031F83152D4540802CB6494523004038ED0DBE302D454000941CB0AB090040D0CDFE40B92D45400057DB4DF0CDFF3FB0A44E40132F454000DA11876CA0FF3F809C69C2F62F4540004587C09180FF3FB8AAD0402C3145400070067FBF58FF3FF8230C0396344540004687C09180FE3F80ABAE433539454000CA72124A9FFD3F88A86DC3283C45400015AE47E17AFC3F9060C77F813E4540006AC020E993FB3F78ABAE433541454000E3B19FC592FB3F603D997FF441454000897C975297FB3F504CDE00334345400023A81ABD9AFB3FD8F4D901D7434540007F37DDB2C3FB3F803FFCFCF74645400014C2A38DE3FB3F28EACC3D2448454000077DE9ED0FFC3F285C8FC2F54845400079280AF449FC3F58465C001A49454000DD57E54265FC3F58465C001A4945400012AAD4EC81FC3F48FBCA83F4484540007397C459D1FB3F30DB87BCE54E4540007B4B395F2CFB3F38EACC3D2450454000121D024702F93FA87A32FFE853454000ABED26F8E6F83F80423D7D04544540006CF7AB00DFF73F602B137EA953454000F1AB72A1B2F73F3835B401D852454000A6A7C82122F73F000341800C4D454000BFD2F9F0ACF63F2814E97E4E5345400095E524943EF63F386552431B58454000D96CE525BFF53F886308008E5B45400028931ADA40F53F80A86DC3285C454000C4633F8B25F53FB0622AFD845B4540002402D53FC8F23F3035B401D85A4540008722DDCF69F23F9087A2409F5C454000301004C850F23F286893C3275D4540002B931ADA40F23F00CD203EB05D454000BE41B45634F23F109700FC535E4540002B931ADA40F23F08DC65BFEE5E4540000CD7A3703DF23F001808026460454000FFDCD0941DF23F30F911BF6261454000FA821612F0F13FD8B837BF61624540007C82C47677F13F785A457F686445400090C2F5285CF13FB0BF97C28364454000004BE7C3B3EC3FD88558FD11684540000CB474055BEA3FA8E67283A16A454000D8A3703D0AE73FE07FD6FCF86D454000BEAFCA85CAE63F801B62BCE66D45400070ACC43C2BE63F885182FE426D4540009EDFF76F5EE53F60793BC2696B4540005CDAA9B9DCE43FE0BEB9BF7A644540005AB77A4EFAE43FB0E0F0828860454000B2FCF9B660E53F104E2844C05F4540005ADB4DF0CDE53FB8B6D4415E5D45400004232F6BE2E53FB0B05241455B454000C6AA4198DBE53FA0E67283A15A454000FA285C8FC2E53F282F3201BF584540001248C2BE9DE53FE8E8633E2058454000F8BA45602CE53FB0656B7D9158454000F6DD74CB0EE33F305C8FC2F55845400054B81E85EBE13F90457EFD10594540007AA697184BE03FB0656B7D915845400074CFF3A70DE03F4801F73C7F58454000681B7FA2B2DB3F2838F581E457454000440AD7A370D13F883CBB7CEB59454000C840102043D13F5007793D985A4540009458C4B0C3D03FD8F4D901D75B454000C8AA4198DBC73F38E44A3D0B5E45400060DAA9B9DCC63F8048BF7D1D5E45400070D3D85E0BC63F8096E7C1DD5D454000C014731074C23F10BEDBBC715C454000E0FBAA5CA8BC3F6034D6FECE5A45400000D253E410813F20BD6F7CED574540000000000000000070AF777FBC5745400000BE64E3C176BFB8E9B303AE57454000A03BDD79E2A9BFB0656B7D91584540004039B5334CADBF8018213CDA58454000C05DBC1FB7AFBF5073B9C15059454000C05DBC1FB7AFBFA8A10DC0065A4540000009C38025AFBFD0D03FC1C55A45400010D1217024B0BFD0C77C40A05B454000006D72F8A4BFBF285C8FC2F5604540006869A7E672C3BFD89A1F7F6963454000D8A3703D0AC7BF785A457F686445400088BFB4A84FCABF0048A643A765454000CCCCCCCCCCD0BF00CADFBDA368454000B0230ED940D3BF58FEB5BC726B4540002CC6C03A8ED3BF58431B800D6C454000FCFF3861C2D3BF28C6A4BF976C454000588FC2F528D4BFE0FD9C82FC6A454000D858897956D4BFD0B837BF616A4540001068E90AB6D4BFA874B0FECF694540004077499C15D9BFD8FA5B02F0654540006A3EAE0D95E1BF502B137EA963454000F0E2FDB8FDE1BF88423D7D0464454000DEE9CE13CFE6BF385C8FC2F570454000880E812301E7BF10C11C3D7E71454000E49D43192AE7BF0806820019724540000EAFEB176CE7BF30E78BBD17734540009CBCC8047CE7BF909065C1C4734540004C27D9EA72E7BFB059677C5F7445400038AE467625E7BF50E960FD9F75454000960854FF20E7BF10E528401476454000F4BA45602CE7BF889C69C2F67745400004465ED6C4E7BFC882177D057B454000144031B2E4E7BF08C79E3D977B454000B81E85EB51E8BF502B137EA97B454000949A3DD08AE8BFB0DDAF027C7B45400006D847A72EE9BF081E8A027D7A45400000B5183C4CE9BF803CBB7CEB79454000A824B20F32EABF58465C001A79454000124031B2E4EDBF803CBB7CEB794540006A8995D148EEBF6055A181587A45400044BE4BA9CBEFBF303B3602F17C454000E49D43192AF1BF7893A641D1804540004450357A35F3BF8896E7C1DD8545400055DB4DF0CDF4BFA8AAD0402C8945400024CB49287DF5BF889FAA420385454000A439B2F28BF5BF00BEDBBC71844540007E37DDB2C3F5BF58431B800D84454000A0DFF76F5EF6BF80397AFCDE844540002B7FBE2DD8F6BFB0E33103958545400091AE997CF3F6BFB09509BFD485454000A4A7C82122F7BF6828D2FD9C864540003333333333F7BF386E15C44087454000FB6EBA6587F7BFD8FD9C82FC8A454000C3F5285C8FF7BF602B137EA98B4540004387C09180F7BF58707841448C4540005FE97C7856F7BF20ED0DBE308D454000EB1A2D073AF7BF20ED0DBE308D454000E366B801DFF6BF38DB87BCE58E4540006D1ADB6BC1F6BFE0D38041D28F454000F2CEA10C95F6BF08C11C3D7E914540005B8FC2F528F6BFA874B0FECF994540000DFAD2DB1FF6BFD87954FCDF9B45400084EB51B81EF6BF500ABABDA49F4540003CD34B8C25F6BF1018080264A045400039B01C2143F6BF00274D83A2A14540001B2B31CF8AF6BF901EA33CF3A24540007D6E68CA0EF8BF08D6E3BED5A445400024CB49287DFABF50853FC39BA74540003556629E15FBBF00BB9A3C65A7454000BF9B6ED961FBBF10DC65BFEEA6454000020CCB9FAFFBBF2090680245A6454000A75CE15D6EFCBFD0F4D901D7AB4540002C93E1787EFCBFD88558FD11AE45400048E17A14AEFBBF5801F73C7FB0454000B13385CEABFABF6073B9C150B1454000EB51B81E85F9BFF820CB8289B745400018D1764C5DF9BF5001F73C7FB845400054A4C2D882F8BFD80F238447C14540004E27D9EA72F8BF883CBB7CEBC1454000AD105663C9F7BF10E2E7BF07C9454000DE205A2B1AF7BF383E7782FDD1454000AE47E17A14F7BF28ED0DBE30D54540005EB2F1600BF7BF6001F73C7FD845400044BE4BA9CBF6BF08BEDBBC71E44540002B4833168DF5BFB077F17EDC064640000391459A78F5BF305C8FC2F508464000E8F7FD9B57F5BF881EA33CF30A464000C2BE9D4444F5BFB8DDAF027C0B464000630CACE338F5BFD8A6B1BD160C4640007A14AE47E1F4BF08E2E7BF0719464000EB1A2D073AF4BF5855A18158324640002CB6494523F4BF00D9243FE2394640000A98C0ADFBF3BF301AF9BCE23F4640008C9B1A68FEF3BF1881B1BE8141464000EA55647400F4BF98FC4FFEEE414640006208008EBDF3BF384D9F1D704746400060E97C7856F3BF386552431B504640004387C09180F2BF587078414454464000E8F7FD9B57F2BF30DEC83CF253464000A6CAF78C04F2BF1015C7815753464000CD9541B581F1BFD0C77C40A05346400027EE78935FF1BF082DCF83BB534640005C5837DEDDF0BFD0BEB9BF7A544640004D5E6402BEF0BF503A58FFE754464000815A0C1EA6F0BFA8E33103955546400069C020E993F0BFA8DA6E826F5646400002ECA35397F0BFD0BB783F6E57464000CAA99D61EAF0BFB8E67283A15A4640000000000000F1BF0815C781575B464000F8821612F0F1BF00CADFBDA3604640004A72C0AE26F2BFD8EE5701BE61464000857D3B8988F2BF306211C30E6346400076BAF3C4B3F2BF0015C781576346400085B4C6A0D3F2BF80992842EA62464000AAB69BE09BF3BFA8B05241455B464000D66CE525BFF3BFB0C2D8429059464000A4703D0AD7F3BFE8B2B5BE485846400052B81E85EBF3BFD876137CD3564640003A799109F8F3BF8096E7C1DD55464000880E812301F4BF30D505BCCC54464000295C8FC2F5F3BF38E109BDFE60464000301004C850F3BF608BC1C3B481464000E10CFE7EB1F2BF084BE7C3B39A464000A65CE15D6EF2BFF820CB8289AF464000B4FB55806FF2BF286BD44334B2464000368DEDB560F2BF808D2441B8B6464000B1A19BFD41F2BF082A8E03AFBE464000630CACE338F2BF104E2844C0BF464000EC51B81E85F1BF608E0244C1C6464000E7F7FD9B57F1BF504F1F813FC8464000EB1A2D073AF1BF08301004C8C8464000BE64E3C116F1BF78457EFD10C946400063D520CCEDF0BFD8A9F23D23C94640004A3B3597DBF0BF089D82FC6CC846400092533BC3D4F0BFB0BC564277C74640001A62BCE6D5F0BF00DC65BFEEC64640003D9CC074DAF0BFB8DA6E826FC64640000AA01859F2F0BF000341800CC5464000D026874FFAF0BF28DEC83CF2C346400059350873FBF0BFB0DDAF027CC3464000DAC69FA8ECF0BFA86BED7DAAC24640001F85EB51B8F0BF00C11C3D7EC1464000B06A10E6F6EFBFB8B6D4415EBD464000C8CD7003BEEFBF30D505BCCCBC4640009ABCC8047CEFBF68F5F23B4DBC464000F6DD74CB0EEFBF302CF180B2BB464000A80183A44FEEBFB0B0524145BB464000DCC5FB71FBEDBF881EA33CF3BA464000DA34B6D782EDBF883CBB7CEBB946400002B5183C4CEDBF5073B9C150B9464000C4AA4198DBE9BF6040DAFF00AF46400036C478CDABE9BF60FB743C66AE464000EC51B81E85E9BF10CD203EB0AD464000BED2F9F0ACE8BF88ABAE4335A94640007AA697184BE8BF783FFCFCF7A646400038E7A7388EE7BF40A704C4249E464000C817B49080E7BF88C613419C9D464000D02A33A575E7BF88CFD6C1C19C4640008A9FC6BD79E7BF5852D2C3D09A46400022E3512A61E7BF385F5E807D984640006AF7AB00DFE6BF602E54FEB59046400020A81ABD9AE6BF88AEEFC3418E4640003A0B7BDA61E6BF8887A2409F8C4640007A82C47677E1BF10D061BEBC7246400002B5183C4CE1BFB8A10DC00672464000F4BA45602CE1BFB8E67283A172464000F4BA45602CE1BF904B00FE2973464000A20227DB40E1BF801B62BCE67D464000504A085655E1BF588E0244C17E464000B8B06EBCBBE1BFE0FD9C82FC8246400090C2F5285CE3BF3829B000A68646400092533BC3D4E3BFA86E2EFEB687464000FAB9A1293BE4BFE07C957CEC8846400022A81ABD9AE4BF30F04E3E3D8A46400040BFEFDFBCE4BFD8FD9C82FC8A46400038799109F8E4BF00240C03968C464000CE3AE3FB62E5BF3838F581E48F4640000A8CBCAC89E5BF808AE3C0AB9146400068D619DF97E6BF40CEFBFF38A94640003A799109F8E6BFE0CDFE40B9AD464000E2E82ADDDDE7BF6831957EC2B5464000F0E2FDB8FDE7BFD8C43BC093B64640003C9CC074DAE8BFD082177D05BB464000E29D43192AE9BF805A457F68BC46400096766A2EB7E9BF5876FA415DBE4640009A99999999EBBF282CF180B2C3464000880E812301F0BF3829B000A6CE46400098620E824EF1BFA07A32FFE8D3464000B4FB55806FF1BF805A457F68D446400090F98040A7F2BF7821E4BCFFD7464000E1B19FC592F3BF808AE3C0ABD9464000A6936C75B9F3BFB85CA8FC6BD94640003D9CC074DAF3BFB074B0FECFD94640004512BD8CE2F3BF582575029ADA46400002232F6BE2F3BF88992842EADA4640005E7B6649C0F3BF2814E97E4EE346400058FE7C5BB0F3BF80397AFCDEE4464000AAB69BE09BF3BFA868ACFD9DE5464000B98E71C505F3BF10B743C362E64640005F0322C455F2BF784276DEC6E6464000A0DFF76F5EF2BFB0A44E4013EF4640000AD7A3703DF1BFE0D03FC1C5F2464000A4A7C82122F1BF009A417C60F34640003656629E15F1BF30F6D03E56F44640003D9CC074DAF0BF98C2D8429001474000DCE9CE13CFF0BF885A457F680447400092533BC3D4F0BF00D6E3BED5044740004A3B3597DBF0BF805182FE420547400051B81E85EBF1BF286552431B10474000368DEDB560F2BFD8C77C40A013474000E00CFE7EB1F1BF58465C001A21474000A17F828BD5F1BF48404CC28528474000108B187698F2BF38D8463CD92947400057FE7C5BB0F2BF38D8463CD9294740007E37DDB2C3F2BF508BC1C3B4294740003233333333F3BF382F3201BF28474000C1BE9D4444F3BFA8E0F0828828474000412D060F53F3BFE0B2B5BE48284740008422DDCF69F3BF908461C09227474000C61858C771F3BF80A52C431C274740007460394286F3BFD8031F83152547400029931ADA40F4BF3841B8020A27474000624337FB83F7BFA853E57B4632474000EE8D210078FABF8881AE7D0139474000F2CEA10C95FCBF8860C77F813E4740004A72C0AE26FDBF587C7C4276484740000AD7A3703DFDBF00D061BEBC4A47400005465ED6C4FDBFF8264D83A251474000C972124A9FFEBF38EACC3D245847400096766A2EB7FEBF08301004C8584740803BA6EECA0E00C010C11C3D7E61474080C2BE9D444400C0109A417C6063474080C0C8CB9A7800C0B0ECF483BA64474080A0168387A900C0B8AD11C13866474080643909A5CF00C0808461C0926747408017D1764CDD00C028EACC3D2468474000295C8FC2F500C0A85CA8FC6B69474080A339B2F20B01C03814E97E4E6B4740008F8B6A111101C0B8716F7EC36C4740805A6265341201C0000682001972474000D7A3703D0A01C0D0FD9C82FC7247400077F17EDCFE00C0F82CCF83BB7347408077BAF3C4B300C0B8E0F08288784740809CF3531C4700C01048A643A77D474000C80C54C6BFFFBF68E256410C84474000D66CE525BFFFBF805A457F6884474000CCCCCCCCCCFFBF88CC07043A854740804387C0910000C0908461C092874740008F8B6A111100C0786649809A8847408023D5777E3100C0D0066003228A474080425A63D06900C008BEDBBC718C474080C0C8CB9A7800C088397AFCDE8C474080AD47E17A9400C008A0C37C798D4740807A14AE47E100C06040DAFF008F474080953FDF16EC00C00809C380258F4740805B5837DE5D01C0804E417E3690474080067B13435201C068F5F23B4D9C47400030D7A2054801C0806F287CB69E47408015A8C5E04101C0A0779CA2239F4740002A560DC23C01C0B8A1D45E449F4740809EE925C61201C008C79E3D97A3474080B48D3F515900C0B0716F7EC3A447400059350873FBFFBFA8A78FC01FA4474000992B836A03FFBF28E78BBD17A347400077BAF3C4B3FEBF081E8A027DA2474000FFC874E8B4FEBFD006600322A24740005CC64D0D74FEBFA0656B7D91A0474000C1BE9D4444FEBFD8D38041D29F474000A3703D0AD7FCBF08E869C0209B4740009FDFF76F5EFCBFB8E67283A19A47400082919735F1FBBF101E8A027D9A474000F6285C8FC2FBBF5007793D989A47400048E17A14AEFBBFD0D03FC1C59A47400017080264A8FBBFD8FD9C82FC9A474000B4C4CA6824FEBF500DFB3DB1A4474000F91400E359FEBF80CC07043AA54740004D5E6402BEFEBF9048BF7D1DA6474080B7E7F9D30600C08818213CDAA8474080C09140832D00C008E2E7BF07A9474000D21C59F94500C030E109BDFEA84740800BCD751A0901C0580ABABDA4A747400059315C1D8001C0409B8E006EA44740807E6E68CA8E01C05801309E41A34740801377BCC92F02C008DC65BFEE9E474080A8C0C9365002C0D0C43BC0939E4740807C410B097803C038266F8099A1474000E8F7FD9BD703C0B0DDAF027CA3474000698995D14804C05831957EC2A5474080FCA5457D5204C0D07FD6FCF8A54740804F8BC1C35404C0B8DA6E826FA64740801E85EB513804C0A85CA8FC6BB14740805FE97C78D603C090397AFCDEB4474000FA78E8BBBB03C0001B498270B5474000AE47E17A9403C05870784144B4474080736039428603C0302CF180B2B3474000A243E0484003C080A86DC328B4474080698995D14803C050499D8026B6474080B7223141AD03C078BDC282FBB9474080490ED8D5C403C078ABAE4335B9474080A8C0C936D003C0E8A9F23D23B9474080B48D3F51D903C06073B9C150B9474080F3C473B6E003C0F0264D83A2B94740809A8F6B43E503C0283E7782FDB94740802DAC1BEFEE03C080A52C431CBF4740805608ABB1E403C0D0D38041D2BF474080B48D3F51D903C0A89B8BBFEDBF47408001F6D1A9CB03C03838F581E4BF474080BE9B6ED96103C0A89B8BBFEDBF474080BB783F6EFF02C00800000000C047400091EF52EAF202C0E000DE0209C0474000FED2A23EE902C0804E417E36C0474080CEF9298EE302C0A8E0F08288C0474080652FDB4E1B03C05873B9C150C1474080E270E6571304C0F02CCF83BBC34740807F9BC58BA504C008D6E3BED5C447408020B248134F05C008274D83A2C14740002C7FBE2D5806C0C8C43BC093BE474080A339B2F28B06C0E009A1832EBF474080AF743E3CAB06C0580ABABDA4BF47408077BAF3C4B306C03838F581E4BF4740008C62B9A5F506C0306893C327C54740806CE34F54F606C0408F519E79C5474080FFCA4A93F206C060C1FD8007C647400014799274ED06C0B8DAC35E28C6474000E92807B3E906C0A8AD11C138C64740801A31B3CFC306C0B8DAC35E28C647408087122D797C06C0F89F6EA0C0C547408077BAF3C43306C028E44A3D0BC6474080D6A3703D0A06C0A868ACFD9DC54740009B8F6B43E505C0A868ACFD9DC5474080D349B6BADC05C0B09509BFD4C5474000BC783F6E7F05C050431B800DCC47400014AE47E17A05C010BEDBBC71CC474000C61858C77105C0B85FE97C78CE47408090EF52EA7205C05040DAFF00CF4740803BA6EECA8E05C0D80F238447D14740803656629E9505C0B0C2D84290D147400061DF4E22A205C0808AE3C0ABD1474000950C00551C07C0F860FD9FC3CC47400047E7FC146707C0702711E15FCA474080FA78E8BBBB08C03035B401D8CA47408039B01C21C308C0784B00FE29CB474000E5D4CE30F508C000240C0396CC474000000000000009C0A8ECF483BACC47400064027E8D0409C020F6D03E56CC474000B8E7F9D30609C0504CDE0033CB47400083BEF4F60709C0F02CCF83BBC3474000DCF3FC690309C0D8D03FC1C5C24740006DE34F54F608C0D88558FD11C0474000490ED8D5C408C000E5284014BE47400058FE7C5BB008C08887A2409FBC4740003BDD79E2D908C008BEDBBC71BC4740806E10AD150D09C0F8D5E3BED5BC4740005A6265341209C030ED0DBE30BD47408077BAF3C43309C0584CDE0033C347408058FE7C5B3009C0602B137EA9C347400094490D6D2009C0000C040132C447408045B41D531709C0B89ECC3FFAC4474080AD47E17A1409C0081B498270C5474000F71E2E390E09C058853FC39BC74740806E10AD150D09C000301004C8C84740003BA6EECA0E09C0B874B0FECFC9474000E370E6571309C0D0D03FC1C5CA47408084EB51B81E09C090423D7D04CC47408077BAF3C43309C038E44A3D0BCE474080B1A19BFD4109C0D0C43BC093CE474000746039428609C0507C7C4276D04740803E00A94DBC09C0A8B0524145D34740005A626534120CC060465C001AE147408059BDC3ED100DC0D00166BE83E3474080E7F7FD9B570EC0B868ACFD9DE5474000F4FBFECDAB0EC0B85FE97C78E6474080698995D1C80EC00009C38025E74740804387C091000FC008C11C3D7EE9474000662FDB4E1B0FC0004BE7C3B3EA474080D8D0CDFE200FC0386211C30EEB4740003F00A94D3C0FC0206893C327ED4740800773BB97DB0FC008D9243FE2F1474000B29C84D26710C09021E4BCFFEF47400022A81ABD9A10C0B0B6D4415EED4740406BB6F2929F10C0C882177D05EB474000272F32019F10C0101E8A027DEA474080CEF9298EA310C0808AE3C0ABE94740C051B81E85AB10C0786649809AE8474080B6F1272ABB10C008DC65BFEEE64740403E05C078D610C0109700FC53E64740008FC2F528DC10C0B8AD11C138E64740C0D11C59F90511C0D8CDFE40B9E54740C069C020E91311C06031957EC2E5474040CDC7B5A17211C0508E0244C1E64740007592AD2E7711C008DC65BFEEE64740C00CFFE9067A11C028F38FBE49E7474040A46B26DF7C11C058465C001AE94740400AD7A3707D11C0F8264D83A2E94740C0583508737B11C078A2EBC20FEA4740C0B8196EC07711C04855A18158EA47404078EC67B16411C0801EA33CF3EA47400061DF4E226211C0A8B0524145EB4740007365506D6011C0889065C1C4EB4740406BB6F2925F11C0A0ECF483BAEC474000D12170246011C0785182FE42ED474040666666666611C060853FC39BEF4740C05D85949F7411C0306211C30EF347400016DBA4A29111C058853FC39BF7474000E275FD82AD11C0E0FD9C82FCFA4740C0B3C9E193BE11C0D0BEB9BF7AFC474000B3976DA7CD11C0580438BD8BFD4740406CE8667FF011C0F8FFFFFFFFFF4740405F251FBBFB11C0E091EA3BBF00484000193A76501912C0004BE7C3B30248408062484E261E12C0B8984A3FE1024840402F151BF32A12C0386BD443340248404039B5334C5D12C0D08BDAFD2A02484000EE79FEB4C112C0D0F4D901D7034840807B0F971CC712C090423D7D04044840406BB6F292DF12C000D6E3BED50448400002B9C491E712C060EB19C23105484000E8F7FD9BD712C0001808026408484000F2CEA10CD512C0382F3201BF08484040C2F5285CCF12C09018213CDA084840001C261AA47011C08060C77F810E4840801281EA1F6411C060FB743C660E4840006AC020E95311C0A8B6D4415E0D484080C87729753911C08087A2409F0C484040333333333311C038232E008D0C4840C083B9DDCB2D11C058888043A80C4840404A09C1AA2A11C0B89ECC3FFA0C4840802407EC6A2211C0F8298E03AF0E484000B7EC10FF2011C00809C380250F4840C021A81ABD1A11C0B874B0FECF114840803BDD79E21911C05855A1815812484080DD205A2B1A11C058FEB5BC7213484040D349B6BA1C11C0B059677C5F144840C08618AF793511C0682E54FEB518484040AC1A84B93D11C0E073D2FBC61948404083BEF4F64711C0B06BED7DAA1A4840C0415F7AFBC311C08860C77F811E4840C0332E1C08D911C03841B8020A1F484080A23EC91DE611C05040DAFF001F48408079E2395BF011C03029B000A61E4840C0620CACE3F811C0B0AD11C1381E484000F3C98AE1FA11C030327381CB1D48400049D74CBEF911C0E0B5F63E551D48400049D74CBEF911C088397AFCDE1C4840008196AE600B12C020266F8099194840C0A23EC91D2612C000C45DBD8A164840C0633E20D02912C070AEEFC341164840800778D2C23512C08048BF7D1D1648400005508C2C3912C058FB743C6616484080B6F1272A7B12C0306BD4433422484000560DC2DC7E12C0E8A6B1BD162448404060E4654D7C12C008BEDBBC71244840C08096AE604B12C0383E7782FD29484040A46B26DF3C12C0D882177D052B4840C0DC2571563412C058FEB5BC722B48404078EC67B12412C0A87A32FFE82B4840800DFAD2DB1F12C0082DCF83BB2B484000D12170242012C0B8B05241452B484000EC4CA1F32A12C0302F3201BF284840C05D85949F3412C0D809A1832E2748404019FED30D3412C0D0F19881CA26484000C8409E5D2E12C0D8AC33BE2F264840C01281EA1F2412C0605260014C25484040C972124A1F12C0D088997D1E2548404061DF4E22A211C058F5F23B4D24484000B3976DA70D11C008BEDBBC71244840805A626534D210C0E0CDFE40B925484000B4C9E193BE10C060FB743C6626484040880E8123C110C0E0C43BC09326484040333333333311C008E2E7BF0729484080CB9A58E09B11C0A8A10DC0062A484000880E8123C111C0A8E67283A12A484040520ABABDC411C0481FBAA0BE2B4840003AB01C21C311C0001B4982702D484000F4FBFECD6B12C0B0A78FC01F2C484040CEC29E76D812C03835B401D82A484080976C3CD80213C0B86BED7DAA2A4840402DB1321A0913C000D061BEBC2A48400055DB4DF00D13C080992842EA2A48404016DBA4A21113C0504CDE00332B48400078B5DC991913C078397AFCDE2C484000698EACFC2213C0803FFCFCF72E484040CEF9298E2313C000BB9A3C652F484040FED2A23E2913C0D8FA5B02F035484040FED2A23E2913C0F8C35DBD8A364840C00F2219721C13C080ABAE433541484080DD205A2B1A13C000274D83A2414840802502D53F0813C0D00CE2033B4448404049D74CBEF912C08096E7C1DD45484000A8C5E061EA12C0F020CB8289474840005D8AABCACE12C0305C8FC2F5484840C0D6A3703DCA12C0A8AAD0402C494840407B0F971C8712C0386BD443344A4840404487C0918012C030F04E3E3D4A4840404A09C1AA6A12C078ABAE43354948408008AA46AF6612C0305C8FC2F5484840000BD28C456312C0E0CABDC0AC48484080CB9A58E05B12C0B8E9B303AE474840C0332E1C085912C0805D86FF74494840003AB01C214312C0A0BC5642774F484000880E81234112C05037177FDB4F4840004A09C1AA2A12C06073B9C150514840C000FBE8D42512C0905D86FF74514840004A09C1AA6A11C0081286014B56484080D79E5912B010C08821E4BCFF5748400091EF52EAF20FC0A8BF97C2835C48408092E52494BE0FC080397AFCDE5C48408015A4198BC60FC060793BC2695B484080346090F4C90FC05855A181585A484000E17A14AEC70FC008D9243FE2594840000F27309DB60FC0B86E2EFEB657484080CEC29E76980FC0F8DEA63FFB534840008FC2F528DC0EC0B85CA8FC6B5148408020B24813CF0EC0B07A32FFE853484000CEF9298EE30EC080A52C431C57484080BE9B6ED9E10EC02820ED7F80574840006BED7DAAAA0EC0109A417C605B484080F84B8BFAA40EC0082DCF83BB5B4840809CBCC8047C0EC0283B3602F15C484080402D060FD30DC0E0AF743E3C5B4840804E5E6402BE0DC080992842EA5A4840801E4E603A6D0DC0D07C957CEC58484080ED7E15E01B0DC038F38FBE4957484000490ED8D5C40CC08060C77F8156484080E49D4319AA0CC08060C77F8156484000DE205A2B9A0CC06040DAFF00574840802A52616C410CC06828D2FD9C5E4840804387C091800CC000D9243FE261484080D6A3703D8A0CC078A2EBC20F62484000C972124A9F0CC0883CBB7CEB61484000F94B8BFAA40CC0D08BDAFD2A624840804C310741A70CC0504CDE003363484000F94B8BFAA40CC068F5F23B4D6448400085EB51B89E0CC0805182FE4265484000DE205A2B9A0CC00848A643A765484080BD6E11184B0CC0508BC1C3B46948408099999999190CC0884B00FE296B48408088450C3BCC0BC0E0C77C40A06B484000D7A3703D0A0BC070ABAE433569484000EA245B5DEE0AC0B074B0FECF694840003BDD79E2D909C0E009A1832E6F484080C2BE9D44C409C0E0BB783F6E6F48408077F17EDCFE08C0888D2441B86E484080230C03967C08C0D873D2FBC669484000C745B5880807C028DB87BCE55648400077F17EDC7E06C06028D2FD9C4E4840807D37DDB2C305C0D00CE2033B444840004B04AA7F9005C0908AE3C0AB41484000583508737B05C0784E417E364048408001F6D1A9CB03C0B0E9B303AE4F4840809735B1C0B703C000CADFBDA35048408077BAF3C4B303C010E2E7BF075148400023D5777EB103C0A8C2D842905148408070067FBF5803C0682B137EA953484000E5D4CE307502C010C45DBD8A5648400016A4198B4602C030E44A3D0B56484000B8E7F9D30601C0E0EE5701BE514840009EEBFB705000C03820B41EBE4C4840807E6C921F5100C068B8ACC2664C48400096766A2EB7FFBFA074B0FECF41484000E82E89B3A2FFBF30266F809941484000C3F5285C8FFFBF00274D83A2414840009C853DED30FFBF804B00FE2943484000510ABABD24FFBF1878D2C265434840005512D90719FFBFE0F4D901D743484000179AEB3412FFBF58F5F23B4D4448400092E524943EFFBFB074B0FECF49484000698995D148FFBFD08BDAFD2A4A4840000E315EF36AFFBF504CDE00334B48400055A4C2D882FFBFE87954FCDF4B484000A0168387A9FFBF58707841444C4840005F7B6649C0FFBF68F5F23B4D4C484000BA0A293FE9FFBF00DFA63FFB4B484000B3976DA70D00C0286893C3274D484080643733FA1100C04011363CBD50484000D993C0E61C00C0500D6D003652484000560A815C2200C09820EA3E0053484080F3C29D0B2300C080C30B225253484000DDE9CE13CFFFBFA89B8BBFED5748400052B81E85EBFEBF100F45813E59484000F1CEA10C95FDBFD8D03FC1C55A484000921CB0AB89FDBFD8D03FC1C55A484000953FDF166CFDBF804E417E36584840000D315EF36AFDBFA8E9B303AE574840005CC64D0D74FDBF38F38FBE495748400054A4C2D882FDBF6040DAFF00574840009DF3531CC7FDBF9048BF7D1D56484000F2052D24E0FDBF080C0401325448400052B81E85EBFDBF604CDE003353484000292504ABAAFDBF5801F73C7F50484000A439B2F28BFDBFD0BB783F6E4F484000C51858C771FDBFD8F19881CA4E4840004450357A35FDBF88AEEFC3414E48400078F17EDCFEFCBF50499D80264E484000118B187698FCBF50499D80264E4840004A04AA7F90FBBFB0AD11C1384E48400047AAEFFC62FABF508E0244C14E484000960854FF20FABFB0A44E40134F484000BA0A293FE9F9BF600ABABDA44F48400014E5D2F8C5F9BF20EACC3D245048400033B918036BF9BF10786000E15148400060E97C7856F8BF905D86FF74514840003C0AD7A370F7BFA8C2D8429051484000AAED26F8E6F5BFD0B837BF6152484000AB24B20F32F7BFB05FE97C78564840001B62BCE6D5F7BF00D3A23EC95748400058350873FBF7BF804E417E365848400039799109F8F8BFB85626FC525F4840000000000000F9BFB06E2EFEB65F484000A7CAF78C04F9BF904E417E3660484000B2A19BFD41F9BFD0AF743E3C6B4840004350357A35F9BFB8DA6E826F6E484000B8E7F9D306F9BFF80241800C75484000ABED26F8E6F8BFB8A10DC00682484000EA1A2D073AF9BF88457EFD1081484000FF368B174BF9BF7818213CDA804840008EC2F5285CF9BFE8A9F23D2381484000A75CE15D6EF9BF803CBB7CEB81484000C2F5285C8FF9BF386893C32785484000F5285C8FC2F9BF58FEB5BC728B4840006D1ADB6BC1F9BFA8622AFD849B48400022DFA5D4E5FABF08CD203EB0A5484000FF368B174BFBBF282F3201BFA84840003D9CC074DAFBBF809FAA4203AD4840000000000000FCBF285FD04202AE4840003C0AD7A370FCBFE0D38041D2AF484000703D0AD7A3FCBF8021E4BCFFAF4840002B7FBE2DD8FCBFB09B8BBFEDAF48400009A01859F2FCBFD000DE0209B048400078F17EDCFEFCBF30172AFF5AB0484000FB6EBA6587FDBF909C69C2F6BF484000A439B2F28BFDBF282F3201BFC84840003D0AD7A370FDBFB8A10DC006CA484000768368AD68FDBF386211C30ECB4840008522DDCF69FDBFF8230C0396CC4840000391459A78FDBF10C45DBD8ACE48400069C020E993FDBF28F911BF62D1484000D0EFFB37AFFDBFF8E769C020D3484000A7936C75B9FDBFB0DDAF027CD348400093533BC3D4FDBFE8A6B1BD16D4484000B4C4CA6824FEBF80397AFCDED4484000EF74E78967FEBF605260014CD5484000AAB69BE09BFEBF00A0C37C79D54840008F8B6A1111FFBFD0AC33BE2FD6484000950854FF20FFBFA85FE97C78D64840002CB6494523FFBF883FFCFCF7D6484000EE3D5C721CFFBF602B137EA9DB484000662FDB4E1BFFBFD00CE2033BDC4840008F8B6A1111FFBF50888043A8DC484000111D024702FFBF503A58FFE7DC484000D9C69FA8ECFEBFC8031F8315DD484000FBA5457DD2FEBFE088997D1EDD4840005F200890A1FEBF78397AFCDEDC484000624337FB83FDBF109A417C60DB484000C51858C771FBBFA8A44E4013D74840009DF3531CC7FABFD0031F8315D54840003E4162BBBBFABF500DFB3DB1D4484000B13385CEABFABF00BEDBBC71D4484000CFB8702064FABF000C040132D448400063D520CCEDF9BFD87954FCDFD3484000108B187698F8BF58431B800DD4484000D63BDC0E4DF8BF1090680245D4484000A6CAF78C04F8BF000341800CD5484000A7936C75B9F7BFA85FE97C78D6484000BFD2F9F0ACF7BFE076137CD3D64840004B04AA7F90F7BF8821E4BCFFD7484000F4F1D07777F7BF5873B9C150D9484000E1B19FC592F6BF38F04E3E3DDA484000AD47E17A14F6BF001E8A027DDA48400039799109F8F5BF281DACFF73DA484000E59D43192AF5BF608BC1C3B4D9484000416491269EF4BFD8F71A82E3D8484000EB1A2D073AF4BF888461C092D74840007397C459D1F3BF20DEC83CF2D348400058FE7C5BB0F3BFD8CABDC0ACD0484000E82E89B3A2F3BF286E15C440CF484000F84B8BFAA4F3BF3029B000A6CE484000CFEFFB37AFF3BF80AEEFC341CE4840003DD34B8C25F4BFF8230C0396CC484000BFD2F9F0ACF4BF10D061BEBCCA484000C64FE3DEBCF4BF381DACFF73CA484000FCA5457DD2F4BF588BC1C3B4C9484000E466B801DFF4BF282F3201BFC84840007A14AE47E1F4BF28EACC3D24C8484000B48D3F51D9F4BF10E5284014C648400014E5D2F8C5F4BFA8716F7EC3C4484000B13385CEABF4BF886308008EC3484000118B187698F4BF3035B401D8C2484000EB1A2D073AF4BFF820CB8289BF484000662FDB4E1BF4BFA85FE97C78BE48400030D978B005F4BFE0CDFE40B9BD484000DCE9CE13CFF3BF20DEC83CF2BB484000F94B8BFAA4F2BF60431B800DB4484000FCA5457DD2F1BF508E0244C1AE484000D0EFFB37AFF1BFE0D38041D2AF484000F4F1D07777F1BF10E2E7BF07B148400006B474055BF1BFF8264D83A2B1484000E49D43192AF1BFD8B837BF61B24840003656629E15F1BF8081204086B2484000C040102043EFBFE0D03FC1C5B248400056FE7C5BB0EDBF8081204086B24840009CBCC8047CEDBFA8B915C26AB2484000467364E517EDBF58465C001AB14840004EB9C2BBDCECBFB0E0F08288B0484000788368AD68ECBFB09B8BBFEDAF4840001863601DC7EBBFD009A1832EAF48400090E524943EEBBF808D2441B8AE4840000491459A78EABF001286014BAE484000546D37C137E7BF809FAA4203AD484000225D33F9E6E3BF80A86DC328AC484000E22F2DEA93E2BF100C040132AC484000CE81E50819E0BF68F5F23B4DAC484000B442588D25DBBF909065C1C4AB48400088C77E164BDABFD0C77C40A0AB484000F073435376D8BFE0B837BF61AA48400028A77686A9D7BF888AE3C0ABA9484000D8A3703D0AD7BF080F45813EA9484000D05D126745D3BFF8DB65BFEEA64840006866666666D2BF60FB743C66A648400078CC07043ACDBF58F5F23B4DA4484000905242B0AABABF081286014BA648400030A3E6ABE4B7BF08C45DBD8AA6484000B0B794F3C5B2BF78A52C431CA7484000000C040132A4BFD8B2B5BE48A8484000000000000000006067D13B15AA484000402FDE8FDBAF3F100341800CAD48400040ECDB4944B43FE0FA5B02F0AD48400010FA7DFFE6B53F6028D2FD9CAE484000B0060C923EB93F6001F73C7FB04840004077499C15BD3F0006820019B2484000B0737E8AE3C03FA8622AFD84B348400030527DE717C33F805A457F68B448400078404B57B0C53F789FAA4203B5484000F0BBE9961DCE3F002A8E03AFB648400008B5183C4CD13FB0A44E4013B74840000CDC813AE5D23F80CC07043AB7484000847C975297D73F584F1F813FB8484000500306499FD83F706649809AB848400018F92EA52EDB3FA874B0FECFB94840009431B08EE3DC3FE082177D05BB484000148A743FA7DD3F809065C1C4BB484000F0758BC058DE3F8087A2409FBC484000086D72F8A4DF3FA85FE97C78BE4840007861DD7877DF3FA85FE97C78BE484000000589EDEEDE3F305FD04202BE48400024F4A5B73FDC3FB859677C5FBC4840001041D5E8D5D83F6007793D98BA4840002C806264C9D73F8854C37E4FBA48400060200890A1D63FD006600322BA484000703D0AD7A3D43F283E7782FDB948400030806264C9D33FB0A10DC006BA4840005449641F64D03F9081204086BA484000188FFD2C96C43F80423D7D04BC48400030C37FBA81BE3F28E44A3D0BBE4840007069A7E672BB3FE076137CD3BE484000B0415F7AFBB33F10C11C3D7EC1484000C088B663EAB23FA853E57B46C24840006071C79BFCB23F58793BC269C348400040882CD2C4B33FB059677C5FC4484000B0B45373B9C53F80C9C6832DD8484000C8F869DC9BC73F603D997FF4D94840001000000000C83FB053E57B46DA48400048BFEFDFBCCA3FA87A32FFE8DB4840003014E97E4ECB3FB0A78FC01FDC4840004877499C15D13F901B62BCE6DD484000409B1C3EE9D33F905704FF5BDF484000544EED0C53DB3F303B3602F1E44840004278EDD206E23FB8A78FC01FEC4840005CFDD824BFE23F386893C327ED4840002ACB49287DE43FB877F17EDCEE484000E2E82ADDDDE53FD0D38041D2EF484000FAB9A1293BE63F8821E4BCFFEF4840000A45BA9FD3E63FD08558FD11F04840005712D90719F13F00C45DBD8AF6484000055ABA822DF13FF0298E03AFF6484000FBB9A1293BF33FA8A78FC01FFC484000ED51B81E85F33F383B3602F1FC4840001E85EB51B8F33F0848A643A7FD484000CBE02879F5F53F68D905836B0849400010548D5E4DF63FA0C2D8429009494000B2D826158DF63FA8E67283A10A494000C0098508F8F63F08240C03960C4940009E2ADF3312F73F90CC07043A0D494000368DEDB560F73F2838F581E40F49400046F5D6C016F83F38D8463CD919494000A539B2F28BF83F283B3602F1244940003AE7A7388EF83F301A6B7F6725494000BDAFCA85CAF83FD888997D1E2D4940002D7FBE2DD8F83F08E52840142E49400002232F6BE2F83FB85FE97C782E494000295C8FC2F5F83F082A8E03AF2E49400019D1764C5DF93FF8BA9A3C652F494000E2B19FC592F93FD0BB783F6E2F494000848AAA5FA9F93FC88BBE82342F494000890E812301F93FF84AE7C3B332494000B36A10E6F6F83F28E78BBD1733494000E96514CBEDF83FF8DEA63FFB3349400082C8224D3CF93F10C79E3D9743494000B8E7F9D306F93F500ABABDA457494000C7866EF607F93F5055A181585A4940006CC020E993F93F888461C092674940000100000000FA3F38172AFF5A704940003F4162BBBBFB3F08CADFBDA378494000737495EEEEFB3F60F833BC597949400011548D5E4DFC3F4855A181587A494000D0EFFB37AFFC3FD8AF743E3C7B494000CF0358E417FF3F10BB9A3C657F494080BE9B6ED9E1014080397AFCDE84494080F3052D24E00240883FFCFCF78649408069C020E91303402829B000A686494080B1A19BFD4103403041B8020A8749400046EBA86A620340D8BB783F6E87494000F9821612F00340D0EE5701BE89494000A5A7C8212204405807793D988A49408095128255550440602B137EA98B4940'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('GM','DE','DEU','276','Germany','34895','82652369','150','155','9.851','51.11','0106000020E6100000170000000103000000010000000C00000020A4198BA66B2140A8CB290131D947406075C8CD705B21406870067FBFD84740205DC136E2592140D00F238447D94740A0ECF483BA5821401024D3A1D3D94740A085048C2E5721404882FE428FDA4740C05626FC52572140D882177D05DB4740C06ABB09BE592140584CDE0033DB474080116DC7D46521400015C78157DB4740405C8FC2F5682140B8B0524145DB4740C06BED7DAA6A2140781EA33CF3DA4740C091088D606B2140001E8A027DDA474020A4198BA66B2140A8CB290131D9474001030000000100000019000000C06ABB09BE391B40D0031F8315CD4A40407D410B09381B4080397AFCDECC4A4040EFAB72A1321B40283B3602F1CC4A4080573F36C92F1B40D0031F8315CD4A40C05DC136E2191B40D0031F8315CD4A40805B94D920031B4008240C0396CC4A40401A355F25FF1A4000BEDBBC71CC4A4000CCD1E3F7E61A40F8E769C020CB4A4080D6A88768E41A40B0984A3FE1CA4A40C017080264E81A408854C37E4FCA4A4080C64FE3DEFC1A40B86E2EFEB6C74A40C05B94D920C31A4000CADFBDA3C84A408045B9347EB11A40E0A9F23D23C94A4000D48041D2A71A40488BC1C3B4C94A40C0703D0AD7A31A40B053E57B46CA4A404083C30B22A21A40D882177D05CB4A40C046EBA86AA21A40A87A32FFE8CB4A40001B3048FAA41A408087A2409FCC4A4040CCD1E3F7A61A40503A58FFE7CC4A4080035ABA82AD1A40605260014CCD4A40C02BBB6070FD1A40D809A1832ECF4A40008B6D52D1081B40606D37C137CF4A4080012D5DC1161B4010DC65BFEECE4A404038BA4A77371B40A8B6D4415ECD4A40C06ABB09BE391B40D0031F8315CD4A400103000000010000001000000000B2A19BFDC11B4000CD203EB0D54A40406211C30E931B40585260014CD54A40C0A4A2B1F6871B40B8B6D4415ED54A40C09F1B9AB2831B40607FBDC282D54A40404C361E6C811B4038327381CBD54A4080FDD7B969831B4008E5284014D64A40C03788D68A861B40001286014BD64A4040F0A65B76981B40788D2441B8D64A40C0B628B341C61B40D009A1832ED74A40C0A9F23D23411C40889C69C2F6D74A40406211C30E531C40B09B8BBFEDD74A408009DCBA9B571C40D8D38041D2D74A4080A148F7735A1C40908461C092D74A4080A148F7735A1C40306E15C440D74A40C09BC1DF2F561C402841B8020AD74A4000B2A19BFDC11B4000CD203EB0D54A4001030000000100000012000000C04069A851F81C40C88BDAFD2ADA4A404046EBA86AA21C40905D86FF74D94A40C0AB1F9BE4971C40A8C2D84290D94A4040CAA48636901C4010D9243FE2D94A40C0DE52CE178B1C40D8B837BF61DA4A40804C6DA9838C1C4010D061BEBCDA4A4000861DC6A48F1C40801EA33CF3DA4A4040D576137CB31C40080C040132DC4A400077BF0AF0CD1C40F8D5E3BED5DC4A4040E7FC14C7311D40080341800CDD4A40407E6E68CA4E1D40789FAA4203DD4A40405512D907591D4088397AFCDEDC4A4040977153035D1D40B8ECF483BADC4A40002DB64945631D4060F5F23B4DDC4A40C082C30B22621D4028DEC83CF2DB4A4080E4D9E55B4F1D40B0DDAF027CDB4A400091F469150D1D406055A18158DA4A40C04069A851F81C40C88BDAFD2ADA4A400103000000010000000E000000A0CF0D4DD9612040B0716F7EC3DC4A40208D9AAF923F204010D061BEBCDA4A40209F20B1DD3D204088992842EADA4A40401B4982703D2040A8B0524145DB4A40202FDE8FDB3F20408887A2409FDC4A40C082C30B2242204030ED0DBE30DD4A4040CDE50643452040B068ACFD9DDD4A40004F95EF19492040881B62BCE6DD4A40400AF5F41150204048499D8026DE4A4040E2AC889A58204030E44A3D0BDE4A40C0A7E331035D204030327381CBDD4A40C094490D6D602040101B498270DD4A40E079008BFC622040303B3602F1DC4A40A0CF0D4DD9612040B0716F7EC3DC4A4001030000000100000018000000806893C3277D1E40B8656B7D91E04A4000A01B9AB2831E4038F38FBE49DF4A4080634337FB831E406040DAFF00DF4A4080240C03967C1E4038F38FBE49DF4A4080E9245B5D6E1E40888461C092DF4A40C05512D907591E40D0D38041D2DF4A408090F469154D1E406037177FDBDF4A4080E1B19FC5121E40B8BC564277DF4A40C0DC2A88810E1E40805704FF5BDF4A4080A27A6B600B1E400809C38025DF4A4040C2FA3F87E91D4008BEDBBC71DC4A40001B3048FAE41D4028232E008DDC4A40C094490D6DE01D40D8031F8315DD4A40C04813EF00DF1D40B89509BFD4DD4A40802FDE8FDBDF1D40908D2441B8DE4A4000F0DDE68DE31D40D0D38041D2DF4A4000A8C5E061EA1D4000CADFBDA3E04A408045B9347EF11D40205C8FC2F5E04A4040CAA48636101E40D00F238447E14A400033384A5E4D1E40B05CA8FC6BE14A40809BC6F65A701E4028F911BF62E14A4080295C8FC2751E405873B9C150E14A40802634492C791E40E0A9F23D23E14A40806893C3277D1E40B8656B7D91E04A400103000000010000000F000000804E95EF19091F4050F833BC59E14A4000A69D9ACBAD1E40886649809AE04A4080DB2F9FACA81E4050465C001AE14A400018080264A81E40F8C01C3D7EE14A4000643E20D0A91E4030D8463CD9E14A4080035ABA82AD1E40301DACFF73E24A4000EFAB72A1B21E40901EA33CF3E24A408082C8224DBC1E40906308008EE34A4080A27A6B60CB1E40F02CCF83BBE34A40407D410B09381F40906308008EE34A40402CBB60703D1F40A8DDAF027CE34A4040A243E048401F40B8B0524145E34A40001286014B3E1F40901EA33CF3E24A4080944E24983A1F406834D6FECEE24A40804E95EF19091F4050F833BC59E14A400103000000010000000C000000E06ABB09BED92040D8F19881CAF64A40C04D637B2DD82040C8C43BC093F64A4020E6E8F17BD32040D8F19881CAF64A40409BC6F65AD020405873B9C150F94A4020301004C8D02040508BC1C3B4F94A40C0D03FC1C5D220408854C37E4FFA4A40C000193A76D82040E8AF743E3CFB4A4000F52D73BADC2040A8DDAF027CFB4A40E0CF0D4DD9E1204000C79E3D97FB4A40005C8FC2F5E82040B8B0524145FB4A404006820019EA2040C8FD9C82FCFA4A40E06ABB09BED92040D8F19881CAF64A400103000000010000001B000000C0DE52CE17EB2640D882177D05FB4A4000AE65321CE72640D8D03FC1C5FA4A40804B3B3597DB2640286211C30EFB4A4080737E8AE3D82640F8E769C020FB4A40605C8FC2F5C82640B07A32FFE8FB4A4060BB5F05F8C6264058431B800DFC4A40C08B868C47C12640A8716F7EC3FC4A40C0B2B5BE48C02640000341800CFD4A400009C38025BF2640E0CDFE40B9FD4A4000BC783F6EBF264008C45DBD8AFE4A40A021E4BCFFBF2640F8DB65BFEEFE4A40E0CF0D4DD9C12640808461C092FF4A40205A80B6D5C42640D800DE0209004B4000C4094CA7CD2640D8F71A82E3004B4040DF6B088EE326403035B401D8024B4000D48041D2E72640206211C30E034B40A0CCCCCCCCEC2640804B00FE29034B40206BD44334F22640804B00FE29034B40001077F52AFA2640881EA33CF3024B40202DCF83BBFB264000D061BEBC024B4000EC6AF294FD2640E006600322024B40C0A7E33103FD2640E00F238447014B40C01B62BCE6F52640E07FD6FCF8FD4A4000EE974F56F42640605260014CFD4A40407D5A457FF0264080423D7D04FC4A40A0A4897780EF2640F02CCF83BBFB4A40C0DE52CE17EB2640D882177D05FB4A4001030000000100000007000000805CA8FC6BE12B40504CDE0033034B4020240C0396DC2B400806820019024B40601D71C806DA2B405055A18158024B406054FEB5BCDA2B4000D061BEBC024B4000E3A7716FDE2B40886308008E034B4000261B0FB6E02B40B0622AFD84034B40805CA8FC6BE12B40504CDE0033034B400103000000010000000F0000008023F3C81F642140805182FE42054B40C053E57B46622140D888997D1E054B4000A8E331035D214088CC07043A054B40A0A148F7735A2140D8CDFE40B9054B4060E2AC889A582140109700FC53064B40200341800C55214090C9C6832D084B4020295C8FC255214030F911BF62094B40A05FE97C78562140588BC1C3B4094B40C0C98B4CC0572140583D997FF4094B4040C763062A5B21404855A181580A4B40C03E3C4B90612140004BE7C3B30A4B40A079008BFC6221405882FE428F0A4B402077D844666621403020ED7F80074B40000D36751E652140A8E3310395054B408023F3C81F642140805182FE42054B400103000000010000000B0000000020990E9D1627405037177FDB074B400051BD35B0052740B8AD11C138064B400051BD35B00527406028D2FD9C064B404021CB8289072740104E2844C0074B40A06DFC89CA0E274040D8463CD9094B40C05DDA70581227405882FE428F0A4B4020240C03961C2740A8A78FC01F0C4B4000E3A7716F1E274050707841440C4B40E0E5B0FB8E392740A8D72D02630D4B4080B950F9D7222740B0C2D84290094B400020990E9D1627405037177FDB074B400103000000010000004A000000C0DB2F9FAC002C4090B7CEBF5D084B4020295C8FC2352C40D0D38041D2FF4A4040F52D73BA5C2C4050F833BC59F94A40E06E2EFEB65F2C40D87C957CECF84A40E0C3094CA76D2C40805704FF5BF74A4040E6E8F17B732C40B877F17EDCF64A4020DC2A88816E2C40604CDE0033F34A40400AF5F411702C40204DBC033CEF4A40A0F4143944642C40889C69C2F6EF4A40C0CF0D4DD9612C40D000DE0209F04A40C0E7154F3D2A2C4008D3A23EC9EF4A40C085048C2E172C40600ABABDA4EF4A400015C78157132C40885704FF5BEF4A40606002B7EE0E2C40082A8E03AFEE4A406023F3C81F042C40585260014CED4A4020B1A6B228FC2B40A0716F7EC3EC4A40400473F4F8E52B4008DFA63FFBEB4A40200F45813EC92B4050FEB5BC72EB4A40E08B868C47C12B40D0C77C40A0EB4A40A0601BF164A72B40D05B3CBCE7EC4A40A0067FBF98A52B40D80F238447ED4A400077D84466A62B408096E7C1DDED4A40C06BED7DAAAA2B402841B8020AEF4A408015E0BBCDAB2B40B85626FC52EF4A4080035ABA82AD2B400821CB8289EF4A4020E3A7716FBE2B400818080264F04A40E02CCF83BBDB2B40B8984A3FE1F24A40E09D7E5017E12B40E82478431AF54A404064575A46EA2B40986B0A6476F84A4020F65E7CD1F62B40C8DD04DF34FB4A4040E84B6F7F062C40988026C286F94A4000AF2479AE0F2C40F0CD1ABCAFF84A40E075FD82DD182C4070F7E461A1F84A40E0F4DA6CAC1C2C403805A4FD0FFE4A4060B1DCD26A182C40984ECFBBB1004B40A00644882B072C40F0B5847CD0014B406000362042042C4030EA93DC61034B40202384471BFF2B402026E1421E054B406002D4D4B2F52B40385019FF3E074B402052D4997BE82B40806F0C01C0074B4040C0CC77F0DB2B402887C1FC15084B40A00D881057D62B402872A59E05074B40C0AD49B725DA2B40E069F981AB044B40206211C30ED32B4058793BC269034B40C02975C938CE2B40B874B0FECF014B406015E0BBCDCB2B40080F45813E014B4040E2AC889AB82B40D0D38041D2FF4A4080C554FA09B72B40D800DE0209004B4040CDE50643A52B40580DFB3DB1044B4080A9BBB20B9E2B40007C629D2A094B40008A592F86A22B40F85F3C83860C4B40E068C70DBF9B2B40786C3D43380E4B40000D36751E852B4008D9243FE2114B4020D6A88768842B40306BD44334124B40006C06B820832B40E8AF743E3C134B40E0703D0AD7832B40B8A78FC01F144B4020895E46B1842B40D8BEB9BF7A144B4020AE65321C872B40000341800C154B4020068200198A2B4000A0C37C79154B40A017EFC7ED8F2B40801B62BCE6154B40605DC136E2992B40D0FA5B02F0154B4000B3B5BE48A02B40B0E3310395154B4040B950F9D7A22B40D0031F8315154B4040DF6B088EA32B40B0716F7EC3144B40809E077767A52B409015E0BBCD134B40202A8E03AFA62B405855A18158124B4020A5A2B1F6A72B40508BC1C3B4114B408074B0FECFA92B40E0A9F23D23114B40007A19C572BB2B400048A643A70D4B4060F23E8EE6C82B40887286E28E0B4B40406C5CFFAED72B40A8E1067C7E0A4B40206E14596BE02B40989944BDE0094B40C04D7E8B4EEE2B4018F6B4C35F094B40C0DB2F9FAC002C4090B7CEBF5D084B4001030000000100000008000000A0978A8D79F52540582E54FEB5304B40E01A498270FD2540D8F71A82E3304B40C04E95EF19092640D0CABDC0AC304B40E0CABDC0AC082640587C7C4276304B4020FBAF73D3062640B0B393C151304B40C03E3C4B90012640504F1F813F304B40A0737E8AE3F825401018080264304B40A0978A8D79F52540582E54FEB5304B4001030000000100000009000000E068ACFD9D752940D0B5F63E55354B4080656B7D9160294028ED0DBE30354B40E0EA56CF495F2940580438BD8B354B40405A80B6D564294058FB743C66364B40C0D38041D2672940D876137CD3364B4020356090F4692940508E0244C1364B40E0ED974F5674294058499D8026364B40C0129F3BC1762940A068ACFD9D354B40E068ACFD9D752940D0B5F63E55354B4001030000000100000014000000000F45813EC9214000E869C0203B4B40E0CCCCCCCCAC214030E78BBD173B4B40403F373465A72140D8AF743E3C3B4B4080DF6B088EA32140806308008E3B4B4000AAF23D23A1214060431B800D3C4B408018213CDAA02140E0BEB9BF7A3C4B408018213CDAA02140A06E2EFEB63F4B40C08B868C47A12140286552431B404B40E053E57B46A221400018080264404B4040D9E90775B9214028E78BBD17434B40809885764EBB2140E8AF743E3C434B4000CA8B4CC0D72140584CDE0033434B40A0069B3A8FE22140801EA33CF3424B408015E0BBCDEB2140301DACFF73424B40E09BDF30D1E82140B8AAD0402C414B4060AA0B7899D92140580DFB3DB13C4B40C01B62BCE6D52140E87954FCDF3B4B40A0ED974F56D42140582B137EA93B4B40809BC6F65AD02140089A417C603B4B40000F45813EC9214000E869C0203B4B4001030000000100000019000000A0E1934E24A02640E0A6B1BD16344B40206E15C44047264050431B800D344B4020BC783F6E3F2640E0A6B1BD16344B40603A3DEFC60A2640B8E9414129384B40200D36751E05264060465C001A394B408023F3C81F04264030F911BF62394B40C079008BFC02264078A2EBC20F3A4B40C02CB6494503264030E78BBD173B4B4080116DC7D4052640080341800C3D4B4000C2FA3F87092640E876137CD33E4B40C07F828B150D264038EACC3D24404B40809BC6F65A10264010E2E7BF07414B40805FE97C781626406055A18158424B40C0A9F23D23212640A059677C5F444B40A02CB64945232640D8BEB9BF7A444B40201286014B5E26405082FE428F424B4020B6F63E55752640786649809A404B40A000193A7678264088C9C6832D404B40607156444D7C2640D0BB783F6E3F4B40805A99F04B7D26401009C380253F4B4080FBE428408C2640C0BF7ADCB73A4B40605DC136E2992640D8C43BC093364B40404B3B35979B2640D87FD6FCF8354B40002FDE8FDB9F2640F8BDDBBC71344B40A0E1934E24A02640E0A6B1BD16344B40010300000001000000170000002015C78157532140286E15C4403F4B4060634337FB43214030DB87BCE53E4B40404B3B35973B2140B0A44E40133F4B40A0AA0B7899392140586D37C1373F4B40C000193A76382140B8BC5642773F4B40C0AA24B20F322140E0A9F23D23414B40A020B248132F2140283E7782FD414B40602975C9382E2140884B00FE29434B4040AD4CF8A52E2140906308008E434B4040861DC6A42F2140C8F4D901D7434B40406211C30E3321404870784144444B40209CDF30D14821408896E7C1DD454B40A0C2137AFD61214028DB87BCE5464B4000D48041D267214028DB87BCE5464B40E0D58F4DF26B21405028D2FD9C464B4020A7B1BD166C2140A8AD11C138464B40C091088D606B214078A86DC328444B40C06BED7DAA6A21407815E0BBCD434B40C053E57B46622140885D86FF74414B400038A110015F2140786649809A404B40007156444D5C2140286552431B404B408009DCBA9B572140B8BC5642773F4B402015C78157532140286E15C4403F4B40010300000001000000140000000051BD35B0252A40F8C35DBD8A3E4B40E0B2B5BE48202A40806308008E3B4B402009C380251F2A4060431B800D3C4B40C0955D30B81E2A40A89ECC3FFA3C4B40E0EA56CF491F2A4088AEEFC3413E4B4040261B0FB6202A401000000000404B408045B9347E312A4000C79E3D974B4B40A0E4D4CE30352A40885A457F684C4B40802FF7C951382A4008D6E3BED54C4B40E0B0A6B2283C2A40306893C3274D4B4040C422861D462A40D0B5F63E554D4B40C0622AFD844B2A40D0B5F63E554D4B40C0035ABA824D2A40306893C3274D4B40406002B7EE4E2A40503A58FFE74C4B4060A48977804F2A4008240C03964C4B4040013274EC502A40D8D03FC1C54A4B4040013274EC502A40E0B837BF614A4B4060B3CEF8BE382A4030F6D03E56444B408009DCBA9B372A4088423D7D04444B400051BD35B0252A40F8C35DBD8A3E4B40010300000001000000930000008023F3C81FC42A40E073D2FBC6514B400000732D5AC82A40C09ACAA2B04D4B40C0D13AAA9AD02A404825AE635C4B4B40809A22C0E9DD2A4038ADDBA0F6494B40A0545227A0E92A4078B8C83D5D494B406020EC14ABF62A401836035C90494B4060B7B3AF3C082B4038B7ED7BD4494B4000861DC6A42F2B403835B401D84A4B40607156444D3C2B40D882177D054B4B40A0A7CAF78C442B40E0FD9C82FC4A4B40406E15C440472B4080992842EA4A4B40E0AF743E3C4B2B405807793D984A4B40A0BC9179E4572B408818213CDA484B4060A148F7735A2B4020172AFF5A484B4060C763062A5B2B40D800DE0209484B40002DCF83BB5B2B40081B498270454B402007B474055B2B4078A86DC328444B40E06ABB09BE592B40009A417C60434B40C085048C2E572B402835B401D8424B40C0978A8D79552B40A86BED7DAA424B40E0622AFD844B2B40283E7782FD414B40606552431B482B4008274D83A2414B40C06DFC89CA2E2B40B0AD11C1383E4B40E022DA8EA92B2B4030327381CB3D4B40E0921CB0AB292B40286893C3273D4B40206552431B282B4010BEDBBC713C4B4000AE65321C272B40484CDE00333B4B406030F14751272B40C04604E3E03A4B4000D48041D2272B4000068200193A4B40202C9D0FCF2A2B40B0E0F08288384B4000B1A6B2283C2B40082DCF83BB334B40C0CDFE40B93D2B40B8622AFD84334B40406C06B820432B40F814C78157334B40C01EA33CF34A2B40109A417C60334B4000B6F63E55552B40A8DDAF027C334B40E00F77F52A5A2B402814E97E4E334B4000F2ECF2AD672B40908AE3C0AB314B40C0E7154F3D6A2B40B0AAD0402C314B40C0035ABA826D2B4020172AFF5A304B40C08EC70C54762B40381A6B7F672D4B40A0B5DD04DF7C2B40D0B837BF612A4B4000AD33BE2F762B403814E97E4E234B4000BFB9BF7A742B4000E869C020234B400069C537146E2B40C8D03FC1C5224B40E0A6B1BD166C2B402835B401D8224B40A023F3C81F642B40B87A32FFE8234B40802CB64945632B40080C040132244B4080A7CAF78C642B40A859677C5F244B40A0D58F4DF26B2B40385FD04202264B40A0BFD2F9F06C2B4050465C001A294B40A00C1D3BA86C2B4000C11C3D7E294B40C0D8D0CDFE602B40F0230C03962C4B4000E3A7716F5E2B40500DFB3DB12C4B4080F4143944042B40D87954FCDF2B4B40E053E57B46022B40F82CCF83BB2B4B40409BC6F65AF02A40B0A10DC0062A4B40C07C410B09B82A40904B00FE29234B40E01F990E9DB62A40881EA33CF3224B4020295C8FC2B52A405007793D98224B4040C554FA09B72A40080F45813E214B4060FA96395DCE2A40583D997FF4214B4060C1E10511D12A40583D997FF4214B4020C87C40A0D32A4010D9243FE2214B4080C554FA09D72A40905D86FF74214B40A07C410B09D82A40A0AAD0402C214B4040D026874FDA2A40604F1F813F204B40604B3B3597DB2A40606D37C1371F4B4000FEF0F3DFDB2A40B85FE97C781E4B40C0F755B950D92A40901B62BCE61D4B404023DA8EA9CB2A40885A457F681C4B40000F45813EC92A4028F6D03E561C4B40206C06B820A32A40E0D38041D21F4B40400F45813E892A4008CADFBDA3204B4020DF6B088E832A40F82F1004C8204B40002FDE8FDB7F2A4088457EFD10214B40A017EFC7ED4F2A4080A52C431C274B4000E3A7716F3E2A408854C37E4F2A4B4020240C03963C2A4008D061BEBC2A4B4080BEA085043C2A4060FEB5BC722B4B40207156444D3C2A40B07A32FFE82B4B40A082C30B22422A4078A52C431C2F4B40C079008BFC422A40B0BC5642772F4B4040895E46B1442A40500ABABDA42F4B4020E9297288482A40A09B8BBFED2F4B40C0035ABA824D2A40D800DE0209304B4040CAA48636502A40D800DE0209304B40202A8E03AF662A40B06E2EFEB62F4B40A0F1D3B8376F2A40785704FF5B2F4B40406BD44334722A4030F38FBE492F4B4080B3CEF8BE782A40888461C0922F4B40C0116DC7D4852A40587C7C4276304B40E0D38041D2872A40D0CABDC0AC304B40205C8FC2F5882A40385C8FC2F5304B40A099D2FA5B7A2A40289C4F1DAB344B4000F0DE51636A2A40F893313ECC364B40204B21904B542A4078067FBF98374B40000341800C752A40B0622AFD843B4B4040B16A10E6762A40A86B5F402F3E4B40204C1938A0552A4090DB1324B6414B4060826F9A3E4B2A4070C47762D6454B40E05FE97C78762A40888D2441B8464B406068E89FE0822A40304487C091464B4040EEB1F4A19B2A40683D27BD6F464B4040882B67EFAC2A40C03159DC7F484B40E04BA7751BBC2A40B83176C24B4A4B40402FA3586EC12A4008BA84436F474B4000FB062637CA2A40D849EF1B5F454B40A0C6A01342D72A404853E8BCC6424B40C078B29B19E52A400067D47C953E4B40C01324B6BBF72A4088EA7420EB3D4B4080E3310395012B402069A9BC1D3F4B4040C573B680082B4090DB1324B6414B4000E7E3DA50012B40D0B5DAC35E464B40A05298F738EB2A40D040D7BE80464B4080A4FACE2FDA2A4060ACE122F7484B40C01D6FF25BC42A4098B08BA2074A4B4040315D88D5BF2A4018963FDF164E4B4080614F3BFCB52A40581630815B4D4B40209CDF30D1A82A405807793D984A4B402038A110019F2A4020F911BF62494B4060DB148F8B922A400845BA9F53484B408069C36169902A401848348122484B4040261B0FB6802A4008BB9A3C65474B40405FD042027E2A4008BB9A3C65474B40E05A99F04B7D2A40888461C092474B40606211C30E732A40E8A9F23D23514B40606211C30E732A40883CBB7CEB514B40E0989EB0C4732A409054C37E4F524B4000DC114E0B762A4090992842EA524B40E05A99F04B7D2A4060431B800D544B4040FBAF73D3862A40E0B5F63E55554B4040AD4CF8A58E2A40D8FA5B02F0554B408068ACFD9D952A40E0AC33BE2F564B400083DC4598BA2A40783FFCFCF7564B4060A7CAF78CC42A401009C38025574B40802634492CD92A4010BB9A3C65574B4000B1A6B228DC2A40B05626FC52574B40C0E1934E24E02A405040DAFF00574B40A0B950F9D7E22A408860C77F81564B40406C06B820E32A4050499D8026564B40A053E57B46E22A40A89509BFD4554B40207A19C572DB2A40B8BF97C283544B40A02FF7C951D82A40D8A6B1BD16544B40C091088D60CB2A40B8DDAF027C534B40E0A4A2B1F6C72A4030E78BBD17534B40809E077767C52A405882FE428F524B408023F3C81FC42A40E073D2FBC6514B40010300000001000000120000004083DC4598BA20409060C77F814E4B40000341800CB52040A8DA6E826F4E4B4000EFAB72A1B2204000C45DBD8A4E4B40A0F1D3B837AF204010DC65BFEE4E4B4040356090F4A92040E0D38041D24F4B4060E2AC889A98204068F5F23B4D544B40A0C554FA09972040603A58FFE7544B40A0129F3BC1962040E0B5F63E55554B4080BC9179E497204038E44A3D0B564B40401B4982709D2040809C69C2F6574B40E06E2EFEB69F20405801F73C7F584B40A0A4897780AF20406007793D985A4B40606211C30EB32040D0FD9C82FC5A4B40C0E4D4CE30B5204028E78BBD175B4B40A05626FC52B72040801EA33CF35A4B4000CDCCCCCCCC204038172AFF5A504B40804278B471BC20403829B000A64E4B404083DC4598BA20409060C77F814E4B4001030000000100000016000000E0C64ACCB3222140A06E2EFEB6574B40A0656B7D91202140908461C092574B40C01D71C806FA2040104E2844C0574B40E0311F10E8F42040B09B8BBFED574B402069C53714CE2040306BD443345A4B40C0AF743E3CCB2040A86BED7DAA5A4B40C0AF743E3CCB2040009A417C605B4B40200AF5F411D02040A8B6D4415E5D4B40E0C77C40A0D32040D8AC33BE2F5E4B40801D71C806DA20406040DAFF005F4B4040B08D78B2E3204000D3A23EC95F4B40E059677C5FEC2040504F1F813F604B40E0989EB0C4132140D0CABDC0AC604B40001077F52A1A21405001F73C7F604B4060B08D78B2232140D800DE0209604B4020356090F429214058853FC39B5F4B40A091088D602B2140805704FF5B5F4B40803BFBCA832C214078A52C431C5F4B40207D5A457F30214030F6D03E565C4B40604E7CB5A330214028DEC83CF25B4B40801A3048FA242140584F1F813F584B40E0C64ACCB3222140A06E2EFEB6574B400103000000010000003B060000A0978A8D79F52540582E54FEB5304B40200F45813EE9254030E109BDFE304B40E0F0D8CF62E92540D0CABDC0AC304B40A01EA33CF3EA2540504F1F813F304B40A0BFD2F9F0EC2540386552431B304B4080F755B950F9254058853FC39B2F4B40E0CABDC0AC082640785704FF5B2F4B40E0D24ECDE5162640C05626FC522F4B4060116DC7D425264080C9C6832D304B4080CAA4863630264078992842EA1A4B40609BC6F65A30264008068200191A4B4060861DC6A42F2640E00F238447194B4000D9D0CDFE2026406040DAFF00174B40404278B4711C26405076FA415D164B400077D84466C6254028DEC83CF20B4B40A08B868C47C12540009A417C600B4B40E05A99F04BBD2540604CDE00330B4B4040B60F79CBAD2540A8622AFD840B4B402077D84466A62540002DCF83BB0B4B4080D026874F9A254048FEB5BC720B4B40E017080264882540E0D38041D2074B40A023F3C81F8425403829B000A6064B4080069B3A8F822540D87FD6FCF8054B40A03579CA6A822540D888997D1E054B40802CB64945832540885A457F68044B4020FBAF73D38625403035B401D8024B4000B937BF618A254000274D83A2014B40407497C459912540D08558FD11004B4000BFB9BF7A942540500ABABDA4FF4A40201077F52A9A2540686D37C137FF4A40C01A3048FAA42540386E15C440FF4A40406684B707B92540686D37C137FF4A40E0CDFE40B9BD2540883FFCFCF7FE4A40A0069B3A8FC22540B0DA6E826FFE4A4040A7CAF78CC425408896E7C1DDFD4A40A01A3048FAC42540507FBDC282FD4A404021CB8289C725406007793D98FA4A4020A5A2B1F6C72540508BC1C3B4F94A40001077F52ABA2540B0B6D4415EF54A406043FF0417A32540785AB741EDF14A40E088450C3BCC2540E009A1832EF74A40E0C726F911CF2540D882893F8AFA4A40C076BF0AF0ED254000A0C37C79FD4A40402A8E03AF06264008BB9A3C65FF4A4020FC8A355C1C2640283B3602F1004B40207D5A457F302640D0EE5701BE014B402083DC45985A2640A8A10DC006024B40A05A99F04B5D2640603D997FF4014B40C0D8D0CDFE60264028266F8099014B40A03579CA6A62264068F833BC59014B4040895E46B1642640686D37C137FF4A40E0A7E331037D264000CADFBDA3F84A40E0BB783F6E7F264038EACC3D24F84A40E0A9F23D23812640A89B8BBFEDF74A4000FBAF73D3862640E0BB783F6EF74A40E0AF743E3C8B2640286E15C440F74A402015C78157D32640D0CDFE40B9F54A40E0AC33BE2FF6264080992842EAFA4A40A0BEA08504FC264078A52C431CFF4A40E0230C0396FC26402020ED7F80FF4A40205C8FC2F5082740D8A6B1BD16044B40603BFBCA830C274010BEDBBC71044B40A06DFC89CA0E2740885A457F68044B40A0D24ECDE5162740089A417C60034B4080BEA085041C274050FEB5BC72034B40A0116DC7D425274080A86DC328044B40209CDF30D12827409087A2409F044B4000B3B5BE48402740808AE3C0AB094B40A053E57B464227409054C37E4F0A4B4000C74ACCB342274030E78BBD170B4B40A08B868C47412740002DCF83BB0B4B40C051D66F263E274028232E008D0C4B40E0F42D73BA3C274030ED0DBE300D4B40A05A99F04B3D2740B8E33103950D4B40C018213CDA402740B8DA6E826F0E4B40203F373465472740B86E2EFEB60F4B40001077F52A5A2740584CDE0033134B4000EC6AF2945D2740906308008E134B40600F5EBBB46127409015E0BBCD134B404048FAB48A662740B07A32FFE8134B4000965D30B87E274080423D7D04144B40A0737E8AE3F82740D0AC33BE2F164B40A03579CA6A422840587C7C4276184B40603F373465A72840580DFB3DB1244B40C017EFC7EDAF28407848BF7D1D264B40E08EC70C54B628403020ED7F80274B40E06E2EFEB6DF284080A2EBC20F324B40E0DB114E0BF628408018213CDA384B4080B60F79CB0D2940580DFB3DB13C4B40C0716F7EC314294010D061BEBC3A4B40A0BB5F05F846294028DE3AFF76394B4080BEBB95255229409835EA211A394B4000BD8DCD8E5C2940F84E05DCF3384B40609885764E9B294008CADFBDA3384B40E04E95EF19C92940282F3201BF384B4000B4E73235D129406001F73C7F384B4000D34ECDE5D629400821CB8289374B40A0737E8AE3D829405840DAFF00374B40A02634492CD929403829B000A6364B4080E2AC889AD8294070AEEFC341364B40C038BA4A77D72940D87FD6FCF8354B4040295C8FC2D529406831957EC2354B40A0B950F9D7C22940B0ECF483BA344B40C0B14CBF44842940A0E733A0DE344B4000DFFDF15E75294010AB3FC230364B404092205C016D2940D800FA7DFF364B40A031CD74AF632940D800FA7DFF364B40E0F01131255A29405804E3E0D2354B4020037B4CA4542940A8B393C151344B40E022DC6454492940B09ECC3FFA344B40C0FA96395DEE2840B86BED7DAA324B40C00C1D3BA8EC2840001E8A027D324B40C01D71C806DA2840B8E9B303AE2F4B40E02CCF83BBBB2840805704FF5B274B40A014AE47E1BA28405040DAFF00274B402083DC4598BA284010C45DBD8A264B40A05A99F04BBD2840883CBB7CEB214B4000965D30B8BE2840808AE3C0AB214B40A09E077767C528408018213CDA204B4080AD4CF8A5CE2840889C69C2F61F4B402015C78157D32840A86E2EFEB61F4B40C0703D0AD7E3284050853FC39B1F4B4020A5A2B1F6E728405037177FDB1F4B40A0F0D8CF62E92840306552431B204B4020F2ECF2ADE72840E8B2B5BE48204B40C0BB783F6EDF28406001F73C7F204B404054FEB5BCDA2840282F3201BF204B40A0DB114E0BD6284030F911BF62214B40004C546F0DD42840583D997FF4214B4020C87C40A0D32840004BE7C3B3224B4080716F7EC3D42840B8DDAF027C234B40C05626FC52D72840B0BF97C283244B404054FEB5BCDA2840281A6B7F67254B40C0BEB9BF7AF4284028F04E3E3D2A4B40C085048C2EF7284008D061BEBC2A4B4040D9E9077519294060499D80262E4B4000356090F42929400809C380252F4B40202FDE8FDB3F2940B06E2EFEB62F4B40E0EB6AF2945D294030EACC3D24304B400021CB8289872940B8E9B303AE2F4B408088450C3B0C2A40804B00FE29334B4080D026874F3A2A408015E0BBCD234B40207156444D3C2A40D8AF743E3C234B4040C2137AFD412A40004BE7C3B3224B40C0CCCCCCCC6C2A40604F1F813F204B40207D5A457F902A40001286014B1E4B4020E6E8F17B932A40B09509BFD41D4B40E082C30B22C22A40009700FC53164B40606552431BE82A4028232E008D0C4B4000F1D8CF62E92A4060F5F23B4D0C4B40A068ACFD9DF52A400815C781570B4B40606893C327FD2A40C882177D050B4B40002FDE8FDBFF2A40C882177D050B4B4040295C8FC2F52A40903FFCFCF70E4B40E0DB114E0BF62A40B05626FC520F4B4000CEFE40B9FD2A403838F581E40F4B40C074B0FECF692B40801B62BCE6154B408059677C5F6C2B40D0FA5B02F0154B4000573F36C96F2B40E0CDFE40B9154B40C07A32FFE8932B4030E44A3D0B0E4B4080D9E90775992B40604CDE00330B4B40A0B3CEF8BE982B404855A181580A4B40401E8A027D922B4058FB743C66064B40E09BDF30D1A82B4078AEEFC341FE4A40E0FDF0F3DFBB2B40D0F4D901D7F34A40E00F77F52ABA2B40E0C77C40A0F34A4060D6A88768A42B4090C9C6832DF04A40201B4982709D2B40E0AC33BE2FEE4A4040F52D73BA9C2B4038327381CBED4A40201B4982709D2B4010A0C37C79ED4A4000B3B5BE48A02B40100C040132EC4A40C0DE52CE17EB2B40584CDE0033E34A4000EFAB72A1722C40588BC1C3B4D94A4020965D30B87E2C4078ABAE4335D94A40C0D38041D2872C406073B9C150D94A4020CA6DFB1E8D2C4070DFA3FE7AD94A40C0C43BC0939E2C4080A52C431CC74A40E06C1FF296D32C40A8D72D0263AB4A400015C78157D32C40783FFCFCF7A64A402068EA758BC82C40301DACFF73924A40C0703D0AD7C32C4030DB87BCE58E4A40A03E3C4B90C12C40505260014C8D4A4000BFB9BF7AB42C40588E0244C1864A40A0F1D3B837AF2C406831957EC2854A408017618A72992C40780F4240BE824A404015C78157932C4080A2EBC20F824A40C0E4D4CE30752C40608E0244C17E4A4000274D83A2712C4060FB743C667E4A404048FAB48A662C4028E44A3D0B7E4A40805FE97C78562C40F8230C03967C4A40A03BFBCA834C2C40E8AF743E3C7B4A40202C9D0FCF4A2C405082FE428F7A4A40208A592F864A2C40F8058200197A4A40E059677C5F4C2C40A8DA6E826F6E4A4040A7CAF78C642C4000E2E7BF07694A40A0B60F79CB6D2C40B8E0F08288684A4020EFAB72A1B22C40804E417E36604A40E0737E8AE3B82C40805704FF5B5F4A40A0F4143944C42C40500438BD8B5D4A4020809BC58BE52C40A8DA6E826F564A4020E6E8F17BF32C40082DCF83BB534A40C0129F3BC1F62C402814E97E4E534A40C079008BFC022D400806820019524A40E0F0D8CF62092D4000274D83A2514A40A02975C9380E2D40B05CA8FC6B514A40C02FF7C951182D4010CADFBDA3504A40208D9AAF921F2D40A09B8BBFED4F4A40600C1D3BA82C2D40009700FC534E4A40A0B81B446B352D4020205F42054D4A4040FBAF73D3462D40A8C2D84290494A40E0D38041D2472D40D00F238447494A400018080264482D40285C8FC2F5484A4020B728B341462D40600ABABDA43F4A40C0116DC7D4452D40E0F19881CA3E4A402009C380253F2D40E0031F83153D4A4060BFD2F9F02C2D40B8E0F08288384A40E0E7154F3D2A2D40D08558FD11384A40803579CA6A222D40F820CB8289374A40001286014B1E2D40905704FF5B374A4080737E8AE3182D4028DB87BCE5364A406009DCBA9B172D402829B000A6364A40A05FE97C78162D405076FA415D364A40206211C30E132D40E0A6B1BD16344A4020274D83A2112D4080992842EA324A4020274D83A2112D409081204086324A40C0A4A2B1F6272D4038ED0DBE30254A40A074B0FECF292D409087A2409F244A4020B4E73235312D4008E869C020234A40E04B546F0D342D40084BE7C3B3224A4020573F36C94F2D405073B9C150214A4000287FF78E622D40B0656B7D91204A404018080264682D40909C69C2F61F4A40C015E0BBCD6B2D40686D37C1371F4A40C050A4FB396D2D406828D2FD9C1E4A4020E275FD82852D40D89DEE3CF1084A40009BADBCE46F2D40485FECBDF8F84940603ECBF3E06E2D40189C6C0377F8494080069B3A8F622D40386211C30EF34940E02EDE8FDB5F2D405882FE428FF249408015E0BBCD4B2D40883FFCFCF7EE494000B937BF614A2D40808D2441B8EE4940E0D38041D2472D404876FA415DEE4940207A19C5723B2D40605260014CED494000295C8FC2352D4080423D7D04EC494020321F10E8342D40602B137EA9EB494040E6E8F17B332D40B8B915C26AEA4940E0D03FC1C5322D40D8A9F23D23E9494020A26131EA322D4008301004C8E84940A068ACFD9D352D40F820CB8289E74940E0C77C40A0532D40805182FE42DD4940C0978A8D79552D40580DFB3DB1DC4940809885764E5B2D4058793BC269DB4940A09E077767652D40F8D8243FE2D9494060DC2A88816E2D408018213CDAD84940E0311F10E8742D40D000DE0209D8494000C74ACCB3822D406831957EC2D54940A02CB64945832D40081B498270D54940E0703D0AD7832D40885A457F68D449402051BD35B0852D406040DAFF00CF494080116DC7D4852D4080AEEFC341CE4940000D36751E852D40A8B6D4415ECD4940A053E57B46822D40905A457F68CC49406069C537146E2D40902F682101C7494080737E8AE3782D4010C79E3D97C34940007156444D7C2D40484CDE0033C3494000CDCCCCCCAC2D40E0D38041D2BF49408009DCBA9BD72D4008CD203EB0BD494040BB5F05F8E62D4028F6D03E56BC494000E9297288E82D40B0A78FC01FBC4940C0F0D8CF62E92D40E0F4D901D7BB494040E6E8F17BF32D40089D82FC6CB849406044A2D0B2F62D4080A52C431CAF49404045B9347EF12D40D8FA5B02F0AD49404045B9347EF12D40587FBDC282AD494000DC114E0BF62D403814E97E4EAB4940E0737E8AE3F82D400006820019AA4940C0CDFE40B9FD2D4060465C001AA94940801A3048FA042E408021E4BCFFA7494040D367075C0F2E40D8CDFE40B9A5494000EFAB72A1122E4030232E008DA44940A07A32FFE8132E40D0D03FC1C5A24940207D5A457F102E405028D2FD9C9E4940206893C327FD2D40D009A1832E8F4940E0E4D4CE30F52D40A8A10DC0068A4940C06DFC89CAEE2D40B077F17EDC8649408076BF0AF0ED2D408060C77F81864940E0F42D73BADC2D40B8B393C15180494020B0743E3CCB2D405834D6FECE7A4940E0D38041D2A72D40E0C1FA3F87714940200473F4F8A52D40D8F71A82E37049406077D84466A62D4080C9C6832D704940606552431BA82D40E076137CD36E49406077D84466A62D40A868ACFD9D6D4940202DCF83BB9B2D4008E2E7BF0769494080A148F7739A2D407893A641D1684940A0035ABA828D2D40302F3201BF68494000E9297288882D40302F3201BF6849404054FEB5BC7A2D40885D86FF7469494060A48977806F2D40D0066003226A4940C0C3094CA74D2D4000BEDBBC716C4940E01186014B3E2D40507FBDC2826D4940C0A7E331033D2D405031957EC26D4940804278B4713C2D4000E52840146E4940802CB64945432D4000301004C8704940C00F5EBBB4412D40B8AD11C13876494040F86EF3C6312D405831957EC27D494080FDD7B969232D40602E54FEB5804940002DCF83BBFB2C40480DFB3DB1844940C0C43BC0939E2C40B077F17EDC8649400007B474059B2C40E0C43BC093864940006BD44334922C4038D505BCCC84494000A5A2B1F6872C4088ABAE4335814940A0B950F9D7822C4080A52C431C7F494080069B3A8F822C40608E0244C17E4940406C06B820832C40B8DA6E826F7E4940A0B08D78B2A32C4078ABAE433579494060CDE50643A52C4028E109BDFE78494000240C0396BC2C40B0E9B303AE77494000BC783F6E9F2C40D07C957CEC70494020861DC6A44F2C40B07A32FFE86B4940E05A99F04BFD2B4028172AFF5A684940802634492CF92B4038EACC3D246849408020B24813CF2B40080341800C654940C02975C938CE2B40A0ECF483BA644940A05758703FC82B40A8B915C26A62494080BC9179E4772B40580438BD8B5D494060129F3BC1562B40483A58FFE75C4940801A3048FA442B4010BEDBBC715C494020068200192A2B406034D6FECE5A4940200341800C152B40D8B2B5BE4858494020809BC58B052B40B8B052414553494000A5A2B1F6072B406834D6FECE52494040068200190A2B40B053E57B46524940E0B837BF610A2B40783CBB7CEB514940E0F0D8CF62092B4008274D83A251494080B81E85EBF12A4008A0C37C794D494080035ABA82ED2A40F8D5E3BED54C4940002C9D0FCFEA2A4088397AFCDE4C4940008D9AAF92DF2A4008A0C37C794D4940E0E4D4CE30D52A4048499D80264E494020C87C40A0D32A405876FA415D4E4940800F5EBBB4C12A40B8656B7D91504940A0656B7D91802A40A8622AFD844B49404038A110017F2A403814E97E4E4B4940E0D03FC1C5722A40E8B2B5BE4848494040F86EF3C6712A403020ED7F8047494040F86EF3C6712A4088A52C431C47494020EFAB72A1722A40A8DA6E826F46494020EFAB72A1722A40285FD04202464940E0AA24B20F722A400848A643A7454940601EA33CF36A2A40386211C30E434940206552431B682A40D08BDAFD2A424940C0CF0D4DD9612A40507C7C4276404940209F20B1DD5D2A40604F1F813F40494000CBBDC0AC282A40004E2844C03F4940C0921CB0AB092A40886649809A384940200473F4F8052A406037177FDB37494020FEF0F3DFFB2940881B62BCE6354940609FE40E9BF82940500438BD8B354940402A8E03AFE629408887A2409F34494020261B0FB6E0294030F6D03E563449408068ACFD9DD52940D8031F8315354940A00C1D3BA8CC2940089700FC53364940C0AF743E3CCB294010C45DBD8A364940C0AC33BE2FB62940886649809A384940C0921CB0ABA92940A874B0FECF394940A02CB64945A32940D88BDAFD2A3A49408032384A5E8D294078457EFD10394940E0F0D8CF628929408818213CDA384940205FD042027E2940580ABABDA4374940A04D637B2D782940E876137CD3364940E0C98B4CC0572940B8ECF483BA3449402009C380253F2940B8ECF483BA34494040F52D73BA3C2940B8ECF483BA344940C0C1FA3F87092940A8B915C26A32494000B728B34106294088A2EBC20F324940C0737E8AE3F82840104E2844C02F4940C0A6B1BD16CC2840808461C092274940002A8E03AFA62840A8AD11C1381E4940609E077767A52840381DACFF731A49402045B9347E912840786308008E1B4940C0FA96395D8E2840A859677C5F1C4940C0F41439446428400009C38025274940207156444D5C28404801F73C7F2849406054FEB5BC5A2840582E54FEB528494060027FF8F92F2840C070E7C248294940E09E20B1DD3D284058853FC39B2749400009C380253F2840905704FF5B274940202C9D0FCF6A284000CD203EB0154940C091088D606B2840A89ECC3FFA144940C0DE52CE176B284028232E008D14494060A7CAF78C642840B0B915C26A124940C02CB64945632840888AE3C0AB114940C0069B3A8F6228408018213CDA10494020AAB8718B69284040C5AA41980D494020A5A2B1F6872840587C7C4276084940001B4982709D284000E528401406494000FEF0F3DFDB2840586D37C137FF484000B4E73235F12840E0AC33BE2FFE4840C014AE47E1FA2840809FAA4203FD4840407156444DFC284028D505BCCCFC48400020990E9D162940487FBDC282F54840E05626FC5217294028ED0DBE30F54840A04D637B2D182940B0A78FC01FF44840E07C410B09182940A8984A3FE1F24840609BC6F65AF0284010BEDBBC71E4484060D367075CEF2840A8A78FC01FE44840400F45813EE9284000E2E7BF07D94840E0989EB0C4F32840089D82FC6CD8484080A7CAF78C042940785704FF5BD74840002A8E03AF062940686D37C137D7484000A5A2B1F6072940883FFCFCF7D64840C03BFBCA830C294030ED0DBE30D5484080BEA085041C294008DC65BFEECE4840E05758703F282940104E2844C0C7484000AB24B20F322940B8622AFD84C34840A0F755B95059294068FB743C66B64840E01D8A027D92294050431B800DAC4840C05626FC52972940A0DDAF027CAB4840407A19C5729B2940E0AF743E3CAB4840A0CF0D4DD9C12940383E7782FDA9484080F4143944C42940903CBB7CEBA948404048FAB48AC62940603D997FF4A94840C05758703FC829400806820019AA4840200F45813EC92940E0B837BF61AA484080CDE50643C52940A0DDAF027CAB484060895E46B1C429408815E0BBCDAB484060895E46B1C42940100C040132AC48406051BD35B0C52940885A457F68AC4840606552431BC82940885A457F68AC4840A023F3C81FE4294050FEB5BC72AB48404006820019EA2940206211C30EAB4840206002B7EEEE2940F81D8A027DAA48408017EFC7ED0F2A4010D6E3BED5A4484060E2AC889A582A40281A6B7F679548408018213CDAA02A4090CC07043A8D484060CDE50643A52A4008240C03968C4840C0B837BF61CA2A40B8DA6E826F86484000B0743E3CCB2A4048499D802686484060882AFC19CE2A40905451BCCA804840601A3048FA042B40C8BEB9BF7A7C4840A0DC9BDF30212B40E818C91EA17C4840000F45813E292B4058707841447C484080BFD2F9F02C2B40302CF180B27B484080AD4CF8A52E2B403035B401D87A484040573F36C92F2B40101E8A027D7A4840006211C30E332B4040D8463CD9794840C01B62BCE6352B40608BC1C3B479484040261B0FB6402B40A8A10DC0067A4840808B868C47412B40888AE3C0AB7948408021E4BCFF3F2B40E00F23844779484000B3B5BE48402B40904E417E36784840C05758703F482B40889FAA4203754840A059677C5F4C2B4010DFA63FFB73484060861DC6A44F2B400015C7815773484000A26131EA522B4000D061BEBC72484000B6F63E55552B4090812040867248402007B474055B2B40B0AAD0402C71484000D00D4DD9612B40089D82FC6C704840E0B837BF616A2B40D0CABDC0AC704840A09BC6F65A702B40089D82FC6C704840E0A16131EA722B40B8656B7D91704840A0129F3BC1762B4050465C001A714840A02634492C792B40E0A9F23D23714840809885764E7B2B408818213CDA704840C0B0A6B2287C2B40A89B8BBFED6F4840C09E20B1DD7D2B40A8A44E40136F4840A00F5EBBB4812B40D07FD6FCF86D484080FDD7B969832B40D088997D1E6D484080116DC7D4852B40785A457F686C4840402A8E03AF862B40F8DEA63FFB6B4840E0A4A2B1F6872B40E0C77C40A06B4840E0346090F4892B400815C781576B48406020B248138F2B40D0FD9C82FC6A4840A05DDA7058922B406055A181586A48404007B474059B2B4008D3A23EC9674840E0251B0FB6A02B40A8DA6E826F664840A03E3C4B90A12B40285FD04202664840800F5EBBB4A12B4010A0C37C79654840C0E1934E24A02B40B8BF97C283644840202FDE8FDB9F2B4030DEC83CF2634840A03E3C4B90A12B40D0C77C40A0634840E0E7154F3DAA2B40504CDE0033634840002C9D0FCFAA2B40D082177D05634840C0A9F23D23A12B40A85FE97C785E4840406E15C440A72B408854C37E4F524840803F373465A72B40D873D2FBC65148404048FAB48AA62B40C800DE020950484040CDE50643A52B405040DAFF004F484000B1A6B2289C2B40D0D03FC1C54A48408014AE47E19A2B40D8B837BF614A4840E00D6ABFB5732B40209F3BC1FE41484000CEFE40B95D2B40809065C1C443484060D9E90775592B40D00CE2033B444840C0978A8D79552B40A8716F7EC344484020301004C8502B40001286014B464840C0C3094CA74D2B4010DC65BFEE4648402090DB2F9F342B40502E54FEB548484060B60F79CB0D2B40A0984A3FE14A4840C0D38041D2072B4090992842EA4A4840C0C64ACCB3022B40B8E67283A14A4840002A8E03AFE62A408893A641D1484840C082C30B22E22A400818080264484840C0955D30B8DE2A40E0D38041D2474840A077F17EDCDE2A4030F38FBE49474840406C06B820E32A40A05FE97C78464840E00C36751EE52A4008CD203EB045484000B937BF61EA2A40B053E57B464248400006820019EA2A40608BC1C3B4414840808B868C47E12A40A06E2EFEB63748402009C38025DF2A40B0AD11C13836484080B3CEF8BED82A40D8B837BF6132484060BC9179E4D72A40883CBB7CEB3148402020990E9DD62A40E0C1FA3F87314840E0E7154F3DCA2A40B077F17EDC2E4840C0622AFD84AB2A4080A2EBC20F2A4840C0B2B5BE48A02A40089D82FC6C284840C0978A8D79952A40805704FF5B27484040AD4CF8A58E2A40D0F19881CA264840C023F3C81F842A4080AEEFC3412648408020B248134F2A40381A6B7F67254840004F95EF19092A4088ABAE4335214840C021E4BCFFBF294030F04E3E3D1A484000B1A6B228BC2940588BC1C3B4194840605C8FC2F5882940D8F71A82E310484000809BC58B852940D8B2B5BE4810484060F41439448429405837177FDB0F484060069B3A8F822940883FFCFCF70E4840A00F5EBBB4812940E07FD6FCF80D4840C053E57B46822940507FBDC2820D4840606E15C44087294088992842EA0A4840E0F0D8CF62892940D0066003220A4840601B62BCE695294060853FC39B074840404278B4719C29405876FA415D064840A0CCCCCCCCAC2940D0F4D901D703484020321F10E8B42940C053E57B460248406038BA4A77B72940B0C2D8429001484020356090F4B92940F8FFFFFFFFFF4740E0B54B1B0EBB29407055BDFC4EFF4740C05FE97C78D629405807793D98FA4740206002B7EEEE2940E8A6B1BD16F4474060A7CAF78C042A40E0B5F63E55ED4740A05DDA7058F22940306552431BE8474060A4897780EF294000BB9A3C65E747404051BD35B0E5294010A0C37C79E5474000AAF23D23E1294010BEDBBC71E44740005517F032D32940B09509BFD4DD4740E0EEAB72A1D22940D0B5F63E55DD4740C05DDA7058D22940B0ECF483BADC474000A26131EAD229406070784144DC474040295C8FC2D5294000C79E3D97DB4740A0737E8AE3D82940A8DDAF027CDB4740C02FF7C951F82940884B00FE29DB4740407A19C572FB2940584CDE0033DB4740E0CDFE40B9FD294060793BC269DB4740800F5EBBB4012A40D87954FCDFDB4740406E15C440072A40480DFB3DB1DC4740A074B0FECF092A4010D6E3BED5DC4740803BFBCA830C2A4038D505BCCCDC474000274D83A2112A4000BEDBBC71DC4740009F20B1DD1D2A40D0B837BF61DA47406077D84466262A4028172AFF5AD84740205C8FC2F5282A4060853FC39BD74740005517F032332A405082FE428FD247404015C78157332A40B8A10DC006D2474000B1A6B2281C2A400800000000C0474080C763062A1B2A400021CB8289BF4740A06ABB09BE192A40506D37C137BF474000E9297288082A40080C040132BC4740200473F4F8052A4060431B800DBC4740C0069B3A8F022A40E8A6B1BD16BC4740E07F828B15ED294088397AFCDEBC4740C0B69A75C6E72940B871FDBB3EBD474000C53BC0939E2940F8298E03AFC64740407A19C5729B2940C05626FC52C74740E00B040132942940D88BDAFD2ACA4740E01D8A027D922940D8FD9C82FCCA47402015C7815793294050FEB5BC72CB4740C06ABB09BE992940B85FE97C78CE4740C051D66F269E294038DB87BCE5CE474000D9D0CDFEA02940803FFCFCF7CE474000D48041D2A7294038DB87BCE5CE4740C0F0D8CF62A92940606D37C137CF474000E9297288A82940600ABABDA4CF47402051BD35B0A52940A0B393C151D04740A05A99F04B7D2940E009A1832ED7474080E2AC889A782940888461C092D7474020AB24B20F72294060853FC39BD7474020321F10E8542940A8E9B303AED74740A0129F3BC1362940089700FC53D64740C08FDB2F9F3429409048BF7D1DD6474020274D83A2312940101B498270D54740A07B0F971C272940381DACFF73D247408082C30B22222940D08BDAFD2AD24740200F45813E092940E07C957CECD047402048FAB48A06294088457EFD10D1474080A7CAF78C0429404873B9C150D14740405C8FC2F5E8284008A0C37C79D5474060BB5F05F866284078A86DC328D4474080F69507E969284018570740DCD14740C0B837BF616A2840E8B2B5BE48D04740E0921CB0AB692840D009A1832ECF4740A0AC510FD1682840982C6002B7CE47406026FDBD146628404807EBFF1CCE474040B64AB038642840D8F4D901D7CD4740E017080264482840B8AD11C138CE4740C0737E8AE3382840082A8E03AFCE4740E0955D30B81E2840D0BB783F6ECF4740C02CB64945032840B09B8BBFEDCF474060C554FA09D727406028D2FD9CCE474020CEFE40B95D27403035B401D8CA4740402C9D0FCF2A2740A8DDAF027CC34740C0D38041D22727406834D6FECEC2474040C422861D2627404882FE428FC2474040FEF0F3DF1B2740203E7782FDC14740E0C64ACCB3022740B0AAD0402CC14740E0E7154F3DEA2640A0C2D84290C1474000CA8B4CC097264038DB87BCE5B6474040AA0B78993926406034D6FECEB2474000013274EC302640004BE7C3B3B2474080AD4CF8A50E26405007793D98B24740C0F4143944042640B06BED7DAAB247408009DCBA9BF72540881EA33CF3B2474000321F10E8F4254030E78BBD17B34740001E8A027DF22540B0B0524145B34740E0B3E73235F12540D0C77C40A0B3474000274D83A2D125408854C37E4FC24740800F5EBBB461254028DB87BCE5C6474080DF6B088E232540306893C327C5474060BC9179E4F724405007793D98CA4740A07C410B09F82440784B00FE29CB4740E085048C2EF72440F8C69E3D97CB474080716F7EC3F42440909065C1C4CB4740A0B81E85EBF12440302CF180B2CB4740006C06B820E3244000D061BEBCCA4740201286014BDE2440B0B915C26ACA4740C0B0A6B228DC2440286BD44334CA47402083DC4598DA244028D8463CD9C94740E0BB783F6EDF2440F02CCF83BBC34740E06BED7DAAEA2440B877F17EDCBE474060D367075CEF2440881B62BCE6BD474040CAA48636F02440587FBDC282BD4740407D5A457FF02440A09ECC3FFABC4740E0D03FC1C5F22440E8B2B5BE48B84740A05DDA7058F22440104E2844C0B7474060BEA08504DC2440004BE7C3B3B247402069C53714AE2440B0B393C151A84740C00C1D3BA8AC24409021E4BCFFA7474000CBBDC0ACA82440B8BC564277A74740A03BFBCA838C2440A09ECC3FFAA44740A085048C2E77244050793BC269A34740A0716F7EC3742440A8B0524145A3474020274D83A2712440D0AF743E3CA3474060B3CEF8BE582440884B00FE29A347408059677C5F6C2440D00F238447A94740A05FE97C78762440905704FF5BAF4740A085048C2E772440C8D38041D2AF4740A05FE97C787624408893A641D1B04740C0DB114E0B16244010BB9A3C65BF4740205C8FC2F5E82340D0031F8315C54740C0656B7D91A0234008DFA63FFBCB4740E09E20B1DD9D2340B0A78FC01FCC4740404E7CB5A3902340D8A6B1BD16CC474000A7B1BD168C2340302CF180B2CB4740002A8E03AF8623403035B401D8CA4740C06E2EFEB67F234090457EFD10C94740804278B4717C234010D3A23EC9C74740206684B707792340305FD04202C64740A07CD0B359752340D852B29C84C44740E0EE586C936223402863601DC7C34740E04BC631924D23402863601DC7C34740E097C118913823402863601DC7C347406028B517D13623402863601DC7C3474020CD0358E42723401824EF1CCAC4474080B7EBA529222340900B957F2DC5474060EA059FE6F42240302F4E7CB5C94740604C6C3EAE8522402835B401D8D44740A03BFBCA832C2240A8E9B303AED74740206552431B28224000D3A23EC9D7474020295C8FC215224088C9C6832DD847408059677C5F0C2240E000DE0209D8474080069B3A8F022240805704FF5BD74740401286014BFE214000DC65BFEED6474040E2AC889AF821409048BF7D1DD64740E05DDA7058F22140101B498270D5474040CDE50643E5214078A86DC328D44740001286014BDE214008C79E3D97D34740C01B62BCE6D52140A8B0524145D3474060D367075CCF2140D8AF743E3CD34740A04E95EF19C92140009A417C60D34740202E3BC43FC42140405F251FBBD3474000AD33BE2FB62140885D86FF74D947400023DA8EA9AB2140B07A32FFE8DB4740E051D66F269E2140E8AC33BE2FDE4740002DCF83BB9B21405076FA415DDE4740A0AA0B78999921408848BF7D1DDE4740802975C9388E2140A8BF97C283DC4740A091088D608B2140E0F4D901D7DB47402023DA8EA98B21403014E97E4EDB4740C00C1D3BA88C214080992842EADA4740A0E65608AB992140D8EEC9C342D74740C0116DC7D4852140886649809AD8474000EC6AF2947D2140285C8FC2F5D8474060B81FF0C0702140B0490C022BD9474000B6F63E557521401006820019DA474060815A0C1E762140D0552C7E53DA474060BC9179E47721403835B401D8DA4740A02FF7C951782140109A417C60DB4740C0F755B950792140B0656B7D91E04740C0F755B95079214000E2E7BF07E14740A02FF7C951782140805D86FF74E147400038A110015F2140580DFB3DB1E4474040EFAB72A152214058499D8026E647400054FEB5BC3A2140A877F17EDCE64740A009DCBA9B37214008DC65BFEEE64740A0CF0D4DD921214028F38FBE49E7474000C53BC0931E2140606D37C137E74740A0978A8D79F52040A8984A3FE1E2474000999EB0C4F320406082FE428FE24740A05DDA7058F2204038F04E3E3DE2474060CAA48636D020401006820019DA4740207D5A457FD02040A8C2D84290D94740E0C77C40A0D32040E876137CD3D6474060D9E90775D9204010CD203EB0D5474000E6E8F17BF320405834D6FECED2474020EC6AF294FD20402835B401D8D24740C0F0D8CF62092140904B00FE29D34740A050A4FB390D2140502B137EA9D3474060FA96395D0E2140D0A6B1BD16D4474020A26131EA122140080341800CD547408038BA4A77172140101B498270D5474040D026874F1A2140500438BD8BD54740400F45813E292140B8E3310395D54740A081583673382140203FFF3D78D54740E09E20B1DD3D21408887A2409FD44740C0D8D0CDFE40214000DFA63FFBD34740E053E57B46422140E0C77C40A0D34740C079008BFC422140904B00FE29D34740A082C30B22422140004BE7C3B3D24740207D5A457F302140809FAA4203CD4740A06DFC89CA2E2140A8ECF483BACC47408085B18520272140F8EA1C03B2CB474040B936548C232140283944DC9CCC4740803E3C4B902121403829B000A6CE4740002FDE8FDB1F21400821CB8289CF4740009F20B1DD1D214008D3A23EC9CF4740E009F5F41110214028E109BDFED04740E0E7154F3D0A2140B8AAD0402CD147402051BD35B0052140F82F1004C8D0474000BFB9BF7AF420406076FA415DCE47406069C53714EE2040D888997D1ECD47400009C38025DF2040A85CA8FC6BC94740606552431BC8204038F04E3E3DCA474020295C8FC2952040580438BD8BCD474000E6E8F17B932040001286014BCE474080C1E10511912040B85FE97C78CE4740809885764E7B204028F38FBE49CF4740200F45813E692040788461C092CF4740A0116DC7D4652040788461C092CF4740E079008BFC622040A8BC564277CF47408077F17EDC5E20405040DAFF00CF4740A0B3CEF8BE382040E0B837BF61CA4740C05626FC52372040A8A10DC006CA4740E0E4D4CE3035204080ABAE4335C9474000BFB9BF7A342040282F3201BFC84740206211C30E3320401018080264C84740A0F1D3B8372F20403038F581E4C74740E059677C5F2C2040004E2844C0C74740A0C1E10511112040D809A1832EC7474040D026874FBA1F40F8298E03AFC6474000BFD2F9F0AC1F40588E0244C1C6474000323D6189A71F4028DB87BCE5C64740C0F2052D24A01F40D8BB783F6EC74740000C040132141F40E076137CD3C6474080137CD3F4C91E40600438BD8BC54740802FDE8FDB9F1E40A85FE97C78C6474080BEA085047C1E40C8D38041D2C74740C06BED7DAAAA1E4010C11C3D7EC947408069C53714AE1E40E073D2FBC6C9474080F9821612B01E40D88BDAFD2ACA474000E5D4CE30B51E40805182FE42CD474000EFAB72A1B21E40B868ACFD9DCD4740002861A6ED8F1E40585260014CCD4740402235ED625A1E4040959A3DD0CA474040A837A3E65B1E4008B8CB7EDDCB4740C0ED7E15E05B1E40100341800CCD4740C0AB1F9BE4571E408096E7C1DDCD4740C0490ED8D5441E4008C11C3D7ED1474000D6AD9E933E1E40D806600322D247404020B75F3E291E40D0F4D901D7D3474080DBF813951D1E40F8230C0396D447400060E97C78161E4030ED0DBE30D54740C069C020E9131E40500438BD8BD5474000D57B2AA70D1E40A89B8BBFEDD74740C0DE52CE170B1E40B0A10DC006DA4740C08713984E1B1E4090397AFCDEE44740C0934E24983A1E40B8DA6E826FEE4740409CC1DF2F561E40D8C77C40A0F34740806893C3277D1E4050431B800DFC4740C019355F257F1E40100341800CFD474040BC783F6E7F1E40B8AD11C138FE4740402CBB60707D1E40606D37C137FF474040F357C85C791E40F8FFFFFFFFFF4740C0DC257156741E40F82F1004C8004840801B62BCE6551E40B8DDAF027C034840C088450C3B4C1E40805A457F6804484000F1D8CF62491E40B8716F7EC30448404051BCCADA461E40804EB340BB05484080E3A25A44441E40A8E9B303AE074840003888D68A461E4088992842EA0A4840C03F373465471E4048793BC2690B484000836C59BE4E1E4018BDC5C37B0E484000301004C8501E40C05626FC520F484040E1B19FC5521E40B06E2EFEB60F4840C052CF82506E1E4038BF9A030415484080F30016F9C51E40009A417C60234840C0BEA08504FC1E408054C37E4F2A4840C007AF5DDA001F4038E78BBD172B484000D95C35CF011F40D8EB8843362C48408084F068E3F81E403820ED7F802F4840004D689258F21E4040D8463CD9314840004D689258F21E40D082177D05334840005D8DEC4AFB1E40B037F8C26436484040A8FC6B79351F40588BC1C3B4494840C00C36751E851F40789FAA4203554840005612D907D91F40600DFB3DB15C4840A0F1D3B8372F2040A877F17EDC664840E0E4D4CE30352040A8E0F08288684840A05FE97C78362040000F45813E694840A000193A76382040E0C77C40A06B484060AA0B789939204030F6D03E566C4840001286014B3E2040888D2441B86E484040809BC58B452040B0A10DC006724840406E15C440472040A8E67283A1724840803E3C4B9061204040D8463CD9794840C0C1FA3F87692040F8CF61BEBC7A4840A0B0E07EC0732040785A2904727B484060861DC6A44F2040A89ECC3FFA7C48402083DC45981A2040D8CABDC0AC804840E0ED974F56142040A05CA8FC6B81484040AAF23D23C11F4080AEEFC341864840403E4162BBBB1F4080AEEFC341864840004F95EF19491F40D8FA5B02F0854840C05417F032F31E4008A0C37C7985484040BFD2F9F0AC1E40201A6B7F6785484080530438BD9B1E40C0B0E07EC0854840808D959867851E4028172AFF5A8848404008AF5DDA801E408818213CDA88484000EFAB72A1F21D40809FAA42039548400015AE47E1BA1D408860C77F8196484080E7FC14C7B11D40082A8E03AF96484080313D6189A71D403829B000A6964840008B6D52D1881D40E0AC33BE2F96484040A243E048801D40285FD0420296484040C64FE3DE7C1D408096E7C1DD95484000EF7211DF791D4090A8177C9A954840807C410B09781D4030232E008D944840004D689258721D40F81D8A027D924840803D0AD7A3701D40286BD44334924840806BED7DAA2A1D405076FA415D8E4840402A8E03AF261D40A8AD11C1388E4840C08713984E9B1C403820ED7F808F484000F52D73BA5C1C40A8B393C151904840406AC020E9131C408021E4BCFF97484000240C0396BC1B40A8A78FC01F9C48408084F068E3B81B4050707841449C484080AD4CF8A5AE1B40D80CE2033B9C484040A8C5E0616A1B40B87A32FFE89B4840C0703D0AD7631B40806308008E9B4840C0EA56CF495F1B40306211C30E9B484040DBF813955D1B4010D061BEBC9A4840C03106D6715C1B40D8B837BF619A4840805A99F04B5D1B40B8A10DC0069A484080C422861D661B4008180802649848408052B81E856B1B400821CB8289974840809BC6F65A701B402841B8020A97484040E7FC14C7711B40508E0244C196484040E7FC14C7711B4058FB743C66964840C0F9821612701B4010E5284014964840C094490D6D601B4058707841449448400007B474055B1B40D8F4D901D79348400026396057531B40F8C69E3D9793484080921CB0AB491B40302CF180B2934840803D0AD7A3F01A40286893C327954840005A677C5FEC1A40805182FE42954840C05C8FC2F5E81A40001B498270954840C01A3048FAE41A40D87FD6FCF8954840C0B0A6B228DC1A40D0BB783F6E974840008813984EDB1A4008D3A23EC997484040ED7E15E0DB1A4090C9C6832D984840C0DBF81395DD1A406001F73C7F98484000BC783F6EBF1A40805704FF5B9F484040D9D0CDFE601A40B85FE97C78AE4840C0F1D3B8372F1A40F8CC203EB0B5484000C2FA3F87291A408860C77F81B64840C0D8D0CDFE201A401009C38025B74840C0E8297288081A40D0CABDC0ACB84840008D9AAF92DF1940306211C30EBB48400006820019AA1940583A58FFE7BC484000DE57E542A5194080397AFCDEBC4840805E46B1DC72194030923D42CDBA484040D576137C7319406828D2FD9CBE4840C0ED7DAA0A6D19407012F5824FC34840C04F90D8EEAE194080CC07043AD54840405B99F04BDD1940587C7C4276D8484000D6A88768E4194000301004C8D84840409BC6F65AF0194048465C001AD9484080B0389CF9051A4040BCE7C072DA484000F855B950191A4080A52C431CE74840805512D907191A403020ED7F80E74840C0012D5DC1161A40D8D38041D2E7484080035ABA82ED1940D8D38041D2E74840407D410B09B819400021CB8289E748400014B35E0C951940D8CABDC0ACE84840408B6D52D1481940F8230C0396EC4840C04146408543194080DFA3FE7AED4840808D959867051940582E54FEB5F0484040A243E048001940B0AAD0402CF1484080573F36C9EF1840A8984A3FE1F2484040D576137CB3184028266F8099F94840C0A2755435B11840F8D8243FE2F94840C02861A6ED8F1840586D37C137FF4840C051BD35B0851840D873D2FBC6014940C03AE2900D7418400809C3802507494080D576137C731840F820CB8289074940402634492C791840D0C77C40A00B4940805B94D92083184020DB87BCE50E4940408D95986785184050853FC39B0F4940C07FD8D2A38918406076FA415D1049400021B248138F1840909065C1C413494080D38041D2A7184030F6D03E561C494000C2FA3F87A918408087A2409F1C49404045B9347EB118405831957EC21D4940008D9AAF921F194058F5F23B4D24494040C422861D661940D000DE0209284940C08B14CAC2971940687500C45D294940C0BB783F6E7F1940F81708026438494000D6AD9E937E1940302F3201BF384940C0BEA085047C194028F911BF6239494000378DEDB5601940E07FD6FCF83D4940001C62BCE6551940F8298E03AF3E4940C00C36751E451940F820CB82893F494000C64FE3DE3C1940004E2844C03F49408020B248130F1940B06E2EFEB63F494000CEFE40B9FD184050793BC2694B49408013B35E0C151940E876137CD34E4940009CC1DF2F161940E009A1832E4F494000B6F63E551519400021CB82894F4940806211C30E131940D0D38041D24F494080AF743E3CAB184080423D7D04544940407D410B093818409087A2409F5C494040A260C6140C1840D09A9141EE6049408047E6913F081840002A8E03AF664940C0D47B2AA70D18400015C781576B4940C03AE7A7380E1840F02CCF83BB6B494080438CD7BC1A1840A8BF97C2836C494040F1D3B8372F1840000341800C6D4940C04291EEE7341840000341800C6D4940C06ABB09BE39184008240C03966C4940001286014B3E1840D8BEB9BF7A6C49400054E57B4642184008240C03966C4940808D959867451840A8716F7EC36C4940C0F0D8CF62491840D0B5F63E556D4940009CC1DF2F561840D8BB783F6E6F494000022D5DC1561840D0D38041D26F49400026396057531840383B3602F1744940807C46223452184088CC07043A75494000977153031D1840789FAA42037D494040FF04172B1A184080CC07043A7D494080B81E85EB11184008A0C37C797D49400023DA8EA9CB174008E52840147E4940403F373465C7174008E52840147E4940C014AE47E1BA1740D0CDFE40B97D494080E07F2BD9A1174058888043A87C4940405DC136E2991740805A457F687C494040D253E410911740B0BF97C2837C4940C0D026874F7A1740A0B915C26A824940C04291EEE7741740B0E331039585494000A8FC6B79751740801B62BCE6854940C0DAFD2AC077174060499D802686494000B1A6B2289C1740D08558FD1188494040378DEDB5A0174080C9C6832D884940403465A71FA417408821E4BCFF874940405B94D920031840D0D03FC1C58A4940C0703D0AD7631840F82F1004C8904940803106D6715C1840B068ACFD9D95494080583A1F9E551840D07FD6FCF8954940C07497C4595118408860C77F8196494040DC2A88814E1840E009A1832E974940404C6DA9834C1840B8B393C151984940004F95EF1949184028E78BBD179B4940C0F0D8CF62491840A8622AFD849B494000356090F4491840B07A32FFE89B4940803AE7A7384E1840588E0244C19E4940C02F1004C85018403041B8020A9F4940001E8A027D92184038327381CBA5494080F0DDE68DE31840101286014BAE4940803465A71FE41840002A8E03AFAE494080F0DDE68DE31840D0C77C40A0BB4940C02CB64945E3184080423D7D04BC4940C0AD47E17AD41840D80F238447C14940C020B24813CF1840D08BDAFD2AC249408046EBA86AA21840B8BC564277C7494080E6012CF28B18409018213CDAC84940803788D68A861840D00F238447C94940C094490D6D601840A8B6D4415ECD494040EB56CF495F1840E0CDFE40B9CD494040DBF813951D1840201DACFF73DA4940003C4CFBE6CE1740186C5CFFAEDF4940C059677C5FEC17406073B9C150E149404045B9347EF11740D873D2FBC6E14940004D689258F21740E08BDAFD2AE24940C09BC6F65AF01740B07A32FFE8E3494000BFD2F9F0EC1740B0BF97C283E4494040ED7E15E0DB174080A52C431CE749408099999999D9174008BB9A3C65E74940405B94D92003184020F04E3E3DEA494080D5AD9E937E1840888AE3C0ABF1494000944E2498BA18405007793D98F2494000323D618967194030232E008DEC4940805DC136E2D91940885182FE42ED4940C0B0A6B2281C1A40B89B8BBFEDEF494040D9D0CDFE601A40004BE7C3B3F2494080FE092E56B41A40A89ECC3FFAF449404070422102BE1A40809FAA4203F5494000E4A25A44C41A409087A2409FF4494000B728B341C61A4038F6D03E56F44940807E6E68CACE1A40582B137EA9F3494080E07F2BD9E11A4090992842EAF249408022DFA5D4E51A40881EA33CF3F249404082C8224DFC1A4000DFA63FFBF34940404B3B35971B1B40E0FA5B02F0F549400076C4211B281B40D8F19881CAF6494000301004C8501B4008C79E3D97FB494000E2B19FC5521B4030F6D03E56FC494040B81E85EB511B40D088997D1EFD49400077BF0AF04D1B4010C45DBD8AFE4940C0989EB0C4331B40D07C957CEC004A40C0035ABA822D1B405873B9C150014A404006820019EA1A40A8BF97C283044A40C0AA24B20FF21A40B874B0FECF094A4000AB5E7EA7091B40782A1900AA0E4A404085EB51B85E1B40B0A44E40130F4A40405C8FC2F5681B40F808C380250F4A4040A3755435711B4000BB9A3C650F4A4000EA5BE674791B40E08558FD11104A4000C64FE3DE7C1B40D8CABDC0AC104A40C05DBC1FB77F1B40B074B0FECF114A40C0A9F23D23811B40E082177D05134A40C0F5285C8F821B40009A417C60134A40C0438CD7BC9A1B40D8FA5B02F0154A40409F20B1DD9D1B4048499D8026164A4000ED7E15E0DB1B4028172AFF5A184A4000B0743E3C2B1C401048A643A71D4A40C07406465E361C40A01D37FC6E1E4A4080F2052D24201C40B0B915C26A224A4040F52D73BA1C1C4050FEB5BC72234A4040F52D73BA1C1C40E87954FCDF234A4040DBF813951D1C40A8ECF483BA244A4000D9D0CDFE201C4088AEEFC341264A4040CCD1E3F7261C40D000DE0209284A40C0C2853C823B1C40586D37C1372B4A40803F373465471C40386893C3272D4A40408B6D52D1481C40D8FA5B02F02D4A40C05B94D920431C4028F911BF62314A4040BC783F6E3F1C40D0B837BF61324A400082C8224D3C1C40D882177D05334A4080300BED9CF61B403035B401D83A4A40C05417F032F31B40D082177D053B4A400094179980EF1B40A8984A3FE13A4A4040DE57E542E51B40B05CA8FC6B394A404097715303DD1B40582E54FEB5384A4000D253E410D11B405837177FDB374A40C0D47B2AA7CD1B40B8E9B303AE374A40008B6D52D1C81B4058853FC39B374A40007F6E68CA0E1B40D0D03FC1C53A4A4000FED7B969031B40E0AF743E3C3B4A40001E8A027DD21A40E0AC33BE2F3E4A40C0E3D9E55BCF1A40E0F19881CA3E4A40404C361E6CC11A40101286014B464A4040B950F9D7C21A403029B000A6464A4080703D0AD7E31A4060853FC39B474A40C0B628B341061B40286552431B484A40C0921CB0AB091B40E0B2B5BE48484A40C0DE52CE170B1B40706649809A484A40000E315EF3EA1A40B077F17EDC4E4A4000323D6189E71A402020ED7F804F4A40005FD5592DE01A40D84FAA7D3A504A400083C30B22E21A40B0656B7D91504A4000FBAF73D3061B4038E78BBD17534A40C01D8A027D121B40A0DDAF027C534A404094490D6D201B40082DCF83BB534A40800C040132941B4000C79E3D97534A4040ED7E15E09B1B4050FEB5BC72534A4040EB56CF499F1B40B0B0524145534A4000CCD1E3F7A61B406082FE428F524A40000E315EF3AA1B40383E7782FD514A4000EA245B5DAE1B40E873D2FBC6514A40009A999999191C40385C8FC2F5504A40408D9AAF921F1C40385C8FC2F5504A40809AD024B1241C4030E109BDFE504A40405A677C5F2C1C40E00F238447514A4040A3755435311C40E873D2FBC6514A40C04291EEE7341C40E0B837BF61524A4040E2AC889A381C4050FEB5BC72534A400082C8224D3C1C40B09ECC3FFA544A40C0A9F23D23411C4038F6D03E565C4A4040B950F9D7421C40E0B2B5BE48604A400054E57B46421C40D0B837BF61624A40C05B94D920431C40F0230C0396644A40C0A7CAF78C441C40081286014B664A40803F373465471C40B0B393C151684A40807E6E68CA4E1C40C8C1FA3F87694A4040FBEAAA405D1C40C8E95DBC1F6B4A400047E6913F881C40E073D2FBC6714A40807C410B09B81C40908461C092774A4000F30016F9C51C4078812040867A4A404079E75086CA1C40A8622AFD847B4A408090F46915CD1C40D80CE2033B7C4A404046B41D53D71C40504F1F813F804A4040B3CEF8BED81C40A8A10DC006824A40000C040132D41C4010C45DBD8A964A40C0A7565F5DD51C402027F73B149F4A400015AE47E1FA1C405037177FDBA74A404000000000001D4030172AFF5AA84A40C03788D68A061D40382F3201BFA84A404060E97C78161D409018213CDAA84A40C0E17A14AE471D4000CADFBDA3A84A400038BF61A2511D405801F73C7FA84A40405512D907591D4090C9C6832DA84A400085EB51B85E1D40A86E2EFEB6A74A4000C74ACCB3621D4088A52C431CA74A408018080264681D40082A8E03AFA64A408015E0BBCD6B1D408860C77F81A64A40C0E4D4CE30751D40F81186014BA64A4080F1D3B8376F1D403020ED7F80A74A40C0313D6189671D4000CADFBDA3A84A40009F20B1DD5D1D40000F45813EA94A4000AE47E17A541D40905D86FF74A94A404018080264E81C40306211C30EAB4A404082C8224DBC1C40E0C77C40A0AB4A40004C361E6C811C40A8622AFD84AB4A404085EB51B85E1C40A8B0524145AB4A4000DF52CE174B1C40E082177D05AB4A40407A19C5723B1C40884B00FE29AB4A4080989EB0C4331C40B0DDAF027CAB4A4080013274EC301C40F82CCF83BBAB4A40405A677C5F2C1C405070784144AC4A4040B3CEF8BE181C40888D2441B8AE4A40406AC020E9131C40580ABABDA4AF4A4000301004C8101C40602E54FEB5B04A40C0CAA48636101C4050465C001AB14A40C07E6E68CA0E1C40E0F4D901D7B34A40402861A6ED0F1C40D0031F8315B54A40C05FE97C78161C4010CADFBDA3B84A4080F2052D24201C40B8B6D4415EBD4A404083C30B22221C408048BF7D1DBE4A40C0FF04172B5A1C405807793D98CA4A408046EBA86A621C40809065C1C4CB4A400018080264681C40000C040132CC4A40C06893C327BD1C40206BD44334D24A404018080264E81C40D888997D1ED54A40C090EF52EAF21C4000CD203EB0D54A40404F90D8EE2E1D40A86E2EFEB6D74A40005B99F04B5D1D4028EACC3D24D84A40C032384A5ECD1D408021E4BCFFD74A404085EB51B8DE1D40B09B8BBFEDD74A40C0703D0AD7E31D405037177FDBD74A4080F9821612F01D40D0BB783F6ED74A4080E9297288081E4008E5284014D64A40006211C30E131E40D87FD6FCF8D54A4000C87C40A0531E40586D37C137D74A40C0DE52CE17CB1E40F0264D83A2D94A40008D9AAF925F1F4050793BC269DB4A40C0E17A14AE871F40D0F4D901D7DB4A40409CF86A47A11F40E8A6B1BD16DC4A4080E6012CF2CB1F40D0F4D901D7DB4A404040321D3AED1F40806308008EDB4A4080F4143944042040B8984A3FE1DA4A4000B937BF610A2040381DACFF73DA4A4060035ABA820D204070A2EBC20FDA4A40A0AD4CF8A50E2040D873D2FBC6D94A4060F1D3B8370F2040A05CA8FC6BD94A40C088450C3B0C2040B0E0F08288D84A40C0622AFD840B204090C9C6832DD84A40E0DE52CE170B204008D3A23EC9D74A40A091088D600B204000C45DBD8AD64A40A00C1D3BA80C20408096E7C1DDD54A408009DCBA9B172040805D86FF74D14A4000CEFE40B91D204080C9C6832DD04A40E0BB783F6E3F20403835B401D8CA4A40207D5A457F502040E0B2B5BE48C84A4000274D83A25120409021E4BCFFC74A40C05417F03253204010BB9A3C65C74A4020321F10E85420405876FA415DC64A4000B6F63E55552040500438BD8BC54A40C0AC33BE2F562040B0DDAF027CC34A4000DC114E0B56204000E869C020C34A4000C87C40A0532040B0E67283A1C24A4040CDE50643452040905D86FF74C14A4000EB56CF493F204010E2E7BF07C14A40A0716F7EC3342040A8E0F08288C04A4000B0743E3C2B2040584F1F813FC04A408094490D6D20204030172AFF5AC04A4000BC783F6E1F2040E08558FD11C04A40C08C9AAF921F2040B0E9B303AEBF4A40E0CF0D4DD9212040001B498270BD4A40A0B08D78B223204010BEDBBC71BC4A4020FBAF73D3262040504CDE0033BB4A40C04E95EF19292040B8E67283A1BA4A4000AB24B20F322040D0F71A82E3B84A40E09BDF30D1682040082DCF83BBB34A40E02B9D0FCF6A204000C79E3D97B34A40006BD443347220402814E97E4EB34A40E07C410B09782040B8B0524145B34A4000A8E331037D2040109A417C60B34A400009C380257F2040A8DDAF027CB34A40A017EFC7ED8F2040A8B6D4415EB54A40A04B546F0D94204010E5284014B64A40601B62BCE6952040F8298E03AFB64A4000C53BC0939E2040E073D2FBC6B94A4000B3B5BE48A02040B0B915C26ABA4A40A08B868C47A12040582B137EA9BB4A4080B08D78B2A320405037177FDBBF4A408023F3C81FA42040B8AAD0402CC14A4080B08D78B2A32040583D997FF4C14A40E0A9F23D23A12040B8984A3FE1C24A40605FD042029E2040A8B0524145C34A40609885764E9B20400815C78157C34A4000AD33BE2F962040D0AF743E3CC34A400023DA8EA98B2040A86BED7DAAC24A4060BB5F05F88620408081204086C24A4080AA0B7899792040D8B837BF61C24A40E05626FC52772040081E8A027DC24A40C0129F3BC17620402835B401D8C24A4000D34ECDE5762040A8A78FC01FC44A4080F755B95079204010BB9A3C65C74A40604278B4717C2040D882177D05CB4A404051BD35B085204028ED0DBE30CD4A400023DA8EA98B2040F8E4284014CE4A4080C1E10511912040D8C43BC093CE4A4040F52D73BA9C2040883FFCFCF7CE4A40809E077767A52040883FFCFCF7CE4A40C06DFC89CAAE204008C45DBD8ACE4A40406893C327FD20403841B8020AC74A40C0F0D8CF62092140E0EE5701BEC14A40C0F4143944042140682E54FEB5C04A4080C2137AFD01214090C9C6832DC04A40C051D66F26FE2040803FFCFCF7BE4A40407A19C572FB2040285FD04202BE4A40C01D71C806FA2040E0B5F63E55BD4A40A000193A76F82040100C040132BC4A408085048C2EF720400806820019BA4A4080BC9179E4F72040600438BD8BB54A40A000193A76F8204008DFA63FFBB34A40201077F52AFA20408818213CDAB04A40609885764EFB2040084E2844C0AF4A40C077F17EDCFE20409048BF7D1DAE4A40A03E3C4B90012140D8B5F63E55AD4A4080FDD7B96903214068FB743C66AE4A408023F3C81F042140A8E9B303AEAF4A40A079008BFC02214060FB743C66B64A40C0069B3A8F02214058853FC39BB74A4000EB56CF49FF2040888AE3C0ABB94A40605FD04202FE2040504CDE0033BB4A400038A11001FF2040805A457F68BC4A40C018213CDA002140607FBDC282BD4A40A02CB64945032140B85FE97C78BE4A4080116DC7D40521405040DAFF00BF4A40C0CF9CF5291F2140989FC6BDF9C14A40803E3C4B9021214008D061BEBCC24A40E079008BFC22214060FEB5BC72C34A40E079008BFC2221405070784144C44A40A0069B3A8F2221408887A2409FC44A4000EC6AF2941D2140B05FE97C78C64A40E080B4FF010621405840DAFF00CF4A40A05A99F04BFD2040D08BDAFD2AD24A40C01D71C806FA204058793BC269D34A4060E2AC889AF82040C8BEB9BF7AD44A40C05626FC52F72040285FD04202D64A40E0D24ECDE5F62040D009A1832ED74A40A038BA4A77F7204030172AFF5AD84A40C06ABB09BEF9204038D8463CD9D94A4040E2AC889A182140282F3201BFE84A4060C422861D262140B09ECC3FFAEC4A40E04E95EF19292140901B62BCE6ED4A40C0989EB0C4332140A0B393C151F04A40E0B5F63E55352140A8656B7D91F04A4080F755B9503921407818213CDAF04A400069C537144E21400006820019F24A40A0716F7EC3542140A8B915C26AF24A40404278B4715C21408081204086F24A40C051D66F265E21409054C37E4FF24A40E0921CB0AB692140306552431BF04A408088450C3B6C2140788461C092EF4A40C07F828B156D2140A877F17EDCEE4A408076BF0AF06D2140D0C43BC093EE4A40E0716F7EC374214038327381CBED4A40802CB64945832140B059677C5FEC4A40A07F828B158D2140F8C69E3D97EB4A40C04D637B2D982140D8FD9C82FCEA4A40A0716F7EC3B42140286BD44334EA4A40204E7CB5A3D02140303E7782FDE94A40C089592F860A2240B059677C5FEC4A40C01B62BCE63522408860C77F81EE4A4080C2137AFD412240A877F17EDCEE4A40807F828B156D2240808D2441B8EE4A40200AF5F411702240082A8E03AFEE4A406032384A5E8D2240E0FA5B02F0ED4A4080D367075C8F224038327381CBED4A4060C1E10511912240B868ACFD9DED4A404020990E9D962240580DFB3DB1EC4A4020634337FBA32240C053E57B46EA4A4060C422861DA62240D0EE5701BEE94A40A07A32FFE8B3224060499D8026E64A40E053E57B46C2224028F911BF62E14A40407497C459D12240587FBDC282DD4A4000321F10E8D42240B8ECF483BADC4A408000193A7618234058499D8026CE4A40002FDE8FDB1F234008240C0396CC4A40609E077767252340602B137EA9CB4A4000B937BF612A2340D882177D05CB4A40A000193A7658234080A52C431CC74A40A0F4143944642340B8DA6E826FC64A40607EA7C98C87234000E59A0299C54A406054FEB5BC9A234008BEDBBC71C44A4000BC783F6E9F2340D80CE2033BC44A4040895E46B1A4234078A86DC328C44A4020AE65321CA72340D80CE2033BC44A40605C8FC2F5A82340785A457F68C44A4000E8154F3DAA234058888043A8C44A40801EA33CF3AA2340A09ECC3FFAC44A40801EA33CF3AA2340381A6B7F67C54A40C04E95EF19A92340D07FD6FCF8C54A4000B728B341A62340B8DA6E826FC64A4060F4143944A423405828D2FD9CC64A40407497C4599123406037177FDBC74A40A059677C5F8C2340E000DE0209C84A40603E213B6F7B234050164CFC51C84A40E0D03FC1C5722340F817080264C84A4080C422861D662340302F3201BFC84A40206893C3275D234088ABAE4335C94A4000999EB0C453234080A2EBC20FCA4A402048FAB48A26234008C45DBD8ACE4A40E0EA56CF491F2340808461C092CF4A4040BC9179E417234060465C001AD14A40E0E1934E24E022402829B000A6DE4A40604278B471DC2240D0D38041D2DF4A40E068ACFD9DD52240104BE7C3B3E24A4000301004C8D02240301A6B7F67E54A4020356090F4C92240D8A9F23D23E94A40200F45813EC92240805D86FF74E94A4060BFD2F9F0AC2240286893C327ED4A40E0D38041D2A72240D8CDFE40B9ED4A4020EFAB72A1922240B09B8BBFEDEF4A4040DC2A88818E2240884E417E36F04A40C07C410B09782240905D86FF74F14A4080C1E10511712240D873D2FBC6F14A40E04E95EF19692240283E7782FDF14A4020B3B5BE48202240801EA33CF3F24A40604278B471FC214070A2EBC20FF24A40C038BA4A77F72140583D997FF4F14A4080F1D3B837EF21405082FE428FF24A40E00C36751EE52140A8A78FC01FF44A408014AE47E1DA2140D0CDFE40B9F54A40C07A32FFE8D32140B877F17EDCF64A40800C1D3BA8CC2140109D82FC6CF84A408023F3C81FC42140D882177D05FB4A40E05417F032B32140D8A9F23D23014B40A00C1D3BA8AC2140D0C77C40A0034B40E0A6B1BD16AC214008DFA63FFB034B4080FA96395DAE2140B8BF97C283044B406045B9347EB12140383B3602F1044B40C0B5F63E55B52140805182FE42054B40407A19C572BB21400848A643A7054B40A079008BFCC2214038327381CB054B40E0A4A2B1F6C721400848A643A7054B4080A148F773DA2140A0716F7EC3044B40C023F3C81FE42140A87A32FFE8034B408015E0BBCDEB21403035B401D8024B4000B4E73235F12140A853E57B46024B40C0E4D4CE30F52140E0B837BF61024B40E0B2B5BE480022401015C78157034B40803E3C4B90012240F8C69E3D97034B406051BD35B0052240B868ACFD9D054B408048FAB48A06224058FB743C66064B40C09BDF30D1082240B8984A3FE10A4B4000B4E73235F121409018213CDA104B408009DCBA9BB721406037177FDB0F4B4060B81E85EBB1214008301004C8104B40607D5A457FB0214008E2E7BF07114B40C09BDF30D1A82140781EA33CF3124B404077D84466A62140D87954FCDF134B4000E2934E24A0214060FB743C66164B4060C2137AFDA12140B0B393C151184B4020809BC58BA5214088812040861A4B40E06DFC89CAAE2140E08558FD11204B4060A4897780AF2140009D82FC6C204B4000301004C8B02140E0CABDC0AC204B40A0716F7EC3B42140305C8FC2F5204B4080D6A88768C421400048A643A7254B40005C8FC2F5A82140500438BD8B254B408023F3C81F6421405007793D98224B4080FDD7B969632140C053E57B46224B40E0CF0D4DD961214078A2EBC20F224B4020B1A6B2285C214078A2EBC20F224B40A0129F3BC1562140D08BDAFD2A224B4020861DC6A44F2140101E8A027D224B4020C2FA3F87492140881EA33CF3224B40A0FDD7B969432140002DCF83BB234B4080F755B950392140D0C43BC093264B40A0D24ECDE53621403020ED7F80274B40C0716F7EC33421405801F73C7F284B40E014C78157332140A8C2D84290294B40C0D03FC1C53221408854C37E4F2A4B4000A26131EA32214008D061BEBC2A4B4000E3A7716F3E2140587C7C4276304B4080A7CAF78C442140B053E57B46324B40C0AD65321C472140D0D03FC1C5324B40402C9D0FCF4A214038E78BBD17334B40C050A4FB394D2140804B00FE29334B40E0C1FA3F8789214008240C0396344B4020809BC58BA5214028ED0DBE30354B4000A5A2B1F6A72140C8031F8315354B4000931CB0ABA9214078397AFCDE344B40A0BFD2F9F0AC214050431B800D344B4080FA96395DAE2140D8F4D901D7334B4080C1E10511B12140789065C1C4334B40C0DB114E0BB62140A87A32FFE8334B4080C422861DC62140809FAA4203354B40C05A99F04BFD214040D8463CD9394B4080069B3A8F02224090992842EA3A4B4000F2ECF2AD072240805A457F683C4B40E017080264082240B8716F7EC33C4B4000356090F409224080A52C431C3F4B4000CBBDC0AC08224000D3A23EC93F4B4080B950F9D702224058465C001A414B4080A4897780EF2140905182FE42454B402023DA8EA9EB2140B8E3310395454B40405A80B6D5E42140D0FA5B02F0454B40C05CA8FC6BE12140009700FC53464B4060BC9179E4D7214058853FC39B474B40000341800CD52140D800DE0209484B40E0C77C40A0B32140A8BC5642774F4B408018213CDAA02140580438BD8B554B40E0B0A6B2289C2140104E2844C0574B40A053E57B4682214028E78BBD175B4B40A07C410B0978214060F5F23B4D5C4B40605A80B6D564214058853FC39B5F4B4020861DC6A44F21409060C77F81664B40E0A6B1BD164C2140B06E2EFEB6674B40208A592F864A2140A8B393C151684B40209CDF30D1482140E073D2FBC6694B4000A5A2B1F6472140B0B05241456B4B40803D26529A25214000D6E3BED56C4B402077D7D990272140B0AD11C1386E4B40C0627FD93D292140887555A0166F4B4000BEA4315A172140005E11FC6F6F4B4040AF777FBCC7204018CCD1E3F76E4B408014AE47E19A204008E52840146E4B40205DC136E29920406031957EC26D4B4060E2AC889A98204000240C03966C4B40A0129F3BC1962040F8264D83A2694B40C068ACFD9D952040100341800C654B40C08EC70C5496204058F5F23B4D644B4060AA0B7899992040286211C30E634B40205DC136E299204038F04E3E3D624B4080737E8AE3982040608E0244C15E4B40A0B3CEF8BE982040E0C43BC0935E4B40C0C77C40A093204060FB743C665E4B40607D5A457F902040286E15C4405F4B40A017EFC7ED8F204058853FC39B5F4B4020861DC6A48F204028172AFF5A604B4020861DC6A48F2040584CDE0033634B40000AF5F411902040502E54FEB5684B4000301004C890204090992842EA6A4B40200341800C9520408081204086724B40C05626FC5297204088423D7D04744B40407A19C5729B2040E0C43BC093764B404009C380259F2040E0B2B5BE48784B402009C38025BF20405870784144844B40C023F3C81FC4204038327381CB854B4000F1D8CF62C92040D8F19881CA864B4040D367075CCF2040306E15C440874B40201E8A027DD22040586D37C137874B40C01A3048FAE42040D8F19881CA864B4020B0743E3CEB20406076FA415D864B40E07F828B15ED204050499D8026864B40A094490D6DE0204030E78BBD17834B40A0BC9179E4D72040888AE3C0AB814B40C0AA24B20FD2204078ABAE4335814B40A032384A5ECD204000E2E7BF07814B40E0622AFD84CB20408018213CDA804B4020E3A7716FBE2040386E15C4407F4B40C0E4D4CE30B5204030232E008D7C4B4000EE974F56B42040809065C1C47B4B402090DB2F9FB42040E873D2FBC6794B40C010018750D5204008A986FD9E764B40201BD5E940D620408890BA9D7D754B4060CE893DB4D72040B0FB5580EF744B40C0D7497D59DA2040886F456282744B40A0499BAA7BDC2040C03176C24B744B40C0C16D6DE1E9204060130B7C45734B402002BA2F67EE204098A8893E1F734B4020BBEF181EFB204060130B7C45734B40E05DDA7058322140503D997FF4734B400009522976342140B0FB5580EF744B404041F2CEA134214068DC460378754B40C070033E3F5421404816A243E0744B40A0EA56CF495F2140306211C30E734B4080C422861D662140B853E57B46724B40609BC6F65A70214088A2EBC20F724B40C03579CA6A8221402835B401D8724B40002A8E03AF862140306211C30E734B40E05DDA7058922140F8DEA63FFB734B40E017080264A82140B89ECC3FFA744B40602F3201BFAE214090DBDAC2F3744B40A0C554FA09D72140D80CE2033B744B40C0CF0D4DD9E12140B07A32FFE8734B40C05FE97C78562240908D2441B86E4B40A0D03FC1C5722240805182FE426D4B408009DCBA9B772240E00CE2033B6C4B40A0716F7EC3742240D0D03FC1C56A4B408009DCBA9B772240E0C1FA3F87694B40604278B4717C22406001F73C7F684B40E0CF0D4DD9812240F020CB8289674B4080A4897780AF22403820ED7F80674B40E0C98B4CC0B722408021E4BCFF674B4020F52D73BABC224088457EFD10694B4060B5DD04DFBC22405073B9C150694B4000D00D4DD9C12240386BD443346A4B40205C8FC2F5C8224090992842EA6A4B40E0ED974F56D42240B06BED7DAA6A4B404006BAF605E42240F88A6EBDA6694B40C053E57B46E22240E07C957CEC684B40A021E4BCFFDF224000BB9A3C65674B406018213CDAE02240F8298E03AF664B40606552431B282340888AE3C0AB694B40406BD44334522340889C69C2F6674B40006BD443349223407887A2409F644B40E020CB8289C72340B09ECC3FFA644B40601EA33CF3CA2340D0B5F63E55654B4040573F36C9CF234000A0C37C79654B4000B6F63E55D52340885182FE42654B402009C38025DF2340E0A6B1BD16644B40603BFBCA83EC2340C8B837BF61624B40C0AA24B20FF22340B05CA8FC6B614B40C04B546F0DF423408818213CDA604B40E0A16131EA122440F05A423EE8554B402015C78157132440C82B103D29554B4000BFB9BF7A142440B001D88008514B40204E7CB5A3102440A8A44E4013474B4000809BC58B052440202CF180B2434B40602CB64945032440884B00FE29434B4080DF14562A002440A8CCB1BCAB424B4000013274ECF02340285C8FC2F5404B40E00E45813EC9234000CD203EB03D4B40605FD04202BE2340D888997D1E3D4B40E05417F032B32340E0B5F63E553D4B4000301004C8B02340805182FE423D4B4060573F36C9AF2340303B3602F13C4B40A017EFC7EDAF234028232E008D3C4B40E00B040132B4234050FEB5BC723B4B40201077F52ABA23405882FE428F3A4B4020EC6AF294BD2340D08BDAFD2A3A4B40800F5EBBB4C12340583D997FF4394B40C0F0D8CF62C9234000068200193A4B40A0FDD7B969032440004BE7C3B33C4B40C07A32FFE8332440D0C43BC0933E4B4080B3CEF8BE382440908D2441B83E4B40E0D8D0CDFE402440002A8E03AF3E4B4040240C0396BC2440F84D2844C0374B40A04D637B2D38254060499D80262E4B408023F3C81F44254038D505BCCC2C4B4020AE65321C472540A059677C5F2C4B40000F45813E4925407815E0BBCD2B4B40202C9D0FCF4A2540884B00FE292B4B40A076BF0AF04D25406055A181582A4B40202DCF83BB5B25409021E4BCFF274B402009C380255F254060853FC39B274B40A03E3C4B90612540B8BC564277274B408074B0FECF69254020F38FBE49274B4000F2ECF2AD872540286E15C440274B4020D367075C8F254010BB9A3C65274B404015C78157932540580ABABDA4274B406054FEB5BC9A2540B8B393C151284B4020D6A88768A42540B85CA8FC6B294B4040F2ECF2ADA7254038D8463CD9294B4000D68F4DF2AB254090812040862A4B4020861DC6A4AF25400015C781572B4B4040CDE50643C52540009700FC532E4B40E08C9AAF92DF254048465C001A314B4080F4143944E42540E00F238447314B40206E15C440E72540100F45813E314B40A0978A8D79F52540582E54FEB5304B40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('GR','GR','GRC','300','Greece','12890','11099737','150','39','21.766','39.666','0106000020E6100000440000000103000000010000000D000000B0F8F884EC2038401048A643A76D4140B0F8F884EC2038400021CB828967414070DC2A88811E3840888461C092674140C0B5F63E55153840D0C1FA3F87694140B0EF3504C71138406082FE428F6A4140C001BC051210384038E78BBD176B4140107A19C5720B384038D505BCCC6C4140B0622AFD840B3840D0B5F63E556D4140406C06B820133840D809A1832E6F4140A0FE7A85051B3840E076137CD36E414010861DC6A41F3840E8AC33BE2F6E4140702E54FEB5203840E07FD6FCF86D4140B0F8F884EC2038401048A643A76D41400103000000010000000E000000E03FC1C58AE63A40D8FA5B02F0AD4140B05CA8FC6BE13A4028DEC83CF2AB414020904C874EDB3A4088397AFCDEAC414020990F0874DA3A40D088997D1EAD41400073F4F8BDD93A405831957EC2AD4140D0C1FA3F87D93A40580ABABDA4AF4140901B62BCE6E53A405031957EC2B54140B0F27684D3E63A40E07FD6FCF8B5414080F1D3B837FF3A4058853FC39BB74140002C2CB81F043B40C05626FC52B74140C004FD851E053B400809C38025B74140808461C092FF3A40F82CCF83BBB3414040DB87BCE5F63A40B053E57B46B24140E03FC1C58AE63A40D8FA5B02F0AD4140010300000001000000F00000008015E0BBCDDB3740C8D03FC1C5C24140F0CABDC0ACF8374010D9243FE2C14140A077F17EDCFE3740303E7782FDC14140904C4F58E209384080EBA7FFACC3414010A0353FFE0A3840B87A32FFE8C341404071C806D211384050499D8026C6414060FDD8243F1238409835B1C057C64140C0ABADD85F1238409005854199C64140C0B5F63E55153840602E54FEB5C84140200C040132143840B85CA8FC6BC94140F07876F9D6133840A874B0FECFC94140A07A32FFE81338408854C37E4FCA414090F4143944143840104BE7C3B3CA41406031957EC21538403014E97E4ECB4140E031AEB8381E384038D505BCCCCC4140E0B2B5BE48203840000341800CCD4140A0E67283A122384038D505BCCCCC4140F0A6B1BD162C384008C79E3D97CB4140D031AEB8382E3840884B00FE29CB414070A7CAF78C34384008A0C37C79C5414070A7CAF78C343840A89ECC3FFAC44140000C040132343840E0BEB9BF7AC441408017EFC7ED2F3840D80F238447C141400029EB37132F384088457EFD10C14140009A417C602B384030172AFF5AC0414050D9E90775293840D000DE0209C04140E05A0A48FB233840009D82FC6CC04140307A8B87F7203840084B033FAABF4140A09B525E2B1D384040B05582C5BF4140106FBA65871C384090CC9541B5BF414060BEA085041C3840B026FA7C94BF414020D8D5E4291B3840207EA99F37BF414070ECF659651A384048137D3ECABE4140E04E9484441A3840E8F1ED5D83BE4140F0A529029C1A384018B41EBE4CBE4140E045D1031F1B384058499D8026BE414000240C03962C384080A2EBC20FBA41400029EB37132F3840D0EE5701BEB94140002C2CB81F4438404840DAFF00AF4140D068ACFD9D45384068FB743C66AE4140205C8FC2F5483840881B62BCE6AD414040D8463CD9513840789FAA4203AD4140C068ACFD9D553840303B3602F1AC414060465C001A593840789FAA4203AD4140D0CDFE40B95D384030ED0DBE30AD414050BB5F05F8763840089700FC53AE414040DEC83CF27B3840002A8E03AFAE41401009C380257F384000DC65BFEEAE4140102A8E03AF96384008301004C8B041401073F4F8BD99384050465C001AB14140502B137EA99B3840B85CA8FC6BB14140C031AEB8389E38401006820019B24140F0A9F23D23A13840B8B0524145B34140503D997FF4C9384030F6D03E56B441407028D2FD9CF63840809065C1C4B34140A0F5B704E00B3940E0A9F23D23B14140407A19C5720B3940706649809AB04140D0420246970B394038F38FBE49AF4140D0393FC5710C3940500438BD8BAD414040D505BCCC0C3940206893C327AD41403069C537140E3940B0BF97C283AC414000938D075B103940A8A78FC01FAC4140B0E7A4F78D3339405834D6FECEAA4140D0D38041D247394010D061BEBCAA4140001B4982704D3940801EA33CF3AA414070BFD2F9F05C3940D0FD9C82FCAA4140D0656B7D91603940801EA33CF3AA4140704CDE0033633940B06BED7DAAAA4140B07A32FFE86339404855A18158AA4140A068ACFD9D65394030172AFF5AA841408009DCBA9B67394000BB9A3C65A741403069C537146E394000CD203EB0A5414060C2137AFD713940C8B5F63E55A541405028D2FD9C763940001B498270A54140E0CDFE40B97D3940B8AD11C138A64140307D5A457F903940F82F1004C8A84140F031AEB8389E3940B06BED7DAAAA4140A000193A76A83940D0F4D901D7AB4140908AE3C0ABA93940D0F4D901D7AB4140A0F4143944C439402835B401D8AA4140D05147C7D5C43940101E8A027DAA414070D6A88768C43940303E7782FDA94140B07A32FFE8C33940B0C2D84290A9414050C2137AFDC13940507C7C4276A841406040DAFF00BF3940B85626FC52A74140F042024697BB3940A8DA6E826FA641408014AE47E1BA394058499D8026A6414010990F0874BA39400848A643A7A54140F05D4BC807B93940E073D2FBC6A1414010990F0874BA3940A8AAD0402CA14140502B137EA9BB394030E109BDFEA04140C0ECF483BABC394060465C001AA14140705260014CBD3940E0C1FA3F87A1414070B60F79CBBD39408881204086A2414070B60F79CBBD3940D082177D05A34140C0D7666325BE394058790261A7A4414080A3E5400FC13940107B681F2BA4414050F9F4D896C13940901DE21FB6A2414090D2890453C1394060BF44BC75A0414030B43A3943BD394060FA25E2AD9D414060BC9179E4B7394058431B800D9C41409009DCBA9BB73940A8DDAF027C9B4140A0116DC7D4B53940089700FC53964140B0FB3905F9B53940881B62BCE6954140B0E9B303AEB73940A859677C5F944140F0B837BF61BA3940D08BDAFD2A924140700F5EBBB4C1394090C9C6832D904140A0E9B303AEC73940E0F19881CA8E41401073F4F8BDC939406076FA415D8E414080A86DC328CC394038E44A3D0B8E41409077F17EDCCE3940A89509BFD48D41409018213CDAD0394010E52840148E4140C05A0A48FBD33940F808C380258F4140107FF8F9EFDD3940B0DDAF027C9341401096CE8767E539403029B000A696414090F27684D3063A40B0ECF483BA9C4140E0D38041D2073A4080397AFCDE9C414040F04E3E3D0A3A4010D6E3BED59C4140D0D38041D2173A40F02CCF83BB9B4140A00C1D3BA81C3A40B053E57B469A414030D2C43BC0373A40D0F19881CA9E41400088BB7A154D3A40C80CE2033BA44140C0B837BF614A3A40F82F1004C89041402077D84466463A40504CDE00338B4140107FF8F9EF3D3A40D0031F831585414040D505BCCC3C3A4058F5F23B4D8441409087A2409F343A40D8D03FC1C5824140E0BEB9BF7A243A403838F581E47F4140D0DDAF027C233A40084E2844C07F414070AD4CF8A51E3A40A8A44E40137F4140C059677C5F1C3A406040DAFF007F414050C763062A1B3A400809C380257F414050D026874F1A3A40E0BB783F6E7F4140F0548847E2193A40E0B2B5BE48804140F0548847E2193A4008301004C8804140C0C1FA3F87193A40B0AAD0402C814140D03730B951183A40A874B0FECF814140E0AC33BE2F163A4028F04E3E3D82414050D505BCCCFC3940D00CE2033B8441407093A641D1983940100F45813E81414040DB87BCE5963940D07C957CEC804140000341800C953940B8656B7D91804140908461C0928F39402820ED7F807F4140908D2441B88E394038F38FBE497F4140D03A71395E8D39402829B000A67E414080FDD7B96983394010CD203EB07D4140D0A9F23D23813940B068ACFD9D7D4140A0116DC7D455394000E52840147E414030EACC3D2430394010D9243FE279414040F6D03E56043940F808C38025774140C0E3310395ED384088A52C431C774140206BD44334D238408021E4BCFF774140602E54FEB5C03840786649809A784140C03C80457EC13840F0264D83A2794140E034EF3845C33840B0A10DC0068241405055A18158C23840D00CE2033B844140F046753A90C13840E07FD6FCF885414060DC2A8881BE384060465C001A894140001B498270BD3840E073D2FBC689414060465C001AB93840F8C69E3D978B414060B950F9D7B23840B059677C5F8C4140C046753A90B13840885A457F688C4140A08461C092AF384080A86DC3288C4140505260014CAD384050431B800D8C4140C0DDAF027CA33840100C0401328C4140102A8E03AF963840885A457F688C414010301004C890384030232E008D8C4140908461C0928F384088CC07043A8D414000917EFB3A8C384028F38FBE498F414060465C001A89384030F911BF62914140B0F27684D386384030F04E3E3D92414080AEEFC341663840A89B8BBFED97414030CF83BBB3623840109D82FC6C9841404055A1815832384008274D83A2994140A0ABAE433531384008274D83A2994140809065C1C4233840A8C2D84290994140A074B0FECF1938405873B9C15099414090A2EBC20F123840109D82FC6C98414040CC423BA70D3840B8B393C151984140C04334BA830C3840B8B393C151984140B074B0FECF093840607C7C42769841401021CB82890738409018213CDA984140102A8E03AF06384050465C001A9941405055A18158F2374058F5F23B4D9C4140A07A32FFE8E33740D0FA5B02F09D41400082397AFCD23740808461C0929F414090EF3504C7D13740F820CB82899F4140809065C1C4B33740801B62BCE69D4140B0EF3504C7B13740B0E33103959D4140F0C43BC093AE3740B0ECF483BA9C4140F02E6D382C993740507FBDC2829D4140809C69C2F697374008CD203EB09D4140E0AC33BE2F963740E8AC33BE2F9E41401096CE876785374090397AFCDEA44140C004FD851E8537403829B000A6A64140800F5EBBB491374050793BC269C34140B004FD851E9537409018213CDAC84140F09FC37C7995374058F833BC59C9414020857AFA089837407815E0BBCDCB4140F0AF743E3C9B37408060C77F81CE41409015E0BBCD9B3740D0AC33BE2FCE414050BEA085049C3740E0CDFE40B9CD4140E0A6B1BD169C3740905182FE42CD414090A86DC3289C374000CADFBDA3C841400088BB7A159D374048FEB5BC72C34140D0CDFE40B99D3740B8E67283A1C24140201286014B9E3740C053E57B46C24140D0AC33BE2FA63740889C69C2F6BF4140D04D637B2DA837400821CB8289BF4140B06BED7DAAAA37403820ED7F80BF414030F6D03E56B43740604F1F813FC0414000857AFA08B83740305C8FC2F5C0414070AA0B7899B9374008C11C3D7EC1414040F04E3E3DBA374040D8463CD9C14140109A417C60BB3740881B62BCE6C54140B00D315EF3BA374028357BA015C84140F005820019BA3740A8C2D84290C9414050C422861DB63740D8B5F63E55CD414050CDE50643B53740281DACFF73D24140F0B5F63E55B53740E0FD9C82FCD24140C068ACFD9DB5374058FEB5BC72D34140A009DCBA9BB7374028ED0DBE30D541401088BB7A15BD3740F84D2844C0D74140A096E7C1DDBD3740D000DE0209D8414040861DC6A4BF37405037177FDBD7414040CDE50643C53740901B62BCE6D54140E03FC1C58AC63740885182FE42D54140B05FE97C78C63740B0ECF483BAD44140A0116DC7D4C53740B059677C5FD4414020F6D03E56C43740286211C30ED3414020F6D03E56C437405807793D98D24140E0488446B0C537408060C77F81CE4140B04D637B2DC83740584F1F813FC841408093A641D1C83740903FFCFCF7C6414060AA0B7899C93740D8AC33BE2FC641407014AE47E1CA3740500438BD8BC54140C0ECF483BACC3740206893C327C54140709C69C2F6D73740386211C30EC34140E02E6D382CD93740B8984A3FE1C241408015E0BBCDDB3740C8D03FC1C5C2414001030000000100000019000000F03730B951283B4090457EFD10B9414070D6A88768243B40884B00FE29B341402009C380251F3B40B077F17EDCB641402094BF7B47113B40D87954FCDFCB414040E109BDFE103B4030F6D03E56CC4140A0F8F884EC103B40081B498270CD4140407497C459113B408896E7C1DDCD414000763579CA1E3B40B8B6D4415ED54140A0E0F08288283B4090423D7D04DC414080AA0B7899293B40B8716F7EC3DC41401073F4F8BD293B40505260014CDD4140C0EAE5779A283B4060853FC39BDF4140C0EAE5779A283B40081E8A027DE24140305C8FC2F5283B408896E7C1DDE541406028D2FD9C363B40908AE3C0ABE94140A009DCBA9B373B4030D8463CD9E94140D0B837BF613A3B40E873D2FBC6E94140D0AF743E3C3B3B40C8C1FA3F87E9414040E78BBD173B3B40D0D38041D2E74140008E3D7B2E373B40B8716F7EC3DC41403077D84466363B40B87A32FFE8DB4140201B4982702D3B40283B3602F1CC4140909065C1C4333B4020ED0DBE30BD4140E0C1FA3F87293B40D0EE5701BEB94140F03730B951283B4090457EFD10B9414001030000000100000011000000100341800C55374000274D83A2E94140F0BEB9BF7A543740E00F238447E941402015C7815753374020F911BF62E94140407156444D4C3740203B3602F1EC4140102DCF83BB4B3740585260014CED4140F036FE4465473740E8A9F23D23F14140A0FB3905F945374010D061BEBCF24140701B62BCE6453740484CDE0033F341406028D2FD9C46374030E78BBD17F3414050BC9179E4473740B0B915C26AF2414040CC423BA74D374028266F8099F14140F09C82FC6C50374088457EFD10F14140107497C4595137408893A641D1F0414080FDD7B969533740480ABABDA4EF414080F4143944543740B077F17EDCEE4140801A3048FA543740D0031F8315ED4140100341800C55374000274D83A2E941400103000000010000001E000000900C1D3BA80C3740D8C1FA3F87114240202DCF83BB0B374030F911BF62114240E0B837BF610A3740B85CA8FC6B11424040F38FBE49FF3640E08BDAFD2A12424070BFD2F9F0FC3640104BE7C3B31242402069C53714EE3640D0F19881CA16424010917EFB3AEC364000D3A23EC9174240D0C1FA3F87E93640D0C1FA3F87194240000F45813EE93640503D997FF419424000857AFA08E83640503A58FFE71C4240C0B5F63E55E53640382F3201BF28424030ED0DBE30E53640508BC1C3B42942401088BB7A15ED3640B0B393C151304240107FF8F9EFED3640B8656B7D91304240F0C77C40A0F33640B05CA8FC6B31424050CDE50643F53640D8F71A82E330424020809BC58BF53640587C7C4276304240701A3048FAF43640B0B393C151304240D03730B951F83640D8B5F63E552D424050B5DD04DFFC364038266F8099294240001B498270FD3640000F45813E294240D05CA8FC6B013740885704FF5B274240101E8A027D0237401009C3802527424050ED0DBE3005374038DB87BCE5264240701B62BCE615374078ABAE4335214240703D997FF4193740E0D38041D21F4240407A19C5721B3740606D37C1371F4240102DCF83BB1B3740F89600FC531E424060AD4CF8A50E37405082FE428F124240900C1D3BA80C3740D8C1FA3F8711424001030000000100000011000000F03383F8C0D6394020232E008D2C424030780AB952C73940D80CE2033B2C424080C075C58CC43940007C293C682C4240206893C327BD3940101B4982702D424010904C874EBB3940B8DA6E826F2E4240204087F9F2BA39402099D53BDC2E4240204087F9F2BA3940F0F36DC1522F42402037C478CDBB3940B0B393C15130424070D6A88768C4394070B130444E3342400096CE8767C53940A09BFD8172334240307B4B395FCC39400812F8C3CF314240A0BB253960DB3940D8FA5B02F02D4240A0BB253960DB3940101B4982702D4240D04BC5C6BCDA3940D8031F83152D4240103F558506DA394088724D81CC2C4240D05D4BC807D9394058888043A82C4240F03383F8C0D6394020232E008D2C42400103000000010000000E00000050CE177B2F663940001E8A027D324240000341800C653940001E8A027D324240A00DC00644643940D8D03FC1C532424070431B800D643940382CF180B2334240000C040132643940D00CE2033B344240D05147C7D564394008240C039634424090116DC7D4653940B0ECF483BA344240A0F27684D3663940B0ECF483BA344240306552431B68394038232E008D344240305C8FC2F56839406070784144344240E05D4BC807693940D8B22781CD334240C00391459A68394070B130444E334240709C69C2F6673940D8BBEA01F332424050CE177B2F663940001E8A027D3242400103000000010000002D00000010F911BF62C93B40303E7782FDF1414010857AFA08C83B40583D997FF4F14140A0716F7EC3C43B40D8B837BF61F24140502B137EA9BB3B408887A2409FF44140901EA33CF3BA3B40603A58FFE7F441407081204086BA3B40E0B5F63E55F54140107CB779E3B83B405040DAFF00F74140406552431BB83B40109D82FC6CF84140F0CABDC0ACB83B40D8C1FA3F87F9414050E78BBD17BB3B40485260014CFD4140D0ED26F8A6BD3B40B8B6D4415E0D4240504F1F813FB83B40D8EEC9C342154240F05E7D3CF4C93B40D8EB884336204240A0E3310395CD3B405055A18158224240101286014BCE3B40B8E67283A122424050D4997B48E03B40201ADD41EC28424060D7DAFB54E53B4080812040862A424090CC79C6BEE83B40B0DDAF027C2B4240D03C80457E113C40E0F4D901D733424040840EBA841B3C40B0E3310395354240200341800C353C4058672783A3384240C0FB3905F9353C40D0D90242EB3942401081CD3978363C40E0F10A444F3A4240206E15C440373C40B0A4C002983A4240206552431B383C40101E8A027D3A4240209694BBCF393C40303E7782FD39424090F5B704E03B3C40A89E3E027F38424080D87DC7F03C3C40D809A1832E374240801A3048FA343C4080008BFCFA2B4240D058FB3BDB2F3C409898BC0166264240000C040132243C40D8BBEA01F31A424040DD5CFC6D1F3C406070EA03C917424050D4997B48103C40503448C1530E42406055A18158023C408893A641D1084240F05B3CBCE7F43B40B0CEDC43C205424080ACE0B721F23B40605B23827104424050DC2A8881EE3B4050DA1B7C61024240809C69C2F6E73B40A85FE97C78FE414070C422861DE63B4088397AFCDEFC414080A7CAF78CE43B40D0FD9C82FCFA4140C0E3310395DD3B40B05626FC52F7414050D2C43BC0D73B40383B3602F1F4414020DB87BCE5D63B40580DFB3DB1F44140A0ECF483BACC3B405055A18158F2414010F911BF62C93B40303E7782FDF14140010300000001000000130000002081CD3978663B40A8E9B303AE2F424060CDE50643653B40888461C0922F4240307497C459513B4008240C039634424090A86DC3284C3B40888192020B364240207A19C5724B3B40603448C153364240002DCF83BB4B3B4030205F42053B424080B262B83A4C3B40B09BFD81723B4240C0E33103954D3B4050431B800D3C4240E04BC5C6BC5A3B40809FAA42033D4240B0F5B704E05B3B40D8D6C1C1DE3C4240B0ECF483BA5C3B409087A2409F3C4240307E8CB96B713B408087A2409F344240A0ACE0B721723B40A0923A014D344240C01F46088F723B40309C16BCE8334240101E8A027D723B4060793BC26933424000938D075B703B4010068200193242409014AE47E16A3B40E0EB884336304240309694BBCF693B401823A0C2113042402081CD3978663B40A8E9B303AE2F424001030000000100000018000000B00EF27A30753940F84AE7C3B32A4240201E8A027D723940D0066003222A4240A0963C9E966B3940888A389D642B424010FF7744856239409895B4E21B2C424070BB2539606B3940B098BC01662E4240A083D904186E394090020B60CA324240A0BF97C2836A39400045F30016374240509ACDE3306439400061527C7C3A42402099D53BDC5E39401015C781573B424060DC2A88815E3940002DCF83BB3B4240B0DA6E826F5E3940100C0401323C4240A00A7F86375F394050E09D7C7A3C424050B81E85EB613940E0031F83153D42403081CD3978663940A8ECF483BA3C42401037C478CD6B394080A86DC3283C4240101B4982706D39405864E602973B4240901683876973394080ABAE43353942400045D7851F743940D0F71A82E33842409014AE47E17A3940D0EEC9C342354240F05CDF87837C3940D00CE2033B344240306893C3277D394080992842EA324240A0A86DC3287C3940301D1EC2F82D4240206552431B783940887B1002F22B4240B00EF27A30753940F84AE7C3B32A42400103000000010000001B000000002BC0779B573A408093A641D1404240207E8CB96B513A40786649809A4042400043C879FF4F3A4050672783A34042404098A3C7EF4D3A40807E5182FE40424040C8957A164C3A4000FAEFC16B414240F0548847E2493A40D8F10A444F42424060D9E90775493A40F84AE7C3B342424050CDE50643453A40E009A1832E4742407085B18520433A4078758E01D9494240C01F46088F423A40D8D03FC1C54A4240F0D03FC1C5423A4070B130444E4B4240504CDE0033433A40F02CCF83BB4B4240109C16BCE8433A40E0DF8442044C4240207497C459613A40C85E7D3CF4514240B0F06778B3623A40303E7782FD514240A09C69C2F6673A4020473A0323514240A093A641D1683A40281ADD41EC50424070D7DAFB54753A40D85B3CBCE74C4240203D4679E6753A4038232E008D4C424030956247E3783A40888D96033D4A4240E00391459A783A40B0A10DC0064A4240105A9E0777773A4030111AC1C649424080D53C47E4673A40A8380EBC5A484240408DD13AAA5A3A40081E8A027D424240A008707A175B3A40485E64027E414240A008707A175B3A407803CC7C07414240002BC0779B573A408093A641D140424001030000000100000015000000E055BABBCEDA3B40B0DDAF027C43424090A52C431CD73B40604CDE0033434240C0FFACF9F1CB3B402829B000A646424060DA1B7C61CA3B40E009A1832E474240309221C7D6C33B4030266F8099494240C05147C7D5C43B40E0FD9C82FC4A42401043C879FFCF3B40101808026450424060C93846B2D33B400806820019524240408A90BA9DD53B40F81D8A027D524240F0548847E2D93B407884D38217534240F03F87F9F2DA3B40204DBC033C53424040C8957A16DC3B40204DBC033C534240C0E3310395DD3B4008068200195242409096E7C1DDDD3B4000274D83A251424050DD5CFC6DDF3B40F8298E03AF4E424050D4997B48E03B408087A2409F4C424020938D075BE03B402844F982164C4240A001BC0512E03B40503D0B4279454240309012BBB6DF3B4028C0B0FCF9444240E04CF73AA9DB3B40282CF180B2434240E055BABBCEDA3B40B0DDAF027C43424001030000000100000014000000E034EF3845F3384000C79E3D974B424070A2EBC20FF2384000C79E3D974B4240A00C1D3BA8EC384038DEC83CF24B424060D026874FEA384058F5F23B4D4C4240209A417C60DB3840805D86FF74514240703D997FF4D9384078A2EBC20F52424090E9B303AED7384050FEB5BC72534240D05626FC52D73840D8F4D901D7534240306E15C440D7384020F6D03E5654424010857AFA08D8384010BEDBBC71544240A0FE7A8505DB3840A8ECF483BA544240D0A6B1BD16DC384030D505BCCC544240D0DA6E826FDE384060888043A854424060CAA48636F0384030E109BDFE50424040431B800DF43840F820CB82894F424070D6A88768F438400009C380254F42401077D84466F63840600DFB3DB14C424070C422861DF63840B8A78FC01F4C4240E0B5F63E55F53840E0F4D901D74B4240E034EF3845F3384000C79E3D974B42400103000000010000001000000050BB5F05F816394020473A032351424070C93846B2133940D0F71A82E350424060CBD6FA2211394020473A032351424060D4997B48103940A01AF67B6251424000938D075B103940D0D90242EB514240A0073E062B1A3940202F3201BF584240100C040132243940E0C77C40A05B424060D7DAFB54253940F82CCF83BB5B42409001BC0512303940F82CCF83BB5B424050CAA48636303940B0DDAF027C5B42402009C380252F3940D8F10A444F5A4240406552431B28394000FD304278564240A0E67283A122394030232E008D54424080C6F7C5A51E3940204DBC033C53424050E3DEFC861939400012F8C3CF51424050BB5F05F816394020473A03235142400103000000010000000D000000002F6D382CC93540089700FC535E42402077D84466C635404873B9C15059424050D6A88768C43540D873D2FBC659424050EACC3D24C03540604CDE00335B4240C06E2EFEB6BF354008C79E3D975B424020861DC6A4BF354060431B800D5C42405037177FDBBF3540B0BF97C2835C424070B81E85EBC13540B8B393C15160424050CF83BBB3C2354000CADFBDA360424060B08D78B2C3354000CADFBDA3604240B0E0F08288C835401009C380255F424060465C001AC93540E876137CD35E4240002F6D382CC93540089700FC535E424001030000000100000017000000E0548847E2693840B8BF97C28354424020895E46B1543840504CDE003353424050B08D78B25338401015C78157534240306C06B820533840886308008E534240A0E67283A152384010BEDBBC7154424040CF83BBB3523840001B498270554240F08D3D7B2E573840A09509BFD45D4240F0847AFA08583840E876137CD35E424030F911BF625938402820ED7F805F424050D026874F5A3840B86E2EFEB65F424080FDD7B96983384028F04E3E3D62424020DB87BCE586384028F04E3E3D624240002F6D382C89384008D9243FE2614240307156444D8C384088ABAE4335614240A00C1D3BA88C38407893A641D160424070BFD2F9F08C3840808AE3C0AB594240C059677C5F8C3840B0E0F08288584240009A417C608B384050853FC39B574240C0B837BF618A3840508E0244C1564240F072F4F8BD89384058FB743C66564240F07BB779E388384058499D802656424000068200197A384000D6E3BED5544240E0548847E2693840B8BF97C28354424001030000000100000011000000B0F06778B362394058793BC269534240E0420246975B39405882FE428F524240D0F3A8F8BF57394058793BC26953424070BB5F05F8563940002DCF83BB534240206BD44334423940505260014C5D4240106211C30E43394008274D83A2614240C0C77C40A04339401006820019624240E049B6BA9C463940E0DF844204644240105A9E0777473940607078414464424090E33103954D3940889FAA42036542403099D53BDC4E3940D85B3CBCE7644240D0DDAF027C53394078B130444E634240504F1F813F68394028179CC1DF5B4240A0E0F08288683940806308008E5B424060D6A887686439409087A2409F54424080C93846B2633940886308008E534240B0F06778B362394058793BC26953424001030000000100000012000000A08AE3C0ABA93840A8E9B303AE5F4240B0EAE5779AA83840888461C0925F424030E44A3D0BA6384060853FC39B5F4240A018213CDAA03840A89B8BBFED5F4240A021E4BCFF9F384088C9C6832D6042409077F17EDC9E3840E0F71A82E3604240E0A6B1BD169C3840D8C77C40A0634240900C1D3BA89C384058431B800D644240808D2441B89E384080397AFCDE644240906E2EFEB69F3840000341800C65424060D6A88768A43840B89ECC3FFA64424060CDE50643A5384038D505BCCC64424070D026874FAA3840109A417C60634240D042024697AB384028F04E3E3D624240102DCF83BBAB3840D00F238447614240D042024697AB3840302F3201BF60424000990F0874AA3840809C69C2F65F4240A08AE3C0ABA93840A8E9B303AE5F42400103000000010000000C00000070B950F9D7B235405828D2FD9C5E424000274D83A2B13540C8C43BC0935E4240206BD44334B23540B0984A3FE16242400082397AFCB2354008240C039664424040F6D03E56B43540E07FD6FCF8654240F00241800CB53540081286014B66424000990F0874BA354000A0C37C79654240A081204086BA3540889FAA4203654240A000193A76B835406007793D98624240A09C69C2F6B73540E08BDAFD2A624240C0DDAF027CB33540903FFCFCF75E424070B950F9D7B235405828D2FD9C5E4240010300000001000000120000007040DAFF008F3840B8B0524145634240C0ECF483BA8C3840884B00FE29634240009A417C608B3840E8AF743E3C634240F072F4F8BD8938409015E0BBCD634240206552431B88384010D6E3BED5644240E0488446B08538403041B8020A6742401096CE8767853840909C69C2F66742401096CE8767853840805D86FF7469424070116DC7D4853840603D997FF46942400009C380258F384000240C03966C42408021E4BCFF8F38409087A2409F6C42401021CB828997384000D061BEBC6A424020F911BF62993840805D86FF74694240F03730B95198384008BB9A3C65674240A0E9B303AE97384078AEEFC341664240B07A32FFE893384058431B800D644240506C06B820933840809065C1C46342407040DAFF008F3840B8B05241456342400103000000010000000D000000E052793BC2753940080F45813E69424070C93846B2733940787E5182FE684240208FE046CA6E39408803CC7C07694240D0420246976B3940C85E7D3CF4694240202DCF83BB6B3940F81D8A027D6A424080A86DC3286C3940D8FD9C82FC6A4240C01AF67B62793940306E15C4406F424050D158FB3B7B3940A0AA4203B16C4240102DCF83BB7B3940087C293C686C4240102DCF83BB7B3940787B1002F26B4240C04BC5C6BC7A3940084BE7C3B36A4240F0058200197A39405055A181586A4240E052793BC2753940080F45813E6942400103000000010000000C000000D0C77C40A0D33940D8B22781CD63424070BB253960CB39400812F8C3CF614240901A3048FAC4394078758E01D9614240A0992842EAC23940306BD44334624240A01C058882BD3940906308008E634240202E01F8A7BC3940F87B293C6864424080A99F3715BD394080724D81CC644240B0FC6B79E5D639405864E602976B424080AEEFC341F6394080758E01D9714240F03E558506FA39402838F581E46F4240E04CF73AA9EB394018205F42056B4240D0C77C40A0D33940D8B22781CD63424001030000000100000024000000306E15C440F73A40306E15C440574240E0CABDC0ACF83A40808192020B564240F0599E0777F73A4010E5284014564240D05A0A48FBF33A40A8DA6E826F5642405075C93846F23A4078FD497CEE564240207156444DEC3A4058DA1B7C615A4240002DCF83BBEB3A40586DA983BC5A424050C763062AEB3A4098C85A43A95B4240204087F9F2EA3A40D0CABDC0AC60424050BEA08504EC3A40F8F9EFC16B614240A08461C0920F3B40E0E847C3296B4240A0BE66B96C103B4050378941606B424090DEFFC709273B408893A641D1704240B0FE7A85052B3B40B0C2D84290714240201B4982702D3B4020111AC1C67142408093A641D1483B40A8B0524145734240A0AF21382E573B404873B9C15071424090CC79C6BE583B40F82F1004C870424070D026874F5A3B40A8A70183A46F4240B0FE7A85055B3B40508E0244C16E4240104087F9F25A3B40E0FA5B02F06D4240406552431B583B40A8ECF483BA6C4240A017B5FB55543B4030179CC1DF6B4240001B4982704D3B40504CDE00336B42402021CB8289473B40D0D03FC1C56A4240001286014B3E3B4070758E01D969424080D53C47E4373B40301ADD41EC684240000F45813E093B4088A2EBC20F62424080AF21382E073B40D8EE5701BE614240405FD04202FE3A4088C9C6832D604240B0FE7A8505FB3A4060853FC39B5F4240A01AF67B62F93A40A8A44E40135F4240A093A641D1F83A40608E0244C15E4240B019C40776F83A4080AEEFC3415E4240C036FE4465F73A4070A2EBC20F5A4240306E15C440F73A40306E15C4405742400103000000010000000D000000001286014BAE3940081808026470424090B262B83AAC394090C9C6832D70424070B5DD04DF9C3940202F3201BF70424080A86DC3289C3940D0E2C5C210714240A0FFACF9F19B3940505E64027E71424000541C075E9D3940302922C32A724240E00050C58DA33940E0C77C40A0734240B0FC6B79E5A6394080008BFCFA73424050D158FB3BAB394000E869C020734240C0FFACF9F1AB3940A0D11DC4CE7242403099D53BDCAE394030473A0323714240F041960513AF3940D8CABDC0AC704240001286014BAE3940081808026470424001030000000100000010000000F0C77C40A013394078758E01D97942406055A181581239404852D2C3D078424020274D83A2113940200588821979424060BB5F05F8063940506A6803B07D42403077D84466063940888192020B7E4240C0052FFA0A063940F8F62004E47F424050CE177B2F063940503ACAC16C804240E049B6BA9C063940301ADD41EC80424080CC79C6BE083940C89750C1E18142402098A3C7EF0D3940D8DF844204844240708D2441B80E3940B0923A014D844240708461C0920F3940A802603C83844240C00DC00644143940085E11FC6F85424080C1A73979153940085E11FC6F85424090AEEFC341163940808A558330854240F0C77C40A013394078758E01D97942400103000000010000001500000090AEEFC341B6384010C79E3D9773424050CDE50643B5384010C79E3D9773424070B81E85EBB1384030ED0DBE30754240C077F17EDCAE3840B0A44E4013774240D05D4BC807A93840381A6B7F677D4240007976F9D6A33840082DCF83BB834240002C2CB81FA43840301A6B7F67854240109700FC53A63840A8E331039585424070D9E90775A93840585260014C854240F05A0A48FBB338408815E0BBCD834240503A58FFE7B43840886308008E83424030CC423BA7BD3840F8DB65BFEE7E424000763579CABE384078AEEFC3417E4240B07A32FFE8C33840A86BED7DAA7A424070F4143944C43840B053E57B467A424020F6D03E56C43840D073D2FBC679424040431B800DC4384088ABAE433579424050B950F9D7C23840109D82FC6C78424090F5B704E0BB3840B068ACFD9D75424030F911BF62B93840500DFB3DB174424090AEEFC341B6384010C79E3D9773424001030000000100000010000000108C9FC6BDF93A40503448C153764240504F1F813FF83A40503448C1537642405075C93846F23A40D8F19881CA764240209C508880EF3A40F8F36DC15277424010904C874EEB3A40B0AAD0402C794240A0EF3504C7E13A408893A641D1884240209BE447FCE23A40A01AF67B6289424050431B800DE43A4020111AC1C6894240003D4679E6F53A40D009A1832E874240307B4B395FFC3A400848A643A7854240507B4B395F0C3B40D809A1832E7F4240C0F6E978CC0C3B40D0F19881CA7E4240C0F6E978CC0C3B40605E64027E794240002E01F8A70C3B4050465C001A794240102DCF83BB0B3B40D8B56801DA784240108C9FC6BDF93A40503448C1537642400103000000010000000E000000208A90BA9DD53940209C16BCE88B4240801A3048FAD43940806308008E8B4240C0EF3504C7D13940282CF180B28B4240307288B839CD3940A8ECF483BA8C424060D158FB3BCB3940788A5583308D424060DA1B7C61CA3940101B4982708D4240B019C40776C8394088FD497CEE8E4240F050DB8651C839400879E8BB5B8F4240305C8FC2F5C839400021CB82898F4240F014C78157D339402023A0C21190424090B8E4B853D63940B098BC01668E4240002A8E03AFD63940385FD042028E4240B0052FFA0AD63940007C293C688C4240208A90BA9DD53940209C16BCE88B424001030000000100000014000000B001BC0512403940D8E2C5C210814240B002EE79FE30394050888043A87C424010990F08742A3940A8B6D4415E7D424070DEFFC709273940D0FA5B02F07D4240908461C0921F3940386E15C4407F4240408FE046CA1E3940888461C0927F4240004087F9F21A3940585E64027E814240C01AF67B62193940286211C30E834240104818062C193940F8FF71C284834240A010018750193940D8DF844204844240A0A86DC3281C394000F46DC15287424090DBBE47FD213940707B1002F28B4240103483F8C0263940503448C1538E4240109694BBCF293940908461C0928F4240000F45813E393940B0A10DC0069242402093533BC3443940E0EE5701BE9142409093A641D1483940583ACAC16C90424030895E46B1443940508E0244C1864240C0C77C40A0433940809FAA4203854240B001BC0512403940D8E2C5C21081424001030000000100000014000000209BE447FCE23A4008F7AE415F8C4240306893C327DD3A40080C0401328C42403083DC4598DA3A4008F7AE415F8C424060D9E90775D93A40B0BF97C2838C424090A2EBC20FD23A4050499D80268E4240901A3048FAC43A40506A6803B095424040895E46B1C43A40184A7B832F964240F05B3CBCE7C43A40E0C43BC09396424090AF21382EC73A40D800DE020998424090D53C47E4C73A40B0B393C15198424040465C001AC93A40503ACAC16C98424090A2EBC20FD23A40909C69C2F69742408014AE47E1DA3A405058E20165974240102DCF83BBDB3A40D809A1832E974240307156444DDC3A40F8298E03AF96424070D367075CDF3A40A0B0524145934240D00050C58DE33A40301D1EC2F88D4240709065C1C4E33A40789FAA42038D4240E0C77C40A0E33A408887A2409F8C4240209BE447FCE23A4008F7AE415F8C42400103000000010000001E00000050C422861D763940586A6803B0754240209C16BCE8733940B0A17F828B754240D058FB3BDB6F3940A0CEDC43C2754240E057C9C7EE6E3940788192020B764240D0F3A8F8BF57394078ABAE433589424030780AB95257394020266F809989424060CC79C6BE583940386211C30E8B424070E3DEFC865939400815C781578B4240C061BEBC007F3940E058FB3BDB97424010301004C8803940B0B393C151984240A0EF3504C7813940587C7C4276984240F05D4BC8078939405873B9C15099424020068200198A3940F8F9EFC16B994240207A19C5728B3940B0957B8159994240207156444D8C394048465C001A99424000301004C89039400809C38025974240D0C77C40A0933940507FBDC28295424060CDE5064395394058E09D7C7A944240A0E0F08288983940B01AF67B62914240208C9FC6BD993940586D37C1378F4240208C9FC6BD993940488E0244C18E424040D9E90775993940586A6803B08D424070A52C431C97394000F46DC152874240A0B8E4B8539639400848A643A785424080C075C58C943940383E7782FD81424060DC2A88818E3940A8A4C002987A42409096E7C1DD8D3940888D96033D7A424080A99F37158D3940D85E7D3CF4794240F05CDF87837C3940608E0244C176424050C422861D763940586A6803B075424001030000000100000019000000505C8FC2F5883840785704FF5B97424060B3CEF8BE883840602E54FEB59042405055A18158823840B8DA6E826F8E424000938D075B8038407848BF7D1D8E4240A08D2441B87E3840908461C0928F4240305FD042027E38404837177FDB8F424080116DC7D475384028F911BF62914240A0716F7EC3743840B85CA8FC6B914240207D5A457F703840D87C957CEC9042405040DAFF006F384028172AFF5A90424070BEA085046C38404837177FDB8F4240E04BC5C6BC6A3840A89B8BBFED8F4240B0073E062B6A3840E0B2B5BE4890424040D026874F6A384008301004C89042409015E0BBCD6B384088423D7D04944240201286014B6E3840D0FA5B02F0954240F0A9F23D23713840888461C09297424080116DC7D475384090457EFD10994240D04BC5C6BC7A384030D8463CD9994240305FD042027E3840603D997FF499424050431B800D843840D8EE5701BE994240909C69C2F6873840B0656B7D91984240B0E0F08288883840904E417E36984240F07BB779E3883840D0D38041D2974240505C8FC2F5883840785704FF5B9742400103000000010000000A00000050E09D7C7AC43A4028BD6F7CED974240C0DDAF027CC33A40004E2844C0974240A01F46088FC23A403038F581E4974240409221C7D6C33A40B0AAD0402C994240D0488446B0C53A40B03E90BC739A42403077D84466C63A40606DA983BC9A4240002BC0779BC73A403835B401D89A424080C3B64599C93A40001E8A027D9A4240D0548847E2C93A4088FA08FCE199424050E09D7C7AC43A4028BD6F7CED97424001030000000100000014000000206552431B283740508E0244C19E424080069B3A8F2237406076FA415D9E424080ABAE433521374058FB743C669E4240A08461C0921F374010DC65BFEE9E4240D05D4BC807193740B06BED7DAAA24240B0EAE5779A183740386211C30EA34240A093A641D1183740B0622AFD84A3424070D9E90775193740282CF180B2A3424080035ABA821D37405070784144A44240E0C43BC0931E3740A859677C5FA44240B001BC05122037405070784144A44240201E8A027D223740D0F4D901D7A34240E03FC1C58A26374090992842EAA24240C05D4BC8072937400006820019A2424080812040862A374008C11C3D7EA1424030E78BBD172B3740E8A9F23D23A14240F04BC5C6BC2A3740282F3201BFA04240C0C1FA3F87293740D8BB783F6E9F4240C05D4BC8072937405840DAFF009F4240206552431B283740508E0244C19E424001030000000100000014000000F02E6D382C6937408860C77F81A64240B05FE97C78663740881B62BCE6A54240702E54FEB5603740B0AD11C138A64240B06E2EFEB65F37405876FA415DA642407037177FDB5F3740908D2441B8A6424040CF83BBB36237404837177FDBA74240C0E7A4F78D633740D88558FD11A8424010F04E3E3D7A3740386893C327AD4240F02B2CB81F843740F8298E03AFAE424050CDE50643853740D0F19881CAAE4240001B4982708D374038F38FBE49AF4240D04E0647C98F3740686D37C137AF4240B004FD851E953740B877F17EDCAE4240E0B5F63E559537405028D2FD9CAE4240F034EF3845933740B8E3310395AD42401000000000803740A8E0F08288A84240F028EB37137F374028172AFF5AA84240206211C30E733740D88558FD11A84240C0073E062B6A3740002A8E03AFA64240F02E6D382C6937408860C77F81A642400103000000010000001C000000D0A9F23D236138401009C38025A742409017EFC7ED5F384080A52C431CA74240A077F17EDC5E3840B05626FC52A742404069C537145E384060853FC39BA742409096E7C1DD5D3840D88558FD11A842404069C537145E3840B8AD11C138B6424090FA96395D5E3840F0298E03AFB6424090F1D3B8375F38403820ED7F80B7424040E44A3D0B663840D0D03FC1C5BA4240E05D4BC80769384030DEC83CF2BB4240F0B2B5BE4870384000CD203EB0BD4240207497C4597138400848A643A7BD42400094BF7B47713840B8716F7EC3BC4240A018213CDA7038405070784144BC4240C031AEB8386E3840806649809AB84240F057C9C7EE6E3840D0B2B5BE48B8424070C2137AFD713840606D37C137B74240F03FC1C58A763840808D2441B8B64240007CB779E37838403829B000A6B64240407A19C5727B384028F6D03E56B442408015E0BBCD7B384038DEC83CF2B34240102DCF83BB7B3840901EA33CF3B24240F08F4C874E7B3840B8B915C26AB24240206BD44334723840B89ECC3FFAAC42402083DC45986A3840808AE3C0ABA94240A0F27684D3663840804E417E36A84240108BFCFA2162384020F38FBE49A74240D0A9F23D236138401009C38025A7424001030000000100000012000000B0FFACF9F15B3940F80B040132B44240C0FE7A85055B3940B0A78FC01FB44240E05A0A48FB533940403D0B4279B5424070D367075C4F394080A86DC328BC42400009C380254F394000240C0396BC424060DD5CFC6D4F39400848A643A7BD424000938D075B503940F8FC304278BE4240D05B3CBCE754394050DD5CFC6DBF424050D9E9077559394088C9C6832DC04240102A8E03AF6639401009C38025BF4240203D4679E6753940585B238271BC4240002A8E03AF763940A8A78FC01FBC4240002A8E03AF763940C8C77C40A0BB424090B8E4B85376394028266F8099B94240B0052FFA0A76394030473A0323B94240B00EF27A30753940D0F71A82E3B84240E061BEBC005F394030232E008DB44240B0FFACF9F15B3940F80B040132B4424001030000000100000013000000107976F9D6F3384068F833BC59B14240C03DB2B96AE2384008C45DBD8AAE424030ED0DBE30E5384010BB9A3C65BF424080F4143944E43840580ABABDA4BF424060B08D78B2E338401000000000C04240C034EF3845E338400018080264C04240106211C30EE33840D00F238447C14240809065C1C4E3384038266F8099C14240007CB779E3E8384088ABAE4335C1424030D505BCCCEC384000CADFBDA3C04240D057C9C7EEEE384088C9C6832DC04240A0656B7D91F038400021CB8289BF4240800F5EBBB4F13840A877F17EDCBE4240D0DDAF027CF3384000D6E3BED5BC424060B3CEF8BEF8384008DFA63FFBB34240405C8FC2F5F83840886308008EB34240F03730B951F83840804B00FE29B3424010895E46B1F43840A0C2D84290B14240107976F9D6F3384068F833BC59B142400103000000010000000E000000E0BB783F6E7F3740786649809AC04240A0F5B704E07B37405801F73C7FC0424070B08D78B2733740B8AAD0402CC14240A0069B3A8F72374028F911BF62C14240A077F17EDC6E374088992842EAC24240F0753579CA6E374050793BC269C342408015E0BBCD7B374010D6E3BED5C442408087A2409F8437403014E97E4EC342405031957EC285374028E78BBD17C34240C0FB3905F9853740A86BED7DAAC24240F05A0A48FB83374008274D83A2C14240201E8A027D82374010E2E7BF07C1424020274D83A28137408093A641D1C04240E0BB783F6E7F3740786649809AC042400103000000010000001B00000000990F08743A3940007C293C68C4424040895E46B1343940B0DDAF027CC3424090ACE0B721323940080072C284C34240B008707A172B3940000C040132C44240306893C3271D39405061A5828AC64240808D2441B8FE3840883CBB7CEBD142402083DC4598FA384030D505BCCCD4424050AA0B7899F93840285FD04202D64240C074B0FECFF93840B85FE97C78D642405034D6FECEFA38406028D2FD9CD64240B0F06778B3023940908D2441B8D64240C055BABBCE0A3940A8C519C39CD6424090CFBA46CB0D3940F081AB3C81D64240106211C30E133940F8FF71C284D3424050CDE506431539407884D38217D342406085B185202339408881204086D2424060D367075C2F3940302922C32AD2424000301004C830394078A2EBC20FD24240A0F27684D3363940281ADD41ECD04240406893C3273D394050853FC39BCF424050D367075C3F39403829B000A6CE4240B001BC0512403940583448C153CE4240207497C459413940082DCF83BBCB4240407E8CB96B413940606DA983BCCA424080B5A33847413940808D96033DCA424000904C874E3B394058888043A8C4424000990F08743A3940007C293C68C442400103000000010000001D000000C0393FC5714C3840009A417C60C34240D05D4BC807493840884B00FE29C34240A009DCBA9B473840A8B0524145C3424030DB87BCE546384008C79E3D97C34240D05FE97C7846384010DFA63FFBC34240603A58FFE7443840109A417C60CB4240200341800C453840A87A32FFE8CB424030E44A3D0B4638408096E7C1DDCD4240002A8E03AF4638405840DAFF00CF4240306552431B48384038172AFF5AD04240E02E6D382C493840080F45813ED14240A059677C5F4C3840D8F4D901D7D34240709FAA42034D3840100C040132D44240809065C1C4533840508E0244C1D64240C068ACFD9D5538401009C38025D74240A074B0FECF593840B05626FC52D74240205FD042025E3840B05626FC52D7424000763579CA5E3840B05626FC52D74240703A58FFE7643840E0AC33BE2FD6424080F755B950693840D8F4D901D7D3424080F755B950693840089A417C60D34240D0488446B0653840386E15C440CF4240A087A2409F64384058FB743C66CE424010274D83A2613840885A457F68CC4240D028EB37135F3840901EA33CF3CA424030CC423BA75D38408054C37E4FCA4240B0656B7D915038408087A2409FC44240E028EB37134F384058431B800DC44240C0393FC5714C3840009A417C60C342400103000000010000001900000050D7DAFB54053A4080758E01D9C14240A0FFACF9F1FB3940E0F71A82E3C04240A008707A17FB394028473A0323C142401006820019FA3940E0D90242EBC14240208C9FC6BDF9394058DA1B7C61C2424070E3DEFC86F93940A89BFD8172C3424070E3DEFC86F93940D0DF844204C4424080BB253960FB39400048A643A7C54240A0FFACF9F1FB3940385FD04202C6424060BEA085040C3A408078CF81E5CE4240107D5A457F103A4050672783A3D04240307E8CB96B113A40D0F71A82E3D0424020895E46B1143A40A8957B8159D142400043C879FF4F3A402041B8020AD74240D05E7D3CF4593A40D058FB3BDBD74240E0393FC5715C3A403838F581E4D7424020240C03965C3A40A0BC564277D74240207156444D5C3A40D8DC43C2F7D6424080BB2539605B3A4008E5284014D64240E0D03FC1C5523A40080F45813ED14240D057C9C7EE4E3A40606D37C137CF4240001B4982704D3A403829B000A6CE424070E09D7C7A443A40A8C85A43A9CB424080DEFFC709373A40F820CB8289C7424050D7DAFB54053A4080758E01D9C14240010300000001000000130000002015C78157833740A8E0F08288D84240D0393FC5717C3740082A8E03AFD64240703D997FF479374008DC65BFEED6424060BB5F05F876374020EACC3D24D8424060DC2A88816E37409096E7C1DDDD4240D04334BA836C37409093A641D1E04240E0393FC5716C3740C80F238447E1424060BFD2F9F06C374030266F8099E1424060B60F79CB6D374030D8463CD9E1424050C554FA097737408054C37E4FE2424080A2EBC20F8237405807793D98E24240D06BED7DAA8A3740B86BED7DAAE2424070AD4CF8A58E3740286BD44334E24240F0928D075B90374000274D83A2E14240B0656B7D9190374080ABAE4335E1424060CAA486369037409093A641D1E04240E028EB37138F37400800000000E0424030E44A3D0B86374088A2EBC20FDA42402015C78157833740A8E0F08288D8424001030000000100000021000000A0EF3504C7113B4000E869C020DB4240A0BE66B96C103B40081E8A027DDA4240009C5088800F3B4000F12C4146DA4240A0073E062B0A3B40D85E7D3CF4D9424070CDE50643E53A40286893C327D54240407E8CB96BD13A40505E64027ED14240B002EE79FEC03A40A09E3E027FD842400042960513BF3A40E0F71A82E3D8424070C422861DB63A4008093543AADA4240A087A2409FB43A4008093543AADA4240F058FB3BDBAF3A40888D96033DDA424080B8E4B853A63A40B01AF67B62D942400045D7851FA43A4058465C001AD94240708461C0929F3A40809C69C2F6D742404099D53BDC9E3A40B0E9B303AED74240809FAA42039D3A40B0A44E4013D7424010956247E3983A409898BC0166D64240A09C69C2F6973A403029B000A6D64240F05B3CBCE7943A405070EA03C9D742409087A2409F943A408087140324D842407055A18158923A40587FBDC282DD4240C0E67283A1923A40301D1EC2F8DD424090E0F08288983A40301ADD41ECE04240B010018750993A4080ABAE4335E1424050DA1B7C61AA3A40888A558330E54240307A19C572AB3A40A8B6D4415EE54240D055BABBCEBA3A4058DD5CFC6DE74240201286014BBE3A40E0D38041D2E7424030861DC6A4BF3A40D858FB3BDBE74240406893C327FD3A402844F98216E4424050780AB952073B40D8D03FC1C5E2424060CBD6FA22113B40D8031F8315DD4240A0EF3504C7113B4000E869C020DB424001030000000100000020000000801B62BCE6E53440B8A44E4013E742405069C53714FE344010D6E3BED5DC424010861DC6A4FF3440009A417C60DB4240E0C43BC093FE3440B85CA8FC6BD94240E03C80457EF13440A0A78FC01FDC424020240C0396EC3440905182FE42DD424070D026874FEA34400048A643A7DD4240D0B5F63E55E53440B8E3310395DD42407018213CDAE0344080CC07043ADD424000763579CADE3440303B3602F1DC4240007FF8F9EFDD3440500DFB3DB1DC4240B05626FC52D73440809C69C2F6D7424070BB5F05F8D63440A0BC564277D7424050E44A3D0BD6344010D061BEBCD24240C0716F7EC3D4344010D061BEBCD242409017EFC7EDCF344058793BC269D342407040DAFF00CF3440582B137EA9D34240102A8E03AFB63440B0BF97C283DC424070431B800DB4344028327381CBDD42402094BF7B47A13440F020CB8289E74240B0656B7D91A0344010CADFBDA3E84240A08D2441B89E3440C8BEB9BF7AEC4240A0F1D3B8379F3440E0AC33BE2FEE4240A0F8F884ECA03440E08558FD11F0424020895E46B1A43440D0FD9C82FCF2424020CC423BA7AD3440B89509BFD4F54240506C06B820B33440A8A44E4013F74240B07A32FFE8B33440D0F19881CAF6424020904C874ECB344060888043A8EC4240909FAA4203DD3440D806600322EA4240A0992842EAE23440604F1F813FE84240801B62BCE6E53440B8A44E4013E742400103000000010000001B000000C06BED7DAACA384010D3A23EC9FF4240B05FE97C78F63840B0E9B303AEEF424030861DC6A4FF3840B053E57B46E24240A06E2EFEB6FF3840E873D2FBC6E1424030F38FBE49FF3840C80F238447E14240C059677C5FFC3840881B62BCE6DD4240A0116DC7D4F53840104E2844C0D7424080069B3A8FF23840682E54FEB5D84240D06BED7DAAEA384008C79E3D97DB42402006820019EA3840B07A32FFE8DB4240009C508880DF38401006820019E242409087A2409FD43840604F1F813FE84240B0716F7EC3C438403020ED7F80EF4240E05A0A48FBC33840D8D38041D2EF4240602E54FEB5C03840F89C82FC6CF04240A00C1D3BA8BC3840F82F1004C8F04240F020CB8289B7384008D3A23EC9EF42405028D2FD9CB63840A86E2EFEB6EF4240C046753A90B138402829B000A6F64240402E54FEB5B03840E873D2FBC6F9424020301004C8B038408854C37E4FFA424080ABAE4335B138406834D6FECEFA4240C03DB2B96AB23840D8C77C40A0FB424050431B800DB43840B8A78FC01FFC4240C0DA6E826FBE3840C8F19881CAFE4240208E3D7B2EC7384058853FC39BFF4240C06BED7DAACA384010D3A23EC9FF4240010300000001000000160000003077D84466763740487C7C4276F04240D0B5F63E5575374030172AFF5AF0424030CF83BBB3723740A0656B7D91F0424060B3CEF8BE6837406055A18158F24240F0D38041D26737406007793D98F24240B05626FC52673740E8A6B1BD16F44240E05D4BC80769374000DC65BFEEF64240A021E4BCFF6F3740E8AC33BE2FFE424080A86DC3287C3740B89B8BBFEDFF424080FA96395D7E3740386552431B004340E0B2B5BE488037402838F581E4FF4240D046753A90813740004E2844C0FF4240801A3048FA843740905704FF5BFF424090AEEFC341863740D809A1832EFF4240603D997FF4893740E8AC33BE2FFE4240D0B837BF618A374028327381CBFD4240C0A6B1BD168C374038F38FBE49F742407015E0BBCD8B37406040DAFF00F7424060D026874F8A3740B89509BFD4F54240D0C1FA3F87893740587FBDC282F54240D04D637B2D783740D87C957CECF042403077D84466763740487C7C4276F042400103000000010000002E00000030D505BCCC9C3440281DACFF73324340D031AEB838AE3440A8622AFD84234340D04E0647C9CF34400021CB82890F434070CAA48636D034400809C380250F4340D0B2B5BE48D034402829B000A60E43407037177FDBCF3440587FBDC2820D434040DEC83CF2CB3440B0E0F082880843409014AE47E1CA3440A86E2EFEB60743400073F4F8BDC9344050853FC39B07434080A86DC328BC344008D3A23EC907434010763579CA8E344008C79E3D970B434060D6A88768843440D088997D1E0D4340E034EF3845833440505260014C0D4340502E54FEB560344058431B800D144340D04D637B2D58344060FB743C66164340C036FE4465573440F8298E03AF16434050C554FA0957344058853FC39B174340306E15C44057344080ABAE43351943407009DCBA9B573440608BC1C3B419434070C763062A5B344000CD203EB01D434030E44A3D0B663440908AE3C0AB2943408018213CDA703440203E7782FD294340407497C45971344030266F8099294340100F45813E793440888461C09227434080812040867A3440E0BB783F6E2743409015E0BBCD7B3440B8BC564277274340B0ECF483BA7C3440580ABABDA427434030EACC3D24803440886649809A28434030D8463CD981344050465C001A294340000C040132843440503D997FF429434070F755B950893440B8A78FC01F2C4340407A19C5728B34405031957EC22D434040DEC83CF28B3440A8AD11C1382E434080A86DC3288C3440F8298E03AF2E434060BFD2F9F08C344000274D83A231434020917EFB3A8C3440281DACFF73324340B0073E062B8A3440885A457F68344340A093A641D188344000BB9A3C65374340E0CABDC0AC8834402838F581E437434070D9E90775893440E07954FCDF3B4340E025AAB7068A3440E00CE2033B3C4340B0FE7A85058B3440805A457F683C4340B059677C5F8C3440805A457F683C4340A017EFC7ED8F344060F5F23B4D3C4340206BD44334923440B87A32FFE83B434030D505BCCC9C3440281DACFF7332434001030000000100000013000000407156444DBC3440A8E9B303AE274340504F1F813FB83440A8A44E401327434060BB5F05F8B63440586D37C137274340000341800CB53440A8E9B303AE274340306211C30EB3344000CADFBDA3284340002DCF83BBAB344028ED0DBE302D4340100341800CA53440881EA33CF332434090E33103959D3440604CDE00333B4340A09FAA42039D344060431B800D3C4340D050A4FB399D34408887A2409F3C434070C422861DA63440E000DE0209404340106552431BA8344038EACC3D244043409015E0BBCDAB34401009C380253F4340D05147C7D5B43440E07C957CEC38434060CDE50643B53440A8656B7D91384340101286014BBE3440B8E9B303AE2F434060B950F9D7C2344008274D83A2294340B0E67283A1C23440B0AAD0402C294340407156444DBC3440A8E9B303AE27434001030000000100000038000000F03FC1C58A063A402029B000A6164340909065C1C4033A40F8E769C020134340E061BEBC00FF394020179CC1DF13434090CC79C6BEF83940283B3602F114434060BB5F05F8F63940081B498270154340B0F6E978CCEC3940281ADD41EC184340207288B839DD3940F881AB3C811E4340C0F6E978CCDC39408078CF81E51E4340C0F6E978CCDC3940B841D13C801F4340505260014CDD3940A89E3E027F20434070DC2A8881DE394020111AC1C6214340309012BBB6DF3940081E8A027D224340309E25C808E83940386893C327254340C0FE7A8505EB3940D0CDFE40B9254340C04E0647C9EF3940788192020B26434090B5A33847F13940788192020B2643408096E7C1DDFD3940E0DF8442042C434000541C075EFD3940D800DE0209304340307288B839FD394020473A032331434070D87DC7F0FC394028266F809931434090ACE0B721F2394000F12C41463A4340307D5A457FF03940A0D11DC4CE3A4340208DD13AAAEA3940887B1002F23B43402018080264E83940E00CE2033B3C434050D6A88768E43940007C293C683C43401015C78157E339408887A2409F3C434010314278B4E13940206893C3273D4340207B4B395FDC3940586D37C1373F43400006820019DA3940286552431B404340C0E0F08288D8394088ABAE4335414340909065C1C4D339408087A2409F444340F014C78157D33940000341800C454340604CDE0033D33940B0E3310395454340A09C69C2F6D739408803CC7C07494340D0548847E2D93940383E7782FD49434010240C0396DC3940084BE7C3B34A4340A08D2441B8DE3940286211C30E4B4340101E8A027DE2394050378941604B434010938D075B003A4030C0B0FCF94C4340D0DDAF027C233A40B0B393C151484340F049B6BA9C263A40D809A1832E4743401018080264283A40D0E506431D4643408093A641D1283A40506A6803B045434050465C001A293A40E0D6C1C1DE444340C00050C58D233A40306E15C440374340306BD44334223A40001B49827035434090ACE0B721223A4058707841443443400096CE8767253A405061A5828A2E4340C010018750293A40D0066003222A4340208C9FC6BD293A40D8EE5701BE294340100F45813E293A40A8A44E4013274340E05D4BC807293A40C8C43BC09326434090073E062B1A3A4050853FC39B1F434070465C001A093A40F802B3429118434050BB5F05F8063A40A0A44E4013174340F03FC1C58A063A402029B000A61643400103000000010000000A000000108E3D7B2EE73440B89509BFD445434080AEEFC341E63440F847A643A7454340F095CE8767E5344028327381CB454340D0AC33BE2FE634405001F73C7F484340E025AAB706EA3440B86BED7DAA4A4340808461C092EF3440D0B5F63E554D434010938D075BF0344010A0C37C794D434020E109BDFEF03440D888997D1E4D4340E04543C6A3F0344078423D7D044C4340108E3D7B2EE73440B89509BFD44543400103000000010000001100000090C3B645999939402844F98216444340E058FB3BDB8F3940807B1002F243434070BB5F05F886394030179CC1DF4B434070BB5F05F886394088931804564C4340005A9E0777873940080FB743C34C4340306F47382D883940100341800C4D434090F8F884EC9039408096E7C1DD4D43401021CB8289973940D05B3CBCE74C4340107156444D9C3940D8F4D901D74B4340809FAA42039D3940F8FF71C2844B43402098A3C7EF9D3940084BE7C3B34A4340208FE046CA9E394088FA08FCE149434080A86DC3289C3940081B498270454340B0F5B704E09B394038C0B0FCF9444340107A19C5729B394038232E008D444340408DD13AAA9A3940607078414444434090C3B645999939402844F9821644434001030000000100000013000000C0716F7EC3A43440E0B837BF614A434070C763062A8B3440504F1F813F484340801EA33CF38A3440C8CABDC0AC4843407034D6FECE8A34402814E97E4E4B434010763579CA8E34400021CB82895743401009C380258F3440D88558FD115843400026AAB7069A3440302CF180B26343407087A2409FA4344040D8463CD9694340B0FB3905F9A5344080812040866A4340F0D38041D2A73440881EA33CF36A4340B0E7A4F78DB334403035B401D86A4340D0488446B0B5344080812040866A4340306E15C440B73440583D997FF4694340D04BC5C6BCBA3440905704FF5B674340A014AE47E1BA344038DB87BCE566434020F911BF62B93440D80F23844751434040465C001AB9344090C9C6832D5043407000193A76B83440E0D38041D24F4340C0716F7EC3A43440E0B837BF614A434001030000000100000024000000C077F17EDCAE384058499D80266643405040DAFF00AF38408815E0BBCD634340101286014BAE384058FEB5BC7263434040B3CEF8BEA8384038F04E3E3D624340D068ACFD9DA53840B874B0FECF61434010938D075BA03840603D997FF46143409077F17EDC9E38400806820019624340207FF8F9EF9D38405855A1815862434050D505BCCC9C3840D882177D056343405034D6FECE9A3840A0BF97C28364434050465C001A993840C8031F831565434040D2C43BC0973840E088997D1E654340306BD44334923840A87A32FFE8634340D0A9F23D23913840D882177D05634340D0A9F23D239138406082FE428F62434010274D83A291384038F911BF6261434030CC423BA78D38405855A18158624340F07BB779E388384050F5F23B4D644340603A58FFE7743840382F3201BF704340D034EF38457338406834D6FECE724340406C06B82073384080ABAE433579434090FDD7B969733840908AE3C0AB794340A07A32FFE873384010068200197A4340C0B5F63E55753840E0AF743E3C7B434090FB3905F975384000C79E3D977B4340A0073E062B7A384078397AFCDE7C434040E78BBD177B3840D0031F83157D4340D0A6B1BD167C3840885182FE427D4340101B4982707D384028ED0DBE307D4340D04543C6A3803840A8BF97C2837C4340C046753A9081384058707841447C4340107976F9D693384008C45DBD8A764340D0B837BF61AA384008C11C3D7E6943407096E7C1DDAD3840905704FF5B674340D0DA6E826FAE38405840DAFF00674340C077F17EDCAE384058499D80266643400103000000010000006D00000070AEEFC34176374088CC07043A6D4340E0CABDC0AC783740D0F4D901D76B4340F02B2CB81F8437405037177FDB6743402021CB828997374000D9243FE2614340C07A32FFE8C33740301DACFF735A434050B3CEF8BED83740B05626FC525743405055A18158F2374000D6E3BED5544340D0DDAF027CF33740603A58FFE754434050B81E85EB01384050499D8026564340E036FE4465273840C8D03FC1C5524340B05626FC5227384038F911BF624943408017EFC7ED2F384038F04E3E3D32434030F38FBE493F384000CD203EB01D434020D8463CD9413840E87954FCDF1B4340D03DB2B96A423840B0622AFD841B4340603A58FFE7443840D88BDAFD2A1A434010240C03964C3840A8B393C151184340E0488446B0553840A8BF97C28314434090129F3BC156384058F5F23B4D14434090035ABA826D3840301DACFF73124340701B62BCE6753840E873D2FBC6114340306E15C440773840508BC1C3B4114340B074B0FECF793840908AE3C0AB11434070B60F79CB8D384080A2EBC20F124340E046753A90913840B0984A3FE1124340208E3D7B2E973840884E417E36084340406E15C440973840A86E2EFEB607434040DB87BCE596384050499D80260643407028D2FD9C963840E0031F8315054340209700FC5396384050431B800D04434040E44A3D0B963840B8DDAF027C03434070FDD7B969933840B8E0F08288004340109D82FC6C9038405076FA415DFE424030F6D03E56843840D0B837BF61FA424080FDD7B969833840C806600322FA4240E0A9F23D23813840B0A10DC006FA4240702B137EA97B38408854C37E4FFA4240D0B837BF617A3840001E8A027DFA4240506C06B820633840D809A1832EFF4240A0DDAF027C533840D8CDFE40B90543400096CE876735384058431B800D14434050E44A3D0B263840886308008E1B4340D059677C5F1C3840603A58FFE724434050D505BCCC0C3840E076137CD32E4340F0C43BC0930E38405837177FDB2F43401009C380250F3840D8B2B5BE48304340F028EB37130F384000301004C830434060AD4CF8A50E3840A8AAD0402C314340B0ECF483BA0C3840D88BDAFD2A324340107A19C5720B38408054C37E4F324340200000000000384058793BC26933434070AD4CF8A5FE374050FEB5BC72334340F0B837BF61FA374038F04E3E3D3243409000193A76F8374028D8463CD931434070CAA48636F0374010C11C3D7E31434030D2C43BC0E73740E00F238447314340F01186014BCE3740B874B0FECF314340B0FB3905F9C53740286BD44334324340B059677C5FAC3740D0BEB9BF7A34434060D6A88768A43740B868ACFD9D354340F07EF8F9EF9D374010D9243FE2394340D031AEB8389E3740E00CE2033B3C43400029EB37139F3740E0BEB9BF7A3C434020938D075BA0374080CC07043A3D4340206211C30EA337400018080264404340704CDE0033A33740D87C957CEC404340C0EF3504C7A13740E8AF743E3C43434050CAA48636A03740D8B5F63E5545434030861DC6A49F374008CD203EB0454340100F45813E993740385C8FC2F54843408000193A76983740E00F238447494340405FD042027E3740E07C957CEC504340F05147C7D55437403041B8020A5F4340404CDE00333337405055A181586A4340306BD443343237405007793D986A4340D03730B951283740E0BEB9BF7A6C4340901B62BCE625374000D6E3BED56C4340306C06B820233740E0031F83156D434060C2137AFD213740789FAA42036D434050E109BDFE20374000D6E3BED56C434070CAA4863620374028232E008D6C4340F031AEB8381E3740080C0401326C434070465C001A19374050FEB5BC726B434070CDE50643D5364060F833BC5969434070A7CAF78CD43640F8264D83A2694340E0BEB9BF7AD43640D8066003226A4340B004FD851ED53640484CDE00336B4340B05FE97C78D6364060888043A86C4340F03730B951D8364088AEEFC3416E434080F755B950D93640B8DA6E826F6E43402069C53714EE3640D00660032272434040B3CEF8BE183740781B62BCE67D434080ABAE4335213740009D82FC6C8043400021CB8289473740580DFB3DB18443409014AE47E14A3740A89ECC3FFA844340A0ECF483BA4C3740383B3602F1844340009C5088804F3740580DFB3DB1844340E04543C6A3503740E0BEB9BF7A844340D057C9C7EE5E3740305C8FC2F58043409017EFC7ED5F3740502E54FEB5804340407D5A457F60374038172AFF5A804340702E54FEB5603740B89B8BBFED7F4340109D82FC6C603740B85626FC527F43409017EFC7ED5F374038DB87BCE57E4340D04E0647C95F3740D87FD6FCF87D434060CAA48636603740D0031F83157D4340A0F8F884EC60374058707841447C4340C053E57B46723740A8E9B303AE6F434070AEEFC34176374088CC07043A6D43400103000000010000001400000000240C0396BC3740A8C2D8429089434060D9E90775B93740E0A9F23D23894340C068ACFD9DB53740905D86FF74894340A08AE3C0ABA93740E082177D058B43401018080264A83740E07954FCDF8B4340106E15C440973740D80F23844799434060C554FA09973740588BC1C3B4994340106E15C440973740D08BDAFD2A9A434020857AFA08983740201DACFF739A4340F02E6D382C9937405882FE428F9A4340C059677C5F9C374030F04E3E3D9A43408000193A76C8374030EACC3D2490434030F911BF62C937403038F581E48F4340503D997FF4C93740F820CB82898F4340F025AAB706CA3740A8A44E40138F4340808AE3C0ABC937405828D2FD9C8E4340B05FE97C78C63740B8ECF483BA8C434050ED0DBE30C5374010DFA63FFB8B434040E109BDFEC03740104BE7C3B38A434000240C0396BC3740A8C2D8429089434001030000000100000013000000106BD4433482374000BEDBBC7194434040895E46B1743740F8C9DFBDA39043404031957EC2653740B8B915C26A924340B0716F7EC36437406082FE428F924340E0BEB9BF7A643740A8DDAF027C934340E05147C7D5643740D0BEB9BF7A944340E0B5F63E55653740503A58FFE7944340C0EF3504C7713740805D86FF7499434060C422861D763740B06BED7DAA9A434050B3CEF8BE783740B8E67283A19A4340800C1D3BA87C3740C053E57B469A4340101B4982707D3740303E7782FD99434000938D075B803740282F3201BF984340900F5EBBB4813740306552431B98434090069B3A8F823740B85626FC52974340106211C30E833740A05FE97C78964340306C06B820833740E07FD6FCF895434050CF83BBB382374080397AFCDE944340106BD4433482374000BEDBBC719443400103000000010000000F000000F0D03FC1C5323440F89600FC53964340A0E33103952D3440001286014B964340D0B837BF612A3440808D2441B8964340A08AE3C0AB293440803FFCFCF79643400082397AFC223440888AE3C0AB994340F04E0647C91F344038F6D03E569C4340F0BB783F6E1F344030327381CB9D434030861DC6A41F344088AEEFC3419E4340008BFCFA212234403029B000A69E4340704CDE0033233440508E0244C19E434010F04E3E3D2A3440E0BEB9BF7A9C43409021E4BCFF2F3440303E7782FD994340106211C30E3334405837177FDB974340809065C1C43334409060C77F81964340F0D03FC1C5323440F89600FC539643400103000000010000001100000040D505BCCCDC374010C11C3D7E914340B0FE7A8505DB374008E2E7BF07914340403D997FF4D93740100F45813E91434040E44A3D0BD63740E006600322924340F095CE8767D53740901EA33CF392434040809BC58BD53740A8DDAF027C934340C0393FC571EC37406073B9C150A143401082397AFCF23740789FAA4203A54340F02B2CB81FF43740D8031F8315A54340503A58FFE7F4374040D505BCCCA44340503A58FFE7F43740D8BEB9BF7AA443408081204086FA3740B853E57B46A24340F04BC5C6BCFA3740A874B0FECFA14340F0B837BF61FA37406073B9C150A1434040DEC83CF2EB3740B077F17EDC9643400021CB8289E73740283B3602F194434040D505BCCCDC374010C11C3D7E9143400103000000010000005700000020874F3A91603A4028205F4205A34340E04F38BBB5603A40081E8A027DA2434080B5A33847613A40D006600322A2434080ACE0B721623A4078FA08FCE1A1434090E9B303AE673A40A09E3E027FA0434050E3DEFC86793A402044F982169C4340406E15C440873A40082DCF83BB93434000904C874E9B3A4030145B41D3864340A0ECF483BA9C3A400848A643A7854340101286014B9E3A401015C78157834340D0DA6E826F9E3A40A0D11DC4CE8243402098A3C7EF9D3A40E05E7D3CF4814340505260014C9D3A4028266F80998143403081CD3978863A40A8AA4203B17C434010895E46B1843A4058E09D7C7A7C43402015C78157733A40807B1002F27B4340309C16BCE8633A4098923A014D7C4340A0992842EA523A40306893C3277D43402043C879FF2F3A40386BD44334824340A0992842EA223A40286893C327854340B0F27684D3163A40000F45813E89434090AEEFC341163A4038266F8099894340F0298E03AF163A40283E7782FD894340F0420246971B3A40D8C77C40A08B4340B0F6E978CC1C3A40F82CCF83BB8B4340205FD042021E3A40D8C77C40A08B4340A014AE47E12A3A40386893C3278D4340B0FC6B79E5463A40E0DF844204944340200F45813E493A40403D0B4279954340F03F87F9F24A3A40D8C43BC093964340B008707A174B3A4070A52C431C974340E055BABBCE4A3A40808461C09297434060D9E90775493A40604F1F813F984340309BE447FC423A40D0D90242EB994340E04543C6A3403A40302922C32A9A4340A0E33103953D3A40302922C32A9A4340A0B262B83A3C3A40D8066003229A4340409BE447FC323A40D0EE5701BE99434090A86DC3282C3A40281ADD41EC98434040D026874F2A3A40507C7C4276984340100F45813E293A40B8E9B303AE9743401018080264283A401048A643A795434030780AB952273A4098923A014D944340C0ECF483BA1C3A405076FA415D8E434040C8957A161C3A40708192020B8E4340E0488446B0153A40B0DDAF027C8B4340209221C7D6133A4028205F42058B4340307E8CB96B113A40B0D11DC4CE8A4340B001BC0512103A402835B401D88A4340D0420246970B3A40A89BFD81728B434050FBCA83F4FC3940B85B9203768D4340209221C7D6E3394080A2EBC20F924340207288B839DD3940A8C85A43A993434040CE177B2FD63940E0F19881CA96434090C1A73979D5394070A52C431C974340200341800CD53940A041D13C80974340F055BABBCEDA39401000000000A0434050D158FB3BDB39400018080264A04340002E01F8A7DC39407803CC7C07A14340407497C459E13940104BE7C3B3A243402018080264E83940B8ECF483BAA44340E05CDF8783EC3940B0B6D4415EA5434050BEA08504EC394008F7AE415FA4434090A86DC328EC3940D0F4D901D7A34340C0ECF483BAEC3940B0DDAF027CA3434080CFBA46CBED394078B130444EA34340F04D9A0645F33940306211C30EA343407081204086FA3940B0D11DC4CEA2434070BEA08504FC3940E0D03FC1C5A2434000904C874E2B3A40F8F9EFC16BA9434080B262B83A2C3A40908AE3C0ABA94340809FAA42032D3A40D05E7D3CF4A94340106893C3272D3A40001E8A027DAA4340202DCF83BB2B3A40D00CE2033BAC4340A01133FB3C2A3A40B8A44E4013AF434010990F08742A3A4058853FC39BAF4340D0ED26F8A62D3A40C8BE2B82FFAF434080CC79C6BE383A408003CC7C07B14340901133FB3C3A3A408003CC7C07B14340A0992842EA523A4020BD6F7CEDAF43402096CE8767653A40A8C85A43A9AB434030840EBA846B3A40488BC1C3B4A94340B0073E062B6A3A40C80F238447A94340A004FD851E653A400809C38025A7434050E09D7C7A643A40D0F19881CAA6434090ABAE4335613A40B0BF97C283A4434020874F3A91603A4028205F4205A34340010300000001000000150000004069C53714FE3840282CF180B2BB4340206893C327FD3840B0DDAF027CBB4340C059677C5FFC3840682B137EA9BB4340E04BC5C6BCFA3840905182FE42BD4340503D997FF4F9384030E44A3D0BBE4340504F1F813FF8384008E2E7BF07C14340F0CABDC0ACF83840C806600322C24340F025AAB706FA38406070784144C4434010990F0874FA3840A8716F7EC3C44340F057C9C7EEFE3840F820CB8289C743402000000000003940D8B8A981E6C74340307D5A457F00394020E1ED4108C8434000274D83A2013940684562821AC84340309C16BCE8033940D891CEC0C8C7434060BB5F05F806394028EAB0C22DC7434030840EBA840B394050551344DDC54340101B4982700D394050732B84D5C44340F0CDFE40B90D3940807B1002F2C34340A0ECF483BA0C3940D04065FCFBC24340109E25C80808394048BF44BC75C043404069C53714FE3840282CF180B2BB43400103000000010000003D000000F087BB7A15ED334000CD203EB0E54340D03DB2B96AF2334068F5F23B4DE44340F014C78157F3334008E869C020E34340F014C78157F3334098C2D84290E14340207497C459F13340386E15C440DF43408096E7C1DDED3340B0E3310395DD4340106893C327ED3340885182FE42DD43407081204086EA3340A8BF97C283DC4340E0C1FA3F87E9334028F6D03E56DC434040EACC3D24E03340602B137EA9DB434090F755B950D933405855A18158DA4340B0E9B303AED73340503D997FF4D9434070C554FA09D7334030266F8099D94340F0298E03AFD6334080457EFD10D9434020DB87BCE5D63340C8C43BC093D6434060B3CEF8BED8334028E78BBD17D3434090035ABA82ED3340D8031F8315BD4340F0C43BC093EE3340A859677C5FBC43408087A2409F04344050853FC39BB7434090A52C431C07344028F38FBE49B74340F017080264083440B05626FC52B74340307156444D0C3440B09B8BBFEDB74340908D2441B80E3440786649809AB8434060CAA48636103440000F45813EB943401094BF7B4711344088A2EBC20FBA43405055A1815812344088A2EBC20FBA4340206C06B820133440D873D2FBC6B943402009C380251F344038172AFF5AB0434030F38FBE491F34405837177FDBAF434020763579CA1E3440D8BB783F6EAF4340201B4982701D3440808D2441B8AE434020240C03961C3440A85FE97C78AE434070D6A887681434400009C38025AF43404055A18158E23340E0F71A82E3B84340307497C459E13340E8A9F23D23B94340A001BC0512E03340B074B0FECFB943406034D6FECEDA3340D8FA5B02F0BD4340C0B837BF61DA3340089700FC53BE4340A074B0FECFD93340506D37C137BF43409093A641D1D833409081204086C24340F07BB779E3D8334008240C0396C44340C0C1FA3F87D9334000A0C37C79C54340206552431BD833402029B000A6C64340F0D03FC1C5D23340D0EE5701BEC94340D03C80457ED13340B0B915C26ACA4340D0DA6E826FCE334010C79E3D97CB434090035ABA82BD3340889C69C2F6CF4340909FAA4203AD33405876FA415DD64340C059677C5FAC3340002A8E03AFD64340100C040132A4334030F38FBE49DF4340207976F9D6A333408018213CDAE043405028D2FD9CA63340A8984A3FE1E24340207156444DAC3340607FBDC282E54340A0ABAE4335B133406031957EC2E54340E03DB2B96AB2334000CD203EB0E54340B06BED7DAACA3340286893C327E5434040DEC83CF2CB334038ED0DBE30E5434050B60F79CBCD3340B868ACFD9DE543408014AE47E1DA3340202F3201BFE84340001B498270DD3340A8656B7D91E84340F087BB7A15ED334000CD203EB0E543400103000000010000000E000000E040F3397767334000DFA63FFBEB4340A0716F7EC36433403814E97E4EEB43402015C781576333400815C78157EB43406055A18158623340806308008EEB4340502E54FEB5603340A8A78FC01FEC4340F0B2B5BE48603340B0BF97C283EC4340502E54FEB5603340D8F19881CAEE434020E109BDFE603340E009A1832EEF4340900F5EBBB46133402820ED7F80EF434070A86DC3286C334010BB9A3C65EF434070035ABA826D3340805704FF5BEF4340E031AEB8386E33403841B8020AEF4340E0CDFE40B96D3340C8C43BC093EE4340E040F3397767334000DFA63FFBEB43400103000000010000003C00000040C1E10511713940786649809A0044409017B5FB5564394080FA08FCE1F9434010904C874E5B394038232E008DF44340003F5585065A3940F02CCF83BBF34340E03FC1C58A56394060672783A3F0434070C422861D5639408087140324F04340D049B6BA9C563940E05B3CBCE7EC434070BB5F05F8563940B0BF97C283EC4340C01001875059394000E869C020EB434010068200195A3940A0D11DC4CEEA4340C0FE7A85055B39405082FE428FEA4340A01C0588825D3940808AE3C0ABE9434030861DC6A45F3940584F1F813FE8434060D367075C5F39405070EA03C9E74340B008707A175B394060888043A8E44340103483F8C056394030C0B0FCF9E44340407497C4595139400006F4C29DE54340D057C9C7EE4E3940285FD04202E64340A09FAA42034D3940F881AB3C81E6434020904C874E4B3940B0A44E4013E74340C04BC5C6BC4A394058DD5CFC6DE74340B017B5FB5544394080A52C431CEF4340206E15C44047394030111AC1C6F143400021CB8289473940888D96033DF24340105A9E0777473940506DA983BCF2434070C075C58C44394058E09D7C7AF44340309221C7D6433940F00EB743C3F44340201E8A027D423940283B3602F1F4434000541C075E3D394038C0B0FCF9F44340A0B262B83A3C3940E0D6C1C1DEF44340A0812040863A394000F7AE415FF44340102A8E03AF363940B0D11DC4CEF24340C00EF27A303539400812F8C3CFF14340C0C43BC0932E3940A83B4F3C67ED4340D0CDFE40B92D394008F7AE415FEC4340D0CDFE40B92D3940209C16BCE8EB4340D0C77C40A0333940C8D90242EBE94340A093A641D1383940104E2844C0E74340B0073E062B3A3940B0A44E4013E74340F03E5585063A3940D0C43BC093E6434040465C001A393940583448C153E64340B008707A172B39406076FA415DE6434060C3B64599293940F881AB3C81E6434060CBD6FA22113940D0F4D901D7EB4340708461C0920F394028232E008DEC43402098A3C7EF0D394050499D8026EE4340B0FE7A85050B394088B130444EFB4340D0420246970B3940D8B8A981E6FD4340C0F6E978CC0C3940082A8E03AFFE434060B81E85EB213940D8CABDC0AC004440409C16BCE8233940E0B56801DA004440F03E5585063A39400818080264004440A0BB2539603B3940A8B393C151004440208A90BA9D453940F881AB3C81FE4340A01342075D5E3940202F3201BF004440B0E67283A1723940A8923A014D044440E00050C58D73394080931804560444400045D7851F743940D0DF84420404444090A2EBC20F723940000F45813E01444040C1E10511713940786649809A00444001030000000100000018000000F03E5585069A3940D0BBEA01F3324440C002EE79FE90394090992842EA324440908D2441B88E3940483789416033444050431B800D84394008E5284014364440B01C0588827D394030BD6F7CED374440C0F27684D3763940888D96033D3A4440C0FB3905F9753940A8A4C002983A4440F0264D83A2713940D85B3CBCE73C444070DC2A88817E3940F820CB82893F4440E03FC1C58A863940D8F71A82E3404440204087F9F28A3940B0957B8159414440F01186014B8E3940585E64027E4144405075C93846923940087F6ABC744144409017B5FB55943940E00F238447414440704F1F813FA8394078A52C431C3F4440C04F38BBB5B0394078931804563C4440D0F92AF9D8B13940B0C85A43A93B444080A2EBC20FB23940584CDE00333B4440406BD44334B2394030145B41D336444070B81E85EBB139405876FA415D36444060CBD6FA22B1394008E5284014364440205C8FC2F5A8394088724D81CC34444070C763062A9B394030205F4205334440F03E5585069A3940D0BBEA01F33244400103000000010000001E000000B0FB3905F9C538409018213CDA504440000C040132C4384088AEEFC3414E44408015E0BBCDAB384008068200194A4440A0716F7EC3A4384088457EFD1049444070A7CAF78CA4384008C11C3D7E494440B0E7A4F78DA3384030F04E3E3D4A4440F025AAB7069A38408048BF7D1D4E4440B05626FC5297384008DC65BFEE4E4440E034EF38459338403838F581E44F4440A0EF3504C7913840E000DE0209504440A0EAE5779A883840D0BB783F6E4F44409009DCBA9B873840908461C0924F4440A0DDAF027C833840D8C1FA3F87514440406211C30E833840803CBB7CEB514440C03DB2B96A823840D80CE2033B54444020809BC58B853840D0CABDC0AC584440A0EAE5779A88384060793BC2695B444020990F08748A384050888043A85C444010301004C8903840C88558FD116044408093A641D198384050FEB5BC726344401073F4F8BD993840302CF180B2634440F028EB37139F3840D888997D1E654440002C2CB81FA43840D87FD6FCF865444040ED0DBE30A538408048BF7D1D664440A009DCBA9BA73840E0FA5B02F06544406055A18158B23840B87A32FFE8634440002DCF83BBBB3840303E7782FD614440A0992842EAC238402838F581E45F4440C0E7A4F78DC3384008CD203EB05D4440B0FB3905F9C538409018213CDA5044400103000000010000001605000020904C874E4B3A40A8E67283A1DA44409014747B494F3A40A0A4C00298DA4440C0BFCFB8705C3A40B8E07EC003DB4440A0FB3905F9653A40503ACAC16CD84440A01A3048FA843A4050465C001AD1444080DBBE47FD913A4080AEEFC341CE4440D04BC5C6BC9A3A40D8B8A981E6C54440C0D03FC1C5A23A40D0CDFE40B9B5444080992842EAA23A40505260014CB54440309BE447FCA23A407893180456B444407085B18520A33A40507C7C4276B04440309BE447FCA23A40E0DC43C2F7AE4440B0E67283A1A23A40E0FA5B02F0AD44404075C93846A23A40B8B6D4415EAD444010314278B4A13A40D05B3CBCE7AC444050499D80269E3A4008E869C020AB4440005DDF87839C3A405882FE428FAA4440A0812040869A3A40182922C32AAA444070D026874F6A3A4088ABAE4335A14440001E8A027D623A40503ACAC16CA0444090ABAE4335613A40503ACAC16CA04440901342075D5E3A40A8E0F08288A04440F02CCF83BB5B3A40D8F71A82E3A04440404CDE0033533A40788192020B9E4440A0992842EA523A40309C16BCE88B4440505FD042025E3A405070784144844440209012BBB65F3A40B0C85A43A9834440C001BC0512603A40A8B0524145834440B00BB1FA23603A4098D11DC4CE824440105DDF87835C3A405055A181587A444040BEA085045C3A4088758E01D979444070C3B64599493A40A09BFD817273444060D4997B48403A40D8EE5701BE714440002A8E03AF363A402850FD8348704440407B4B395F2C3A40F02F1004C868444090B5A33847213A4098CB9BC3B56044409017EFC7ED1F3A400000000000604440001286014B1E3A4058DD5CFC6D5F4440F0420246971B3A40F8298E03AF5E444080AF21382E173A40B8AD11C1385E444080ABAE4335113A40201D1EC2F85D444050CDE506430D3A4000000000005E4440407A19C5720B3A40304A7B832F5E4440309694BBCF093A400009C380255F4440305C8FC2F5083A40281ADD41EC604440306E15C440073A40B03B4F3C67654440D04BC5C6BC0A3A40F8F36DC15267444080116DC7D4053A40306BD443346A4440B01AF67B62E93940B0BF97C2836C4440004B598638CE39403026E1421E6D44400096CE8767C5394028C0B0FCF96C444030861DC6A4BF394020232E008D6C44400051DB8651B8394050707841446C444080C6F7C5A5AE3940D8031F83156D44409087A2409F9439408090D783496F444000938D075B803940585E64027E71444070BB2539606B394020179CC1DF73444050C763062A5B394020BD6F7CED774440F05D4BC807593940483ACAC16C78444080A2EBC20F523940887E5182FE784440A096E7C1DD4D3940A8AAD0402C79444060B5DD04DF4C3940887E5182FE784440407156444D3C3940386552431B784440206893C3272D3940F002B34291784440A0E67283A122394088758E01D9794440C0F92AF9D8213940302922C32A7A444060C1E10511213940D0BBEA01F37A444090DBBE47FD21394000240C03967C4440C0F06778B322394030C0B0FCF97C444060D53C47E4273940503448C1537E44402083DC45982A39407878CF81E57E444080812040862A3940306E15C4407F4440A0116DC7D4253940C8E2C5C21081444020895E46B12439406073B9C1508144401015C78157233940F87E6ABC74814440F041960513133940705DF8C1F980444050718E3A3A0A39405046CEC29E804440D0A44E4013093940F82422FC8B804440604CDE0033E3384028ED0DBE307544408015E0BBCDDB38406082FE428F72444090D860E124CD3840B02231410D6D444040D2C43BC0C73840000341800C6D444030D8463CD9A1384028327381CB6D4440F04543C6A3A03840881B62BCE66D4440109C5088809F38405828D2FD9C6E444020F911BF62993840E0FD9C82FC72444010274D83A291384060F833BC5979444060C1E10511913840888AE3C0AB794440A06E2EFEB68F384040D8463CD979444060C2137AFD81384030F04E3E3D7A444080FA96395D6E38408018213CDA784440801B62BCE6653840B89B8BBFED774440D05A0A48FB633840808461C092774440009700FC535638405807793D9872444060C2137AFD513840602E54FEB57044402094BF7B4751384028172AFF5A7044408018213CDA5038406037177FDB6F4440B06E2EFEB64F3840F8230C03966C44408018213CDA50384000068200196A4440106552431B2838402841B8020A5F4440E0AC33BE2F2638403829B000A65E444070B3CEF8BE18384050431B800D5C444030809BC58B153840602B137EA95B4440D046753A90113840602B137EA95B4440505260014C0D3840D87954FCDF5B4440D0C43BC093FE374090CC07043A5D4440C050A4FB39FD3740301A6B7F675D4440B05626FC52F7374058FB743C665E444020990F0874EA374008CADFBDA3604440C0E0F08288E83740D0A9F23D23614440F081397AFCE23740D8AF743E3C634440C0EAE5779AD83740B8716F7EC3644440D0AC33BE2FD6374060888043A864444010917EFB3ABC374008CADFBDA360444060465C001AB93740808461C0925F4440C0E9B303AEB7374020DB87BCE55E4440009700FC53B6374058499D80265E4440B053E57B46B23740E0AF743E3C5B4440009D82FC6CB03740B0656B7D91584440B001BC0512B037406040DAFF00574440502E54FEB5B0374060499D8026564440C0622AFD84CB3740B8E67283A14A444030CF83BBB3D2374090457EFD10414440E046753A90D13740B877F17EDC3E444040C2137AFDD13740B89ECC3FFA3C4440506C06B820D33740A0B05241453B4440D05A0A48FBD33740081E8A027D3A44407031957EC2D53740885D86FF743944408015E0BBCDDB3740205FD04202364440E04E0647C9DF374060431B800D344440F08AFCFA21E2374000E869C020334440406C06B820E33740B8984A3FE132444010917EFB3AEC3740A8AAD0402C31444050E44A3D0BF63740507C7C4276304440307D5A457F00384078ABAE4335314440F03C80457E01384030F911BF6231444010904C874E2B3840E088997D1E2D4440D0C43BC0932E3840F8BDDBBC712C444060BFD2F9F03C3840904E417E36284440F0CDFE40B93D38403038F581E4274440D0B2B5BE48603840889C69C2F6174440306211C30E6338403829B000A6164440A087A2409F643840A8E331039515444020A0C37C7965384030D505BCCC144440A0FB3905F965384050FEB5BC7213444040809BC58B6538405055A18158124440D05147C7D5643840603D997FF4114440B07A32FFE8633840D0EE5701BE11444080A2EBC20F523840C05626FC520F444010861DC6A44F3840686D37C1370F444070FA96395D4E3840686D37C1370F44401088BB7A154D3840785704FF5B0F4440D0A6B1BD164C384058853FC39B0F4440801EA33CF34A3840B0B393C151104440F0980F08744A3840A8AAD0402C114440D0B837BF614A3840D88BDAFD2A124440007CB779E3483840909065C1C413444030DEC83CF22B384088992842EA22444010904C874E2B3840E8AF743E3C2344408093A641D1283840E8A6B1BD16244440F09600FC53263840A059677C5F244440D04E0647C91F3840C888997D1E254440306893C3271D3840C888997D1E254440A000193A7618384010D6E3BED5244440505260014C0D3840381A6B7F6725444070BEA085040C3840B0E33103952544408009DCBA9B073840B0DA6E826F26444020938D075B003840386552431B284440B0DA6E826FFE3740886649809A28444020857AFA08F83740281DACFF732A4440106E15C440F73740D0D03FC1C52A4440503A58FFE7F43740100C0401322C444080069B3A8FF23740E088997D1E2D44407037177FDBEF3740901B62BCE62D444010240C0396EC3740D8C43BC0932E44400018080264E837405840DAFF002F44401073F4F8BDD9374008D3A23EC92F4440000341800CD537403820ED7F802F444020904C874EBB3740100341800C2D444060D026874FBA374078397AFCDE2C4440F0B5F63E55B5374080992842EA2A444080992842EAB237405873B9C150294440D03DB2B96AB23740D8F71A82E3284440207497C459B13740686D37C137274440B0F8F884ECB037408848BF7D1D264440F081397AFCB23740884B00FE29234440F0BEB9BF7AB43740A8C2D84290214440D0C1FA3F87B93740E876137CD31E444070C422861DC6374058465C001A1944408093A641D1C83740E8B2B5BE4818444030E78BBD17CB3740507C7C4276184440207156444DCC3740A8656B7D911844400094BF7B47E1374070AEEFC341164440909C69C2F6E73740100341800C154440205C8FC2F5E8374030D505BCCC14444050D9E90775F93740B8E0F08288104440D03A71395EFD3740E0C43BC0930E4440505FD04202FE3740A8AD11C1380E4440A09065C1C4033840B87A32FFE8034440007976F9D6033840905D86FF74014440B0E7A4F78D033840D0F71A82E300444060499D8026FE374038F04E3E3DFA4340D03A71395EFD3740603D997FF4F94340C059677C5FFC3740E073D2FBC6F9434080ABAE4335F13740282F3201BFF8434080AD4CF8A5EE3740582E54FEB5F843403077D84466E63740A87A32FFE8FB434070B08D78B2D33740A8B0524145034440F0B837BF61CA3740B053E57B460A4440C06BED7DAACA3740F899417C600B444030F04E3E3DCA3740809065C1C40B4440504CDE0033C33740909C69C2F60F44400073F4F8BDB93740607FBDC282154440F05A0A48FBB33740B0E0F082881844408015E0BBCDAB374028DEC83CF21B4440108E3D7B2EA73740805182FE421D4440B0E7A4F78DA33740A89509BFD41D4440E0548847E269374088423D7D04244440406E15C44067374058431B800D24444070C422861D66374020DEC83CF223444070FDD7B969633740A0B0524145234440109D82FC6C603740283E7782FD21444090812040865A374010BB9A3C651F44405028D2FD9C563740206893C3271D4440801A3048FA543740E07954FCDF1B444060A7CAF78C5437400815C781571B4440F0BEB9BF7A5437405834D6FECE1A4440503A58FFE7543740583D997FF4194440E031AEB8385E3740B8B915C26A1244407034D6FECE7A374030327381CB054440C06E2EFEB67F374060431B800D044440C0D03FC1C58237400815C78157034440B0E0F08288983740889C69C2F6FF434040B5DD04DF9C374028F38FBE49FF434060BFD2F9F0AC374028F6D03E56FC4340D0BB783F6EBF374008BB9A3C65F74340B06E2EFEB6BF3740A85FE97C78F643400009C38025BF374028E44A3D0BF64340001286014BBE3740B09509BFD4F54340F005820019BA374078CC07043AF543405031957EC2B53740B0ECF483BAF44340A0716F7EC3A43740885182FE42F54340B0ECF483BA9C374008CD203EB0F54340B0E0F08288983740305FD04202F643406037177FDB6F374068F5F23B4DFC4340D0A9F23D23613740B8A44E4013FF4340208BFCFA21523740386E15C4400F44402082397AFC523740504F1F813F104440106211C30E533740D8C43BC09316444060B950F9D7523740D000DE020918444080A2EBC20F523740B074B0FECF194440207D5A457F503740B87A32FFE81B444020861DC6A44F3740580DFB3DB11C4440F031AEB8384E3740E0B5F63E551D4440B059677C5F4C3740D8FA5B02F01D444000990F08744A3740B8DA6E826F1E4440A07A32FFE8433740084E2844C01F4440D0D03FC1C5423740809C69C2F61F4440001B4982702D3740801EA33CF3224440A059677C5F1C3740081286014B264440A0AEEFC341E63640C8D03FC1C5324440809C69C2F6D7364038D505BCCC3C444060BFD2F9F0DC36405001F73C7F4044405037177FDBDF364020172AFF5A404440A0E7A4F78DE336405001F73C7F404440D0A6B1BD16EC364030266F80994144405055A18158F23640888120408642444040BB5F05F8F63640D0C77C40A043444090F755B950F9364030232E008D44444050C763062AFB3640D8CDFE40B9454440307A19C572FB3640001286014B4644408081204086FA36400821CB8289474440F034EF3845F3364028F38FBE494F44405055A18158F23640D88558FD1150444050E109BDFEF03640602E54FEB550444010F911BF62E93640B853E57B46524440A0129F3BC1E636405082FE428F52444010A0C37C79E536405082FE428F52444050CC423BA7DD3640E0EE5701BE514440900C1D3BA8DC3640B8656B7D9150444070B5DD04DFDC364020EACC3D2450444050D505BCCCDC364048853FC39B4F444070BEA08504DC3640E0BEB9BF7A4C44402083DC4598DA36408815E0BBCD4B4440D0A9F23D23D13640E07C957CEC48444060CAA48636D03640E0CABDC0AC48444030F6D03E56B436405855A1815842444080A52C431CA736405873B9C150414440B05626FC52973640709FAA42033D4440B004FD851E9536403014E97E4E3B44401096CE8767953640B0984A3FE13A4440E0393FC5719C3640080C0401323444406040DAFF009F36405055A181583244401094BF7B47A13640F8E1E7BF0731444030D505BCCC9C3640D8B5F63E55254440C06BED7DAA9A3640A8622AFD84234440E04334BA838C364030232E008D14444010917EFB3A8C364008DFA63FFB134440D0A6B1BD168C364078992842EA124440E04334BA838C364000E2E7BF0711444010274D83A2913640B05626FC52074440D03730B951983640B0C2D8429001444020CC423BA79D3640D0BB783F6EFF4340A0FCFA2136A03640A017601F9DFE4340C06E2EFEB6AF3640602B137EA9FB4340C05A0A48FBB3364000D061BEBCFA4340F0488446B0B53640286BD44334FA4340109700FC53B6364028D8463CD9F94340B0073E062BDA3640A8E3310395E54340E0AF743E3CDB3640B059677C5FE4434070BEA08504DC3640206211C30EE34340107156444DDC364030EACC3D24E04340201B498270DD3640301A6B7F67DD43403069C53714DE364008240C0396DC43400073F4F8BDE93640586D37C137CF4340800C1D3BA8EC364008DFA63FFBCB4340107FF8F9EFED36406034D6FECECA4340E0B2B5BE48F03640883CBB7CEBC9434080A2EBC20FF2364038F911BF62C94340E0B5F63E55053740082DCF83BBC34340B05FE97C78063740B8622AFD84C34340F031AEB8381E3740081E8A027DBA43402015C78157233740B8B393C151B84340206BD44334423740301DACFF73AA434070A7CAF78C44374050465C001AA9434070129F3BC1463740A8E9B303AEA74340F0C77C40A0533740080341800C9D434050431B800D54374060888043A89C434070BC9179E4573740E0CABDC0AC984340D03730B95158374010D3A23EC9974340D03730B951583740E0F19881CA964340E036FE4465573740B09509BFD4954340C034EF3845533740809065C1C49343409018213CDA503740901EA33CF3924340B0716F7EC334374008A0C37C798D4340200F45813E29374010DFA63FFB8B434040D367075C1F3740E8AF743E3C8B4340A0A52C431C173740801EA33CF38A434080116DC7D415374088992842EA8A43409087A2409F143740E082177D058B43409077F17EDC0E374088423D7D048C4340207FF8F9EF0D374048707841448C434090035ABA820D374058888043A88C43408096E7C1DD0D374030ED0DBE308D434030D8463CD911374050465C001A91434090992842EA123740383E7782FD914340F00B04013214374000D061BEBC92434030E44A3D0B163740F0E769C020934340D0A6B1BD161C3740B8622AFD8493434080035ABA821D3740C8B837BF61924340107FF8F9EF1D3740383E7782FD914340505260014C1D3740D07C957CEC904340702B137EA91B374058853FC39B8F4340A0FE7A85051B3740286E15C4408F4340E02E6D382C193740D8B5F63E558D4340B074B0FECF193740789FAA42038D43409014AE47E11A3740D088997D1E8D4340A00C1D3BA82C3740D0CABDC0AC904340B0FB3905F93537402814E97E4E9343407028D2FD9C363740602B137EA993434050B3CEF8BE383740808D2441B8964340207CB779E3383740386E15C440974340C0EAE5779A383740B8E9B303AE974340D0CDFE40B92D3740682E54FEB5A04340A074B0FECF293740104BE7C3B3A24340002F6D382C293740E082177D05A34340E0BB783F6E1F374000DC65BFEEA6434080AD4CF8A51E3740686D37C137A7434000763579CAFE3640306893C327AD4340406BD44334F2364058499D8026AE434070C1E10511F1364028E44A3D0BAE4340B001BC0512F03640801B62BCE6AD434070D6A88768D43640306211C30EA34340E0C77C40A0D3364008D061BEBCA24340001E8A027DD23640583D997FF4A14340D0A9F23D23D136405801F73C7FA04340D0A9F23D23D13640A0BC5642779F4340D05CA8FC6BD13640D0C43BC0939E434070069B3A8FD23640D8F4D901D79B4340506C06B820D33640101E8A027D9A434020A0C37C79D53640C88558FD11984340708AE3C0ABD9364050888043A8944340E04BC5C6BCDA364038DEC83CF29343409015E0BBCDDB3640A87A32FFE8934340C001BC0512E036408096E7C1DD954340E04543C6A3E03640001286014B96434010938D075BE03640588E0244C1964340B074B0FECFE9364080423D7D0494434090A52C431CF73640E009A1832E8F434090F755B950F936405831957EC28D434000763579CAFE3640602E54FEB5884340908D2441B8FE364010A0C37C7985434050B3CEF8BE0837408887A2409F844340C0E67283A1123740A8ECF483BA844340106893C3270D37400806820019824340101E8A027D023740306893C3277D4340B001BC0512F03640B877F17EDC76434070CDE50643D5364088A2EBC20F72434080069B3A8FC236403020ED7F806F4340B05CA8FC6BC1364010BB9A3C656F434070CAA48636C03640885704FF5B6F434060BEA08504BC36400021CB82896F4340204432E4D8AE3640F8CC599F72704340C04AB0389CAD3640C0DA519CA3704340E0CABDC0ACA836406073B9C150714340F040F33977A73640283E7782FD714340406E15C440A73640301DACFF73724340A0F27684D3A636406834D6FECE724340B068ACFD9DA53640A8622AFD8473434040895E46B1A43640809065C1C4734340007FF8F9EF9D3640A059677C5F744340A00C1D3BA89C364030F6D03E5674434030DB87BCE5863640285C8FC2F570434050C422861D863640D8CABDC0AC70434030E44A3D0B86364038EACC3D24704340A01B62BCE6853640E0AC33BE2F6E434090FB3905F9853640D0CDFE40B96D4340E0CDFE40B98D3640C8D03FC1C56A4340B077F17EDC8E36405882FE428F6A434080F4143944943640588BC1C3B4694340E0488446B095364020266F809969434050C763062A9B3640A85CA8FC6B69434000917EFB3A9C3640D8C1FA3F8769434060499D80269E3640883CBB7CEB694340109CDD5A26AB3640082104E44B6A43406028D2FD9CB6364060F833BC59694340800F5EBBB4C1364030D505BCCC644340C068ACFD9DC53640D8F4D901D7634340F02B2CB81FF43640904E417E3660434010938D075B10374000CADFBDA3584340D046753A90113740B8BC564277574340A009DCBA9B173740D8FD9C82FC52434040E78BBD171B37408893A641D1504340A0F5B704E01B3740B0E0F08288504340709FAA42031D3740A8B393C1515043402069C537141E37400818080264504340106BD4433422374028E109BDFE504340A01EA33CF32A37409054C37E4F524340908461C0922F37403814E97E4E534340109D82FC6C303740806308008E53434070ABAE4335313740D0F4D901D7534340F046753A90313740A859677C5F544340307497C45931374040D505BCCC54434010857AFA08483740002DCF83BB53434070D9E90775493740E0C77C40A0534340B0F8F884EC5037405007793D9852434020274D83A2513740C053E57B4652434000A0C37C7955374008D3A23EC94F4340A01B62BCE655374000BB9A3C654F43405028D2FD9C56374010E52840144E43405028D2FD9C563740580438BD8B4D434090AEEFC341563740100341800C4D4340F031AEB8384E374010CADFBDA34843405031957EC255374080397AFCDE44434090129F3BC15637408087A2409F44434080AEEFC34166374038E109BDFE404340306E15C4407737406037177FDB3F4340007CB779E3883740A89B8BBFED3F4340B0E9B303AE9737403814E97E4E3B434060BC9179E497374058465C001A39434010068200199A3740D009A1832E374340E0D38041D2A7374078AEEFC3412E4340C0EAE5779AA83740E07FD6FCF82D434060BFD2F9F0AC37408087A2409F2C4340F0230C0396CC3740885D86FF74294340E0548847E2D93740D88558FD11284340D050A4FB39ED37405831957EC2254340901B62BCE6F5374060431B800D24434090992842EA12384080ABAE4335194340F081397AFC123840582E54FEB5184340F0264D83A2113840B859677C5F144340109C5088800F38408854C37E4F124340D05CA8FC6B013840D8CABDC0AC084340E0D03FC1C502384028F6D03E56FC4240E0D38041D2073840B0E9B303AEEF424050DC2A88810E3840100C040132EC424030E44A3D0B16384060FB743C66E64240A0AEEFC341163840D0FA5B02F0E54240A0A52C431C173840602B137EA9E3424050BB5F05F8163840804B00FE29E34240B0EF3504C7113840584F1F813FD842407017EFC7ED0F38403029B000A6D6424000990F08740A384030DEC83CF2D342407093A641D108384058793BC269D3424040D2C43BC007384050FEB5BC72D3424080FDD7B969F33740D0CDFE40B9D54240A0EF3504C7F13740F81186014BD64240700C1D3BA8EC3740080C040132DC42400018080264E83740B05CA8FC6BE14240604CDE0033E33740000C040132E4424020240C0396DC374010DC65BFEEE64240107CB779E3D83740889C69C2F6E742407055A18158D237405073B9C150E94240A0ABAE4335D13740E0C1FA3F87E9424080AEEFC341C637405834D6FECEEA42408021E4BCFF8F3740809065C1C4FB4240A0F1D3B8378F374058431B800DFC4240E031AEB8388E3740885182FE42FD4240C0DA6E826F8E3740E0CDFE40B9FD4240D0B2B5BE489037408848BF7D1DFE4240108BFCFA219237409060C77F81FE4240D03FC1C58A963740D08558FD11004340B0E9B303AE9737408018213CDA004340405C8FC2F5983740E0B837BF61024340F02E6D382C99374050FEB5BC72034340207CB779E3983740909065C1C403434050E44A3D0B963740A89ECC3FFA044340E05A0A48FB933740001B498270054340101E8A027D923740580438BD8B054340F05A0A48FB83374038ED0DBE3005434060C2137AFD81374090397AFCDE0443402096CE8767753740A0E67283A102434050CC423BA76D37404801F73C7F004340909FAA42036D374030EACC3D24004340E0AF743E3C6B3740883FFCFCF7FE4240F0C1FA3F87693740081B498270FD4240503A58FFE754374028ED0DBE30FD4240808461C0923F3740306893C327FD4240207156444D3C374080397AFCDEFC424010904C874E3B3740600DFB3DB1FC42400040321D3A2D374030D8463CD9F94240C05626FC5227374010BB9A3C65F74240701A3048FA24374010C45DBD8AF642406055A181582237409096E7C1DDF5424000938D075B203740587FBDC282F5424040DEC83CF21B3740386893C327F5424010938D075B10374010D6E3BED5F44240E05D4BC807093740B8E3310395F5424020F6D03E56043740A8AD11C138F642401082397AFC023740500438BD8BF54240205FD04202FE3640B8AAD0402CF1424070B60F79CBFD3640682E54FEB5F04240C04543C6A3003740A89ECC3FFAEC424070ABAE433501374060888043A8EC4240506C06B82003374080A86DC328EC4240F0C1FA3F870537406031957EC2EB424030EACC3D2410374050FEB5BC72EB42402096CE87671537401015C78157EB424090812040861A3740002DCF83BBEB424020E44A3D0B26374008E2E7BF07E1424090F755B950293740905704FF5BCF4240C0C1FA3F8729374010DC65BFEECE4240D0622AFD842B3740001286014BCE4240108BFCFA21323740F80B040132CC424050C554FA09473740E076137CD3C64240B0E67283A152374078A86DC328C44240F02B2CB81F54374058431B800DC44240F0AC33BE2F56374060F5F23B4DC44240002DCF83BB5B374008A0C37C79C54240001B4982705D3740D0FA5B02F0C5424040B60F79CB5D3740B0DA6E826FC64240307156444D5C3740B8E0F08288C8424070B3CEF8BE583740286211C30ECB424030F6D03E56543740A0B6D4415ECD4240D0E7A4F78D5337401048A643A7CD424060BC9179E46737402814E97E4ECB4240906B7C26FB6B37406840683D7CC3424090A2EBC20F723740786649809AC04240708461C0927F3740080341800CBD4240F0B5F63E5585374030E78BBD17BB4240C068ACFD9D853740B06BED7DAABA4240C05FE97C78863740884E417E36B8424080116DC7D48537405837177FDBB74240B0DDAF027C833740803FFCFCF7B64240900F5EBBB48137409060C77F81B64240E04E0647C97F3740E8AC33BE2FB64240E0A6B1BD166C3740A8BF97C283B442402073F4F8BD693740B859677C5FB4424020F6D03E566437409087A2409FB4424010274D83A2613740503A58FFE7B44240F04BC5C6BC5A3740885182FE42B5424060CDE506434537402814E97E4EB3424010904C874E3B3740582E54FEB5B042405034D6FECE3A3740D8B2B5BE48B04240306BD44334323740286552431BA84240E0C77C40A0333740903FFCFCF7A6424070F414394434374050499D8026A64240D0DDAF027C3337409096E7C1DDA5424070AD4CF8A52E3740286893C327A54240E03A71395E2D374038ED0DBE30A54240E036FE4465273740881B62BCE6A54240009700FC5326374008E5284014A6424070C2137AFD11374030ED0DBE30AD424030E109BDFE103740801B62BCE6AD424030E109BDFE1037408054C37E4FB24240C0EF3504C71137405807793D98B2424070B950F9D7123740084BE7C3B3B24240A07A32FFE8133740001E8A027DB24240D068ACFD9D153740483D997FF4B1424070129F3BC116374000D9243FE2B1424060C763062A1B374038F04E3E3DB24240406211C30E233740487FBDC282B5424060B950F9D7223740889C69C2F6B7424050E109BDFE20374060F833BC59B94240D06BED7DAAFA3640B8A10DC006C24240E0C43BC093EE3640A859677C5FC44240101B498270ED3640F8230C0396C44240B0E9B303AEC73640B8622AFD84CB4240009700FC53C63640886308008ECB4240306C06B820C33640109A417C60CB424070FA96395DBE3640001E8A027DCA4240A0FE7A8505BB364010C11C3D7EC94240B074B0FECFB93640302F3201BFC84240D05D4BC807B936406037177FDBC7424070465C001AB936405076FA415DC6424040F04E3E3DBA36405876FA415DBE42409081204086BA3640D8FA5B02F0BD4240406BD44334C23640D00CE2033BB44240F008C38025CF3640D80CE2033BAC4240A0F755B950E936408818213CDA98424010F911BF62E936401018080264984240E03730B951E8364078A52C431C97424040C554FA09E736405076FA415D964240F03FC1C58AE63640801B62BCE695424030ED0DBE30E53640E08BDAFD2A9242402096CE8767E53640602E54FEB590424030DB87BCE5E6364080A52C431C8F4240704F1F813FE83640B05FE97C788E4240D05D4BC807E93640101286014B8E4240A0622AFD84EB3640D8AC33BE2F8E4240505260014CED3640E009A1832E8F424050499D8026EE364010BB9A3C658F424070D367075CEF3640C8BB783F6E8F424030F6D03E56F43640E009A1832E8F4240100341800CF53640A077F17EDC8E424010274D83A2013740804B00FE298342404055A18158023740D0F19881CA7E4240E0C77C40A0033740E000DE0209784240107976F9D603374060853FC39B77424090035ABA820D3740D009A1832E6F4240306E15C440173740E00F238447694240A050A4FB391D3740884B00FE29634240101B4982701D374008D061BEBC62424050BFD2F9F01C37408854C37E4F624240A0AEEFC34116374000D3A23EC95F4240F0A9F23D23113740908D2441B85E42408017EFC7ED0F3740B877F17EDC5E424090035ABA820D3740D8F19881CA5E4240504F1F813F08374030327381CB5D424040D2C43BC0073740D8B5F63E555D4240A0F27684D3063740282CF180B25B4240B05626FC5207374050431B800D544240101808026408374060F833BC59514240F0CABDC0AC083740C87C957CEC50424050D9E9077509374030EACC3D24504240F00B040132143740A874B0FECF49424080A86DC3281C37409021E4BCFF4742401015C781573337405055A181583A424070F414394434374028266F809939424020F6D03E56343740D8A9F23D23394240E05A0A48FB333740D800DE0209384240C0E7A4F78D333740F820CB8289374240E0D03FC1C532374030F38FBE49374240907A32FFE823374008C45DBD8A364240B0E67283A1223740D8C43BC09336424050C554FA09173740A8B393C151384240F05D4BC807F93640A8B915C26A424240604F1F813FF83640F84AE7C3B3424240B0E9B303AEF73640E082177D0543424050D6A88768F4364048499D8026464240F014C78157E336403035B401D85242402073F4F8BDC936408896E7C1DD65424060465C001AC93640A8AD11C138664240B04D637B2DC83640A85FE97C78664240A0116DC7D4C53640F8298E03AF664240A0FE7A8505BB36400809C38025674240B0716F7EC3A436403041B8020A6742404055A18158A23640883FFCFCF7664240D0B2B5BE48A03640888D2441B8664240D0EAE5779A983640381A6B7F6765424090129F3BC1963640889FAA4203654240A0E67283A1923640286211C30E634240D034EF384583364010A0C37C79554240B0622AFD847B3640B0E33103954D4240E04BC5C6BC7A3640D87954FCDF4B4240B0FE7A85057B3640A8A78FC01F444240B0622AFD847B3640A8B0524145434240107156444D7C3640081E8A027D42424080FA96395D7E3640A8656B7D91404240E057C9C7EE7E3640884E417E3640424010000000008036405067EE21E13F4240E04543C6A3803640B0E9B303AE3F424050C1E1051181364028F38FBE493F4240D046753A90813640A8DA6E826F3E424020D8463CD9813640B8BF97C2833C424070C2137AFD813640886308008E3B4240008BFCFA21823640303E7782FD39424040B81E85EB813640A85CA8FC6B394240406893C3277D3640B05CA8FC6B314240E025AAB7067A3640906308008E3342405031957EC265364060888043A83C4240D04543C6A360364028232E008D44424060C763062A5B3640D8C1FA3F8759424070BEA085044C3640B0B393C15168424090FA96395D3E364008D3A23EC96F4240009C5088802F3640B853E57B4672424000A0C37C79253640508BC1C3B479424060465C001A293640B0B393C151804240D0CABDC0AC283640608BC1C3B481424000857AFA08283640888120408682424090A52C431C273640D0D03FC1C582424080116DC7D425364078992842EA824240E057C9C7EE1E364058793BC26983424030CF83BBB312364030DEC83CF283424030EACC3D2410364030DEC83CF283424020D505BCCC0C3640082DCF83BB834240C040F33977073640804B00FE29834240C04BC5C6BCFA3540D07C957CEC804240F02B2CB81FF43540B8E9B303AE7F42409021E4BCFFEF3540B0DA6E826F7E4240C077F17EDCEE3540A868ACFD9D7D4240406893C327ED3540F82CCF83BB7B424020917EFB3AEC354008DC65BFEE6E4240407156444DEC3540A8DA6E826F6E424050BFD2F9F0EC35409087A2409F6C4240D0DA6E826FEE354000E2E7BF07694240C077F17EDCEE354010CADFBDA3684240B001BC0512F03540909C69C2F6674240306C06B820F33540D0F19881CA664240F0AC33BE2FF6354060499D802666424050EACC3D24F03540A8C2D8429061424000274D83A2E13540080C0401325C4240009D82FC6CE0354038F6D03E565C424030861DC6A4DF35408887A2409F5C4240B0DA6E826FDE3540505260014C5D4240F0CABDC0ACD8354088ABAE433561424050ED0DBE30D53540809065C1C463424020F6D03E56D4354038232E008D644240107976F9D6D33540381A6B7F6765424050B08D78B2D335405076FA415D664240E034EF3845D33540588E0244C1664240101E8A027DD235403041B8020A674240D03C80457ED13540D809A1832E67424040F38FBE49CF35400809C3802567424030ED0DBE30C53540B0DA6E826F66424050D6A88768C43540A8AD11C138664240907A32FFE8C335405031957EC2654240F0C77C40A0C3354028ED0DBE3065424040F6D03E56B4354038172AFF5A684240A07A32FFE8B33540582E54FEB568424030E109BDFEB0354030DEC83CF26B4240906E2EFEB6AF3540D0BB783F6E6F4240F04E0647C9AF3540305C8FC2F570424030EACC3D24B0354078A2EBC20F724240001E8A027DB23540789FAA4203754240901A3048FAB43540D0CDFE40B975424060C422861DB6354010C45DBD8A764240D05FE97C78B635403841B8020A774240102A8E03AFB635402820ED7F80774240A0AEEFC341B63540E0F71A82E378424040ED0DBE30B5354008274D83A2794240404CDE0033A3354080ABAE4335814240C0ECF483BA9C354050FEB5BC72834240701A3048FA943540E0D38041D287424060A7CAF78C943540B0E0F08288884240E04543C6A39035405082FE428F924240F09C82FC6C903540A8622AFD84934240B0F8F884EC90354058888043A8944240809065C1C49335409093A641D1984240100C0401329435405873B9C150994240901B62BCE6953540001E8A027D9A4240008E3D7B2E973540804B00FE299B42408014AE47E19A3540600DFB3DB19C4240307497C459A13540285FD042029E4240207A19C572AB35405055A18158A2424050D505BCCCAC3540D082177D05A3424030D8463CD9B13540B0A44E4013A74240008BFCFA21B23540580ABABDA4A74240C053E57B46B23540508BC1C3B4A94240B0DA6E826FAE354080C9C6832DB04240207CB779E3A8354078AEEFC341B64240209700FC53A63540A8656B7D91B842406034D6FECE9A3540786649809AC042408087A2409F94354028DEC83CF2C34240201E8A027D92354088397AFCDEC4424010763579CA8E35405076FA415DC64240E03730B951883540B0656B7D91C84240F0298E03AF66354058793BC269D3424040C763062A4B3540602B137EA9E3424040DB87BCE5463540889FAA4203E5424050BEA085043C3540F020CB8289E7424060BC9179E43735400818080264E84240C068ACFD9D35354000301004C8E8424010240C03962C3540D0EE5701BEE94240D068ACFD9D253540206BD44334EA424020763579CA1E35403035B401D8EA424080A86DC3281C354010C79E3D97EB4240E0AF743E3C1B3540B059677C5FEC4240E0AF743E3C1B3540B8B6D4415EED424070BEA085041C3540584F1F813FF0424050D505BCCC1C3540081E8A027DF24240E04E0647C91F3540903FFCFCF7F64240E04543C6A3203540A89B8BBFEDF74240206BD44334223540587C7C4276F84240A0E7A4F78D233540089D82FC6CF84240C0BEB9BF7A243540804E417E36F84240C0AC33BE2F2635400809C38025F74240A0A52C431C27354030DB87BCE5F64240D0548847E22935402829B000A6F6424070035ABA822D3540608E0244C1F6424020301004C8303540A8A44E4013F74240100341800C353540E0B2B5BE48F84240E036FE446537354078457EFD10F94240C0EAE5779A483540386E15C440FF4240A018213CDA503540302CF180B2034340305FD042025E35405828D2FD9C0E4340B06E2EFEB65F3540D0C1FA3F87114340B06E2EFEB65F3540B8622AFD84134340E0BB783F6E5F3540B89ECC3FFA144340C03DB2B96A623540206211C30E1B434060B81E85EB713540608BC1C3B4194340F02E6D382C793540D8B2B5BE48184340502B137EA97B3540B0BC564277174340A009DCBA9B873540600DFB3DB1144340A0073E062B8A3540905A457F68144340F017080264983540286211C30E13434030D505BCCC9C3540A8DDAF027C13434070F4143944A4354028F6D03E5614434020E78BBD17AB3540507FBDC28215434050DEC83CF2AB35406831957EC2154340605260014CAD3540B0DA6E826F164340306E15C440B73540002DCF83BB1B4340107CB779E3B83540809FAA42031D4340B0622AFD84BB35405037177FDB1F434080035ABA82BD3540C882177D0523434050499D8026BE354050793BC26923434030E44A3D0BC6354030DB87BCE5264340C0E9B303AEC73540E0BB783F6E27434080F755B950D935403014E97E4E2B4340F02CCF83BBDB3540D8C77C40A02B43401096CE8767F53540E08BDAFD2A2A4340F09FC37C79053640580ABABDA4274340209700FC53063640B877F17EDC26434090129F3BC106364008A0C37C79254340106E15C440073640F8230C03962443405034D6FECE0A3640306211C30E234340A0F5B704E02B364078A2EBC20F1A434030D505BCCC2C3640B874B0FECF194340208E3D7B2E373640B06E2EFEB617434050D9E9077539364030F38FBE491743408018213CDA60364008D061BEBC1243409087A2409F74364080457EFD1011434060D9E907758936408060C77F810E434060BB5F05F8A63640E0EE5701BE0943406031957EC2B53640109700FC5306434070B3CEF8BEB83640B868ACFD9D054340D0C1FA3F87B93640E0B5F63E55054340D04BC5C6BCBA364060888043A804434060B950F9D7C236408893A641D1004340A00C1D3BA8CC364028F6D03E56FC4240B0622AFD84DB3640587C7C4276F84240C031AEB838DE3640D88558FD11F84240A000193A76E83640D88558FD11F84240B05CA8FC6BF1364008301004C8F84240F0BEB9BF7AF4364088ABAE4335F94240F0B5F63E55F53640B05CA8FC6BF94240C05626FC52F73640001E8A027DFA4240F07BB779E3F83640809065C1C4FB42403083DC4598FA3640E0CDFE40B9FD424090073E062BFA36408848BF7D1DFE42402082397AFCF23640904E417E360043400018080264E836403035B401D8024340C05A0A48FBE33640D8F4D901D7034340F0BB783F6EDF364008DFA63FFB03434050DC2A8881DE3640909065C1C4034340B0F5B704E0DB3640D8F4D901D70343402083DC4598DA364090423D7D040443405034D6FECEDA364010BEDBBC71044340402B137EA9DB3640580DFB3DB104434000274D83A2E1364058FB743C66064340B0EF3504C7F13640D0066003220A4340207976F9D6F33640D8B837BF610A43402077D84466F636406055A181580A4340D057C9C7EEFE3640000F45813E094340D053E57B4602374008CADFBDA3084340703A58FFE70437405037177FDB07434040E44A3D0B063740600ABABDA4074340502B137EA90B3740A8BC5642770743402009C380250F3740885704FF5B074340D05D4BC8071937403020ED7F8007434010F04E3E3D1A37400821CB8289074340905CC5E2371D374098417C60C7074340A017EFC7ED1F37408021E4BCFF074340C0AF743E3C2B3740D8C1FA3F870943407031957EC2353740D80CE2033B0C4340D036FE4465373740B0716F7EC30C434060BC9179E437374030ED0DBE300D4340503D997FF4393740F8E769C020134340E0548847E239374000C79E3D9713434050465C001A393740B07A32FFE8134340C077F17EDC1E37403035B401D81A4340E0CDFE40B91D3740D082177D051B4340B05FE97C78063740D8F4D901D71B4340F020CB8289F736401015C781571B4340B05CA8FC6BF13640A0E67283A11A4340B0EF3504C7F13640B89B8BBFED174340A059677C5FEC3640385C8FC2F518434090116DC7D4D53640B09ECC3FFA1C4340F0847AFA08C836408096E7C1DD1D4340E05A0A48FBC3364028F38FBE491F4340C0656B7D91B03640B85CA8FC6B294340C05FE97C789636408854C37E4F2A4340D0CABDC0AC88364070A86DC3282C4340B0E67283A1823640D800DE020930434080129F3BC17636406076FA415D364340A0FB3905F9753640082A8E03AF3643408014AE47E16A3640D0F71A82E33843402073F4F8BD69364058465C001A394340106E15C44067364060F833BC59394340E03FC1C58A66364010E2E7BF073943408018213CDA603640D88BDAFD2A324340407D5A457F603640888AE3C0AB314340702E54FEB5603640080F45813E31434080FDD7B96963364008C45DBD8A2E434020809BC58B653640583A58FFE72C4340F09FC37C79653640A8BF97C2832C4340C0716F7EC3643640000C0401322C4340A0EF3504C7613640C8FD9C82FC2A4340A0F8F884EC603640D8D03FC1C52A4340001286014B5E3640D8D03FC1C52A434010274D83A2313640884B00FE292B434040E78BBD172B3640905A457F682C434020EACC3D24203640F820CB82892F4340901EA33CF30A3640881EA33CF33243400073F4F8BDF9354050431B800D344340B0E67283A1F23540885A457F68344340C03FC1C58AB6354028ED0DBE302D4340E05D4BC807A93540381A6B7F672D43401082397AFCA23540D0B5F63E552D4340B0E0F0828898354010DFA63FFB2B434040DEC83CF28B3540D87C957CEC28434090E0F08288883540809C69C2F627434080129F3BC1763540F8DB65BFEE2E4340A0E33103955D3540D0BB783F6E3743400073F4F8BD59354000BB9A3C6537434030DB87BCE55635406082FE428F3243406031957EC2553540D0EE5701BE31434010F6D03E5644354060793BC2692B4340909FAA42033D3540B0AAD0402C2943401088BB7A152D354080AEEFC34126434060BEA085042C354050499D8026264340E02E6D382C293540101286014B26434080116DC7D425354000DC65BFEE264340B0F5B704E01B354038232E008D2C43409015E0BBCD1B3540A85FE97C782E4340107156444D1C3540C05626FC522F4340207D5A457F203540806649809A30434020CF83BBB322354010C11C3D7E314340909065C1C42335408054C37E4F32434060B08D78B22335406034D6FECE324340F0BB783F6E1F35405040DAFF0037434060B60F79CB1D3540E08558FD1138434010E8305F5E1C354048438D4292374340001CEDB8E11B3540F8D58EE21C374340A014AE47E11A3540C8A90F24EF36434040D026874F1A3540803FFCFCF7364340E0AF743E3C1B35400009C38025374340B0F5B704E01B35400821CB8289374340B059677C5F1C3540889C69C2F637434050D505BCCC1C354028E109BDFE384340C04334BA831C3540905D86FF7439434060C422861D1635400018080264404340405260014CFD34406031957EC2554340E04334BA83FC344030E44A3D0B564340102A8E03AFE6344010CD203EB05D434010F38FBE49CF344080ABAE4335614340009700FC53C63440D07C957CEC604340200341800CC5344090457EFD1061434090F4143944C4344038F911BF62614340C0C77C40A0C33440608BC1C3B4614340202DCF83BBBB34408048BF7D1D664340107A19C572BB344000C45DBD8A664340D042024697BB344050853FC39B6743407017EFC7EDBF344008BEDBBC71744340909C69C2F6C73440206E15C4407743400018080264F83440B0656B7D917843409009DCBA9B07354078A52C431C774340106552431B083540888D2441B8764340B04D637B2D08354080CC07043A754340809C69C2F607354058888043A87443405028D2FD9C06354010DFA63FFB734340B0E9414129063540482234828D7343405028D2FD9C063540A86BED7DAA724340E036FE4465073540D0B837BF61724340002DCF83BB0B354010E2E7BF07714340A00C1D3BA80C354008301004C8704340D0B5F63E551535405828D2FD9C6E434080AEEFC341163540D0C43BC0936E434060431B800D24354038F38FBE497743404083DC45982A354008D6E3BED57C434040F04E3E3D2A35406831957EC27D4340B074B0FECF2935408848BF7D1D7E43403077D84466263540604F1F813F804340B0DDAF027C233540303E7782FD81434050DEC83CF21B3540D07FD6FCF885434070C763062A1B354088AEEFC341864340100F45813E193540D8F19881CA864340406552431B1835405040DAFF00874340F0EEC9C342153540306E15C440874340F0420246970B3540588BC1C3B4814340C077F17EDCEE3440D0BB783F6E874340D0DDAF027CD33440E0C43BC0938E43405055A18158D234402829B000A68E4340407497C459D13440A85FE97C788E4340009700FC53C6344088992842EA8A434040B81E85EBC13440B8E67283A182434070AA0B7899C93440A86E2EFEB67F43401082397AFCD23440A8716F7EC37C4340709065C1C4D33440D0BEB9BF7A7C434040D6A88768D43440B0A78FC01F7C434020895E46B1D43440302CF180B27B43407087A2409FD43440804B00FE297B434080F4143944D43440B86BED7DAA7A4340306C06B820D334406082FE428F7A434040CC423BA7BD3440A0C2D84290794340B059677C5FBC3440608BC1C3B4794340209A417C60BB3440903CBB7CEB794340E0C1FA3F87B93440901EA33CF37A4340109700FC53B63440D0031F83157D434070431B800DB434402841B8020A7F4340909065C1C4B33440A8BC5642777F4340007976F9D6B33440000000000080434040E44A3D0BB63440F82F1004C8804340102A8E03AFB63440A8AAD0402C81434070A52C431CB7344028266F809981434070A52C431CB73440B8E67283A1824340000C040132B43440881B62BCE685434030D8463CD9B13440B09B8BBFED87434030EACC3D24B0344038E109BDFE884340206893C327AD3440306BD443348A4340A093A641D188344010D3A23EC9974340901EA33CF37A3440E082177D05A343402021CB82897734403014E97E4EA3434050CF83BBB3623440905A457F68A44340000F45813E59344040D505BCCCA4434050BC9179E4573440303B3602F1A44340F07EF8F9EF4D3440E0B2B5BE48A84340C059677C5F4C34408818213CDAA8434050D026874F4A3440A074B0FECFA94340C0F27684D3363440C800DE0209B8434090A52C431C373440B8B393C151B8434000763579CA3E34405801F73C7FB8434060D026874F3A3440001E8A027DC24340E0B2B5BE48303440306E15C440CF43401088BB7A152D34400018080264D0434070D026874F2A3440E8A9F23D23D1434060CAA486361034403841B8020AD74340A0F1D3B8370F3440286E15C440D743409096E7C1DD0D344010BB9A3C65D743401003B34291023440607FD93D79D8434080FDD7B969033440D07C957CECD843401096CE8767053440D00F238447D94340C04D637B2D083440100F45813ED94340208E3D7B2E173440506D37C137D7434020857AFA0818344000DC65BFEED64340100F45813E19344080AEEFC341D64340A014AE47E11A344010CD203EB0D54340F00B04013224344000DFA63FFBD34340B06BED7DAA2A3440D0AF743E3CD34340E03C80457E3134404807793D98D243402082397AFC3234408081204086D2434070BC9179E437344010D061BEBCD2434070B3CEF8BE383440D0FD9C82FCD24340D0656B7D915034408087A2409FDC43400094BF7B47513440283B3602F1DC4340C0EF3504C7513440A8B6D4415EDD4340008BFCFA21523440801B62BCE6DD4340C05CA8FC6B513440888D2441B8DE4340207156444D4C34406034D6FECEE2434010068200194A3440E0F19881CAE643402083DC45984A3440306E15C440E74340207A19C5724B34403020ED7F80E74340D03A71395E4D34402838F581E4E74340705B5B785E4E3440F0BAF083F3E743401009C380255F3440B09ECC3FFAE44340E0B2B5BE4860344030D505BCCCE4434020274D83A2613440A0716F7EC3E44340B0E67283A1623440383B3602F1E4434030DB87BCE5663440001286014BE64340604F1F813F683440803FFCFCF7E64340D0C1FA3F87693440009D82FC6CE84340F0058200196A3440D8C1FA3F87E9434060D026874F6A344000E869C020EB4340D0C1FA3F8769344028DEC83CF2EB4340D0CABDC0AC683440500DFB3DB1EC434050AD4CF8A55E34401006820019F24340C03FC1C58A563440E07FD6FCF8F5434060C422861D5634405076FA415DF64340D0656B7D91503440508E0244C1FE4340C0F8F884EC5034400009C38025FF434060BEA085046C3440C8BB783F6E074440D0B2B5BE48703440602E54FEB5084440504CDE0033733440D00F23844709444030C85D842976344000C11C3D7E09444010068200197A3440607C7C4276084440207A19C5727B3440B8B393C151084440101286014B8E34405801F73C7F084440F0B5F63E5595344008E2E7BF070944406034D6FECE9A344008274D83A2094440E028EB37139F344080992842EA0A4440604F1F813FA83440382CF180B20B444050D026874FAA344058431B800D0C444050BEA08504AC344038232E008D0C4440D04334BA83AC3440B89ECC3FFA0C4440C0EAE5779AB8344028232E008D1C4440E0CABDC0ACB83440D8031F83151D4440A0E0F08288B83440908461C0921F444060BB5F05F8B63440D8CABDC0AC204440A0FB3905F9B53440803CBB7CEB21444070AEEFC341B63440306211C30E234440D03FC1C58AB63440D8C77C40A023444050C554FA09B7344058431B800D244440202DCF83BBBB3440A8A44E401327444080035ABA82BD3440888461C092274440206BD44334C23440A09B8BBFED274440D0C1FA3F87C934408081204086324440E0EA0088BBCA344008F148BC3C374440E0B5F63E55D53440884B00FE293B4440E02E6D382CE93440906308008E3B4440E025AAB706EA3440A0B05241453B444070C763062AEB344028E78BBD173B44405037177FDBEF344060FEB5BC723B444090A2EBC20FF23440809065C1C43B444090992842EAF2344088423D7D043C444060B08D78B2F3344030F6D03E563C44403083DC45980A3540B89B8BBFED474440A01EA33CF30A3540507C7C4276484440C0E33103950D3540C809A1832E4F4440D0CDFE40B90D3540A06E2EFEB64F44409096E7C1DD0D3540B8ECF483BA544440C0E33103950D3540D8AC33BE2F564440705260014C0D35405828D2FD9C56444030DEC83CF20B354000D3A23EC9574440607500C45D09354010992B836A594440E036FE4465073540A8E67283A15A4440E0B5F63E5505354000C79E3D975B4440A0F5B704E0FB3440607FBDC28265444060F12900C6FB34400085ECBC8D6D444040AA7D3A1E1F3540C8CDFE40B96D44406028D2FD9C2635405831957EC26D4440C0656B7D91503540E009A1832E6F4440E0D38041D257354060853FC39B6F4440F08F4C874E5B3540A89B8BBFED6F444070FA96395D5E3540089D82FC6C704440B05CA8FC6B613540908AE3C0AB714440009700FC53663540E0A6B1BD16744440D0D38041D2673540600DFB3DB1744440C0B837BF616A354000A0C37C79754440307A19C5726B35401048A643A7754440C0DDAF027C83354030232E008D744440A009DCBA9B87354028F6D03E56744440B0EAE5779A883540B8A78FC01F74444010F911BF628935409015E0BBCD734440A059677C5F8C354080A2EBC20F72444070B81E85EB9135408821E4BCFF6F444060B950F9D7923540084E2844C06F444050D6A88768943540580ABABDA46F444060AA0B7899993540B86E2EFEB66F444020D2C43BC0C7354020DB87BCE57644406034D6FECECA354000BB9A3C6577444070D9E90775E93540089700FC53864440D0548847E2E93540E876137CD3864440703D997FF4E9354038F38FBE4987444040465C001AE93540886649809A88444050B3CEF8BEE83540D0C1FA3F87894440A081204086EA3540000C0401328C4440F00E45813EF9354010CADFBDA3904440A0FE7A8505FB354060465C001A9144407087A2409F34364010A0C37C79954440A00F5EBBB4413640E0FA5B02F0954440704CDE0033433640A89509BFD4954440405FD042024E3640D0C77C40A093444070BC9179E457364080ABAE433591444040F38FBE496F3640F820CB82898F4440E034EF3845733640F820CB82898F4440E0A6B1BD167C3640F820CB82898F444020895E46B1943640905704FF5B8F4440901B62BCE695364030F38FBE498F444090A52C431C973640905704FF5B8F4440A000193A76B83640C053E57B46924440A06BED7DAABA36408881204086924440A059677C5FBC3640386211C30E934440107FF8F9EFBD3640B059677C5F94444070FA96395DBE3640483A58FFE794444080A2EBC20FC23640386893C3279D4440907F677BF4C23640288C2D0439A04440C07A32FFE8C33640E07FD6FCF8A54440A0DDAF027CC336405076FA415DA6444040CF83BBB3C236402029B000A6A64440F03DB2B96AC23640A0A44E4013A74440101E8A027DC2364058853FC39BA744407089B2B794C336402078EE3D5CA84440E0488446B0C53640E0C1FA3F87A94440F0847AFA08C83640281DACFF73AA444070B60F79CBCD3640885A457F68AC444040EACC3D24D036409087A2409FAC4440306893C327ED3640A87A32FFE8AB4440C00166BE83EF3640701283C0CAAB4440F072F4F8BDF93640881EA33CF3AA4440D04D637B2D18374000E2E7BF07A94440708D2441B81E374090457EFD10A94440001286014B2E37405073B9C150A94440407D5A457F30374098C2D84290A94440D0DDAF027C333740E006600322AA444070BB5F05F836374008E869C020AB4440C0073E062B3A374020F6D03E56AC4440E04BC5C6BC3A3740A0716F7EC3AC4440901EA33CF33A374088CC07043AAD4440503D997FF4393740803FFCFCF7AE444010990F08743A37408021E4BCFFAF4440E0AF743E3C3B3740A0B393C151B0444060C422861D463740904B00FE29B34440D05D4BC8074937408015E0BBCDB34440407A19C5724B374000DFA63FFBB3444000301004C8703740805A457F68B44440603D997FF48937402835B401D8B244401088BB7A158D3740D806600322B2444050465C001A993740202F3201BFB04440E046753A90A13740A0B393C151B04440D0D03FC1C5A237400818080264B04440A09FAA4203BD374060F5F23B4DB44440C0F5B704E0CB37403838F581E4B7444090992842EAE2374030D8463CD9B9444050D9E90775F937400018080264B844402083DC4598FA3740607C7C4276B8444020E109BDFE1038408848BF7D1DBE444020EACC3D24103840286BD44334C2444020EACC3D24103840B86BED7DAAC24440E04543C6A310384008E869C020C3444060A7CAF78C143840805182FE42C5444070BC9179E417384058FB743C66C64440205C8FC2F518384000C45DBD8AC64440D025AAB7061A38409060C77F81C64440604F1F813F283840805182FE42C54440C06DC2BD32333840288733BF9AC5444080A52C431C3738402841B8020AC744409077F17EDC3E3840D8CABDC0ACC8444020E109BDFE403840305C8FC2F5C84440A0E7A4F78D43384010E2E7BF07C94440801A3048FA443840305C8FC2F5C84440305FD042024E3840B8AD11C138C6444010763579CA4E3840E0FA5B02F0C54440D05626FC527738403829B000A6C64440307D5A457F903840089D82FC6CC044401094BF7B479138402829B000A6BE444010990F08749A38409021E4BCFFB74440B0F5B704E09B3840B05626FC52B7444050D505BCCC9C3840A8A44E4013B7444080A7CAF78CC43840D0BB783F6EAF444090F1D3B837CF3840E0031F8315AD4440A021E4BCFFCF3840009D82FC6CB044400094BF7B47D13840A8622AFD84B34440C0EF3504C7D13840D0F4D901D7B3444050C422861DE63840A0ECF483BAB44440E036FE4465E73840A0ECF483BAB444404013D3855809394008992B836AAF4440E0C66647AA0F3940003961C268AE4440208C9FC6BD29394058672783A3A84440808461C0922F3940A0A44E4013A74440F03905F9D930394008240C0396A64440505260014C3D39400003B34291A04440A0DA6E826F3E3940A8380EBC5AA04440202BC0779B47394080A52C431C9F4440505C8FC2F548394080A52C431C9F4440B0FB3905F95539403838F581E49F44400051DB86515839402023A0C211A04440A0F8F884EC803940000341800CA54440B0F6E978CC8C39403023A0C211A84440A00A7F86378F3940385C8FC2F5A84440307497C459913940080F45813EA9444090AF21382EA73940E0CABDC0ACA8444080BE66B96CD0394030205F4205AB44400060200890E13940B0A70183A4A74440209BE447FCE23940808461C092A74440C0D38041D2E73940C8D38041D2A74440408DD13AAAFA3940D0F71A82E3A8444070B5DD04DFFC394060465C001AA94440109221C7D6233A40B03B4F3C67AD4440B0F06778B3323A40504F1F813FB8444000429605132F3A40A8ECF483BAC4444050DC2A88812E3A40A0A17F828BC544406085B18520233A400003B34291D04440101E8A027D223A40201ADD41ECD0444070ABAE4335213A40201ADD41ECD0444050827005141E3A40607C7C4276D0444040DA1B7C611A3A402850FD8348D04440C01AF67B62193A40A09E3E027FD044400060200890113A40A8BF97C283D44440103A05F9D9103A405870EA03C9D74440B0F8F884EC103A40E00F238447D94440406211C30E133A4008E869C020DB444020895E46B1143A40082DCF83BBDB4440D0DDAF027C233A40A8C519C39CDE4440208C9FC6BD293A40808461C092DF444040BEA085042C3A405070EA03C9DF4440201B4982702D3A40104E2844C0DF4440E0E3DBBB06393A40C0490C022BDF444040048E041A3C3A40E80FCD3CB9DE4440606DE179A93C3A40C0B5DAC35EDE4440209221C7D6433A40D0C77C40A0DB444050BB5F05F8463A4028BA2EFCE0DA444020904C874E4B3A40A8E67283A1DA4440'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('HR','HR','HRV','191','Croatia','5592','455149','150','39','16.693','45.723','0106000020E61000001300000001030000000100000013000000E036FE4465E73040383B3602F15C4540701A3048FAE43040B8716F7EC35C4540A0FB3905F9D53040286893C3275D454070A7CAF78CD43040585260014C5D4540001E8A027DD23040D8CDFE40B95D4540A021E4BCFFCF3040F808C380255F454010938D075BD030409054C37E4F624540E03C80457ED13040A8B0524145634540A059677C5FDC3040806308008E63454080035ABA82DD3040806308008E634540E028EB3713DF3040A8622AFD84634540E03A71395EED3040E082177D0563454000763579CAEE3040B8984A3FE1624540A0656B7D91F030406055A18158624540602E54FEB5F030406073B9C150614540E03A71395EED3040A877F17EDC5E4540C0B837BF61EA3040A8E33103955D454060D9E90775E93040E0B5F63E555D4540E036FE4465E73040383B3602F15C454001030000000100000017000000908D2441B8BE3140B0656B7D91584540F01A498270BD3140B8E0F0828858454030F04E3E3DBA314038F911BF62594540306C06B820B331408054C37E4F5A4540407D5A457FB031405007793D985A4540201E8A027DA2314030DEC83CF25B4540C04334BA839C3140E00CE2033B5C4540E0393FC5718C314088CC07043A5D454060D367075C5F3140D87C957CEC6045409015E0BBCD5B314000C11C3D7E614540E0488446B0553140B8984A3FE1624540E02B2CB81F543140B0DDAF027C6345405055A1815852314088397AFCDE644540F034EF3845533140D088997D1E65454070BFD2F9F05C3140002A8E03AF66454000301004C86031402829B000A666454070AEEFC3416631409048BF7D1D66454070AA0B7899A93140001286014B5E45406034D6FECEAA31408048BF7D1D5E4540C0FE7A8505BB3140A8984A3FE15A454090035ABA82BD3140303E7782FD5945406040DAFF00BF31408018213CDA584540908D2441B8BE3140B0656B7D915845400103000000010000002100000090A2EBC20FD23040B8984A3FE17A4540709FAA4203DD3040D8B837BF617A454020861DC6A4DF3040081E8A027D7A454000A0C37C79E5304000E869C0207B454090F755B950E9304088423D7D047C454010301004C8F03040F8230C03967C4540208E3D7B2EF73040A89ECC3FFA7C4540F00241800C053140789FAA42037D4540407A19C5720B3140F8D5E3BED57C4540E0D03FC1C522314000E869C0207B45406040DAFF002F3140A8E3310395754540F03DB2B96A223140580DFB3DB1744540B06E2EFEB61F314060888043A87445408096598462FB30405016A243E0764540A0F8F884ECF0304060888043A8744540E0CDFE40B9DD304090992842EA724540603A58FFE7D43040302CF180B2734540200F45813EB9304000CD203EB0754540D0A6B1BD16AC304000C45DBD8A764540005AF3E32FA930404819E3C3EC754540709F8EC70CA4304008705E9CF876454050EE3EC747AB3040B840BB438A794540C0FC169D2CB53040C03D7AC37D7A454050807EDFBFB1304060A626C11B7C454090A2EBC20FA23040B8E33103957D4540F01D8A027DA23040881B62BCE67D454030895E46B1A43040101286014B7E454010861DC6A4AF3040E876137CD37E4540A0EAE5779AB8304008E52840147E4540A015E0BBCDBB3040101B4982707D4540A0EF3504C7C13040B0BF97C2837C4540D0488446B0C5304060431B800D7C454090A2EBC20FD23040B8984A3FE17A45400103000000010000004E000000E04334BA834C3140E0F71A82E38045402088BB7A156D3140B8984A3FE17A4540009D82FC6C70314030F04E3E3D7A4540F093BF7B47713140283E7782FD79454050CF83BBB37231404873B9C150794540A0116DC7D485314038327381CB75454040F911BF62A93140909C69C2F66F4540008E3D7B2EA73140E0C1FA3F877145409099D2FA5BA6314058D40B3ECD714540A0F1D3B837AF3140B868ACFD9D754540B001BC0512B03140D87FD6FCF875454040CF83BBB3B23140082A8E03AF76454060C554FA09B731403829B000A6764540D0C43BC093BE314038327381CB75454080A86DC328CC3140302CF180B2734540C05626FC52D7314008BB9A3C656F45400018080264D8314028E44A3D0B6E4540205C8FC2F5D831401048A643A76D4540209D82FC6CE03140B05CA8FC6B69454060C2137AFDE131408818213CDA6845407031957EC2F53140F82CCF83BB634540107A19C572FB31409054C37E4F624540C06E2EFEB6FF3140905D86FF7461454050465C001A293240305C8FC2F5584540A093A641D1383240286211C30E534540109A417C603B3240286BD44334524540207976F9D643324010BB9A3C654F4540C0716F7EC34432400809C380254F454020DB87BCE5463240D0F19881CA4E4540F072F4F8BD4932402829B000A64E4540001B4982704D3240903FFCFCF74E4540D04E0647C94F324038F38FBE494F454090116DC7D45532405001F73C7F50454050B3CEF8BE583240A0E0F0828850454050D505BCCC5C3240804E417E365045406031957EC26532402829B000A64E454070D9E90775693240B068ACFD9D4D45408087A2409F743240F89C82FC6C48454050431B800D743240004BE7C3B342454050431B800D74324028266F809941454060A7CAF78C743240D000DE020940454070116DC7D4753240F89600FC533E4540E036FE4465773240306893C3273D4540F04BC5C6BC7A3240906308008E3B4540F09B5088807F3240D8EE5701BE3945400072C284D1803240D0C1FA3F87394540403A58FFE7843240B86E2EFEB6374540B068ACFD9D853240805704FF5B3745404077D84466863240E0C43BC093364540202A8E03AF863240D0FD9C82FC324540E0AC33BE2F863240E0D03FC1C53245401015C78157833240306211C30E334540D0A9F23D23813240F8DEA63FFB334540307B2FBE685B324070C4CC3E8F3F454050BB5F05F8363240C88BDAFD2A4A454010763579CA0E3240283B3602F1544540B0656B7D91E03140B853E57B466245402000000000C03140101286014B66454000917EFB3ABC31405831957EC2654540F01A4982708D3140D8C77C40A06B4540009D82FC6C7031405837177FDB6F4540F01A4982705D3140286893C327754540E0D38041D2373140D8B5F63E557D4540D02B2CB81F343140A09509BFD47D454070B950F9D7323140881B62BCE67D454030D8463CD931314010CD203EB07D454010938D075B303140080341800C7D4540C0BB783F6E2F314040D505BCCC7C4540D04334BA832C314040D505BCCC7C454050ED0DBE30253140789FAA42037D45406055A1815812314080AEEFC3417E45400015C78157033140D0CABDC0AC8045400082397AFC023140D87C957CEC80454050C1E10511013140E07FD6FCF8854540A00F5EBBB40131408848BF7D1D86454060431B800D04314078AEEFC341864540F05147C7D5443140D0C1FA3F87814540E04334BA834C3140E0F71A82E380454001030000000100000012000000D0B5F63E553530403835B401D882454070BC9179E4173040D00F238447814540207D5A457F10304050F833BC5981454060BFD2F9F00C3040D08558FD11884540B0F8F884EC10304030E109BDFE8845406031957EC2153040903CBB7CEB89454090812040861A3040E0B837BF618A4540306893C3271D304088812040868A4540709065C1C42330406082FE428F8A454060D367075C2F3040281DACFF738A4540B0FE7A85053B3040A8A10DC0068A454080F1D3B8373F3040805D86FF74894540207D5A457F403040E00F2384478945409018213CDA4030408818213CDA88454090ABAE43354130408821E4BCFF874540E04543C6A3403040500ABABDA487454060C422861D363040884B00FE29834540D0B5F63E553530403835B401D88245400103000000010000002900000020359886E18F30401024287E8C9D4540F0CB9A58E0933040B84F8E02449B4540605B23827198304070BB7B80EE9B4540809FAA42039D3040F899417C609B454090DD5A26C3A5304060103CBEBD9B4540509E4143FFA83040A8A44E40139B4540D0C1FA3F87A9304008274D83A299454000FF2268CCB030400097E4805D974540B05759DB14B33040A002999D459545401012BEF737B83040806CCB80B394454030861DC6A4CF304058888043A894454070C422861DF6304030E78BBD1793454040B60F79CB1D3140A85CA8FC6B914540F057C85C1928314030DBC01DA8914540B0868C47A930314010483481229045404041D47D002A3140D80627A25F8F4540A0A86DC3281C314038DB87BCE58E454010763579CA0E314058FB743C668E454080ABAE4335E13040D0BB783F6E8F4540A058350873BF3040C0B321FFCC9045409081204086AA3040306E15C4408F4540E040F33977A73040B85626FC528F4540C0CABDC0AC883040D8B837BF6192454050BB5F05F8763040B0BF97C283944540C031AEB8386E3040F8CC203EB0954540A0F8F884EC60304088C9C6832D9845406037177FDB5F3040109D82FC6C984540209C5088805F30409018213CDA984540D0B2B5BE48603040B0AAD0402C9945401094BF7B4761304058F833BC59994540200341800C75304080992842EA9A4540B074B0FECF793040F8E769C0209B4540C0ACDEE17684304040683D7C999A45406079E6E5B08F3040E8EBA4BE2C974540B0EFFCA204953040D05296218E974540F0E49A02998D3040B84F8E02449B45401096EA025E863040F87B293C689C4540705B94D9208730400079E8BB5B9D4540F0949D7E508B3040E0E21A9FC99C454010282A1BD68C3040A0A487A1D59D454020359886E18F30401024287E8C9D45400103000000010000001F000000E025AAB706DA3040281DACFF73A24540E0D38041D2D73040E006600322A24540C0DDAF027CD3304038F04E3E3DA2454050E78BBD17CB3040E0B837BF61A24540E036FE4465B7304080A2EBC20FA24540C0716F7EC3B43040603D997FF4A14540A017EFC7EDAF304010C11C3D7EA1454030E109BDFEA03040E0C1FA3F87A14540107976F9D6933040E0B837BF61A24540100341800C853040089A417C60A3454060B5DD04DF7C3040A0BF97C283A4454070C763062A6B3040D000DE0209A84540F02E6D382C693040B0E0F08288A845408000193A766830408018213CDAA845408009DCBA9B673040808AE3C0ABA945408009DCBA9B673040386BD44334AA4540106893C3276D3040A874B0FECFB145403069C537146E304088A2EBC20FB2454020861DC6A46F3040B0A10DC006B24540E0548847E2993040A8E0F08288B04540F034EF3845B33040E009A1832EAF454010301004C8C03040B8DA6E826FAE4540102A8E03AFC63040385FD04202AE454060499D8026CE3040D8031F8315AD454080F1D3B837CF304088397AFCDEAC454080ABAE4335E13040A0AAD0402CA94540B053E57B46E23040E07C957CECA845402082397AFCE23040786649809AA84540B0DDAF027CE33040A86E2EFEB6A74540306C06B820E330408048BF7D1DA64540E025AAB706DA3040281DACFF73A2454001030000000100000012000000D05A0A48FB6330405007793D98AA4540D0656B7D91603040D806600322AA4540F008C380255F304030F04E3E3DAA4540407D5A457F5030405070784144AC4540F095CE876735304038E109BDFEB0454040895E46B13430406073B9C150B1454090E67283A1323040382CF180B2B34540001E8A027D32304078A86DC328B44540E0D03FC1C5323040500DFB3DB1B44540901A3048FA343040709FAA4203B54540505260014C3D3040B89ECC3FFAB44540207D5A457F40304010D6E3BED5B44540A009DCBA9B4730406070784144B44540C0E7A4F78D533040301DACFF73B245407087A2409F543040306BD44334B24540A09065C1C463304010C79E3D97AB4540E02B2CB81F643040904B00FE29AB4540D05A0A48FB6330405007793D98AA45400103000000010000000D000000A021E4BCFF5F2F40302F3201BFD0454000E3A7716F5E2F40582E54FEB5D04540A0978A8D79552F40C8C1FA3F87D14540406552431B482F402814E97E4ED34540E0C98B4CC0372F4020E44A3D0BD645402020990E9D362F4058FB743C66D6454040E2AC889A382F40A05FE97C78D64540803E3C4B90412F40E8AC33BE2FD6454080DF6B088E432F4058499D8026D64540406211C30E532F4090CC07043AD54540C0716F7EC3542F40B09ECC3FFAD44540E0A4A2B1F6672F4010C11C3D7ED14540A021E4BCFF5F2F40302F3201BFD0454001030000000100000013000000007497C459B12E40F820CB8289E74540A0D558C2DAC02E401093A98251E3454000D48041D2A72E40D088997D1EE5454060C2137AFD812E4038E78BBD17EB4540E0B0A6B2287C2E406070784144EC45402007B474057B2E407887A2409FEC4540E0ED974F56742E40B077F17EDCEE454000C87C40A0732E4030F38FBE49EF4540A05417F032732E40004E2844C0EF454020BFB9BF7A742E4028EACC3D24F0454080C554FA09772E40904E417E36F04540E00F77F52A7A2E408021E4BCFFEF4540A094490D6D802E408848BF7D1DEE4540802CB64945832E4000A0C37C79ED4540E017080264882E407887A2409FEC454000AD33BE2F962E40D882177D05EB45404051BD35B0A52E40A0C2D84290E9454040DC2A8881AE2E4080C9C6832DE84540007497C459B12E40F820CB8289E745400103000000010000001000000060895E46B1E42E40B0C2D84290F14540A03579CA6AE22E40A85CA8FC6BF14540C0BEB9BF7AD42E40883CBB7CEBF1454000274D83A2D12E4078A2EBC20FF2454000999EB0C4B32E40D0C43BC093F645400007B474059B2E40E0D03FC1C5FA45404077D84466862E40B0B393C15100464020809BC58B852E408818213CDA00464000A5A2B1F6872E40100F45813E01464020B0743E3C8B2E4028F911BF6201464000301004C8902E405873B9C150014640E0D8D0CDFEC02E40B07A32FFE8FB4540C023F3C81FC42E403014E97E4EFB454060B08D78B2E32E40A0984A3FE1F24540609E077767E52E40A8A10DC006F2454060895E46B1E42E40B0C2D84290F145400103000000010000000E000000E0B2B5BE48802E40E00660032202464020A8E331037D2E40903CBB7CEB014640202DCF83BB5B2E40A85FE97C78064640C0069B3A8F422E405834D6FECE0A464080DF6B088E232E4020E109BDFE104640002FDE8FDB1F2E40682B137EA9134640C021E4BCFF1F2E40A8A78FC01F14464080069B3A8F222E4078A86DC328144640A017EFC7ED4F2E40E0FA5B02F00D46408000193A76582E40B8716F7EC30C4640604278B4717C2E40C8F19881CA0646400009C380257F2E408848BF7D1D064640206C06B820832E4080992842EA024640E0B2B5BE48802E40E00660032202464001030000000100000039000000A01B62BCE6B52D40B8DA6E826F16464000B1A6B228FC2D40004BE7C3B30A4640C087A06AF40A2E40009DBB5D2F094640E08BBCAC890D2E40C0ADD85F76054640C0D03FC1C5122E4058FEB5BC72034640E06ABB09BE192E40E873D2FBC6014640A0E7154F3D2A2E40009700FC53FE4540C015E0BBCD2B2E40385FD04202FE4540C0DCB5847C302E40084E2844C0FD4540A017601F9D322E40A09B36E334FE4540C04EECA17D3C2E407803CC7C07FD454040747ADE8D3D2E405880D3BB78FB4540E067244223402E4028D2A8C0C9FA4540000F45813E492E40A874B0FECFF945408079573D605E2E4070855B3E92F64540A06DFC89CA6E2E40A8ECF483BAF44540E0AA24B20F722E4080A86DC328F44540A07A32FFE8732E401015C78157F3454000EFAB72A1722E40881EA33CF3F2454080F1D3B8376F2E40A8A10DC006F2454060FDD7B969632E403820ED7F80EF4540A0656B7D91602E4050853FC39BEF454000B1A6B2285C2E40D000DE0209F04540E0D58F4DF24B2E40883CBB7CEBF145402077D84466462E4010D061BEBCF24540E05626FC52372E406031957EC2F54540206211C30E332E40908D2441B8F6454040895E46B1242E405082FE428FFA4540C05A99F04B1D2E4058888043A8FC4540C04D637B2D182E40E0C43BC093FE4540201E8A027D122E40587C7C4276004640A06DFC89CA0E2E40D0C1FA3F870146406083DC4598FA2D4078A52C431C0746402090DB2F9FF42D4038172AFF5A084640007497C459F12D40305C8FC2F50846404026A94C31DF2D40B8D4B320940B4640A0978A8D79D52D40D87FD6FCF80D464080DF6B088EC32D40D8CABDC0AC104640A0893E1F65BC2D40E0ABAB02B5104640203A3FC571B82D40B8E67283A110464000D5EAABABB22D4068B56B425A114640207842AF3FA92D4050499D802612464060397CD289A42D40485CE49EAE12464020356090F4A12D4070B54E5C8E134640E05AB56B42A22D4030C5E3A25A14464060397CD289A42D4058096B63EC144640209A42E735A62D4018D82AC1E2144640A0170AD80EA62D40588847E2E513464040C8CF46AEAB2D40D07CB262B8124640A03D5DDDB1B02D40485CE49EAE1246404031074147B32D40B08FF98040134640C05F94A0BFB82D40E8A9B9DC60124640E051D66F26BE2D40B853E57B46124640802FF7C951B82D40E8A6B1BD16144640A0E4D4CE30B52D40905182FE4215464020BFB9BF7AB42D40A8AD11C138164640A01B62BCE6B52D40B8DA6E826F1646400103000000010000004800000020412B3064AD2D40A0F0F620044E4640E0C43BC093BE2D4008CD203EB04D4640C0B2B5BE48C02D40E07FD6FCF84D46406045B9347ED12D4028327381CB4D4640407A19C572DB2D4008240C03964C46404023DA8EA9EB2D40D0066003224A4640E04334BA83F02D40A0504F1F8147464040C2C073EFF92D404089CF9D6045464080B14CBF44042E40B07D3A1E3344464020BFB9BF7A142E40A8B0524145434640E0DB114E0B162E40801EA33CF3424640802FF7C951182E40386BD44334424640409E077767252E4000CD203EB03D46404077D84466262E40585260014C3D4640601A3048FA242E40E0031F83153D4640C021E4BCFF1F2E40281A6B7F673D464040FEF0F3DF1B2E40901B62BCE63D464000F110C64F132E40A8141F9F903F4640204DF6CFD3082E40F05A423EE83F464040809BC58B052E40B074B0FECF414640C08F15FC36FC2D406837DE1D1943464080698995D1F02D40484A253CA1434640E0F75278D0E42D40F0D6DD3CD545464080C9C7EE02D52D4020F0F961844646408047567E19D42D4088BA0F406A454640C0C9C51858DF2D409090813CBB44464040ECF82F10FC2D4048CEC29E763E46406084B9DDCB1D2E407857CB9D9936464060BB438A01322E406040A19E3E3446402091D442C9242E40786A12BC2137464080A10F96B1192E4038FBCA83F438464040E4BA29E5152E40A095ED43DE3C4640E0C98B4CC0172E40809FAA42033D464060A148F7731A2E40B09ECC3FFA3C464040240C03961C2E40A0716F7EC33C46400023DA8EA92B2E40084BE7C3B33A464020FEF0F3DF3B2E40484F1F813F38464060C763062A7B2E40F8D5E3BED52C46404000000000802E4050793BC2692B464020261B0FB6802E40D0FD9C82FC2A464000BC783F6E7F2E40583D997FF429464080CAA48636702E40F808C38025274640A0143C855C592E4048B071FDBB284640802634492C592E40901B62BCE6254640E05FE97C78562E40A89509BFD425464000D48041D2472E4038DB87BCE5264640E0703D0AD7432E4000BB9A3C65274640E0E1934E24402E40B09B8BBFED274640A04D637B2D382E40A05CA8FC6B294640C04B546F0D342E40A8B915C26A2A4640001E8A027D322E40A8B05241452B4640606B7D91D02E2E401893FE5E0A2F4640C091D09673392E40D8F753E3A52F464060F2CF0CE23B2E408030F0DC7B30464000AFEDED96342E40E0F736FDD931464060AA0CE36E282E407082E15CC3324640A00A0E2F88202E40F80E7EE20032464020CB82893F122E408045459C4E32464060FA980F080C2E406079C9FFE43546406037177FDBF32D4058677C5F5C3A4640A0DA368C82D02D4048747ADE8D3D4640A0A983BC1ECC2D40409E245D333F4640C0716E13EED52D4078962023A0404640A05A99F04B7D2D40B85FE97C78564640A02634492C792D40D000DE02095846406009DCBA9B772D408018213CDA5846408085048C2E772D4060F833BC59594640C02FF7C951782D40F8264D83A25946400083DC45987A2D40A85CA8FC6B59464020EC6AF2947D2D40D0F71A82E358464040E2033BFE932D400836E7E09954464020412B3064AD2D40A0F0F620044E46400103000000010000001E00000000B0743E3C0B2D40580DFB3DB13C464020E9297288082D4000240C03963C46404051BD35B0052D40580DFB3DB13C464020B1A6B228BC2C40906308008E4B464000AB24B20FB22C40E87954FCDF534640E0A6B1BD16AC2C4008C11C3D7E5946400023DA8EA9AB2C4080812040865A4640C0CCCCCCCCAC2C4088992842EA5A464060573F36C9AF2C4088992842EA5A464060B950F9D7C22C404873B9C150594640000D36751EC52C4058465C001A594640206552431BC82C406001F73C7F584640E00E45813EC92C40306552431B58464020B937BF61CA2C40606D37C137574640008A592F86CA2C4058499D8026564640C0921CB0ABC92C40885A457F68544640A074B0FECFC92C4010CADFBDA3504640A0DE52CE17CB2C40004E2844C04F4640207D5A457FD02C40605260014C4D4640000341800CD52C409015E0BBCD4B464040D026874FDA2C40301DACFF734A4640C04B546F0DF42C40F8230C03964446406054FEB5BCFA2C4050793BC2694346408082C30B22022D40B8984A3FE1424640406552431B082D4038266F809941464020861DC6A40F2D40A86E2EFEB63F464020274D83A2112D4008DC65BFEE3E464020274D83A2112D4058FB743C663E464080D367075C0F2D40E0031F83153D464000B0743E3C0B2D40580DFB3DB13C46400103000000010000001800000080CD7344BE832D400088D860E166464020179D2CB58E2D40F85D11FC6F6546406013D21A83A62D40B0D4B3209461464080F755B950B92D40A859677C5F5C46400007B47405BB2D40381DACFF735A4640A0737E8AE3B82D40B853E57B465A46408045B9347EB12D40883CBB7CEB59464080DC2A8881AE2D40B8A10DC0065A4640A059677C5FAC2D4030F04E3E3D5A4640407A19C5727B2D4008274D83A2614640A0A609DB4F662D4028327381CB61464020A5677A89512D4050FE60E0B965464000C1559E40602D403041F163CC654640A0A609DB4F662D4048EF54C03D674640000C040132742D4028E44A3D0B6646400023DA8EA96B2D4030E109BDFE68464040634337FB632D40D88BDAFD2A6A4640E08C9AAF925F2D4008E869C0206B464000965D30B85E2D40886308008E6B4640A06E2EFEB65F2D4030DEC83CF26B4640001E8A027D722D4090CC07043A6D4640401B4982707D2D40D0BEB9BF7A6C464060A7CAF78C842D40F814C781576B464080CD7344BE832D400088D860E16646400103000000010000004700000040859675FFE82C40589EEBFB7074464000B77D8FFAE32C40F03FF9BB77704640C0AF743E3CEB2C40903CBB7CEB69464000E3A7716FEE2C4040B3CF6394674640005471E316EB2C4018C99063EB63464020815D4D9EF22C4038C2A2224E614640E0003274ECF02C40D8F19881CA5E464040B1C05774F32C400069FF03AC594640C02CB64945032D408096E7C1DD554640206002B7EE0E2D40603D997FF4514640000AF5F411102D4090457EFD1051464080D367075C0F2D40582E54FEB5504640E0F0D8CF62092D40588E0244C14E4640C0D38041D2072D40B0DA6E826F4E464020240C0396FC2C40A868ACFD9D4D4640405DC136E2F92C40600438BD8B4D4640E0C98B4CC0F72C4028327381CB4D464080BB5F05F8E62C4080C9C6832D504640803F373465C72C40305C8FC2F5584640E0B2B6291EC72C40786F0C01C05D4640C085CABF96BF2C40C846205ED75F46408047AAEFFCBA2C408848BF7D1D664640E0921CB0ABA92C40A8716F7EC36C46406051A04FE4A12C40D0AF1F62837146406016F71F99962C40B0B60DA32074464080C5E061DA972C40487172BF437746406043E389209E2C4070A06B5F4079464060B60F79CBAD2C40281A6B7F6775464060573F36C9AF2C40D088997D1E75464060BC9179E4B72C40080C0401327446408014AE47E1BA2C40D8A6B1BD167446402077D84466C62C4028DEC83CF2734640004F95EF19C92C4060431B800D744640E0AF743E3CCB2C40E00CE2033B744640C059677C5FCC2C408887A2409F74464060BFD2F9F0CC2C40206893C327754640405C8FC2F5C82C40D0B837BF617A4640E0D24ECDE5B62C40203B3602F1844640E0E4D4CE30B52C4038327381CB854640004C546F0DB42C40E8AC33BE2F86464020861DC6A4AF2C4088A52C431C87464000C4094CA7AD2C4000BB9A3C6587464040D6A88768A42C4090C9C6832D88464020261B0FB6A02C40682E54FEB588464000CEFE40B99D2C4060F833BC5989464040BFD2F9F08C2C4088CC07043A8D464000A7B1BD168C2C40908D2441B88E4640C0D58F4DF28B2C40286E15C4408F4640A032384A5E8D2C40804E417E3690464020240C03969C2C40081B498270954640C08C9AAF929F2C409048BF7D1D964640A05CA8FC6BA12C4060FB743C6696464080703D0AD7A32C408060C77F81964640A05DDA7058B22C40480438BD8B9546408085048C2EB72C40386893C327954640201077F52ABA2C4038232E008D944640805A99F04BBD2C40009A417C6093464040F52D73BABC2C402835B401D89246408014AE47E1BA2C406007793D9892464020D9E90775B92C4028F04E3E3D924640C05626FC52B72C40B85CA8FC6B914640E0E4D4CE30B52C40286E15C4408F4640A0C98B4CC0B72C40303B3602F18C464000D9D0CDFEC02C40808D2441B886464080B81E85EBD12C40886649809A804640E05FE97C78D62C4078A52C431C7F464040D026874FDA2C4028E44A3D0B7E4640E0B2446799ED2C40003FAA61BF7D46406030478FDFF32C40F0C308E1D17A4640E0A3C519C3EC2C40C0BC395CAB79464040859675FFE82C40589EEBFB7074464001030000000100000023000000A079008BFC822D405801F73C7F7846406009DCBA9B772D40B8B393C151784640207497C459712D4028172AFF5A78464000809BC58B652D406073B9C150794640200F45813E492D40809065C1C47B464080BB5F05F8462D4010DFA63FFB7B4640C02E51BD35202D4088B454DE8E82464080F755B950F92C4058707841448446408068ACFD9DF52C4030D505BCCC844640A032384A5EED2C4058499D8026864640E0D8D0CDFEE02C4008CADFBDA3884640009F20B1DDDD2C40D80F238447894640404B3B3597DB2C40A0A10DC0068A464060C763062ADB2C40D082177D058B4640202DCF83BBDB2C40806308008E8B464080C3B64599ED2C40004BAE62F18F4640E0066003220C2D40A0620E828E924640A04B546F0D142D403829B000A69E4640802634492C192D403820ED7F809F46408014AE47E11A2D4010D3A23EC99F464020EC6AF2941D2D40F84D2844C09F4640008A592F862A2D40803FFCFCF79E4640C07F828B152D2D40E0F19881CA9E4640006002B7EE2E2D4000C45DBD8A9E464020013274EC302D40D8CDFE40B99D464020301004C8502D40A06E2EFEB68F464020E9297288682D40282F3201BF88464000295C8FC2952D40B0AAD0402C814640C0A7E331039D2D40F820CB82897F4640C094490D6DA02D40B0DA6E826F7E4640803E3C4B90A12D40507FBDC2827D4640E0D8D0CDFEA02D40709FAA42037D464000B1A6B2289C2D40E8A6B1BD167C4640809E077767852D4000CADFBDA3784640A079008BFC822D405801F73C7F784640010300000001000000F102000070069B3A8F92304000D6E3BED53C4740D0488446B095304028232E008D3C4740D0DDE7F8689930404074417DCB3C47409027D87F9D9B3040309F573CF53C4740C0F8F884ECA0304040D505BCCC3C4740000F45813EA9304010C79E3D973B4740106893C327CD30400806820019324740108E3D7B2ED73040785704FF5B2F4740E0CDFE40B9DD3040600438BD8B2D4740B06E2EFEB6DF3040905A457F682C47409018213CDAE03040682B137EA92B474050E109BDFEE03040584CDE00332B4740D05D4BC807E1304048BF28417F274740109C887E6DE1304028C0B0FCF9264740207976F9D6E33040E0BEB9BF7A24474060A7CAF78CE4304078A86DC328244740307A19C572EB3040D80F2384472147402023A0C211F03040307AA702EE1F474050465C001AF93040901B62BCE61D474070D026874F0A314058793BC2691B4740209700FC53263140386E15C440174740D036FE44652731403041B8020A174740F03730B951283140588E0244C11647404069C537142E3140B8A78FC01F144740209C5088802F314058FEB5BC721347409014AE47E13A314008BEDBBC710C4740505260014C3D3140004BE7C3B30A474090ABAE4335413140D876137CD3064740106BD44334423140881EA33CF3024740B05CA8FC6B413140A0E67283A1024740B0EF3504C7413140286BD44334024740B06E2EFEB64F314008D6E3BED5FC4640E0548847E2593140B0A10DC006FA46409015E0BBCD5B314030266F8099F9464070B08D78B2633140D88558FD11F84640B0FE7A85056B3140580ABABDA4F74640B059677C5F6C314060853FC39BF7464050DC2A88816E3140809C69C2F6F7464020F38FBE496F3140E0B2B5BE48F846401009C380256F314008301004C8F84640E0CF29C8CF6E3140C0E07EC003F9464080035ABA826D3140783CBB7CEBF946401096CE8767753140E08BDAFD2AFA4640D0C77C40A0933140F817080264F8464090116DC7D4953140A89B8BBFEDF74640F040F33977973140B05626FC52F74640E0B2B5BE48A0314028DEC83CF2F34640A07A32FFE8A331409054C37E4FF24640A0AEEFC341A63140A0B393C151F046405043FF0417A73140988DB27E33ED4640704F1F813FA83140D0C77C40A0EB4640205C8FC2F5A831402014E97E4EEB4640109A417C60AB3140A8984A3FE1EA4640D03C80457EE1314028F6D03E56E44640F0264D83A2013240B0ECF483BAE44640406E15C440273240A8716F7EC3E44640009D82FC6C303240885A457F68E4464070B08D78B23332406070784144E44640C0E0F0828838324010DFA63FFBE3464040E78BBD173B3240D8C77C40A0E3464050BFD2F9F03C3240286211C30EE3464050499D80263E32405855A18158E2464050EACC3D2440324030D8463CD9E14640F0D03FC1C542324030266F8099E1464020F6D03E56543240886649809AE04640B0FB3905F9553240A0E0F08288E04640E03730B95168324000D3A23EC9DF464010240C03966C32403038F581E4DF4640D03C80457E71324028172AFF5AE04640B050A4FB398D3240E8AC33BE2FE6464090F1D3B8378F32406828D2FD9CE646400018080264983240888AE3C0ABE94640E025AAB7069A3240C053E57B46EA4640F03A71395E9D32405870784144EC464020F38FBE499F324000CD203EB0ED4640208E3D7B2EB73240303B3602F1F44640F02E6D382CB93240785A457F68F44640A0E9B303AEC732408081204086F24640708D2441B8CE3240806308008EF34640B02D043928D1324070361D01DCF446407096CB46E7D43240D0AF58C345F0464050CDE50643D532405037177FDBEF464070A2EBC20FE232400806820019EA4640709065C1C4E3324028266F8099E94640B05626FC52E7324028E109BDFEE84640F0CABDC0ACE83240D0F71A82E3E84640900C1D3BA8EC3240B89B8BBFEDE7464070A7CAF78CF4324000BEDBBC71E44640B047C5FF1DF53240E0A6B1BD16E44640F095CE8767F53240602B137EA9E34640A02897C62FF8324038BC5983F7D54640306552431BF83240001B498270D5464060DA8D3EE6F73240A8D8B5BDDDD44640801B62BCE6F53240002DCF83BBD34640109D82FC6CF03240282F3201BFD046406040DAFF00EF3240D000DE0209D0464060AA0B7899E9324010D3A23EC9CF4640F0154F3DD2E83240805D86FF74CF4640E070033E3FE832401821E7FD7FCE46404028D2FD9CE63240903CBB7CEBC9464060C554FA09E7324030E109BDFEC8464060E960FD9FE7324098C519C39CC84640207CB779E3EC3240B8A78FC01FC6464050948444DAEE3240481630815BC54640A0E925C632F1324010FDBE7FF3C4464000E259828CF4324048EFC682C2C44640A0ABE63922F7324010FDBE7FF3C4464070514A0856F93240E8B1BB4049C5464080F1D3B837FF3240E0BB783F6EC74640607D04FEF0FF3240081555BFD2C7464050E109BDFE0033408821E4BCFFC74640C0C77C40A003334088C9C6832DC8464000D1CDFE400533404005A4FD0FC84640009700FC530633406037177FDBC74640F08095438B18334050317903CCC2464070067FBF981933409802D2FE07C24640F0E2E13D071A3340782AA73D25C146400024287E8C193340D07FD6FCF8BF4640B0328CBB41183340F8CC920035BF4640E060527C7C163340E0A96400A8BE464070992842EA123340B0AD11C138BE4640600CE544BB0E3340B8CB457C27BE4640D050A4FB390D3340F81186014BBE46408014AE47E10A3340082A8E03AFBE4640309221C7D6073340A05CA8FC6BBF464000D1CDFE4005334088543541D4BF4640E024EA059F023340E0CAD93BA3BF46401000000000003340D076137CD3BE464010DCF3FC69FF3240B837F8C264BE4640F028EB3713FF32407896E7C1DDBD4640E0B837BF61FA324000D9243FE2B14640007C7F83F6FA324090BD50C076B046402088BB7A15FD3240B0BC564277AF464020D505BCCC1C334050499D8026A64640C0DDAF027C23334028D505BCCCA4464030895E46B130334000882D3D9AA24640F0EB1681B1423340888AE3C0AB9F4640C03AAB05F6483340E8CA4BFE279F464020A298BC0152334078C18BBE829E4640C0C7D2872E58334090C34483149E464000904C874E5B3340D87FD6FCF89D4640F0627D0393633340880C8FFD2C9E4640E05BAE7E6C663340E8AC33BE2F9E464040E78BBD176B334020E44A3D0B9E4640E04334BA836C3340503A58FFE79C46401088BB7A156D3340A8984A3FE19A4640700C1D3BA86C3340784E417E3698464010917EFB3A6C33403041B8020A974640F0980F08746A33408060C77F81964640000F45813E69334060FB743C6696464020F04E3E3D5A3340D8AC33BE2F9646401082397AFC423340A8A44E401397464070CAA4863640334008BB9A3C6597464010F38FBE493F3340500ABABDA4974640A0A86DC3283C3340805D86FF7499464070BC9179E4373340F85A7B9FAA9A46408072F8A41335334038E78BBD179B46409021E4BCFF2F3340789065C1C49B46408015E0BBCD2B3340302CF180B29B4640E0548847E2293340804B00FE299B4640C06BED7DAA1A3340A859677C5F8C4640B0E33103951D3340E0A6B1BD16844640A09FAA42030D3340D8F19881CA764640A0FE7A85050B3340286E15C44077464040F911BF62093340805704FF5B774640D03730B9510833401009C38025774640B0DDAF027C033340E0B5F63E55754640C0D03FC1C5023340789FAA4203754640D046753A90013340080C040132744640E0A9F23D23013340889065C1C473464090ABAE4335013340D8AF743E3C734640D03DB2B96A023340101E8A027D72464060431B800D04334040D8463CD9714640C05626FC52073340E0CABDC0AC704640A0073E062B0A334070AEEFC3416E4640A009DCBA9B0733408048BF7D1D6E464050BC9179E4F73240885182FE426D4640000341800CF5324020ED0DBE306D4640F0393FC571DC3240901B62BCE66D464070AA0B7899D93240E0AC33BE2F6E4640E036FE4465D7324000C45DBD8A6E4640C068ACFD9DD5324088A52C431C6F464000904C874ECB32405882FE428F7246401073F4F8BDC93240904B00FE297346409087A2409FC4324088CC07043A75464070B950F9D7C2324088C9C6832D784640B0E7A4F78DC33240285C8FC2F578464040E44A3D0BC63240E0F71A82E3784640E0D38041D2C7324028172AFF5A78464010F04E3E3DCA324088C9C6832D78464020917EFB3ACC3240706649809A784640809FAA4203CD3240A8C2D84290794640102DCF83BBCB3240888D2441B87E464000904C874ECB3240500ABABDA47F46406055A18158A23240B06BED7DAA8A4640F08F4C874E6B3240D8FA5B02F08D4640100341800C45324000C11C3D7E914640107D5A457F403240D873D2FBC6914640702B137EA93B324028F911BF62914640E040F33977373240786649809A90464060C422861D36324000D3A23EC98F464080116DC7D4353240002A8E03AF8E4640D05FE97C7836324030327381CB8D464090E9B303AE373240E0031F83158D4640E0D38041D2373240080C0401328C4640D05FE97C78363240089A417C608B46409087A2409F343240B8984A3FE18A464090069B3A8F323240381DACFF738A46408096E7C1DD2D3240583D997FF4894640E04BC5C6BC2A324078A2EBC20F8A4640307497C45921324080812040868A4640908D2441B81E3240B06BED7DAA8A4640C059677C5F1C3240D082177D058B464060C2137AFD113240B0B6D4415E8D4640A077F17EDCEE3140C053E57B468A464060AA0B7899E93140682E54FEB588464010861DC6A4DF3140A8DA6E826F864640306893C327DD3140E8AC33BE2F8646400006820019DA3140109700FC5386464030ED0DBE30D5314088A52C431C874640A0A2EBC20FC2314030E78BBD178B4640D04543C6A3B03140A06E2EFEB68F4640E0CABDC0AC983140D8FA5B02F08D46408081AE7D0185314088423D7D048E464070DC2A88817E314008E52840148E4640A0F5B704E07B3140B0AD11C1388E464060BEA085047C314080A52C431C8F464060C763062A7B314008301004C8904640D03730B951483140E0C43BC0939646401009C380253F314008C79E3D97934640A0E33103953D3140E082177D05934640B0FE7A85053B3140E0D03FC1C592464050CAA48636303140801EA33CF3924640D03A71395E2D3140E082177D05934640106BD44334123140386552431B98464040D505BCCC0C3140E873D2FBC699464070C763062A0B3140E0B837BF619A464070D026874F0A3140504CDE00339B4640A0F755B950093140D0031F83159D464030FF21FDF6E9304070C45A7C0AA2464050289A07B0D8304008570740DC99464040923D42CDD8304000D9960167994640A0C62FBC92D830405819FF3EE3984640404B1FBAA0D63040B859677C5F984640206211C30ED330408821E4BCFF974640A021E4BCFFCF30408821E4BCFF97464010763579CAAE304038F04E3E3D9A4640908AE3C0ABA9304080992842EA9A4640B088618731A13040A8508880439C464000C3B986199A304030DE3AFF769D4640C07FBA810297304030DE3AFF769D4640C0C551B9898A30405804AA7F109D4640B0961FB8CA873040901EA33CF39C464090129F3BC1863040B0ECF483BA9C464070CE177B2F82304068BE4A3E769B46406088B83995803040D8940F41D59A4640703D997FF4793040F8D2A23EC9974640E01ABB44F56A3040B8196EC0E78F464060307F85CC5D304000577902618546406067D13B155C30403868AF3E1E82464050151A88655B30405086C77E16814640E0177AC4E8593040A85C8C817580464070F23FF9BB5730408848BF7D1D8046405050C3B7B04A3040B8F81400E37F4640A0E7A4F78D43304090457EFD10814640109C5088803F3040903CBB7CEB8146401018080264383040D0C77C40A0834640D0488446B0353040885A457F68844640001E8A027D32304008CD203EB0854640E0CDFE40B91D3040908461C0928F464060BEA085041C3040382F3201BF904640100F45813E0930405855A181589A4640801B62BCE6053040B8622AFD849B4640B07A32FFE803304038DEC83CF29B4640208D9AAF92DF2F40885182FE429D464060AA0B7899D92F4028ED0DBE309D464080703D0AD7C32F40D0BEB9BF7A9C4640E0DE52CE17AB2F40F0E769C0209B464020809BC58BA52F40B053E57B469A4640E0EA56CF499F2F4008E2E7BF07994640C014AE47E19A2F40D08558FD119846402020990E9D962F403041B8020A974640E0D03FC1C5922F40305FD042029646408017EFC7ED8F2F40B8ECF483BA944640C0A4A2B1F6872F4080812040868A4640E020CB8289872F40A85CA8FC6B89464020F2ECF2AD872F40606D37C1378746408074B0FECF892F407848BF7D1D76464040F52D73BA7C2F4038F04E3E3D6A464060D026874F7A2F4010C11C3D7E694640406684B707792F40B0656B7D91684640C0F755B950792F408821E4BCFF67464060BEA085047C2F40B077F17EDC664640000D36751E852F4030F6D03E56644640405C8FC2F5882F400015C78157634640E068ACFD9DB52F4048FEB5BC725B4640C0C98B4CC0B72F40604CDE00335B464060A148F773BA2F40386211C30E5B4640A021E4BCFFBF2F4088992842EA5A4640407A19C572DB2F40904B00FE295B464000D9D0CDFEE02F40801EA33CF35A4640A02CB64945E32F40004BE7C3B35A464040356090F4E92F4038266F8099594640C059677C5FEC2F408893A641D158464030CF83BBB3023040883FFCFCF74E4640A0E0F0828808304000C11C3D7E494640F081397AFC123040B87A32FFE843464010240C03961C3040905D86FF7441464070DC2A88811E3040C8F71A82E340464000938D075B203040E0D38041D23F4640208BFCFA21223040B8AD11C1383E464030CF83BBB3323040905182FE422D4640C0A9F23D2331304090C9C6832D28464020895E46B1243040C8066003221A46407087A2409F243040D0C1FA3F8719464040CDE50643253040B0AAD0402C1946402077D84466263040D8F71A82E3184640405C8FC2F5283040D0CABDC0AC184640F0A6B1BD162C3040886649809A1846400082397AFC32304030E109BDFE18464040DB87BCE5363040D00F23844719464060BFD2F9F03C304028F911BF62194640E01649BBD13F3040E009A1832E194640F07876F9D6433040504F1F813F18464030D2C43BC04730402829B000A6164640E03A71395E4D3040A8A78FC01F144640A0F1D3B8374F3040E082177D05134640D0A9F23D2351304030F911BF6211464080069B3A8F523040600ABABDA40F464040CF83BBB352304088A52C431C0F464050D6A88768543040E0B5F63E550D464090129F3BC156304030DEC83CF20B46405034D6FECE5A3040281DACFF730A4640E0B837BF616A3040600438BD8B054640B050A4FB396D3040B0ECF483BA04464010938D075B703040E0A6B1BD16044640002A8E03AF76304060793BC26903464080ABAE4335813040901EA33CF3024640F02B2CB81F8430406034D6FECE0246409009DCBA9B873040B053E57B46024640C0C1FA3F87893040D8EE5701BE014640D0BEB9BF7AA43040505260014CF54540D05FE97C78A63040E00CE2033BF445405055A18158B23040B0E3310395ED4540D0E7A4F78DB3304080397AFCDEEC4540100341800CB53040602B137EA9EB454090AEEFC341B63040E873D2FBC6E9454060D6A88768D4304090397AFCDEDC45408021E4BCFFEF3040888461C092CF454010895E46B1F4304080CC07043ACD4540503D997FF4F93040E082177D05CB4540A0F5B704E00B314038ED0DBE30C5454020F38FBE490F3140D8A6B1BD16C44540B053E57B46123140089A417C60C34540002F6D382C193140D0EE5701BEC14540001B4982701D3140D0F71A82E3C04540E05D4BC807293140A86E2EFEB6BF4540E02E6D382C39314028ED0DBE30BD4540E0BB783F6E3F314038DEC83CF2BB45402082397AFC4231403835B401D8BA4540801A3048FA44314030D8463CD9B945401096CE8767453140B05CA8FC6BB94540C068ACFD9D453140D8F71A82E3B8454030ED0DBE304531405837177FDBB74540106211C30E433140B877F17EDCB6454050D8463CD94131408848BF7D1DB64540D046753A90413140000341800CB5454050BB5F05F84631405007793D98AA4540D040F33977473140F8264D83A2A9454060465C001A493140B85626FC52A74540A0073E062B4A3140285FD04202A64540307156444D4C314030DEC83CF2A34540A0F1D3B8374F3140A8E67283A1A2454020F38FBE496F3140903FFCFCF79645402009C380258F3140B8A44E40138F4540D053E57B469231406076FA415D8E454040DB87BCE5963140E0031F83158D4540207497C459A1314028D8463CD98945408087A2409FA4314080C9C6832D884540009700FC53A631403041B8020A87454070B3CEF8BEA83140000341800C854540A0073E062BAA3140F02CCF83BB834540602B137EA9AB3140D006600322824540001286014BAE3140A8A44E40137F4540502844C021B03140A0B1DAFCBF7C45407040DAFF00AF31408015E0BBCD7B4540D050A4FB39AD31403814E97E4E7B454040E78BBD17AB3140801EA33CF37A4540D0E2A9471A943140D012F241CF7845408000193A76883140D80F238447794540503A58FFE784314038D8463CD97945401082397AFC8231406055A181587A454060B5DD04DF7C314040D505BCCC7C4540F00E45813E79314068FB743C667E454070B3CEF8BE783140D8F19881CA7E45409000193A76783140B053E57B46824540F0BEB9BF7A743140607078414484454080A7CAF78C5431403829B000A68E4540A0E67283A15231400009C380258F4540F09C82FC6C403140002DCF83BB934540305C8FC2F538314058888043A8944540A077F17EDC2E3140D07FD6FCF895454060B60F79CB2D3140D8AC33BE2F964540B0ECF483BA2C3140B8DA6E826F96454010274D83A2213140885D86FF7499454050CF83BBB3123140D0FA5B02F09D454040CAA48636103140004E2844C09F454010240C03960C3140E0B837BF61A2454000990F08740A3140089A417C60A34540D04543C6A3F03040002A8E03AFAE4540C03DB2B96AE2304008C79E3D97B3454050E109BDFEE03040F82CCF83BBB34540A059677C5FDC3040D87954FCDFB34540F03FC1C58AD63040D87954FCDFB34540F0B2B5BE48D03040E8A6B1BD16B44540E0C77C40A0C3304058888043A8B44540E04334BA83BC3040905182FE42B54540007976F9D6A3304020172AFF5AB8454020CF83BBB3A23040B0656B7D91B84540B0DA6E826F9E3040805D86FF74B94540D04E0647C97F30400818080264C04540008E3D7B2E773040E0C77C40A0C3454070465C001A793040D8A6B1BD16C4454070465C001A793040E0BEB9BF7AC44540A0A52C431C773040A89ECC3FFAC44540F057C9C7EE6E304030327381CBC5454080035ABA826D3040881B62BCE6C54540F0A6B1BD165C30408860C77F81C64540002F6D382C5930408860C77F81C64540E0BB783F6E4F3040587FBDC282C5454000301004C830304008C11C3D7EC14540502B137EA92B3040A8BC564277BF4540C0622AFD842B3040B85FE97C78BE4540E0CDFE40B91D3040809FAA4203BD454040E78BBD171B304078397AFCDEBC4540C04D637B2D18304078397AFCDEBC454000068200190A3040A8E3310395BD4540A093A641D10830406831957EC2BD4540A01D71C806FA2F40A8656B7D91C04540A0A148F773DA2F40286E15C440C7454000295C8FC2D52F40382F3201BFC84540A0716F7EC3D42F40E0A9F23D23C94540C08FDB2F9FD42F40B06E2EFEB6CF4540C08FDB2F9FD42F40504F1F813FD04540C068ACFD9DD52F40582E54FEB5D04540804D637B2DD82F4000301004C8D0454080B5DD04DFDC2F401018080264D04540E06E2EFEB6DF2F40D8B2B5BE48D0454020B937BF61EA2F40B8E0F08288D0454060D367075CEF2F40302F3201BFD0454020CAA48636F02F4050465C001AD14540800F5EBBB4E12F403820ED7F80D74540C05417F032932F4000CADFBDA3E0454060C1E10511912F409018213CDAE04540A06DFC89CA8E2F409018213CDAE0454000261B0FB6602F40202CF180B2E3454000A26131EA322F40F80B040132EC4540207497C459112F40D0F71A82E3F0454020013274EC102F40F8D8243FE2F1454060573F36C90F2F40C053E57B46F2454000789B374E0A2F40404415FE0CF3454000E3A7716FFE2E40B8BF97C283F44540802FF7C951F82E4088CC07043AF54540807F828B15ED2E40D0CDFE40B9F54540603F373465E72E40B85FE97C78F6454060861DC6A4CF2E40786308008EFB454060CAA48636902E4060F833BC59094640C0D24ECDE5762E40306E15C4400F4640E0C3094CA74D2E40E0A9F23D231946404029931ADA502E4040226DE34F1C4640601D71C8063A2E405073B9C15021464060D026874F3A2E40E073D2FBC6214640209F20B1DD3D2E4010C79E3D97234640E0BB783F6E3F2E4030DEC83CF223464000FBAF73D3462E405870784144244640C0F0D8CF62492E40B0A78FC01F24464000B0743E3C4B2E40D8F4D901D723464040B60F79CB4D2E40784B00FE29234640A0143C855C592E40307233DC801F46400018080264682E4010CADFBDA3204640E08E71C5C5692E4008C4245CC82146402047ACC5A7602E4068DF878384244640C0215514AF6A2E40888D791D712446406082548A1D6D2E40D86932E36D2546406026361FD7762E40082D5DC1362446406045B9347E912E40808461C0921F4640000C040132942E40500ABABDA41F4640E068ACFD9D952E40909C69C2F61F4640C08EC70C54962E40507C7C4276204640801B62BCE6952E40305C8FC2F520464020D367075C8F2E40F808C3802527464080F8A41309862E4020C0064488294640C0224F92AE892E4080336ABE4A2A4640C0B5BE4868932E40F87E6ABC7429464000CAA5F10BAF2E40B061DBA2CC244640C052D0ED25C52E404047E4BB94224640200C040132D42E40E00F238447214640006C06B820032F40B8E0F08288204640E022DA8EA90B2F40806649809A2046406069C537140E2F40282F3201BF20464080D367075C0F2F40D8A9F23D23214640A0F1D3B8370F2F40888AE3C0AB2146406032384A5E0D2F40101E8A027D224640008A592F860A2F4008E869C020234640E0A4A2B1F6072F40B0B0524145234640A00F5EBBB4012F401015C78157234640A05FE97C78F62E40504CDE0033234640E0C77C40A0F32E401015C7815723464080BB5F05F8E62E4080A86DC32824464040D6A88768E42E4020F6D03E56244640A0C3094CA78D2E402829B000A62E4640603F373465872E406037177FDB2F4640E0A7E331035D2E4030EACC3D24384640206552431B482E4030232E008D3C464080C1E10511312E409054C37E4F42464060BFD2F9F00C2E4038EACC3D2448464000B937BF610A2E40B8B393C15148464060D6A88768042E40E0B2B5BE48484640C094490D6D002E4008301004C848464080C763062AFB2D40E08BDAFD2A4A464020C87C40A0F32D4058F5F23B4D4C4640C06DFC89CAEE2D40E0CDFE40B94D464060D026874FDA2D40D8F4D901D7534640402C9D0FCFCA2D40A8656B7D91584640E0F0D8CF62C92D40A85CA8FC6B59464060BB5F05F8C62D40604CDE00335B464040C422861DC62D4078A86DC3285C464040C2137AFDC12D40A8A44E4013674640A00F5EBBB4C12D4010CADFBDA3684640603E3C4B90C12D402814E97E4E6B4640A082C30B22C22D40809FAA42036D464080DF6B088EC32D40D87FD6FCF86D4640E0CABDC0ACC82D40A85CA8FC6B714640402C9D0FCFCA2D40C053E57B4672464000301004C8D02D40E00CE2033B74464040EFAB72A1D22D40D088997D1E754640E01F990E9DD62D4000C11C3D7E794640A038BA4A77D72D40809065C1C47B4640C08EC70C54D62D4058888043A87C464040D367075CAF2D40101286014B8E464080B60F79CBAD2D405828D2FD9C8E46406077D84466A62D403841B8020A8F4640C0FDD7B969A32D401009C380258F4640A06ABB09BE992D40084E2844C08F4640E0703D0AD7832D40B8AAD0402C9146400038A110017F2D40A8C2D84290914640E0D24ECDE5762D40081E8A027D92464080D367075C6F2D40906308008E93464080F755B950592D40C05626FC52974640A0622AFD842B2D40D0B2B5BE48A04640A085048C2EF72C40D8D38041D2A7464000F1D8CF62E92C409018213CDAA8464060C2137AFDE12C4028F911BF62A94640E0CABDC0ACA82C40A8B6D4415EAD46404077D84466A62C4080CC07043AAD4640C02CB64945A32C4038232E008DAC4640801B62BCE6952C4038266F8099A9464020E6E8F17B932C408093A641D1A8464020301004C8902C40D0BB783F6EA7464060C2137AFD812C4008CD203EB09D464020E3A7716F7E2C406082FE428F9A4640009F20B1DD7D2C40A8A10DC0069A46404000000000802C4080C9C6832D9846402054FEB5BC7A2C40709FAA42039546402020990E9D762C40A86BED7DAA924640E0285C8FC2752C4028F04E3E3D924640006002B7EE6E2C4000D3A23EC98F464060D026874F5A2C40881EA33CF38A4640E0D24ECDE5562C405055A181588A4640C08FDB2F9F542C40386BD443348A4640206002B7EE4E2C4030F04E3E3D8A4640C06DFC89CA4E2C40080F45813E89464060573F36C94F2C40100341800C854640A0716F7EC3542C40B0B393C151804640A0E1CFF066552C400800000000804640805FE97C78562C40B0BC5642777F4640C05626FC52572C4008C45DBD8A7E464080978A8D79552C40A868ACFD9D7D4640E0A6B1BD164C2C4048793BC2697B4640E06BED7DAA4A2C4028E78BBD177B46404018080264482C40306211C30E7B4640E0CCCCCCCC2C2C40306211C30E7B4640E0955D30B8FE2B4010D061BEBC72464060BEA08504FC2B40080F45813E714640C07A32FFE8F32B4048888043A86C46402015C78157F32B4088A86DC3286C4640C05417F032F32B4000274D83A2694640004C546F0DF42B405873B9C150694640E0A7E33103FD2B40582E54FEB5684640C051D66F26FE2B4038172AFF5A68464000C53BC093FE2B405837177FDB674640E0CDFE40B9FD2B40D8BB783F6E674640206211C30ED32B40B0E67283A1624640607D5A457FD02B40A86BED7DAA624640A059677C5FCC2B40F8E769C020634640A0F4143944A42B40B8B6D4415E6D464000B3B5BE48A02B40D876137CD36E464020CBBDC0ACA82B40A877F17EDC6E464080F1D3B837AF2B4028EACC3D2470464020573F36C9AF2B4008CADFBDA3704640606002B7EEAE2B4088457EFD1071464060DF6B088E832B40A868ACFD9D7D464020F52D73BA5C2B40D8C43BC09386464080716F7EC3342B40000C04013294464020013274EC302B40480ABABDA49F4640809BC6F65A302B40B0E0F08288A0464000FBAF73D3262B40A0DA6E826FA64640E0B3E73235112B4060793BC269B34640E051D66F26FE2A40D076137CD3BE4640E053E57B46022B40A8E0F08288C0464040B08D78B2032B409018213CDAC046406051BD35B0052B408093A641D1C04640C0B0A6B2281C2B4028F38FBE49BF4640A078978BF82E2B4070CA4E3FA8BD464040301004C8302B40286893C327BD4640A0C554FA09372B4000DFA63FFBBB4640E0D8D0CDFE402B4010D061BEBCBA4640803F373465472B400806820019BA46402023DA8EA94B2B40D0EE5701BEB94640E0DB114E0B562B40D0A9F23D23B94640404B3B35975B2B40305C8FC2F5B84640005858703F682B408018213CDAB84640A09BC6F65AD02B40A8A10DC006BA464040F2ECF2ADE72B40201DACFF73BA4640805FE97C78F62B4010D061BEBCBA4640802634492CF92B40A0984A3FE1BA4640A0A148F773FA2B40D8AF743E3CBB4640009F20B1DDFD2B40805A457F68BC4640E0B628B341462C4000D6E3BED5BC46402077D84466C62C408048BF7D1DBE464080622AFD84CB2C40089700FC53BE4640207D5A457FD02C406028D2FD9CBE4640C0D24ECDE5D62C40306E15C440BF464060B3CEF8BEF82C408015E0BBCDC34640E09E20B1DDFD2C40D8B5F63E55C5464020261B0FB6002D405828D2FD9CC6464040B81E85EB112D404876FA415DCE46408021E4BCFF1F2D40580DFB3DB1D44640A08B868C47212D40D888997D1ED54640803F373465272D4000CD203EB0D54640A07A32FFE8332D40A8DA6E826FD646402020990E9D362D40109700FC53D64640E04D637B2D382D40285FD04202D64640602634492C392D400848A643A7D5464080D9E90775392D40809FAA4203D54640A07C410B09382D40B874B0FECFD14640E04D637B2D382D40604F1F813FD0464080C763062A3B2D405840DAFF00CF464080656B7D91402D4008CD203EB0CD4640001E8A027D722D4088423D7D04C44640A0B950F9D7A22D40582B137EA9BB4640E0D9ACFA5CA52D4058A12C7C7DBB4640C0EE1F0BD1A92D4078E525FF93BB46400032AEB838BA2D4020813FFCFCBB464000301004C8D02D40809FAA4203BD4640A061F88898D22D407091ED7C3FBD464000999EB0C4D32D400848A643A7BD46406055A18158D62D401887A5811FBF4640C02F134548F52D40F8C3CF7F0FC0464080FA96395D2E2E40B8BF97C283BC464000179CC1DF2F2E40D8CA2F8331BC4640C07F828B154D2E4030F38FBE49B7464060F833BC59532E409808E23C9CB64640200D198F52592E40F881AB3C81B64640C076BF0AF08D2E40D8AF743E3CBB464080BCADF4DA9C2E40685E807D74C44640E02CCF83BB9B2E4010D6E3BED5C446400081D07AF89A2E40F80E45813EC54640E01C740987962E40C02572C119CC464080ECF7C43A9D2E401066BE839FD0464060BABBCE86B42E40707C98BD6CD34640204278B471BC2E40583D997FF4D9464000B1A6B228BC2E40081E8A027DDA464080C763062ABB2E402835B401D8DA4640C009DCBA9BB72E4060FEB5BC72DB4640A05DDA7058B22E4008C79E3D97DB4640E02CCF83BB9B2E40A8B915C26ADA4640C0B0A6B2289C2E4058F833BC59D94640C0B0A6B2289C2E408093A641D1D846400007B474059B2E40F89C82FC6CD84640E01F990E9D962E40C800DE0209D84640C0ED974F56942E40884E417E36D8464080C1E10511912E40D87C957CECD8464000573F36C98F2E40D873D2FBC6D9464060CAA48636902E406055A18158DA4640A0978A8D79952E40B8E3310395DD46408009DCBA9B972E4068FB743C66DE4640201286014B9E2E40504F1F813FE04640000D36751EA52E40885D86FF74E14640801EA33CF3AA2E401006820019E24640A06E2EFEB6FF2E40D8FD9C82FCEA46400090DB2F9F342F409087A2409FEC4640807C410B09382F409087A2409FEC46402054FEB5BC3A2F40C8BEB9BF7AEC4640E0EB6AF2943D2F408815E0BBCDEB4640002FDE8FDB3F2F4030E78BBD17EB4640801A3048FA442F40206BD44334EA4640A01EA33CF34A2F40805D86FF74E94640C050A4FB394D2F4060F833BC59E9464060CAA48636502F4038F911BF62E9464060DF6B088E632F40909065C1C4EB464060CDE50643652F4050431B800DEC4640C0A16131EA722F4038EACC3D24F84640809BC6F65A702F40B09ECC3FFA04474060573F36C96F2F4038E44A3D0B064740A076BF0AF06D2F40A877F17EDC064740E059677C5F6C2F40F808C3802507474000356090F4692F40885704FF5B074740002DCF83BB5B2F40009D82FC6C08474040EFAB72A1522F40786649809A084740A09BC6F65A502F40C8F71A82E3084740A0116DC7D4452F4080812040860A4740E053E57B46422F4000E869C0200B4740C05FE97C78362F40E876137CD30E4740606211C30E332F4028F04E3E3D124740E0989EB0C4332F40104BE7C3B3124740A0F755B950392F40A8B6D4415E154740A059677C5F4C2F40089A417C601B474060F1D3B8374F2F40D8A6B1BD161C474040EFAB72A1522F4048888043A81C4740C0C98B4CC0572F40B09ECC3FFA1C474060A148F7735A2F40809FAA42031D474040634337FB632F4008D6E3BED51C47408000193A76982F408096E7C1DD1D474060D6A8876804304050499D8026264740A07A32FFE813304010068200192A4740A0716F7EC3143040D0B837BF612A4740F0B5F63E55153040D8D03FC1C52A474030F6D03E5614304038D505BCCC2C4740F07876F9D6133040306893C3272D4740F081397AFC12304008C45DBD8A2E4740406C06B820133040B8E9B303AE2F474040FB58C16F13304070EB19C231314740F0D03FC1C5223040D07954FCDF334740107976F9D623304050431B800D344740002C2CB81F44304000CD203EB03547401000000000403040B0AD11C1383E47405037177FDB3F3040488E0244C13E4740603C11C4794030404898DBBDDC3F4740008BFCFA21423040E0F71A82E3404740C0BEB9BF7A44304038D8463CD941474000DA1EBDE14A3040089DF4BEF1434740901B62BCE655304030F6D03E564447404055A18158623040F0230C039644474050C422861D763040D8D03FC1C5424740F036FE44657730406007793D9842474070FA96395D7E304058F833BC59414740E057C9C7EE7E3040285C8FC2F540474060E61F7D937E3040109D82FC6C404740009C5088807F304088C9C6832D40474070213A048E843040D09A9141EE3E4740201A4F04718E3040187250C24C3D474070069B3A8F92304000D6E3BED53C4740'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('HU','HU','HUN','348','Hungary','9210','10086387','150','151','19.134','47.07','0106000020E610000001000000010300000001000000680200008C2D043928D1324072361D01DCF446407E8D2441B8CE32407C6308008EF34640A7E9B303AEC732408081204086F24640D82E6D382CB932407D5A457F68F44640008E3D7B2EB73240253B3602F1F4464028F38FBE499F3240FFCC203EB0ED4640D63A71395E9D32405470784144EC4640D925AAB7069A3240AC53E57B46EA4640FC170802649832407E8AE3C0ABE9464084F1D3B8378F32405628D2FD9CE64640AD50A4FB398D3240D6AC33BE2FE64640D13C80457E7132402B172AFF5AE04640FB230C03966C32402638F581E4DF4640D63730B951683240FED2A23EC9DF4640A4FB3905F9553240A8E0F08288E0464027F6D03E565432407B6649809AE04640D0D03FC1C542324029266F8099E1464029EACC3D244032402CD8463CD9E1464052499D80263E32405055A18158E2464055BFD2F9F03C3240286211C30EE3464029E78BBD173B3240D2C77C40A0E34640A8E0F08288383240FCDEA63FFBE3464057B08D78B23332405470784144E44640FE9C82FC6C3032407D5A457F68E44640266E15C440273240A8716F7EC3E44640FA264D83A2013240A7ECF483BAE44640D13C80457EE1314027F6D03E56E44640FE99417C60AB3140AB984A3FE1EA4640295C8FC2F5A831402B14E97E4EEB4640514F1F813FA83140D2C77C40A0EB46404243FF0417A73140868DB27E33ED464079AEEFC341A63140A7B393C151F04640A77A32FFE8A331407E54C37E4FF24640D5B2B5BE48A031402BDEC83CF2F34640D540F33977973140AC5626FC52F746407B116DC7D4953140AA9B8BBFEDF74640D2C77C40A0933140FC17080264F84640FB95CE8767753140D28BDAFD2AFA464082035ABA826D3140823CBB7CEBF94640DDCF29C8CF6E3140B1E07EC003F94640FF08C380256F3140F92F1004C8F8464028F38FBE496F3140D5B2B5BE48F846404DDC2A88816E31407C9C69C2F6F74640AB59677C5F6C314051853FC39BF74640A4FE7A85056B3140520ABABDA4F7464057B08D78B2633140D38558FD11F846407F15E0BBCD5B314029266F8099F94640CE548847E2593140A9A10DC006FA4640A86E2EFEB64F3140FED5E3BED5FC4640A6EF3504C7413140276BD44334024740AB5CA8FC6B413140A7E67283A1024740276BD443344231407E1EA33CF30247407AABAE4335413140D576137CD3064740505260014C3D3140FD4AE7C3B30A47407B14AE47E13A314001BEDBBC710C4740FA9B5088802F314054FEB5BC721347402B69C537142E3140A8A78FC01F144740D63730B951283140508E0244C1164740D236FE44652731402541B8020A174740FF9600FC53263140266E15C4401747404ED026874F0A314053793BC2691B474052465C001AF930407E1B62BCE61D47402123A0C211F030402D7AA702EE1F4740257A19C572EB3040D00F23844721474059A7CAF78CE430407AA86DC328244740037976F9D6E33040D3BEB9BF7A2447401B9C887E6DE1304027C0B0FCF9264740CC5D4BC807E130403CBF28417F2747402AE109BDFEE03040514CDE00332B47407E18213CDAE03040562B137EA92B4740A86E2EFEB6DF30407D5A457F682C4740D1CDFE40B9DD3040530438BD8B2D4740008E3D7B2ED730407E5704FF5B2F4740276893C327CD3040FF05820019324740FE0E45813EA9304000C79E3D973B4740A5F8F884ECA030402CD505BCCC3C47407427D87F9D9B3040239F573CF53C4740D63730B9518830402AE109BDFE404740FB20CB82898730405473B9C150414740ABEAE5779A68304027F6D03E565447402DCF83BBB3623040A774B0FECF594740E945ED7E15603040A5BF97C2835C4740FC1A4982705D304052431B800D5C474051BEA085045C304081423D7D045C4740D5AF743E3C5B304027F6D03E565C4740ABE7A4F78D533040AA656B7D916047400282397AFC523040D47C957CEC604740FB928D075B50304029232E008D644740FB928D075B503040A968ACFD9D654740552E54FEB55030408048BF7D1D664740FA264D83A251304055FB743C66664740FF9600FC535630407F8461C0926747400473F4F8BD593040FBE769C0206B47400473F4F8BD593040562B137EA96B474083F755B950593040D7A6B1BD166C4740ABEAE5779A5830407D5A457F686C4740A8E33103954D3040A9A44E40136F474029E78BBD174B3040A5BC5642776F4740000341800C453040AA9B8BBFED6F4740FE99417C603B30407F4E417E36704740FF058200193A3040286552431B70474051C1E10511313040AC5626FC526F4740FD1186014B2E304000C45DBD8A6E47407B9FAA42032D304055FB743C666E47404FCDE506432530407D96E7C1DD6D474052431B800D2430407D96E7C1DD6D47407C992842EA223040FCE42840146E47407F87A2409F1C3040AC5626FC526F474056B950F9D72230402B172AFF5A7047407E9065C1C423304000CADFBDA3704740A5F8F884EC403040A96BED7DAA7A4740A6F27684D3463040AB5FE97C787E474082035ABA824D30407D5D86FF748147407D93A641D1583040D00F23844781474058AA0B78996930402AE109BDFE80474052B81E85EB7130407B6649809A804740D5AF743E3C7B3040D38558FD11804740D4BB783F6E7F3040D5B2B5BE48804740A6EF3504C78130407B6649809A8047402DCF83BBB38230407E18213CDA8047402DCF83BBB3823040D00F238447814740AB5CA8FC6B8130407E8D2441B88E4740FB20CB82897730405534D6FECE924740D6AC33BE2F763040FFCF61BEBC924740A8716F7EC37430405534D6FECE924740037976F9D6733040286211C30E93474051BEA085046C30405055A181589A4740562B137EA96B3040D0D03FC1C59A4740562B137EA96B30402B14E97E4E9B47402CD8463CD971304028F38FBE499F4740286552431B7830402AE109BDFEA04740FE0E45813E7930407AABAE4335A14740A3073E062B7A30407D5D86FF74A147407D96E7C1DD7D3040D3F4D901D7A34740D1CDFE40B97D304027F6D03E56A44740CE5147C7D5743040556D37C137AF4740FD14C78157733040A8A78FC01FB44740FD14C781577330407F87A2409FB4474057B08D78B2733040276893C327B54740D3BEB9BF7A743040FD9FC37C79B5474024809BC58B753040FE47A643A7B54740A8E0F08288783040D1CDFE40B9B54740D0420246977B3040527FBDC282B54740A7E9B303AE973040A9DA6E826FB64740F92CCF83BBA730403BC8EBC1A4BA474059A7CAF78CB43040FD4AE7C3B3C247407F129F3BC1B63040A968ACFD9DC54740D5AF743E3CAB3040FD1186014BCE4740533D997FF4A930405340DAFF00CF474050C422861DA630407B6649809AD0474029ED0DBE30A53040D3F71A82E3D047400282397AFCA23040FE0E45813ED14740D13C80457EA1304027F911BF62D147407A17EFC7ED9F304027F911BF62D1474028F04E3E3D9A3040527C7C4276D04740266E15C440973040A8E0F08288D04740D731AEB8387E3040D0D03FC1C5D24740D0D03FC1C572304001BEDBBC71D44740027FF8F9EF6D30407E5182FE42D547407B9FAA42036D3040530438BD8BD54740505260014C6D3040D3FA5B02F0D54740FD14C7815773304055F833BC59D94740FD1186014B8E3040F92F1004C8E04740A86E2EFEB68F30407E18213CDAE04740A7ECF483BA9C3040A8AAD0402CE147402DCF83BBB3A230405473B9C150E14740266E15C440B730402AE44A3D0BDE4740D82E6D382CB93040527FBDC282DD47400473F4F8BDB93040D388997D1EDD4740A96BED7DAABA3040A7B0524145DB474051BEA08504BC3040A9A10DC006DA4740A7ECF483BABC3040508BC1C3B4D9474052B81E85EBC13040AA9B8BBFEDD74740286211C30EC33040A86E2EFEB6D74740A8716F7EC3C43040520ABABDA4D74740286211C30ED33040FB20CB8289D74740D82E6D382CE93040FE9C82FC6CD8474059A7CAF78CF43040D47C957CECD8474056B60F79CB0D31405534D6FECEDA47405055A181581231407E5182FE42DD4740D446753A901131405055A18158E247405340DAFF000F3140000341800CE547402B69C537140E31405376FA415DE64740027FF8F9EF0D314001BEDBBC71EC4740FA9B5088800F3140514F1F813FF04740562B137EA91B314027F6D03E56FC4740A968ACFD9D25314000000000000048402383DC45982A314029266F8099014840276893C3272D3140FC1D8A027D024840FD1186014B2E3140FD4AE7C3B30248407E18213CDA3031407E1EA33CF3024840FB230C03963C31402B14E97E4E0348409F0436E7E03D3140A7B052414503484099D711876C403140514CDE003303484051C1E105114131407BA2EBC20F024840D0D03FC1C5423140D47C957CEC00484057B08D78B243314000CADFBDA3004840A4FB3905F94531407F4E417E360048405437177FDB4F3140FD4D2844C0FF4740A4FB3905F9553140FED2A23EC9FF4740008E3D7B2E573140A7E9B303AEFF4740A4FE7A85055B3140D2C43BC093FE4740E4BED53A716931400F7BA180EDF847407AABAE4335713140D4B5F63E55F5474081069B3A8F7231407F87A2409FF447407C992842EA723140FE0B040132F4474029ED0DBE30753140A96BED7DAAF24740D236FE4465773140508BC1C3B4F14740A4349BC7617C31409F77634161F04740FF9600FC53B63140A7E67283A1E2474025B03907CFC8314000C79E3D97DF47401D93C5FD47CA3140077E54C37EDF4740A968ACFD9DE53140CA8B4CC0AFDF47407F129F3BC1E631402638F581E4DF47402383DC4598EA3140D5B2B5BE48E04740CE548847E2F93140D4EE5701BEE147402AE44A3D0B1632407AABAE4335E147404DDC2A88811E3240D3F71A82E3E04740800F5EBBB4213240D1CABDC0ACE04740008BFCFA21323240A86E2EFEB6DF4740D7A6B1BD164C32405376FA415DDE47407A17EFC7ED4F3240A9DA6E826FDE47402577D84466563240D576137CD3DE4740A5F8F884EC603240520ABABDA4DF4740A774B0FECF6932405401F73C7FE04740D53DB2B96A723240D28BDAFD2AE24740D2C77C40A0733240AC53E57B46E24740FA980F08748A324028F04E3E3DE24740037CB779E39832407E8AE3C0ABE14740286211C30EA33240A8AAD0402CE147402DD2C43BC0A7324052465C001AE14740F92CCF83BBAB324027F911BF62E1474052B5DD04DFAC324029266F8099E14740F92F1004C8B032405307793D98E247408200193A76B832407F87A2409FE44740FF05820019BA32407E5182FE42E54740AA622AFD84BB32402AE44A3D0BE647400188BB7A15BD32407E5704FF5BE74740DFDC5F3DEEBF3240E945ED7E15E8474052431B800DC43240FC17080264E847400473F4F8BDC932407B6649809AE84740D3C1FA3F87D93240D1CABDC0ACE8474029E78BBD17DB3240AC53E57B46EA47408081204086DA3240A7E67283A1EA474052B81E85EBD13240527FBDC282ED47405534D6FECECA3240AC5626FC52EF47407E8AE3C0ABC932407F8461C092EF474079AEEFC341C63240FED2A23EC9EF4740A304FD851EC532407D21E4BCFFEF474027F6D03E56C432402B172AFF5AF04740D53DB2B96AC23240562B137EA9F34740AC53E57B46C232407AA86DC328F44740FC1D8A027DC23240D47FD6FCF8F547402DCF83BBB3C2324000C45DBD8AF6474024809BC58BC5324000C79E3D97FB474085D21742CED33240B4C876BE9F0448403719558671D7324072C45A7C0A06484059198D7C5ED932406000E14389064840462234828DE73240A41AF67B620748407A1A3048FAE832407D5D86FF7407484097900F7A36F73240B0AA5E7EA70748400F9D9E7763FD3240B343FCC3960848404777103B53003340D576137CD30848400CC9C9C4AD0A3340DD60A8C30A0948405D6DC5FEB22333405B79C9FFE4074840579412825535334004E8F7FD9B074840FB3C4679E6753340D2FD9C82FC0A484021956247E37833407F4B00FE290B4840D05E7D3CF479334053793BC2690B4840A4FE7A85057B3340D00CE2033B0C4840D2C43BC0937E3340A7B393C15110484023861DC6A47F3340508BC1C3B4114840FE9C82FC6C803340D5AF743E3C134840276BD4433482334052499D8026164840D6AC33BE2F8633405055A181581A4840E2B19FC5528833403D80457EFD1A48401651137D3E8A3340ABD1AB014A1B4840AB5CA8FC6BA13340D3FA5B02F01D48407A1A3048FAA43340D3FA5B02F01D4840D3C1FA3F87A93340FFCC203EB01D4840FF93BF7B47C133405534D6FECE1A4840ABEAE5779AC83340D4EE5701BE1948407E8AE3C0ABC9334001C11C3D7E1948408081204086CA33407AABAE43351948407B14AE47E1CA3340552E54FEB5184840533D997FF4C93340266E15C440174840AC5626FC52E73340D3F71A82E3104840FC17080264E83340D1CABDC0AC10484058AA0B7899E933407B6649809A10484050C763062AEB334000CADFBDA3104840A301BC0512F033405473B9C150114840D6A9F23D23F13340A4C2D84290114840FA298E03AFF63340D5AF743E3C1348404DD9E90775F9334052431B800D144840FF93BF7B470134408048BF7D1D164840A77A32FFE803344055FB743C66164840F3AB3940300F3440F702B3429116484056BC9179E417344027F911BF62194840CD5A0A48FB233440253B3602F11C4840267156444D3C3440514CDE00332348407F129F3BC1463440F92F1004C82048402DD2C43BC0473440A8E0F0828820484027F911BF624934405401F73C7F204840CF4BC5C6BC4A34407B6649809A204840A7ECF483BA4C344052465C001A2148407AABAE43355134408081204086224840266E15C4405734407F87A2409F2448402BDEC83CF25B3440A9DA6E826F264840027FF8F9EF5D3440FB20CB8289274840D13FC1C58A663440527FBDC2822D4840AC5626FC52673440A9DA6E826F2E48402DD2C43BC06734402920ED7F802F48404DD9E907756934402A1DACFF733248402383DC45986A3440D57954FCDF3348407F8461C0926F34402920ED7F80374840D446753A907134407B6649809A384840FB95CE8767753440AC53E57B463A48405437177FDB7F3440EC8497E0D43D48404FCAA48636803440AA656B7D91404840A3073E062B8A3440A7ECF483BA44484029ED0DBE30A53440A7E9B303AE47484052465C001AA93440286552431B4848405628D2FD9CB634407E18213CDA484840CF4E0647C9CF3440A774B0FECF494840D446753A90D13440D673D2FBC649484059A7CAF78CD4344029266F8099494840A6F27684D3D63440A8AAD0402C494840CC5D4BC807D9344029EACC3D244848407E8D2441B8DE34407C60C77F81464840552E54FEB5F03440FE99417C604348402B6C06B820F33440D482177D0543484059A7CAF78CF43440AB984A3FE1424840A968ACFD9D153540D4EE5701BE414840266E15C440273540AB5CA8FC6B4148402AE109BDFE4035402635B401D8424840FCE1E7BF074F354052499D802646484083FA96395D6E3540D4EE5701BE494840257497C459713540FA264D83A2494840A7E67283A17235407D5D86FF744948402CD8463CD981354079AEEFC341464840AD50A4FB399D3540FED2A23EC93F48407D96E7C1DD9D3540D4BB783F6E3F4840A777F17EDC9E3540D2C43BC0933E4840FF08C380259F35408048BF7D1D3E4840D4BB783F6E9F3540000341800C3D4840D4BB783F6E9F35402BDEC83CF23B4840F92F1004C8A03540D3C1FA3F87394840AB5FE97C78B6354079AEEFC3412E48407C9C69C2F6B73540A968ACFD9D2D4840D925AAB706BA3540D388997D1E2D4840D5AF743E3CBB3540253B3602F12C484054C554FA09C73540D2C77C40A02B48407D93A641D1C8354000C79E3D972B48400282397AFCD235407C6308008E2B484052431B800DD435407F15E0BBCD2B4840A4FB3905F9D53540253B3602F12C4840FC17080264D835407E1B62BCE62D484083F755B950D9354079AEEFC3412E4840D4B837BF61DA3540AB5FE97C782E484052B5DD04DFDC3540D4F19881CA2E48407F8461C092EF3540A8E0F0828830484054C554FA09F73540D3F71A82E3304840FB20CB828907364029266F80993148404DDC2A88810E364001C11C3D7E3148402DCF83BBB312364052465C001A314840A4FB3905F9153640FC17080264304840ABEAE5779A1836407EC9C6832D304840D925AAB7061A3640D5B2B5BE48304840AB59677C5F1C3640D1CABDC0AC304840D13FC1C58A26364056F5F23B4D344840A73D25E7C4263640EECC04C3B93448408E3BA583F52B3640661536035C344840FCA886FD9E343640FD9FC37C79354840FE2AC0779B373640250516C094354840A0A4C002983A3640A6B6D4415E354840CE5147C7D544364025C9737D1F344840FD9FC37C79453640F92CCF83BB334840FB95CE876745364024D236FE443348407A1A3048FA4436405534D6FECE32484029ED0DBE30453640FCE42840142E4840CC5D4BC807593640514CDE0033234840A5F8F884EC60364051DD5CFC6D1F4840008BFCFA21623640A38FF980401F4840CBF78C4468743640D009A1832E1F484054C8957A167C3640D38558FD11204840F4531C075E7D36407F4E417E362048404A79AD84EE7E364029EACC3D2420484000000000008036400B0C59DDEA1F4840D6A9F23D23813640240B98C0AD1F484055C2137AFD8136404F58E201651F48402B6C06B820933640F9BD4D7FF617484021956247E39836407C992842EA124840D82E6D382C993640A6B915C26A1248407C2766BD189A3640D09D60FF7510484028F04E3E3D9A3640D576137CD30E4840F8359204E19A3640AB5FE97C780E48401D75745C8D9C36405167EE21E10D4840B1E07EC0039F3640C37FBA81020D48404F07B29E5AA136403C4D66BCAD0C4840AB4198DBBDA43640AA7D3A1E330C48404E61A5828AA63640787B1002F20B4840D34CF73AA9AB36407F15E0BBCD0B48407B336ABE4AAE3640D064FF3C0D0C4840793F6EBF7CB23640AA9ECC3FFA0C4840D0D6C1C1DEBC36402829B000A60E48402A6F47382DC836402541B8020A0F4840228C9FC6BDC9364026C632FD120F484050C763062ACB3640FDDB65BFEE0E48407AA86DC328CC3640FA298E03AF0E48402A6F47382DD836402635B401D80A4840C93D5DDDB1D8364093AB58FCA60A4840A774B0FECFD9364028F04E3E3D0A4840FF93BF7B47E136405376FA415D064840CFD90242EBE13640295FD0420206484056B950F9D7E23640276893C327054840A583F57F0EE33640520DFB3DB1044840209BE447FCE236402444F98216044840D446753A90E13640D0D03FC1C50248402BDEC83CF2DB3640556D37C137FF47407A54FCDF11E53640A75CE15D2EFA4740FC17080264C83640520DFB3DB1EC4740D63730B951C83640A8A78FC01FEC47402DD2C43BC0C73640F92CCF83BBEB474079AEEFC341C63640286211C30EEB4740AC5626FC52A73640FE99417C60E347405055A18158A23640D0D03FC1C5E24740A7ECF483BA9C3640D4B837BF61E24740D63730B951983640D28BDAFD2AE247407E8D2441B88E36407BA2EBC20FE2474051BEA085048C36407E54C37E4FE24740A5F8F884EC803640D1031F8315E547400000000000803640F4FC69A33AE54740505260014C7D3640FE47A643A7E54740CC5D4BC807793640295FD04202E6474027F6D03E56743640D3FA5B02F0E5474055C2137AFD713640530438BD8BE547402DCF83BBB3523640A7E9B303AEDF4740FA264D83A2513640A5BC564277DF47402BDB87BCE54636407E5182FE42DD47404FCDE5064345364051888043A8DC4740533D997FF4393640FF08C38025D7474027F911BF62393640508E0244C1D64740D6A9F23D23313640272F3201BFD047407E18213CDA3036407F4E417E36D04740BE892139993036402B14E97E4ECD4740A86E2EFEB62F36407F87A2409FCC4740D63A71395E2D3640562B137EA9CB4740ABEAE5779A2836407E1EA33CF3CA474097AAB4C5351E3640CBBE2B82FFC94740A4FE7A85050B3640A7ECF483BAC44740D63730B951083640D57954FCDFC3474050C422861D063640AB984A3FE1C24740A77A32FFE80336402CD8463CD9C14740A7E67283A102364052465C001AC14740D446753A9001364051853FC39BBF4740800F5EBBB4013640D47FD6FCF8BD474081069B3A8F02364029232E008DBC4740A8716F7EC3043640A6B915C26ABA4740A968ACFD9D0536402AE109BDFEB847404FCDE50643053640A9DA6E826FB64740CD5A0A48FB033640A96BED7DAAB24740FD14C781570336407E8AE3C0ABB14740FC1D8A027D023640272F3201BFB0474052B81E85EB0136402B172AFF5AB047407AABAE43350136407D21E4BCFFAF4740D828EB3713FF35407F8461C092AF4740267156444DFC35407E5704FF5BAF47402577D84466F635407AA52C431CAF47407A17EFC7EDEF3540A9DA6E826FAE47407E8D2441B8EE354079AEEFC341AE474055BFD2F9F0EC3540D1CDFE40B9AD47407AA86DC328EC3540A6B6D4415EAD4740CF4E0647C9DF35405376FA415DA647404DDC2A8881DE3540530438BD8BA54740D0D38041D2D735407C60C77F819E4740D540F33977D735402AE44A3D0B9E4740AC5626FC52D7354082397AFCDE9C474056BC9179E4D735402BDEC83CF29B47407D93A641D1D83540FBE769C0209B4740FE0E45813ED93540FF058200199A4740FE0E45813ED93540A8E0F08288984740514F1F813FD83540A7E9B303AE974740FA980F0874CA354002BB9A3C658F4740514F1F813FC835405376FA415D8E4740A304FD851EC53540FFCC203EB08D4740FB928D075BC035407B9FAA42038D47407AA86DC328BC3540A8A78FC01F8C47405531957EC2B53540276BD443348A4740D236FE4465A735407AA86DC328844740FA298E03AFA635407F15E0BBCD834740A6F27684D3A63540A7B0524145834740266E15C440A73540AB984A3FE18247406C76A4FACEA7354096CCB1BCAB824740552E54FEB5B0354055F833BC59814740D446753A90B13540FCE1E7BF0781474055C2137AFDB1354000CADFBDA3804740008BFCFA21B23540286552431B804740D6A9F23D23B13540266E15C4407F4740F92CCF83BBAB3540286211C30E7B47407B9FAA42039D3540A8AAD0402C714740562B137EA98B354054FEB5BC726B4740D540F33977873540253E7782FD6947407F129F3BC1863540FA264D83A2694740000341800C8535402B172AFF5A684740D731AEB8387E35407E8AE3C0AB61474055BFD2F9F07C35402B172AFF5A604740AD50A4FB397D35402638F581E45F47407E8D2441B87E3540556D37C1375F4740552E54FEB58035407E8D2441B85E474024809BC58B8535402AE44A3D0B5E4740008E3D7B2E873540FC1A4982705D4740D540F33977873540AA9ECC3FFA5C4740266E15C44087354001BEDBBC715C47402BDB87BCE5863540FCDEA63FFB5B4740A968ACFD9D853540D5AF743E3C5B4740A9DA6E826F7E3540AA9B8BBFED574740F86EF3C6497D354061889CBE9E574740A7E9B303AE773540FED2A23EC95747404DD6A88768743540FD4D2844C0574740514CDE0033733540A86E2EFEB6574740D6A9F23D2371354028F38FBE4957474027F6D03E56543540A86E2EFEB64F4740D2C77C40A05335407E5704FF5B4F47402B6C06B820533540813FFCFCF74E4740D828EB37134F3540F92CCF83BB4B474058AD4CF8A54E3540A7B05241454B474050C763062A4B35407AA86DC328444740533D997FF44935407E1EA33CF33A4740286552431B3835405470784144344740D4B5F63E55353540A9DDAF027C334740FC1D8A027D323540FF058200193247402AE109BDFE3035407D93A641D1304740D4BB783F6E2F354055FB743C662E4740D1CDFE40B92D35402CD8463CD9294740A8E33103952D3540FD1186014B264740AD50A4FB392D3540AB9509BFD425474022895E46B114354051853FC39B1F474084F1D3B8370F35405628D2FD9C1E4740D1CDFE40B90D3540D2C43BC0931E4740AB59677C5F0C35407E8D2441B81E4740FE0E45813E09354002BB9A3C651F4740D63A71395EFD34407B6649809A20474083FA96395DDE3440FD14C78157234740D1CABDC0ACD83440F92CCF83BB2347404DD6A88768D43440A9DDAF027C23474055C2137AFDD134407F4B00FE29234740AAF3A8F8BFCB344093E1783E032247408200193A76C834407AABAE43352147407C992842EAC2344051853FC39B1F47407E18213CDAC03440D2C43BC0931E47408200193A76B83440A8E0F08288184740D63730B951B834407D21E4BCFF174740E7A90EB919BA34402D3E05C078164740A774B0FECFB934407E1B62BCE61547408200193A76B8344029ED0DBE30154740CE5147C7D5B4344052431B800D1447400A9DD7D825B234406E4E250340134740027FF8F9EFAD3440276BD443341247407A17EFC7ED9F3440D1CABDC0AC104740D2C43BC0939E34407D93A641D110474029ED0DBE30953440D3F4D901D71347404FCAA48636903440D388997D1E154740CC5D4BC80789344052499D802616474086C954C1A87C3440D009A1832E1747407AA52C431C5734407D5A457F68144740CC5D4BC8074934405534D6FECE124740A6F27684D34634408081204086124740D4B5F63E55453440FDD8243FE211474057B08D78B2433440D1CABDC0AC1047409A780778D24234407A6CCB80B30E474055C2137AFD4134407AA52C431C0F47404DD6A887683434407F4B00FE2913474082FDD7B969333440FE99417C60134740FD1186014B1E3440A6B6D4415E154740A7ECF483BA1C3440FC1A4982701547402AE44A3D0BF633407D96E7C1DD154740D7A6B1BD16DC3340D57954FCDF1347407E8AE3C0ABD933407C6308008E134740A8E0F08288D83340FE99417C60134740A7E9B303AED7334029E78BBD1713474058AD4CF8A5BE3340A8716F7EC3144740878A71FE26B4334055A357039416474000917EFB3AAC3340FF08C38025174740CC5D4BC807A93340556D37C1371747407BA2EBC20F923340A7AD11C1381647404ED367075C8F3340295FD04202164740276BD44334823340A6B915C26A124740D13C80457E8133407BA2EBC20F124740D6A9F23D2381334029266F8099114740FA264D83A28133407AABAE4335114740D3BEB9BF7A8433405437177FDB0F4740CE5147C7D584334002BB9A3C650F4740D3BEB9BF7A843340FDDB65BFEE0E47407C992842EA823340FD1186014B0E47408109DCBA9B7733407BA2EBC20F0A47407E1B62BCE675334001C11C3D7E09474083F755B9504933402829B000A6FE4640286552431B4833407C60C77F81FE4640FE0E45813E293340FD1186014BFE46402DD2C43BC02733405376FA415DFE46407F129F3BC1263340D2C43BC093FE46402AE44A3D0B263340FDDB65BFEEFE46407C992842EA223340823CBB7CEB014740AB5CA8FC6B2133405182FE428F024740A86E2EFEB61F3340D482177D050347404DDC2A88811E3340514CDE0033034740AA622AFD841B33402B14E97E4E034740D1CABDC0AC183340FBE769C020034740AB5FE97C78163340FFCF61BEBC0247407F87A2409F143340276BD44334024740D734EF384503334081423D7D04FC4640800F5EBBB4013340FE99417C60FB4640A777F17EDCFE3240823CBB7CEBF94640A5F5B704E0DB32407F87A2409FF44640A4FB3905F9D532407F87A2409FF446408C2D043928D1324072361D01DCF44640'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('IT','IT','ITA','380','Italy','29411','58646360','150','39','12.8','42.7','0106000020E6100000160000000103000000030000008B050000A05CA8FC6B412840904E417E368047406051BD35B0452840809065C1C47B474020AB24B20F522840D0F19881CA764740A0B5DD04DF5C284008BEDBBC71744740E0A9F23D2361284010DFA63FFB734740E0D24ECDE5762840D873D2FBC671474060A148F7739A2840582B137EA96B4740E0CF0D4DD9C12840709FAA42035D474020AE65321CC7284008C79E3D975B474000D68F4DF2CB2840A86BED7DAA5A474000AB24B20FD22840503D997FF4594740A03E3C4B90E12840109D82FC6C58474000556CCCEBF82840C0777FBC5757474020FEF0F3DF1B2940580DFB3DB1544740A02975C9382E294038F6D03E5654474080069B3A8F62294010BEDBBC71544740C0716F7EC374294030F04E3E3D52474060C554FA0977294078A2EBC20F524740401077F52A7A2940583D997FF451474020240C03967C294000068200195247400076C58CF07E294028C022BF7E524740A00F5EBBB4812940D8FD9C82FC524740E0B628B3418629401015C78157534740E0921CB0AB8929403814E97E4E5347402015C781579329405882FE428F5247402051BD35B0A52940E07C957CEC50474020F2ECF2ADA72940E0CABDC0AC504740C0703D0AD7832A40A09B8BBFED474740604B3B3597DB2A40D08558FD114847402083DC45981A2B40206E15C440474740E0CDFE40B91D2B400809C38025474740E0737E8AE3382B4060499D8026464740C036548CF36F2B40705B3FFD67434740A09BC6F65A702B4088992842EA424740200AF5F411702B40A874B0FECF414740E0A6B1BD166C2B40B0A44E40133F4740409E077767652B4090992842EA3A474060B08D78B2632B40B8A10DC0063A4740C0D8D0CDFE602B40D80F2384473947400009C380255F2B40F8E1E7BF0739474020301004C8502B40B0C2D84290394740A0116DC7D4052B40100F45813E314740600F5EBBB4E12A4030F6D03E562C47408023F3C81FC42A4030E44A3D0B26474060A7CAF78CC42A40587FBDC28225474040E6E8F17BD32A40D0C77C40A01B4740000341800CD52A402814E97E4E1B4740A05626FC52D72A4038E78BBD171B4740A01D71C806DA2A40206211C30E1B474040FBAF73D3E62A40602B137EA91B4740205C8FC2F5E82A40E87954FCDF1B47402069C53714EE2A40B8B6D4415E1D474060B3CEF8BEF82A406031957EC21D4740607A19C572FB2A40B868ACFD9D1D4740205DC136E2192B40A87A32FFE81B474020301004C8502B408821E4BCFF174740200C040132542B40D8BB783F6E1747400020990E9D562B40888D2441B81647400020990E9D562B40E8AC33BE2F164740C0978A8D79552B4028327381CB154740A07F828B154D2B40D882177D05134740C06BED7DAA4A2B4028F04E3E3D124740A017EFC7ED2F2B4008A0C37C790D4740006C06B820232B4008C79E3D970B4740C077F17EDC1E2B40604CDE00330B4740C0B0A6B2281C2B4000E869C0200B4740E05626FC52172B40E0D03FC1C50A4740E07A32FFE8132B40D08BDAFD2A0A474020B0743E3C0B2B40306552431B084740C0978A8D79F52A40608BC1C3B401474040295C8FC2F52A40A85CA8FC6B014740A05CA8FC6B012B40D0F19881CAFE4640E0CABDC0AC082B4008CD203EB0FD464000E6E8F17B132B4058431B800DFC464020295C8FC2152B40E0F4D901D7FB4640C077F17EDC1E2B40A8BF97C283FC4640C018213CDA202B40B0ECF483BAFC4640C0F4143944242B40D0B5F63E55FD4640000F45813E292B40B077F17EDCFE4640C091088D602B2B403041B8020AFF4640400C040132342B40D809A1832EFF4640E0D8D0CDFE402B405840DAFF00FF464080B08D78B2432B40B077F17EDCFE4640E00C36751E452B4008C45DBD8AFE4640200473F4F8452B408848BF7D1DFE46400077D84466462B40A8716F7EC3FC4640609E077767452B4008D9243FE2F94640A0A7CAF78C442B4008301004C8F8464040F52D73BA3C2B4058888043A8F446406083DC45983A2B408015E0BBCDF34640802634492C392B40B0DDAF027CF3464040573F36C92F2B40386BD44334F2464080AD4CF8A52E2B40B074B0FECFF14640E0C3094CA72D2B4058F833BC59F1464000D48041D2272B40E0B5F63E55ED46402018080264282B4020F6D03E56EC464060C1E10511312B4030EACC3D24E84640406BD44334322B4010D3A23EC9E7464060E2AC889A382B4078A52C431CE74640200D36751E652B40B859677C5FE4464020274D83A2912B4008301004C8E04640C07A32FFE8932B40B8656B7D91E0464000CA8B4CC0972B40E000DE0209E046402023DA8EA9AB2B40E07954FCDFDB4640A0978A8D79D52B40603D997FF4D146400020990E9DD62B4028266F8099D14640E08EC70C54D62B40D0A9F23D23D14640E00F77F52ABA2B4060793BC269CB464000C87C40A0B32B4080992842EACA4640E0D38041D2A72B406034D6FECECA46404054FEB5BC9A2B40286211C30ECB46408020B248136F2B4058F5F23B4DCC4640A0B81E85EB912B40283B3602F1CC464060E2AC889A982B4000A0C37C79CD464000FEF0F3DF9B2B4010E5284014CE464040BEA085049C2B4008C45DBD8ACE464040D9E90775792B40682E54FEB5D8464080BC9179E4772B4010E2E7BF07D946408017EFC7ED4F2B40587C7C4276E0464080B08D78B2432B40301DACFF73E24640C05CA8FC6B412B40A06BED7DAAE2464080D45FAFB0282B40F063E94317E4464080AA0B7899192B40A8716F7EC3E4464020AB24B20F122B40809065C1C4E34640E06DFC89CA0E2B40804B00FE29E34640C03BFBCA830C2B40D8EE5701BEE14640C088450C3B0C2B40E0A9F23D23E14640C015E0BBCD0B2B40888461C092DF46400023DA8EA90B2B40903FFCFCF7DE4640E0A6B1BD160C2B405828D2FD9CDE464060A48977800F2B4030E44A3D0BDE4640406002B7EE0E2B40B0716F7EC3DC4640A06E2EFEB6FF2A405034D6FECEDA4640405FD04202DE2A40D076137CD3D64640802634492CD92A4000C45DBD8AD64640009CDF30D1C82A4008E5284014D6464080116DC7D4C52A4050499D8026D64640A08B868C47C12A40D0C43BC093D64640C018213CDAC02A402841B8020AD74640A02CB64945C32A40B0A44E4013D74640E0B628B341C62A40803FFCFCF7D64640C0CABDC0ACC82A4088A52C431CD746408017EFC7EDCF2A40908461C092D7464000274D83A2D12A40D8D38041D2D74640E0737E8AE3D82A40E0F71A82E3D846406083DC4598DA2A40B8AAD0402CD94640207A19C572DB2A40B853E57B46DA4640609885764EDB2A405034D6FECEDA4640004C546F0DD42A4008BEDBBC71DC4640401E8A027DD22A40B8ECF483BADC464040CAA48636D02A40303B3602F1DC4640A0955F0663BC2A403059DC7F64DE4640C020B248136F2A4058FEB5BC72E34640A079008BFC622A4000C79E3D97E34640206C06B820432A406834D6FECEE2464020261B0FB6402A40A06BED7DAAE246402083DC45983A2A40383E7782FDE14640C02634492C392A40908AE3C0ABE14640801A3048FA242A40E07954FCDFDB4640A0703D0AD7232A40B0DDAF027CDB464020DF6B088E232A40B8984A3FE1DA464020809BC58B252A4058465C001AD9464000B4E73235312A4058793BC269D3464080B60F79CB2D2A4028266F8099D1464000A7B1BD162C2A4060F833BC59D1464080656B7D91202A40D0A9F23D23D14640E094490D6D002A4010CADFBDA3D04640802FF7C951D829400009C38025CF464040D026874FBA2940D00CE2033BCC4640406684B7079929409093A641D1C8464020356090F4692940F8DEA63FFBC34640202A8E03AF462940E8B2B5BE48C0464060BEA085043C294028F38FBE49BF4640C0CCCCCCCC2C2940E0FA5B02F0BD4640A06ABB09BED92840B85626FC52B74640C05626FC52D72840D809A1832EB74640A0ED974F56D4284030F38FBE49B74640E0E5E8F17BD32840B06E2EFEB6B746402015C78157D32840904E417E36B846402090DB2F9FD4284078ABAE4335B94640804D637B2DD82840B0B915C26ABA4640C0E1934E24E02840383B3602F1BC4640809E077767E52840901B62BCE6BD4640406E15C440E7284050499D8026BE464020931CB0ABE92840A0DA6E826FBE4640A02FF7C951F82840C800DE0209C0464000E2934E2400294030172AFF5AC0464000AAF23D230129400018080264C0464080069B3A8F02294048853FC39BBF4640A082C30B22022940B05626FC52BF4640C05A99F04BFD28402041B8020ABF4640E0FDF0F3DFFB2840082A8E03AFBE4640407156444DFC2840089700FC53BE4640E0C43BC093FE28408048BF7D1DBE4640801A3048FA0429408048BF7D1DBE4640603F37346507294088AEEFC341BE4640C0622AFD840B2940082A8E03AFBE464040F2ECF2AD27294088397AFCDEC4464000E8154F3D2A2940B068ACFD9DC54640E0921CB0AB292940D07FD6FCF8C54640E0D8D0CDFE0029408818213CDAC84640401286014BFE28408818213CDAC84640E0285C8FC2F52840089D82FC6CC8464000356090F4C92840D80CE2033BC44640A01B62BCE6952840805182FE42BD4640400AF5F411902840B87A32FFE8BB464080C1E1051151284088C9C6832DA84640408FA67A324F2840404415FE0CA7464060B60F79CB4D284000CD203EB0A54640001E8A027D522840E073D2FBC6A146408038BA4A77772840E00F23844799464080F755B950B92840D009A1832E874640C035B22B2DE32840385393E00D814640807C410B09F82840D0AC33BE2F7E464080A148F773FA28405076FA415D7E46400052D66F26FE2840A85FE97C787E46406051BD35B0052940009700FC537E4640C0C1FA3F87092940D0FA5B02F07D4640E0DE52CE170B2940A868ACFD9D7D464020AB24B20F12294010DFA63FFB7B4640C04B546F0D142940E082177D057B4640E07A32FFE8132940A8B915C26A7A464080A148F773FA28402841B8020A6F4640C05FE97C78F62840D0B5F63E556D4640606211C30EF32840B0A78FC01F6C4640009CDF30D1E8284080ABAE4335694640803F373465E728408818213CDA684640E0BEB9BF7AE42840A8FCDD3B6A684640603579CA6AE22840904E417E3668464060D026874FDA2840809FAA42036D46404054FEB5BCDA2840607FBDC2826D4640C051D66F26DE2840808D2441B86E4640A03E3C4B90E12840A8656B7D91704640A0069B3A8FE2284020266F8099714640A03E3C4B90E128405882FE428F724640C051D66F26DE284000E869C020734640604B3B3597DB2840A8B052414573464040321F10E8D428400815C78157734640C0A16131EAD2284000E869C0207346404018080264C82840A86E2EFEB66F4640606E15C440C72840B85626FC526F4640403F373465C72840E0F19881CA6E464000B0743E3CCB2840605260014C654640E08EC70C54B6284028DB87BCE5664640C05A99F04B9D28408815E0BBCD6B4640E0ED974F56942840D8F4D901D76B4640206BD44334922840D0C77C40A06B4640C0FA96395D8E2840903CBB7CEB69464000AE65321C872840B859677C5F64464000895E46B18428405855A18158624640202FDE8FDB7F2840F8CC203EB05D4640C0CDFE40B97D2840E0C77C40A05B4640206893C3277D284040D8463CD9594640A051D66F267E284008D3A23EC957464040D367075C8F2840383B3602F13C4640A07A32FFE8932840B874B0FECF394640E05417F032B32840A8ECF483BA244640C0129F3BC1B62840888120408622464020240C0396BC2840808461C0921F464080716F7EC3D4284078457EFD10194640402DCF83BBDB284010BB9A3C6517464040A7CAF78CE4284008A0C37C79154640C0C1FA3F8709294008E52840140E4640A038BA4A771729401015C781570B464020A8E331035D2940B877F17EDCFE454080CDE50643652940D8FA5B02F0FD4540E0003274EC702940000341800CFD454040C763062A7B294008BEDBBC71FC4540603B8A73D481294010B1C1C249FC45400021CB8289872940080C040132FC45400038A110019F294008C79E3D97FB4540A03E3C4B90A1294060FEB5BC72FB4540200473F4F8A52940306211C30EFB4540A0FA96395DCE29405876FA415DF64540A0F755B950192A40886308008EEB45406021E4BCFF1F2A40B8B915C26AEA4540C0B2B5BE48402A40500DFB3DB1E445402043554CA5572A4098205C0185E04540A079008BFC622A40E0AC33BE2FDE454020E6E8F17B932A40803FFCFCF7D64540C014AE47E19A2A40C8FA5B02F0D54540E01F990E9DB62A4038E78BBD17D34540001077F52ADA2A40B06E2EFEB6CF454040861DC6A4EF2A409048BF7D1DCE4540E0B5F63E55F52A4028E44A3D0BCE454060D9E90775F92A40009700FC53CE454080BC9179E4172B40381A6B7F67CD4540401B4982701D2B408087A2409FCC454020A26131EA322B40285C8FC2F5C84540001286014B3E2B4030DB87BCE5C64540C0BB783F6E3F2B405828D2FD9CC64540C094490D6D402B40D888997D1EC54540008D9AAF923F2B4060888043A8C44540E05A99F04B3D2B40B87A32FFE8C3454040F52D73BA3C2B4058793BC269C34540E0EA56CF493F2B40884E417E36C04540808B868C47412B40B077F17EDCBE454060D6A88768442B401048A643A7BD45408059677C5F6C2B4088397AFCDEAC4540206BD44334B22B40A8A10DC0068A4540A0AA0B7899B92B407893A641D1804540E09E20B1DDBD2B40F8230C03967C454020261B0FB6C02B409054C37E4F7A4540A0703D0AD7C32B40786649809A784540C0622AFD84CB2B40483A58FFE774454040861DC6A4CF2B40089A417C60734540A0737E8AE3D82B40B8A78FC01F6C4540E0A9F23D23E12B40B877F17EDC6645408000193A76F82B4058793BC2695B4540A0A148F773FA2B40A0E67283A15A4540E0E8297288082C406831957EC2554540E09E20B1DD1D2C40A85626FC524F45406077D84466262C4010D6E3BED54C454060B950F9D7422C40805182FE424545402077D84466662C406831957EC23D45408082C30B22022D40885D86FF74214540E06E2EFEB61F2D4048707841441C454080B08D78B2232D40889065C1C41B4540A068ACFD9D352D4028F04E3E3D1A454060C2137AFD412D40905D86FF74194540E0EEAB72A1522D40804E417E36184540800C1D3BA86C2D4088AEEFC34116454080FA96395D6E2D40205FD04202164540A017EFC7ED6F2D40286893C327154540A017EFC7ED6F2D408887A2409F1445406069C537146E2D40D08BDAFD2A12454040013274EC702D406831957EC20D454000AB24B20F722D4078397AFCDE0C4540A038BA4A77772D40886308008E0B45404054FEB5BC7A2D40901EA33CF30A4540803579CA6A822D40483D997FF4094540403317B83C862D4008A6457D920945406077D84466A62D4028327381CB05454000CDCCCCCCAC2D40386893C327054540C0AD65321CC72D40E0D03FC1C50245408059677C5FCC2D40081E8A027D024540E0A9F23D23E12D40B0A10DC006024540A051D66F26FE2D40B8656B7D91004540E088450C3B0C2E40B8DA6E826FFE4440A0FA96395D0E2E4000CD203EB0FD444040240C03961C2E40101E8A027DFA444040B08D78B2232E40A85CA8FC6BF9444000D13FC1C5322E40889C69C2F6F74440004CFDBCA9482E4098F38C7DC9F64440C06DFC89CA4E2E40B85FE97C78F644408038BA4A77572E40E8AC33BE2FF64440E037A11001BF2E40A87A32FFE8F34440C01EA33CF3CA2E40302CF180B2F3444020E6E8F17BD32E40302CF180B2F34440200F45813EE92E4080423D7D04F4444020C53BC093FE2E40B059677C5FF44440A05417F032332F40B8AD11C138F6444020295C8FC2552F401048A643A7F54440205DC136E2592F4090CC07043AF54440C08C9AAF925F2F40809FAA4203F54440000D36751E852F40D0B5F63E55F54440008A592F868A2F40301A6B7F67F54440C0129F3BC1B62F40A8DA6E826FF6444000999EB0C4D32F40A86E2EFEB6F744400015C78157033040A8AAD0402CF944409087A2409F043040080F45813EF9444040D2C43BC0073040E8A9F23D23F9444060B60F79CB0D30408893A641D1F844409004FD851E153040E0D38041D2F7444020F6D03E56243040809FAA4203F5444050ED0DBE30253040A8716F7EC3F444405031957EC2253040B059677C5FF44440A001BC0512303040D87954FCDFEB444030D8463CD931304008D9243FE2E94440306BD44334323040885D86FF74E94440108BFCFA2132304010C45DBD8AE6444040C2137AFD313040D07FD6FCF8E54440F04543C6A330304000DFA63FFBE3444030F04E3E3D2A304028E109BDFEE04440C0E7A4F78D233040E0F19881CADE4440E0D38041D20730402829B000A6D64440C0737E8AE3F82F40B07A32FFE8D3444020A26131EAF22F403014E97E4ED34440606C06B820E32F40B053E57B46D24440206893C327DD2F40508BC1C3B4D1444020D9E90775D92F40F80E45813ED1444000BFB9BF7AD42F400018080264D04440C0CCCCCCCCCC2F4030DB87BCE5CE4440E0B837BF61CA2F409048BF7D1DCE444020E9297288C82F40B87A32FFE8CB4440A0D38041D2C72F4010D061BEBCCA44400021CB8289C72F4058465C001AC94440005858703FC82F4050853FC39BC74440208A592F86CA2F40A8ECF483BAC444408032384A5ECD2F40D082177D05C34440A0C554FA09D72F40D809A1832EBF4440401B498270DD2F4028ED0DBE30BD44402020990E9DF62F40B8656B7D91B84440A01D71C806FA2F409021E4BCFFB744407000193A76083040B068ACFD9DB54440B0DDAF027C13304078A86DC328B44440C04D637B2D18304060FEB5BC72B34440A0ABAE4335313040E0F19881CAAE4440107FF8F9EF7D3040E0B2B5BE48A044400018080264A830406001F73C7F984440503D997FF4C930408815E0BBCD934440A0ECF483BA0C3140001E8A027D8A4440505FD042022E314088423D7D048444409001BC0512303140806308008E834440F093BF7B474131403029B000A67E4440F01708026448314028232E008D7C4440701EA33CF34A3140002DCF83BB7B4440705260014C4D31403035B401D87A4440F03DB2B96A523140E0CABDC0AC7844409093A641D178314028F04E3E3D6A4440908AE3C0AB793140583D997FF4694440E028EB37137F3140D87C957CEC68444040B950F9D7C23140600438BD8B5D44408017EFC7EDEF3140B877F17EDC5644400082397AFC023240081E8A027D524440B0DDAF027C033240D006600322524440002A8E03AF0632405876FA415D4E4440A0F755B950093240386BD443344A4440D05D4BC807093240588BC1C3B4494440D0548847E209324030F38FBE49474440A0073E062B0A3240B077F17EDC464440503A58FFE7143240504CDE0033434440C04543C6A320324038F38FBE493F4440009700FC5346324000240C0396344440D0393FC5716C3240D0031F83152544401088BB7A156D3240B0716F7EC32444409018213CDA703240803CBB7CEB214440E0488446B0753240A0E33103951D4440206C06B82083324010C11C3D7E114440E034EF384583324030E109BDFE104440107976F9D6833240E0CDFE40B90D4440C0E7A4F78D8332408087A2409F0C44406034D6FECE7A324030327381CB05444060D9E90775793240D088997D1E05444020D2C43BC0773240F8230C039604444080069B3A8F7232408015E0BBCD034440402E54FEB5703240009A417C60034440407A19C5726B3240A8BC564277FF4340801EA33CF36A32405040DAFF00FF4340A0AEEFC341663240D0D38041D2F74340A004FD851E653240B89ECC3FFAF44340F00241800C65324000BEDBBC71F44340C0488446B065324000C79E3D97F34340002A8E03AF6632406834D6FECEF2434090F27684D36632405855A18158F24340F00B040132643240682E54FEB5E8434060431B800D643240584F1F813FE8434000301004C8603240B85FE97C78E6434050D367075C5F32408096E7C1DDE5434050D9E90775593240B8B6D4415EE54340D05147C7D55432402841B8020AE74340D05A0A48FB533240B85626FC52E74340D0C43BC0934E32407818213CDAE84340C0E33103954D324088457EFD10E9434050431B800D443240381DACFF73EA434010861DC6A43F3240B8E67283A1EA434000068200193A3240B06BED7DAAEA4340206211C30E333240604CDE0033EB43408096E7C1DD2D324060F5F23B4DEC434070B5DD04DF2C3240B0BF97C283EC434050BC9179E42732400048A643A7ED4340A0116DC7D41532403014E97E4EF34340100C040132143240E0F4D901D7F3434010240C03960C3240E076137CD3F64340D0AF743E3C0B32402020ED7F80F74340205C8FC2F5083240D8F71A82E3F8434060AD4CF8A5FE3140306E15C440FF434050DC2A8881FE3140104E2844C0FF43401009C38025FF314028EACC3D2400444050CAA48636003240604F1F813F00444090069B3A8F0232402838F581E4FF434060B08D78B2033240F8FFFFFFFFFF4340200341800C053240682E54FEB5004440F0488446B0053240C8EE5701BE014440F0488446B0053240B853E57B46024440C05A0A48FB03324058431B800D0C4440F07876F9D6033240A8BF97C2830C44406055A18158023240F847A643A70D4440F0847AFA08E8314000CADFBDA320444040DEC83CF2DB314058F5F23B4D244440801EA33CF3DA3140A8BF97C283244440305C8FC2F5C8314010CD203EB0254440E034EF3845C33140E07FD6FCF825444050B60F79CBAD314028DB87BCE5264440A0FE7A8505AB314000DC65BFEE26444090992842EAA23140E076137CD326444020D505BCCC8C31405076FA415D264440F03DB2B96A823140305FD0420226444060C1E1051181314060499D802626444070A7CAF78C6431408054C37E4F2A444040F6D03E56343140A8A78FC01F344440007976F9D6333140B8BF97C283344440D05A0A48FB333140E0031F831535444070A7CAF78C34314008A0C37C79354440E057C9C7EE3E314028F04E3E3D3A44408087A2409F443140F8230C03963C444040F04E3E3D4A3140B8A78FC01F3C4440D0BB783F6E4F314058F5F23B4D3C44401094BF7B47513140B0716F7EC33C4440F03DB2B96A523140507FBDC2823D4440D0DDAF027C53314028DB87BCE53E44401082397AFC52314038F38FBE493F444010301004C8503140A0E9B303AE3F4440D0BB783F6E4F3140F8D2A23EC93F444050BB5F05F8163140B86BED7DAA424440200C040132143140084BE7C3B342444020274D83A21131406082FE428F42444060BEA085040C3140483D997FF441444070A7CAF78C0431409093A641D1404440808461C092FF30406037177FDB3F4440101E8A027DF2304048707841443C44409017EFC7EDEF3040B0DDAF027C3B444030D505BCCCEC30408854C37E4F3A4440F0548847E2E9304010E2E7BF07394440E04E0647C9DF3040E87954FCDF334440806A12BC21DD304040FF21FDF631444090A86DC328CC304000301004C828444050465C001AC9304000DC65BFEE264440C04543C6A3C0304028172AFF5A20444090F1D3B837BF3040089700FC531E4440D028EB3713BF30406031957EC21D44409096E7C1DDBD3040282CF180B21B44400088BB7A15BD3040004BE7C3B31A444060C2137AFDB13040886308008E134440101286014BAE30400806820019124440204A7B832FA43040C00AB77C240F4440406C06B820A33040E076137CD30E4440F0BB783F6E9F3040605260014C0D4440405FD042029E30408087A2409F0C4440E0420246979B3040884B00FE290B44405034D6FECE9A3040E08BDAFD2A0A444020F911BF62993040A09509BFD4054440E0C1FA3F87993040E0B5F63E55054440402B137EA99B304090C9C6832D004440D04334BA839C3040A877F17EDCFE434060CAA48636903040781EA33CF3F2434030F911BF6289304060853FC39BEF4340B001BC0512803040905D86FF74E94340009C5088807F304088457EFD10E94340A096E7C1DD7D3040606D37C137E743401088BB7A157D3040A8E3310395E5434010240C03967C3040D8F4D901D7E3434010240C03967C304038F04E3E3DE24340A0E33103957D30403038F581E4DF4340F08D3D7B2E87304080CC07043AD54340B04D637B2D883040E0BEB9BF7AD44340C0FE7A85058B3040D0AF743E3CD343409096E7C1DD8D30408081204086D24340A001BC0512903040D006600322D243407093A641D1983040786649809AD0434010938D075BA03040A86E2EFEB6CF434070B60F79CBBD30405040DAFF00CF434070B950F9D7D2304000301004C8C84340D03FC1C58AF63040A8A44E4013BF434040B3CEF8BE083140682B137EA9BB4340107976F9D6233140886308008EB34340202A8E03AF263140883CBB7CEBB14340D0DDAF027C233140A8BC564277AF4340108BFCFA212231408848BF7D1DAE4340007FF8F9EF1D31409093A641D1A84340001B4982701D3140B86E2EFEB6A7434090F5B704E01B3140808AE3C0ABA14340D0CDFE40B91D3140D088997D1E8D4340305FD042021E314078A86DC3288C4340C0E7A4F78D233140D0BB783F6E874340000341800C253140089700FC53864340209700FC532631400848A643A7854340C06BED7DAA2A314038F6D03E5684434010904C874E2B3140A86E2EFEB67F434010904C874E2B31402814E97E4E7B4340407D5A457F20314010CD203EB075434090812040861A31406007793D98724340C0548847E21931404870784144744340F01708026418314080397AFCDE744340E036FE4465173140D8031F831575434010990F0874FA304030EACC3D24784340F02E6D382CF93040504F1F813F7843404077D84466F63040D8B2B5BE48784340C03C80457EF13040D800DE0209784340007FF8F9EFED3040F8D2A23EC9774340C0F886C267D73040B8E331039575434060431B800DD4304030ED0DBE3075434030E78BBD17BB3040D88558FD117043405040DAFF009F304078ABAE4335694340B0F5B704E09B3040306552431B684340F03730B9519830409060C77F8166434050B950F9D79230408815E0BBCD63434030D505BCCC8C30403041B8020A5F4340603D997FF4893040D8BEB9BF7A5C4340C0CABDC0AC883040F8E769C0205B4340B04D637B2D883040B0A10DC0065A4340B0E0F0828888304030266F8099594340E04334BA838C3040D082177D05534340C04E0647C98F3040286893C3274D434060B81E85EB913040F8DB65BFEE464340404CDE00339330406007793D98424340E0C77C40A0933040D8CA2F83313A4340C0DDAF027C93304008CADFBDA3384340D053E57B46923040606D37C137374340D0A9F23D23913040A8DA6E826F3643402018080264883040E006600322324340E05A0A48FB833040484F1F813F304340A0E33103957D3040B09509BFD42D4340A000193A7678304030F6D03E562C434090992842EA723040F8E769C0202B4340E025AAB7066A3040D0C1FA3F87294340705260014C5D3040D8D38041D227434030F04E3E3D5A3040B05626FC5227434000A0C37C795530405876FA415D26434050B08D78B2533040881B62BCE6254340F0B837BF612A3040A874B0FECF114340200F45813E29304008E2E7BF07114340B0E0F0828828304088C9C6832D104340B0E9B303AE2730402829B000A60E434050ED0DBE30253040803CBB7CEB094340100C04013224304008D3A23EC9074340C0E7A4F78D2330408048BF7D1D064340C0E7A4F78D233040B8BF97C283044340F034EF3845233040089A417C60034340208BFCFA21223040603D997FF4014340A096E7C1DD1D3040301A6B7F67FD424010917EFB3A1C30406070784144FC4240C05FE97C7816304050465C001AF94240F0264D83A2113040E876137CD3F642409021E4BCFF0F3040101286014BF64240C04334BA830C304030E44A3D0BF64240405FD04202FE2F40B068ACFD9DF54240A01A3048FAE42F4000E5284014F64240A000193A76D82F40608E0244C1F64240002DCF83BBBB2F4010C45DBD8AF64240C0D24ECDE5962F400048A643A7F542408017EFC7ED8F2F40B0B6D4415EF542408050A4FB398D2F40B0B6D4415EF54240606C06B820832F409096E7C1DDF54240E02F1004C8702F40E009A1832EF74240C06ABB09BE592F4008D9243FE2F94240A05FE97C78562F40B8B915C26AFA424020999EB0C4532F40286211C30EFB4240C0D38041D2472F405840DAFF00FF4240A0116DC7D4452F40004E2844C0FF4240C0FDD7B969432F4008C11C3D7E01434060B08D78B2432F40080682001902434000B937BF614A2F40E08558FD1108434000B728B341462F40A85FE97C78164340E053E57B46422F405001F73C7F1843408018213CDA402F4060F833BC591943408018213CDA402F40B0B915C26A1A4340C00F5EBBB4412F40580DFB3DB11C434060C2137AFD412F40805182FE421D434080B950F9D7422F40D8CDFE40B91D43408020B248134F2F40508E0244C11E434000356090F4692F408093A641D1204340E01D8A027D722F40D8CABDC0AC204340C05626FC52772F408093A641D1204340402DCF83BB7B2F4058465C001A21434040CDE50643852F4070A2EBC20F22434000DC114E0B962F40B87A32FFE8234340E0C98B4CC0972F4078A86DC328244340E0C43BC0939E2F4030327381CB25434080F4143944A42F40580ABABDA4274340208A592F86CA2F4040D8463CD9394340A017EFC7EDCF2F40B0BF97C2833C4340E06EBBD05CD72F405013EF004F424340802634492CD92F4070A86DC328444340C06ABB09BED92F40605260014C454340A0C554FA09D72F40A85FE97C784643404006820019CA2F40D0EE5701BE494340C0D8D0CDFEC02F4030DEC83CF24B4340C04B546F0DB42F4058499D80264E434080B60F79CBAD2F40808D2441B84E4340606552431BA82F40D0BB783F6E4F43402021CB8289A72F405037177FDB4F4340C0D38041D2A72F40009D82FC6C50434000B937BF61AA2F40B074B0FECF514340C0C3094CA7AD2F40D8FD9C82FC52434020F86EF3C6B12F4028DEC83CF2534340C05FE97C78B62F4040D505BCCC54434080C554FA09F72F4060707841445C4340206684B707F92F40D8BEB9BF7A5C434040E44A3D0B06304058888043A85C4340D0420246970B30408087A2409F5C43400094BF7B4711304060707841445C4340F03FC1C58A1630407815E0BBCD5B434040F911BF6219304028E78BBD175B4340A06BED7DAA1A3040D0FD9C82FC5A434070C1E1051121304008C79E3D975B434050BEA085042C3040E076137CD35E4340D0CDFE40B92D3040785704FF5B5F434090FA96395D2E3040B8E9B303AE5F434050B81E85EB313040281DACFF73624340703A58FFE7343040A068ACFD9D654340B068ACFD9D3530406028D2FD9C664340A0E9B303AE373040386BD443346A4340F03730B951383040B87A32FFE86B4340C0EAE5779A383040C809A1832E6F4340305C8FC2F5383040F8230C0396744340C0EAE5779A38304000E5284014764340306552431B383040B0DA6E826F764340D036FE44653730402829B000A6764340A00F5EBBB431304038F38FBE49774340F0C1FA3F8729304030E109BDFE78434050DB87BCE5263040D8EE5701BE794340D0548847E2193040101E8A027D824340D02E6D382C1930401015C78157834340009D82FC6C103040B8E0F08288904340F0C43BC0930E30405840DAFF00974340808D2441B80E3040E0CABDC0AC98434080FA96395D0E304030D505BCCC9C434040CC423BA70D30408093A641D1A043401073F4F8BD093040B053E57B46AA4340A093A641D108304088A86DC328AC434010857AFA08083040283B3602F1AC4340A01D71C806FA2F402038F581E4B74340A068ACFD9DF52F4038D8463CD9B943400090DB2F9FF42F4028F04E3E3DBA4340605FD04202DE2F4068F833BC59C14340E0D24ECDE5D62F40B0984A3FE1C24340C06DFC89CACE2F4028F6D03E56C44340C0716F7EC3B42F4008E5284014CE43400052D66F269E2F40608E0244C1D64340006893C3279D2F400809C38025D74340806ABB09BE992F408854C37E4FDA4340A0F755B950992F406834D6FECEDA4340C05417F032932F40001B498270E54340207D5A457F902F4040D505BCCCEC4340607497C459912F40881B62BCE6ED434000013274EC902F4000DC65BFEEEE434020DC2A88818E2F4038EACC3D24F04340A0069B3A8F822F40A868ACFD9DF543402009C380257F2F40F8298E03AFF64340E0E4D4CE30752F40F81D8A027DFA4340800C1D3BA86C2F40301A6B7F67FD4340E0B5F63E55552F4028DEC83CF2034440C05DDA7058522F40B0BF97C2830444406030630AD6482F40107E54C37E054440E0B2B5BE48402F40580ABABDA4074440A0F755B950392F40E0F71A82E3084440E050A4FB392D2F40B85CA8FC6B094440E0D38041D2272F4008274D83A2094440800F5EBBB4212F40D073D2FBC6094440404278B4711C2F40508BC1C3B409444020068200190A2F4028F911BF620944404051BD35B0052F40E0A9F23D23094440E082C30B22022F40D0CABDC0AC084440402C9D0FCFEA2E40582B137EA903444040E2AC889AD82E40885704FF5BFF4340C0978A8D79D52E40508E0244C1FE43400015C78157D32E40508E0244C1FE43404007B47405BB2E4050853FC39BFF4340E04D637B2DB82E40A86E2EFEB6FF4340E0AC33BE2FB62E40B09B8BBFEDFF43406032384A5EAD2E4078ABAE433501444020B3B5BE48A02E4088423D7D04044440E0B837BF618A2E40706649809A08444080F4143944842E40D073D2FBC6094440E06BED7DAA4A2E40A87A32FFE8134440A0C2137AFD412E4090CC07043A154440C0B0A6B2283C2E40E0FA5B02F0154440A0129F3BC1362E4058499D80261644406045B9347E312E4010E52840141644406077D84466062E40F8E1E7BF07194440C053E57B46E22D40D07FD6FCF81D44404054FEB5BCDA2D40104BE7C3B3224440E0C3094CA7ED2D40302CF180B22B4440A06ABB09BEF92D40F89FC37C792D44402054FEB5BCFA2D408096E7C1DD2D444000FEF0F3DFFB2D4010DC65BFEE2E4440204278B471FC2D40E08558FD11304440407156444DFC2D40386BD4433432444080C763062AFB2D4030E78BBD17334440A0B60F79CBED2D4080457EFD10394440E06DFC89CACE2D406828D2FD9C464440C04E95EF19C92D40009D82FC6C48444080B60F79CBAD2D4008D3A23EC94F444020356090F4A92D40F02F1004C850444040FBAF73D3A62D4028F911BF62514440A0B60F79CB8D2D4030E44A3D0B5644404023DA8EA98B2D4080AEEFC341564440E0B628B341862D40A85FE97C78564440A05A99F04B7D2D40E0C43BC09356444000C85F5AD45F2D40E89315C3D5514440A0CF0D4DD9412D40F8E769C020534440E01186014B3E2D40A86BED7DAA52444080DD239BAB262D401015E3FC4D4E4440A03579CA6A022D40B05626FC524F44408045460724E92C4068AF3E1EFA4E4440A0B60F79CBCD2C4028D505BCCC4C44402039605793A72C4020A8E15B5849444040321D3A3DA72C40C846CB811E4C4440200951BEA0AD2C40403B191C254F444080978A8D79B52C4030172AFF5A50444060BC9179E4B72C40804E417E365044406083DC4598BA2C40804E417E36504440E0BB783F6EBF2C40109D82FC6C504440A01A3048FAC42C4058465C001A514440C091088D60CB2C4028F04E3E3D524440404E7CB5A3F02C4008E2E7BF0759444020E6E8F17BF32C40608BC1C3B4594440E0ED974F56F42C40E0066003225A444020BFB9BF7AF42C4000D061BEBC5A4440000C040132F42C40584CDE00335B44404015C78157F32C40D0C77C40A05B444040274D83A2F12C40885A457F685C4440E089592F86EA2C40B8A44E40135F4440400D36751EE52C40081808026460444060069B3A8FA22C4030F911BF6269444040B5DD04DF9C2C40D0066003226A4440006BD44334922C4000E869C0206B444040E9297288882C40F82CCF83BB6B4440000473F4F8852C40682B137EA96B4440E0989EB0C4732C40583D997FF4694440C020B248136F2C4058465C001A694440A015E0BBCD6B2C40B09B8BBFED67444080978A8D79552C4028F38FBE49674440A0116DC7D4252C4070ABAE4335694440C04D637B2D182C409048BF7D1D6E4440E0C98B4CC0172C405828D2FD9C6E444060861DC6A40F2C40901EA33CF3724440A0B60F79CB0D2C40809065C1C4734440004F95EF19092C40D8CDFE40B9754440206893C327FD2B40E0B837BF617A4440A0C98B4CC0F72B40E00CE2033B7C4440E0CCCCCCCCCC2B40383E7782FD894440C00C1D3BA8AC2B40B0622AFD849344404054FEB5BC9A2B40E8B2B5BE48984440805FE97C78962B4078ABAE4335994440A050A4FB398D2B40E082177D059B44402087FBC8AD792B40E0033BFE0B9E4440607D5A457F702B40A8E9B303AE9F4440E07F828B156D2B4088C9C6832DA04440C089592F866A2B4028172AFF5AA04440A091088D604B2B4088ABAE4335A14440C05758703F482B40D00F238447A14440009F20B1DD3D2B4038E109BDFEA04440C05626FC52372B40A8E0F08288A04440006C06B820232B40C8C43BC0939E4440A08B868C47212B405876FA415D9E44400020990E9D962A40B09509BFD4A5444080B60F79CB8D2A40B09509BFD4A5444040E9297288882A40E0CDFE40B9A5444020A7B1BD166C2A4088A86DC328A4444040C554FA09572A40B8B915C26AA2444020B0743E3C4B2A40B0AAD0402CA14440E02EDE8FDB3F2A406037177FDB9F4440E0C98B4CC0372A40B8DA6E826F9E4440609BC6F65A102A40D0CABDC0ACA04440E076BF0AF00D2A40783CBB7CEBA14440A01A3048FA042A40301A6B7F67A54440A0656B7D91002A40B077F17EDCA64440C0C98B4CC0F72940E00F238447A9444000999EB0C4F32940C053E57B46AA4440403F373465E7294038ED0DBE30AD4440A05A99F04BDD294000BB9A3C65AF444020E6E8F17BD3294058465C001AB14440E09BDF30D1C82940B8E67283A1B24440E0285C8FC2B52940E0BEB9BF7AB4444040BC9179E4572940D8D03FC1C5BA444080B81E85EB5129406834D6FECEBA4440C01EA33CF34A2940A0B915C26ABA444060BB5F05F8262940D07C957CECC04440E04E95EF19092940D8CABDC0ACC8444000274D83A2F12840D0CDFE40B9CD4440803F373465E728403838F581E4CF4440603579CA6AE2284008301004C8D04440C0129F3BC1B62840B8E0F08288D8444080C1E10511B12840100F45813ED94440A0F1D3B8376F284080A86DC328E4444040B60F79CB6D2840A0E3310395E54440C091088D606B2840809C69C2F6E74440E0CABDC0AC682840B8AAD0402CE9444060BEA085045C2840888D2441B8EE4440601D71C8065A28402820ED7F80EF4440C0ED974F565428405873B9C150F14440C076BF0AF04D2840286211C30EF34440A03579CA6A422840A8E3310395F5444040FEF0F3DF3B2840808D2441B8F64440202C9D0FCF0A2840E0AC33BE2FFE444060129F3BC1D6274030F6D03E5604454040861DC6A4CF274080397AFCDE044540400F45813EC92740283B3602F1044540808B868C47C12740B8ECF483BA04454080D9E90775B9274010DFA63FFB034540C032384A5EAD2740682B137EA9034540008A592F86AA2740D8C77C40A0034540206552431BA82740809065C1C4034540809E077767A5274008BEDBBC7104454020B1A6B2289C2740805704FF5B074540E09E20B1DD7D2740305C8FC2F510454060A148F7737A2740904B00FE2913454040D39FFD48792740E8DC5F3DEE13454020E2AC889A782740B8BF97C28314454020E6E8F17B732740B05626FC521745400018080264682740B8ECF483BA1C454040CDE50643452740081B498270254540A053E57B4642274028E44A3D0B2645400038A110013F27406828D2FD9C2645408045B9347E112740E87954FCDF2B4540C0955D30B8FE26406031957EC22D45404042960513E726405879C9FFE42F45404077D84466C62640E8AF743E3C334540E02EDE8FDBBF2640D0F4D901D73345402083DC4598BA264058431B800D34454020F2ECF2AD872640500438BD8B354540605A80B6D5842640B068ACFD9D3545404020990E9D762640101B49827035454000356090F4692640303B3602F1344540605C8FC2F5682640D8BEB9BF7A34454020AE65321C672640081E8A027D3245400021CB8289672640A8C2D84290314540C0C43BC0935E26402041B8020A2F4540406893C3275D2640908D2441B82E4540809885764E5B26408860C77F812E4540606684B707592640082A8E03AF2E45402020990E9D36264010D9243FE231454000EFAB72A13226408854C37E4F32454020B4E73235312640B0E67283A1324540A07F828B152D2640080C040132344540C06BED7DAA2A264028DB87BCE5364540E0D58F4DF22B2640286E15C440374540E0AA24B20F3226405001F73C7F384540A01B62BCE6352640D07C957CEC38454080A148F7733A2640302F3201BF38454020965D30B83E264028172AFF5A384540A023F3C81F442640504F1F813F38454060F1D3B8374F2640804E417E3638454020E6E8F17B532640886649809A38454000AD33BE2F562640C80F238447394540802FF7C95158264080A2EBC20F3A454020240C03965C2640503A58FFE73C4540A06E2EFEB65F2640606D37C1373F454020261B0FB6602640D8B2B5BE4840454000AAF23D236126408893A641D14045408094490D6D602640B874B0FECF41454000A8E331035D2640B8DDAF027C434540E0003274EC5026402841B8020A474540004F95EF19292640D07C957CEC50454040EFAB72A1F2254090423D7D045C4540C0E7154F3DEA2540001B4982705D454020A8E33103DD2540F808C380255F454080129F3BC1D6254008D3A23EC95F4540803F373465C72540E8A9F23D2361454060AA0B7899B92540C88BDAFD2A624540603F373465872540A0C2D8429069454020C2FA3F87892540E0FD9C82FC6A4540A01EA33CF38A254038232E008D6C45408020B248138F254028266F8099714540A0FA96395D8E2540A0E67283A1724540A0BFD2F9F08C2540B0622AFD84734540E04E95EF1989254030232E008D744540407156444D7C2540109700FC53764540A02FF7C951782540E0F19881CA764540A07A32FFE8732540D009A1832E774540C0E1934E24602540E07C957CEC784540E0737E8AE358254030F911BF62794540C0035ABA822D25405082FE428F7A4540400AF5F411102540E0CDFE40B9854540E0AA24B20F12254010D3A23EC987454020321F10E814254008D3A23EC98F4540A01B62BCE6152540B06BED7DAA92454040295C8FC2152540889065C1C493454000C87C40A01325401009C3802597454080A48977800F25408087A2409F9C4540A091088D600B25403038F581E49F4540803F373465072540A8A10DC006A24540A000193A76D82440801EA33CF3B2454040D6A88768C42440587C7C4276B84540401286014BBE2440908AE3C0ABB9454060C554FA09B72440084BE7C3B3BA45400006820019AA2440A87A32FFE8BB4540609E077767A5244008D6E3BED5BC4540A0A7CAF78CA42440885182FE42BD454080B3CEF8BE98244060F5F23B4DC44540A05626FC5297244038ED0DBE30C54540E0AC33BE2F96244050499D8026C645408033863941932440D88B4CC0AFCB4540A0035ABA828D2440884E417E36D84540A0B60F79CB8D244030F911BF62D94540A0B60F79CB8D244050FEB5BC72DB4540C0CCCCCCCC8C244008E5284014DE4540E0D58F4DF28B2440804E417E36E0454000C2FA3F87892440101B498270E5454020180802648824405076FA415DE64540E0A9F23D2381244038DEC83CF2EB4540A0A148F7737A2440B89B8BBFEDEF4540A038BA4A7777244060465C001AF1454020274D83A2712440881EA33CF3F2454020B0743E3C6B2440A8ECF483BAF4454040FEF0F3DF5B2440D87C957CECF84540207A19C5723B2440080000000000464080C554FA09372440385C8FC2F500464040DC2A88812E2440C8B837BF61024640606C06B820232440E0F4D901D7034640C01D71C8061A24407887A2409F0446406023D8B8FE0D2440B0AA5E7EA7054640A04CA4349BF723408078CF81E5064640C08AA9F4136E2340082A8E03AF0E4640E01D8A027D522340B8A10DC0061246408077F17EDCBE2240B8BF97C283244640802975C938AE224000BB9A3C6527464020B937BF61AA22402038F581E42746408009DCBA9B77224030F6D03E562C4640400341800C752240E0BEB9BF7A2C4640803E3C4B90A12140A85FE97C783646400051BD35B0852140883FFCFCF736464020BC783F6E7F214010DC65BFEE36464020F52D73BA7C2140E076137CD33646408000193A76782140B0DA6E826F364640E0F1ECF2AD472140508BC1C3B4314640E0BB783F6EFF2040A8C2D84290294640402DCF83BBFB204010E2E7BF0729464040C422861DE6204000D6E3BED524464020261B0FB6E0204050FEB5BC72234640C0B2B5BE48E0204090992842EA224640602CB64945E32040C053E57B46224640A023F3C81FE4204040D8463CD921464040D6A88768E420405073B9C15021464040B08D78B2E320408018213CDA2046400090DB2F9FD4204028172AFF5A184640603BFBCA83CC2040E876137CD3164640C05758703FC82040B8DA6E826F1646402006820019AA204060F5F23B4D144640C077F17EDC9E2040F8DEA63FFB13464020295C8FC29520403014E97E4E13464060A48977808F2040B0E67283A1124640C04E95EF19892040B85CA8FC6B114640A02634492C79204088CC07043A0D4640C0129F3BC1762040C8BEB9BF7A0C464000013274EC50204038F38FBE49FF4540A0A48977804F2040009700FC53FE4540C020B248134F204080CC07043AFD4540004E7CB5A350204030F6D03E56FC454020A26131EA52204008C79E3D97FB4540E0716F7EC354204008D061BEBCFA4540E0716F7EC3542040B853E57B46FA4540C0C64ACCB32220407854C37E4FF24540C022DA8EA9CB1F4028F6D03E56EC4540C0D38041D2A71F40B8622AFD84EB45408046B41D53171F4028172AFF5AE84540C0300BED9CF61E4030E44A3D0BE6454080EFAB72A1F21E4028327381CBE5454080D576137CB31E408015E0BBCDE3454080035ABA82AD1E40F82CCF83BBE34540C046EBA86AA21E408015E0BBCDE34540407F69519F741E40B89ECC3FFAE4454000E3A7716F5E1E40D8B5F63E55E54540C037BF61A2511E40D8B5F63E55E54540C088450C3B4C1E4080CC07043AE5454040649291B3201E4068882AFC19E4454000F52D73BA1C1E40303B3602F1E4454040CDCCCCCC0C1E4050465C001AE9454040D5AD9E93FE1D40B0ECF483BAEC4540402634492CF91D404876FA415DEE4540C07C410B09F81D4030F38FBE49EF4540402634492CF91D4038172AFF5AF04540C014AE47E1FA1D408018213CDAF0454080A9F23D23011E40E0C1FA3F87F14540C099D024B1641E40B0DDAF027CFB454000D9D0CDFEA01E40D0CABDC0AC004640C0703D0AD7A31E4078457EFD1001464000D253E410D11E40080F45813E094640C0B5F63E55D51E40D08BDAFD2A0A4640409279E40FD61E40606A6803B00B464040BFD2F9F0AC1E40A86E2EFEB60F464040809BC58BA51E40F82F1004C81046400083C30B22A21E40A8C2D84290114640003F3C4B90A11E40808120408612464040C422861DA61E409096E7C1DD15464040A8FC6B79751E40A8A44E401317464080716F7EC3141E40F8DEA63FFB134640C0DBF81395DD1D40E0EE5701BE11464040A3755435B11D40884E417E3610464080BFD2F9F0AC1D40E08558FD1110464080643E20D0691D40F82F1004C8104640009AD024B1641D40E0F71A82E310464080F2052D24201C4058853FC39B1F464040D48041D2E71B40B059677C5F24464080634337FB831B40D0D38041D22F464080B1A19BFD811B40804E417E3630464080068200196A1B40B853E57B464246400020B75F3E691B4080CC07043A454640C0D47B2AA7CD1B40E0031F831555464000E17F2BD9E11B40600ABABDA45746408015E0BBCDEB1B40B0E0F0828858464000977153031D1C40B05626FC525F46400095490D6D201C40B8B915C26A6A4640C0F8872D3D0A1C409087A2409F6C464080B950F9D7021C40286893C3276D464040DE57E542E51B40A8DA6E826F6E4640404B3B3597DB1B40D876137CD36E4640C0DE52CE17CB1B40885704FF5B6F4640C077F17EDCBE1B400821CB82896F4640C015E0BBCDAB1B40109700FC536E464000416491269E1B40D87FD6FCF86D46404038BF61A2911B408048BF7D1D6E464040EA245B5D6E1B4010DC65BFEE6E464000977153035D1B402838F581E46F4640C05DC136E2191B40B87A32FFE873464040AAF23D23011B40281A6B7F6775464080C64FE3DEFC1A40F8CC203EB075464040809BC58BA51A40E088997D1E854640C0798D5DA27A1A4000068200198E464080240C03967C1A40D0C43BC0938E46404054E57B46821A4020F38FBE498F4640C0D3F20357891A40F0D5C743DF8F46408090F469158D1A4038EACC3D24904640003BE2900DB41A40A8B915C26A924640404C361E6CC11A4088992842EA92464040F8872D3DCA1A40E8AF743E3C934640C0DE52CE170B1B40480438BD8B954640C05FE97C78161B40507FBDC282954640C0634337FB431B4088423D7D04944640C07E6E68CA4E1B40884B00FE2993464000B2A19BFDC11B40883FFCFCF79646400054E57B46421C4030232E008D9C46400022E4BCFF7F1C4008CADFBDA3A04640C0B950F9D7821C4028E109BDFEA04640C0E3A25A44841C40B0C2D84290A146404046EBA86AA21C40B0B393C151B046400060E97C78961C4070A52C431CB746408093347F4C5B1C40A8629CBF09BD464080B950F9D7021C4088A2EBC20FC24640C0BB783F6EFF1B406055A18158C2464040A8FC6B79F51B405070784144C44640C0368DEDB5E01B40885A457F68CC464000105EBBB4411B40785A457F68DC4640C06893C3273D1B40386893C327DD464000D8D5E4293B1B40385FD04202DE464040F1113125321B40F07B9BFEECE346400091EF52EA321B40E07FD6FCF8E5464080944E24983A1B4000D9243FE2E946400082C8224D3C1B40B0B915C26AEA464080B628B341461B4058793BC269EB464040944E24987A1B40580438BD8BED46408021E4BCFF7F1B40A8E3310395ED464080583A1F9E951B4000D6E3BED5EC464080E07F2BD9A11B40A8ECF483BAEC4640409BC6F65AB01B40E0031F8315ED4640803788D68AC61B408096E7C1DDED464080D6A88768E41B40586D37C137EF4640C059677C5FEC1B40600ABABDA4EF4640C05417F032F31B40584F1F813FF04640C0230C0396FC1B4058F833BC59F1464080EDB5A0F7261C4038F38FBE49F7464000A243E048401C40A859677C5FF4464040861DC6A44F1C405834D6FECEF24640405B99F04B5D1C4038266F8099F146408022DFA5D4651C4058465C001AF146404052B81E856B1C40D87C957CECF04640804069A851781C40382F3201BFF04640807A19C572BB1C40B0E0F08288F0464000AAF23D23C11C40B0E0F08288F0464080921CB0ABC91C40D87C957CECF046404015E0BBCDEB1C40801EA33CF3F2464040068200192A1D40385FD04202F64640C0AD4CF8A52E1D4048499D8026F6464080D576137C331D4080AEEFC341F646404007B474055B1D40B89509BFD4F54640C0634337FB831D40D8031F8315F5464000E2B19FC5921D40905182FE42F54640007D410B09B81D40903FFCFCF7F646408013B35E0CD51D40607C7C4276F84640C0809BC58B251E401048A643A7FD464080C554FA09971E40B0E3310395FD464040F52D73BA9C1E40081B498270FD4640809CC1DF2FD61E40302F3201BFF84640C02634492CF91E40B05626FC52F74640C0C64ACCB3221F40B0AD11C138F6464040C954C1A8641F40B0048BC399F5464040417FA1476C1F4070A9F57EA3F546404096766A2E771F4028F911BF62F94640C00F5EBBB4811F40D8BEB9BF7AFC4640C09CF3531C871F40306893C327FD4640C0B0A6B2289C1F40B077F17EDCFE4640C01A3048FAA41F40386E15C440FF464000CDCCCCCCCC1F40386E15C440FF464040D6A88768E41F4058853FC39BFF46408070422102FE1F40D8B2B5BE4800474060D6A8876804204090457EFD100147402021CB8289072040608BC1C3B4014740E088450C3B4C2040F8E769C02013474060BFD2F9F04C204000C79E3D97134740607497C4595120406828D2FD9C16474000274D83A25120400809C3802517474060C1E1051151204080C9C6832D184740C0921CB0AB492040B0A78FC01F1C474020F2ECF2AD472040383B3602F11C474060AA0B7899992040D8CDFE40B9354740E006B474059B204010E528401436474040F52D73BA9C20406076FA415D364740C0D24ECDE5B6204020266F80993947402007B47405BB204078A2EBC20F3A4740207156444DDC2040A8B05241453B474000BC783F6EDF20403814E97E4E3B4740200D36751EE5204000E869C0203B4740006E15C440E72040B8984A3FE13A4740C0622AFD84EB204010D9243FE2394740E059677C5FEC2040D0F71A82E338474080AD4CF8A5EE2040D8B2B5BE4830474060DC2A8881EE204078A52C431C2F4740806BED7DAAEA2040D8D03FC1C52A4740200D36751EE5204028F911BF62294740C079008BFCE22040706649809A28474000965D30B8DE204030327381CB254740201286014BDE2040785182FE4225474060DF6B088EE32040E0D38041D21F4740A023F3C81FE42040A8BC5642771F4740C015E0BBCDEB20408096E7C1DD1D474020D026874F3A2140580ABABDA40F4740207156444D3C214010BB9A3C650F4740C053E57B46622140A89ECC3FFA0C474040BB5F05F8662140603A58FFE70C47404069C537146E2140D088997D1E0D4740401E8A027D722140587FBDC2820D4740A00D897B2C75214050DA8D3EE60D474000C53BC0937E21402820ED7F800F4740C079008BFCA2214088397AFCDE0C474060BB5F05F8A62140A859677C5F0C47400023DA8EA9AB214060FEB5BC720B474060CAA48636B02140081E8A027D0A47406045B9347EB12140D8066003220A474000E6E8F17BB32140D80F238447094740E0311F10E8B42140E0D38041D207474000BFB9BF7AB4214028F38FBE49074740E05417F032B32140803FFCFCF70647406051BD35B0A521409087A2409F044740E053E57B46A2214050431B800D044740E0B2B5BE48A0214008C45DBD8AFE4640206E15C440A72140E07FD6FCF8FD4640008A592F86CA21405855A18158FA4640C0CCCCCCCCCC2140A0C2D84290F9464080A148F773DA21403814E97E4EF34640C0BB783F6EDF2140584F1F813FF04640008D9AAF92DF2140A86E2EFEB6EF4640E0EA56CF49DF2140586D37C137EF4640A0BB5F05F8E62140100C040132EC46400009C38025FF2140D08BDAFD2AEA4640A0D03FC1C5122240D8AF743E3CEB4640801EA33CF32A2240B0E67283A1F24640A015E0BBCD2B224028E78BBD17F34640A015E0BBCD2B224060FEB5BC72F34640E0921CB0AB29224040D505BCCCF44640E0CABDC0AC28224080CC07043AF54640E082C30B22222240101286014BF64640A09BC6F65A102240286E15C440F74640E0CCCCCCCC0C224000D3A23EC9F74640205C8FC2F50822408818213CDAF84640401286014BFE214008240C0396FC46402038A11001FF2140000341800CFD464020E9297288082240A8984A3FE1024740C05DDA7058122240B85626FC52074740E06BED7DAA2A22402820ED7F800F474080B08D78B2432240A8BF97C283144740C0889AE8F349224010902FA18215474000B4E73235512240E07FD6FCF81547402054FEB5BC5A22402829B000A6164740804278B4715C2240F8DB65BFEE164740C0D8D0CDFE6022403038F581E4174740201077F52A7A2240607FBDC2821D4740C0094B3CA07C2240785166834C1E474000C4094CA78D2240101B498270254740E0978A8D7995224058F833BC59294740E0AC33BE2F962240A874B0FECF294740C02FF7C95198224050888043A82C4740A07C410B0998224028ED0DBE302D4740407D5A457F9022406831957EC235474020861DC6A48F2240E0AC33BE2F364740E022DA8EA98B2240D876137CD336474060DF6B088E832240606D37C137374740C03E3C4B90812240A8BC564277374740200000000080224030172AFF5A384740402FDE8FDB7F224060F833BC59394740C0A6B1BD168C2240B8DA6E826F3E4740809BC6F65A902240B8BC5642773F4740C07A32FFE8932240E000DE0209404740A07C410B099822405801F73C7F4047404054FEB5BC9A2240706649809A40474080B3CEF8BEB8224050465C001A4147408077F17EDCBE2240285C8FC2F5404740605C8FC2F5E82240E0BEB9BF7A3C47406048FAB48AE622406028D2FD9C364740A074B0FECFE9224000274D83A2314740202C9D0FCFEA2240100F45813E314740C01EA33CF30A2340D87C957CEC284740E0285C8FC215234038F38FBE49274740C04D637B2D18234080A52C431C27474020356090F4292340385FD04202264740402FDE8FDB3F2340B0B6D4415E254740605A80B6D564234030E44A3D0B264740C06BED7DAA6A2340D8AC33BE2F2647404069C537146E2340608E0244C1264740E089592F868A2340D8B22781CD2B4740C0B2B5BE48A023408896E7C1DD2D4740C08FDB2F9FB42340C05626FC522F474060D367075CCF234000E2E7BF07314740401E8A027DD2234090457EFD10314740802CB64945E3234010CADFBDA33047406077D84466E62340B8E0F08288304740C04D637B2DF82340009700FC532E474040FEF0F3DFFB234028327381CB2D474000F52D73BAFC2340A8B6D4415E2D4740404B3B3597FB2340B859677C5F2C4740C0129F3BC1F623402035B401D82A474060C554FA09F72340A0B915C26A2A4740001B498270FD2340E0B5F63E55254740A05A99F04B1D244020ED0DBE301D474000B3B5BE48202440B8BF97C2831C4740E082C30B2222244068F5F23B4D1C474040CDE50643252440100C0401321C4740E05758703F282440C80CE2033B1C4740A0069B3A8F422440E0031F83151D4740A0A7CAF78C442440585260014C1D4740606552431B4824408096E7C1DD1D4740A0D24ECDE5562440A8656B7D91204740802FF7C951582440E07C957CEC20474020D026874F5A24404855A181582247400054FEB5BC5A2440B8984A3FE1224740A06DFC89CA4E2440603D997FF4314740A0A48977802F2440E0AC33BE2F364740C032384A5E2D2440001286014B364740803579CA6A222440885704FF5B374740404278B4711C2440306552431B384740A02634492C192440682E54FEB538474080BC9179E417244088457EFD1039474040C554FA0917244008C11C3D7E394740A0129F3BC1162440B8A10DC0063A47404020990E9D162440084E2844C03F4740E0D24ECDE5162440D87C957CEC404740C06ABB09BE192440C888997D1E4547408014AE47E11A2440507FBDC282454740C0A7E331033D244070AEEFC3414E474000F52D73BA5C2440E07C957CEC504740A038BA4A77772440883CBB7CEB514740201077F52A7A2440E073D2FBC6514740402DCF83BB7B244008C11C3D7E514740E0CF0D4DD9812440600ABABDA44F4740E082C30B2282244088A52C431C4F4740C03E3C4B90812440D8C43BC0934E4740E0E2A7716F7E2440B0ECF483BA4C474020EC6AF2947D2440602B137EA94B4740E0CDFE40B97D2440804B00FE294B4740E0955D30B87E244000D061BEBC4A474080A148F7739A24400809C38025474740204278B4719C244028DB87BCE5464740C00C1D3BA8AC2440009700FC53464740E0B628B341E62440709FAA420345474020D0D38041EA2440A87D01BD70454740A02975C938EE2440D0FA5B02F045474020B4E73235F124405028D2FD9C464740E0E5E8F17BF324408821E4BCFF4747408000193A76F8244000C79E3D974B4740E0737E8AE3F82440B0A78FC01F4C4740802634492CF92440508E0244C14E4740406684B707F9244028F38FBE494F474060C1E10511F1244030F911BF62514740000D36751EE52440908AE3C0AB6147404076C3B645F12440C022BF7E886F474020A26131EAF22440783FFCFCF76E47402090DB2F9FF424403029B000A66E4740A077F17EDCFE244010A0C37C796D47400009C380251F25408887A2409F6C474060C2137AFD212540580DFB3DB16C4740206211C30E33254030327381CB6D4740605C8FC2F5482540586D37C1376F4740A0035ABA824D254048853FC39B6F4740E0978A8D79552540809C69C2F66F474000FEF0F3DF5B2540809C69C2F66F474000C53BC0935E2540D8D38041D26F4740E0D8D0CDFE602540580ABABDA46F4740A023F3C81F842540089A417C606B4740603F373465872540D0D03FC1C56A4740A05758703F882540E073D2FBC6694740603F3734658725405073B9C150694740E0B5F63E55952540D8C43BC093664740C0DE52CE17AB2540B0ECF483BA6447404048FAB48AC62540084BE7C3B36247400021CB8289072640A8984A3FE1624740E0921CB0AB09264038E78BBD1763474020634337FB23264078ABAE4335694740000D36751E25264028266F80996947404045B9347E3126409018213CDA704740206BD443343226406073B9C15071474000EFAB72A1322640081E8A027D724740207D5A457F302640D0F4D901D7734740609BC6F65A302640A859677C5F7447404045B9347E31264040D505BCCC74474000A26131EA322640D088997D1E754740602634492C39264060FB743C66764740804278B4713C26403041B8020A774740000C040132542640804B00FE297B4740C0C98B4CC0572640082DCF83BB7B474000BC783F6E5F2640F80B0401327C474000CA8B4CC0F72640B074B0FECF814740E006B474053B2740888AE3C0AB814740C0CF0D4DD941274028266F8099814740E074B0FECF692740E0D38041D27F4740A032384A5E6D2740386E15C4407F4740E0C77C40A0732740081B4982707D4740006684B707792740306893C3277D4740C079008BFC822740E088997D1E7D474020E9297288882740585260014C7D47404048FAB48A26284048853FC39B874740E04F1C40BF47284080279F1EDB8A4740E0CDFE40B95D2840E8A6B1BD168C4740C018213CDA602840A0A78FC01F8C47404045B9347E7128403014E97E4E8B474000999EB0C473284028E78BBD178B4740A08EC70C547628406055A181588A4740E0AC33BE2F762840000F45813E89474020EFAB72A1722840D88558FD11884740E0CABDC0AC682840809FAA42038547404051BD35B065284038F6D03E56844740C08B868C47612840D8F4D901D7834740C077F17EDC5E2840302CF180B2834740C02975C9384E284008E869C02083474020FBAF73D3462840B06BED7DAA82474040895E46B1442840201DACFF7382474060C2137AFD412840588BC1C3B481474000AAF23D23412840080F45813E814740A05CA8FC6B412840904E417E3680474018000000A0DE52CE17EB2840004BE7C3B3F24540E076BF0AF0ED2840B8E67283A1F2454000A26131EAF228403035B401D8F24540806ABB09BEF9284030DEC83CF2F34540001B498270FD2840E0031F8315F545400052D66F26FE2840E0AC33BE2FF64540609E077767052940884E417E36F84540000473F4F8052940382F3201BFF8454080CDE5064305294028327381CBFD4540400D36751E052940009700FC53FE454080B950F9D702294010C45DBD8AFE4540407156444DFC28405828D2FD9CFE45402045B9347EF12840009700FC53FE454000CDCCCCCCEC284030E44A3D0BFE45402018080264E828400048A643A7FD4540202A8E03AFE62840381A6B7F67FD4540207CB779E3D428404089963C9EFA4540207497C459D1284028F04E3E3DFA454080D367075CCF284030F911BF62F94540C06DFC89CACE28406028D2FD9CF64540E02D910BCED0284050DDCEBEF2F44540006211C30ED3284000DFA63FFBF34540E0E4D4CE30D528408815E0BBCDF34540A0DE52CE17EB2840004BE7C3B3F245400400000060DD3DE1E2E328405841DE5A99F34440C043A75CCFE9284050EC8FED61F344404041451B3FE7284060C511FC38F4444060DD3DE1E2E328405841DE5A99F34440010300000001000000130000008000193A76D82840B09509BFD4B54640C01D71C806DA2840B0E3310395B546404054FEB5BCDA2840306893C327B54640A07C410B09D82840889FAA4203B5464020F0F8F6AEC12840C02EC37FBAB54640E0BB783F6EBF2840885182FE42B5464000301004C8B02840100F45813EB14640E0A6B1BD16AC2840A0E9B303AEAF4640406552431BA82840385FD04202AE4640206E15C440A72840500438BD8BAD46406051BD35B0A5284088423D7D04AC464060C2137AFDA1284088397AFCDEAC464060B3CEF8BEB8284090CC07043AB5464020240C0396BC2840001286014BB64640E008C38025BF2840E0F19881CAB64640C053E57B46C228405840DAFF00B74640E0A4A2B1F6C728400009C38025B74640A076BF0AF0CD28405840DAFF00B746408000193A76D82840B09509BFD4B546400103000000010000001000000040CAA48636B02340905A457F68844540E0CF0D4DD9A12340B8656B7D91804540C0656B7D91A02340D0CABDC0AC804540606893C3279D2340F80E45813E81454040FEF0F3DF9B234030266F8099814540A02634492C9923403835B401D8824540A085048C2E972340000C0401328445400007B474059B2340B06E2EFEB6874540002DCF83BB9B234080C9C6832D884540A09E077767A52340903CBB7CEB894540E0A4A2B1F6A72340903CBB7CEB894540C074B0FECFA92340888AE3C0AB894540E0DE52CE17AB23405073B9C150894540C07A32FFE8B32340888D2441B8864540207497C459B1234038D505BCCC84454040CAA48636B02340905A457F688445400103000000010000002F000000E0CF0D4DD9E12440E0A6B1BD166C4540E0F42D73BADC2440B059677C5F5C454020FEF0F3DFDB24402014E97E4E5B45402083DC4598DA2440D8FD9C82FC5A454080E2AC889AD82440F8CF61BEBC5A4540C08EC70C54D62440004BE7C3B35A4540A068ACFD9DB52440B8AAD0402C614540206BD44334B22440588BC1C3B46145406017EFC7EDAF2440803CBB7CEB614540A07F828B15AD2440283E7782FD61454080D9E90775992440000F45813E614540A04D637B2D7824400821CB82895F4540E0DE52CE176B24408048BF7D1D5E4540C0AA24B20F522440B8B6D4415E5D4540A059677C5F4C2440281A6B7F675D4540206E15C4404724400848A643A75D4540808B868C474124406076FA415D5E4540E01186014B3E2440803FFCFCF75E454000FEF0F3DF3B2440B0E9B303AE5F454000B6F63E55352440583D997FF4614540400C040132342440B8984A3FE162454040E6E8F17B332440B87A32FFE8634540C07A32FFE8332440789FAA4203654540A05626FC5237244030E44A3D0B6645402054FEB5BC3A24405828D2FD9C664540A018213CDA402440506D37C137674540C0E7154F3D4A244000D3A23EC967454040EC6AF2945D244038EACC3D24684540402C9D0FCF6A2440888461C09267454060573F36C96F2440908D2441B8664540001E8A027D72244030E44A3D0B664540C08EC70C54762440500438BD8B65454040B3CEF8BE782440201A6B7F6765454000A26131EAB224402829B000A6664540C0E4D4CE30B52440D8F19881CA664540C04D637B2DB82440E0BB783F6E674540C0D8D0CDFEC02440508BC1C3B4694540A082C30B22C2244010068200196A454020E9297288C82440E088997D1E6D454000356090F4C9244028E44A3D0B6E4540A09BC6F65AD02440686D37C1376F454040EFAB72A1D2244008BB9A3C656F4540A0978A8D79D52440D8BB783F6E6F4540A0EA56CF49DF2440E0CDFE40B96D4540C018213CDAE02440301A6B7F676D4540805CA8FC6BE12440283B3602F16C4540E0CF0D4DD9E12440E0A6B1BD166C45400103000000010000000C000000A050A4FB392D2440000F45813E494540C06BED7DAA2A2440E8A9F23D234945406048FAB48A26244038266F809949454040DF6B088E232440889065C1C44B4540009CDF30D1282440D0F19881CA4E454040356090F4292440506D37C1374F4540C0CCCCCCCC2C2440A8A44E40134F45408076BF0AF02D2440888D2441B84E4540E04B546F0D342440F8DEA63FFB4B454020EFAB72A1322440F84AE7C3B34A454040F86EF3C6312440306BD443344A4540A050A4FB392D2440000F45813E4945400103000000010000001000000020321F10E8D42540F8264D83A2294540606211C30ED32540A85CA8FC6B294540606002B7EECE254040D8463CD929454080B5DD04DFBC2540580438BD8B2D4540604B3B3597BB2540901B62BCE62D45406083DC4598BA2540D076137CD32E4540E05CA8FC6BC12540808AE3C0AB314540A02CB64945C32540D873D2FBC631454020CBBDC0ACC82540D8C1FA3F87314540002C9D0FCFCA254058F833BC5931454000A26131EAD22540908461C0922F4540200C040132D42540586D37C1372F454060C763062ADB254050FEB5BC722B454040D026874FDA2540D8FD9C82FC2A4540A08EC70C54D62540603D997FF429454020321F10E8D42540F8264D83A229454001030000000100000011000000C082C30B22A2244008CADFBDA3284540204278B4719C2440A8656B7D9128454080C554FA09972440E0CABDC0AC284540E0978A8D79952440305C8FC2F528454000EE974F5694244060F833BC59294540E0989EB0C4932440B074B0FECF294540E0989EB0C4932440089A417C602B4540400C040132942440B87A32FFE82B454000DC114E0B96244030D505BCCC2C4540A07C410B09982440809FAA42032D45406083DC45989A2440D888997D1E2D4540C05CA8FC6BA12440580DFB3DB12C4540609E077767A5244058707841442C454080BB5F05F8A6244030DEC83CF22B4540606552431BA82440A8A10DC0062A4540606552431BA82440B0C2D84290294540C082C30B22A2244008CADFBDA32845400103000000010000001301000000FBAF73D3062340D0D03FC1C5924440C021E4BCFF1F2340B8A44E40138F444060A7CAF78C4423406028D2FD9C7E4440803F3734650723405840DAFF00774440A053E57B4602234028E44A3D0B764440C0CF0D4DD9012340507FBDC282754440A079008BFC022340306893C327754440605A80B6D5042340503A58FFE7744440A0B60F79CB0D234038D505BCCC74444060C2137AFD21234080397AFCDE744440E06ABB09BE392340801B62BCE67544406045B9347E512340D088997D1E6D444020E3A7716F7E2340805704FF5B57444080656B7D9180234008A0C37C79554440E0D8D0CDFE802340905A457F6854444080656B7D91802340E07954FCDF53444000B1A6B2287C2340E0EE5701BE514440407156444D7C234000CADFBDA3504440C06E2EFEB67F2340580DFB3DB14C444080656B7D9180234050707841444C4440A085048C2E972340E8AC33BE2F464440809885764E9B234090CC07043A454440606893C3279D234030D505BCCC4444408018213CDAA0234030232E008D44444040D6A88768A4234050431B800D444440E00373F4F8A52340789065C1C443444020FBAF73D3A623400015C78157434440402A8E03AFA62340D8D03FC1C542444000E3A7716F9E234028DEC83CF23B4440E06ABB09BE99234000CADFBDA3384440C0AF743E3C8B23408081204086324440603F37346587234008C11C3D7E314440C023F3C81F842340E07C957CEC304440C094490D6D8023406001F73C7F304440A0BEA085047C234090C9C6832D304440E0BEB9BF7A74234028F38FBE492F4440E088450C3B6C2340901B62BCE62D4440C0B628B341662340B0ECF483BA2C4440407D5A457F502340B0BC56427727444020C422861D462340B8A78FC01F2444408094490D6D40234008274D83A22144402038A110013F2340602E54FEB520444000965D30B83E234088C9C6832D20444000E3A7716F3E2340B8DA6E826F1E4440E008C380253F2340B0C2D8429019444060069B3A8F4223402838F581E4174440A076BF0AF04D23406082FE428F12444020EFAB72A152234090457EFD10114440A0069B3A8F62234008CD203EB00D444000E9297288682340D8BEB9BF7A0C4440C032384A5E6D234030ED0DBE30054440C0703D0AD7632340B06E2EFEB6F7434020D9E907755923400821CB8289E74340C05626FC52572340909065C1C4E343408085048C2E572340D0F71A82E3E0434060BC9179E45723403038F581E4DF4340406684B70759234010DC65BFEEDE4340005DC136E259234008C45DBD8ADE434060D026874F5A234000A0C37C79DD4340005DC136E2592340E8AF743E3CDB434000C4094CA74D2340081286014BC64340209CDF30D148234080AEEFC341BE4340C079008BFC422340B0A44E4013B743404015C781573323405807793D98AA4340A0B950F9D7222340607FBDC2829D4340C03579CA6A222340A89ECC3FFA9C434040261B0FB6202340080F45813E9943408018213CDA202340502E54FEB5984340603F373465272340480ABABDA497434040E929728828234030F38FBE4997434000CBBDC0AC282340B077F17EDC964340C0FDD7B969232340B8B0524145934340C05CA8FC6B212340281DACFF7392434020A8E331031D2340A0C2D84290914340A0DE52CE170B23400809C380258F4340C010902FA1E22240F87B9BFEEC8F4340606BD44334D22240B0A10DC006924340E09BDF30D1C82240E0A6B1BD16944340603F373465C72240B859677C5F944340007A19C572BB2240808D2441B896434060D367075CAF22408018213CDA98434020895E46B1A422405055A181589A4340E085048C2E972240089A417C609B4340E0F0D8CF620922400006820019A24340206E15C440072240803CBB7CEBA143406051BD35B005224008274D83A2A14340409E07776705224058465C001AA1434020FBAF73D306224080C9C6832D904340005858703F082240789FAA42038D4340A06BED7DAA0A2240B0E67283A18A43408059677C5F0C2240D873D2FBC689434000AD33BE2F1622406031957EC285434080DF6B088E032240A05FE97C787E4340809BC6F65AD0214028DEC83CF2734340C091088D60CB2140F8E769C02073434080BC9179E4B72140A8E0F08288704340C0DB114E0BB62140B8B393C1517043402015C78157B32140584F1F813F704340A076BF0AF0AD21400018080264704340A02975C9386E2140A8AD11C138764340008A592F866A21405831957EC2754340A01EA33CF34A2140503D997FF4714340A09885764E3B2140B8E331039575434060C2137AFD212140D80F23844781434040D026874F1A214050FB743C668643408092205C01052140B85E9A22C0874340003C1570CF0321405037177FDB874340408D9944BD002140809C69C2F687434000EB56CF49FF204090C91B60E6874340209770E82DFE204038B05582C5874340005516855DF42040983E74417D854340E060FE0A99F32040901117804685434060C98FF815F3204058828C800A854340600B0742B2F0204020080264E8824340E00373F4F8E5204078ABAE433581434080E466B801E7204068C43E01147F43404077D84466E620409060C77F817E4340C053E57B46E22040B0A78FC01F7C434000F52D73BADC20403835B401D87A4340201E8A027DD2204088812040867A4340409BC6F65AD02040084BE7C3B37A4340606002B7EECE2040D882177D057B4340A0F755B950B92040484CDE0033834340A05626FC52B7204028232E008D844340607497C459B1204088ABAE433589434040301004C8B02040808AE3C0AB894340606211C30EB3204008C79E3D978B43402020990E9DB620408896E7C1DD8D43408038BA4A77B7204080AEEFC3418E434040AA0B7899B92040B0DA6E826F8E434080F755B950D9204028327381CB8D43406054FEB5BCDA2040B068ACFD9D8D434040B08D78B2E32040D0F4D901D78B43402021CB8289E720402835B401D88A4340C00E4757E9E620405013EF004F8C43408016F6B4C3E72040A008C6C1A58B4340A00D33349EE82040A838471D1D8B434020942F6821E92040504F58E2018B434020FA980F08EC2040E02A4F20EC8A4340E0CCCCCCCCEC2040A8681EC0228B434020A69BC420F020406840A19E3E8C4340808FDFDBF4EF204098FF0241808C4340E0DE52CE17EB204098B4E21B0A8F434000E3A7716FDE2040A8BF97C28394434080BEA08504DC204090CC07043A954340C0AF743E3CCB2040888AE3C0AB994340207A19C572BB2040383B3602F19C4340C02634492CD92040A8B915C26AA24340207156444DDC2040786308008EA34340205FD04202DE2040789FAA4203A54340205FD04202DE2040B068ACFD9DA54340606893C327DD20405828D2FD9CA64340E08EC70C54D6204058FEB5BC72AB4340E0ED974F56D42040D8C77C40A0AB4340E0622AFD84CB204000C79E3D97AB434000F1D8CF62C92040809065C1C4AB434060C422861DC6204080397AFCDEAC434020E3A7716FBE20403820ED7F80AF4340405FD04202BE2040889C69C2F6AF434000CBBDC0ACC82040000F45813EB9434020E6E8F17BD32040E009A1832EBF434040C422861DE620400018080264D04340C01A3048FAE420406073B9C150D1434040895E46B1E4204038D8463CD9D14340C079008BFCE2204038F38FBE49D74340C0C64ACCB3E220408018213CDAE0434060DF6B088EE32040080F45813EE14340A09E077767E52040805D86FF74E1434000A5A2B1F6E7204098C2D84290E14340E0B837BF61EA2040805D86FF74E14340E0A6B1BD16EC204080ABAE4335E14340E06DFC89CAEE2040B0656B7D91E043408014AE47E1FA2040905A457F68DC4340A053E57B4602214080397AFCDEDC434020A7B1BD160C2140D8B2B5BE48E04340E0978A8D79152140909065C1C4E3434080A148F7731A2140B0E0F08288E84340E05A99F04B1D214078A86DC328EC4340201B4982701D2140D8B5F63E55ED4340C0A7E331031D2140B877F17EDCEE434080C763062A1B2140A8E9B303AEEF4340C0737E8AE31821400018080264F04340A0B60F79CB0D2140781EA33CF3F24340E00E45813E092140E0F4D901D7F34340A01A3048FA042140D00CE2033BF4434040013274ECF0204080397AFCDEF44340402C9D0FCFEA2040583A58FFE7F44340005C8FC2F5E8204050888043A8F44340A03579CA6AE22040906308008EF34340A021E4BCFFDF2040B0984A3FE1F24340802FF7C951D82040D006600322F2434000A7B1BD16CC2040D8D03FC1C5F24340A06BED7DAACA2040286211C30EF343400006820019CA2040A0622AFD84F343400006820019CA2040B8A78FC01FF4434000A7B1BD16CC204060465C001AF94340404E7CB5A3D02040E0D38041D2FF4340C0AA24B20FD22040883CBB7CEB01444060B60F79CBED20405055A18158124440E059677C5FEC2040789FAA42031D44404006820019EA2040D8A9F23D23294440A0BEA08504BC2040A8A44E40133F444080B5DD04DF9C2040D0D03FC1C54A4440201077F52A9A204058793BC2694B444000AD33BE2F962040D8F4D901D74B4440E0AD65321C672040D8F19881CA4E4440803E3C4B9061204030DB87BCE54E4440E04D637B2D58204000240C03964C4440A01B62BCE6552040D8F4D901D74B444000B6F63E55552040089A417C604B4440A068ACFD9D5520403035B401D84A4440C0E4D4CE305520409054C37E4F4A444000EFAB72A1522040507C7C427648444000274D83A2512040D000DE020948444060BFD2F9F04C2040A0A10DC0064A4440E0D58F4DF24B2040201DACFF734A444040356090F44920408815E0BBCD4B4440C0F0D8CF62492040F81A4982704D4440E0C1FA3F87492040908461C0924F4440002C9D0FCF4A20403838F581E44F444040F86EF3C6512040285C8FC2F5504440409885764E5B2040905D86FF74514440E04D637B2D582040886649809A584440C00C1D3BA84C204028F6D03E565C4440E088450C3B4C2040386E15C4405F444080069B3A8F622040283B3602F174444000321F10E87420404801F73C7F78444020BFB9BF7A7420408021E4BCFF774440C0716F7EC3742040A8BC564277774440C05FE97C7876204050888043A8744440E05626FC52772040D00CE2033B74444080FA96395D8E20402829B000A66E444040321F10E8942040587FBDC2826D444020B1A6B2289C204020232E008D6C4440001286014B9E2040A859677C5F6C4440E05FE97C78B62040E082177D056B4440A0E7154F3DEA204070ABAE433569444020295C8FC2F5204038E109BDFE68444000C74ACCB3022140B85CA8FC6B69444000DC114E0B162140A8B915C26A6A4440E09BDF30D1282140A8622AFD846B4440E0C77C40A0332140A859677C5F6C44408068ACFD9D352140F8230C03966C444060B3CEF8BE382140386893C3276D4440207156444D3C214080AEEFC3416E44400009C380253F2140D08558FD1170444000AAF23D23412140D8F71A82E3704440601A3048FA442140903CBB7CEB714440209CDF30D1482140C8B837BF61724440E07F828B154D214000D061BEBC724440803579CA6A622140A8BF97C283744440A015E0BBCD6B2140F80241800C7544404007B474057B214028ED0DBE30754440A018213CDA802140E088997D1E75444040E9297288882140A8716F7EC374444060BFD2F9F08C2140E088997D1E75444020BFB9BF7A942140305FD04202764440E077F17EDC9E214058853FC39B774440000AF5F411B021403035B401D87A444000E5D4CE30B52140E00CE2033B7C4440A038BA4A77B72140A89ECC3FFA7C4440C077F17EDCBE2140B0E9B303AE7F4440208D9AAF92BF214090C9C6832D80444020809BC58B0522403820ED7F808F4440603F373465072240B06E2EFEB68F4440E08FDB2F9F142240806649809A904440A05FE97C78162240582E54FEB590444080F755B950192240282F3201BF904440E02CCF83BB1B224010CADFBDA3904440E05DDA7058522240B0E0F0828898444080B81E85EB51224080AEEFC3419E4440A05417F0325322408060C77F819E4440405DC136E2592240B8BC5642779F4440E05626FC52772240886649809AA0444000FBAF73D3062340D0D03FC1C592444001030000000100000016000000E0C3094CA7AD20409021E4BCFF874440E00E45813EA92040A8A44E4013874440C0A4A2B1F6A720406040DAFF0087444040E3A7716F9E2040888461C092874440C0C77C40A09320403038F581E4874440207497C459912040B86E2EFEB6874440605C8FC2F58820406040DAFF00874440809885764E7B2040E07954FCDF834440A05A99F04B7D2040B0AD11C1387E4440C0D03FC1C572204088AEEFC3417E4440602975C9386E20402841B8020A7F4440C0C3094CA76D2040A0656B7D9180444020AD33BE2F76204008A0C37C79854440C0C77C40A093204038D505BCCC8C4440C018213CDAA020405840DAFF008F444080D6A88768A42040F820CB82898F4440E0B628B341A6204008BB9A3C658F444040301004C8B0204088A86DC3288C444040F86EF3C6B12040082DCF83BB8B444000274D83A2B12040B8B05241458B4440C0FA96395DAE2040587C7C4276884440E0C3094CA7AD20409021E4BCFF8744400103000000010000000F00000000C4094CA7ED2940D8A9F23D237144400023DA8EA9EB2940D07C957CEC704440605C8FC2F5E8294008E2E7BF077144400021CB8289E7294068F833BC597144404077D84466E62940488BC1C3B471444060F4143944E42940B86BED7DAA724440A0FDD7B969E3294038E78BBD1773444040D6A88768E4294080423D7D047444408048FAB48AE6294000A0C37C79754440406552431BE8294008CD203EB0754440204E7CB5A3F02940F8298E03AF764440205DC136E2F92940606D37C13777444000E6E8F17BF32940A8984A3FE172444000D13FC1C5F22940908120408672444000C4094CA7ED2940D8A9F23D237144400103000000010000001100000020AE65321CE72B40E873D2FBC659444020E9297288C82B40B0656B7D91584440E00F77F52ABA2B40D8EE5701BE5944402020990E9DB62B4038F04E3E3D5A4440200C040132B42B40901EA33CF35A4440C0E4D4CE30B52B4028E44A3D0B5E4440007A19C572BB2B4028E109BDFE604440A082C30B22C22B40A85CA8FC6B614440205A80B6D5C42B405073B9C150614440C079008BFCE22B40606D37C1375F4440A09E077767E52B402841B8020A5F444000FBAF73D3E62B40588E0244C15E4440E05758703FE82B40A8DA6E826F5E4440E06BED7DAAEA2B40507FBDC2825D44406069C53714EE2B4008DFA63FFB5B44406069C53714EE2B4058FEB5BC725B444020AE65321CE72B40E873D2FBC659444001030000000100000016000000A015E0BBCD6B2C40F84D2844C0474440404B3B35977B2C402841B8020A4744400052D66F267E2C4070A52C431C474440002FDE8FDB7F2C40905704FF5B47444080F4143944842C40480ABABDA4474440000473F4F8852C4000BB9A3C6547444040C422861D862C4070A52C431C474440C0FDD7B969832C4000C45DBD8A464440C03579CA6A822C4058499D802646444000D00D4DD9812C401048A643A7454440A094490D6D802C40001B498270454440C05A99F04B7D2C40285FD042024644404083DC45987A2C408848BF7D1D464440C0AC33BE2F762C40B09509BFD4454440609BC6F65A702C4090CC07043A45444020F2ECF2AD672C4008240C0396444440A01A3048FA642C40600DFB3DB14444406023F3C81F642C40E088997D1E45444040CDE50643652C40E0F19881CA46444060116DC7D4652C40B85626FC5247444000FBAF73D3662C40A86E2EFEB6474440A015E0BBCD6B2C40F84D2844C047444001030000000100000012000000C068ACFD9D95204010DFA63FFB8B4340206211C30E932040E07954FCDF8B434000C4094CA78D204010DFA63FFB8B434040C2137AFD812040905182FE428D4340C0656B7D91802040500438BD8B8D434000B4E73235712040D88BDAFD2A924340404E7CB5A3702040A8E67283A1924340407497C459712040B0ECF483BA944340E0EEAB72A1722040D0031F831595434000F52D73BA7C204028E44A3D0B964340E006B474059B2040A8B393C15198434020FEF0F3DF9B20408021E4BCFF974340E0A7E331039D2040281DACFF7392434080B5DD04DF9C2040D07C957CEC904340404278B4719C2040608E0244C18E4340402DCF83BB9B2040E0CDFE40B98D4340C05626FC52972040000C0401328C4340C068ACFD9D95204010DFA63FFB8B434001030000000100000010000000A032384A5E6D2E40A8E67283A1624340C06BED7DAA6A2E40A8E67283A162434080C2137AFD612E40A87A32FFE8634340A018213CDA602E4030D505BCCC644340C05CA8FC6B612E4028ED0DBE30654340E0AF743E3C6B2E40D8BB783F6E674340C00C1D3BA86C2E40F84D2844C0674340A06DFC89CA6E2E402838F581E467434020BFB9BF7A742E40E0D38041D267434060A148F7737A2E40D009A1832E67434040FEF0F3DF7B2E40B077F17EDC66434040FEF0F3DF7B2E40109700FC53664340A068ACFD9D752E4038DEC83CF2634340200C040132742E40D0C77C40A063434080A48977806F2E40D0D03FC1C5624340A032384A5E6D2E40A8E67283A162434001030000000100000011000000A0B3CEF8BE582A4028172AFF5A584340E0B3E73235512A4088C9C6832D584340C0F1D3B8374F2A40E0B2B5BE4858434060B60F79CB4D2A40B8656B7D91584340A076BF0AF04D2A4080457EFD10594340206211C30E532A4060FEB5BC725B4340E08FDB2F9F542A40382CF180B25B4340A000193A76582A40B8A78FC01F5C4340E0F42D73BA5C2A4058F5F23B4D5C4340E0955D30B85E2A40E8A6B1BD165C43408023F3C81F642A40F899417C605B434060809BC58B652A40306211C30E5B43402051BD35B0652A4090812040865A4340C0F4143944642A40306BD443345A434000240C03965C2A4008301004C8584340E006B474055B2A40A8E0F08288584340A0B3CEF8BE582A4028172AFF5A5843400103000000010000000F00000040240C0396BC2D4080423D7D044443400054FEB5BCBA2D409015E0BBCD434340E0B5F63E55B52D4080423D7D044443402023DA8EA9AB2D40306893C327454340A07C410B09982D402020ED7F80474340A08EC70C54962D40D8B2B5BE48484340C0D24ECDE5962D40C8CABDC0AC484340604B3B35979B2D40B8B915C26A4A4340405FD042029E2D40001E8A027D4A434060A148F773BA2D40D88BDAFD2A4A434000F52D73BABC2D40383E7782FD4943400009C38025BF2D405873B9C15049434000BC783F6EBF2D408818213CDA4843400009C38025BF2D40504F1F813F48434040240C0396BC2D4080423D7D0444434001030000000100000014000000A04E95EF19E92D4010E2E7BF07394340202A8E03AFE62D40305C8FC2F5384340206211C30ED32D40582B137EA93B4340A017EFC7EDCF2D4050707841443C434000C4094CA7CD2D40303B3602F13C4340C015E0BBCDCB2D4080AEEFC3413E4340E0A6B1BD16CC2D40608E0244C13E4340E06DFC89CACE2D4088ABAE43354143406045B9347ED12D4008D9243FE2414340206211C30ED32D40D006600322424340200341800CD52D405855A18158424340406684B707D92D405082FE428F424340E0E7154F3DEA2D40D8D03FC1C5424340A03BFBCA83EC2D406007793D98424340A0035ABA82ED2D4028F04E3E3D42434080AD4CF8A5EE2D4058F833BC59414340C07F828B15ED2D40883CBB7CEB394340600C1D3BA8EC2D4008C11C3D7E394340C0DE52CE17EB2D40000F45813E394340A04E95EF19E92D4010E2E7BF073943400103000000010000001100000040D026874FFA2D406828D2FD9C2E4340C009DCBA9BF72D406828D2FD9C2E4340C068ACFD9DF52D40E076137CD32E434000C2FA3F87E92D4010CADFBDA3304340E0A4A2B1F6E72D40D8F71A82E3304340E0CF0D4DD9E12D4008E869C020334340E05CA8FC6BE12D40F8C69E3D973343408023F3C81FE42D40580438BD8B354340801EA33CF3EA2D40D009A1832E374340C0CCCCCCCCEC2D4028F38FBE49374340C06DFC89CAEE2D40B8A44E4013374340E01186014BFE2D405807793D98324340C082C30B22022E40B8E0F08288304340C082C30B22022E408821E4BCFF2F4340E0FFFFFFFFFF2D40686D37C1372F4340204278B471FC2D40588E0244C12E434040D026874FFA2D406828D2FD9C2E4340010300000001000000EE000000C06DFC89CA0E2F40D0C1FA3F87114340005A80B6D5042F4060FEB5BC720B4340803579CA6A022F4000068200190A4340C08B868C47012F40588BC1C3B4094340C077F17EDCFE2E4020E109BDFE0843402007B47405DB2E40386552431B004340A051D66F26BE2E40B0AAD0402CF94240202DCF83BBBB2E40587C7C4276F842406000193A76782E40A8BF97C283E44240207D5A457F702E4030D8463CD9E1424060861DC6A46F2E40306211C30EDB424040D367075C6F2E40081E8A027DDA4240E0FAAF73D3662E40089A417C60D3424080C763062A5B2E40908AE3C0ABC94240E0D24ECDE5562E40206552431BC8424000295C8FC2552E40B86E2EFEB6C74240809BC6F65A502E40A8AD11C138C64240C020B248134F2E40801B62BCE6C54240008A592F864A2E40000341800CC54240E0F42D73BA3C2E40081E8A027DC24240C05DDA7058322E40D8D38041D2BF4240C017EFC7ED2F2E4080A52C431CBF4240E06DFC89CA2E2E40908D2441B8BE42408059677C5F2C2E40B0B6D4415EBD4240A0D58F4DF22B2E40B0B0524145BB4240A0AD4CF8A52E2E4080543541D4AD42408020B248132F2E40B0716F7EC3AC4240000AF5F411302E40E07954FCDFAB4240C06E2EFEB65F2E40F820CB82899742400018080264682E4078A86DC328944240C0978A8D79752E4038EACC3D2490424060129F3BC1762E40D8D38041D28F42408018213CDA802E40101286014B8E4240206C06B820832E407848BF7D1D8E4240005858703F882E40881B62BCE68D4240C0DB114E0B962E40A89509BFD48D4240602FF7C951982E400048A643A78D4240809885764E9B2E40D8031F83158D424020240C03969C2E40E00CE2033B8C4240E0CF0D4DD9A12E40607FBDC282854240E082C30B22A22E40D8A9F23D2381424000B728B341862E40F847A643A77D4240C0C3094CA76D2E40B053E57B467A4240607156444D5C2E40B86E2EFEB6774240A02975C9384E2E40505260014C754240C0A6B1BD164C2E40B0BF97C283744240A000193A76382E40B0622AFD846B4240607D5A457F302E405076FA415D66424040013274EC302E4058F5F23B4D644240207497C459312E409015E0BBCD634240A0978A8D79352E40302F3201BF60424060D026874F3A2E40E0BB783F6E5F424000A8E331033D2E4080AEEFC3415E424060809BC58B452E40A86E2EFEB65742404051BD35B0452E40508E0244C156424060DF6B088E432E40C8B5F63E5555424000F86EF3C6312E40302CF180B2534240A0D58F4DF22B2E40784B00FE2953424000931CB0AB292E4030E78BBD17534240C02634492C192E40B85626FC5257424000C87C40A0132E40B0E0F08288584240802975C9380E2E40000F45813E59424020356090F4092E4038266F8099594240C050A4FB39CD2D4040D505BCCC5C4240406552431BC82D40789FAA42035D4240604278B471BC2D4080CC07043A5D4240C038BA4A77B72D40386893C3275D424040261B0FB6A02D40A8622AFD845B4240206002B7EE8E2D40D08BDAFD2A5A4240207497C459712D4000DFA63FFB5B4240407A19C5721B2D40D87954FCDF6342408015E0BBCDEB2C405055A181586A424000B937BF61EA2C40504CDE00336B4240A0CF0D4DD9E12C4008D3A23EC96F4240A07C410B09D82C40A8622AFD84734240E04B546F0DD42C40789FAA4203754240E0AA24B20FD22C40D0CDFE40B9754240C0921CB0ABC92C4000CADFBDA378424000EB56CF49BF2C40382CF180B27B4240C02B483316B52C4020DB6B41EF7D424080FA96395DAE2C40C05626FC527F4240407497C459912C40B0ECF483BA84424000931CB0AB892C4058499D8026864240009F20B1DD7D2C40889C69C2F687424080AD4CF8A54E2C4038F6D03E568C424080116DC7D4452C40789FAA42038D4240A04D637B2D382C40D8FA5B02F08D4240200AF5F411302C40D8AC33BE2F8E4240E037A11001FF2B407848BF7D1D8E424020FA27B858E92B40E0976C3CD88C424000965D30B8DE2B40A8A78FC01F8C424080BEA08504DC2B40A8A78FC01F8C4240E005820019CA2B40B0BF97C2838C424080B950F9D7C22B40303B3602F18C4240601D71C8067A2B40000C04013294424040E2AC889A582B40D8B2B5BE4898424080C554FA09572B40B0656B7D9198424000A26131EA522B4010C11C3D7E99424080A48977804F2B40B8B915C26A9A424080035ABA824D2B40804B00FE299B424020931CB0AB492B4088A86DC3289C424020895E46B1242B40B8984A3FE1A24240806E2EFEB61F2B40002DCF83BBA3424000AD33BE2F162B405070784144A44240C0C64ACCB3022B40B8716F7EC3A442400015C78157D32A4000C11C3D7EA94240005C8FC2F5A82A40A8AD11C138AE424040AD4CF8A58E2A40903CBB7CEBB14240C0D58F4DF28B2A408881204086B2424020931CB0AB892A409015E0BBCDB34240C0FDD7B969832A40285FD04202B6424040573F36C96F2A40C053E57B46BA4240C0B5F63E55552A40A0DA6E826FBE4240207497C459512A40A877F17EDCBE4240E059677C5F4C2A4080A52C431CBF4240C0D58F4DF22B2A4080A52C431CBF42408014AE47E1FA2940B8ECF483BAC4424020295C8FC2F52940801B62BCE6C5424080C1E10511F12940888D2441B8C64240005858703FE82940909C69C2F6C74240E06ABB09BED92940C80F238447C94240E05626FC52D72940B05CA8FC6BC942408014AE47E19A294038F04E3E3DCA424020013274EC902940383E7782FDC94240206C06B82083294068F833BC59C94240802FF7C951782940D0CABDC0ACC8424060B81E85EB712940504F1F813FC84240A094490D6D602940E009A1832EC74240A0F755B95059294000DC65BFEEC642400090DB2F9F54294078A52C431CC74240604E7CB5A35029402820ED7F80C742408050A4FB394D29408821E4BCFFC74240206E15C44007294038F6D03E56D4424040573F36C9EF284000C11C3D7ED9424020D9E90775D92840889FAA4203E54240804D637B2DD82840801B62BCE6E542408000193A76D8284060FB743C66E64240A0A148F773DA2840B8A44E4013E74240E037A11001DF2840500ABABDA4E7424000D9D0CDFEE02840D8BB783F6EE74240C082C30B22E22840D809A1832EE7424020F2ECF2ADE72840E0D38041D2E74240E089592F86EA2840009D82FC6CE84240C059677C5FEC2840E00F238447E9424020321F10E8F428408860C77F81EE4240C0E4D4CE30F52840B0E9B303AEEF4240E0716F7EC3F4284028EACC3D24F04240E0989EB0C4F32840A8E0F08288F04240A06DFC89CAEE2840905182FE42F54240C0C64ACCB3022940080F45813E01434000F2ECF2AD072940A0E67283A1024340A0B5DD04DF1C2940600ABABDA407434000965D30B81E29405037177FDB0743408009DCBA9B77294008D9243FE211434020895E46B1A429408093A641D1084340C094490D6DC02940E87954FCDF034340E09BDF30D1C8294008E869C02003434000DF52CE17CB2940D8FD9C82FC02434060CAA48636D02940881EA33CF3024340E0B5F63E55D52940386211C30E034340604278B471DC29402014E97E4E034340000F45813EE92940100C040132044340A074B0FECF092A400821CB8289074340E0230C03961C2A40A8C2D84290094340A0E1934E24202A4070A2EBC20F0A434000634337FB232A40306211C30E0B4340400D36751E252A4060FEB5BC720B43400051BD35B0252A4028232E008D0C4340A018213CDA202A400021CB82890F4340C0955D30B81E2A40E0B2B5BE48104340A0BEA085041C2A40D8F71A82E3104340409885764E1B2A405873B9C150114340202DCF83BB1B2A40D8EE5701BE114340606002B7EE2E2A4028DB87BCE5164340E0C77C40A0332A40B06E2EFEB6174340C0978A8D79352A40B89B8BBFED174340A082C30B22A22A4030DEC83CF21B4340A023F3C81FA42A40002DCF83BB1B4340A0129F3BC1B62A40386552431B184340C0C98B4CC0B72A40004E2844C0174340A0B5DD04DFBC2A40D0B5F63E55154340E0E1934E24C02A40382CF180B2134340E0E1934E24C02A40804B00FE29134340E0F42D73BABC2A40B0A10DC006124340C06ABB09BEB92A40607C7C4276104340201077F52ABA2A40809C69C2F60F4340A05A99F04BBD2A40B877F17EDC0E4340E0955D30B8BE2A4010C45DBD8A0E4340E0703D0AD7C32A405831957EC20D4340C088450C3B6C2B40889FAA4203FD4240C08B868C47812B4028F6D03E56FC4240E0921CB0AB892B40D00CE2033BFC4240000341800C952B4000BEDBBC71FC4240E0F2E84658A42B405031074147FD4240000473F4F8C52B40004E2844C0FF424020AB24B20FD22B408893A641D1004340A0978A8D79D52B40E00F238447014340C0129F3BC1D62B4028266F8099014340A00F5EBBB4E12B40886308008E03434060CDE50643E52B4090423D7D0404434000AE65321C072C4000240C039604434040634337FB432C4090992842EA024340407156444D7C2C4098C2D84290014340A06E2EFEB69F2C4098C2D8429001434020C763062ABB2C408054C37E4F02434000EC6AF294BD2C40E0B837BF6102434000356090F4092D4010A0C37C79054340C023F3C81F442D40000F45813E09434020B728B341462D4030F911BF6209434000931CB0AB492D40B074B0FECF09434020F86EF3C6512D4000E869C0200B434040F86EF3C6912D40809065C1C4134340A06E2EFEB6BF2D40B09509BFD4154340C032384A5EED2D4000BEDBBC711443400015C78157F32D409015E0BBCD1343404077D84466262E40888461C0920F43408059677C5F2C2E40B8BC5642770F434060DC2A88812E2E40888461C0920F434000BFB9BF7A342E40286552431B104340A050A4FB394D2E40A8E67283A112434040A148F7739A2E4088812040861A4340A0B08D78B2032F4030ED0DBE30254340C0A6B1BD160C2F4030327381CB2543402090DB2F9F142F4008E528401426434060D026874F1A2F40D8FA5B02F02543406015E0BBCD4B2F40E0D03FC1C52243402069C537144E2F404807793D98224340806DFC89CA4E2F40D08BDAFD2A224340C0C3094CA74D2F40D873D2FBC6214340407C26FBE7492F40A83B4F3C67214340806ABB09BE392F4090C9C6832D204340000341800C352F401000000000204340C00C1D3BA82C2F4000BB9A3C651F43404021CB8289272F40082A8E03AF1E4340000D36751E252F40E0FA5B02F01D434040B950F9D7222F4038ED0DBE301D4340E0955D30B81E2F4090992842EA1A4340C06DFC89CA0E2F40D0C1FA3F8711434001030000000100000009000000C0116DC7D425284080A2EBC20FFA42404021CB8289272840D07C957CECF84240E04D637B2D1828401006820019FA4240E05FE97C78162840D0B837BF61FA4240206002B7EE0E2840801B62BCE6FD424060D367075C0F2840009700FC53FE4240001286014B1E28406828D2FD9CFE4240E037A110011F2840081286014BFE4240C0116DC7D425284080A2EBC20FFA424001030000000100000010000000E0B5F63E55B52840F8DEA63FFBF34240E0A16131EAB22840B07A32FFE8F3424040295C8FC2952840D8B5F63E55F54240607497C4599128400048A643A7F54240A091088D608B284010BB9A3C65F74240C01EA33CF38A28406037177FDBF74240E088450C3B8C284088C9C6832DF84240606002B7EE8E2840804E417E36F8424000E2934E24A02840504F1F813FF8424020B0743E3CAB2840084E2844C0F74240A0C3094CA7AD284060853FC39BF742406054FEB5BCBA284048499D8026F64240804B3B3597BB2840C8CDFE40B9F5424080D026874FBA2840B0716F7EC3F44240A085048C2EB72840080C040132F44240E0B5F63E55B52840F8DEA63FFBF342400103000000010000001A000000206552431B0828408060C77F815E424020B3B5BE4800284068FB743C665E4240404278B471FC274010C45DBD8A5E424040D9E90775F92740D8F19881CA5E4240005858703FE82740885D86FF7461424020D026874FDA2740A868ACFD9D654240C000193A76D82740F8DB65BFEE664240A0BC9179E4D727405001F73C7F684240C0737E8AE3D8274080ABAE433569424040240C0396DC2740286BD443346A424020965D30B8DE2740A8E67283A16A4240A05CA8FC6BE12740881EA33CF36A4240601A3048FAE4274038E78BBD176B4240C09BDF30D1E8274008E869C0206B4240A00C1D3BA8EC2740D082177D056B4240201286014BFE2740A853E57B466A4240E0703D0AD703284000274D83A269424080B3CEF8BE182840305FD04202664240605DC136E2192840B0E3310395654240204278B4711C2840104BE7C3B3624240202DCF83BB1B284000C11C3D7E61424040D026874F1A2840E0F71A82E36042408000193A76182840001808026460424020C87C40A0132840580ABABDA45F4240A02975C9380E28404840DAFF005F4240206552431B0828408060C77F815E4240'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('LG','LV','LVA','428','Latvia','6205','2301793','150','154','25.641','56.858','0106000020E61000000100000001030000000100000017020000D446753A901135407A6F0C01C0374C40218FE046CA0E354055F833BC59414C40A6F27684D3063540A4C519C39C4E4C40A3073E062B0A3540A73E90BC73524C40800C1D3BA80C3540A680B4FF01564C40A11342075D0E3540A19E3E027F584C40AA656B7D9110354026C632FD125F4C40D34F38BBB5103540514F1F813F604C40FE9C82FC6C1035407C6308008E634C40A301BC05121035407F87A2409F644C403946B247A80D3540F8FF71C284674C40D0D6C1C1DE0C3540D47C957CEC684C40505260014C0D35405307793D986A4C40D1CDFE40B90D3540A583F57F0E6B4C40FA9B5088800F3540F92CCF83BB6B4C40D04543C6A3103540CEDF8442046C4C40CFD90242EB113540D1915CFE436C4C40A304FD851E253540F60B76C3B66F4C40CAFACDC474393540D064FF3C0D744C407C992842EA423540CDE506431D764C40CDE847C3295B3540A7AD11C1387E4C4054C8957A165C35404E61A5828A7E4C40A20DC00644643540A2D11DC4CE824C40FF9600FC53663540CEDF844204844C40FAB48AFED0683540FF9600FC53864C4051DA1B7C616A3540D3F71A82E3884C4077BAF3C4736A3540CDE847C3298B4C4028F04E3E3D6A35402CD505BCCC8C4C40A11001875069354027BD6F7CED8F4C4050E3DEFC86693540A680B4FF019E4C40FCABC77DAB693540D009A1832E9F4C4077BAF3C4736A35404E64E60297A34C404C6DA983BC6A354025C9737D1FA44C40D34CF73AA96B35407D24253D0CA54C4074CFBA46CB6D354079AEEFC341A64C40A19E3E027F70354028F38FBE49A74C40219221C7D6733540A58636001BA84C40CFDC43C2F7763540FCE1E7BF07A94C4027840EBA847B35404C6DA983BCAA4C40ABEAE5779A983540A45016BEBEB84C40219221C7D6A33540D2C43BC093BE4C4051DA1B7C61AA3540D106600322C24C40FB230C0396AC3540787B1002F2C34C40A680B4FF01AE3540A7ECF483BAC44C4022895E46B1B43540520ABABDA4C74C4050E3DEFC86B93540D00F238447C94C40F92CCF83BBBB35402CD8463CD9C94C40FF93BF7B47C13540A96BED7DAACA4C404DD9E90775D935407AA86DC328CC4C4055BFD2F9F0DC3540F9F6AE415FCC4C40FA298E03AFE63540FCDEA63FFBCB4C40A3073E062BEA3540A54DD53DB2CB4C407B336ABE4AEE35404E64E60297CB4C407BBB253960FB3540CEDF844204CC4C40D5B2B5BE480036404F5B238271CC4C402B6C06B820033640FED5E3BED5CC4C4051BB5F05F8063640530438BD8BCD4C40FB230C03960C3640FDDB65BFEECE4C40D82E6D382C19364024473A0323D14C4001857AFA08483640520ABABDA4D74C40CAFACDC474793640F8FC304278DE4C40297B4B395F7C3640A777F17EDCDE4C4029ED0DBE30953640D1CABDC0ACE04C40FDA204FD859A3640295C8FC2F5E04C4000917EFB3A9C36407D93A641D1E04C407B9FAA42039D3640527C7C4276E04C40D63A71395E9D36400000000000E04C40A8FFACF9F19B3640D28E1B7E37DF4C40F73E5585069A36407C60C77F81DE4C40A110018750993640CDE506431DDE4C40A968ACFD9D953640D1949D7E50D94C404FCDE50643953640CEA623809BD74C4024809BC58B9536404E61A5828AD64C404F58E20165973640FDA204FD85D24C40A019C4077698364024473A0323D14C4058AA0B78999936402250FD8348D04C402B6C06B820A33640FE99417C60CB4C4079AEEFC341A636402A1DACFF73CA4C4054C8957A16AC364052465C001AC94C40D5B2B5BE48C03640A5BF97C283C44C40AAF3A8F8BFE73640A48CB80034BA4C4028F38FBE49EF3640FCA5457D92B74C40A3957B8159F13640CFDC43C2F7B64C40219221C7D6F3364055FB743C66B64C40D2C77C40A0033740D482177D05B34C40FB230C03960C3740D1949D7E50B14C4078B7B24467153740A58636001BB04C40FDA204FD851A3740240B98C0ADAF4C405055A18158223740D576137CD3AE4C402B6C06B820233740AB5FE97C78AE4C40F8359204E12A37404F22C2BF08A84C40CD7344BE4B3D37402AE44A3D0B964C40CF6A813D263E3740A489778027954C404C70EA03C93F3740FA298E03AF8E4C40F92F1004C8403740505260014C8D4C405055A18158423740A64412BD8C8C4C40FD1186014B4E374027F911BF62894C40219221C7D6533740F9BD4D7FF6874C40FB20CB82895737404E2B85402E874C40533D997FF4593740FA298E03AF864C402AE44A3D0B963740F9C08EFF027D4C4078B7B24467A53740FBB1497EC47B4C40CC5D4BC807A93740AA622AFD847B4C40CDE847C329AB374026FF93BF7B7B4C40A77A32FFE8C33740787B1002F27B4C40D82E6D382CC937407B2DE8BD317C4C40FCABC77DABD93740501C40BFEF7D4C4023861DC6A4DF3740D2C43BC0937E4C4076C075C58CF437407D5D86FF74814C40F7C9518028FC37402635B401D8824C40AAF3A8F8BF27384050E09D7C7A8C4C40F54718062C393840A19E3E027F904C40D1CDFE40B95D3840FD14C781579B4C4023861DC6A45F3840CEDF8442049C4C40A583F57F0E633840793C2D3F709D4C40D449B6BA9C663840A5BC5642779F4C40D63730B9516838407E18213CDAA04C40228C9FC6BD693840F9BA0CFFE9A24C40A774B0FECF69384052431B800DA44C4052465C001A69384027F6D03E56AC4C407A39ECBE63683840D097DEFE5CAE4C40240ED940BA5C38405055A18158CA4C407D24253D0C553840A3957B8159D94C4027F6D03E56543840508BC1C3B4D94C40218FE046CA4E38407A724D81CCDC4C40D1CDFE40B94D38407B698A00A7DD4C4054C8957A164C38407E5704FF5BDF4C40A3073E062B4A3840FC1A498270E54C4027F911BF62493840A4C2D84290E94C40228C9FC6BD493840D0D03FC1C5EA4C40FE99417C604B3840FED5E3BED5EC4C40E2E47E87A2503840B8E68EFE97EF4C40A583F57F0E5338404F58E20165EF4C4077BD3445805F3840D28E1B7E37EF4C4054C554FA0967384051DD5CFC6DEF4C404E64E602976B384027BD6F7CEDEF4C409F1C0588826D3840F702B34291F04C40F6419605136F384027F911BF62F14C40CCEB884336703840FAF02C4146F24C40221ADD41EC70384079B130444EF34C404E5E64027E713840FBB1497EC4F34C404A7CEE04FB733840D15B3CBCE7F44C407E1EA33CF38A3840A774B0FECFF94C40D1CDFE40B98D3840A48CB80034FA4C40FA9B5088808F38407E54C37E4FFA4C40A110018750B93840AA622AFD84FB4C4052431B800D0439407D24253D0C054D40A774B0FECF09394026FC523F6F064D40FCA5457D920F3940D0D38041D2074D40CFD90242EB113940A8380EBC5A084D40D540F33977173940A8AAD0402C094D40D158FB3BDB1F394052103CBEBD094D40D2C77C40A0233940A774B0FECF094D40228C9FC6BD293940508BC1C3B4094D4027840EBA842B3940D3C1FA3F87094D40A680B4FF012E39402AE109BDFE084D407CB5A33847313940CEA623809B074D402B6C06B82033394055FB743C66064D407B2DE8BD313439407B9FAA4203054D407D24253D0C3539404E64E60297034D40211D1EC2F835394029266F8099014D4054C554FA09373940272F3201BF004D40A110018750393940520ABABDA4FF4C4027840EBA843B394026C632FD12FF4C40A514747B493F39402541B8020AFF4C40D82E6D382C493940FC17080264004D40FE99417C604B3940295C8FC2F5004D402CD505BCCC4C3940A774B0FECF014D4055BFD2F9F04C3940A6B915C26A024D40D0D6C1C1DE4C394054FEB5BC72034D4051BEA085044C3940D0D6C1C1DE044D40257A19C5724B3940505260014C054D40533D997FF44939402AE44A3D0B064D4057B08D78B2433940D158FB3BDB074D40FD14C781574339407E18213CDA084D4027F6D03E564439402CD8463CD9094D40D13FC1C58A4639402A1DACFF730A4D40D3C1FA3F87493940D0D03FC1C50A4D40AA622AFD844B3940A2D11DC4CE0A4D402A7288B8394D3940A7E67283A10A4D407E8D2441B84E3940A6B915C26A0A4D40A8FFACF9F16B394029232E008D044D4023861DC6A46F3940FBB1497EC4034D404D672783A370394054FEB5BC72034D40CFD90242EB713940A96BED7DAA024D40A583F57F0E733940272F3201BF004D40D064FF3C0D74394027BD6F7CEDFF4C40A7052FFA0A76394028F38FBE49FF4C40D731AEB8389E3940530438BD8BF54C4051DD5CFC6D9F3940505260014CF54C40276893C327CD3940D576137CD3EE4C40CDE506431DD6394052499D8026EE4C407BA2EBC20FE23940530438BD8BED4C40D53DB2B96AF23940505260014CED4C40A67D737FF5083A4027F911BF62E94C4027F6D03E56343A40A67D737FF5D84C40D6AC33BE2F463A407B6649809AD04C4058AA0B7899493A40D28E1B7E37CF4C40FB230C03964C3A4079AEEFC341CE4C404FCAA48636503A40FC1A498270CD4C407C992842EA823A407A36AB3E57C34C402AE44A3D0B863A407E1EA33CF3C24C40533D997FF4893A402635B401D8C24C404ED026874F9A3A4079B130444EC34C40A5F5B704E09B3A4054FEB5BC72C34C40D0D6C1C1DE9C3A40FBB1497EC4C34C409F1C0588829D3A40D00CE2033BC44C40FBAE08FEB79E3A405531957EC2C54C4078B471C45AA03A404E61A5828AC64C409F1F46088FA23A407C2AA73D25C74C4025085740A1B23A407E8AE3C0ABC94C4077BD344580DF3A40A3CB9BC3B5D04C402975C93846E23A4052465C001AD14C40A4FB3905F9E53A4024473A0323D14C40F9BD4D7FF6E73A40FCE1E7BF07D14C40F450DB8651F83A404C70EA03C9CF4C40D061BEBC00FF3A407C2AA73D25CF4C40A8716F7EC3043B4079AEEFC341CE4C402A6F47382D083B40A73B4F3C67CD4C407C2766BD180A3B40A8716F7EC3CC4C402A7288B8390D3B4079B130444ECB4C4055C2137AFD113B4000CADFBDA3C84C40FCA886FD9E143B4029EACC3D24C84C40FF9600FC53163B40F9BD4D7FF6C74C40D4BB783F6E4F3B40CEDF844204C44C40B62E35423F5F3B4087C3D2C08FC44C40A9F6E978CC6C3B402444F98216C44C40A583F57F0E733B40FCDEA63FFBC34C4075CC79C6BE783B40CEDF844204C44C4054C8957A168C3B4051888043A8C44C407E1EA33CF38A3B40D009A1832EBF4C407F129F3BC1863B4050E3DEFC86B94C40D13FC1C58A863B40CEE2C5C210B94C40D13FC1C58A863B402502D53F88B84C4051BB5F05F8863B407787140324B84C40A774B0FECF893B407C2AA73D25B74C407D21E4BCFF8F3B4028B7ED7BD4B54C4059A7CAF78C943B40FAEDEBC039B54C4052D158FB3B9B3B40A64412BD8CB44C40F838D384EDAF3B404D672783A3B04C40D734EF3845D33B407D5D86FF74A94C4027F911BF62D93B4029EACC3D24A84C4051DA1B7C61DA3B40D0D38041D2A74C404F5B238271DC3B40FA298E03AFA64C40250516C094DD3B40A6B6D4415EA54C4056B60F79CBDD3B40D0D6C1C1DEA44C40A489778027DD3B4029266F8099A14C40533D997FF4D93B404F22C2BF08984C40D82E6D382CD93B40FD1186014B964C40D1CABDC0ACD83B40A3CEDC43C2954C40FF9600FC53C63B40F9F36DC152874C404FE960FD9FB33B404E25034015754C40CDE847C329BB3B40A38FF980406F4C40514CDE0033C33B40D0D38041D26F4C4050C763062ACB3B40A8380EBC5A704C4058AD4CF8A5CE3B40A19E3E027F704C40F92F1004C8D03B40FE9C82FC6C704C40AB5FE97C78D63B40D38558FD11704C40267156444DDC3B40D28E1B7E376F4C4051DD5CFC6DEF3B40FDD8243FE2694C4078B471C45AF03B40D3C1FA3F87694C40F92F1004C8F03B4052465C001A694C40F92F1004C8F03B40AA656B7D91684C40D061BEBC00EF3B404E61A5828A664C40A11342075DEE3B40FCE4284014664C40240ED940BAEC3B40505260014C654C40F8359204E1EA3B407F87A2409F644C40D446753A90F13B4022E17B7F835C4C40D53DB2B96A023C40D2FD9C82FC524C402A7288B8391D3C4028F04E3E3D424C40F8325184D4253C4075931804563C4C40218FE046CA2E3C40CEDF844204344C40D34CF73AA93B3C407D24253D0C254C40A3923A014D3C3C4025C9737D1F244C40D0D6C1C1DE3C3C407A6CCB80B3224C40A9F6E978CC3C3C40FA264D83A2214C40209BE447FC323C40240B98C0AD174C40CFD90242EB313C40FBAE08FEB7164C40CBF44BC45B2F3C40D15B3CBCE7144C404FE61F7D932E3C40A64412BD8C144C40465ED6C4022B3C408AAE0B3F38134C4027F911BF62293C405116BEBED6134C40FE2AC0779B273C4050E09D7C7A144C402577D84466263C40F50EB743C3144C40A9F92AF9D8213C40D4B5F63E55154C407D21E4BCFF1F3C40FD9FC37C79154C407B336ABE4A1E3C40A73B4F3C67154C402098A3C7EFED3B407C60C77F810E4C4055BFD2F9F0EC3B40234A7B832F0E4C40A708707A17EB3B40FED5E3BED50C4C40A96BED7DAAEA3B40A3923A014D0C4C40CFDC43C2F7E63B4029266F8099094C4022895E46B1E43B407A39ECBE63084C407F15E0BBCDCB3B4029EACC3D24004C40A298BC0166B63B4051DA1B7C61FA4B40240B98C0ADA73B40FDDB65BFEEF64B404D6A6803B0A53B40FD1186014BF64B40A20DC00644A43B407A724D81CCF44B40287E8CB96BA13B40A4C519C39CEE4B40257497C459A13B40530438BD8BED4B402975C93846A23B40520DFB3DB1EC4B402975C93846A23B407AA86DC328EC4B4055C2137AFDA13B404E64E60297EB4B40D446753A90A13B40A583F57F0EEB4B40FBAE08FEB79E3B40272F3201BFE84B40F73E5585069A3B40530438BD8BE54B40560F98874C993B40C8D3F20357E54B4028F38FBE498F3B407B9FAA4203E54B407C9C69C2F6873B40AA9ECC3FFAE44B40FCA5457D924F3B407E5704FF5BE74B4053CE177B2F363B40508BC1C3B4E94B40F9BD4D7FF6273B4027F6D03E56EC4B4079AEEFC341263B40F9F6AE415FEC4B40793C2D3F70FD3A402635B401D8EA4B4079B130444EFB3A4028F04E3E3DEA4B40A019C40776E83A40A3C85A43A9E34B40A8FC6B79E5E63A4028BA2EFCE0E24B4026FF93BF7BE33A40286552431BE04B40AAF06778B3E23A4026C632FD12DF4B40008BFCFA21E23A40A4C519C39CDE4B4029EACC3D24E03A4052D7DAFB54DD4B407B9FAA4203DD3A40FBB1497EC4DB4B4058AA0B7899D93A404F1F813FFCDA4B4052431B800DC43A407D21E4BCFFD74B40218FE046CABE3A40A359D93EE4D74B4079B130444EBB3A40FBEAAA402DD84B40022A1C412AB13A408236397CD2D94B4052D158FB3BAB3A405055A18158DA4B4027F911BF62A93A405055A18158DA4B40FA298E03AFA63A40533D997FF4D94B40008BFCFA21A23A40221ADD41ECD84B407AABAE4335A13A407B6649809AD84B40FBAE08FEB79E3A40A741D13C80D74B40E59CD843FB9C3A401C9947FE60D64B404F58E20165973A4055FB743C66D64B40D734EF3845933A404E61A5828AD64B4001857AFA08883A407C2AA73D25D74B40D0D03FC1C5823A407842AF3F89D74B40FCA5457D927F3A40D158FB3BDBD74B4029EACC3D24603A40D09A1F7F69DB4B40F92CCF83BB5B3A40CEDF844204DC4B40FA298E03AF563A4027C0B0FCF9DC4B404FCAA48636503A40FA298E03AFDE4B40AB5FE97C78463A40A774B0FECFE14B40CE5147C7D5443A40FC1D8A027DE24B4082FDD7B969433A40234DBC033CE34B40A6EF3504C7413A4001BEDBBC71E44B409F1C0588823D3A40A7B393C151E84B402A7288B8393D3A407D93A641D1E84B40FAB48AFED0383A40F8FF71C284EB4B40211D1EC2F8353A407B9FAA4203ED4B404FE960FD9F333A40FCE4284014EE4B407E18213CDA303A402541B8020AEF4B40CD57C9C7EE0E3A402123A0C211F84B408126C286A7033A4061527C7C42FA4B40F641960513FF39402635B401D8FA4B407AABAE4335F139407D24253D0CFD4B4076C6F7C5A5EE3940CFA0A17F82FD4B40F644D7851FE4394027BD6F7CEDFF4B4054C554FA09B73940F8FF71C2840B4C40A60EF27A30B539407AA86DC3280C4C4050E09D7C7AB43940A64412BD8C0C4C40209BE447FCB2394028B7ED7BD40D4C40D53DB2B96AB23940508E0244C10E4C4029ED0DBE30953940FE99417C60134C40A680B4FF016E3940505260014C154C40219221C7D65339407B698A00A7154C40514CDE00334339407C2AA73D25174C40A777F17EDC2E3940A5BC564277174C40CC5D4BC807293940CEA623809B174C4052D7DAFB54253940D0D38041D2174C402975C93846223940FBEAAA402D184C40CDE847C3291B39407B30293E3E194C407D93A641D118394052103CBEBD194C40A8716F7EC31439407E1EA33CF31A4C4081069B3A8F123940D064FF3C0D1C4C40000000000000394028B7ED7BD4254C40F54A598638FE38402541B8020A274C407BBB253960FB3840D1066003222A4C40A019C40776F838407E5182FE422D4C40D15B3CBCE7F43840A67D737FF5304C407AABAE4335F138402444F98216344C4054C8957A16EC384024D5777E51384C4051DA1B7C61EA3840787E5182FE384C40F9BD4D7FF6E7384050E3DEFC86394C40FF9600FC53E63840FCABC77DAB394C407B2DE8BD31E43840508BC1C3B4394C4053CBD6FA22E13840F8F9EFC16B394C40A38FF98040A73840D576137CD32E4C404ED026874F9A3840D1066003222A4C40A304FD851E9538407D21E4BCFF274C40A301BC051290384029ED0DBE30254C40CD57C9C7EE8E3840543A58FFE7244C40F8359204E17A3840FDA204FD85224C40F54718062C793840A73E90BC73224C40A583F57F0E733840FDA204FD85224C402098A3C7EF6D3840F9BA0CFFE9224C40A708707A176B38407A36AB3E57234C40D540F339776738402444F98216244C40A702EE79FE60384028B7ED7BD4254C40D63A71395E5D3840A4C519C39C264C40FC17080264583840FCA5457D92274C40CFDC43C2F75638404C70EA03C9274C407D24253D0C5538407A6F0C01C0274C4055C2137AFD513840A5BC564277274C40037976F9D64338407D24253D0C254C40D0D6C1C1DE2C3840508BC1C3B4214C40A774B0FECF293840AB5CA8FC6B214C40F8325184D42538407D5D86FF74214C40D0D03FC1C5223840A774B0FECF214C40A583F57F0E13384052431B800D244C40D34F38BBB510384029232E008D244C40008BFCFA21023840552E54FEB5284C4074CFBA46CBFD3740D1949D7E50294C40F9BA0CFFE9F23740FDA204FD852A4C4023861DC6A4DF374022179CC1DF2B4C404EEFE2FDB8BD3740FCE42840142E4C40D05E7D3CF4B9374079AEEFC3412E4C407F15E0BBCD9B3740A4C519C39C2E4C407D93A641D1983740D097DEFE5C2E4C40CF488446B0953740527FBDC2822D4C407B2DE8BD31943740520DFB3DB12C4C40AB5CA8FC6B913740A54DD53DB22B4C40A20A7F86378F3740CDE847C3292B4C407AA86DC3288C37402635B401D82A4C40AB5FE97C78863740D0D03FC1C52A4C4027F6D03E56743740A77A32FFE82B4C40CEE2C5C2107137407B2DE8BD312C4C4052499D80265E37407E8D2441B82E4C40F92CCF83BB5B3740A38FF980402F4C407D24253D0C553740A8380EBC5A304C40CFD90242EB513740D1CABDC0AC304C407F15E0BBCD4B3740A45016BEBE304C4076C6F7C5A52E3740FA298E03AF2E4C407F15E0BBCD2B3740FF9600FC532E4C40F8359204E12A3740D47FD6FCF82D4C40A4FE7A85052B3740FD9FC37C792D4C407F15E0BBCD2B3740D1031F83152D4C40793C2D3F702D3740253B3602F12C4C4026FC523F6F2E3740CEA96400A82C4C4052499D80262E37404D2EC6C03A2C4C404D6A6803B0253740D00F238447294C40FF93BF7B47213740FBEAAA402D284C4000917EFB3A1C3740A38FF98040274C40CF4BC5C6BC1A37407AA52C431C274C40ABEAE5779A1837407C2AA73D25274C40AB5CA8FC6B11374029EACC3D24284C4056B60F79CB0D3740D3F71A82E3284C4058AA0B78990937407BA2EBC20F2A4C4001857AFA08083740D0D03FC1C52A4C407F87A2409F043740240ED940BA2C4C40FD14C78157033740527FBDC2822D4C40008BFCFA21023740A777F17EDC2E4C404C70EA03C9FF364080457EFD10314C40CF6A813D26FE36407E54C37E4F324C407845F0BF95FC3640D482177D05334C40FCA886FD9EF43640527FBDC282354C40D53DB2B96AF236402AE44A3D0B364C40A702EE79FEF0364079AEEFC341364C40F641960513EF3640FF9600FC53364C40250516C094ED3640234A7B832F364C404C6DA983BCEA364028B7ED7BD4354C40F9BA0CFFE9E23640A5BF97C283344C4000917EFB3ADC364028BA2EFCE0324C40ABEAE5779AD83640D3C1FA3F87314C402577D84466D63640A67D737FF5304C407E9065C1C4D336402502D53F88304C40A702EE79FEB036407B698A00A72D4C407F15E0BBCDAB36407E1B62BCE62D4C40A110018750A9364055FB743C662E4C4029780AB952A73640D061BEBC002F4C40A8716F7EC3A436404F22C2BF08304C40D0D03FC1C5A23640D1CABDC0AC304C40F92F1004C8A03640D00F238447314C40FCA5457D929F3640D3C1FA3F87314C40800C1D3BA89C3640CFD90242EB314C4079AEEFC341963640FDA204FD85324C40D1CDFE40B98D36407F4B00FE29334C40543A58FFE7843640FBB1497EC4334C40A514747B497F3640CEDF844204344C4052D158FB3B7B3640CEDF844204344C40A20A7F86374F3640A54DD53DB2334C40FB20CB8289273640FD1186014B364C4075C93846B2233640A7AD11C138364C407AABAE4335113640FFCC203EB0354C40D44334BA830C3640CCEEC9C342354C40CE548847E20936404B732B84D5344C40AAF3A8F8BFE73540A38FF980402F4C40A3923A014DBC354027F911BF62294C4051C1E1051191354027327381CB254C4025085740A1723540D158FB3BDB1F4C409F1C0588826D3540CFDC43C2F71E4C40CEDF8442046C354051137D3ECA1E4C407A39ECBE63683540A54A94BDA51E4C407B2DE8BD31643540FA298E03AF1E4C409F1F46088F623540D576137CD31E4C40FE9C82FC6C603540A777F17EDC1E4C404F5B2382715C3540D576137CD31E4C40CF4BC5C6BC5A3540FBAE08FEB71E4C402502D53F8858354052499D80261E4C40AC53E57B46423540A777F17EDC164C404FE61F7D933E3540530438BD8B154C402A7288B8393D3540F50EB743C3144C4054C8957A163C35407BA2EBC20F124C4022179CC1DF3B35407A6F0C01C00F4C40A0A4C002983A3540D1CDFE40B90D4C40F54718062C393540A3923A014D0C4C40D0D38041D2373540F8FF71C2840B4C404D6A6803B03535407E1EA33CF30A4C40CBF78C44683435404C6DA983BC0A4C40793F6EBF7C323540A96BED7DAA0A4C4024809BC58B25354024D236FE440B4C40A86E2EFEB61F3540514CDE00330B4C40A5F5B704E01B35407784D382170B4C40A6F27684D3163540D0D03FC1C50A4C40A777F17EDC0E3540D28BDAFD2A0A4C409AB1683A3B0D3540DE57E542E5094C40A5F5B704E00B3540D47FD6FCF80D4C40D925AAB7060A354024D5777E51104C40D449B6BA9C0635407A008BFCFA134C40CE5147C7D5043540FAEDEBC039154C40FA264D83A20135402829B000A6164C40AA656B7D91003540FDDB65BFEE164C40A489778027FD344024D5777E51184C40FCABC77DABF93440793C2D3F701D4C40FAB48AFED0F83440A5BC5642771F4C40F9BD4D7FF6F7344000C45DBD8A2E4C402499D53BDCFE344080457EFD10414C40F838D384EDFF344055F833BC59414C40FE0B0401320435405473B9C150414C407E1B62BCE60535407AABAE4335414C40AC5626FC52073540FCE1E7BF07414C40286552431B08354000CADFBDA3404C40FE99417C600B3540A96BED7DAA3A4C40D446753A901135407A6F0C01C0374C40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('BO','BY','BLR','112','Belarus','20748','9795287','150','151','28.047','53.54','0106000020E610000001000000010300000001000000E4030000E59CD843FB9C3A401C9947FE60D64B40FBAE08FEB79E3A40A741D13C80D74B407AABAE4335A13A407B6649809AD84B40008BFCFA21A23A40221ADD41ECD84B40FA298E03AFA63A40533D997FF4D94B4027F911BF62A93A405055A18158DA4B4052D158FB3BAB3A405055A18158DA4B40022A1C412AB13A408236397CD2D94B4079B130444EBB3A40FBEAAA402DD84B40218FE046CABE3A40A359D93EE4D74B4052431B800DC43A407D21E4BCFFD74B4058AA0B7899D93A404F1F813FFCDA4B407B9FAA4203DD3A40FBB1497EC4DB4B4029EACC3D24E03A4052D7DAFB54DD4B40008BFCFA21E23A40A4C519C39CDE4B40AAF06778B3E23A4026C632FD12DF4B4026FF93BF7BE33A40286552431BE04B40A8FC6B79E5E63A4028BA2EFCE0E24B40A019C40776E83A40A3C85A43A9E34B4079B130444EFB3A4028F04E3E3DEA4B40793C2D3F70FD3A402635B401D8EA4B4079AEEFC341263B40F9F6AE415FEC4B40F9BD4D7FF6273B4027F6D03E56EC4B4053CE177B2F363B40508BC1C3B4E94B40FCA5457D924F3B407E5704FF5BE74B407C9C69C2F6873B40AA9ECC3FFAE44B4028F38FBE498F3B407B9FAA4203E54B40560F98874C993B40C8D3F20357E54B40F73E5585069A3B40530438BD8BE54B40FBAE08FEB79E3B40272F3201BFE84B40D446753A90A13B40A583F57F0EEB4B4055C2137AFDA13B404E64E60297EB4B402975C93846A23B407AA86DC328EC4B402975C93846A23B40520DFB3DB1EC4B40257497C459A13B40530438BD8BED4B40287E8CB96BA13B40A4C519C39CEE4B40A20DC00644A43B407A724D81CCF44B404D6A6803B0A53B40FD1186014BF64B40240B98C0ADA73B40FDDB65BFEEF64B40A298BC0166B63B4051DA1B7C61FA4B407F15E0BBCDCB3B4029EACC3D24004C4022895E46B1E43B407A39ECBE63084C40CFDC43C2F7E63B4029266F8099094C40A96BED7DAAEA3B40A3923A014D0C4C40A708707A17EB3B40FED5E3BED50C4C4055BFD2F9F0EC3B40234A7B832F0E4C402098A3C7EFED3B407C60C77F810E4C407B336ABE4A1E3C40A73B4F3C67154C407D21E4BCFF1F3C40FD9FC37C79154C40A9F92AF9D8213C40D4B5F63E55154C402577D84466263C40F50EB743C3144C40FE2AC0779B273C4050E09D7C7A144C4027F911BF62293C405116BEBED6134C40465ED6C4022B3C408AAE0B3F38134C40CDE847C3292B3C40D482177D05134C4051DD5CFC6D2F3C40D1949D7E50114C4078B471C45A303C40787E5182FE104C4031074147AB4E3C40DF4E22C2BF064C407D21E4BCFF4F3C4055FB743C66064C4054C554FA09573C404E61A5828A064C40D3C1FA3F87593C40D061BEBC00074C40FDA204FD855A3C4028F38FBE49074C4071AE6186C65B3C408D9944BDE0074C40A9F6E978CC5C3C40A8E0F08288084C4052499D80265E3C407BA2EBC20F0A4C407E18213CDA603C407F15E0BBCD0B4C40A9F92AF9D8613C4025C9737D1F0C4C40514CDE0033633C40A3923A014D0C4C40D4B5F63E55853C40FD9FC37C790D4C4052465C001A893C40FC1A4982700D4C40A4897780279D3C40FED5E3BED50C4C40F92F1004C8A03C40FB230C03960C4C4078B7B24467A53C40FCDEA63FFB0B4C404F58E20165A73C40FE99417C600B4C40793F6EBF7CB23C40543A58FFE7044C40FBB1497EC4B33C4025C9737D1F044C40FCA886FD9EB43C40A7B0524145034C407D24253D0CB53C407E54C37E4F024C40FCA886FD9EB43C40D1CABDC0AC004C407D24253D0CB53C40A86E2EFEB6FF4B40CCEEC9C342B53C40A38FF98040FF4B40CE70033E3FB83C40F50EB743C3FC4B40C18BBE8234BB3C40F3AB394030FB4B4073D87DC7F0BC3C40A96BED7DAAFA4B4051C1E10511C13C407C2766BD18FA4B4029ED0DBE30D53C407B6649809AF84B407D93A641D1D83C404D672783A3F84B4058AA0B7899D93C407903CC7C07F94B402502D53F88D83C4079758E01D9F94B40FC17080264D83C407E54C37E4FFA4B40D1CABDC0ACD83C407C992842EAFA4B4029B16B7BBBD93C40F5A276BF0AFC4B40297B4B395FDC3C40A35C1ABFF0FC4B40D2C43BC093DE3C40CFA0A17F82FD4B40D446753A90013D40A583F57F0E034C40A968ACFD9D053D40D2C77C40A0034C40A8E0F08288083D40A77A32FFE8034C40A20A7F86370F3D407B2DE8BD31044C40D2C77C40A0233D40A2D11DC4CE024C4054C8957A162C3D40253E7782FD014C407F129F3BC1663D40A583F57F0EFB4B4050E3DEFC86693D405307793D98FA4B40D0D6C1C1DE6C3D4052103CBEBDF94B40A583F57F0E733D40D4BB783F6EF74B40F73B1405FA743D40FD1186014BF64B40FA298E03AF763D404E25034015F54B40A8FC6B79E5763D40FCA886FD9EF44B4079AEEFC341763D40D1915CFE43F44B407CB5A33847713D40D064FF3C0DF44B40FE99417C606B3D407C6308008EF34B40CC5D4BC807693D40A583F57F0EF34B402A6F47382D683D40A96BED7DAAF24B40FB20CB8289673D4028F04E3E3DF24B40297B4B395F5C3D40FA298E03AFE64B40F92CCF83BB5B3D40530438BD8BE54B40A8FFACF9F15B3D407D24253D0CE54B40F6419605135F3D4025085740A1E24B40CEE2C5C210613D4001C11C3D7EE14B40D0D03FC1C5623D407D93A641D1E04B4076C075C58C643D407EC9C6832DE04B40268DD13AAA7A3D40221ADD41ECD84B40D0D6C1C1DE7C3D407A39ECBE63D84B4026FC523F6F7E3D40FBEAAA402DD84B40A77A32FFE8833D40CCEB884336D84B407F129F3BC1863D40A19E3E027FD84B40FA980F08748A3D40FDD8243FE2D94B401F9E25C808A83D40533D997FF4E14B402A6F47382DE83D40A3923A014DEC4B40ABED26F8A6ED3D407B9FAA4203ED4B402975C93846F23D40A6B6D4415EED4B4094DE37BEF6F83D407427D87F9DED4B404A79AD84EE3E3E40A6B6D4415EED4B40D540F33977773E407AA52C431CE74B40F4531C075E7D3E4055FB743C66E64B407B336ABE4A7E3E4052499D8026E64B4077BAF3C4739A3E40CCEEC9C342DD4B40A9F6E978CC9C3E407B2DE8BD31DC4B40FC1A4982709D3E405116BEBED6DB4B4055BFD2F9F09C3E40A48CB80034DA4B40AAF3A8F8BFA73E40A64412BD8CD44B40AA656B7D91C03E40CEA96400A8CC4B40800F5EBBB4C13E40F9F6AE415FCC4B40CE5147C7D5C43E40FCDEA63FFBCB4B40FC17080264C83E40CEDF844204CC4B40257A19C572CB3E404D2EC6C03ACC4B40CDE506431DD63E4055FB743C66CE4B40D1CABDC0ACD83E4051137D3ECACE4B400188BB7A15DD3E404E2B85402ECF4B40247D5A457FE03E40A38FF98040CF4B40FCA886FD9EE43E4026C632FD12CF4B40CC5D4BC807E93E40AB5FE97C78CE4B4052D158FB3BEB3E407D96E7C1DDCD4B40A304FD851EED3E407EC6850321CD4B4052499D8026EE3E40533D997FF4C94B404D672783A3F03E40A5BC564277BF4B40D34F38BBB5F03E40FAEDEBC039B54B40A19E3E027FF03E40FBE769C020B34B407D21E4BCFFEF3E4025085740A1B24B409F1C058882ED3E404E5E64027EB14B4077BAF3C473EA3E40F702B34291B04B407B30293E3EE93E40A8380EBC5AB04B4027F6D03E56E43E40FBEAAA402DB04B40209BE447FCE23E407D21E4BCFFAF4B404E64E60297DB3E407E5182FE42AD4B40CE5147C7D5D43E4028F04E3E3DAA4B40FF93BF7B47D13E40A58636001BA84B40F92F1004C8D03E40CEA623809BA74B404FCAA48636D03E404E61A5828AA64B40D5B2B5BE48D03E40530438BD8BA54B40D04543C6A3D03E40D388997D1EA54B40A9F92AF9D8D13E4027F6D03E56A44B40A774B0FECFE93E40253E7782FD994B407AA86DC328EC3E40FA7E6ABC74994B4027874F3A91F03E40FAB48AFED0984B40D0D03FC1C5F23E40CE70033E3F984B4051DA1B7C61FA3E4026FF93BF7B934B402BDB87BCE5063F40D28E1B7E37874B40A7E9B303AE073F405376FA415D864B408109DCBA9B073F40530438BD8B854B40266E15C440073F40253B3602F1844B4079AEEFC341063F40787B1002F2834B40FD304278B4F13E40A3C85A43A97B4B404C70EA03C9EF3E4029E78BBD177B4B402383DC4598EA3E405055A181587A4B402577D84466E63E40FDD8243FE2794B40D63A71395EDD3E407B30293E3E794B407F129F3BC1D63E40FCE4284014764B404F5B238271CC3E407B9FAA42036D4B40FA980F0874CA3E407E1EA33CF36A4B408200193A76C83E40CCEB884336684B40A7E9B303AEC73E40295FD04202664B4001857AFA08C83E40A8E3310395654B40A110018750C93E40D4B5F63E55654B40F73B1405FAD43E407B2DE8BD31644B40A58636001BD83E407F15E0BBCD634B4078B471C45AE03E40A73E90BC73624B40FE99417C60EB3E407EC9C6832D604B40FF93BF7B47013F4029E78BBD175B4B40514CDE0033033F40A73E90BC735A4B4051DA1B7C611A3F4025085740A1524B407D24253D0C253F40FDA204FD854A4B40800F5EBBB4213F40FCE1E7BF07494B40D44334BA831C3F408048BF7D1D464B4021956247E3183F4052431B800D444B4053CE177B2F163F40FAF02C4146424B4029ED0DBE30153F40FE0E45813E414B40A304FD851E153F40552E54FEB5404B40A968ACFD9D153F40D0D38041D23F4B4053CE177B2F163F4051DD5CFC6D3F4B40AAF3A8F8BF173F40A777F17EDC3E4B40FE99417C601B3F40CDE506431D3E4B40287E8CB96B213F40CCEEC9C3423D4B40F1F3DF83D7323F40E8BD3104003B4B4075CC79C6BE383F407E1EA33CF33A4B40FDA204FD853A3F40A2D11DC4CE3A4B407BBB2539603B3F40A73E90BC733A4B40CF4E0647C94F3F40543A58FFE72C4B4029EACC3D24503F4050E09D7C7A2C4B407D21E4BCFF4F3F40787B1002F22B4B40FCA5457D924F3F40AB5CA8FC6B294B404ED367075C4F3F40FDDB65BFEE264B40FCA5457D924F3F40D47FD6FCF8254B40D2C77C40A0533F40240B98C0AD1F4B4027F6D03E56543F4051137D3ECA1E4B40543A58FFE7543F4055FB743C661E4B40D6AC33BE2F863F4079B130444E134B4079B130444E8B3F405055A18158124B4055BFD2F9F0AC3F407B698A00A70D4B40FE2AC0779BB73F40527FBDC2820D4B407DB262B83ABC3F40D1CDFE40B90D4B400000000000C03F40A968ACFD9D0D4B400282397AFCC23F40FAEDEBC0390D4B40A58636001BD83F40514F1F813F084B407D93A641D1D83F407E5704FF5B074B409F1C058882DD3F40F92F1004C8004B40257A19C572DB3F4025C9737D1FFC4A407B2DE8BD31D43F407D5D86FF74F14A40A301BC0512D03F4079AEEFC341EE4A40D2C43BC093CE3F40FC1A498270ED4A40A774B0FECFC93F40FB230C0396EC4A407D93A641D1C83F40D1915CFE43EC4A4050C422861DC63F407C2766BD18EA4A401DC9E53FA4C33F40950B957F2DE74A401DC9E53FA4C33F40C98E8D40BCE64A40FA264D83A2E13F40A3C85A43A9E34A4052D7DAFB54E53F40F8FF71C284E34A40CFDC43C2F7E63F407C6308008EE34A4077BD344580EF3F407B9FAA4203E54A404EECA17DACF83F40D6AC33BE2FE64A40F54A598638FE3F40FBAE08FEB7E64A40F9F36DC1520F4040A67D737FF5E84A40D28BDAFD2A2A4040A4C2D84290E14A40A774B0FECF39404027C0B0FCF9DC4A4029E78BBD173B404022E17B7F83DC4A40FD9FC37C793D404054FEB5BC72DB4A407C60C77F813E404028BA2EFCE0DA4A407E18213CDA404040FAB48AFED0D84A405473B9C1504140407D21E4BCFFD74A4055F833BC59414040A741D13C80D74A40A8AAD0402C414040FDDB65BFEED64A405401F73C7F4040402AE44A3D0BD64A4079AEEFC3413E40407D24253D0CD54A40F60B76C3B6374040D09A1F7F69D34A40A73B4F3C673540407F4B00FE29D34A404E25034015354040FFCF61BEBCD24A40D388997D1E35404028F04E3E3DD24A40FCE4284014364040A968ACFD9DCD4A40D2C43BC093364040A3923A014DCC4A407787140324384040533D997FF4C94A40FAB48AFED03840407AABAE4335C94A40253E7782FD394040FBEAAA402DC84A40CEDF8442043C4040D061BEBC00C74A40CCEEC9C3423D40407C60C77F81C64A4051137D3ECA4E4040FED2A23EC9BF4A407D21E4BCFF4F40407EC9C6832DC04A40FA264D83A2514040514F1F813FC04A40FDA204FD855240407EC9C6832DC04A404F5B2382715440407C9C69C2F6BF4A4028B7ED7BD4554040520ABABDA4BF4A40F8FC3042785E4040D2C77C40A0BB4A40A777F17EDC5E4040A7B0524145BB4A407978CF81E55E4040A2D11DC4CEBA4A40FA298E03AF5E40407AABAE4335B94A40B2101D02475E404092E7FA3E1CB84A40240ED940BA5C40408048BF7D1DAE4A40FF9600FC534E4040D38558FD11A84A40FDD8243FE2394040A3923A014D9C4A4024D5777E51384040FFCF61BEBC9A4A405340DAFF00374040508BC1C3B4994A40F9C08EFF02354040A19E3E027F984A4079AEEFC3412640405019FF3EE3904A407845F0BF951C4040527FBDC2828D4A4028BA2EFCE01240404E64E602978B4A404E5E64027E1140407A36AB3E578B4A404E2B85402E0F4040CDE847C3298B4A40527FBDC2820D4040CDE847C3298B4A40CCEEC9C342F53F402444F982168C4A40A708707A17EB3F40FB230C03968C4A402B69C53714CE3F40D0D38041D28F4A400188BB7A15CD3F40A58636001B904A402BDEC83CF2CB3F405019FF3EE3904A40F92CCF83BBCB3F402635B401D8924A405534D6FECECA3F40520DFB3DB1944A4027F911BF62C93F407978CF81E5964A40286552431BC83F40FBEAAA402D984A40FB20CB8289C73F402502D53F88984A40D13FC1C58AC63F40CCB56801DA984A40543A58FFE7C43F40CF6740BD19994A40257497C459A13F40CCB22781CD9B4A40D1CDFE40B99D3F40787B1002F29B4A4078B471C45A703F4029E78BBD179B4A40793C2D3F706D3F407C992842EA9A4A407AA86DC3286C3F40FFCF61BEBC9A4A40F73E5585066A3F40D28BDAFD2A9A4A40FE2AC0779B673F40CEE2C5C210994A4029ED0DBE30653F40D28E1B7E37974A40F9BA0CFFE9623F40240ED940BA944A40FF93BF7B47613F405182FE428F924A4006A051BAF45F3F40CEA623809B8F4A409F1F46088F623F40D2C43BC0938E4A402B6C06B820633F40234A7B832F8E4A4026FF93BF7B633F405531957EC28D4A40A016838769633F40FAEDEBC0398D4A40F9BA0CFFE9623F40520DFB3DB18C4A40AA656B7D91503F40D2C43BC093864A4027F6D03E56443F40CDE847C329834A40FE0B040132443F40A2D11DC4CE824A4052431B800D643F40A5BF97C283744A40CCF10A444F6A3F407E54C37E4F724A4078B471C45A703F40F702B34291704A40259694BBCF793F407C60C77F816E4A4026FC523F6F7E3F40D47FD6FCF86D4A40AC53E57B46823F405531957EC26D4A404DD9E90775893F40250516C0946D4A4028F04E3E3D8A3F40FAEDEBC0396D4A40D82B2CB81F943F404E2B85402E674A4022895E46B1943F4051137D3ECA664A4053CE177B2F963F40FB230C0396644A40D449B6BA9C963F40A3C85A43A9634A40A019C40776983F405340DAFF005F4A40D63730B951983F40F8FC3042785E4A408109DCBA9B973F40D47FD6FCF85D4A40A9F92AF9D8913F407A6CCB80B35A4A40CD57C9C7EE8E3F40D673D2FBC6594A40FB230C03968C3F4027F911BF62594A4029E78BBD178B3F404D31074147594A407F87A2409F843F407AABAE4335594A40800F5EBBB4813F40787E5182FE584A40247D5A457F803F40FAB48AFED0584A400000000000803F4024D5777E51584A40A301BC0512803F40D0D38041D2574A40A6EF3504C7813F40FA298E03AF564A4078B7B24467953F4025C9737D1F4C4A40008E3D7B2E973F4026FF93BF7B4B4A40A5F5B704E09B3F407978CF81E53E4A40CEE2C5C210A13F4027BD6F7CED2F4A407AABAE4335A13F4051DD5CFC6D2F4A40F92F1004C8A03F40FF9600FC532E4A40D63A71395E9D3F4026FF93BF7B2B4A4054C8957A169C3F405307793D982A4A40A3073E062B9A3F40253E7782FD294A4021956247E3983F40A774B0FECF294A40A6F27684D3963F40D00F238447294A4053CE177B2F963F407D93A641D1284A40D3C1FA3F87993F407AA52C431C274A40ABE7A4F78DB33F40A3923A014D1C4A40008BFCFA21C23F40FDDB65BFEE164A405531957EC2C53F40A7AD11C138164A40D63730B951C83F40FAEDEBC039154A4027F911BF62C93F4050E09D7C7A144A4058AA0B7899C93F4026FF93BF7B134A40FE0E45813EC93F402638F581E40F4A40D1CABDC0ACC83F4028B7ED7BD40D4A4054C8957A16BC3F40250516C0940D4A4028F38FBE499F3F40D3FA5B02F00D4A402AE44A3D0B863F402BDB87BCE50E4A40552E54FEB5803F402541B8020A0F4A407AA86DC3286C3F40FB78E8BB5B0F4A407AABAE4335613F407AA52C431C0F4A40800C1D3BA85C3F40FDDB65BFEE0E4A40A774B0FECF593F407E8D2441B80E4A4029780AB952573F4055FB743C660E4A407C992842EA523F40FC1A4982700D4A400188BB7A154D3F40A3C85A43A90B4A402383DC45984A3F405307793D980A4A40A9F92AF9D8213F40A583F57F0E0B4A4052D158FB3B1B3F40A583F57F0E0B4A4027F911BF62F93E405307793D980A4A404E61A5828AF63E40D4B837BF610A4A4052D7DAFB54F53E40276BD443340A4A4009FD4CBD6EF13E406C5A290472094A40FCA5457D92EF3E40A58636001B084A407C2AA73D25EF3E40A86E2EFEB6074A403C1405FA44EE3E401FBAA0BE65044A408C3045B934EE3E4031957EC2D9034A40FD9FC37C79F53E40286552431B004A40A968ACFD9DE53E40A489778027FD4940514CDE0033D33E404D31074147F94940A20A7F8637BF3E405307793D98F24940CCF10A444FAA3E402CD8463CD9E9494050E3DEFC86A93E407D5D86FF74E9494052465C001AA93E40A67D737FF5E84940CC5D4BC807A93E40FE9C82FC6CE84940A110018750A93E407D21E4BCFFE74940A4FE7A8505AB3E4023145B41D3E6494027840EBA84AB3E40D3FA5B02F0E54940A708707A17AB3E402A1A6B7F67E549407E18213CDAA03E40A583F57F0EDB494023861DC6A49F3E40D28BDAFD2ADA4940D04543C6A3903E405055A18158D2494056B60F79CB8D3E40A6B6D4415EC54940CDE506431D963E40A4C519C39CBE4940A8716F7EC3A43E40A5BC564277AF4940CE5147C7D5A43E40CFDC43C2F7AE4940D15B3CBCE7A43E405307793D98AA49408D2AC3B81BA43E40C30DF8FC30AA4940A777F17EDC9E3E40FA264D83A2A949404F5B2382719C3E40D00F238447A94940008BFCFA21923E40A54A94BDA5A64940AB5CA8FC6B913E40FD1186014BA64940A5F8F884EC903E405531957EC2A549407A8EC877298D3E4070D05E7D3CA04940CFDC43C2F7763E405531957EC2A54940FCABC77DAB593E407D96E7C1DDAD4940D3C1FA3F87593E40AB5CA8FC6BB149407B30293E3E593E40FE99417C60B3494052465C001A593E4022179CC1DFB34940A58636001B583E407AA86DC328B44940FD3383F8C0363E40A1A17F828BBD49407A36AB3E57333E407B336ABE4ABE4940D061BEBC002F3E40A777F17EDCBE4940A4897780272D3E40CFDC43C2F7BE49404DD9E90775293E407C2AA73D25BF494050E09D7C7A243E407C2AA73D25BF4940A4FE7A85050B3E40508E0244C1BE49402B6C06B820033E40A4C519C39CBE4940F92CCF83BBFB3D4079AEEFC341BE494027F911BF62E93D4022E17B7F83BC4940800F5EBBB4E13D402635B401D8BA4940A968ACFD9DD53D40F702B34291B84940FE0B040132C43D407A39ECBE63B849405055A18158C23D40D09D60FF75B84940FBAE08FEB7BE3D4025CCB4FD2BB94940CD7344BE4BBD3D40FDD8243FE2B94940240ED940BABC3D40FAF02C4146BA4940CEDF844204BC3D40FBE769C020BB4940F92CCF83BBBB3D402444F98216BC49407BBB253960BB3D4022E17B7F83BC4940F73E558506BA3D40A3CEDC43C2BD494021956247E3B83D404E61A5828ABE4940AAF3A8F8BFB73D4028F38FBE49BF4940A1A17F828BB53D40D0D38041D2BF49404FE61F7D93AE3D407C9C69C2F6BF4940A29BFD8172AB3D40D158FB3BDBBF494078B471C45AA03D407978CF81E5BE49407C2AA73D259F3D40FBAE08FEB7BE494021956247E3683D407C6308008EB34940C02500FF945A3D4072C45A7C0AB04940FC17080264583D404C70EA03C9AF4940A6F27684D3563D407A6F0C01C0AF49400282397AFC523D407A39ECBE63B0494029EACC3D24503D40D00F238447B149404ED367075C4F3D40FA264D83A2B149407B9FAA42034D3D407F4B00FE29B34940A0A70183A43F3D40A5BC564277BF49404FCAA48636403D407B6649809AC04940A301BC0512403D40FA264D83A2C149407B336ABE4A3E3D40FED5E3BED5C44940F4531C075E3D3D407B698A00A7C5494026FC523F6F2E3D407AA52C431CCF494051DA1B7C612A3D40514F1F813FD04940F54718062C293D40D09D60FF75D04940D731AEB8381E3D40D3C1FA3F87D1494054C554FA09173D4052103CBEBDD14940D4B5F63E55153D40508BC1C3B4D1494081069B3A8F123D407D5D86FF74D14940FC1A4982700D3D40F92F1004C8D04940FC17080264D83C40FDDB65BFEEC64940D82B2CB81FD43C40D3FA5B02F0C54940FA9B508880CF3C407D5A457F68C44940A4FE7A8505CB3C407BA2EBC20FC249402AE44A3D0BC63C40F9F36DC152BF4940D82B2CB81FC43C402AE44A3D0BBE4940514CDE0033C33C404E25034015BD4940286211C30EC33C40CEDF844204BC49407A1A3048FAC43C40A3957B8159B9494052431B800DC43C40501C40BFEFB54940037976F9D6C33C40A6B6D4415EB549402CD8463CD9C13C407A724D81CCB44940D04543C6A3C03C40FCA886FD9EB44940218FE046CABE3C40520DFB3DB1B44940250516C094BD3C40D15B3CBCE7B449407AA86DC328AC3C40A19E3E027FB8494052465C001AA93C4079758E01D9B94940FB20CB8289A73C40A583F57F0EBB49407F129F3BC1A63C40A77A32FFE8BB4940A016838769A33C407D93A641D1C0494056B950F9D7A23C40D4EE5701BEC14940CFD90242EBA13C4025C9737D1FC4494023111AC1C6A13C40276893C327C549407BA2EBC20FA23C40D1CDFE40B9C54940A48CB80034A23C40F9F36DC152C7494055C2137AFDA13C404C70EA03C9C74940287E8CB96BA13C40FBEAAA402DC84940AA656B7D91A03C405401F73C7FC849404ED367075C9F3C40272F3201BFC8494026FC523F6F7E3C40D4B837BF61CA4940240ED940BA7C3C40D4B837BF61CA4940228C9FC6BD793C40276BD44334CA4940211D1EC2F8753C4052103CBEBDC94940CD57C9C7EE6E3C40D09D60FF75C84940A6EF3504C7513C40D09A1F7F69CB494052431B800D443C40CEDF844204D4494082FDD7B969433C40F9F6AE415FD44940276BD44334423C40FCA886FD9ED449402A7288B8393D3C40A64412BD8CD44940D0D38041D2373C40CEDF844204D44940D449B6BA9C363C405116BEBED6D3494052D4997B48303C407E54C37E4FD24940ABED26F8A62D3C4055F833BC59D149407AA86DC3282C3C40F702B34291D04940D63730B951283C40FCE4284014CE49407B2DE8BD31243C404F1F813FFCCA49409F1F46088F223C40AC53E57B46CA4940A4897780271D3C4080457EFD10C94940CF4BC5C6BC1A3C40552E54FEB5C849404E61A5828A163C40A7B393C151C84940CFD90242EB113C40FBEAAA402DC84940D446753A90013C40F9BD4D7FF6C74940A680B4FF01FE3B40FBEAAA402DC84940FCABC77DABF93B40D1CABDC0ACC8494076C075C58CF43B4029266F8099C94940D061BEBC00EF3B40A583F57F0ECB49407AA86DC328EC3B40A77A32FFE8CB4940FCABC77DABE93B40543A58FFE7CC494052D7DAFB54E53B40AB5FE97C78CE4940FC1D8A027DE23B40FB78E8BB5BCF49402098A3C7EFDD3B40D0D38041D2CF4940297B4B395FDC3B404C70EA03C9CF4940533D997FF4D93B404F58E20165CF49407F129F3BC1D63B40A4C519C39CCE4940D734EF3845D33B40D4B5F63E55CD4940A5F8F884ECD03B40D1915CFE43CC4940CF4E0647C9CF3B407A36AB3E57CB49404ED367075CCF3B40276BD44334CA4940F838D384EDCF3B40D00F238447C9494053CBD6FA22D13B407D21E4BCFFC74940257497C459D13B40A741D13C80C74940800F5EBBB4D13B40527FBDC282C54940FA264D83A2D13B4001BEDBBC71C44940FF93BF7B47D13B40A77A32FFE8C34940CF4E0647C9CF3B40CDE847C329C34940FE9C82FC6CC03B40FBB1497EC4BB4940A20A7F8637BF3B404E64E60297BB494074CFBA46CBBD3B40F92CCF83BBBB4940CD57C9C7EEAE3B40CFDC43C2F7BE49402B69C53714AE3B4028F38FBE49BF4940AA0A0DC4B2B53B400B9C6C0377C6494050E3DEFC86B93B40514F1F813FC8494077BAF3C473BA3B407AABAE4335C94940268DD13AAABA3B40D673D2FBC6C94940268DD13AAABA3B407E54C37E4FCA4940CCF10A444FBA3B404C6DA983BCCA4940FCABC77DABB93B40FBE769C020CB4940CE70033E3FB83B405116BEBED6CB494053CE177B2FB63B40F9F6AE415FCC4940F838D384EDAF3B40AA9ECC3FFACC494021956247E3983B40D576137CD3CE49401B800D8810833B401EC022BF7ED04940211D1EC2F8753B40A6B6D4415ECD4940F8C3CF7F0F723B40253B3602F1CC4940A96BED7DAA6A3B4050E09D7C7ACC4940F8359204E14A3B40D1915CFE43CC4940CC5D4BC807493B4027F6D03E56CC4940FB20CB8289473B40A5BF97C283CC49407E1B62BCE6453B40276893C327CD4940514CDE0033333B4027327381CBD54940D0D03FC1C5323B40A7AD11C138D64940209BE447FC323B40D158FB3BDBD74940D064FF3C0D343B4079B130444EDB494022895E46B1343B40F9F6AE415FDC4940D15B3CBCE7343B407AA52C431CDF494022895E46B1343B40FCA5457D92DF4940A016838769333B407E18213CDAE04940D53DB2B96A323B40D6A9F23D23E14940A680B4FF012E3B40FA264D83A2E14940CC5D4BC807293B40253E7782FDE1494022895E46B1143B407A6CCB80B3E24940D540F33977073B40FC1D8A027DE249404DD6A88768043B4051DA1B7C61E24940FE9C82FC6C003B40823CBB7CEBE14940ABEAE5779AF83A40D5B2B5BE48E04940AAF06778B3F23A40D158FB3BDBDF4940CD57C9C7EEEE3A407C9C69C2F6DF4940A29BFD8172EB3A4029EACC3D24E04940A304FD851EE53A40552E54FEB5E04940008BFCFA21D23A4028BA2EFCE0E249405531957EC2C53A40FB230C0396E44940A67D737FF5B83A40FBAE08FEB7E649407AA86DC328AC3A40A7B393C151E84940FF9600FC53A63A402AE109BDFEE849409F1F46088FA23A4052465C001AE94940D34CF73AA99B3A4052465C001AE94940276BD44334923A40272F3201BFE8494056BC9179E4873A40A58636001BE84940A0A70183A47F3A4027BD6F7CEDE749407D24253D0C753A404F22C2BF08E84940A9F92AF9D8713A40A7B393C151E84940FE9C82FC6C703A40FCE1E7BF07E94940A60BB1FA23703A4001C11C3D7EE94940A60BB1FA23703A405182FE428FEA4940221ADD41EC703A40A73B4F3C67ED4940D158FB3BDB6F3A40FFCC203EB0ED4940A3923A014D6C3A407D96E7C1DDED49402A7288B8395D3A40D3FA5B02F0ED4940FA298E03AF563A405531957EC2ED4940250516C0944D3A40505260014CED49404ED026874F4A3A40FAEDEBC039ED4940A60EF27A30353A407D96E7C1DDED49407B336ABE4A2E3A4079AEEFC341EE494027840EBA842B3A402829B000A6EE494079AEEFC341263A40F9BD4D7FF6EF494075C93846B2233A40221ADD41ECF049402BDB87BCE5063A40A5BF97C283F449404E5E64027ED139404C70EA03C9F74940D449B6BA9CC63940CCEB884336F84940037976F9D6C33940F9BD4D7FF6F7494074CFBA46CBBD3940FDDB65BFEEF64940259694BBCFB93940AB5FE97C78F649407EACE0B721B23940CDE506431DF649407EA99F3715AD3940A680B4FF01F64940D82E6D382C993940A968ACFD9DF54940A301BC0512903940A3CEDC43C2F54940309B00C3F28B3940CC43A67C08F64940F92CCF83BB8B3940501C40BFEFF549404D672783A37039402AE44A3D0BF649404F5B2382715C39402829B000A6F64940D0D38041D2573940A9A44E4013F74940F838D384ED4F39402250FD8348F8494054C554FA09473940D673D2FBC6F949400282397AFC4239405055A18158FA4940CAFD0E45813E3940A2D11DC4CEFA4940D0D6C1C1DE3C39407C992842EAFA49402098A3C7EF2D39402635B401D8FA4940A96BED7DAA2A3940FFCF61BEBCFA49407C9C69C2F61739407B6649809AF84940505260014C0D3940F9F36DC152F749402098A3C7EFFD3840240ED940BAF4494029780AB952E73840FE99417C60F349407B2DE8BD31E43840514CDE0033F34940250516C094BD3840FDD8243FE2F14940F44D9A0645B33840A6B915C26AF24940FAB48AFED068384029266F8099F1494024809BC58B6538404E5E64027EF149407B2DE8BD3164384055F833BC59F1494053CBD6FA226138402502D53F88F049407E18213CDA5038407E8AE3C0ABE949404FCAA48636503840D00F238447E949407E8D2441B84E384027BD6F7CEDE74940A680B4FF014E38407B698A00A7E549404F5B2382714C384051DA1B7C61E249407F15E0BBCD4B384055F833BC59E14940CE548847E2493840A741D13C80DF4940FE0E45813E4938407AA52C431CDF4940FB20CB828947384026FC523F6FDE49407BA2EBC20F1238407D21E4BCFFCF4940A4FE7A85050B38408048BF7D1DCE494052B81E85EB013840A3923A014DCC4940A489778027FD374026FF93BF7BCB4940CF6740BD19F93740D482177D05CB49407B2DE8BD31F4374028BA2EFCE0CA4940FA264D83A2F1374079B130444ECB4940D34F38BBB5F03740D2C77C40A0CB49407D21E4BCFFEF3740A5BF97C283CC49404FE61F7D93EE37405531957EC2CD494055BFD2F9F0EC3740CFDC43C2F7CE49404E64E60297EB3740F60B76C3B6CF4940F54718062CE93740A3CB9BC3B5D04940CFDC43C2F7E637407AABAE4335D1494024809BC58BE5374027F911BF62D1494022895E46B1C43740A29BFD8172D34940A5F8F884ECC03740F8FF71C284D34940FAB7CB7EDDBD3740FE99417C60D34940A96BED7DAAAA3740253E7782FDD149404E61A5828AA63740D3C1FA3F87D149407B2DE8BD31A4374052465C001AD149405340DAFF009F3740D0D38041D2CF4940D63A71395E9D37407C2AA73D25CF4940240ED940BA9C3740508E0244C1CE49407F15E0BBCD9B374028B7ED7BD4CD4940D34CF73AA99B3740FAEDEBC039CD4940A8FFACF9F19B3740A8716F7EC3CC49404F5B2382719C374027F6D03E56CC4940F6419605139F3740D09A1F7F69CB4940A86E2EFEB69F3740A583F57F0ECB4940800F5EBBB4A1374055F833BC59C949404D6A6803B0A53740253B3602F1C44940D252793BC2A537407D5A457F68C4494078B7B24467A53740A96BED7DAAC249404DD6A88768A4374051DA1B7C61C24940F9BA0CFFE9A23740A6B915C26AC249401615713AC99A3740A1A17F828BC34940543A58FFE79437402444F98216C44940286552431B94374066BE839F38C449405055A18158923740A5BF97C283C4494078B471C45A9037407D24253D0CC54940A86E2EFEB68F3740FC1A498270C54940A20A7F86378F37407E1B62BCE6C54940D925AAB7068A374022179CC1DFCB4940239F573CF588374021EA3E00A9D34940FC1A4982708D3740A64412BD8CD44940FD1186014B8E3740D15B3CBCE7D44940D2C43BC0938E3740505260014CD549404DDC2A88818E374028B7ED7BD4D5494000917EFB3A8C3740D158FB3BDBD74940A777F17EDC8E3740A7B393C151E049402EC901BB9A9C3740073F7100FDF44940D2FD9C82FC9C3740B9E00CFE7EF54940CCEB884336A03740FA264D83A2F94940D34F38BBB5A037407C2766BD18FA4940F54718062CA93740F92F1004C8004A4026FF93BF7BA33740D28BDAFD2A0A4A40D63730B951983740FF9600FC530E4A40F92CCF83BB5B3740A48CB800341A4A4077BAF3C4735A3740A6B915C26A1A4A40266E15C44057374025085740A11A4A4000917EFB3A4C374029E78BBD171B4A40CF6740BD19393740F9F6AE415F1C4A404B732B84D53437404B732B84D51C4A40FD304278B43137407B698A00A71D4A40A702EE79FE3037402AE44A3D0B1E4A4027C286A7572A37400D39B69E21244A40CAFD0E45813E37404F58E201652F4A404568041BD73F374039B35DA10F304A404D672783A3603740FED2A23EC93F4A404D6A6803B06537402CD8463CD9414A40D255BABBCE6A3740234DBC033C434A40A5F8F884EC80374000CADFBDA3484A407E1B62BCE6853740AB5CA8FC6B494A4021956247E398374027F6D03E564C4A40A48CB80034A23740527FBDC2824D4A40AAF3A8F8BFA737408048BF7D1D4E4A40CCEB884336B03740D061BEBC004F4A40F8325184D4B53740FDDB65BFEE4E4A40E9263108ACB837401590F63FC04E4A40F25CDF8783BC37407C60C77F814E4A40F54A598638BE374000C45DBD8A4E4A402AE109BDFEC03740D576137CD34E4A402975C93846E2374051137D3ECA564A40A019C40776E83740FE9C82FC6C584A4051DA1B7C61EA37407903CC7C07594A40D1CDFE40B9ED374051DA1B7C615A4A40F641960513EF3740CDE847C3295B4A40A301BC0512F037402444F982165C4A407E18213CDAF037404EEFE2FDB85D4A40221ADD41ECF037407C9C69C2F65F4A4027874F3A91F037405307793D98624A40381092054CF03740CDE847C329634A4026FC523F6FEE37407E1B62BCE66D4A40384D9F1D70ED3740D927806264794A40CD57C9C7EEEE3740D00F238447814A40A777F17EDCEE3740A774B0FECF814A407F15E0BBCDDB3740CEE2C5C210994A40D55E44DB31C937407C7E18213CA84A407A36AB3E57B33740253E7782FDB94A40F54A598638AE3740250516C094BD4A40240ED940BAAC3740A777F17EDCBE4A40FE99417C60AB37407EC9C6832DC04A40A77A32FFE8A33740FCA5457D92C74A40A777F17EDC9E3740FC1A498270CD4A40A4897780279D37407A6F0C01C0CF4A407F15E0BBCD9B374029266F8099D14A40D63730B951983740508E0244C1D64A40008E3D7B2E9737404EECA17DACD84A40F226BF45279737400F2A711DE3D84A40FCA886FD9E943740250516C094DD4A40A3073E062B8A3740D2C77C40A0EB4A402B6C06B8208337407C2766BD18F24A400CAEB9A3FF81374019E76F4221F44A402AE109BDFE803740501C40BFEFF54A40552E54FEB58037404D672783A3F84A4037E0F3C308813740BFEFDFBC38F94A4084F414394484374025CCB4FD2BF94A4050C763062A8B3740A45016BEBEF84A40D446753A90913740CCEB884336F84A40CFDC43C2F79637404F58E20165F74A40A1100187509937407978CF81E5F64A40268A90BA9DB5374079AEEFC341F64A40D1CABDC0ACC837407A6F0C01C0F74A40CDE506431DE637407A39ECBE63F84A404F5B238271FC3740FBEAAA402DF84A40D82B2CB81F043840F9BD4D7FF6F74A40D734EF3845133840A359D93EE4F74A40FA298E03AF1638407D21E4BCFFF74A40228C9FC6BD193840CE70033E3FF84A4000917EFB3A1C38404D672783A3F84A40F6419605131F384029266F8099F94A40A86E2EFEB61F3840253E7782FDF94A409F1F46088F2238407C992842EAFA4A40CE5147C7D5243840D09A1F7F69FB4A40AAF3A8F8BF273840282CF180B2FB4A4055BFD2F9F02C38405116BEBED6FB4A40793F6EBF7C3238404E64E60297FB4A40268A90BA9D35384079B130444EFB4A407B30293E3E3938405182FE428FFA4A407EA99F37153D384027F911BF62F94A40FBAE08FEB73E3840A3CB9BC3B5F84A407E18213CDA403840CEA623809BF74A405055A18158423840FF9600FC53F64A40FC1D8A027D423840CCEEC9C342F54A40D734EF3845433840F9F6AE415FF44A40543A58FFE7443840A54DD53DB2F34A407AA52C431C4738407F4B00FE29F34A404E5E64027E613840FCABC77DABF14A40A583F57F0E63384052103CBEBDF14A4050E09D7C7A643840FDD8243FE2F14A401F9E25C8086838405182FE428FF24A40D449B6BA9C76384028B7ED7BD4F54A4075CC79C6BE783840D097DEFE5CF64A40D13C80457E813840CF6740BD19F94A407E1B62BCE6853840A48CB80034FA4A40240ED940BA9C38405340DAFF00FF4A4051DD5CFC6DAF3840514F1F813F004B40CEE2C5C210B138407F4E417E36004B405055A18158B238400000000000004B40FBB1497EC4B33840A38FF98040FF4A40A20DC00644B43840D576137CD3FE4A40CCEEC9C342B53840793C2D3F70FD4A402881CD3978B63840CEA96400A8FC4A402502D53F88B838402444F98216FC4A40CCF10A444FBA38407A008BFCFAFB4A4054C8957A16BC3840CEDF844204FC4A40008BFCFA21D238404E25034015FD4A40A20DC00644D4384079AEEFC341FE4A402AE44A3D0BD63840FCA5457D92FF4A40A8FC6B79E5D63840A8E0F08288004B404F58E20165D738407E54C37E4F024B40008E3D7B2ED738407D5A457F68044B40D449B6BA9CD63840A6B6D4415E054B4022895E46B1D438402541B8020A074B4026FF93BF7BD33840D158FB3BDB074B4081069B3A8FD23840FBEAAA402D084B40FA9B508880CF38407C2766BD180A4B40276893C327CD3840A54DD53DB20B4B40D34CF73AA9CB3840AA9ECC3FFA0C4B4051BEA08504CC3840FD9FC37C790D4B40A7ECF483BACC38407D96E7C1DD0D4B4079AEEFC341D63840FDD8243FE2114B407AA52C431CD73840276BD44334124B40A774B0FECFD938405182FE428F124B4055BFD2F9F0DC3840D0D03FC1C5124B4076C075C58CF438404D2EC6C03A144B401F9E25C808F83840A3923A014D144B40259694BBCFF938407B2DE8BD31144B404F5B238271FC3840CCB22781CD134B40FB928D075B0039405307793D98124B40800F5EBBB401394079758E01D9114B40A7E67283A1023940D3C1FA3F87114B4079AEEFC341063940F92F1004C8104B40D0D38041D20739404D672783A3104B40A4FE7A85050B39407B6649809A104B40D53DB2B96A123940FE0E45813E114B40A304FD851E15394029266F8099114B40533D997FF4193940FC1D8A027D124B404DD9E90775293940FCE4284014164B4074CFBA46CB2D3940D0D38041D2174B40ABE7A4F78D3339407E1EA33CF31A4B40A304FD851E35394075931804561C4B402502D53F885839402B172AFF5A204B404ED367075C5F3940A8E0F08288204B40A20DC00644643940272F3201BF204B4056BC9179E4673940AB5CA8FC6B214B40D255BABBCE6A39405055A18158224B40FB230C03966C3940D482177D05234B40CCEB884336703940AA9ECC3FFA244B4075C93846B27339405376FA415D264B4029780AB9527739402541B8020A274B4075CC79C6BE7839404E2B85402E274B4051DA1B7C617A3940A38FF98040274B40259012BBB67F3940FDDB65BFEE264B407E18213CDA803940A54A94BDA5264B40AA656B7D91903940514F1F813F204B40A583F57F0E933940D009A1832E1F4B407E9065C1C4933940508E0244C11E4B40A01683876993394079AEEFC3411E4B4000917EFB3A8C394026C3F17C061A4B402383DC45988A3940D1949D7E50194B40D446753A90813940F9BD4D7FF6174B407AABAE4335813940D4BB783F6E174B407D93A641D18839405534D6FECE124B40533D997FF48939405182FE428F124B40505260014C8D39407E54C37E4F124B4050E3DEFC86A93940AB5CA8FC6B114B4079B130444EAB3940AB5CA8FC6B114B40A11342075DAE3940FA264D83A2114B40D82B2CB81FC43940A54DD53DB2134B4024809BC58BC539405116BEBED6134B40CC5D4BC807C93940A64412BD8C144B4028F04E3E3DCA3940A73B4F3C67154B40A4FE7A8505CB394026FC523F6F164B40A777F17EDCCE3940D28E1B7E371F4B40218FE046CACE39407A6F0C01C01F4B402B69C53714CE3940286552431B204B40240B98C0ADB739407BA2EBC20F2A4B407E1B62BCE6B539407A6CCB80B32A4B4076C075C58CB43940F9BA0CFFE92A4B4026FF93BF7BB33940A96BED7DAA2A4B40D0D03FC1C5B23940AC53E57B462A4B40221ADD41ECB0394029266F8099294B4055BFD2F9F0AC394080457EFD10294B4075CC79C6BEA839407B6649809A284B407B2DE8BD31A43940514F1F813F284B404F5B2382719C3940D158FB3BDB274B40F73B1405FA9439402638F581E4274B40FA264D83A291394029EACC3D24284B40CD57C9C7EE8E3940AA656B7D91284B40276893C3278D39407AABAE4335294B404F5B2382718C394029266F8099294B407AA86DC3288C39407BA2EBC20F2A4B407AA86DC3288C39405307793D982A4B40D0D6C1C1DE8C3940253B3602F12C4B40250516C0948D3940D47FD6FCF82D4B4058AD4CF8A58E3940A777F17EDC2E4B40CDE506431DA6394028F04E3E3D424B402502D53F88A83940D09A1F7F69434B404C6DA983BCAA3940787B1002F2434B4073D53C47E4B7394027327381CB454B40CDE847C329BB3940A4C519C39C464B40259012BBB6BF3940514F1F813F484B40AB5CA8FC6BC13940A67D737FF5484B40D2C77C40A0C33940D1066003224A4B40CD5A0A48FBC3394079B130444E4B4B40A77A32FFE8C339405116BEBED64B4B40D2C77C40A0C33940A6B6D4415E4D4B407C992842EAC2394079AEEFC3414E4B40800F5EBBB4C1394026C632FD124F4B40A0A70183A4BF3940FBEAAA402D504B40D34CF73AA9BB3940F8FF71C284534B40CDE847C329BB3940787B1002F2534B40A3073E062BBA3940D4B5F63E55554B407C2766BD18BA3940D4BB783F6E574B404F5B238271BC3940D3BEB9BF7A644B407845F0BF95BC39407D24253D0C654B40A489778027BD3940527FBDC282654B40533D997FF4C939404F58E201656F4B40D042024697CB3940A58636001B704B4077BD344580DF394024D5777E51784B40AA656B7D91E039407B6649809A784B404DD9E90775E939407BA2EBC20F7A4B402B69C53714EE394051DA1B7C617A4B404E5E64027EF1394028F04E3E3D7A4B40ABE7A4F78D133A40FBE769C0207B4B40F54718062C293A404E250340157D4B40D252793BC2353A404C6DA983BC824B402A6F47382D383A405116BEBED6834B40FCA5457D923F3A4052465C001A894B40A301BC0512403A40FC1D8A027D8A4B404FCAA48636403A404E64E602978B4B40F838D384ED3F3A40234A7B832F8E4B407E18213CDA403A40D0D38041D28F4B40D53DB2B96A423A407B6649809A904B40FA298E03AF463A405055A18158924B4057B3CEF8BE483A407E1EA33CF3924B4079B130444E7B3A405116BEBED6934B40552E54FEB5803A4026FF93BF7B934B40FD9FC37C79853A40D2FD9C82FC924B40A20DC00644A43A40FE9C82FC6C984B40AB5FE97C78C63A40D38558FD11A04B405534D6FECECA3A40A8AAD0402CA14B40A7ECF483BACC3A402CD8463CD9A14B4078B471C45AD03A40514CDE0033A34B40A9F92AF9D8D13A40FCDEA63FFBA34B40A9F92AF9D8D13A40A5BF97C283A44B40CF4E0647C9CF3A40A8E3310395A54B400188BB7A15CD3A404E61A5828AA64B40D1CABDC0ACC83A40FB20CB8289A74B4027F6D03E56C43A4029EACC3D24A84B4052D7DAFB54A53A40AC53E57B46AA4B40FA264D83A2A13A40D4B837BF61AA4B404DDC2A88819E3A40D28BDAFD2AAA4B4053CBD6FA22913A402250FD8348A84B40A680B4FF018E3A40D38558FD11A84B404F58E20165873A40D1CABDC0ACA84B40D13C80457E813A407D5D86FF74A94B404A7F2F8507793A407A6CCB80B3AA4B40A1A17F828B753A40FE99417C60AB4B4022895E46B1743A40A54DD53DB2AB4B40FCA886FD9E743A404D2EC6C03AAC4B407D24253D0C753A40A8716F7EC3AC4B40A6F27684D3863A407AABAE4335B94B40FE9C82FC6CA03A40A77A32FFE8CB4B40CEE2C5C210A13A407B9FAA4203CD4B40CEE2C5C210A13A40530438BD8BCD4B40D158FB3BDB9F3A40FAF02C4146D24B40CD57C9C7EE9E3A40240ED940BAD44B40E59CD843FB9C3A401C9947FE60D64B40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('LH','LT','LTU','440','Lithuania','6268','3425077','150','154','23.897','55.336','0106000020E6100000020000000103000000010000001D000000009A417C600B3540E873D2FBC6A94B40B0A432C51CFC3440C0DA8AFD65A34B400097E4805DF1344080309B00C3A44B405064E60297FB34405855A18158AA4B40D04543C6A3003540E088997D1EAD4B40A02766BD180A354088B130444EB34B40207A19C5720B3540580DFB3DB1B44B4030D505BCCC0C354010E5284014B64B40307D5A457F103540B074B0FECFB94B4070CDE50643153540809C69C2F6BF4B40102A8E03AF16354008D9243FE2C14B40200B98C0AD17354010DFA63FFBC34B40306F47382D18354078AEEFC341C64B402002D53F88183540D064FF3C0DCC4B40E0CABDC0AC183540A889778027D54B401018080264183540E876137CD3D64B40200B98C0AD17354038C3F17C06DA4B40F049B6BA9C163540B07A32FFE8DB4B4050C554FA09173540F8C9518028DC4B4020956247E318354030FF93BF7BDB4B40C0DF8442041C354088A2EBC20FDA4B40201B4982701D35405031074147D94B4050D367075C1F3540A88636001BD84B40D04F38BBB5203540608E0244C1D64B40F01D8A027D2235403002D53F88D04B4000301004C820354028266F8099C94B4060DA1B7C611A35408096E7C1DDB54B40D04334BA830C3540A8E67283A1AA4B40009A417C600B3540E873D2FBC6A94B4001030000000100000018020000200000000000394020B7ED7BD4254C4090069B3A8F123940D064FF3C0D1C4C4090716F7EC3143940881EA33CF31A4C409093A641D118394050103CBEBD194C40E0E847C3291B39408830293E3E194C403075C9384622394000EBAA402D184C4060D7DAFB54253940E0D38041D2174C40F05D4BC807293940D8A623809B174C40A077F17EDC2E3940A8BC564277174C40604CDE0033433940802AA73D25174C40209221C7D653394078698A00A7154C40C080B4FF016E3940585260014C154C4040ED0DBE30953940109A417C60134C40F03DB2B96AB23940608E0244C10E4C40209BE447FCB2394038B7ED7BD40D4C4070E09D7C7AB43940A84412BD8C0C4C40A00EF27A30B5394078A86DC3280C4C4060C554FA09B73940080072C2840B4C400045D7851FE4394038BD6F7CEDFF4B4070C6F7C5A5EE3940D0A0A17F82FD4B40A0ABAE4335F139407824253D0CFD4B400042960513FF39403835B401D8FA4B40A026C286A7033A4068527C7C42FA4B40E057C9C7EE0E3A403023A0C211F84B40A018213CDA303A403841B8020AEF4B4050E960FD9F333A4008E5284014EE4B40201D1EC2F8353A40789FAA4203ED4B4020B58AFED0383A40F0FF71C284EB4B40307288B8393D3A408893A641D1E84B40B01C0588823D3A40A8B393C151E84B40B0EF3504C7413A40F8BDDBBC71E44B4080FDD7B969433A40284DBC033CE34B40E05147C7D5443A40001E8A027DE24B40C05FE97C78463A40B874B0FECFE14B4060CAA48636503A40F8298E03AFDE4B40202A8E03AF563A4038C0B0FCF9DC4B40F02CCF83BB5B3A40C8DF844204DC4B4030EACC3D24603A40D09A1F7F69DB4B4020A6457D927F3A40D058FB3BDBD74B40E0D03FC1C5823A408042AF3F89D74B4020857AFA08883A40902AA73D25D74B40D034EF3845933A405861A5828AD64B404058E20165973A4068FB743C66D64B40F09CD843FB9C3A40209947FE60D64B40E057C9C7EE9E3A40280ED940BAD44B40D058FB3BDB9F3A4000F12C4146D24B40C0E2C5C210A13A40580438BD8BCD4B40C0E2C5C210A13A40809FAA4203CD4B40F09C82FC6CA03A40A87A32FFE8CB4B40B0F27684D3863A4078ABAE4335B94B40A024253D0C753A40A8716F7EC3AC4B4000A986FD9E743A40582EC6C03AAC4B4020895E46B1743A40A04DD53DB2AB4B40B0A17F828B753A40109A417C60AB4B40507F2F8507793A40786CCB80B3AA4B40D03C80457E813A40885D86FF74A94B405058E20165873A40D0CABDC0ACA84B40A080B4FF018E3A40D88558FD11A84B4040CBD6FA22913A402850FD8348A84B4050DC2A88819E3A40E08BDAFD2AAA4B4020274D83A2A13A40D0B837BF61AA4B4070D7DAFB54A53A40B053E57B46AA4B4040F6D03E56C43A4038EACC3D24A84B40E0CABDC0ACC83A400021CB8289A74B402088BB7A15CD3A405861A5828AA64B40E04E0647C9CF3A40B8E3310395A54B40D0F92AF9D8D13A40B0BF97C283A44B40D0F92AF9D8D13A4000DFA63FFBA34B4090B471C45AD03A40604CDE0033A34B40A0ECF483BACC3A4038D8463CD9A14B407034D6FECECA3A40B8AAD0402CA14B40D05FE97C78C63A40E08558FD11A04B40C00DC00644A43A40009D82FC6C984B4020A0C37C79853A40E0FD9C82FC924B40702E54FEB5803A4030FF93BF7B934B40A0B130444E7B3A404816BEBED6934B4060B3CEF8BE483A40901EA33CF3924B40F0298E03AF463A405855A18158924B40C03DB2B96A423A40886649809A904B409018213CDA403A40D0D38041D28F4B402039D384ED3F3A40204A7B832F8E4B4070CAA48636403A405064E602978B4B40B001BC0512403A40081E8A027D8A4B40F0A5457D923F3A4058465C001A894B40506F47382D383A405816BEBED6834B40E052793BC2353A40586DA983BC824B40F04718062C293A4050250340157D4B40D0E7A4F78D133A40F8E769C0207B4B40405E64027EF1394020F04E3E3D7A4B404069C53714EE394050DA1B7C617A4B4050D9E90775E9394080A2EBC20F7A4B40B0656B7D91E03940886649809A784B4080BD344580DF394020D5777E51784B40E042024697CB3940B08636001B704B40503D997FF4C939405858E201656F4B40A089778027BD3940507FBDC282654B408045F0BF95BC39408024253D0C654B40705B238271BC3940D0BEB9BF7A644B40A02766BD18BA3940D0BB783F6E574B40C0073E062BBA3940E0B5F63E55554B40D0E847C329BB3940787B1002F2534B40E04CF73AA9BB3940F8FF71C284534B40C0A70183A4BF394000EBAA402D504B40700F5EBBB4C1394020C632FD124F4B40A0992842EAC2394078AEEFC3414E4B40E0C77C40A0C33940A0B6D4415E4D4B40B07A32FFE8C339406016BEBED64B4B40D05A0A48FBC3394088B130444E4B4B40E0C77C40A0C33940E0066003224A4B40D05CA8FC6BC13940A07D737FF5484B40209012BBB6BF3940504F1F813F484B40D0E847C329BB394098C519C39C464B4070D53C47E4B7394028327381CB454B40506DA983BCAA3940887B1002F2434B404002D53F88A83940D09A1F7F69434B40E0E506431DA6394028F04E3E3D424B4070AD4CF8A58E3940B877F17EDC2E4B40400516C0948D3940E07FD6FCF82D4B40D0D6C1C1DE8C3940283B3602F12C4B4090A86DC3288C39406007793D982A4B4090A86DC3288C394088A2EBC20F2A4B40705B2382718C394030266F8099294B40206893C3278D394088ABAE4335294B40C057C9C7EE8E3940B8656B7D91284B4000274D83A291394038EACC3D24284B40E03B1405FA9439403838F581E4274B40605B2382719C3940D058FB3BDB274B40702DE8BD31A43940584F1F813F284B4080CC79C6BEA83940706649809A284B4050BFD2F9F0AC394080457EFD10294B40301ADD41ECB0394030266F8099294B40F0D03FC1C5B23940B853E57B462A4B4020FF93BF7BB33940A86BED7DAA2A4B4090C075C58CB4394008BB0CFFE92A4B40901B62BCE6B53940786CCB80B32A4B40300B98C0ADB7394088A2EBC20F2A4B403069C53714CE3940306552431B204B40208FE046CACE3940806F0C01C01F4B409077F17EDCCE3940E08E1B7E371F4B40B0FE7A8505CB394038FC523F6F164B4020F04E3E3DCA3940B83B4F3C67154B40E05D4BC807C93940A04412BD8C144B4040809BC58BC539405016BEBED6134B40E02B2CB81FC43940A84DD53DB2134B40B01342075DAE394008274D83A2114B4070B130444EAB3940B85CA8FC6B114B4050E3DEFC86A93940B85CA8FC6B114B40605260014C8D39408854C37E4F124B40503D997FF48939405082FE428F124B408093A641D18839406834D6FECE124B4080ABAE4335813940D8BB783F6E174B40F046753A90813940F8BD4D7FF6174B402083DC45988A3940D8949D7E50194B4000917EFB3A8C394030C3F17C061A4B40B01683876993394070AEEFC3411E4B40A09065C1C4933940508E0244C11E4B40B083F57F0E933940D009A1832E1F4B40D0656B7D91903940604F1F813F204B408018213CDA803940B04A94BDA5264B40309012BBB67F394008DC65BFEE264B4050DA1B7C617A3940B08FF98040274B4080CC79C6BE783940502B85402E274B4050780AB9527739403841B8020A274B4070C93846B27339405876FA415D264B40D0EB884336703940A89ECC3FFA244B4020240C03966C3940D082177D05234B40C055BABBCE6A39404855A18158224B4050BC9179E4673940A85CA8FC6B214B40A00DC00644643940282F3201BF204B4060D367075C5F3940B0E0F08288204B403002D53F8858394030172AFF5A204B40A004FD851E35394088931804561C4B40B0E7A4F78D333940901EA33CF31A4B4070CFBA46CB2D3940D0D38041D2174B4050D9E9077529394000E5284014164B40603D997FF4193940081E8A027D124B40C004FD851E15394030266F8099114B40D03DB2B96A123940F80E45813E114B40B0FE7A85050B3940706649809A104B40E0D38041D207394060672783A3104B4070AEEFC34106394008301004C8104B40C0E67283A1023940D0C1FA3F87114B40A00F5EBBB401394078758E01D9114B4010938D075B0039406007793D98124B40605B238271FC3840D8B22781CD134B40109694BBCFF93840882DE8BD31144B40209E25C808F83840A0923A014D144B4080C075C58CF43840582EC6C03A144B4050BFD2F9F0DC3840D8D03FC1C5124B40B074B0FECFD938405082FE428F124B40A0A52C431CD73840306BD44334124B40A0AEEFC341D6384008D9243FE2114B40B0ECF483BACC38409096E7C1DD0D4B4040BEA08504CC384008A0C37C790D4B40D04CF73AA9CB3840A89ECC3FFA0C4B40206893C327CD3840B04DD53DB20B4B40109C508880CF3840882766BD180A4B40A0069B3A8FD23840F8EAAA402D084B4040FF93BF7BD33840D858FB3BDB074B4030895E46B1D438402841B8020A074B40E049B6BA9CD63840B8B6D4415E054B40108E3D7B2ED73840885A457F68044B404058E20165D738408054C37E4F024B40C0FC6B79E5D63840B8E0F08288004B4040E44A3D0BD6384008A6457D92FF4A40A00DC00644D4384078AEEFC341FE4A40008BFCFA21D238405825034015FD4A4040C8957A16BC3840E0DF844204FC4A40E0F10A444FBA384078008BFCFAFB4A404002D53F88B838402844F98216FC4A404081CD3978B63840D8A96400A8FC4A40D0EEC9C342B53840703C2D3F70FD4A40C00DC00644B43840E076137CD3FE4A4000B2497EC4B33840A88FF98040FF4A406055A18158B238400000000000004B40C0E2C5C210B13840904E417E36004B4060DD5CFC6DAF3840484F1F813F004B40300ED940BA9C38405840DAFF00FF4A40901B62BCE6853840B08CB80034FA4A40D03C80457E813840D86740BD19F94A4080CC79C6BE783840D897DEFE5CF64A40E049B6BA9C76384028B7ED7BD4F54A40209E25C8086838405082FE428FF24A4060E09D7C7A64384010D9243FE2F14A40B083F57F0E63384050103CBEBDF14A40405E64027E61384008ACC77DABF14A40A0A52C431C473840904B00FE29F34A40603A58FFE7443840A84DD53DB2F34A40D034EF384543384008F7AE415FF44A40F01D8A027D423840D8EEC9C342F54A406055A18158423840089700FC53F64A409018213CDA403840C8A623809BF74A4000AF08FEB73E3840A8CB9BC3B5F84A4070A99F37153D384028F911BF62F94A409030293E3E3938404882FE428FFA4A40308A90BA9D35384078B130444EFB4A40903F6EBF7C3238404864E60297FB4A4070BFD2F9F02C38405016BEBED6FB4A40D0F3A8F8BF273840382CF180B2FB4A40E05147C7D5243840D09A1F7F69FB4A40C01F46088F22384080992842EAFA4A40B06E2EFEB61F3840203E7782FDF94A40F0419605131F384030266F8099F94A4010917EFB3A1C384060672783A3F84A40408C9FC6BD193840D870033E3FF84A40002A8E03AF1638409021E4BCFFF74A40D034EF3845133840A059D93EE4F74A40E02B2CB81F04384000BE4D7FF6F74A40705B238271FC3740F0EAAA402DF84A40D0E506431DE637408039ECBE63F84A40F0CABDC0ACC83740706F0C01C0F74A40208A90BA9DB5374080AEEFC341F64A40C0100187509937407878CF81E5F64A40F0DC43C2F79637405858E20165F74A40F046753A90913740E0EB884336F84A4060C763062A8B3740A05016BEBEF84A4080F414394484374038CCB4FD2BF94A4040E0F3C308813740C0EFDFBC38F94A4080A2EBC20F823740781EA33CF3FA4A4060A7CAF78C843740E87954FCDF034B4050D6A8876884374038E44A3D0B064B40D0FD0E45817E3740D061BEBC000F4B40F0DF8442047C3740508BC1C3B4114B40C0A17F828B753740D0E506431D164B4050732B84D5743740A85FE97C78164B40A00C1D3BA85C3740486A6803B01D4B4010ACC77DAB593740D8C43BC0931E4B4050CDE50643553740600ABABDA41F4B4020F6D03E56343740B8716F7EC3244B40C0ED26F8A61D3740D8DC43C2F7264B4010301004C800374058672783A3304B40F0E26F7B820037404801A260C6304B40F0FFFFFFFFFF364000E2E7BF07314B40F06A813D26FE364000274D83A2314B40B0F6E978CCFC3640B874B0FECF314B40308FE046CADE3640502EC6C03A344B40C0E847C329DB3640B0923A014D344B40809C69C2F6D736402844F98216344B40E0C77C40A0D3364058E960FD9F334B40D0B2B5BE48D0364030BA2EFCE0324B4010A6457D92CF3640001E8A027D324B40B06A65C22FC9364060855B3E922E4B4090129F3BC1C63640504F1F813F304B40C0ED26F8A6BD364008CD203EB0354B4050D158FB3BBB364000AF08FEB7364B40002A8E03AFB636403050FD8348384B400004577902B53640885704FF5B394B4010B2497EC4B336405055A181583A4B4040111AC1C6B136408045F0BF953C4B40B002EE79FEB03640C809A1832E3F4B40F0264D83A2B1364008BB0CFFE9424B4080ACE0B721B236408087A2409F444B40B08636001BB83640A09E3E027F584B40B0EAE5779AB83640B07D737FF5584B40108FE046CABE3640E0B22781CD5B4B40A00A7F8637CF364010A304FD85624B40405E64027ED13640D882177D05634B40E03B1405FAD43640F0E769C020634B40B05FE97C78D6364088B130444E634B40200B98C0ADD73640000072C284634B4040D9E90775D93640802DE8BD31644B40D04334BA83DC364030FC523F6F664B4060499D8026DE3640806F0C01C0674B4050DC2A8881DE3640604F1F813F684B4050DC2A8881DE364038F911BF62694B40201B498270DD36407836AB3E576B4B4090BAF3C473DA3640B08636001B704B4040D9E90775D9364038266F8099714B40200B98C0ADD736405034D6FECE724B40F052793BC2D53640D09A1F7F69734B40C09BFD8172BB3640584CDE00337B4B40103F558506BA3640109A417C607B4B40506F47382DB836400015C781577B4B4050E960FD9FB33640901EA33CF37A4B4060C6F7C5A5AE3640B86BED7DAA7A4B4090CC79C6BEA83640786CCB80B37A4B40A0AF21382EA736403835B401D87A4B40A0FB3905F9A5364038E78BBD177B4B40D05147C7D5A436400015C781577B4B4070431B800DA43640382CF180B27B4B4010FF93BF7BA3364038C9737D1F7C4B4000A304FD859A3640607FBDC282854B40C0073E062B9A3640D87FD6FCF8854B40D034EF3845833640B08636001B884B408009DCBA9B473640786649809A884B40A0A2EBC20F4236405801F73C7F884B40903F6EBF7C3236402038F581E4874B40802AA73D252F3640A86E2EFEB6874B4000A0C37C7925364038C632FD12874B40F05A0A48FB2336407878CF81E5864B40C0D03FC1C5223640082A8E03AF864B40A0F92AF9D8213640109700FC53864B40D058FB3BDB1F3640286893C327854B405040DAFF001F364030D505BCCC844B408015E0BBCD1B3640787B1002F2834B4040465C001A1936405864E60297834B40909065C1C4133640D89A1F7F69834B406037177FDB0F3640F8FF71C284834B40D0D6C1C1DE0C36405816BEBED6834B40C09BFD8172BB3540787E5182FE904B40607F2F8507B93540585E64027E914B40F050DB8651B8354078758E01D9914B4090AF21382EB73540786CCB80B3924B401021CB8289A735408878CF81E5964B40B07A32FFE8A33540500ABABDA4974B40F09C82FC6C9035407830293E3E994B4040FC523F6F6E3540584F1F813FA04B4000B2497EC4633540882DE8BD31A44B4070853FC39B6135406870067FBFA44B40E04E0647C95F3540303B3602F1A44B4020EBAA402D5E3540A81A683EE7A44B401060CAC0015D3540584C50C3B7A44B4090567C43E153354080A8FB00A4A24B40C0D6C1C1DE4C3540E8A9F23D23A14B40F0D38041D2473540584F1F813FA04B4000B8AF03E744354038594E42E99F4B403045813E91433540E81890BDDE9F4B40F0A3C519C3443540F887669E5CA14B40D067244223443540E803029D49A34B409090BA9D7D453540F0AEEC82C1A34B40E0548847E24935405070784144A44B40B0073E062B4A354040D505BCCCA44B40F025AAB7064A3540D8B5F63E55A54B4080A8DE1AD84635400046B41D53A94B404054A9D90341354058732B84D5AA4B4010CF842689413540C0045262D7AE4B40C09273620F3D354090BDDEFDF1AE4B40E046E7FC143B354000C4CF7F0FAE4B4030B49080D131354038384A5E9DAB4B4020B2101D022F354038384A5E9DAB4B40A057923CD72F3540701E4E603AAD4B404038F581E43D3540886308008EB54B4050CA6B25743F3540A00E2BDCF2B74B40C014747B493F354080B130444EBB4B4050E61F7D933E3540602EC6C03ABC4B40C01F46088F32354028266F8099C94B4030ED0DBE302535405861A5828AD64B4010A986FD9E24354000DC65BFEED64B4060B60F79CB1D3540B0D11DC4CEDA4B4080A86DC3281C3540A0622AFD84DB4B40C07D737FF518354058E09D7C7ADC4B40B00DC00644143540D8A0A17F82DD4B4010FF93BF7B1335408896E7C1DDDD4B40A0992842EA12354070336ABE4ADE4B40C057C9C7EE0E354050431B800DE44B40207A19C5720B3540807E5182FEF04B4030E78BBD170B3540F82CCF83BBF34B40C0FE7A85050B3540D8B5F63E55F54B4000917EFB3A0C3540588E0244C1F64B40308FE046CA0E35408803CC7C07F94B401039D384ED0F3540001E8A027DFA4B4060C1E10511113540B089778027FD4B40A0ABAE43351135408078CF81E5FE4B40209C5088800F354068FB743C66064C40308FE046CA0E354030BD6F7CED074C40A0B1683A3B0D3540E857E542E5094C40A077F17EDC0E3540E08BDAFD2A0A4C40A0F27684D3163540E0D03FC1C50A4C40B0F5B704E01B35408884D382170B4C40C06E2EFEB61F3540584CDE00330B4C4030809BC58B25354028D236FE440B4C40A03F6EBF7C323540A86BED7DAA0A4C40D0F78C4468343540506DA983BC0A4C40606A6803B0353540801EA33CF30A4C40C0D38041D2373540080072C2840B4C40004818062C393540A0923A014D0C4C40B0A4C002983A3540E0CDFE40B90D4C4010179CC1DF3B3540886F0C01C00F4C4070C8957A163C354080A2EBC20F124C40407288B8393D3540080FB743C3144C4050E61F7D933E3540600438BD8B154C40D053E57B46423540B077F17EDC164C401002D53F8858354050499D80261E4C40D04BC5C6BC5A354000AF08FEB71E4C40505B2382715C3540E876137CD31E4C40209D82FC6C603540A877F17EDC1E4C40C01F46088F623540E876137CD31E4C40A02DE8BD31643540082A8E03AF1E4C407039ECBE63683540B84A94BDA51E4C40D0DF8442046C354060137D3ECA1E4C40A01C0588826D3540D8DC43C2F71E4C4020085740A1723540D058FB3BDB1F4C4070C1E1051191354028327381CB254C40C0923A014DBC354020F911BF62294C40C0F3A8F8BFE73540A08FF980402F4C40E0548847E209364048732B84D5344C40D04334BA830C3640E0EEC9C342354C40A0ABAE433511364000CD203EB0354C4070C93846B2233640B0AD11C138364C400021CB8289273640F81186014B364C40C00A7F86374F3640B04DD53DB2334C4060D158FB3B7B3640D8DF844204344C40B014747B497F3640D8DF844204344C40603A58FFE7843640F8B1497EC4334C40E0CDFE40B98D3640904B00FE29334C4090AEEFC34196364008A304FD85324C40A00C1D3BA89C3640D0D90242EB314C4010A6457D929F3640E0C1FA3F87314C4010301004C8A03640D80F238447314C40E0D03FC1C5A23640E0CABDC0AC304C40B0716F7EC3A436405822C2BF08304C4030780AB952A73640D861BEBC002F4C40B010018750A9364058FB743C662E4C409015E0BBCDAB3640781B62BCE62D4C40B002EE79FEB0364078698A00A72D4C40A09065C1C4D336403802D53F88304C404077D84466D63640B87D737FF5304C40C0EAE5779AD83640E0C1FA3F87314C40F0907EFB3ADC364028BA2EFCE0324C4010BB0CFFE9E23640B8BF97C283344C40506DA983BCEA364028B7ED7BD4354C40200516C094ED3640284A7B832F364C40F041960513EF3640089700FC53364C40A002EE79FEF0364088AEEFC341364C40C03DB2B96AF2364038E44A3D0B364C4000A986FD9EF43640607FBDC282354C408045F0BF95FC3640D082177D05334C40F06A813D26FE36407854C37E4F324C405070EA03C9FF364088457EFD10314C40108BFCFA21023740B077F17EDC2E4C400015C78157033740507FBDC2822D4C40A087A2409F043740180ED940BA2C4C4020857AFA08083740D8D03FC1C52A4C4050AA0B789909374080A2EBC20F2A4C4060B60F79CB0D3740D8F71A82E3284C40C05CA8FC6B11374030EACC3D24284C40B0EAE5779A183740902AA73D25274C40D04BC5C6BC1A374078A52C431C274C4010917EFB3A1C3740A88FF98040274C402094BF7B4721374008EBAA402D284C40706A6803B0253740C80F238447294C4070499D80262E3740502EC6C03A2C4C4040FC523F6F2E3740D0A96400A82C4C40803C2D3F702D3740283B3602F12C4C40A015E0BBCD2B3740D0031F83152D4C4090FE7A85052B374000A0C37C792D4C4000369204E12A3740E07FD6FCF82D4C40A015E0BBCD2B3740F89600FC532E4C4080C6F7C5A52E3740F8298E03AF2E4C408015E0BBCD4B3740A85016BEBE304C40C0D90242EB513740E0CABDC0AC304C40A024253D0C553740B8380EBC5A304C40002DCF83BB5B3740A08FF980402F4C4070499D80265E3740808D2441B82E4C40D0E2C5C210713740802DE8BD312C4C4040F6D03E56743740A87A32FFE82B4C40C05FE97C78863740D8D03FC1C52A4C40A0A86DC3288C37403835B401D82A4C40A00A7F86378F3740E0E847C3292B4C40A05CA8FC6B913740B84DD53DB22B4C40902DE8BD31943740600DFB3DB12C4C40E0488446B0953740507FBDC2822D4C408093A641D1983740D097DEFE5C2E4C409015E0BBCD9B3740B0C519C39C2E4C40F05E7D3CF4B9374078AEEFC3412E4C4060EFE2FDB8BD374010E52840142E4C4020861DC6A4DF374020179CC1DF2B4C4000BB0CFFE9F2374010A304FD852A4C4070CFBA46CBFD3740D8949D7E50294C40108BFCFA21023840582E54FEB5284C40D04F38BBB510384038232E008D244C40A083F57F0E13384058431B800D244C40F0D03FC1C5223840A874B0FECF214C40F0325184D4253840905D86FF74214C409074B0FECF293840B85CA8FC6B214C40D0D6C1C1DE2C3840508BC1C3B4214C40F07876F9D64338408824253D0C254C4060C2137AFD513840B0BC564277274C409024253D0C553840886F0C01C0274C40D0DC43C2F75638406070EA03C9274C40201808026458384008A6457D92274C40D03A71395E5D384098C519C39C264C40C002EE79FE60384020B7ED7BD4254C40F040F339776738403044F98216244C40A008707A176B38408836AB3E57234C403098A3C7EF6D384008BB0CFFE9224C40A083F57F0E73384000A304FD85224C40E04718062C793840B83E90BC73224C4010369204E17A384000A304FD85224C40D057C9C7EE8E3840583A58FFE7244C40A001BC051290384030ED0DBE30254C40B004FD851E9538408821E4BCFF274C4040D026874F9A3840E0066003222A4C40B08FF98040A73840D876137CD32E4C4060CBD6FA22E1384000FAEFC16B394C40A02DE8BD31E43840508BC1C3B4394C40009700FC53E6384000ACC77DAB394C4010BE4D7FF6E7384058E3DEFC86394C4050DA1B7C61EA3840807E5182FE384C4040C8957A16EC384028D5777E51384C4070ABAE4335F138402044F98216344C40D05B3CBCE7F43840B87D737FF5304C40C019C40776F83840885182FE422D4C4080BB253960FB3840E0066003222A4C40004B598638FE38403041B8020A274C40200000000000394020B7ED7BD4254C40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('LO','SK','SVK','703','Slovakia','4808','5386995','150','151','19.491','48.707','0106000020E6100000010000000103000000010000009301000099D711876C403140514CDE00330348409F0436E7E03D3140A7B0524145034840FB230C03963C31402B14E97E4E0348407E18213CDA3031407E1EA33CF3024840FD1186014B2E3140FD4AE7C3B3024840276893C3272D3140FC1D8A027D0248402383DC45982A314029266F80990148407D96E7C1DD1D3140253B3602F1044840A8716F7EC31431402B14E97E4E0B484092AE997CB31131408FA50F5D501148400E2C47C8400A3140BD6DA6423C1248401D5A643BDF073140E469F981AB124840A4FB3905F9053140D5AF743E3C1348407EE200FA7DFF30409C8C2AC3B81548407E8AE3C0ABF93040286552431B184840FE0B040132F43040A9A44E40131F484082FDD7B969F330402AE109BDFE2048406C5B94D920F33040BFD7101C97234840D63A71395EED3040D57954FCDF234840562B137EA9EB304027F6D03E56244840295C8FC2F5D83040530438BD8B2D4840FC17080264D830407E1B62BCE62D48408109DCBA9BD73040508E0244C12E484054C554FA09D73040520ABABDA42F48407AA52C431CD730407EC9C6832D30484029E78BBD17DB3040D3C1FA3F87394840505260014CDD30407F15E0BBCD3B4840027FF8F9EFDD3040FE0B0401323C4840D63730B951E83040D3F71A82E3404840CD57C9C7EEEE3040FE0B040132444840D13C80457EF1304027F911BF624948405A10CAFB38F23040C310397D3D4F48407B9FAA4203FD3040266E15C4405748405531957EC2053140D009A1832E5F4840533D997FF4093140533D997FF4614840FC8F4C874E0B3140FFCF61BEBC624840267156444D1C31407E54C37E4F6A4840276893C3271D3140A7E67283A16A484022A81ABD1A303140ABD1AB014A6F48407E1EA33CF33A3140FD4D2844C06F4840FC1A4982703D3140A86E2EFEB66F4840552E54FEB5403140A5BC5642776F484022895E46B1543140FED5E3BED56C4840FB928D075B603140823CBB7CEB694840D0D03FC1C562314027F911BF62694840A77A32FFE86331405473B9C150694840D236FE44656731405473B9C15069484050C763062A6B3140A774B0FECF694840552E54FEB5803140FE99417C606B48404FCDE50643A53140000341800C6D4840A7E9B303AEA73140000341800C6D4840FC1A498270AD3140000341800C6D4840FF9600FC53B63140A8E33103956D484052B81E85EBC131407F4E417E36704840FD14C78157C331407B6649809A704840FB20CB8289D73140D576137CD3764840FE0E45813EE93140FCE42840147E484059130B7C45133240E8A562635E85484084F1D3B8371F32405307793D988A48407B116DC7D4253240D4F19881CA8E48407F129F3BC1263240AA9B8BBFED8F48405628D2FD9C26324000CADFBDA39048406ADC9BDF30253240C3F5285C8F92484056BC9179E427324001BEDBBC71944840D1CABDC0AC283240276893C3279548404DD9E90775293240FD1186014B964840FB230C03962C32407C992842EA9A4840A7ECF483BA2C3240FDDB65BFEE9E48407B9FAA42032D324028F38FBE499F4840295FD042022E3240AA9B8BBFED9F48404FCDE50643353240AB59677C5FA44840AB5FE97C7836324082397AFCDEA44840D236FE44653732407B9FAA4203A54840A304FD851E45324055FB743C66A6484001857AFA084832402829B000A6A6484058AD4CF8A54E32402BDB87BCE5A64840257497C4595132407E5704FF5BA74840D6A9F23D23613240AC53E57B46AA4840286211C30E633240D2FD9C82FCAA484080812040868A3240A9A10DC006BA48407F15E0BBCD8B32405182FE428FBA4840AB59677C5F8C3240FD14C78157BB484000917EFB3A8C32407DCC07043ABD4840AB59677C5F8C3240FE47A643A7BD4840276893C3278D3240FF9600FC53BE48407A17EFC7ED8F3240556D37C137BF4840FA264D83A29132402920ED7F80BF4840A8716F7EC3943240A86E2EFEB6BF4840D0D38041D2A73240A8E0F08288C048407E1EA33CF3CA3240D673D2FBC6C14840CFD90242EBD93240A7AD11C138C248407C9C69C2F6F73240FE47A643A7BD484056BC9179E4F73240A6B915C26ABA4840A8E0F08288F83240D57954FCDFB3484057B3CEF8BEF832407C6308008EB3484052465C001AF93240A7B0524145B34840D4B837BF61FA3240D0D03FC1C5B24840FD1186014BFE3240FC1D8A027DB24840286552431B083340D28BDAFD2AB24840D0D38041D2273340514CDE0033B34840CE548847E2293340A7B0524145B34840D4BB783F6E2F3340D3BEB9BF7AB448402DCF83BBB3323340527FBDC282B5484055C2137AFD313340FF08C38025B7484052431B800D343340D47C957CECB8484082035ABA823D3340AA656B7D91C04840D2C43BC0933E3340A8AAD0402CC148407E9065C1C443334029E78BBD17C3484029ED0DBE304533407C6308008EC348407F129F3BC1463340A77A32FFE8C34840A7E67283A1723340543A58FFE7CC48400473F4F8BD7933402CD505BCCCCC48405ED6C4025F85334001C11C3D7EC94840CC5D4BC80789334029232E008DC44840514CDE0033933340D482177D05BB484084F4143944943340FC1D8A027DBA4840ABEAE5779AA8334052431B800DB448407E1B62BCE6B53340AB984A3FE1B24840A8716F7EC3C43340D00CE2033BB4484001857AFA08C8334056F5F23B4DB4484083F755B950C93340D00CE2033BB448404ED026874FCA334052431B800DB44840A96BED7DAACA33407E9065C1C4B348402B69C53714CE3340FA298E03AFAE4840D2C77C40A0D333402BDEC83CF2A3484057B08D78B2D3334000C79E3D97A34840A9DDAF027CD33340D5AF743E3CA348400282397AFCD233407C992842EAA24840AC53E57B46D23340FD4AE7C3B3A24840267156444DCC33402B172AFF5AA048402AE44A3D0BC63340AB9509BFD49D484052431B800DC43340D2C77C40A09B4840D82B2CB81FC43340A7B05241459B4840FB95CE8767C53340A6B915C26A9A4840D236FE4465C73340D4EE5701BE994840FF05820019CA33407AABAE4335994840FE99417C60CB3340D6A9F23D23994840A6F27684D3D63340A8E0F0828898484057B3CEF8BED83340AA656B7D9198484011DF89592FDE33405F7F129F3B994840FC17080264E83340520DFB3DB19C48400473F4F8BDE93340D388997D1E9D48402383DC4598EA3340505260014C9D4840A86E2EFEB6EF3340A8E33103959D4840D3C1FA3F87F93340D1031F83159D484051BEA08504FC334082397AFCDE9C484004763579CAFE3340AB59677C5F9C48403BC8EBC1A400344045F5D6C0569B48404FCDE50643053440D3C1FA3F87994840D925AAB7060A34407EC9C6832D984840FE9C82FC6C103440508E0244C1964840286211C30E133440A9DA6E826F964840CE5147C7D5143440A9DA6E826F9648405531957EC21534407E8D2441B89648402BDB87BCE5163440FB20CB8289974840D540F3397717344052465C001A9948407C9C69C2F6173440FD14C781579B4840FA980F08741A3440D0D38041D29F4840A8716F7EC3243440A7B393C151A84840543A58FFE73434407C6308008EAB4840A77A32FFE853344080457EFD10B14840267156444D5C34407E54C37E4FB248404ED026874F9A3440A7E67283A1B248402DCC423BA7BD3440D673D2FBC6B148407D21E4BCFFCF34405055A18158AA4840D82E6D382CE934407E1B62BCE6A548402383DC4598EA34407E1B62BCE6A5484022895E46B1F434405628D2FD9CA64840A4FE7A8505FB3440A5BC564277A748402BDEC83CF2FB3440FD4D2844C0A7484052465C001A0935402AE44A3D0BAE4840800C1D3BA80C354027F6D03E56B44840AD50A4FB390D3540A8716F7EC3B44840D6A9F23D23113540AB9509BFD4B54840A9DDAF027C133540A7AD11C138B64840D236FE44654735402A1DACFF73BA4840295C8FC2F5483540D4B837BF61BA4840DFC325C79D663540E71BD13DEBB64840A86E2EFEB66F3540AA9ECC3FFAB44840A5F8F884EC7035402CD505BCCCB44840A968ACFD9D7535407F87A2409FB44840266E15C44077354051888043A8B44840A8E0F08288783540FED5E3BED5B448404FCAA486368035402AE44A3D0BB64840ABEAE5779A8835405340DAFF00B74840D5AF743E3C9B35402638F581E4B74840A9DA6E826F9E35405437177FDBB74840D13FC1C58AD635407AABAE4335B148407A1A3048FAF43540282CF180B2AB48407B116DC7D4F5354053793BC269AB4840CE5147C7D5043640AA622AFD84A34840FD9FC37C790536405307793D98A24840AB5FE97C78063640520ABABDA49F4840D6AC33BE2F063640505260014C9D4840FF9600FC53063640A8716F7EC39C48405628D2FD9C06364056F5F23B4D9C48402DD2C43BC0073640AA622AFD849B48407E8AE3C0AB093640D2FD9C82FC9A48407AA86DC3280C36405307793D989A484058AA0B78993936407F15E0BBCD9348407C992842EA523640D4EE5701BE914840D0D38041D25736402CD8463CD99148405534D6FECE5A364029266F80999148408200193A7688364054FEB5BC728B48407B14AE47E18A3640286211C30E8B4840A777F17EDC8E3640D28BDAFD2A8A48402A7288B8398D36407D24253D0C854840533D997FF48936402638F581E47F4840D3C1FA3F8789364051DD5CFC6D7F484057B3CEF8BE8836407AA52C431C7F4840D540F33977873640FDDB65BFEE7E4840CDE506431D76364050E3DEFC86794840A9F6E978CC6C364079758E01D9714840D2C77C40A06336402541B8020A674840D2C77C40A06336402AE44A3D0B664840514CDE0033633640A8E3310395654840A8716F7EC354364024D5777E515848407B2DE8BD3154364027BD6F7CED57484056B950F9D7523640D009A1832E5748407DB262B83A3C3640F9BD4D7FF64F48404F5B2382712C364022179CC1DF4B48404C6DA983BC2A364024D236FE444B4840D1CABDC0AC283640AC53E57B464A4840514F1F813F283640A774B0FECF494840F9BD4D7FF6273640552E54FEB5484840A73D25E7C4263640EECC04C3B9344840D13FC1C58A26364056F5F23B4D344840AB59677C5F1C3640D1CABDC0AC304840D925AAB7061A3640D5B2B5BE48304840ABEAE5779A1836407EC9C6832D304840A4FB3905F9153640FC170802643048402DCF83BBB312364052465C001A3148404DDC2A88810E364001C11C3D7E314840FB20CB828907364029266F809931484054C554FA09F73540D3F71A82E33048407F8461C092EF3540A8E0F0828830484052B5DD04DFDC3540D4F19881CA2E4840D4B837BF61DA3540AB5FE97C782E484083F755B950D9354079AEEFC3412E4840FC17080264D835407E1B62BCE62D4840A4FB3905F9D53540253B3602F12C484052431B800DD435407F15E0BBCD2B48400282397AFCD235407C6308008E2B48407D93A641D1C8354000C79E3D972B484054C554FA09C73540D2C77C40A02B4840D5AF743E3CBB3540253B3602F12C4840D925AAB706BA3540D388997D1E2D48407C9C69C2F6B73540A968ACFD9D2D4840AB5FE97C78B6354079AEEFC3412E4840F92F1004C8A03540D3C1FA3F87394840D4BB783F6E9F35402BDEC83CF23B4840D4BB783F6E9F3540000341800C3D4840FF08C380259F35408048BF7D1D3E4840A777F17EDC9E3540D2C43BC0933E48407D96E7C1DD9D3540D4BB783F6E3F4840AD50A4FB399D3540FED2A23EC93F48402CD8463CD981354079AEEFC341464840A7E67283A17235407D5D86FF74494840257497C459713540FA264D83A249484083FA96395D6E3540D4EE5701BE494840FCE1E7BF074F354052499D80264648402AE109BDFE4035402635B401D8424840266E15C440273540AB5CA8FC6B414840A968ACFD9D153540D4EE5701BE41484059A7CAF78CF43440AB984A3FE14248402B6C06B820F33440D482177D05434840552E54FEB5F03440FE99417C604348407E8D2441B8DE34407C60C77F81464840CC5D4BC807D9344029EACC3D24484840A6F27684D3D63440A8AAD0402C49484059A7CAF78CD4344029266F8099494840D446753A90D13440D673D2FBC6494840CF4E0647C9CF3440A774B0FECF4948405628D2FD9CB634407E18213CDA48484052465C001AA93440286552431B48484029ED0DBE30A53440A7E9B303AE474840A3073E062B8A3440A7ECF483BA4448404FCAA48636803440AA656B7D914048405437177FDB7F3440EC8497E0D43D4840FB95CE8767753440AC53E57B463A4840D446753A907134407B6649809A3848407F8461C0926F34402920ED7F803748402383DC45986A3440D57954FCDF3348404DD9E907756934402A1DACFF733248402DD2C43BC06734402920ED7F802F4840AC5626FC52673440A9DA6E826F2E4840D13FC1C58A663440527FBDC2822D4840027FF8F9EF5D3440FB20CB82892748402BDEC83CF25B3440A9DA6E826F264840266E15C4405734407F87A2409F2448407AABAE43355134408081204086224840A7ECF483BA4C344052465C001A214840CF4BC5C6BC4A34407B6649809A20484027F911BF624934405401F73C7F2048402DD2C43BC0473440A8E0F082882048407F129F3BC1463440F92F1004C8204840267156444D3C3440514CDE0033234840CD5A0A48FB233440253B3602F11C484056BC9179E417344027F911BF62194840F3AB3940300F3440F702B34291164840A77A32FFE803344055FB743C66164840FF93BF7B470134408048BF7D1D1648404DD9E90775F9334052431B800D144840FA298E03AFF63340D5AF743E3C134840D6A9F23D23F13340A4C2D84290114840A301BC0512F033405473B9C15011484050C763062AEB334000CADFBDA310484058AA0B7899E933407B6649809A104840FC17080264E83340D1CABDC0AC104840AC5626FC52E73340D3F71A82E3104840533D997FF4C93340266E15C4401748407B14AE47E1CA3340552E54FEB51848408081204086CA33407AABAE43351948407E8AE3C0ABC9334001C11C3D7E194840ABEAE5779AC83340D4EE5701BE194840FF93BF7B47C133405534D6FECE1A4840D3C1FA3F87A93340FFCC203EB01D48407A1A3048FAA43340D3FA5B02F01D4840AB5CA8FC6BA13340D3FA5B02F01D48401651137D3E8A3340ABD1AB014A1B4840E2B19FC5528833403D80457EFD1A4840D6AC33BE2F8633405055A181581A4840276BD4433482334052499D8026164840FE9C82FC6C803340D5AF743E3C13484023861DC6A47F3340508BC1C3B4114840D2C43BC0937E3340A7B393C151104840A4FE7A85057B3340D00CE2033B0C4840D05E7D3CF479334053793BC2690B484021956247E37833407F4B00FE290B4840FB3C4679E6753340D2FD9C82FC0A4840579412825535334004E8F7FD9B0748405D6DC5FEB22333405B79C9FFE40748400CC9C9C4AD0A3340DD60A8C30A0948404777103B53003340D576137CD30848400F9D9E7763FD3240B343FCC39608484097900F7A36F73240B0AA5E7EA70748407A1A3048FAE832407D5D86FF74074840462234828DE73240A41AF67B6207484059198D7C5ED932406000E143890648403719558671D7324072C45A7C0A06484085D21742CED33240B4C876BE9F04484024809BC58BC5324000C79E3D97FB47402DCF83BBB3C2324000C45DBD8AF64740FC1D8A027DC23240D47FD6FCF8F54740AC53E57B46C232407AA86DC328F44740D53DB2B96AC23240562B137EA9F3474027F6D03E56C432402B172AFF5AF04740A304FD851EC532407D21E4BCFFEF474079AEEFC341C63240FED2A23EC9EF47407E8AE3C0ABC932407F8461C092EF47405534D6FECECA3240AC5626FC52EF474052B81E85EBD13240527FBDC282ED47408081204086DA3240A7E67283A1EA474029E78BBD17DB3240AC53E57B46EA4740D3C1FA3F87D93240D1CABDC0ACE847400473F4F8BDC932407B6649809AE8474052431B800DC43240FC17080264E84740DFDC5F3DEEBF3240E945ED7E15E847400188BB7A15BD32407E5704FF5BE74740AA622AFD84BB32402AE44A3D0BE64740FF05820019BA32407E5182FE42E547408200193A76B832407F87A2409FE44740F92F1004C8B032405307793D98E2474052B5DD04DFAC324029266F8099E14740F92CCF83BBAB324027F911BF62E147402DD2C43BC0A7324052465C001AE14740286211C30EA33240A8AAD0402CE14740037CB779E39832407E8AE3C0ABE14740FA980F08748A324028F04E3E3DE24740D2C77C40A0733240AC53E57B46E24740D53DB2B96A723240D28BDAFD2AE24740A774B0FECF6932405401F73C7FE04740A5F8F884EC603240520ABABDA4DF47402577D84466563240D576137CD3DE47407A17EFC7ED4F3240A9DA6E826FDE4740D7A6B1BD164C32405376FA415DDE4740008BFCFA21323240A86E2EFEB6DF4740800F5EBBB4213240D1CABDC0ACE047404DDC2A88811E3240D3F71A82E3E047402AE44A3D0B1632407AABAE4335E14740CE548847E2F93140D4EE5701BEE147402383DC4598EA3140D5B2B5BE48E047407F129F3BC1E631402638F581E4DF4740A968ACFD9DE53140CA8B4CC0AFDF47401D93C5FD47CA3140077E54C37EDF474025B03907CFC8314000C79E3D97DF4740FF9600FC53B63140A7E67283A1E24740A4349BC7617C31409F77634161F04740D236FE4465773140508BC1C3B4F1474029ED0DBE30753140A96BED7DAAF247407C992842EA723140FE0B040132F4474081069B3A8F7231407F87A2409FF447407AABAE4335713140D4B5F63E55F54740E4BED53A716931400F7BA180EDF84740A4FE7A85055B3140D2C43BC093FE4740008E3D7B2E573140A7E9B303AEFF4740A4FB3905F9553140FED2A23EC9FF47405437177FDB4F3140FD4D2844C0FF4740A4FB3905F94531407F4E417E3600484057B08D78B243314000CADFBDA3004840D0D03FC1C5423140D47C957CEC00484051C1E105114131407BA2EBC20F02484099D711876C403140514CDE0033034840'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('LS','LI','LIE','438','Liechtenstein','16','34598','150','155','9.555','47.153','0106000020E6100000010000000103000000010000001C000000A051BAF42F11234011A8FE4124A3474055C2137AFD212340556D37C1379F4740A777F17EDC3E2340A7B052414593474059A7CAF78C442340552E54FEB59047402F51BD35B04523407E5182FE428D4740020D36751E4523407AA86DC3288C4740D6A9F23D23412340286211C30E8B47408200193A763823402AE109BDFE884740000341800C352340FE9C82FC6C8847405F7B6649803223408AABCABE2B884740CCD24ECDE5162340295C8FC2F588474008E6E8F17B132340295C8FC2F5884740772CB64945032340D5B2B5BE488847408200193A76F82240D0D38041D28747406FF1F09E03F3224090F63FC05A8747404FCDE50643052340D3F4D901D78B47402577D84466062340FED5E3BED58C47403048FAB48A062340295FD042028E47407B116DC7D40523407F8461C0928F474056B950F9D7022340823CBB7CEB914740C8EA56CF49FF2240562B137EA99347402E54FEB5BCFA224029ED0DBE30954740A27C410B09F822405340DAFF0097474056BC9179E4F722407B6649809A98474057B3CEF8BEF82240FA264D83A2994740304B3B3597FB22407C6308008E9B4740D6A9F23D23012340A968ACFD9D9D4740A051BAF42F11234011A8FE4124A34740'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('MK','MK','MKD','807','The former Yugoslav Republic of Macedonia','2543','2033655','150','39','21.698','41.6','0106000020E610000001000000010300000001000000DB000000276BD44334D2344027F6D03E567444405437177FDBCF3440FD14C78157734440FC1A498270CD3440514CDE00337344405055A18158C234407E9065C1C47344407E18213CDAC03440D57954FCDF734440FD1186014BBE3440FE0B04013274444011AB3FC230BC34405CE509849D744440A5F5B704E0BB3440A7ECF483BA744440AA622AFD84AB3440A7B05241458B4440A7E9B303AEA734407C6308008E8B44406D8D08C6C199344027BD6F7CED8B444052431B800D943440FED5E3BED5944440543A58FFE7843440FB20CB82899F4440D04543C6A3803440813FFCFCF7A64440A777F17EDC7E3440FCE1E7BF07A9444052499D80267E3440D4B837BF61AA44405340DAFF007F34402BDEC83CF2AB44404ED367075C7F344001BEDBBC71AC4440AA656B7D9180344029232E008DAC4440D6AC33BE2F863440FED5E3BED5AC44402CD505BCCC8C3440FD4D2844C0AF44407A17EFC7ED8F3440282CF180B2B344407D21E4BCFF8F3440D00CE2033BB44440A86E2EFEB68F344051888043A8B44440276BD443348234402635B401D8BA444057B3CEF8BE783440A86E2EFEB6BF4440514F1F813F783440286552431BC044407E1B62BCE6753440A9A10DC006C24440FD9FC37C79753440A6B915C26AC2444029ED0DBE307534402635B401D8C244404FCDE50643753440FE99417C60C34440AC5626FC527734407AA52C431CC74440D1CABDC0AC883440FE0E45813ED14440D2C77C40A0833440276893C327DD444027F6D03E56843440556D37C137DF4440A304FD851E853440D5B2B5BE48E04440ABEAE5779A88344054FEB5BC72E34440C806D2C5A69134403D7D04FEF0EF4440195932C7F29634406AFAEC80EBF04440A4FE7A85059B3440266E15C440EF444082035ABA829D344055FB743C66EE44407F8461C0929F34407E1B62BCE6ED4440800F5EBBB4A13440530438BD8BED4440037976F9D6B33440A8E3310395ED4440D13FC1C58AB63440FE47A643A7ED4440533D997FF4B934408048BF7D1DEE4440562B137EA9BB3440D2C43BC093EE44404DDC2A8881BE34402638F581E4EF444050C422861DC63440A968ACFD9DF5444051BB5F05F8C63440AB5FE97C78F64440266E15C440C734405340DAFF00F74440D236FE4465C73440286552431BF84440008E3D7B2EC73440A8AAD0402CF944400282397AFCC23440A7ECF483BAFC4440D53DB2B96AC23440A968ACFD9DFD44405055A18158C23440FF08C38025FF4440000341800CC53440FD9FC37C79054540A968ACFD9DC534407C60C77F81064540295C8FC2F5C83440A4C2D842900945407E1EA33CF3CA34405182FE428F0A45407F15E0BBCDCB34407C992842EA0A454004763579CACE3440AA622AFD840B454028F04E3E3DEA34407E5704FF5B0F45405534D6FECE1A35407D5D86FF74194540027FF8F9EF1D3540823CBB7CEB1945407E18213CDA203540823CBB7CEB194540276BD44334223540D673D2FBC619454027F6D03E5624354055F833BC591945407AA52C431C373540514CDE0033134540ABEAE5779A3835405307793D981245402B69C537144E35407C992842EA12454083FA96395D4E3540FE99417C60134540AD4D637B2D583540552E54FEB518454052465C001A593540FCE1E7BF071945405531957EC275354029266F8099214540D540F33977773540A9A10DC006224540FE99417C607B3540AC53E57B4622454058AD4CF8A59E3540A8E0F08288204540A9DA6E826FAE3540FA298E03AF1E45404DD6A88768B4354027327381CB1D4540A4FB3905F9B53540D1CDFE40B91D4540D1CABDC0ACB8354027327381CB1D45407B9FAA4203BD354055FB743C661E4540D236FE4465C73540D3F71A82E3204540CE548847E2C93540508BC1C3B4214540D5AF743E3CCB354029E78BBD17234540FE99417C60CB3540562B137EA9234540A7ECF483BACC3540FE47A643A72545404DDC2A8881CE3540D576137CD3264540D236FE4465D73540A9A10DC0062A45407E8AE3C0ABD935405055A181582A4540A4FE7A8505DB3540D4B837BF612A45402AE44A3D0B063640AA656B7D912845405437177FDB0F3640FA298E03AF264540FC1D8A027D123640AB5FE97C78264540D4B5F63E55153640AB5FE97C7826454028F38FBE492F36407EC9C6832D28454052B81E85EB3136402B172AFF5A2845407C992842EA3236405401F73C7F284540A8716F7EC3343640295C8FC2F5284540A4FB3905F9353640D4EE5701BE294540AB5FE97C78363640D28BDAFD2A2A45407F129F3BC1363640FD4AE7C3B32A4540D236FE44653736407F4B00FE292B45407C9C69C2F6373640A9DDAF027C2B45407D93A641D1383640F92CCF83BB2B45405340DAFF004F36408048BF7D1D2E4540286211C30E53364079AEEFC3412E454029ED0DBE305536407D96E7C1DD2D45407E1B62BCE6553640530438BD8B2D454082035ABA825D36407D5D86FF74294540FC170802646836407E9065C1C423454059A7CAF78C8436402B14E97E4E134540FB95CE8767853640D482177D0513454051BEA085049C36407DCC07043A0D45407F8461C092AF36402B172AFF5A084540FF93BF7B47D136407C6308008E034540D82B2CB81FD4364054FEB5BC720345404FCAA48636E03640A8E0F08288F84440F92F1004C8E03640520ABABDA4F74440D4B5F63E55E536405473B9C150F1444079AEEFC341E63640A8E0F08288F04440FF93BF7B47F1364002BB9A3C65E7444079AEEFC341F63640562B137EA9E34440A7E9B303AEF73640D482177D05E34440037CB779E3F836405534D6FECEE244407A17EFC7EDFF36405307793D98E24440FC1D8A027D02374028F04E3E3DE24440D734EF3845033740533D997FF4E144407E9065C1C4033740A4C2D84290E14440A7E9B303AE0737402AE44A3D0BDE4440FC170802640837407DCC07043ADD444001857AFA08083740D00CE2033BDC44408109DCBA9B073740F92CCF83BBDB4440A8716F7EC304374029266F8099D944407C992842EA023740FE9C82FC6CD84440800C1D3BA8FC36407DCC07043AD54440CE5147C7D5F43640D106600322D24440037976F9D6F336407AABAE4335D14440D2C77C40A0F3364029EACC3D24D04440D2C77C40A0F336407F87A2409FCC444024809BC58BF53640AA9ECC3FFABC4440D540F33977F736402638F581E4AF444051BB5F05F8F63640A777F17EDCAE4440A4FB3905F9F536407E1B62BCE6AD44407F87A2409FF4364029ED0DBE30AD4440FF93BF7B47F13640A8A78FC01FAC4440BD0166BE83EF36406F1283C0CAAB4440276893C327ED3640A77A32FFE8AB444029EACC3D24D036407F87A2409FAC444056B60F79CBCD36407D5A457F68AC444001857AFA08C836402A1DACFF73AA4440CF488446B0C53640D3C1FA3F87A944405589B2B794C336401878EE3D5CA84440FC1D8A027DC2364051853FC39BA74440D53DB2B96AC23640A9A44E4013A744402DCF83BBB3C236402829B000A6A64440A9DDAF027CC336405376FA415DA64440A77A32FFE8C33640D47FD6FCF8A544406B7F677BF4C236402A8C2D0439A044407BA2EBC20FC23640276893C3279D444083FA96395DBE3640543A58FFE7944440027FF8F9EFBD3640AB59677C5F944440AB59677C5FBC3640286211C30E934440A96BED7DAABA364080812040869244408200193A76B83640AC53E57B469244407AA52C431C9736407E5704FF5B8F44407E1B62BCE695364028F38FBE498F444022895E46B19436407E5704FF5B8F4440D7A6B1BD167C3640FB20CB82898F4440D734EF3845733640FB20CB82898F444028F38FBE496F3640FB20CB82898F444056BC9179E45736407AABAE4335914440295FD042024E3640D2C77C40A0934440514CDE0033433640AB9509BFD4954440800F5EBBB4413640D3FA5B02F09544407F87A2409F343640FD9FC37C79954440A4FE7A8505FB354052465C001A914440FE0E45813EF9354000CADFBDA39044408081204086EA3540FE0B0401328C444057B3CEF8BEE83540D3C1FA3F8789444052465C001AE935407B6649809A884440533D997FF4E9354028F38FBE49874440CE548847E2E93540D576137CD38644404DD9E90775E93540FF9600FC538644405534D6FECECA354002BB9A3C657744402DD2C43BC0C735402BDB87BCE576444058AA0B7899993540A86E2EFEB66F44404DD6A88768943540520ABABDA46F444056B950F9D7923540FD4D2844C06F444052B81E85EB9135407D21E4BCFF6F4440AB59677C5F8C35407BA2EBC20F72444027F911BF628935407F15E0BBCD734440ABEAE5779A883540A8A78FC01F7444408109DCBA9B87354027F6D03E56744440A9DDAF027C83354029232E008D744440257A19C5726B3540FE47A643A7754440D4B837BF616A3540FD9FC37C79754440D0D38041D2673540520DFB3DB1744440FF9600FC53663540D7A6B1BD16744440AB5CA8FC6B6135407E8AE3C0AB71444083FA96395D5E3540FE9C82FC6C704440FC8F4C874E5B3540AA9B8BBFED6F4440D0D38041D257354051853FC39B6F4440AA656B7D91503540D009A1832E6F44405628D2FD9C2635405531957EC26D444050AA7D3A1E1F3540D1CDFE40B96D44406BF12900C6FB3440F984ECBC8D6D44402BDEC83CF2FB3440D106600322724440A5F5B704E0FB3440D4B837BF61724440641EF98381FB34409BE7887C977244407D93A641D1F8344081423D7D0474444001857AFA08F8344056F5F23B4D744440000341800CF534407B9FAA4203754440800F5EBBB4F13440FE47A643A7754440D82E6D382CD93440FD4D2844C0774440266E15C440D734407E5704FF5B77444059A7CAF78CD434407D96E7C1DD754440276BD44334D2344027F6D03E56744440'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('MT','MT','MLT','470','Malta','32','402617','150','39','14.442','35.89','0106000020E61000000200000001030000000100000018000000202FDE8FDB1F2D4030E109BDFEE8414040068200190A2D4060FB743C66E64140206684B707D92C4000301004C8E84140803579CA6AC22C40E0A6B1BD16EC41408021E4BCFFBF2C40D0BEB9BF7AEC414020FEF0F3DFBB2C40301A6B7F67ED414000F86EF3C6B12C40B0E9B303AEEF414060B60F79CBAD2C40806649809AF04140A088450C3BAC2C40E8A9F23D23F14140208A592F86AA2C405882FE428FF241404077D84466A62C40B0BF97C283FC414020AE65321CA72C40485260014CFD414000E8154F3DAA2C40B8E3310395FD4140802634492CB92C4028DB87BCE5FE414000240C0396BC2C403041B8020AFF41408021E4BCFFBF2C40E076137CD3FE4140E079008BFCE22C4088992842EAFA414060CDE50643052D40A0DA6E826FF64140A0B3CEF8BE182D40386BD44334F2414000261B0FB6202D4038172AFF5AF04140C0703D0AD7232D4030F38FBE49EF414060B950F9D7222D40D88BDAFD2AEA4140800F5EBBB4212D4010C11C3D7EE94140202FDE8FDB1F2D4030E109BDFEE8414001030000000100000014000000205C8FC2F5882C40885D86FF7401424040261B0FB6802C40885D86FF7401424060D9E90775792C4000274D83A2014240605A80B6D5642C406034D6FECE024240C0CF0D4DD9612C40F0E769C0200342402009C380255F2C40607078414404424000240C03965C2C40B8A44E401307424040F52D73BA5C2C4010D3A23EC9074240800F5EBBB4612C406001F73C7F084240C01EA33CF36A2C40A8AAD0402C09424000B6F63E55752C4028266F8099094240009F20B1DD7D2C4008C11C3D7E094240C00F5EBBB4812C4060F833BC59094240C08B868C47A12C40D876137CD30642408023F3C81FA42C4008C45DBD8A06424080AD4CF8A5AE2C4028F6D03E5604424040DC2A8881AE2C409015E0BBCD03424000D68F4DF2AB2C40A8DDAF027C034240E0CCCCCCCC8C2C4010C11C3D7E014240205C8FC2F5882C40885D86FF74014240'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('BE','BE','BEL','56','Belgium','3052','10398049','150','155','4.664','50.643','0106000020E6100000010000000103000000010000007D0100001283C0CAA13511404D6A6803B0A14940274BADF71B3D1140B340BB438AA1494050340F60914F1140A1681EC022A549400070ECD973291140B0C8AF1F62A749408BE07F2BD92111407B6649809AA84940A1D79FC4E71E114040A4DFBE0EAC49407AFCDEA63F0B114078F17EDC7EAD49404B3ACAC16C021140042159C004B04940802A6EDC621E1140276BD44334B04940772CB6494563114055FB743C66AE49409A931799806F1140FCE4284014AE49407632384A5E8D11405531957EC2AD4940CBD8D0CDFEA0114027327381CBAD4940C2FBAA5CA8AC1140D47FD6FCF8AD49409F8EC70C54B61140FF9600FC53AE4940382EE3A606BA11402829B000A6AE494016A243E048C01140D200DE0209B04940A777F17EDCBE11405401F73C7FB049407F15E0BBCDAB1140D2FD9C82FCB249400307B474059B1140FB230C0396B44940179CC1DF2F961140A6B6D4415EB54940BB25396057931140FA264D83A2B9494054C554FA09971140533D997FF4B9494082035ABA82ED1140A6B6D4415EBD4940F04C689258F21140530438BD8BBD494090DB2F9FAC28124052499D8026BE494058AD4CF8A52E1240FCE4284014BE494007EFAB72A132124027327381CBBD4940F33AE2900D341240A6B6D4415EBD4940B05417F0323312402CD505BCCCBC49402B69C537142E1240D5AF743E3CBB4940AB59677C5F2C1240FFCF61BEBCBA494010CCD1E3F7261240823CBB7CEBB94940373465A71F2412407D93A641D1B84940373465A71F241240D5B2B5BE48B8494050C422861D2612407E5704FF5BB74940BF0D315EF32A12405628D2FD9CB6494044F98216123012407C60C77F81B64940FE0B04013294124052499D8026B6494043FF04172B9A1240D6AC33BE2FB6494018B5FB5580AF12404AD1CABDC0B649401AA3755435B11240FF08C38025B749406E4F90D8EEAE12402920ED7F80B74940C2FBAA5CA8AC1240FE9C82FC6CB8494084F1D3B837AF12407E18213CDAB849405EA27A6B60CB124054FEB5BC72BB4940FC1D8A027DD21240D7A6B1BD16BC4940313F3734650713407F8461C092BF4940D2C77C40A01313402B172AFF5AC04940F52EDE8FDB1F1340527C7C4276C04940266E15C440271340FC17080264C049404ED026874F3A1340AA9B8BBFEDBF49408DD47B2AA74D13405340DAFF00BF49408BE07F2BD9611340A8E3310395BD49403546EBA86A621340D388997D1EBD4940CBD8D0CDFE601340286211C30EBB4940A8716F7EC35413402541B8020AB74940D3C1FA3F87691340000341800CB54940354069A851B81340D482177D05B3494091D5AD9E93BE1340FBE769C020B3494056B950F9D7C21340FE99417C60B34940FC1D8A027DD21340D3BEB9BF7AB44940C9E4D4CE30F513407AA52C431CB749400000000000001440D200DE0209B84940DE921CB0AB091440D6A9F23D23B949406090F469150D1440D106600322BA494023861DC6A40F1440AB59677C5FBC4940257497C45911144082397AFCDEBC4940AD4D637B2D181440A8E3310395BD49404DD6A887682414405376FA415DBE494015A8C5E0612A1440FD1186014BBE4940CADE52CE174B1440AB59677C5FBC4940E57B4622345214407E9065C1C4BB49403546EBA86A62144052465C001AB94940BF0D315EF36A1440A7E9B303AEB74940E9633E20D06914407AA52C431CB74940BA313D6189671440FA298E03AFB64940304B3B35975B1440276893C327B5494097AB1F9BE4571440FED5E3BED5B4494052B81E85EB511440D7A6B1BD16B4494023861DC6A44F1440D2C77C40A0B349404DDC2A88814E1440286211C30EB349407920B248134F14405307793D98B24940E38DCC237F501440D106600322B24940BE13B35E0C55144027F911BF62B149400DE4D9E55B8F144080457EFD10A94940BB25396057931440F92F1004C8A849401F85EB51B89E1440FE9C82FC6CA8494018963FDF16AC1440514F1F813FA84940800F5EBBB4C114407E18213CDAA849401B9DF3531CC71440295C8FC2F5A84940A376BF0AF0CD1440D47C957CECA84940E199D024B1E414407EC9C6832DA8494084F1D3B837EF1440FD4D2844C0A74940B05417F032F31440A5BC564277A74940207F69519FF414405340DAFF00A749409160AA99B5F41440FCA5457D92A14940B937BF61A2511540A4C2D84290A149409A99999999991540253E7782FDA14940F52EDE8FDB9F15407BA2EBC20FA249400DDE57E542A51540D28BDAFD2AA24940B24813EF00DF1540FE0B040132A4494010CCD1E3F7E61540A7ECF483BAA449403145B9347EF115405531957EC2A54940276893C327FD15407E1B62BCE6A5494059A7CAF78C04164027327381CBA54940CADE52CE170B1640FFCC203EB0A54940D4B5F63E551516407E5182FE42A5494049D576137C331640AB984A3FE1A24940B6300BED9C3616408081204086A249400ED8D5E4293B1640D673D2FBC6A14940C8D11C59F9451640096F0F42409C4940FE0B0401329416407BA2EBC20F9A4940C5E3A25A44041740A7B393C151984940AB5FE97C785617407DCC07043A954940B2D826158D651740CEDF844204944940EC51B81E856B1740FD14C78157934940A7CCCD37A26B1740856055BDFC924940D0D38041D2671740276BD44334924940E199D024B16417402CD8463CD99149402F51BD35B04517407E8D2441B88E4940304B3B35971B17402B14E97E4E8349404DDC2A88810E17407E8D2441B87E4940F146E6913F081740AB984A3FE17A49405E9CF86A47A11640D1CABDC0AC7049409A99999999991640514F1F813F704940392861A6ED8F1640AB5FE97C786E4940363AE7A7388E1640D3FA5B02F06D4940CDCCCCCCCC8C1640FED5E3BED56C49407632384A5E8D1640AB59677C5F6C49404FCAA48636901640A9DDAF027C6B49409C8713984E9B1640A4C2D84290694940C8EA56CF499F1640D00F23844769494051BEA08504BC16405437177FDB674940828B153598C61640D3C1FA3F87674940637E6E68CACE1640FF08C3802567494052B81E85EBD11640FB230C03966449408A7615527ED216405985CD0017644940363AE7A738CE1640FBE769C0206349407BF8325184C41640D8D64FFF596149405EA27A6B60CB16402AE109BDFE6049401D91EF52EAF216407AABAE4335614940354069A851F816405473B9C150614940713D0AD7A3301740FC1D8A027D624940257A19C5727B174027F911BF626149409624CFF57D9817405401F73C7F604940207F69519FB41740F92F1004C860494001A260C6140C1840C89A9141EE604940A27C410B093818407F87A2409F5C4940D5AF743E3CAB184081423D7D04544940286211C30E131940D0D38041D24F4940D4B5F63E55151940FB20CB82894F4940179CC1DF2F161940D009A1832E4F4940BE13B35E0C151940D576137CD34E4940D1CDFE40B9FD184053793BC2694B49407920B248130F1940A86E2EFEB63F494011C64FE3DE3C1940FD4D2844C03F4940020D36751E451940FB20CB82893F49407E1B62BCE6551940FA298E03AF3E4940B5368DEDB5601940D47FD6FCF83D494051BEA085047C194027F911BF6239494091D5AD9E937E1940272F3201BF384940D4BB783F6E7F1940FC17080264384940A88B14CAC2971940717500C45D29494050C422861D661940D200DE0209284940DF8C9AAF921F194056F5F23B4D2449403145B9347EB118405531957EC21D4940D3C1FA3F87A918407F87A2409F1C4940D0D38041D2A7184027F6D03E561C49407920B248138F18407E9065C1C4134940887FD8D2A38918405376FA415D1049407B14AE47E17A1840D3F71A82E3104940CEC64ACCB3221840AB59677C5F144940F52EDE8FDB1F1840FB230C0396144940AF5A99F04B1D18407E5182FE421549408C4B55DAE21A1840D42AFA4333174940AB5FE97C78161840AC5626FC52174940363AE7A7380E1840556D37C137174940D0D38041D2E71740D3FA5B02F0154940CBD8D0CDFEE01740A8E33103951549400FD253E410911740A8E33103950D4940637E6E68CA8E1740D4B5F63E550D49408AE6012CF28B174051888043A80C4940F146E6913F8817407E54C37E4F0A4940F146E6913F881740FDD8243FE2094940AB5FE97C78561740FF9600FC53FE484015A8C5E0612A1740514CDE0033FB4840D9B0A6B2281C17405307793D98FA484083F755B950191740D4B837BF61FA4840D4B5F63E55151740A774B0FECFF94840D1CDFE40B9FD16407AA86DC328F4484044F9821612F01640AB984A3FE1EA4840FB230C0396FC164027327381CBE54840E76F422102FE1640FD9FC37C79E54840C007AF5DDA0017407E5182FE42E548400DE4D9E55B0F1740D388997D1EE54840BC1FB75F3E2917402BDEC83CF2E348404ED026874F7A1740A8A78FC01FDC4840C58F31772D811740E275FD82DDDA484057B3CEF8BE981740FED5E3BED5D448402D5DC136E2991740253E7782FDD14840DD989EB0C4731740A8AAD0402CC948402D5DC136E2591740A9DA6E826FC64840179CC1DF2F561740FD1186014BC64840B35E0CE5443B1740C5707500C4C54840D5AF743E3C2B17407D96E7C1DDC548407920B24813CF1640527FBDC282C548401B9DF3531C871640FB230C0396C44840DF8C9AAF925F1640FE99417C60C34840C8EA56CF491F1640AB5CA8FC6BC14840637E6E68CA0E1640D6A9F23D23C14840295C8FC2F5E81540A8E0F08288C048404DD6A88768E41540F92F1004C8C04840753E3C4B90E11540D6A9F23D23C1484070438CD7BCDA1540AC53E57B46C24840723106D671DC1540D0D03FC1C5C248400DDE57E542E51540A77A32FFE8C34840BA313D6189E71540AB59677C5FC4484010CCD1E3F7E61540FED5E3BED5C4484024809BC58BE515407E5182FE42C5484016A243E048C015402CD505BCCCCC48405DA8FC6B79B51540FFCC203EB0CD4840295C8FC2F5A815407C60C77F81CE4840AD4D637B2D981540FB20CB8289CF4840A83AE466B8911540CA8B4CC0AFCF4840286211C30E53154052431B800DD44840FB230C0396FC13407E8D2441B8E6484044F9821612F013405340DAFF00E74840179CC1DF2FD61340FA298E03AFE64840313F373465C71340A8E3310395E54840D1CDFE40B9BD13407DCC07043AE5484007EFAB72A1B21340000341800CE54840FA298E03AFA61340AA9ECC3FFAE448409F94490D6DA01340D1031F8315E54840E76F4221027E13402AE44A3D0BE64840207F69519F741340AC5626FC52E7484008E9297288481340A9A44E4013FF48400307B474055B13407E18213CDA084940E9633E20D0691340D00CE2033B0C49402F51BD35B08513407EC9C6832D10494008E9297288881340A8E0F08288104940CDCCCCCCCC8C1340F92F1004C8104940E869C020E9931340AB5CA8FC6B114940FE0B040132941340533D997FF4114940DBA4A2B1F68713407F15E0BBCD1349409D499BAA7B541340A8E331039515494005FBAF73D34613402A1A6B7F67154940AC53E57B464213407DCC07043A1549407632384A5E0D134055F833BC59114940DE921CB0ABC91240D2C77C40A00B49402F51BD35B0C51240A96BED7DAA0A4940AA656B7D91C0124052465C001A09494016A243E048C012407B6649809A084940723788D68AC61240AA9B8BBFED07494087F8872D3DCA12407AA52C431C0749401B9DF3531CC71240A6B6D4415E054940A27C410B09B81240514F1F813F00494047E7FC14C7B11240FB20CB8289FF4840B43C0FEECE0A1240D00F238447F948409C8713984EDB11407EC9C6832DF84840D4B5F63E55D5114029EACC3D24F8484008E9297288C81140FC17080264F848404C3448C153B81140DBBE47FDF5F84840266E15C440A7114001C11C3D7EF948406F490ED8D5441140A8A78FC01FFC4840E76F422102FE104054FEB5BC72FB4840C2FBAA5CA8EC1040514CDE0033FB4840C26A2C616DDC10408D96033DD4FA4840257A19C572BB1040AA9ECC3FFAFC48409599D2FA5BB21040637C98BD6CFD48402448A5D8D19810406B2DCC423BFD4840C1012D5DC1961040D00F2384470149409A93179980AF1040A4C2D842901149401B9DF3531CC7104055FB743C661E4940295C8FC2F5A81040D00CE2033B244940266E15C440271040527FBDC2822D4940E6EAC726F92110401AA88C7F9F2D494035272F3201DF0F40FE0B0401322C4940F2406491261E0F40AA622AFD842B494007EFAB72A1320E40505260014C2D494093C9A99D616A0D405307793D98324940616BB6F2925F0D40A5BC564277374940AF5A99F04B5D0D40FE9C82FC6C384940B03BDD79E2590D407E18213CDA3849409BAC510FD1480D40A6B915C26A3A4940D34ECDE506430D40C98E8D40BC3A4940E481C8224D3C0D4029E78BBD173B4940679B1BD313F60C40EECC04C3B93E494089D349B6BADC0C40A5BC5642773F4940F73B1405FA240C40A6B915C26A424940A38FF98040A70B407D5D86FF744149401F85EB51B89E0B407AABAE4335414940A29BFD8172FB0A407E5704FF5B3F494044F9821612F00A40D4BB783F6E3F49408ECEF9298E630A407E1EA33CF3424940AF5A99F04B5D0A40A7B05241454349403D0AD7A3703D0A40543A58FFE744494065726A67983A0A40D4B5F63E55454940C408E1D1C6F10940A5BF97C28354494044F9821612F00940527FBDC28255494041F2CEA10C950940D1031F83155D4940D4BB783F6E7F09407F8461C0925F4940444FCAA486760940E9B7AF03E7604940257497C459510940A77A32FFE8634940A088450C3B4C094056F5F23B4D644940E481C8224D3C0940543A58FFE764494007EFAB72A1320940D388997D1E65494024809BC58B2509407DCC07043A654940C4E9245B5DEE0840D4B5F63E55654940E675C4211B680840D57954FCDF6349405794128255550840A9DDAF027C63494059130B7C45370840CB82893F8A624940295C8FC2F5280840A7E67283A16249403C16DBA4A21108402A1DACFF7362494007D0EFFB37AF0740295C8FC2F56049405EA27A6B608B07402BDB87BCE55E494007D0EFFB372F0740253E7782FD5949408274B169A5F006409C53C900505B49406A6D1ADB6B410640552E54FEB560494087FE092E56340540527C7C42766849406E68CA4E3FC804407C60C77F8176494048E17A14AEC70440A5BC5642777F49405794128255550440562B137EA98B4940E675C4211B680440D3F4D901D78B4940A29BFD81727B0440D00CE2033B8C4940BA313D6189E706402B14E97E4E9B4940CBF78C4468A407407C9C69C2F69F4940295C8FC2F5280840FE99417C60A34940E97C789620C308405437177FDBA7494093AAED26F8E60840272F3201BFA8494010B3976DA70D094001C11C3D7EA9494044F9821612700940D482177D05AB49403196E99788F70A40EAB46E83DAAF4940276893C327FD0A40A7E9B303AEA74940B14E95EF19090B4054FEB5BC72A349408AE6012CF20B0B40D482177D05A34940E603029D491B0B40FC17080264A24940F54718062C790B402920ED7F809F494005DCF3FC69830B4028F38FBE499F4940C6FCDCD0949D0B402541B8020A9F4940382EE3A606BA0B40813FFCFCF79E494008E3A7716FDE0B40FF08C380259F4940A96BED7DAA2A0C40FD4D2844C09F4940B323D5777E310C40D38558FD11A04940DAAA24B20F320C407E8AE3C0ABA14940AE47E17A142E0C4029E78BBD17A34940A96BED7DAA2A0C40AA622AFD84A3494055A0168387290C4081423D7D04A44940D5AF743E3C2B0C40FB230C0396A4494007EFAB72A1320C40543A58FFE7A4494016C1FF56B2C30C402BDB87BCE5A649404DDC2A8881CE0C405340DAFF00A74940AF5A99F04BDD0C40FDDB65BFEEA64940DC7F643A745A0D40FD9FC37C79A54940E97C789620430E40823CBB7CEBA14940302C7FBE2D580E40D3C1FA3F87A1494035272F32015F0E407AABAE4335A14940D2C77C40A0530E405376FA415D9E4940D2C77C40A0530E40AB9509BFD49D4940B03BDD79E2590E4029232E008D9C494008E3A7716F5E0E40FE0B0401329C494049D576137C730E407E9065C1C49B4940460C3B8C491F0F405055A181589A4940AE47E17A142E0F40AC53E57B469A494065726A67983A0F405055A181589A49401F85EB51B89E0F4054FEB5BC729B4940EA5DBC1FB73F1040D5B2B5BE48A0494056B950F9D7821040282CF180B2A349400DDE57E542A51040FE47A643A7A549401AA3755435B11040AB5FE97C78A64940D9B0A6B228DC1040AC53E57B46AA4940E9633E20D0E9104000C79E3D97AB4940B95164ADA1F4104084D558C2DAAC4940CE8E54DFF9051140E3512AE109AB4940922232ACE20D11407E3672DD94A84940D49E9273621F1140068195438BA6494011C64FE3DE3C1140276893C327A549407D21E4BCFF3F11402CD505BCCCA44940AA656B7D9140114027F6D03E56A4494094DDCCE847331140F0DE516342A249401283C0CAA13511404D6A6803B0A14940'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('FO','FO','FRO','234','Faroe Islands','0','48205','150','154','-6.864','62.05','0106000020E6100000090000000103000000010000001300000040272F32019F1AC030D8463CD9B14E40C01281EA1FA41AC0488BC1C3B4B14E4000963FDF16AC1AC030D8463CD9B14E40407365506DE01AC088A86DC328B44E404061DF4E22621BC0A07A32FFE8BB4E400094128255D51BC08087A2409FCC4E40C03BDD79E2D91BC0386E15C440CF4E4080A3703D0AD71BC0B06E2EFEB6CF4E40801D537765C71BC010C11C3D7ED14E40C05D85949FB41BC00806820019D24E4080A23EC91DA61BC0E0B837BF61D24E40005D8AABCA8E1BC05882FE428FD24E40C0A7C5E061EA1AC0508BC1C3B4C94E408000FBE8D4E51AC028F911BF62C94E40003E05C078D61AC0B8BC564277C74E4040272F32019F1AC0D8BB783F6EB74E4080B06F2711911AC02814E97E4EB34E400016DBA4A2911AC03835B401D8B24E4040272F32019F1AC030D8463CD9B14E4001030000000100000013000000004A09C1AA6A1AC0A8AAD0402CE94E4080EB51B81E851AC0B85CA8FC6BE14E40801803EB388E1AC0D88558FD11E04E4080CB9A58E09B1AC0A8A44E4013DF4E404016DBA4A2D11AC0A0622AFD84E34E40402C7FBE2D581BC0C8CABDC0ACE84E404039B5334C5D1BC010CADFBDA3E84E4040B16A10E6761BC0504CDE0033EB4E4000A5660FB4A21BC00815C78157F34E404061DF4E22A21BC08015E0BBCDF34E4080C1C3B46F9E1BC0080C040132F44E4040C3F01131751BC078A86DC328F44E40403883BF5F6C1BC0D0A6B1BD16F44E400061DF4E22221BC05834D6FECEF24E40C0295778971B1BC05007793D98F24E4080BC732843A51AC0E0FA5B02F0ED4E4080CB9A58E09B1AC0585260014CED4E40004A09C1AA6A1AC0D0EE5701BEE94E40004A09C1AA6A1AC0A8AAD0402CE94E4001030000000100000022000000806F0B96EA321CC0E0CABDC0AC084F40801E85EB51381CC0A86E2EFEB6074F4000A243E048401CC0109700FC53064F4040FED2A23EA91CC0D882177D05034F4080F0A1444BBE1CC08881204086024F40C0BA46CB81CE1CC0E0B837BF61024F4040C2BE9D44C41CC008DFA63FFB034F4000282A1BD6C41CC0C8031F8315054F40009544F641C61CC0580438BD8B054F4040BD6E1118CB1CC058FB743C66064F40C0332E1C08D91CC0885704FF5B074F408054E0641BE81CC0604F1F813F084F40C047E17A14EE1CC0E8B2B5BE48084F40002EAC1BEFEE1CC0A86E2EFEB6074F4040880E8123011DC010A0C37C79054F4000BF9B6ED9611DC0082A8E03AF064F4000BA4BE2AC681DC038DB87BCE5064F40003AB01C21831DC0A8B393C151084F4080D9CBB6D3861DC0682E54FEB5084F4080C8772975B91DC0A077F17EDC0E4F404060E4654DBC1DC0D8D38041D20F4F4080A46B26DFBC1DC028172AFF5A104F40400AD7A370BD1DC0503D997FF4114F40C09CBCC804BC1DC0D0B837BF61124F40805D85949FB41DC09081204086124F4040DAC69FA8EC1CC0D8BEB9BF7A144F408078EC67B1E41CC0905A457F68144F404071C79BFCA61CC0081E8A027D104F4080C8772975391CC08887A2409F0C4F40C047E17A142E1CC0D8A6B1BD160C4F40C0A7C5E0612A1CC0282CF180B20B4F4040FED2A23E291CC0D8AF743E3C0B4F4080E49D43192A1CC0B8E67283A10A4F40806F0B96EA321CC0E0CABDC0AC084F4001030000000100000027000000C069C020E9D31AC09021E4BCFFF74E4000272F3201DF1AC0B8BC564277F74E404008AA46AFE61AC060853FC39BF74E4000E8F7FD9B171BC030266F8099F94E40800CFFE9067A1BC0B8E9B303AEFF4E40402C7FBE2DD81BC0D87FD6FCF8054F40001FBC7669231CC008C7D79E590E4F40C0A0D9756F851CC090B4C6A013104F40C083B9DDCBED1CC000E5284014164F40C079E2395BF01CC08060C77F81164F40001C261AA4F01CC03041B8020A174F4000D0EFFB37EF1CC0302F3201BF184F4040C8409E5DEE1CC068F833BC59194F40008A3BDEE4D71CC010BEDBBC71244F40802502D53FC81CC05040DAFF00274F4000282A1BD6C41CC010BB9A3C65274F4000D7A3703D8A1CC030DB87BCE5264F40C039B01C21831CC0002A8E03AF264F400078B5DC99591CC088CC07043A254F40802502D53F481CC010BEDBBC71244F40C0DBF3FC69431CC0A8A78FC01F244F40C0FFFFFFFF3F1CC0002DCF83BB234F40C0F2C98AE13A1CC0B8984A3FE1224F40C08618AF79351CC0305C8FC2F5204F40C047E17A142E1CC00009C380251F4F400052B81E852B1CC0808D2441B81E4F40C05EB7088C251CC0901B62BCE61D4F40000F27309DF61BC0582E54FEB5184F4080BC732843E51BC0785704FF5B174F4040C745B588C81BC0507FBDC282154F40C0A7C5E061AA1BC0382CF180B2134F4080B91457955D1BC0A89B8BBFED0F4F40001C261AA4F01AC0A8E3310395054F4080A23EC91DE61AC0D0BEB9BF7A044F40C0D0217024E01AC0602B137EA9034F40402DB1321AC91AC0A8B6D4415EFD4E40C0698995D1C81AC010D6E3BED5FC4E4080C2F5285CCF1AC028172AFF5AF84E40C069C020E9D31AC09021E4BCFFF74E400103000000010000000D00000000F3C98AE17A1AC0301A6B7F671D4F4000B4C9E1937E1AC0809FAA42031D4F40801D537765871AC0E088997D1E1D4F4000BF9B6ED9A11AC0285FD042021E4F404049D74CBEB91AC02841B8020A1F4F4040F0A1444BBE1AC0905704FF5B1F4F40C091EA3BBFD81AC0B868ACFD9D254F404061DF4E22E21AC0A8B915C26A2A4F40801D537765871AC0A8AAD0402C214F40404487C091801AC0009D82FC6C204F4040B6F1272A7B1AC0B85FE97C781E4F40C00CFFE9067A1AC0285FD042021E4F4000F3C98AE17A1AC0301A6B7F671D4F4001030000000100000018000000007B14AE47A11AC0D0F4D901D70B4F40007B14AE47A11AC00009C38025074F400084B9DDCBAD1AC03820ED7F80074F40C0976C3CD8021BC0E07954FCDF0B4F40C0D79E5912B01BC0381A6B7F67154F40001B2B31CFCA1BC0785704FF5B174F40C0652FDB4EDB1BC0302F3201BF184F40C08096AE600B1CC0B09ECC3FFA1C4F400078B5DC99191CC0A8DA6E826F1E4F40801F80D4261E1CC028F38FBE491F4F40C0FFFFFFFF3F1CC09096E7C1DD254F4040AC1A84B93D1CC038EACC3D24284F4040F2CEA10CD51BC050793BC2692B4F40006F10AD15CD1BC0A0B05241452B4F40004487C091C01BC0E0D03FC1C52A4F4080726A67983A1BC0286893C327254F40001C261AA4F01AC0D80F238447214F40001059A489671AC080ABAE4335194F40801281EA1F641AC08818213CDA184F40C0DD205A2B5A1AC0B8AAD0402C114F40C0D571FC50991AC0D088997D1E0D4F40007D3CF4DD9D1AC0B8716F7EC30C4F404015A930B6A01AC060F5F23B4D0C4F40007B14AE47A11AC0D0F4D901D70B4F400103000000010000001900000000DAC69FA8AC19C0F820CB8289174F4080FCA5457D121AC0A868ACFD9D154F4080CB9A58E01B1AC078AEEFC341164F40C0620CACE3381AC080ABAE4335194F40C0D6A3703D4A1AC038E78BBD171B4F40006AC020E9531AC030D505BCCC1C4F40C0DD205A2B5A1AC0F0298E03AF1E4F40C0F59A1E14341AC0E0E8633E20204F40806A813D26321AC0F0AE25E483264F40C0E5CE4C304C1AC0D8D39CBCC82C4F40404A09C1AA2A1AC05831957EC22D4F40C05EB7088C251AC0C8F4D901D72B4F4000E048A0C1161AC0602E54FEB5284F4080C0C8CB9AF819C0505260014C254F40C05D85949FF419C0603A58FFE7244F40C01E85EB51B819C0B0B915C26A224F408024D060539719C0D80F238447214F404016DBA4A29119C0F8E1E7BF07214F40C01803EB388E19C008CADFBDA3204F404055DB4DF08D19C0306552431B204F4000FFCD8B138F19C03820ED7F801F4F4040B7EC10FFA019C0B8E0F08288184F40802407EC6AA219C030EACC3D24184F40C0A23EC91DA619C0B06E2EFEB6174F4000DAC69FA8AC19C0F820CB8289174F4001030000000100000017000000008A3BDEE4571AC08893A641D1204F40C07A14AE47611AC0F82F1004C8204F40002EAC1BEF6E1AC060465C001A214F408077BAF3C4731AC0A85CA8FC6B214F4000F3C98AE17A1AC0D08BDAFD2A224F4080F6234564A81AC0D00F238447294F4000963FDF16AC1AC0306BD443342A4F40003883BF5FAC1AC008D061BEBC2A4F40004A09C1AAAA1AC008BEDBBC712C4F4000643E20D0A91AC0000341800C2D4F408078EC67B1A41AC0A0E9B303AE2F4F4040C1C3B46F9E1AC03038F581E42F4F400094128255951AC03038F581E42F4F40C010548D5E8D1AC0004E2844C02F4F40801D537765871AC0B0BC5642772F4F40008196AE604B1AC0586D37C137274F4080415F7AFB431AC0D8FA5B02F0254F4000560DC2DC3E1AC090423D7D04244F4000B4C9E1933E1AC050FEB5BC72234F4000F850A2253F1AC0D8FD9C82FC224F40C039B01C21431AC0583D997FF4214F40C0D6A3703D4A1AC0E8A9F23D23214F40008A3BDEE4571AC08893A641D1204F400103000000010000000E000000400DFAD2DB9F19C0805A457F68244F40C03AAB05F6A819C0805A457F68244F4040DF4DB7ECB019C028232E008D244F4000F4FBFECDEB19C07848BF7D1D264F40C0DC257156F419C0885704FF5B274F40C0D79E5912301AC050465C001A314F4040C8409E5D2E1AC0C8C1FA3F87314F40806BB6F2921F1AC0281DACFF73324F40803BDD79E2191AC0084BE7C3B3324F4040A69883A0131AC06034D6FECE324F4040F0A1444BFE19C0805D86FF74314F400021AD31E8F419C09093A641D1304F4040B06F27119119C0205FD04202264F40400DFAD2DB9F19C0805A457F68244F40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('AN','AD','AND','20','Andorra','46.8','73483','150','39','1.576','42.549','0106000020E6100000010000000103000000010000001D000000E010AAD4EC81FC3F3BFBCA83F44845400DDE57E54265FC3F52465C001A494540EE77280AF449FC3F52465C001A494540BC067DE9ED0FFC3F295C8FC2F54845408811C2A38DE3FB3F29EACC3D244845401C7E37DDB2C3FB3F813FFCFCF7464540F321A81ABD9AFB3FD3F4D901D7434540E8887C975297FB3F514CDE00334345408FE1B19FC592FB3F533D997FF4414540E869C020E993FB3F7AABAE43354145402C4487C09180FB3FFC17080264404540E869C020E993FA3F27F6D03E563C4540C90391459A78FA3FD57954FCDF3B4540AE282504ABAAF83F7C9C69C2F6374540850A0E2F8888F83FD0D38041D2374540DAAA24B20F32F83F5437177FDB374540EF586C938A46F73FA8E0F08288384540297B4B395F2CF73F508BC1C3B4394540C233A14962C9F63FFF08C380253F45406A4E5E6402BEF63F7D96E7C1DD45454044183F8D7BF3F63FD673D2FBC64945401EA4A7C82122F73F000341800C4D454007EFAB72A1B2F73F2635B401D85245402F6AF7AB00DFF73F562B137EA953454093AAED26F8E6F83F81423D7D04544540B2101D024702F93FA77A32FFE8534540297B4B395F2CFB3F29EACC3D24504540257497C459D1FB3F2BDB87BCE54E4540E010AAD4EC81FC3F3BFBCA83F4484540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('GI','GI','GIB','292','Gibraltar','0.6','291','150','39','-5.345','36.138','0106000020E6100000010000000103000000010000000A0000006000E143895615C0A2D11DC4CE144240280F0BB5A65915C03DD7F7E120134240CA501553E95715C0C5707500C4114240B51A12F7585A15C0E3361AC05B0E424030629F008A6115C0BC79AA436E0E4240B01BB62DCA6C15C0CA4FAA7D3A104240DA1A118C836B15C0348639419B124240A35698BED76015C0A65F22DE3A1342404BCCB392566C15C09C1A683EE71442406000E143895615C0A2D11DC4CE144240'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('IM','IM','IMN','833','Isle of Man','57.2','78357','150','154','-4.527','54.229','0106000020E6100000010000000103000000010000002A000000F50F2219721C13C07AA52C431C074B4051A5660FB42213C028F38FBE49074B4066666666662613C051853FC39B074B403D1059A4892713C0D38558FD11084B403D1059A4892713C07B6649809A084B4086E5CFB705DB12C054FEB5BC721B4B407024D06053D712C07F15E0BBCD1B4B407901F6D1A9CB12C052431B800D1C4B4057941282559512C0AB5FE97C781E4B407C0E2C47C89012C07E8D2441B81E4B4000000000008012C05437177FDB1F4B40E5620CACE37812C0A8E0F08288204B407FF62345646812C0AC53E57B46224B402461DF4E226212C0286211C30E234B40C6DD205A2B5A12C056F5F23B4D244B40BC067DE9ED4F12C0295FD04202264B40255B5D4E093812C0D4B837BF612A4B40390F27309D3612C07C992842EA2A4B400CCB9F6F0B3612C081423D7D042C4B4015A8C5E0612A12C0A8E33103952D4B405C8FC2F5281C12C05340DAFF002F4B40F31B261AA4F011C0A4C2D84290314B40B22FD978B0C511C07E1EA33CF3324B40E5620CACE37811C0D4B5F63E55354B4087DF4DB7EC7011C07E5182FE42354B402C4A09C1AA6A11C0FB230C0396344B403FFED2A23E6911C0AB59677C5F344B403B1C5DA5BB3B11C0AB5FE97C78264B40FEF2C98AE13A11C0295FD04202264B4094A46B26DF3C11C0530438BD8B254B404ACFF412634911C053793BC269234B40E08096AE608B11C0FCE1E7BF07194B40E869C020E99311C05437177FDB174B400EBF9B6ED9E111C029266F8099114B404FB16A10E6F611C07F4E417E36104B406077BAF3C43312C0A5BF97C2830C4B402A560DC2DC7E12C0F92F1004C8084B4094A46B26DFBC12C02CD8463CD9094B40EF39B01C21C312C0A9A10DC0060A4B403C16DBA4A2D112C0276BD443340A4B402461DF4E22E212C0D4EE5701BE094B40F50F2219721C13C07AA52C431C074B40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('LU','LU','LUX','442','Luxembourg','258','456613','150','155','6.088','49.771','0106000020E610000001000000010300000001000000540000008C4B55DAE21A1840D42AFA4333174940AF5A99F04B1D18407E5182FE42154940F52EDE8FDB1F1840FB230C0396144940CEC64ACCB3221840AB59677C5F1449407B14AE47E17A1840D3F71A82E3104940887FD8D2A38918405376FA415D1049409B8D95986785184051853FC39B0F49406C5B94D9208318402BDB87BCE50E4940782634492C791840D2C77C40A00B494049D576137C731840FB20CB8289074940F33AE2900D741840FF08C380250749402F51BD35B0851840D673D2FBC6014940392861A6ED8F1840556D37C137FF48401AA3755435B11840FDD8243FE2F9484049D576137CB3184029266F8099F948402E573F36C9EF1840AB984A3FE1F2484016A243E048001940A8AAD0402CF148409B8D959867051940552E54FEB5F048402D414640854319406EDFA3FE7AED48401E8B6D52D1481940FB230C0396EC4840BE13B35E0C951940D1CABDC0ACE84840A27C410B09B81940FB20CB8289E7484082035ABA82ED1940D0D38041D2E74840C1012D5DC1161A40D0D38041D2E748406D5512D907191A402920ED7F80E7484083F755B950191A407AA52C431CE748404BB0389CF9051A403CBCE7C072DA48405A9BC6F65AF0194052465C001AD948404DD6A88768E41940F92F1004C8D84840AF5A99F04BDD1940527C7C4276D848406E4F90D8EEAE19407DCC07043AD548406CED7DAA0A6D19406612F5824FC3484049D576137C7319405628D2FD9CBE4840895E46B1DC72194032923D42CDBA48404FCAA4863650194052431B800DBC484089EC832C0B3619407B9FAA4203BD484038D906EE40FD18402B508BC1C3C048405DA8FC6B79F518402AE109BDFEC04840D5AF743E3CEB184080457EFD10C14840BC1FB75F3EA918407B6649809AC04840F52EDE8FDB9F18405401F73C7FC04840BD19355F257F1840FA298E03AFBE4840E76F4221027E18405376FA415DBE4840BB2BBB60707D1840527FBDC282BD48407B14AE47E17A1840AB59677C5FBC48406284F068E3781840A8A78FC01FBC4840B5368DEDB5601840D106600322BA484006F52D73BA5C1840253E7782FDB9484055BFD2F9F0EC174027F911BF62B94840BC1FB75F3EE91740AB5CA8FC6BB948407F15E0BBCD6B174029EACC3D24C0484070438CD7BC5A1740A774B0FECFC14840BD19355F253F174051888043A8C44840BB2BBB60703D1740AA9ECC3FFAC44840B35E0CE5443B1740C5707500C4C54840179CC1DF2F561740FD1186014BC648402D5DC136E2591740A9DA6E826FC64840DD989EB0C4731740A8AAD0402CC948402D5DC136E2991740253E7782FDD1484057B3CEF8BE981740FED5E3BED5D44840C58F31772D811740E275FD82DDDA48404ED026874F7A1740A8A78FC01FDC4840BC1FB75F3E2917402BDEC83CF2E348400DE4D9E55B0F1740D388997D1EE54840C007AF5DDA0017407E5182FE42E54840E76F422102FE1640FD9FC37C79E54840FB230C0396FC164027327381CBE5484044F9821612F01640AB984A3FE1EA4840D1CDFE40B9FD16407AA86DC328F44840D4B5F63E55151740A774B0FECFF9484083F755B950191740D4B837BF61FA4840D9B0A6B2281C17405307793D98FA484015A8C5E0612A1740514CDE0033FB4840AB5FE97C78561740FF9600FC53FE4840F146E6913F881740FDD8243FE2094940F146E6913F8817407E54C37E4F0A49408AE6012CF28B174051888043A80C4940637E6E68CA8E1740D4B5F63E550D49400FD253E410911740A8E33103950D4940CBD8D0CDFEE01740A8E3310395154940D0D38041D2E71740D3FA5B02F0154940363AE7A7380E1840556D37C137174940AB5FE97C78161840AC5626FC521749408C4B55DAE21A1840D42AFA4333174940'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('MN','MC','MCO','492','Monaco','0.2','36950','150','155','7.412','43.75','0106000020E6100000010000000103000000010000000F00000069723106D6C11D40E17B7F83F6E045401AA3755435B11D407E8D2441B8DE4540EC51B81E85AB1D40D47FD6FCF8DD4540ED461FF301911D40C6A6954220DD4540F722DA8EA98B1D40813FFCFCF7DE4540F722DA8EA98B1D40D4BB783F6EDF45406090F469158D1D40D0D38041D2DF454006F52D73BA9C1D407D5D86FF74E14540FF05820019AA1D40A7E67283A1E245402B69C53714AE1D40AB984A3FE1E245401D91EF52EAB21D407E1EA33CF3E245408CDAFD2AC0B71D40FFCF61BEBCE245407B14AE47E1BA1D402A1DACFF73E24540C007AF5DDAC01D405473B9C150E1454069723106D6C11D40E17B7F83F6E04540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('MJ','ME','MNE','499','Montenegro','10235','607969','150','39','19.254','42.792','0106000020E6100000010000000103000000010000000C0100007F87A2409F743240FE9C82FC6C4845407F129F3BC1763240D3F71A82E348454027F911BF62893240D6AC33BE2F4E45402CD505BCCC8C324028F38FBE494F45407E18213CDA903240552E54FEB55045407BA2EBC20F92324027F911BF62514540286211C30E9332405055A18158524540037976F9D6933240D3F4D901D7534540ABE7A4F78D93324082397AFCDE544540CF4E0647C98F3240D0D03FC1C55A4540D4BB783F6E8F32407F4B00FE295B4540A777F17EDC8E32407C6308008E5B4540276893C3278D324052431B800D5C45402BDEC83CF28B324054707841445C454052465C001A89324001BEDBBC715C45407F129F3BC1863240A7ECF483BA5C4540A8716F7EC38432407E5182FE425D454052431B800D843240A8E33103955D45402DCC423BA77D3240FF05820019624540000341800C753240FE0E45813E6945407F87A2409F7432407E8AE3C0AB69454027F6D03E56743240A96BED7DAA6A454080812040867A3240A6B915C26A7A4540A4FE7A85057B324054FEB5BC727B4540A5F5B704E07B32407D5A457F687C454028F38FBE497F3240508E0244C17E4540AC53E57B46823240D38558FD1180454079AEEFC341863240A4C2D8429081454052465C001A893240276BD44334824540D63A71395E8D32407C992842EA8245404DD6A88768943240F92CCF83BB834540800F5EBBB4A132407D5A457F6884454052431B800DA43240A8716F7EC3844540CF488446B0A53240505260014C8545402577D84466A63240FE47A643A7854540A6F27684D3A63240FCE4284014864540FC17080264A832407AABAE433589454057B3CEF8BEA83240AC53E57B468A4540FC17080264A83240F92CCF83BB8B4540AC5626FC52A73240508E0244C18E4540D13FC1C58AA63240520ABABDA48F4540A304FD851EA532407E18213CDA904540CE5147C7D5A43240A774B0FECF914540D4B5F63E55A532402635B401D8924540A7E67283A1B23240A7B393C151A04540514CDE0033B33240552E54FEB5A04540543A58FFE7B432405473B9C150A1454082397AFCDED63240EE2422FC8BAC45407AC7293A92DF3240C097C28366AD454082FDD7B969E33240A968ACFD9DAD4540ABEAE5779AE832407D96E7C1DDAD4540ADC266800BEA324047551344DDAD4540257A19C572EB3240D1CDFE40B9AD4540A304FD851EF53240D106600322AA4540E69315C3D5F532406094A0BFD0A945401956F146E6F532406BF46A80D2A8454084F4143944F43240FB20CB8289A7454057B08D78B2F33240A9DA6E826FA6454027F6D03E56F43240A8E3310395A545400ADB4FC6F8F432407DCC07043AA5454084F41439440433402829B000A69E4540E7E26F7B820C33404A438D42929D45402B69C537140E33405531957EC29D45407E18213CDA103340D2C43BC0939E4540D446753A901133402BDB87BCE59E4540FC1D8A027D123340FD4D2844C09F4540FE0B04013214334029266F8099A145408109DCBA9B1733405628D2FD9CA645407C9C69C2F6173340FB20CB8289A7454054C554FA09073340FDDB65BFEEB645407E1B62BCE6053340FD4D2844C0B745407C992842EA023340D47C957CECB8454023861DC6A4FF324029266F8099B945400188BB7A15FD3240823CBB7CEBB94540FF05820019FA3240253E7782FDB945407B116DC7D4F53240823CBB7CEBB94540543A58FFE7F43240D28BDAFD2ABA454022895E46B1F43240A96BED7DAABA45402B6C06B820F3324051853FC39BBF454056B950F9D7F23240D1CABDC0ACC04540286211C30EF332407AABAE4335C14540D2C77C40A0F3324029266F8099C14540800F5EBBB4013340FF08C38025C745400282397AFC023340D009A1832EC74540D6AC33BE2F363340D0D03FC1C5C2454083F755B950393340FF05820019C24540CC07043A933A3340B7EC10FFB0C145407AABAE4335413340AB984A3FE1BA4540FB20CB8289473340A4C2D84290B94540800F5EBBB4713340D0D38041D2AF4540286211C30E8333407AABAE4335A9454059A7CAF78C8433407B6649809AA84540AB59677C5F8C3340D3BEB9BF7AA445405340DAFF008F33405307793D98A24540D4BB783F6E8F3340508BC1C3B4A145404FCAA486369033407D93A641D1A04540A4FB3905F9953340A7AD11C1389E454027F6D03E56A43340D0D38041D29745407B116DC7D4A53340266E15C440974540286552431BA83340D4F19881CA964540F92CCF83BBAB3340FF9600FC53964540FF93BF7B47B133407D96E7C1DD954540ABEAE5779AC833407E1EA33CF3924540D042024697EB3340A968ACFD9D8D4540514F1F813FF8334000C79E3D978B4540D82E6D382C093440A8716F7EC384454028F38FBE490F3440552E54FEB58045405531957EC2253440AB59677C5F7C4540008E3D7B2E27344001BEDBBC717C4540D925AAB7062A344056F5F23B4D7C45402DCC423BA72D3440D3F4D901D77B4540FC1D8A027D423440A8E0F082887845404DD9E907754934407E5704FF5B7745407AA86DC3284C3440D2C43BC09376454056BC9179E45734407BA2EBC20F72454083F755B9505934407D5D86FF74714540247D5A457F603440520DFB3DB16C454055C2137AFD6134407E1EA33CF36A4540D6A9F23D23613440A96BED7DAA6A4540FE99417C603B3440AB5CA8FC6B61454052B5DD04DF1C344028F04E3E3D624540CF4BC5C6BC1A34405307793D98624540FA298E03AF163440D482177D05634540D2C77C40A0133440286211C30E63454051C1E105111134407E1EA33CF3624540FF058200190A34407BA2EBC20F624540037976F9D6033440A7B393C1516045402DCC423BA7FD33407D96E7C1DD5D45407E1EA33CF3FA33407D5A457F685C4540FF05820019FA33407C6308008E5B45407E8AE3C0ABF933405182FE428F5A454028F04E3E3DFA3340FF058200195A45407E1EA33CF3FA3340D673D2FBC659454055C2137AFD01344051853FC39B574540A77A32FFE8033440FF08C38025574540AB5FE97C780634402BDB87BCE5564540D2393FC5710C3440508E0244C156454052B81E85EB11344079AEEFC341564540AD4D637B2D183440000341800C554540D925AAB7061A3440D3BEB9BF7A544540257A19C5721B34407E9065C1C4534540FE99417C601B3440D0D03FC1C552454029E78BBD171B3440AC53E57B46524540A52E19C7481234405C7347FFCB474540FE9C82FC6C103440D38558FD1148454004763579CA0E34407EC9C6832D4845402DCC423BA70D3440D38558FD11484540FB230C03960C34402638F581E4474540D4BB783F6EEF3340D4B837BF61424540FE99417C60EB334029266F809941454081069B3A8FD233407D5A457F683C4540AD50A4FB39CD3340FD9FC37C793D454050C763062ACB3340D3FA5B02F03D45404ED026874FCA3340A7AD11C1383E45402AE44A3D0BC63340520ABABDA43F4540A77A32FFE8C333407B6649809A404540FF08C38025BF3340527FBDC28245454084F1D3B837BF3340295FD042024645400000000000C0334028F04E3E3D4A4540D04543C6A3C03340A7E67283A14A454081069B3A8FC23340286211C30E4B4540D82B2CB81FC433407E1EA33CF34A454029ED0DBE30C53340FBE769C0204B45407B116DC7D4C53340AA622AFD844B45402AE44A3D0BC63340FCDEA63FFB4B45407E1B62BCE6C53340D3BEB9BF7A4C4540D13C80457EC13340FDD8243FE25145407E18213CDAC03340276BD44334524540D925AAB706BA3340D3BEB9BF7A544540CC5D4BC807B93340A7ECF483BA544540D13FC1C58AB6334029232E008D544540FD9FC37C79B5334027F6D03E56544540514F1F813FA83340FE9C82FC6C504540D4B5F63E55A533407AA52C431C4F4540008BFCFA21A233407DCC07043A4D45402DCC423BA79D33405182FE428F4A454051BEA085049C3340D00F2384474945407F15E0BBCD9B3340552E54FEB5484540AB59677C5F9C3340D0D38041D24745402CD505BCCC9C334055FB743C66464540A5F5B704E09B3340FC1A498270454540D5AF743E3C9B3340000341800C454540000341800C853340AB5CA8FC6B3945404DD9E907754933407B6649809A184540D63730B951483340FD4D2844C01745407D93A641D148334002BB9A3C6517454052B5DD04DF4C33407E1B62BCE6154540000341800C553340AA622AFD841345407E8D2441B85E33405401F73C7F1045407C992842EA6233407AA52C431C0F4540A4FB3905F96533407D96E7C1DD0D4540AB5FE97C78663340FD9FC37C790D454050C422861D663340AA9ECC3FFA0C45405055A18158623340FD4AE7C3B30A4540BA6587F887613340BEF8A23D5E0A4540F92F1004C86033407BA2EBC20F0A4540C6FB71FBE55F3340698B6B7C260945407F8461C0925F3340AA656B7D910845407D93A641D15833407E54C37E4FFA444056BC9179E45733402CD505BCCCF44440CF6A813D265E334019ABCDFFABEC4440800C1D3BA84C33408081204086F24440D236FE4465473340D2C77C40A0F344407E8D2441B83E3340A8716F7EC3F44440267156444D3C3340FB230C0396F444404DD9E90775393340A7ECF483BAF444404DDC2A88812E3340A777F17EDCF64440562B137EA92B334051853FC39BF744408109DCBA9B27334080457EFD10F944405628D2FD9C2633402CD8463CD9F94440ABE7A4F78D2333407F87A2409FFC44407C992842EA223340FD9FC37C79FD44407C992842EA2233407E1B62BCE6FD4440A77A32FFE8233340D009A1832EFF444024809BC58B2533407E8AE3C0AB01454029ED0DBE30253340FD14C78157034540A9DDAF027C233340530438BD8B054540D82B2CB81F143340FD1186014B0E4540A9DA6E826F0E334027F911BF62114540AD50A4FB390D3340A4C2D842901145407F15E0BBCD0B334029266F8099114540FF93BF7B470133407AA86DC3281445402BDB87BCE5F63240A7B393C151184540D734EF3845E332407E1EA33CF3224540008BFCFA21E23240562B137EA92345404FCAA48636E032407AA86DC328244540A777F17EDCDE324056F5F23B4D244540D3C1FA3F87D93240520DFB3DB1244540D63730B951D83240A8716F7EC32445407F8461C092CF324001BEDBBC7124454054C554FA09A73240FC1708026430454084F4143944A43240D4BB783F6E2F4540D04543C6A3A032407E8D2441B82E4540FA9B5088809F32405628D2FD9C2E45402B69C537149E32407E8D2441B82E4540A7ECF483BA9C3240A777F17EDC2E45407E9065C1C4933240A4C2D84290314540A5F5B704E08B32407E5182FE42354540F92CCF83BB8B32405531957EC2354540D7A6B1BD168C324079AEEFC34136454082035ABA828D3240813FFCFCF736454083FA96395D8E3240556D37C1373745405437177FDB8F324002BB9A3C65374540A4FB3905F99532405340DAFF0037454055BFD2F9F09C32405376FA415D3645404ED367075C9F3240295FD04202364540FA264D83A2A1324029ED0DBE303545402DCF83BBB3A23240253B3602F134454081069B3A8FB23240A6B915C26A324540037976F9D6B332405055A181583245404DD6A88768B43240FFCF61BEBC32454024809BC58BB532402CD505BCCC34454024809BC58BB53240D4B5F63E55354540A8716F7EC3B4324052499D8026364540D2C43BC093AE3240A96BED7DAA3A454052B5DD04DFAC3240D5AF743E3C3B4540A9DDAF027C833240AC53E57B463A4540276BD44334823240276BD443343A4540FF93BF7B47813240533D997FF43945400072C284D1803240D3C1FA3F87394540FA9B5088807F3240D4EE5701BE394540CF4BC5C6BC7A32407C6308008E3B4540D236FE4465773240276893C3273D45407B116DC7D4753240FF9600FC533E454059A7CAF78C743240D200DE020940454052431B800D74324029266F809941454052431B800D743240FD4AE7C3B34245407F87A2409F743240FE9C82FC6C484540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES (NULL,'AX','ALA','248','land Islands','0','0','150','154','19.952','60.198','0106000020E61000000500000001030000000100000014000000C0FB3905F9353440101B498270FD4D40E064FF3C0D343440080341800CFD4D405085B1852023344000DC65BFEEFE4D40D0E2C5C210213440805704FF5BFF4D4070C1E1051101344008C45DBD8A064E40E04E0647C9FF3340A0A44E4013074E40402E54FEB5003440B89B8BBFED074E40208BFCFA21023440B0656B7D91084E40406552431B183440A87A32FFE80B4E4050D026874F1A3440C80CE2033B0C4E4050DEC83CF21B3440002DCF83BB0B4E4090A86DC3281C3440B0B05241450B4E40109C5088801F34408054C37E4F0A4E40D0548847E229344000301004C8084E40B05CA8FC6B313440D8B2B5BE48084E4060A7CAF78C34344030EACC3D24084E4090AEEFC341363440B8E9B303AE074E4030F04E3E3D3A344028172AFF5A004E4020B8CB7EDD3934400800000000004E40C0FB3905F9353440101B498270FD4D400103000000010000001000000070CDE50643453440905704FF5B074E401015C7815743344010DC65BFEE064E40F0BEB9BF7A343440B0B915C26A0A4E40C034EF3845333440D8FD9C82FC0A4E4080992842EA323440D0C77C40A00B4E4050D6A88768343440285FD042020E4E40008E3D7B2E373440B074B0FECF114E4060465C001A39344030F04E3E3D124E40A01A3048FA44344070A2EBC20F124E40202A8E03AF46344038266F8099114E4050AA0B7899493440A8656B7D91104E405034D6FECE4A3440D000DE0209104E40E0420246974B3440D0BB783F6E0F4E40C059677C5F4C344010E52840140E4E40207156444D4C3440B8B6D4415E0D4E4070CDE50643453440905704FF5B074E4001030000000100000017000000C050A4FB39AD3340D0A6B1BD16144E40207156444DAC3340D8AF743E3C134E40D04BC5C6BC9A334008C79E3D97134E40D034EF384593334050853FC39B0F4E40C001BC0512903340A86E2EFEB60F4E402088BB7A158D33408021E4BCFF0F4E40901EA33CF38A3340009D82FC6C104E40A0FB3905F98533403814E97E4E134E4030CF83BBB3823340B8DA6E826F164E40506C06B820833340586D37C137174E4050465C001A89334010D6E3BED51C4E40A0812040868A334000A0C37C791D4E40E04543C6A3903340D0D38041D21F4E406055A18158923340B0B393C151204E40C0BEB9BF7A94334010CADFBDA3204E4030DB87BCE59633408818213CDA204E4000068200199A3340282F3201BF204E40800C1D3BA89C33401018080264204E40B0656B7D91A03340686D37C1371F4E408081204086AA3340302F3201BF184E4010904C874EAB334038EACC3D24184E40E04334BA83AC334050499D8026164E40C050A4FB39AD3340D0A6B1BD16144E4001030000000100000010000000F0488446B0653440285C8FC2F5184E40604CDE0033633440302F3201BF184E400018080264583440600438BD8B1D4E401021CB82895734408848BF7D1D1E4E40108E3D7B2E573440D0F19881CA1E4E4030D2C43BC0573440808461C0921F4E40E02E6D382C593440904E417E36204E40F0CDFE40B95D3440383E7782FD214E4050EACC3D24603440286BD44334224E40503A58FFE7643440D88BDAFD2A224E40B06E2EFEB66F3440385C8FC2F5204E40A0F8F884EC7034401018080264204E401094BF7B47713440004E2844C01F4E4040E109BDFE70344078A52C431C1F4E409093A641D168344010068200191A4E40F0488446B0653440285C8FC2F5184E4001030000000100000059000000D0488446B015344000D6E3BED52C4E4060C554FA0947344038E78BBD17234E4020D2C43BC0373440A86BED7DAA1A4E4040DEC83CF22B3440A89ECC3FFA144E40E0C1FA3F87293440B0716F7EC3144E408009DCBA9B17344030327381CB154E40801B62BCE6153440101286014B164E40B004FD851E15344030DB87BCE5164E40E0548847E219344000C79E3D971B4E4020E78BBD171B344030F6D03E561C4E40F0BB783F6E1F3440283B3602F11C4E4020763579CA1E3440888D2441B81E4E4060C1E10511113440E0FA5B02F0254E40D04E0647C90F34409060C77F81264E4050BEA085040C344000BB9A3C65274E4060D9E90775093440104E2844C0274E40C05FE97C78063440104E2844C0274E40F025AAB706EA33409015E0BBCD1B4E40503D997FF4E9334020E78BBD171B4E40B050A4FB39ED3340D0CABDC0AC184E4090FA96395DEE3340E000DE0209184E40A021E4BCFFEF3340888461C092174E40008BFCFA21F233401009C38025174E4040D505BCCCFC334030327381CB154E40A005854199063440C84F1C40BF134E40306893C3270D3440383B3602F10C4E40A0035ABA820D344058707841440C4E40A09FAA42030D3440B8DDAF027C0B4E40109A417C600B3440881EA33CF30A4E4020809BC58B053440D8FD9C82FC0A4E404037177FDBFF334050FEB5BC720B4E4040BC9179E4F73340886308008E0B4E4040ED0DBE30F5334050FEB5BC720B4E40B0E7A4F78DF3334090992842EA0A4E40C0E67283A1F2334078A2EBC20F0A4E4000274D83A2F1334000A0C37C79054E40F0B2B5BE48F03340808461C092074E4090035ABA82ED3340D0D03FC1C50A4E40B0ECF483BAEC3340089A417C600B4E40B0FE7A8505EB3340E87954FCDF0B4E408000193A76E83340100C0401320C4E40000341800CE5334010BEDBBC710C4E408021E4BCFFDF334080A86DC3280C4E40A0FA96395DDE3340D0C77C40A00B4E40908D2441B8DE3340881EA33CF30A4E40F09B508880DF33405055A181580A4E40001286014BDE334000D9243FE2094E40C0F5B704E0DB3340608BC1C3B4094E40505C8FC2F5D83340608BC1C3B4094E4030809BC58BC533405055A181580A4E4050CAA48636C0334080A86DC3280C4E4050B3CEF8BEB8334028EACC3D24104E401082397AFCB2334038F6D03E56144E40306BD44334B23340303B3602F1144E40B0FB3905F9A533408818213CDA204E4020E44A3D0BA6334028266F8099214E40906E2EFEB6BF33405040DAFF00274E40704BC79C67C83340C05B920376254E4030DB87BCE5C63340B05CA8FC6B214E409087A2409FC43340B89B8BBFED1F4E40604CDE0033C3334030F38FBE491F4E4020CF83BBB3C233407860C77F811E4E409014AE47E1CA33405801F73C7F184E40102DCF83BBCB33403838F581E4174E401009C38025CF3340A8E9B303AE174E4070C1E10511D13340286552431B184E40201286014BEE334050FEB5BC72234E40F0BB783F6EEF3340100C040132244E408017EFC7EDEF3340B09ECC3FFA244E40A021E4BCFFEF3340D8CDFE40B9254E4090FA96395DEE334038DB87BCE5264E4040E44A3D0BE63340B0DDAF027C2B4E4070D6A88768E4334028DEC83CF22B4E4060B81E85EBE13340889065C1C42B4E4010301004C8E03340C882177D052B4E406037177FDBDF3340D08BDAFD2A2A4E4060D367075CDF334030F911BF62294E4070499D8026DE334008CADFBDA3284E40C0ECF483BADC33408021E4BCFF274E40C03D25E7C4D63340F03C2AFEEF284E4040E719FB92D53340508E90813C294E4090E9B303AEC73340500DFB3DB12C4E400018080264C83340B0B6D4415E2D4E40E057C9C7EECE3340B8B393C151304E40504CDE0033D33340306BD44334324E40307A19C572DB3340682B137EA9334E40A0FA96395DDE3340682B137EA9334E4050BC9179E4E73340584CDE0033334E40D0488446B015344000D6E3BED52C4E40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('NL','NL','NLD','528','Netherlands','3388','1632769','150','155','5.389','52.077','0106000020E6100000090000000103000000010000003B00000000B85510031D0E40080C040132AC494080DE57E542E50E4058793BC269AB494080FA821612F00E40B0622AFD84AB494080E04DB7ECB00F40B05626FC52AF4940003D0FEECECA1040B09B8BBFEDAF4940407C462234D210404837177FDBAF4940C0AB1F9BE4D71040A8E9B303AEAF4940C0B0A6B228DC104010BB9A3C65AF49400085EB51B8DE10401009C38025AF4940405264ADA1F4104088D558C2DAAC494080643E20D0E9104010C79E3D97AB4940C0B0A6B228DC1040C053E57B46AA494000A3755435B11040B85FE97C78A6494080DE57E542A510401048A643A7A5494040B950F9D7821040302CF180B2A34940405EBC1FB73F1040D8B2B5BE48A049408085EB51B89E0F4060FEB5BC729B494000736A67983A0F406055A181589A49408047E17A142E0F40B853E57B469A4940000D3B8C491F0F406055A181589A494080D676137C730E40809065C1C49B494080E3A7716F5E0E40000C0401329C4940003CDD79E2590E4038232E008D9C494080C77C40A0530E40B89509BFD49D494080C77C40A0530E405076FA415D9E494000272F32015F0E4080ABAE4335A14940802C7FBE2D580E40C8C1FA3F87A14940807D789620430E40903CBB7CEBA149408080643A745A0D40F89FC37C79A54940005B99F04BDD0C4010DC65BFEEA6494000DD2A8881CE0C405840DAFF00A7494000C1FF56B2C30C4038DB87BCE5A6494000EFAB72A1320C40503A58FFE7A4494080AF743E3C2B0C4008240C0396A4494000A0168387290C4080423D7D04A44940806CED7DAA2A0C40B8622AFD84A349408047E17A142E0C4038E78BBD17A3494080AB24B20F320C40908AE3C0ABA149400024D5777E310C40D08558FD11A04940806CED7DAA2A0C40004E2844C09F494000E3A7716FDE0B400809C380259F4940802EE3A606BA0B40883FFCFCF79E494000FEDCD0949D0B403041B8020A9F494080DCF3FC69830B4030F38FBE499F4940004818062C790B402820ED7F809F49408004029D491B0B401018080264A2494000E7012CF20B0B40D882177D05A34940004F95EF19090B4058FEB5BC72A34940806893C327FD0A40B0E9B303AEA749400096E99788F70A40F8B46E83DAAF49400029931ADA400B4058F833BC59B1494080D48041D2270C4058888043A8B4494080DD2A88814E0C40B8ECF483BAB4494080ABED26F8660C4008BEDBBC71B4494080416491261E0D409018213CDAB04940008D959867C50D40500438BD8BAD4940007C14AE47E10D4028D505BCCCAC4940801D8F19A8EC0D408887A2409FAC494000B85510031D0E40080C040132AC494001030000000100000042000000403AE7A7380E1740306893C327354A40C0E3A25A4404174038D505BCCC344A400083C30B22E2164080397AFCDE344A40C03788D68AC61640D00CE2033B344A40C03AE7A7388E1640D8EE5701BE314A40C0BB783F6E7F1640886649809A304A4080EFAB72A1721640B05626FC522F4A4000861DC6A44F164038F38FBE492F4A40003D0FEECE4A164080A52C431C2F4A4040F6285C8F42164010C45DBD8A2E4A40C0F1D3B8372F1640080341800C2D4A408069C537142E1640E0BEB9BF7A2C4A4080AD4CF8A52E164088423D7D042C4A4000240C03963C1640588BC1C3B4294A40406893C3273D1640000F45813E294A40C0D38041D2271640286893C327254A40C08A7269FC2216405870784144244A4080E3A7716F1E164090423D7D04244A40C07497C459111640F8C69E3D97234A4000D34ECDE5B61540B874B0FECF214A4040643E20D0A91540B874B0FECF214A4080416491269E1540D88BDAFD2A224A4040C554FA099715406034D6FECE224A4000944E24987A154030D505BCCC244A4000EA245B5D6E15400848A643A7254A40001E8A027D521540788461C092274A40C084F068E3381540D8CABDC0AC284A40805A99F04B1D1540588BC1C3B4294A40C0D5AD9E93FE14405082FE428F2A4A40005612D907D91440A8622AFD842B4A40008E959867C5144060FEB5BC722B4A40405EBC1FB7BF14400815C781572B4A4000295C8FC2B51440801EA33CF32A4A4080643E20D0A914405834D6FECE2A4A40409AD024B1A4144088992842EA2A4A40402FDE8FDB9F1440904B00FE292B4A40804B3B35979B144060FEB5BC722B4A4000B6F63E55951440A8A78FC01F2C4A40C07497C459911440603A58FFE72C4A40403D0FEECE8A1440D0CABDC0AC304A400091F469158D144038E109BDFE304A4040CB0D863AAC14405819710168324A4080EA5BE674B91440B07A32FFE8334A40802861A6EDCF1440D0031F8315354A40C0931799802F1540B874B0FECF394A40809DF3531C871540285FD042023E4A40806F48A302A71540403B191C253F4A40C07B630800CE1540300E677E35414A40808A00A777D115402005888219434A40406AC020E9D31540E0C77C40A0434A4080C1FA3F87E9154080AEEFC341464A40C0DE52CE174B16403014E97E4E4B4A40806211C30E931640283B3602F14C4A408020B248134F174008E2E7BF07494A404026396057531740382F3201BF484A40404B3B35975B1740D8D38041D2474A4000963FDF166C17400048A643A7454A4000AB24B20F721740E0BEB9BF7A444A404036CB65A37317406076887FD8424A4000963FDF166C17402841B8020A3F4A4000713D0AD76317406031957EC23D4A40806211C30E5317402814E97E4E3B4A404045B9347E31174078A52C431C374A40C0E9245B5D2E1740888D2441B8364A40C0809BC58B251740A8AD11C138364A40403AE7A7380E1740306893C327354A40010300000001000000450000004045B9347EB11540805D86FF74514A4000A27A6B60CB1540D0F19881CA4E4A40000C040132D41540E0CDFE40B94D4A40C0DB2F9FACE81540D8D03FC1C54A4A4040A3755435F115406073B9C150494A4040E7FC14C7F115408093A641D1484A4080013274ECF0154028172AFF5A484A40806DC5FEB2DB154008EE79FEB4474A40002FFCE07CCA1540B8675DA3E5444A40002F89B322CA1540489B559FAB414A4000B9C49107C2154078B5C01E13414A40805721E527B51540686D533C2E404A408021C84109A3154000E814E4673F4A40404B02D4D482154040B08EE3873E4A4080B9196EC037154058A35703943A4A40C09A9141EEC21440A089778027354A40C0B91803EBB814407088D51F61344A40808369183EB2144048B3B27DC8334A40C0F86C1D1CAC14403835B401D8324A40408D25AC8DA11440081286014B324A40C02BD8463C891440A8711AA20A314A4040B03907CF441440E86C8FDE70314A40C082E15CC33C14402051853FC3314A40C04E965AEF37144028357BA015324A4000639CBF0935144078EE3D5C72324A4000D2C43BC033144090D233BDC4324A40400645F30036144028020EA14A334A400001158E20551440F06987BF26354A40008D9AAF925F1440D0D38041D2374A40C0E07F2BD96114405837177FDB374A4080C1FA3F876914405001F73C7F384A40405A677C5F6C1440D8F71A82E3384A4000AB24B20F72144080A86DC3283C4A40404D689258721440580DFB3DB13C4A40400B96EA026E14403802D53F883E4A40809E961FB86A144008DFFB1BB43F4A4080E811A3E766144060888043A8404A40C0902A8A57491440D040498105464A40C039984D80311440880F971C77484A4080B96DDFA32E1440187250C24C494A4040D8F4A0A02414405080D3BB784D4A400062855B3E22144050FE99417C4E4A40C04D0F0A4A2114405810AE80424F4A400062855B3E22144048581B6327504A40408D791D71281440C8853C821B514A4040F9821612301440D8B27C5D86514A40406F47382D38144010DFFB1BB4514A40401E6CB1DB67144090F947DFA4514A40C01E166A4D7314409059BDC3ED504A40C094DA8B687B144048581B6327504A4000C0CE4D9B811440C0F561BD514F4A40C075A8A6248B1440A05698BED74E4A4000AC5791D1911440A05698BED74E4A40C0EBC1A4F8981440709D6340F64E4A40409735B1C0A71440C82BBB60704F4A40409180D1E5CD14408024253D0C514A40002828452BE7144020B41EBE4C524A4040A8FC6B79F51440E042572250534A40401EC18D94FD1440E0E2E13D07544A40C0145B41D3021540780F4240BE544A4000F67EA31D0715407057AF22A3554A40404A0A2C80091540A85912A0A6564A40008A1F63EE0A1540B06B26DF6C574A40C0931799802F1540507C7C4276584A40C0A8FC6B793515400818080264584A4000B81E85EB51154000BB9A3C65574A4000FED7B969831540580438BD8B554A40403F373465871540885182FE42554A404045B9347EB11540805D86FF74514A400103000000010000001B0000000021B248130F1340608E0244C17E4A40C09F1B9AB203134008C45DBD8A7E4A4080FE092E56F41240F8298E03AF7E4A40C01FB75F3EE9124078A52C431C7F4A40C0E07F2BD9E11240B06E2EFEB67F4A400097715303DD12405001F73C7F804A4000B6F63E55D51240A8E67283A1824A40C0C77C40A0D3124008240C0396844A408013B35E0CD5124008CD203EB0854A40C006B47405DB1240D009A1832E874A40008B7269FCE21240507C7C4276884A40402634492CF91240D082177D058B4A4040643E20D0691340686D37C137974A40809BC6F65A70134000D3A23EC9974A40C06ABB09BE791340206552431B984A4040E4A25A448413406037177FDB974A4000E9297288881340888461C092974A4040DF52CE178B1340286E15C440974A4080C422861DA61340E08BDAFD2A924A4080C422861DA613408887A2409F8C4A4080C64ACCB3A2134010C79E3D978B4A4000977153039D1340D0D03FC1C58A4A4000105EBBB481134030F38FBE49874A4080F1D3B8376F1340889FAA4203854A40C07C410B09381340D8F71A82E3804A4080884A23662613406037177FDB7F4A400021B248130F1340608E0244C17E4A4001030000000100000014000000800C040132D41340A8DA6E826F9E4A408020B248138F1340E0FD9C82FC9A4A404047E6913F881340F0E769C0209B4A40000D36751E85134058FEB5BC729B4A4040B728B34186134050431B800D9C4A4000E9297288881340D0BEB9BF7A9C4A40401E8A027D921340600438BD8B9D4A4080C422861DA613402841B8020A9F4A4040ED7E15E0DB1340B06BED7DAAA24A4000E5D4CE30F513405870784144A44A40C053E57B46021440809FAA4203A54A4080E6012CF20B1440001B498270A54A40407D410B093814405040DAFF00A74A40007497C45951144008D3A23EC9A74A4040F2052D24601440B0E9B303AEA74A4080C422861D6614403020ED7F80A74A4000B0743E3C6B1440306E15C440A74A4080BFD2F9F06C1440D076137CD3A64A4040A8C5E0616A144050FB743C66A64A40800C040132D41340A8DA6E826F9E4A400103000000010000001900000080FF04172BDA144040D505BCCCAC4A404032384A5ECD1440B8ECF483BAAC4A40401A355F25BF1440B0716F7EC3AC4A40C05417F032B31440D088997D1EAD4A4080FBAA5CA8AC144028327381CBAD4A40C0AF743E3CAB1440A8AD11C138AE4A40406CED7DAAAA1440888D2441B8AE4A4040BFD2F9F0AC14406037177FDBAF4A40C0F1D3B837AF1440B0B393C151B04A40404069A851B8144008301004C8B04A4000EB56CF49DF1440B8B915C26AB24A40C0C1FA3F87E91440D8D03FC1C5B24A4080DB2F9FAC281640E0C1FA3F87B94A40C02EE3A6063A164040D8463CD9B94A40804C6DA9834C1640603D997FF4B94A400038BF61A2511640588BC1C3B4B94A40C069C020E95316405073B9C150B94A400038BF61A251164010CADFBDA3B84A4080E4D9E55B4F1640904E417E36B84A4080E6012CF24B1640E0D38041D2B74A400047E6913F4816403820ED7F80B74A4040D5AD9E933E1640B8A44E4013B74A40C0633E20D069154008301004C8B04A400078F17EDC3E1540888461C092AF4A4080FF04172BDA144040D505BCCCAC4A40010300000001000000E002000040240C03967C1B40885182FE42B54A40008813984E9B1B4010D6E3BED5AC4A40C053E57B46C21B40A8C2D84290A94A4040A5A2B1F6C71B40E0A9F23D23A94A4080CAA48636501C40A85CA8FC6BA14A4000448CD7BC5A1C40D0F71A82E3A04A4000323D6189671C406001F73C7FA04A4080B950F9D7C21C40588E0244C19E4A400077BF0AF0CD1C40F8298E03AF9E4A40007C462234D21C40D876137CD39E4A40C0A7565F5DD51C402027F73B149F4A40000C040132D41C4010C45DBD8A964A4040B3CEF8BED81C40A8A10DC006824A404046B41D53D71C40504F1F813F804A408090F46915CD1C40D80CE2033B7C4A404079E75086CA1C40A8622AFD847B4A4000F30016F9C51C4078812040867A4A40807C410B09B81C40908461C092774A400047E6913F881C40E073D2FBC6714A4040FBEAAA405D1C40C8E95DBC1F6B4A40807E6E68CA4E1C40C8C1FA3F87694A40803F373465471C40B0B393C151684A40C0A7CAF78C441C40081286014B664A40C05B94D920431C40F0230C0396644A400054E57B46421C40D0B837BF61624A4040B950F9D7421C40E0B2B5BE48604A40C0A9F23D23411C4038F6D03E565C4A400082C8224D3C1C40B09ECC3FFA544A4040E2AC889A381C4050FEB5BC72534A40C04291EEE7341C40E0B837BF61524A4040A3755435311C40E873D2FBC6514A40405A677C5F2C1C40E00F238447514A40809AD024B1241C4030E109BDFE504A40408D9AAF921F1C40385C8FC2F5504A40009A999999191C40385C8FC2F5504A4000EA245B5DAE1B40E873D2FBC6514A40000E315EF3AA1B40383E7782FD514A4000CCD1E3F7A61B406082FE428F524A4040EB56CF499F1B40B0B0524145534A4040ED7E15E09B1B4050FEB5BC72534A40800C040132941B4000C79E3D97534A404094490D6D201B40082DCF83BB534A40C01D8A027D121B40A0DDAF027C534A4000FBAF73D3061B4038E78BBD17534A400083C30B22E21A40B0656B7D91504A40005FD5592DE01A40D84FAA7D3A504A4000323D6189E71A402020ED7F804F4A40000E315EF3EA1A40B077F17EDC4E4A40C0DE52CE170B1B40706649809A484A40C0921CB0AB091B40E0B2B5BE48484A40C0B628B341061B40286552431B484A4080703D0AD7E31A4060853FC39B474A4040B950F9D7C21A403029B000A6464A40404C361E6CC11A40101286014B464A40C0E3D9E55BCF1A40E0F19881CA3E4A40001E8A027DD21A40E0AC33BE2F3E4A4000FED7B969031B40E0AF743E3C3B4A40007F6E68CA0E1B40D0D03FC1C53A4A40008B6D52D1C81B4058853FC39B374A40C0D47B2AA7CD1B40B8E9B303AE374A4000D253E410D11B405837177FDB374A404097715303DD1B40582E54FEB5384A4040DE57E542E51B40B05CA8FC6B394A400094179980EF1B40A8984A3FE13A4A40C05417F032F31B40D082177D053B4A4080300BED9CF61B403035B401D83A4A400082C8224D3C1C40D882177D05334A4040BC783F6E3F1C40D0B837BF61324A40C05B94D920431C4028F911BF62314A40408B6D52D1481C40D8FA5B02F02D4A40803F373465471C40386893C3272D4A40C0C2853C823B1C40586D37C1372B4A4040CCD1E3F7261C40D000DE0209284A4000D9D0CDFE201C4088AEEFC341264A4040DBF813951D1C40A8ECF483BA244A4040F52D73BA1C1C40E87954FCDF234A4040F52D73BA1C1C4050FEB5BC72234A4080F2052D24201C40B0B915C26A224A40C07406465E361C40A01D37FC6E1E4A4000B0743E3C2B1C401048A643A71D4A4000ED7E15E0DB1B4028172AFF5A184A40409F20B1DD9D1B4048499D8026164A40C0438CD7BC9A1B40D8FA5B02F0154A40C0F5285C8F821B40009A417C60134A40C0A9F23D23811B40E082177D05134A40C05DBC1FB77F1B40B074B0FECF114A4000C64FE3DE7C1B40D8CABDC0AC104A4000EA5BE674791B40E08558FD11104A4040A3755435711B4000BB9A3C650F4A40405C8FC2F5681B40F808C380250F4A404085EB51B85E1B40B0A44E40130F4A4000AB5E7EA7091B40782A1900AA0E4A40C0AA24B20FF21A40B874B0FECF094A404006820019EA1A40A8BF97C283044A40C0035ABA822D1B405873B9C150014A40C0989EB0C4331B40D07C957CEC004A400077BF0AF04D1B4010C45DBD8AFE494040B81E85EB511B40D088997D1EFD494000E2B19FC5521B4030F6D03E56FC494000301004C8501B4008C79E3D97FB49400076C4211B281B40D8F19881CAF64940404B3B35971B1B40E0FA5B02F0F549404082C8224DFC1A4000DFA63FFBF349408022DFA5D4E51A40881EA33CF3F2494080E07F2BD9E11A4090992842EAF24940807E6E68CACE1A40582B137EA9F3494000B728B341C61A4038F6D03E56F4494000E4A25A44C41A409087A2409FF449404070422102BE1A40809FAA4203F5494080FE092E56B41A40A89ECC3FFAF4494040D9D0CDFE601A40004BE7C3B3F24940C0B0A6B2281C1A40B89B8BBFEDEF4940805DC136E2D91940885182FE42ED494000323D618967194030232E008DEC494000944E2498BA18405007793D98F2494080D5AD9E937E1840888AE3C0ABF14940405B94D92003184020F04E3E3DEA49408099999999D9174008BB9A3C65E7494040ED7E15E0DB174080A52C431CE7494000BFD2F9F0EC1740B0BF97C283E44940C09BC6F65AF01740B07A32FFE8E34940004D689258F21740E08BDAFD2AE249404045B9347EF11740D873D2FBC6E14940C059677C5FEC17406073B9C150E14940003C4CFBE6CE1740186C5CFFAEDF494040DBF813951D1840201DACFF73DA494040EB56CF495F1840E0CDFE40B9CD4940C094490D6D601840A8B6D4415ECD4940803788D68A861840D00F238447C9494080E6012CF28B18409018213CDAC849408046EBA86AA21840B8BC564277C74940C020B24813CF1840D08BDAFD2AC24940C0AD47E17AD41840D80F238447C14940C02CB64945E3184080423D7D04BC494080F0DDE68DE31840D0C77C40A0BB4940803465A71FE41840002A8E03AFAE494080F0DDE68DE31840101286014BAE4940001E8A027D92184038327381CBA54940C02F1004C85018403041B8020A9F4940803AE7A7384E1840588E0244C19E494000356090F4491840B07A32FFE89B4940C0F0D8CF62491840A8622AFD849B4940004F95EF1949184028E78BBD179B4940404C6DA9834C1840B8B393C15198494040DC2A88814E1840E009A1832E974940C07497C4595118408860C77F8196494080583A1F9E551840D07FD6FCF8954940803106D6715C1840B068ACFD9D954940C0703D0AD7631840F82F1004C8904940405B94D920031840D0D03FC1C58A4940403465A71FA417408821E4BCFF87494040378DEDB5A0174080C9C6832D88494000B1A6B2289C1740D08558FD11884940C0DAFD2AC077174060499D802686494000A8FC6B79751740801B62BCE6854940C04291EEE7741740B0E3310395854940C0D026874F7A1740A0B915C26A82494040D253E410911740B0BF97C2837C4940405DC136E2991740805A457F687C494080E07F2BD9A1174058888043A87C4940C014AE47E1BA1740D0CDFE40B97D4940403F373465C7174008E52840147E49400023DA8EA9CB174008E52840147E494080B81E85EB11184008A0C37C797D494040FF04172B1A184080CC07043A7D494000977153031D1840789FAA42037D4940807C46223452184088CC07043A7549400026396057531840383B3602F174494000022D5DC1561840D0D38041D26F4940009CC1DF2F561840D8BB783F6E6F4940C0F0D8CF62491840D0B5F63E556D4940808D959867451840A8716F7EC36C49400054E57B4642184008240C03966C4940001286014B3E1840D8BEB9BF7A6C4940C06ABB09BE39184008240C03966C4940C04291EEE7341840000341800C6D494040F1D3B8372F1840000341800C6D494080438CD7BC1A1840A8BF97C2836C4940C03AE7A7380E1840F02CCF83BB6B4940C0D47B2AA70D18400015C781576B49408047E6913F081840002A8E03AF66494040A260C6140C1840D09A9141EE604940007F69519FB41740F82F1004C8604940C024CFF57D9817406001F73C7F604940407A19C5727B174030F911BF62614940803D0AD7A3301740081E8A027D624940804069A851F816404873B9C1506149404091EF52EAF2164078ABAE4335614940C0A27A6B60CB164028E109BDFE60494080F8325184C41640D8D64FFF59614940803AE7A738CE164000E869C020634940007715527ED216406885CD001764494000B81E85EBD11640F8230C0396644940807E6E68CACE16401009C38025674940808B153598C61640D0C1FA3F8767494040BEA08504BC16406037177FDB674940C0EA56CF499F1640D00F238447694940808713984E9B1640A8C2D84290694940C0CAA48636901640A8DDAF027C6B49400033384A5E8D1640B859677C5F6C494000CDCCCCCC8C164010D6E3BED56C4940C03AE7A7388E1640D0FA5B02F06D4940402861A6ED8F1640A85FE97C786E4940009A999999991640484F1F813F704940C09CF86A47A11640C8CABDC0AC7049400047E6913F081740B8984A3FE17A4940C0DC2A88810E1740908D2441B87E4940804B3B35971B17403014E97E4E8349408051BD35B0451740808D2441B88E4940C099D024B164174040D8463CD991494000D48041D2671740386BD4433492494000CDCD37A26B1740906055BDFC9249408052B81E856B17400815C7815793494040D926158D651740D0DF844204944940C05FE97C7856174088CC07043A954940C0E3A25A44041740B8B393C151984940000C04013294164088A2EBC20F9A494040D21C59F9451640006F0F42409C494040D8D5E4293B1640E873D2FBC6A1494000310BED9C3616408881204086A2494080D576137C331640A8984A3FE1A2494000B6F63E55151640885182FE42A5494000DF52CE170B164008CD203EB0A54940C0A7CAF78C04164038327381CBA54940806893C327FD1540901B62BCE6A54940C045B9347EF115406831957EC2A5494040CCD1E3F7E61540B0ECF483BAA44940004913EF00DF1540100C040132A4494040DE57E542A51540D88BDAFD2AA24940002FDE8FDB9F154080A2EBC20FA249408099999999991540383E7782FDA149404038BF61A2511540A0C2D84290A149408060AA99B5F4144008A6457D92A14940807F69519FF414405840DAFF00A74940805417F032F31440A8BC564277A7494080F1D3B837EF1440F84D2844C0A74940009AD024B1E4144090C9C6832DA849404077BF0AF0CD1440E07C957CECA84940809DF3531CC71440305C8FC2F5A84940800F5EBBB4C114408018213CDAA8494040963FDF16AC1440604F1F813FA849400085EB51B89E1440009D82FC6CA84940C025396057931440F82F1004C8A84940C0E3D9E55B8F144088457EFD10A94940C013B35E0C55144028F911BF62B14940408ECC237F501440D006600322B249408020B248134F14406007793D98B2494040DC2A88814E1440306211C30EB3494080861DC6A44F1440D8C77C40A0B3494040B81E85EB511440E8A6B1BD16B4494080AB1F9BE457144010D6E3BED5B44940004B3B35975B1440386893C327B5494040323D6189671440F8298E03AFB6494000643E20D069144078A52C431CB74940400E315EF36A1440A0E9B303AEB74940C046EBA86A62144050465C001AB94940C07B462234521440789065C1C4BB494040DF52CE174B1440B859677C5FBC494080A8C5E0612A1440001286014BBE494040D6A887682414406076FA415DBE4940404E637B2D181440B0E3310395BD4940407497C45911144078397AFCDEBC4940C0861DC6A40F1440B859677C5FBC4940C090F469150D1440E006600322BA4940C0921CB0AB091440D8A9F23D23B949400000000000001440D800DE0209B8494000E5D4CE30F5134078A52C431CB74940001E8A027DD21340D8BEB9BF7AB4494040B950F9D7C21340009A417C60B3494080D5AD9E93BE1340F8E769C020B34940804069A851B81340E082177D05B34940C0C1FA3F87691340000341800CB5494040726F7EC35413403041B8020AB7494040D9D0CDFE601340286211C30EBB49404046EBA86A621340E088997D1EBD494000E17F2BD9611340B0E3310395BD4940C0D47B2AA74D13405840DAFF00BF494040D026874F3A1340B89B8BBFEDBF4940406E15C4402713400818080264C04940402FDE8FDB1F1340507C7C4276C0494040C87C40A013134038172AFF5AC04940403F373465071340808461C092BF4940401E8A027DD21240E0A6B1BD16BC4940C0A27A6B60CB124058FEB5BC72BB494040F1D3B837AF12408818213CDAB8494000FCAA5CA8AC1240089D82FC6CB84940C04F90D8EEAE12402820ED7F80B7494040A3755435B112400809C38025B7494000B5FB5580AF124048D1CABDC0B6494040FF04172B9A1240D8AC33BE2FB64940000C04013294124060499D8026B6494080F98216123012408060C77F81B64940400E315EF32A12405028D2FD9CB6494040C422861D261240805704FF5BB74940403465A71F241240D8B2B5BE48B84940403465A71F2412409093A641D1B8494000CCD1E3F7261240903CBB7CEBB94940005A677C5F2C124000D061BEBCBA49408069C537142E1240E0AF743E3CBB4940005517F03233124030D505BCCCBC4940C03AE2900D341240A0B6D4415EBD494000EFAB72A132124038327381CBBD4940C0AD4CF8A52E124010E5284014BE494080DB2F9FAC28124058499D8026BE4940804D689258F21140600438BD8BBD4940C0035ABA82ED1140A0B6D4415EBD494040C554FA09971140483D997FF4B94940C02539605793114000274D83A2B94940809CC1DF2F961140A8B6D4415EB549404007B474059B1140F8230C0396B449408015E0BBCDAB1140D0FD9C82FCB249408077F17EDCBE11405801F73C7FB0494040A243E048C01140E000DE0209B04940802EE3A606BA11403029B000A6AE4940008FC70C54B61140089700FC53AE494040FCAA5CA8AC1140D07FD6FCF8AD494080D8D0CDFEA0114030327381CBAD49408032384A5E8D11406031957EC2AD494080931799806F114008E5284014AE4940802CB6494563114068FB743C66AE4940002B6EDC621E1140306BD44334B04940403ACAC16C021140082159C004B0494080E4D9E55BCF1040C8F4D901D7B3494040EA5BE6743910408060C77F81B6494080EA245B5D6E0F40A0E9B303AEB7494000963FDF166C0F4078A52C431CB7494000313D6189670F402829B000A6B64940002A931ADA400F40584CDE0033B3494000EFAB72A1320F405082FE428FB24940002CB64945A30E4008D9243FE2B14940007A1EDC9D950E40803CBB7CEBB14940807A1EDC9D950C40D8F71A82E3B8494080B4CEF8BE580C40D88BDAFD2ABA4940004A0ED8D5440C40A8E67283A1BA49400085EB51B89E0B40004BE7C3B3C2494000A37A6B608B0B40282CF180B2C3494000B728B341860B4060431B800DC4494080FBAF73D3860B4000240C0396C44940005B626534920B40B0B6D4415EC549408094490D6DA00B40205FD04202C64940001F85EB51B80B40E876137CD3C649400047EBA86AE20B40286552431BC8494080BEA59C2F160C40D8C1FA3F87C9494080DF4DB7EC300C4028F04E3E3DCA494080C4591135710C408015E0BBCDCB4940806F10AD158D0C4008BEDBBC71CC494000F98C4468A40C408087A2409FCC49400014C95702890D40B8471ADCD6CC494000A1168387A90E400048A643A7CD494080EFAB72A1B20E400048A643A7CD494000D676137CF30E40B89ECC3FFACC4940009CFD8172FB0E40500DFB3DB1CC494000809BC58B250F406834D6FECECA494000D0EFFB372F0F4088A2EBC20FCA494000736A67983A0F408093A641D1C8494080630CACE3380F4030172AFF5AC849408024D5777E310F40E000DE0209C8494080963FDF16EC0E40D07FD6FCF8C549408083F8C08EBF0E40C888B663EAC64940008ECC237F900E40101286014BC6494000F0C9C342ED0E4090CC5CE0F2C4494080E161DA37170F4020902FA182C5494080272F32015F0F40101286014BC6494080A59D9ACB6D0F40E0AC33BE2FC64940008C9FC6BD790F40205FD04202C6494000FBAF73D3061040D8AF743E3CC349404020B75F3E291040F8264D83A2C14940C02634492C391040502E54FEB5C04940400D36751E451040905704FF5BBF4940C0FAAF73D346104010DC65BFEEBE4940406AC020E953104050431B800DBC49404083C30B22621040E873D2FBC6B9494080E7FC14C771104000301004C8B84940C0656B7D91801040386552431BB8494000B6F63E55951040F8D2A23EC9B7494040ED7E15E09B1040004E2844C0B74940C0989EB0C4F31040500ABABDA4B74940C02634492CF91040004E2844C0B7494080B950F9D702114030EACC3D24B84940001478279F0E1140D8334B02D4B84940C0ED7E15E01B114030E109BDFEB84940C0368DEDB5201140B0AAD0402CB94940401A3048FA241140B05CA8FC6BB949408076C4211B281140B874B0FECFB9494040A8C5E0612A114038F04E3E3DBA494000FCAA5CA82C114038DEC83CF2BB494000B0743E3C2B1140503A58FFE7BC494040643E20D0291140D0B5F63E55BD494040F0DDE68D2311409060C77F81BE4940407497C45911114088457EFD10C149408090F469150D114060F833BC59C149408075A8A624EB10405897530262C24940003206D671DC10400806820019C2494040301004C8D01040883CBB7CEBC1494000726F7EC354104030DEC83CF2C3494080F5328AE5F60F40E08BDAFD2ACA49408052B81E85EB0F402835B401D8CA4940006216DA39ED0F403014E97E4ECB4940805DC64D0DF40F40D8C77C40A0CB4940805B94D920031040E8A6B1BD16CC4940C00D315EF32A104008A0C37C79CD4940405EBC1FB73F10409048BF7D1DCE494080D253E41051104060FB743C66CE494000A69D9ACBAD1040587FBDC282CD494000B950F9D7C21040583A58FFE7CC494080E9297288C81040500DFB3DB1CC4940805F5E807DD4104020DBDD0374CB494040583A1F9ED51040A8622AFD84CB49400060E97C78D61040E8A6B1BD16CC494080E1B19FC5D21040583A58FFE7CC49408076BF0AF0CD10400048A643A7CD4940C04E95EF19C9104060FB743C66CE49400061E28FA2BE1040E89CD843FBCE4940C0633E20D0A91040608E0244C1CE4940C0DBF813959D10402829B000A6CE49404020B248138F1040888D2441B8CE4940C0346090F4891040B877F17EDCCE4940003BE2900D741040D0CABDC0ACD0494040A3755435711040D0C1FA3F87D1494040AA4203B16C10403835423F53D34940C0C1FA3F8769104080992842EAD249400046EBA86A621040B053E57B46D2494080438CD7BC5A1040608BC1C3B4D149400077BF0AF04D1040385C8FC2F5D04940C0634337FB431040886649809AD04940400C040132141040C05626FC52CF4940C04E95EF19091040A8A44E4013CF494080A4703D0AD70F40002A8E03AFCE4940800AD7A370BD0F402829B000A6CE494080B6F1272A3B0F4050465C001AD149408024D5777E310F405873B9C150D1494080128B1876180E4058FB743C66D6494080622AFD84B30D40E8361AC05BD6494080E82E89B3A20D403829B000A6D64940805A626534920D40606D37C137D74940804487C091800D40604F1F813FD84940806793C3277D0D40E0CABDC0ACD8494000E18442047C0D40D0A9F23D23D949400001000000800D403035B401D8DA494080DCF3FC69830D401015C78157DB4940002B89EC838C0D405870784144DC49408095490D6DA00D40805182FE42DD4940000F27309DB60D40E0FA5B02F0DD494000366090F4C90D40F81186014BDE494000630CACE3380E403020ED7F80DF4940808E959867450E40908461C092DF49400000000000800E40B05626FC52DF4940003B1E3350990E40789FAA4203DF4940803E373465070F40586D37C137DF494080F2CEA10C150F40586D37C137DF4940807F9BC58BA50F40E0AC33BE2FDE4940805EBC1FB7BF0F40901B62BCE6DD494000DD2A8881CE0F40505260014CDD494080A7CAF78C041040A0984A3FE1DA494040A7CAF78C441040803FFCFCF7D64940C06BED7DAA6A1040B0ECF483BAD44940C0D576137C7310408096E7C1DDD54940C0D24ECDE5761040E8AC33BE2FD6494040BC783F6E7F1040F8298E03AFD64940008D9AAF929F1040F020CB8289D7494040185FB4C7AB1040308FFCC1C0D749400054E57B46821040201DACFF73DA4940C06893C3273D104090C9C6832DE04940802EE3A6063A104010E2E7BF07E14940C08C9AAF921F1040500DFB3DB1E44940003206D6711C1040789FAA4203E54940400C040132141040B8E3310395E54940008E95986705104080AEEFC341E649400009E1D1C6F10F40E0C43BC093E64940802C7FBE2DD80F40608E0244C1E64940807F9BC58BA50F405828D2FD9CE64940002F6CCD56FE0E4048CB48BDA7E4494000A69D9ACBED0E40A85626FC52E7494080963FDF16EC0E4000D3A23EC9E74940001E8F19A8EC0E40B0B393C151E8494000C5591135F10E4008301004C8E8494080E7012CF20B0F40885D86FF74E94940809E20B1DDDD0F4028F6D03E56EC494000295C8FC2F50F40A8BF97C283EC494000FBAF73D3061040B859677C5FEC4940802861A6ED0F1040D87954FCDFEB4940C0B0A6B2281C1040D882177D05EB4940C0D5AD9E933E10408848BF7D1DEE494000D253E410111040D0F4D901D7FB49400089450C3B0C1040386893C327FD4940804C6DA9830C10400048A643A7FD494080E4D9E55B0F104030E44A3D0BFE494040583A1F9E151040B05FE97C78FE494040D48041D227104068FB743C66FE494000045ABA822D1040A8AD11C138FE4940C0230C03963C104030E44A3D0BFE494040B81E85EB511040D8FA5B02F0FD49400022DFA5D4651040D07FD6FCF8FD494080E7FC14C771104048499D8026FE4940C0656B7D91801040002A8E03AFFE4940C032384A5E8D1040B8BC564277FF4940805512D907991040B0B393C151004A408091EF52EA721140D07FD6FCF8154A4000EA5BE674791140002A8E03AF164A4080999999999911405855A181581A4A4000C74ACCB3A21140A8DDAF027C1B4A4080AD4CF8A5AE1140889FAA42031D4A40C096766A2EB71140A8AD11C1381E4A4080E3A25A44C41140A8B393C151204A40C04598A25CFA114010D9243FE2294A40807C462234121240D8AC33BE2F2E4A40C0D38041D2271240306BD44334324A400016E0BBCD2B1240884B00FE29334A4080FE092E56341240E0CDFE40B9354A40C051BD35B045124010C11C3D7E394A40807E6E68CA4E1240A8E67283A13A4A4040137F1475561240F0845E7F123B4A404091F0BDBFA1124000000000003A4A4080D76839D0D31240F07BD45FAF364A40008483BD896113404071395E81344A4000A453573E8B1340E81E12BEF7314A40C00F0533A6A01340E0486760E42F4A40C0944A7842CF13405831957EC22F4A4000DBFD2AC0F71340B0AD11C1382E4A4080B1A19BFD811440B853E57B462A4A40C04C689258F214408021E4BCFF274A40001A355F25FF1440B09B8BBFED274A4080490ED8D5041540104E2844C0274A4040180802642815406028D2FD9C264A4040E7FC14C73115408048BF7D1D264A4040295C8FC23515408096E7C1DD254A40C0E63C635F52154088B130444E234A40405DC136E2591540B0B0524145234A40007F69519F741540084BE7C3B3224A4080A243E048801540281DACFF73224A40C04E95EF19891540883CBB7CEB214A40009CF86A47A11540484F1F813F204A400052B81E85AB15403038F581E41F4A4040EFAB72A1B21540C8D38041D21F4A400085F068E3B815403038F581E41F4A4040F0A65B76181640B874B0FECF214A408046EBA86A221640286BD44334224A40C03F321D3A2D164030E78BBD17234A40808EC70C543616405870784144244A400022E4BCFF3F164010E5284014264A40C0E17A14AE471640E08558FD11284A4000861DC6A44F16404873B9C150294A4040C554FA09571640583D997FF4294A40405EBC1FB77F1640D8B5F63E552D4A4040A7CAF78C841640B068ACFD9D2D4A4000AD4CF8A5AE16400021CB82892F4A40C0F65D11FCBF164070B587BD50304A4040861DC6A4CF164038E109BDFE304A4000F0DDE68DE31640508BC1C3B4314A40C074E61E12EE164070BB7B80EE314A404003250516F016400800000000324A408084F068E3F816408854C37E4F324A40803788D68A061740781EA33CF3324A40008F8B6A11111740789DF17D71334A4080B3CEF8BE181740D87954FCDF334A4080C45C52B53D1740D082893F8A364A4040BD35B055421740989C853DED364A40C03C122F4F47174028D8B8FE5D374A4040884A2366661740206211C30E3B4A40805C8FC2F5681740A0DDAF027C3B4A40C05B94D92083174078ABAE4335414A404029965B5A7D1740389E4143FF424A4000713D0AD7631740602E54FEB5484A40401A3048FA641740584CDE00334B4A408052B81E856B1740A04A7842AF4D4A40C04E95EF19091740F847A643A74D4A408096766A2EB71640E0CDFE40B94D4A40C0DB2F9FACA816408896E7C1DD4D4A40801808026468164030DEC83CF2534A404022DFA5D465164068F5F23B4D544A4040DE57E54265164030D505BCCC544A40803E3C4B90611640E876137CD35E4A40C0EFDDE68D631640607C7C4276604A40C0809BC58B65164038E109BDFE604A40802EE3A6067A1640809065C1C4634A40008B7269FCA21640302F3201BF684A4000FCAA5CA8AC1640E873D2FBC6694A4040E5D4CE30B516408054C37E4F6A4A408010ACAA97DF164070B2463D446B4A40C04B3B3597DB1640886308008E6B4A400007B474059B1640F89FC37C796D4A4040B6F63E55951640487FBDC2826D4A40409CF86A4761164008240C03966C4A404007B474055B16408815E0BBCD6B4A4080B3CEF8BE581640F814C781576B4A4040583A1F9E551640D882177D056B4A40804C6DA9834C1640001E8A027D6A4A40C007AF5DDA4016405855A181586A4A4040FCAA5CA8AC1540809FAA42036D4A4040884A2366A6154028ED0DBE306D4A404009DCBA9B971540901B62BCE66D4A40401A355F257F1540600ABABDA46F4A40C0E95BE67479154030172AFF5A704A40803BE2900D741540B0C2D84290714A40C0300BED9C76154078A2EBC20F724A4080C64FE3DE7C1540C8D03FC1C5724A40C06211C30E93154090423D7D04744A4080DBF813959D154038F6D03E56744A40002A8E03AFA6154000D6E3BED5744A40C0313D6189A71540281A6B7F67754A4040FCAA5CA8AC1540D0C1FA3F87794A4040AD4CF8A5AE154060FEB5BC727B4A4040DE57E542A51540302CF180B2834A40803E3C4B90A11540D0BEB9BF7A844A4000666B7D9180154000E2E7BF07894A40404391EEE774154028E109BDFE884A40008813984E5B15400818080264884A40C08EC70C54361540588E0244C1864A40401808026428154020E44A3D0B864A400033384A5E0D1540A8BF97C283844A4040E1D1C611CB1440C897C283667F4A40802A8E03AF66144058F833BC59794A40C09E20B1DD5D144030F911BF62714A40C0A9F23D23811440E00F238447694A408051BD35B0C51440B8656B7D91604A4040356090F4C914408093A641D1604A40C020B24813CF1440285C8FC2F5604A40C05A99F04BDD1440285C8FC2F5604A40C059677C5FEC144008301004C8604A4000977153031D1540286552431B604A40001B3048FA2415403020ED7F805F4A4080C1FA3F87291540E876137CD35E4A408052B81E852B1540B8DA6E826F5E4A4000AD4CF8A52E1540A0E33103955D4A40C038BA4A77371540101E8A027D5A4A40C0A8FC6B79351540583D997FF4594A40000686AC6E05154008A304FD85584A404038BA4A77F7144030232E008D544A408015E0BBCDEB1440602B137EA9534A4000F1D8CF62C9144000274D83A2514A40C015E0BBCDAB14405001F73C7F504A40C0012D5DC19614405837177FDB4F4A40C07497C459911440B06E2EFEB64F4A4040F8872D3D8A1440B06E2EFEB64F4A404047E6913F88144030EACC3D24504A4080BFD2F9F06C1440286BD44334524A4000D48041D2671440281DACFF73524A40C02634492C391440A853E57B46524A40805417F032331440D88BDAFD2A524A4040643E20D0291440D0EE5701BE514A40C082C30B22221440A8AAD0402C514A4040DBF813951D1440904E417E36504A4080F52D73BA1C1440C05626FC524F4A40C05A99F04B1D1440E076137CD34E4A40C051B81E852B1440885D86FF74494A4000013274EC301440804E417E36484A40C08D959867451440505260014C454A4080F755B950591440B853E57B46424A4040416491265E1440305C8FC2F5404A40004913EF005F1440D000DE0209404A40C03106D6715C1440B0BC564277374A40402861A6ED4F1440885182FE42354A408031EA5A7B2F1440C0313D6189334A4040977153031D1440286552431B304A4000C554FA09171440E000DE0209304A4040301004C8101440286552431B304A408093179980AF1340B85CA8FC6B314A404083C30B22A21340508BC1C3B4314A40800F5F268A801340200B0A8332354A400096B1A19B4D1340B880423D7D364A4080C9039145DA1240380E2E1D73384A408036AAD381AC12404059A31EA23B4A40C0B81E85EB511240B059677C5F3C4A40807497C45951124090397AFCDE3C4A40C0438CD7BC5A12403829B000A63E4A40009AD024B1641240D873D2FBC6414A40006893C3277D1240B859677C5F4C4A40409DF3531C871240A8AAD0402C514A4040A27A6B608B1240A0DDAF027C534A4080DE52CE178B124088A52C431C574A40009F20B1DD9D1240804E417E36604A404052B81E85EB124058F833BC59794A4040573F36C9EF12408854C37E4F7A4A404096766A2EF71240801EA33CF37A4A40805EBC1FB7FF1240584CDE00337B4A4000F0A65B76181340B0DDAF027C7B4A4040963FDF162C1340906308008E7B4A40C0F1D3B8372F134060FEB5BC727B4A4080C64FE3DE3C134088A2EBC20F7A4A40C02BBB60703D134000CADFBDA3784A408014AE47E13A1340804E417E36784A40002734492C391340A8E9B303AE774A4040D026874F3A1340908D2441B8764A40C0BEA085043C1340101286014B764A40C007AF5DDA401340500438BD8B754A40003AE7A7384E1340A8ECF483BA744A40404E637B2D5813405070784144744A40805417F032731340484CDE0033734A40402CBB60707D13403035B401D8724A40C0CCCCCCCC8C1340004BE7C3B3724A40C0E2A7716F9E1340881EA33CF3724A40C014AE47E1BA1340B0622AFD84734A40C051BD35B0C51340D0F4D901D7734A4080AB1F9BE4571440B853E57B467A4A4080C1FA3F87691440A0B05241457B4A40C0E2AC889AB814401018080264804A4000E9667FA0BC1440A80E643DB5804A404022DFA5D4E5144088A86DC328844A40C0230C0396FC1440285FD04202864A4080490ED8D5041540D8C43BC093864A40C04291EEE73415405073B9C150894A400021B248134F1540D08BDAFD2A8A4A408045B9347E7115405834D6FECE8A4A40809F1B9AB2831540002DCF83BB8B4A4040A27A6B608B1540B059677C5F8C4A408076BF0AF08D154028D505BCCC8C4A40C0B0A6B2289C15400021CB82898F4A40801A3048FAA41540503D997FF4914A40C00D315EF3AA154088397AFCDE944A40805C8FC2F5A815405831957EC2954A404020B75F3EA91540081286014B964A40400D36751EC51540F0E769C0209B4A4000583A1F9ED51540283B3602F19C4A40805A99F04BDD1540600438BD8B9D4A40C0DE52CE174B164090397AFCDEA44A40404E637B2D581640D0CDFE40B9A54A40C0809BC58B651640A0DA6E826FA64A4080CAA48636901740D07C957CECB04A408040321D3AED1740286211C30EB34A404085EB51B85E184008240C0396B44A40803D0AD7A3B01840283B3602F1B44A40003E4162BBBB1840B09ECC3FFAB44A40C0BBEB6CC8BF1840D0F19881CAB44A40003F373465C71840D0BEB9BF7AB44A40C0F982161230194058FEB5BC72B34A4000E4D9E55BCF1940B0DA6E826FB64A4040F8872D3DCA1A4008E869C020BB4A408046EBA86AE21A40B8DDAF027CBB4A4000DBFD2AC0F71A40D0C77C40A0BB4A4080B0A6B2281C1B40D0D03FC1C5BA4A408052B81E856B1B40604F1F813FB84A40C0D576137C731B40889C69C2F6B74A40402EE3A6067A1B40F020CB8289B74A40C081C8224D7C1B4030F38FBE49B74A40C03D4162BB7B1B4028E44A3D0BB64A4040240C03967C1B40885182FE42B54A400103000000010000001D000000C0E6012CF2CB1640D8AF743E3CBB4A4080E07F2BD9E1164030E78BBD17BB4A40404069A851381740089A417C60BB4A4000B0743E3C6B1740909065C1C4BB4A404085EB51B89E1740B0A78FC01FBC4A40805EBC1FB7BF1740E00CE2033BBC4A40403AE7A738CE174090423D7D04BC4A40001E8A027DD21740002DCF83BBBB4A40006211C30ED31740D8AF743E3CBB4A40403D0FEECECA1740004BE7C3B3BA4A408077F17EDC3E174080C9C6832DB84A404045B9347E31174030EACC3D24B84A4000ED7E15E01B17400818080264B84A40C01B62BCE6151740806649809AB84A4040D5AD9E93FE16408018213CDAB84A404091EF52EAF2164010CADFBDA3B84A400082C8224DBC1640B0DA6E826FB64A4040884A2366A61640D8C43BC093B64A40009A99999999164010DC65BFEEB64A408090F469158D164010D3A23EC9B74A408047E6913F881640B0E0F08288B84A4080E17A14AE87164000E2E7BF07B94A4040E929728888164060F833BC59B94A40C05A99F04B9D1640B0A78FC01FBC4A40C09CF86A47A1164010BEDBBC71BC4A4040CCD1E3F7A6164028232E008DBC4A4080BFD2F9F0AC1640B059677C5FBC4A4040EFAB72A1B21640302CF180B2BB4A40C0E6012CF2CB1640D8AF743E3CBB4A400103000000010000001700000000F9872D3D8A184078A2EBC20FBA4A40408D95986785184078A2EBC20FBA4A40004C361E6C811840B06BED7DAABA4A404096766A2E771840805A457F68BC4A40007D410B0978184030D505BCCCBC4A4080D026874F7A1840E0031F8315BD4A4080A27A6B608B184038DB87BCE5BE4A40400C0401329418400821CB8289BF4A4000F0A65B76981840B0E9B303AEBF4A4080E07F2BD9A118402038F581E4BF4A4000310BED9C361940905D86FF74C14A40C053E57B46421940B85CA8FC6BC14A4000AE47E17A54194010E2E7BF07C14A40804B3B35975B194008CADFBDA3C04A40005B99F04B5D194030172AFF5AC04A40403106D6715C1940C800DE0209C04A408099999999591940D8D38041D2BF4A4080C554FA09171940285FD04202BE4A40809BC6F65AF01840A89ECC3FFABC4A4080CCD1E3F7E6184030D505BCCCBC4A40C0CBD1E3F7A61840B059677C5FBC4A40403106D6719C18408815E0BBCDBB4A4000F9872D3D8A184078A2EBC20FBA4A40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('NO','NO','NOR','578','Norway','30625','4638836','150','154','8.74','61.152','0106000020E61000005E00000001030000000200000070150000805512D907591540D87954FCDFCB4E408051BB5F0548154008240C0396CC4E4000E7FEEA712F1540806F7EC344CD4E40C0C3263273211540E0B27C5D86CD4E40C042942F6811154080698A00A7CD4E40405FEE93A3F0144048D73043E3CD4E4080BA4C4D82C714406831957EC2CD4E40C084F068E3781440F8E4284014CE4E40C09BC6F65AF0144058853FC39BCF4E4080A59D9ACBED1440A8B393C151D04E40C0E3A25A44C41440484F1F813FD04E4040E2AC889A781440D8B2B5BE48D04E40C02BBB6070FD134038172AFF5AD04E4000EA245B5DEE13401018080264D04E408022DFA5D4E51340B0656B7D91D04E4040E3A7716FDE134000E2E7BF07D14E4040A148F773DA1340888AE3C0ABD14E40C00F5EBBB4C11340E0FA5B02F0D54E4040666B7D91C01340D0C43BC093D64E4080634337FBC31340306E15C440D74E4000F52D73BADC134060431B800DDC4E4080643E20D0E91340089700FC53DE4E4080AD4CF8A5EE134000DC65BFEEDE4E4000DBFD2AC0F7134038F38FBE49DF4E40C08D9598674514408854C37E4FE24E40C02EDE8FDB1F1540607FBDC282ED4E404052B81E856B1540E0C77C40A0F34E40404391EEE774154028DEC83CF2F34E4000713D0AD7A3154058888043A8F44E4040EFAB72A1B215408887A2409FF44E40C082C30B226216405007793D98F24E40809BC6F65AB01640E07C957CECF04E40802634492CB91640B0E0F08288F04E4040DC2A8881CE1640D009A1832EEF4E4000944E2498FA16408815E0BBCDEB4E40C05417F032F31740A853E57B46EA4E4040BC783F6E3F18408054C37E4FEA4E4080A59D9ACBED184008E869C020EB4E4080240C0396FC184038E78BBD17EB4E4000356090F4091940881EA33CF3EA4E4080035ABA822D19408054C37E4FEA4E40C038BA4A77371940A8A10DC006EA4E40408B6D52D1481940E00F238447E94E4040C554FA0957194038172AFF5AE84E40C08C9AAF925F1940909C69C2F6E74E4080643E20D0691940B8E9B303AEE74E4000A148F7739A194028DB87BCE5E64E40C094490D6DE019407860C77F81E64E4080F0D8CF62091A400809C38025E74E40C0E1B19FC5121A402020ED7F80E74E408046EBA86A221A40B0B393C151E84E40C0F1D3B8372F1A4068F833BC59E94E4080F9821612301A40286BD44334EA4E40C0F1D3B8372F1A40D082177D05EB4E4080F9821612301A40082DCF83BBEB4E40004D689258321A40B8BF97C283EC4E400096766A2E371A40D888997D1EED4E4040CEFE40B93D1A40B868ACFD9DED4E4000583A1F9E551A4008DC65BFEEEE4E4080F2052D24601A40D009A1832EEF4E40004069A851781A40A8BC564277EF4E40C0F30016F9851A403020ED7F80EF4E404083C30B22A21A40B85626FC52EF4E40007A19C572BB1A40803FFCFCF7EE4E400085EB51B8DE1A40109700FC53EE4E40C07E69519FF41A4038327381CBED4E404077BF0AF00D1B4088A52C431CEF4E4000A243E048C01A40D0F71A82E3F04E40808713984E9B1A40D80F238447F14E40C00D315EF36A1A40E07C957CECF04E40400D36751E451A40786649809AF04E40004D689258321A40889C69C2F6EF4E40406CED7DAA2A1A400821CB8289EF4E40003465A71F241A402841B8020AEF4E40C04813EF001F1A40A8DA6E826FEE4E400060E97C78161A40D888997D1EED4E40C0E1B19FC5121A4010BEDBBC71EC4E40008ECC237F101A40D0C77C40A0EB4E40C04E95EF19091A4038F04E3E3DEA4E40404C361E6C011A4028D8463CD9E94E4000310BED9CF6194028266F8099E94E4000013274ECB019400806820019EA4E40008B6D52D1881940F81D8A027DEA4E40C0809BC58B65194008E869C020EB4E40C0368DEDB5E01840585260014CED4E40C09DEDD11BCE1740E833D93F4FEF4E40000F62670ABD174068E21DE049EF4E4000425E0F26A51740F096AB1F9BEE4E408084EFFD0D9A1740B8AD11C138EE4E4000CEFE40B93D17406031957EC2ED4E40807F69519F341740301A6B7F67ED4E40406E15C440271740580438BD8BED4E40407E6E68CA0E1740508E0244C1EE4E40C0A143E048001740B0E9B303AEEF4E400018080264E81640B0C2D84290F14E404052B81E85EB1640883CBB7CEBF14E400023DA8EA90B1740B8E67283A1F24E4080573F36C92F174030E78BBD17F34E40C007B309303C174078185A9D9CF34E4000295DFA97541740E86C3A02B8F34E40007A185A9D5C174078483140A2F34E4080B3CF6394771740488655BC91F34E40C075C58CF086174080EBA7FFACF34E40403BE3FBE292174088423D7D04F44E40C07497C45991174070E55E6056F44E40C02A8BC22E8A1740109C6C0377F44E40C0A8F8BF237A1740D806EE409DF44E408038BBB54C56174070DF6A9DB8F44E4080D8D0CDFE201740206893C327F54E40C08A7269FC2216403029B000A6F64E4080BEA08504BC1540A8E9B303AEF74E40C0AB1F9BE4971540586D37C137F74E40C090F469158D1540903FFCFCF7F64E40C0E8297288481540303B3602F1F44E40C0DB2F9FAC281540080C040132F44E40C01A3048FAA41440B853E57B46F24E408009DCBA9B971440386BD44334F24E4040A8C5E0616A1440E0BEB9BF7AF44E4000D48041D267144080CC07043AF54E4000B0743E3C6B1440881B62BCE6F54E40C04C6DA9838C1440682B137EA9FB4E40C07497C4599114406070784144FC4E40805512D907991440480DFB3DB1FC4E4000F0DDE68DA31440B0716F7EC3FC4E40406CED7DAAAA144058F5F23B4DFC4E4080A243E048C01440A0B915C26AFA4E40803E3C4B90E11440306211C30EFB4E4040C554FA09971540A0C2D84290014F40C05A99F04B9D154080A2EBC20F024F4080438CD7BC9A1540D0D03FC1C5024F4000C87C40A0931540E0AF743E3C034F4040DBF813951D1540B0C2D84290094F4000C87C40A0D31440A859677C5F0C4F40C077F17EDCBE1440303B3602F10C4F4000310BED9C761440805182FE420D4F40001B3048FA641440A89509BFD40D4F4080EA56CF495F14405876FA415D0E4F40C0A27A6B604B144008C79E3D97134F4000E7012CF24B144058F5F23B4D144F40C0CAA48636501440D0F19881CA164F40C0C77C40A0531440B0BC564277174F40C0EFA65B765814403038F581E4174F40405DC136E299144008E869C0201B4F40409AD024B1A41440109A417C601B4F40803D0AD7A3B01440804B00FE291B4F40803788D68AC61440B874B0FECF194F4000CEFE40B9FD1440E07FD6FCF8154F4000F1D8CF62C91540885704FF5B074F40C0A148F773DA1540D8CDFE40B9054F400046EBA86AE21540D0BEB9BF7A044F40C0E07F2BD9E1154000C79E3D97034F40C06DE00ED4D91540D02AFA4333014F40004B3B3597DB1540582E54FEB5004F40809AD024B1E4154000E2E7BF07014F4080992842EAF61540A8E7887C97024F40C00F5EBBB4011640D07954FCDF034F408045B9347E311640B8A10DC0060A4F4080A27A6B600B1640B0622AFD840B4F4040FF04172BDA154050707841440C4F40803D0AD7A3B01540281A6B7F670D4F40407E6E68CA8E1540903FFCFCF70E4F40003D0FEECE8A154060853FC39B0F4F40C0921CB0AB8915400018080264104F40805C8FC2F5A815408060C77F81164F40803D0AD7A3B0154000DC65BFEE164F40802EE3A606BA1540206E15C440174F40801E8A027DD21540888461C092174F4000F2D3B837EF1540888461C092174F40C03D4162BBBB164028E44A3D0B164F40803E3C4B9061174068F833BC59194F4040F1D3B8376F174038F911BF62194F40009DF3531C871740385C8FC2F5184F40002861A6ED8F1740886649809A184F4040809BC58BA51740686D37C137174F40C0AF743E3CAB1740F8298E03AF164F40C0F1D3B837AF174028E44A3D0B164F4040E7FC14C7B11740D8B5F63E55154F4080D576137CB31740F82CCF83BB134F408091EF52EAB217402035B401D8124F408069C53714AE174010C45DBD8A0E4F40C090F46915CD17400048A643A70D4F4000B0743E3C2B18408887A2409F0C4F40404C6DA9830C1940808AE3C0AB094F4000B6F63E55151940D80F238447094F40803106D6711C19408893A641D1084F40C094490D6D201940884E417E36084F40C022DFA5D4251940600ABABDA4074F40C0AD4CF8A52E194028F38FBE49074F40402634492C3919400009C38025074F40C0A59D9ACB6D1940B8A44E4013074F4000295C8FC27519403820ED7F80074F40C07E69519F741940306552431B084F4040963FDF166C19406001F73C7F084F40C099999999191940B8984A3FE10A4F4000E4D9E55B0F1940904B00FE290B4F40C0B1A19BFD0119403814E97E4E0B4F40803BE2900DB4184060431B800D0C4F4000704221027E1840A859677C5F0C4F40001B3048FA641840A89ECC3FFA0C4F4000B1A6B2285C1840B0B6D4415E0D4F408013B35E0C551840A89509BFD40D4F4080D576137CB31740805D86FF74194F4000A69D9ACBAD1740A8A10DC0061A4F404052B81E85AB174000D061BEBC1A4F4080963FDF16AC1740D0C77C40A01B4F4040F1D8CF62C91740884E417E36204F40C0DC2A8881CE17408893A641D1204F408018080264E81740B8984A3FE1224F40008B6D52D1081840F81A498270254F4080B3CEF8BE18184088AEEFC341264F40C04291EEE7341840286E15C440274F40008B7269FC221940686D37C1372F4F4000A69D9ACB2D1940B0BC5642772F4F40002EE3A6063A1940888461C0922F4F4080A7CAF78C44194038F38FBE492F4F400023DA8EA94B1940E076137CD32E4F4080A148F773DA1940600ABABDA41F4F4040C2FA3F87E91940E0FA5B02F01D4F404091EF52EA321A4030ED0DBE30154F4000666B7D91401A4048793BC269134F40C0B950F9D7421A40104BE7C3B3124F4000B2A19BFD411A40A874B0FECF114F4000DBFD2AC0371A40706649809A104F40003465A71F241A40B0A44E40130F4F40C04813EF001F1A40B05FE97C780E4F4000416491261E1A40A0E33103950D4F4000CCD1E3F7261A40281A6B7F670D4F40806AC020E9531A40D88558FD11104F4000A148F7735A1A40B8656B7D91104F4080F52D73BA5C1A4058F833BC59114F40404E637B2D581A406834D6FECE124F4040356090F4491A40381A6B7F67154F4000A3755435F1194060F833BC59214F4080C422861DE61940B0B915C26A224F4000E9297288C81940E0031F8315254F400045B9347EB11940B05FE97C78264F4000963FDF16AC19403841B8020A274F404046EBA86AA21940804E417E36284F40C0D47B2AA78D194078A86DC3282C4F4040A27A6B608B194080397AFCDE2C4F404079E750868A194010CD203EB02D4F4040A27A6B608B194008C45DBD8A2E4F40C0D47B2AA78D1940C05626FC522F4F40407497C459911940D800DE0209304F40C05FE97C7896194010CADFBDA3304F4040977153039D1940D8A9F23D23314F40801A3048FAA41940A0C2D84290314F40C0DAFD2AC0B71940286BD44334324F4080F0D8CF62C91A4028E109BDFE384F4080C554FA09D71A40D0F71A82E3384F40804069A851781B40487FBDC282354F40C0A9F23D23811B40E088997D1E354F404047E6913F881B4050888043A8344F400079E750868A1B4038DEC83CF2334F4000931CB0AB891B40286211C30E334F40001286014B7E1B40385C8FC2F5304F4040BEA085047C1B4080C9C6832D304F4080D8D5E4297B1B40C05626FC522F4F4040240C03967C1B40E0CDFE40B92D4F4000E4A25A44841B4008BEDBBC712C4F4040FE092E56B41B40D0BB783F6E274F4040F6285C8FC21B40B05FE97C78264F4040E3A7716FDE1B40281A6B7F67254F40C059677C5FEC1B40E0BEB9BF7A244F40C0285C8FC2F51B403814E97E4E234F4080BEA08504FC1B40583D997FF4214F40C0656B7D91001C40B0E0F08288204F40404F95EF19091C408054C37E4F1A4F404079E750860A1C40582E54FEB5184F4000F1D8CF62091C40D0D38041D2174F40C0B1A19BFD011C40B0DA6E826F164F40807F69519FF41B40081B498270154F40009AD024B1E41B408087A2409F144F4000F9872D3DCA1B406007793D98124F40800D36751EC51B40283E7782FD114F40C007AF5DDAC01B40382F3201BF104F400022E4BCFFBF1B403838F581E40F4F4000666B7D91C01B40B0A44E40130F4F40C0B950F9D7C21B405876FA415D0E4F4000FBAF73D3C61B40D0CDFE40B90D4F40C06211C30ED31B408887A2409F0C4F40009CF86A47E11B40282CF180B20B4F4040643E20D0E91B403814E97E4E0B4F40005C94D920031C40881EA33CF30A4F40007C462234121C40B8984A3FE10A4F40C0953FDF162C1C40386211C30E0B4F40C00F5EBBB4411C40B0622AFD840B4F4000DF52CE174B1C40D0F4D901D70B4F40803106D6715C1C4028232E008D0C4F40C0012D5DC1561C40D8AC33BE2F0E4F4040FBAF73D3461C40B0B6D4415E0D4F40002CBB60703D1C40080341800C0D4F4000D48041D2271C40F8230C03960C4F4040DF52CE170B1C40F8230C03960C4F4080A59D9ACBED1B40A0E33103950D4F40009CF86A47E11B405828D2FD9C0E4F40404913EF00DF1B40B05626FC520F4F40C0F2052D24E01B40804E417E36104F4040DE57E542E51B408093A641D1104F4080944E2498FA1B408854C37E4F124F4000F6285C8F021C4008D061BEBC124F40009CC1DF2F161C40D80CE2033B144F4080368DEDB5201C40081B498270154F4000DE57E542251C403041B8020A174F40C06E15C440271C4000301004C8184F4000DE57E542251C40804B00FE291B4F4080368DEDB5201C409087A2409F1C4F4080AB1F9BE4171C40E8A9F23D23214F404046B41D53171C40583D997FF4214F40C03106D6711C1C408081204086224F4080C422861D261C403035B401D8224F40806BED7DAA6A1C40386211C30E234F4080963FDF162C1D40E0C77C40A0234F40406BBB09BE391D40B8DDAF027C234F40403AE7A7384E1D40B8984A3FE1224F4040C554FA09571D40101E8A027D224F4080416491265E1D40A0A10DC006224F40C05417F032731D40806649809A204F40C03AE7A7388E1D408096E7C1DD1D4F4040B6F63E55951D40301A6B7F671D4F40C0DB2F9FACA81D40100341800C1D4F40C0C1FA3F87A91D406831957EC21D4F4040B3CEF8BE981D40884E417E36204F404026396057931D40282F3201BF204F40C05417F032731D401015C78157234F40C0438CD7BC5A1D40805A457F68244F4080A7CAF78C441D40303B3602F1244F40C0D38041D2271D40286893C327254F40C04B3B35971B1D40789FAA4203254F40C0F9821612F01C40A8A78FC01F244F4040B3CEF8BED81C40889065C1C4234F40802BBB6070BD1C40282CF180B2234F4080573F36C9AF1C40D0F4D901D7234F40002A8E03AFE61B40A8E9B303AE274F40C05DC136E2D91B40A8E0F08288284F4000AE47E17AD41B4080457EFD10294F40C015E0BBCDAB1B400048A643A72D4F40C01FB75F3EA91B405076FA415D2E4F408045B9347EB11B40608E0244C12E4F408082C8224DBC1B40883FFCFCF72E4F400060E97C78D61B400809C380252F4F40009CF86A47E11B4008BB9A3C652F4F40801A3048FAE41B403038F581E42F4F4000EB56CF49DF1B40587C7C4276304F4080E07F2BD9A11B40A868ACFD9D354F400016E0BBCD6B1B40E0C1FA3F87394F40006CED7DAA2A1B40383B3602F13C4F40C0F2052D24201B4088CC07043A3D4F40802634492CB91A4058F86C1D1C3C4F40C09BC420B0B21A40808DEBDFF53B4F40407E737FF5A81A40103FFF3D783B4F40400C022B87961A40483ACAC16C3A4F4040013274EC301A40F84D2844C0374F4080CAA48636101A402841B8020A374F40402639605793194008CD203EB0354F408051BD35B0851940A868ACFD9D354F40C07C410B097819406831957EC2354F40803F373465071940785D86FF74394F4040E4A25A440419403814E97E4E3B4F408014AE47E17A1940D07FD6FCF83D4F40C019355F25BF19401009C380253F4F40C01186014BFE194048853FC39B3F4F404088450C3B0C1A40580ABABDA43F4F404007B474055B1A402041B8020A3F4F4040BEA25BAF791A404810AE80423F4F40807F6ABC74931A400851F701483F4F4080230F4416991A40104E7D20793F4F40C0726BD26D991A40F8F09E03CB3F4F40409DF3531C871A4008274D83A2414F4080EA5BE674391A408015E0BBCD434F40C015E0BBCD2B1A4028DEC83CF2434F4000BC783F6EFF194010DFA63FFB434F40801B62BCE6D51940E07954FCDF434F40C053E57B4642194028E78BBD17434F4040B81E85EB111940889065C1C4434F408070422102FE1840D07C957CEC484F4040C64FE3DEFC1840A0C2D84290494F40C0B1A19BFD011940D88BDAFD2A4A4F4000E4D9E55B0F1940804B00FE294B4F40806E15C44027194000BEDBBC714C4F4080D026874F3A1940D0031F83154D4F408032384A5E4D19401048A643A74D4F40008813984E5B1940C8FA5B02F04D4F4080FBAA5CA82C1A404876FA415D4E4F4040D026874F3A1A40B8AD11C1384E4F40805B94D920431A408096E7C1DD4D4F400076C4211B681A4000D061BEBC4A4F4040D253E410D11A40805D86FF74514F404045B9347EF11A4008E869C020534F40403F373465071B40806308008E534F40C08713984EDB1B40504CDE0033534F4000B1A6B2285C1C4090992842EA524F40403BE2900D741D40D882177D054B4F40C09CF3531C071E40587FBDC282454F4040861DC6A40F1E40D088997D1E454F40C0B5F63E55151E4038232E008D444F40405512D907191E40B07A32FFE8434F400076C4211B281E403838F581E43F4F40C03F373465471E40381A6B7F67454F4000CDCCCCCC4C1E40385FD04202464F40409CC1DF2F561E40009700FC53464F40C09CF86A47611E4010C45DBD8A464F40406BBB09BEB91E40C05626FC52474F4000E3A7716F1E1F4080ABAE4335494F40802861A6ED0F1F40483D997FF4494F40C05417F032F31E40D88BDAFD2A4A4F4040DE57E542E51E40E0066003224A4F404040321D3A6D1E4000301004C8484F40801B62BCE6551E40587C7C4276484F40004391EEE7341E4000D3A23EC9474F40405512D907191E40B86E2EFEB6474F4080CDFE40B9FD1D408821E4BCFF474F40C022DFA5D4E51D40587C7C4276484F40C00B040132D41D40100F45813E494F400091F46915CD1D40608BC1C3B4494F4080BFD2F9F0AC1D40D00CE2033B4C4F40805C8FC2F5A81D4080397AFCDE4C4F404046EBA86AA21D405840DAFF004F4F40C02CB64945A31D40B06E2EFEB64F4F40C0DB2F9FACA81D40A8B393C151504F40C045B41D53171E40E0B5F63E55554F404018080264681E40A0656B7D91584F40808D959867851E4000C11C3D7E594F40004913EF001F1F4058888043A85C4F4000068200192A1F4088397AFCDE5C4F40C0CCCCCCCC4C1F40381A6B7F675D4F4040999EB0C4731F4010CD203EB05D4F40805417F032F31F405076FA415D5E4F4080656B7D91002040A8AD11C1385E4F406051BD35B0052040881B62BCE65D4F40A03579CA6A2220408015E0BBCD5B4F40C0DE52CE172B2040E082177D055B4F408014AE47E13A2040D00F238447594F40C0CF0D4DD9412040B8B393C151584F40C0B628B341462040B09B8BBFED574F4020B937BF614A2040B8B393C151584F40E0E7154F3D4A2040E0A9F23D23594F40004F95EF1949204038D8463CD9594F40406E15C440472040081E8A027D5A4F40C0CF0D4DD941204008C79E3D975B4F408014AE47E13A204020232E008D5C4F40C0C98B4CC01720405001F73C7F604F40005EBC1FB7FF1F40E873D2FBC6614F40800D36751EC51E400048A643A75D4F4080035ABA82AD1E40485260014C5D4F40006BBB09BE391E40D8C1FA3F87594F404020B75F3E291E40682E54FEB5584F408009DCBA9B171E407821E4BCFF574F4000944E2498FA1D402041B8020A574F408069C53714EE1D4008DC65BFEE564F404085EB51B8DE1D40783FFCFCF7564F4040E4D9E55B8F1D40A0BC564277574F40C0E2AC889A781D40303B3602F15C4F40408ECC237FD01D40D0CABDC0AC604F40C0D24ECDE5F61D40503D997FF4614F4000068200192A1E402814E97E4E634F4040B1A6B2285C1E40E0F4D901D7634F40002861A6ED8F1E40D00CE2033B644F40C006B474059B1E4000BEDBBC71644F4000EA5BE674B91E40605260014C654F4080CAA48636901E40D8CDFE40B9654F404008AF5DDA801E4020327381CB654F40C0FE092E56741E4008CD203EB0654F40405DC136E2D91D40A8DDAF027C634F4080CAA48636D01D40804B00FE29634F40005EBC1FB7BF1D405855A18158624F40C093179980AF1D40D0C1FA3F87614F40C0DB2F9FACA81D4008E2E7BF07614F4040B6F63E55951D401018080264604F40C0DC2A88814E1D40A85626FC525F4F40C0CAA48636D01C4060499D80265E4F404045B9347EF11B40A859677C5F5C4F4080F0DDE68DE31B4030F6D03E565C4F40C01B62BCE6D51B40D8BEB9BF7A5C4F40C090F46915CD1B4088397AFCDE5C4F4080D24F38BBE51B403011A8FE41664F40C0B41B7DCCF71B4020BA675DA36D4F40C007AF5DDAC01B40F8DEA63FFB734F400089450C3BCC1B40506D37C137774F4000DE57E542251C40E0F4D901D77B4F40803106D6715C1C40D0FA5B02F07D4F4000A3755435711C40A85FE97C787E4F4000E9297288081D40E0C1FA3F87814F404060E97C78161D4038F911BF62814F4000A3755435311D40604F1F813F804F40C0B628B341861D4090812040867A4F4000E4A25A44C41D40D8B5F63E55754F40C0A27A6B60CB1D4010D6E3BED5744F40C009DCBA9BD71D408887A2409F744F4040809BC58BE51D4058888043A8744F40C0B5F63E55151E40101B498270754F408051BD35B0451E406040DAFF00774F40C013B35E0C551E40A89B8BBFED774F4000DE57E542651E40488BC1C3B4794F4000963FDF166C1E4020F04E3E3D7A4F4080D8D5E4297B1E40F8E769C0207B4F4080EFA65B76981E4058431B800D7C4F40002EE3A606BA1E40B0ECF483BA7C4F40402FDE8FDBDF1E40D0031F83157D4F40C02BBB6070FD1E40F80241800C7D4F408046B41D53171F40600DFB3DB17C4F4080F2052D24201F4058F5F23B4D7C4F4080809BC58B251F40082DCF83BB7B4F40408A7269FC221F40901EA33CF37A4F4040DBF813951D1F405855A181587A4F40802861A6ED0F1F4068F833BC59794F40001A355F25FF1E40A0E0F08288784F408040321D3AED1E40D0D38041D2774F404007B47405DB1E4080A52C431C774F40C0E17A14AEC71E40B05FE97C78764F404096766A2EB71E400048A643A7754F40409BC6F65AB01E40386893C327754F40C06BED7DAAAA1E4020232E008D744F4000E5D4CE30B51E405070784144744F400052B81E85EB1E40101B498270754F40C02861A6ED8F1F4008D9243FE2794F40405DC136E2991F40286BD443347A4F40C0B628B341C61F4080423D7D047C4F40C08713984EDB1F4038232E008D7C4F400020B75F3EE91F4008240C03967C4F408096766A2EF71F40885A457F687C4F408018213CDA002040B8A78FC01F7C4F4000B937BF610A204060793BC2697B4F4040B5DD04DF1C2040A874B0FECF794F4000356090F429204000CADFBDA3784F4000D68F4DF22B204088C9C6832D784F40A0C554FA0937204030ED0DBE30754F40406684B70739204020232E008D744F4060BC9179E4372040801EA33CF3724F40C07C410B09382040C88BDAFD2A724F40C0921CB0AB492040A8A10DC0066A4F40C00C1D3BA84C2040E0CABDC0AC684F40E0D03FC1C5522040500ABABDA4674F40605DC136E2592040F8298E03AF664F40401286014B5E2040001286014B664F4080B60F79CB6D2040A8B6D4415E654F4000D13FC1C592204050431B800D644F40406893C3279D204060793BC269634F400083DC4598FA20408015E0BBCD5B4F40605FD04202FE20403014E97E4E5B4F4020B937BF610A2140000F45813E594F40407D5A457F102140884E417E36584F40C05417F032132140600ABABDA4574F40C0D24ECDE51621405876FA415D564F4080B3CEF8BE182140302CF180B2534F40C0703D0AD723214008E5284014564F4020DF6B088E232140A877F17EDC564F40C082C30B22222140283E7782FD594F4020AAF23D23212140104BE7C3B35A4F4020E3A7716F1E2140A8B05241455B4F406014AE47E11A2140F82CCF83BB5B4F40606211C30E1321408087A2409F5C4F40C0921CB0ABA920403829B000A6664F4040CDE50643A520403041B8020A674F40C01D71C8069A204058853FC39B674F40C0B2B5BE4880204038172AFF5A684F400007B474057B2040E0CABDC0AC684F4080CDE50643652040B06BED7DAA6A4F400052D66F265E2040D0C77C40A06B4F40207A19C5725B204080A86DC3286C4F40A0F755B950592040B868ACFD9D6D4F40E05FE97C78562040000F45813E714F4040BC9179E4572040B8A10DC006724F40605DC136E259204008D061BEBC724F40A01D71C8065A2040000341800C754F40607497C459512040E0B2B5BE48784F40A0A48977804F2040D07C957CEC784F40201808026448204008D9243FE2794F40406C06B820032040B0BC5642777F4F40404913EF00DF1F40B8E0F08288804F4080DC2A8881CE1F40B06E2EFEB67F4F40405B94D920C31F403820ED7F807F4F4040A148F7739A1F40C05626FC527F4F40403AE7A7388E1F40F820CB82897F4F4040634337FB831F405837177FDB7F4F40C00F5EBBB4811F40B0656B7D91804F4000E4A25A44841F4060F833BC59814F40C0EA56CF49DF1F40B074B0FECF894F404040321D3AED1F405834D6FECE8A4F4000B4E73235112040080341800C8D4F40E0DB114E0B162040B0B6D4415E8D4F40C0656B7D912020409096E7C1DD8D4F4040F2ECF2AD272040881B62BCE68D4F4060B60F79CB2D204010CD203EB08D4F404020990E9D36204088397AFCDE8C4F4060BEA085043C2040889065C1C48B4F4080FDD7B969432040B8A10DC0068A4F40809E07776745204030F911BF62894F4040809BC58B452040786649809A884F40E05CA8FC6B412040586D37C137874F4000D9D0CDFE4020408860C77F81864F4080C2137AFD41204038327381CB854F4020634337FB432040286893C327854F40401B4982709D2040E000DE0209784F40C06BED7DAAAA2040E0D03FC1C5724F40C085048C2EB72040682E54FEB5704F4040E3A7716FFE204068F5F23B4D6C4F40009CDF30D1082140582B137EA96B4F4040573F36C90F2140302CF180B26B4F40C07A32FFE8132140D8A6B1BD166C4F4000B6F63E5515214090397AFCDE6C4F40C0E4D4CE301521400848A643A76D4F40401E8A027D122140B0AD11C1386E4F40809E077767052140D0BB783F6E6F4F4000321F10E8D4204068F833BC59794F400090DB2F9FD42040383E7782FD794F4060B3CEF8BED82040D0B837BF617A4F4040634337FBE320406834D6FECE7A4F40207497C459F12040901EA33CF37A4F4000E9297288082140084BE7C3B37A4F4060895E46B12421406834D6FECE7A4F4060B81E85EB31214080992842EA7A4F4020B0743E3C4B2140109A417C607B4F4060CAA48636502140382CF180B27B4F40C0C77C40A0532140000C0401327C4F40200341800C552140B09ECC3FFA7C4F40A04B546F0D54214008CD203EB07D4F40E06DFC89CA4E2140305FD042027E4F4000D48041D2072140B09509BFD47D4F40604278B471DC2040885182FE427D4F40603F373465C72040D00CE2033B7C4F40C06E2EFEB6BF204058F5F23B4D7C4F40807A32FFE8732040886308008E834F4000274D83A2512040C8C43BC0938E4F404045B9347E51204010BB9A3C658F4F4020321F10E85420403838F581E48F4F40A014AE47E17A2040A8E67283A1924F40C0656B7D918020403835B401D8924F40C01D71C8069A20403014E97E4E934F40800F5EBBB4A12040E8AF743E3C934F40609BC6F65A10214028F911BF62914F40A0F4143944242140A874B0FECF914F40C03579CA6A222140301DACFF73924F40E079008BFC222140B8A78FC01F944F4020DF6B088E23214008D6E3BED5944F406077D84466262140301A6B7F67954F4080A48977802F21408848BF7D1D964F40602CB64945432140905704FF5B974F40E0AA24B20F7221405837177FDB974F40400E9F7422892140B08C463EAF984F40002DCF83BB9B214000E2E7BF07994F40C094490D6DE02140281DACFF739A4F40A053E57B46E22140D0D03FC1C59A4F40C051D66F26BE21406034D6FECE9A4F40400A100533A621405882FE428F9A4F4000E2934E244021405073B9C150994F40C014AE47E13A214000274D83A2994F40805626FC52372140E0066003229A4F404020990E9DF62040D088997D1EA54F40E08FDB2F9FF42040B8E3310395A54F4000274D83A21121402820ED7F80A74F40A05626FC52172140B86E2EFEB6A74F40E0AF743E3C2B2140809C69C2F6A74F40E0656B7D91402140E000DE0209A84F408032384A5E4D2140504F1F813FA84F40C07C410B09582140302F3201BFA84F40405A80B6D5842140A8DDAF027CAB4F4080BB5F05F8862140000C040132AC4F40A018213CDA802140905A457F68AC4F4020EFAB72A1722140B859677C5FAC4F40A03BFBCA836C21408087A2409FAC4F40E0A4A2B1F6672140889FAA4203AD4F4080D6A88768642140507FBDC282AD4F40E0CABDC0AC482140B05CA8FC6BB14F40000473F4F8452140603D997FF4B14F404051BD35B04521405807793D98B24F40C0AD65321C472140089A417C60B34F4000356090F449214008DFA63FFBB34F40C02975C9384E2140B059677C5FB44F40A04D637B2D582140B09ECC3FFAB44F40807C60C77F79214010F148BC3CB54F40207A19C5727B2140607FBDC282B54F40C094490D6D80214038327381CBB54F4080A4897780EF2140E07C957CECB84F40801D71C806FA2140C882177D05BB4F4040EC6AF294FD2140A8622AFD84BB4F4080069B3A8F022240D0F4D901D7BB4F40C0D38041D2072240A8622AFD84BB4F40806E2EFEB61F22408018213CDAB84F4000FBAF73D32622402838F581E4B74F4000CA8B4CC0372240301A6B7F67B54F40206893C3273D224068F5F23B4DB44F40002C9D0FCF4A22403038F581E4AF4F40A05FE97C78762240605260014CAD4F400009C38025BF22400809C38025AF4F40A0C1E10511D12240B8E9B303AEAF4F400007B47405DB2240484F1F813FB04F40E059677C5FEC224028D8463CD9B14F40200341800CF52240F8C69E3D97B34F4000F86EF3C6F1224050FEB5BC72B34F40C0E7154F3DCA224030E109BDFEB04F40E05417F03273224078A52C431CAF4F40A0C3094CA76D2240A0A44E4013AF4F402021CB8289672240C05626FC52AF4F4040295C8FC2552240A0C2D84290B14F40406211C30E5322400806820019B24F4000CDCCCCCC4C2240E0B5F63E55BD4F40C00C1D3BA84C2240D07FD6FCF8BD4F404069C537144E2240608E0244C1BE4F4080CAA48636502240C8BB783F6EBF4F40E0989EB0C4532240A89B8BBFEDBF4F40207156444D7C224000BEDBBC71C44F40C08B868C47812240F0230C0396C44F40E0D38041D2A72240000341800CC54F40E0B5F63E55D5224030F6D03E56C44F4040CAA48636F02240B0656B7D91C84F4060BEA08504FC224038E78BBD17CB4F40A077F17EDCFE2240B8622AFD84CB4F40A0A48977800F234020ED0DBE30CD4F40A07A32FFE8132340A8E3310395CD4F40A0622AFD844B23405037177FDBCF4F4060D367075C6F2340E0CABDC0ACD04F40E074B0FECFE92340009D82FC6CB84F40E0622AFD84EB234008D3A23EC9B74F40A059677C5FEC2340B8A44E4013B74F40E0622AFD84EB2340E0AC33BE2FB64F4020356090F4E92340301A6B7F67B54F40E079008BFCE223408054C37E4FB24F4020999EB0C4F32340B0E3310395AD4F40A0716F7EC314244038232E008DAC4F402069C537144E2440D87C957CECA84F40803579CA6A822440386893C327A54F4080FDD7B969832440A05CA8FC6BA14F406048FAB48A86244030F911BF62A14F4000C2FA3F87892440583D997FF4A14F404023DA8EA98B2440B8E67283A1A24F40600C1D3BA88C2440A8622AFD84A34F40206002B7EE8E244088C9C6832DA84F404069C537148E2440E0F71A82E3A84F40606E15C440872440A86BED7DAAAA4F40E0703D0AD7832440884B00FE29AB4F40A000193A76782440809065C1C4AB4F406045B9347E71244038DEC83CF2AB4F40E0ED974F5654244080423D7D04AC4F40C0955D30B83E2440D8BEB9BF7AAC4F40C06BED7DAA2A24408896E7C1DDAD4F4080C2137AFD212440F8298E03AFAE4F4060D026874F1A2440B8E9B303AEAF4F406009DCBA9B172440484F1F813FB04F40801B62BCE6152440D8F71A82E3B04F40200341800C15244028266F8099B14F40200341800C152440B0B915C26AB24F40A04D637B2D18244008DFA63FFBB34F4000D9D0CDFE202440D8CDFE40B9B54F402018080264282440082A8E03AFB64F4060C1E10511312440A8BC564277B74F40C0E1934E2440244030172AFF5AB84F40C01EA33CF34A24408018213CDAB84F40405C8FC2F5882440904B00FE29BB4F4080AD4CF8A58E24400815C78157BB4F4000295C8FC29524400815C78157BB4F40C0CDFE40B99D2440A8B0524145BB4F40A079008BFCE22440883CBB7CEBB94F40A07F828B150D2540788461C092B74F40801D71C8061A25400009C38025B74F4000F2ECF2AD272540306E15C440B74F40806ABB09BE79254090C9C6832DB84F40C0E40D30F3B5254090118942CBB84F40406E15C440C72540000F45813EB94F40E0AA24B20FD22540C8EE5701BEB94F40000341800CD525409054C37E4FBA4F4000EE974F56D42540C882177D05BB4F408017EFC7EDCF254048FEB5BC72BB4F4040809BC58BC52540A8A78FC01FBC4F40008D9AAF92BF2540A859677C5FBC4F4060E2AC889AB8254028232E008DBC4F40C02CB64945A32540B8716F7EC3BC4F40207156444D9C2540303B3602F1BC4F4060CAA4863690254008A0C37C79BD4F40E0CCCCCCCC8C2540D07FD6FCF8BD4F402021CB828987254080A52C431CBF4F40400D36751E852540607C7C4276C04F40400D36751E852540F80E45813EC14F4040C422861D862540D006600322C24F40C0D38041D287254080992842EAC24F4060B60F79CB8D2540E8A6B1BD16C44F406045B9347E91254038232E008DC44F40801B62BCE6952540283B3602F1C44F400007B474059B254078CC07043AC54F406018213CDAA02540381A6B7F67C54F4020F2ECF2ADC72540D0FA5B02F0C54F400015C78157D32540009700FC53C64F4080C554FA09D72540D0F19881CAC64F406000193A76D8254008BB9A3C65C74F4040BC9179E4D7254000240C0396CC4F4000EFAB72A1D22540503A58FFE7CC4F404023DA8EA9CB2540C8031F8315CD4F4040A7CAF78CC42540D888997D1ECD4F40C0BB783F6EBF254008D6E3BED5CC4F4040E2AC889A782540582E54FEB5C84F4020573F36C96F2540909C69C2F6C74F40C0E1934E246025408848BF7D1DC64F40202DCF83BB5B2540E0CDFE40B9C54F4080129F3BC1562540081B498270C54F40204E7CB5A350254008CD203EB0C54F40007497C45951254060FB743C66C64F4000013274EC702540001B498270CD4F40E0B0A6B2287C254038DB87BCE5CE4F40A0F755B950D92540A89B8BBFEDD74F40E0DE52CE17EB2540885D86FF74D94F4020AB24B20FF2254008D9243FE2D94F40C0A16131EA1226403014E97E4EDB4F408014AE47E11A2640584CDE0033DB4F402009C380251F2640D8D03FC1C5DA4F40A0F414394424264008274D83A2D94F40E0AF743E3C2B2640885D86FF74D94F4040861DC6A44F26406055A18158DA4F4080F755B950592640E082177D05DB4F408082C30B226226407815E0BBCDDB4F40A017EFC7ED6F2640801B62BCE6DD4F4020274D83A2712640F8298E03AFDE4F4020274D83A2712640B0BC564277DF4F40200341800C75264000E2E7BF07E14F40C0CF0D4DD9812640B053E57B46E24F4020A7B1BD168C26403835B401D8E24F40E0AA24B20F922640D882177D05E34F40E0CCCCCCCCAC2640B0B0524145E34F4080BC9179E4D72640D00CE2033BE44F40C0F0D8CF62E92640A8716F7EC3E44F40803BFBCA83EC2640B8B6D4415EE54F40A0CCCCCCCCEC2640803FFCFCF7E64F40E0AF743E3CEB264050853FC39BE74F40202FDE8FDBDF2640B8984A3FE1EA4F40805A99F04BDD264050FEB5BC72EB4F40205DC136E2D9264030DEC83CF2EB4F40C08FDB2F9FD4264060F5F23B4DEC4F4080C554FA09972640D8F19881CAEE4F4040301004C89026403841B8020AEF4F40009CDF30D18826401009C38025EF4F40404278B4717C264030DB87BCE5EE4F4000D13FC1C5722640B0AD11C138EE4F40A09E077767652640E0031F8315ED4F40E0E1934E2460264028D505BCCCEC4F4000F1D8CF6249264000DFA63FFBEB4F40A0B950F9D7422640E87954FCDFEB4F40C014AE47E13A264000DFA63FFBEB4F402020990E9D362640805A457F68EC4F40606211C30E332640603A58FFE7EC4F404045B9347E312640500438BD8BED4F40C0FA96395D2E2640109D82FC6CF04F40C020B248132F2640E0A9F23D23F14F404045B9347E312640A874B0FECFF14F400090DB2F9F342640D0B837BF61F24F40E020CB8289872640E0FD9C82FCFA4F4020F86EF3C6B12640A8BF97C283FC4F4000D13FC1C5D22640203B3602F1FC4F4060F755B950D92640889FAA4203FD4F404009C38025DF264090CC07043AFD4F40C0D24ECDE5F62640889C69C2F6FF4F402054FEB5BCFA2640EC4EB0FF3A005040009F20B1DDFD2640C00166BE83005040405FD04202FE2640C43AC780EC005040407156444DFC2640080F45813E01504080737E8AE3D82640D8CDFE40B9015040802CB64945A3264098E4B9BE0F025040C0129F3BC1B626405834D6FECE065040C038BA4A77B72640B0A44E401307504000634337FBA32640DCBB783F6E075040E0230C03969C264044BCE7C07207504080BFD2F9F06C26405C34D6FECE025040E0F0D8CF626926409026DE019E01504040F2ECF2AD672640080F45813E015040207156444D5C2640C00166BE83005040E0C64ACCB342264000C45DBD8AFE4F4060D367075C2F264090CC07043AFD4F406083DC45981A2640E0A6B1BD16FC4F40A0FDD7B969032640B053E57B46FA4F4060634337FBE3254058853FC39BF74F4080B3CEF8BED8254060499D8026F64F40A08EC70C54D6254000A0C37C79F54F40A05417F032D3254080397AFCDEF44F404023DA8EA9CB2540B07A32FFE8F34F40A0B5DD04DF9C25400018080264F04F4000F2ECF2AD872540B05626FC52EF4F40C0D24ECDE5762540A877F17EDCEE4F404021CB8289672540D07FD6FCF8ED4F408079008BFC622540B868ACFD9DED4F4000C53BC0935E254088CC07043AED4F40205C8FC2F528254050853FC39BE74F40000473F4F82525402841B8020AE74F40C0AD65321C2725403829B000A6E64F40A0C3094CA72D2540508E0244C1E64F40403F373465472540884E417E36E84F40C0D8D0CDFE802540E00CE2033BEC4F40004C546F0DB4254038EACC3D24F04F40607156444DBC254010E2E7BF07F14F40004F95EF19C92540B853E57B46F24F40606002B7EECE2540301DACFF73F24F40C0AC33BE2FD62540301DACFF73F24F40403F37346507264028172AFF5AF04F4000C4094CA70D2640D88558FD11F04F4080C1E1051111264060853FC39BEF4F40A01A3048FA242640889065C1C4EB4F40E020CB8289272640484CDE0033EB4F40E053E57B46E22540A85FE97C78DE4F4060D9E90775D9254010CD203EB0DD4F4000EE974F56D42540381A6B7F67DD4F4040B950F9D7C2254080397AFCDEDC4F4000AB24B20FB22540000C040132DC4F40E01A4982709D2540306211C30EDB4F4000E9297288482540881B62BCE6D54F4020895E46B1442540281A6B7F67D54F40C02CB6494543254040D505BCCCD44F40805CA8FC6B412540386211C30ED34F400038A110013F2540D8B837BF61D24F408009DCBA9B37254030F911BF62D14F40807C410B09182540E0F19881CACE4F40C04E95EF19C924409093A641D1C84F40808B868C47A12440785704FF5BC74F4020895E46B1842440785704FF5BC74F40C051D66F267E244030F38FBE49C74F402015C78157732440D0F19881CAC64F40208A592F866A2440305FD04202C64F40A05A457F68562440585E64027EC34F40A0A48977802F2440E0B2B5BE48C04F40A000193A761824402820ED7F80BF4F40200000000000244020170E8464BF4F40409885764EDB2340109D82FC6CC04F40C0D24ECDE5D623408093A641D1C04F40606211C30ED32340D073D2FBC6C14F4000965D30B89E2340B85626FC52CF4F4000A8E331039D2340889C69C2F6CF4F40C04B546F0D94234040D505BCCCD44F40401077F52A9A23403838F581E4D74F40E09E20B1DD9D23400018080264D84F40200D36751EA523400018080264D84F40A04B546F0DB4234038EACC3D24D84F40205DC136E2B92340B8B393C151D84F402090DB2F9FD4234030266F8099D94F4080069B3A8F022440D80CE2033BDC4F4000261B0FB62024400809C38025DF4F4000274D83A23124409093A641D1E04F40805DDA7058322440C8C1FA3F87E14F4020A7B1BD162C2440E873D2FBC6E14F40C0C64ACCB3022440A8984A3FE1E24F40E04B546F0DD4234020172AFF5AE04F40E0AF743E3CCB2340888461C092DF4F40C085048C2E772340E0EE5701BED94F4060634337FB23234060888043A8D44F408077F17EDC1E2340A859677C5FD44F4040E2AC889A18234008BEDBBC71D44F40200C04013214234000D6E3BED5D44F40A07A32FFE813234008A0C37C79D54F40E05FE97C78162340D8EE5701BEE14F4040BC9179E4172340E0B837BF61E24F402048FAB48A26234028F6D03E56E44F40C0E7154F3D2A234030D505BCCCE44F4000965D30B83E2340803FFCFCF7E64F40403F373465472340F84D2844C0E74F4000FBAF73D3662340A85CA8FC6BE94F408048FAB48AA623403029B000A6EE4F4060F755B950B92340B85CA8FC6BF14F4060C422861D462440504F1F813FF84F40A032384A5E4D2440504F1F813FF84F4000EFAB72A1522440A89B8BBFEDF74F4020AD33BE2F562440E0BB783F6EF74F402083DC45985A24403041B8020AF74F4000AAF23D2361244078A52C431CF74F4080F4143944642440B06E2EFEB6F74F4060B3CEF8BE58244000D9243FE2F94F40201B4982703D24408848BF7D1DFE4F4040E3A7716F1E244038327381CBFD4F4060F755B950192440487FBDC282FD4F40A0D24ECDE5F62340E0F19881CAFE4F40E0B837BF610A2440504F1F813F045040400341800C5524400CA8FE41240C5040E082C30B228224402829B000A60E5040C0D03FC1C5B2244044C269C18B115040A01A3048FAE424402C2F3201BF145040A03BFBCA83EC2440EC3C2AFEEF15504080716F7EC3F42440D4D03FC1C5165040E0C64ACCB302254098205C018517504000068200190A254098205C018517504060D9E90775192540EC57738060175040E09E20B1DD1D2540E84B6F7F2E17504020FBAF73D326254068D0D03FC116504020C2FA3F87292540941D1B817816504020B0743E3C2B254050499D8026165040E06DFC89CA2E254070FAEC80EB155040200341800C352540C8310400C7155040A076BF0AF04D254044C5AA419816504040B60F79CB4D25409CDBF63DEA16504020E8A221E3212540A06B98A1F1185040402D23F59EFA2440648BDD3EAB195040A04FAC53E5EB24408051F4C0C7195040C0012EC896FD2440ACA78FC01F1B504020B728B34106254068BB09BE691B5040E076BF0AF00D2540C01F7EFE7B1B50408032384A5E2D254070C70DBF9B1B5040A0035ABA824D2540546D37C1371B5040E04D637B2D582540186058FE7C1A504000B728B341862540A8B393C15118504000CEFE40B99D25406CBB09BE6917504060C1E10511B12540EC84D0419717504080716F7EC3B42540DCF4D901D7175040406893C3279D2540F04B6F7F2E1B504000E5D4CE30952540F042ACFE081C5040C017EFC7ED8F25407C4E417E361C5040C00F5EBBB481254094EA3BBF281C5040002DCF83BB7B2540C4438A01121C504000B4E7323571254000D3A23EC91B5040E0AF743E3C6B25402C2CF180B21B5040C0703D0AD76325402C2CF180B21B504000EC6AF2945D2540D4D38041D21B5040E04D637B2D58254060DF15C1FF1B504000999EB0C4532540000C0401321C504040CAA48636502540F07B0DC1711C504020013274EC5025401C9337C0CC1C5040C023F3C81F64254044A19E3E021E50400007B474059B25400418080264205040A0D8D0CDFEA025403CBF28417F2050402065A9F57EAB25402096067E54205040C032384A5ECD2540885704FF5B1F5040E0EB6AF294DD2540804E417E36245040C05CA8FC6BE12540A8AAD0402C255040E0DE52CE17EB2540C81C3D7E6F26504020F86EF3C6F12540186058FE7C26504000AB24B20F1226406C03B00111255040008D9AAF921F2640E87B0DC171245040C0A9F23D23212640B06E2EFEB623504000EB56CF491F264004DC65BFEE2250402009C380251F2640E8818FC18A225040E0251B0FB62026409C1ADA006C215040603579CA6A222640EC45ED7E15215040E0D58F4DF28B2640583A58FFE71C5040206BD4433492264090DE37BEF61750406045B9347E712640F04EB0FF3A14504040A7CAF78C8426403CB665C059155040007D5A457FB026405C3A58FFE7185040A0656B7D91E026405431957EC21D5040606C06B820E3264000E869C0201F5040605A80B6D5E4264090205C01851F5040202A8E03AFE62640AC7A32FFE81F5040C082C30B22022740146C5CFFAE22504060C422861D06274004DC65BFEE225040200AF5F41110274048B0E3BF40235040E051D66F261E274030F38FBE49235040A09E077767252740E84B6F7F2E2350408099F04BFD2C2740C858A65F22235040E0CDFE40B93D27409014580053235040C0716F7EC374274054465C001A2550406021E4BCFF5F2740DCEE5701BE255040A02975C9382E274000E2E7BF07255040E0C98B4CC0172740E842ACFE08245040E014C95702112740FCA276BF0A245040404F9143C40D2740743925202624504020A5A2B1F607274028F6D03E56245040A018213CDA00274008D6E3BED52450402090DB2F9FF4264068D993C0E6255040A015E0BBCDEB2640808D2441B8265040E059677C5FCC26402C1DACFF732A5040605C8FC2F5C8264010A5BDC1172B5040C0622AFD84CB2640DCBB783F6E2B5040601B62BCE6D5264070CA4E3FA82C5040E094490D6DE026406CC18BBE822D504060A148F7731A2740282F3201BF305040C0F1D3B8372F274044B665C059315040C0B5F63E55352740145D177E70315040405C8FC2F548274028266F8099315040E05FE97C785627402CF911BF62315040401077F52A7A2740FC0E45813E31504040C554FA099727402C327381CB31504060FA96395DAE274008D061BEBC325040C032384A5EAD27405440DAFF0033504040D9E90775992740EC57738060335040E0A16131EA922740D4BB783F6E335040E0B0A6B2287C2740EC5773806033504040F4160FEF6127402C508BC1C3335040E00E45813E49274034172AFF5A345040A0B60F79CB4D274028327381CB35504020013274EC50274000E5284014365040C038BA4A77772740EC42ACFE08385040C0D38041D2E7274098205C01853B5040C038B874CC21284000EBAA402D3D5040400F45813E29284044B665C0593D504020301004C8302840DCB5F63E553D5040E0298E03AF46284000E2E7BF073D5040E07F828B154D28405C3A58FFE73C50406045B9347E512840500DFB3DB13C5040200341800C552840EC7B0DC1713C5040A0129F3BC156284048A7203F1B3C5040201077F52A5A28405837177FDB3B5040C03E3C4B90612840889065C1C43B5040A017EFC7ED6F284004D3A23EC93B504020A26131EA722840FCDEA63FFB3B5040809BC6F65A7028405C707841443C5040C0F0D8CF626928401072DEFFC73C5040E0BB783F6E5F284040AA61BF273D5040200AF5F411502840D8CDFE40B93D5040000473F4F8452840A8A10DC0063E5040606893C3273D2840B4490C022B3E5040A032384A5E2D284094F0BDBF413E5040E04D637B2D182840D8AC33BE2F3E504000AB24B20F12284008068200193E504000C87C40A0D32740DCBEB9BF7A3C5040E0C1FA3F87C9274010A8FE41243C5040E0C43BC0937E2740D8A9F23D2339504080B08D78B2E32640FCD8243FE2315040605C8FC2F5C8264098EA3BBF28305040200D36751EC52640AC9B8BBFED2F5040A094490D6DC02640186F9D7FBB2F5040400341800CB526402C20ED7F802F5040201B4982709D264018A5BDC1172F50406038BA4A779726405840DAFF002F5040206893C3277D2640D4D03FC1C52E504060E2AC889A782640F03F6B7EFC2E5040402DCF83BB7B2640A8B05241452F5040E0285C8FC2952640E842ACFE08305040E02EDE8FDBBF2640786308008E335040E09BDF30D1A82640AC6E2EFEB6335040401B4982707D2640C4438A011234504060BC9179E4772640E84EB0FF3A3450408085048C2E7726407C6649809A34504060D026874F7A2640EC39E97DE3345040405C8FC2F5882640D4CDFE40B9355040C0FA96395D8E26407C96E7C1DD355040A06E2EFEB6BF2640EC818FC18A36504000C53BC093DE2640A877F17EDC365040400C040132F42640DCF19881CA36504060D9E9077519274028F38FBE4937504060C2137AFD612740185D177E70395040002A8E03AF6627409826DE019E395040A02DCC423B5F2740EC633E20D0395040C0EB6B5D6A5C2740FCE7A221E3395040C01E85EB5158274024F64201DB39504080B5F97FD5512740501C7920B239504000D9D0CDFE402740A8B6D4415E39504020965D30B89E2640D8D03FC1C536504040DF6B088E8326403CC5AA4198365040C051D66F267E2640D8D03FC1C5365040A08B868C4781264048A4DFBE0E375040E04D637B2D98264028232E008D38504060B5DD04DF9C2640302F3201BF385040000C040132B4264008CD203EB03950408014AE47E1DA264094E7FA3E1C3B5040C0978A8D79152740500DFB3DB13C5040A014AE47E11A274008D6E3BED53C504000EB56CF493F274028266F80993D5040A01A3048FA44274068C18BBE823D504020B937BF614A2740DCB5F63E553D5040804278B4715C2740B4CE6A813D3D504020EC6987BF5E27408869183E223D5040E0EFC2D66C6D27409C478C9E5B3D504080D367075C8F27407C54C37E4F3E50400083DC45989A2740F078CC40653F504080AA0B78999927405C2B137EA93F5040C06ABB09BE9927404C431B800D405040C077F17EDC9E2740C82EC37FBA405040C0CF0D4DD9C12740981D1B817842504080B950F9D7E2274008D3A23EC9435040402D793C2DEF2740FCC610001C445040E05417F032F32740884E417E364450400000000000002840B09B8BBFED43504080D6A88768042840A86E2EFEB643504060A7CAF78C042840D0BB783F6E435040E045B6F3FD0428405013EF004F435040C0F4143944042840BC4049810543504040634337FB03284040E603029D42504020895E46B104284090F0BDBF41425040E0346090F4092840848AE3C0AB415040807ADFF8DA0B284018AE0E80B841504020013274EC102840448386FE09435040A0ED974F561428400015C78157435040A02FF7C951182840888461C092435040A051D66F261E2840888461C092435040C088450C3B4C28408060C77F81425040A053E57B46822840EC78CC4065435040C05626FC52D72840281A6B7F67455040202FDE8FDB3F294024232E008D48504000AAF23D23E129400C6F9D7FBB53504080703D0AD7E32940BC438A011254504060CDE50643E52940C40166BE8354504080A7CAF78CE429406CF7AB00DF54504040C2137AFDE1294040AA61BF2755504000A8E33103DD294090ED7C3F35555040C04D637B2DD8294098E1783E03555040A0F4143944A42940D4B5F63E55515040C07D7214206A2940C0F5D37FD64D50406051BD35B0652940DCC1FA3F874D5040C01B5F7B66592940E024CD1FD34C5040405DC136E2F928406CCA4E3FA848504000EE974F56F42840C822BF7E8848504080DC2A8881EE2840C822BF7E88485040C0DE52CE17CB2840447D04FEF048504040895E46B1C428407003B0011149504000CEFE40B9BD2840C02500FF94495040E02CCF83BBBB2840AC74B0FECF495040407A19C572BB28407C54C37E4F4A5040E01A498270BD2840146C5CFFAE4A5040804D637B2DD8284070D0D03FC14E504080CDE50643052940E8577380604F504020B1A6B2283C29401863997E894F5040C090D7834959294064BB7B80EE4F504040D237691A5C29409C629CBF095050408084EFFD0D5A29405C8B4F013050504080DAFD2AC0572940808159A14850504020A7B1BD164C2940C03AC780EC505040A0656B7D91E02840281A6B7F67515040E0737E8AE3D82840901ADA006C515040207156444DBC2840040F45813E515040606BD44334B228409CE1783E03515040E0F0D8CF62A928401C66DAFE95505040405A80B6D5842840981D1B81784E5040C0BB783F6E7F2840C028417FA14E5040008D9AAF927F2840448386FE094F5040C0D58F4DF2AB28401C8DB5BFB3525040E0716F7EC3F428403C8386FE0957504020C556D0B4042940EC9C668176575040A0094CA775132940A46B5F402F585040A068ACFD9DF5284040A7203F1B5C5040A08EC70C54F628409C1799805F5C504020295C8FC21529401C66DAFE955C504000F52D73BA1C29408087A2409F5C5040C08B868C47212940805A457F685C5040C07A32FFE833294074BB09BE695B50404007B474053B294094DBF63DEA5A504020895E46B14429407006F1811D5A5040202A8E03AF4629405C34D6FECE5A504080FDD7B969432940C4FE243E775B5040A0C554FA0937294030F911BF625D5040A06E2EFEB61F2940D8B2B5BE48605040C017EFC7ED0F2940EC45ED7E1561504000B728B341062940582E54FEB5605040E0EA56CF49FF2840D8CABDC0AC60504080129F3BC1F628402C2F3201BF605040607497C459F12840BC3AC780EC605040005DC136E2D92840D0CDFE40B961504020B6F63E55D52840EC3C2AFEEF615040008A592F86CA2840146C5CFFAE625040A0D38041D2C7284064FD2D01F8625040C0DB114E0BB62840C0310400C7655040C04B546F0DB42840C82EC37FBA685040C0DB114E0BB62840C446CB811E69504060B3CEF8BEB82840845D86FF7469504080B5DD04DFDC2840540DFB3DB16C504000B3B5BE48E02840A49ECC3FFA6C5040206684B707F928403CB9A640666E5040405FD04202FE2840D8C43BC0936E504080F4143944042940A86BED7DAA6E5040E0CCCCCCCC0C294044C5AA41986E50404015C78157132940281DACFF736E504000E3A7716F1E29406806F1811D6E5040C079008BFC2229406CD993C0E66D50406048FAB48A262940208A743FA76D5040C015E0BBCD2B29407003B001116D5040A06ABB09BE39294004D061BEBC6A5040A0C554FA0937294040B9A640666A5040A0129F3BC13629404080457EFD695040C02FF7C951382940848AE3C0AB6950404007B474053B294030F911BF62695040C091088D604B2940AC716F7EC3685040E051D66F267E294014A8FE4124685040E00373F4F8852940ACA78FC01F685040A088450C3B8C2940884E417E3668504080C1E10511912940805A457F6868504000999EB0C4932940C82EC37FBA685040E00B040132942940DCA9F23D23695040C0E4D4CE305529401463997E896B504040068200192A294070C4CC3E8F6E504020FEF0F3DF1B2940EC84D041976F5040401077F52A1A2940AC9B8BBFED6F5040407A19C5721B294028172AFF5A70504060BC9179E4372940F03C2AFEEF75504020068200194A2940241A6B7F67795040A0CCCCCCCC4C2940D0CDFE40B9795040E0285C8FC2552940146C5CFFAE7A5040602634492C59294068FD2D01F87A5040C00F5EBBB4612940C41F7EFE7B7B5040000473F4F8652940AC6E2EFEB67B5040406893C3277D2940282F3201BF7C504000301004C8902940E85DF580797D5040407A19C5729B29402C327381CB7D504000D9D0CDFEA02940E83C2AFEEF7D5040206552431BA82940BC3D0801F97D5040A06DFC89CAAE2940AC9509BFD47D50402023DA8EA9CB2940B09ECC3FFA7C504040295C8FC2D529401466DAFE957C5040804278B4711C2A4008CD203EB079504040013274EC502A40EC54320054765040A0978A8D79552A406C06F1811D76504080AA0B7899592A405855A18158765040E006B474055B2A40D8D03FC1C5765040800C1D3BA84C2A40A8A10DC0067A5040E0DE52CE174B2A405455A181587A504000E3A7716F3E2A409C0B957F2D7C5040A0AA0B7899392A40A8B393C1517C50400018080264282A4010A8FE41247C5040002FDE8FDB1F2A40804E417E367C504060AA0B7899F92940E0A9F23D237D504000B728B341E62940503D997FF47D5040606893C327DD29403CB9A640667E504080F755B950D92940AC77F17EDC7E50402083DC4598DA29403014E97E4E7F5040C04E95EF19E929408454C37E4F82504000B0743E3CEB29401C8DB5BFB382504040861DC6A4CF294038BCE7C07283504080CDE50643C529405C6D37C13783504080BEA085047C29407C60C77F8182504000321F10E8742940981D1B8178825040A032384A5E6D2940D0C43BC093825040C0737E8AE358294094DE37BEF6835040206684B707592940DCB2B5BE48845040601EA33CF3AA294048A7203F1B885040004E7CB5A3B02940EC4EB0FF3A885040C0E7154F3DCA29408C239D819188504080E2AC889AD82940F08711C2A3885040C04E95EF19E9294030232E008D885040C08FDB2F9FF429401866DAFE95885040E006B47405FB2940D4CABDC0AC885040406C06B820232A4028F911BF628950402015C78157532A40106C5CFFAE8A504000EE974F56742A407C8461C0928B5040609E077767852A40BC0166BE838C5040205C8FC2F5882A401C9337C0CC8C50408015E0BBCD8B2A40DCA9F23D238D5040A0BC9179E4972A40F8D8243FE28D5040A06E2EFEB69F2A40E8482EFF218E5040E07A32FFE8B32A408454C37E4F8E504080AA0B7899192B4010A5BDC1178F5040E0A9F23D23212B406CFD2D01F88E504080116DC7D4252B406CD0D03FC18E5040C0F0D8CF62292B407C60C77F818E5040605C8FC2F5282B4004068200198E504000AE65321C272B40EC51F17F478D504080FDD7B969232B40149F3BC1FE8C5040A076BF0AF00D2B409C1799805F8C5040C050A4FB390D2B40D8D38041D287504020D367075C0F2B40FCE769C02087504040013274EC102B405434D6FECE86504000E6E8F17B132B407C8120408686504040D9E90775192B40C01C3D7E6F8650408000193A76382B4044A7203F1B8C5040609885764E3B2B40EC5AB4006D8C504040D367075C4F2B40A8AD11C1388E5040406211C30E532B407C60C77F818E504080BEA085045C2B402C35B401D88E5040205C8FC2F5682B40E83F6B7EFC8E5040C09E20B1DD7D2B4004E869C0208F5040C01A3048FA842B40844B00FE298F504080BFD2F9F08C2B4004E869C0208F504080C763062A9B2B40AC984A3FE18E5040E0955D30B89E2B40C828417FA18E5040A01B62BCE6B52B4054499D80268E5040A05CA8FC6BC12B40ACB915C26A8E5040C0BB783F6EFF2B40B09B8BBFED8F504060CDE50643452C40AC9B8BBFED935040C0DE52CE174B2C401866DAFE95945040E06BED7DAA4A2C40449E5DBEF5945040206552431B482C40FC0E45813E955040A0FDD7B969432C40805D86FF74955040A0B5DD04DF3C2C409026DE019E95504060C554FA09372C40E85DF58079955040A0F1D3B837EF2B403CB0E3BF4093504020C53BC0937E2B4068CD8FBFB4915040E07A32FFE8732B40E85AB4006D905040A09BC6F65A702B4014A8FE4124905040A06BED7DAA6A2B400400000000905040803F373465472B4028F38FBE498F5040A018213CDA402B40584CDE00338F5040406684B707392B405C6D37C1378F504040B60F79CB2D2B40F084D041978F5040A0D24ECDE5F62A40A8A78FC01F90504060BEA08504BC2A403CBCE7C0728F5040E0703D0AD7632A401872DEFFC78C5040406684B707592A406CBE4A3E768C5040E0CABDC0AC482A4068006F81048C504020B728B341262A40DCAF743E3C8B5040A0CF0D4DD9212A40546D37C1378B5040A0F755B950192A402CF38FBE498B504040301004C8102A405C2B137EA98B5040E076BF0AF00D2A40B07A32FFE88B5040C059677C5F0C2A40E84EB0FF3A8C5040C020B248130F2A4098239D81918C5040C0921CB0AB692A409C1ADA006C91504060AD4CF8A56E2A402C266F80999150400023DA8EA9AB2A40544CDE0033935040E0A16131EAB22A40D4AF743E3C935040E0989EB0C4D32A4068FD2D01F8925040404B3B3597FB2A401499B9C0E5925040200F45813E092B405840DAFF0093504040EFAB72A1122B40D8BB783F6E93504040013274EC102B401C90F63FC0935040E091088D600B2B40AC9B8BBFED935040C0D03FC1C5F22A4050431B800D945040403F373465A72A402C172AFF5A945040C082C30B22822A40D4AF743E3C935040E009F5F411702A40B4984A3FE1925040803579CA6A622A40D4D03FC1C5925040A088450C3B4C2A40408386FE09935040A08EC70C54162A40EC4EB0FF3A945040004E7CB5A3102A407C5A457F68945040E0D58F4DF20B2A408487A2409F9450402018080264082A4068F7AB00DF9450402051BD35B0052A4040AA61BF2795504000261B0FB6002A40EC482EFF21965040C0E1934E24002A40186058FE7C96504080B08D78B2032A40D0D03FC1C596504020CBBDC0AC082A4070FD2D01F8965040A068ACFD9D152A40FCE769C02097504080BB5F05F8262A4094205C018597504040068200194A2A401C9337C0CC98504000D13FC1C5522A40EC51F17F47995040C068ACFD9D552A4030266F8099995040C0C98B4CC0572A404080457EFD99504040CAA48636502A40888461C0929B504080AD4CF8A54E2A403038F581E49B504000CDCCCCCC2C2A40EC84D041979F5040E0AD65321C272A40889065C1C49F50402009C380251F2A4004D3A23EC99F5040607497C459112A40C82B82FFAD9F5040C06BED7DAA0A2A40D8D38041D29F5040C0ED974F56F42940B83AC780ECA05040204E7CB5A3F02940A8AAD0402CA1504040321F10E8F42940301A6B7F67A150408015E0BBCD2B2A405476FA415DA25040C038BA4A77372A405476FA415DA2504080B950F9D7422A403CA19E3E02A25040C06BED7DAA6A2A402C2F3201BFA05040C032384A5E6D2A4068BE4A3E76A05040407497C459912A40B0B6D4415EA1504020356090F4E92A40849065C1C4A35040E0C98B4CC0F72A40449E5DBEF5A4504060B5DD04DFFC2A40DCA9F23D23A5504040C554FA09172B404080457EFDA55040A0C2137AFD212B408454C37E4FA65040001286014B3E2B40981D1B8178A650402051BD35B0452B408060C77F81A65040C0C3094CA74D2B40146058FE7CA65040808EC70C54562B4044B9A64066A650404077D84466662B405076FA415DA65040A0C3094CA76D2B4044B9A64066A6504000E6E8F17B732B408481204086A65040C076BF0AF06D2B40148DB5BFB3A65040606002B7EE4E2B4004E869C020A75040A0BB5F05F8462B40844B00FE29A750400069C537140E2B40C4344580D3A65040C017EFC7ED072B40DC4BE141B3A65040A07A32FFE8F32A40C43D0801F9A5504080A4897780EF2A40D8EE5701BEA55040609E077767E52A4004D6E3BED5A4504020F52D73BADC2A40D8F4D901D7A35040A02FF7C951D82A4070C70DBF9BA35040400C040132D42A40BCFE243E77A35040E0C3094CA7CD2A40EC57738060A350402069C537148E2A406CC4CC3E8FA25040609E077767852A40C028417FA1A2504060BC9179E4772A4098DBF63DEAA25040A03BFBCA836C2A40B0B0524145A35040009CDF30D1682A4094205C0185A35040E0A4A2B1F6672A4068D311C0CDA3504060E2AC889A582A405873B9C150A9504060E2AC889A582A4014691B7FA2A95040202FDE8FDB5F2A40DCAC33BE2FAA5040C0F4143944642A40C01C3D7E6FAA5040E0A4A2B1F6C72A40B074B0FECFA95040C038BA4A77F72A4028ED0DBE30A95040C05DDA7058122B407C87A2409FA850408048F8DEDF082B40A03270404BA95040202A8D98D9072B4000D09A1F7FA95040A063416150062B40284A09C1AAA9504000C53A55BEFF2A40DCE8633E20AA5040A044A2D0B2F62A401C6058FE7CAA50404045B9347ED12A4068C70DBF9BAB5040E0921CB0ABC92A40B06E2EFEB6AB50404018080264A82A40FCDEA63FFBAB5040C0D8D0CDFEA02A40189CFA40F2AB50400007B474059B2A40E842ACFE08AC5040E0B5F63E55952A40EC4EB0FF3AAC504000295C8FC2752A405473B9C150AD5040E0716F7EC3742A4028266F8099AD5040606002B7EE8E2A4058499D8026AE504060C554FA09972A40F0482EFF21AE50404069C53714CE2A408496E7C1DDAD5040801D71C806FA2A406CC18BBE82AD5040A06E2EFEB6FF2A405473B9C150AD504060978BF84E142B409CF90E7EE2AC504020F75965A6142B4018ABCDFFABAC504080CCECF3181D2B4074218FE046AC5040800F5EBBB4212B40844E417E36AC5040C09E060C92262B40106CCEC133AC5040803E3C4B90612B40A8A78FC01FAC5040005858703F682B40080C040132AC50400069C537146E2B40ACB393C151AC504060A148F773BA2B4010A27C410BAE504060895E46B1C42B403CB9A64066AE5040E04E95EF19C92B40C428417FA1AE50402048FAB48AC62B4004DC65BFEEAE504060D9E89C9F7A2B408460C77F81AE5040C06455849B642B4070DC627E6EAE5040805EBA490C622B40001286014BAE5040C0CF0EB8AE602B40CC82FB010FAE5040A04277499C5D2B4044EC4CA1F3AD5040E037A110013F2B4028266F8099AD5040E0D58F4DF22B2B405473B9C150AD5040809E077767252B40000F45813EAD5040201286014B1E2B40505260014CAD504080AA0B7899192B406CC18BBE82AD504040C554FA09172B4030327381CBAD5040000C040132142B402435B401D8AE5040C0ED974F56142B40884B00FE29AF5040A0716F7EC3142B407C6308008EAF5040007156444D1C2B4094EA3BBF28B05040805CA8FC6B212B4034172AFF5AB05040606E15C440272B40D8BEB9BF7AB05040E0BEB9BF7A342B40EC8711C2A3B05040202DCF83BB3B2B40D4CABDC0ACB0504020EC6987BF3E2B40109337C0CCB05040C06456EF70432B4024C0E95DBCB0504040A59F70764B2B4040E3C28190B0504060850662D9542B40A02CB5DE6FB05040A00018CFA0592B4028DBF97E6AB05040A0BA641C23612B40C89107228BB0504040378AAC35642B40606A847EA6B0504060C5387F13622B4034444E5FCFB05040C05DBEF5615D2B4024179CC1DFB05040005B7C0A80492B40E4546B6116B15040401E8A027D322B402C1A6B7F67B15040A079008BFC222B40ACB6D4415EB15040A085048C2E172B4050465C001AB150406045B9347E112B40EC51F17F47B15040C0AD65321C072B40848AE3C0ABB15040A0FDD7B969032B40E43C2AFEEFB1504000D00D4DD9012B4090F0BDBF41B25040409E077767052B40EC818FC18AB25040E091088D600B2B40B06BED7DAAB2504060DF6B088E232B400809C38025B35040202DCF83BB3B2B406CC70DBF9BB35040C051D66F267E2B40B0984A3FE1B25040609885764EFB2B4054499D8026B25040609885764EFB2B405476FA415DB25040C0DE52CE17EB2B4068DCD440F3B2504000965D30B8DE2B40ACB0524145B35040801B62BCE6D52B407C5704FF5BB35040207D5A457FB02B40ACB0524145B35040A0F0D8CF62A92B409814580053B35040E0C64ACCB3A22B40C4FE243E77B35040A03579CA6A622B40C446CB811EB55040C0035ABA820D2B40000F45813EB95040402C9D0FCF0A2B4040C269C18BB95040C0F1D3B8370F2B408054C37E4FBA5040C07C410B09182B403014E97E4EBB504020240C03961C2B401C63997E89BB5040800F5EBBB4212B40AC6E2EFEB6BB50400021CB8289272B405437177FDBBB5040A02975C9382E2B40A89B8BBFEDBB5040C068ACFD9D352B409CDE37BEF6BB5040006C06B820832B4064DF15C1FFBB5040809885764EDB2B40B077F17EDCBA5040A0FDD7B969E32B40BC344580D3BA504000356090F4E92B401C99B9C0E5BA504000965D30B83E2C4004D061BEBCBE5040A03E3C4B90612C4090F0BDBF41BE504020931CB0AB692C4024F04E3E3DBE504060861DC6A46F2C405476FA415DBE5040200C040132742C4040C5AA4198BE504000F1D8CF62892C40543A58FFE7C050402023DA8EA98B2C40545260014CC15040A059677C5F8C2C4044A19E3E02C25040E02B9D0FCF8A2C40EC54320054C25040002DCF83BB9B2C40DCBB783F6EC35040E0E7154F3DCA2C40C4378600E0C35040C05417F032D32C4070D311C0CDC35040A050A4FB390D2D40AC984A3FE1C25040A04B546F0D142D4000D061BEBCC250406009DCBA9B172D40106058FE7CC25040201077F52A1A2D40E0AC33BE2FC250404054FEB5BC1A2D40B49509BFD4C15040201077F52A1A2D401C5D177E70C15040A000193A76182D40149F3BC1FEC0504020C763062A1B2D405C2E54FEB5C05040E0A9F23D23212D4000D6E3BED5C05040E0B628B341262D409CE1783E03C15040E076BF0AF02D2D40C004A73E90C1504020013274EC302D406CD993C0E6C150404045B9347E312D40FC1186014BC2504060C1E10511312D40AC6BED7DAAC2504020DC2A88812E2D4070DCD440F3C25040002C9D0FCF2A2D40544CDE0033C3504080C422861D262D40DCBB783F6EC35040E094490D6D202D4068C70DBF9BC3504040AA0B7899D92C4028232E008DC45040605FD04202BE2C40C40166BE83C45040C000193A76982C40C822BF7E88C45040C0622AFD848B2C401072DEFFC7C45040C0D38041D2872C4000E2E7BF07C5504040D6A88768A42C40E845ED7E15C95040605C8FC2F5A82C405C73B9C150C9504000E6E8F17BB32C40888AE3C0ABC9504020809BC58BE52C408481204086CA5040401E8A027D322D40DCB837BF61CA504080D026874F5A2D40EC6F422102CA5040E0F0D8CF62692D402C327381CBC95040E07F828B156D2D403CC269C18BC9504020861DC6A46F2D40845182FE42C9504000999EB0C4732D40EC8711C2A3C85040E0E4D4CE30752D4040B324404DC8504020295C8FC2752D40149CFA40F2C75040E0E4D4CE30752D407C6308008EC75040C06ABB09BE792D409C14580053C750404009C380257F2D402C20ED7F80C7504060B950F9D7822D4000D3A23EC9C75040A03E3C4B90812D4068F7AB00DFC850400000000000802D4030ED0DBE30C95040200341800C752D40BC3D0801F9C950406045B9347E712D40ACAD11C138CA5040E0CCCCCCCC6C2D40C81C3D7E6FCA5040C01A3048FA642D406CC4CC3E8FCA5040A01D71C8063A2D40844B00FE29CB5040206BD44334322D40ACB0524145CB5040200341800C152D4004E869C020CB5040E0A6B1BD160C2D40506D37C137CB504020AE65321C072D400415C78157CB504040CAA48636102D4068D311C0CDCB50404054FEB5BC1A2D4090EA3BBF28CC5040200473F4F8252D406CBE4A3E76CC5040A0CCCCCCCC2C2D40C022BF7E88CC50400015C78157932D4044C269C18BCD5040604B3B35979B2D4070C18BBE82CD5040E006B47405DB2D4094ED7C3F35CD5040E094490D6DE02D403C7D04FEF0CC504020EC6AF294DD2D40BC1F7EFE7BCB504060BEA08504DC2D40388386FE09CB504080737E8AE3D82D407C8D2441B8CA5040E0DE52CE17CB2D4010A27C410BCA504000A5A2B1F6C72D406CCD8FBFB4C950404018080264C82D4044B665C059C9504000356090F4C92D4094E1783E03C95040A0A4897780EF2D40F0482EFF21C65040C05417F032F32D408496E7C1DDC55040605DC136E2F92D40D0CDFE40B9C5504040261B0FB6002E4030327381CBC55040C0703D0AD7032E406806F1811DC6504060D6A88768042E408881204086C6504020634337FB032E40B4984A3FE1C65040407156444DFC2D401C90F63FC0C75040E0AC33BE2FF62D4040B324404DC85040A015E0BBCDEB2D40542E54FEB5C85040A0EA56CF49DF2D40040341800CC95040E0F42D73BADC2D4044B665C059C950408088450C3BEC2D4068DCD440F3CA504060D367075CEF2D40ACB0524145CB5040606552431B082E40EC39E97DE3CC5040A032384A5E0D2E406803B00111CD504060D9E90775192E405873B9C150CD504000BC783F6E1F2E40941ADA006CCD504060BB5F05F8262E40845D86FF74CD50408018213CDA802E402438F581E4CB5040E0978A8D79B52E408060C77F81CA504080C2137AFDC12E40C0490C022BCA5040400F45813EC92E401C8A743FA7C95040C06BED7DAACA2E405C73B9C150C95040C01EA33CF3CA2E40449E5DBEF5C8504020B937BF61CA2E4098239D8191C85040406E15C440C72E40F814C78157C75040E017080264E82E40846649809AC4504000CEFE40B9FD2E40900B957F2DC4504020F86EF3C6F12E40407D04FEF0C85040E0C1FA3F87C92E4070006F8104CC5040405A80B6D5C42E40504F1F813FCC5040A053E57B46C22E40C022BF7E88CC504080B08D78B2C32E40EC39E97DE3CC50400059518369D02E4068C77F8120CD5040E0861A8524D32E407C6000E143CD504020D029C8CFD62E40DC15C1FF56CD5040804067D2A6DA2E40C864AA6054CD5040E05626FC52F72E40E851F17F47CD5040207497C459112F406CD65240DACC5040A0DE52CE172B2F402CF6D03E56CC504040F86EF3C6312F40000C040132CC504000EE974F56342F402438F581E4CB5040C0737E8AE3382F40C42B82FFADCB504020261B0FB6402F40846308008ECB5040A050A4FB396D2F401899B9C0E5CA504020B6F63E55752F40AC77F17EDCCA50404054FEB5BC7A2F40388386FE09CB5040A0A148F7737A2F40EC78CC4065CB504060BC9179E4772F402C2CF180B2CB504020D6A88768642F40980ED6FF39CD5040A07A32FFE8D32E4048A4DFBE0ECF5040C050A4FB398D2E4044BCE7C072CF5040A0116DC7D4852E40DCBB783F6ECF5040A06E2EFEB67F2E402C14E97E4ECF504040E2AC889A782E40FCDB65BFEECE504000EFAB72A1722E405834D6FECECE504060D6A88768642E40888D2441B8CE50402021CB8289272E40106F9D7FBBCF504020261B0FB6202E40C4378600E0CF5040A082C30B22222E40F04EB0FF3AD05040403F373465272E400018080264D05040406002B7EE2E2E40E85AB4006DD05040E0311F10E8342E4028232E008DD05040A01A3048FA442E407003B00111D1504000C2FA3F87492E40505260014CD15040800C1D3BA84C2E409426DE019ED1504020A26131EA522E40E84B6F7F2ED35040E0E5E8F17B532E40808461C092D3504040B60F79CB4D2E40849065C1C4D3504040BB5F05F8462E40302CF180B2D3504000C87C40A0132E4098DBF63DEAD25040A0BC9179E4B72D406CC18BBE82D15040E05D9F39EBAB2D408036AB3E57D050404048FAB48AA62D40C4378600E0CF5040A0BFD2F9F06C2D4004D9243FE2CD5040A03579CA6A622D40D8C1FA3F87CD5040E08EC70C54562D40E851F17F47CD5040002A8E03AF462D40E851F17F47CD5040008D9AAF923F2D4040B665C059CD5040E0230C03963C2D40C004A73E90CD5040C0C98B4CC0172D4070D311C0CDCF504080C1E10511112D40106F9D7FBBCF5040802634492CB92C4068FD2D01F8CE504060AA0B7899B92C40CCD38041D2CF504080B60F79CBED2C401099B9C0E5D25040C077F17EDC1E2D405055A18158D65040C0A4A2B1F6272D40149F3BC1FED85040809E077767252D40545260014CD9504020F52D73BA3C2D408081204086DA5040E08B868C47412D406CD0D03FC1DA5040200AF5F411502D40544CDE0033DB50402051BD35B0852D40A877F17EDCDA5040A068ACFD9D952D40C828417FA1DA5040804278B4719C2D40981D1B8178DA504020AAF23D23A12D4098F0BDBF41DA504060B08D78B2A32D40583D997FF4D950404038A110019F2D4094ED7C3F35D9504000FEF0F3DF9B2D4070F7AB00DFD85040A023F3C81FC42D4070D993C0E6D95040201C5E1091DA2D405864744012DB50404012A1116CD42D4034682101A3DB5040C0069964E4C42D40F0C000C287DB5040A091088D60AB2D40940B957F2DDC504040809BC58BA52D4030172AFF5ADC504080BC9179E4772D405840DAFF00DF5040E0311F10E8742D40586D37C137DF504000BFB9BF7A742D40808461C092DF5040406684B707792D406CD311C0CDDF5040C0FDD7B969A32D402C327381CBE15040206211C30ED32D40D4BB783F6EE35040602FF7C951D82D40E884D04197E3504000274D83A2F12D4058431B800DE45040E05DDA7058122E40BC0166BE83E45040E053E57B46222E4040BF28417FE45040C04E95EF19292E4034172AFF5AE450408023F3C81F442E400415C78157E35040A0035ABA824D2E401C99B9C0E5E25040E009F5F411502E4044E603029DE25040407D5A457F502E4028F04E3E3DE25040800C1D3BA84C2E40BC3D0801F9E15040E0A4A2B1F6472E40DCEE5701BEE1504040DF6B088E032E400009C38025DF5040E0737E8AE3F82D40D8F19881CADE504040643DB5FAEA2D40F4BDBF417BDE5040608FC18A53DD2D40DCDCD1FF72DE5040A0FEEDB25FDF2D4060A626C11BDE5040404C50C3B7F82D403C80457EFDDD5040207C2AA73DFD2D40DC0F786000DE5040603F373465072E403C80457EFDDD5040206BD44334122E40E854320054DE5040C0C98B4CC0372E407C6308008EDF5040606E15C440A72E401099B9C0E5DE5040E089592F86CA2E4048E603029DDE5040007A19C572DB2E4040B9A64066DE5040E053E57B46E22E402CF04E3E3DDE50400023DA8EA9EB2E4030327381CBDD504000301004C8F02E4090ED7C3F35DD504040A48977800F2F40D4B5F63E55D95040A07F828B152D2F4040B324404DD4504000E2934E24402F4004E2E7BF07D1504000F2ECF2AD472F40080341800CD15040C088450C3B4C2F40885182FE42D1504000F52D73BA5C2F40E854320054D2504000261B0FB6602F4044C5AA4198D25040E0703D0AD7632F4004DC65BFEED25040E0B628B341662F40A4B0524145D35040606E15C440672F4094205C0185D35040005A80B6D5642F40D4D38041D2D35040C014AE47E13A2F408060C77F81D6504000E9297288082F40D8AF743E3CDB5040000AF5F411102F405C31957EC2DD5040200341800C152F407C81204086DE5040604B3B35971B2F40E84B6F7F2EDF5040A057E883652C2F400000000000E05040802975C9382E2F40C064E3C116E0504020A8E331033D2F40542E54FEB5E0504020C422861D662F4028F04E3E3DE25040A0622AFD846B2F40B0B915C26AE2504000C74ACCB3822F405440DAFF00E35040009CDF30D1882F4090E7FA3E1CE350402020990E9D962F4044B0E3BF40E35040E04F38BBB5B42F40ECB4FCC055E350408023F3C81FC42F40805704FF5BE3504000E8154F3DCA2F40B8FE243E77E35040E059677C5FCC2F40849065C1C4E3504000356090F4C92F4058431B800DE45040A0C2137AFDC12F40980B957F2DE45040407497C459B12F40504F1F813FE45040E074B0FECFA92F40E84EB0FF3AE4504000AB24B20F722F40146F9D7FBBE350406048FAB48A662F403CBCE7C072E35040E0003274EC502F4070D0D03FC1E25040002A8E03AF462F405476FA415DE2504080B3CEF8BE382F4004CD203EB0E1504000FEF0F3DF1B2F408487A2409FE05040805FE97C78162F40E87B0DC171E05040809BC6F65A102F40A8B393C151E05040C02FF7C951B82E401072DEFFC7E05040E06DFC89CA8E2E40A8AAD0402CE15040C0D8D0CDFE802E40E85DF58079E1504060C763062A7B2E40888AE3C0ABE15040A009DCBA9B772E406CFAEC80EBE15040E00241800C752E40ACAD11C138E25040607156444D5C2E40BC40498105E750402054FEB5BC5A2E400015C78157E75040204278B4715C2E40809065C1C4E75040C082C30B22622E40D4BEB9BF7AE85040A038BA4A77972E40D8CDFE40B9ED5040A02634492C992E40FCD8243FE2ED5040E0E2A7716F9E2E4048A19E3E02EE5040A09E077767A52E408096E7C1DDED5040E0D24ECDE5B62E40585260014CED5040C09BDF30D1E82E402C38F581E4EB504020D6A88768042F40A8B0524145EB504080B60F79CB4D2F40586D37C137EB504020D462F030352F405CC43E0114EC5040400F45813E292F40C44659BF99EC5040C0EC66463F222F40A4353FFED2EC5040A01C5BCF101E2F40C82B499EEBEC504060A1496249192F40189F3BC1FEEC5040000D1AFA27102F40585EF23FF9EC5040608099EFE0072F4094088D60E3EC5040C02CB64945032F40705776C1E0EC5040609886E123FA2E40B8FE9600FCEC5040E05301F73CF72E401487A5811FED5040C0C3094CA7CD2E4000DC65BFEEEE5040E076BF0AF0CD2E40DCAF743E3CEF5040E013B2F336F62E4068AC36FFAFEE5040201E8997A7132F40B81CAF40F4EE5040C052D0ED25252F40DC12B9E00CEF504020931CB0AB292F40FCC3CF7F0FEF5040A07D5704FF332F40607C0A80F1EE504040D026874F3A2F40BC4CDBBFB2EE504000C2F9D4B14A2F408096E7C1DDED504040A7CAF78C842F40B0A78FC01FEC5040400F45813E892F402C38F581E4EB5040E0989EB0C4932F40C41F7EFE7BEB504080A7CAF78CA42F4068FD2D01F8EA5040E09BDF30D1A82F4094E7FA3E1CEB5040C0622AFD84AB2F4098EA3BBF28EC50408017EFC7ED8F2F40D8C43BC093EE5040E051D66F265E2F4004DFA63FFBEF504080DF6B088E432F40EC8711C2A3F05040E0C3094CA72D2F406803B00111F15040C082C30B22C22E40BC40498105F35040A077F17EDCBE2E40186C5CFFAEF25040E0D24ECDE5B62E40E8482EFF21F25040008D9AAF925F2E40208A743FA7ED5040E0AC33BE2F562E4090ED7C3F35ED504080CDE50643252E40EC84D04197EB5040A0656B7D91002E40C01C3D7E6FEA5040C08EC70C54D62D40D8C1FA3F87E95040200AF5F411B02D406CF7AB00DFE85040C0E1934E24A02D40F439E97DE3E85040400473F4F8852D4044AA61BF27E95040A02634492C792D40F07E4E417EE95040A0978A8D79752D405C31957EC2E95040C0DB114E0B762D4050499D8026EA504060AD4CF8A58E2D4010A27C410BEE50400015C78157932D409811178046EE50408059677C5FCC2D4044E603029DEE504000CA8B4CC0F72D4040C5AA4198EE5040201E8A027D122E40E857738060EF504000B4E73235112E40848AE3C0ABF1504080B3CEF8BEF82D406CCD8FBFB4F15040606893C327BD2D4098ED7C3F35F1504040D367075CAF2D406803B00111F15040A0622AFD848B2D4018A27C410BF2504000D48041D2872D408454C37E4FF2504060B950F9D7822D40584CDE0033F350408023F3C81F842D401863997E89F350404045B9347E912D40DCB2B5BE48F450402054FEB5BC9A2D40C42EC37FBAF45040808B868C47012E4068CD8FBFB4F55040C04D637B2D182E405C31957EC2F55040C0EA56CF491F2E409426DE019EF5504060634337FB232E4030F911BF62F55040A0E7154F3D2A2E406CC18BBE82F55040C0B5F63E55352E4040B9A64066F6504000D13FC1C5322E40146C5CFFAEF6504000AAF23D23212E405434D6FECEF6504060D9E90775192E40D8F19881CAF6504000895E46B1042E40D0C43BC093F6504060B950F9D7E22D4050499D8026F6504060CAA48636D02D40C8310400C7F55040A03579CA6AC22D4010691B7FA2F550400054FEB5BCBA2D409426DE019EF55040C0989EB0C4B32D405C31957EC2F5504000A26131EAB22D4014A27C410BF65040200D36751EC52D401463997E89F7504020C2FA3F87C92D40C82B82FFADF7504000861DC6A4EF2D405C3A58FFE7F8504040BEA08504FC2D4040AA61BF27F95040A091088D600B2E4030ED0DBE30F950400090DB2F9F142E4054465C001AF95040E05A99F04B5D2E40D8B2B5BE48F85040E014C78157732E405837177FDBF75040C04D637B2D782E40D0C77C40A0F7504040C422861D862E4018A5BDC117F75040C0F0D8CF62A92E40282F3201BFF8504080BFD2F9F00C2F4098DBF63DEAFA5040202C9D0FCF6A2F407C6649809AFC5040A0B3CEF8BE782F40C82EC37FBAFC5040C05758703F882F40B0716F7EC3FC504080CAA48636902F40EC8711C2A3FC5040A0BEA085049C2F405870784144FC504040261B0FB6A02F40F042ACFE08FC504060D6A88768A42F4000D3A23EC9FB504080BB5F05F8A62F40C01F7EFE7BFB5040E09BDF30D1A82F40D4F19881CAFA5040205FD04202BE2F4014A5BDC117FB504040CAA48636D02F408087A2409FFC5040C0F0D8CF62E92F40806308008EFF504020A7B1BD16EC2F4000D6E3BED500514020AB24B20FB22F40941D1B8178025140E0FDF0F3DF9B2F40B0AD11C1380251404048FAB48A862F4068CD8FBFB401514080A7CAF78C442F40C03D0801F901514000A26131EA322F400006820019025140409CDEC5FB092F407C5DF8C1F9025140A03579CA6AE22E401C967840D9015140A05CA8FC6BE12E406CBE4A3E76005140C021E4BCFFDF2E40A8A78FC01F005140A07A32FFE8D32E402C14E97E4EFF5040C0C3094CA7CD2E40EC4B6F7F2EFF504000C2FA3F87A92E40C02B82FFADFF504020895E46B1A42E40AC7A32FFE8FF5040A05A99F04B9D2E40E85AB4006D005140C07C410B09982E409CE1783E03015140207497C459912E4070FAEC80EB01514040013274EC902E409C11178046025140000C040132942E403CE603029D02514020861DC6A4AF2E40806649809A04514000CA8B4CC0B72E4040AA61BF2705514040EC6AF294DD2E401C63997E89075140A02634492CF92E40845A457F68085140A0D8D0CDFE002F40F05AB4006D08514060DF6B088E032F40B0A78FC01F08514000261B0FB6002F40D4BB783F6E075140C08C9AAF92FF2E4008D061BEBC065140202043C70E0A2F407009C03FA506514080F700DD970B2F40448F519E79065140003C86C77E0E2F408CD5E6FF55065140A01C041DAD122F40046F0F42400651402016DD7A4D2F2F4084336ABE4A07514020689599D23A2F4080B4FF01D6075140C05A99F04B3D2F40B0BF2500FF075140E0C760C5A93E2F405C1C075E2D08514000321F10E8542F4028F911BF62095140C07F828B156D2F4048AA61BF27095140004C546F0D742F4094E1783E030951404020990E9D762F40542E54FEB5085140207A19C5727B2F40A8A10DC006065140C07C410B09782F4070CD8FBFB4055140E01D8A027D722F40D4C1FA3F8705514000356090F4692F40B804A73E90055140E0CF0D4DD9612F4004CD203EB0055140E0F99AE5B2492F40FCCF9A1F7F055140C081AE7D01452F409C2FF65E7C05514020F302ECA3432F4014842BA050055140E0FDF0F3DF3B2F40FCDEA63FFB035140407156444D3C2F4068C70DBF9B0351408077F17EDC3E2F40941458005303514060B08D78B2432F4018A5BDC117035140C0C1FA3F87492F409CDBF63DEA0251408020B248134F2F40B077F17EDC025140000C040132B42F4018967840D9055140002DCF83BBBB2F40281DACFF730651402038A11001BF2F40D0D03FC1C5065140A03579CA6AC22F4090E7FA3E1C0751400023DA8EA9CB2F4018A8FE4124085140C051D66F26DE2F40C02B82FFAD0B514020634337FBE32F40E8818FC18A0E514020895E46B1E42F40F8DB65BFEE0E5140206552431BE82F40A8B05241450F5140E088450C3BEC2F401463997E890F514040F86EF3C6F12F40B06E2EFEB60F5140F03C80457E0130403CC8EBC1A40F514040809BC58B05304098205C01850F5140A0E0F0828808304094145800530F514080A86DC3280C30405434D6FECE0E514090812040861A3040BC28417FA10A5140A0FE7A85051B304038C269C18B095140C0E9B303AE1730402C172AFF5A045140307497C45931304040E603029DFE504070D6A8876834304094E4B9BE0FFE504050C554FA0937304050465C001AFD5040107CB779E3383040805704FF5BFB5040A0E0F0828838304070FD2D01F8FA50401021CB8289373040F0818FC18AFA5040703A58FFE7343040C4310400C7F95040000341800C353040981ADA006CF950408009DCBA9B37304008D6E3BED5F85040D05147C7D564304094239D8191F45040D0393FC5716C3040B09B8BBFEDF3504000857AFA087830400809C38025F35040E057C9C7EE7E3040C4344580D3F25040107D5A457F80304090205C0185F3504060431B800D7430402CF04E3E3DF65040106893C3276D304070C4CC3E8FF6504040F38FBE495F3040544CDE0033F7504080A2EBC20F5230405837177FDBF75040B0DDAF027C4330408093A641D1F85040900F5EBBB4413040EC45ED7E15F95040009D82FC6C4030402CF911BF62F95040A004FD851E3530403038F581E4FF5040A004FD851E35304040A7203F1B005140201B4982703D30407C87A2409F00514050CAA486364030401472DEFFC700514090F755B950593040E85AB4006D0051408000193A766830402420ED7F80FF504080035ABA826D3040F054320054FE504050C1E1051171304028327381CBFD504080116DC7D475304040B665C059FD504070B3CEF8BE78304048AA61BF27FD5040A0ECF483BA7C3040FCE1E7BF07FD5040E05147C7D584304090E1783E03FD50409009DCBA9B873040B0AAD0402CFD50400026AAB7068A304028F911BF62FD5040D04E0647C97F3040540DFB3DB100514060B5DD04DF7C3040E839E97DE3005140007CB779E37830409CE1783E0301514020917EFB3A6C30403CB665C059015140A0FDD7B969633040E47E4E417E01514060D367075C5F30409826DE019E015140909FAA42035D30401C967840D9015140D03A71395E5D30402CF04E3E3D02514090FA96395D5E3040AC6BED7DAA02514040ED0DBE3065304094DE37BEF603514030E44A3D0B7630400806820019065140205C8FC2F578304068D993C0E605514070CAA4863680304068F7AB00DF045140701A3048FA8430407C5A457F680451406034D6FECE8A30406C006F810404514010F911BF62A930409CDBF63DEA025140505260014CAD3040F8DB65BFEE02514070D367075CAF3040544CDE003303514090A52C431CB730405C70784144045140603D997FF4893040D0EE5701BE055140201EA67D7383304080A5F3E15907514020F6251B0F723040940854FF200751401039EFFFE3683040B8B0E07EC0055140B0E9B303AE5730401866DAFE9504514040D505BCCC4C3040D0B837BF6106514010763579CA4E3040C42B82FFAD07514050B3CEF8BE683040C0310400C709514040E78BBD177B304044B0E3BF400B5140800C1D3BA87C30401C9CFA40F20B514060CDE506437530403CB665C0590D51409015E0BBCD6B3040185D177E700D51401047E5266A59304028ED0DBE300D514050069CA5645130406CAF3E1EFA0C514020FA997ADD4A304074E2E47E870C514050499D80263E3040C464E3C1160C5140E0548847E2393040ACA78FC01F0C5140F04543C6A330304044B324404D0C514000240C03962C3040EC5AB4006D0C5140808AE3C0AB2930407C87A2409F0C5140405C8FC2F5283040409E5DBEF50C514050D026874F2A3040C8310400C70D514050BEA085042C304000068200190E5140209C5088802F3040BC490C022B0E5140000C040132343040FCE42840140E5140A0E9B303AE37304070FAEC80EB0D51405037177FDB3F30406CD993C0E60D514060BC75FEED4E30400C33A6608D0E514080E28FA2CE503040583750E09D0E5140300934D8D4513040B8D47ABFD10E5140C0C85A43A9513040C89DD2C1FA0E514020F62686E4503040340B26FE280F5140C0A623809B4D30402C085740A10F5140A02C9963794B3040100FD3BEB90F514070DA70581A48304090C09140830F5140D05B9203764530402805DD5ED20F5140009D82FC6C4030405837177FDB0F5140D0A6B1BD161C304040AA61BF27115140908AE3C0AB193040B0B6D4415E11514020990F08741A3040CCCDFE40B9115140406BD4433422304040BCE7C07213514080F4143944243040146F9D7FBB135140F01A4982702D3040B0A78FC01F145140F04543C6A3303040544F1F813F14514060B950F9D7823040ACB393C1511051405031957EC2853040A8A78FC01F105140F0AF743E3C8B3040FC14C781570F5140D0B2B5BE4890304050499D80260E514010274D83A2913040E47E4E417E0D5140A0EF3504C7913040D8A9F23D230D514070C2137AFDA130400809C380250B5140C05626FC52B7304050465C001A09514030F04E3E3DBA3040583A58FFE708514010895E46B1C43040F05AB4006D085140F0907EFB3ACC304018A8FE4124085140201286014BCE3040845A457F68085140D04334BA83CC3040D0CABDC0AC085140002DCF83BBBB30405440DAFF000B5140A0129F3BC1A6304030172AFF5A0C514070C2137AFDA130408493A641D10C514050B3CEF8BE9830401C6058FE7C0E51401021CB8289973040D4D03FC1C50E5140A0F27684D396304094E7FA3E1C0F5140F0D38041D29730401463997E890F5140008E3D7B2E773040BC344580D3125140503D997FF46930405840DAFF0013514050CAA48636403040542E54FEB5145140B050A4FB393D3040583A58FFE7145140A04D637B2D38304000E5284014165140E0548847E239304044B9A640661651406034D6FECE4A3040D8AF743E3C17514080ABAE4335513040C81F7EFE7B17514090A86DC3288C3040A8B6D4415E19514040DB87BCE5963040C004A73E90195140E05147C7D5B43040188A743FA719514060D9E90775B9304044C269C18B195140909FAA4203BD304030F911BF621951400006820019DA30405C37177FDB175140D0393FC571DC304040C8EBC1A4175140B001BC0512E030408CE7FA3E1C175140107497C459E13040C4344580D31651409018213CDAE03040B0B915C26A16514010763579CADE304054499D8026165140407156444DDC3040E43C2AFEEF15514030D2C43BC0D73040105D177E70155140D068ACFD9DD53040A4AAD0402C155140007976F9D6D3304004D6E3BED514514090FDD7B969D33040E87B0DC171145140D068ACFD9DD5304034172AFF5A145140306C06B820E33040542E54FEB5145140009700FC53E6304004D6E3BED5145140E0AF743E3CFB304014967840D91551404069C53714FE304048A19E3E021651407055A1815802314068C4CC3E8F16514030DB87BCE5063140448386FE09175140E0CDFE40B90D31405C6D37C137175140A001BC0512203140846308008E175140107976F9D6233140C81F7EFE7B17514080129F3BC126314028F38FBE49175140F0B837BF612A314070D0D03FC1165140206C06B82053314028F6D03E5610514020F6D03E56543140E842ACFE08105140A01A3048FA5431402CF6D03E560C514080A7CAF78C543140B09B8BBFED0B5140D0DDAF027C5331402420ED7F800B5140407D5A457F5031401899B9C0E50A5140D04543C6A350314084812040860A5140709065C1C4533140B0B915C26A0A5140D03FC1C58A5631403CC5AA41980A51405034D6FECE5A314004E869C0200B5140D04334BA835C31403CBCE7C0720B514070D026874F6A3140AC6BED7DAA0E51401083DC45986A3140F03F6B7EFC0E514000990F08746A3140FC14C781570F5140B074B0FECF693140BC2B82FFAD0F5140D0AC33BE2F66314090239D819110514060D6A887686431408093A641D1105140809C69C2F6573140001286014B125140E0C77C40A0533140188DB5BFB3125140702E54FEB55031401C99B9C0E51251400073F4F8BD493140DCAF743E3C13514030DB87BCE5463140BCFE243E7713514060A7CAF78C443140302CF180B2135140C0EAE5779A38314098ED7C3F35155140A0F27684D3363140E45DF58079155140A0FDD7B969333140C81F7EFE7B17514090F4143944343140D0D38041D21751405040DAFF003F31409826DE019E195140106BD44334423140D0CDFE40B9195140306211C30E5331409826DE019E195140B05626FC52573140C004A73E901951400082397AFC623140DCA9F23D23195140107CB779E3683140302F3201BF1851404029CC7B9C6D3140B0EFC34142185140602B137EA97B3140ACB052414517514050465C001A893140D4C43BC093165140D03A71395E8D31408481204086165140D0656B7D919031402829B000A6165140506C06B820933140A877F17EDC165140D05A0A48FB933140584CDE0033175140E046753A90913140D0BB783F6E175140B0FB3905F98531405C37177FDB175140307A19C5727B314030172AFF5A185140A00F5EBBB461314028327381CB195140908D2441B85E31403C80457EFD1951404069C537145E3140EC543200541A514050CAA4863660314038C5AA41981A514050C554FA09673140D4D03FC1C51A5140D050A4FB397D3140C4404981051B514030EACC3D24903140804B00FE291B5140E02B2CB81F943140804B00FE291B5140E03DB2B96A9231408093A641D11C514090035ABA828D3140DCC1FA3F8721514050C763062A8B31405831957EC2215140106552431B883140D8CDFE40B9215140503A58FFE78431409026DE019E215140F0B837BF615A31401C90F63FC01F514020895E46B1543140D8BB783F6E1F514080069B3A8F523140884B00FE291F5140D057C9C7EE4E31408460C77F811E514090E33103954D3140F0482EFF211E51400026AAB7064A3140F07E4E417E1D5140106211C30E4331406CF7AB00DF1C51401073F4F8BD393140D0BEB9BF7A1C51406040DAFF002F3140D8B2B5BE481C5140306893C3271D3140FCDEA63FFB1B514040DC2A88810E314004D3A23EC91B5140A0AEEFC341063140D8D38041D21B514030CF83BBB3023140FCDEA63FFB1B5140C0F8F884EC003140584F1F813F1C5140F0A9F23D2301314024232E008D1C5140D034EF384503314008D6E3BED51C514000990F08740A3140489E5DBEF51C514080FA96395D0E3140489E5DBEF51C5140F0BEB9BF7A143140000F45813E1D514050BB5F05F8163140805D86FF741D514070B3CEF8BE183140C4310400C71D5140002F6D382C193140D8AC33BE2F1E5140B0E0F082881831408460C77F811E514040CAA48636103140FCE769C0201F5140C05CA8FC6B01314044A7203F1B2051408096E7C1DDFD30405870784144205140F0D38041D2F73040F8DEA63FFB1F514050B950F9D7F230401C63997E891F5140602E54FEB5F03040B0B05241451F5140D057C9C7EEEE30406CDCD440F31E5140D06BED7DAAEA30403CB9A640661E5140B0E0F08288E83040F0482EFF211E514080FA96395DDE3040447D04FEF01C5140A09C69C2F6D73040582E54FEB51C514040B3CEF8BEA8304068DF15C1FF1B514040BB5F05F8863040889065C1C41B514040CF83BBB382304070D311C0CD1B5140B06E2EFEB67F304068DF15C1FF1B5140109700FC53763040980B957F2D205140D068ACFD9D753040C00166BE8320514040C554FA09773040F039E97DE3205140D0AF743E3C7B3040981ADA006C215140D03730B951883040C41C3D7E6F22514030DEC83CF28B3040146058FE7C225140C028417FA1933040107EE200FA21514080AA0B7899993040A874B0FECF21514090035ABA829D3040AC9509BFD4215140A021E4BCFF9F304010A27C410B225140008BFCFA21A23040F054320054225140406C06B820A3304070D0D03FC122514020D8463CD9A13040388386FE09235140801B62BCE6953040D0D38041D2235140C0DDAF027C93304058431B800D245140700F5EBBB4913040B0B393C151245140109D82FC6C9030407C6649809A24514060D367075C8F304094ED7C3F35255140D028EB37138F3040F03C2AFEEF255140209C5088808F3040EC54320054265140A0F8F884EC9030401C8DB5BFB326514070D6A88768943040885704FF5B27514060AD4CF8A59E3040A8716F7EC3285140F0A9F23D23A13040109F3BC1FE2851400096CE8767C53040FCCF61BEBC2A514030D2C43BC0D73040E884D041972B514060C554FA09F73040F039E97DE32C514020E78BBD17FB3040583A58FFE72C5140C0622AFD842B3140EC51F17F472D514070B81E85EB4131407006F1811D2E5140100F45813E5931403CC269C18B2D5140D03A71395E5D3140981ADA006C2D5140F04E0647C95F314030ED0DBE302D514000274D83A2613140C43AC780EC2C514070B950F9D7623140EC8711C2A32C5140C0DDAF027C63314040B324404D2C5140A0FB3905F9653140AC6E2EFEB62B5140E0D38041D267314040BCE7C0722B514010240C03966C3140EC3F6B7EFC2A5140708461C0926F3140D8F19881CA2A5140002A8E03AF763140901D1B81782A5140109A417C607B31405876FA415D2A51409014AE47E1AA3140C4310400C729514040499D8026AE314000D9243FE2295140001B498270AD3140B0AD11C1382A5140602B137EA9AB31401C6058FE7C2A5140E040F33977A7314064FD2D01F82A514050CF83BBB3A23140D8BB783F6E2B51401009C380259F3140E884D041972B5140B0FE7A85059B3140186F9D7FBB2B5140102A8E03AF963140849065C1C42B5140C0622AFD848B314038C8EBC1A42B514000763579CA7E3140186F9D7FBB2B5140D06BED7DAA7A3140C0378600E02B5140D050A4FB394D3140148DB5BFB32E514060D026874F4A31401899B9C0E52E51402088BB7A153D314004DFA63FFB2F5140D0393FC5713C314048B324404D305140F031AEB8383E31408087A2409F30514050499D80266E3140C02B82FFAD335140C05CA8FC6B71314070D311C0CD335140C004FD851E7531405C37177FDB335140A074B0FECF7931407C9065C1C4335140E03A71395E7D31406CC70DBF9B3351404031957EC285314068FD2D01F8325140A0FDD7B969933140FC1186014B32514070A7CAF78CC4314048B324404D305140A014AE47E1CA3140F07B0DC171305140E0C1FA3F87C93140845D86FF74315140107CB779E3C8314028327381CB315140A0E9B303AEC73140FCE428401432514040895E46B1C431409C1117804632514020938D075BC03140EC54320054325140C059677C5FBC3140EC54320054325140B004FD851EB5314048ADA23F3432514070C1E10511B1314048ADA23F34325140D02E6D382CA93140ACB915C26A32514090A2EBC20FA2314004D061BEBC325140D05D4BC8077931408093A641D1345140D03730B951783140D8A9F23D2335514040B60F79CB7D3140D4C1FA3F8735514030809BC58BA53140FCDEA63FFB37514080A52C431CB73140449E5DBEF538514030E78BBD17BB3140B09ECC3FFA385140C059677C5FBC3140D4CABDC0AC385140A015E0BBCDBB3140D4B2B5BE48385140909FAA4203BD3140FCDEA63FFB375140D0BB783F6EBF31401C90F63FC03751400082397AFCC23140EC84D04197375140C06E2EFEB6CF3140A4B052414537514060431B800DD43140D0AF743E3C37514050BB5F05F8D63140F078CC4065375140D02E6D382CD931405C2B137EA9375140D02E6D382CD9314068006F8104385140C05626FC52D73140D4B2B5BE48385140809C69C2F6B73140D4BB783F6E3B5140A08461C092AF3140B8FE243E773B5140B0F8F884ECA03140DCAF743E3C3B5140C0E67283A192314068DCD440F33A5140C0716F7EC384314040C5AA41983A5140E0C43BC0937E3140E4543200543A514060D9E90775793140FCD8243FE2395140206E15C4407731409026DE019E39514030895E46B17431402C1A6B7F67395140B0EF3504C7713140080F45813E39514080FA96395D6E3140845182FE423951402088BB7A156D3140C404A73E90395140809FAA42036D31406CFAEC80EB39514060B5DD04DF7C3140885704FF5B3F51400094BF7B47A13140C81C3D7E6F465140406C06B820A3314070D0D03FC146514030E44A3D0BA6314098DBF63DEA4651408021E4BCFFAF314044B0E3BF40475140E036FE4465B73140E857738060475140E036FE4465E73140ACA78FC01F4851404069C537141E3240805182FE42495140B0716F7EC3243240F05DF5807949514060BB5F05F8263240D8EE5701BE49514030ED0DBE300532407C812040864E514010938D075B00324048E603029D4E5140605260014CFD3140BC344580D34E5140F028EB3713FF3140E83C2AFEEF515140F0A9F23D23013240148DB5BFB3525140200C04013204324040BCE7C072535140D05FE97C78063240AC6E2EFEB6535140D05D4BC807093240A89B8BBFED535140A0DDAF027C1332407C4E417E3654514040C422861D163240EC5AB4006D545140A0EF3504C72132406CCD8FBFB4555140E0A6B1BD162C3240C42EC37FBA585140B050A4FB392D324000D9243FE2595140106893C3272D32402CF04E3E3D5A5140E0393FC5712C3240602B137EA95B514040F6D03E563432409026DE019E5D5140B0EF3504C7413240FCE769C0205F5140E05147C7D54432402CF38FBE495F5140505C8FC2F54832402CF38FBE495F514030DEC83CF24B324014A5BDC1175F5140C0DA6E826F4E3240AC77F17EDC5E51408009DCBA9B57324068D993C0E65D5140E0AF743E3C5B3240B0B6D4415E5D514040F38FBE497F32403038F581E45751401082397AFC823240941117804656514010068200198A32400009C38025535140007FF8F9EFAD3240F08711C2A3505140A0656B7D91B0324038BF28417F505140504CDE0033B33240542E54FEB550514070D6A88768B43240E0A9F23D23515140000341800CB53240D4C1FA3F87515140000341800CB53240FCD8243FE2515140107976F9D6B33240D8AC33BE2F52514060CAA48636B03240808D2441B852514040B60F79CBAD32406CDCD440F352514050BEA08504AC3240546D37C1375351406034D6FECEAA324094205C01855351406034D6FECEAA3240BC378600E05351400088BB7A15AD324018A8FE4124545140A001BC0512B0324048B324404D5451402096CE8767C532401872DEFFC7545140D0C43BC093DE3240E47B0DC171545140E0D03FC1C5E23240A8B393C15154514050ED0DBE30E53240C4438A0112545140702D211FF4E43240F03C635FB25351404031957EC2E53240E8577380605351407055A18158F2324044E603029D525140E0C1FA3F87F9324090F0BDBF41525140F0CDFE40B9FD3240EC482EFF2152514050D8463CD90133407006F1811D525140809065C1C4033340C81C3D7E6F525140809065C1C40333405C34D6FECE525140E0D38041D2F7324030F6D03E56545140206211C30EF332401C9337C0CC5451402083DC4598EA3240E445ED7E1555514020809BC58BD53240C0310400C7555140809FAA4203CD3240A89509BFD455514050B3CEF8BEC83240C43D0801F9555140E046753A90C132408454C37E4F56514030D505BCCCAC32402C14E97E4E575140306C06B820A332403038F581E45751407096E7C1DD9D3240981799805F58514020E44A3D0B763240DCBEB9BF7A5C5140100C040132743240282F3201BF5C5140F05A0A48FB7332402CF911BF625D5140009700FC537632405870784144605140C0F27684D37632407C6649809A60514060B3CEF8BE783240C03AC780EC60514000763579CA7E3240040F45813E61514090FE7A8505AB3240BC28417FA16251400021CB8289D73240E85773806063514060C763062ADB32405C6D37C137635140D059677C5FDC324094DBF63DEA625140100F45813EE93240D4F19881CA5E5140100F45813EE9324070CD8FBFB45D5140C074B0FECFE93240B0B6D4415E5D5140C0FE7A8505EB3240EC45ED7E155D514090ABAE433501334040C269C18B595140106211C30E033340E851F17F475951401096CE8767053340080341800C595140D0EAE5779A183340844B00FE29575140505FD042021E334004D061BEBC56514060CDE50643253340D8B837BF6156514070D9E907752933408CF0BDBF41565140207FF8F9EF2D3340E0AC33BE2F565140D050A4FB393D33405855A18158565140407497C4594133405855A18158565140A01EA33CF34A33406C06F1811D5651400015C78157533340A89509BFD455514070F755B950593340941ADA006C5551403069C537145E3340409E5DBEF55451405037177FDB5F3340580DFB3DB1545140F0264D83A261334058431B800D545140D046753A90613340302CF180B2535140C03A71395E5D334044E603029D525140B0FE7A85055B33405055A18158525140101808026458334058499D80265251407055A18158523340AC9509BFD4515140C057C9C7EE4E3340D8CDFE40B951514080A52C431C473340888AE3C0AB515140C05FE97C78363340DCEE5701BE515140206211C30E3333400C691B7FA2515140C001BC0512303340E85DF58079515140F0CDFE40B92D334090ED7C3F355151408015E0BBCD2B33405C3A58FFE750514020F04E3E3D2A3340C822BF7E88505140B0073E062B2A334098EA3BBF2850514050DEC83CF22B3340A87A32FFE84F5140009D82FC6C303340DCF4D901D74F5140C04E0647C94F3340B8490C022B4E514010857AFA08583340ACA10DC0064E514020301004C8703340281DACFF734E5140F0C77C40A073334048A7203F1B50514080F4143944743340109CFA40F2535140306C06B8207333407C6649809A5451409014AE47E16A3340F054320054565140B050A4FB395D334008D3A23EC957514020F04E3E3D5A334000DFA63FFB575140909FAA42034D3340041808026458514060B3CEF8BE483340B80166BE8358514020F6D03E564433401C66DAFE95585140B0656B7D91403340C022BF7E885851403077D84466363340884E417E36585140B0622AFD842B334070006F810458514050C554FA09273340C0438A01125851406037177FDB1F3340805A457F68585140502E54FEB50033405C3A58FFE75C5140109C508880FF324090ED7C3F355D5140C077F17EDCFE3240D4C1FA3F875D5140E057C9C7EEFE324068D993C0E65D51409018213CDA00334094EA3BBF28605140E03C80457E0133402C232E008D605140B05626FC52173340E0AC33BE2F625140B0FE7A85052B334094DBF63DEA62514020763579CA2E33406CFD2D01F8625140201E8A027D3233405834D6FECE625140206E15C440373340F054320054625140700C1D3BA83C3340DCC1FA3F87615140E028EB37133F3340545260014C61514050B950F9D742334040B665C05961514080992842EA4233406CCD8FBFB4615140D025AAB7063A3340A8A78FC01F645140002A8E03AF363340504F1F813F64514090992842EA323340000C040132645140E03FC1C58A16334090205C0185635140209D82FC6C103340584CDE0033635140E0CDFE40B90D3340E83F6B7EFC625140A074B0FECF0933405076FA415D625140D040F33977073340040682001962514060B08D78B203334018A27C410B625140B001BC051200334040ADA23F3462514040CC423BA7FD3240301DACFF736251409087A2409FF4324008D3A23EC9635140306BD44334F23240C42EC37FBA64514000274D83A2F132409C1ADA006C655140307D5A457FF032405434D6FECE665140A00F5EBBB4F13240D4AF743E3C675140703A58FFE7F4324094DE37BEF6675140808D2441B8FE3240B804A73E90695140002DCF83BB1B3340C82500FF946D514080035ABA822D3340A86E2EFEB66F51400009C380253F3340281A6B7F67715140E0488446B0453340188A743FA7715140901A3048FAB43340FCDEA63FFB735140C03A71395EBD334094DE37BEF6735140C053E57B46C233405837177FDB735140C0B5F63E55C533403CC8EBC1A473514030D2C43BC0C7334070BB09BE6973514040BC9179E4C7334000E869C02073514080116DC7D4C53340583D997FF4715140B004FD851EB53340000341800C6D514030CC423BA7AD334040BCE7C0726B5140C050A4FB39AD33400009C380256B5140206893C327AD3340D0D03FC1C56A5140908461C092AF3340F0818FC18A6A5140F040F33977B73340ACAD11C1386A5140100F45813EB93340543D997FF4695140C074B0FECFB933409426DE019E695140708AE3C0ABB933405C3A58FFE7685140A04D637B2DB83340E878CC4065675140A0F27684D3B633403CE603029D665140107976F9D6B33340AC74B0FECF655140306BD44334B23340845D86FF74655140D04543C6A3A033404C0DFB3DB1605140F040F33977873340D8C1FA3F8759514010857AFA0888334028ED0DBE30595140F099417C608B3340505260014C5951409096E7C1DDAD3340C41F7EFE7B5B51406037177FDBAF33406CD311C0CD5B5140102A8E03AFB63340ACAD11C1385E5140B05626FC52B7334044E603029D5E514010857AFA08B83340901799805F60514040DB87BCE5B63340DCC1FA3F87615140E05A0A48FBD33340D4CDFE40B96D5140C0656B7D91F033405C76FA415D725140D05D4BC807F93340B0AD11C138725140A015E0BBCD0B3440E84B6F7F2E735140E05A0A48FB133440E83C2AFEEF75514030DB87BCE5263440A86E2EFEB67B5140E03730B9512834406CDF15C1FF7B5140B04D637B2D483440EC543200547E5140C0622AFD844B344048ADA23F347E51409096E7C1DD4D3440C03D0801F97D5140F03C80457E513440901ADA006C7D5140306C06B820633440DCB837BF617A5140F0058200196A3440407D04FEF0785140D059677C5F6C344030F6D03E5678514030D505BCCC6C344044C8EBC1A4775140307A19C5726B3440546D37C137775140200C0401326434408093A641D1745140E025AAB7065A3440000C040132705140C0488446B055344014967840D96D5140901A3048FA5434407C5D86FF746D5140A0ABAE4335513440FCE769C0206B514050C763062A4B34401472DEFFC7645140A0E0F082884834403035B401D85E5140F0D38041D2473440241DACFF735E514050ED0DBE304534409026DE019E5D514040D8463CD941344068F7AB00DF5C514020301004C8303440D4EE5701BE59514060BEA085042C3440980ED6FF3959514050D9E90775193440A86E2EFEB657514070AD4CF8A50E3440AC984A3FE1565140C03DB2B96A0234408CF0BDBF41565140B06E2EFEB6FF334094E4B9BE0F565140F03A71395EFD334028327381CB555140209A417C60FB3340F05DF5807955514000904C874EEB3340DCEE5701BE5151402083DC4598EA334044B665C0595151407081204086EA3340B09ECC3FFA50514050E78BBD17EB33406CCA4E3FA8505140405FD04202EE3340E87B0DC171505140D03DB2B96AF23340001808026450514020E44A3D0B063440E884D04197535140C0B837BF610A3440980B957F2D54514040CC423BA72D3440F084D04197575140F0D03FC1C532344054431B800D58514070116DC7D4353440884E417E3658514060DC2A88814E34403029B000A65A514070B950F9D7523440C0378600E05B514070C763062A5B3440B4490C022B5E5140D03FC1C58A76344040BF28417F645140504F1F813F7834406CF7AB00DF64514050BEA085047C3440BC3AC780EC6451406040DAFF007F34405C2E54FEB5645140909065C1C4833440F04EB0FF3A645140306E15C440873440C02B82FFAD635140101286014B8E34406CFD2D01F8625140E04334BA839C3440F8D8243FE261514000301004C8B03440242F3201BF60514060D6A88768B4344098239D8191605140B0E9B303AED7344090E7FA3E1C5F5140F0B837BF61DA34403014E97E4E5F51408081204086DA34405C2B137EA95F51408093A641D1D83440149CFA40F25F514080992842EAD2344034172AFF5A605140C0F5B704E0AB3440DCBB783F6E63514030CF83BBB3823440C41F7EFE7B675140505FD042027E344094DE37BEF667514000917EFB3A7C3440EC4EB0FF3A68514020E78BBD177B3440C822BF7E88685140F0AF743E3C7B3440F039E97DE36851409018213CDA903440C42EC37FBA70514000763579CA9E3440C446CB811E715140D0488446B0B5344040A19E3E02725140F0B5F63E55C53440D4D03FC1C5725140109A417C60CB3440804B00FE2973514050B60F79CBCD3440D8BB783F6E7351407040DAFF00CF3440D4C77C40A073514040EACC3D24D0344094DE37BEF673514080FDD7B969D33440C046CB811E755140D0DDAF027CD33440E85DF58079755140406211C30ED3344030327381CB75514060B81E85EBD134400806820019765140700C1D3BA8CC344098DBF63DEA765140D0622AFD84CB3440546D37C13777514020990F0874CA344094205C01857751403083DC4598CA3440C0378600E0775140A09FAA4203CD344018A8FE412478514040DB87BCE5E634408096E7C1DD79514090F1D3B8370F354028232E008D7C514030CF83BBB312354070CA4E3FA87C514060BB5F05F816354040BF28417F7C5140F040F33977173540940B957F2D7C5140D0B5F63E551535405C37177FDB7B5140109D82FC6C1035400015C781577B514020CC423BA70D35400809C380257B5140B05626FC520735402C35B401D87A5140800F5EBBB4013540C41C3D7E6F7A5140A0F1D3B837FF3440C0490C022B7A5140A06BED7DAAFA344030266F809979514060CDE50643E53440A86BED7DAA765140B0716F7EC3E434405876FA415D76514070C2137AFDF1344068DF15C1FF73514030CC423BA7FD3440C01C3D7E6F7251400000000000003540DCAC33BE2F725140503A58FFE704354090E4B9BE0F725140C0622AFD840B35408054C37E4F725140C050A4FB390D3540186C5CFFAE725140206211C30E23354070C70DBF9B77514030F04E3E3D3A35409C111780467E5140007FF8F9EF3D35403020ED7F807F514060D367075C3F3540A87A32FFE87F51401082397AFC423540C40166BE8380514060AD4CF8A54E3540885182FE42815140C0EF3504C75135409C1ADA006C815140007CB779E358354028266F8099815140D04543C6A360354008CD203EB081514020068200196A3540F07E4E417E815140307497C459713540C046CB811E8151402069C537148E3540FCDB65BFEE7E514020068200199A354004E2E7BF077D51403083DC45989A35405C2E54FEB57C5140F072F4F8BD993540B0B393C1517C5140604F1F813F9835403038F581E47B514020895E46B1943540844B00FE297B51405031957EC2953540A877F17EDC7A5140D04E0647C99F354068FAEC80EB795140505FD04202AE35407C93A641D178514000274D83A2B13540EC8711C2A3785140D0AC33BE2FB6354098239D8191785140E0C43BC093BE3540C422BF7E887851402077D84466C63540040C04013278514030E78BBD17CB3540302CF180B2775140D02B2CB81FE43540109F3BC1FE7451409014AE47E1EA3540A87A32FFE8735140A0E3310395ED3540941458005373514030DB87BCE5F63540545260014C71514060D026874FFA3540888461C0926F5140109A417C60FB354044B0E3BF406F5140207CB779E30836401899B9C0E56E5140E046753A901136405834D6FECE6E514050BC9179E417364098E7FA3E1C6F5140E025AAB7061A364074BB09BE696F514020F04E3E3D1A3640809065C1C46F5140B074B0FECF19364040A7203F1B705140C07A32FFE803364068D993C0E67551407009DCBA9BE73540940B957F2D7C5140C0A6B1BD16CC354058499D8026825140705260014CCD3540186058FE7C825140D04E0647C9CF3540FCCF61BEBC825140A0E67283A1D2354004DC65BFEE82514030F911BF62D93540E84B6F7F2E835140D05A0A48FBE3354040BCE7C07283514020904C874EFB35401C63997E89835140F03DB2B96A023640AC6E2EFEB6835140B068ACFD9D0536405437177FDB835140406552431B08364044A7203F1B84514040D2C43BC0173640A8AD11C138865140E0C1FA3F871936405440DAFF0087514050B3CEF8BE18364044B0E3BF4087514040809BC58B153640D8AF743E3C875140C0C43BC0930E36408060C77F81865140C059677C5F0C3640F054320054865140E04334BA83FC354068C18BBE8285514050C422861DF635409C0ED6FF39855140B001BC0512C03540E884D0419783514080A86DC328BC35407C6308008E835140306E15C440B73540C82B82FFAD835140E0AF743E3C7B35407006F1811D8651408093A641D17835405476FA415D86514080A52C431C773540C028417FA186514040E44A3D0B76354000DC65BFEE865140D057C9C7EE6E35406803B0011189514090F414394454354048ADA23F348A514030F38FBE494F3540EC543200548A5140402B137EA94B35407C60C77F818A5140A0F27684D3463540E43F6B7EFC8A514020F6D03E56343540447D04FEF08C5140303EE944823535400851F701488D5140E03FC1C58A363540185D177E708D514050D9E90775393540208A743FA78D5140D074CC79C63E35400C3C3080F08D514050D505BCCC4C35406CD311C0CD8F5140F00B0401328435403CBCE7C07293514020809BC58B953540C4FE243E77935140F0B5F63E5595354090E7FA3E1C93514090AEEFC341963540C81C3D7E6F925140E036FE446597354054499D80269251400088BB7A159D3540189F3BC1FE905140D0BB783F6E9F3540282F3201BF905140101E8A027DA23540C422BF7E889051409014AE47E1BA3540504CDE00338F514070DC2A8881CE354094E7FA3E1C8F51405069C53714CE3540D8BB783F6E8F514070DC2A8881CE354094EA3BBF289051408021E4BCFFCF354098239D8191905140306BD44334D23540F039E97DE3905140406E15C440D7354028F911BF62915140F005820019FA354048B324404D945140705260014CFD3540F07B0DC171945140A0F8F884EC003640C022BF7E88945140E036FE44652736407006F1811D92514050D026874F3A364038B9A6406692514040B950F9D74236405476FA415D925140D0393FC5714C3640C0490C022B925140F0BB783F6E4F36405C3D997FF4915140E0A9F23D23513640888AE3C0AB9151409018213CDA5036405C73B9C150915140A05626FC5247364068C70DBF9B8B5140206552431B583640040F45813E895140E03730B9518836402C2CF180B287514060B5DD04DF8C36406CC70DBF9B87514010763579CA8E3640D4F4D901D7875140E0CDFE40B98D364014A8FE4124885140109A417C608B36400418080264885140F05147C7D58436401C9337C0CC88514010000000008036401060CAC00189514060BFD2F9F07C3640DCA9F23D23895140F034EF384563364000068200198A514020990F08745A3640E0AC33BE2F8A5140F0AC33BE2F5636405855A181588A5140F07876F9D65336403CC5AA41988A514060431B800D54364070DCD440F38A5140A0C2F4BD86603640AC7D737FF58F5140101E8A027D623640804E417E3690514040C422861D66364040B324404D905140F0B837BF616A3640D4B2B5BE489051401000000000803640B0A78FC01F905140801A3048FA843640FCDEA63FFB8F514040C422861D963640546D37C1378F514060465C001A993640EC3F6B7EFC8E5140002F6D382C993640808D2441B88E5140A014AE47E1AA36402CF04E3E3D8E51407093A641D1D83640805D86FF748D5140C03A71395EDD36402CF911BF628D514070FA96395DEE3640505260014C8D51401015C78157F3364040AA61BF278D514020DB87BCE5F63640A49ECC3FFA8C5140200F45813EF93640C02EC37FBA8C514030F04E3E3DFA3640E85AB4006D8C514090F755B950F93640E842ACFE088C514020809BC58BF536402814E97E4E8B5140A07A32FFE8E336403C7D04FEF0885140B004FD851ED536409814580053875140D053E57B46D2364004E869C020875140A015E0BBCDCB36403035B401D8865140C0E0F08288B836408854C37E4F865140800F5EBBB4913640981ADA006C855140D0548847E289364040B665C059855140C0B5F63E55853640145D177E7085514070B5DD04DF7C3640E85DF58079855140305C8FC2F5783640145D177E7085514030D8463CD9713640845182FE42855140207A19C5726B3640AC9ECC3FFA845140002C2CB81F54364040BCE7C07283514080FA96395D4E36403C8386FE098351408015E0BBCD4B3640D4F19881CA825140A08AE3C0AB493640186058FE7C82514050DEC83CF24B364028F04E3E3D8251405037177FDB4F36409811178046825140206211C30E533640A8B915C26A825140602B137EA95B3640C04049810583514080A2EBC20F6236403014E97E4E83514040B950F9D7723640A47A32FFE883514080035ABA827D3640980B957F2D8451401000000000803640C02BF4C132845140B0F8F884EC90364030F6D03E56845140201808026498364070BE4A3E768451407028D2FD9CA636407C93A641D1845140D0B2B5BE48D03640B0A10DC0068651408096E7C1DDDD3640146058FE7C865140F0A9F23D23E13640C028417FA18651409096E7C1DDFD36401C8A743FA7855140502B137EA90B3740805D86FF74815140D06BED7DAA2A3740545260014C7D51405037177FDB4F3740884E417E367C5140F0D03FC1C5523740805A457F687C514060BB5F05F87637402835B401D87E5140E0C1FA3F877937400CA5BDC1177F514040F911BF62893740EC45ED7E15815140F0170802648837402CF911BF62815140F05147C7D5843740C02500FF94815140E0B2B5BE48803740208A743FA78151401021CB8289773740C4310400C78151400029EB37136F3740B09509BFD4815140A09065C1C463374008CD203EB0815140908461C0925F374070CD8FBFB481514090FE7A85055B374030327381CB81514090129F3BC1563740543D997FF4815140604CDE003353374058499D8026825140C0E67283A1423740884B00FE2983514030861DC6A43F3740EC5773806083514020E78BBD173B3740C0378600E083514040BFD2F9F02C374004CD203EB0855140D0C43BC0932E3740B83D0801F9855140D068ACFD9D4537401899B9C0E586514040BFB67EFA5737402496067E54875140F0420246975B3740A8B6D4415E89514080992842EA523740080C0401328C514090716F7EC35437409CE4B9BE0F8E51408018213CDA603740FC058200198E5140C0656B7D9180374064FD2D01F88E5140801A3048FA84374048B0E3BF408F514070BC9179E487374040BCE7C0728F5140801A3048FA843740C82B82FFAD8F514040DB87BCE5763740FCDEA63FFB8F5140C053E57B4672374050431B800D90514090FA96395D6E3740F042ACFE0890514020E78BBD176B37402838F581E48F514060B3CEF8BE683740D0C1FA3F8791514050C554FA09773740A89B8BBFED935140901B62BCE695374028232E008D985140D0B5F63E55A53740FC058200199A514060BB5F05F8A6374088812040869A5140305C8FC2F5A83740B4984A3FE19A51406040DAFF00CF3740B0984A3FE19E5140A00F5EBBB4D1374004E869C0209F5140B06BED7DAADA37402C2CF180B29F5140603A58FFE7E4374058431B800DA051408081204086FA37407C6649809AA05140506C06B8200338402C232E008DA0514040D2C43BC00738406CBE4A3E76A05140C0656B7D91403840D4F19881CA9E514030D2C43BC047384038B9A640669E514040CC423BA74D38405C3D997FF49D5140B0F8F884EC5038402C1A6B7F679D5140504CDE00335338403CAA61BF279D5140D040F33977573840B09ECC3FFA9C514030E78BBD175B3840040341800C9D514090A86DC3285C3840145D177E709D514050C763062A5B3840DCEE5701BE9D514090992842EA42384094239D8191A05140C0656B7D9140384000D6E3BED5A05140B06BED7DAA3A3840EC51F17F47A15140D0488446B0353840941ADA006CA1514050D2C43BC027384030172AFF5AA45140102DCF83BB4B3840D0D03FC1C5AA5140207976F9D65338402820ED7F80AB514070BFD2F9F05C3840C4438A0112AC5140D0548847E2793840E857738060AB5140107D5A457F80384070FD2D01F8AA5140809065C1C48338403CB9A64066AA514030861DC6A49F38401C90F63FC0A7514030809BC58BA538403414E97E4EA7514050499D8026AE384018A5BDC117A7514050D8463CD9B138407C4B00FE29A7514030ED0DBE30B538403414E97E4EA75140604F1F813FB838402C20ED7F80A75140D06BED7DAABA38406CD311C0CDA7514050BEA08504BC3840B0A78FC01FA85140306893C327BD38401072DEFFC7A8514050B5DD04DFBC3840BC46CB811EA9514090FE7A8505BB3840D8CDFE40B9A95140D0D38041D2B73840001286014BAA51402082397AFCB23840F8E769C020AB51409017EFC7ED8F384028F38FBE49AF5140307156444D8C3840C81F7EFE7BAF51409009DCBA9B873840848461C092AF51409014AE47E17A38406CC70DBF9BAF5140A04D637B2D68384094DE37BEF6AF5140000C040132643840C0438A0112B051406031957EC2453840A89ECC3FFAB05140008BFCFA2142384028ED0DBE30B15140E04E0647C93F3840185D177E70B151409077F17EDC3E3840D4EE5701BEB15140D046753A9041384090ED7C3F35B55140C05A0A48FB43384068C18BBE82B5514040C554FA0947384070CD8FBFB4B55140001E8A027D6238406CBB09BE69B7514040DB87BCE5663840F078CC4065B75140A0E0F0828868384090E7FA3E1CB75140E0C1FA3F876938405C34D6FECEB65140C074B0FECF6938409C1D1B8178B6514020F911BF626938407006F1811DB65140A009DCBA9B773840D8B2B5BE48B451404083DC45987A384050431B800DB45140F040F339779738406806F1811DB2514060499D80269E384008CD203EB0B15140001E8A027DA23840148A743FA7B1514070A7CAF78CA43840ACA10DC006B25140D0B5F63E55A5384000D061BEBCB25140C05147C7D5A43840E478CC4065B35140007976F9D6A33840242CF180B2B35140502B137EA99B38405C34D6FECEB65140506C06B820933840D0D38041D2BB51407031957EC2953840A4B6D4415EBD51401021CB828997384010691B7FA2BD5140007CB779E3A838402CF04E3E3DBE514050BFD2F9F0AC38409C11178046BE5140C004FD851EB538408054C37E4FBE5140F0CABDC0ACC838401C967840D9BD514000990F0874DA3840CCB22781CDBB5140D0A6B1BD16DC3840144240BE84BB5140809FAA4203DD3840D48E1B7E37BB514040DEC83CF2DB384028145B41D3BA5140E0C1FA3F87D9384070A3737E8ABA5140E0A9F23D23E1384064C43E0114BA5140A0E0F08288F8384030F04E3E3DBA514000917EFB3AFC38408454C37E4FBA5140201B498270FD3840805A457F68BC514090035ABA82FD3840540DFB3DB1BC5140C050A4FB39FD384098E1783E03BD5140502B137EA9FB3840505260014CBD514080F755B950F9384040C269C18BBD51401018080264F8384080758E01D9BD5140F0C1FA3F87F93840F8AE7AC03CBE514060BFD2F9F0FC38405876FA415DBE51402000000000003940086F0F4240BE5140901A3048FA0439403C80457EFDBD5140A09C69C2F6073940C8310400C7BD514040CAA486361039406403B00111BD5140100F45813E29394040E603029DBA5140E040F33977373940E47B0DC171B85140E05D4BC80739394094EA3BBF28B85140F04334BA833C3940B0B0524145B75140A017EFC7ED3F3940DCB837BF61B651409018213CDA40394098E4B9BE0FB6514080992842EA423940BC46CB811EB55140406C06B820433940149337C0CCB4514080992842EA42394048A7203F1BB45140201E8A027D4239401C90F63FC0B3514090A52C431C473940EC57738060B351408000193A7658394048A7203F1BB45140E02B2CB81F643940849065C1C4B75140901A3048FA643940D8BEB9BF7AB8514070A7CAF78C643940DCA9F23D23B9514090F8F884EC6039405C76FA415DBA5140F0A6B1BD165C3940584CDE0033BB51409074B0FECF593940C4FE243E77BB5140809C69C2F6573940C0438A0112BC5140B0F27684D3563940582E54FEB5BC51404028D2FD9C56394004E2E7BF07BD514060C554FA0957394030F911BF62BD5140207CB779E3583940AC74B0FECFBD5140502B137EA95B394014A27C410BBE5140F04E0647C95F39409CE4B9BE0FBE5140B0716F7EC364394070FAEC80EBBD51407000193A76683940D0CDFE40B9BD5140207497C45971394004E2E7BF07BD51405028D2FD9C76394028232E008DBC514040CF83BBB38239402C14E97E4EBB5140106E15C4408739405834D6FECEBA51408093A641D18839408481204086BA51402083DC45988A394070D993C0E6B95140D034EF3845A33940E445ED7E15B95140A0FE7A8505DB394098ED7C3F35B95140D0DA6E826FDE39402CED0DBE30B9514040C422861DE6394090E1783E03B951402018080264E83940242F3201BFB8514000240C0396EC3940846308008EB75140001B498270ED3940DCAF743E3CB75140207156444DEC3940AC77F17EDCB65140A074B0FECFE939406CC4CC3E8FB65140A0ECF483BADC394030ED0DBE30B55140703D997FF4D93940407D04FEF0B4514060C422861DC639409014580053B351409017EFC7EDAF3940D8C1FA3F87B15140A009DCBA9BA73940448386FE09AF514030D2C43BC0A739401C8DB5BFB3AE514090FB3905F9A53940FC1186014BAE5140F07876F9D6A33940F03C2AFEEFAD5140207497C459A1394014691B7FA2AD514070BB5F05F88639405440DAFF00AB5140F0AF743E3C5B3940D8F19881CAA65140A09C69C2F6373940848461C092A35140703A58FFE7343940E878CC4065A351400073F4F8BD193940409E5DBEF5A0514050BB5F05F81639405C2E54FEB5A051408087A2409F143940845A457F68A0514060B950F9D71239400800000000A051405031957EC2153940809065C1C49F514040F911BF62193940D8F4D901D79F514080A52C431C273940A4B393C151A0514050CAA4863630394070F7AB00DFA051406055A18158423940B0B05241459F514090716F7EC3443940B8490C022B9A5140009700FC534639406CD993C0E6995140A01B62BCE6453940D4C1FA3F87995140002C2CB81F443940C046CB811E995140900F5EBBB44139408093A641D198514080FA96395D3E3940540DFB3DB198514000990F08743A39408093A641D1985140E034EF3845333940EC45ED7E15995140A021E4BCFF2F3940940ED6FF3999514070F41439442439407C5A457F6898514070C554FA091739400409C38025975140F0B5F63E5515394004D061BEBC96514020990F08741A3940F07B0DC17194514060BEA085041C394090EA3BBF289451408021E4BCFF1F3940980B957F2D9451401082397AFC2239409C1799805F945140A053E57B46223940FCD8243FE2915140901A3048FA043940EC577380608F514060BFD2F9F0FC38402C29B000A68E51407014AE47E1FA3840041286014B8E5140B0F27684D3F638407C5A457F688C5140A053E57B46F238405431957EC2895140D03C80457EF13840FC0241800C89514010301004C8F0384094111780468651401094BF7B47F138409026DE019E85514050B950F9D7F23840D8B5F63E55855140F02CCF83BBFB3840A8B393C15184514020000000000039409C1A683EE783514000301004C8003940D8F4D901D7835140D0B5F63E550539401C90F63FC0835140107CB779E3083940D4D38041D2835140D0420246970B3940C4438A011284514050AD4CF8A50E39401048FB1F60855140D0D7497D590E39405CA0DD21C58551405096E997880B394048D13C8045865140107CB779E30839402C0516C09486514020C30E63D2073940607C0A80F1865140401D739EB10739400809C38025875140B0D6A546E80739407C5704FF5B875140002522FC8B083940C0E68EFE97875140D05B04C6FA0A3940BCFB5580EF875140C05B59A2B310394088936DE00E895140C0E9B303AE173940941ADA006C895140C0FB3905F91539409CE1783E038951400043908312163940F48D5A61FA875140C00DBF9B6E153940B0FECF61BE875140C0B94E232D153940B4D172A087875140C0D0B1834A183940F4CF0CE203865140F05FE7A6CD1839404404E3E0D2855140A00C1D3BA81C3940583A58FFE7845140B0716F7EC3243940F039E97DE38451402018080264283940449E5DBEF5845140D0A6B1BD163C3940DCEE5701BE855140C05CA8FC6B41394024F04E3E3D865140207976F9D6433940F0818FC18A865140D0B5F63E55653940582E54FEB58C5140D0DDAF027C833940583A58FFE79051402077D844668639406CCD8FBFB49151402021CB828987394000E528401492514030F911BF62893940CCD03FC1C5925140405C8FC2F5883940D4BB783F6E935140F09FC37C7985394044C8EBC1A4935140D050A4FB397D3940582B137EA9935140200C04013274394004DFA63FFB935140808D2441B86E3940F817080264945140C04334BA836C3940E88711C2A394514080FA96395D6E3940D4B5F63E55955140D034EF3845733940EC54320054965140A01B62BCE6753940186C5CFFAE965140007CB779E3783940A877F17EDC965140306C06B820833940189CFA40F2975140000341800C953940F0482EFF219A5140107156444DCC394050465C001AA1514070069B3A8FF23940E851F17F47A55140D0B5F63E55F539406CC18BBE82A55140406552431BF839405C31957EC2A55140F04E0647C9FF394044C5AA4198A6514070C2137AFD013A4070DCD440F3A65140406C06B820033A409C14580053A75140A0AEEFC341063A40E0A9F23D23A95140A0129F3BC1063A40EC7E4E417EA951402069C537143E3A407C81204086B25140503D997FF4593A40241DACFF73B6514060AD4CF8A55E3A4090E7FA3E1CB75140B0FB3905F9853A4040B0E3BF40BB5140502B137EA98B3A40A86E2EFEB6BB514070C2137AFD913A40C464E3C116BC5140007FF8F9EFAD3A4004E2E7BF07BD514010274D83A2B13A403C9E5DBEF5BC514050465C001AB93A40ACB0524145BB5140503D997FF4B93A406CFD2D01F8BA514050BEA08504BC3A4040B665C059B95140702E54FEB5B03A4010A5BDC117AF5140D0BB783F6EAF3A401C8DB5BFB3AE5140A0FE7A8505AB3A4044A19E3E02AE5140009700FC53A63A4040B665C059AD5140502E54FEB5A03A40EC39E97DE3AC514000990F08749A3A40BC0166BE83AC5140A018213CDA903A40F042ACFE08AC5140F025AAB7068A3A4000D3A23EC9AB5140307A19C5727B3A403CBCE7C072AB5140503A58FFE7743A40F8E769C020AB5140F057C9C7EE5E3A406CFAEC80EBA95140808AE3C0AB593A4028F911BF62A9514040D2C43BC0573A40B09ECC3FFAA85140503D997FF4593A40542E54FEB5A85140201286014B5E3A40D4CABDC0ACA85140A000193A76683A40040341800CA9514080A2EBC20F723A403CC269C18BA95140B06E2EFEB67F3A4010A27C410BAA514070FDD7B969833A407006F1811DAA5140207A19C5728B3A4058499D8026AA5140801A3048FAA43A4030ED0DBE30A95140008E3D7B2EA73A40C43AC780ECA85140C05626FC52A73A40806649809AA85140A0129F3BC1A63A40544F1F813FA85140D0AF743E3C9B3A40981D1B8178A25140D05D4BC807993A40E8482EFF21A25140D031AEB8388E3A402838F581E49F5140E0C77C40A0833A403CC8EBC1A49B5140206C06B820833A4030F38FBE499B5140D0A9F23D23813A40848461C0929751401094BF7B47813A40D4AF743E3C97514070F4143944843A40AC6BED7DAA96514080A52C431C873A40C41C3D7E6F96514020DEC83CF28B3A409C1117804696514030861DC6A48F3A405855A18158965140E03DB2B96A923A40D0C43BC093965140C0656B7D91A03A405C37177FDB975140A0A2EBC20FC23A40F03F6B7EFC9A5140209A417C60CB3A40D4B2B5BE489C5140505260014CCD3A40500DFB3DB19C514050B60F79CBCD3A40040341800C9D5140F0CDFE40B9CD3A404480457EFD9D5140B059677C5FCC3A40F0818FC18A9E5140D040F33977D73A4070D0D03FC19E5140206893C327ED3A409C1D1B81789E514070F755B950F93A40900ED6FF399D51400021CB8289073B405055A181589E5140A0E3310395FD3A40805182FE42A15140A08AE3C0ABF93A406C006F8104A45140E0C1FA3F87F93A4028F6D03E56A45140206211C30E033B4010691B7FA2A55140D057C9C7EE0E3B40ACA44E4013A75140B053E57B46123B4044A4DFBE0EA751404028D2FD9C163B40E8818FC18AA6514050D9E90775193B408054C37E4FA65140D0A6B1BD163C3B40885182FE42A5514080A7CAF78C443B4004E2E7BF07A55140C0716F7EC3443B405473B9C150A5514080069B3A8F423B40BC04A73E90A55140307A19C5723B3B40E854320054A651406031957EC2353B40D8F19881CAA6514020A0C37C79253B402C38F581E4A75140C068ACFD9D153B401872DEFFC7AC514050DB87BCE5163B4048AA61BF27AD5140F04BC5C6BC1A3B40C43D0801F9AD514050B81E85EB213B40D8AF743E3CAF5140A09065C1C4233B403020ED7F80AF5140406E15C440273B40D4C77C40A0AF51402094BF7B47413B40189CFA40F2AF5140C0D38041D2473B4028ED0DBE30B151409000193A76483B4040C269C18BB151409096E7C1DD4D3B40C064E3C116B45140F008C380254F3B40DCBEB9BF7AB45140A00F5EBBB4513B40A4716F7EC3B451407031957EC2553B401072DEFFC7B4514010068200195A3B40C02EC37FBAB4514010240C03966C3B409C0B957F2DB45140A09065C1C4833B403CC8EBC1A4B3514000301004C8903B402C20ED7F80B3514090E67283A1823B40884B00FE29B751405031957EC2753B4058431B800DB8514070C2137AFD613B40E84EB0FF3AB85140F008C380254F3B409C1799805FB8514090129F3BC1463B40845A457F68B85140208BFCFA21423B40BC0166BE83B8514060A7CAF78C343B40583A58FFE7B85140800C1D3BA82C3B405873B9C150B95140B074B0FECF293B4044C269C18BB95140001E8A027D223B40FC1186014BBA5140209C5088801F3B40A877F17EDCBA514060D367075C1F3B40584CDE0033BB514040B950F9D7223B40D0B5F63E55BD5140D02E6D382C393B4090ED7C3F35C15140102DCF83BB3B3B4068C18BBE82C15140208BFCFA21423B408096E7C1DDC15140901B62BCE6453B40E83C2AFEEFC1514000A0C37C79753B40E45AB4006DC051402073F4F8BD793B40584F1F813FC05140000341800C853B40C422BF7E88C45140D0488446B0853B40EC39E97DE3C45140809C69C2F6873B40040F45813EC55140502E54FEB5903B40F03C2AFEEFC55140B0F27684D3A63B40D8AF743E3CC7514050E78BBD17BB3B40C82500FF94C55140D0BEB9BF7AC43B403014E97E4EC35140908D2441B8DE3B4098E4B9BE0FC2514050B950F9D7E23B4098E4B9BE0FC25140306E15C440F73B401C99B9C0E5C2514000990F0874FA3B40ACA44E4013C3514080A2EBC20F023C4064DF15C1FFC3514070BC9179E4073C4070BE4A3E76C4514030ED0DBE30353C40BC46CB811EC5514060D9E90775393C40C03AC780ECC45140307156444D3C3C404C0DFB3DB1C45140C0DA6E826F3E3C40EC5AB4006DC45140407497C459413C405437177FDBC3514050B950F9D7423C40DCAF743E3CC3514070992842EA423C401C99B9C0E5C25140A09C69C2F6573C40844E417E36C05140502E54FEB5603C4048A7203F1BC0514050D2C43BC0773C4068C70DBF9BBF5140900C1D3BA87C3C40D8BB783F6EBF5140D0BEB9BF7A843C40C440498105BF514000068200198A3C40E8818FC18ABE514020917EFB3A8C3C409C11178046BE5140809FAA42038D3C40C03D0801F9BD5140E0CABDC0AC883C40F04EB0FF3ABC514060CDE50643853C4098E7FA3E1CBB5140F046753A90713C4040A4DFBE0EB75140505260014C5D3C40A4716F7EC3B45140D0DDAF027C433C40C428417FA1B25140B0656B7D91403C4040B9A64066B25140E03A71395E3D3C40B0AD11C138B25140908AE3C0AB393C4050499D8026B25140D034EF3845233C40EC3C2AFEEFB15140200C040132043C4048E603029DB25140107497C459013C402835B401D8B2514060B5DD04DFCC3B40AC6BED7DAAB25140E02E6D382CC93B4048E603029DB25140F0488446B0C53B401C6058FE7CB25140406C06B820C33B4044ADA23F34B25140007976F9D6C33B4000D9243FE2B1514050431B800DD43B40C046CB811EB151401082397AFCE23B40F439E97DE3B0514050DEC83CF2EB3B40C42EC37FBAB05140F087BB7A151D3C405C6D37C137AF5140D0656B7D91203C405C40DAFF00AF5140A00F5EBBB4213C40D8D03FC1C5AE514030EACC3D24203C402C1DACFF73AE514060B60F79CB1D3C400406820019AE514050E44A3D0B163C409C0ED6FF39AD5140504CDE0033133C40149F3BC1FEAC5140908AE3C0AB093C406CBE4A3E76AC5140B0E9B303AED73B4018691B7FA2A95140D0EAE5779AA83B4068FD2D01F8A651405031957EC2A53B4000D061BEBCA65140603D997FF4A93B4070C4CC3E8FA65140B0FB3905F9B53B40CCC43BC093A6514050CC423BA7BD3B403029B000A6A6514040DEC83CF2CB3B405840DAFF00A7514090AEEFC341D63B40EC57738060A7514000301004C8203C40106C5CFFAEAA514070D026874F2A3C40546D37C137AB5140406893C3272D3C403CBCE7C072AB5140E04E0647C92F3C40146F9D7FBBAB514080A2EBC20F323C40C864E3C116AC514060431B800D343C4040BF28417FAC51402077D84466363C4000D6E3BED5AC5140E0488446B0453C40B49509BFD4AD514030F911BF62493C4004D9243FE2AD5140C0622AFD844B3C409826DE019EAD514000917EFB3A4C3C405873B9C150AD5140909FAA42034D3C40D0CABDC0ACAC5140206893C3274D3C40C42B82FFADAB5140503D997FF4493C4068D993C0E6A95140D0EAE5779A483C4068C18BBE82A951407028D2FD9C463C40BC46CB811EA9514060CAA48636403C4090DE37BEF6A75140007FF8F9EF3D3C4068C70DBF9BA75140C05D4BC807393C4068FD2D01F8A65140F093BF7B47313C406806F1811DA65140102A8E03AF263C4098E1783E03A551400094BF7B47213C40D4BEB9BF7AA4514020F38FBE49FF3B4014691B7FA2A1514070AA0B7899F93B40B0AAD0402CA15140F0A9F23D23F13B407C6649809AA05140A014AE47E1EA3B40504F1F813FA05140A001BC0512E03B401C63997E899F5140109A417C60DB3B403C8386FE099F51400026AAB706DA3B402829B000A69E51404084807C09E13B40784B72C0AE9C514080129F3BC1E63B40D4B2B5BE489C514010F911BF62F93B40186058FE7C9E5140702E54FEB5103C40D4BB783F6E9F5140C0FE7A85051B3C40FCD2A23EC99F514090116DC7D4253C40EC42ACFE08A05140B050A4FB392D3C4018A8FE4124A0514080AD4CF8A52E3C405437177FDB9F5140D0A6B1BD162C3C40888461C0929F5140E03DB2B96A223C4090E7FA3E1C9F514090A86DC3281C3C4070D0D03FC19E51404077D84466163C40001286014B9E5140908D2441B80E3C40981ADA006C9D5140F0393FC5710C3C406C03B001119D514090812040860A3C4068CA4E3FA89C514090812040860A3C4024F6D03E569C514020904C874E0B3C4068006F81049C5140E03A71395E0D3C40849065C1C49B514060AD4CF8A51E3C40D4D38041D29B5140F03C80457E213C4050431B800D9C5140C0DDAF027C233C4070BE4A3E769C514050868E1D54263C4020C3D501109D514020E5D2F885273C40A883BC1E4C9D514040CC423BA72D3C40001286014B9E5140109A417C603B3C409C1799805FA051409096E7C1DD4D3C40D0CABDC0ACA05140E046753A90513C40C82EC37FBAA0514040ED0DBE30553C4064CA4E3FA8A05140801B62BCE6553C4034172AFF5AA0514070A7CAF78C543C4098DE37BEF69F5140A0069B3A8F523C40888461C0929F5140201286014B4E3C405C34D6FECE9E514060C1E10511413C408487A2409F9C5140F093BF7B47313C4040A19E3E029A514000904C874E2B3C401472DEFFC7985140F036FE4465273C4040C8EBC1A4975140E040F33977273C40E43F6B7EFC96514050B3CEF8BE283C402C29B000A68E51401073F4F8BD293C4098E1783E038D51403069C537142E3C40804B00FE298B5140E0BB783F6E2F3C40AC984A3FE18A5140708461C0922F3C4048ADA23F348A5140E057C9C7EE2E3C4010967840D9895140E0B837BF612A3C4030172AFF5A885140A000193A76283C401C9CFA40F287514070C2137AFD213C403035B401D886514010904C874E1B3C40A874B0FECF855140202A8E03AF163C4098ED7C3F35855140603D997FF4093C409CDE37BEF683514070ABAE4335113C40C4438A0112845140A087A2409F143C40040C04013284514010068200191A3C40C422BF7E8884514030861DC6A41F3C40189F3BC1FE845140206BD44334223C40EC51F17F47855140107CB779E3283C40F05432005486514050CF83BBB3323C402CF6D03E56885140A0073E062B3A3C40A4AD11C1388A5140307A19C5723B3C403CC5AA41988A5140307A19C5723B3C40FCDB65BFEE8A5140206E15C440373C4004D3A23EC98B514080992842EA323C4010691B7FA28D5140B0F8F884EC303C406CFAEC80EB9151409018213CDA303C4090F0BDBF4192514060D9E90775393C40503A58FFE7985140307A19C5723B3C40208A743FA7995140901A3048FA543C405055A181589E5140A01EA33CF37A3C4040B324404DA851407055A18158823C40546D37C137AB5140108E3D7B2E873C40B0AAD0402CAD5140D0488446B0853C4028327381CBAD5140D0488446B0853C40E8482EFF21AE514050C554FA09873C407C60C77F81AE514070C763062A8B3C402C14E97E4EAF5140405FD04202BE3C4008D061BEBCB65140E0A9F23D23C13C405440DAFF00B7514030CC423BA7CD3C40849065C1C4B75140F02B2CB81FD43C4044A7203F1BB851403083DC4598DA3C4034172AFF5AB85140108BFCFA21E23C406CBE4A3E76B85140D0AC33BE2FE63C406CBE4A3E76B851400082397AFCF23C4034172AFF5AB85140200F45813E093D40109CFA40F2B75140D031AEB8383E3D40EC482EFF21B6514040E109BDFE403D40FCD8243FE2B55140506C06B820433D409026DE019EB5514000274D83A2513D40D4D03FC1C5B25140305C8FC2F5583D40980B957F2DAC5140A093A641D1583D408060C77F81AA5140200C040132943D409C0ED6FF39AD51409017EFC7ED9F3D40E8482EFF21AE5140809C69C2F6A73D40E83F6B7EFCAE5140F0B837BF61AA3D409414580053AF5140D03A71395EAD3D40806308008EAF514000274D83A2B13D403020ED7F80AF5140907A32FFE8C33D40BC40498105AF5140206552431BC83D40C0344580D3AE5140F00E45813EC93D4098ED7C3F35AD514060465C001AC93D40C022BF7E88AC5140D03730B951C83D405437177FDBAB5140C0F27684D3C63D40FC08C38025AB5140F05A0A48FBC33D40DCB837BF61AA514050D8463CD9C13D404480457EFDA95140E0BB783F6EBF3D4018691B7FA2A95140702B137EA9BB3D403CAA61BF27A9514070B08D78B2B33D4040B324404DA85140F0A9F23D23B13D4098EA3BBF28A8514060DC2A8881AE3D40C0378600E0A75140F087BB7A15AD3D402C20ED7F80A75140307D5A457FB03D40A8B0524145A75140000C040132B43D409C14580053A7514060BEA08504CC3D40EC4EB0FF3AA85140901B62BCE6D53D40D4CABDC0ACA851408093A641D1D83D405C3A58FFE7A85140901EA33CF3DA3D40585260014CA95140F02CCF83BBDB3D401C8A743FA7A951409096E7C1DDDD3D4010A27C410BAA5140F0B2B5BE48E03D403CB9A64066AA5140900F5EBBB4F13D40AC716F7EC3AC514050D6A88768F43D40000341800CAD514040E78BBD17FB3D40D4B5F63E55AD51405055A18158023E40E87E4E417EAD5140306BD44334123E40DCC1FA3F87AD514070AEEFC341163E40DCC1FA3F87AD514000068200191A3E4024F911BF62AD514080035ABA821D3E4048AA61BF27AD514050C2137AFD313E40C01F7EFE7BAB51406028D2FD9C563E4068D0D03FC1A65140000F45813E593E40B8490C022BA65140E040F33977573E401C967840D9A5514020917EFB3A4C3E4068D65240DAA4514090A86DC3283C3E40C81F7EFE7BA3514030E109BDFE103E408454C37E4FA25140E05A0A48FB033E4068C4CC3E8FA25140D0B2B5BE48003E407C60C77F81A25140D04543C6A3003E4098F0BDBF41A251401015C78157033E4044A19E3E02A2514050D9E90775093E4044C269C18BA15140D031AEB8380E3E40A8B6D4415EA1514060A7CAF78C243E408493A641D1A05140C0E0F08288283E408493A641D1A0514010917EFB3A2C3E4070F7AB00DFA05140202A8E03AF363E402CED0DBE30A15140A0F4143944443E4000CD203EB0A15140F040F33977473E4014967840D9A15140F03A71395E4D3E408454C37E4FA25140C001BC0512503E403CC5AA4198A25140F0AC33BE2F563E40E83F6B7EFCA2514060B5DD04DF5C3E4040B0E3BF40A35140C0D38041D2673E40C0FE243E77A3514040F38FBE496F3E40848461C092A3514050C554FA09773E406CC70DBF9BA35140E0420246977B3E40C81F7EFE7BA3514020809BC58B953E40C828417FA1A25140207CB779E3983E40ACB915C26AA251408014AE47E19A3E4054499D8026A251406034D6FECE9A3E40B074B0FECFA15140E034EF3845A33E40E8577380609F5140A0FDD7B969D33E40C82B82FFAD9B51407096E7C1DDED3E40C43AC780EC9C514020274D83A2F13E401072DEFFC79C5140F0C77C40A0F33E40C00166BE839C5140306BD44334023F40DCB5F63E5599514010990F08740A3F40BC490C022B965140D05A0A48FB133F408060C77F81925140406C06B820133F4054499D802692514050CAA48636103F40E83C2AFEEF915140000F45813EE93E4098239D819190514030809BC58BE53E40C00166BE8390514000274D83A2E13E40C422BF7E88905140702B137EA9BB3E40DCBEB9BF7A905140D05D4BC807893E407C6308008E8F5140A01B62BCE6853E40F078CC40658F5140E04334BA835C3E403020ED7F808B5140D0B837BF615A3E4098E7FA3E1C8B514070AA0B7899593E406CD0D03FC18A514040F04E3E3D5A3E40C01C3D7E6F8A5140D0622AFD845B3E4050499D80268A5140D050A4FB395D3E40F03C2AFEEF895140101E8A027D623E401C5D177E70895140800F5EBBB4613E40F045ED7E15895140A08461C0925F3E40580DFB3DB18851404083DC45985A3E40C0438A0112885140909C69C2F6573E4008D3A23EC987514040B81E85EB513E40EC78CC4065875140101B4982701D3E40C00166BE83845140D04D637B2D183E40FC170802648451405040DAFF00EF3D40F042ACFE08845140306552431BE83D4068006F810484514020938D075BE03D4068006F810484514060BEA08504CC3D40804E417E36845140D0D38041D2C73D40D4B2B5BE48845140306C06B820C33D4070BE4A3E76845140007976F9D6833D4040ADA23F34865140D0DDAF027C433D403CBCE7C07287514060465C001A093D40884E417E3688514070C1E10511D13C40D4D03FC1C58A5140808461C092BF3C402814E97E4E8B5140209A417C60BB3C40885704FF5B8B5140E034EF3845B33C4070BB09BE698B514020857AFA08A83C4024F38FBE498B5140A096E7C1DD9D3C4070DCD440F38A5140704F1F813F983C40106058FE7C8A5140704F1F813F983C4050499D80268A5140A0ECF483BA9C3C40ACA10DC0068A5140809C69C2F6A73C4050499D80268A5140C0E67283A1B23C40D8B837BF618A514040E44A3D0BB63C407C60C77F818A5140B0E3310395BD3C4068C4CC3E8F8A514020E109BDFEC03C405855A181588A514020E109BDFEC03C4044A19E3E028A5140A0DA6E826FBE3C40D4CDFE40B9895140F0AF743E3CAB3C406CDF15C1FF875140A01A3048FAA43C4040C8EBC1A4875140603F5244869D3C40F4D8960167875140D0A6B1BD169C3C40584CDE003387514030D505BCCC9C3C401899B9C0E58651408018213CDAA03C40148DB5BFB386514050ED0DBE30D53C40B0716F7EC3845140407D5A457F003D40EC57738060835140A0DDAF027C333D40F439E97DE38051400015C78157433D408093A641D1805140100341800C653D4048A7203F1B805140109700FC53863D40EC4B6F7F2E7F5140B07A32FFE8A33D408454C37E4F7E514050DEC83CF2AB3D4064FAEC80EB7D5140F02E6D382CA93D40E87E4E417E7D5140009700FC53963D40C02B82FFAD7B5140C06E2EFEB68F3D400015C781577B5140307D5A457F803D40C41C3D7E6F7A5140908D2441B86E3D40080F45813E7951401009C380255F3D4040A4DFBE0E775140A0E33103955D3D4008D061BEBC765140E04543C6A3603D40D8C43BC093765140A0EAE5779A683D408460C77F8176514000917EFB3A6C3D40D8C43BC09376514040F38FBE496F3D4008D061BEBC765140F0CABDC0AC783D40544F1F813F785140009A417C607B3D4094E1783E03795140D05FE97C78863D40B83D0801F9795140A0F755B950893D4040ADA23F347A514060B5DD04DF8C3D4090F0BDBF417A514060D6A88768B43D40D4C43BC0937A5140A093A641D1B83D40301DACFF737A5140407A19C572BB3D40A8AD11C1387A514040D505BCCCBC3D40E43C2AFEEF79514020809BC58BC53D40C02500FF9475514000A0C37C79C53D40000F45813E75514050B60F79CBBD3D4098205C0185735140A0ABAE4335B13D4014A27C410B725140D04334BA83AC3D4044C269C18B71514050E44A3D0BA63D40E851F17F477151401082397AFCA23D4058465C001A71514060AD4CF8A57E3D40188DB5BFB36A514020240C03967C3D40001286014B6A514020240C03967C3D40543D997FF46951408017EFC7ED7F3D4098E4B9BE0F6A5140E03730B951883D4068D0D03FC16A5140406893C3278D3D40EC577380606B5140708D2441B88E3D40302CF180B26B514050EACC3D24903D40C864E3C1166C5140208BFCFA21923D40D8BEB9BF7A6C514050D6A88768943D407C93A641D16C5140B05626FC52A73D403CC5AA41986E5140C0073E062BAA3D40C4344580D36E5140D0656B7D91B03D4010A5BDC1176F5140E040F33977B73D40ACB05241456F5140C0D03FC1C5F23D40504F1F813F705140202A8E03AF063E402C35B401D86E5140200C040132243E40A8B393C1516C5140F0393FC5712C3E4004DFA63FFB6B5140D0B2B5BE48303E4004DFA63FFB6B514000938D075B303E40A8B393C1516C514070D367075C2F3E402C232E008D6C51408087A2409F243E408454C37E4F6E514000F165A208213E4044E048A0C170514040289A07B0303E40984A3FE1EC70514090D097DEFE283E4044F8174163735140A000193A76283E408881204086765140C04BC5C6BC2A3E40B07A32FFE877514090E33103952D3E4018A8FE412478514000904C874E4B3E40941799805F7851405040DAFF004F3E40E84EB0FF3A7851406055A18158523E4068006F810478514090F4143944543E40146F9D7FBB775140E03FC1C58A663E40489E5DBEF574514090A52C431C673E40F08711C2A37451408014AE47E16A3E40D8A9F23D23715140207A19C5726B3E40C0490C022B6E514030E78BBD176B3E4004D6E3BED56C514060AA0B7899693E4018A8FE41246C5140B04D637B2D683E401890F63FC06B514020809BC58B653E40BCFE243E776B5140F0D03FC1C5623E4048B0E3BF406B514070B3CEF8BE583E4098DBF63DEA6A5140009700FC53563E40D0D03FC1C56A5140703D997FF4593E40C028417FA16A51405069C537145E3E406CC4CC3E8F6A514090F755B950693E4040C5AA41986A5140E0393FC5716C3E40D0D03FC1C56A51406040DAFF006F3E4040A4DFBE0E6B5140307497C459713E40F078CC40656B5140306211C30E733E40AC6E2EFEB66B5140A09065C1C4733E40C4438A01126C5140406552431B783E402C14E97E4E6F5140A04D637B2D783E4040C8EBC1A46F514050C554FA09773E405470784144705140C0D4EC8156743E404C287D21E4705140E034EF3845733E40D8A9F23D2371514030D8463CD9713E4070BB09BE6973514060B81E85EB713E400C6F9D7FBB73514070A7CAF78C743E406C006F810474514050BC9179E4773E40A8A78FC01F745140E0C43BC0938E3E40080C040132745140009700FC53963E409C0B957F2D745140E03DB2B96AA23E40E842ACFE0874514080116DC7D4B53E4068C70DBF9B73514070465C001AB93E40F057738060735140C02EC37FBAC93E4070067FBF9872514060588CBAD6DA3E4088CC9541B5725140A0A52C431CE73E402C35B401D86E5140D03C80457EF13E40040C0401326C5140201E8A027DF23E4000D9243FE2695140D0E7A4F78DF33E4030F38FBE49675140F034EF3845F33E40C428417FA1665140208BFCFA21F23E407C5182FE42655140E04E0647C9EF3E40884E417E36645140D042024697EB3E4074BB09BE69635140305C8FC2F5E83E4004E869C02063514060C422861DE63E401899B9C0E5625140106893C327DD3E405855A18158625140506C06B820D33E40B0A10DC00662514050BEA08504CC3E40F03C2AFEEF61514050D6A88768C43E405C3D997FF46151408015E0BBCD8B3E40C4344580D3625140E040F33977873E4068DCD440F362514090992842EA823E400809C3802563514070431B800D743E4044B324404D6451407087A2409F643E4024327381CB655140B077F17EDC5E3E4044C5AA4198665140A000193A76583E40F057738060675140A01B62BCE6553E40D4C77C40A067514050499D80264E3E402C172AFF5A685140F02B2CB81F343E40186058FE7C6A514070CAA48636303E40106C5CFFAE6A5140A0A86DC3282C3E4068D0D03FC16A5140D03730B951283E4068D0D03FC16A5140E0A9F23D23213E402C29B000A66A514040CC423BA71D3E405C5227A0896A514000990F08741A3E40C81C3D7E6F6A514010A0C37C79153E403CA19E3E026A5140B0E7A4F78D133E40D0EE5701BE69514070B950F9D7123E402CF911BF62695140C0E67283A1123E400018080264685140D03FC1C58A163E409C0B957F2D685140B0073E062B1A3E40EC4EB0FF3A685140A0F04BFDBC213E40586D37C13768514060A7CAF78C243E40844E417E36685140A08D2441B82E3E4068CD8FBFB465514070D367075C2F3E40505260014C65514080AD4CF8A52E3E40302F3201BF645140306893C3272D3E40F04EB0FF3A645140E05D4BC807193E40804E417E366051409001BC0512103E40546D37C1375F514040E44A3D0BE63D40282CF180B25B514020F04E3E3DAA3D40B09B8BBFED57514020990F08749A3D4048A4DFBE0E575140C03DB2B96A923D402829B000A6565140B074B0FECF893D40A8AD11C1385651409015E0BBCD7B3D40B074B0FECF555140B0E0F08288683D405873B9C1505551407055A18158523D40E47B0DC17154514050D367075C4F3D40980B957F2D545140D03A71395E4D3D40BC378600E053514070BEA085044C3D40C01F7EFE7B535140F099417C604B3D40F8E769C02053514000904C874E4B3D40D4F19881CA52514050DEC83CF24B3D4058499D80265251408096E7C1DD4D3D40940ED6FF39515140F04E0647C94F3D408487A2409F50514050C1E10511513D4028F6D03E565051407055A18158523D40B06E2EFEB64F5140E08233F8FB513D4040B0AA5E7E4F5140C0B321FFCC503D4014B14F00C54E5140B059677C5F4C3D40805A457F684C5140B0FE7A85054B3D40282CF180B24B5140D0A9F23D23413D40C42B82FFAD475140C050A4FB393D3D40B0984A3FE1465140C0FE7A85053B3D40848120408646514050D6A88768343D40EC7E4E417E455140406BD44334323D403CAA61BF2745514080035ABA822D3D40C00166BE8344514090ABAE4335213D40ACA44E401343514020F911BF62193D40E85432005442514060CAA48636103D408496E7C1DD415140C0ECF483BA0C3D40AC74B0FECF415140C004FD851E053D4040A19E3E0242514060CEFBFF38013D40FCCFD38041425140B07FD767CEFE3C40C8ACDEE1764251403027F73B14F53C4074F4F8BD4D435140D05A0A48FBE33C408C239D8191445140F042024697DB3C40845182FE42455140107976F9D6D33C404480457EFD455140E03A71395ECD3C4070D0D03FC146514060D9E90775C93C40D8C77C40A04751409093A641D1C83C40A89B8BBFED475140C04D637B2DC83C401066DAFE95485140206552431BC83C40C42500FF9449514070B3CEF8BEC83C4090111780464A514040DEC83CF2CB3C4054431B800D4C5140800F5EBBB4D13C402835B401D84E514050B08D78B2D33C40D4AF743E3C4F514040C422861DD63C401463997E894F514080A52C431CE73C4028266F809951514070BEA08504EC3C40D8AC33BE2F52514050DC2A8881EE3C409C1D1B8178525140A096E7C1DDFD3C40C864E3C116545140D04543C6A3003D4048B324404D545140B0E0F08288083D4048AA61BF27555140109D82FC6C103D4044A19E3E0256514030F38FBE491F3D40106F9D7FBB575140703A58FFE7443D40C43AC780EC5C514050465C001A493D40888AE3C0AB5D5140B0ECF483BA4C3D4008D061BEBC5E5140B0ECF483BA4C3D40ACA44E40135F5140207A19C5724B3D40302CF180B25F5140E028EB37132F3D40BC438A01126851401088BB7A152D3D406CCA4E3FA8685140E04543C6A3203D402838F581E46B514000904C874E1B3D40000341800C6D514080F755B950193D405C73B9C1506D5140F03DB2B96A023D407006F1811D6E5140305FD04202FE3C4030F04E3E3D6E5140206BD44334F23C40BC28417FA16E5140107CB779E3E83C406CFD2D01F86E514050DC2A8881BE3C407C87A2409F70514030D8463CD9B13C4028ED0DBE30715140C0E9B303AE673C401866DAFE9574514090ABAE4335613C40489E5DBEF574514080F1D3B8375F3C40940ED6FF397551408096E7C1DD5D3C406CC18BBE82755140202DCF83BB5B3C406806F1811D765140202DCF83BB5B3C40281DACFF73765140404F1F813F583C4064DF15C1FF775140A0F27684D3563C40D4B2B5BE48785140D0D03FC1C5523C40109337C0CC785140C0BB783F6E4F3C4094E1783E03795140202A8E03AF463C4028F911BF627951400026AAB7063A3C40DCEE5701BE795140201E8A027D323C4048A19E3E027A514000990F08742A3C40DCB837BF617A514050C554FA09273C403CC5AA41987A514090A86DC3281C3C40846308008E7B5140406552431B183C40C0438A01127C5140009C508880FF3B40EC84D041977F5140D0A6B1BD16FC3B4010A8FE4124805140B06BED7DAAFA3B40E85AB4006D805140E02E6D382CF93B40040341800C815140305C8FC2F5F83B40D4B837BF6182514070AA0B7899F93B40FCCF61BEBC825140E0C1FA3F87F93B40ACA44E401383514010857AFA08F83B40C82B82FFAD835140701B62BCE6F53B40D4B2B5BE48845140A00F5EBBB4F13B40E0A9F23D2385514030861DC6A4EF3B402C1A6B7F67855140A0E925C632ED3B4070E525FF93855140E0AF743E3CEB3B401C8A743FA785514060C554FA09E73B4004CD203EB0855140F09B508880DF3B4018691B7FA285514070D9E90775993B40EC8711C2A3845140D0D03FC1C5923B40845A457F688451400094BF7B47913B40C864E3C116845140A0F5B704E06B3B407003B0011181514030D505BCCC4C3B40E878CC40657F5140502B137EA94B3B405C40DAFF007F514090A86DC3284C3B40186C5CFFAE7E514070B60F79CB4D3B40ACB915C26A7E5140D0C43BC0934E3B4000068200197E5140D0BB783F6E4F3B40845D86FF747D5140C0E33103954D3B40FC0241800C7D5140F04BC5C6BC4A3B40189337C0CC7C5140C0D38041D2473B408087A2409F7C5140A0716F7EC3343B40106F9D7FBB7B514020895E46B1143B4094111780467A514010274D83A2113B4054499D80267A5140107FF8F9EF0D3B4000E52840147A5140D0C1FA3F87093B407006F1811D7A5140B05626FC52E73A400809C380257B514080069B3A8FE23A402C14E97E4E7B514010F38FBE49DF3A402820ED7F807B5140E0CDFE40B9DD3A4068D311C0CD7B5140A0035ABA82DD3A406CBE4A3E767C5140307A19C572DB3A405C2E54FEB57C5140909BE1067CCE3A4060BB7B80EE7C514050B60F79CB9D3A40543A58FFE77C514000068200199A3A408493A641D17C5140602B137EA97B3A406CDF15C1FF7B51409000193A76783A405C37177FDB7B5140604CDE0033733A400015C781577B5140708461C0926F3A4084812040867A514010240C03966C3A40D4CDFE40B9795140A0812040866A3A40449E5DBEF578514060BB5F05F8663A406CD311C0CD775140A004FD851E653A40F078CC406577514000301004C8603A40146C5CFFAE765140C0C43BC0935E3A403CB9A6406676514020240C03962C3A4040A7203F1B70514050BC9179E4273A4090205C01856F5140E03DB2B96A223A40448386FE096F5140F072F4F8BD193A40146058FE7C6E514090069B3A8F023A401C8A743FA76D5140906E2EFEB6FF3940E45DF580796D5140809FAA4203FD39409C0ED6FF396D514000990F0874FA3940C03AC780EC6C5140406E15C440F73940544F1F813F6C5140B07A32FFE8F3394094205C01856B5140108BFCFA21F2394014A5BDC1176B5140D0A9F23D23F13940188DB5BFB36A51401094BF7B47F13940D0B837BF616A514090E67283A1F239406406F1811D6A514060BB5F05F8F63940C02500FF9469514020F911BF62F939406CCA4E3FA8685140E0C1FA3F87F9394028F6D03E56685140F02E6D382CF93940189CFA40F2675140C0EAE5779AF8394068C70DBF9B675140102A8E03AFF639408081204086665140B004FD851EF53940C8310400C76551401082397AFCF23940109F3BC1FE645140D04E0647C9DF3940FCE769C0205F514090FB3905F9D53940BC3AC780EC5851402096CE8767D539401C66DAFE9558514060D6A88768D43940FC0B040132585140E04E0647C9CF3940F084D0419757514070CDE50643C539402829B000A65651401094BF7B47C1394070D993C0E65551408017EFC7EDBF394070C18BBE82555140705260014CBD39409C1799805F5451405028D2FD9CB6394028F6D03E5650514020ED0DBE30B5394040C269C18B4D5140E0B5F63E55B5394094ED7C3F354D5140207A19C572BB3940EC3F6B7EFC46514040895E46B1C439401099B9C0E542514040B950F9D7C239402C14E97E4E3F514080ABAE4335B13940809065C1C43B5140A0F755B950A939405055A181583A5140A0A52C431CA7394048A19E3E023A51406031957EC2A53940C82500FF9439514020D8463CD9A13940F039E97DE3385140808461C0929F39401466DAFE95385140B0ECF483BA9C3940785A457F68385140801B62BCE6953940544F1F813F385140306BD44334923940EC4EB0FF3A385140007FF8F9EF8D394024F6D03E5638514080A2EBC20F82394070D65240DA38514070035ABA827D394094E1783E03395140D02E6D382C79394054465C001A395140B0EF3504C77139406C03B0011139514080FA96395D6E3940189F3BC1FE385140D04D637B2D683940C02EC37FBA385140001E8A027D62394028172AFF5A385140206893C3275D3940AC9B8BBFED37514040DEC83CF23B39408093A641D134514040DB87BCE5363940ACB393C15134514050CAA4863630394070BB09BE69335140207156444D2C39401C8DB5BFB3325140C06BED7DAA2A3940FC1186014B3251408009DCBA9B273940DCA9F23D2331514060C763062A1B3940F078CC40652B5140D0B837BF611A3940A86BED7DAA2A51406034D6FECE1A394040A19E3E022A5140E04334BA831C39402CF911BF62295140C0A6B1BD161C394000E2E7BF0729514020990F08741A39408887A2409F285140C0E0F082881839405C70784144285140D0E7A4F78D133940889065C1C4275140707973B856EF3840148AE6012C25514010A051BAF4DB384068A6B4FE96255140A0E3A3C519DB3840E839E97DE3255140D01E12BEF7D738406CB2B8FFC8265140D068ACFD9DD53840885704FF5B275140F00B040132D438403CC8EBC1A4275140F04E0647C9CF3840D0BEB9BF7A285140F0907EFB3ACC384098E1783E03295140B0FB3905F9C53840C4310400C7295140D0A9F23D23C1384094F0BDBF412A5140402E54FEB5B038402CF38FBE492B514030E109BDFEA03840FCDEA63FFB2B5140000C040132943840544F1F813F2C514080FDD7B969833840C422BF7E882C5140D034EF3845733840BC2EC37FBA2C5140E04BC5C6BC6A3840583A58FFE72C5140909FAA42035D3840D8B5F63E552D5140603D997FF4593840E85DF580792D51405028D2FD9C563840888AE3C0AB2D5140108E3D7B2E373840809065C1C42F51404055A1815832384040A7203F1B305140B077F17EDC1E384050499D802632514070465C001A193840FCDB65BFEE325140A009DCBA9B173840544CDE0033335140002A8E03AF1638403020ED7F8033514030ED0DBE3015384004D3A23EC9335140C0F8F884EC103840D8B2B5BE48345140F031AEB8380E3840C40166BE83345140107A19C5720B3840C42EC37FBA345140F040F33977073840503A58FFE7345140503D997FF4F93740E451F17F47355140A0AEEFC341E63740B0B6D4415E355140E0AF743E3CDB3740E451F17F47355140D0BEB9BF7AD43740C046CB811E355140D053E57B46D237408093A641D134514050C1E10511D13740D4BEB9BF7A345140D03A71395ECD3740FCDB65BFEE3251409015E0BBCDCB37407C60C77F81325140F0CABDC0ACC8374000CD203EB0315140504CDE0033C337407C6649809A30514030CC423BA7BD374090205C01852F514090AEEFC341B6374000E52840142E5140002C2CB81FB43740C0310400C72D5140207497C459B13740C82500FF942D5140405FD04202AE3740EC7E4E417E2D5140E025AAB706AA3740D0C1FA3F872D514070CDE50643953740E0A9F23D232D5140F0BEB9BF7A843740542E54FEB52C51407009DCBA9B77374058707841442C51401018080264683740808461C0922B514050CDE5064355374044ADA23F342A51404083DC45984A3740B0B6D4415E295140D04D637B2D483740C046CB811E29514030CF83BBB3423740C02EC37FBA28514070F4143944343740F04EB0FF3A285140D0B2B5BE48303740001808026428514090073E062B2A3740189337C0CC28514060B08D78B223374040C269C18B29514010F911BF62193740E84B6F7F2E2B514090069B3A8F12374058707841442C514010938D075B103740C00166BE832C51402088BB7A15DD364028172AFF5A2C5140A0035ABA82CD3640544F1F813F2C514040D505BCCC8C3640506D37C1372F5140100000000080364034897AC1A72E5140B0FB3905F965364068C18BBE822D514080AD4CF8A55E36408454C37E4F325140306893C3275D36403020ED7F80335140000F45813E59364070FAEC80EB35514070B3CEF8BE5836409CE4B9BE0F365140C036FE4465473640F05AB4006D385140101E8A027D323640EC78CC40653B5140800F5EBBB4313640C0438A01123C514080069B3A8F3236406CBE4A3E763C5140E05A0A48FB33364070F7AB00DF3C5140E0B5F63E55353640C446CB811E3D51402083DC45980A3640FC14C781574351406089963C9EFE3540540169FF03455140C0C43BC093AE3540ACAD11C138525140008BFCFA2152354070F7AB00DF5451404069C537140E3540C428417FA14E5140F025AAB7060A354040A19E3E024E5140D03730B95108354010691B7FA24D5140F08D3D7B2E0735405473B9C1504D51405034D6FECE0A3540FC1186014B4A5140D0CDFE40B90D3540149F3BC1FE485140A0F8F884EC103540C864E3C116485140A0F41439441435401C63997E8947514060BFD2F9F01C354098DBF63DEA46514050D505BCCC1C3540F0818FC18A465140E0A6B1BD161C354058499D8026465140503D997FF4193540D8B5F63E55455140D0488446B0153540AC6E2EFEB64351401082397AFC123540B4984A3FE14251401094BF7B471135408460C77F8142514090F1D3B8370F354044ADA23F344251409000193A76083540F0482EFF21425140A0FE7A8505FB34401099B9C0E5425140109C508880EF34401C90F63FC0435140B0FB3905F9D5344044B665C059455140101E8A027DD23440D4C1FA3F8745514050C422861DC634404480457EFD455140809FAA4203BD3440C0490C022B46514070F755B950B93440EC482EFF21465140A0069B3A8FB23440E83C2AFEEF45514020D505BCCCAC3440C82500FF9445514060BEA085049C3440E87B0DC171445140504C50C3B79434406C361D01DC435140E05D4BC80789344068C70DBF9B4351408093A641D1183440188DB5BFB3425140306893C3273D34404080457EFD3D5140D0656B7D9150344068BB09BE693B5140A08AE3C0AB5934405855A1815832514010938D075B50344048B324404D305140A09FAA42033D3440544F1F813F2C5140207976F9D6333440D4B837BF612A5140F03A71395E2D3440301A6B7F6729514040EACC3D241034405873B9C150255140C05147C7D5F433405C34D6FECE225140D03FC1C58A16344044A7203F1B20514030E44A3D0B363440B077F17EDC1E51401096CE8767353440281DACFF731E514060B950F9D73234409426DE019E1D5140809FAA42032D3440D8CABDC0AC1C51407034D6FECE2A34407C5A457F681C514070FDD7B969133440E8818FC18A1A5140307156444D0C3440B074B0FECF19514020D2C43BC0073440E851F17F47195140900F5EBBB40134400418080264185140E025AAB706FA334004E869C02017514090F27684D3F63340DCB837BF61165140603A58FFE7F4334098E4B9BE0F16514020CF83BBB3F23340A874B0FECF155140C001BC0512F0334030266F8099155140D04334BA83EC33403CC269C18B155140B0FB3905F9E5334014967840D9155140307156444DDC334044B9A640661651408009DCBA9BB733405C37177FDB175140E0AF743E3C8B3340C42500FF94195140A074B0FECF6933402835B401D81A5140909065C1C4F33240546D37C1371F5140800C1D3BA89C3240A8B915C26A1E5140502B137EA95B32408060C77F8122514080AEEFC341263240AC9ECC3FFA205140809CDB847B19324068855B3E92205140206E15C44017324044BF28417F205140503A58FFE71432406CBB09BE691F5140B077F17EDC0E324098EA3BBF281C5140102DCF83BB0B324048ADA23F341A514040CC423BA70D324004E2E7BF07195140B0EF3504C7113240106C5CFFAE165140B0FB3905F915324030F6D03E561451403083DC45981A3240BC3D0801F911514040D2C43BC0273240BC28417FA10A514030CF83BBB32232409026DE019E095140D0656B7D91F031405C37177FDBFF50405055A18158E23140C00166BE83FC5040602B137EA9DB3140502E54FEB5FC5040A0716F7EC3D43140FCE1E7BF07FD504040B81E85EBD13140040F45813EFD5040505260014CCD31406CCD8FBFB4FD5040F01186014BBE3140BC40498105FF504040499D8026AE3140DCB2B5BE4800514050C422861DA63140543A58FFE7005140A0E9B303AE9731406CD993C0E601514030E44A3D0B4631402C327381CB055140A0868C47A9403140D4D03FC1C50451401060AE450B3C3140F47EDC7EF903514050CAA48636303140EC3C2AFEEF0151402006820019BA30403CC269C18BF9504020F38FBE49AF30407C5182FE42F5504020763579CA9E3040AC77F17EDCEE5040D03FC1C58A963040602B137EA9EB504040B08D78B293304044C5AA4198EA504050C2137AFD91304014A27C410BEA5040208BFCFA21823040E83F6B7EFCE65040406E15C4406730406CFAEC80EBE1504060B81E85EB613040189F3BC1FEE05040B0716F7EC334304048A7203F1BE05040A0ABAE43353130400000000000E05040C0FB3905F91530405855A18158DA5040A0AEEFC341163040ACA10DC006DA504050BB5F05F816304068CD8FBFB4D95040A06BED7DAA1A30408493A641D1D85040C0393FC5711C30402C232E008DD85040D0DDAF027C23304090205C0185D7504030F911BF62293040D0D03FC1C5D6504070D6A8876834304028266F8099D550408000193A76383040BC46CB811ED55040206211C30E4330407C6308008ED350402077D84466563040540DFB3DB1D05040D04334BA835C3040586D37C137CF5040D0AC33BE2F663040E857738060CB504050BC9179E4673040301DACFF73CA50403083DC45985A3040DCA9F23D23C15040A0069B3A8F02304098E1783E03B95040C08EC70C54762F40DCF4D901D7AB5040A094490D6D402F40D8D03FC1C5A65040A02975C9380E2F40AC6E2EFEB6A35040A06ABB09BEB92E40848D2441B89E5040A051D66F26BE2E4040C269C18B9D5040A07F828B15CD2E4018A27C410B9A5040A02C280CCAE42E4090239D819194504040861DC6A4EF2E40B8490C022B92504060BFD2F9F00C2E4028266F8099895040E05FE97C78F62D403CC269C18B89504060A48977806F2D40189F3BC1FE88504060069B3A8F022D40DCBEB9BF7A88504040895E46B1042D40FC14C78157875040C074B0FECF092D40080341800C85504000F86EF3C6112D409826DE019E815040A0716F7EC3142D40D8BEB9BF7A80504040DF6B088E232D40B0716F7EC37C5040004F95EF19292D40EC84D041977B504000CA8B4CC0372D40C464E3C116785040801A3048FA442D40C03AC780EC745040C0FDD7B969432D4054707841447450400052D66F263E2D40C040498105735040C0E4D4CE30352D40EC7E4E417E715040C07F828B152D2D40E87B0DC171705040E05CA8FC6B212D40FCE769C0206F5040E00B040132142D40B0B6D4415E6D504040B81E85EB112D40A49ECC3FFA6C5040607D5A457F102D4028232E008D6C5040C0B2B5BE48002D40EC7E4E417E655040C0C43BC093FE2C4000E2E7BF0761504040EC6AF294FD2C4094239D81915C504000F52D73BAFC2C40C864E3C116585040606893C327FD2C4070FD2D01F8565040604278B471FC2C40BC438A011254504080B5DD04DFBC2C4008D3A23EC94F5040C08EC70C54B62C4040B665C0594D504020E9297288A82C40C02500FF9449504060DF6B088EA32C40ACB393C15148504080EA573A1F9E2C40CC586DFE5F475040A095B6B8C6972C407C42AF3F894650408000193A76782C4004E869C020435040806DFC89CA2E2C402C2F3201BF3C5040C0F0D8CF62E92B40F05DF58079355040A082C30B22C22B4044B665C05931504020B937BF61AA2B4004DC65BFEE2E504040DAC70A7E732B40A85016BEBE295040C0E7154F3D6A2B403C7D04FEF0285040205A80B6D5642B40D4B2B5BE482850404083DC45985A2B401C99B9C0E526504020BFB9BF7A542B40DCEE5701BE255040A05417F032532B40585260014C25504000C87C40A0532B40407D04FEF0245040C05A99F04B5D2B4030232E008D24504020634337FBA32B4000D9243FE2215040C050A4FB39CD2B40D4BEB9BF7A205040604E7CB5A3102C40D8AF743E3C1F5040204B3B35973B2C406C06F1811D1E5040800C1D3BA84C2C40F8E4284014165040A0035ABA824D2C403CB665C059155040A0F1D3B8374F2C402C38F581E40B5040C0DE52CE174B2C40FCE769C0200B5040C01D71C806FA2B4048AA61BF270150404020990E9DF62B4004D6E3BED5005040A0E4D4CE30952A4044C269C18B05504000295C8FC2752A40583D997FF4055040606C06B820632A405431957EC2055040A09E077767452A4040B665C059055040407D5A457F102A402C232E008D045040C01D71C806FA2940ACA78FC01F045040C0B2B5BE48E0294074BB09BE6903504000274D83A2B129409026DE019E015040A0129F3BC196294070BE4A3E76005040006893C3275D29409015E0BBCDFB4F4040A7CAF78C442940D0CABDC0ACF84F4020573F36C90F2940A06E2EFEB6EF4F40206BD44334F22840B06BED7DAAEA4F406045B9347EB12840605260014CDD4F40E06DFC89CA4E284088A86DC328CC4F40603F373465472840D0D03FC1C5CA4F40407A19C5725B2840A8C2D84290C14F40E0703D0AD76328409048BF7D1DBE4F4000B728B3414628402838F581E4B74F40606552431B282840608BC1C3B4B14F40E0BB783F6EFF2740885D86FF74A94F4000BC783F6EDF27402835B401D8A24F4060DEE34C130E28401818247D5A974F4020A26131EA12284078AEEFC341964F40C074B0FECF49284038327381CB854F40C08EC70C54562840A8A10DC006824F408032384A5E4D2840B89B8BBFED7F4F40801D71C8063A28409015E0BBCD7B4F40009F20B1DD1D2840B8E3310395754F40C06DFC89CA0E284028F04E3E3D724F40A06ABB09BE192840089A417C606B4F40C082C30B22222840C8F19881CA664F4080B60F79CB2D2840A89B8BBFED5F4F4040CDE50643252840E0C77C40A05B4F4060BC9179E4172840286893C327554F40A02FF7C951182840B8622AFD844B4F40A091088D602B2840F82CCF83BB434F408059677C5F4C284090992842EA3A4F40A04D637B2D582840D000DE0209384F40E0E2A7716F5E284078AEEFC341364F40E0B628B3416628409015E0BBCD334F40A0622AFD846B2840903CBB7CEB314F40408A90BA9D7D2840905182FE422B4F40A02CB6494583284008D9243FE2294F40C01EA33CF38A2840D0BB783F6E274F4000B6F63E55952840B8984A3FE1224F40C038BA4A7797284008C11C3D7E214F40E0B0170AD8962840C02231410D214F4060D6A8876884284028F04E3E3D124F406069C537146E284000301004C8004F406048FAB48A6628403014E97E4EFB4E4000A8E331035D284040D505BCCCF44E4060C554FA09572840507C7C4276F04E4040274D83A2512840D8A6B1BD16EC4E40A06E2EFEB63F2840785182FE42DD4E4000356090F4492840D0F4D901D7DB4E40C04E95EF19C928408854C37E4FCA4E4040CAA48636D0284028F911BF62C94E40607156444DDC2840D8F71A82E3C84E4080B08D78B2E3284008301004C8C84E4040573F36C9EF2840D07C957CECC84E40C05FE97C78F62840D8F71A82E3C84E406015E0BBCD0B2940886649809AC84E4040D367075C0F2940607C7C4276C84E40A088450C3B8C2940D0031F8315B54E40A08EC70C54B6294068FB743C66AE4E40E0C1FA3F87A92940809C69C2F6A74E4060BC9179E4972940905704FF5B9F4E40E091088D608B2940488BC1C3B4994E40C085048C2E572940D8AF743E3C8B4E40C02497FF90462940F096E4805D874E4040E3A7716F3E2940E0F19881CA864E40C0ED974F563429404876FA415D864E40803579CA6A22294058499D8026864E4000E2934E240029409060C77F81864E40E089592F86EA284020DB87BCE5864E40201B498270DD2840803FFCFCF7864E40E02F1004C8D0284020DB87BCE5864E40402A8E03AFC62840A05FE97C78864E402020990E9D962840809065C1C4834E40A077F17EDC7E2840C8B837BF61824E40A0B81E85EB71284020F911BF62814E4080FA96395D6E2840D8F71A82E3804E40A0622AFD846B2840B0B393C151804E4080BFD2F9F06C2840A0E9B303AE7F4E40A0F1D3B8376F284078A52C431C7F4E40C009DCBA9B772840500438BD8B7D4E40C0CDFE40B97D284038232E008D7C4E40E0AF743E3C8B284058465C001A794E40405FD042029E2840B0C2D84290714E40E0A6B1BD16AC2840E0FD9C82FC6A4E4020999EB0C4B328406040DAFF00674E40400341800CB528405076FA415D664E406054FEB5BCBA2840809065C1C4634E40A0C2137AFDC128406073B9C150614E404051BD35B0C52840286552431B604E4060AA0B7899D9284090992842EA5A4E40E079008BFC02294010CADFBDA3504E40C0CCCCCCCC2C294050793BC269434E40809BC6F65A302940D08BDAFD2A424E40E0AC33BE2F362940001B4982703D4E40C05626FC5237294008DFA63FFB3B4E40A0C554FA09372940504CDE00333B4E40C08FDB2F9F342940C8CABDC0AC384E40A0B81E85EB31294060FB743C66364E40A076BF0AF02D294028E78BBD17334E40005A80B6D52429400018080264304E404015C7815713294088423D7D042C4E40C02975C9380E2940E0D03FC1C52A4E40E053E57B46022940781EA33CF31A4E4060634337FB03294008301004C8184E4080F414394404294038F38FBE49174E40A023F3C81F042940B05FE97C78164E40A0703D0AD703294010CD203EB0154E40C05CA8FC6B0129408081204086124E400009C38025FF2840889C69C2F60F4E400052D66F26FE284088A52C431C0F4E4020A8E33103FD2840B8AD11C1380E4E4080A148F773FA284000240C03960C4E40200C040132F42840E073D2FBC6094E40803BFBCA83EC284030EACC3D24084E406051BD35B0A52840A09ECC3FFAFC4D40E077F17EDC9E284088423D7D04FC4D40C053E57B46622840B8BF97C283F44D4000E6E8F17B5328406034D6FECEF24D4000F2ECF2AD472840608BC1C3B4F14D40A03579CA6A422840E0C1FA3F87F14D40C0D24ECDE536284038F911BF62F14D404045B9347E112840A85CA8FC6BF14D40C0F4143944042840D0EE5701BEF14D400038A11001FF2740303E7782FDF14D4020295C8FC2F52740004BE7C3B3F24D4020861DC6A4EF274090992842EAF24D4000356090F4E927406034D6FECEF24D40C094490D6DC02740905704FF5BEF4D402090DB2F9FB4274078AEEFC341EE4D4080B05582C5A12740A0923A014DEC4D40206893C327BD27403038F581E4E74D40406C06B820C3274030DB87BCE5E64D40200473F4F8C52740101286014BE64D40C05758703FC82740C8CDFE40B9E54D40C01EA33CF3CA274008BEDBBC71E44D40602618CE35CC27404816A243E0E24D40A0FA96395DCE27408860C77F81DE4D4080DC2A8881CE2740100C040132DC4D40802975C938CE27405007793D98DA4D40E050A4FB39CD2740D0EE5701BED94D40C01EA33CF3CA2740305C8FC2F5D84D40206552431BA8274058FEB5BC72D34D408023F3C81FA42740286211C30ED34D40208D9AAF929F27406034D6FECED24D4060CAA48636902740B053E57B46D24D40006E15C440872740488BC1C3B4D14D40602CB6494583274068F833BC59D14D40000D36751E552740B0AD11C138CC4D40C01B62BCE6552740F82CCF83BBCB4D4060A148F7737A27406040DAFF00B74D4040013274EC902740B0C2D84290A94D40E0311F10E8942740D876137CD3A64D40C07C410B09982740E0AF743E3CA34D40406684B70799274030E109BDFEA04D4040B3CEF8BE98274008BB9A3C659F4D40A085048C2E9727405028D2FD9C9E4D400007D2C5A695274058F295404A9E4D4000F86EF3C691274000A0C37C799D4D4060787B10028A2740C8559E40D89B4D402021CB828987274028E78BBD179B4D4040895E46B1842740508BC1C3B4994D40E053E57B46822740D88558FD11984D40A094490D6D802740089700FC53964D402083DC45987A2740D0B2B5BE48904D402083DC45987A2740B0E9B303AE8F4D4080BEA085047C27402841B8020A8F4D40E051D66F267E2740A8DA6E826F8E4D40C0D8D0CDFE802740306893C3278D4D40603E3C4B90812740F8BDDBBC718C4D40E0656B7D91802740886308008E8B4D40C018213CDA402740B059677C5F744D40C051D66F263E27408815E0BBCD734D40404B75012F332740E8067C7E18734D4000D68F4DF22B2740D0D03FC1C5724D40E01186014BFE2640100F45813E714D40C07F828B15ED264048465C001A714D4000FBAF73D3E62640D8A9F23D23714D40C018213CDAE026405873B9C150714D40406893C327DD2640D0EE5701BE714D40E006B47405DB26408054C37E4F724D40201077F52ADA26403035B401D8724D4060AA0B7899D9264000C79E3D97734D40A000193A76D8264038327381CB754D4060E2AC889AD826406028D2FD9C764D400069C70DBFDB2640601CCEFC6A7E4D40401B498270DD2640D8F19881CA7E4D4040E3A7716FDE2640580ABABDA47F4D40E0A7E33103DD2640E0B2B5BE48804D4000809BC58BC52640D8EE5701BE894D40801D71C806BA2640585260014C8D4D40E08EC70C54B62640D8CDFE40B98D4D40603BFBCA83AC2640109700FC538E4D4080B3CEF8BE982640D8C43BC0938E4D40406552431B68264008CD203EB08D4D40A018213CDA20264010DC65BFEE8E4D40207497C459112640E08558FD11904D40C00F5EBBB4E12540D888997D1E954D4060BFD2F9F0CC254030F04E3E3D924D40802FF7C9519825404837177FDB974D402021CB8289872540000C0401329C4D404045B9347E512540D0C43BC093AE4D40A02975C9384E2540A0E9B303AEB74D40007497C459512540805704FF5BB74D40A0C554FA09572540E0BB783F6EB74D4060D026874F5A2540A89B8BBFEDB74D40607156444D5C2540886649809AB84D40A08B868C476125403835B401D8BA4D40E0C64ACCB362254000C79E3D97BB4D40E0C64ACCB3622540885A457F68BC4D40A0C936700762254068976F7D58BD4D40406684B70759254000BB9A3C65BF4D40406BD4433452254060465C001AC14D40A0F1D3B8374F2540D8B837BF61C24D404067B796C9482540C0EC82C135C74D40806F61DD7847254050BC3C9D2BCE4D4080A5D766633D254080A2EBC20FD24D402038A110011F2540D8F4D901D7DB4D4040EC6AF2941D2540805182FE42DD4D4000E3A7716F1E254050499D8026DE4D4020B0743E3C2B2540D088997D1EE54D4000E6E8F17B3325406037177FDBE74D4060A7CAF78C44254028ED0DBE30ED4D4000D48041D24725401048A643A7ED4D40800C1D3BA84C2540507FBDC282ED4D40407D5A457F502540D0031F8315ED4D40A07C410B09582540A8DDAF027CEB4D40C023F3C81F642540089700FC53E64D40405A80B6D5642540B8E3310395E54D4080A4FACE2F7A254060B83A00E2E64D4020A4FE7A8585254020E42EC214EB4D400009C380257F2540E0C1FA3F87F14D40A0BEA085047C2540A8A10DC006F24D4000C87C40A0732540D0D03FC1C5F24D4060FDD7B969632540886308008EF34D40C0CDFE40B95D2540D0C77C40A0F34D40A0135E8253572540C0A4DC7D8EF14D40A0ED974F5654254060465C001AF14D4040573F36C94F25408893A641D1F04D40C089592F862A2540A8B393C151F04D40E0C43BC0931E25400818080264F04D40A05417F032132540904E417E36F04D402069C537140E2540D800DE0209F04D4020AAF23D23012540B8A44E4013EF4D40009F20B1DDFD2440D8C43BC093EE4D40E0D03FC1C5F22440A8BF97C283EC4D404045B9347EF1244038DEC83CF2EB4D40406BD44334F22440584CDE0033EB4D40E05FE97C78F62440888D2441B8E64D40E085048C2EF72440385FD04202E64D40808FC2F528FC2440D8368C82E0E34D40202DCF83BBFB2440808AE3C0ABE14D40207A19C572FB2440B85FE97C78DE4D40E0A7E33103FD2440080341800CDD4D40E074B0FECF092540D809A1832ED74D4000A7B1BD160C25406828D2FD9CD64D40A020B248130F25408848BF7D1DD64D4040040132741C25404077F4BF5CD54D4020E929728828254050431B800DD44D400023DA8EA92B254000C79E3D97D34D40001E8A027D32254008D9243FE2D14D40A0978A8D79352540886649809AD04D40606684B707392540B89ECC3FFACC4D40606684B707392540080C040132CC4D40A04D637B2D3825403014E97E4ECB4D40A0129F3BC13625405082FE428FCA4D40404E7CB5A33025405801F73C7FC84D40402C9D0FCF2A2540D0BB783F6EC74D4000CEFE40B91D2540607FBDC282C54D40002A8E03AF062540504CDE0033C34D40605DC136E2F9244030F04E3E3DC24D40809BC6F65AF02440E073D2FBC6C14D40E06BED7DAAEA2440888AE3C0ABC14D40A0B08D78B2E32440E073D2FBC6C14D402083DC4598DA2440201DACFF73C24D40602FF7C951D82440D082177D05C34D40A0129F3BC1D62440582B137EA9C34D4000D34ECDE5D6244010BEDBBC71C44D40606684B707D92440B8B393C151C84D40C06ABB09BED92440B8AAD0402CC94D4040C763062ADB2440583D997FF4C94D4060BEA08504DC24402835B401D8CA4D4060BEA08504DC2440E0C77C40A0CB4D40C0ED974F56D4244080397AFCDED44D40E0C77C40A0D32440B0E3310395D54D40606BD44334D22440A0AD11C138D64D4080B950F9D7C22440805D86FF74D94D40002FDE8FDBBF2440603D997FF4D94D4040E6E8F17B93244038327381CBDD4D4000C2FA3F878924406076FA415DDE4D40E0955D30B87E244008E5284014DE4D40200341800C752440B868ACFD9DDD4D4000F86EF3C6712440D888997D1EDD4D402015C78157732440C8BEB9BF7ADC4D40C0F414394484244038F911BF62D94D40008A592F868A2440806649809AD84D40A0B60F79CB8D2440D8B2B5BE48D84D40A03385CE6B9C2440F80B76C3B6D74D4040DF6B088EA32440D8BB783F6ED74D40606552431BA824403041B8020AD74D40C021E4BCFFBF244038D505BCCCD44D40E053E57B46C22440D00CE2033BD44D40A0703D0AD7C32440D8C77C40A0D34D4040C422861DC6244020F04E3E3DD24D4020B0743E3CCB244080CC07043ACD4D40A0D58F4DF2CB2440282CF180B2CB4D40A0D58F4DF2CB2440B0984A3FE1CA4D4020809BC58BC52440580DFB3DB1C44D40A023F3C81FC42440B87A32FFE8C34D40803E3C4B90C124401015C78157C34D4000CEFE40B9BD2440881EA33CF3C24D40C038BA4A77B72440881EA33CF3C24D40A032384A5EAD2440089A417C60C34D4000CBBDC0ACA82440302CF180B2C34D4000240C03969C2440383B3602F1C44D40400C04013294244000CD203EB0C54D40A02CB64945832440D009A1832EC74D40E0955D30B87E24403020ED7F80C74D40A000193A767824403020ED7F80C74D40A000193A76782440082A8E03AFC64D4060F755B95079244050499D8026C64D40E0E2A7716F7E244000D6E3BED5C44D4000FBAF73D38624403814E97E4EC34D4080B81E85EBB12440503A58FFE7BC4D40A0737E8AE3D82440D8F71A82E3B84D40006211C30EF32440081286014BB64D40C009DCBA9BF72440386893C327B54D40001808026408254010D3A23EC9A74D4000180802640825405840DAFF00A74D40A0BB5F05F8062540B8AD11C138A64D40401E8A027DF224405001F73C7FA04D40A050A4FB39ED2440805704FF5B9F4D40C0F0D8CF62E92440883FFCFCF79E4D40A01A3048FAE42440F8298E03AF9E4D40A0C2137AFDE124400809C380259F4D40C0656B7D91E02440D0D38041D29F4D40402FDE8FDBDF2440B8E0F08288A04D40E0F42D73BADC244030E109BDFEA04D4080F4143944C424405855A18158A24D40E051D66F26BE24405855A18158A24D4020D026874FBA2440483D997FF4A14D40802FF7C951B82440E00F238447A14D404021CB8289A72440B853E57B469A4D40C08EC70C54762440283B3602F1844D40C088450C3B4C24409081204086824D40200AF5F41150244088992842EA824D40005517F03253244048793BC269834D4040295C8FC255244010DFA63FFB834D40C085048C2E572440B0716F7EC3844D40C05FE97C7856244000A0C37C79854D4020E6E8F17B532440E07FD6FCF8854D40C076BF0AF04D244028E44A3D0B864D4000634337FB432440F847A643A7854D4000C4094CA70D244038560DC2DC804D40C0F1D3B8370F2440482C0DFCA87E4D40C0F1D3B8370F24409814CAC2D77D4D4080AD4CF8A50E2440B0075A81217D4D40C050A4FB390D244020B743C3627C4D40806BED7DAA0A24402072DEFFC77B4D40206C06B82003244068DF15C1FF7A4D40E09BDF30D1E8234040D8463CD9794D40A08B868C47C1234030F04E3E3D7A4D40801EA33CF3AA234050793BC2697B4D40E06DFC89CAAE23408015E0BBCD7B4D40207497C459B12340805A457F687C4D4020EFAB72A1B2234038ED0DBE307D4D4020EFAB72A1B22340D8F19881CA7E4D4000F86EF3C6B123403020ED7F807F4D4060A4897780AF2340D88558FD11804D40402A8E03AFA6234038D8463CD9814D40E0EF8975AAA42340288D43FD2E824D4000A26131EA9223408087A2409F844D4060A148F7733A2340B8A44E40138F4D4020965D30B81E234010DC65BFEE8E4D4040E2AC889A18234038DB87BCE58E4D4020321F10E8142340F0298E03AF8E4D4000EE974F56142340285FD042028E4D402020990E9D162340001B4982708D4D4020261B0FB640234008BB9A3C65874D40001286014B5E2340E8A6B1BD16844D4060B950F9D7622340A89509BFD47D4D40E05626FC523723406028D2FD9C764D4000321F10E8342340B8AD11C138764D40C0703D0AD7032340D88BDAFD2A724D4040274D83A2D12240382CF180B26B4D4080A46DFC89B22240B8E600C11C614D404069C53714AE2240306552431B604D4000D00D4DD96122406070784144544D4060A148F7735A2240A8DDAF027C534D40C018213CDA20224030DB87BCE54E4D4040861DC6A40F2240D0CDFE40B94D4D40803E3C4B90012240A89ECC3FFA4C4D40E09E20B1DDFD2140F8230C03964C4D40406E15C440E7214058F833BC59494D4020C2FA3F87A92140600438BD8B3D4D40604AEB6F0998214030FF93BF7B3B4D40E016BA12817A2140B82BBB6070394D40005131CEDF6C21407876DD5B91384D40C04CF910546D2140B041D13C80354D40C053E57B46622140E8B2B5BE48304D4040CDE506430521405807793D98224D40602975C938CE2040B8656B7D91204D402038A110017F204038D8463CD9194D40A05A99F04B7D204058F833BC59194D4040B5DD04DF7C2040281A6B7F67154D408045B9347E7120405837177FDB0F4D40A020B248136F204030F38FBE490F4D4000A7B1BD166C2040C8F19881CA0E4D40603F373465672040588E0244C10E4D408053E57B46622040883FFCFCF70E4D40A07631CD744F2040081BD7BFEB114D4080B08D78B2432040889FAA42030D4D40A08B868C47412040885A457F680C4D40404278B4713C2040000C0401320C4D40406893C327BD1F40D88BDAFD2A0A4D4040C64FE3DE3C1F40F8C9DFBDA3084D40C0D6A88768A41E400048A643A7054D40C0F5285C8F821E4008D061BEBC024D40407A19C5727B1E406055A18158024D4080E7FC14C7711E40D006600322024D40006893C3273D1E4030F911BF62014D4040977153031D1E4010E2E7BF07014D408093179980EF1D40682E54FEB5004D4040D576137C731D4008274D83A2014D40C0A9F23D23011D4008BEDBBC71044D40401A3048FAE41C40B068ACFD9D054D404007B474059B1C409048BF7D1D064D40401E8A027D521C4058431B800D044D4080A27A6B604B1C40E0C77C40A0034D40C032384A5E4D1C4088992842EA024D4080301004C8501C40B853E57B46024D40C0E1B19FC5521C40A8C2D84290014D40807C462234521C409018213CDA004D4000DF52CE174B1C40607C7C4276004D40804D689258321C403020ED7F80FF4C40C07E6E68CA0E1C40A0DA6E826FFE4C40804C361E6C011C40B85FE97C78FE4C4000D6AD9E93BE1B40789FAA4203054D40803106D6719C1B40E009A1832E074D404094490D6D201B4078AEEFC3410E4D4040BFD2F9F0EC1A4020DB87BCE50E4D4080643E20D0E91A40804E417E36084D4040AD4CF8A56E1A4008301004C8084D40C03465A71F641A4030E109BDFE084D404082C8224D3C1A40D0BEB9BF7A0C4D40006BBB09BE391A40A8BC5642770F4D40C0F755B950591A40582B137EA9134D4040D576137C731A4058FB743C66164D4040240C0396BC1A4080812040861A4D400038BF61A2111B408060C77F811E4D40C0B950F9D7021B40789C69C2F61F4D404038BA4A77771A4050465C001A214D4040013274EC701940A06BED7DAA224D40400FB6D8ED631940402C0DFCA8224D40008B7269FC221940386E15C440274D4040AD4CF8A5EE1840A8AAD0402C294D40C03106D671DC1840E073D2FBC6294D40804B3B35979B1840881EA33CF32A4D4040F1D8CF62891840B0622AFD842B4D40C088450C3B0C1840786649809A304D404084F068E3F81740583D997FF4314D40005090D8EEEE1740306211C30E334D4080D6A88768E41740303B3602F1344D40C082C30B22E217400048A643A7354D40402FDE8FDBDF1740E000DE0209384D4000F52D73BADC1740584CDE00333B4D40405512D907D91740E0F4D901D73B4D40C069C020E9D31740B859677C5F3C4D40C0A143E048C0174080397AFCDE3C4D4000EFAB72A1B21740503A58FFE73C4D4080A148F7739A174038D505BCCC3C4D4080861DC6A48F174050888043A83C4D4040643E20D069174008240C03963C4D40C0F42D73BA1C17408896E7C1DD3D4D40403F373465071740081286014B3E4D4000BC783F6EFF16402029B000A63E4D40000C040132941640D8CDFE40B9454D408007AF5DDA80164088A52C431C474D40003E4162BB7B1640600ABABDA4474D400079E750860A1640306893C327554D4040FBAF73D30616405031957EC2554D4000726F7EC3D4154028F38FBE495F4D40802E01F8A7D4154078CADC7C23604D40408D9AAF92DF15404873B9C150614D40C0E1B19FC5121640508BC1C3B4694D40005A677C5F2C1640909C69C2F66F4D404096766A2E371640B059677C5F744D4000E5D4CE30351640D0F4D901D77B4D40C0633E20D0291640D0CDFE40B97D4D400018080264281640D8D38041D27F4D40409BC6F65A301640382CF180B2834D40C0EC832C0B361640000C040132844D40C007AF5DDA40164010DFA63FFB834D40008B6D52D1481640D8C77C40A0834D4000022D5DC1D6164000D6E3BED57C4D408014ADDC0BDC1640F09C9FE2387C4D4000465ED6C4D2164070855B3E92784D4000166EF948FA164018028063CF764D4040317903CC2C1740F863CC5D4B764D404053B0C6D9441740C007AF5DDA764D4080ED2B0FD243174038834D9D47794D40009CC1DF2F561740D8AF743E3C7B4D40C0C64ACCB36217403814E97E4E7B4D40C0035ABA826D174030E78BBD177B4D408021E4BCFF7F1740101E8A027D7A4D40002861A6ED8F1740C8EE5701BE794D400070422102BE1740D0BB783F6E774D4080A7CAF78CC41740803FFCFCF7764D40404F95EF19091840D0EE5701BE714D40407A19C5723B1840E07FD6FCF86D4D4080B1A19BFD411840507FBDC2826D4D4000A3755435711840E8AF743E3C6B4D40408D95986785184008D061BEBC6A4D4040FCAA5CA8AC184090812040866A4D4000DC2F9FACE81840D8D03FC1C56A4D408015E0BBCDEB18403014E97E4E6B4D4080809BC58BE51840809065C1C46B4D408090F46915CD1840E0F4D901D76B4D4000FF092E56B41840F82CCF83BB6B4D400076C4211BA81840D87954FCDF6B4D4080E1B19FC592184058F5F23B4D6C4D4040F1D8CF62891840F0230C03966C4D40409BC6F65A701840A868ACFD9D6D4D400018080264681840305FD042026E4D4000FF04172B5A1840E076137CD36E4D404047E6913F481840B0B393C151704D4040704221023E184038F911BF62714D40C0D026874F3A1840A8A10DC006724D40C06ABB09BE3918406034D6FECE724D4040C64FE3DE3C1840B8622AFD84734D4040F52D73BA5C1840A86E2EFEB6774D404052B81E856B1840905D86FF74794D404096766A2E771840381DACFF737A4D4080D5AD9E937E1840B8984A3FE17A4D4040FBAF73D3861840604CDE00337B4D4040A7CAF78CC41840505260014C7D4D40C0EA56CF49DF1840D8AC33BE2F7E4D4040B728B34106194080A52C431C7F4D40009F20B1DD9D1940306BD44334824D4000A3755435F11940382CF180B2834D404007B474055B1A40081B498270854D40C0E9245B5D6E1A40801B62BCE6854D40401286014B7E1A405028D2FD9C864D404078F17EDC7E1A40C05626FC52874D40403BE2900D741A40F820CB8289874D4080634337FB031A4078AEEFC341864D40005612D9079919408087A2409F844D40C0B950F9D7821940D80CE2033B844D40000ADCBA9BD71840D8CABDC0AC804D40803D0AD7A3B01840084E2844C07F4D4040E3A7716F9E1840E009A1832E7F4D4000B728B3418618407848BF7D1D7E4D40007D410B09781840805182FE427D4D4000884A2366661840002DCF83BB7B4D408052B81E852B1840A87A32FFE8734D4040643E20D0291840886308008E734D40803465A71F241840286211C30E734D4040B1A6B2281C184050FEB5BC72734D4080B81E85EB111840A0BF97C283744D40403EEC8502E6174088094E7D207B4D4080F1F09E03DB1740707808E3A7814D40809B5434D6BE174008F775E09C814D40806893C3277D17403038F581E4874D4040EA5BE674791740B8E0F08288884D408096766A2E771740100F45813E894D40802634492C791740A8A10DC0068A4D400082C8224D7C1740084BE7C3B38A4D404008AF5DDA8017402814E97E4E8B4D40004C6DA9838C174028F6D03E568C4D408013B35E0C95174050888043A88C4D4080E1B19FC5D21740E0F19881CA8E4D40C0921CB0AB0918409054C37E4F924D4040A7CAF78C0418403035B401D8924D408053E57B46021840806308008E934D4080E3A25A4404184038F6D03E56944D40C03F373465071840080341800C954D400054E57B46421840E08BDAFD2A9A4D40809CC1DF2F961840805704FF5B9F4D40C015E0BBCDAB1840886649809AA04D40C0CDFE40B93D194070A52C431CA74D40807E6E68CA4E1940F84D2844C0A74D408046EBA86A621940884E417E36A84D40C0E2AC889A7819406001F73C7FA84D4080416491269E194008CADFBDA3A84D40C04069A851B81940507C7C4276A84D4080D253E410D11940B0E0F08288A84D40C03106D671DC1940E0CABDC0ACA84D40C04B3B3597DB1940D80F238447A94D40C07B462234D2194028266F8099A94D400095490D6DA01940E073D2FBC6A94D40C007AF5DDA801940E073D2FBC6A94D40006AC020E953194078ABAE4335A94D4000A243E048401940282F3201BFA84D4000F2D3B8372F1940306552431BA84D4040378DEDB520194030F38FBE49A74D40004F95EF1909194090CC07043AA54D40802634492CF91840885A457F68A44D4000931CB0AB891840D8A9F23D23A14D4080D5AD9E937E184008E2E7BF07A14D4000310BED9C76184020F911BF62A14D40807A19C572FB1740386BD44334AA4D40C02BBB6070FD1740D082177D05AB4D4040B1A6B2281C1840B05626FC52AF4D40C0368DEDB5201840B09B8BBFEDAF4D40002A8E03AF261840109D82FC6CB04D40C03C0FEECE4A18407881204086B24D40C01FB75F3E691840A0A78FC01FB44D40C0ED7E15E0DB184030232E008DBC4D4000E17F2BD9E1184010DC65BFEEBE4D4000B0743E3CEB184028EACC3D24C04D4040A3755435F1184008CADFBDA3C04D40C06ABB09BEF91840305C8FC2F5C04D40808ECC237F90194088CC07043AC54D40C0BFD2F9F0AC1940285FD04202C64D40C0F0D8CF62C91940D8F19881CAC64D4040F2052D24E01940B0A44E4013C74D4080295C8FC2B51940286552431BC84D404047E6913F0819408081204086CA4D40001286014BFE1840109D82FC6CC84D408059677C5FEC1840080341800CC54D404022DFA5D4E51840D8F4D901D7C34D404093179980AF18407887A2409FBC4D40000E315EF3AA184080423D7D04BC4D4080977153039D1840286BD44334BA4D4040C554FA09971840608BC1C3B4B94D4040634337FB831840504F1F813FB84D4080931799806F184028DB87BCE5B64D40406AC020E9531840386893C327B54D4080E6012CF2CB1740805182FE42AD4D4000B728B341C61740809FAA4203AD4D408082C8224DBC174028D505BCCCAC4D4080FE092E56B41740286893C327AD4D40C0F1D3B837AF174000CD203EB0AD4D40C0F0D8CF6289174028E78BBD17B34D4080B1A19BFD81174030F6D03E56B44D40C05B94D920831740D0FA5B02F0B54D40009DF3531C8717402820ED7F80B74D4080F8872D3D8A1740784E417E36B84D404020B248138F17409093A641D1B84D40C09BC1DF2F961740100F45813EB94D4040C74ACCB3A2174050465C001AB94D40C06BED7DAAAA1740582E54FEB5B84D40004A0ED8D5C41740B0656B7D91B84D404091EF52EAF2174008E2E7BF07B94D40001E8A027D921840600DFB3DB1BC4D404007B474059B1840889FAA4203BD4D40C045B41D539718401048A643A7BD4D4080E4D9E55B8F184028E44A3D0BBE4D4000E4A25A4484184078AEEFC341BE4D40402634492C791840001286014BBE4D40C0716F7EC3941740889FAA4203BD4D4000D8D5E4293B174050431B800DBC4D40C0FF04172BDA16403038F581E4B74D400020B75F3EA91640C819A721AAB44D4000FBB0DEA8A5164048C8409E5DB44D40C0AF7614E7A81640D849287D21B44D4000713D0AD7A31640009A417C60B34D4000EA5BE674B9164058888043A8B44D40004F95EF19C91640381A6B7F67B54D408037BF61A2D11640E0CDFE40B9B54D40403465A71FE41640081286014BB64D4040DAFD2AC0F71640608E0244C1B64D4000861DC6A40F1740883FFCFCF7B64D40C0B0A6B2281C17406040DAFF00B74D40801808026428174028DB87BCE5B64D40803D0AD7A33017408060C77F81B64D4040643E20D0691740B85CA8FC6BB14D40804F90D8EE6E1740E0F71A82E3B04D4040EFAB72A1721740584F1F813FB04D40C0D576137C731740B8BC564277AF4D400040321D3A6D1740E00CE2033BAC4D40C099D024B1641740E87954FCDFAB4D408021E4BCFFBF16403820ED7F80A74D4040A243E04880164028E109BDFEA84D4080B950F9D7821640484CDE0033AB4D40800B056C07731640C0C804FC1AAD4D40406CE7FBA9711640E0D0782288AD4D40C07D737FF568164040E0810184AF4D4040105B7A34651640E0DF675C38B04D40409CF86A47611640703C11C479B04D4000D1251C7A5B1640B8282504ABB04D40C0573CF548531640A0ED0A7DB0B04D4000A69E05A14C1640D02500FF94B04D40C08847E2E5491640E0DF675C38B04D40C003594FAD4E1640B02E6EA301B04D404075931804561640C05B2041F1AF4D40C052EC681C5A1640204B033FAAAF4D40C0D8D479545C16400851F70148AF4D408032384A5E4D1640F8264D83A2A94D4000F9872D3D4A1640305C8FC2F5A84D408051BD35B045164038172AFF5AA84D40C01A3048FA241640F80B040132A44D404060E97C781616400015C78157A34D4080A27A6B600B1640504CDE0033A34D4040A3755435F11540109A417C60A34D40004B3B3597DB1540789065C1C4A34D40C06211C30E931540D0031F8315A54D40C0921CB0AB891540A0B6D4415EA54D4080C422861D261540B059677C5FAC4D40004B3B35971B154010A0C37C79AD4D4040301004C8D014400809C38025B74D40C0B7072120BF1440689D6340F6BE4D400096766A2EB71440D8B2B5BE48C04D40408EC70C54B6144088457EFD10C14D40C07C410B09B8144040D8463CD9C14D40C038BA4A77371540D0D38041D2CF4D40C02634492CB91540B0C2D84290D94D40C0298E03AFE61540603A58FFE7DC4D4040A59D9ACBED1540E0B5F63E55DD4D4080DAFD2AC0F71540580438BD8BDD4D40803C0FEECE0A1640281DACFF73DA4D400091F469150D1640588BC1C3B4D94D40C0A4A2B1F60716408896E7C1DDD54D4080F30016F9051640D0031F8315D54D40C069C53714EE1540C8CDFE40B9CD4D40408ECC237FD01540B0AD11C138C64D40C04E97C5C4D6154058BF44BC75C24D4000EFAB72A1F21540904B00FE29C34D4080D8D5E429FB1540B8DDAF027CC34D40C0F5285C8F021640B87A32FFE8C34D40803AE7A7380E1640383B3602F1C44D400037FFAF3A121640583D0B4279C54D4080A148F7731A1640D076137CD3C64D4080DB2F9FAC281640D8C1FA3F87C94D40806BED7DAA2A16408854C37E4FCA4D4040C2FA3F8729164000E869C020CB4D40806E15C440271640D0F4D901D7CB4D40402FDE8FDB1F1640D8031F8315CD4D4080A148F7731A1640B068ACFD9DCD4D40C04D637B2D181640009700FC53CE4D4000B3CEF8BE1816403841B8020ACF4D40803106D6711C1640886649809AD04D40402A8E03AF26164000C79E3D97D34D40C0633E20D02916406070784144D44D404091EF52EA32164000A0C37C79D54D408084F068E3381640305FD04202D64D400022E4BCFF3F1640B0DA6E826FD64D40008B6D52D1481640588E0244C1D64D4080012D5DC1561640808D2441B8D64D4000ED832C0BB61640507FBDC282D54D404096766A2EF71640588E0244C1D64D40403E4162BBFB1640905704FF5BD74D40006BBB09BE39174068F5F23B4DDC4D4000AAF23D23411740580DFB3DB1DC4D40C0921CB0AB491740080341800CDD4D4080861DC6A48F1740D8F19881CADE4D4000BEA08504BC1740B85FE97C78DE4D40C0E3A25A44C417408048BF7D1DDE4D4040301004C8D01740D87FD6FCF8DD4D40C0D026874F3A1840803FFCFCF7DE4D4040E4A25A44441840586D37C137DF4D40404D689258321940B8622AFD84EB4D40406BBB09BE39194038DEC83CF2EB4D4080D5AD9E933E194038232E008DEC4D4040666B7D91401940306893C327ED4D4000E5D4CE30351940889FAA4203ED4D4000C87C40A0D31840001E8A027DEA4D4000013274ECB0184088ABAE4335E94D40C0D8D0CDFEA01840587C7C4276E84D40403D0FEECE8A1840506D37C137E74D40C077F17EDC7E1840D8AC33BE2FE64D4040BFD2F9F06C184010D6E3BED5E44D4080D8D5E4293B1840B074B0FECFE14D40804D68925832184000C11C3D7EE14D4000E3A7716F1E184020E109BDFEE04D4080EFAB72A1F2174030172AFF5AE04D40009AD024B1E417400018080264E04D4080F52D73BA5C1740C88BDAFD2AE24D4080A3755435311740E07954FCDFE34D4000DF52CE17CB16405807793D98EA4D40807C462234D2164028DB87BCE5EE4D40C03D0AD7A3F01640B059677C5FF44D40C0B5F63E55151740B85FE97C78F64D4040E6012CF24B1740584F1F813FF84D404008AF5DDA801740000F45813EF94D40C009DCBA9B971740A8C2D84290F94D40C090F46915CD1740A8C2D84290F94D4040C554FA09D71740B074B0FECFF94D4040E3A7716FDE174030F04E3E3DFA4D4080D6A88768E4174010D061BEBCFA4D40C059677C5FEC174060431B800DFC4D40C0573F36C9EF1740B8ECF483BAFC4D4040963FDF16EC1740B0B6D4415EFD4D40008ECC237FD0174028172AFF5A004E404069C53714EE1740D87954FCDF034E40C0FDD7B9690318408848BF7D1D064E40404B3B35971B184030EACC3D24084E40408A7269FC221840B0656B7D91084E40804F90D8EE6E1840B868ACFD9D0D4E4040931CB0AB491840B0AD11C138164E40808B6D52D14818404840DAFF00174E40C0F0D8CF62491840B86E2EFEB6174E40C0CCCCCCCC4C18400018080264184E4000726F7EC354184050F833BC59194E400038BF61A2D11840A89509BFD4254E40006AC020E9531940500438BD8B2D4E404083C30B22E21940C888997D1E354E4000643E20D0E91940507FBDC282354E4000E4A25A44041A408060C77F81364E40C0B3CEF8BE181A40883FFCFCF7364E40C053E57B46421A4028DB87BCE5364E4000DE57E542651A40009700FC53364E400085F068E3781A40E0CDFE40B9354E40C0F0D8CF62891A40B89ECC3FFA344E40402861A6ED8F1A40A8BF97C283344E400077BF0AF08D1A40F82CCF83BB334E40804C361E6C811A40104BE7C3B3324E400069C537146E1A40B8B393C151304E4080B0A6B2285C1A4030327381CB2D4E400038BF61A2511A40002DCF83BB2B4E408094490D6D201A40D8A9F23D23214E40C04E95EF19091A40E0C77C40A0134E4080A7CAF78C041A4000C45DBD8A0E4E4000E17A14AE071A40809FAA42030D4E40008ECC237F101A40D88BDAFD2A0A4E4040583A1F9E151A40B874B0FECF094E40805512D907191A40F81D8A027D0A4E40C0438CD7BC1A1A4058707841440C4E4000AC1F9BE4171A40D0BB783F6E0F4E40C0FF04172B1A1A4070A2EBC20F124E4000C74ACCB3221A4080CC07043A154E4040CAA48636501A4010CADFBDA3204E4040EFAB72A1721A40F82F1004C8284E40C06ABB09BE791A40D08BDAFD2A2A4E40C099999999991A40B8BC5642772F4E40C0E2A7716F9E1A40E000DE0209304E408038BA4A77F71A40A09B8BBFED374E40C05FE97C78161B40001E8A027D3A4E40C03465A71F241B4058793BC2693B4E40807F69519F341B40B0A78FC01F3C4E40801B62BCE6551B409087A2409F3C4E40C0EC832C0BB61B4038E44A3D0B3E4E40C0B950F9D7C21B4010E52840143E4E40006CED7DAAEA1B40D8CDFE40B93D4E40404C6DA9830C1C40C8031F83153D4E40009CC1DF2F161C40A8716F7EC33C4E4000FCAA5CA82C1C4028F6D03E563C4E4000EA5BE674391C40B059677C5F3C4E4080A27A6B604B1C40809FAA42033D4E40406211C30E531C40001B4982703D4E400018080264681C40508E0244C13E4E4080AD4CF8A56E1C40306E15C4403F4E40000E315EF36A1C402838F581E43F4E40402FDE8FDB5F1C40306552431B404E40C00D315EF3EA1B40282F3201BF404E40009AD024B1E41B40881B62BCE6454E4080921CB0AB091C4008D9243FE2494E40C07E6E68CA0E1C406007793D984A4E400077BF0AF00D1C40584CDE00334B4E404054E57B46021C40E8AF743E3C4B4E40C0313D6189E71B40B853E57B464A4E4040E4D9E55BCF1B4080457EFD10494E400083C30B22A21B40B068ACFD9D454E40C0E3D9E55B8F1B40D8A6B1BD16444E400008AF5DDA801B40C053E57B46424E4080BB783F6E3F1B4000C45DBD8A3E4E40404C361E6CC11A40B0B393C151384E4080013274ECB01A40888461C092374E40004913EF009F1A40F8DB65BFEE364E40003888D68A861A40588E0244C1364E40407A19C5727B1A40883FFCFCF7364E40C00D315EF36A1A40B06E2EFEB6374E40C03465A71F641A4080C9C6832D384E40404913EF005F1A40302F3201BF384E40C08713984E5B1A4068F833BC59394E40C05A99F04B5D1A40D88BDAFD2A3A4E408051BD35B0451A403035B401D83A4E404041649126DE1940B0656B7D91384E40C021E4BCFF7F194008CD203EB0354E4000378DEDB5601940B8A78FC01F344E4040B950F9D7421940301DACFF73324E4040999EB0C433194008274D83A2314E4040C2FA3F8729194028F911BF62314E4000416491261E1940B85CA8FC6B314E40004F95EF19091940803CBB7CEB314E404008AF5DDA0019408854C37E4F324E40402EE3A606FA1840D8D03FC1C5324E40006E15C440E71840D80CE2033B344E408082C30B22E2184038D505BCCC344E40C05DC136E2D918403014E97E4E334E4080A243E048C01840B0BF97C2832C4E40003465A71FA4184030DEC83CF2234E40005DC136E299184000D9243FE2214E40403AE7A7388E18405837177FDB1F4E40004A0ED8D5841840F8298E03AF1E4E4040BEA085047C1840009700FC531E4E40404D6892587218402829B000A61E4E40C0A59D9ACBED1740A8AD11C1381E4E4000F855B950991740009A417C60134E404051BD35B08517408848BF7D1D064E4000A01B9AB2831740D0B5F63E55054E4080295C8FC2751740B8622AFD84034E4040643E20D0691740001E8A027D024E404054E57B46421740B8656B7D91004E40004D689258321740D0D38041D2FF4D4000FBAF73D3061740D8AC33BE2FFE4D40406893C327FD1640101286014BFE4D4040F0A65B76D81640109D82FC6C004E408037BF61A2D11640D8F71A82E3004E400082C8224DBC1640B0ECF483BA044E4040CFBEF220BD164020A88C7F9F054E40005EBC1FB7BF164010D3A23EC9074E4000583A1F9E9516402835B401D8124E4000CDCCCCCC8C1640081E8A027D124E40006CED7DAA6A164070A2EBC20F124E4000D253E410511640583D997FF4114E4080A7CAF78C44164070A2EBC20F124E4000944E24983A16406055A18158124E40404D68925832164010D061BEBC124E40C03F321D3A2D1640A8B0524145134E4080035ABA822D164000DFA63FFB134E4040E9297288881640B09B8BBFED274E4080E7FC14C7B11640A09509BFD42D4E40802634492CB9164080AEEFC3412E4E40807E6E68CACE16405828D2FD9C2E4E40003F3C4B90E11640E009A1832E2F4E4000A69D9ACBED1640804E417E36304E40404D689258F216408093A641D1304E4080F9821612F01640D0C1FA3F87314E40C01FB75F3EE91640283E7782FD314E40809E20B1DDDD164038D8463CD9314E404014B35E0CD51640D0C1FA3F87314E404051BD35B08516405876FA415D2E4E40405EBC1FB77F16409096E7C1DD2D4E40008FC70C5476164058888043A82C4E4080035ABA822D164000E2E7BF07214E4080D47B2AA7CD154000DC65BFEE164E40801A3048FAA41540786649809A104E40C08713984E9B1540C8F71A82E3104E4000E7FC14C771154010D061BEBC124E404039454772391540D08EFF0241184E40C09BC3B5DAE3144060B5A4A31C1A4E400063B66455E41440F8A2AF20CD1A4E4040CCEF3499411540585EB9DE36214E4000CC99ED0A3D1540906CE7FBA9214E4040963FDF16AC1440A0DDAF027C234E4080D6A88768A41440A8ECF483BA244E404038BF61A291144038F6D03E562C4E40001E8A027D9214409048BF7D1D2E4E4040AE47E17A94144030DB87BCE52E4E40805512D9079914402820ED7F802F4E4040301004C8D01440306BD44334324E4000F6285C8F021540D0F19881CA364E400052B81E85EB144030DEC83CF23B4E40006CED7DAAEA144030232E008D3C4E40C00D315EF3EA1440001B4982703D4E400045B9347EF11440D876137CD33E4E4080921CB0AB091540D0F71A82E3404E4000977153031D15404855A18158424E400016E0BBCD2B1540604CDE0033434E40C038BA4A77371540904B00FE29434E404047E6913F481540381DACFF73424E4080703D0AD7631540786649809A404E4080A8FC6B79751540B8A44E40133F4E4040E4D9E55B8F1540286893C3273D4E40C05FE97C78D615403038F581E4374E4000B0743E3CEB15408060C77F81364E40C0D026874FFA154008CD203EB0354E4040D253E410111640905182FE42354E40409F20B1DD1D1640306893C327354E4040963FDF162C1640C888997D1E354E4080A59D9ACB6D1640C888997D1E354E40C08A6D52D1881640306893C327354E40C0CAA48636901640B0E3310395354E4000E4D9E55BCF1640D88BDAFD2A3A4E40800C040132D41640D0D03FC1C53A4E4000448CD7BCDA164088A86DC3283C4E4000F52D73BADC1640D876137CD33E4E40809CF86A47E11640109700FC53564E4080D47B2AA7CD16408018213CDA584E40401A3048FAA416405834D6FECE5A4E4080B950F9D7821640A8B05241455B4E400022E4BCFF3F164030172AFF5A584E40802CB64945231640B874B0FECF514E4040013274EC701540B8B393C151484E4040FBAF73D3461540B8BC564277474E40805DC136E2191540488E0244C1464E408023DA8EA90B1540D8F19881CA464E4040A243E0480015405040DAFF00474E404069C53714EE1440580ABABDA4474E4040A27A6B60CB1440803CBB7CEB494E4040F2052D24601440084BE7C3B3524E4000B1A6B2285C1440F814C78157534E40C09999999959144050431B800D544E40008D9AAF925F144030232E008D544E4000643E20D069144030D505BCCC544E40C0D24ECDE576144078397AFCDE544E400054E57B4682144050888043A8544E40406211C30E931440A87A32FFE8534E4000EA245B5DAE144080ABAE4335514E404082C8224DBC1440B0B393C151504E40C022DA8EA9CB14402820ED7F804F4E40003206D671DC1440588E0244C14E4E4040884A2366E614402829B000A64E4E40C0C1FA3F87E914400809C380254F4E4080301004C8901440381DACFF735A4E4080F30016F9851440B0622AFD845B4E4040E5D4CE3075144010BEDBBC715C4E40C0FBAA5CA86C144028D505BCCC5C4E4040B3CEF8BE581440281A6B7F675D4E40404B3B35971B1440C809A1832E5F4E404096766A2EB7134080AEEFC341664E40C03D4162BBBB1340F8298E03AF664E40406893C327FD13406040DAFF00674E40804C6DA9830C1440D8AC33BE2F664E400018080264681440D0B837BF61624E4000EB56CF49DF144008E52840145E4E400007B474051B1540A859677C5F5C4E40C02CB6494523154000DFA63FFB5B4E4040A375543531154030E78BBD175B4E4040BEA085043C1540303E7782FD594E40806893C3273D154078ABAE4335594E40806ABB09BE3915406001F73C7F584E40C0D026874F3A1540D876137CD3564E4000B81E85EB511540286211C30E534E4000F52D73BA5C1540383E7782FD514E40806BED7DAA6A154090457EFD10514E40C0EC832C0B761540D8F71A82E3504E40803D0AD7A3B01540D8B2B5BE48504E4080BEA08504BC1540D8B2B5BE48504E40C021E4BCFFBF154050431B800D544E404078F17EDCBE154078397AFCDE544E40801A3048FAA415405073B9C150594E40808C9AAF929F154040D8463CD9594E40404391EEE774154088CC07043A5D4E40406211C30E531540B8DA6E826F5E4E40004F95EF19491540908D2441B85E4E4000E7012CF20B154028172AFF5A604E40C0B1A19BFD01154000CADFBDA3604E4040EA5BE674F9144010E2E7BF07614E40403BE2900DF41440A8C2D84290614E4040F9821612F01440B853E57B46624E4040AB24B20FF21440306211C30E634E4080300BED9CF61440682B137EA9634E4000CCD1E3F766154008240C03966C4E40C0EC832C0B761540001B4982706D4E4080A243E04880154008CD203EB06D4E40C0DAFD2AC0B715406828D2FD9C6E4E40409F1B9AB2C31540588E0244C16E4E4040B81E85EBD11540808D2441B86E4E4040D6A88768E4154010E52840146E4E4000AD4CF8A5EE1540D87FD6FCF86D4E40C03D4162BBFB1540285FD042026E4E40807E6E68CA0E1640D8C43BC0936E4E4040EB56CF491F1640B85626FC526F4E408046EBA86A221640B0E9B303AE6F4E40C009DCBA9BD71540881EA33CF3724E40C01FB75F3E691540306552431B704E400046B41D53571540A8BC5642776F4E40C076BF0AF04D1540B8AD11C1386E4E40C0E8297288481540A8716F7EC36C4E4040490ED8D5441540804B00FE296B4E40404C361E6C411540001E8A027D6A4E4000C64FE3DE3C154030D8463CD9694E40C0A8FC6B79351540805D86FF74694E40404F95EF19091540F8D2A23EC9674E404078F17EDCFE1440B06E2EFEB6674E404014B35E0C95144008BB9A3C65674E4040E2AC889A78144020172AFF5A684E40C094F430B47A1440A8353FFED26A4E4000EFAB72A1721440E0B837BF616A4E400018080264681440E0066003226A4E4040F52D73BA5C1440383E7782FD694E40803AE7A7384E1440A8A10DC0066A4E40804C361E6C411440E0B837BF616A4E400085F068E3381440D8D03FC1C56A4E4080E7FC14C7311440504CDE00336B4E408059677C5F2C1440789065C1C46B4E4040D6A88768241440889FAA42036D4E40C0F1D3B837EF1340B8AAD0402C794E404069C53714EE1340A874B0FECF794E40C0573F36C9EF13406007793D987A4E400002BC05120414400800000000804E40C0490ED8D5041440E0A6B1BD16844E4040A5A2B1F6071440A8716F7EC3844E4000CDCCCCCC0C1440A0B6D4415E854E4080B3CEF8BE18144058FB743C66864E4000941799802F1440B8E9B303AE874E40004069A851381440D000DE0209884E404023DA8EA94B1440806649809A884E40C06BED7DAA6A144060F833BC59894E4040FDD7B96983144078ABAE4335894E4000323D6189A714408018213CDA884E40C05417F032B31440E0CABDC0AC884E4040EFAB72A1F2144030F38FBE49874E4000D8D5E429FB144010DC65BFEE864E40C0B1A19BFD011540A05FE97C78864E40C03AE7A7380E154008240C0396844E40C013B35E0C15154088A86DC328844E400020B75F3E291540886308008E834E40C08EC70C5436154058FEB5BC72834E4000045ABA82AD1540B8B0524145834E4000E2B19FC5D21540A8BF97C283844E4080F755B950D91540781B62BCE6854E400022DFA5D4E5154010DC65BFEE864E4000AD4CF8A5EE1540386E15C440874E4040A243E04880164058793BC2698B4E40806E15C440E71640E0BEB9BF7A8C4E40C00D315EF32A174038ED0DBE308D4E40407497C45951174030327381CB8D4E40404F90D8EEAE1740104E2844C08F4E40C03D0AD7A370184008DC65BFEE8E4E40C0CDFE40B97D1840D8F19881CA8E4E404078F17EDCFE1840A8A78FC01F8C4E40808B6D52D10819408815E0BBCD8B4E4080861DC6A40F19401015C781578B4E408013B35E0C1519405834D6FECE8A4E40C05512D907191940D08BDAFD2A8A4E40C04E95EF19491940507C7C4276884E40406893C3277D1940B89B8BBFED874E40C0368DEDB5A01940B0E0F08288884E408032384A5E0D1A40805A457F688C4E4080F52D73BA5C1A40009A417C60934E404085EB51B89E1A4050793BC269934E40C021E4BCFF3F1B4028F04E3E3D924E408023DA8EA94B1B40B8A10DC006924E40C0573A1F9E551B40508BC1C3B4914E40C09E20B1DD5D1B406073B9C150914E40C08DCC237FD01B40B8E67283A18A4E404007B47405DB1B40E0C1FA3F87894E4000F1D8CF62091C40B0A10DC006824E4000FED7B969831C40908D2441B8764E408051BD35B0851C40205FD04202764E4080A7CAF78C841C40D888997D1E754E4040666B7D91801C4010D061BEBC724E4000BEA085047C1C40A8AAD0402C714E40804069A851781C406001F73C7F704E4000A8C5E0616A1C4010E52840146E4E40007F69519F741C408848BF7D1D6E4E40800D36751E851C40D876137CD36E4E4080B81E85EB911C405837177FDB6F4E4000ED7E15E09B1C4000E2E7BF07714E40002A8E03AFA61C4000E869C020734E400052B81E85AB1C40580DFB3DB1744E40C059677C5FAC1C40A8E3310395754E4000045ABA82AD1C4020EACC3D24784E400052B81E85AB1C409018213CDA784E40002DB64945A31C40000F45813E794E40409CC1DF2F961C4028F911BF62794E40803BE2900D741C40B8A10DC0067A4E4040068200196A1C406055A181587A4E408007B474055B1C40604CDE00337B4E4000931CB0AB491C40B0716F7EC37C4E404026396057131C4050888043A8844E40C06893C327FD1B40D8066003228A4E40C0230C0396FC1B4090992842EA8A4E40802BBB6070FD1B40C8C77C40A08B4E408007AF5DDA001C4068F5F23B4D8C4E4080AE47E17A141C4090397AFCDE8C4E400095490D6D201C40A89ECC3FFA8C4E4040BEA085043C1C4030D505BCCC8C4E404014B35E0C551C40A89ECC3FFA8C4E40803D0AD7A3B01C40A89509BFD48D4E4040666B7D91401D40D8D38041D28F4E4000D34ECDE5B61D40686D37C137974E4080F52D73BA9C1D409093A641D1984E4080E3A25A44841D40B0AAD0402C994E4040D576137C731D40503D997FF4994E40C0E9245B5D6E1D4090812040869A4E4040DE57E542651D40382CF180B29B4E4040DAFD2AC0371D4090397AFCDEA44E404096766A2E371D4000CD203EB0A54E40004391EEE7741D40888D2441B8AE4E40807C462234D21D4008C45DBD8AB64E4040EB56CF49DF1D40F820CB8289B74E40404F90D8EEEE1D4038172AFF5AB84E40C069C020E9131E40F8264D83A2B94E4040E3A7716F1E1E4040D8463CD9B94E4080D38041D2271E40D08BDAFD2ABA4E408038BA4A77371E40D8FD9C82FCBA4E40C06F4221023E1E40B8DDAF027CBB4E408047E6913F481E40580DFB3DB1BC4E40C088450C3B4C1E40B8B6D4415EBD4E40C0490ED8D5441E4010A0C37C79BD4E40807A19C5723B1E40286893C327BD4E40408713984EDB1D405073B9C150B94E4080F8872D3DCA1D40806649809AB84E4040EFAB72A1B21D4008BB9A3C65B74E4040CAA48636501D40286552431BB04E4040240C03963C1D4068FB743C66AE4E4000416491261E1D40808AE3C0ABA94E40C009DCBA9B171D40302CF180B2A34E4040013274EC301D40C88558FD11A04E4080A8C5E0616A1D40B0B393C151984E4000F52D73BA1C1D4060F5F23B4D944E40404E637B2D981C40B853E57B46924E408041649126DE1B4038E44A3D0B8E4E40C01D8A027DD21B4008E52840148E4E40406893C327BD1B406028D2FD9C8E4E40404391EEE7B41B40783FFCFCF78E4E4040013274ECB01B4048853FC39B8F4E40000E315EF3AA1B40285C8FC2F5904E4000A8C5E061AA1B40E0EE5701BE914E4080FBAA5CA8AC1B405082FE428F924E4000F3052D24A01B40500DFB3DB1944E40403E3C4B90611B405076FA415D964E40C0B1A19BFD411B40E009A1832E974E40005612D907191B400809C38025974E4080A8FC6B79F51A40888D2441B8964E404076C4211BE81A40002A8E03AF964E408007B47405DB1A40E076137CD3964E40C0F755B950591A40084BE7C3B39A4E4040E9297288481A40A8DDAF027C9B4E40800F5EBBB4411A4038DEC83CF29B4E4080FDD98F14411A4018C64FE3DE9C4E40009548A297411A40F02ADD5D679D4E40C046E6913F481A40E82494BE109E4E40007F6E68CA4E1A40883FFCFCF79E4E4080F52D73BA5C1A402838F581E49F4E40003E4162BB7B1A40B0C2D84290A14E40C07E6E68CA8E1A4030E78BBD17A34E4080F30016F9C51A40806308008EAB4E4080F0D8CF62C91A405070784144AC4E4040EB56CF49DF1A40383E7782FDB14E408097715303DD1A40084BE7C3B3B24E4000F855B950D91A400015C78157B34E40008ECC237FD01A40109A417C60B34E4080356090F4C91A40B0984A3FE1B24E4040DBF813955D1A40E0B837BF61A24E40C06F9692E5141A40189FAD83839F4E40000936AE7F271A40D079FF1F279A4E4080A7CAF78C041A4070ABAE4335914E40C01186014BFE1940D8CABDC0AC904E4080BEA08504BC19406028D2FD9C8E4E400045B9347EB119405876FA415D8E4E408046EBA86A6219408048BF7D1D8E4E4080A27A6B604B194000C45DBD8A8E4E40004C361E6C411940D076137CD38E4E40405517F032F31840D00F238447914E40403106D671DC174088423D7D04944E40401A355F25FF1640786308008E934E40C007AF5DDA401640285C8FC2F5904E4000310BED9C361640682E54FEB5904E40C04D637B2D1816405040DAFF008F4E400051BD35B005164010A0C37C798D4E40C02EDE8FDBDF15401015C781578B4E4040D9D0CDFEA0154000E2E7BF07894E4080012D5DC1961540F82F1004C8884E400091F469154D154068F5F23B4D8C4E40C03106D6711C1540E0AC33BE2F8E4E40802CB64945A3144038E109BDFE904E4000310BED9C761440D006600322924E40805417F03233144060F5F23B4D944E40C0035ABA822D144010D6E3BED5944E40C00D315EF32A1440500438BD8B954E4080573F36C92F144060499D8026964E4080BEA085043C1440E009A1832E974E4000022D5DC156144088C9C6832D984E40803465A71F641440504F1F813F984E40001286014B7E1440D800DE0209984E40402A8E03AFA6144028DB87BCE5964E40C0A59D9ACBAD1440B8DA6E826F964E4040F30016F9C5144080CC07043A954E4080DC2A8881CE144088397AFCDE944E4080FF04172BDA144058888043A8944E404022DFA5D4E5144040D505BCCC944E40003E4162BBFB1440A8A44E4013974E4080EC832C0BF6144060853FC39B974E40C08713984EDB1440D0C1FA3F87994E40C022DA8EA9CB14405855A181589A4E4000DF52CE178B1440600DFB3DB19C4E4040999EB0C4731440B0ECF483BA9C4E4040438CD7BC5A1440A8BF97C2839C4E40806AC020E9131440A8DDAF027C9B4E408014AE47E1FA1340D8C77C40A09B4E4000999EB0C4F31340E0A6B1BD169C4E40C0DC2A8881CE1340507C7C4276A04E4080CAA48636D0134060465C001AA14E40005090D8EEAE1440F84AE7C3B3AA4E40805C8FC2F5A81540B8BC564277AF4E400077BF0AF0CD1540D0D38041D2AF4E4000A8FC6B79F51540B8BC564277AF4E4080C554FA09171640D0F19881CAAE4E40805EBC1FB73F164048499D8026AE4E40C0FDD7B969831640D07FD6FCF8AD4E4000F1D8CF6289164048499D8026AE4E40404069A85178164030DB87BCE5AE4E404046EBA86A62164010BB9A3C65AF4E4080921CB0ABC91540286552431BB04E404094490D6DA0154088C9C6832DB04E400077BF0AF00D1540E876137CD3AE4E40C0B1A19BFD011540002A8E03AFAE4E4000A8C5E061AA1440789FAA4203AD4E4000B6F63E55951440B0BF97C283AC4E4040FDD7B969831440E07954FCDFAB4E4000EFAB72A172144028E78BBD17AB4E4080AE47E17A54144030F911BF62A94E40C0A27A6B604B144080457EFD10A94E4080300BED9C361440A0656B7D91A84E40C0C1FA3F87291440D8CABDC0ACA84E40809F1B9AB203144020232E008DAC4E4040CDCCCCCCCC1340D00CE2033BB44E400023DA8EA9CB134008D6E3BED5B44E40C0438CD7BCDA134008CD203EB0B54E4040713D0AD7E3134028E44A3D0BB64E404008AF5DDA40144000301004C8B84E4040DF52CE174B144000E2E7BF07B94E40C0573A1F9E551440080F45813EB94E40C0BEA08504BC1440A8A10DC006BA4E4040F0A65B7658154000D9243FE2B94E4000B1A6B2281C1640B077F17EDCB64E404076C4211B2816403041B8020AB74E40C0230C03967C1640B874B0FECFB94E40C020B248130F174000D9243FE2B94E40C01B62BCE6151740A85CA8FC6BB94E40C0F2052D24201740D8A9F23D23B94E404040321D3A2D174000E2E7BF07B94E4000DBFD2AC0371740080F45813EB94E40404069A851381740603D997FF4B94E4040583A1F9E151740286893C327BD4E40407E6E68CA0E1740B868ACFD9DBD4E40804291EEE7F41640788D2441B8BE4E40C04813EF00DF1640586D37C137BF4E4000B81E85EBD11640885704FF5BBF4E4040E2AC889AB81640B85626FC52BF4E404026396057931640803FFCFCF7BE4E40C08A6D52D1881640788D2441B8BE4E4000AAF23D23811640109700FC53BE4E404014AE47E17A164038327381CBBD4E40C0BFD2F9F06C164090397AFCDEBC4E40C01B62BCE655164010C79E3D97BB4E40008E9598674516403035B401D8BA4E408014AE47E13A16405007793D98BA4E40004B3B3597DB154028266F8099B94E4040DC2A8881CE1540608BC1C3B4B94E40C007AF5DDAC014405037177FDBBF4E4000B6F63E55951440588BC1C3B4C14E40403AE7A7388E1440C88BDAFD2AC24E40408B6D52D1881440F84AE7C3B3C24E4080F30016F985144050793BC269C34E40C00C36751E851440080C040132C44E40807C4622349214402829B000A6C64E408000000000001540C8C43BC093C64E4080118B18761815409047702365C74E400008B13385FE1440B0353FFED2C84E40C05DC136E2D91440783CBB7CEBC94E400083C30B22A2144020E78BBD17CB4E4000AC1F9BE4971440109A417C60CB4E40C04D637B2D981440B07A32FFE8CB4E40806AC020E9D31440600DFB3DB1CC4E40004E637B2D18154038232E008DCC4E40C032384A5E4D1540E0A6B1BD16CC4E40805512D907591540D87954FCDFCB4E400D000000805512D907591540D87954FCDFCB4E40005B99F04B5D154060793BC269CB4E4040D47E6B272A1540F0F1B4FCC0CB4E404083C30B2222154088DB1324B6CB4E40C0406667D11B1540E8F42EDE8FCB4E4080D0251C7A1B1540C092567C43CB4E4040E3A59BC42015401090A16307CB4E40003E0AD7A330154030EA059FE6CA4E4000583CF548531540E85701BEDBCA4E4040A9F7544E5B154030EA059FE6CA4E4080EB54F99E611540F85487DC0CCB4E40806344A2D0621540B8622AFD84CB4E40805512D907591540D87954FCDFCB4E400103000000010000000A000000D0D38041D2273E40ACA10DC006725140603A58FFE7243E403C80457EFD715140A0E33103951D3E400006820019725140407156444D1C3E40D8B837BF61725140F0CDFE40B91D3E406CD0D03FC1725140E0B2B5BE48203E40408386FE097351402015C78157233E40A8984A3FE1725140C0FB3905F9253E40C828417FA1725140206E15C440273E405455A18158725140D0D38041D2273E40ACA10DC00672514001030000000100000014000000E0C77C40A0D33D40F07B0DC17170514030E78BBD17CB3D40DCB2B5BE48705140B0FE7A8505BB3D40786649809A705140D05626FC52B73D40AC716F7EC3705140F036FE4465B73D40F045ED7E15715140E0ECBAB722C53D404CE3175E497351405071C79BFCCE3D40E8455F419A745140C0BC8E3864CF3D40FCE7305F5E7751405055A18158D23D4000CD203EB079514020895E46B1D43D40B0A10DC0067A51402021CB8289D73D4090F0BDBF417A51409001BC0512E03D4098E4B9BE0F7A514040895E46B1E43D40FCD8243FE2795140D0B837BF61FA3D4094E1783E03795140702E54FEB5003E408487A2409F785140207156444D0C3E40489E5DBEF57451407014AE47E10A3E400C6F9D7FBB7351405031957EC2F53D40C01C3D7E6F725140202A8E03AFD63D40786649809A705140E0C77C40A0D33D40F07B0DC17170514001030000000100000057000000C05A0A48FBD339408454C37E4FC65140B0EF3504C7E13940A474B0FECFC55140F02B2CB81FE43940A89509BFD4C55140C05626FC52E7394044A19E3E02C65140306BD44334F2394070D0D03FC1C65140C06BED7DAAFA39400015C78157C75140106893C327FD3940D8C77C40A0C75140C0F8F884EC003A402C2CF180B2C75140801A3048FA043A40888461C092C75140306E15C440073A409814580053C751400073F4F8BD093A4004D061BEBCC65140407A19C5720B3A406C06F1811DC65140702B137EA90B3A4028327381CBC55140F0980F08740A3A402C1A6B7F67C55140704F1F813F083A40000341800CC551406031957EC2053A40B0716F7EC3C4514090992842EA023A40C00166BE83C45140209700FC53F6394000D3A23EC9C3514000240C0396EC39402CF38FBE49C3514030CC423BA7ED3940D8B2B5BE48C05140D0656B7D91F0394050431B800DC05140703A58FFE7F43940C0378600E0BF5140C0AC33BE2F063A40889065C1C4BF514070FA96395D0E3A4004D3A23EC9BF5140D03C80457E113A40FCDEA63FFBBF5140E05A0A48FB133A405C70784144C05140E036FE4465173A4094E1783E03C1514060AA0B7899193A40B0B6D4415EC15140F0A6B1BD161C3A40208A743FA7C15140A087A2409F243A40D0B837BF61C25140A014AE47E12A3A4008D061BEBCC2514090FA96395D2E3A40AC77F17EDCC25140001E8A027D323A40B0984A3FE1C251406031957EC2353A4008D061BEBCC2514010857AFA08383A409C1D1B8178C25140704F1F813F383A4058499D8026C25140002A8E03AF363A407003B00111C1514010A0C37C79353A40500DFB3DB1C05140D034EF3845333A4028F6D03E56C05140605260014C2D3A40A87A32FFE8BF514000A0C37C79153A405876FA415DBE51405055A18158123A40DCAC33BE2FBE5140307A19C572EB394040C269C18BBD5140E036FE4465E73940D8C1FA3F87BD5140D0D38041D2D7394010691B7FA2BD51409000193A76B83940D8A9F23D23BD514020EACC3D24A03940EC78CC4065BB5140809FAA42039D39405C6D37C137BB514080AA0B789999394010A5BDC117BB514090116DC7D4953940BC40498105BB5140605260014C8D394004E869C020BB5140503D997FF4893940ACB0524145BB514070BB5F05F88639403020ED7F80BB514020895E46B1843940809065C1C4BB5140B06BED7DAA6A3940B077F17EDCBE514080035ABA826D394018A5BDC117BF5140B0F8F884EC703940D4AF743E3CBF514020809BC58B8539406C006F8104C05140C0ECF483BA8C3940844E417E36C05140908461C0928F394064BE4A3E76C0514040F38FBE498F39401072DEFFC7C05140C059677C5F8C394094E1783E03C1514020857AFA0888394030ED0DBE30C15140C05FE97C787639409026DE019EC1514020F38FBE496F3940981ADA006CC15140901A3048FA64394000E2E7BF07C15140908D2441B85E39406CCA4E3FA8C0514060BC9179E45739400018080264C05140A08D2441B84E3940C40166BE83C051407015E0BBCD4B3940282F3201BFC05140A0073E062B4A394000E2E7BF07C15140F00E45813E493940DCB5F63E55C15140109A417C604B3940148DB5BFB3C2514000938D075B50394070BE4A3E76C45140108BFCFA21523940C82EC37FBAC4514020809BC58B55394070F7AB00DFC45140D05A0A48FB633940EC51F17F47C5514050B950F9D78239405431957EC2C55140D0A205685B9539402C0B5F5FEBC5514040CC423BA79D3940A877F17EDCC65140C0393FC571AC394068D65240DAC85140107CB779E3C839406CD993C0E6C9514060BFD2F9F0CC3940C8310400C7C9514050DC2A8881CE3940E47E4E417EC95140C04334BA83CC3940C0438A0112C85140F099417C60CB3940C02B82FFADC75140C05A0A48FBD339408454C37E4FC6514001030000000100000014000000900C1D3BA8CC3840D4C1FA3F87C15140D05147C7D5C43840981ADA006CC1514030D505BCCCBC38402C327381CBC15140801EA33CF3AA38405C34D6FECEC25140A09C69C2F6A738403C8386FE09C35140D068ACFD9DA538402CF38FBE49C35140C05A0A48FBA338407C8461C092C3514070B08D78B2A338402838F581E4C35140002C2CB81FA43840544F1F813FC45140701B62BCE6A53840D0CABDC0ACC45140603D997FF4B9384044B9A64066C651400088BB7A15BD38403CC5AA4198C651408018213CDAC038400C6C5CFFAEC6514070CDE50643C538402829B000A6C65140000F45813ED938403C5FECBDF8C55140A081204086DA3840BC10AB3FC2C55140305C8FC2F5D83840200ED940BAC45140C0656B7D91D0384058499D8026C2514020763579CACE3840DCEE5701BEC15140900C1D3BA8CC3840D4C1FA3F87C15140010300000001000000110000005037177FDB0F3840BC490C022BBA51409015E0BBCD0B3840E8482EFF21BA514080129F3BC10638409411178046BA51409093A641D1E8374068D65240DABC5140E0A9F23D23E13740D4AF743E3CBF5140E03C80457EE13740EC84D04197BF5140D059677C5FEC37400C9F3BC1FEC051400009C38025EF3740FC0E45813EC1514080F755B950F93740208A743FA7C151400088BB7A15FD3740D8CDFE40B9C15140C001BC0512103840D4C1FA3F87C15140002C2CB81F143840981ADA006CC15140305C8FC2F5383840602B137EA9BF5140B0DA6E826F3E3840BC3AC780ECBC5140A01EA33CF32A384040B0E3BF40BB5140A009DCBA9B17384044B9A64066BA51405037177FDB0F3840BC490C022BBA5140010300000001000000200000005040DAFF00DF37401872DEFFC7A0514050C554FA09D73740C82EC37FBAA051404069C53714CE374000D6E3BED5A05140F09FC37C79C53740FCE1E7BF07A1514040D8463CD9C137409C0ED6FF39A151407037177FDBBF3740941ADA006CA1514040F04E3E3DBA3740A8AD11C138A2514030DB87BCE5B63740D8D03FC1C5A2514050CDE50643B5374048A4DFBE0EA3514090F4143944B43740885704FF5BA3514040C2137AFDA13740000C040132AC51407055A18158A2374094239D8191AC514010938D075BB037400015C78157AF514050CF83BBB3B23740542B137EA9AF5140200341800CB53740D0D38041D2AF5140001B498270BD3740D0D38041D2AF5140A077F17EDCCE3740282CF180B2AF5140B0E7A4F78DD33740D4C77C40A0AF514070AEEFC341D6374038BCE7C072AF5140200F45813EF93740409E5DBEF5AC514050BC9179E4073840B07A32FFE8AB514020F04E3E3D0A384044C8EBC1A4AB5140A0F1D3B8371F3840C82B82FFADA7514070CAA48636203840EC57738060A75140009C5088801F3840AC6BED7DAAA65140E028EB37131F38408054C37E4FA65140101B4982701D38406CD993C0E6A55140A0FE7A85051B3840C02500FF94A55140C07A32FFE8F337401C5D177E70A15140B0656B7D91F03740545260014CA15140009700FC53E637403C7D04FEF0A051405040DAFF00DF37401872DEFFC7A0514001030000000100000022000000B0E0F08288983740109F3BC1FEA45140108E3D7B2EA73740C864E3C116A05140A093A641D1A8374028266F80999D5140D04D637B2DA8374068F7AB00DF9C5140D05147C7D5A4374050431B800D9C5140A0073E062B8A3740BC3AC780EC985140F017080264583740809065C1C4935140B0FE7A85053B3740A874B0FECF91514040D2C43BC0373740888AE3C0AB91514000857AFA08283740C404A73E9091514010763579CA1E374014967840D99151400021CB828917374028F04E3E3D92514040ED0DBE30153740186058FE7C925140E0548847E2D93640C03D0801F99951402096CE8767E53640500DFB3DB19C514000857AFA08E83640407D04FEF09C5140D0CDFE40B92D3740A877F17EDCA25140D04543C6A330374048A4DFBE0EA3514020F6D03E563437400409C38025A3514080F755B950393740BC40498105A35140207156444D3C3740DCF19881CAA2514030E109BDFE403740FC1186014BA2514030CF83BBB3423740ACA10DC006A25140406552431B6837401863997E89A351407028D2FD9C6637408460C77F81A65140E034EF384563374044A4DFBE0EA7514070992842EA623740E478CC4065A75140C0E7A4F78D633740242CF180B2A75140406E15C44067374004D3A23EC9A7514050BC9179E477374004D3A23EC9A7514060B5DD04DF7C37405C2B137EA9A75140C0548847E28937407C4B00FE29A751402021CB82899737405473B9C150A55140B0E0F08288983740109F3BC1FEA4514001030000000100000078000000D0C77C40A073374050499D8026B251401077D8446666374000E869C020AF5140306211C30E633740E83F6B7EFCAE514040861DC6A45F374098E7FA3E1CAF5140809FAA42034D3740A8B6D4415EAD5140001286014B2E37401C8A743FA7A9514070129F3BC116374028ED0DBE30A5514060C422861DE636408454C37E4FA2514060B3CEF8BEC83640805182FE42A1514050D6A88768C43640EC51F17F47A1514080FDD7B969C33640C42500FF94A151402082397AFCC2364068FAEC80EBA15140C07A32FFE8C336408454C37E4FA25140A0116DC7D4C53640B06BED7DAAA25140C05FE97C78C636406CFD2D01F8A25140F02B2CB81FC436405C6D37C137A35140E028EB3713BF3640D4C77C40A0A35140109A417C60BB3640CCD38041D2A3514070431B800DA43640080C040132A4514060C1E10511A1364068DF15C1FFA351407018213CDAA0364040C8EBC1A4A35140307497C459A1364040E603029DA25140A0069B3A8FA2364014691B7FA2A1514000274D83A2A13640040F45813EA151406040DAFF009F3640AC9ECC3FFAA05140108E3D7B2E773640146F9D7FBB9F5140B0E7A4F78D73364044C8EBC1A49F5140008E3D7B2E573640E8577380609F5140604CDE0033533640805704FF5B9F514080F1D3B8374F36403CBCE7C0729F514080A86DC3284C3640582B137EA99F514000990F08744A36401C9CFA40F29F51402000000000403640F817080264A05140603D997FF4293640888AE3C0AB9D514090AEEFC341263640D8CDFE40B99D5140A07A32FFE82336405C3D997FF49D5140B0DDAF027C233640001286014B9E514090FDD7B969233640D4C43BC0939E514030D2C43BC02736401C9337C0CCA05140F00E45813E29364094ED7C3F35A1514060C763062A2B3640C004A73E90A151409074B0FECF39364068C4CC3E8FA25140D0656B7D91403640C81F7EFE7BA35140D0787764AC42364084D21742CEA551405056293DD34336404410E7E104A6514070A7CAF78C443640B0AD11C138A6514050C763062A3B3640FCC6D79E59A65140F07F0F5EBB383640E854320054A65140508BFA2477243640F49CF4BEF1A55140A0E0F082881836405455A18158A65140A068ACFD9D15364050499D8026A65140709065C1C4033640146C5CFFAEA65140D0E7A4F78DF3354094E1783E03A95140306C06B820F3354044B665C059A95140F05A0A48FBF33540DCEE5701BEA95140A01B62BCE6F535400806820019AA514040F04E3E3DFA354004E5284014AA51409046E867EA2536406CF12900C6A95140B0C28366D729364014842BA050A95140700C1D3BA82C3640D8F126BF45A9514020335184D435364048A7E7DD58A95140800E48C2BE453640CC91CEC0C8A9514010301004C8603640546D37C137AB5140009C5088805F36407C4E417E36AC5140407497C459613640AC9ECC3FFAAC5140F034EF384563364040B665C059AD5140E0AC33BE2F66364044C269C18BAD5140C0B5F63E55853640C004A73E90AD5140D0CABDC0AC883640C004A73E90AD5140A09FAA42038D3640281A6B7F67AD514060499D80269E36409C1799805FAC5140709C69C2F6A736401890F63FC0AB514080F755B950A9364094205C0185AB5140E025AAB706AA36402CF38FBE49AB51401018080264A836405440DAFF00AB514000240C03969C3640ACAD11C138AA5140F0847AFA0898364028266F8099A9514050D2C43BC0973640080F45813EA951408093A641D1983640407D04FEF0A8514050C763062A9B3640500DFB3DB1A851406037177FDB9F36408487A2409FA8514030ED0DBE30B53640500DFB3DB1A8514070499D8026CE3640189F3BC1FEA85140A0EF3504C7D13640E845ED7E15A9514070431B800DD4364028F911BF62A95140A00C1D3BA8CC36407C4E417E36AC51408014AE47E1CA3640D8BEB9BF7AAC5140306C06B820C336402CED0DBE30AD5140D042024697BB36408CF0BDBF41AE5140B074B0FECFB936408081204086AE514030D2C43BC0B7364000E869C020AF5140D05626FC52B73640C4FE243E77AF5140205C8FC2F5B836406CC70DBF9BAF5140D0EAE5779AC836402CF6D03E56B05140605260014CDD36402829B000A6AE5140C0B5F63E55E53640EC5AB4006DAC5140F0488446B0E53640C864E3C116AC514070B81E85EBF13640A86BED7DAAAA5140F0298E03AFF63640C0490C022BAA514090FE7A8505FB364058499D8026AA5140205FD04202FE36405055A18158AA5140D0AF743E3C1B3740E83F6B7EFCAE5140505C8FC2F5283740941D1B8178B251400018080264483740241A6B7F67B15140D0393FC5714C3740505260014CB1514090A52C431C57374050499D8026B2514060465C001A5937407860C77F81B25140206552431B5837405434D6FECEB251405031957EC255374044A4DFBE0EB35140B0E67283A152374090DE37BEF6B35140B053E57B4652374040B324404DB45140F09C82FC6C5037402C29B000A6B65140B05CA8FC6B5137403C8386FE09B75140F0BEB9BF7A543740DCAF743E3CB75140D0D38041D2573740DCAF743E3CB75140C0AF743E3C5B374014A5BDC117B75140E031AEB8385E3740B0984A3FE1B65140D04543C6A3603740C028417FA1B65140C0F8F884EC703740FCDEA63FFBB35140D0C77C40A073374050499D8026B251400103000000010000001F000000D0488446B0D53640805182FE42955140F00B040132E43640E88711C2A3945140D04D637B2DE83640D0CABDC0AC94514040CF83BBB3F23640EC5AB4006D945140D0DDAF027C0337403CC269C18B91514020A0C37C79053740407D04FEF090514090116DC7D4053740806649809A905140703A58FFE7043740804E417E369051404055A181580237409CDE37BEF68F5140F0548847E2F93640186F9D7FBB8F5140D0A6B1BD16EC3640FCDEA63FFB8F514060AD4CF8A5DE364094EA3BBF28905140F040F33977D73640FCDEA63FFB8F5140502B137EA9CB36402838F581E48F5140E036FE4465C73640A47A32FFE88F5140B0E7A4F78DA336400C72DEFFC7905140F0D03FC1C5923640900ED6FF39915140709C69C2F67736405055A18158925140A001BC0512703640106C5CFFAE92514010904C874E6B3640F04B6F7F2E93514070D367075C5F364050465C001A955140A0FA96395D5E3640281A6B7F67955140D0A9F23D2361364050499D8026965140107CB779E378364068DF15C1FF975140C04334BA837C3640C064E3C1169851401006820019AA3640080341800C99514080FA96395DAE364098E1783E03995140C001BC0512B036402C2F3201BF985140E03C80457EB136403CA7203F1B98514020CF83BBB3B2364098E7FA3E1C975140D0488446B0D53640805182FE429551400103000000010000001400000070116DC7D4C535406C03B00111915140B001BC0512C0354068CA4E3FA8905140407A19C572BB3540BC2EC37FBA905140A0F27684D3B63540845182FE42915140001E8A027DB235409C1D1B8178925140C0F8F884ECB0354014A5BDC1179351402009C38025AF3540EC5AB4006D945140906E2EFEB6AF3540E87E4E417E955140C0E67283A1B23540EC7B0DC171985140C05147C7D5B435402C2F3201BF9851400018080264B8354008D6E3BED5985140B059677C5FBC35402C2F3201BF985140E0BB783F6EBF3540C822BF7E88985140A01A3048FAD43540AC6BED7DAA965140D036FE4465D73540ACB915C26A965140504F1F813FD835405431957EC2955140D036FE4465D73540A8B6D4415E95514070D6A88768D43540C022BF7E88945140C0E9B303AEC73540981ADA006C91514070116DC7D4C535406C03B001119151400103000000010000000D000000801EA33CF3BA3540F084D041977B5140A00F5EBBB4B13540D8AF743E3C7B5140B0DA6E826FAE3540E8577380607B5140E0A6B1BD16AC35406CC70DBF9B7B5140B0FE7A8505AB3540AC7A32FFE87B514040C763062AAB3540DCB2B5BE487C5140B0ECF483BAAC354028232E008D7C5140206211C30EB3354068D65240DA7C51407009DCBA9BB735401472DEFFC77C5140D0AF743E3CBB35401C66DAFE957C5140407156444DBC3540DCB2B5BE487C5140D0A6B1BD16BC3540A49B8BBFED7B5140801EA33CF3BA3540F084D041977B514001030000000100000019000000307D5A457FE43440804E7ADFF881514090069B3A8FF23440E83653211E805140103AB01C210B3540AC957B815980514050465C001A193540846649809A80514020F04E3E3D1A354044B324404D805140A07A32FFE8F33440BC0166BE837C514040CC423BA7ED3440884E417E367C5140506C06B820E33440AC7A32FFE87B514040F38FBE49DF3440BC378600E07B5140B0F27684D3D634403038F581E47B514080992842EAD234406CDF15C1FF7B514070035ABA82CD3440F07B0DC1717C5140D0A6B1BD16CC344070CA4E3FA87C514080116DC7D4C53440E8482EFF217E5140201E8A027DC23440408386FE097F514060C2137AFDC13440845704FF5B7F514090A2EBC20FC234400C6F9D7FBB7F514060B950F9D7C23440A8A78FC01F80514070C554FA09C734402CF911BF6281514040F04E3E3DCA3440B8490C022B825140307156444DCC3440186058FE7C82514010763579CACE3440FCCF61BEBC825140B053E57B46D23440BC344580D3825140E03FC1C58AD63440BC344580D3825140307D5A457FE43440804E7ADFF88151400103000000010000001000000070CAA48636003540885182FE42815140307156444DFC344090ED7C3F3581514030D2C43BC0F73440F051F17F47815140002C2CB81FF43440805D86FF7481514060B08D78B2F33440208A743FA7815140C0BEB9BF7AF4344014A27C410B825140406211C30E03354064DF15C1FF835140B05626FC5207354064DF15C1FF83514050D026874F0A354000D3A23EC983514000240C03960C3540E84B6F7F2E8351400088BB7A150D3540B077F17EDC82514050B5DD04DF0C3540186058FE7C825140207A19C5720B354004E528401482514030F911BF620935405C31957EC2815140E03FC1C58A063540BC04A73E9081514070CAA48636003540885182FE4281514001030000000100000018000000107A19C572EB3440E845ED7E15855140B0716F7EC3E4344004D6E3BED5845140C0E3310395DD3440C43AC780EC84514020F6D03E56D43440AC9509BFD485514080069B3A8FD23440040682001986514010301004C8D03440DCB837BF61865140D0B2B5BE48D03440148DB5BFB3865140B0656B7D91D03440D4BB783F6E875140407497C459D13440D0D38041D2875140100C040132D4344070CA4E3FA8885140B0E9B303AED7344030F911BF628951409074B0FECFD9344068CD8FBFB4895140D04334BA83DC344044C269C18B895140F01186014BDE3440E851F17F47895140D0BB783F6EDF3440A89ECC3FFA885140D0B5F63E55E53440000C040132885140B0073E062BEA3440A86E2EFEB6875140B050A4FB39ED34402820ED7F80875140808461C092EF3440ACB0524145875140207497C459F13440E83F6B7EFC86514020D8463CD9F13440B06BED7DAA865140C001BC0512F03440001286014B865140B050A4FB39ED34407C5D86FF74855140107A19C572EB3440E845ED7E1585514001030000000100000022000000A01A3048FAD434407C5A457F688C5140307A19C572CB3440D4D38041D2835140D0CABDC0ACC8344064C70DBF9B835140809FAA4203BD3440C01F7EFE7B835140E03FC1C58AA63440EC3F6B7EFC82514060BEA085049C3440188DB5BFB3825140B001BC0512903440F039E97DE384514040DB87BCE5863440C0378600E083514070431B800D843440C82B82FFAD8351406037177FDB7F3440C82B82FFAD835140B0E9B303AE77344000D3A23EC98351401015C78157733440A89B8BBFED83514040861DC6A46F344044A7203F1B845140A00C1D3BA86C3440A8B393C151845140C0FB3905F96534406C03B0011185514060B08D78B2633440888AE3C0AB855140B0E67283A1623440F054320054865140C0D03FC1C5623440106C5CFFAE865140002A8E03AF663440A8B6D4415E895140C04D637B2D68344050499D80268A5140D059677C5F6C344070BB09BE698B51405069C537146E344004D3A23EC98B51408096E7C1DD8D3440BC1C3D7E6F8E5140A07A32FFE8933440D8F19881CA8E514030F38FBE49AF344018A5BDC1178F5140C036FE4465B73440FCE769C0208F5140E04543C6A3C03440EC3F6B7EFC8E514030F6D03E56C434405434D6FECE8E5140F036FE4465C7344048E603029D8E514080AD4CF8A5CE344000D9243FE28D514070C1E10511D1344010691B7FA28D514050B950F9D7D23440B0B6D4415E8D5140B004FD851ED53440A8716F7EC38C5140A01A3048FAD434407C5A457F688C51400103000000010000001400000060499D8026AE34401090F63FC0735140C04BC5C6BC9A344070DCD440F3725140C0D03FC1C592344018A5BDC117735140207D5A457F903440282CF180B27351409021E4BCFF8F3440E842ACFE0874514080FA96395D8E34406806F1811D765140A0DA6E826F8E34409C1D1B817876514080F1D3B8378F3440AC77F17EDC765140F0AC33BE2F96344004D6E3BED578514070BC9179E497344030ED0DBE30795140603D997FF499344068C18BBE82795140F0393FC5719C3440C0310400C7795140A08461C0929F344068FAEC80EB795140A014AE47E1BA3440C0490C022B7A5140B050A4FB39BD3440E43C2AFEEF795140F0CDFE40B9BD344030266F809979514080A86DC328BC3440F08711C2A3745140D04BC5C6BCBA34402C172AFF5A7451408009DCBA9BB73440080C04013274514060499D8026AE34401090F63FC07351400103000000010000002700000040B5DD04DF1C3440148DB5BFB386514060B08D78B20334409CDE37BEF6835140709FAA4203FD3340AC6E2EFEB683514060AD4CF8A5EE3340805704FF5B83514040D026874FEA334094205C018583514020809BC58BD5334064DF15C1FF835140101B498270CD3340149CFA40F2835140A093A641D1C8334064DF15C1FF835140A004FD851EC53340980B957F2D845140E03C80457EC13340542E54FEB5845140F0B2B5BE48C0334094E1783E03855140906E2EFEB6BF334040B665C05985514080F1D3B837BF334010A27C410B865140F0BB783F6EBF334004E869C020875140109C508880BF3340C81F7EFE7B87514050CAA48636C03340BC378600E0875140F0B2B5BE48C03340E44EB0FF3A885140906E2EFEB6BF334094239D8191885140901A3048FAB4334040B0E3BF408B5140001286014BAE33402C172AFF5A8C514060B3CEF8BEA8334040AA61BF278D5140207976F9D6A333409426DE019E8D5140702E54FEB5A03340B09509BFD48D5140C0EF3504C791334088812040868E5140E0420246978B334004DC65BFEE8E5140F02E6D382C8933401063997E898F5140100F45813E8933402838F581E48F5140C0BEB9BF7A943340E845ED7E15915140306E15C440973340585260014C915140F0393FC571AC3340B0B915C26A925140D057C9C7EEAE3340C0490C022B925140908AE3C0ABC93340301A6B7F678D51409014AE47E1CA334058465C001A8D514040DEC83CF2CB3340EC7B0DC1718C5140C0CABDC0ACD83340B0A44E40138B514060BEA08504FC3340F045ED7E1589514010274D83A21134406CDF15C1FF87514060AD4CF8A51E3440846308008E87514040B5DD04DF1C3440148DB5BFB38651400103000000010000000B00000030809BC58BF533402C172AFF5A805140A00F5EBBB4F1334044B324404D80514010990F0874EA3340C40166BE83805140B05626FC52E73340C02EC37FBA805140D0AC33BE2FE6334000E2E7BF07815140C0EAE5779AE83340F051F17F4781514070A7CAF78CF43340B0B6D4415E81514070D9E90775F93340885182FE42815140406893C327FD3340EC45ED7E158151405040DAFF00FF33408093A641D180514030809BC58BF533402C172AFF5A8051400103000000010000001300000090ABAE43359133408460C77F8176514090F755B950793340D0EE5701BE755140C068ACFD9D7533406CFAEC80EB755140B0F27684D37633409C1D1B8178765140D0488446B08533401466DAFE9578514000990F08748A3340BC46CB811E795140407156444DCC3340E842ACFE08805140107D5A457FD03340E842ACFE088051401096CE8767D53340A87A32FFE87F51409000193A76D83340B06E2EFEB67F5140E03A71395EDD3340D4AF743E3C7F514090116DC7D4E53340A4AD11C1387E51407031957EC2E533407C96E7C1DD7D514010895E46B1E43340D8C1FA3F877D51404083DC4598CA3340C0378600E0775140C0E0F08288C833407C6308008E7751406031957EC2C533400415C7815777514020F04E3E3DBA3340504CDE003377514090ABAE43359133408460C77F817651400103000000010000004200000070BFD2F9F04C33407C8AE3C0AB81514040809BC58B553340D8CABDC0AC80514060BFD2F9F05C334094DE37BEF67F5140603A58FFE764334030F38FBE497F5140B0EAE5779A68334094E7FA3E1C7F5140C0393FC5716C3340804B00FE297F5140A0F5B704E06B33403020ED7F807F514060D9E90775693340C064E3C116805140D0C1FA3F8769334068BE4A3E76805140A0073E062B6A334064D65240DA80514010917EFB3A6C3340ACAAD0402C815140406211C30E73334040A19E3E02825140A00C1D3BA87C334040A4DFBE0E835140C04E0647C97F3340546D37C137835140E034EF38458333409C1458005383514080A52C431C873340805704FF5B835140E0A6B1BD168C334048B0E3BF40835140E04E0647C98F3340ACA44E401383514050DB87BCE5A63340505260014C81514090F755B950A93340040341800C815140C0E3310395AD334024232E008D805140D0656B7D91B03340FCDEA63FFB7F5140D0A9F23D23B13340602B137EA97F5140C04E0647C9AF3340AC984A3FE17E5140C0DA6E826FAE33402C1DACFF737E5140E03DB2B96A823340DCEE5701BE795140000F45813E693340E85DF580797551409004FD851E653340B09ECC3FFA74514040D9E90775593340584F1F813F745140808AE3C0AB49334098205C0185735140405FD042022E3340186C5CFFAE725140A0069B3A8F2233408081204086725140B0DA6E826F1E33408081204086725140F0C1FA3F871933403029B000A672514060C554FA09173340A8984A3FE172514010301004C810334068BE4A3E7674514040EACC3D241033401072DEFFC7745140D06BED7DAA0A3340C02500FF94755140704F1F813F083340B09509BFD475514070A7CAF78CF43240302CF180B2775140B0DA6E826FEE324044A7203F1B7851401015C78157E332408487A2409F78514090F755B950D9324048AA61BF27795140901A3048FAC4324090F0BDBF417A514050B81E85EBC13240981D1B81787A514060BFD2F9F0BC324000DC65BFEE7A514020E78BBD17BB3240584CDE00337B5140D0EAE5779AB8324008D3A23EC97B5140D0EAE5779AB8324090EA3BBF287C514050AA0B7899B9324040BF28417F7C5140A01B62BCE6D532400018080264805140A0FE7A8505DB32406CF7AB00DF805140407D5A457FE03240505260014C815140C053E57B46F23240C4310400C781514090069B3A8F023340D4EE5701BE815140107FF8F9EF0D3340505260014C815140E0393FC5711C3340D8F4D901D7835140306E15C4402733405C73B9C15085514020F911BF62293340EC7E4E417E855140206552431B383340C0490C022B865140D0AF743E3C3B33405C3D997FF4855140C050A4FB394D3340D8F4D901D78351402083DC45984A33405840DAFF00835140503D997FF449334048E603029D82514050C763062A4B3340543D997FF481514070BFD2F9F04C33407C8AE3C0AB81514001030000000100000016000000A0622AFD849B33408481204086865140603A58FFE79433409411178046865140A04D637B2D883340001286014B865140307D5A457F803340F0818FC18A865140B050A4FB395D3340BC378600E0875140E04BC5C6BC5A334040A7203F1B885140E0C1FA3F87593340805A457F6888514020F04E3E3D5A33401C9337C0CC885140B0F5B704E05B3340B0AAD0402C895140B0E33103955D334044C269C18B8951408087A2409F64334068FD2D01F88A51406028D2FD9C66334024F38FBE498B5140A074B0FECF693340DCBB783F6E8B5140D0DA6E826F6E3340F0577380608B5140D03C80457E713340EC4B6F7F2E8B5140704F1F813F9833409C1799805F885140A06BED7DAA9A3340ACA78FC01F885140F04334BA839C33405037177FDB875140E0CDFE40B99D3340888461C092875140101286014B9E3340D8AF743E3C875140A0E33103959D33403035B401D8865140A0622AFD849B3340848120408686514001030000000100000011000000F0BB783F6E2F3340D4F4D901D7875140000C04013224334040C8EBC1A487514020990F08740A334018A27C410B8A5140B0EAE5779A0833408454C37E4F8A514040F04E3E3D0A3340186C5CFFAE8A5140C0E67283A12233401C90F63FC08F5140809065C1C433334070BE4A3E7690514000857AFA0838334070BE4A3E769051407015E0BBCD3B3340D4B2B5BE48905140009C5088803F33401C90F63FC08F5140F0D03FC1C5423340E878CC40658B514080A2EBC20F4233405C40DAFF008B514060B5DD04DF3C33403C7D04FEF0885140C0420246973B3340C022BF7E88885140D02E6D382C39334054707841448851403077D8446636334058431B800D885140F0BB783F6E2F3340D4F4D901D787514001030000000100000062000000107976F9D6E33240D4B2B5BE486C514000904C874ECB32405840DAFF006B514040DB87BCE5C63240B09509BFD4695140C0488446B0C53240981ADA006C695140D0BEB9BF7AC432400C9F3BC1FE685140D0BEB9BF7AC432408487A2409F68514070AEEFC341C632402C172AFF5A685140B0073E062BCA3240D8B2B5BE4868514080FA96395DCE3240D8B2B5BE4868514060C2137AFDD1324048A7203F1B685140207976F9D6D33240DCF4D901D7675140D0CABDC0ACD832403029B000A6665140D0CABDC0ACD83240041286014B6651407000193A76C83240E85AB4006D645140406C06B820C3324070006F8104645140909FAA4203BD32402C2CF180B2635140100F45813EB9324040C8EBC1A463514020F6D03E56B432401490F63FC0635140B059677C5F9C32405C37177FDB635140F0C1FA3F87893240F084D0419763514040B3CEF8BE683240FCDB65BFEE625140C0488446B0653240D8D03FC1C5625140406552431B5832405855A1815862514050B60F79CB3D32405C3D997FF4615140E025AAB7063A324070D993C0E661514000301004C830324068FAEC80EB615140107CB779E3283240A8AD11C138625140D0420246970B324014A8FE41246451406028D2FD9C063240846649809A6451405037177FDBFF3140D4B5F63E5565514080F1D3B837FF3140188A743FA765514010938D075B003240FCE4284014665140C04D637B2D083240D8D38041D267514020A0C37C7925324068F7AB00DF685140708AE3C0AB29324068F7AB00DF685140C0716F7EC3443240D4C77C40A0675140B0E9B303AE473240500DFB3DB1685140C001BC0512303240EC39E97DE36C5140F0BB783F6E2F324098ED7C3F356D5140F01D8A027D323240ACB6D4415E6D5140C059677C5F4C3240DCA9F23D236D514070C18BBE82503240EC21533E046D51402096CE87676532401C9337C0CC6C5140A0F27684D3963240D4B2B5BE486C5140E0BB783F6E9F324064DF15C1FF6B514050D8463CD9A1324018A8FE41246C514080ABAE4335A1324070BE4A3E766C5140E0BB783F6E9F3240C82EC37FBA6C5140B059677C5F9C3240C03AC780EC6C5140D0488446B085324038C269C18B6D514090F5B704E07B32405431957EC26D5140B06E2EFEB66F32406CCD8FBFB46D5140F087BB7A155D324004068200196E5140F025AAB7065A3240FC1186014B6E5140B04D637B2D58324068C4CC3E8F6E5140306211C30E53324000D6E3BED5705140E03DB2B96A52324044AA61BF27715140306211C30E53324044C269C18B715140901A3048FA5432407C96E7C1DD715140E0B837BF615A32408054C37E4F725140406C06B8206332402835B401D8725140A0AEEFC341663240C828417FA1725140109A417C607B3240580DFB3DB1705140C03DB2B96AA2324068D65240DA70514000A0C37C79A53240146058FE7C6E514050C422861DA63240C0490C022B6E5140909C69C2F6A73240DCC1FA3F876D5140602B137EA9AB324094E1783E036D5140D0488446B0B5324000D3A23EC96B514060B3CEF8BEB83240E884D041976B5140605260014CBD32401C63997E896B514010938D075BC03240302CF180B26B5140C0E67283A1C232409CDE37BEF66B5140000C040132C43240149F3BC1FE705140A018213CDAC03240A8B052414573514020DEC83CF2BB32400C6F9D7FBB73514060CAA48636B03240447D04FEF07451407040DAFF00AF3240940ED6FF3975514060D9E90775A9324090E7FA3E1C7751409093A641D1A8324040BCE7C0727751400026AAB706AA32405437177FDB77514050BEA08504AC3240980B957F2D785140A05CA8FC6BB132407C6649809A785140107FF8F9EFCD324044BF28417F785140B053E57B46D2324034172AFF5A7851401096CE8767D5324094EA3BBF28785140E057C9C7EEFE3240149337C0CC745140207976F9D603334028F6D03E5674514060C763062A0B3340A8B052414573514000763579CA0E3340D8B837BF61725140B0656B7D9110334030F911BF62715140B0656B7D9110334004E2E7BF0771514010F38FBE490F3340786649809A70514020904C874E0B334000DFA63FFB6F51408087A2409F04334004E869C0206F51406040DAFF00EF32406C03B001116D514060AA0B7899E93240EC8711C2A36C5140107976F9D6E33240D4B2B5BE486C514001030000000100000020000000305C8FC2F5C8324004E869C020875140D0A6B1BD16CC32406CC4CC3E8F865140F04E0647C9EF32402C2CF180B287514030D8463CD9F1324090205C0185875140109C508880FF324004CD203EB0855140502E54FEB500334028F911BF62855140B001BC0512003340189F3BC1FE845140A0DA6E826FFE32408487A2409F8451407000193A76F832405C2B137EA9835140D0B5F63E55F5324094205C0185835140F03C80457EF13240BCFE243E77835140F0CABDC0ACE8324094205C01858351401094BF7B47E13240805704FF5B835140C0F27684D3D632403C8386FE09835140F02B2CB81FD43240BC344580D3825140B0FE7A8505CB324070CD8FBFB4815140D05D4BC807C93240301A6B7F678151406031957EC2C532406CCA4E3FA8805140909065C1C4C3324028F6D03E568051400029EB3713BF324070D311C0CD7F5140207156444DBC3240EC84D041977F51400096CE8767B53240F0577380607F514060C1E10511B1324098205C01857F5140A0F1D3B837AF324004D3A23EC97F5140001286014BAE3240844E417E36805140D0CABDC0ACA832405034D6FECE825140A0116DC7D4B53240EC42ACFE0888514050DB87BCE5B632409C1799805F885140F0B837BF61BA3240D4BEB9BF7A88514090FA96395DBE32400418080264885140A018213CDAC0324090EA3BBF28885140305C8FC2F5C8324004E869C020875140010300000001000000C8000000804E7ADFF8A23140F0909BE10661514040861DC6A4AF31401466DAFE95605140B053E57B46B231407C93A641D1605140406BD44334B23140B0AAD0402C615140D03C80457EB13140E87E4E417E61514060C763062AAB31406CFD2D01F862514050BB5F05F8A63140808AE3C0AB65514030DB87BCE5A63140ACA10DC00666514070AA0B7899A931402CF04E3E3D665140206552431BD8314068CD8FBFB465514060C763062ADB31406CC18BBE82655140A09FAA4203DD3140000F45813E65514040DB87BCE5F63140F05DF580796151402082397AFC123240808461C0925B514000A0C37C7915324068FD2D01F85A514040C422861D1632403029B000A65A5140A074B0FECF193240ACB0524145575140A074B0FECF19324094DBF63DEA565140F07BB779E3183240D4C43BC09356514090AEEFC3411632405C76FA415D565140D0DA6E826F0E3240FC1186014B56514010857AFA08F831405C3D997FF4555140000341800CF5314028327381CB5551408014AE47E1EA314004D6E3BED5545140D0EAE5779AE8314098239D8191545140B0E9B303AEE73140E84EB0FF3A54514070CAA48636E03140FC14C781574F5140A09065C1C4F33140A8716F7EC34C5140E0D38041D2F731401472DEFFC74C514070C763062AFB3140F439E97DE34C514020861DC6A4FF3140FCD5E3BED54C5140C05CA8FC6B01324090239D81914C5140C0F8F884EC003240940B957F2D4C514060AD4CF8A5FE3140AC7A32FFE84B514090129F3BC1E631406CD0D03FC14A514040D505BCCCDC3140ACB915C26A4A514010A0C37C7995314018A27C410B4A5140E0488446B0853140940B957F2D4C5140D04D637B2D6831405855A181584A514070AEEFC341363140C4310400C745514030D8463CD9313140080F45813E455140C059677C5F2C31405870784144445140901EA33CF32A31402C38F581E4435140E0548847E2293140BCFE243E7743514030F911BF62293140ACA44E4013435140C06BED7DAA2A3140D4D03FC1C542514090035ABA822D3140848D2441B84251406037177FDB2F3140B077F17EDC425140A0069B3A8F32314004DC65BFEE42514040895E46B134314068D0D03FC1425140C03FC1C58A3631401C6058FE7C425140108E3D7B2E373140B8490C022B4251406031957EC235314030327381CB415140B0E7A4F78D333140D8C1FA3F874151405034D6FECE2A314004E2E7BF0741514020D2C43BC0173140F04EB0FF3A405140702B137EA90B3140844E417E36405140D04BC5C6BC0A3140EC7B0DC1714051400073F4F8BD093140080341800C41514070AA0B78990931409C1ADA006C415140B06BED7DAA0A31401C967840D9415140100341800C1531407C4B00FE2943514040E109BDFE20314010A8FE412444514050B950F9D722314070BE4A3E7644514040CF83BBB32231407C93A641D1445140D0B2B5BE48203140040341800C455140C0A6B1BD161C314030ED0DBE30455140B0716F7EC3F4304024F6D03E56445140E03FC1C58AE63040BCFE243E77435140F0C77C40A0E3304030F38FBE49435140F04E0647C9CF3040E84B6F7F2E435140B05FE97C78C63040B0A78FC01F44514090116DC7D4C5304070BE4A3E76445140E0BEB9BF7AC43040C4310400C745514040809BC58BC5304040ADA23F34465140B05626FC52C73040F0818FC18A465140901EA33CF3CA3040F04B6F7F2E475140106893C327CD30403CBCE7C072475140009D82FC6CD03040888461C092475140D0BEB9BF7AD43040E884D0419747514020904C874EEB30405437177FDB475140F0A9F23D23013140A4B393C151485140306211C30E2331406CFD2D01F84A514070CDE50643253140D8AF743E3C4B5140100F45813E293140D4F4D901D74B514020E78BBD172B314090EA3BBF284C5140D04334BA832C3140BC22BF7E884C514020F04E3E3D2A31408887A2409F4C5140B05626FC5227314068BE4A3E764C5140908461C0921F314070D311C0CD4B5140A00C1D3BA81C314040C8EBC1A44B5140C0FB3905F915314074BB09BE694B514070B81E85EB113140E878CC40654B5140E03730B951083140F084D041974B5140602E54FEB5F0304068BE4A3E764C514070CAA48636E03040B8490C022B4E5140F0D03FC1C5E2304040B9A640664E514030F911BF62E9304048E603029D4E514010301004C8F0304068D0D03FC14E514010938D075B0031401499B9C0E54E5140E025AAB7060A3140188DB5BFB34E5140201E8A027D123140C01C3D7E6F4E5140002DCF83BB1B31408054C37E4F4E5140A0FA96395D1E31407C812040864E514040EACC3D242031402835B401D84E514080A7CAF78C24314090DE37BEF64F5140A0861A8524133140C0581822A7515140F0A3FE7A8511314084AE7D01BD515140109F1EDB32103140B0D4B320945151408084EFFD0D0A3140084B75012F515140F0548847E2E93040148DB5BFB3525140D040F33977E7304098DBF63DEA52514020809BC58BE53040F04B6F7F2E5351401096CE8767E530401C63997E8953514020DB87BCE5E63040A89B8BBFED535140A074B0FECFE93040C864E3C116545140C0E3310395ED304094EA3BBF2854514070B08D78B2033140C4438A01125451401027BEDA51143140384DD87E32545140F022DBF97E1631401457CEDE1954514090FC3383F81831401457CEDE19545140E0A7397991193140103F389F3A54514090C7F0D8CF1631404CBC75FEED555140801A3048FA14314064E256410C565140509D8026C21231400CFA449E24565140D0073D9B550B31405855A18158565140805B069CA50831406CC746205E565140B059F5B9DA06314048D13C8045565140508237A4510531400CFA449E24565140708EC9E2FE033140C43D0801F955514050D026874FFA3040ACB915C26A5651407028D2FD9CF630405855A181585651409093A641D1E830408481204086565140F05A0A48FBE33040C828417FA1565140E0B2B5BE48E03040DCF19881CA565140A017EFC7EDDF304048A4DFBE0E575140001286014BEE3040C446CB811E595140407D5A457FF0304030F911BF62595140208D2782380B31408081204086595140D05A0A48FB3331407896E7C1DD59514090812040864A3140FCE42840145A5140007976F9D663314040B9A640665A514040E78BBD177B3140B077F17EDC5A5140A0035ABA827D31405840DAFF005B514040B60F79CB7D31403414E97E4E5B514020904C874E7B31401463997E895B5140F05A0A48FB7331405837177FDB5B5140B02E6EA301683140A87A32FFE85B514070EB5223F463314094E1B19FC55B5140D0A3FE7A8561314070309B00C35B514060B81E85EB51314094DE37BEF65B514060B950F9D7423140E87B0DC1715C51408096E7C1DD3D31405C3A58FFE75C514040DEC83CF23B314040AA61BF275D51406037177FDB2F31406CBB09BE695F5140A06E2EFEB62F314000D3A23EC95F51407055A181583231400800000000605140D05FE97C7836314068006F8104605140E0C1FA3F87393140D4D38041D25F5140F09C82FC6C40314014A5BDC1175F5140900F5EBBB4413140D4F19881CA5E5140D0CABDC0AC483140D8CDFE40B95D5140002DCF83BB4B3140D4C1FA3F875D514060CAA48636503140E85DF580795D5140101AC1C6F55B314020C022BF7E5E514030629F008A5D31405C971AA19F5E5140701F2BF86D5C31408CA2409FC85E5140809C69C2F6573140C4438A0112605140007FF8F9EF4D3140D8B5F63E55615140D050A4FB394D3140848AE3C0AB615140009C5088804F3140F03C2AFEEF61514050B950F9D752314018A27C410B62514070BB5F05F856314094E4B9BE0F625140E025AAB7066A3140EC51F17F47615140200341800C7531401872DEFFC76051407014AE47E18A3140FCE769C0205F5140C059677C5F8C314000DC65BFEE5E5140F03C80457E913140DCEE5701BE5D51400015C78157933140E85DF580795D514050C554FA09973140E0A9F23D235D5140005E4A5D329A3140282026E1425E51406070CD1DFD9B3140C437143E5B5E5140002A00C6339C31409841B5C1895E514070CD7344BE8F31404C3DD2E0B660514040AD4D637B8D31403071AB2006615140B004FD851E853140A8AD11C138625140D04543C6A380314090F0BDBF41625140D059677C5F7C314044B9A64066625140F00E45813E7931403CC5AA4198625140C068ACFD9D75314014A8FE412464514030809BC58B753140BC0166BE83645140206552431B78314098F0BDBF4166514010917EFB3A7C314098F0BDBF41665140D036FE4465873140281A6B7F67655140F0548847E2893140ACAAD0402C65514020CC423BA78D314070CA4E3FA8645140307497C459913140A8A78FC01F645140605ED5592D983140385019FF3E635140E08F6AD8EF9D31408CD21742CE615140804E7ADFF8A23140F0909BE10661514001030000000100000010000000D04BC5C6BC6A3140106F9D7FBB3F5140C0BB783F6E5F3140BC404981053F51409015E0BBCD5B3140EC4B6F7F2E3F514050C763062A5B31403020ED7F803F5140901EA33CF35A3140CCD38041D23F514050D026874F5A314040C269C18B41514000917EFB3A5C31408054C37E4F425140B0E7A4F78D63314068C70DBF9B435140E05D4BC8076931408C239D8191445140E0AF743E3C6B314070D65240DA445140A06E2EFEB68F314004E528401446514020938D075B903140DCEE5701BE455140B0E9B303AE873140845704FF5B435140A0116DC7D4853140408386FE09435140207497C459713140BC22BF7E88405140D04BC5C6BC6A3140106F9D7FBB3F5140010300000001000000170000008096E7C1DD3D3140981D1B8178325140D0548847E2393140981D1B8178325140C0488446B03531403CC5AA419832514030CF83BBB3323140DCF19881CA32514000301004C83031405C40DAFF00335140100341800C15314068C18BBE8239514030F6D03E56143140AC9509BFD43951401096CE876715314090F0BDBF413A5140206E15C440173140D4C43BC0933A5140F072F4F8BD1931405C34D6FECE3A514030DEC83CF24B3140AC77F17EDC3A5140E05147C7D55431402829B000A63A51407014AE47E15A314028F04E3E3D3A5140605260014C5D3140A4A10DC0063A5140A0E33103956D3140FCDEA63FFB375140E0BB783F6E6F3140AC6E2EFEB6375140B001BC0512703140EC5773806037514080F1D3B8376F3140408386FE0937514040DEC83CF26B31405455A181583651401073F4F8BD693140F8E4284014365140D057C9C7EE4E31408C205C0185335140E0A9F23D234131403CC5AA41983251408096E7C1DD3D3140981D1B81783251400103000000010000001300000040B60F79CB1D314090EA3BBF28305140F017080264183140809065C1C42F5140C004FD851E153140582B137EA92F514090E9B303AE073140D4F4D901D72F514070B08D78B2033140D4F4D901D72F514010809BC58BF530401863997E892F5140D028EB3713EF30403014E97E4E2F5140D034EF3845D3304098E4B9BE0F2E5140F0B2B5BE48D0304090F0BDBF412E514030EACC3D24D0304044E603029D2E514030DB87BCE5D63040149F3BC1FE305140A0E0F08288F83040A8A10DC00636514040B5DD04DFFC3040D8C43BC09336514030EACC3D24003140146C5CFFAE3651400015C78157033140D8C43BC0933651404031957EC2253140C004A73E90315140A0116DC7D425314094ED7C3F3531514070F4143944243140A89ECC3FFA30514040B60F79CB1D314090EA3BBF2830514001030000000100000019000000C0C1FA3F8789304040B324404D38514000A0C37C79853040D4B2B5BE4838514080A2EBC20F823040A8B393C151385140A096E7C1DD7D3040E87B0DC171385140E0AF743E3C6B304030ED0DBE30395140D0B2B5BE48603040A4A10DC0063A514010A0C37C79453040EC51F17F473D5140A0E7A4F78D433040DCC1FA3F873D514060B950F9D74230407C96E7C1DD3D5140F07876F9D6433040FC1186014B3E514030D2C43BC0473040AC984A3FE13E5140D0548847E2493040804B00FE293F5140D059677C5F4C3040F0577380603F5140B001BC051250304038BCE7C0723F5140E0BEB9BF7A54304070BB09BE693F5140F0393FC5718C3040F03C2AFEEF3D5140A001BC0512903040BC310400C73D514070069B3A8F92304044C269C18B3D5140A04D637B2D9830401872DEFFC73C5140F025AAB7069A3040BC0166BE833C5140207A19C5729B30405437177FDB3B5140D036FE446597304054465C001A395140D0AC33BE2F9630407C93A641D1385140A001BC0512903040C422BF7E88385140C0C1FA3F8789304040B324404D385140010300000001000000B6000000605DC136E2F92F40ACA78FC01F30514080F1D3B837EF2F40D0C1FA3F872D5140E0C3094CA7ED2F4030ED0DBE302D5140E05758703FE82F40F05AB4006D2C5140E05CA8FC6BE12F40849065C1C42B5140805A99F04BDD2F402C20ED7F802B514080D026874FBA2F40301A6B7F67295140E0B5F63E55B52F4028ED0DBE30295140C06E2EFEB69F2F40A49ECC3FFA285140A01D71C8069A2F40189337C0CC28514080CAA48636902F402C172AFF5A28514020A7B1BD168C2F40C064E3C11628514020CBBDC0AC882F401490F63FC0275140200473F4F8852F40F057738060275140609885764E7B2F4098E4B9BE0F2251406083DC45987A2F40888AE3C0AB215140E0BB783F6E7F2F40888AE3C0AB2151404083DC45989A2F40844B00FE29235140405FD042029E2F40C81F7EFE7B23514040261B0FB6A02F40BC378600E023514080069B3A8FA22F4048B324404D245140802CB64945A32F40580DFB3DB1245140E0B2B5BE48A02F403CB665C05925514020E3A7716F9E2F4018A27C410B2651400052D66F269E2F4040B9A64066265140C021E4BCFF9F2F40C0344580D3265140C0FDD7B969A32F400409C38025275140603BFBCA83AC2F40602B137EA92751408045B9347EB12F40C4378600E0275140A07A32FFE8F32F4048E603029D2A5140206E15C440173040AC77F17EDC2E514050B60F79CB1D304068FAEC80EB315140A0F5B704E01B3040E0AC33BE2F325140D0CABDC0AC18304004D061BEBC325140002A8E03AF163040885704FF5B335140009700FC53163040C064E3C11634514060D9E907751930401472DEFFC7345140C0DA6E826F1E3040940ED6FF3935514070B60F79CB2D30408460C77F81365140A0F414394434304000D061BEBC3651405034D6FECE5A3040B077F17EDC365140C06E2EFEB66F30402CF04E3E3D365140206BD4433472304040A19E3E0236514070035ABA827D3040C4378600E0335140009A417C608B3040543A58FFE7305140D05CA8FC6B91304098239D81912C5140C04543C6A3903040D0CDFE40B929514040EACC3D249030405473B9C150295140F008C380258F3040F439E97DE328514070B60F79CB8D3040C40166BE83285140C0C1FA3F8789304094DE37BEF627514060C554FA098730401490F63FC0275140F03DB2B96A82304040B0E3BF40275140E031AEB8387E30401C8DB5BFB326514060B5DD04DF7C3040EC54320054265140C0393FC5717C3040F03C2AFEEF255140309622F94A803040481630815B235140D03A71395E5D3040888461C09223514050D9E90775593040846308008E235140402B137EA93B3040584CDE00332351407093A641D1383040BC40498105235140406BD44334223040E845ED7E1521514030ED0DBE30153040D8F4D901D71F5140201E8A027D12304014A5BDC1171F514040D505BCCC0C304010691B7FA21D51404023DA8EA9EB2F409C1799805F185140E020CB8289E72F4040A7203F1B185140E0CDFE40B9DD2F4040C8EBC1A4175140E01D8A027DD22F402C14E97E4E17514060F4143944C42F40F04B6F7F2E175140406893C327BD2F409814580053175140A05A99F04BBD2F40C004A73E90195140E0DB114E0BB62F403CC8EBC1A41B5140E0989EB0C4932F40A89ECC3FFA185140C01A3048FA642F40AC9509BFD415514080035ABA822D2F4094205C0185135140204E7CB5A3102F40A4AAD0402C155140E06BED7DAA0A2F4040B665C059155140E00F77F52ADA2E4040B665C05915514080A148F773BA2E40282F3201BF14514020EFAB72A1B22E40542E54FEB5145140A0622AFD84AB2E4064F7AB00DF14514000D48041D2A72E40E0A9F23D23155140005A80B6D5A42E40C0310400C715514020D6A88768A42E4054499D80261651404048FAB48AC62E40504F1F813F185140C0D8D0CDFEE02E40980ED6FF39195140C0656B7D91002F402C1DACFF731A5140E0CABDC0AC082F405C40DAFF001B514020634337FB232F40F07E4E417E1D5140E0C3094CA72D2F4048E603029D1E5140E0C64ACCB3222F4018A8FE4124205140009F20B1DD1D2F40941799805F205140C068ACFD9D152F40D8BEB9BF7A205140004C546F0D142F4018A8FE4124205140C068ACFD9D152F40D4D38041D21F5140C02FF7C951182F4094205C01851F514060BEA085041C2F40B0B05241451F5140E037A110011F2F4048E603029D1E5140001286014B1E2F40ACAD11C1381E5140402DCF83BB1B2F40B09509BFD41D51404051BD35B0052F4024232E008D1C514000D00D4DD9E12E4064C4CC3E8F1A514020A8E33103DD2E40EC543200541A5140A05626FC52D72E4050499D80261A514040573F36C9AF2E40545260014C19514080DF6B088E832E400015C7815717514000A26131EA722E40EC482EFF211651400020990E9D762E40FCD8243FE2155140A01B62BCE6752E40EC7E4E417E155140801A3048FA642E40F05AB4006D145140606684B707392E403CA19E3E02125140000C040132342E40C4310400C7115140C076BF0AF00D2E4094DE37BEF60F514020F2ECF2AD072E40DCF4D901D70F5140A0656B7D91002E40889065C1C40F5140802634492CF92D40DCF4D901D70F5140A02FF7C951F82D4008D6E3BED5105140201B498270FD2D40C040498105135140E0FFFFFFFFFF2D40F078CC4065135140E0DE52CE172B2E402C14E97E4E17514020F52D73BA7C2E4098111780461E5140E05758703FA82E40B4984A3FE11E514000D68F4DF2AB2E4040A4DFBE0E1F51404077D84466862E40EC51F17F47215140C0EA56CF497F2E40981ADA006C21514080A48977806F2E4028F911BF6221514080C2137AFD612E4030ED0DBE30215140E0A7E331035D2E40981ADA006C215140008D9AAF925F2E402C327381CB215140E050A4FB396D2E4040C8EBC1A4235140E0AA24B20F722E40BC378600E0235140E0D03FC1C5B22E40E87E4E417E255140802634492CB92E409826DE019E255140A06BED7DAAEA2E4014A27C410B2A514040D6A88768E42E40F814C781572B5140002FDE8FDBDF2E4030F6D03E562C51402038A11001DF2E40040341800C2D514080A7CAF78CE42E405055A181582E5140206E15C440E72E407C8D2441B82E5140C03BFBCA83EC2E405C34D6FECE2E51404069C537142E2F40A46BED7DAA2E514080129F3BC1362F40C028417FA12E51400009C380253F2F4084812040862E5140400D36751E452F40F0543200542E5140C076BF0AF04D2F4014967840D92D514080F755B950592F406C03B001112D514040895E46B1642F40282F3201BF2C51408032384A5E6D2F40542E54FEB52C5140005517F032532F40C4344580D32E514040D367075C4F2F4014A5BDC1172F5140C089592F864A2F403014E97E4E2F5140E00F77F52A3A2F4074BB09BE692F5140E05CA8FC6B212F4074BB09BE692F514020D9E90775192F40EC78CC40652F5140006211C30E132F40ACB05241452F51406032384A5E0D2F4014A5BDC1172F514040895E46B1042F4004E869C0202F514020C53BC093FE2E4098145800532F5140A00C1D3BA8EC2E40000C040132305140C09BDF30D1E82E40F07B0DC171305140206E15C440E72E401872DEFFC7305140205C8FC2F5E82E4044BCE7C07233514020B0743E3CEB2E40106F9D7FBB335140E053E57B46422F4054707841443C51406051BD35B0452F401066DAFE953C5140E0B3E73235512F403C7D04FEF03C5140201286014B5E2F40B0AAD0402C3D5140A05A99F04BBD2F4068CD8FBFB43D514020C422861DC62F40848AE3C0AB3D5140A088450C3BCC2F40F05DF580793D5140A016687748D12F40B00DDC813A3D514020C763062ADB2F40E845ED7E15395140604B3B3597DB2F40C02EC37FBA3851408094490D6DC02F401C8DB5BFB332514000CEFE40B9BD2F40EC54320054325140E0A9F23D23E12F409C11178046325140A074B0FECFE92F4030F04E3E3D325140A01B62BCE6F52F4010967840D93151406038BA4A77F72F40D8C1FA3F8731514040AA0B7899F92F40D8BEB9BF7A305140605DC136E2F92F40ACA78FC01F3051400103000000010000001C000000E0D38041D26730408454C37E4F1A5140901A3048FA64304050499D80261A5140D05CA8FC6B613040FCE42840141A5140F0C1FA3F8759304018A27C410B1A5140B0656B7D91503040DCAC33BE2F1A5140700C1D3BA84C3040BC490C022B1A514030809BC58B45304018A27C410B1A514070431B800D343040188A743FA719514090F8F884EC303040D8C1FA3F871951407040DAFF001F3040C464E3C11618514050BFD2F9F01C3040504F1F813F185140C04D637B2D18304030F911BF62195140B0EAE5779A183040C8310400C7195140E05A0A48FB233040C428417FA11E51405031957EC22530406CDCD440F31E51404069C537142E304050431B800D205140108E3D7B2E373040FCE1E7BF0721514080A86DC3283C3040E85DF5807921514050B08D78B253304054499D8026225140B0E9B303AE573040C0490C022B22514060D367075C5F3040FCD8243FE22151404055A1815862304004CD203EB02151404077D84466663040D8B5F63E5521514010068200196A30407C93A641D1205140C0AC33BE2F76304044ADA23F341E5140E040F339777730406CFAEC80EB1D514040C554FA097730406CC18BBE821D5140E0D38041D26730408454C37E4F1A514001030000000100000032000000A0622AFD840B2F404480457EFD39514040861DC6A4EF2E40149CFA40F2375140406552431BE82E4068006F8104385140206C06B820E32E40EC4EB0FF3A385140E0EA56CF49DF2E4044BF28417F38514020AD33BE2FD62E4028F911BF623951400090DB2F9FD42E406CCD8FBFB4395140A009DCBA9BD72E4090111780463E51406000193A76D82E40186C5CFFAE3E5140A077F17EDC1E2F4098E4B9BE0F465140606C06B820232F40E454320054465140405DC136E2392F4070C70DBF9B4751408077F17EDC3E2F40D4D38041D247514000B937BF614A2F40980B957F2D485140C03E3C4B90612F4070F7AB00DF485140802634492C792F40409E5DBEF5485140A0656B7D91802F40FCE1E7BF0749514000AE65321C872F4048AA61BF2749514020A7B1BD168C2F40A8B6D4415E495140609BC6F65A902F40188A743FA7495140A07A32FFE8932F40C43D0801F949514020965D30B89E2F40C81F7EFE7B4B5140C05DDA7058B22F40B0AD11C1384E5140401077F52ABA2F40A8B05241454F5140606211C30EF32F40BC3D0801F9515140006893C327FD2F40B0B915C26A525140700C1D3BA81C304068006F810454514000938D075B2030405437177FDB535140901B62BCE6253040E854320054525140E036FE4465273040888AE3C0AB515140B0E9B303AE273040449E5DBEF5505140002A8E03AF16304004068200194A5140603A58FFE7143040C0310400C7495140C077F17EDC0E3040583A58FFE7485140A05626FC52073040E84EB0FF3A48514060D6A88768043040C4438A011248514020965D30B8FE2F40D8C77C40A0475140609BC6F65AF02F401C99B9C0E546514040DF6B088EE32F4004E528401446514000BC783F6EBF2F4040BCE7C07243514020EC6AF294BD2F40C4404981054351402038A11001BF2F40188DB5BFB342514000BC783F6EBF2F40E854320054425140C0C43BC093BE2F40EC3C2AFEEF41514080D026874FBA2F40808AE3C0AB415140E0B5F63E55B52F40185D177E7041514060E2AC889A782F40B09B8BBFED3F5140A088450C3B6C2F4040C8EBC1A43F5140002A8E03AF462F40C0344580D33E5140A0622AFD840B2F404480457EFD3951400103000000010000001700000040DC2A8881CE2F402829B000A6FE504040D9E90775B92F40301DACFF73FE5040C0C98B4CC0572F4040E603029DFE504040D026874F3A2F40C41C3D7E6FFE5040E0A4A2B1F6072F40888D2441B8FE5040A0C2137AFD012F4094DBF63DEAFE5040E0BB783F6EFF2E405C6D37C137FF5040A0C2137AFD012F40F084D04197FF5040C0F0D8CF62092F40000C040132005140C06DFC89CA0E2F40981799805F00514020B1A6B2281C2F4028232E008D005140A05626FC52372F40E839E97DE3005140401286014B3E2F403C9E5DBEF500514080B60F79CB4D2F40109F3BC1FE005140E059677C5F6C2F40A89ECC3FFA00514000240C03967C2F403C9E5DBEF500514020999EB0C4B32F406CF7AB00DF0051406054FEB5BCBA2F40C42EC37FBA005140E059677C5FCC2F4090EA3BBF28005140601B62BCE6D52F402C2CF180B2FF5040A000193A76D82F4074BB09BE69FF5040A0B3CEF8BED82F40448386FE09FF504040DC2A8881CE2F402829B000A6FE50400103000000010000006E00000020634337FBC32E40FC05820019365140C0FA96395DCE2E40585260014C2D5140E076BF0AF0CD2E40C422BF7E882C5140803BFBCA83CC2E401C90F63FC02B5140C06BED7DAACA2E403414E97E4E2B5140803F373465C72E40EC3F6B7EFC2A5140A02CB64945C32E40188DB5BFB32A514080D9E90775B92E4094F0BDBF412A5140000D36751EA52E40301A6B7F6729514060634337FB232E408493A641D1245140401286014B1E2E40E88711C2A3245140C05FE97C78162E408087A2409F245140C0035ABA82CD2D4094ED7C3F352551402083DC4598BA2D40A8B6D4415E255140E014C78157B32D40D8C1FA3F8725514000FEF0F3DF9B2D40544CDE0033275140207A19C5729B2D40806308008E275140808B868C47A12D40C822BF7E8828514060895E46B1A42D4068D65240DA285140E08EC70C54B62D40DCB5F63E55295140A0978A8D79D52D4040A19E3E022A5140E09E20B1DD1D2E40808461C0922B514000C2FA3F87492E40785A457F682C514040301004C8502E40DCBEB9BF7A2C5140400C040132542E40149337C0CC2C5140C0CCCCCCCC4C2E401C9CFA40F22F514060809BC58B452E4040A7203F1B305140401286014B1E2E408087A2409F30514000895E46B1042E40EC39E97DE3305140E01186014BFE2D40AC716F7EC3305140802CB64945032E40C022BF7E88305140A0BC9179E4172E4058431B800D30514000D00D4DD9212E4070C70DBF9B2F5140A03579CA6A222E40D8AF743E3C2F51402038A110011F2E4094DBF63DEA2E5140200C040132142E40BC3D0801F92D5140A051D66F26FE2D40500DFB3DB12C514060CAA48636D02D40F814C781572B5140C074B0FECFC92D40546D37C1372B514020CDE50643A52D40146C5CFFAE2A5140A0B5DD04DF7C2D40DCAC33BE2F2A5140A0129F3BC1762D405876FA415D2A514020999EB0C4532D40A86BED7DAA2A514040D9E90775192D40D4C77C40A0275140C0656B7D91002D4080812040862651406051BD35B0E52C40AC6BED7DAA265140008D9AAF92DF2C402C35B401D8265140202DCF83BBDB2C4098E7FA3E1C275140C0AC33BE2FD62C40C02B82FFAD2751406023F3C81FC42C409CE4B9BE0F2A5140605FD04202BE2C401C90F63FC02B5140A0656B7D91C02C400CA8FE41242C514080069B3A8FE22C40149F3BC1FE3051408009DCBA9BF72C40EC5432005432514000E8154F3D0A2D4024F38FBE493351408020B248130F2D408C205C018533514000634337FB432D406CF7AB00DF34514000B937BF614A2D40109F3BC1FE345140005517F032532D40489E5DBEF534514060A148F7735A2D408093A641D1345140C05A99F04B5D2D40C822BF7E88345140C0D8D0CDFE602D408C205C0185335140000473F4F8C52D405470784144305140A076BF0AF0CD2D40DCB2B5BE4830514000AB24B20FD22D402C232E008D305140C018213CDAE02D40C41C3D7E6F325140605A80B6D5E42D40804B00FE29335140202A8E03AFE62D40F084D0419733514080C422861DE62D4094DE37BEF633514060A7CAF78CE42D40D8B2B5BE48345140E0CF0D4DD9E12D4090239D8191345140C05DDA7058D22D402C266F809935514060A4897780CF2D4000D9243FE2355140803579CA6AE22D402835B401D8365140606E15C440E72D40ACA44E4013375140801D71C8061A2E40A8B915C26A365140A03579CA6A222E40041286014B365140C0035ABA822D2E4000D9243FE2355140A05FE97C78362E40301A6B7F6735514020FEF0F3DF3B2E4008D6E3BED5345140401B4982703D2E403CBF28417F345140E0BB783F6E3F2E405C7078414434514080D6A88768442E40E842ACFE08345140C0A6B1BD164C2E4000DFA63FFB33514060D367075C4F2E4044B324404D345140E009F5F411502E40540DFB3DB134514040DC2A88814E2E4004E2E7BF0735514000E8154F3D4A2E4010691B7FA23551400021CB8289472E40EC3C2AFEEF355140E017080264282E4054465C001A39514020F86EF3C6112E403C8386FE093B51402069C537140E2E400415C781573B514040E9297288082E40B07A32FFE83B5140200473F4F8052E40504F1F813F3C5140E0C64ACCB3022E40543A58FFE73C5140A053E57B46022E40805182FE423D5140200473F4F8052E40E8482EFF213E514000DF52CE170B2E40AC984A3FE13E514080B81E85EB112E40806308008E3F5140A0D24ECDE5162E407C9065C1C43F5140A0BFD2F9F02C2E40C40166BE83405140A0B08D78B2432E40C42EC37FBA405140E0346090F4492E40BC22BF7E8840514040321F10E8542E40F0577380603F5140A07C410B09582E40888D2441B83E5140E0AC33BE2F562E40FC1186014B3E5140E074B0FECF692E40C404A73E90395140801B62BCE6952E40D4B2B5BE48385140C0E1934E24C02E405876FA415D36514020634337FBC32E40FC05820019365140010300000001000000110000004021CB8289672E409026DE019EF9504000C2FA3F87492E40EC7E4E417EF950400051BD35B0052E408096E7C1DDF95040004C546F0DF42D40BC3D0801F9F95040E0D58F4DF2EB2D400806820019FA504000261B0FB6E02D40AC77F17EDCFA504000A8E33103DD2D40FCE769C020FB5040E0E2A7716FDE2D40BCFE243E77FB504000B0743E3CEB2D401872DEFFC7FC5040A0F1D3B837EF2D406C03B00111FD504000C87C40A0132E405C73B9C150FD50400069C537142E2E40FCE1E7BF07FD5040407A19C5729B2E401C99B9C0E5FA5040A0737E8AE3982E4008D061BEBCFA5040E017080264882E40ACAD11C138FA50400090DB2F9F742E40A874B0FECFF950404021CB8289672E409026DE019EF950400103000000010000004000000080035ABA820D2E40888D2441B816514040D367075CAF2D408496E7C1DD115140E0B2B5BE48A02D40940ED6FF39115140609BC6F65A902D406CCA4E3FA8105140601EA33CF38A2D40DCBEB9BF7A105140204E7CB5A3102D4000D6E3BED50C5140A023F3C81F042D401C66DAFE950C5140004F95EF19C92C40106F9D7FBB0B5140A09885764E7B2C40C43D0801F9095140A0F0D8CF62692C4038C269C18B095140C0B628B341662C40D8EE5701BE095140803F373465672C408493A641D10C51408074B0FECF692C4028ED0DBE300D514080BEA085049C2C4094205C0185135140A03579CA6AA22C40980B957F2D14514020AE65321CA72C40845A457F68145140206002B7EEAE2C40F05AB4006D145140C0DB114E0BB62C40D4B2B5BE481451404007B47405BB2C40C4438A0112145140E0CDFE40B9BD2C40849065C1C4135140E0BB783F6EBF2C4040BCE7C072135140E0989EB0C4D32C4008D061BEBC125140E05626FC52F72C4004DC65BFEE12514040EC6AF294FD2C4040A4DFBE0E1351408018213CDA002D40F078CC4065135140A05CA8FC6B012D4000D3A23EC91351404015C78157F32C4030266F809915514060CAA48636F02C40A874B0FECF15514020F52D73BADC2C40D8D03FC1C5165140C000193A76F82C40805A457F68185140C068ACFD9D152D40188A743FA719514000DC114E0B362D406CD0D03FC11A5140E08B868C47412D4094E7FA3E1C1B51404021CB8289472D40D4AF743E3C1B514060A7CAF78C842D40DCBB783F6E1B5140C0CCCCCCCC8C2D4094145800531B5140E0AA24B20F922D40EC4B6F7F2E1B5140A0BEA085049C2D4000D061BEBC1A514080C763062A9B2D4068F4A3E19419514060B2B8FFC89C2D403C7A354069195140C0D02346CF9D2D40F48D210038195140801C5BCF109E2D40149F3BC1FE18514020CEFE40B99D2D409C2023A0C2185140002EE411DC982D40389B8E006E18514000DC2BF3568D2D401CD82AC1E2175140C02B9FE579882D4060B2F1608B175140E0A9F23D23812D408060C77F81165140800F5EBBB4812D40EC482EFF2116514040679AB0FD942D40D48E1B7E3717514080B3CEF8BE982D4080336ABE4A175140C068AB92C8B62D4048EF54C03D18514020FF058200B92D408C9675FF58185140E04D621058B92D4064B532E197185140A0012EC896B52D4000F7AE415F1951408082E0F1EDB52D40388639419B195140806BED7DAACA2D4044BCE7C0721B514000AD33BE2FD62D40602B137EA91B514020068200194A2E40F439E97DE31C514020B4E73235512E40489E5DBEF51C5140E05FE97C78562E4008D6E3BED51C5140A017EFC7ED4F2E40900B957F2D1C514040A148F7733A2E408454C37E4F1A5140E0264D83A2112E405440DAFF0017514080035ABA820D2E40888D2441B816514001030000000100000012000000C0CABDC0ACE82D405837177FDB375140E05CA8FC6BE12D4000D3A23EC9375140404E7CB5A3D02D406CD311C0CD37514000E2934E24C02D402C38F581E4375140E0C98B4CC0B72D4064DF15C1FF375140C0C3094CA7AD2D40E87B0DC171385140C076BF0AF0AD2D40B0716F7EC338514020BFB9BF7AB42D402CF38FBE493B5140A01B62BCE6B52D4044C8EBC1A43B5140604278B471BC2D40809065C1C43B514060CDE50643C52D40146F9D7FBB3B514040BB5F05F8E62D40B0B05241453B5140A0035ABA82ED2D40844B00FE293B5140609BC6F65AF02D40B0984A3FE13A51400015C78157F32D40E85DF58079395140400C040132F42D40282F3201BF385140401E8A027DF22D40A8B393C151385140C0CABDC0ACE82D405837177FDB3751400103000000010000002000000000CEFE40B9BD2D4044C269C18B0D51400020990E9DB62D40EC5DF580790D5140A032384A5EAD2D4044C269C18B0D514040E9297288A82D40C8310400C70D514060895E46B1A42D40ACA10DC0060E5140406C06B820A32D405455A181580E5140E0C64ACCB3A22D40848D2441B80E5140802CB64945A32D4094E7FA3E1C0F5140801A3048FAA42D401463997E890F5140A0A7CAF78CA42D40A87A32FFE80F514080BB5F05F8A62D40D8B2B5BE4810514000DF52CE17AB2D4090239D8191105140207D5A457FB02D402C2F3201BF10514040B08D78B2C32D40208A743FA7115140E06DFC89CACE2D403880457EFD115140200341800CD52D4068D993C0E611514080737E8AE3D82D4010691B7FA2115140E0CDFE40B9DD2D40981ADA006C115140C03E3C4B90E12D4040AA61BF27115140606C06B820E32D4008D6E3BED51051404009C38025DF2D4024232E008D10514080737E8AE3D82D40E85AB4006D105140A000193A76D82D40A8A78FC01F10514040C763062ADB2D40DCF4D901D70F51400083DC4598DA2D40D8BB783F6E0F5140C05626FC52D72D4094E7FA3E1C0F51402015C78157D32D40C0344580D30E514060DC2A8881CE2D4038C5AA41980E5140208A592F86CA2D40EC543200540E5140006E15C440C72D403C80457EFD0D5140602CB64945C32D40D0CDFE40B90D514000CEFE40B9BD2D4044C269C18B0D514001030000000100000012000000803E3C4B90812C4068DCD440F3D65040A07A32FFE8732C405C34D6FECED65040006002B7EE6E2C4000DC65BFEED6504000013274EC702C40DCAF743E3CD7504080CDE50643852C40AC9ECC3FFAD85040E04E95EF19892C40805182FE42D95040E0DB114E0B962C404080457EFDD95040005858703FA82C4090DBF63DEADA504000BFB9BF7AB42C40804B00FE29DB504020C763062ABB2C40D8AF743E3CDB50408021E4BCFFBF2C40BC40498105DB5040E094490D6DC02C40B06BED7DAADA5040604B3B3597BB2C40A8B6D4415ED95040A0C98B4CC0B72C402C232E008DD8504020B6F63E55B52C4094EA3BBF28D850406045B9347EB12C402838F581E4D75040606E15C440A72C4070C70DBF9BD75040803E3C4B90812C4068DCD440F3D650400103000000010000001600000060634337FB832C40C00166BE83C85040008A592F866A2C406CBE4A3E76C05040202A8E03AF662C40940B957F2DC05040A053E57B46622C4098DE37BEF6BF5040604B3B35975B2C40BC378600E0BF5040E00B040132542C405037177FDBBF50408032384A5E4D2C4070C18BBE82C15040C015E0BBCD4B2C4010967840D9C15040C053E57B46422C40408386FE09C3504000965D30B83E2C4024F38FBE49C35040C076BF0AF02D2C40584F1F813FC45040E04E95EF19292C4068BE4A3E76C45040E0B2B5BE48202C40C822BF7E88C45040206BD44334122C40E85AB4006DC4504040356090F4092C4068BE4A3E76C45040C082C30B22022C4090239D8191C45040206893C327FD2B40540DFB3DB1C45040207A19C572FB2B4000E2E7BF07C5504000C53BC093FE2B4038B665C059C55040405FD042021E2C402C20ED7F80C75040008A592F866A2C407C93A641D1C8504060634337FB832C40C00166BE83C8504001030000000100000015000000C05758703F682C403414E97E4E0F5140C094490D6D602C40A8B05241450F5140C05626FC52572C4044BCE7C0720F5140E01D8A027D522C40602B137EA90F514000B1A6B2281C2C405876FA415D12514060D9E90775192C40A86BED7DAA125140C0737E8AE3182C40C040498105135140A0F755B950192C406CBB09BE69135140802CB64945232C4044BF28417F1451406054FEB5BC3A2C401466DAFE9514514040634337FB432C4044BF28417F145140E0C3094CA76D2C40B0B052414513514000B6F63E55752C4068D0D03FC1125140806ABB09BE792C4058499D8026125140007A19C5727B2C40B09509BFD411514020A8E331037D2C40F07E4E417E115140E0EB6AF2947D2C40D4A9F23D2311514060C763062A7B2C402C2F3201BF10514000274D83A2712C40889065C1C40F5140E0C3094CA76D2C40C41F7EFE7B0F5140C05758703F682C403414E97E4E0F51400103000000010000003600000060573F36C9EF2B4040B0E3BF400F5140800F5EBBB4012C400409C380250F5140C00C1D3BA80C2C403020ED7F800F514060AD4CF8A50E2C40C4378600E00F5140A020B248130F2C40E85AB4006D105140E0989EB0C4132C406CCA4E3FA8105140C0737E8AE3182C402C2F3201BF10514020261B0FB6202C401072DEFFC710514060CAA48636302C40C40166BE83105140E0A9F23D23412C40AC9B8BBFED0F514040634337FB432C403CC8EBC1A40F514060809BC58B452C4094145800530F5140200D36751E452C409CDBF63DEA0E5140E0CF0D4DD9412C4038C5AA41980E5140E04B546F0D142C400015C781570B514060AD4CF8A50E2C40844B00FE290B514040CDE50643052C40D8AF743E3C0B5140A021E4BCFFDF2B405440DAFF000B51406000193A76B82B40C0490C022B0A5140C059677C5FAC2B40542E54FEB508514080B81E85EBB12B40B0A78FC01F085140201E8A027DB22B40849065C1C4075140E0AA24B20FB22B40805704FF5B075140207D5A457FB02B4000DC65BFEE0651408015E0BBCDAB2B40188DB5BFB3065140A06BED7DAA6A2B40D8B2B5BE4804514080CDE50643652B4048A7203F1B0451402038A110015F2B4094DE37BEF603514000068200194A2B405C70784144045140202FDE8FDB3F2B40B0B6D4415E055140806E2EFEB61F2B40500DFB3DB1045140402C9D0FCF0A2B408081204086025140803E3C4B90012B4044C5AA41980251404083DC4598FA2A40D8F19881CA025140201E8A027DF22A40544CDE0033035140002C9D0FCFEA2A40B06E2EFEB603514020A5A2B1F6E72A4068DF15C1FF03514020B728B341E62A40ACB393C151045140E050A4FB39ED2A40E85DF5807905514080CAA48636F02A40A874B0FECF0551408020B248130F2B40C4438A0112085140001E8A027D122B4004E2E7BF070D514040274D83A2112B40AC6BED7DAA0E514040068200190A2B4000D061BEBC0E5140403F373465072B40C4404981050F5140C0656B7D91202B40540DFB3DB110514060CDE50643252B40B83AC780EC10514020F86EF3C6512B40E85432005412514020D026874F5A2B40001286014B125140604B3B35979B2B4090ED7C3F3511514080BB5F05F8C62B40080C04013210514020AB24B20FD22B4070D311C0CD0F51400021CB8289E72B40845704FF5B0F514060573F36C9EF2B4040B0E3BF400F514001030000000100000011000000A05DDA7058F22B40844E417E36105140008A592F86EA2B409C0B957F2D105140603F373465C72B40D4B837BF6112514080F4143944C42B400415C78157135140E08EC70C54D62B40A8B393C151145140E02CCF83BBDB2B4044BF28417F145140A088450C3BEC2B4044BF28417F145140406BD44334F22B40A8B393C151145140E085048C2EF72B40C864E3C11614514080C763062AFB2B40D8F4D901D7135140009F20B1DDFD2B407C6308008E135140008D9AAF92FF2B40546D37C137135140C0E1934E24002C40AC77F17EDC125140E037A11001FF2B40109F3BC1FE105140E05A99F04BFD2B4090239D819110514060E2AC889AF82B4028F6D03E56105140A05DDA7058F22B40844E417E361051400103000000010000001D00000000B3B5BE48E02A40546D37C137075140E0703D0AD7C32A40B49509BFD401514080FA96395DAE2A40E839E97DE3005140200473F4F8852A40885704FF5BFF5040A0656B7D91802A40EC4B6F7F2EFF504080A148F7737A2A4048A4DFBE0EFF50400015C78157732A4058465C001A015140C06DFC89CA6E2A40ACA10DC006025140E0D58F4DF26B2A408054C37E4F02514060A7CAF78C642A405876FA415D025140A053E57B46622A403C80457EFD015140A03E3C4B90612A4028ED0DBE3001514020C53BC0935E2A40B0B393C15100514060D026874F5A2A40940B957F2D005140C08EC70C54562A40E85AB4006D00514000E6E8F17B532A40C42EC37FBA005140E0A16131EA522A40F045ED7E15015140A05DDA7058522A4044C5AA419802514000999EB0C4532A40408386FE09035140E0B5F63E55952A40585260014C095140C02634492C992A40C82500FF94095140E0C43BC0939E2A405431957EC209514020809BC58BA52A4014967840D909514040C554FA09B72A40848AE3C0AB095140809E077767C52A4028F911BF62095140A0622AFD84CB2A4098ED7C3F35095140E085048C2ED72A40E87B0DC171085140008D9AAF92DF2A40E884D0419707514000B3B5BE48E02A40546D37C13707514001030000000100000010000000802634492CF9294040E603029D8E504020240C0396DC2940146058FE7C8E5040A05A99F04BDD29406CD0D03FC18E5040E0E1934E24E02940A4A44E40138F5040A0B08D78B2E32940885704FF5B8F50408020B24813EF2940940B957F2D9050406009DCBA9BF72940E88711C2A3905040A0622AFD840B2A40A4B6D4415E915040205C8FC2F5282A403C80457EFD915040006E15C440472A4040A19E3E0292504060573F36C94F2A40EC3C2AFEEF91504080C1E10511512A405C31957EC291504040895E46B1442A40980ED6FF39915040A00C1D3BA82C2A4030172AFF5A9050400038A11001FF29406CD0D03FC18E5040802634492CF9294040E603029D8E504001030000000100000010000000C020B24813AF29401490F63FC0F35040804D637B2D98294040C8EBC1A4F35040A0B81E85EB912940106F9D7FBBF35040406BD4433492294014A8FE4124F45040E089592F86CA2940C03AC780ECFC5040C0B2B5BE48E0294054431B800D005140C02CB64945E329400418080264005140A0BEA085041C2A408881204086065140E079008BFC222A4040C5AA4198065140A0E4D4CE30352A4098E4B9BE0F065140C0622AFD844B2A40B0B6D4415E05514060573F36C94F2A4024ED0DBE3005514000B728B341462A4028F911BF62FD5040205A80B6D5442A40409E5DBEF5FC5040000D36751E052A4048A7203F1BF85040C020B24813AF29401490F63FC0F350400103000000010000002600000020295C8FC2152940241A6B7F6779504060CAA48636102940C42EC37FBA785040C02634492CF92840282CF180B2775040E076BF0AF0ED2840DCBB783F6E775040A0656B7D91E028402C14E97E4E77504000A26131EAF2284028232E008D785040C05FE97C78F62840FCD5E3BED5785040C05FE97C78F6284040AA61BF27795040C05758703FE828402CF911BF62795040A08B868C47E128403CB665C059795040E0BEB9BF7AD4284028ED0DBE30795040C0F755B950D928400009C380257B5040E0AF743E3CEB28404480457EFD7D5040E076BF0AF0ED2840E4543200547E5040206BD44334F228406CC4CC3E8F7E5040C0FDD7B969032940E8577380607F50408045B9347E11294004DFA63FFB7F5040809885764E1B294034172AFF5A80504080116DC7D4252940D0CABDC0AC805040C0B3E732353129403C7D04FEF0805040605FD042023E294050465C001A815040000D36751E452940DCA9F23D23815040A0BEA08504BC2940D4B5F63E55815040A0703D0AD7C329405873B9C150815040C0C1FA3F87C92940DCA9F23D23815040A07F828B15CD2940EC39E97DE380504040AD4CF8A5CE29402C232E008D805040C0AF743E3CCB29405470784144805040A082C30B22C229402838F581E47F504080622AFD84AB2940805704FF5B7F5040E0955D30B89E29404C4CDE00337F504000E6E8F17B93294000DC65BFEE7E504020E3A7716F5E2940585260014C7D504060D9E9077559294054465C001A7D50408032384A5E2D29409CDBF63DEA7A50406018213CDA20294044ADA23F347A5040A02634492C19294008CD203EB079504020295C8FC2152940241A6B7F677950400103000000010000001100000060BC9179E4972940D4CDFE40B98D5040406BD4433492294030266F80998D5040C0035ABA828D2940B074B0FECF8D5040C02975C9386E2940DCBB783F6E8F504060DC2A88816E2940D4F4D901D78F5040A02634492C792940540DFB3DB1905040200D36751E852940185D177E7091504000C4094CA78D29406CD993C0E69150406009DCBA9B9729409C11178046925040E076BF0AF0AD2940EC54320054925040409885764EBB294014A27C410B925040009F20B1DDBD29405C31957EC291504040261B0FB6C02940000F45813E91504020F52D73BABC29401C9CFA40F28F504040E2AC889AB82940844B00FE298F504000EE974F56B42940FCDB65BFEE8E504060BC9179E4972940D4CDFE40B98D50400103000000010000001600000000BFB9BF7AB428401C5D177E70815040806ABB09BE99284068CA4E3FA880504040295C8FC29528407893A641D180504000573F36C9AF2840A89ECC3FFA845040C05FE97C78F62840F05AB4006D885040607156444DDC28408854C37E4F8A5040605FD04202DE284044E603029D8A50402020990E9DF62840C4438A01128C5040C014AE47E1FA284048B324404D8C5040407A19C5721B2940D8EE5701BE8D50408094490D6D202940F03C2AFEEF8D504060BB5F05F826294028327381CB8D5040C0ED974F5634294034172AFF5A8C5040A0DB114E0B362940F042ACFE088C5040207D5A457F502940188DB5BFB3865040C020B248134F29409C1117804686504080622AFD844B294010691B7FA2855040406E15C440472940241A6B7F67855040A09BC6F65A1029403020ED7F80835040E0E7154F3DEA28402C1DACFF73825040204E7CB5A3D028406C06F1811D82504000BFB9BF7AB428401C5D177E708150400103000000010000001D0000004048FAB48A262840DCC1FA3F874D504000B3B5BE48202840105D177E704D5040004F95EF19292840D0F19881CA4E504000B4E73235312840884E417E36505040A0AA0B789939284068CD8FBFB451504020965D30B83E28405C40DAFF00535040A02634492C5928402C327381CB595040E0B628B341662840E0AC33BE2F5E5040A0B81E85EB712840146C5CFFAE625040E05A99F04B7D2840D4B2B5BE4864504000000000008028408487A2409F645040C023F3C81F84284068F7AB00DF64504000DF52CE178B2840583A58FFE7645040604E7CB5A3902840BC2EC37FBA645040C0E4D4CE30952840C00166BE83645040202C9D0FCFCA28402C172AFF5A60504000D9D0CDFEE02840E0AC33BE2F5E504040DF6B088EE328406CD993C0E65D5040C05CA8FC6B012940E845ED7E1559504000B1A6B228FC2840845A457F68585040807C410B09F82840980B957F2D585040C0EA56CF49BF284010691B7FA2555040E05A99F04B7D28407C96E7C1DD515040609885764E7B2840F05DF5807951504020B3B5BE48602840A86E2EFEB64F5040A0AD4CF8A54E2840B0984A3FE14E504000356090F4492840106C5CFFAE4E5040C0D58F4DF22B2840848AE3C0AB4D50404048FAB48A262840DCC1FA3F874D504001030000000100000018000000200AF5F41150284028F38FBE49435040A03579CA6A4228405C6D37C137435040E0B628B341062840EC5AB4006D44504040D9E90775F92740580DFB3DB1445040E01F990E9DF62740E839E97DE344504080F1D3B8372F28406CBB09BE694B5040201E8A027D322840302CF180B24B5040A0FA96395D4E284064F7AB00DF4C5040206211C30E5328406C03B001114D504080BC9179E4572840080F45813E4D5040005FD042025E2840D8B5F63E554D504020D6A8876864284030ED0DBE304D5040A0622AFD846B2840500DFB3DB14C50400000000000802840884B00FE294B504060C422861D862840C428417FA14A5040A05CA8FC6BA12840408386FE09475040A082C30B22A22840AC6BED7DAA46504000BC783F6E9F2840EC54320054465040801D71C8069A284004D9243FE245504080B81E85EB912840281A6B7F674550400018080264882840080341800C455040000AF5F41170284090EA3BBF2844504080116DC7D4652840D4F4D901D7435040200AF5F41150284028F38FBE494350400103000000010000001A00000000D13FC1C5F22740ACA78FC01F685040A07F828B15CD27405C73B9C15065504080DC2A8881CE274054499D8026665040002C9D0FCFCA274038B9A64066665040605DC136E2B927400809C38025675040C051D66F269E2740A8A44E401367504060F755B9509927401899B9C0E566504000E5D4CE309527402829B000A666504060DC2A88818E2740148DB5BFB3665040209CDF30D1882740B0984A3FE166504060CDE5064385274004E869C02067504040D6A88768842740BC1F7EFE7B67504040068200198A2740E88711C2A3685040A0AD4CF8A58E2740A8B6D4415E69504020295C8FC2952740C41C3D7E6F6A5040E006B474059B274098E7FA3E1C6B5040E0A9F23D23A12740106F9D7FBB6B5040000F45813EA92740844E417E366C504020356090F4C92740EC45ED7E156D504000013274ECD02740C046CB811E6D5040E0F42D73BAFC2740582E54FEB56C5040E094490D6D00284068BE4A3E766C5040E0703D0AD7032840CCD38041D26B504060A7CAF78C04284044BCE7C0726B504000C74ACCB3022840B0A44E40136B504000D13FC1C5F22740ACA78FC01F68504001030000000100000012000000400473F4F8452740940B957F2D44504040068200192A27408060C77F8142504080B950F9D722274040E603029D4250408045B9347E11274004E869C020435040200AF5F4111027403038F581E4435040A0C1E10511112740504F1F813F4450400090DB2F9F142740D4B5F63E55455040C0C64ACCB32227406CD993C0E6455040405C8FC2F5482740A8B0524145475040C059677C5F4C2740941458005347504060BB5F05F8862740E878CC40654750400023DA8EA98B2740A8B0524145475040E0F0D8CF62892740C440498105475040E08C9AAF927F2740BC490C022B46504080DC2A88816E2740E47E4E417E45504060D6A8876864274044AA61BF2745504060AA0B7899592740E839E97DE3445040400473F4F8452740940B957F2D44504001030000000100000017000000E05758703FE82640543A58FFE7205040C0DB114E0BD626403CADA23F341E5040607D5A457FD026403CC5AA41981E504040301004C8902640846649809A205040008A592F868A2640C42EC37FBA205040A079008BFC8226402C2F3201BF205040A0C554FA0977264028232E008D205040E059677C5F6C264050707841442050404051BD35B0652640F04EB0FF3A205040C0EA56CF495F26405070784144205040205DC136E2592640EC7B0DC171205040A0129F3BC116264048A19E3E02265040E00B040132142640001286014B2650402015C78157132640A86BED7DAA26504000E6E8F17B13264040BCE7C07227504000999EB0C4132640504F1F813F285040E0AC33BE2F1626401466DAFE9528504060116DC7D425264044C269C18B295040803BFBCA832C264030266F809929504000000000008026405476FA415D26504060116DC7D4E526402C266F80992150402018080264E826405473B9C150215040E05758703FE82640543A58FFE720504001030000000100000019000000807A32FFE8B3264030266F809929504040861DC6A4AF26405437177FDB2750402069C53714AE2640846308008E2750404048FAB48AA62640F0818FC18A265040802CB64945A3264040ADA23F342650402009C380259F2640D8AC33BE2F265040E0EA56CF499F2640D8C43BC093265040E0EB6AF2949D264098DBF63DEA2650406048FAB48A862640502E54FEB528504080C2137AFD812640C03AC780EC2850408038BA4A77772640EC8711C2A3285040204E7CB5A37026407C6649809A28504020E929728868264068CA4E3FA8285040A014AE47E15A264070F7AB00DF285040401077F52A5A2640040F45813E295040C079008BFC622640A877F17EDC2A504060CDE5064365264004E869C0202B5040A017EFC7ED6F264074BB09BE692B5040C082C30B22822640C02B82FFAD2B5040006002B7EE8E264070D311C0CD2B504080C554FA099726401490F63FC02B5040200F45813EA926405040DAFF002B504060CAA48636B026407C60C77F812A504000A26131EAB22640A8AD11C1382A5040807A32FFE8B3264030266F809929504001030000000100000014000000200473F4F88526407C87A2409F385040E0B3E73235712640E83F6B7EFC3650408032384A5E6D264070D0D03FC1365040C0EA56CF495F2640E8482EFF21365040606552431B4826402CED0DBE3035504060C2137AFD412640E845ED7E15355040C0E1934E24202640FC1186014B365040E0AD65321CE72540582B137EA93750408017EFC7EDCF2540108DB5BFB3365040C06BED7DAACA254068C4CC3E8F36504040B60F79CBAD25404080457EFD3550402077D84466A6254000E5284014365040E0B628B341A6254044B9A64066365040C06DFC89CAAE2540C4344580D336504000274D83A2D12540BC0166BE83385040A08EC70C543626408093A641D13C5040A09885764E3B26401072DEFFC73C5040803F37346587264028ED0DBE30395040206552431B88264000D6E3BED5385040200473F4F88526407C87A2409F38504001030000000100000017000000C0E1934E24202640100F45813EE14F4000F86EF3C6112640686D37C137DF4F40E091088D600B2640C05626FC52DF4F40209CDF30D10826403038F581E4DF4F40606E15C440072640B8E0F08288E04F40606E15C4400726405873B9C150E14F40605C8FC2F50826400806820019E24F40E091088D600B2640D0D03FC1C5E24F4080FA96395D0E2640109A417C60E34F4060BEA085041C26408048BF7D1DE64F40C0A9F23D2321264058FB743C66E64F40C0622AFD844B26403820ED7F80E74F4040068200196A2640884E417E36E84F4000AB24B20F722640306552431BE84F40C08FDB2F9F7426400821CB8289E74F4080978A8D79752640E0F19881CAE64F40206211C30E7326408048BF7D1DE64F40C06DFC89CA6E2640E0FA5B02F0E54F40005858703F682640B09509BFD4E54F4000A7B1BD164C2640306893C327E54F40001077F52A3A2640602B137EA9E34F40C0703D0AD7232640D8EE5701BEE14F40C0E1934E24202640100F45813EE14F400103000000010000001B00000080B3CEF8BE382640A874B0FECF3D5040C03E3C4B90A12540ACB052414537504080BB5F05F886254068C4CC3E8F3650402054FEB5BC7A25405076FA415D365040C05FE97C7876254048A4DFBE0E375040A01B62BCE67525402420ED7F8037504060B5DD04DF7C2540845D86FF74395040E0C43BC0937E25401C967840D9395040C00F5EBBB4812540E4482EFF213A5040C02975C9388E25405434D6FECE3A5040000C0401329425409CDBF63DEA3A5040606684B707992540D8F19881CA3A504000FEF0F3DFBB2540845704FF5B3B504000301004C8F0254008D6E3BED53C5040E0E1934E240026404C5260014C3D504000E9297288082640208A743FA73D5040A03BFBCA830C264068D993C0E63D5040C018CA89760D2640FCD214014E3E5040A088450C3B0C2640BC344580D33E504080D367075C0F264090E7FA3E1C3F504080978A8D79152640546D37C1373F504020B1A6B2281C2640884B00FE293F5040A0A48977802F2640AC77F17EDC3E5040000341800C352640106C5CFFAE3E504040E2AC889A382640C81C3D7E6F3E5040A09885764E3B264058499D80263E504080B3CEF8BE382640A874B0FECF3D50400103000000010000002C000000E0A7E33103FD2040D876137CD3B64F40C04E95EF19E92040D8C43BC093B64F40401077F52ADA20403829B000A6B64F40406211C30ED32040E0F19881CAB64F408085048C2E97204028EACC3D24B84F4000301004C8902040A0AAD0402CB94F4060573F36C98F2040883CBB7CEBB94F4080D367075C8F2040B0DDAF027CBB4F4040B81E85EB9120409096E7C1DDBD4F40E05417F0329320403029B000A6BE4F4020B6F63E55952040B05626FC52BF4F40A04D637B2D982040A89B8BBFEDBF4F40C091088D60AB204028F04E3E3DC24F402007B47405BB204080423D7D04C44F40606893C327DD2040386E15C440C74F40006E15C440E720405837177FDBC74F40A0BFD2F9F0EC2040D08558FD11C84F400083DC4598FA2040904E417E36C84F402083DC45983A2140302F3201BFC84F400054FEB5BC3A2140D87FD6FCF8CD4F40A05CA8FC6BA12140B074B0FECFD14F4080B08D78B2E32140282CF180B2D34F400006820019EA21408015E0BBCDD34F4000B4E73235F12140582B137EA9D34F4040D026874F5A2240D8B2B5BE48C84F4080B3CEF8BE5822402020ED7F80C74F40C0BEB9BF7A54224078A52C431CC74F40E0C3094CA72D2240D8C77C40A0C34F4080D026874F1A22408854C37E4FC24F40A059677C5FEC2140A8E9B303AEBF4F4040F52D73BADC2140A077F17EDCBE4F40A021E4BCFFBF21409096E7C1DDBD4F4000A26131EA922140080341800CBD4F40803BFBCA838C2140303B3602F1BC4F408017EFC7ED6F214088397AFCDEBC4F4000C2FA3F87692140B8716F7EC3BC4F4040B81E85EB51214088423D7D04BC4F40E0B5F63E55352140D0FD9C82FCBA4F400051BD35B0252140D08BDAFD2ABA4F40C0737E8AE3182140305C8FC2F5B84F4000B6F63E55152140507C7C4276B84F40C0CCCCCCCC0C2140600ABABDA4B74F4060B950F9D70221402841B8020AB74F40E0A7E33103FD2040D876137CD3B64F4001030000000100000029000000E09E20B1DD9D2140A86E2EFEB6E74F4000F2ECF2ADA72140905182FE42DD4F40C0D38041D2A72140D8BEB9BF7ADC4F40206E15C440A72140809065C1C4DB4F4080CDE50643A52140E8AF743E3CDB4F40E053E57B46A22140A86BED7DAADA4F4060C763062A9B2140788AE3C0ABD94F4060129F3BC1962140D00F238447D94F40C00C1D3BA88C2140D8CABDC0ACD84F4020AAF23D23812140584F1F813FD84F4060CAA48636502140903FFCFCF7D64F4000D13FC1C5F22040B8716F7EC3D44F400023DA8EA9EB2040603A58FFE7D44F40806BED7DAAEA2040B068ACFD9DD54F40005858703FE82040908D2441B8D64F40E05A99F04BBD2040D07FD6FCF8D54F40A009DCBA9BB720406031957EC2D54F40E0C3094CA7AD2040206893C327D54F4040DF6B088EA32040B0BF97C283D44F40406893C3279D2040F8230C0396D44F4080BFD2F9F08C2040089700FC53D64F4000E8154F3D8A204030DB87BCE5D64F40A088450C3B8C2040908461C092D74F40207497C4599120403838F581E4D74F4000FBAF73D3A62040D87C957CECD84F40805DDA7058B2204058F833BC59D94F40C0737E8AE3B82040885D86FF74D94F4040BFD2F9F0CC2040508BC1C3B4D94F40E0CABDC0ACE820406055A18158DA4F40C06DFC89CA0E2140E8A6B1BD16DC4F40E0989EB0C4132140905A457F68DC4F40406684B707592140D8F71A82E3E04F40C077F17EDC5E21408054C37E4FE24F40A02634492C5921400806820019E24F4040B3CEF8BE582140B86BED7DAAE24F40407A19C5725B2140286211C30EE34F40E0978A8D79752140A8DA6E826FE64F40605DC136E2792140D876137CD3E64F40C0D03FC1C5922140E0D38041D2E74F40C000193A76982140D000DE0209E84F40E09E20B1DD9D2140A86E2EFEB6E74F400103000000010000000D00000020F52D73BA7C214008BEDBBC71344D4080129F3BC176214008BEDBBC71344D40400C040132742140F8D5E3BED5344D40C01B62BCE6752140101286014B364D4000CA8B4CC07721406040DAFF00374D4060AA0B7899792140A8E9B303AE374D40206893C3277D2140D88558FD11384D40808B868C47812140804E417E36384D40C0116DC7D48521403838F581E4374D40C0116DC7D4852140D8FA5B02F0354D4020634337FB832140905182FE42354D40E0D8D0CDFE802140B0716F7EC3344D4020F52D73BA7C214008BEDBBC71344D400103000000010000001700000080C422861D0621409018213CDAA84F400038A11001FF20409018213CDAA84F4080C1E10511F12040E0A9F23D23A94F4000AAF23D23E120401006820019AA4F4000F52D73BADC2040001E8A027DAA4F40E077F17EDCDE2040884B00FE29AB4F40C02FF7C951F82040F820CB8289AF4F4020FEF0F3DFFB2040D800DE0209B04F40C0F41439440421408818213CDAB04F40206002B7EE0E214068F833BC59B14F40E0978A8D79152140805D86FF74B14F40A020B248132F2140385C8FC2F5B04F40A09885764E3B2140587C7C4276B04F40E02EDE8FDB3F2140D08558FD11B04F40A0978A8D79552140B0E3310395AD4F40A04D637B2D582140889FAA4203AD4F40C01D71C8065A2140B859677C5FAC4F408009DCBA9B572140884B00FE29AB4F40A0716F7EC35421404882FE428FAA4F40402C9D0FCF4A2140503D997FF4A94F40200D36751E452140D8EE5701BEA94F40C0E1934E242021409018213CDAA84F4080C422861D0621409018213CDAA84F4001030000000100000015000000C05758703FC82040B859677C5F944F4020AAF23D23C12040B859677C5F944F40001077F52ABA2040A8BF97C283944F4000295C8FC2B52040503A58FFE7944F40206BD44334B22040301A6B7F67954F40E0DE52CE178B2040E0031F83159D4F4040180802648820400848A643A79D4F4020C2FA3F8789204058F833BC59A14F4040068200198A204070A2EBC20FA24F40E06ABB09BED92040805A457F68A44F40A021E4BCFFDF204038F6D03E56A44F4020AE65321CE7204050793BC269A34F4000EC6AF2941D214050FEB5BC729B4F40801A3048FA242140888AE3C0AB994F4080BB5F05F8262140484F1F813F984F4020B728B341262140905704FF5B974F40A0069B3A8F2221406828D2FD9C964F406014AE47E11A2140801B62BCE6954F4020A7B1BD160C2140B89ECC3FFA944F40C06ABB09BEF92040A8BF97C283944F40C05758703FC82040B859677C5F944F400103000000010000001100000020C2FA3F8789204028F6D03E56944F4040D367075C6F204010DFA63FFB934F40A01EA33CF36A2040B859677C5F944F40406C06B820632040B06E2EFEB6974F40409885764E5B2040206211C30E9B4F4000FEF0F3DF5B2040909065C1C49B4F40E0C43BC0935E2040B059677C5F9C4F40A0B950F9D7622040A0716F7EC39C4F40E0D38041D2672040100341800C9D4F40602975C9386E204038ED0DBE309D4F40801B62BCE6752040D888997D1E9D4F4060A148F7737A2040A8ECF483BA9C4F4080FA96395D8E2040C87C957CEC984F4060BEA085049C20408848BF7D1D964F40209F20B1DD9D204000A0C37C79954F40001286014B9E204080397AFCDE944F4020C2FA3F8789204028F6D03E56944F4001030000000100000017000000C077F17EDC1E2040C806600322924F40E0C64ACCB3022040B0A10DC006924F40006CED7DAAEA1F4080A2EBC20F924F40C0300BED9CB61F40605260014C954F40C07E69519FB41F40305FD04202964F40C02EE3A606BA1F406828D2FD9C964F4040AAF23D23C11F4078A52C431C974F40C000193A76182040286893C3279D4F40E0E1934E24202040901B62BCE69D4F404051BD35B02520408048BF7D1D9E4F40E0A6B1BD162C2040B8AD11C1389E4F40A05DDA7058322040E0AC33BE2F9E4F40C0F755B950392040285FD042029E4F4000C53BC0933E2040D8CDFE40B99D4F4020CBBDC0AC482040B059677C5F9C4F4080129F3BC1562040385C8FC2F5984F4040E2AC889A58204038172AFF5A984F404038A110015F2040000C040132944F4020BC783F6E5F204000C79E3D97934F4080A148F7735A2040B8B0524145934F402051BD35B0452040D8D03FC1C5924F40E059677C5F2C2040B053E57B46924F40C077F17EDC1E2040C806600322924F400103000000010000001A000000606211C30E53204078AEEFC341AE4F40609BC6F65A5020401048A643A7AD4F40606C06B820432040F02CCF83BBAB4F4020861DC6A42F204008D9243FE2A94F40E06BED7DAA2A2040A8C2D84290A94F4000013274ECF01F400021CB8289A74F400015AE47E1FA1F40A8DDAF027CAB4F408096766A2EF71F40E0A6B1BD16AC4F40C0E9245B5DEE1F40D8BEB9BF7AAC4F40004D689258B21F40E0CDFE40B9AD4F4040B950F9D7821F4000A0C37C79AD4F4040310BED9C361F40B0DA6E826FAE4F404040321D3A2D1F4058853FC39BAF4F4000713D0AD7231F409093A641D1B04F40803E3C4B90211F40E0C1FA3F87B14F4040977153031D1F4030DEC83CF2B34F40C0EA56CF491F1F4030232E008DB44F40C0989EB0C4F31F40889065C1C4BB4F40606552431B082040D0F4D901D7BB4F4060BB5F05F82620408015E0BBCDBB4F40206002B7EE2E2040002DCF83BBBB4F40E01D8A027D322040A8B0524145BB4F40602634492C59204058793BC269B34F4000FEF0F3DF5B20403035B401D8B24F40405FD042025E2040B05CA8FC6BB14F40606211C30E53204078AEEFC341AE4F4001030000000100000014000000C06893C3273D1F40D8FD9C82FC824F4040977153031D1F4038F04E3E3D824F40C0921CB0AB091F40881EA33CF3824F4000AE47E17AD41E40585260014C854F4000B950F9D7C21E4008E5284014864F40803D4162BBBB1E4000C45DBD8A864F4080DAFD2AC0B71E40D009A1832E874F40C0B5F63E55D51E40E0D03FC1C58A4F40403106D671DC1E40A8B05241458B4F4000323D6189E71E40B0DDAF027C8B4F4040E17A14AE471F4060431B800D8C4F40C046EBA86A621F40080C0401328C4F40C04D637B2D981F40A8622AFD848B4F4000EB56CF499F1F40306211C30E8B4F40801FB75F3EA91F40D0066003228A4F400076C4211BA81F40A05CA8FC6B894F4040ED7E15E09B1F40306E15C440874F40C076BF0AF08D1F4088AEEFC341864F4080A148F7735A1F40A07A32FFE8834F40C06893C3273D1F40D8FD9C82FC824F40010300000001000000150000004045B9347E311E4028F911BF62794F408079E750860A1E4038EACC3D24784F408093179980EF1D4010068200197A4F400018080264E81D406082FE428F7A4F4040EB56CF49DF1D40901EA33CF37A4F40C0716F7EC3D41D40B8B05241457B4F40808B6D52D1C81D40A8DDAF027C7B4F4080BFD2F9F0AC1D40809065C1C47B4F404046EBA86AA21D40E0A6B1BD167C4F40009A999999991D40D0BEB9BF7A7C4F408007AF5DDA801D40E0CDFE40B97D4F4080EA5BE674791D40E8AC33BE2F7E4F4040A8FC6B79751D40E076137CD37E4F40008FC70C54761D40F820CB82897F4F4040B3CEF8BE981D40885704FF5B874F40800D315EF36A1E40B87A32FFE88B4F40C099999999991E40D8B837BF618A4F40405512D907D91E40A8B393C151804F40C0B5F63E55D51E4010D3A23EC97F4F4040CDCCCCCCCC1E4008BB9A3C657F4F404045B9347E311E4028F911BF62794F400103000000010000000F0000004023DA8EA98B1B4058FEB5BC72634F40C0CDFE40B97D1B4060793BC269634F40803E3C4B90211B40B8A44E4013674F40C05DC136E2191B40B0622AFD846B4F4000A148F7731A1B40E00CE2033B6C4F40C03465A71F241B4028232E008D6C4F40C0D5AD9E933E1B40A8ECF483BA6C4F4080DE57E542A51B40E0031F83156D4F40005517F032B31B40383B3602F16C4F40C0BEA08504BC1B4000240C03966C4F40805B94D920C31B40D8A6B1BD166C4F40809DF3531CC71B4050FEB5BC726B4F40C0921CB0ABC91B40A85CA8FC6B694F40C0012D5DC1961B40382CF180B2634F404023DA8EA98B1B4058FEB5BC72634F4001030000000100000016000000004D689258F21A40281A6B7F67554F4000ED832C0BB61A40582B137EA9534F408052B81E85AB1A4000DFA63FFB534F40805DC136E2991A4050FB743C66564F4080F755B950991A40586D37C137574F40C0D576137CB31A4058431B800D5C4F40C038BA4A77B71A40B0716F7EC35C4F404070422102BE1A40905182FE425D4F4000B728B341C61A4010CD203EB05D4F40C0E1B19FC5D21A4028327381CB5D4F400008AF5DDA801B40E009A1832E5F4F4000DC2A88818E1B403841B8020A5F4F40001C62BCE6951B40E0C43BC0935E4F40008813984E9B1B40385FD042025E4F4040035ABA82AD1B40E0D03FC1C55A4F4000EA245B5DAE1B40583D997FF4594F4080DE57E542A51B409018213CDA584F40807C462234921B40884E417E36584F4040A3755435711B400021CB8289574F404020B75F3E291B4000C45DBD8A564F40406893C327FD1A400848A643A7554F40004D689258F21A40281A6B7F67554F400103000000010000001400000080634337FB031940E006600322324F4040643E20D0E91840483D997FF4314F4080438CD7BCDA1840383E7782FD314F408009DCBA9B971840383E7782FD314F4040944E24987A1840383E7782FD314F4040C74ACCB3621840B8B915C26A324F4000E4D9E55B4F184038E78BBD17334F4000CEFE40B93D1840E0F4D901D7334F40C0ED7E15E01B184070A52C431C374F40000ADCBA9B171840F84D2844C0374F4000295C8FC2B5184008CADFBDA3384F40800F5EBBB4C11840806649809A384F40C051BD35B0451940D8CDFE40B9354F40C02861A6ED4F1940001B498270354F4040583A1F9E551940503A58FFE7344F404014B35E0C551940F80B040132344F40C0DC2A88814E1940602B137EA9334F40803D4162BB3B1940504CDE0033334F40C022DFA5D425194000D061BEBC324F4080634337FB031940E006600322324F400103000000010000001A00000040861DC6A4CF174080CC07043A9D4D4000310BED9CB61740D088997D1E9D4D40008D9AAF929F1740081B4982709D4D4080A148F7739A1740305FD042029E4D40C0D8D0CDFEA0174008BB9A3C659F4D40C0967153039D1740908AE3C0ABA14D40C04813EF009F1740001E8A027DA24D4000F0DDE68DA3174038E78BBD17A34D40408D959867C51740885A457F68A44D40405512D907D9174078397AFCDEA44D400094179980EF1740306893C327A54D40409DF3531C071840D0B5F63E55A54D4080B81E85EB111840E088997D1EA54D40808713984E1B184008D6E3BED5A44D4080C422861D2618405870784144A44D4000B0743E3C2B1840082DCF83BBA34D4080E7FC14C7311840B8B0524145A34D4040A8FC6B79351840A8E67283A1A24D40C0D026874F3A18401006820019A24D4080240C03963C184020F911BF62A14D4080BEA085043C1840D0CABDC0ACA04D40C08EC70C5436184080C9C6832DA04D40C04F90D8EE2E1840004E2844C09F4D40C0934E2498FA1740801B62BCE69D4D4000013274ECF017400048A643A79D4D4040861DC6A4CF174080CC07043A9D4D400103000000010000001E00000080F52D73BA5C1740808D2441B81E4F408020B248134F1740F0298E03AF1E4F4080313D618967174000E869C020234F408076C4211B681740582B137EA9234F40C05512D907591740503D997FF4294F40C05FE97C78561740A86BED7DAA2A4F4040C64FE3DE3C17406834D6FECE2A4F40403BE2900D341740584CDE00332B4F40C05417F03233174010DFA63FFB2B4F40008FC70C54361740D8AC33BE2F2E4F40404069A851381740883FFCFCF72E4F40402861A6ED4F17401006820019324F40004913EF005F1740A87A32FFE8334F4080809BC58B651740885A457F68344F4000A8FC6B79751740885182FE42354F408037BF61A291174078AEEFC341364F4040323D6189A71740808D2441B8364F4000E5D4CE30B51740E0F19881CA364F40805EBC1FB7BF17403829B000A6364F4080716F7EC3D4174010E5284014364F40002DB64945E31740306893C327354F40C05C8FC2F5E817409087A2409F344F40808713984E1B1840386893C3272D4F40C0EFA65B7618184008D9243FE2294F40004A0ED8D5C41740A8A78FC01F244F4000310BED9CB61740904B00FE29234F40405DC136E29917405073B9C150214F40C03D4162BB7B17400821CB82891F4F40804D689258721740606D37C1371F4F4080F52D73BA5C1740808D2441B81E4F40010300000001000000190000000038BF61A2D1174050FEB5BC720B4E40406BBB09BEB9174098C2D84290094E40C0EC832C0BB61740286BD443340A4E4080DE57E542A51740109700FC530E4E4000F0DDE68DA317402838F581E40F4E40405C8FC2F5A8174030F911BF62114E40404D689258B217404807793D98124E40804069A851B8174028E78BBD17134E40805EBC1FB7BF1740A8622AFD84134E4000D253E410D11740080C040132144E4000C2FA3F87E9174028232E008D144E40008FC70C54F61740F8230C0396144E4000D6AD9E93FE1740D80CE2033B144E40407497C459111840E0D03FC1C5124E40C013B35E0C151840D806600322124E40009A999999191840682E54FEB5104E40C05512D907191840E0D38041D20F4E40C0C554FA091718402841B8020A0F4E40007C462234121840A8DA6E826F0E4E40C0B628B341061840281A6B7F670D4E408077F17EDCFE1740809FAA42030D4E4080EC832C0BF6174060888043A80C4E4040E07F2BD9E11740100C0401320C4E40405512D907D91740E87954FCDF0B4E400038BF61A2D1174050FEB5BC720B4E4001030000000100000008000000405512D907D9174008BEDBBC717C4D40008ECC237FD01740A8A78FC01F7C4D40C09CF3531CC71740E00CE2033B7C4D40C0E17A14AEC71740D088997D1E7D4D40403D0FEECECA174030327381CB7D4D40C01B62BCE6D51740D8FA5B02F07D4D4040C554FA09D71740F8CC203EB07D4D40405512D907D9174008BEDBBC717C4D40010300000001000000180000004046B41D539716408821E4BCFF174F4080573F36C96F1640B06E2EFEB6174F40404391EEE7341640F8D2A23EC9174F40005C8FC2F52816408821E4BCFF174F4000F3052D2420164020172AFF5A184F400051BD35B005164050431B800D1C4F4040B728B341061640B0ECF483BA1C4F40C07497C4591116400821CB82891F4F40005A677C5F2C1640B0622AFD84234F4000A375543531164080A86DC328244F4040F6285C8F421640603A58FFE7244F40407E6E68CA4E1640080341800C254F4040BC783F6EBF16400848A643A7254F4040DC2A8881CE1640B868ACFD9D254F40807A19C5723B1740881EA33CF3224F4000240C03963C17405055A18158224F40C09BC6F65A301740B0A78FC01F1C4F4040FCAA5CA82C174060793BC2691B4F4080D38041D22717406034D6FECE1A4F40C0AB1F9BE4171740603D997FF4194F40008E9598670517405873B9C150194F4000944E2498FA164090457EFD10194F4000DF52CE17CB16401018080264184F404046B41D539716408821E4BCFF174F400103000000010000000900000040977153031D1740D80F238447794D40C045B41D53171740305C8FC2F5784D40C0DE52CE170B174088457EFD10794D40403F373465071740588BC1C3B4794D40800D36751E051740B0B915C26A7A4D4000D57B2AA70D174010D061BEBC7A4D40400C040132141740381DACFF737A4D40C0438CD7BC1A1740303E7782FD794D4040977153031D1740D80F238447794D400103000000010000000E000000C0D38041D2E71640383E7782FD894D4000F52D73BADC164030D8463CD9894D40009DF3531CC7164038F04E3E3D8A4D4000310BED9C36164090C9C6832D904D408045B9347E311640682E54FEB5904D40C0B950F9D7421640C053E57B46924D40404C361E6CC11640B0E0F08288904D40C099999999D9164000BB9A3C658F4D40402A8E03AFE61640B85FE97C788E4D4040E7FC14C7F1164008240C03968C4D40C03AE2900DF41640D07954FCDF8B4D4080D576137CF31640E0FD9C82FC8A4D40404F90D8EEEE1640B8B915C26A8A4D40C0D38041D2E71640383E7782FD894D400103000000010000001F000000005517F032331640686D37C137374E4000B1A6B2281C1640F8DB65BFEE364E40C0E3D9E55B0F16403041B8020A374E40808D959867051640C05626FC52374E4000F2D3B837EF1540806649809A384E4040B1A6B228DC154080A2EBC20F3A4E40402861A6EDCF1540286211C30E3B4E40C03D0AD7A3701540386211C30E434E40C0B5F63E55951540002A8E03AF464E40408ECC237FD01540508BC1C3B4494E40C04813EF001F164000A0C37C794D4E40C0E95BE674391640A85FE97C784E4E40C007AF5DDA40164028DB87BCE54E4E40C025396057531640089D82FC6C504E400060E97C78561640D8A9F23D23514E4040A148F7735A1640084BE7C3B3524E4040977153035D1640B059677C5F544E40C08713984E5B1640D87FD6FCF8554E4000ED7E15E05B1640B077F17EDC564E40404913EF005F16400821CB8289574E4080F1D3B8376F164028EACC3D24584E40006BBB09BE79164030172AFF5A584E40400D36751E85164090C9C6832D584E40003BE2900DB41640D8BB783F6E574E400015AE47E1BA1640803FFCFCF7564E40C00F5EBBB4C11640109700FC53564E4040B728B341C616405855A18158524E40402EE3A606BA1640A0BF97C2833C4E4000A8FC6B79B51640A87A32FFE83B4E4040FCAA5CA86C1640909C69C2F6374E40005517F032331640686D37C137374E4001030000000100000014000000C0999999991916405055A18158F24D400091F469150D16408054C37E4FF24D4080FDD7B9690316405007793D98F24D40C0AA24B20F72154010CD203EB0FD4D4000EA245B5D6E1540089700FC53FE4D408045B9347E7115406040DAFF00FF4D4040E9297288C8154090CC07043A054E4080861DC6A4CF15401048A643A7054E4040B728B34106164078A52C431C074E4080A148F7731A164058853FC39B074E40C013B35E0C95164098C2D84290094E40C0E07F2BD9A1164000274D83A2094E40809AD024B1A41640D8BB783F6E074E4080313D6189A71640109A417C60034E4000D48041D2A71640908AE3C0AB014E40C0298E03AFA61640A89B8BBFEDFF4D4040F0DDE68DA31640506D37C137FF4D40409CF86A47611640082A8E03AFF64D408046EBA86A221640004BE7C3B3F24D40C0999999991916405055A18158F24D400103000000010000002200000080CCD1E3F7A61540884E417E36E04D4080FF04172B9A154090C9C6832DE04D4040AAF23D23811540884E417E36E04D408038BA4A777715405801F73C7FE04D40C0F1D3B8376F1540E0F71A82E3E04D40C00F5EBBB441154030F6D03E56E44D40C081C8224D3C154088397AFCDEE44D4040E2AC889A381540587FBDC282E54D400077BF0AF00D154000301004C8F04D4000105EBBB401154020F6D03E56F44D4080AB1F9BE4171540306211C30EFB4D400007B474051B1540889065C1C4FB4D400046EBA86A221540080C040132FC4D40400E315EF32A1540B0BF97C283FC4D40001E8A027D52154008BEDBBC71FC4D4000B1A6B2285C154078A86DC328FC4D404022DFA5D4A5154030172AFF5AF84D4040D576137CB31540A8BC564277F74D40C0BB783F6EBF1540B85FE97C78F64D4080490ED8D5C41540901B62BCE6F54D4080ED7E15E0DB1540D08BDAFD2AF24D40408D9AAF92DF1540805D86FF74F14D4040573F36C9EF154058499D8026EE4D4000ED832C0BF6154038D505BCCCEC4D40C04069A851F81540E0A6B1BD16EC4D40802634492CF915402814E97E4EEB4D4040944E2498FA15408818213CDAE84D40C014AE47E1FA15400809C38025E74D4040E2AC889AF815400048A643A7E54D40003BE2900DF41540000341800CE54D400095490D6DE0154008D061BEBCE24D4080944E2498BA1540682E54FEB5E04D4040AB24B20FB215400018080264E04D4080CCD1E3F7A61540884E417E36E04D400103000000010000002E00000080D47B2AA70D1540A8AD11C138E64D4080B1A19BFD411540B09B8BBFEDDF4D4000931CB0AB491540082A8E03AFDE4D40C03E3C4B90611540D806600322DA4D4080977153035D1540E0C1FA3F87D94D400078F17EDC3E1540B89B8BBFEDD74D4080035ABA822D1540386E15C440D74D40C0703D0AD72315405840DAFF00D74D40C0EFA65B76181540B077F17EDCD64D40806211C30E13154000BB9A3C65D74D40C009DCBA9B171540E0D38041D2D74D404085EB51B81E1540604F1F813FD84D40C022DFA5D42515404801F73C7FD84D4000C64FE3DE3C1540888AE3C0ABD94D4000F2D3B8372F1540D076137CD3DE4D40C0FBAA5CA82C15400821CB8289DF4D4040323D6189271540E08558FD11E04D404022DFA5D4E51440B8B393C151E04D40C0ED7E15E0DB1440E08558FD11E04D40C0490ED8D5C4144038DB87BCE5DE4D40401A355F25BF14406076FA415DDE4D40406893C327BD1440A8E3310395DD4D40409BC6F65AB01440C88558FD11D84D4040A646E867BA14404035D07CCED54D4040A5A2B1F6C71440889FAA4203D54D40C090F46915CD1440A0C2D84290D14D404077BF0AF0CD144008301004C8D04D40003AE7A738CE1440E0C43BC093CE4D400089450C3BCC144028327381CBCD4D40803788D68AC61440905182FE42CD4D408014AE47E1BA1440D80CE2033BCC4D40C0A59D9ACBAD14403014E97E4ECB4D4040EB56CF499F1440381DACFF73CA4D4040F0A65B76981440D0B837BF61CA4D40404D68925872144010C11C3D7ED14D4040E17A14AE471440E082177D05E34D4080FBAF73D3461440D0F4D901D7E34D4000E92972884814408887A2409FE44D40C069C537146E14402029B000A6EE4D4040A3755435711440905704FF5BEF4D40806ABB09BE791440B8E9B303AEEF4D40C03788D68A861440004E2844C0EF4D40406211C30E931440500ABABDA4EF4D40008813984E9B1440D809A1832EEF4D408047E6913F081540608E0244C1E64D4080D47B2AA70D1540A8AD11C138E64D4001030000000100000019000000802A8E03AF26154088423D7D049C4D4080F8872D3D0A154090992842EA924D40C0B1A19BFD011540C8D03FC1C5924D40C04F90D8EEEE14401015C78157934D40C03465A71FE414401015C78157934D40C0B950F9D7C2144090992842EA924D4080D6A88768A41440C053E57B46924D40C04813EF009F14405834D6FECE924D40C0E8297288881440A874B0FECF994D4000B728B34186144078812040869A4D40009DF3531C87144048707841449C4D4080CCCCCCCC8C1440608BC1C3B4A14D4000DC2A88818E14408881204086A24D40408EC70C54B61440000C040132B44D40C0BEA08504BC1440B8ECF483BAB44D40809DF3531CC7144088397AFCDEB44D40407C462234D21440905A457F68B44D4080B3CEF8BED8144028DEC83CF2B34D40002DB64945E31440B0984A3FE1B24D4000D6A88768241540E8A9F23D23A94D40802A8E03AF261540009D82FC6CA84D40C0953FDF162C1540D07C957CECA04D40C0FBAA5CA82C1540206E15C4409F4D40C0953FDF162C15405076FA415D9E4D40802A8E03AF26154088423D7D049C4D4001030000000100000010000000401E8A027D12154000CADFBDA3004E4000356090F4091540B0B393C151004E40804C6DA983CC1440908AE3C0AB014E40C0E3A25A44C41440B0A10DC006024E4080F9821612B0144060793BC269034E4040963FDF16AC144080423D7D04044E4000C2FA3F87A91440B0ECF483BA044E4000F3052D24A01440386552431B084E40005A677C5FAC1440803FFCFCF70E4E4040013274ECB01440788461C0920F4E40808C9AAF92DF144030D505BCCC0C4E40801A3048FAE4144058707841440C4E4000356090F409154010D3A23EC9074E40C0573A1F9E151540801B62BCE6054E40805FE97C78161540E088997D1E054E40401E8A027D12154000CADFBDA3004E400103000000010000000B0000008041649126DE1440883FFCFCF71E4E4080E1B19FC5D21440E076137CD31E4E4080E6012CF2CB144030F38FBE491F4E40804C6DA983CC144030EACC3D24204E40C01D8A027DD21440C8CABDC0AC204E404007B47405DB144030E109BDFE204E4040D48041D2E7144090457EFD10214E40C04F90D8EEEE1440806649809A204E40C0BFD2F9F0EC1440D0D38041D21F4E4080CCD1E3F7E6144030F38FBE491F4E408041649126DE1440883FFCFCF71E4E400103000000010000001400000040240C0396BC134020E78BBD17E34E40C03D0AD7A3B01340781EA33CF3E24E408020B248138F134058F5F23B4DE44E4040B728B341861340480DFB3DB1E44E40807A19C5723B1340D8FD9C82FCEA4E408038BA4A77371340F8C69E3D97EB4E404082C8224D3C1340C80CE2033BEC4E400085F068E37813404873B9C150F14E4000E9297288881340D08BDAFD2AF24E408076C4211BA8134088992842EAF24E4080FE092E56B41340386211C30EF34E4000A243E048C01340B8984A3FE1F24E40C0E6012CF2CB1340B06BED7DAAF24E40C020B24813CF1440C8B5F63E55ED4E40002DB64945E31440C80CE2033BEC4E4040D6A88768E41440F8C69E3D97EB4E4040D9D0CDFEE0144078992842EAEA4E40C05417F032B31440080F45813EE94E40C0BEA08504FC134038232E008DE44E4040240C0396BC134020E78BBD17E34E400103000000010000000F00000040A5A2B1F6C7144030F6D03E56344E40C076BF0AF08D1440104BE7C3B3324E4000EFAB72A172144078CC07043A354E4080B5F63E551514405840DAFF003F4E40C007AF5DDA00144000DFA63FFB434E40C0EFA65B76581440588BC1C3B4414E4000F3052D24A014405840DAFF003F4E4040013274ECB0144070AEEFC3413E4E4000DBFD2AC0B7144038327381CB3D4E4040F6285C8FC21440B0ECF483BA3C4E4080E6012CF2CB1440886308008E3B4E4080DC2A8881CE14403035B401D83A4E40C01B62BCE6D51440D0AC33BE2F364E40806AC020E9D31440A8B6D4415E354E4040A5A2B1F6C7144030F6D03E56344E400103000000010000001500000040CEFE40B9BD1440F82F1004C8404E40803D0AD7A3B01440282F3201BF404E408076C4211B681440E00CE2033B444E408020B248134F1440E0B5F63E55454E4000E3A7716F1E1440D07FD6FCF8454E404091EF52EAF21340D8D38041D2474E40808EC70C54B6134080397AFCDE4C4E4040E5D4CE30B5134000A0C37C794D4E40C0DE52CE170B144080397AFCDE4C4E40C05FE97C78161440500DFB3DB14C4E4080068200196A1440A86BED7DAA4A4E40003BE2900D741440D0B837BF614A4E4040240C03967C1440283E7782FD494E4000323D6189A71440805704FF5B474E404082C8224DBC1440385FD04202464E40800F5EBBB4C1144008A0C37C79454E40C0921CB0ABC91440080C040132444E4080E6012CF2CB1440B8DDAF027C434E40C0DE52CE17CB1440C8EE5701BE414E40803788D68AC61440E8A9F23D23414E4040CEFE40B9BD1440F82F1004C8404E40010300000001000000140000000083C30B22A21440301DACFF734A4E40C08A7269FCA2144038D8463CD9494E408009DCBA9B97144008D9243FE2494E4000356090F4491440D80CE2033B4C4E40C021E4BCFF3F1440F0230C03964C4E4040A5A2B1F6071440785704FF5B4F4E40C02EE3A606FA1340504F1F813F504E40400E315EF3AA1340D87FD6FCF8554E40802FDE8FDB9F13402841B8020A574E40C0B1A19BFD811340381DACFF735A4E40C00D315EF36A13406031957EC25D4E4000013274EC70134088AEEFC3415E4E4080240C03967C134008E52840145E4E40C076BF0AF0CD134038F6D03E565C4E400052B81E85EB1340B8DDAF027C5B4E4080EFAB72A1F21340D082177D055B4E40004A0ED8D5841440E076137CD34E4E4040861DC6A48F144010CD203EB04D4E40C08C9AAF929F1440884B00FE294B4E400083C30B22A21440301DACFF734A4E400103000000010000000A0000004051BD35B045144050499D8026F64E4080240C03963C1440A09509BFD4F54E40009F20B1DD1D144050888043A8FC4E4040356090F4091440D0EE5701BE014F4080C422861D661440281DACFF73024F40804F90D8EE6E144038F04E3E3D024F400054E57B468214403041B8020AFF4E4000301004C850144038F38FBE49F74E40C088450C3B4C1440002A8E03AFF64E404051BD35B045144050499D8026F64E400103000000010000001500000000EFAB72A172144000D3A23EC9174E4080068200196A1440B8BC564277174E408014AE47E1FA1340B07A32FFE81B4E4040F0A65B76D81340E8AC33BE2F1E4E4000D57B2AA7CD1340386E15C4401F4E4000931CB0ABC913403038F581E41F4E40806893C327BD134058793BC269234E40C014AE47E1BA1340B0A78FC01F244E40806ABB09BEB91340383B3602F1244E40C00C36751EC51340888D2441B8364E4040E3A7716FDE13405001F73C7F384E40003465A71FE41340089D82FC6C384E4080F8872D3D4A144078A86DC3282C4E40C009DCBA9B5714404855A181582A4E40004B3B35975B1440C8EE5701BE294E4000D6A88768641440B0E9B303AE274E4040809BC58B65144038DB87BCE5264E4040323D6189671440585260014C254E4000AB24B20F721440682B137EA91B4E40C0D576137C73144028F911BF62194E4000EFAB72A172144000D3A23EC9174E400103000000010000001B00000080AA24B20FF21340B8B6D4415E8D4E400052B81E85EB134000DFA63FFB8B4E4000EB56CF49DF1340881EA33CF38A4E40008ECC237FD0134008068200198A4E40C0703D0AD7A313400818080264884E40C0B1A19BFD81134090992842EA8A4E4080704221027E1340806308008E8B4E40C04069A851781340D8A6B1BD168C4E4000FCAA5CA86C1340A8A78FC01F8C4E4000DE57E542651340302CF180B28B4E40008E959867451340A8AAD0402C894E408053E57B46421340507C7C4276884E40C07C410B0938134008CD203EB0854E4080EFAB72A1321340B8AD11C138864E4000EA245B5D2E1340D876137CD3864E4000045ABA822D1340480ABABDA4874E4000CCD1E3F726134008D061BEBC924E4040068200192A134060FEB5BC72934E4040884A23666613403841B8020A974E4000ED832C0BB61340B0B393C151984E40404C361E6CC11340206552431B984E40C0E8297288C81340A8E9B303AE974E40C0012D5DC1D61340E0C43BC093964E4000F855B950D913409096E7C1DD954E404045B9347EF113402041B8020A8F4E4080EFAB72A1F2134088AEEFC3418E4E4080AA24B20FF21340B8B6D4415E8D4E4001030000000100000012000000004F95EF19C912405076FA415D7E4E404078F17EDCBE1240081286014B7E4E400061E0B9F79012400800000000804E4040F30016F98512408818213CDA804E4040CEFE40B97D12401006820019824E408014AE47E17A12406034D6FECE824E4000240C03967C1240B077F17EDC864E4000D6AD9E937E1240480ABABDA4874E40405B94D920831240604F1F813F884E404079E750868A1240E0CABDC0AC884E40C03106D6719C124060F833BC59894E4040884A2366A61240080F45813E894E40C0035ABA82AD12408893A641D1884E40407F69519FB412408021E4BCFF874E40C033695375DF12400800000000804E4000D9D0CDFEE01240888461C0927F4E4000B1A6B228DC1240883FFCFCF77E4E40004F95EF19C912405076FA415D7E4E40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('PL','PL','POL','616','Poland','30629','38195558','150','151','19.401','52.125','0106000020E6100000010000000103000000010000009C030000CFD90242EBD93240A7AD11C138C24840A3073E062BDA32407C6308008EC34840CC5D4BC807D93240FDDB65BFEEC648402BDB87BCE5D632407AA86DC328CC4840CF4E0647C9CF32402AE44A3D0BD648404ED367075CCF3240FF9600FC53D648404DD9E90775C9324028F38FBE49D748405055A18158A23240A9DA6E826FDE484007F0164850943240A7B393C151E84840A8716F7EC39432407AA86DC328F4484027F6D03E569432402CD505BCCCF448407E9065C1C4933240000341800CF5484004763579CA8E3240D47FD6FCF8F54840D1CDFE40B98D324052499D8026F64840A7ECF483BA8C3240FCE4284014F648407E8AE3C0AB5932407EC9C6832DF8484029ED0DBE304532405307793D98FA4840286552431B18324082397AFCDE044940D4635B069C0D324092EA3BBF28074940D53DB2B96A023240AB5CA8FC6B014940A777F17EDCEE31402A1A6B7F67FD48407AA86DC328EC3140000341800CFD4840CE548847E2E93140AA9ECC3FFAFC4840D734EF3845E331407B9FAA4203FD484055C2137AFDE13140000341800CFD4840295FD04202DE3140A8E3310395FD484001857AFA08D831407C60C77F81FE484050C422861DD63140D576137CD3FE4840FC17080264A83140AB9509BFD40D4940257A19C5729B31407C992842EA124940A774B0FECF993140282CF180B2134940CC5D4BC8079931405470784144144940FE0E45813E993140520DFB3DB11449400473F4F8BD9931407B9FAA4203154940AA622AFD849B3140AB9509BFD4154940D63A71395E9D3140FCE42840141649407F8461C0929F31408048BF7D1D164940276BD44334A23140295FD042021649402BDB87BCE5A63140295FD0420216494051C1E10511B13140D4F19881CA1649407C992842EAB231402541B8020A174940514CDE0033C331407E54C37E4F1A4940ABE7A4F78DC33140FD4AE7C3B31A4940D2C77C40A0C3314029E78BBD171B4940FD14C78157C33140FFCC203EB01D4940D734EF3845C331402AE44A3D0B1E4940F92F1004C8C031408048BF7D1D264940CE548847E2B93140272F3201BF284940CC5D4BC807B93140D47C957CEC284940FE0B040132B4314027F911BF62294940276BD44334B231407AABAE4335294940800F5EBBB4B13140D3F71A82E3284940FA264D83A2B131405401F73C7F28494052B81E85EBB1314002BB9A3C65274940A6EF3504C7B1314079AEEFC3412649407AABAE4335B13140D47FD6FCF8254940D4B837BF61AA31407F4B00FE29234940286552431BA831405182FE428F224940276BD44334A23140253E7782FD2149407E8D2441B89E3140253E7782FD214940A777F17EDC6E31405307793D982249407E18213CDA6031407E9065C1C4234940ABEAE5779A4831402AE109BDFE284940FF058200193A3140FE0B0401322C4940FB95CE8767353140AB9509BFD42D494057B08D78B2333140D2C43BC0932E4940D731AEB8381E3140D0D03FC1C532494004763579CA0E314029232E008D3449402AE109BDFEF03040A7E9B303AE374940D82E6D382CE9304027F6D03E563849402AE44A3D0BE630402B172AFF5A384940A77A32FFE8E33040514F1F813F384940514CDE0033E330407D21E4BCFF3749407E8D2441B8DE30407DCC07043A354940D731AEB838DE304082397AFCDE3449402B69C53714DE304029232E008D344940D2C43BC093DE3040D57954FCDF3349407D21E4BCFFEF304000C79E3D972B4940CC5D4BC807F93040A7E9B303AE274940AA656B7D910031407E9065C1C41B49407C9C69C2F6F73040A5BF97C2831C4940CE548847E2E93040D3BEB9BF7A1C494057B3CEF8BEE8304001BEDBBC711C494058AA0B7899D93040A9A10DC0061A494001857AFA08D83040FA264D83A2194940F92F1004C8D03040FB20CB8289174940D2C43BC093CE304055FB743C6616494053D0ED258DCD3040EA5DBC1FB715494027F911BF62C93040253E7782FD1149407E8AE3C0ABB93040A8716F7EC30C494056BC9179E4B73040A5BF97C2830C49407F129F3BC1B63040D3BEB9BF7A0C4940FE0B040132B43040FB230C03960C494027F6D03E56A430407D96E7C1DD0D4940FD14C78157A33040295FD042020E4940505260014C9D3040AC5626FC520F4940AB5FE97C78963040823CBB7CEB114940FF93BF7B4791304029232E008D144940D5B2B5BE48903040D1031F83151549402AE109BDFE903040D4F19881CA164940552E54FEB5903040FDD8243FE2194940FF08C380258F304053793BC2691B49402CD505BCCC8C30402CD505BCCC1C49407F15E0BBCD8B3040D4B5F63E551D4940FB95CE8767753040A777F17EDC2649402AE109BDFE703040A8E0F0828828494084F1D3B8375F3040A7AD11C1382E4940A8E33103954D3040FC17080264304940D82B2CB81F443040FDD8243FE23149408200193A763830407D5A457F68344940A7E9B303AE3730407F87A2409F34494022895E46B134304079AEEFC34136494052431B800D343040A777F17EDC364940A77A32FFE8333040556D37C137374940FE0B040132343040D200DE020938494024809BC58B353040FCE1E7BF073949407F129F3BC1363040A4C2D842903949407F8461C0924F3040A8E0F08288404940800F5EBBB4513040D1CABDC0AC4049405628D2FD9C5630402638F581E43F494057B3CEF8BE58304051853FC39B3F4940FF058200195A3040FB20CB82893F4940D2393FC5715C3040FB20CB82893F4940FD1186014B5E3040D0D38041D23F4940286552431B6830407E1EA33CF34249402DCF83BBB37230405473B9C1504949400282397AFC723040508BC1C3B4494940A7E67283A1723040D4B837BF614A4940A6EF3504C77130407E1EA33CF34A4940A9DA6E826F6E304082397AFCDE4C49407D96E7C1DD6D3040D388997D1E4D49407E8D2441B85E30402A1DACFF73524940FB20CB82895730407F87A2409F5449405531957EC2553040AA9ECC3FFA544940FD14C7815753304029ED0DBE305549402CD505BCCC3C3040AB9509BFD4554940514CDE0033233040FCDEA63FFB534940D731AEB8381E3040B62BF4C132544940AC53E57B4612304055F833BC5951494079AEEFC34106304000CADFBDA35049402D5A80B6D5E42F40514F1F813F584940B05417F032932F40266E15C4405F4940F71F990E9D362F407C992842EA6249407A1D71C806FA2E40520DFB3DB16449403546EBA86AC22E407E9065C1C4634940AF5A99F04BBD2E402A1DACFF736A49405AA148F773BA2E40282CF180B26B494083F755B950B92E402BDEC83CF26B4940CBDB114E0BB62E4056F5F23B4D6C4940FC17080264A82E402A1A6B7F676D4940F437A110019F2E407D96E7C1DD6D4940257A19C5729B2E405628D2FD9C6E494051C1E10511912E40A9A10DC006724940247D5A457F902E405055A18158724940753BFBCA838C2E407F87A2409F744940A96BED7DAA8A2E40D3FA5B02F0754940D5AF743E3C8B2E40D009A1832E774940F722DA8EA98B2E4051853FC39B77494056B60F79CB8D2E407EC9C6832D784940F71F990E9D962E40AB5CA8FC6B794940A185048C2E972E40D1066003227A494055BFD2F9F08C2E402CD505BCCC7C49402383DC45987A2E40813FFCFCF77E49402383DC45985A2E40FDD8243FE28149405A9E077767052E40D47FD6FCF87D4940DAAD65321C072E402A1A6B7F677D4940DF89592F860A2E40D57954FCDF7B4940DF89592F860A2E40A9DDAF027C7B4940A774B0FECF092E407E8AE3C0AB7949404CDF6B088E032E407E5704FF5B6F4940CEC64ACCB3022E405340DAFF006F49407E18213CDA002E402BDB87BCE56E49402D6002B7EEEE2D40D47FD6FCF86D4940286552431BA82D40D576137CD36E49402577D84466A62D407EC9C6832D704940040473F4F8A52D40D3F71A82E3704940D0D38041D2A72D40D3C1FA3F87714940D5AF743E3CCB2D405534D6FECE7A494006F52D73BADC2D40A7B393C151804940A376BF0AF0ED2D407C60C77F81864940A46DFC89CAEE2D40A777F17EDC864940C9E4D4CE30F52D40A9A10DC0068A4940276893C327FD2D40D009A1832E8F4940247D5A457F102E405628D2FD9C9E4940A77A32FFE8132E40D0D03FC1C5A2494007EFAB72A1122E4029232E008DA449404ED367075C0F2E40D1CDFE40B9A549407A1A3048FA042E407D21E4BCFFA74940D1CDFE40B9FD2D4052465C001AA94940A3737E8AE3F82D40FF05820019AA4940CBDB114E0BF62D402B14E97E4EAB49403145B9347EF12D40527FBDC282AD49403145B9347EF12D40D3FA5B02F0AD49406344A2D0B2F62D407AA52C431CAF494008E6E8F17BF32D40FE9C82FC6CB84940C7F0D8CF62E92D40D3F4D901D7BB494008E9297288E82D40A8A78FC01FBC494051BB5F05F8E62D4027F6D03E56BC49408109DCBA9BD72D40FFCC203EB0BD4940CDCCCCCCCCAC2D40D0D38041D2BF4940267156444D7C2D40514CDE0033C34940A3737E8AE3782D4000C79E3D97C349402B69C537146E2D40942F682101C74940AC53E57B46822D407D5A457F68CC4940020D36751E852D40A6B6D4415ECD49407B116DC7D4852D4079AEEFC341CE49402F51BD35B0852D405340DAFF00CF4940A4703D0AD7832D407D5A457F68D44940772CB64945832D40FC1A498270D54940CEC64ACCB3822D405531957EC2D54940F4311F10E8742D40D200DE0209D849404DDC2A88816E2D407E18213CDAD849405A9E077767652D40FDD8243FE2D949405B9885764E5B2D4053793BC269DB49409E978A8D79552D40520DFB3DB1DC4940D2C77C40A0532D407E5182FE42DD4940A968ACFD9D352D40FB20CB8289E74940DCA16131EA322D40F92F1004C8E84940D0D03FC1C5322D40D6A9F23D23E9494008E6E8F17B332D40A6B915C26AEA4940F4311F10E8342D40562B137EA9EB4940F6285C8FC2352D4081423D7D04EC4940257A19C5723B2D40505260014CED4940D0D38041D2472D405376FA415DEE4940D4B837BF614A2D407E8D2441B8EE49407F15E0BBCD4B2D40813FFCFCF7EE4940F52EDE8FDB5F2D405182FE428FF2494081069B3A8F622D40286211C30EF34940573ECBF3E06E2D400B9C6C0377F84940D89AADBCE46F2D40395FECBDF8F8494004E275FD82852D40D89DEE3CF1084A40AD50A4FB396D2D405628D2FD9C1E4A407F15E0BBCD6B2D40556D37C1371F4A40FC17080264682D407C9C69C2F61F4A40FE277FF78E622D40AA656B7D91204A402E573F36C94F2D405473B9C150214A40B24B546F0D342D40FD4AE7C3B3224A40D9B3E73235312D40FBE769C020234A40A774B0FECF292D407F87A2409F244A40DBA4A2B1F6272D4029ED0DBE30254A40FA264D83A2112D408081204086324A40FA264D83A2112D407C992842EA324A40286211C30E132D40D7A6B1BD16344A40AB5FE97C78162D405376FA415D364A408109DCBA9B172D402829B000A6364A40A3737E8AE3182D402BDB87BCE5364A40FD1186014B1E2D407E5704FF5B374A40763579CA6A222D40FB20CB8289374A40C9E7154F3D2A2D40D38558FD11384A4055BFD2F9F02C2D40A8E0F08288384A40FF08C380253F2D40D1031F83153D4A407B116DC7D4452D40D4F19881CA3E4A40D8B628B341462D40520ABABDA43F4A40FC17080264482D40295C8FC2F5484A40D0D38041D2472D40D00F238447494A4005FBAF73D3462D40A4C2D84290494A40C3B81B446B352D4021205F42054D4A40800C1D3BA82C2D40FF9600FC534E4A40DF8C9AAF921F2D40AA9B8BBFED4F4A40772FF7C951182D4000CADFBDA3504A40782975C9380E2D40AB5CA8FC6B514A40C7F0D8CF62092D40FA264D83A2514A40A379008BFC022D40FF05820019524A407F129F3BC1F62C402B14E97E4E534A4008E6E8F17BF32C40F92CCF83BB534A4024809BC58BE52C40A9DA6E826F564A4084F4143944C42C40530438BD8B5D4A40A3737E8AE3B82C407E5704FF5B5F4A4007EFAB72A1B22C407F4E417E36604A4056B60F79CB6D2C40A8E0F08288684A4059A7CAF78C642C40FCE1E7BF07694A40AB59677C5F4C2C40A9DA6E826F6E4A40DF89592F864A2C40FF058200197A4A40F52B9D0FCF4A2C405182FE428F7A4A40753BFBCA834C2C40D5AF743E3C7B4A40AB5FE97C78562C40FB230C03967C4A403048FAB48A662C402AE44A3D0B7E4A40FA264D83A2712C4055FB743C667E4A40C9E4D4CE30752C40508E0244C17E4A40FD14C78157932C407BA2EBC20F824A407217618A72992C406F0F4240BE824A4084F1D3B837AF2C405531957EC2854A40D3BEB9BF7AB42C40508E0244C1864A40753E3C4B90C12C40505260014C8D4A40A4703D0AD7C32C402BDB87BCE58E4A40E867EA758BC82C402A1DACFF73924A40FD14C78157D32C40813FFCFCF7A64A40AD6C1FF296D32C40AAD72D0263AB4A40D2C43BC0939E2C407AA52C431CC74A4008CA6DFB1E8D2C406EDFA3FE7AD94A40257A19C572BB2C40D3C1FA3F87D94A404DDC2A8881CE2C40A5BC564277D74A40DD989EB0C4D32C402BDB87BCE5D64A40772FF7C951D82C405628D2FD9CD64A40CDCCCCCCCC0C2D4029232E008DD44A4051BEA085041C2D40A777F17EDCD64A40276893C3273D2D402CD8463CD9E14A40295FD042023E2D40FFCF61BEBCE24A405AA148F7733A2D405401F73C7FE84A40AA622AFD842B2D40A8A78FC01FEC4A40266E15C440272D40FED5E3BED5EC4A40DC9E20B1DD1D2D40D1CDFE40B9ED4A40A3737E8AE3182D407D96E7C1DDED4A408200193A76F82C40D2C43BC093EE4A4023861DC6A4EF2C40508E0244C1EE4A40286211C30ED32C40FDDB65BFEEEE4A40C8ED974F56D42C40FA298E03AFEE4A40C9E4D4CE30D52C40295FD04202EE4A4008E6E8F17BD32C4056F5F23B4DEC4A402F4E7CB5A3D02C40D3F4D901D7EB4A402D6002B7EEAE2C405340DAFF00E74A40800C1D3BA8AC2C402541B8020AE74A40D3BEB9BF7A942C405473B9C150E94A40B05758703F882C4029E78BBD17EB4A40030AF5F411702C40234DBC033CEF4A404DDC2A88816E2C40514CDE0033F34A4008E6E8F17B732C40A777F17EDCF64A407B14AE47E17A2C4079AEEFC341F64A407A1A3048FA842C407D96E7C1DDF54A40D0D38041D2A72C402CD505BCCCF44A40FD14C78157B32C4029232E008DF44A40AF5A99F04BBD2C4051888043A8F44A407923F3C81FC42C4082397AFCDEF44A40D4B5F63E55D52C40FE47A643A7F54A40FD1186014BDE2C407C60C77F81F64A407638BA4A77F72C40FE0E45813EF94A40A777F17EDCFE2C40D4B837BF61FA4A4024809BC58B052D407F4B00FE29FB4A4008E3A7716F1E2D407B9FAA4203FD4A4007EC6AF2947D2D40562B137EA9034B40CBD8D0CDFEA02D407B9FAA4203054B40A968ACFD9DF52D40D6A9F23D23094B40A8716F7EC3742E40AA656B7D91104B40CCD24ECDE5962E40FD4AE7C3B3124B40FF08C380259F2E40FBE769C020134B40C9E4D4CE30B52E4081423D7D04144B408FA7E507AECA2E4004E5B67D8F144B4004FEF0F3DFDB2E40A8716F7EC3144B4083F755B950F92E4029ED0DBE30154B400000000000002F40FC1A498270154B40CDCCCCCCCC4C2F40552E54FEB5184B4051C1E10511512F40D47C957CEC184B40276893C3277D2F407F4B00FE291B4B404FCDE50643852F40562B137EA91B4B40F71F990E9D962F40253B3602F11C4B40A96BED7DAAAA2F407E8D2441B81E4B40F92F1004C8B02F40A9A44E40131F4B40F6251B0FB6C02F40FB20CB82891F4B4000917EFB3A0C304001C11C3D7E214B40CEE2C5C210213040F3AE7AC03C244B408A90BA9D7D213040FAB7CB7EDD234B40E751F17F471C3040BA4C4D8237224B405055A18158123040295C8FC2F5204B400282397AFC123040552E54FEB5204B402577D84466163040D5B2B5BE48204B408109DCBA9B173040514F1F813F204B4084F41439442430402B172AFF5A204B40FD9FC37C79253040FC17080264204B40A7ECF483BA2C3040A8AAD0402C214B402DD2C43BC0373040D482177D05234B4009A52F849C373040FE261422E0244B40ACFF73982F3730405A7F4B00FE254B4000C79E3D97353040AB5FE97C78264B40D0D6C1C1DE2C3040766C04E275254B40F644D7851F2430402E20B41EBE244B40BCCADAA6782C304082E49D4319264B406403E962D3323040DE3CD52137274B40529B38B9DF413040C7BB2363B52B4B401DAED51EF63A3040C040102043294B40B1E07EC0033B30403317B83CD6284B40BD6E1118EB3B3040DC2DC901BB284B4090F63FC05A3D3040C6BE64E3C1284B40DA5548F949413040338CBB41B4284B40D542C9E4D442304070EB6E9EEA284B4091F0BDBF414330408FE4F21FD2294B40ED48F59D5F443040F4A8F8BF232A4B40CD5A0A48FB5330407AA86DC3282C4B4029ED0DBE30553040A7ECF483BA2C4B40FB95CE8767553040276893C3272D4B407F87A2409F54304000C45DBD8A2E4B40A9DDAF027C533040D0D38041D22F4B4056B950F9D7523040D38558FD11304B40D446753A905130407EC9C6832D304B40A9DA6E826F4E3040D0D38041D22F4B40A7ECF483BA4C3040A5BC5642772F4B40AA622AFD844B3040FF08C380252F4B40D13C80457E5130407BA2EBC20F324B40F981AB3C81683040A9A44E40133B4B407E1B62BCE67530407C9C69C2F63F4B408F71C5C5517D30407A39ECBE63424B40CD5A0A48FB833040AB59677C5F444B4050C763062A8B3040D1CDFE40B9454B405055A1815892304000C45DBD8A464B40A9DDAF027CA3304029EACC3D24484B404ED026874FAA3040AA656B7D91484B40A6EF3504C7B13040F92F1004C8484B40A968ACFD9DB530407D93A641D1484B4029E78BBD17CB3040508BC1C3B4494B405055A18158E23040A9DDAF027C4B4B404ED026874FEA3040A5BF97C2834C4B40D731AEB838EE3040D1031F83154D4B40D0D03FC1C5F230407E1B62BCE64D4B4082FDD7B969033140A6B915C26A524B402577D84466063140FD14C78157534B40514F1F813F083140FE0B040132544B40FA980F08740A3140543A58FFE7544B40D4BB783F6E0F3140D47FD6FCF8554B40AC53E57B46123140A9DA6E826F564B4028F38FBE493F3140D4B5F63E555D4B40FF93BF7B47413140A968ACFD9D5D4B40A7ECF483BA5C3140A86E2EFEB65F4B40FF08C380256F31402B172AFF5A604B40D0D38041D2873140A4C2D84290614B40A968ACFD9D953140D4B837BF61624B40533D997FF4993140FFCF61BEBC624B406534F279C5AF31405340DAFF00654B4079AEEFC341C63140556D37C137674B40A968ACFD9DE531407D5D86FF74694B40D5AF743E3CEB3140A774B0FECF694B40ABEAE5779A083240FD4AE7C3B36A4B40A8E33103950D32405534D6FECE6A4B404DD6A88768543240FBE769C0206B4B405531957EC255324029E78BBD176B4B4058AA0B7899593240FD4AE7C3B36A4B40D4BB783F6E5F3240527C7C4276684B407903CC7C07733240EFA83121E6644B401D740987DE8632400457790261614B401CB1169F02943240F2608BDD3E5F4B406BD619DF179B3240B6DAC35E285E4B40FE0B040132B43240FA264D83A2594B40FC1A498270BD3240A86E2EFEB6574B40FF9600FC53C63240505260014C554B404DD6A88768D4324000CADFBDA3504B407A1A3048FAD432402B172AFF5A504B40CF488446B0D53240FD4D2844C04F4B4050C422861DD632407AA52C431C4F4B4050C422861DD63240FF9600FC534E4B407F87A2409FD43240A8716F7EC34C4B4057B08D78B2D3324052431B800D4C4B40D0D03FC1C5D23240D57954FCDF4B4B40AB5CA8FC6BD13240A77A32FFE84B4B40F92F1004C8D032407AA86DC3284C4B40FE0E45813EC93240D009A1832E4F4B405628D2FD9CC63240A8E0F08288504B4022895E46B1C432407E8AE3C0AB514B40A7E67283A1C23240FBE769C020534B404FCAA48636C03240FED5E3BED5544B40276893C327BD32408048BF7D1D564B40CC5D4BC807B93240FB20CB8289574B404FCDE50643B53240D1CABDC0AC584B4027F6D03E56B43240D3F71A82E3584B40172D40DB6A9232408599B67F655D4B40B114C95702813240FBCC599F72604B40EC3026FDBD7C324064EB19C231614B40DA3C0E83F97B324014CFD90242614B40C8073D9B557B324064EB19C231614B40BF0D315EF37A3240D93F4F0306614B403D1059A489773240B952CF82505E4B402DD2C43BC06732407AA52C431C5F4B407C9C69C2F6673240295FD042025E4B40FC17080264683240D1CDFE40B95D4B4056BC9179E47732407DCC07043A554B407C992842EA823240F92F1004C8504B4050C763062A8B32402BDEC83CF24B4B4052B5DD04DF8C32405534D6FECE4A4B40D1CDFE40B98D3240276BD443344A4B40A5F8F884EC903240D576137CD3464B407AABAE433591324052499D8026464B4081069B3A8F923240A7AD11C1383E4B40008BFCFA21923240A6B6D4415E3D4B40257497C4599132407F87A2409F3C4B40AB5CA8FC6B913240D3F4D901D73B4B40D53DB2B96A923240D673D2FBC6394B40D2C77C40A0933240A8E0F08288384B4029ED0DBE30953240A86E2EFEB6374B40008E3D7B2E9732405340DAFF00374B4057B3CEF8BE98324000C45DBD8A364B40AB59677C5F9C32405531957EC2354B40D4B5F63E55B532402AE109BDFE304B4055C2137AFDC13240A5BC5642772F4B4050C422861DD632407DCC07043A2D4B40CE548847E2D93240FED5E3BED52C4B4081069B3A8FE2324056F5F23B4D2C4B407F129F3BC1E632407AA86DC3282C4B40F92CCF83BBEB3240D00CE2033B2C4B40D828EB3713EF324001BEDBBC712C4B40FE0B040132F432407B9FAA42032D4B40D0D38041D2F73240D00CE2033B2C4B4052465C001AF93240A8A78FC01F2C4B407B116DC7D40533407F15E0BBCD2B4B40A5F5B704E00B33407F15E0BBCD2B4B40ABE7A4F78D233340AB59677C5F2C4B402577D84466363340505260014C2D4B405437177FDB5F3340D0D38041D22F4B407B14AE47E16A3340552E54FEB5304B40AA656B7D9170334027F911BF62314B40FC1D8A027D8233407E9065C1C4334B4050C422861D86334001BEDBBC71344B40A301BC05129033402BDB87BCE5364B407B9FAA42039D3340276BD443343A4B408527F4FA93A033408693347F4C3B4B40FA298E03AFA633405055A181583A4B40952C27A1F4A133407F69519FE4384B40F92F1004C8A03340A8E0F08288384B4079AEEFC341863340D0D03FC1C5324B402DCC423BA76D3340508E0244C12E4B40A019C40776683340D3FA5B02F02D4B40D0D03FC1C56233407E5182FE422D4B4056B60F79CB5D3340AA9ECC3FFA2C4B404DD9E90775493340D3BEB9BF7A2C4B4022895E46B1443340A8A78FC01F2C4B4051BEA085043C3340FBE769C0202B4B40A51133FB3C3A3340FC1D8A027D2A4B40F73E5585063A33407C2766BD182A4B4029EACC3D24403340A54DD53DB2234B40D446753A90413340AA622AFD84234B405340DAFF005F334051DA1B7C61224B4057B3CEF8BE783340D0D38041D2274B40297B4B395F7C33407B6649809A284B407F8461C0928F334027F6D03E562C4B407AABAE4335913340D3BEB9BF7A2C4B40514CDE0033933340D3BEB9BF7A2C4B40A8716F7EC394334027F6D03E562C4B4023861DC6A49F3340CEA96400A82C4B402975C93846A23340D1031F83152D4B40FA298E03AFB6334080457EFD10314B40DEAE97A608CC3340B22E6EA301384B40FCA5457D92DB3340C7A0134207374B4051C1E105110134407B698A00A7354B40008E3D7B2E173440250516C094354B40ABEAE5779A283440240ED940BA344B40276893C3274D34407C992842EA324B40C8B3CBB73E543440F48AA71E69324B401C06F357C8543440F9F6AE415F324B407C2AA73D255F3440FA264D83A2314B40218FE046CA6E34407E18213CDA304B40A489778027BD344028B7ED7BD42D4B407E1B62BCE6E53440250516C0942D4B4078B471C45A203540F92CCF83BB2B4B404FE61F7D932E3540A583F57F0E2B4B407BBB2539603B35405307793D982A4B40ABEAE5779A48354028F04E3E3D2A4B40A680B4FF015E3540FDD8243FE2294B404DD9E90775693540508BC1C3B4294B407CB5A338477135407E8AE3C0AB294B40D6AC33BE2F8635402CD8463CD9294B40677E3507089235405EA0A4C0022A4B400EF3E505D89335404374081C092A4B4029EACC3D24A03540276BD443342A4B40F8359204E1BA35405055A181582A4B4048A7AE7C96BB3540C6850321592A4B40A4FE7A8505DB35402A1DACFF732A4B407BBB253960FB35405307793D982A4B4028F04E3E3D2A364028BA2EFCE02A4B40CD5A0A48FB43364024D236FE442B4B40F8359204E14A3640A29BFD81722B4B401409A69A594B3640F7AE415F7A2B4B4052499D80264E3640A3C85A43A92B4B4055BFD2F9F06C36404D2EC6C03A2C4B404968CBB9146F36404D2EC6C03A2C4B40FCA886FD9E7436404D2EC6C03A2C4B40FF93BF7B47A13640CEA96400A82C4B40F73E558506AA3640253B3602F12C4B4052B81E85EBC136407D96E7C1DD2D4B40D449B6BA9CC63640A7AD11C1382E4B40BE6A65C22FC9364062855B3E922E4B40FCA5457D92CF3640FC1D8A027D324B40D5B2B5BE48D0364028BA2EFCE0324B40D2C77C40A0D336404FE960FD9F334B407C9C69C2F6D736402444F98216344B40CDE847C329DB3640A3923A014D344B40218FE046CADE36404D2EC6C03A344B40A9F6E978CCFC3640A774B0FECF314B40CF6A813D26FE3640FA264D83A2314B400000000000003740FCE1E7BF07314B40E7E26F7B820037404701A260C6304B40F92F1004C80037404D672783A3304B40ABED26F8A61D3740CFDC43C2F7264B4027F6D03E56343740A8716F7EC3244B404FCDE50643553740520ABABDA41F4B40FCABC77DAB593740D2C43BC0931E4B40800C1D3BA85C37404D6A6803B01D4B404B732B84D5743740AB5FE97C78164B40A1A17F828B753740CDE506431D164B40CEDF8442047C3740508BC1C3B4114B40CAFD0E45817E3740D061BEBC000F4B404DD6A887688437402AE44A3D0B064B4059A7CAF78C843740D57954FCDF034B407BA2EBC20F8237407E1EA33CF3FA4A4037E0F3C308813740BFEFDFBC38F94A40552E54FEB58037404D672783A3F84A402AE109BDFE803740501C40BFEFF54A400CAEB9A3FF81374019E76F4221F44A402B6C06B8208337407C2766BD18F24A40A3073E062B8A3740D2C77C40A0EB4A40FCA886FD9E943740250516C094DD4A40F226BF45279737400F2A711DE3D84A40008E3D7B2E9737404EECA17DACD84A40D63730B951983740508E0244C1D64A407F15E0BBCD9B374029266F8099D14A40A4897780279D37407A6F0C01C0CF4A40A777F17EDC9E3740FC1A498270CD4A40A77A32FFE8A33740FCA5457D92C74A40FE99417C60AB37407EC9C6832DC04A40240ED940BAAC3740A777F17EDCBE4A40F54A598638AE3740250516C094BD4A407A36AB3E57B33740253E7782FDB94A40D55E44DB31C937407C7E18213CA84A407F15E0BBCDDB3740CEE2C5C210994A40A777F17EDCEE3740A774B0FECF814A40CD57C9C7EEEE3740D00F238447814A40384D9F1D70ED3740D927806264794A4026FC523F6FEE37407E1B62BCE66D4A40381092054CF03740CDE847C329634A4027874F3A91F037405307793D98624A40221ADD41ECF037407C9C69C2F65F4A407E18213CDAF037404EEFE2FDB85D4A40A301BC0512F037402444F982165C4A40F641960513EF3740CDE847C3295B4A40D1CDFE40B9ED374051DA1B7C615A4A4051DA1B7C61EA37407903CC7C07594A40A019C40776E83740FE9C82FC6C584A402975C93846E2374051137D3ECA564A402AE109BDFEC03740D576137CD34E4A40F54A598638BE374000C45DBD8A4E4A40F25CDF8783BC37407C60C77F814E4A40E9263108ACB837401590F63FC04E4A40F8325184D4B53740FDDB65BFEE4E4A40CCEB884336B03740D061BEBC004F4A40AAF3A8F8BFA737408048BF7D1D4E4A40A48CB80034A23740527FBDC2824D4A4021956247E398374027F6D03E564C4A407E1B62BCE6853740AB5CA8FC6B494A40A5F8F884EC80374000CADFBDA3484A40D255BABBCE6A3740234DBC033C434A404D6A6803B06537402CD8463CD9414A404D672783A3603740FED2A23EC93F4A404568041BD73F374039B35DA10F304A40CAFD0E45813E37404F58E201652F4A4027C286A7572A37400D39B69E21244A40A702EE79FE3037402AE44A3D0B1E4A40FD304278B43137407B698A00A71D4A404B732B84D53437404B732B84D51C4A40CF6740BD19393740F9F6AE415F1C4A4000917EFB3A4C374029E78BBD171B4A40266E15C44057374025085740A11A4A4077BAF3C4735A3740A6B915C26A1A4A40F92CCF83BB5B3740A48CB800341A4A40D63730B951983740FF9600FC530E4A4026FF93BF7BA33740D28BDAFD2A0A4A40F54718062CA93740F92F1004C8004A40D34F38BBB5A037407C2766BD18FA4940CCEB884336A03740FA264D83A2F94940D2FD9C82FC9C3740B9E00CFE7EF549402EC901BB9A9C3740073F7100FDF44940A777F17EDC8E3740A7B393C151E0494000917EFB3A8C3740D158FB3BDBD749404DDC2A88818E374028B7ED7BD4D54940D2C43BC0938E3740505260014CD54940FD1186014B8E3740D15B3CBCE7D44940FC1A4982708D3740A64412BD8CD44940239F573CF588374021EA3E00A9D34940D925AAB7068A374022179CC1DFCB4940A20A7F86378F37407E1B62BCE6C54940A86E2EFEB68F3740FC1A498270C5494078B471C45A9037407D24253D0CC549405055A18158923740A5BF97C283C44940286552431B94374066BE839F38C44940543A58FFE79437402444F98216C449401615713AC99A3740A1A17F828BC349404F5B2382719C3740FE9C82FC6CC0494077BE9F1A2F9D3740DD24068195BF49407D96E7C1DD9D3740D009A1832EBF494023861DC6A49F37404E61A5828ABE4940910BCEE0EF9F374066A032FE7DBE4940A5F8F884ECA03740FF9600FC53BE494033198EE733A43740FF9600FC53BE494050E09D7C7AA43740FF9600FC53BE4940D540F33977A737402AE44A3D0BBE4940E52A16BF29A837401536035C90BD4940ABEAE5779AA83740CCEEC9C342BD4940287E8CB96BB13740CCB22781CDB349407CB5A33847B13740514CDE0033B3494076C6F7C5A5AE3740A741D13C80AF494052499D8026AE37402541B8020AAF4940F641960513AF3740253B3602F1A449407BBB253960BB374026FF93BF7B9B4940800F5EBBB4C1374050E3DEFC8699494023861DC6A4CF3740A968ACFD9D954940FB20CB8289E73740D3F71A82E3884940D0D38041D2E73740A8E0F08288884940EDD3F19881EE374046EF54C03D7F4940FD3383F8C0F6374079758E01D97949404F58E20165F73740FA7E6ABC74794940F9C08EFF02FD3740D009A1832E7749404F58E20165073840D09A1F7F6973494052465C001A0938405534D6FECE724940D5AF743E3C0B3840FAF02C41467249405340DAFF000F3840FCABC77DAB714940BB6246787B1038407842AF3F89714940AB5FE97C78163840787E5182FE704940AAF3A8F8BF173840F92F1004C87049404DD6A88768243840A7AD11C1386E49407D24253D0C25384028B7ED7BD46D4940F73B1405FA243840240ED940BA6C4940D53DB2B96A223840FBE769C0206B4940287E8CB96B21384028BA2EFCE06A4940D63A71395E1D3840A6B915C26A6A494057B08D78B2133840D28BDAFD2A6A4940FC1A4982700D3840A6B915C26A6A49407BA2EBC20F063840342F87DD776A494075392520260538408EAED2DD756A49402A7288B839FD3740D4B837BF616A49404A7F2F8507F93740253E7782FD694940A8FC6B79E5F63740D3C1FA3F87694940FD9FC37C79F53740F92F1004C8684940F73B1405FAF43740A7B393C151684940D064FF3C0DF43740508E0244C1664940B9533A58FFF33740A88FC01F7E664940219221C7D6F33740D1CDFE40B9654940CBF78C4468F43740A8716F7EC36449407D24253D0CF53740AB59677C5F6449407E9065C1C4033840FBAE08FEB75E4940FC1D8A027D123840CEE2C5C210594940257A19C5721B384052465C001A514940B56D1805C11B38408048BF7D1D504940D44334BA831C3840AA656B7D91484940FF93BF7B47013840A73B4F3C67354940D158FB3BDBFF3740520DFB3DB1344940FAB7CB7EDDFD374025C9737D1F34494050E3DEFC86F93740CCB22781CD3349402098A3C7EFED3740A3C85A43A9334940088ECBB8A9E137402638F581E43349407D93A641D1D83740D064FF3C0D344940247D5A457FD03740787B1002F2334940CF4BC5C6BCCA3740F8FF71C284334940D13C80457EC13740FC1D8A027D324940F46C567DAEBA3740CB85CABF96314940ABEAE5779AB83740D1949D7E503149401B48179B56B63740B8CB7EDDE9304940A60EF27A30B53740A3CB9BC3B53049407B2DE8BD31B43740FE9C82FC6C3049409F1F46088FB237407A6F0C01C02F4940FA264D83A2B13740D576137CD32E4940062D246074B13740E38DCC237F2E49402AC8CF46AEAF37405CAFE941412B4940CBF44BC45BAF3740A96BED7DAA2A49402A90D959F4AE374087E123624A2A4940505260014CAD3740D3C1FA3F8729494029780AB952973740A73E90BC73224940FA264D83A2913740272F3201BF2049404ED026874F8A3740EA93DC61131F4940D061BEBC007F3740D1915CFE431C49407E18213CDA6037407F4B00FE291349400D51853FC357374065C405A051104940FB20CB8289573740514F1F813F104940A583F57F0E533740508E0244C10E4940D1CDFE40B94D3740543A58FFE70C49404E64E602973B374055FB743C660649407B30293E3E393740530438BD8B05494078B7B2446725374028B7ED7BD4FD4840297B4B395F1C374028F04E3E3DFA4840A7E9B303AEC7364055FB743C66D64840FE2AC0779BB73640A6B6D4415ECD484006D50627A2AF3640B2D7BB3FDEC948407B336ABE4AAE3640D00F238447C948407EA99F3715AD36405401F73C7FC84840A019C40776A83640FB230C0396C44840AAF3A8F8BFA736404E64E60297C34840F9BD4D7FF6A73640FDA204FD85C2484023111AC1C6B13640508BC1C3B4B948404C6DA983BCBA3640D09A1F7F69B34840DEAB5626FCBA36403080F0A144B34840F25CDF8783BC3640D4B837BF61B24840F9C08EFF02BD3640533D997FF4B14840CD7344BE4BBD36404E5E64027EB14840A7E67283A1C2364027327381CBA5484081069B3A8FC236402444F98216A448407AABAE4335C136407A6CCB80B3A24840F73E558506BA364022179CC1DF9B484050E09D7C7AB436407AA52C431C974840A016838769B33640A7AD11C138964840514CDE0033B33640D1CDFE40B9954840F44D9A0645B33640768A558330954840F644D7851FB43640D0D6C1C1DE9448408F6CAE9AE7B43640D0D6C1C1DE944840A1A17F828BB53640D0D6C1C1DE944840008E3D7B2EC7364024D236FE449348404ED026874FDA3640530438BD8B8D484052D4997B48E03640F8FF71C2848B4840D34F38BBB5E036407784D382178B484052D4997B48E03640A7E67283A18A484055BFD2F9F0DC3640FB20CB82898748404A97FE25A9DC3640ED9925016A864840D44334BA83DC364028B7ED7BD48548402A7288B839DD3640253B3602F18448407B336ABE4ADE3640A54DD53DB2834840FED5E3BED5E23640AB59677C5F804840A301BC0512E03640D5B2B5BE4880484026FC523F6FDE3640514F1F813F80484052D158FB3BDB3640FE9C82FC6C804840F73E558506DA36407B6649809A804840D0D6C1C1DEBC36402AE44A3D0B86484052465C001A993640A3C85A43A98B4840267156444D9836400F9C33A2B48B48407E1B62BCE69536405116BEBED68B48400282397AFC923640D2C77C40A08B4840A301BC051290364028BA2EFCE08A4840A777F17EDC8E3640D28BDAFD2A8A48407B14AE47E18A3640286211C30E8B48408200193A7688364054FEB5BC728B48405534D6FECE5A364029266F8099914840D0D38041D25736402CD8463CD99148407C992842EA523640D4EE5701BE91484058AA0B78993936407F15E0BBCD9348407AA86DC3280C36405307793D989A48407E8AE3C0AB093640D2FD9C82FC9A48402DD2C43BC0073640AA622AFD849B48405628D2FD9C06364056F5F23B4D9C4840FF9600FC53063640A8716F7EC39C4840D6AC33BE2F063640505260014C9D4840AB5FE97C78063640520ABABDA49F4840FD9FC37C790536405307793D98A24840CE5147C7D5043640AA622AFD84A348407B116DC7D4F5354053793BC269AB48407A1A3048FAF43540282CF180B2AB4840D13FC1C58AD635407AABAE4335B14840A9DA6E826F9E35405437177FDBB74840D5AF743E3C9B35402638F581E4B74840ABEAE5779A8835405340DAFF00B748404FCAA486368035402AE44A3D0BB64840A8E0F08288783540FED5E3BED5B44840266E15C44077354051888043A8B44840A968ACFD9D7535407F87A2409FB44840A5F8F884EC7035402CD505BCCCB44840A86E2EFEB66F3540AA9ECC3FFAB44840DFC325C79D663540E71BD13DEBB64840295C8FC2F5483540D4B837BF61BA4840D236FE44654735402A1DACFF73BA4840A9DDAF027C133540A7AD11C138B64840D6A9F23D23113540AB9509BFD4B54840AD50A4FB390D3540A8716F7EC3B44840800C1D3BA80C354027F6D03E56B4484052465C001A0935402AE44A3D0BAE48402BDEC83CF2FB3440FD4D2844C0A74840A4FE7A8505FB3440A5BC564277A7484022895E46B1F434405628D2FD9CA648402383DC4598EA34407E1B62BCE6A54840D82E6D382CE934407E1B62BCE6A548407D21E4BCFFCF34405055A18158AA48402DCC423BA7BD3440D673D2FBC6B148404ED026874F9A3440A7E67283A1B24840267156444D5C34407E54C37E4FB24840A77A32FFE853344080457EFD10B14840543A58FFE73434407C6308008EAB4840A8716F7EC3243440A7B393C151A84840FA980F08741A3440D0D38041D29F48407C9C69C2F6173440FD14C781579B4840D540F3397717344052465C001A9948402BDB87BCE5163440FB20CB82899748405531957EC21534407E8D2441B8964840CE5147C7D5143440A9DA6E826F964840286211C30E133440A9DA6E826F964840FE9C82FC6C103440508E0244C1964840D925AAB7060A34407EC9C6832D9848404FCDE50643053440D3C1FA3F879948403BC8EBC1A400344045F5D6C0569B484004763579CAFE3340AB59677C5F9C484051BEA08504FC334082397AFCDE9C4840D3C1FA3F87F93340D1031F83159D4840A86E2EFEB6EF3340A8E33103959D48402383DC4598EA3340505260014C9D48400473F4F8BDE93340D388997D1E9D4840FC17080264E83340520DFB3DB19C484011DF89592FDE33405F7F129F3B99484057B3CEF8BED83340AA656B7D91984840A6F27684D3D63340A8E0F08288984840FE99417C60CB3340D6A9F23D23994840FF05820019CA33407AABAE4335994840D236FE4465C73340D4EE5701BE994840FB95CE8767C53340A6B915C26A9A4840D82B2CB81FC43340A7B05241459B484052431B800DC43340D2C77C40A09B48402AE44A3D0BC63340AB9509BFD49D4840267156444DCC33402B172AFF5AA04840AC53E57B46D23340FD4AE7C3B3A248400282397AFCD233407C992842EAA24840A9DDAF027CD33340D5AF743E3CA3484057B08D78B2D3334000C79E3D97A34840D2C77C40A0D333402BDEC83CF2A348402B69C53714CE3340FA298E03AFAE4840A96BED7DAACA33407E9065C1C4B348404ED026874FCA334052431B800DB4484083F755B950C93340D00CE2033BB4484001857AFA08C8334056F5F23B4DB44840A8716F7EC3C43340D00CE2033BB448407E1B62BCE6B53340AB984A3FE1B24840ABEAE5779AA8334052431B800DB4484084F4143944943340FC1D8A027DBA4840514CDE0033933340D482177D05BB4840CC5D4BC80789334029232E008DC448405ED6C4025F85334001C11C3D7EC948400473F4F8BD7933402CD505BCCCCC4840A7E67283A1723340543A58FFE7CC48407F129F3BC1463340A77A32FFE8C3484029ED0DBE304533407C6308008EC348407E9065C1C443334029E78BBD17C34840D2C43BC0933E3340A8AAD0402CC1484082035ABA823D3340AA656B7D91C0484052431B800D343340D47C957CECB8484055C2137AFD313340FF08C38025B748402DCF83BBB3323340527FBDC282B54840D4BB783F6E2F3340D3BEB9BF7AB44840CE548847E2293340A7B0524145B34840D0D38041D2273340514CDE0033B34840286552431B083340D28BDAFD2AB24840FD1186014BFE3240FC1D8A027DB24840D4B837BF61FA3240D0D03FC1C5B2484052465C001AF93240A7B0524145B3484057B3CEF8BEF832407C6308008EB34840A8E0F08288F83240D57954FCDFB3484056BC9179E4F73240A6B915C26ABA48407C9C69C2F6F73240FE47A643A7BD4840CFD90242EBD93240A7AD11C138C24840'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('PO','PT','PRT','620','Portugal','9150','10528226','150','39','-8.058','40.309','0106000020E61000000800000001030000000100000025000000B0CE6A813D1A31C028F911BF6269404030C24D46950D31C048853FC39B67404020C8CF46AE0731C0104E2844C0674040600A48FB1F0431C09021E4BCFF67404030C58EC6A10231C0584F1F813F684040E00FB1C1C2F530C06055A181586A40403053CC41D0E930C050793BC2696B404030C8CF46AEE730C0009A417C606B4040008D0B0742E630C0F8E769C0206B4040806C59BE2EB730C0E8A9F23D2361404020BF0CC688B830C000BB9A3C655F40407072DBBE47D130C088992842EA524040C033BDC458D230C0081E8A027D52404020D192C7D3D630C0E0EE5701BE5140404025917D90F130C038266F8099514040007EC68503FD30C0E07954FCDF534040A052B3075A1131C02829B000A656404050A01683871931C0C05626FC5257404000FDBE7FF31A31C058853FC39B574040F0DE347D762831C0D8D03FC1C55A40405025917D903131C0E088997D1E5D404040AF5B04C63231C0F89FC37C795D4040B0389CF9D53431C058FB743C665E4040A0295778973B31C05882FE428F624040302FC03E3A3D31C0C8C77C40A0634040B023D5777E4131C048853FC39B6740408072DBBE474131C0804E417E36684040E079E2395B4031C0382F3201BF684040F0ED79FEB43131C028DB87BCE56E4040B02C98F8A33031C0C05626FC526F404000D0EFFB372F31C058853FC39B6F404090583508732B31C008BB9A3C656F404040A9D903AD2831C0608E0244C16E4040A0B9A3FFE52631C05831957EC26D40408069183E222231C0009A417C606B404070E81038122031C0081E8A027D6A4040B0CE6A813D1A31C028F911BF6269404001030000000100000010000000600D897B2C4930C050431B800D8C404020C03E3A754930C0D800DE020988404080F964C5704D30C000D3A23EC9874040700E2C47C85030C088C9C6832D884040601CCEFC6A5230C0D800DE020988404030B43A39435530C0E0BB783F6E87404080FFE6C5895730C02829B000A6864040B046AF06285D30C0F82CCF83BB834040B0D1AB014A5F30C0F82CCF83BB834040A02616F88A6630C0303B3602F1844040303883BF5F5C30C058FEB5BC728B404080F3E2C4575330C0B09509BFD48D4040C0963AC8EB5130C010E52840148E40406091D101495030C0801B62BCE68D4040600D897B2C4930C0283B3602F18C4040600D897B2C4930C050431B800D8C40400103000000010000001C00000080EA1F44320439C0B8A78FC01F7C4240A04A22FB200339C008301004C8784240C02AFA43330339C0D88558FD11784240E08EA9BBB20339C0805704FF5B774240B0389CF9D50439C000DC65BFEE76424020A5F5B7040C39C0580ABABDA47742408051103CBE1939C0285C8FC2F57842408063963D092839C0D0CABDC0AC78424070E49D43192A39C000CADFBDA3784240F0F3FBFECD2B39C08093A641D17842408066D7BD152D39C0B0AAD0402C794240805D143DF02D39C0508BC1C3B479424070F3E2C4573339C000A0C37C797D424070F3E2C4573339C0D0AC33BE2F7E4240B0402D060F3339C0883FFCFCF77E4240D033BDC4583239C0888461C0927F424030BABC395C2F39C048465C001A81424030C24D46952D39C0E00F23844781424070F964C5701D39C0B86BED7DAA824240B0436E861B1839C0901EA33CF382424020AB77B81D1639C0D882177D0583424070EA1F44321439C078992842EA824240B03E1EFAEE0E39C08054C37E4F824240B0AA5E7EA70D39C0603D997FF481424070022846960C39C010C11C3D7E81424020BF0CC6880839C058853FC39B7F4240B0389CF9D50439C0B8ECF483BA7C424080EA1F44320439C0B8A78FC01F7C424001030000000100000033000000E00FB1C1C29539C0B874B0FECFE94240F0EA387EA88C39C0F8264D83A2E94240E082A5BA806F39C07854C37E4FEA4240F0F0BA7EC16639C0504CDE0033EB4240D00C7041B66039C05870784144EC4240B0D1AB014A5F39C09087A2409FEC42406010CAFB385E39C0080341800CED424030508BC1C35439C08860C77F81EE4240B0AD9FFEB35239C0D0C43BC093EE42405025917D903139C03029B000A6EE424060198D7C5E2D39C08860C77F81EE424020B77BB94F2A39C0E0FA5B02F0ED424020C8CF46AE2739C088CC07043AED424030BDFDB9682439C0E87954FCDFEB424030C6C03A8E2339C01015C78157EB4240B049F086342239C0E00F238447E942409052B3075A2139C02838F581E4E74240F0ED79FEB42139C0B8A44E4013E74240D02137C30D2439C0503D997FF4E14240807EDFBF792539C0602E54FEB5E04240A0B0E07EC02739C06037177FDBDF4240304A09C1AA2A39C038F38FBE49DF42403047C8409E3539C0B8DA6E826FDE424000E8F7FD9B3739C068FB743C66DE4240A0B0E07EC05739C08087A2409FDC424020508BC1C37439C08854C37E4FDA42405091D101499039C0485260014CDD4240F0627D0393AF39C068FB743C66DE42405025917D90B139C08060C77F81DE424030AB77B81DB639C0A85626FC52DF424070E49D4319BA39C0089D82FC6CE04240304D4A41B7CF39C0B077F17EDCE642403041464085DB39C0D8FD9C82FCEA424060198D7C5EDD39C090397AFCDEEC4240B046AF0628DD39C00848A643A7ED4240304A09C1AADA39C0E8A9F23D23F1424030C8CF46AED739C0B0DDAF027CF34240B029577897CB39C05070784144F4424040B29C84D2C739C0D8BEB9BF7AF44240B0C266800BC639C060F5F23B4DF44240409A94826EBF39C00815C78157F34240006A317898BA39C06007793D98F24240A04A22FB20B339C0584F1F813FF0424040AF5B04C6B239C00821CB8289EF424060130B7C45B339C0D87FD6FCF8ED424030C58EC6A1B239C0B8B6D4415EED424030CE5147C7B139C000D6E3BED5EC424080F0A1444BAE39C0002DCF83BBEB42408002284696AC39C0886308008EEB424050A01683879939C0603D997FF4E94240E00FB1C1C29539C0B874B0FECFE9424001030000000100000032000000600A48FB1F243CC0700322C49539434040317903CC203CC078334E4354394340509A94826E1F3CC078334E43543943406004C6FA061A3CC058465C001A39434020DA5548F9153CC0D80F23844739434030C58EC6A1123CC010E2E7BF073943407072DBBE47113CC0D8CABDC0AC384340203883BF5F0C3CC0B8A44E401337434030C03E3A75093CC0A8E3310395354340600D897B2C093CC030D505BCCC3443400069FF03AC093CC0D8A6B1BD16344340F0D8B27C5D0E3CC0281DACFF733243407063963D09183CC0D88BDAFD2A3243407051103CBE193CC05055A18158324340100F289B72253CC0085DFB027A3343408008AA46AF263CC078A3737E8A3343408072DBBE47313CC0D8F4D901D733434070EA1F4432343CC0504CDE003333434070E7DEC3253F3CC058853FC39B2F4340600A48FB1F443CC078992842EA324340B0CB290131453CC0089A417C6033434030BF0CC688483CC08815E0BBCD334340D08EA9BBB2633CC0A8ECF483BA34434000EB387EA86C3CC0503A58FFE734434020B98AC56F6E3CC090397AFCDE344340F06FB378B1743CC0D8F4D901D73343408008AA46AF763CC0A87A32FFE8334340F065BE839F843CC0306552431B384340E00FB1C1C2853CC0B0E0F082883843408008AA46AF863CC088457EFD1039434030B77BB94F8A3CC088423D7D043C4340203883BF5F8C3CC0C8BB783F6E3F4340A0B321FFCC8C3CC038EACC3D24404340D0307C444C8D3CC0A8C2D8429041434000EB387EA88C3CC0A8DDAF027C43434080EE92382B8A3CC038232E008D444340E006EE409D863CC05031957EC2454340D079E2395B803CC0E076137CD346434050A35703947E3CC06040DAFF0047434050151A8865773CC008BB9A3C65474340F0FFFFFFFF6F3CC0B0BC564277474340B0BCE47FF26B3CC0C05626FC52474340008ACA8635613CC0081286014B464340204A09C1AA5A3CC0D8B5F63E55454340E085E63A8D543CC0000C04013244434000EE79FEB4513CC008C79E3D9743434080EA1F4432443CC0084E2844C03F43408072DBBE47313CC0C882177D053B4340304D4A41B72F3CC0E0D03FC1C53A4340600A48FB1F243CC0700322C49539434001030000000100000028000000008D0B0742163BC08893A641D150434030BCCB457C233BC0A8656B7D9150434020C37FBA812E3BC0C053E57B46524340B0B321FFCC3C3BC02835B401D8524340008D0B0742463BC0D8AF743E3C534340A0583508734B3BC0282CF180B253434040A35703944E3BC0E00CE2033B54434000D671FC50593BC0B0A44E4013574340006A3178985A3BC0C8BB783F6E574340B03DEC85025E3BC0382F3201BF5843407072DBBE47613BC0801EA33CF35A434080F3E2C457633BC0D0FA5B02F05D4340006F8104C5633BC02829B000A65E434030BCCB457C633BC0E0BB783F6E5F434000E5B67D8F623BC0608BC1C3B46143406091D10149603BC058FEB5BC7263434020BABC395C5F3BC008DFA63FFB634340A046AF06285D3BC008D6E3BED5644340D085E63A8D543BC0D87FD6FCF865434050880E8123513BC058FB743C66664340B0D1AB014A4F3BC0D8C43BC09366434070ED60C43E493BC0E0F19881CA66434030A2B437F8463BC0E0F19881CA664340B03E1EFAEE3E3BC06028D2FD9C664340D0A3703D0A373BC0109700FC5366434020C37FBA812E3BC06831957EC2654340707EDFBF79253BC0100341800C654340D08EA9BBB2233BC008D6E3BED5644340007EC685031D3BC038DEC83CF2634340F0F63C7FDA103BC0B874B0FECF61434000EB387EA80C3BC0A09B8BBFED5F43407051103CBE093BC0B0DA6E826F5E4340705AD3BCE3083BC0801B62BCE65D4340C02D3BC43F083BC0605260014C5D4340D0187442E8043BC038E109BDFE584340D07C23BA67053BC0607C7C427658434080F964C5700D3BC05007793D9852434000D9B27C5D0E3BC0000682001952434030BDFDB968143BC0305C8FC2F5504340008D0B0742163BC08893A641D15043400103000000010000001B000000806C59BE2E373FC090CC07043AAD4340D0307C444C3D3FC090CC07043AAD4340F089CA8635413FC0885182FE42AD4340E0976C3CD8423FC0507FBDC282AD4340006F8104C5433FC028E44A3D0BAE434020C8CF46AE473FC040D8463CD9B143408051103CBE493FC05870784144B44340A0CE6A813D4A3FC0383B3602F1B4434020BF0CC688483FC058465C001AB9434040AF5B04C6423FC02820ED7F80BF43407069183E22423FC0286552431BC04340A0BF2500FF403FC0B8656B7D91C04340B0C5A700183B3FC0A06BED7DAAC2434000F1BA7EC1363FC06834D6FECEC243400070B378B1343FC000D061BEBCC2434030C6C03A8E333FC0001E8A027DC24340B04C310741273FC0A85626FC52BF43400067F0F78B253FC0D8AC33BE2FBE4340800E2C47C8203FC008D061BEBCBA43400000000000203FC0D006600322BA4340E082A5BA801F3FC0905D86FF74B94340800569C6A2213FC0D888997D1EB54340F0F97DFFE6253FC02838F581E4AF4340601F0F7D77273FC0588E0244C1AE4340F07DC685032D3FC0A8B6D4415EAD4340F0CFEFFB372F3FC0D0B5F63E55AD4340806C59BE2E373FC090CC07043AAD434001030000000100000007020000407AFB73D16820C0909C69C2F6EF4440E056B3CEF86620C0B8E9B303AEEF444000D12170246020C05837177FDBEF444000B265F9BA5C20C0B8E9B303AEEF4440C03BDD79E25920C02820ED7F80EF4440406EF7729F5420C0A85FE97C78EE444060FCA5457D5220C05831957EC2ED4440C0963AC8EB5120C0D87954FCDFEB444040AF5B04C65220C0803CBB7CEBE9444040B6D782DE5320C048683D7C99E844406083BEF4F64720C0908461C092E74440E0DBF3FC694320C0908461C092E74440C09DEE3CF12C20C060853FC39BE7444000E5B67D8F2220C028172AFF5AE84440004FCC7A311C20C0A8B9A3FFE5E84440608940F50F1220C008D9243FE2E9444040726A6798BA1FC0909C69C2F6EF444000D0EFFB37AF1FC0302F3201BFF0444080EB51B81E851FC0386893C327ED444080F0A1444B7E1FC0C888997D1EED4440C0B8196EC0771FC0507FBDC282ED4440805EB7088C651FC02829B000A6EE4440807138F3AB091FC0A8984A3FE1F2444000C0CDE2C5D21EC0789065C1C4F3444080EB51B81EC51EC0D8F4D901D7F3444040560DC2DCBE1EC000C79E3D97F3444080B4C4CA68641EC0588E0244C1EE4440C0355B79C96F1EC0D80CE2033BEC444080CDC7B5A1721EC0B0984A3FE1EA444040C8409E5D6E1EC0D0B837BF61EA44404021AD31E8B41DC0000F45813EE9444080B4C4CA68A41DC028F911BF62E94440C0402D060F531DC078A86DC328EC4440C0BFCDE2C5121DC008C45DBD8AEE44408090BB0853D41CC0C0075A8121F144400011548D5ECD1CC048465C001AF14440009A94826EBF1CC0E0FD9C82FCF2444080C51858C7B11CC08048BF7D1DF64440806F0B96EAB21CC0E0F19881CAF64440C058350873BB1CC0D000DE0209F84440005EBC1FB7BF1CC000D6E3BED5FC444040B6F1272ABB1CC0B0B6D4415EFD444040C2F5285C8F1CC0286E15C440FF444080698995D1881CC0885704FF5BFF4440004487C091801CC080A52C431CFF4440C0F3FBFECD6B1CC0089700FC53FE444080630795B85E1CC008A0C37C79FD4440C0402D060F531CC0282CF180B2FB444040A69883A0531CC0386211C30EFB444040C2F5285C4F1CC05882FE428FFA4440004487C091401CC0E073D2FBC6F9444080C8772975391CC0D0EE5701BEF94440C05C8AABCA0E1CC0883CBB7CEBF94440003AB01C21031CC0381DACFF73FA444080C1C3B46FEE1BC090689082A7FC4440801D537765C71BC0583D997FF4F9444000B4C9E193BE1BC0D8C1FA3F87F94440400DFAD2DB9F1BC0E07C957CECF84440401F80D426DE1AC02838F581E4F74440807138F3ABC91AC02838F581E4F74440C0FFFFFFFFBF1AC02838F581E4F744400005508C2C791AC00818080264F84440803AAB05F6681AC0785D86FF74F94440007365506D601AC078A2EBC20FFA4440C0C51858C7311AC0285FD04202F6444040D349B6BA1C1AC060FEB5BC72EB4440001C261AA4301AC0883CBB7CEBE14440C08618AF79351AC068F833BC59D94440805D85949F341AC0587C7C4276D8444080F6234564281AC0883FFCFCF7D64440009544F641061AC050888043A8D44440000AD7A370FD19C070A86DC328D44440407365506DE019C0D8B5F63E55D54440C0643909A5CF19C05076FA415DD644408002284696BC19C0A8A44E4013D74440406F0B96EAB219C06040DAFF00D7444040CEF9298E6319C028E44A3D0BD6444000B16A10E63619C0583A58FFE7D44440C0D6A3703D0A19C08854C37E4FD24440003201BF460219C008274D83A2D14440407B0F971CC718C0B87A32FFE8CB4440C05DBC1FB7BF18C0386BD44334CA444080BDDC2747C118C0F0D05B3CBCC94440C0415F7AFBC318C0E07C957CECC84440806CE8667FD018C0E0AC33BE2FC6444000E8F7FD9BD718C0B09ECC3FFAC4444080630795B8DE18C0909065C1C4C34440C02DAC1BEF2E19C0D8D38041D2B7444040C8409E5D6E19C0682E54FEB5B04440004487C091C019C08893A641D1A8444080570394860A1AC0783CBB7CEBA14440401C5DA5BB3B1AC06040DAFF009F444080963AC8EB511AC0002A8E03AF9E44404078EC67B1641AC0286E15C4409F444000630CACE3781AC00021CB82899F4440000455A357931AC0B05626FC529F444040560DC2DCBE1AC0604CDE00339B4440003AB01C21C31AC0B0E67283A19A4440C0DBF3FC69031BC008C11C3D7E91444000C2BE9D44041BC060FB743C668E4440C085E63A8D041BC0E088997D1E8D4440C0402D060F131BC0503D997FF489444040272F32011F1BC038EACC3D2488444000630CACE3381BC0B89509BFD4854440C0A3703D0A571BC060431B800D8444408078EC67B1641BC0682B137EA983444000C6A4BF97B21BC000BE4D7FF6834440C00CFFE906BA1BC09054C37E4F82444000B9196EC0B71BC0808AE3C0AB814440800E2C47C8901BC0B8716F7EC37C444040022846967C1BC0D0D03FC1C57A4440006DE34F54761BC0B0B915C26A7A44400084B9DDCB6D1BC0E00F238447794440007592AD2E371BC03038F581E46F4440406F0B96EA321BC0B8E33103956D44404021AD31E8341BC058888043A86C4440807B0F971C471BC08096E7C1DD5D4440C0CFEFFB372F1BC0F0E769C020434440003AB01C21431BC0F8264D83A231444080402D060F531BC0886649809A28444040F8C08EFF721BC0608E0244C122444040560DC2DC7E1BC0508BC1C3B42144400083BEF4F6871BC06073B9C150214440801281EA1FA41BC08093A641D120444040419B1C3EC91BC0C028B34126214440C0D11C59F9051CC0500438BD8B1D444040BD6E11180B1CC0B0BF97C2831C444080CB9A58E01B1CC0D000DE02091844400011548D5E0D1CC030D8463CD911444000282A1BD6041CC030EACC3D24104440806F0B96EAF21BC0D8BB783F6E0F444040A0168387E91BC0A8A44E40130F444080A3703D0AD71BC0E076137CD30E4440C010548D5ECD1BC0F8DB65BFEE0E444080EB51B81EC51BC0B0DA6E826F0E44408046AF0628BD1BC05031957EC20D4440007592AD2EB71BC0889FAA42030D444080BF9657AE871BC00048A643A705444080583508737B1BC0E0D03FC1C5024440001C5DA5BB7B1BC04873B9C150014440008718AF79F51BC0A8716F7EC3DC43400016DBA4A2111CC068FB743C66D64340C0436D1B46311CC07048A30227D543404034B918033B1CC098D233BDC4D4434000583A1F9E951CC060F5F23B4DD44340008FC2F5289C1CC030F6D03E56D4434080E49D4319AA1CC0B8ECF483BAD4434080FCA5457DD21CC0201A6B7F67D54340C0570394860A1DC030E44A3D0BD64340C052B3075A111DC0385FD04202D6434080726A67983A1DC060431B800DD44340C010548D5E4D1DC0E082177D05D34340C0BFCDE2C5521DC08081204086D24340C077B5DC99591DC0A8B915C26AD24340007B14AE47A11DC0D0FD9C82FCD24340C0B94BE2ACA81DC028E78BBD17D3434040D39FFD48211EC048AD307DAFD54340C0295778971B1EC0803CBB7CEBD14340C0E7F7FD9B171EC088457EFD10D14340C0D11C59F9051EC0580438BD8BCD4340005EBC1FB7FF1DC0B8716F7EC3CC434080EB51B81E851DC02820ED7F80BF43408060E4654D7C1DC030DB87BCE5BE434080570394864A1DC0588BC1C3B4B1434040880E8123411DC0B8A78FC01FAC4340C0C0C8CB9AF81CC0B0B05241459B43408091EA3BBF981CC000DC65BFEE8E434080963AC8EB911CC0A8AD11C1388E4340002DB1321A891CC0801B62BCE68D4340400F27309D761CC0D8B5F63E558D434000FED2A23E691CC0381A6B7F678D4340003AB01C21431CC0002A8E03AF8E4340800CFFE9063A1CC078A52C431C8F43404077BAF3C4331CC03038F581E48F434040FED2A23E291CC0B86E2EFEB68F4340C0F97DFFE6151CC028DB87BCE58E434080EB51B81E051CC0E0CDFE40B98D434000C8409E5DEE1BC0202CF180B28B4340402C7FBE2DD81BC0306E15C44087434040CC9541B5D11BC0089A417C60834340006AC020E9D31BC05882FE428F824340000AD7A3703D1CC050499D80266E4340009CC1DF2F561CC0881EA33CF36A43404054E0641BA81CC0E0A6B1BD16644340C0A57EDE54D41CC040F88903E85F43408058350873FB1CC0D0FA5B02F05D4340C01D537765071DC080CC07043A5D4340C0570394860A1DC038232E008D5C4340C0067DE9ED0F1DC0A86BED7DAA5A43404016DBA4A2111DC0B0A10DC0065A434080698995D1481DC0D8C1FA3F87394340404487C091401DC0A8B393C1513843400017D68D77371DC008D3A23EC937434040B29C84D2271DC03829B000A6364340406BB6F2921F1DC038E44A3D0B36434000342E1C08191DC0C8B5F63E5535434000282A1BD6C41CC038E109BDFE2843400084B9DDCBAD1CC0805A457F68244340C0AD47E17A941CC03020ED7F801F434080EB51B81E851CC0483A58FFE71C4340C0B94BE2AC681CC0904E417E36184340001059A489671CC0808461C092174340803BDD79E2591CC0009700FC53164340C0402D060F531CC05076FA415D16434040758D96031D1CC08821E4BCFF1743408052B3075A111CC0B8E0F0828818434000C51D6FF20B1CC000E2E7BF0719434080570394860A1CC0888AE3C0AB1943400005508C2CF91BC06034D6FECE1A434040CEC29E76D81BC0D0C77C40A01B4340C057039486CA1BC030DEC83CF21B4340C039B01C21C31BC0E87954FCDF1B4340401553E927BC1BC0F0517FBDC21A434000EE79FEB4C11BC0D0F19881CA164340C015A4198BC61BC008D6E3BED514434080BA46CB81CE1BC0783CBB7CEB114340802A52616C011CC0B059677C5F04434080D9CBB6D3061CC010C79E3D9703434000B4C9E1937E1CC0E00F238447014340008A3BDEE4D71CC058853FC39BFF42408058350873FB1CC0E076137CD3FE4240C085E63A8D041DC060FB743C66FE4240807138F3AB091DC01048A643A7FD4240C0272A1BD6041DC0A8716F7EC3FC42400090BDDEFD011DC06834D6FECEFA42400090BDDEFD011DC02820ED7F80F74240007E37DDB2031DC0E876137CD3F6424080758D96031D1DC0A0BC564277EF4240004F594DD7231DC08048BF7D1DEE4240C0BF9657AE471DC038172AFF5AE8424040C2BE9D44841DC0F8E769C020E3424080EA1F4432941DC0903CBB7CEBE142404081919735B11DC0686D37C137DF4240807138F3ABC91DC0D8C1FA3F87D9424000342E1C08191EC0888D2441B8C64240405A80B6D50C1EC0B8AA5E7EA7C34240003AB01C21031EC0B0984A3FE1C242408079E2395BF01DC05037177FDBBF424040A5660FB4E21DC0B868ACFD9DBD424040CEC29E76D81DC08081204086BA424040137CD3F4C91DC0B0E3310395B542408046AF0628BD1DC0883FFCFCF7AE424040965AEF37BA1DC0805A457F68A0424080F6234564A81DC0D0D38041D2974240C0C51858C7B11DC060FB743C6696424000E6CAA0DAC01DC0E076137CD3964240C0B2976DA7CD1DC000DC65BFEE964240C00AD28C45E31DC0588E0244C1964240006DE34F54361EC0B07A32FFE8934240C07D37DDB2431EC03014E97E4E93424080C2F5285C4F1EC0A86BED7DAA9242404094128255551EC08854C37E4F9242408077BAF3C4731EC0607C7C4276904240C07492AD2E771EC0D8D38041D28F4240800778D2C2751EC01009C380258F4240005B5D4E09781EC08860C77F818E424080A46B26DF7C1EC008E52840148E424040C745B588081FC0D0BEB9BF7A8442404024D06053971FC0D8A9F23D23814240C0B4C4CA68E41FC090457EFD10814240E0010F0C200420C0E0B837BF61824240402DB1321A0920C0B0B052414583424080EA1F44321420C0D888997D1E854240C0B7054B751920C0901B62BCE685424040A5660FB42220C05840DAFF0087424060941282553520C0A0AAD0402C894240608FC2F5283C20C040D8463CD98942400049D74CBE5920C08015E0BBCD8B4240608FC2F528BC20C0505260014C8D424000E5B67D8FC220C000D6E3BED58C424020B4AB90F2CB20C0E07954FCDF8B42402047C8409ED520C00815C781578B4240609A94826EDF20C0881EA33CF38A424060A5660FB4E220C030E78BBD178B4240C02FD978B00521C038ED0DBE308D4240A052B3075A5121C0D8FA5B02F08D424040880E8123A121C0A8656B7D91884240C07F643A74DA21C080A2EBC20F824240205B5D4E09F821C05807793D9882424080E5CFB705FB21C0901EA33CF3824240A029577897FB21C000C79E3D97834240E076A1B94EFB21C028F6D03E56844240E09AADBCE4F721C0082A8E03AF86424000CEE0EF17EB21C0D0F4D901D78B424080D9CBB6D3E621C0303B3602F18C424080415F7AFBE321C0505260014C8D424020AE2990D9E121C030327381CB8D424080EE92382BDA21C0B8B393C15190424000DF347D76D821C038E109BDFE9042406077BAF3C4D321C0B0984A3FE1924240C0355B79C9CF21C0500DFB3DB1944240A0BA46CB81CE21C0D8B5F63E559542400035423F53B721C090992842EAA2424080F6234564A821C0582E54FEB5B0424020425C397B9721C000871744A4B8424080402D060F9321C028E78BBD17C3424040333333339321C008BEDBBC71DC424060022846969C21C01006820019E2424000A1D9756F9521C03035B401D8E84240E0D362F0309521C008C11C3D7EE9424000508BC1C39421C0D0D03FC1C5EA424000F1BA7EC19621C02835B401D8F24240000E130D529821C010D6E3BED5F44240C0B7054B759921C008A0C37C79F54240A02094F7719C21C0E876137CD3F6424020272F32019F21C038F38FBE49F7424000D0EFFB37AF21C080ABAE4335014340203883BF5FAC21C05882FE428F02434040AC1A84B99D21C0E082177D050B4340A02094F7719C21C0889065C1C40B434000E8F7FD9B9721C00809C380250F434080EA1F44329421C030D8463CD9114340A03E1EFAEE8E21C078A52C431C174340C0088B8A388D21C0C8C804FC1A1B4340C0942BBCCB8D21C0E08558FD11204340A047E17A148E21C0B0C2D84290214340E0CFEFFB378F21C010C45DBD8A26434060CDC7B5A19221C010068200192A43400047C8409E9521C0480DFB3DB12C4340E0F2C98AE19A21C0B89B8BBFED2F4340203CF6B3587221C0C8B5F63E55354340E091EA3BBF5821C0B09ECC3FFA344340407138F3AB8921C0306BD44334424340407AFB73D1C821C08854C37E4F424340E0B1834A5CCF21C028F04E3E3D42434080CDC7B5A1D221C088A2EBC20F424340E0AE42CA4FDA21C05801F73C7F404340A04F72874DFC21C00815C781573B434000D12170242022C0889C69C2F6374340401B2B31CF2A22C0D0BB783F6E3743402030F2B2265E22C0D8CDFE40B9354340C02616F88A6622C0B074B0FECF39434080C1C3B46F5E22C000D6E3BED53C434040AC1A84B95D22C0500438BD8B3D4340800BEBC6BB5B22C09018213CDA404340A0583508735B22C000C11C3D7E41434080F964C5705D22C0E8A6B1BD1644434020560DC2DC5E22C0A8B6D4415E45434080F62345646822C0D07954FCDF4B43404024EEB1F46922C030232E008D4C434000F60A0BEE6F22C05840DAFF004F4340A023D5777E7122C0808461C0924F4340E016D68D777722C05073B9C1505143404030F2B2267E22C0C8D03FC1C5524340E019170E848C22C0789FAA4203554340E08B683BA68E22C0A0E3310395554340408E90813C8B22C0881B62BCE65543400008910C396E22C0E876137CD3564340003E05C0785622C030DB87BCE5564340205E9ECE154D22C03029B000A6564340C0A23EC91D2622C0F82F1004C850434000D9B27C5D0E22C030266F80995943406083BEF4F60722C0A8B6D4415E5D434060A2258FA7ED21C090457EFD10614340608C81751CE721C0908AE3C0AB614340004487C091E021C0903CBB7CEB614340C0409DF2E8D621C05822C2BF0862434040B16A10E6D621C05807793D98624340E0A57F492ADB21C058499D80266643406002284696DC21C0508E0244C166434020D4450A65E921C0504A253CA16B4340A03E1EFAEEEE21C03035B401D86A4340E0963AC8EBF121C01015C781576B43406094128255F521C0805A457F686C4340E0A3703D0AF721C0080341800C6D434020A8A78FC0F721C0D0CDFE40B96D434080DC0C37E0FB21C0B853E57B4672434000D671FC50F921C058F5F23B4D744340205B5D4E09F821C05873B9C150794340E076A1B94EFB21C030E109BDFE784340406BB6F292FF21C0A89B8BBFED774340203BC43F6C0122C0805704FF5B774340203BC43F6C2122C0F81A4982706D4340408C81751C2722C0881EA33CF36A43402053CC41D02922C0888AE3C0AB694340E09DEE3CF12C22C0A86E2EFEB6674340E0D8B27C5D2E22C06076FA415D664340E0B1834A5C2F22C0D00CE2033B64434000F60A0BEE2F22C0901EA33CF3624340C0355B79C92F22C038F04E3E3D624340803E1EFAEE2E22C0A0C2D84290614340E082A5BA802F22C0D8B2B5BE48604340608940F50F3222C03041B8020A5F434000F1BA7EC13622C0D0031F83155D434080EE92382B3A22C0C8F4D901D75B434060F964C5703D22C048793BC2695B434000D3307C444422C0B0984A3FE15A434020ABE80FCD6C22C0109D82FC6C58434000F94B8BFAA422C05828D2FD9C564340E09CBCC804DC22C0B8656B7D915843400067614F3BEC22C058F833BC5959434060CDC7B5A1F222C0283E7782FD594340205B5D4E09F822C0B0984A3FE15A43402039B5334CFD22C0A0BF97C283644340A02094F771FC22C0306893C3276543402049D74CBEF922C058FB743C66664340C0BA46CB81EE22C03035B401D86A434000CEE0EF17EB22C0D8A6B1BD166C43408008AA46AFE622C0080341800C6D434000F94B8BFAE422C00848A643A76D434000E5B67D8FE222C008DC65BFEE6E4340E0D0217024E022C0584F1F813F704340005B5D4E09D822C0507FBDC282754340202A70B20DD422C08818213CDA78434080FCA5457DD222C0286BD443347A4340202A70B20DD422C0D87FD6FCF87D434020508BC1C3D422C03829B000A67E43402047C8409ED522C0B85626FC527F4340E00D130D52D822C0E0D38041D27F4340E0AE42CA4FDA22C0507C7C427680434060EE92382BDA22C0101E8A027D824340200F27309DD622C088A2EBC20F8A4340E0CDE0EF17CB22C0A8A44E40138F4340C029577897BB22C030232E008D944340C03BDD79E2B922C028ED0DBE30954340C0B1834A5CAF22C0806308008E9B4340E019170E84AC22C0285FD042029E434000EB387EA8AC22C0382F3201BFA0434040ABE80FCDAC22C0A86BED7DAAA24340C0874B8E3BAD22C0B041D13C80A543400005508C2CB922C008240C0396AC4340E0A3703D0AB722C0808D2441B8AE4340608B4F01309622C00806820019B2434000DD2571567422C0A86E2EFEB6B743402053CC41D04922C0109A417C60C34340E0F3FBFECD2B22C0788D2441B8CE434040A9D903AD2822C0583D997FF4D14340000E130D521822C0E0CDFE40B9DD4340E0942BBCCB0D22C0B0B0524145E34340202C7FBE2DF821C088397AFCDEEC43408046AF0628DD21C058793BC269FB434020C1C6F5EFCA21C0F011F8C3CF05444060ED60C43EC921C0B8DA6E826F064440408C81751CC721C0580ABABDA4074440401E6CB1DBBF21C058F5F23B4D0C44400049D74CBEB921C0302F3201BF104440E0D571FC50B921C0901EA33CF3124440E00AD28C45C321C0B0A44E40131F444080C404357CB321C030F38FBE49274440E007910C39AE21C0286211C30E2B4440E08827BB999921C028DEC83CF23B4440606EF7729F9421C0B8E0F08288404440A01342075D9221C0706A847EA6424440C02C98F8A39021C008D6E3BED5444440E0D8B27C5D8E21C000BB9A3C65474440C0942BBCCB8D21C08021E4BCFF474440E08711C2A37D21C0A81D37FC6E504440E05A5F24B47521C028711DE38A514440007AE1CE857121C0F0AEEC82C15144402061DF4E226221C08087A2409F544440203CF6B3585221C0909C69C2F6574440600569C6A25121C0385C8FC2F5584440E076A1B94E5B21C03814E97E4E6344404083BEF4F66721C008DFA63FFB5B4440409EEBFB707021C018BDC5C37B584440603332C85D7421C02826E1421E574440A0807A336A7621C0F890B75CFD564440E0DE347D767821C0A8A44E4013574440E0E7F7FD9B7721C0504F1F813F584440202A70B20D7421C0306893C3275D4440E082A5BA806F21C038172AFF5A60444060B29C84D26721C00848A643A765444080EB51B81E6521C0089700FC53664440C0976C3CD86221C0B8B393C15168444080E5CFB7055B21C0286E15C4406F4440E0CA9F6F0B5621C0382CF180B2734440401B2B31CF4A21C0600ABABDA47F444000D7A3703D4A21C010E2E7BF07814440004240BE844A21C068368FC360824440A05B76887F5021C0B0B6D4415E8544402076A6D0797521C0101286014B9E4440E0DC2571569421C0D8FA5B02F0B5444060915F3FC48E21C0B0B6627FD9BB444000F60A0BEE8F21C0305FD04202BE4440C0B7054B759921C0B0E0F08288C8444040B9DE3653A121C01860CAC001CF4440A046AF0628BD21C0082DCF83BBDB444000F73C7FDAC021C000CD203EB0DD444000E5B67D8FC221C0808461C092DF444000DCF3FC69C321C08018213CDAE0444000E5B67D8FC221C0F899417C60EB4440203201BF46C221C088423D7D04EC444080D349B6BABC21C028327381CBED4440006DE34F54B621C008BB9A3C65EF4440204487C091A021C0B8622AFD84F34440601EDD088B9221C0480ABABDA4F5444020C72B103D8121C0805182FE42F74440408446B0717D21C0883CBB7CEBF944408046AF06287D21C000E869C020FB4440C02094F7717C21C0002DCF83BBFB444060EE92382B7A21C038F6D03E56FC444080D00836AE4721C028327381CB054540407D3CF4DD3D21C0B877F17EDC06454000F1BA7EC13621C0888461C09207454000FDBE7FF30A21C05807793D980A454060FFE6C5890721C0B86BED7DAA0A454060FCA5457DF220C03835B401D80A4540A0B4C4CA68E420C03835B401D80A454020272F32019F20C0885182FE420D4540E0C75EEFFE8020C0D0EE5701BE114540E06778B3066720C04065FCFB8C134540C0BD874B8E6320C0D082177D05134540A047E17A142E20C09093A641D1084540E0F3FBFECD2B20C0D8B2B5BE48084540607AFB73D12820C000DC65BFEE0645402053CC41D02920C0C8F4D901D703454000D7A3703D2A20C0E8AF743E3C03454020414640852B20C06007793D98024540C0942BBCCB2D20C0F80582001902454060DF4DB7EC3020C0508BC1C3B401454040A8A78FC03720C058465C001A01454000F94B8BFA4420C04837177FDBFF4440406EF7729F5420C0A8ECF483BAFC4440407AFB73D16820C03820ED7F80F74440E09DEE3CF16C20C070AEEFC341F6444000F60A0BEE6F20C0203B3602F1F44440E0A8C0C9367020C050F5F23B4DF44440E082A5BA806F20C0302CF180B2F34440407AFB73D16820C0909C69C2F6EF4440'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('RO','RO','ROU','642','Romania','22987','21627557','150','151','24.969','45.844','0106000020E610000001000000010300000001000000CF030000E7A90EB919BA34402D3E05C078164740D63730B951B834407D21E4BCFF1747408200193A76B83440A8E0F082881847407E18213CDAC03440D2C43BC0931E47407C992842EAC2344051853FC39B1F47408200193A76C834407AABAE4335214740AAF3A8F8BFCB344093E1783E0322474055C2137AFDD134407F4B00FE292347404DD6A88768D43440A9DDAF027C234740D1CABDC0ACD83440F92CCF83BB23474083FA96395DDE3440FD14C78157234740D63A71395EFD34407B6649809A204740FE0E45813E09354002BB9A3C651F4740AB59677C5F0C35407E8D2441B81E4740D1CDFE40B90D3540D2C43BC0931E474084F1D3B8370F35405628D2FD9C1E474022895E46B114354051853FC39B1F4740AD50A4FB392D3540AB9509BFD4254740A8E33103952D3540FD1186014B264740D1CDFE40B92D35402CD8463CD9294740D4BB783F6E2F354055FB743C662E47402AE109BDFE3035407D93A641D1304740FC1D8A027D323540FF05820019324740D4B5F63E55353540A9DDAF027C334740286552431B3835405470784144344740533D997FF44935407E1EA33CF33A474050C763062A4B35407AA86DC32844474058AD4CF8A54E3540A7B05241454B4740D828EB37134F3540F92CCF83BB4B47402B6C06B820533540813FFCFCF74E4740D2C77C40A05335407E5704FF5B4F474027F6D03E56543540A86E2EFEB64F4740D6A9F23D2371354028F38FBE49574740514CDE0033733540A86E2EFEB65747404DD6A88768743540FD4D2844C0574740A7E9B303AE773540FED2A23EC9574740F86EF3C6497D354061889CBE9E574740A9DA6E826F7E3540AA9B8BBFED574740A968ACFD9D853540D5AF743E3C5B47402BDB87BCE5863540FCDEA63FFB5B4740266E15C44087354001BEDBBC715C4740D540F33977873540AA9ECC3FFA5C4740008E3D7B2E873540FC1A4982705D474024809BC58B8535402AE44A3D0B5E4740552E54FEB58035407E8D2441B85E47407E8D2441B87E3540556D37C1375F4740AD50A4FB397D35402638F581E45F474055BFD2F9F07C35402B172AFF5A604740D731AEB8387E35407E8AE3C0AB614740000341800C8535402B172AFF5A6847407F129F3BC1863540FA264D83A2694740D540F33977873540253E7782FD694740562B137EA98B354054FEB5BC726B47407B9FAA42039D3540A8AAD0402C714740F92CCF83BBAB3540286211C30E7B4740D6A9F23D23B13540266E15C4407F4740008BFCFA21B23540286552431B80474055C2137AFDB1354000CADFBDA3804740D446753A90B13540FCE1E7BF07814740552E54FEB5B0354055F833BC598147406C76A4FACEA7354096CCB1BCAB824740266E15C440A73540AB984A3FE1824740A6F27684D3A63540A7B0524145834740FA298E03AFA635407F15E0BBCD834740D236FE4465A735407AA86DC3288447405531957EC2B53540276BD443348A47407AA86DC328BC3540A8A78FC01F8C4740FB928D075BC035407B9FAA42038D4740A304FD851EC53540FFCC203EB08D4740514F1F813FC835405376FA415D8E4740FA980F0874CA354002BB9A3C658F4740514F1F813FD83540A7E9B303AE974740FE0E45813ED93540A8E0F08288984740FE0E45813ED93540FF058200199A47407D93A641D1D83540FBE769C0209B474056BC9179E4D735402BDEC83CF29B4740AC5626FC52D7354082397AFCDE9C4740D540F33977D735402AE44A3D0B9E4740D0D38041D2D735407C60C77F819E47404DDC2A8881DE3540530438BD8BA54740CF4E0647C9DF35405376FA415DA647407AA86DC328EC3540A6B6D4415EAD474055BFD2F9F0EC3540D1CDFE40B9AD47407E8D2441B8EE354079AEEFC341AE47407A17EFC7EDEF3540A9DA6E826FAE47402577D84466F635407AA52C431CAF4740267156444DFC35407E5704FF5BAF4740D828EB3713FF35407F8461C092AF47407AABAE43350136407D21E4BCFFAF474052B81E85EB0136402B172AFF5AB04740FC1D8A027D023640272F3201BFB04740FD14C781570336407E8AE3C0ABB14740CD5A0A48FB033640A96BED7DAAB247404FCDE50643053640A9DA6E826FB64740A968ACFD9D0536402AE109BDFEB84740A8716F7EC3043640A6B915C26ABA474081069B3A8F02364029232E008DBC4740800F5EBBB4013640D47FD6FCF8BD4740D446753A9001364051853FC39BBF4740A7E67283A102364052465C001AC14740A77A32FFE80336402CD8463CD9C1474050C422861D063640AB984A3FE1C24740D63730B951083640D57954FCDFC34740A4FE7A85050B3640A7ECF483BAC4474097AAB4C5351E3640CBBE2B82FFC94740ABEAE5779A2836407E1EA33CF3CA4740D63A71395E2D3640562B137EA9CB4740A86E2EFEB62F36407F87A2409FCC4740BE892139993036402B14E97E4ECD47407E18213CDA3036407F4E417E36D04740D6A9F23D23313640272F3201BFD0474027F911BF62393640508E0244C1D64740533D997FF4393640FF08C38025D747404FCDE5064345364051888043A8DC47402BDB87BCE54636407E5182FE42DD4740FA264D83A2513640A5BC564277DF47402DCF83BBB3523640A7E9B303AEDF474055C2137AFD713640530438BD8BE5474027F6D03E56743640D3FA5B02F0E54740CC5D4BC807793640295FD04202E64740505260014C7D3640FE47A643A7E547400000000000803640F4FC69A33AE54740A5F8F884EC803640D1031F8315E5474051BEA085048C36407E54C37E4FE247407E8D2441B88E36407BA2EBC20FE24740D63730B951983640D28BDAFD2AE24740A7ECF483BA9C3640D4B837BF61E247405055A18158A23640D0D03FC1C5E24740AC5626FC52A73640FE99417C60E3474079AEEFC341C63640286211C30EEB47402DD2C43BC0C73640F92CCF83BBEB4740D63730B951C83640A8A78FC01FEC4740FC17080264C83640520DFB3DB1EC47407A54FCDF11E53640A75CE15D2EFA4740FB95CE8767E53640FF05820019FA47402B69C53714EE36407E1EA33CF3FA474029E78BBD170B37407AA52C431CFF4740A968ACFD9D153740AB5CA8FC6B01484029780AB952173740A9A10DC006024840D3C1FA3F87193740A54DD53DB2034840D255BABBCE1A3740D1031F8315054840297B4B395F1C3740CFDC43C2F70648402A7288B8391D374052465C001A0948404DDC2A88811E3740FC1D8A027D0A4840A86E2EFEB61F374079B130444E0B48407AABAE4335213740FCDEA63FFB0B4840F8325184D4253740D4B5F63E550D48402A6F47382D283740D1CDFE40B90D4840A4FE7A85052B37407E1B62BCE60D484052499D80262E374028B7ED7BD40D4840FA264D83A2413740FBB1497EC40B4840037976F9D643374079B130444E0B48402BDB87BCE5463740A9A10DC0060A484001857AFA08483740FE0E45813E09484050C763062A4B3740FD1186014B0648407F15E0BBCD4B3740D3FA5B02F0054840800C1D3BA84C3740A968ACFD9D05484058AD4CF8A54E3740D388997D1E054840CDE847C3295B37407A6CCB80B3024840CC5D4BC807693740D38558FD11004840A4FE7A85057B3740D388997D1EFD47402CD505BCCC7C3740D1031F8315FD4740D4BB783F6E7F37407DCC07043AFD47405055A181588237407D96E7C1DDFD47402B6C06B820833740D6AC33BE2FFE47407B698A00A78337405358A9A0A2FE47401C5DA5BBEB9037407D21E4BCFFFF47407C992842EAD237407E9065C1C4FB4740514F1F813FF83740286211C30EFB4740A6F27684D3063840FC1D8A027DFA47400473F4F8BD09384028F04E3E3DFA47402BDB87BCE5163840D38558FD11F84740D1CABDC0AC1838402920ED7F80F7474051BEA085041C3840D1CDFE40B9F5474056B60F79CB1D3840276893C327F5474029EACC3D24203840A7ECF483BAF44740D446753A90213840FB230C0396F44740286211C30E233840D3BEB9BF7AF447404DDC2A88813E3840562B137EA9F347407A17EFC7ED3F3840F92CCF83BBF3474057B08D78B25338402BDB87BCE5F6474058AA0B7899693840D4B837BF61FA474082035ABA826D3840D0D03FC1C5FA4740CD57C9C7EE6E38402635B401D8FA4740FE0B040132743840FD4AE7C3B3FA4740A9DA6E826F8E3840253E7782FDF947404DDC2A8881923840C022BF7E88F947405628D2FD9C96384080457EFD10F947407AA86DC3289C3840AA9B8BBFEDF74740CD57C9C7EE9E38407AA52C431CF74740A4FE7A8505AB3840A9DDAF027CF3474000917EFB3AAC3840D0D03FC1C5F24740D44334BA83AC3840AC53E57B46F24740AB59677C5FAC3840508BC1C3B4F1474050C763062AAB3840D5B2B5BE48F04740A4FE7A8505AB3840A7E9B303AEEF4740D5AF743E3CAB3840556D37C137EF4740562B137EA9AB3840D4F19881CAEE47400188BB7A15AD38408048BF7D1DEE4740FA264D83A2B13840520DFB3DB1EC47405531957EC2B53840562B137EA9EB474083F755B950B93840D482177D05EB474029ED0DBE30C53840FCE1E7BF07E9474082035ABA82CD3840D1CABDC0ACE84740A301BC0512D03840A7B393C151E847402AE109BDFED03840D38558FD11E84740A7E67283A1D23840D4BB783F6EE74740A304FD851ED53840FCE4284014E647407B9FAA4203DD3840D00F238447E1474027F6D03E56E4384027F6D03E56DC47407A1A3048FAE43840FCDEA63FFBDB47407F129F3BC1E6384053793BC269DB4740286552431BE83840D5AF743E3CDB4740FE99417C60EB384029E78BBD17DB4740CCB22781CDED3840B7B3AF3C48DB4740D82B2CB81FF43840D7A6B1BD16DC474001857AFA08F8384001BEDBBC71DC4740E1270EA0DFFF38401D1D5723BBDC4740FE2AC0779B0739401B118C834BDD4740FD2D01F8A70C39407D96E7C1DDDD4740FB3C4679E61539407590D78349DF47407AA86DC3281C39404D672783A3E04740259012BBB61F394023111AC1C6E14740A4FB3905F9253940FA7B293C68E447404888F2052D2839404B3D0B4279E54740A41AF67B6229394079AEEFC341E64740F92CCF83BB2B3940A8E0F08288E847402098A3C7EF2D3940768D96033DEA474076DF313CF6373940A5BC564277EF4740FB3F87F9F23A39404852D2C3D0F04740D0D6C1C1DE3C3940A3957B8159F147407CB5A33847413940202922C32AF24740A320787C7B533940A489778027F54740F3599E0777573940527FBDC282F547407BBE66B96C803940A5BC564277F747402577D84466863940A0A70183A4F747404E5E64027E9139404C70EA03C9F74740FA298E03AF963940CEA623809BF7474078B7B24467A53940F4DE180280F74740A4FB3905F9C53940240B98C0ADF74740A8E0F08288C8394076DF313CF6F74740CF4BC5C6BCCA3940F5D555815AF847407AABAE4335D13940FAF02C4146FA474052D7DAFB54D53940514CDE0033FB474073D53C47E4D73940A29BFD8172FB474072E1404816EC3940F50EB743C3FC474050E3DEFC86093A40CCB8A981E6FD474080F0A1444B1A3A40DFFAB0DEA8FD4740FC1A4982701D3A40F148BC3C9DFD47402577D84466263A409C8C2AC3B8FD47404F779E78CE2A3A40471FF30181FE47404D83A279002F3A409E7AA4C16DFF4740A9F92AF9D8313A407F4E417E3600484025085740A1323A40AA656B7D91004840CF488446B0453A4052103CBEBD09484081069B3A8F523A407A724D81CC14484081069B3A8F523A40D4B5F63E55154840D446753A90513A40CDE506431D164840D009A1832E513A4032B08EE387164840F92F1004C8503A40CFDC43C2F71648400F48C2BE9D503A4076543541D41748404E61A5828A763A40CCB22781CD1B484050E3DEFC86793A4022179CC1DF1B48404C70EA03C97F3A407C6308008E1B484052431B800D843A4029E78BBD171B4840D6AC33BE2F863A4025085740A11A48408109DCBA9B873A405182FE428F1A4840037CB779E3883A407A6CCB80B31A4840257497C459913A4050E09D7C7A1C48409F1F46088FA23A40B2DAFCBFEA204840A20DC00644B43A40D673D2FBC62148405340DAFF00CF3A4027BD6F7CED1F4840A016838769D33A40A38FF980401F4840CBF78C4468F43A407A6F0C01C017484029EACC3D24003B40A77A32FFE8134840C90391459A283B40A06B5F402FFE4740A016838769333B40F1BDBF417BF34740C51EDAC70A363B401F2FA4C343EC474076E272BC023D3B409F02603C83E44740AAF3A8F8BF473B40A3CB9BC3B5D8474072E14048164C3B40CEA96400A8D4474041D7BE805E4C3B4014AE47E17AD44740FD2D01F8A74C3B40A3923A014DD44740249C16BCE8533B404E5E64027ED147400B9C6C03775C3B40FE2C9622F9CE4740CD57C9C7EE6E3B40F5D555815AC8474051C1E10511793B40D9CD8C7E34BE4740A320787C7B933B402499D53BDCAE4740FC3905F9D9A03B40755AB741EDA747405055A18158A23B407590D78349A74740F94ECC7A31A43B40494C50C3B7A647402098A3C7EFAD3B40F705F4C29DA54740A298BC0166B63B40F50EB743C3A4474076DF313CF6B73B40F50EB743C3A4474021AD31E884B83B40333509DE90A4474079CDAB3AABB93B407AA86DC328A4474023A298BC01BE3B40FA264D83A2A1474021956247E3C83B40768D96033D9A4740FE0E45813EC93B40F511F8C3CF994740267156444DCC3B40F8FF71C284934740F25CDF8783DC3B402026E1421E8D47404D672783A3F03B40A3CEDC43C28547400B09185DDEF03B407CBABA63B1854740FA264D83A2F13B404B3D0B427985474080290307B4F43B4089B48D3F51854740CC28965B5AFD3B40AEBCE47FF283474073DBBE47FD013C40CDE847C329834740D1CABDC0AC083C40253E7782FD814740276BD44334123C402499D53BDC7E47404DD6A88768143C40CCB8A981E67D4740F73B1405FA143C404CC2853C827D4740CF488446B0153C40CEA96400A87C4740D0F23CB83B1B3C4027327381CB754740C806D2C5A61D3C40FA264D83A271474076C6F7C5A51E3C402AC93A1C5D6D474049827005141E3C40240ED940BA6C4740F4531C075E1D3C40F2EA1C03B26B4740F4531C075E1D3C40CDE847C3296B4740D1CDFE40B91D3C404C6DA983BC6A47401B47ACC5A72C3C40FA298E03AF5E4740F94ECC7A31343C40F8F9EFC16B594740240B98C0AD373C40F9F36DC1525747404F779E78CE3A3C40FCE4284014564740F90FE9B7AF3B3C402E8CF4A27655474022179CC1DF3B3C4052D7DAFB545547404A79AD84EE3E3C4023145B41D34E47404E7CB5A3383F3C406B9A779CA24D474022365838493F3C40A6B6D4415E4D4740D04543C6A3403C404C70EA03C9374740AF5E454607403C40C6A6954220374740A1BAB9F8DB3E3C407D96E7C1DD354740F25F200890313C40FAF02C41462A4740C90050C58D233C40F75AD07B63184740ABED26F8A61D3C407C9C69C2F60F4740774EB340BB1B3C406BD619DF170D47404F58E20165173C40508BC1C3B4094740268A90BA9D153C404E5E64027E014740A4FB3905F9153C40A8E0F08288004740C80C54C6BF173C407AFD497CEEFE4640F450DB8651183C40D2C43BC093FE4640390EBC5AEE183C40B22E6EA301FE4640257A19C5721B3C40A3C85A43A9FB4640218FE046CA1E3C4023A298BC01F64640CE548847E2293C40D0D6C1C1DEDC4640F9484A7A182A3C40F9F6AE415FDC4640A51133FB3C2A3C40249C16BCE8DB46404C6DA983BC2A3C4027327381CBD54640268DD13AAA2A3C40CCEEC9C342D5464076C3B64599293C40CD3AE3FBE2D04640F8510DFB3D293C40F75AD07B63D04640C90391459A283C40CBBE2B82FFCF4640240B98C0AD273C407A6F0C01C0CF46401C45D61A4A253C401B9C887E6DCF4640C51B9947FE203C404F58E20165CF4640FD304278B4113C40F6083543AACA4640CEDF8442042C3C40F50EB743C3BC4640505260014C2D3C402444F98216BC4640F9484A7A18363C40F148BC3C9DB9464065DF15C1FF363C406939D0436DB9464076DF313CF6373C4029266F8099B946401A3048FAB43A3C4030116F9D7FB94640F8325184D4453C407A6F0C01C0B74640F3599E0777473C40C9C7EE0225B746407C9C69C2F6473C409FB0C403CAB64640D1CABDC0AC483C40CD3D247CEFB54640239F573CF5483C40745DF8C1F9B4464075CC79C6BE483C404819710168B44640EE7BD45FAF483C40C504357C0BB34640D1CABDC0AC483C40A2D11DC4CEB24640CC5D4BC807493C4079758E01D9B146407E8AE3C0AB493C40787E5182FEB04640257A19C5724B3C404F58E20165AF4640D1CDFE40B94D3C40FC1A498270AD464027A1F485904F3C4079573D601EAC4640D158FB3BDB4F3C40249C16BCE8AB464051C1E10511513C40514CDE0033AB464022895E46B1543C4029266F8099A9464073D53C47E4573C40F75AD07B63A84640CCEB884336603C40F8FC304278A646404985B18520933C4073637AC2129F4640CCEB884336B03C401F2FA4C3439C4640C712D6C6D8B13C40F7C95180289C4640683D7C9928B23C40F7C95180289C46404C88B9A46AB33C40F7C95180289C46404E7D2079E7B43C40F7C95180289C4640CC5D4BC807C93C40FC1A4982709D464054C8957A16CC3C40778192020B9E464080290307B4CC3C405ED905836B9E4640A7ECF483BACC3C4023145B41D39E4640FE0E45813ED93C40A4C519C39CA64640D0D38041D2F73C4052465C001AA94640FE2AC0779B373D405376FA415DB64640CE548847E2393D402829B000A6B64640FA264D83A2513D407EC9C6832DB84640209BE447FC523D40CCEB884336B84640A110018750693D404C70EA03C9B74640FC3905F9D9803D404B732B84D5B4464022895E46B1843D40A3923A014DB44640F3565D876A923D40768D96033DB24640A8FC6B79E5963D40A3957B8159B14640FA980F08749A3D40514F1F813FB04640286211C30EA33D404B732B84D5AC4640A304FD851EA53D40D3F4D901D7AB4640A7E9B303AEA73D40D05E7D3CF4A94640D255BABBCEAA3D40A4C519C39CA64640F92CCF83BBAB3D407A724D81CCA446407AA86DC328AC3D404C37894160A3464051BEA08504AC3D40CCF10A444FA246400FB8AE9811AA3D40EC18575C1C9B4640C712D6C6D8A13D40D2C77C40A09B4640247D5A457FA03D407C6308008E9B4640259012BBB69F3D40A7B05241459B464047551344DD9F3D4053910A630B9B4640FA42C879FF9F3D402635B401D89A4640F644D7851FA43D4079AEEFC341964640CC5D4BC807A93D40A31D37FC6E8E4640F94ECC7A31A43D404D6A6803B07D464073D87DC7F09C3D407B9FAA42036D464027840EBA849B3D40D2C77C40A06B464050E3DEFC86993D40514CDE00336B4640FD2D01F8A78C3D40787E5182FE684640A016838769733D40FB20CB8289674640219221C7D6633D40FA298E03AF664640CEFBFF38615A3D405376FA415D664640286211C30E573D405376FA415D66464079CA6ABA9E543D405376FA415D6646404FCAA48636403D407D96E7C1DD65464023145B41D3363D40527FBDC2826546407CB5A33847113D401E32E54350694640505260014C0D3D409EB30584D66B4640A9F6E978CC0C3D404D2EC6C03A6C464027840EBA840B3D40D3FA5B02F06D4640259694BBCF093D40240ED940BA744640F9484A7A180A3D4076543541D4754640FB3F87F9F20A3D40508E0244C17646407EA99F37150D3D401FF64201DB77464078B471C45A103D40C7A0134207794640276BD44334123D409D8026C286794640CF488446B0153D40D05E7D3CF4794640FC17080264183D407BA2EBC20F7A4640268DD13AAA1A3D405055A181587A46407DB262B83A1C3D40CBBBEA01F37A4640FB230C03961C3D40A320787C7B7B4640FD2D01F8A71C3D40CEDF8442047C464072E14048161C3D40F9F6AE415F7C46404DD9E90775193D40FAEDEBC0397D464072E14048160C3D40A8380EBC5A804640268DD13AAA0A3D40527C7C4276804640F65D11FC6FFD3C40F92F1004C88046404F779E78CEFA3C40F92F1004C8804640228C9FC6BDF93C407B6649809A8046402577D84466E63C40F92CCF83BB7B4640259012BBB6DF3C40F8F9EFC16B794640F8544E7B4ADE3C40A3CB9BC3B578464074CFBA46CBDD3C402250FD8348784640240ED940BADC3C40508E0244C17646404F5B238271DC3C407B698A00A7754640C70F9546CCDC3C40CCB56801DA7046407EA99F3715DD3C404B3ACAC16C70464078D0ECBAB7DE3C40D0D38041D26F4640249C16BCE8E33C40508E0244C16E46404D6A6803B0E53C40A7AD11C1386E4640CFD90242EBF13C40FAF02C41466A46404985B18520F33C40A4C2D842906946404985B18520F33C4024473A0323694640505260014CED3C40D2C77C40A0634640514F1F813FE83C40A3CB9BC3B560464078B7B24467E53C40D1CABDC0AC604640A514747B49DF3C40778714032460464072E1404816DC3C4051853FC39B5F4640297B4B395FCC3C402444F982165C4640A708707A17CB3C4079B130444E5B4640A019C40776C83C404D310741475946407C9C69C2F6C73C404852D2C3D0584640FE2AC0779BC73C404D6A6803B0554640A6F0A0D975C73C406F4562821A544640D1CABDC0ACC83C40755776C1E0524640D731AEB838CA3C401230BABC39524640FB3F87F9F2CA3C40CFD90242EB514640FB230C0396CC3C4079758E01D95146407BBE66B96CD03C40CAC4AD82185246407C9C69C2F6D73C40F6083543AA524640F73E558506DA3C4021205F4205534640F92CCF83BBDB3C404E64E60297534640FB20CB8289E73C40CEA623809B574640F450DB8651E83C40F1F62004E4574640239F573CF5E83C402250FD8348584640454772F90FE93C40C767B27F9E584640C80C54C6BFE73C40A41AF67B62594640A4FB3905F9E53C40FC1D8A027D5A46407CB8E4B853E63C40CC4065FCFB5A4640F3599E0777E73C40755776C1E05A4640A165DD3F16EE3C409D11A5BDC1594640A20DC00644F43C404E5E64027E594640A1A17F828BF53C401E32E54350594640D0D6C1C1DEFC3C40FBEAAA402D5846402098A3C7EFFD3C4076DF313CF657464076C6F7C5A5FE3C40A0A70183A4574640218FE046CAFE3C40C9C7EE0225574640A31D37FC6EFE3C402829B000A656464021956247E3F83C4025085740A15246404B92E7FA3EF83C40768D96033D52464076C075C58CF43C40F2ED5D83BE504640CC0A45BA9FF33C40A19E3E027F504640F3565D876AF23C40F5D555815A504640F25F200890F13C404D672783A3504640C51B9947FEF03C407903CC7C075146407AABAE4335F13C404E5E64027E514640CFF8BEB854F53C401D0247020D544640A58636001BF83C407A724D81CC54464079CDAB3AABF93C40F5D8960167554640FB3F87F9F2FA3C40234A7B832F56464079B130444EFB3C40FA298E03AF56464018EAB0C22DFB3C4081B4FF01D6564640FB3F87F9F2FA3C407AA52C431C574640F9484A7A18FA3C404F58E20165574640F8325184D4F53C402250FD8348584640A417B5FB55F43C407172BF435158464069723106D6D13C40041E1840F84E4640E2AC889AE8CB3C405D70067FBF50464050E09D7C7AC43C407B6649809A504640A9DDAF027CC33C40FC17080264504640AAF06778B3C23C40D200DE0209504640D13C80457EC13C407AA52C431C4F464053CBD6FA22C13C402829B000A64E464052B81E85EBC13C4080812040864246409C86A8C29FCD3C4044A4A65D4C434640E8FA3E1C24D03C40213EB0E3BF4446409F1C058882ED3C402541B8020A4F4640228C9FC6BDE93C40A7B05241454B4640A6EF3504C7E13C40A73B4F3C67454640FF08C38025DF3C40F92CCF83BB434640FC17080264D83C40A0A70183A43F4640CE5147C7D5D43C40D1CDFE40B93D4640F44D9A0645D33C40000341800C3D46408690F3FE3FCE3C401DE736E15E3B4640B64AB0389CCD3C4087DEE2E13D3B46401D93C5FD47CA3C405E82531F483A46407BA2EBC20FC23C40556D37C1373746402499D53BDCBE3C407D96E7C1DD354640F3599E0777A73C40A29BFD81722B4640A60EF27A30A53C40A6B915C26A2A464076C075C58CA43C40253E7782FD2946409F1F46088FA23C4027BD6F7CED2746407CB5A33847A13C40A7AD11C13826464051C1E10511A13C404D6A6803B0254640A702EE79FEA03C40A2D11DC4CE22464073DBBE47FDA13C407AA86DC328144640CC5D4BC807A93C40D0D6C1C1DEFC4540CF488446B0A53C40202922C32AFA45407EA99F37159D3C40CCB56801DAF04540F450DB8651983C40A73E90BC73EA45407B116DC7D4953C40F981AB3C81E64540A417B5FB55943C407BFA08FCE1E14540A417B5FB55943C407903CC7C07E145409696917A4F953C40F60B76C3B6DF45407AA86DC3287C3C40266E15C440DF4540D236FE4465673C40D200DE0209E0454073DBBE47FD413C4079758E01D9E14540267156444D3C3C405182FE428FE24540D2C43BC0932E3C40A5BF97C283E445407BA2EBC20F223C40A4C519C39CE6454054C8957A160C3C40A73E90BC73EA4540FE2AC0779B073C4053793BC269EB4540247D5A457F003C40CCEEC9C342ED4540A514747B49FF3B40211D1EC2F8ED4540D1CDFE40B9FD3B407F8461C092EF45407CB8E4B853F63B40286552431BF8454052D7DAFB54F53B40F511F8C3CFF94540A60EF27A30F53B404C6DA983BCFA45404DD6A88768F43B40A5BF97C283FC4540D2C77C40A0F33B40505260014CFD4540A9F92AF9D8F13B405376FA415DFE45409F1C058882ED3B40A8380EBC5A00464052D158FB3BEB3B40A3CB9BC3B5004640FF05820019EA3B40F702B34291004640F54A598638DE3B40211D1EC2F8FD45404ED026874FDA3B402026E1421EFD454052D7DAFB54D53B4052431B800DFC454073DBBE47FDD13B40D2C77C40A0FB4540A11342075DCE3B4053793BC269FB4540A514747B49BF3B40D0D03FC1C5FA4540F25CDF8783BC3B402635B401D8FA4540A708707A17BB3B4021205F4205FB4540AAF3A8F8BFB73B407E9065C1C4FB454053CE177B2FB63B40F9F6AE415FFC45407A1A3048FAB43B40D1031F8315FD454041102043C7B23B40D009A1832EFF4540A514747B49AF3B40F6083543AA0246402098A3C7EFAD3B40D3F4D901D7034640505260014CAD3B40FE0B040132044640F25CDF8783AC3B40A5BF97C283044640F54718062CA93B407DCC07043A0546407C9C69C2F6A73B40FC1A498270054640D13FC1C58AA63B40527FBDC2820546404DD6A88768A43B40276893C327054640A6EF3504C7A13B40A3923A014D0446407AABAE4335A13B4022179CC1DF0346407F8461C0929F3B40234DBC033C0346402A7288B8399D3B4021205F4205034640259694BBCF793B40FC1D8A027D024640CF4BC5C6BC6A3B40A7E67283A10246402577D84466663B40A2D11DC4CE024640FB95CE8767653B407784D38217034640A9F6E978CC4C3B40CCF10A444F0A464051DA1B7C614A3B40A7B05241450B4640FE2AC0779B473B40D1031F83150D4640D236FE4465473B40527FBDC2820D4640AD31E884D0453B407C992842EA104640A60BB1FA23403B40CBBE2B82FF0F464052B5DD04DF3C3B407F8461C0920F4640CC5D4BC807393B40FB78E8BB5B0F46404985B18520333B40A0A70183A40F4640FA42C879FF2F3B4027BD6F7CED0F4640FA980F08742A3B404D672783A3104640D2393FC5711C3B40A9A10DC006124640FFB0A54753093B4072361D01DC1246407B116DC7D4E93A40B119E0826C11464056BC9179E4E33A404337FB03E5104640266E15C440D73A40D4F19881CA0E4640257A19C572CB3A40FE0B0401320C4640FC36C478CDAB3A407AABAE433509464080812040867A3A404C3448C1530646400B0BEE073C703A407590D78349054640171230BABC693A402D41464085054640FE0B040132643A404D6A6803B0054640A6EF3504C7613A40A1A17F828B054640505260014C4D3A40787B1002F2034640D15B3CBCE7243A4079AEEFC341FE4540A5F8F884EC203A4052D7DAFB54FD4540FB230C03961C3A40787B1002F2FB45407B116DC7D4153A40A4C2D84290F945409F1F46088FF23940D1031F8315ED4540A60BB1FA23F03940A8A78FC01FEC4540249C16BCE8E339402829B000A6E64540B9C4910722E339405891D10149E6454052B81E85EBE13940A73B4F3C67E54540CE5147C7D5E0394082AB3C81B0E345404DD9E90775C93940A7B0524145DB4540D252793BC2C53940CCF10A444FDA4540AAF06778B3C23940D4EE5701BED94540E6B2D1393FBD3940745DF8C1F9D84540ED0BE8853BBB3940F1F3DF83D7D84540467D923B6CAE3940B1169F0260D84540A8FFACF9F19B3940F50EB743C3D445402A6F47382D88394051DA1B7C61D24540272F3201BF76394018B49080D1D14540151BF33AE270394098689082A7D0454071CADC7C236E394018EDF1423AD0454080812040866A39407C9C69C2F6CF4540FB95CE87676539404C70EA03C9CF45403B3AAE46766139400169FF03ACCF4540A301BC0512603940F60B76C3B6CF454073D87DC7F05C39407C9C69C2F6CF4540A1100187505939404D672783A3D04540A8FC6B79E556394050E3DEFC86D14540247D5A457F503940A9DDAF027CD345402881CD3978463940FCE4284014D64540286211C30E433940D4F19881CAD6454050E3DEFC86393940CBBE2B82FFD7454088F37002D30539401EF98381E7DA4540FA264D83A2E138407F4B00FE29DB454050C763062ACB3840D5AF743E3CDB4540CC5D4BC807B9384053793BC269DB45407F87A2409FB438407C6308008EDB45406C938AC6DAAF38401EFCC401F4DB45407B9FAA42039D38402638F581E4DF4540D82E6D382C9938405401F73C7FE045407D21E4BCFF8F3840A8AAD0402CE14540AC5626FC52873840AB5CA8FC6BE14540FA264D83A2813840A4C2D84290E1454028F38FBE497F38405473B9C150E1454029ED0DBE30753840AC5626FC52DF4540D5B2B5BE4870384079AEEFC341DE45402DD2C43BC0673840A8A78FC01FDC4540D63A71395E5D3840A4C2D84290D94540AB59677C5F5C384055F833BC59D9454028F04E3E3D5A3840FCE1E7BF07D94540D0D38041D25738407E18213CDAD84540C1559E40D85138406DACC43C2BD9454004763579CA4E3840D00F238447D9454083F755B950493840D00F238447D945402CD8463CD9413840D3F71A82E3D8454027F911BF62393840514F1F813FD845407BA2EBC20F323840A86E2EFEB6D745407F8461C0922F384051853FC39BD745402B69C537142E3840520ABABDA4D745409EB30584D62738404913EF004FD845405BD1E638B71D3840CB85CABF96D9454078B7B24467113840ABCE6A813DDC45402CD505BCCCFC3740266E15C440DF4540D6AC33BE2FC63740543A58FFE7E445407AABAE4335A137405531957EC2E545402CD505BCCC9C37407E1B62BCE6E54540D925AAB7069A3740A7AD11C138E6454055C2137AFD91374028F38FBE49E745403E0801F9128A37403A596ABDDFE8454018EAB0C22D873740438CD7BCAAE945404DA3C9C5188437409259BDC3EDEA45404417D4B7CC813740657094BC3AEB45405055A18158723740253B3602F1EC4540A3957B81596D3740103FFF3D78ED4540FD6662BA106B37404E64E60297ED4540ABEAE5779A483740543A58FFE7EC4540655419C6DD443740B0AD9FFEB3EC454006D671FC5041374082751C3F54EC454016FC36C47839374020B75F3E59EB454056B950F9D7323740A6B915C26AEA45402463B5F97F293740944DB9C2BBE845405531957EC2253740D0D38041D2E74540ABE7A4F78D233740A5BC564277E74540FD1186014B1237403C4D66BCADE64540CFF57D38481037403C4D66BCADE64540FB20CB8289F73640AA656B7D91E845407A1A3048FAE43640D482177D05EB4540A301BC0512E03640D3F4D901D7EB45407B9FAA4203DD3640FB230C0396EC4540B7442E3883DB3640D28E1B7E37ED45403D80457EFDD83640B3075A8121EF45401F2C634337D73640E04BE141B3F14540B894F3C5DED7364079758E01D9F345407AABAE4335E13640FE47A643A7FD4540FC1D8A027DE23640AB5FE97C78FE4540AD4D637B2DE836405437177FDBFF454026FF93BF7BEB3640D097DEFE5C004640C1C41F459DF536404A438D4292014640257A19C572FB36407D5D86FF740146402CD505BCCCFC364001C11C3D7E014640CD57C9C7EEFE3640A774B0FECF014640D593F947DF0037406473D53C47024640D63730B951083740D1CDFE40B90546407E1EA33CF30A3740266E15C440074640FE99417C600B3740FD4D2844C00746407F15E0BBCD0B37407E18213CDA084640FC8F4C874E0B3740D4EE5701BE094640D3C1FA3F870937405534D6FECE0A4640A968ACFD9D053740D57954FCDF0B4640A5F8F884EC003740A7ECF483BA0C464068976F7D58FF36402D776682E10C4640ABE7A4F78DF336407E5182FE420D464055C2137AFDF13640A6B6D4415E0D46402BDEC83CF2EB36407E1B62BCE60D4640D63730B951E8364000C45DBD8A0E4640D53DB2B96AB236407F4B00FE291B4640A86E2EFEB6AF364081423D7D041C46408A592F8672AE364073309B00C31C464051C1E10511B13640A774B0FECF214640A5F8F884ECB03640D0D03FC1C52246407D21E4BCFFAF36407C6308008E234640FD1186014BAE36407AA86DC32824464000917EFB3AAC364051888043A8244640FC17080264A8364029ED0DBE30254640D82B2CB81FA43640FE47A643A7254640643A747ADE9D36401C08C90226264640FB20CB82899736407C60C77F81264640A9DDAF027C9336405340DAFF002746407AABAE4335913640A5BC564277274640A7ECF483BA8C364055F833BC592946404DD9E90775893640286211C30E2B4640A7E9B303AE873640FE0B0401322C46405628D2FD9C76364029266F8099394640B62BF4C132763640DBC1887D023A4640AE6186C613753640E78D93C2BC3B4640AE6186C613753640494C50C3B73C46405531957EC2753640D1CDFE40B93D4640D13FC1C58A763640295FD042023E4640000341800C9536407E1B62BCE64546407AA52C431C973640FD1186014B46464051BEA085049C3640FA298E03AF464640D828EB37139F364000C45DBD8A46464052B81E85EBA13640A7AD11C1384646404FCDE50643A53640527FBDC2824546407E1EA33CF3AA3640A77A32FFE8434640D63A71395EAD3640A9DDAF027C4346403B56293DD3AF364038656EBE11434640ACC5A70018B3364063B83A00E242464024809BC58BB53640286211C30E434640D7A6B1BD16BC364052431B800D444640D731AEB838BE36407D5A457F68444640D6A9F23D23C13640D1031F8315454640342E1C08C9C23640944A7842AF4546404AB8904770C3364040A4DFBE0E464640B9196EC0E7C3364062855B3E92464640EFE53E390AC43640CEE2C5C21047464078F01307D0C33640462234828D474640A38FF98040C33640F27B9BFEEC4746408109DCBA9BB73640D388997D1E4D46407F129F3BC1B636402A1A6B7F674D46405531957EC2B53640FE47A643A74D464051BEA08504AC3640556D37C1374F4640037CB779E3A836407E5704FF5B4F46407A1A3048FAA43640D009A1832E4F464028F38FBE499F3640556D37C1374F4640D7A6B1BD169C3640D4BB783F6E4F46405534D6FECE9A3640520ABABDA44F4640A7E9B303AE973640FC17080264504640286211C30E933640D4EE5701BE514640A4FE7A85058B364056F5F23B4D544640000341800C8536405376FA415D5646407BA2EBC20F823640520ABABDA457464084F1D3B8377F3640295C8FC2F5584640FC1A4982707D3640A9A10DC0065A4640A96BED7DAA7A36407C992842EA5A4640514F1F813F783640FD14C781575B464029ED0DBE3075364000C79E3D975B4640A86E2EFEB66F364054FEB5BC725B46404DDC2A88816E36402B14E97E4E5B4640D2393FC5716C36407C992842EA5A46407BA2EBC20F523640530438BD8B554640D5B2B5BE485036407B9FAA42035546405340DAFF004F3640FE0B040132544640D1CDFE40B94D3640A96BED7DAA52464000917EFB3A4C364027F911BF62514640A4FB3905F9453640D4B5F63E554D4640276BD443344236407C992842EA4A46407A17EFC7ED2F3640556D37C1373F4640505260014C2D3640FFCC203EB03D4640D5AF743E3C2B36407E5182FE423D4640FD9FC37C79253640D4B5F63E553D4640A5F8F884EC203640A968ACFD9D3D4640FC8F4C874E1B3640508E0244C13E4640AC5626FC52173640FED2A23EC93F4640A968ACFD9D153640FC17080264404640FF058200190A36405628D2FD9C46464052465C001A0936407E5704FF5B474640A8E0F08288083640514F1F813F484640E8A38CB8000836401FBDE13E724B4640D540F3397707364081423D7D044C46402AE109BDFE003640527C7C4276504640FB928D075B003640F92F1004C8504640A9DA6E826FFE354055F833BC59514640276893C327FD3540D3C1FA3F8751464057B3CEF8BEE83540FBE769C020534640ABEAE5779AC83540A7ECF483BA5446400188BB7A15BD3540D7A6B1BD165446405534D6FECEBA35407F15E0BBCD534640D0D38041D2A73540D7A6B1BD1654464079AEEFC341A63540FE0B0401325446407E9065C1C4A33540FB230C03965446402CD8463CD9A13540D388997D1E554640D4BB783F6E9F35402AE44A3D0B564640FD1186014B9E3540D576137CD3564640FC1A4982709D354029EACC3D24584640D63A71395E9D35407B6649809A584640D63A71395E9D3540D00F23844759464056B60F79CB9D35407C992842EA5A46404BC8073D9B9D35407D96E7C1DD5B4640A96BED7DAA9A3540A7E9B303AE5F46407E8AE3C0AB993540527C7C4276604640D63730B951983540D6A9F23D236146405628D2FD9C963540508BC1C3B4614640F92F1004C8903540D0D03FC1C5624640A4FE7A85058B3540FE99417C6063464079AEEFC341863540D2C77C40A0634640D3C1FA3F877935407C6308008E634640D82B2CB81F74354053793BC269634640D175E107E767354085D21742CE6346404162BB7B80663540787B1002F2634640CA367007EA64354040683D7C996446400A2DEBFEB15C35403677F4BF5C69464055BFD2F9F05C3540185A9D9CA16A4640D1CDFE40B95D35402829B000A66E4640FA9B5088805F3540D009A1832E6F4640AB5FE97C786635407D21E4BCFF6F46404ED026874F6A3540A7B393C151704640A6EF3504C77135407EC9C6832D704640AB5FE97C78763540AA9B8BBFED6F46402383DC45987A3540D200DE0209704640AA656B7D918035407B6649809A704640D2393FC5718C35402CD8463CD971464082035ABA828D3540A9A10DC006724640FD1186014B8E35405055A181587246405340DAFF008F3540FD4AE7C3B372464028F38FBE498F3540A7B052414573464028F38FBE498F354056F5F23B4D744640A9DA6E826F8E3540A8E3310395754640276893C3278D3540D4F19881CA76464051BEA085048C3540FB20CB8289774640FA980F08748A354029EACC3D247846407AA52C431C8735407E18213CDA7846400473F4F8BD79354029E78BBD177B4640A8E0F08288783540A7B05241457B464024809BC58B75354054FEB5BC727B4640A5F8F884EC7035407C992842EA7A4640295FD042026E354029E78BBD177B4640D1CABDC0AC68354056F5F23B4D7C4640D0D38041D2673540FB230C03967C4640D5B2B5BE486035407F8461C0927F46405340DAFF005F3540D5B2B5BE48804640027FF8F9EF5D354080457EFD10814640295FD042025E3540253E7782FD814640D2C43BC0935E3540D4B837BF61824640D4BB783F6E5F3540A96BED7DAA824640A6EF3504C7613540D2FD9C82FC824640AB5CA8FC6B713540A777F17EDC864640D734EF3845833540FED2A23EC98F4640D2C77C40A0833540514F1F813F904640D82B2CB81F843540FDD8243FE2914640A77A32FFE88335407C992842EA924640A9DDAF027C833540FD14C78157934640D0420246977B35402920ED7F8097464053E8BCC62E793540DD5D6743FE974640A96BED7DAA6A3540A9DDAF027C9B4640A7E9B303AE673540562B137EA99B4640533D997FF4593540D57954FCDF9B46407F129F3BC14635402A1A6B7F679D4640D3BEB9BF7A44354027327381CB9D4640D44334BA830C35405401F73C7FA84640FB230C0396FC34405470784144AC4640CD57C9C7EECE3440505260014CBD4640FC8F4C874ECB34402AE109BDFEC0464022895E46B1C43440D1031F8315CD464084F4143944C43440FCE4284014CE464027F6D03E56C43440266E15C440CF464022895E46B1C43440A86E2EFEB6CF46405531957EC2C53440A8E0F08288D04640D0D38041D2C7344029266F8099D146407F15E0BBCDCB3440FBE769C020D34640D44334BA83CC344052431B800DD44640295FD04202CE3440266E15C440DF4640027FF8F9EFCD3440D47C957CECE04640276893C327CD3440A774B0FECFE14640F92CCF83BBCB34402A1DACFF73E246400473F4F8BDC934407E1EA33CF3E24640FC17080264C83440286211C30EE346402BDB87BCE5C63440D482177D05E346407E1B62BCE6C534405534D6FECEE24640D3BEB9BF7AC43440D106600322E24640D2C77C40A0C33440FE0E45813EE1464055C2137AFDC13440D200DE0209E04640D4BB783F6EBF3440D009A1832EDF46400188BB7A15BD3440A777F17EDCDE464028F04E3E3DBA34407E8D2441B8DE464057B3CEF8BEB83440D4F19881CADE46405628D2FD9CB63440556D37C137DF46405531957EC2B534402920ED7F80DF4640D925AAB706AA3440AB9509BFD4E5464052465C001AA934402829B000A6E64640AD4D637B2DA83440D38558FD11E84640AD4D637B2DA834405055A18158EA4640A7E9B303AEA73440FFCF61BEBCEA4640D540F339779734402A1DACFF73F24640FE0B040132943440D2C77C40A0F346405437177FDB8F3440D3BEB9BF7AF44640562B137EA98B34402CD505BCCCF44640A6F27684D3863440A8716F7EC3F44640CD5A0A48FB83344082397AFCDEF44640FA264D83A28134407DCC07043AF54640F92F1004C860344029ED0DBE30FD4640FD1186014B5E3440FCE4284014FE4640AB59677C5F5C3440FF08C38025FF46407B14AE47E15A3440FC170802640047404ED026874F5A34405473B9C15001474080812040865A3440D482177D0503474028F04E3E3D5A3440A9DDAF027C034740AC53E57B4652344029EACC3D240847404DDC2A88814E3440D4EE5701BE0947409A780778D24234407A6CCB80B30E474057B08D78B2433440D1CABDC0AC104740D4B5F63E55453440FDD8243FE2114740A6F27684D34634408081204086124740CC5D4BC8074934405534D6FECE1247407AA52C431C5734407D5A457F6814474086C954C1A87C3440D009A1832E174740CC5D4BC80789344052499D80261647404FCAA48636903440D388997D1E15474029ED0DBE30953440D3F4D901D7134740D2C43BC0939E34407D93A641D11047407A17EFC7ED9F3440D1CABDC0AC104740027FF8F9EFAD3440276BD443341247400A9DD7D825B234406E4E250340134740CE5147C7D5B4344052431B800D1447408200193A76B8344029ED0DBE30154740A774B0FECFB934407E1B62BCE6154740E7A90EB919BA34402D3E05C078164740'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('MD','MD','MDA','498','Republic of Moldova','3288','3876661','150','151','28.599','47.193','0106000020E610000001000000010300000001000000A901000076C6F7C5A51E3C402AC93A1C5D6D4740C806D2C5A61D3C40FA264D83A2714740D0F23CB83B1B3C4027327381CB754740CF488446B0153C40CEA96400A87C4740F73B1405FA143C404CC2853C827D47404DD6A88768143C40CCB8A981E67D4740276BD44334123C402499D53BDC7E4740D1CABDC0AC083C40253E7782FD81474073DBBE47FD013C40CDE847C329834740CC28965B5AFD3B40AEBCE47FF283474080290307B4F43B4089B48D3F51854740FA264D83A2F13B404B3D0B42798547400B09185DDEF03B407CBABA63B18547404D672783A3F03B40A3CEDC43C2854740F25CDF8783DC3B402026E1421E8D4740267156444DCC3B40F8FF71C284934740FE0E45813EC93B40F511F8C3CF99474021956247E3C83B40768D96033D9A474023A298BC01BE3B40FA264D83A2A1474079CDAB3AABB93B407AA86DC328A4474021AD31E884B83B40333509DE90A4474076DF313CF6B73B40F50EB743C3A44740A298BC0166B63B40F50EB743C3A447402098A3C7EFAD3B40F705F4C29DA54740F94ECC7A31A43B40494C50C3B7A647405055A18158A23B407590D78349A74740FC3905F9D9A03B40755AB741EDA74740A320787C7B933B402499D53BDCAE474051C1E10511793B40D9CD8C7E34BE4740CD57C9C7EE6E3B40F5D555815AC847400B9C6C03775C3B40FE2C9622F9CE4740249C16BCE8533B404E5E64027ED14740FD2D01F8A74C3B40A3923A014DD4474041D7BE805E4C3B4014AE47E17AD4474072E14048164C3B40CEA96400A8D44740AAF3A8F8BF473B40A3CB9BC3B5D8474076E272BC023D3B409F02603C83E44740C51EDAC70A363B401F2FA4C343EC4740A016838769333B40F1BDBF417BF34740C90391459A283B40A06B5F402FFE474029EACC3D24003B40A77A32FFE8134840CBF78C4468F43A407A6F0C01C0174840A016838769D33A40A38FF980401F48405340DAFF00CF3A4027BD6F7CED1F4840A20DC00644B43A40D673D2FBC62148409F1F46088FA23A40B2DAFCBFEA204840BB61DBA2CCA23A402A8C2D0439224840F9BA0CFFE9A23A402635B401D8224840FCA886FD9EA43A402CD505BCCC244840CDE506431DA63A4052499D8026264840FB20CB8289A73A40A777F17EDC264840F8C3CF7F0FB23A404E64E602972B4840F9BA0CFFE9B23A40A77A32FFE82B48404A7CEE04FBB33A4025C9737D1F2C484053CE177B2FB63A40D2C77C40A02B48402502D53F88B83A40D1066003222A4840CD57C9C7EECE3A40A7E67283A12A4840CDE847C329FB3A4027327381CB2D484022179CC1DF3B3B4026C632FD122F4840FBAE08FEB73E3B40D28E1B7E372F4840A20DC00644743B402250FD8348384840309E4143FF843B40DD240681953B484054C8957A168C3B40787B1002F23B4840AB5CA8FC6BC13B40D673D2FBC6394840D4B5F63E55C53B40D1949D7E50394840A9F6E978CCDC3B407C6308008E334840FBAE08FEB7DE3B40D2FD9C82FC324840FE9C82FC6CE03B4079758E01D93148402975C93846E23B40F60B76C3B62F4840A016838769E33B40CFDC43C2F72E4840A8716F7EC3E43B4079AEEFC3412E4840FCABC77DABE93B40A64412BD8C2C484076C6F7C5A5EE3B40514CDE00332B484074D2FBC6D7F23B40276BD443342A48404E61A5828AF63B4029266F80992948407E9065C1C4033C40A8E0F08288284840A5F8F884EC103C4029EACC3D24284840F73B1405FA143C40520ABABDA42748407E1B62BCE6153C407E5704FF5B274840FA298E03AF163C402541B8020A274840FC17080264183C407E1B62BCE625484057B3CEF8BE183C40253B3602F1244840A58636001B183C40514CDE0033234840CDE506431D163C4055F833BC59214840F73B1405FA143C407C2AA73D251F4840A304FD851E153C40A54A94BDA51E48402AE44A3D0B163C407D96E7C1DD1D4840A6F27684D3163C40A1A17F828B1D48402A6F47382D183C4023D8B8FE5D1D4840F644D7851F343C405307793D981A4840A67D737FF5383C40FAF02C41461A4840FC36C478CD3B3C4051DA1B7C611A484073D87DC7F03C3C405182FE428F1A484081069B3A8F423C404D2EC6C03A1C4840FE0E45813E493C402AE44A3D0B1E4840AA622AFD844B3C40F8FC3042781E4840CFDC43C2F7563C407AA52C431C1F4840FC17080264583C40D009A1832E1F48407C2766BD185A3C407AA52C431C1F484079B130444E5B3C40A777F17EDC1E48407B9FAA42035D3C4079AEEFC3411E4840250516C0945D3C407E1B62BCE61D48404DDC2A88815E3C404E250340151D4840FCA5457D925F3C40CCB22781CD1B4840A86E2EFEB65F3C40D0D03FC1C51A4840A777F17EDC5E3C40CF6740BD19194840505260014C5D3C404C70EA03C917484026FF93BF7B633C4027C0B0FCF91448404C70EA03C96F3C40A96BED7DAA124840247D5A457F803C40A8AAD0402C114840276893C3278D3C40A64412BD8C144840FCA5457D928F3C40D0D6C1C1DE1448407AABAE4335913C40D0D6C1C1DE14484050E09D7C7AA43C40A3C85A43A9134840A9F6E978CCBC3C4052103CBEBD11484082035ABA82CD3C402250FD83481048405437177FDBCF3C40D0D38041D20F4840514CDE0033D33C40A4C519C39C0E4840543A58FFE7D43C40FD9FC37C790D48409AB1683A3BE13C40C216BB7D560148404E5E64027EE13C407AABAE4335014840A9F92AF9D8E13C40552E54FEB500484079CA6ABA9EE43C40481630815BFF4740F75AD07B63E83C409C8C2AC3B8FD4740A2B437F8C2F43C40F3E49A0299F947401C446B459BF73C40F2ED5D83BEF8474079CDAB3AABF93C401B0E4B033FF84740F65D11FC6FFD3C4099654F029BF74740A7E67283A1023D40481630815BF74740F8325184D4053D40C4B2994352F74740D05E7D3CF4093D404301DBC188F7474072E14048160C3D40CBBE2B82FFF747407D96E7C1DD0D3D40F0C000C287F84740A514747B490F3D401E32E54350F9474078B471C45A103D406F4BE48233FA4740D0ECBAB722113D40A06EA0C03BFB4740F25F200890113D40C4B5DAC35EFC47407EACE0B721123D40C8940F41D5FC474074D2FBC6D7123D40C5AC174339FD474079CA6ABA9E143D40F1F09E03CBFD4740F450DB8651183D40A06B5F402FFE4740FD2D01F8A71C3D401E3526C45CFE4740D0D03FC1C5223D401E3526C45CFE4740A417B5FB55243D40726C3D4338FE474079AEEFC341263D404628B682A6FD4740CFDC43C2F7263D409F7422C154FD4740A3923A014D2C3D404CC5C6BC8EFA4740250516C0942D3D404434BA83D8F94740A6EF3504C7413D40A2D11DC4CEE247407EACE0B721423D409F77634161E247407BA2EBC20F423D4079758E01D9E14740FD304278B4413D40A3957B8159E14740C8091346B3323D401E3526C45CCE4740A3957B8159313D40250516C094CD4740259694BBCF293D40D0D03FC1C5CA47404888F2052D283D40D106600322CA474052431B800D243D401FF64201DBC74740C8091346B3223D4073637AC212C74740FA264D83A2213D40234A7B832FC64740FA264D83A2213D407B698A00A7C54740CFD90242EB213D40A7ECF483BAC447409F1F46088F223D409EB30584D6C34740D2C77C40A0233D404CC5C6BC8EC2474024809BC58B253D40527C7C4276C04740A20A7F86372F3D40A3CB9BC3B5B847404C70EA03C92F3D407172BF4351B84740469737876B313D40F60B76C3B6B7474077DCF0BBE9323D404A438D4292B74740A417B5FB55343D40A0A70183A4B74740F16261889C363D40CBBE2B82FFB74740F75AD07B63383D404D31074147B94740228C9FC6BD393D407460394206BA4740506EDBF7A83B3D404A404CC285BA4740C70F9546CC3C3D407A6CCB80B3BA4740A11342075D3E3D404C6DA983BCBA4740A3B1F677B63F3D405182FE428FBA4740D04543C6A3403D40FAF02C4146BA4740FD2D01F8A74C3D40778192020BB64740A5F5B704E05B3D404B3ACAC16CB04740257497C459613D4027327381CBAD4740FD304278B4613D40A6B6D4415EAD474023111AC1C6613D407593180456AC47404D672783A3603D40CAC4AD8218AA4740F92F1004C8603D40FA264D83A2A94740A48CB80034623D404B3ACAC16CA84740D0D38041D2673D40A3CEDC43C2A547402383DC45986A3D40D15B3CBCE7A44740C806D2C5A66D3D407F87A2409FA447404F58E20165773D40CAC16C020CA54740A0A4C002987A3D407B698A00A7A5474079B130444E7B3D40778192020BA64740240ED940BA7C3D409E7AA4C16DA747409F1C0588827D3D40A8AAD0402CA94740F65D11FC6F7D3D407A6CCB80B3AA4740F54A5986387E3D40F92CCF83BBAB4740F6419605137F3D401D0247020DAC47404FCAA48636803D404D2EC6C03AAC47404DD6A88768843D40F9F6AE415FAC47407D96E7C1DD8D3D402444F98216AC474078B471C45A903D40A3C85A43A9AB4740276BD44334923D407784D38217AB4740F94ECC7A31943D407BA2EBC20FAA47407DAF21382E973D40F60B76C3B6A74740A323B9FC87983D40295FD04202A6474079CDAB3AAB993D40CCB22781CDA34740228C9FC6BD993D40A2D11DC4CEA2474079CDAB3AAB993D40FAF02C4146A24740C8091346B3923D404A404CC285924740478E740646923D40A9A10DC00692474073D53C47E4973D40234DBC033C834740F3599E0777973D407A6CCB80B38247407C992842EA923D40FA264D83A279474074D2FBC6D7923D401D05888219794740FD14C78157933D40A3CB9BC3B5784740C70F9546CCBC3D40D05E7D3CF4714740CEDF844204DC3D402829B000A66E4740A31D37FC6EDE3D4079AEEFC3416E4740257497C459E13D40FC1A4982706D47404D672783A3F03D4052465C001A694740F660527C7CF23D40A8E0F08288684740514CDE0033F33D40CCEB884336684740A019C40776F83D40755AB741ED5F47404A7F2F8507F93D4023A298BC015E47401F9E25C808F83D40FA264D83A2494740240B98C0ADF73D4024473A0323494740469A780778F63D40A7B393C15148474044A33B889DF53D40CBBE2B82FF474740CD0182397AF43D40D0D38041D247474022179CC1DFEB3D40240B98C0AD4747402383DC4598EA3D404A438D42924747405682C5E1CCE73D401CB4571F0F47474078B7B24467E53D40A4C519C39C46474078B7B24467E53D40A7ECF483BA444740C51EDAC70AE63D409EB30584D64347404888F2052DE83D402635B401D8424740D1CDFE40B9ED3D40D1CABDC0AC404740A6EF3504C7013E40F5DBD781733A4740CC5D4BC807093E40A3CB9BC3B5384740FC3905F9D9103E40F60B76C3B63747407DAF21382E173E40D061BEBC00374740A51133FB3C1A3E40CFDC43C2F7364740C61858C7F11B3E402499D53BDC364740F92CCF83BB1F3E40B952CF825036474057E9EE3A1B223E40B95510035D354740C712D6C6D8213E404F5B238271344740CA349A5C8C213E408F17D2E121344740A5F8F884EC203E40A320787C7B334740A514747B491F3E40202922C32A3247402098A3C7EF1D3E40F8F9EFC16B3147402383DC45981A3E40CD3AE3FBE2304740D0D38041D2173E40A3CB9BC3B53047404F5B2382710C3E40A19E3E027F304740F641960513FF3D40A19E3E027F304740F3599E0777F73D407B6649809A3047404982700514EE3D4052465C001A3147404E64E60297EB3D40CD3AE3FBE2304740228C9FC6BDE93D40A19E3E027F30474074CFBA46CBDD3D4075931804562C4740F44D9A0645D33D404E2B85402E2F47404694F6065FBC3D404D672783A3384740506EDBF7A8BB3D401B0E4B033F384740CD04C3B986A93D40F702B34291304740F8325184D4A53D40F4DE1802802F4740D2C77C40A0A33D40C9C7EE02252F47407BBE66B96CA03D40A38FF980402F4740CD57C9C7EE9E3D404F58E201652F4740D0F23CB83B9B3D40CBBE2B82FF2F4740CC5D4BC807993D404DBF44BC75304740F838D384ED7F3D40F9F36DC15237474023A298BC017E3D40F5D555815A38474077D9AF3BDD7D3D40CCB56801DA384740CAFD0E45817E3D40CFD90242EB394740A6EF3504C7813D40F4E159828C3C47407BA2EBC20F823D402026E1421E3D474052B81E85EB813D40250516C0943D4740F25F200890813D4023A298BC013E4740FC3905F9D9803D401E3526C45C3E4740A1BAB9F8DB7E3D402499D53BDC3E4740F4531C075E7D3D40D061BEBC003F474077BAF3C4737A3D40CFDC43C2F73E4740259694BBCF593D40F7C95180283C4740C806D2C5A64D3D404A438D4292374740FD1186014B4E3D40494C50C3B7364740F94B8BFA244F3D40F5D896016735474051DD5CFC6D4F3D404F5B238271344740F94B8BFA244F3D4022179CC1DF3347404DDC2A88814E3D40A320787C7B334740C806D2C5A64D3D40CDE847C32933474076E272BC023D3D40C9C7EE02252F47404F779E78CE3A3D409FB0C403CA2E4740A41AF67B62393D40508E0244C12E4740469A780778363D401EFF0582002F4740CD0182397A343D40F4DE1802802F4740C90050C58D333D407172BF4351304740A016838769333D404852D2C3D0304740219221C7D6333D401E32E54350314740CD0182397A343D40508BC1C3B4314740F8325184D4353D40F5DBD78173324740D0D38041D2373D404E64E60297334740CD04C3B986393D40D0D6C1C1DE3447404E8061F9F3393D40A6B6D4415E35474077BAF3C4733A3D40778192020B3E474076C3B64599393D40FA7E6ABC74414740F54718062C393D40755776C1E04247404888F2052D383D40C9CA2F8331444740FA5FAE450B343D40EAAEEC82C1454740F25CDF87832C3D40D1031F8315454740A4FE7A85050B3D407A6F0C01C03F474021956247E3083D404F58E201653F4740CC07043A93FE3C40FAEDEBC0393D4740F92CCF83BBFB3C409E7DE5417A3C47404888F2052DF83C404C378941603B47407AC7293A92EF3C404C70EA03C937474076C6F7C5A5EE3C4023145B41D3364740CC07043A93EE3C40A3CEDC43C2354740514CDE0033F33C40CAC16C020C25474050E09D7C7A043D4075931804561C4740F16261889C063D404C378941601B4740CE548847E2093D409FAD8383BD19474051DA1B7C610A3D401E32E543501947407AC4E8B9850A3D404852D2C3D01847404ED026874F0A3D401B0E4B033F184740F73E558506FA3C407E8AE3C0AB01474077D66EBBD0F83C40CCB56801DA0047401F9E25C808F83C40A8E0F0828800474079CA6ABA9EF43C402123A0C21100474024809BC58BE53C409FB0C403CAFE4640A417B5FB55D43C40FAEDEBC039FD46407EA99F3715CD3C409E7DE5417AFC4640CF488446B0C53C40282CF180B2FB4640F3565D876AC23C40FBE769C020FB4640D13C80457EC13C40755776C1E0FA4640FC3905F9D9C03C404A404CC285FA46404E7ADFF8DABF3C40FA264D83A2F94640CBF44BC45BBF3C404DBF44BC75F84640CEFE40B96DBF3C407AFD497CEEF64640FB928D075BC03C40CDE506431DF64640257497C459C13C407A724D81CCF44640A417B5FB55C43C402638F581E4EF4640CE5147C7D5C43C40CFDC43C2F7EE46402593533BC3C43C40A31D37FC6EEE4640514CDE0033C33C409E7DE5417AEC464078B471C45AB03C40F9F6AE415FE44640218FE046CAAE3C40F92CCF83BBE34640D0D6C1C1DEAC3C40234DBC033CE34640FC36C478CDAB3C4022A5D93C0EE34640240B98C0ADA73C40755776C1E0E246404F779E78CE9A3C40A0A4C00298E24640F450DB8651983C409F77634161E2464078B7B24467953C407E8AE3C0ABE1464079AEEFC341863C4021205F4205DB4640250516C0947D3C40527FBDC282D546404A95287B4B7D3C402026E1421ED5464023A298BC017E3C40240ED940BAD44640219221C7D6833C40F2EA1C03B2D34640D13FC1C58A863C40755776C1E0D24640266E15C440873C404A404CC285D24640AAF3A8F8BF873C40202922C32AD24640D0D38041D2873C4052431B800DC446402881CD3978863C40F6083543AAC24640F8325184D4853C40FAF02C4146C24640286211C30E833C4050E3DEFC86C14640FC3905F9D9803C40A8AAD0402CC146409CC24A05157D3C40CCB56801DAC04640223317B83C7A3C407D93A641D1C04640240B98C0AD673C40F8F9EFC16BC146404E7D2079E7643C4029266F8099C1464074CFBA46CB5D3C40FAF02C4146C24640A019C40776583C40CBBBEA01F3C24640A702EE79FE503C40F8FF71C284C3464052D158FB3B4B3C404DBC033C69C34640D1CABDC0AC483C40234DBC033CC346402577D84466463C40CBBBEA01F3C246407BA2EBC20F423C40A48CB80034C24640A301BC0512403C40508BC1C3B4C14640A11342075D3E3C4024473A0323C1464073D87DC7F03C3C404B3ACAC16CC04640F73E5585063A3C40A298BC0166BE46404791B58652373C404E64E60297BB4640CFDC43C2F7363C4022A5D93C0EBB464065DF15C1FF363C406939D0436DB94640F9484A7A18363C40F148BC3C9DB94640505260014C2D3C402444F98216BC4640CEDF8442042C3C40F50EB743C3BC4640FD304278B4113C40F6083543AACA4640C51B9947FE203C404F58E20165CF46401C45D61A4A253C401B9C887E6DCF4640240B98C0AD273C407A6F0C01C0CF4640C90391459A283C40CBBE2B82FFCF4640F8510DFB3D293C40F75AD07B63D0464076C3B64599293C40CD3AE3FBE2D04640268DD13AAA2A3C40CCEEC9C342D546404C6DA983BC2A3C4027327381CBD54640A51133FB3C2A3C40249C16BCE8DB4640F9484A7A182A3C40F9F6AE415FDC4640CE548847E2293C40D0D6C1C1DEDC4640218FE046CA1E3C4023A298BC01F64640257A19C5721B3C40A3C85A43A9FB4640390EBC5AEE183C40B22E6EA301FE4640F450DB8651183C40D2C43BC093FE4640C80C54C6BF173C407AFD497CEEFE4640A4FB3905F9153C40A8E0F08288004740268A90BA9D153C404E5E64027E0147404F58E20165173C40508BC1C3B4094740774EB340BB1B3C406BD619DF170D4740ABED26F8A61D3C407C9C69C2F60F4740C90050C58D233C40F75AD07B63184740F25F200890313C40FAF02C41462A4740A1BAB9F8DB3E3C407D96E7C1DD354740AF5E454607403C40C6A6954220374740D04543C6A3403C404C70EA03C937474022365838493F3C40A6B6D4415E4D47404E7CB5A3383F3C406B9A779CA24D47404A79AD84EE3E3C4023145B41D34E474022179CC1DF3B3C4052D7DAFB54554740F90FE9B7AF3B3C402E8CF4A2765547404F779E78CE3A3C40FCE4284014564740240B98C0AD373C40F9F36DC152574740F94ECC7A31343C40F8F9EFC16B5947401B47ACC5A72C3C40FA298E03AF5E4740D1CDFE40B91D3C404C6DA983BC6A4740F4531C075E1D3C40CDE847C3296B4740F4531C075E1D3C40F2EA1C03B26B474049827005141E3C40240ED940BA6C474076C6F7C5A51E3C402AC93A1C5D6D4740'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('SI','SI','SVN','705','Slovenia','2014','1999425','150','39','14.827','46.124','0106000020E6100000010000000103000000010000002D010000B936548CF36F2B40605B3FFD674347407632384A5E8D2B405055A1815842474004013274ECB02B405182FE428F424740A86E2EFEB6DF2B40A9A10DC006424740DC9BDF30D1282C40FA298E03AF3E47409F91088D602B2C4000C45DBD8A3E474058AA0B7899392C40A8E33103953D4740DBA7E331033D2C407B9FAA42033D4740AA656B7D91402C40D57954FCDF3B474082FDD7B969432C40A96BED7DAA3A4740A27F828B154D2C407D93A641D13847402D6002B7EE4E2C40AA656B7D91384740FA264D83A2512C40FE9C82FC6C384740A8716F7EC3F42C40FFCC203EB035474054C554FA09172D407AA86DC328344740DF8C9AAF929F2D40D00F238447414740D6A9F23D23A12D40FA264D83A24147402577D84466A62D40505260014C454740C9E7154F3DAA2D40A8E0F08288484740AA622AFD84AB2D40A4C2D842904947402383DC4598BA2D40D6AC33BE2F4E4740D1CDFE40B9BD2D40D576137CD34E47407638BA4A77172E40A9DDAF027C534740CBD8D0CDFE202E4054FEB5BC725347401D1F2DCE18262E402711E15F0453474008E6E8F17B332E40FCDEA63FFB5347407E1B62BCE6352E40A8A78FC01F544740313F373465472E40A8A78FC01F5447407A17EFC7EDCF2E40AA622AFD84534740D3BEB9BF7A342F402638F581E4574740DBA7E331039D2F40FCDEA63FFB5B4740D4B837BF61AA2F4001BEDBBC715C4740286211C30EB32F40FB230C03965C4740FB230C0396BC2F4029232E008D5C47402D5DC136E2F92F4029EACC3D24604740A56ABB09BEF92F40A8AAD0402C6147404CE2AC889AF82F402CD8463CD96947404CE2AC889AF82F40D4B837BF616A4740021077F52AFA2F40FD4AE7C3B36A474006F52D73BAFC2F402635B401D86A47405797530262023040D89DEE3CF16A47407F87A2409F1C3040AC5626FC526F47407C992842EA223040FCE42840146E474052431B800D2430407D96E7C1DD6D47404FCDE506432530407D96E7C1DD6D47407B9FAA42032D304055FB743C666E4740FD1186014B2E304000C45DBD8A6E474051C1E10511313040AC5626FC526F4740FF058200193A3040286552431B704740FE99417C603B30407F4E417E36704740000341800C453040AA9B8BBFED6F474029E78BBD174B3040A5BC5642776F4740A8E33103954D3040A9A44E40136F4740ABEAE5779A5830407D5A457F686C474083F755B950593040D7A6B1BD166C47400473F4F8BD593040562B137EA96B47400473F4F8BD593040FBE769C0206B4740FF9600FC535630407F8461C092674740FA264D83A251304055FB743C66664740552E54FEB55030408048BF7D1D664740FB928D075B503040A968ACFD9D654740FB928D075B50304029232E008D6447400282397AFC523040D47C957CEC604740ABE7A4F78D533040AA656B7D91604740D5AF743E3C5B304027F6D03E565C474051BEA085045C304081423D7D045C4740FC1A4982705D304052431B800D5C4740E945ED7E15603040A5BF97C2835C47402DCF83BBB3623040A774B0FECF594740ABEAE5779A68304027F6D03E56544740FB20CB82898730405473B9C150414740D63730B9518830402AE109BDFE4047407427D87F9D9B3040239F573CF53C4740CADDE7F8689930403F74417DCB3C4740CF488446B095304029232E008D3C474081069B3A8F923040FED5E3BED53C47401A1A4F04718E3040087250C24C3D474064213A048E843040C89A9141EE3E4740FA9B5088807F30407EC9C6832D4047404FE61F7D937E3040FE9C82FC6C404740CD57C9C7EE7E3040295C8FC2F540474083FA96395D7E304055F833BC59414740D236FE44657730405307793D9842474050C422861D763040D0D03FC1C54247405055A18158623040FB230C03964447407E1B62BCE655304027F6D03E56444740E0D91EBDE14A3040F59CF4BEF1434740D3BEB9BF7A4430402CD8463CD9414740008BFCFA21423040D3F71A82E3404740683C11C4794030404298DBBDDC3F47405437177FDB3F3040508E0244C13E47400000000000403040A7AD11C1383E4740D82B2CB81F443040FFCC203EB0354740037976F9D623304052431B800D344740D0D03FC1C5223040D57954FCDF33474044FB58C16F13304064EB19C2313147402B6C06B820133040A7E9B303AE2F47400282397AFC12304000C45DBD8A2E4740037976F9D6133040276893C3272D474027F6D03E561430402CD505BCCC2C4740D4B5F63E55153040D0D03FC1C52A4740A8716F7EC3143040D4B837BF612A4740A77A32FFE8133040FF058200192A47404DD6A8876804304052499D80262647408200193A76982F407D96E7C1DD1D47402C634337FB632F40FED5E3BED51C47405AA148F7735A2F407B9FAA42031D4740CDC98B4CC0572F40AA9ECC3FFA1C474007EFAB72A1522F4051888043A81C474084F1D3B8374F2F40D7A6B1BD161C4740AB59677C5F4C2F40FE99417C601B474083F755B950392F40A6B6D4415E154740DD989EB0C4332F40FD4AE7C3B3124740286211C30E332F4028F04E3E3D124740AB5FE97C78362F40D576137CD30E4740AC53E57B46422F40FBE769C0200B47407B116DC7D4452F4080812040860A47405A9BC6F65A502F40D3F71A82E308474007EFAB72A1522F407B6649809A084740F92CCF83BB5B2F40FE9C82FC6C084740F4346090F4692F407E5704FF5B074740AB59677C5F6C2F40FF08C38025074740A376BF0AF06D2F40A777F17EDC0647402E573F36C96F2F402AE44A3D0B0647405A9BC6F65A702F40AA9ECC3FFA044740DCA16131EA722F4029EACC3D24F846404FCDE50643652F4052431B800DEC46404CDF6B088E632F407E9065C1C4EB46404FCAA48636502F4027F911BF62E94640AD50A4FB394D2F4055F833BC59E946407E1EA33CF34A2F407D5D86FF74E946407A1A3048FA442F40276BD44334EA4640F52EDE8FDB3F2F4029E78BBD17EB464007EC6AF2943D2F407F15E0BBCDEB46402E54FEB5BC3A2F40D3BEB9BF7AEC4640A27C410B09382F407F87A2409FEC4640DE8FDB2F9F342F407F87A2409FEC4640A86E2EFEB6FF2E40D2FD9C82FCEA46407E1EA33CF3AA2E40FF05820019E24640020D36751EA52E407D5D86FF74E14640FD1186014B9E2E40514F1F813FE046408109DCBA9B972E4055FB743C66DE46409E978A8D79952E40A8E3310395DD46404FCAA48636902E405055A18158DA46402E573F36C98F2E40D673D2FBC6D9464051C1E10511912E40D47C957CECD84640C8ED974F56942E407F4E417E36D84640F71F990E9D962E40D200DE0209D846400307B474059B2E40FE9C82FC6CD84640D9B0A6B2289C2E407D93A641D1D84640D9B0A6B2289C2E4055F833BC59D94640F92CCF83BB9B2E40A6B915C26ADA4640AF5DDA7058B22E4000C79E3D97DB46408109DCBA9BB72E4054FEB5BC72DB464050C763062ABB2E402635B401D8DA4640D9B0A6B228BC2E40FC1D8A027DDA4640314278B471BC2E40533D997FF4D9464056BABBCE86B42E40637C98BD6CD3464035ECF7C43A9D2E400266BE839FD04640081D740987962E40B72572C119CC4640B680D07AF89A2E40FE0E45813EC54640F92CCF83BB9B2E40FED5E3BED5C4464066BCADF4DA9C2E405F5E807D74C44640A376BF0AF08D2E40D5AF743E3CBB4640170D198F52592E40F981AB3C81B6464055F833BC59532E409E08E23C9CB64640A27F828B154D2E4028F38FBE49B7464022179CC1DF2F2E40C9CA2F8331BC464083FA96395D2E2E40A5BF97C283BC4640882F134548F52D40F8C3CF7F0FC046405055A18158D62D400E87A5811FBF4640DD989EB0C4D32D40FE47A643A7BD4640A661F88898D22D406891ED7C3FBD4640F92F1004C8D02D407B9FAA4203BD4640D731AEB838BA2D401F813FFCFCBB4640B3EE1F0BD1A92D406DE525FF93BB4640E8D9ACFA5CA52D4049A12C7C7DBB464056B950F9D7A22D40562B137EA9BB4640FC1D8A027D722D4081423D7D04C44640AA656B7D91402D40FFCC203EB0CD464050C763062A3B2D405340DAFF00CF4640AD4D637B2D382D40514F1F813FD04640A27C410B09382D40A774B0FECFD146404DD9E90775392D407B9FAA4203D54640782634492C392D40FE47A643A7D54640AD4D637B2D382D40295FD04202D64640F71F990E9D362D40FF9600FC53D64640A77A32FFE8332D40A9DA6E826FD64640313F373465272D40FFCC203EB0D54640A08B868C47212D40D388997D1ED546407D21E4BCFF1F2D40520DFB3DB1D4464052B81E85EB112D405376FA415DCE4640F6251B0FB6002D405628D2FD9CC64640DC9E20B1DDFD2C40D4B5F63E55C5464057B3CEF8BEF82C407F15E0BBCDC34640CCD24ECDE5D62C40266E15C440BF4640247D5A457FD02C405628D2FD9CBE4640AA622AFD84CB2C40FF9600FC53BE46402577D84466C62C408048BF7D1DBE4640D8B628B341462C40FED5E3BED5BC4640DC9E20B1DDFD2B407D5A457F68BC46405AA148F773FA2B40D5AF743E3CBB4640782634492CF92B40AB984A3FE1BA4640AB5FE97C78F62B40FFCF61BEBCBA464006F2ECF2ADE72B402A1DACFF73BA46405A9BC6F65AD02B40A9A10DC006BA4640B05758703F682B407E18213CDAB84640304B3B35975B2B40295C8FC2F5B84640CBDB114E0B562B40D6A9F23D23B94640F722DA8EA94B2B40D4EE5701BEB94640313F373465472B40FF05820019BA4640CBD8D0CDFE402B40FFCF61BEBCBA464054C554FA09372B40FCDEA63FFBBB4640F92F1004C8302B40276893C327BD46405778978BF82E2B4068CA4E3FA8BD464056B60F79CB2D2B40D28BDAFD2AC24640F4311F10E8542B40527FBDC282C54640AF5A99F04B7D2B407D96E7C1DDC54640A86E2EFEB67F2B40295FD04202C64640D6A9F23D23812B405376FA415DC64640800F5EBBB4812B40A777F17EDCC646407920B248136F2B4056F5F23B4DCC46402E54FEB5BC9A2B40286211C30ECB4640D0D38041D2A72B405534D6FECECA4640D2C77C40A0B32B407C992842EACA4640021077F52ABA2B4053793BC269CB46409F8EC70C54D62B40D6A9F23D23D14640F71F990E9DD62B4029266F8099D146409E978A8D79D52B40533D997FF4D14640F722DA8EA9AB2B40D57954FCDFDB4640CDC98B4CC0972B40D200DE0209E04640A77A32FFE8932B40AA656B7D91E04640FA264D83A2912B40F92F1004C8E04640020D36751E652B40AB59677C5FE446404CE2AC889A382B407AA52C431CE74640276BD44334322B40FED2A23EC9E7464051C1E10511312B4029EACC3D24E84640FC17080264282B4027F6D03E56EC4640D0D38041D2272B40D4B5F63E55ED4640CEC3094CA72D2B4055F833BC59F1464058AD4CF8A52E2B40A774B0FECFF146402E573F36C92F2B40276BD44334F24640782634492C392B40A9DDAF027CF346402383DC45983A2B407F15E0BBCDF3464006F52D73BA3C2B4051888043A8F4464059A7CAF78C442B40F92F1004C8F846405A9E077767452B40FDD8243FE2F946402577D84466462B40A8716F7EC3FC4640040473F4F8452B408048BF7D1DFE4640020D36751E452B4000C45DBD8AFE464057B08D78B2432B40A777F17EDCFE4640CBD8D0CDFE402B405340DAFF00FF4640FE0B040132342B40D009A1832EFF46409F91088D602B2B402541B8020AFF4640FE0E45813E292B40A777F17EDCFE464084F4143944242B40D4B5F63E55FD46407E18213CDA202B40A7ECF483BAFC4640A777F17EDC1E2B40A5BF97C283FC4640F6285C8FC2152B40D3F4D901D7FB464008E6E8F17B132B4052431B800DFC4640D1CABDC0AC082B40FFCC203EB0FD4640AB5CA8FC6B012B40D4F19881CAFE4640F6285C8FC2F52A40AB5CA8FC6B0147409E978A8D79F52A40508BC1C3B4014740D5AF743E3C0B2B40286552431B084740A77A32FFE8132B40D28BDAFD2A0A4740AC5626FC52172B40D0D03FC1C50A4740D9B0A6B2281C2B40FBE769C0200B4740A777F17EDC1E2B40514CDE00330B47402B6C06B820232B4000C79E3D970B47407A17EFC7ED2F2B40FD9FC37C790D4740A96BED7DAA4A2B4028F04E3E3D124740A27F828B154D2B40D482177D051347409E978A8D79552B4027327381CB154740F71F990E9D562B40D6AC33BE2F164740F71F990E9D562B407E8D2441B8164740FE0B040132542B40D4BB783F6E174740F92F1004C8502B407D21E4BCFF1747402D5DC136E2192B40A77A32FFE81B4740257A19C572FB2A40A968ACFD9D1D474057B3CEF8BEF82A405531957EC21D47402B69C53714EE2A40A6B6D4415E1D4740295C8FC2F5E82A40D57954FCDF1B474005FBAF73D3E62A40562B137EA91B47407A1D71C806DA2A40286211C30E1B4740AC5626FC52D72A4029E78BBD171B4740000341800CD52A402B14E97E4E1B474008E6E8F17BD32A40D2C77C40A01B474059A7CAF78CC42A40527FBDC2822547407923F3C81FC42A402AE44A3D0B264740800F5EBBB4E12A4027F6D03E562C47407B116DC7D4052B40FE0E45813E314740F92F1004C8502B40A4C2D84290394740FF08C380255F2B40FCE1E7BF07394740CBD8D0CDFE602B40D00F23844739474057B08D78B2632B40A9A10DC0063A47405A9E077767652B407C992842EA3A4740D7A6B1BD166C2B40A9A44E40133F4740030AF5F411702B40A774B0FECF4147405A9BC6F65A702B407C992842EA424740B936548CF36F2B40605B3FFD67434740'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('SP','ES','ESP','724','Spain','49904','43397491','150','39','-3.649','40.227','0106000020E61000001000000001030000000100000028000000F068FF03ACE931C030809BC58BC53B40303E05C078F631C040F38FBE49AF3B40D0A3703D0AF731C04069C53714AE3B40B029577897FB31C0504CDE0033A33B40E08EA9BBB20332C090AEEFC341A63B4040151A88652732C0000C040132B43B4030BF0CC6882832C0703A58FFE7B43B40E076A1B94E2B32C000904C874EBB3B40D0092FC1A92B32C0B0ECF483BABC3B40D0092FC1A92B32C03069C53714BE3B4060FB027AE12A32C0C0F8F884ECC03B4080ED60C43E2932C0206211C30EC33B40D07C23BA672532C0801A3048FAC43B4020C58EC6A12232C0A0FB3905F9C53B4030A83638112132C0D068ACFD9DC53B40B0AA5E7EA71D32C0F014C78157C33B40B04F72874D1C32C0D0D03FC1C5C23B40204487C0911032C0C05CA8FC6BC13B40006C4084B80E32C000274D83A2C13B4020AEB8382A0B32C0C0E67283A1C23B403053CC41D00932C0604CDE0033C33B40F071C284D10832C060431B800DC43B4030594E42E90332C0D0B837BF61CA3B40F0F63C7FDA0032C050EACC3D24D03B406091D101490032C0107497C459D13B406007077B13FF31C080A2EBC20FD23B406007077B13EF31C0505C8FC2F5D83B40B0AA5E7EA7ED31C0C0C1FA3F87D93B4050164CFC51E831C0200F45813ED93B4030AB77B81DE631C0B0E9B303AED73B40A0415F7AFBE331C030F6D03E56D43B4030C58EC6A1E231C060C2137AFDD13B40D0A02FBDFDE131C020301004C8D03B40700569C6A2E131C0B06E2EFEB6CF3B40A0B6627FD9E131C0A0ECF483BACC3B4070FCA5457DE231C0407A19C572CB3B408008AA46AFE631C0D04D637B2DC83B40D09AADBCE4E731C0E040F33977C73B40805AD3BCE3E831C06028D2FD9CC63B40F068FF03ACE931C030809BC58BC53B400103000000010000002A000000600BEBC6BB1B2FC0E03C80457EC13B4080C745B588282FC040C763062ABB3B400076A6D079352FC0201286014BBE3B40000E130D52382FC09077F17EDCBE3B4080C1C3B46F3E2FC030861DC6A4BF3B4000D462F030552FC030EACC3D24C03B40C091EA3BBF582FC010938D075BC03B40C0321AF9BC5A2FC0A018213CDAC03B4080E8103812902FC000A0C37C79D53B40C0963AC8EB912FC02077D84466D63B40E0F84B8BFAA42FC0C074B0FECFE93B40C07C23BA67A52FC0B0FE7A8505EB3B4000D3307C44A42FC0109700FC53F63B402061DF4E22A22FC0E04E0647C9FF3B40206AA2CF47A12FC080ABAE4335013C4080E7DEC3259F2FC080A2EBC20F023C4080DC0C37E09B2FC06055A18158023C4000DD257156942FC0201E8A027D023C40C09FFD4811912FC0F0D03FC1C5023C40204C18CDCA8E2FC080FDD7B969033C40608B4F0130762FC030DEC83CF20B3C40E0E175FD826D2FC0A0F8F884EC103C40E0F3FBFECD6B2FC050C2137AFD113C4040687572866A2FC0504CDE0033133C402024EEB1F4692FC0B0716F7EC3143C4080EB51B81E652FC0001E8A027D223C40A0677A89B1642FC070431B800D243C4000F94B8BFA642FC0D068ACFD9D253C4080D00836AE672FC0A09C69C2F6273C40E0AB014A43452FC01021CB8289273C4020560DC2DCDE2EC0008BFCFA21223C40C0A57F492ABB2EC0B0E67283A1023C40E0F2C98AE1BA2EC070C1E10511013C402053CC41D0C92EC0D03730B951D83B40E076A1B94EDB2EC010240C0396CC3B40E0ED79FEB4E12EC040F04E3E3DCA3B4080677A89B1E42EC00073F4F8BDC93B40A023D5777EF12EC0A000193A76C83B40E00D130D52F82EC010857AFA08C83B40201268B0A90B2FC0A0716F7EC3C43B40E0D8B27C5D0E2FC090F4143944C43B40600BEBC6BB1B2FC0E03C80457EC13B400103000000010000001E000000B0B321FFCC2C31C030F6D03E56043C40A0C5A700183B31C090069B3A8F023C40705451BCCA3E31C0F0D03FC1C5023C40D033BDC4584231C0801A3048FA043C4050185B08724C31C030DEC83CF20B3C405010CAFB384E31C0007FF8F9EF0D3C40B0AD9FFEB35231C0A09065C1C4133C4030BCCB457C5331C0E05147C7D5143C400066BE839F5431C0B05626FC52173C4080EB51B81E5531C09096E7C1DD1D3C40D02137C30D5431C0D05A0A48FB233C4030CE5147C75131C09014AE47E12A3C4060880E81235131C0D0A6B1BD162C3C40B0C8E880245031C050BFD2F9F02C3C4000EB387EA84C31C080F1D3B8372F3C40A049F086344231C030895E46B1343C40E079E2395B4031C0F05147C7D5343C40A0B6627FD93131C0A017EFC7ED2F3C400064AF777F3031C040D367075C2F3C408066D7BD151D31C040ED0DBE30253C4080E49D43191A31C0001E8A027D223C4000D671FC501931C0C05CA8FC6B213C4010D192C7D31631C0900C1D3BA81C3C40C0A3703D0A1731C080F755B950193C4080FFE6C5891731C0E0AC33BE2F163C407063963D091831C0B0716F7EC3143C400072C284D11831C050B08D78B2133C4050185B08721C31C07037177FDB0F3C4000E8F7FD9B2731C0009700FC53063C40B0B321FFCC2C31C030F6D03E56043C40010300000001000000340000003035423F535730C010763579CA5E3C40500D897B2C5930C070B5DD04DF5C3C402053CC41D05930C0702B137EA95B3C40D0187442E86430C09093A641D1383C4080E5CFB7056B30C040ED0DBE30253C4040A01683877930C010895E46B1143C4030A2B437F88630C0C0FB3905F9053C40A0436E861B8830C0F0B5F63E55053C40A0BCE47FF28B30C030ED0DBE30053C40304D4A41B78F30C000A0C37C79053C40B04A22FB209330C0801A3048FA043C4020D192C7D3A630C080AD4CF8A5FE3B40D02D3BC43FA830C050499D8026FE3B4010D4D347E0AB30C040DEC83CF2FB3B40700569C6A2B130C05028D2FD9C063C40706055BDFCB230C0B0E0F08288083C40500D897B2CB930C0D0A9F23D23113C40D01BB5C2F4B930C0306BD44334123C40304487C091C030C010068200191A3C4020BCCB457CC330C0B0ECF483BA1C3C4080E49D4319CA30C09087A2409F243C40D0187442E8D430C060C2137AFD313C403047C8409ED530C0306C06B820333C400069FF03ACE930C0C036FE4465573C4030C03E3A75E930C010857AFA08583C4030C901BB9AE830C040465C001A593C40601F0F7D77E730C0B074B0FECF593C408063963D09D830C0109C5088805F3C40F06FB378B1D430C09021E4BCFF5F3C40E0976C3CD8D230C0E04E0647C95F3C40A023D5777ED130C020F38FBE495F3C406091D10149D030C050DC2A88815E3C40D0092FC1A9CB30C0B050A4FB395D3C40B0C8E88024C030C0809FAA42035D3C40700569C6A2B130C0F0C43BC0935E3C405091D101499030C090F4143944643C4030560DC2DC7E30C0F0058200196A3C40B0AA5E7EA77D30C06034D6FECE6A3C4030AEB8382A6B30C0F0A6B1BD167C3C40D01BB5C2F46930C060DC2A88817E3C400072C284D16830C0A0992842EA823C40706C59BE2E6730C0901A3048FA843C40303BC43F6C6130C050B3CEF8BE883C405091D101496030C070D9E90775893C4030AB77B81D4630C040B81E85EB913C40202C7FBE2D2830C0201E8A027D923C408063963D092830C0307D5A457F803C4060198D7C5E2D30C060499D80267E3C40B0B0E07EC03730C0200F45813E793C4080EE92382B3A30C060BC9179E4773C40806F9A3E3B3C30C0E0AC33BE2F763C403035423F535730C010763579CA5E3C400103000000010000004000000080FFE6C589A72CC090F5B704E00B3C404097530262AA2CC0109A417C600B3C40E09FFD4811B12CC0602B137EA90B3C40C02FD978B0C52CC0C0ECF483BA0C3C4000DCF3FC69E32CC0800F5EBBB4113C400076A6D079D52CC08000193A76183C4040AF5B04C6D22CC0405C8FC2F5183C4080E15CC30CB52CC0F057C9C7EE1E3C40004487C091A02CC0A07A32FFE8233C404030F2B2269E2CC070A7CAF78C243C40A02FD978B0852CC02088BB7A152D3C40E01C588E90812CC010763579CA2E3C40E09DEE3CF16C2CC040F911BF62393C40608E90813C6B2CC0D0B837BF613A3C4080C745B588682CC0D0C43BC0933E3C40A0436E861B682CC070A2EBC20F423C40402DB1321A692CC08000193A76483C4060D00836AE672CC0207A19C5724B3C4000581CCEFC622CC0E03DB2B96A523C40A01D537765472CC00009C380256F3C4080E49D43192A2CC0D05A0A48FB833C4000FC8C0B071A2CC0C0656B7D91903C402053CC41D0092CC080992842EAA23C4080677A89B1042CC02073F4F8BDA93C4080415F7AFB032CC00088BB7A15AD3C4060EB51B81E052CC000274D83A2B13C4080415F7AFB032CC0D05147C7D5B43C4060A5660FB4022CC040E44A3D0BB63C40E0C75EEFFE002CC050C554FA09B73C40C0997B48F8E62BC02088BB7A15BD3C40E0D9E4F049DF2BC0C077F17EDCBE3C40200F27309DD62BC0F0B2B5BE48C03C406008AA46AFC62BC0D046753A90C13C402039B5334CBD2BC010938D075BC03C40E076A1B94EBB2BC0F0BB783F6EBF3C40E0A8C0C936B02BC01006820019BA3C4000FDBE7FF3AA2BC0F095CE8767B53C402024EEB1F4A92BC0E02B2CB81FB43C406083BEF4F6A72BC06037177FDBAF3C40E085E63A8DA42BC0E0BB783F6E9F3C40A0BD874B8EA32BC0206E15C440973C4080415F7AFBA32BC0809065C1C4933C40608C81751CA72BC0E05D4BC807893C40E091EA3BBFB82BC050D8463CD9613C40E0F84B8BFAC42BC0C0DDAF027C533C40803E1EFAEECE2BC020857AFA08483C40C0C0C8CB9AD82BC0D04E0647C93F3C40E09CBCC804DC2BC0E0CDFE40B93D3C40203201BF46E22BC060C763062A3B3C40A055F48766E62BC0D0C1FA3F87393C404083BEF4F6E72BC090F755B950393C4000F0880AD5052CC090A52C431C373C40C082A5BA800F2CC05028D2FD9C363C40E08827BB99192CC090AEEFC341363C40E00AD28C45232CC0F0B5F63E55353C40A049F08634322CC02015C78157333C408008AA46AF662CC000904C874E2B3C40001A170E846C2CC050B3CEF8BE283C4040A69883A0732CC0D05147C7D5243C4060E5CFB7057B2CC02009C380251F3C4080C1C3B46F7E2CC0F087BB7A151D3C40E0A8C0C936902CC0B004FD851E153C4000E5B67D8FA22CC0306893C3270D3C4080FFE6C589A72CC090F5B704E00B3C40010300000001000000270000005001857AFAD431C0100C040132743C4050F8C1F9D4D531C0107976F9D6733C40F071C284D1D831C0B05FE97C78763C40B0321AF9BCDA31C0604F1F813F783C40303883BF5FDC31C0F025AAB7067A3C40E09DEE3CF1DC31C010904C874E7B3C4020560DC2DCDE31C000274D83A2813C40509A94826EDF31C0D04D637B2D883C4030BABC395CDF31C0403D997FF4893C40F0627D0393DF31C0B0622AFD848B3C40D079E2395BE031C0405FD042028E3C40608B4F0130F631C090116DC7D4B53C406004C6FA06FA31C0901EA33CF3BA3C4030A5F5B704FC31C020917EFB3ABC3C4050198D7C5EFD31C0B0ECF483BABC3C40304487C0910032C080F1D3B837BF3C4010D714C8EC0032C0E04543C6A3C03C40800E2C47C80032C0C0C77C40A0C33C40E082A5BA80FF31C050C422861DC63C4050A0168387F931C0A08D2441B8CE3C4030BF0CC688F831C0A08461C092CF3C4080FCA5457DF231C0504CDE0033D33C40D091EA3BBFE831C08093A641D1D83C4080FFE6C589E731C050D9E90775D93C40F086890629CC31C0B04D637B2DD83C40006A317898CA31C0C0D38041D2D73C408063963D09C831C090129F3BC1D63C408057923CD7C331C01015C78157D33C40203201BF46C231C080ABAE4335D13C4050151A8865B731C05040DAFF00BF3C40501F0F7D77B731C0B0E3310395BD3C40302FC03E3ABD31C0C0420246979B3C40203201BF46C231C09021E4BCFF8F3C4030BF0CC688C831C0F040F33977873C40B044A0FA07C931C0E02B2CB81F843C4030C03E3A75C931C030CF83BBB3823C4080E49D4319CA31C0F03C80457E813C40D0092FC1A9CB31C060D367075C7F3C405001857AFAD431C0100C040132743C4001030000000100000022000000202C7FBE2D382BC0406893C327ED3C40E007910C394E2BC01073F4F8BDE93C408049F08634522BC0C074B0FECFE93C40E076A1B94E5B2BC0E0AF743E3CEB3C4020272F32015F2BC0107A19C572EB3C4060EB51B81E652BC0E04BC5C6BCEA3C40A02C98F8A3702BC07093A641D1E83C40A0402D060F732BC0A04D637B2DE83C400035423F53772BC0B05FE97C78E63C402024EEB1F4892BC0200F45813ED93C40E0F3FBFECD8B2BC0C05FE97C78D63C40A0BD874B8EA32BC050C763062ADB3C40E0DC257156B42BC010857AFA08E83C4080E49D4319AA2BC0D0DA6E826FFE3C4080D9CBB6D3A62BC0F03DB2B96A023D40206DE34F54962BC0909FAA42030D3D4000DD257156942BC09096E7C1DD0D3D40609A94826E7F2BC070A7CAF78C143D40C0A23EC91D462BC0109C5088801F3D4080E8103812302BC0F014C78157233D4020ABE80FCD2C2BC0D0C77C40A0233D406077BAF3C4F32AC0007FF8F9EF3D3D40E079E2395BF02AC0D031AEB8383E3D4000E5B67D8FE22AC010904C874E3B3D40E00D130D52D82AC050CDE50643353D40006420CF2ED72AC0E05A0A48FB333D40E0AE42CA4FDA2AC040E78BBD172B3D40E0F2C98AE1DA2AC0D0C1FA3F87293D4060E8103812F02AC0A0DDAF027C033D40003E05C078F62AC0A0F1D3B837FF3C40C0C0C8CB9AF82AC070FA96395DFE3C40004F594DD7032BC09081204086FA3C406094128255152BC090FB3905F9F53C40202C7FBE2D382BC0406893C327ED3C400103000000010000001000000080AAED26F86607C0E006600322A241408077F17EDC7E07C0888AE3C0ABA1414000F71E2E398E07C0608BC1C3B4A1414000DE205A2B9A07C000D9243FE2A14140807C0A80F1AC07C0084BE7C3B3A241408077BAF3C4B307C0504CDE0033A3414000838769DFBC07C0885A457F68A4414000C2BE9D44C407C0D8CDFE40B9A5414080490ED8D5C407C0606D37C137A7414000E6CAA0DAC007C08021E4BCFFA741408077BAF3C4B307C0E8A9F23D23A9414000B0743E3CAB07C038266F8099A9414000E370E6579307C0D806600322AA414080C51858C77107C0A89509BFD4A54140807397C4595107C0D082177D05A3414080AAED26F86607C0E006600322A241400103000000010000000F000000407B0F971C4715C0604F1F813FF041404061DF4E226215C0082DCF83BBEB414000EC4CA1F36A15C000BEDBBC71EC414040E6CAA0DA8015C030F38FBE49EF4140007E37DDB28315C0E0D38041D2EF41404067614F3B8C15C0E0C1FA3F87F14140400E2C47C89015C05834D6FECEF2414040F2CEA10C9515C0B059677C5FF44140C0D0EAE40C9515C0F012807F4AF54140404E5E64027E15C0607FBDC282F5414000CB9F6F0B7615C0607FBDC282F5414040C8409E5D6E15C0505260014CF54140C07A14AE476115C028D505BCCCF44140C0D6A3703D4A15C0B06BED7DAAF24140407B0F971C4715C0604F1F813FF041400103000000010000000900000000356090F44908C000D6E3BED5F4414000272F32015F08C0080C040132F4414000BA4BE2AC6808C010BEDBBC71F4414000BA4BE2AC6808C088CC07043AF5414080CEF9298E6308C0D0CDFE40B9F5414080DC2A88814E08C050FB743C66F64140009735B1C03708C0089700FC53F64140009735B1C03708C000CD203EB0F5414000356090F44908C000D6E3BED5F441400103000000010000000C0000004033333333B31BC08896E7C1DD954240C07133DC80AF1BC0B0716F7EC3944240800778D2C2B51BC0283B3602F1944240401C5DA5BBBB1BC0A8B6D4415E95424040B06F2711D11BC0A8A44E401397424000FA7DFFE6D51BC058853FC39B97424040B7EC10FFE01BC080A2EBC20F9A4240C0B4C4CA68E41BC080992842EA9A4240C0CB9A58E0DB1BC0804B00FE299B42400094128255D51BC0901EA33CF39A4240008196AE60CB1BC0A8A10DC0069A42404033333333B31BC08896E7C1DD954240010300000001000000190000000092E524943EF93FE000DE02095843400048AAEFFC62F93F08E528401456434000FC135CAC68F93F281A6B7F6755434000DCFD2AC037F93FB87A32FFE85343400074CE4F711CF93F002DCF83BB53434000ABED26F8E6F83F002DCF83BB53434000AB5B3D277DF83F002DCF83BB5343400049AAEFFC62F83F8015E0BBCD534340007A280AF449F83FD8A6B1BD16544340003756629E15F83FF8CC203EB055434000419B1C3EE9F73FB05FE97C7856434000FE135CAC68F73F084E2844C05743400021F301814EF73FA89B8BBFED57434000DE205A2B1AF73F10BB9A3C655743400095E524943EF63F4855A18158524340008D683BA62EF63F90992842EA524340006EACC43C2BF63FE00CE2033B544340002EB6494523F63FC8BB783F6E574340001D9947FE20F63F8093A641D1584340001D9947FE20F63F08C79E3D975B4340001D9947FE20F63FD80CE2033B5C43400048AAEFFC62F63FB0DA6E826F5E4340000EFAD2DB1FF73FB877F17EDC5E4340006EACC43C2BF93F5801F73C7F5843400092E524943EF93FE000DE02095843400103000000010000001D00000000CC9541B581F83F30D8463CD979434000346ABE4A7EF63FE00CE2033B6C434000193F8D7BF3F53F5055A181586A43400014C2A38DE3F53F303B3602F16C43400036A14962C9F53F50499D80266E4340002085EB51B8F53F908D2441B86E434000F84B8BFAA4F53F1009C380256F4340001B2B31CF8AF53F3020ED7F806F434000B5FB55806FF43F786649809A7043400050CC7A3154F43F00180802647043400087EB51B81EF43FF8C35DBD8A6E434000D9A3703D0AF43FD07FD6FCF86D434000F8821612F0F33F7848BF7D1D6E434000C3F5285C8FF33F3838F581E46F4340005649641F64F33FD0FD9C82FC72434000FA4B8BFAA4F33F68F833BC59794340007A14AE47E1F33FA87A32FFE87B43400002C974E8B4F43F90423D7D04844340004D3B3597DBF43F383B3602F184434000C3BE9D4444F53FB0A44E401387434000CDCCCCCCCCF53F6073B9C150894340004C04AA7F90F73F08A0C37C798D434000301004C850F83F0809C380258F4340003F4162BBBBF83F78A52C431C8F43400031478FDF9BF93F60F5F23B4D8C434000D0EFFB37AFF93FF82CCF83BB8B434000D86CE525BFF93FA8B915C26A8A434000A5703D0AD7F93FC8C77C40A083434000CC9541B581F83F30D8463CD979434001030000000100000044000000809CFD8172FB094028E44A3D0BDE434080BDA59C2F160A40801B62BCE6DD43408032333333330A40B0DA6E826FDE434000B3CEF8BE580A40B0BC564277DF434080012D5DC1960A4080ABAE4335E14340006CED7DAAAA0A4078A2EBC20FE2434080A243E048C00A402814E97E4EE3434000077DE9ED0F0B40D8FD9C82FCE2434080A7CAF78C840B40D800DE0209E0434080E8F7FD9BD70B40B859677C5FDC43408060E97C78D60B40D882177D05DB4340008718AF79B50B4058888043A8D4434000AE47E17A940B40583D997FF4D1434000EB51B81E050B40588E0244C1C64340804818062CF90A40081286014BC6434080D48041D2A70A40109A417C60C3434080077DE9ED8F0A40A8E67283A1C24340000AE1D1C6710A40E0B2B5BE48C043400099A3C7EF4D0A40D0F4D901D7BB434080E82E89B3220A4000D6E3BED5B4434000B6FB5580EF09403829B000A6AE434000D58041D2A70840801EA33CF3A243408054E57B46820840E0EE5701BEA1434080A04D0E9F740840808AE3C0ABA14340803E4162BB3B0840D80CE2033BA443400046EBA86AE2074008301004C8A84340802CB64945A3064090CC07043AAD434000DE57E54265064058499D8026AE43400079E750864A0640F8298E03AFAE434000A243E048400640386E15C440AF4340001B2B31CF0A064030F04E3E3DB2434080F4328AE5F6054090423D7D04B443408009E1D1C6F10540580DFB3DB1B4434000406EBF7CD2054020232E008DBC434000727495EEEE0540E876137CD3BE4340000491459AF80540A85626FC52BF43408030D978B0050640888461C092BF434000931CB0AB090640B0B393C151C043400040373465070640205C8FC2F5C04340002A5C8FC2F50540B0A10DC006C24340001281EA1FE40540286211C30EC343400080643A74DA0540B8622AFD84C34340803AE7A7388E05402029B000A6C6434080AAED26F866054058853FC39BC7434000CDCCCCCC4C054030EACC3D24C84340805EBC1FB73F0540604F1F813FC8434080272F32015F0440804B00FE29C3434000A5703D0A5704405807793D98C243400078F17EDC7E0340D8D03FC1C5C2434000B85510031D0340584CDE0033C34340808522DDCFE902400009C38025C7434000032D5DC1160340A8DA6E826FCE43400021B248134F044008274D83A2D94340800491459A780540B868ACFD9DE5434000630CACE3380640A8A78FC01FEC434000ABED26F8E607408087A2409FF44340005B626534920840305FD04202F6434080596C938AC6084050888043A8F443408082C8224DBC0840109A417C60F3434000CC9F6F0BB608401006820019F243408096766A2EB7084028F911BF62F143408078F17EDCFE0840889C69C2F6E74340006AC020E9130940281A6B7F67E5434000A9F7544E1B094030D505BCCCE443408097766A2E3709402814E97E4EE34340804C689258720940E00F238447E1434000EA245B5DEE0940A8AD11C138DE4340809CFD8172FB094028E44A3D0BDE43400103000000010000002500000080AB1F9BE4171140206211C30EFB4340C05B94D9204311405801F73C7FF04340C0A7CAF78C44114060F5F23B4DEC4340404C361E6C411140081E8A027DEA4340405517F032331140884E417E36E8434080E9245B5D2E1140104E2844C0E743408076C4211B281140885704FF5BE743400007B474051B1140606D37C137E743400033384A5E0D11400821CB8289E74340C0FAAF73D3061140104E2844C0E74340403BE2900DF41040507C7C4276E843408096766A2E7710401009C38025EF4340C06E15C44067104028172AFF5AF0434000977153035D1040F80E45813EF14340C0A148F7735A1040203E7782FDF1434040022D5DC1561040B0E67283A1F24340C037BF61A251104020E78BBD17F3434000068200192A104028ED0DBE30F54340005B99F04B1D10405031957EC2F5434080368DEDB5E00F40A0A44E4013F7434000EA5BE674B90F402020ED7F80F7434000105EBBB4810F40905704FF5BF74340009BD024B1640F40F8DB65BFEEF6434080346090F4490F407860C77F81F6434000D9D0CDFE200F408896E7C1DDF54340006AC020E9130F4028327381CBF5434000B828B341060F405031957EC2F5434000B95510039D0E4000E5284014F6434000F3052D24600E40386BD44334024440004B72C0AEA60E40608E0244C1064440809CC6F65AB00E40586D37C137074440804D689258F20E40C8BB783F6E0744408000000000800F400021CB8289074440402CBB60707D1040E009A1832E07444000EFAB72A1B21040B8DA6E826F064440C096766A2EF71040D009A1832EFF434080AB1F9BE4171140206211C30EFB43400103000000010000007704000000963FDF166C1FC0D00F238447E1454080AAED26F8661FC0B8DDAF027CDB454000B4C9E1933E1FC0580DFB3DB1DC4540809DEE3CF12C1FC0281A6B7F67DD4540C000FBE8D4E51EC0A8E9B303AEDF4540804E5E6402BE1EC0D8D38041D2DF454080B06F2711111EC0205FD04202DE45400022A81ABDDA1DC0A89ECC3FFADC4540000F27309D761DC000C45DBD8AD64540408940F50F721DC020E44A3D0BD64540C03BDD79E2591DC0B86BED7DAAD2454040B06F2711511DC09093A641D1D0454080C51858C7311DC038232E008DCC4540403883BF5F2C1DC058431B800DCC454080415F7AFB031DC028172AFF5AC84540400F27309DF61CC0908461C092C7454000CEC29E76D81CC0B8B393C151C84540401B2B31CFCA1CC0E0B2B5BE48C8454040C8409E5D2E1CC060853FC39BC74540401059A489271CC0885704FF5BC7454000F94B8BFA241CC0205FD04202C6454000A5660FB4221CC0B8716F7EC3C4454040F52C08E52D1CC050F2237EC5BE454040A69883A0131CC0E0031F8315C54540009A94826EFF1BC000D3A23EC9C7454080D11C59F9C51BC0503D997FF4C9454040B06F2711111BC0D8CABDC0ACC84540804C310741671AC0B8BC564277C74540C09DEE3CF1EC19C03841B8020AC7454000272F32015F19C020F38FBE49C74540C02DAC1BEF2E19C0E0F71A82E3C84540C0CFEFFB376F18C03838F581E4C74540C07A14AE476118C0B09B8BBFEDC74540C0B2976DA74D18C0109D82FC6CC84540801D537765C717C088423D7D04CC454040C745B5888817C0F8D2A23EC9CF4540404A09C1AA6A17C0901EA33CF3D245404039B5334C1D17C06040DAFF00CF454080C745B5880817C058431B800DCC454040560DC2DCFE16C028E78BBD17CB4540002EAC1BEFEE16C0D873D2FBC6C94540C039B01C21C316C0E0AC33BE2FC6454000CB9F6F0BB616C0B868ACFD9DC54540002EAC1BEFAE16C0A0E3310395C54540C0D571FC509916C0D0CDFE40B9C545408052B3075A9116C030327381CBC54540C01B261AA47016C0B8DA6E826FC64540008940F50F3216C0002A8E03AFC6454000E048A0C1D615C030DB87BCE5C6454000E8F7FD9B9715C0908D2441B8C64540401059A4892715C038F6D03E56C44540C0573A1F9E1515C0484CDE0033C3454040CFF412630915C05055A18158C2454080D79E5912F014C0D8BB783F6EBF4540C029577897DB14C0301A6B7F67BD4540C0AD47E17AD414C0306893C327BD454040D9CBB6D3C614C028ED0DBE30BD45404049D74CBE3914C088A86DC328BC45400052B81E85EB13C0D882177D05BB4540807B0F971C8713C0B05CA8FC6BB94540401B2B31CF0A13C0E076137CD3B6454040A46B26DFFC12C060499D8026B64540C02DAC1BEFEE12C0F847A643A7B54540007365506DA012C058F5F23B4DB4454040ABE80FCD8C12C058431B800DB4454000B7EC10FF6012C008C79E3D97B34540805D30B8E60E12C0206F9D7FBBB2454040880E81230112C00015C78157B34540806F0B96EAB211C048793BC269B3454080C2F5285C8F11C088992842EAB24540C039B01C214311C0283E7782FDB1454000E8F7FD9B1711C0283E7782FDB1454080BC732843E510C0104BE7C3B3B24540C03BDD79E2D910C088992842EAB2454080A46B26DF7C10C0605260014CB54540C05D85949F3410C010CADFBDA3B84540803BA6EECA8E0FC0D07954FCDFBB454080583508737B0EC02841B8020ABF454080B81E85EB510EC038DB87BCE5BE454080E17A14AE470EC0A8DA6E826FBE4540001D588E90210EC088A86DC328BC454000D0EFFB37AF0CC05073B9C150C1454080A59D9ACB6D0CC0F8E1E7BF07C1454000A0DFF76F5E0CC0282F3201BFC04540803106D6719C0BC000C79E3D97BB454080DD205A2B9A0AC0480438BD8BB545400088450C3BCC09C06834D6FECEB24540000D501A6A3409C01812A27C41AD454000C09140832D08C06031957EC2AD454080EB51B81E0508C080457EFD10B145400083BEF4F68707C0004E2844C0B7454000963FDF166C07C0F8D2A23EC9B74540803BDD79E2D906C008BB9A3C65B74540806CE34F547606C0A8A44E4013B745408002232F6BE205C0E0C43BC093B64540802FD978B08504C0503D997FF4B14540803106D6711C04C0607C7C4276B04540803BA6EECA0E04C0804E417E36B04540800D315EF3EA03C080AEEFC341AE45400003232F6BE203C0B068ACFD9DAD4540809735B1C0B703C0582B137EA9AB454080406491269E03C02835B401D8AA45408094128255D502C00009C38025A74540802502D53FC802C0803FFCFCF7A645408017D1764C5D02C0901B62BCE6A5454080D349B6BA5C01C0885182FE42A5454080A143E0484001C0885182FE42A545408048D74CBEF900C0D87FD6FCF8A5454000118B187698FFBF5882FE428FAA4540001E4E603A6DFDBF602E54FEB5B045400096766A2EB7FCBFD006600322B245400022A81ABD9AFCBF306BD44334B2454000326ABE4A7EFCBFD873D2FBC6B14540002C93E1787EFCBFD88558FD11AE454000A75CE15D6EFCBFD0F4D901D7AB454000020CCB9FAFFBBF2090680245A6454000BF9B6ED961FBBF10DC65BFEEA64540003556629E15FBBF00BB9A3C65A745400024CB49287DFABF50853FC39BA74540007D6E68CA0EF8BF08D6E3BED5A44540001B2B31CF8AF6BF901EA33CF3A245400039B01C2143F6BF00274D83A2A14540003CD34B8C25F6BF1018080264A045400084EB51B81EF6BF500ABABDA49F4540000DFAD2DB1FF6BFD87954FCDF9B4540005B8FC2F528F6BFA874B0FECF99454000F2CEA10C95F6BF08C11C3D7E914540006D1ADB6BC1F6BFE0D38041D28F454000E366B801DFF6BF38DB87BCE58E454000EB1A2D073AF7BF20ED0DBE308D4540005FE97C7856F7BF20ED0DBE308D4540004387C09180F7BF58707841448C454000C3F5285C8FF7BF602B137EA98B454000FB6EBA6587F7BFD8FD9C82FC8A4540003333333333F7BF386E15C44087454000A4A7C82122F7BF6828D2FD9C8645400091AE997CF3F6BFB09509BFD4854540002B7FBE2DD8F6BFB0E331039585454000A0DFF76F5EF6BF80397AFCDE844540007E37DDB2C3F5BF58431B800D84454000A439B2F28BF5BF00BEDBBC718445400024CB49287DF5BF889FAA42038545400055DB4DF0CDF4BFA8AAD0402C894540004450357A35F3BF8896E7C1DD85454000E49D43192AF1BF7893A641D18045400044BE4BA9CBEFBF303B3602F17C4540006A8995D148EEBF6055A181587A454000124031B2E4EDBF803CBB7CEB79454000A824B20F32EABF58465C001A7945400000B5183C4CE9BF803CBB7CEB7945400006D847A72EE9BF081E8A027D7A454000949A3DD08AE8BFB0DDAF027C7B454000B81E85EB51E8BF502B137EA97B454000144031B2E4E7BF08C79E3D977B45400004465ED6C4E7BFC882177D057B454000F4BA45602CE7BF889C69C2F677454000960854FF20E7BF10E52840147645400038AE467625E7BF50E960FD9F754540004C27D9EA72E7BFB059677C5F744540009CBCC8047CE7BF909065C1C4734540000EAFEB176CE7BF30E78BBD1773454000E49D43192AE7BF080682001972454000880E812301E7BF10C11C3D7E71454000DEE9CE13CFE6BF385C8FC2F570454000F0E2FDB8FDE1BF88423D7D04644540006A3EAE0D95E1BF502B137EA9634540004077499C15D9BFD8FA5B02F0654540001068E90AB6D4BFA874B0FECF69454000D858897956D4BFD0B837BF616A454000588FC2F528D4BFE0FD9C82FC6A454000FCFF3861C2D3BF28C6A4BF976C4540002CC6C03A8ED3BF58431B800D6C454000B0230ED940D3BF58FEB5BC726B454000CCCCCCCCCCD0BF00CADFBDA36845400088BFB4A84FCABF0048A643A765454000D8A3703D0AC7BF785A457F68644540006869A7E672C3BFD89A1F7F6963454000006D72F8A4BFBF285C8FC2F56045400010D1217024B0BFD0C77C40A05B4540000009C38025AFBFD0D03FC1C55A454000C05DBC1FB7AFBFA8A10DC0065A454000C05DBC1FB7AFBF5073B9C150594540004039B5334CADBF8018213CDA58454000A03BDD79E2A9BFB0656B7D915845400000BE64E3C176BFB8E9B303AE574540000000000000000070AF777FBC5745400000D253E410813F20BD6F7CED57454000E0FBAA5CA8BC3F6034D6FECE5A454000C014731074C23F10BEDBBC715C45400070D3D85E0BC63F8096E7C1DD5D45400060DAA9B9DCC63F8048BF7D1D5E454000C8AA4198DBC73F38E44A3D0B5E4540009458C4B0C3D03FD8F4D901D75B454000C840102043D13F5007793D985A454000440AD7A370D13F883CBB7CEB59454000681B7FA2B2DB3F2838F581E45745400074CFF3A70DE03F4801F73C7F584540007AA697184BE03FB0656B7D915845400054B81E85EBE13F90457EFD1059454000F6DD74CB0EE33F305C8FC2F558454000F8BA45602CE53FB0656B7D91584540001248C2BE9DE53FE8E8633E2058454000FA285C8FC2E53F282F3201BF58454000C6AA4198DBE53FA0E67283A15A45400004232F6BE2E53FB0B05241455B4540005ADB4DF0CDE53FB8B6D4415E5D454000B2FCF9B660E53F104E2844C05F4540005AB77A4EFAE43FB0E0F08288604540005CDAA9B9DCE43FE0BEB9BF7A644540009EDFF76F5EE53F60793BC2696B45400070ACC43C2BE63F885182FE426D454000BEAFCA85CAE63F801B62BCE66D454000D8A3703D0AE73FE07FD6FCF86D4540000CB474055BEA3FA8E67283A16A454000004BE7C3B3EC3FD88558FD116845400090C2F5285CF13FB0BF97C283644540007C82C47677F13F785A457F6864454000FA821612F0F13FD8B837BF6162454000FFDCD0941DF23F30F911BF62614540000CD7A3703DF23F0018080264604540002B931ADA40F23F08DC65BFEE5E454000BE41B45634F23F109700FC535E4540002B931ADA40F23F00CD203EB05D454000301004C850F23F286893C3275D4540008722DDCF69F23F9087A2409F5C4540002402D53FC8F23F3035B401D85A454000C4633F8B25F53FB0622AFD845B45400028931ADA40F53F80A86DC3285C454000D96CE525BFF53F886308008E5B45400095E524943EF63F386552431B58454000BFD2F9F0ACF63F2814E97E4E53454000A6A7C82122F73F000341800C4D454000183F8D7BF3F63FD873D2FBC6494540004E5E6402BEF63F8096E7C1DD4545400035A14962C9F63F0009C380253F4540007B4B395F2CF73F488BC1C3B439454000596C938A46F73FA0E0F0828838454000AD24B20F32F83F6037177FDB374540000A0E2F8888F83FD0D38041D237454000282504ABAAF83F789C69C2F6374540000391459A78FA3FD87954FCDF3B4540006BC020E993FA3F28F6D03E563C4540004687C09180FB3F0818080264404540006AC020E993FB3F78ABAE43354145400015AE47E17AFC3F9060C77F813E454000CA72124A9FFD3F88A86DC3283C4540004687C09180FE3F80ABAE43353945400070067FBF58FF3FF8230C0396344540004587C09180FF3FB8AAD0402C31454000DA11876CA0FF3F809C69C2F62F45400057DB4DF0CDFF3FB0A44E40132F454000941CB0AB090040D0CDFE40B92D4540802CB6494523004038ED0DBE302D454080E04DB7EC300040E0031F83152D454080BC783F6E7F004000CD203EB02D4540005EBC1FB7BF00406028D2FD9C2E454080B5FB5580EF004080457EFD1031454000E1844204FC00406055A1815832454000346ABE4AFE0040D0FD9C82FC32454080C845B588080140D80CE2033B3445400021E9D32A1A0140381A6B7F6735454080CB9F6F0B360140D8FA5B02F0354540009A9999991902403038F581E43745400090F98040270240789C69C2F637454080541B9C883E0240D085CABF963745400018080264A80240587FBDC28235454000986C3CD8820340682E54FEB5304540001C2B31CF8A034090C9C6832D30454000B1A19BFDC1034088CC07043A2D454080378DEDB5E00340B87A32FFE82B4540804391EEE7340440B06BED7DAA2A4540001B62BCE65504405882FE428F2A454000518BC1C3540540909065C1C42B454000DF57E542650540D0CDFE40B92D4540006E1ADB6B410540A0656B7D9130454000B1A19BFD41054070ABAE4335314540806116DA396D054050793BC2693345400089450C3BCC054010CD203EB03545408099999999990740507FBDC2823D454080D349B6BA5C0840A8716F7EC33C454000C09B6ED9610840B8A78FC01F3C454000DF57E5426508403835B401D83A454080A9F7544E9B0840504F1F813F38454000C64FE3DEBC08403841B8020A37454000F855B950D9084000DC65BFEE3645408006871744440940B0BC56427737454000E4A7716F5E0940084E2844C037454080C57762D66B094028594E42E93745400080643A745A094010C45DBD8A3645400016E5D2F8450940285C8FC2F53045400016E5D2F84509405801F73C7F304540000D040132540940089700FC532E4540009F20B1DD5D09406031957EC22D454000634337FB83094080A86DC3282C4540006F10AD158D09408815E0BBCD2B454000BEA59C2F960940C8C77C40A02B45400085EB51B89E0940D8F4D901D72B45400085EB51B89E094068F5F23B4D2C45408090F98040A7094000240C03962C454000D6AD9E93BE0940A8ECF483BA2C4540806BB6F292DF0940B8716F7EC32C45408060200890210A40D8A6B1BD162C454000C64FE3DE3C0A4050FEB5BC722B454000931CB0AB890A4028266F809929454000B3976DA78D0A40D0A9F23D23294540801B2B31CF8A0A40E0CABDC0AC2845400001378B174B0A40B053E57B4622454000C64FE3DE3C0A4008E2E7BF072145408060200890210A400809C380251F45400021E9D32A1A0A40E076137CD31E4540805EBC1FB7BF09405831957EC21D454000F4FBFECDAB094000E52840141E454080E2B19FC592094028DB87BCE51E45400014AE47E17A0940504F1F813F20454000E6D4CE30750940302F3201BF204540006216DA396D0940B0AAD0402C21454000301004C8500940908AE3C0AB21454080490ED8D544094030266F809921454080726A67983A0940885D86FF74214540002DB64945230940587C7C427620454000E5D4CE30F50840485260014C1D454000EB245B5DEE084030F6D03E561C454000C9A99D61EA084050793BC2691B4540808B7269FCE20840B8AAD0402C19454080BF9B6ED9E10840786649809A18454000C9A99D61EA084050FEB5BC7213454000E5D4CE30F50840E0C1FA3F87114540805A6265341209400009C380250F454000809BC58B250940D876137CD30E454080CFEFFB372F094010DC65BFEE0E45400089450C3B4C0940E0F19881CA0E4540801C62BCE65509403829B000A60E454000B5FB55806F0940D8CDFE40B90D45400014AE47E17A0940203B3602F10C454000F4FBFECDAB094080ABAE4335094540804291EEE7B40940D0D38041D207454000C1FF56B2C3094078ABAE4335F9444080B95510039D0940B053E57B46F2444000ABED26F86609403041B8020AEF4440006993C327FD08408087A2409FEC444000128B1876180840881EA33CF3E24440805A626534920740A8716F7EC3DC444000634337FB83074088A86DC328DC444080A14D0E9F740740D0C77C40A0DB4440000BD7A370BD0540B8B393C151D04440008622DDCF690540B8DA6E826FCE444000B4CEF8BED80440E0C77C40A0CB444000B1ABC95376044010D9243FE2C9444080531C075E4D044028E109BDFEC8444080D0EFFB372F02403014E97E4EBB444080022D5DC1160240A0B915C26ABA44400084BEF4F607024030266F8099B9444080EFE2FDB8FD0140D87C957CECB8444000C4591135F101409021E4BCFFB74440807397C459510140D8F4D901D7AB444080EA5BE67439014038172AFF5AA8444080AB24B20F3201403820ED7F80A7444080F0E2FDB8FD004000A0C37C79A54440008A7269FCE2004008240C0396A444408094490D6DA00040E8AF743E3CA3444000717495EE6E0040D0B837BF61A2444080E92E89B3220040908AE3C0ABA1444000C2F5285C0F0040908AE3C0ABA1444000C1098508F8FF3F508BC1C3B4A14440000AD7A3703DFE3F38EACC3D24A04440001477BCC92FFC3F00DFA63FFB9B444000640CACE338FB3F9054C37E4F9A444000EE884336D0FA3FB074B0FECF99444000963FDF166CFA3F00C11C3D7E99444000D549B6BADCF93F88457EFD1099444000DB34B6D782F83FB0E9B303AE974440004918062CF9F73FA877F17EDC964440005B8FC2F528F53FB0656B7D9190444000E17A14AE47F33FB09ECC3FFA8C44400060200890A1F03F9021E4BCFF874440002684471BC7EF3F48499D8026864440005ADAA9B9DCEE3F080C040132844440009807B0C82FEE3FD00660032282444000B46A10E6F6ED3F285C8FC2F580444000887C975297ED3FA877F17EDC7E44400058B77A4EFAEC3F08E52840147E444000026E162F96EC3F90397AFCDE7C444000867D3B8988E63FD88558FD1168444000768368AD68E63F88A52C431C67444000482C62D861E63F3029B000A66644400018D1764C5DE63FE0AC33BE2F664440006866666666E63FD0CDFE40B965444000FC27B858D1E63F587078414464444000B4463D4423E73F3814E97E4E63444000C6F484259EE73F0806820019624440002062BCE6D5EA3F00A0C37C795D4440003C0AD7A370EB3F885182FE425D444000E60B5A48C0EB3FA868ACFD9D5D44400094300C58F2EB3F781B62BCE65D444000B4FB55806FEC3F507FBDC2825D444000703D0AD7A3EC3F90CC07043A5D444000CCCCCCCCCCEC3FB0ECF483BA5C4440009031B08EE3EC3FB0A78FC01F5C444000CC3B873254EC3F483D997FF4594440000C698D41A7EB3F58853FC39B57444000A20227DB40EB3F10C45DBD8A564440009E2ADF3312E63FA8AAD0402C494440008E9FC6BD79E53F884E417E3648444000DAA3703D0AE53F5837177FDB47444000FE6D162F96E43FA86E2EFEB6474440003C55BE6724E43F306552431B4844400082130A11F0E33F0818080264484440002AEDD45C6EE33F588BC1C3B4494440006865C22F75E33F9054C37E4F4A4440004AE17A14AEE33F00DFA63FFB4B444000144031B2E4E33F002DCF83BB4B444000AE47E17A14E43F089A417C604B44400098E4805D4DE43F50FEB5BC724B444000E20CFE7EB1E63F50707841444C444000C6F484259EE73F08D9243FE251444000EE74E78967E73F503D997FF4514440007AA697184BE63F38266F809951444000B8B06EBCBBE33F88C9C6832D50444000341004C850E33FD8D38041D24F4440003C9CC074DAE23FA0DA6E826F4E4440006E88F19A57E13F8018213CDA4844400032C51C049DE03F28F6D03E5644444000D233F6259BE03F200B98C0AD43444000606BEF5355DD3F000F45813E39444000FC0489EDEED63FD0F19881CA26444000DC10E335AFD63FA8AD11C13826444000942C27A1F4D13F78336ABE4A1E444000C01B446B45CB3FB841D13C8017444000E044A0FA07A93F08A986FD9E0444400000F969DC9BA73FD0DF84420404444000800E2C47C8A03F887E5182FE00444000206211C30EA3BF5855A18158F2434000E0573A1F9EB5BFA89ECC3FFAEC4340005069A7E672BBBF70A2EBC20FEA43400030CC423BA7BDBFF82F1004C8E8434000E0C2BAF1EEC6BFA8AD11C138DE4340003855BE6724D4BF9081204086C2434000542250FD83D4BFD00F238447C14340006CF7AB00DFD4BFA85626FC52BF434000785F950B95D5BF0018080264B8434000DC0DA2B5A2D5BF104E2844C0B743400050DAA9B9DCCEBFB8B915C26A92434000285C8FC2F5C8BFA877F17EDC8643400090C2F5285CC7BF002DCF83BB83434000F8B759BC58C2BF90CC07043A7D434000B0F869DC9BB7BF6040DAFF007743400050B81E85EBB1BF30F6D03E56744340002085EB51B8AEBF0815C7815773434000A015C26A2CA9BF301DACFF7372434000606A2FA2EDA0BFB8AD2D3C2F71434000805A626534823FE097DEFE5C6E434000807D3CF4DD9D3F58EFE2FDB86D434000A0737E8AE3A83F601C40BFEF6D434000408FC2F528AC3F38CFF57D386E43400060AB06616EAF3F80336ABE4A6E434000506325E659B13FD8E506431D6E43400000BCE9961DB63F803C2D3F706D434000D088B663EAC23F28C3F17C066A434000B044A0FA07C93F802AA73D25674340001863601DC7C93FA8C519C39C6643400038C6C03A8ECB3F8803CC7C07614340008081204086CA3F48EFE2FDB85D434000980A9C6C03C53F583107414759434000C014731074C23FA0A70183A45743400040A5846055A53F08ACC77DAB5143400000662FDB4E7BBF507C7C42765043400000B81E85EB91BFB0E9B303AE4F434000806ABB09BEA9BFD00CE2033B4C4340004060E4654DACBF602B137EA94B434000D8EE5701BEC1BF80397AFCDE44434000F07002D369C3BFF0230C0396444340000491459A78D2BF80AEEFC3413E43400074A73B4F3CD3BF0048A643A73D43400094E4805D4DD4BF28232E008D3C43400094770E65A8D4BF78A86DC3283C4340005CFC34EECDD7BFB0E0F082883843400050DCF126BFD8BF0009C380253743400026EE78935FE0BF30266F8099294340004450357A35E3BFB06E2EFEB617434000982B836A03E5BF285FD0420206434000C287122DF9E7BF306BD44334F24240007EECF5EE0FE8BFA8C2D84290F142400096E4805D4DE8BF109700FC53EE424000DA58897956E8BF00CD203EB0ED42400070F7393E5AE8BFA071E14048EC424000F84B8BFAA4E9BFD8C43BC093E642400006228B34F1EABF6037177FDBDF4240007C82C47677EBBFA859677C5FDC424000EC51B81E85EBBFF82CCF83BBDB4240003E0AD7A370EBBF00E869C020DB4240006ECFF3A70DEABFE0031F8315D5424000E40B5A48C0E9BFA8A78FC01FD442400006D847A72EE9BF90992842EAD2424000845968E7B4E7BFE0CABDC0ACD0424000DA34B6D782E7BFA8656B7D91D042400064B14D2A1AE7BF38F911BF62D142400064D47C95FCE6BF303E7782FDD142400064D47C95FCE6BFB8E67283A1D242400030A2ED98BAE6BFB0B915C26AD242400078A697184BE6BF305C8FC2F5D0424000ACB5F7A9AAE6BF20DB87BCE5CE4240009C4EB2D5E5E6BF08CD203EB0CD424000EE74E78967E7BFD0BEB9BF7ACC42400066F84F37D0E7BF80423D7D04CC424000E07A14AE47EDBF002A8E03AFC6424000ACD9CA4B7EEDBFE0C43BC093C642400014AE47E17AEEBF0809C38025C742400082C8224D3CEFBF5873B9C150C94240007CA5F3E159EFBF30D8463CD9C942400015E5D2F8C5F0BFE006600322CA4240007397C459D1F3BF00274D83A2C94240000AD7A3703DF5BFE0BB783F6EC7424000B95510039DF5BF009700FC53C64240003656629E15F7BF28F38FBE49BF42400039B01C2143F7BF50FB743C66BE424000EE74E78967F7BFE0B5F63E55BD4240002C4833168DF7BF10C79E3D97BB4240004E5E6402BEF7BF507C7C4276B842400006465ED6C4F7BFE0D38041D2B74240004A72C0AE26F8BF285FD04202B64240003656629E15F9BF804B00FE29B3424000BC5CC47722FABF808D96033DB042400088450C3B4CFABFB06E2EFEB6AF424000D349B6BADCFABFB8ECF483BAAC424000B7E7F9D306FBBFC8F4D901D7AB42400018080264A8FCBFD8CDFE40B99D42400006465ED6C4FCBFA0BF97C2839C42400009A01859F2FCBF903CBB7CEB99424000E0438996FCFCBFD8A9F23D23994240007D6E68CA0EFDBF686D37C13797424000035ABA822DFDBF3014E97E4E934240004450357A35FDBF602E54FEB59042400092E524943EFDBF20F38FBE498F424000A439B2F28BFDBF101E8A027D8A424000B5FB55806FFEBF00BEDBBC717C424000D449B6BADCFEBFE0B2B5BE4878424000B16A10E6F6FEBF88C9C6832D784240002502D53FC8FFBFB06BED7DAA7242400059350873FBFFBFA0AAD0402C7142408038BA4A777700C0004E2844C06742400005508C2C7900C078A52C431C67424080C0C8CB9A7800C0D0031F83156542408014AE47E17A00C0809065C1C463424080101D02478200C0584CDE0033634240002EAC1BEFEE00C050499D80265E424080C745B5880801C0B068ACFD9D5D424080FFFFFFFF7F01C0282CF180B25B4240009EE925C69201C0A0ECF483BA5C424000838769DFBC01C0E0BB783F6E5F424000B48D3F51D901C030D8463CD961424000A243E0484002C0385C8FC2F568424000BD6E11184B02C0B05CA8FC6B69424000CEF9298E6302C0D88BDAFD2A6A424080A143E048C002C0886308008E6B42400011548D5ECD02C0D0C77C40A06B424000C4EBFA05DB03C038F04E3E3D6A424080819197357104C0D8B2B5BE48684240809CBCC8047C04C05837177FDB6742400094490D6DA004C0507FBDC28265424000630CACE3B804C0E0F4D901D7634240007E37DDB2C304C09081204086624240009DF3531CC704C008D9243FE26142400055DB4DF0CD04C028172AFF5A60424080CCCCCCCCCC04C0580ABABDA45F4240802B7FBE2DD804C0089700FC535E4240002EAC1BEFEE04C008BEDBBC715C424080B91457951D05C0E0EE5701BE5942408077BAF3C43305C0C8F71A82E358424000D7A3703D8A05C0A86E2EFEB657424080E17A14AEC705C0306E15C4405742408008AA46AF2606C0D876137CD356424080AF3DB324E006C028E109BDFE58424000F0A1444BFE06C0B853E57B465A42408083BEF4F60707C088992842EA5A4240006F10AD150D07C008C79E3D975B42400022A81ABD1A07C0B0716F7EC35C424080AF743E3C2B07C0881B62BCE65D4240802B7FBE2D5807C0805704FF5B5F424080E9245B5D6E07C0809C69C2F65F424000000000000009C0E000DE02096042408070067FBFD809C0084E2844C05F4240009EE925C6120AC060853FC39B5F42408084EB51B89E0AC0002A8E03AF5E4240808D959867C50AC030E44A3D0B5E4240002C7FBE2DD80AC0080341800C5D4240807A14AE47E10AC0805A457F685C42400003232F6BE20AC0889065C1C45B424080B94BE2ACE80AC0904B00FE295B42408070067FBF580BC0C8F71A82E3584240006DE34F54760BC0D8CABDC0AC58424080C972124A9F0BC0B0E0F0828858424000838769DFBC0BC0786649809A584240805FE97C78D60BC0C8F71A82E3584240005708ABB1E40BC0B8AAD0402C594240003F00A94D3C0CC0E0C77C40A05B42408039B01C21C30CC060853FC39B5F424080D349B6BADC0CC0B8BC5642775F424080406491261E0DC0D8F19881CA5E424080C3EBFA055B0DC0881B62BCE65D424000EE74E789670DC0587FBDC2825D424000F71E2E398E0DC080CC07043A5D42400055DB4DF0CD0DC0785182FE425D424000698995D1480EC03841B8020A5F42400083BEF4F6870EC008000000006042400079E75086CA0EC0B8B393C15160424000D671FC501910C030DB87BCE55E42404092E52494AE10C0B8C8E880245C4240C08618AF79F510C03814E97E4E5B424000CFF412634911C0801EA33CF35A4240C0643909A54F11C0801EA33CF35A42408079E2395B7011C0D0F4D901D75B424080B06F27119111C028232E008D5C4240C0893BDEE49711C008BEDBBC715C424040C1C3B46F9E11C0080C0401325C42404002284696BC11C0D8C1FA3F87594240009A94826EBF11C0E07C957CEC584240C0332E1C08D911C030DEC83CF253424080DF4DB7ECF011C0500ABABDA44F424000F3C98AE1FA11C08896E7C1DD4D4240802502D53F8812C058F833BC5941424000FA7DFFE69512C0F82F1004C84042400094128255D512C000C45DBD8A3E4240C0CB9A58E0DB12C0A8DA6E826F3E424040C2BE9D440413C0E0AC33BE2F3E42408001F6D1A90B13C050499D80263E4240407365506D2013C06076FA415D3E4240801E4E603A2D13C0508E0244C13E424040880E81234113C00821CB82893F424080EA1F44325413C05037177FDB3F4240C03AAB05F66813C0306552431B404240C039B01C218313C0306552431B40424040B29C84D2A713C05037177FDB3F424040D4449F8FC213C008DC65BFEE3E4240C08096AE604B14C0805D86FF743942408091EA3BBF5814C08018213CDA38424000FED2A23EA914C0306893C327354240C0D79E5912B014C008D6E3BED53442404021AD31E8B414C000BEDBBC71344240007365506DE014C0E0BB783F6E2F424040560DC2DC3E15C0801B62BCE61D424000880E81234115C0885182FE421D42404055DB4DF04D15C0C80F23844719424040941282555515C0385FD042021642408000E143895615C0B0D11DC4CE14424040CCB392566C15C0A81A683EE7144240C015A4198B8615C0E076137CD316424040508BC1C39415C0903FFCFCF716424040E49D4319AA15C028DB87BCE5164240C01B261AA4B015C0608E0244C1164240C00CFFE906BA15C00048A643A71542404083BEF4F6C715C0A8B915C26A1242400016A4198BC615C058465C001A114240C00CFFE906BA15C010D061BEBC0A424080D79E5912B015C0588BC1C3B409424080B392567CB315C088457EFD100942408001F6D1A9CB15C0F8298E03AF064240C0DC2571567416C000301004C8004240C079E2395B3017C0805D86FF7409424080726A67983A17C07854C37E4F0A4240C0B3C9E1933E17C0A0984A3FE10A424080137CD3F44917C000240C03960C424080B06F27115117C030327381CB0D424000CEC29E765817C030DB87BCE50E4240C00F2219725C17C0A0BC5642770F4240404A09C1AA6A17C0D00F238447114240C085E63A8D8417C020232E008D14424000CFF412638917C0789FAA420315424080BC732843A517C000DC65BFEE164240003883BF5FAC17C0E009A1832E174240C0DD205A2B1A18C060853FC39B174240C0B7054B752118C0B8BCAB1E3017424080666666662618C0A8A44E40131742408019FED30D3418C0B0656B7D911842404061DF4E22A218C0B0A44E401327424040F6234564E818C09015E0BBCD3342404001F6D1A90B19C080A86DC3283C4240C010548D5E0D19C00848A643A73D4240C05DBC1FB7FF18C030DEC83CF23B4240008718AF79F518C008E869C0203B4240002EAC1BEFEE18C0386211C30E3B4240001059A489E718C01015C781573B4240C07A14AE47E118C0909065C1C43B4240C00F221972DC18C058707841443C424080DF4DB7ECB018C0A8C2D842904142400021AD31E8B418C0D006600322424240403883BF5FEC18C030266F80994942408077BAF3C4F318C0B8B915C26A4A4240C01B261AA43019C0D8C43BC0934E4240C0D571FC505919C0D8BB783F6E4F424080CDC7B5A17219C028DB87BCE54E4240C004508C2C7919C0883FFCFCF74E4240C0C41D6FF28B19C05837177FDB4F4240C0963AC8EB9119C080C9C6832D504240C07F643A749A19C0A8AAD0402C514240800778D2C2B519C000BB9A3C6557424000F3C98AE1BA19C0786649809A584240400AD7A370BD19C0000F45813E594240409544F641C619C088423D7D045C424040C2BE9D44C419C03029B000A65E4240005EBC1FB7BF19C0E009A1832E5F4240C0953FDF166C19C0E0AC33BE2F6E4240800E2C47C8501AC0001E8A027D824240C04C310741E71AC0889065C1C48B424080C1C3B46F9E1BC030ED0DBE3095424040B60E0EF6D61BC0B0893E1F659C4240C080971936EA1BC0206F2BBD369B42408005A1BC8FE31BC0507F8461C0964240C0E68D93C2FC1BC0D08EE21C75984240000F27309D361CC0B0B05241459B4240805A626534521CC0D8F4D901D79B4240003201BF46821CC0D00CE2033B9C42408023D5777EB11CC08815E0BBCD9B4240C0698995D1081DC0A8E67283A19A424080CEF9298E231DC038F04E3E3D9A4240C010548D5E4D1DC0100F45813E99424040D349B6BA5C1DC080C9C6832D984240C0295778975B1DC02820ED7F809742404015A930B6601DC06040DAFF00974240C09DEE3CF16C1DC08060C77F8196424040CFF41263891DC0E0CDFE40B9954240002C7FBE2D981DC00809C38025974240C00AD28C45A31DC0B874B0FECF99424040965AEF37BA1DC0805A457F68A042408046AF0628BD1DC0883FFCFCF7AE424040137CD3F4C91DC0B0E3310395B5424040CEC29E76D81DC08081204086BA424040A5660FB4E21DC0B868ACFD9DBD42408079E2395BF01DC05037177FDBBF4240003AB01C21031EC0B0984A3FE1C24240405A80B6D50C1EC0B8AA5E7EA7C3424000342E1C08191EC0888D2441B8C64240807138F3ABC91DC0D8C1FA3F87D942404081919735B11DC0686D37C137DF424080EA1F4432941DC0903CBB7CEBE1424040C2BE9D44841DC0F8E769C020E34240C0BF9657AE471DC038172AFF5AE84240004F594DD7231DC08048BF7D1DEE424080758D96031D1DC0A0BC564277EF4240007E37DDB2031DC0E876137CD3F642400090BDDEFD011DC02820ED7F80F742400090BDDEFD011DC06834D6FECEFA4240C0272A1BD6041DC0A8716F7EC3FC4240807138F3AB091DC01048A643A7FD4240C085E63A8D041DC060FB743C66FE42408058350873FB1CC0E076137CD3FE4240008A3BDEE4D71CC058853FC39BFF424000B4C9E1937E1CC0E00F23844701434080D9CBB6D3061CC010C79E3D97034340802A52616C011CC0B059677C5F04434080BA46CB81CE1BC0783CBB7CEB114340C015A4198BC61BC008D6E3BED514434000EE79FEB4C11BC0D0F19881CA164340401553E927BC1BC0F0517FBDC21A4340C039B01C21C31BC0E87954FCDF1B4340C057039486CA1BC030DEC83CF21B434040CEC29E76D81BC0D0C77C40A01B43400005508C2CF91BC06034D6FECE1A434080570394860A1CC0888AE3C0AB19434000C51D6FF20B1CC000E2E7BF071943408052B3075A111CC0B8E0F0828818434040758D96031D1CC08821E4BCFF174340C0402D060F531CC05076FA415D164340803BDD79E2591CC0009700FC53164340001059A489671CC0808461C092174340C0B94BE2AC681CC0904E417E3618434080EB51B81E851CC0483A58FFE71C4340C0AD47E17A941CC03020ED7F801F43400084B9DDCBAD1CC0805A457F6824434000282A1BD6C41CC038E109BDFE28434000342E1C08191DC0C8B5F63E55354340406BB6F2921F1DC038E44A3D0B36434040B29C84D2271DC03829B000A63643400017D68D77371DC008D3A23EC9374340404487C091401DC0A8B393C15138434080698995D1481DC0D8C1FA3F873943404016DBA4A2111DC0B0A10DC0065A4340C0067DE9ED0F1DC0A86BED7DAA5A4340C0570394860A1DC038232E008D5C4340C01D537765071DC080CC07043A5D43408058350873FB1CC0D0FA5B02F05D4340C0A57EDE54D41CC040F88903E85F43404054E0641BA81CC0E0A6B1BD16644340009CC1DF2F561CC0881EA33CF36A4340000AD7A3703D1CC050499D80266E4340006AC020E9D31BC05882FE428F82434040CC9541B5D11BC0089A417C60834340402C7FBE2DD81BC0306E15C44087434000C8409E5DEE1BC0202CF180B28B434080EB51B81E051CC0E0CDFE40B98D4340C0F97DFFE6151CC028DB87BCE58E434040FED2A23E291CC0B86E2EFEB68F43404077BAF3C4331CC03038F581E48F4340800CFFE9063A1CC078A52C431C8F4340003AB01C21431CC0002A8E03AF8E434000FED2A23E691CC0381A6B7F678D4340400F27309D761CC0D8B5F63E558D4340002DB1321A891CC0801B62BCE68D434080963AC8EB911CC0A8AD11C1388E43408091EA3BBF981CC000DC65BFEE8E4340C0C0C8CB9AF81CC0B0B05241459B434040880E8123411DC0B8A78FC01FAC434080570394864A1DC0588BC1C3B4B143408060E4654D7C1DC030DB87BCE5BE434080EB51B81E851DC02820ED7F80BF4340005EBC1FB7FF1DC0B8716F7EC3CC4340C0D11C59F9051EC0580438BD8BCD4340C0E7F7FD9B171EC088457EFD10D14340C0295778971B1EC0803CBB7CEBD1434040D39FFD48211EC048AD307DAFD54340C0B94BE2ACA81DC028E78BBD17D34340007B14AE47A11DC0D0FD9C82FCD24340C077B5DC99591DC0A8B915C26AD24340C0BFCDE2C5521DC08081204086D24340C010548D5E4D1DC0E082177D05D3434080726A67983A1DC060431B800DD44340C052B3075A111DC0385FD04202D64340C0570394860A1DC030E44A3D0BD6434080FCA5457DD21CC0201A6B7F67D5434080E49D4319AA1CC0B8ECF483BAD44340008FC2F5289C1CC030F6D03E56D4434000583A1F9E951CC060F5F23B4DD443404034B918033B1CC098D233BDC4D44340C0436D1B46311CC07048A30227D543400016DBA4A2111CC068FB743C66D64340008718AF79F51BC0A8716F7EC3DC4340001C5DA5BB7B1BC04873B9C15001444080583508737B1BC0E0D03FC1C502444080BF9657AE871BC00048A643A7054440007592AD2EB71BC0889FAA42030D44408046AF0628BD1BC05031957EC20D444080EB51B81EC51BC0B0DA6E826F0E4440C010548D5ECD1BC0F8DB65BFEE0E444080A3703D0AD71BC0E076137CD30E444040A0168387E91BC0A8A44E40130F4440806F0B96EAF21BC0D8BB783F6E0F444000282A1BD6041CC030EACC3D241044400011548D5E0D1CC030D8463CD911444080CB9A58E01B1CC0D000DE020918444040BD6E11180B1CC0B0BF97C2831C4440C0D11C59F9051CC0500438BD8B1D444040419B1C3EC91BC0C028B34126214440801281EA1FA41BC08093A641D12044400083BEF4F6871BC06073B9C15021444040560DC2DC7E1BC0508BC1C3B421444040F8C08EFF721BC0608E0244C122444080402D060F531BC0886649809A284440003AB01C21431BC0F8264D83A2314440C0CFEFFB372F1BC0F0E769C020434440807B0F971C471BC08096E7C1DD5D44404021AD31E8341BC058888043A86C4440406F0B96EA321BC0B8E33103956D4440007592AD2E371BC03038F581E46F44400084B9DDCB6D1BC0E00F238447794440006DE34F54761BC0B0B915C26A7A444040022846967C1BC0D0D03FC1C57A4440800E2C47C8901BC0B8716F7EC37C444000B9196EC0B71BC0808AE3C0AB814440C00CFFE906BA1BC09054C37E4F82444000C6A4BF97B21BC000BE4D7FF68344408078EC67B1641BC0682B137EA9834440C0A3703D0A571BC060431B800D84444000630CACE3381BC0B89509BFD485444040272F32011F1BC038EACC3D24884440C0402D060F131BC0503D997FF4894440C085E63A8D041BC0E088997D1E8D444000C2BE9D44041BC060FB743C668E4440C0DBF3FC69031BC008C11C3D7E914440003AB01C21C31AC0B0E67283A19A444040560DC2DCBE1AC0604CDE00339B4440000455A357931AC0B05626FC529F444000630CACE3781AC00021CB82899F44404078EC67B1641AC0286E15C4409F444080963AC8EB511AC0002A8E03AF9E4440401C5DA5BB3B1AC06040DAFF009F444080570394860A1AC0783CBB7CEBA14440004487C091C019C08893A641D1A8444040C8409E5D6E19C0682E54FEB5B04440C02DAC1BEF2E19C0D8D38041D2B7444080630795B8DE18C0909065C1C4C3444000E8F7FD9BD718C0B09ECC3FFAC44440806CE8667FD018C0E0AC33BE2FC64440C0415F7AFBC318C0E07C957CECC8444080BDDC2747C118C0F0D05B3CBCC94440C05DBC1FB7BF18C0386BD44334CA4440407B0F971CC718C0B87A32FFE8CB4440003201BF460219C008274D83A2D14440C0D6A3703D0A19C08854C37E4FD2444000B16A10E63619C0583A58FFE7D4444040CEF9298E6319C028E44A3D0BD64440406F0B96EAB219C06040DAFF00D744408002284696BC19C0A8A44E4013D74440C0643909A5CF19C05076FA415DD64440407365506DE019C0D8B5F63E55D54440000AD7A370FD19C070A86DC328D44440009544F641061AC050888043A8D4444080F6234564281AC0883FFCFCF7D64440805D85949F341AC0587C7C4276D84440C08618AF79351AC068F833BC59D94440001C261AA4301AC0883CBB7CEBE1444040D349B6BA1C1AC060FEB5BC72EB4440C0C51858C7311AC0285FD04202F64440007365506D601AC078A2EBC20FFA4440803AAB05F6681AC0785D86FF74F944400005508C2C791AC00818080264F84440C0FFFFFFFFBF1AC02838F581E4F74440807138F3ABC91AC02838F581E4F74440401F80D426DE1AC02838F581E4F74440400DFAD2DB9F1BC0E07C957CECF8444000B4C9E193BE1BC0D8C1FA3F87F94440801D537765C71BC0583D997FF4F9444080C1C3B46FEE1BC090689082A7FC4440003AB01C21031CC0381DACFF73FA4440C05C8AABCA0E1CC0883CBB7CEBF9444080C8772975391CC0D0EE5701BEF94440004487C091401CC0E073D2FBC6F9444040C2F5285C4F1CC05882FE428FFA444040A69883A0531CC0386211C30EFB4440C0402D060F531CC0282CF180B2FB444080630795B85E1CC008A0C37C79FD4440C0F3FBFECD6B1CC0089700FC53FE4440004487C091801CC080A52C431CFF444080698995D1881CC0885704FF5BFF444040C2F5285C8F1CC0286E15C440FF444040B6F1272ABB1CC0B0B6D4415EFD4440005EBC1FB7BF1CC000D6E3BED5FC4440C058350873BB1CC0D000DE0209F84440806F0B96EAB21CC0E0F19881CAF6444080C51858C7B11CC08048BF7D1DF64440009A94826EBF1CC0E0FD9C82FCF244400011548D5ECD1CC048465C001AF144408090BB0853D41CC0C0075A8121F14440C0BFCDE2C5121DC008C45DBD8AEE4440C0402D060F531DC078A86DC328EC444080B4C4CA68A41DC028F911BF62E944404021AD31E8B41DC0000F45813EE9444040C8409E5D6E1EC0D0B837BF61EA444080CDC7B5A1721EC0B0984A3FE1EA4440C0355B79C96F1EC0D80CE2033BEC444080B4C4CA68641EC0588E0244C1EE444040560DC2DCBE1EC000C79E3D97F3444080EB51B81EC51EC0D8F4D901D7F3444000C0CDE2C5D21EC0789065C1C4F34440807138F3AB091FC0A8984A3FE1F24440805EB7088C651FC02829B000A6EE4440C0B8196EC0771FC0507FBDC282ED444080F0A1444B7E1FC0C888997D1EED444080EB51B81E851FC0386893C327ED444000D0EFFB37AF1FC0302F3201BFF0444040726A6798BA1FC0909C69C2F6EF4440608940F50F1220C008D9243FE2E94440004FCC7A311C20C0A8B9A3FFE5E8444000E5B67D8F2220C028172AFF5AE84440C09DEE3CF12C20C060853FC39BE74440E0DBF3FC694320C0908461C092E744406083BEF4F64720C0908461C092E7444040B6D782DE5320C048683D7C99E8444040AF5B04C65220C0803CBB7CEBE94440C0963AC8EB5120C0D87954FCDFEB444060FCA5457D5220C05831957EC2ED4440406EF7729F5420C0A85FE97C78EE4440C03BDD79E25920C02820ED7F80EF444000B265F9BA5C20C0B8E9B303AEEF444000D12170246020C05837177FDBEF4440E056B3CEF86620C0B8E9B303AEEF4440407AFB73D16820C0909C69C2F6EF4440E082A5BA806F20C0302CF180B2F34440E0A8C0C9367020C050F5F23B4DF4444000F60A0BEE6F20C0203B3602F1F44440E09DEE3CF16C20C070AEEFC341F64440407AFB73D16820C03820ED7F80F74440406EF7729F5420C0A8ECF483BAFC444000F94B8BFA4420C04837177FDBFF444040A8A78FC03720C058465C001A01454060DF4DB7EC3020C0508BC1C3B4014540C0942BBCCB2D20C0F80582001902454020414640852B20C06007793D9802454000D7A3703D2A20C0E8AF743E3C0345402053CC41D02920C0C8F4D901D7034540607AFB73D12820C000DC65BFEE064540E0F3FBFECD2B20C0D8B2B5BE48084540A047E17A142E20C09093A641D1084540C0BD874B8E6320C0D082177D05134540E06778B3066720C04065FCFB8C134540E0C75EEFFE8020C0D0EE5701BE11454020272F32019F20C0885182FE420D4540A0B4C4CA68E420C03835B401D80A454060FCA5457DF220C03835B401D80A454060FFE6C5890721C0B86BED7DAA0A454000FDBE7FF30A21C05807793D980A454000F1BA7EC13621C0888461C092074540407D3CF4DD3D21C0B877F17EDC06454080D00836AE4721C028327381CB05454060EE92382B7A21C038F6D03E56FC4440C02094F7717C21C0002DCF83BBFB44408046AF06287D21C000E869C020FB4440408446B0717D21C0883CBB7CEBF94440E08EA9BBB28321C00818080264F84440201268B0A98B21C0803FFCFCF7F644408052B3075A9121C08048BF7D1DF64440A01820D104A221C0D891CEC0C8F5444000342DB132B221C00009C38025F3444060E5CFB705BB21C0D08558FD11F0444080C1C3B46FBE21C0386552431BF0444000DCF3FC69C321C090457EFD10F1444080D9CBB6D3C621C03820ED7F80F744406085CD0017CC21C0B09509BFD40D4540E0FCBE7FF3CA21C0A05FE97C780E454060E7DEC3259F21C0B09B8BBFED1745400067614F3B8C21C01842791F471B4540E085E63A8D8421C0A8B7239C161C4540608940F50F7221C0608E0244C11E45402053CC41D04921C0503A58FFE7244540A03AAB05F62821C038F6D03E562C4540407AFB73D12821C0809FAA42032D454040333333333321C0805182FE422D45402039B5334C3D21C030D505BCCC2C4540E08EA9BBB24321C010C79E3D972B454000D9B27C5D4E21C0E07C957CEC28454080E81038125021C0A8B393C15128454080DF4DB7EC5021C0480ABABDA427454040ABE80FCD4C21C0D8C43BC09326454000EB387EA84C21C08096E7C1DD25454000D0EFFB374F21C0301A6B7F67254540A03DEC85025E21C09015E0BBCD234540A05EB7088C8521C0B0AAD0402C214540E0B81AD9959621C040AA0CE36E20454020B16A10E6B621C0B86E2EFEB61F4540E0AE42CA4FBA21C0084E2844C01F45406086FF7403BD21C080C9C6832D204540406EF7729FB421C0781B62BCE6254540C0389CF9D5A421C0A8A10DC0062A4540206DE34F549621C0D8AF743E3C2B4540E013950D6B6221C03014E97E4E334540005B5D4E095821C0000341800C354540E0F50A0BEE4F21C0608E0244C136454000F73C7FDA6021C0504F1F813F3845404083BEF4F66721C000D3A23EC9374540E09CBCC8047C21C0D8B5F63E5535454000F73C7FDA8021C060F5F23B4D34454080E063B0E28C21C0604CDE0033334540E0FECEF6E88D21C03017B83CD632454040807EDFBF9121C0F8872D3D9A324540C0BA46CB81AE21C000068200193245402061DF4E22C221C010CD203EB0354540C0BD874B8EC321C080AEEFC341364540E09FFD4811D121C0E0F4D901D73B4540204C18CDCACE21C020327381CB3D454060F6234564C821C0808461C0923F4540A02FD978B0C521C0D000DE020940454080F0A1444BBE21C0386552431B4045408061F88898BA21C0889C69C2F63F454020A8A78FC0B721C0F020CB82893F4540003E05C078B621C010DC65BFEE3E45404018EAB0C2B521C0001286014B3E4540400F27309DB621C0605260014C3D45400035423F53B721C050888043A83C4540C0321AF9BCBA21C028F6D03E563C454080F964C570BD21C038DEC83CF23B454060747973B8BE21C02814E97E4E3B4540A046AF0628BD21C080A2EBC20F3A4540E08827BB99B921C010068200193A45406085CD0017AC21C0F8E769C0203B454000C85EEFFEA021C010DC65BFEE3E454040A35703949E21C0101E8A027D4245408008AA46AFA621C000240C0396444540401B2B31CFAA21C0A8DA6E826F46454000CEE0EF17AB21C0B0A44E401347454060B29C84D2A721C0A8C2D8429049454060EB51B81EA521C0B8A10DC0064A4540E0ED79FEB4A121C038D8463CD949454020272F32019F21C0905D86FF7449454080DC0C37E09B21C0E0EE5701BE494540004C18CDCA8E21C060F5F23B4D4C454060C1C3B46F7E21C0908AE3C0AB514540A05B76887F7021C0B0DA6E826F564540E079E2395B7021C090457EFD10594540E0FC4CBD6E7121C0D04F1C40BF59454020594E42E9B321C08087A2409F544540408B4F0130D621C0089D82FC6C504540C091EA3BBFD821C0E000DE020950454040747973B8DE21C048499D80264E4540609A94826EDF21C0381A6B7F674D454000560DC2DCDE21C040D505BCCC4C4540E0976C3CD8E221C0E082177D054B454040AC1A84B9FD21C080A86DC32844454060A9D903AD0822C0F8CF61BEBC42454040B4AB90F20B22C0004BE7C3B3424540203CF6B3581222C0D8AF743E3C43454000D462F0301522C0302CF180B2434540609A94826E1F22C0C88BDAFD2A4A45406086FF74031D22C000E52840144E454080D68A36C71122C08896E7C1DD55454000EB387EA80C22C0D0F71A82E358454060975302620A22C0206BD443345A4540E00AD28C450322C058707841445C4540C0A3703D0AD721C008BEDBBC7164454060AF5B04C6D221C0500438BD8B654540C0B4C4CA680422C0009A417C60634540003883BF5F2C22C0508E0244C15E4540408B4F01303622C0A0B393C15160454060E7DEC3253F22C0A8B915C26A62454060B29C84D24722C05831957EC2654540205AB917984522C0101286014B664540E0F63C7FDA4022C0908D2441B8664540004D4A41B73F22C0B8622AFD846B4540607138F3AB4922C05055A1815872454060F3E2C4575322C08860C77F8176454060747973B85E22C0803CBB7CEB794540C0A02FBDFD6122C038266F8099794540E08EA9BBB28322C088CC07043A75454040687572868A22C0580DFB3DB1744540608B4F01309622C010E5284014764540A0677A89B18422C028E44A3D0B864540608E90813C6B22C0806308008E9345404024EEB1F46922C078A86DC32894454020B16A10E65622C000D3A23EC997454040975302624A22C0602E54FEB5984540A0BD874B8E4322C0B0AAD0402C9945406091D101494022C0D00F238447994540E0942BBCCB2D22C00018080264984540408940F50F1222C010068200199A454080FFE6C589E721C0507FBDC2829D454060E7DEC325DF21C02829B000A69E45406094128255F521C0B86BED7DAAA24540400F27309DF621C0F814C78157A3454000FA7DFFE6F521C078423D7D04A4454060E8103812F021C09087A2409FA44540A02616F88AE621C0A8E3310395A545402015A930B6C021C0E07C957CECA84540E0A23EC91DA621C010D9243FE2A94540600E2C47C89021C0E0F19881CAA6454040AF5B04C67221C0885182FE42A54540408C81751C6721C0A8716F7EC3A4454000C85EEFFE6021C0301A6B7F67A54540A02C98F8A35021C0D876137CD3A6454080643909A5CF20C0000F45813EB14540607AFB73D1A820C0382CF180B2B345406083BEF4F68720C0488E0244C1C6454000DCF3FC690320C00806820019DA4540C0E7F7FD9B971FC0A874B0FECFE14540000F27309D761FC02835B401D8E2454000DAC69FA86C1FC0803CBB7CEBE1454000963FDF166C1FC0D00F238447E14540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('SW','SE','SWE','752','Sweden','41033','9038049','150','154','15.27','62.011','0106000020E61000001300000001030000000100000040000000C0AC33BE2FD6304038D8463CD9694C40C05A0A48FBD33040F0264D83A2694C40F0A9F23D23D13040588BC1C3B4694C40F057C9C7EECE304000C11C3D7E694C40405C8FC2F5C83040B0E9B303AE674C401021CB8289C73040F808C38025674C4050ED0DBE30C530408096E7C1DD654C400026AAB706BA304008D9243FE2594C4020CF83BBB3A23040B8B915C26A424C40E0C77C40A0933040D8A6B1BD16344C40A0A2EBC20F923040101E8A027D324C40A0EF3504C7913040888AE3C0AB314C4050C2137AFD913040604F1F813F304C40E03DB2B96A923040808461C0922F4C40E034EF38459330405840DAFF002F4C400015C7815793304078AEEFC3412E4C404055A18158923040081B4982702D4C40C0E33103958D3040E873D2FBC6294C404040DAFF007F3040E876137CD31E4C40F04334BA837C3040B868ACFD9D1D4C40000F45813E793040A8ECF483BA1C4C407017EFC7ED6F3040386211C30E1B4C40405FD042026E304010D061BEBC1A4C40202DCF83BB6B3040D082177D051B4C40A0812040866A3040806308008E1B4C40F02E6D382C69304028D505BCCC1C4C40406E15C44067304028E78BBD17234C40A0F4143944643040A8622AFD843B4C4040895E46B1643040082DCF83BB434C40D0B5F63E5565304008240C0396444C40E0420246976B3040386211C30E4B4C408014AE47E18A3040089A417C60634C40900C1D3BA89C30400809C380256F4C408096E7C1DD9D3040D0D38041D26F4C4050C1E10511A13040A8E0F08288704C40A004FD851EA5304050465C001A714C406037177FDBBF3040D8B2B5BE48784C4070465C001AD93040804E417E36884C402077D84466E63040E00F238447914C40B068ACFD9DF530408887A2409F9C4C40D03FC1C58AF63040B0B6D4415E9D4C40208E3D7B2EF7304000DC65BFEE9E4C4090116DC7D4F53040E0F71A82E3A04C4010809BC58BF5304028E78BBD17A34C40801B62BCE6F53040D87954FCDFA34C40B05626FC52F73040B0E3310395A54C40F02E6D382CF93040A8A44E4013A74C40E042024697FB30401018080264A84C40D031AEB838FE3040A0C2D84290A94C40A0069B3A8F023140504CDE0033AB4C40C0488446B005314088A86DC328AC4C4070465C001A093140100341800CAD4C4040DC2A88810E3140D87FD6FCF8AD4C40F00E45813E19314090397AFCDEAC4C4090FE7A85051B314000240C0396AC4C40D04E0647C91F314090457EFD10A94C4050BFD2F9F00C31402838F581E4974C40C053E57B46023140D8F71A82E3904C4050E44A3D0BF6304008274D83A2894C40C050A4FB39ED304088397AFCDE844C40107497C459E130405840DAFF00774C40E02E6D382CD9304088423D7D046C4C40D05626FC52D7304080812040866A4C40C0AC33BE2FD6304038D8463CD9694C400103000000010000004E000000A0716F7EC3343240B0ECF483BA744C40E0AF743E3C2B3240D8BEB9BF7A744C4090116DC7D4253240B0ECF483BA744C40B07A32FFE8233240E088997D1E754C40E0BEB9BF7A24324028327381CB754C40A0E0F08288283240B8E0F08288784C4030809BC58B3532406028D2FD9C7E4C40800F5EBBB4413240A8A78FC01F844C40E0A9F23D23413240D0066003228A4C40B059677C5F2C3240D88BDAFD2A924C40A0FB3905F92532409048BF7D1D9E4C408000193A76283240089D82FC6CA84C40E0BEB9BF7A243240805A457F68B44C40A0035ABA821D3240480438BD8BBD4C4000917EFB3A1C32402820ED7F80BF4C4090A86DC3281C3240908AE3C0ABC14C40E04334BA831C3240001E8A027DC24C4060DC2A88811E324008DFA63FFBC34C40C0DDAF027C23324000C45DBD8AC64C408096E7C1DD2D32403814E97E4ECB4C40101D02470231324090F3FE3F4ECC4C40A0AEEFC341363240500438BD8BCD4C4060D026874F3A324088AEEFC341CE4C40305FD042023E32403841B8020ACF4C40E04E0647C93F3240B8BC564277CF4C40F0298E03AF463240B8AAD0402CD14C40307A19C5724B3240A86BED7DAAD24C4080129F3BC1563240206E15C440D74C4050E78BBD175B324090457EFD10D94C40C0EF3504C761324008DFA63FFBDB4C4090F27684D366324000C45DBD8ADE4C40407A19C5726B32405073B9C150E14C40E05147C7D5743240508E0244C1E64C4050C422861D76324010BB9A3C65E74C409009DCBA9B773240B09B8BBFEDE74C4050C763062A7B3240F02F1004C8E84C40D0C43BC093AE3240283B3602F1F44C40D04543C6A3B03240885182FE42F54C40B05626FC52B73240781B62BCE6F54C4050AA0B7899B932408848BF7D1DF64C40A0EF3504C7E13240D8CDFE40B9F54C4060C554FA09E73240600438BD8BF54C40F025AAB706EA3240081B498270F54C4090ABAE433501334058F5F23B4DF44C40D046753A90013340602B137EA9F34C4050E109BDFE003340286211C30EF34C40C0E0F0828808334038D8463CD9E94C40F07EF8F9EFED3240F0298E03AFDE4C4090F755B950D9324050F5F23B4DDC4C401009C38025CF324080A2EBC20FDA4C4040E78BBD17CB3240A059677C5FD44C40001E8A027DC2324000E2E7BF07C14C409087A2409FC4324000BEDBBC71BC4C40901A3048FAC432407815E0BBCDBB4C40B074B0FECFC9324028F911BF62B94C4050DB87BCE5B6324060853FC39B9F4C4080AEEFC341B6324000DC65BFEE9E4C409000193A76A8324050707841449C4C40605260014C8D324000BB9A3C65974C40A09065C1C483324000CD203EB0954C40908461C0927F3240286893C327954C408087A2409F743240D8A6B1BD16944C40107D5A457F703240886308008E934C407034D6FECE6A3240281DACFF73924C40C0488446B0653240A8AAD0402C914C40F00B04013264324010CADFBDA3904C400082397AFC6232408821E4BCFF8F4C408000193A76583240306BD443348A4C40D036FE4465573240885D86FF74894C40A0F27684D356324008301004C8884C40801B62BCE6553240D0FD9C82FC824C40B0FB3905F955324030F04E3E3D824C4050BC9179E457324038D8463CD9814C4050B3CEF8BE583240E0D38041D27F4C40001B4982704D32408821E4BCFF774C40D0622AFD844B3240500ABABDA4774C40108E3D7B2E37324080397AFCDE744C40A0716F7EC3343240B0ECF483BA744C400103000000010000001E000000B068ACFD9D5533405055A18158FA4C4030F911BF624933408021E4BCFFF74C4060C554FA0947334038172AFF5AF84C4090AEEFC341463340305C8FC2F5F84C407087A2409F443340A85CA8FC6BF94C40800F5EBBB4413340E0C1FA3F87F94C4050BFD2F9F03C334078ABAE4335F94C40702B137EA92B3340803FFCFCF7F64C40A08AE3C0AB2933403829B000A6F64C406028D2FD9C263340B0E3310395F54C40D0B5F63E55253340283B3602F1F44C40A0F4143944243340F80B040132F44C40007976F9D623334060793BC269F34C40C0B2B5BE48203340B0DDAF027CEB4C4060BC9179E4173340000341800CED4C40C07A32FFE81333408896E7C1DDED4C4040CF83BBB312334060FB743C66EE4C4070AA0B789909334000D061BEBCF24C409093A641D10833400015C78157F34C409093A641D108334038D505BCCCF44C40F00E45813E093340B0E3310395F54C4090129F3BC1163340100C040132FC4C40B0E0F082881833408887A2409FFC4C405034D6FECE1A334000D6E3BED5FC4C40F02E6D382C493340809FAA4203FD4C40C0F5B704E04B3340809FAA4203FD4C40908D2441B84E3340A8ECF483BAFC4C40A004FD851E553340806308008EFB4C40801B62BCE6553340881EA33CF3FA4C40B068ACFD9D5533405055A18158FA4C4001030000000100000017000000809BC6F65A302740905704FF5BF74C40C0622AFD842B27400009C38025F74C4000B728B341262740386E15C440F74C40A0FA96395D0E274060F833BC59F94C40E0622AFD840B274040D8463CD9F94C40E07A14AE47092740D8C1FA3F87FD4C40801A3048FA042740082A8E03AFFE4C402009C38025FF2640E0F71A82E3004D40E0C43BC093FE264008274D83A2014D404038A11001FF264088423D7D04044D40E0D8D0CDFE002740500DFB3DB1044D40E089592F860A27409048BF7D1D064D4040D367075C0F2740081286014B064D40C04CA3C9C578274090E464E256054D40607A19C5727B2740B07A32FFE8034D4080BEA085047C2740604CDE0033034D4080F755B950792740A0656B7D91004D40A0BC9179E4772740D8D38041D2FF4C40E0B5F63E55752740586D37C137FF4C40C0AA24B20F722740508E0244C1FE4C4000274D83A25127405882FE428FFA4C40202C9D0FCF4A2740588BC1C3B4F94C40809BC6F65A302740905704FF5BF74C400103000000010000000A00000050C1E10511D13040B077F17EDC0E4D40A0E0F08288C83040B859677C5F0C4D40B05626FC52C7304080397AFCDE0C4D40208E3D7B2EC73040A868ACFD9D0D4D40B04D637B2DC830404876FA415D0E4D40708AE3C0ABC9304020DB87BCE50E4D40F087BB7A15CD304010D3A23EC90F4D40808461C092CF3040B89B8BBFED0F4D4000274D83A2D13040F020CB82890F4D4050C1E10511D13040B077F17EDC0E4D400103000000010000001F000000A0B5DD04DF9C2740D8BB783F6E0F4D40C06ABB09BE992740883FFCFCF70E4D40C076BF0AF06D2740283B3602F10C4D4040D026874F5A274050888043A80C4D40202FDE8FDB3F27406831957EC20D4D4000EB56CF493F2740A85FE97C780E4D404020990E9D362740D809A1832E0F4D40208A592F862A2740606D37C1370F4D40809885764E1B2740588E0244C10E4D40A0F1D3B837EF2640B09ECC3FFA0C4D4020DC2A8881EE264060707841440C4D40C032384A5EED2640B0AAD0402C094D404069C53714EE2640587C7C4276084D40009CDF30D1E82640C80F238447094D40202A8E03AFE6264030D8463CD9094D408032384A5ECD2640E0CABDC0AC104D40A02975C938CE2640E0C1FA3F87114D40406BD44334D22640A0984A3FE1124D40E05FE97C78562740885A457F68244D406014AE47E15A2740600DFB3DB1244D40C01EA33CF36A274008240C0396244D408045B9347E71274000BEDBBC71244D40C02634492C79274058431B800D244D4000D13FC1C5922740E0BB783F6E1F4D40E0955D30B89E2740B8ECF483BA1C4D408021E4BCFF9F274060431B800D1C4D40C0656B7D91A027400815C781571B4D40800F5EBBB4A12740285FD04202164D40E0A9F23D23A127403035B401D8124D40A0EA56CF499F274060465C001A114D40A0B5DD04DF9C2740D8BB783F6E0F4D4001030000000100000011000000700C1D3BA83C3340784B00FE292B4D40D0548847E2393340784B00FE292B4D4070BC9179E4373340886308008E2B4D407017EFC7ED2F33408093A641D1304D401009C380252F3340A05CA8FC6B314D40E04E0647C92F33400006820019324D4070AA0B789939334010D9243FE2314D401082397AFC423340B8AAD0402C314D40F01186014B4E3340D000DE0209304D40506C06B820533340B85626FC522F4D40B0716F7EC3543340A877F17EDC2E4D40007976F9D6533340001286014B2E4D40602E54FEB550334088CC07043A2D4D40D03A71395E4D334068F5F23B4D2C4D4010904C874E4B334008DFA63FFB2B4D40F05D4BC807493340909065C1C42B4D40700C1D3BA83C3340784B00FE292B4D400103000000010000001900000040E109BDFEB03140B8B6D4415E754D40E05147C7D5B43140909065C1C4734D40208BFCFA21B23140A87A32FFE8734D40306893C327AD3140585260014C754D40A0F5B704E0AB3140B09509BFD4754D40F005820019AA31402841B8020A774D40002C2CB81FA43140E0C77C40A07B4D40C0C77C40A0A3314060F5F23B4D7C4D40C0C77C40A0A33140789FAA42037D4D4030F6D03E56A431405828D2FD9C7E4D4070465C001AA93140D0031F8315854D40801EA33CF3AA3140F8298E03AF864D40A09FAA4203AD31406040DAFF00874D4080AD4CF8A5AE314008C45DBD8A864D40B053E57B46B23140D0031F8315854D40C0D38041D2B731408854C37E4F824D4060B3CEF8BEB8314038E109BDFE804D402018080264B83140804E417E36804D40B05626FC52B73140C8BB783F6E7F4D4080F4143944B431405876FA415D7E4D40406BD44334B2314088397AFCDE7C4D40702E54FEB5B03140588BC1C3B4794D40B001BC0512B031403829B000A6764D4040EACC3D24B03140E0FA5B02F0754D4040E109BDFEB03140B8B6D4415E754D400103000000010000001200000040BC9179E4673240306211C30E834D40F04543C6A3603240081E8A027D824D40B0E33103955D32406007793D98824D40207156444D5C3240F8E769C020834D40C0622AFD845B3240F82CCF83BB834D40207A19C5725B3240D8BEB9BF7A844D40D068ACFD9D6532405855A181588A4D40704F1F813F683240D0C77C40A08B4D40B074B0FECF69324088A86DC3288C4D40900F5EBBB4713240D876137CD38E4D402015C7815773324088A52C431C8F4D40E0488446B0753240B85626FC528F4D40604F1F813F783240D8BB783F6E8F4D40D06BED7DAA7A3240905704FF5B8F4D409096E7C1DD7D3240306893C3278D4D40C0E33103957D324030232E008D8C4D4010240C03966C324058888043A8844D4040BC9179E4673240306211C30E834D4001030000000100000011000000F0C1FA3F8789324058888043A89C4D4070BB5F05F886324038232E008D9C4D40B07A32FFE883324058888043A89C4D4040E109BDFE803240583A58FFE79C4D40009C5088806F3240587C7C4276A04D4050B60F79CB6D3240D07C957CECA04D4070B08D78B263324000BEDBBC71A44D4040F6D03E56643240306893C327A54D40D040F33977773240F89FC37C79A54D403083DC45987A3240A0B6D4415EA54D4070AD4CF8A57E324090CC07043AA54D40A0F8F884EC803240B09ECC3FFAA44D4000068200199A3240385C8FC2F5A04D4020917EFB3A9C3240B8E0F08288A04D40D03DB2B96A923240E0CDFE40B99D4D40F0B2B5BE48903240381A6B7F679D4D40F0C1FA3F8789324058888043A89C4D400103000000010000001500000040D9E90775C93140F84D2844C0A74D4070A52C431CC731403820ED7F80A74D40C0A9F23D23C1314050853FC39BA74D4060B3CEF8BEB83140507C7C4276A84D407037177FDBAF3140303E7782FDA94D4060BEA08504AC31403035B401D8AA4D4060D9E90775A93140B87A32FFE8AB4D403069C537149E314088992842EAB24D40B0FE7A85059B3140D8B5F63E55B54D40407156444D9C3140C87FD6FCF8B54D4080FA96395D9E3140009700FC53B64D40502E54FEB5A0314010C45DBD8AB64D40D0E7A4F78DA3314010C45DBD8AB64D40F03FC1C58AA63140081286014BB64D4020D505BCCCBC31406055A18158B24D4060DC2A8881BE314008D9243FE2B14D4060C422861DC63140A06E2EFEB6AF4D4060BB5F05F8C6314080A52C431CAF4D40E025AAB706CA3140E8A9F23D23A94D40E025AAB706CA3140009D82FC6CA84D4040D9E90775C93140F84D2844C0A74D4001030000000100000019000000F0A6B1BD16BC3140781B62BCE6A54D400094BF7B47D13140886308008EA34D40A0A2EBC20FC2314038DEC83CF2A34D40E0C43BC093AE3140D0031F8315A54D40D0CABDC0ACA83140A868ACFD9DA54D40F0AC33BE2FA63140C8FA5B02F0A54D40C0C77C40A0A33140001286014BA64D40F0BB783F6E9F3140B8A44E4013A74D40B059677C5F9C3140E08558FD11A84D4040CDE50643853140E8A6B1BD16B44D40E05147C7D5843140B8ECF483BAB44D4050ED0DBE30853140500438BD8BB54D4050E44A3D0B8631409048BF7D1DB64D40106552431B883140B0DA6E826FB64D40F025AAB7068A31405828D2FD9CB64D40A0A2EBC20F923140B877F17EDCB64D40F0BB783F6E9F3140607C7C4276B04D4090ABAE4335A1314028F38FBE49AF4D40206211C30EA3314060888043A8AC4D40406C06B820A33140B87A32FFE8AB4D4050CF83BBB3A2314000E869C020AB4D4060B950F9D7A23140888AE3C0ABA94D40D034EF3845A3314000E2E7BF07A94D4080116DC7D4A53140E0CABDC0ACA84D40F0A6B1BD16BC3140781B62BCE6A54D4001030000000100000012000000200C040132443140B09B8BBFEDAF4D4020274D83A241314008D3A23EC9AF4D4070C763062A3B3140D88558FD11B04D40F0D38041D227314058465C001AB14D40D0488446B025314000C11C3D7EB14D4060C2137AFD1131401006820019BA4D4070B81E85EB1131406034D6FECEBA4D4050BB5F05F8163140A8984A3FE1BA4D40D03FC1C58A263140281DACFF73BA4D40D0393FC5713C3140A0C2D84290B94D40B0EF3504C7413140B0AAD0402CB94D4030F6D03E564431408818213CDAB84D4020D2C43BC0473140A89B8BBFEDB74D40A0F8F884EC503140D80CE2033BB44D40A05CA8FC6B51314008C79E3D97B34D4080ABAE4335513140801EA33CF3B24D4010F38FBE494F3140301DACFF73B24D40200C040132443140B09B8BBFEDAF4D400103000000010000001A0000000015C7815793324020F911BF62B94D40502E54FEB5903240C80F238447B94D40B0E33103958D324020F911BF62B94D40B0F27684D386324008DFA63FFBBB4D4010809BC58B853240A8BF97C283BC4D40B004FD851E853240781B62BCE6BD4D40B004FD851E8532403829B000A6BE4D4090116DC7D4853240B85626FC52BF4D40D036FE44658732405837177FDBBF4D4070C2137AFD913240089A417C60C34D40B059677C5F9C3240D87FD6FCF8C54D40106BD44334A232401009C38025C74D4090716F7EC3A43240306E15C440C74D40206893C327BD3240E0AC33BE2FC64D4090F1D3B837BF32406031957EC2C54D40C0622AFD84BB3240603A58FFE7C44D4050D9E90775B9324000240C0396C44D4080A52C431CB73240B059677C5FC44D4090FE7A8505AB324058793BC269C34D40F036FE446597324028EACC3D24C04D40102A8E03AF963240D8BB783F6EBF4D40A0A52C431C973240E0F19881CABE4D40209A417C609B32409015E0BBCDBB4D40801EA33CF39A3240D882177D05BB4D402096CE8767953240608BC1C3B4B94D400015C7815793324020F911BF62B94D400103000000010000001400000050B81E85EB91324000BB9A3C65274E40F04E0647C98F3240B8A44E4013274E4020240C03968C3240D009A1832E274E400096CE8767853240009D82FC6C284E40E034EF38458332408018213CDA284E40002A8E03AF663240608E0244C12E4E40603A58FFE7643240809C69C2F62F4E40D0BEB9BF7A643240706649809A304E40C0EF3504C7613240605260014C354E402009C380255F3240306E15C4403F4E40F04E0647C95F3240889C69C2F63F4E40C05CA8FC6B6132406001F73C7F404E40007976F9D6633240682E54FEB5404E40E0CABDC0AC683240889C69C2F63F4E4080A86DC3286C3240001286014B3E4E40C0716F7EC3743240888D2441B8364E4040D8463CD981324028232E008D2C4E40F0C1FA3F87893240D0F4D901D72B4E40C0E67283A1923240306552431B284E4050B81E85EB91324000BB9A3C65274E400103000000010000000F0000005055A181588231408060C77F812E4F40C0A6B1BD167C3140A85FE97C782E4F40603A58FFE7743140608E0244C12E4F40900F5EBBB47131403041B8020A2F4F40D0A6B1BD166C3140A0E9B303AE2F4F40B06BED7DAA6A3140784E417E36304F40A08AE3C0AB6931409093A641D1304F4060DC2A88815E3140002DCF83BB3B4F40505FD042025E3140B059677C5F3C4F40808461C0925F3140A8ECF483BA3C4F40F03FC1C58A76314030E78BBD173B4F40007CB779E3783140B06BED7DAA3A4F4050B08D78B2833140100341800C354F407014AE47E18A3140B877F17EDC2E4F405055A181588231408060C77F812E4F4001030000000100000016000000A08461C0920F32407896E7C1DD554F40A0ECF483BA0C32406031957EC2554F40A06BED7DAA0A324038E44A3D0B564F40000F45813E093240D0C43BC093564F4090F27684D3063240A86E2EFEB6574F40A01B62BCE6053240B8B393C151584F40603A58FFE704324008274D83A2594F406031957EC2053240604CDE00335B4F40D025AAB7060A324060499D80265E4F40102DCF83BB0B3240002A8E03AF5E4F40E0BB783F6E0F3240686D37C1375F4F4080A2EBC20F123240E0BB783F6E5F4F40A0ABAE4335213240D0F19881CA5E4F40000C0401322432405828D2FD9C5E4F40B068ACFD9D25324000E52840145E4F40208E3D7B2E273240485260014C5D4F40A04D637B2D28324028DEC83CF25B4F40A0E9B303AE273240884B00FE295B4F40C050A4FB391D3240B09B8BBFED574F40307A19C5721B3240F8BA9A3C65574F4050D9E90775193240783FFCFCF7564F40A08461C0920F32407896E7C1DD554F400103000000010000001000000030CF83BBB3E23440904E417E36E04F4060CAA48636E034403038F581E4DF4F40106E15C440D73440908AE3C0ABE14F402077D84466D63440B053E57B46E24F40E03FC1C58AD63440E0FD9C82FCE24F409009DCBA9BD73440D8F4D901D7E34F40405C8FC2F5D8344008240C0396E44F408014AE47E1DA3440E088997D1EE54F40908461C092DF3440B09509BFD4E54F40A0069B3A8FE23440901B62BCE6E54F404077D84466E634401048A643A7E54F40100F45813EE93440585260014CE54F4070BEA08504EC3440100C040132E44F40F0CDFE40B9ED3440E0FD9C82FCE24F40C03A71395EED3440E0B837BF61E24F4030CF83BBB3E23440904E417E36E04F40010300000001000000720800000009C38025CF3540BC0166BE83245140206C06B820D3354040BF28417F245140D03A71395EDD35405C2E54FEB524514000274D83A2E13540E88711C2A3245140C0488446B0E53540D4BEB9BF7A245140F028EB3713EF35401863997E89235140C068ACFD9DF535405C34D6FECE225140D0BB783F6EFF354068C18BBE8221514040E109BDFE003640080F45813E2151404031957EC2053640F05AB4006D205140405C8FC2F5083640C0378600E01F51402073F4F8BD093640546D37C1371F5140E04BC5C6BC0A364098DBF63DEA1E514070BFD2F9F00C3640A86BED7DAA1E514020938D075B103640901D1B81781E51405028D2FD9C26364030327381CB1D51408014AE47E12A3640CCCDFE40B91D5140A0F1D3B8375F36407C8AE3C0AB1D5140D031AEB8386E36405C3A58FFE71C51401000000000803640147B681F2B1C5140503A58FFE7943640FC14C781571B5140107CB779E3A83640408386FE091B5140C04334BA83AC3640FCDB65BFEE1A514050B950F9D7D2364000D6E3BED518514070D6A88768D4364094239D81911851402088BB7A15DD3640B0984A3FE1165140109700FC53E636409C0ED6FF39155140D05D4BC807E9364094E1783E03155140B06E2EFEB6EF36408487A2409F145140C04D637B2DF8364030F6D03E56145140207156444D0C37405034D6FECE1251406040DAFF000F3740D8C43BC093125140F0A9F23D23113740E85432005412514020990F08745A374044B665C0590551405069C537145E374010A8FE4124045140407D5A457F6037407C6308008E035140A01A3048FA643740848D2441B8025140206552431B88374090205C0185FF5040A0FDD7B969A337405C73B9C150FD504060C422861DA6374050465C001AFD5040D04D637B2DA837406CD65240DAFC5040A081204086AA37405870784144FC50407034D6FECEAA3740A89B8BBFEDFB5040E0B837BF61AA374094205C0185FB5040107CB779E3A8374090E7FA3E1CFB504070A52C431CA7374064D0D03FC1FA5040000341800CA53740C81C3D7E6FFA5040E0420246979B3740145D177E70F95040F0CABDC0AC9837404C5260014CF95040602B137EA98B3740449E5DBEF5F8504060B950F9D782374030232E008DF850403069C537147E374050431B800DF85040800C1D3BA87C3740D0C77C40A0F75040102DCF83BB7B3740D4AF743E3CF75040C0EAE5779A78374070CA4E3FA8F45040E03730B951783740DCB2B5BE48F4504050B60F79CB7D374028266F8099ED504060C2137AFD81374044C5AA4198EA5040A093A641D178374070C70DBF9BE35040F057C9C7EE6E3740C41F7EFE7BDF50404069C537146E374018A5BDC117DF504060B60F79CB6D3740281DACFF73DE504090FA96395D6E374030327381CBDD5040D0D03FC1C5723740489E5DBEF5DC5040A0F27684D376374068BE4A3E76DC504070D9E90775793740F04EB0FF3ADC5040800C1D3BA87C3740E842ACFE08DC504050EACC3D24803740B09B8BBFEDDB5040106211C30E833740BC438A0112DC504070C554FA09873740D8CABDC0ACDC504040F911BF62893740BC3AC780ECDC504000240C03968C374098E1783E03DD5040A01A3048FA943740189337C0CCDC5040A0A86DC328BC3740ACB0524145DB5040406211C30EC337401499B9C0E5DA504080A7CAF78CC43740C828417FA1DA5040E05147C7D5C43740FC1186014BDA50408000193A76C83740845182FE42D55040B04D637B2DC83740F039E97DE3D45040B0FB3905F9C53740B0A78FC01FD450409017EFC7EDBF37408881204086D25040A096E7C1DDBD3740B0AD11C138D2504020904C874EBB3740A8A10DC006D2504050CDE50643B5374030327381CBD15040C077F17EDCAE374010691B7FA2D15040D0D03FC1C5A2374028ED0DBE30D150408017EFC7ED9F3740080341800CD15040605260014C9D374068D65240DAD05040C0FE7A85059B3740846649809AD05040B04D637B2D9837407C9065C1C4CF5040E0AC33BE2F963740448386FE09CF504070A2EBC20F9237405476FA415DCA50405055A18158923740B0A10DC006CA5040A087A2409F943740145D177E70C9504080FA96395DAE3740408386FE09C3504060C763062ABB3740C022BF7E88C05040E0C43BC093BE37400800000000C0504050C2137AFDC13740C81F7EFE7BBF5040808AE3C0ABC937405C34D6FECEBE5040207FF8F9EFDD3740E884D04197BB5040A08461C092EF37401866DAFE95B85040A0F8F884ECF03740ACB393C151B85040504CDE0033F337400C6F9D7FBBB75040C0B2B5BE480038405C37177FDBB3504040C2137AFD013840D8AF743E3CB3504000274D83A2013840B0984A3FE1B250408017EFC7EDFF37402829B000A6B2504050B5DD04DFFC3740D4C43BC093B2504040CF83BBB3F23740146058FE7CB250407037177FDBEF37405476FA415DB25040A0716F7EC3E43740149CFA40F2AF5040F07876F9D6E337407C6308008EAF5040002C2CB81FE43740546D37C137AF50405028D2FD9CE6374028266F8099AD504090A52C431CE737401463997E89AB504030F6D03E56E437409C0ED6FF39A55040604CDE0033E33740D8BEB9BF7AA450406055A18158E23740C864E3C116A45040B0F8F884ECE037405C2B137EA9A3504080F1D3B837DF37403014E97E4EA35040800C1D3BA8DC374090E7FA3E1CA3504070B08D78B2D337405C34D6FECEA2504060AD4CF8A5CE3740A4B915C26AA25040908AE3C0ABB9374050431B800DA050401083DC4598AA3740C8310400C79D5040E0CABDC0ACA83740EC5DF580799D504060BB5F05F8A6374058465C001A9D504040809BC58BA53740540DFB3DB19C5040B07A32FFE8A33740AC7A32FFE89B5040D0C77C40A0A33740806308008E9B5040E02E6D382CA9374040B324404D94504070D9E90775A93740FCDEA63FFB9350401083DC4598AA3740FC14C7815793504020F38FBE49AF374068D65240DA905040206552431BB83740B846CB811E8D5040007CB779E3B837407893A641D18C504060D026874FBA3740C422BF7E888C504010917EFB3ABC3740D4B2B5BE488C504080ABAE4335C13740D8F4D901D78B5040C057C9C7EECE3740AC77F17EDC8A504040C2137AFDD13740A86BED7DAA8A504040465C001AD93740E8543200548A5040B050A4FB39DD3740D8AC33BE2F8A5040E0A9F23D23E137407006F1811D8A504030895E46B1E43740E83C2AFEEF89504070AA0B7899E93740EC7E4E417E89504050BFD2F9F0EC3740449E5DBEF5885040001286014BEE3740D4CABDC0AC885040702E54FEB5F03740889065C1C487504050B950F9D7F237401C6058FE7C86504050D2C43BC0F73740E88711C2A384504010857AFA08083840545260014C81504060465C001A2938405431957EC2755040C06BED7DAA2A384044AA61BF2775504050C763062A2B3840D8BEB9BF7A745040103483F8C02A38400406820019745040F08D3D7B2E273840846308008E735040A01A3048FA2438403014E97E4E7350404040DAFF001F384004E869C02073504060C763062A1B3840506D37C13773504030895E46B1143840E884D04197735040C03A71395E0D3840A86E2EFEB673504070D026874F0A3840D8C77C40A0735040E0393FC571FC3740808D2441B8725040C0716F7EC3F43740D8AC33BE2F72504050B08D78B2F3374018967840D971504050B950F9D7F237407C5D86FF74715040D03C80457EF13740040341800C7150407037177FDBEF3740500DFB3DB170504030CC423BA7ED3740E87B0DC171705040A06BED7DAAEA374044BF28417F70504070C422861DC6374008D061BEBC725040A0116DC7D4C5374040A4DFBE0E735040C036FE4465A7374070C70DBF9B73504030895E46B184374044B0E3BF4073504030F38FBE496F3740D4CABDC0AC705040A01A3048FA643740BC46CB811E7150408017EFC7ED3F374044B0E3BF4073504040BEA085043C374068F7AB00DF705040F02B2CB81F243740D4EE5701BE6D5040900F5EBBB421374040C269C18B6D5040A0716F7EC3143740C42EC37FBA6C504070B950F9D7123740A49ECC3FFA6C5040A001BC05120037409C0B957F2D705040000C040132D43640980B957F2D745040B0E7A4F78DD3364000D6E3BED574504030CF83BBB3D2364044AA61BF2775504050D026874FCA36405834D6FECE765040E02E6D382CB93640582E54FEB5785040809FAA4203AD3640D4EE5701BE795040000341800CA53640543D997FF4795040506C06B820A33640C8310400C7795040C0DDAF027CA33640805D86FF74795040209700FC53A63640F439E97DE3785040E04BC5C6BCAA3640E85AB4006D785040900C1D3BA8AC3640940B957F2D7850403069C53714AE3640AC7A32FFE8775040F057C9C7EEAE36406CC70DBF9B77504060D6A88768B43640C42B82FFAD73504050D367075CAF3640F039E97DE370504080035ABA82AD36401466DAFE95705040F099417C60AB3640A8B393C151705040305C8FC2F5A83640B0A78FC01F70504040E44A3D0BA63640E442ACFE0870504080129F3BC1A63640F05AB4006D70504010857AFA08A8364070D65240DA705040504F1F813FA836408CED7C3F35715040D03FC1C58AA63640A874B0FECF715040A015E0BBCD9B36405440DAFF00735040B06BED7DAA7A3640981D1B8178765040B0E7A4F78D733640DCF19881CA76504050C763062A6B36405C40DAFF0077504040EACC3D2460364010A5BDC117775040306893C3275D3640E83F6B7EFC765040C0420246975B3640D8D03FC1C576504090F414394454364050465C001A75504040C2137AFD413640F04EB0FF3A6C504020F0C000C23F3640D8BEB9BF7A68504020F758FAD0453640F48AE07F2B6850400069AA27F3473640D094D6DF1268504020E33444154A3640B8E3BF4010685040A0AE601BF14C36405013EF004F68504040C1E10511513640846308008E675040C053E57B4652364004DFA63FFB675040201E8A027D5236402CF6D03E5668504040C1E105115136408087A2409F6850401009C380254F364070F7AB00DF685040407156444D4C3640941ADA006C69504070D9E9077549364030F04E3E3D6A5040C0EAE5779A48364068C4CC3E8F6A5040B0073E062B4A3640D8D03FC1C56A5040F0CDFE40B94D364040E603029D6A504050CF83BBB3523640E0AC33BE2F6A504040CF83BBB3623640504F1F813F685040E0393FC5716C3640849065C1C4635040206893C3276D364094E7FA3E1C635040C059677C5F6C3640188DB5BFB36250402083DC45986A36403CB9A6406662504060BC9179E467364094F0BDBF41625040503A58FFE7643640281DACFF7362504070C1E1051161364004DC65BFEE625040E0CDFE40B95D3640BCFE243E7763504010187AC4E83D3640787B1002F2645040703733FAD1343640BCB3E89D0A65504060D6A88768143640AC77F17EDC665040206893C327DD3540AC6BED7DAA6A5040C06BED7DAADA3540AC984A3FE16A5040F0CABDC0ACD8354000E869C0206B5040406E15C440D73540E878CC40656B504050B08D78B2D335408887A2409F6C5040A053E57B46D23540F439E97DE36C504030F6D03E56C435402CF04E3E3D6E5040F0D03FC1C5C2354000D9243FE26D5040604CDE0033C3354040C269C18B6D5040A01B62BCE6C53540E48711C2A36C5040E05A0A48FBD33540D0C43BC0936A504060BC9179E4D7354000068200196A5040F0B837BF61DA354004D9243FE26950404031957EC20536409411178046665040F0753579CA0E36406CCD8FBFB4655040F0CDFE40B91D36405C73B9C15065504040CAA4863620364054465C001A6550401082397AFC3236401C99B9C0E5625040800F5EBBB431364048E603029D62504070D367075C2F3640A8B915C26A6250400026AAB7062A36406806F1811D625040A0F486FBC80D36400427DBC01D615040A001BC05120036406CF7AB00DF60504030D505BCCCFC3540A49ECC3FFA60504050B3CEF8BEE8354070CD8FBFB461504070AEEFC341E6354070FAEC80EB61504090F4143944E43540B8490C022B625040406C06B820E33540D4B837BF616250400094BF7B47E135405455A1815862504020DEC83CF2DB35409CE4B9BE0F62504020F04E3E3DDA354070FAEC80EB615040502B137EA9DB3540208A743FA7615040102A8E03AFE6354004D3A23EC95F5040E025AAB706EA3540A8B05241455F5040809FAA4203ED3540B0A44E40135F5040C0656B7D91F0354048A4DFBE0E5F504080A86DC328EC3540EC7B0DC17160504060B5DD04DFEC3540540DFB3DB16050405037177FDBEF3540C40166BE83605040D06BED7DAAFA3540FC14C781575F504050D2C43BC0073640C42500FF945D5040406552431B083640805182FE425D5040E0BEB9BF7A043640D4BB783F6E5B504040CF83BBB302364004E869C0205B5040107FF8F9EFED3540E85DF58079595040909FAA4203AD3540FCE1E7BF07595040F0C1FA3F87A93540000341800C5950407031957EC2A53540BC46CB811E59504040CF83BBB3A235405C73B9C15059504010301004C8A035403CC269C18B595040E04334BA839C3540DCB837BF615A50400026AAB7069A354040C5AA41985A504090AEEFC3419635402829B000A65A5040407A19C5728B35407006F1811D5A504020F911BF62793540282F3201BF58504050BC9179E4773540941799805F5850401016DD7A4D7F3540FCCF61BEBC56504060C8073D9B8135408484EFFD0D5650405001A260C68835407C7B1002F25450409021C841098B3540A489B0E1E954504050D6A8876894354010A8FE4124545040C05FE97C789635407C5A457F6854504090A52C431C973540149337C0CC54504090AEEFC34196354054465C001A55504090129F3BC1963540885182FE42555040C0ECF483BA9C3540F439E97DE3545040A0F1D3B8379F3540D8CABDC0AC545040001E8A027DB235403029B000A652504060D6A88768B4354040B9A6406652504090F4143944B4354018A27C410B52504090FDD7B969B33540545260014C51504050B81E85EBB13540C03AC780EC505040503D997FF4A93540D4F4D901D74F50408009DCBA9BA73540D8C77C40A04F5040E03FC1C58A963540BC404981054F5040402E54FEB5903540C4344580D34E5040E0CDFE40B98D3540BC404981054F5040407156444D8C354028F38FBE494F504090812040868A35403038F581E44F50400073F4F8BD89354094239D819150504070EBE0606F7E3540A0957B815952504020857AFA087835407878CF81E55350409015C440D7763540F8B1F4A10B545040F03FC1C58A5635405C2B137EA9575040206211C30E5335406CD311C0CD575040009D82FC6C5035405C2B137EA9575040000C040132443540B09509BFD455504030CF83BBB342354028266F8099555040E02B2CB81F443540DCB5F63E55555040206BD44334523540582E54FEB5545040A0AEEFC3415635401866DAFE955450406034D6FECE6A3540EC84D04197535040207497C459813540AC7A32FFE84F5040407156444D8C35400CA27C410B4E50401009C380258F3540EC7E4E417E4D50400088BB7A159D35403CB9A640664A5040B077F17EDC9E354030327381CB495040A0F1D3B8379F3540805D86FF74495040D028EB37139F354054465C001A49504000A0C37C7995354070006F8104445040809065C1C49335402C2CF180B24350409018213CDA9035406CC70DBF9B435040F0C682C2A08835405431957EC243504050DC2A88817E3540AC7A32FFE8435040502B137EA97B3540D0D38041D2435040E05D4BC807793540582B137EA943504050BC9179E4773540D8AF743E3C435040A0E9B303AE773540AC984A3FE14250408000193A7678354040ADA23F34425040A014AE47E17A35404080457EFD415040F040F3397777354070BE4A3E76405040A08461C0925F3540C81C3D7E6F3E5040809FAA42034D3540EC45ED7E153D50401094BF7B47413540A8716F7EC33C5040C0DA6E826F3E35406CCA4E3FA83C504050A7CAF78C3435406803B00111395040503A58FFE7343540C42EC37FBA38504000A0C37C79353540584CDE0033375040B077F17EDC2E3540BC46CB811E355040900F5EBBB4213540845A457F68345040F0BB783F6E1F354034172AFF5A34504050DEC83CF21B354044BF28417F345040305C8FC2F51835404C0DFB3DB13450401021CB8289173540409E5DBEF53450407031957EC2153540C004A73E9035504040E44A3D0B163540FC1186014B365040A004FD851E1535403CC5AA419836504030CF83BBB31235405834D6FECE365040209C5088800F3540D8D03FC1C5365040C0622AFD840B354090F0BDBF4136504020068200190A3540F8D8243FE235504050D9E90775093540E87E4E417E355040200F45813E093540B0716F7EC334504020068200190A354070BE4A3E76345040C0622AFD840B3540980B957F2D345040A004FD851E1535409C1D1B817832504050C554FA09173540ACAD11C138325040305C8FC2F51835404480457EFD315040F099417C601B3540C4310400C7315040D01D8CD827203540C4581822A7315040C0ABADD85F2235404CD7851F9C3150409093A641D12835400C691B7FA231504060C554FA093735400806820019325040F04BC5C6BC3A354010A27C410B325040108BFCFA214235405831957EC2315040901EA33CF34A354090ED7C3F35315040C03A71395E4D35400C9F3BC1FE30504020763579CA4E3540C02EC37FBA305040808461C0924F354050431B800D3050403069C537144E35405C76FA415D2A5040B0073E062B4A3540146058FE7C2A5040406E15C440473540B06BED7DAA2A5040B0716F7EC3443540AC984A3FE12A5040206893C3273D35405C37177FDB2B504060D9E9077529354098F0BDBF412E5040B0BF42E6CA2435405876FA415D2E504040072461DF2235401C9C887E6D2E5040903C821B291F3540702711E15F2E5040A014AE47E11A354098F0BDBF412E5040E04BC5C6BC1A354000D9243FE22D5040900C1D3BA81C3540F04EB0FF3A2C5040B0DA6E826F1E35406CC70DBF9B2B5040C053E57B4622354004E869C0202B504020A0C37C79453540E857738060275040109A417C605B3540A874B0FECF255040F04334BA835C3540ACAD11C138265040107FF8F9EF5D354040C5AA4198265040A08461C0925F354008D061BEBC26504080A52C431C77354008D6E3BED52450407096E7C1DD8D3540FCE42840142250405031957EC295354018A8FE41241C504070CDE5064375354094E7FA3E1C175040E05A0A48FB633540805D86FF74155040F01D8A027D523540D4F4D901D713504050CAA4863650354040C8EBC1A4135040100F45813E49354010A5BDC117135040102A8E03AF463540FCDB65BFEE12504070D6A88768443540AC984A3FE1125040001E8A027D42354098E7FA3E1C135040108BFCFA2142354038BCE7C0721350401094BF7B474135401490F63FC013504070499D80263E35405C37177FDB13504090A86DC3283C3540F084D0419713504070B3CEF8BEF834406CC18BBE820950409004FD851EF53440BC3AC780EC08504090F4143944F434401866DAFE95085040A0E9B303AEE73440844B00FE2903504060CDE50643E5344094EA3BBF28005040D0AF743E3CCB3440885D86FF74F14F4090A52C431CC73440286E15C440EF4F4030ED0DBE30C53440908D2441B8EE4F40A081204086BA344028232E008DEC4F4080FDD7B969A33440306552431BE84F40305C8FC2F5883440001286014BE64F40A0A2EBC20F82344028E109BDFEE84F408017EFC7ED7F34405073B9C150E94F4060DC2A88817E34408018213CDAE84F40A0E67283A172344090457EFD10E14F40701EA33CF36A34406073B9C150D94F40C0548847E2693440607C7C4276D84F40106211C30E633440101286014BD64F4040C1E1051161344008E5284014D64F40708D2441B85E3440B05FE97C78D64F4050C1E10511513440E0BEB9BF7AD44F40E0393FC5714C344010D061BEBCD24F40C0E7A4F78D43344088CC07043AD54F4050AA0B789919344028DEC83CF2D34F40406211C30E03344030F911BF62D14F4080AEEFC341E63340D87FD6FCF8CD4F40A087A2409FE43340A068ACFD9DCD4F40D05FE97C78C633406070784144C44F40F04E0647C9BF3340D006600322C24F4030F38FBE49BF334058F833BC59C14F40906E2EFEB6BF3340D0CABDC0ACC04F4050C1E10511C1334038EACC3D24C04F400082397AFCC23340580ABABDA4BF4F40C05147C7D5C43340B8DA6E826FBE4F40E040F33977C73340604CDE0033BB4F40807347FFCBC5334038E3C28190BA4F40E0BEB9BF7AB4334028F38FBE49B74F40A077F17EDCAE33405040DAFF00B74F40C0FE7A8505AB3340606D37C137B74F40F02B2CB81FA4334008CADFBDA3B84F40F0D03FC1C5A23340A0AAD0402CB94F40207976F9D6A33340E0D03FC1C5BA4F408087A2409FA4334048FEB5BC72BB4F4020895E46B1A4334078A86DC328BC4F40809065C1C4A33340B8716F7EC3BC4F4050B60F79CB9D3340B05626FC52BF4F40109D82FC6C803340009700FC53C64F402073F4F8BD793340500ABABDA4C74F40202A8E03AF763340D0D38041D2C74F40E05A0A48FB73334058853FC39BC74F40A0E33103956D3340009700FC53C64F4010917EFB3A6C33408896E7C1DDC54F40700C1D3BA86C334028ED0DBE30C54F40200F45813E793340303E7782FDB94F40101E8A027D72334030172AFF5AB84F4040CC423BA75D3340B0E9B303AEB74F40E025AAB7065A3340A86E2EFEB6B74F40F03C80457E51334008C11C3D7EB94F40A001BC0512503340B8A10DC006BA4F40106A87BF264F33400815C78157BB4F4030DEC83CF24B33400815C78157BB4F4020068200194A33405834D6FECEBA4F40B0E0F08288483340D08BDAFD2ABA4F40106E15C440473340A85CA8FC6BB94F4090AEEFC341463340A8656B7D91B84F404028D2FD9C463340D8CDFE40B9B54F4060C554FA0947334028F6D03E56B44F40A0FE7A85053B3340783CBB7CEBA94F40C0EAE5779A28334028172AFF5AA84F40007976F9D6233340B86E2EFEB6A74F407040DAFF000F3340507C7C4276A04F40602B137EA90B334028F38FBE499F4F40D0B837BF610A334000C45DBD8A9E4F4020904C874E0B334038ED0DBE309D4F4090ECF483BA0C334030DEC83CF29B4F4010F38FBE490F3340302CF180B29B4F40A0116DC7D415334058793BC2699B4F409015E0BBCD1B33401015C781579B4F4000917EFB3A1C3340B86BED7DAA9A4F4060C1E10511113340B077F17EDC964F40D057C9C7EE0E3340B0DA6E826F964F4060BEA085040C3340009700FC53964F4060D9E90775093340D8C43BC093964F40305C8FC2F5F83240A8984A3FE19A4F401021CB8289F7324050FEB5BC729B4F406028D2FD9CF6324090423D7D049C4F4050C554FA09F7324000D6E3BED59C4F4070A52C431CF73240580438BD8B9D4F40A0716F7EC3F4324000BB9A3C659F4F40B05626FC52E7324088992842EAA24F40709065C1C4E33240C882177D05A34F4040F0C000C2CF3240D8FD63213AA04F40D0D7497D59CE3240D000DE0209A04F4050629F008ACD324028F0C000C29F4F407054FCDF11CD324058B56B425A9F4F4030083BC5AACD32400091B75CFD9E4F4030F6B4C35FCF32403853E8BCC69E4F40C08C2958E3D8324080EEAF1EF79D4F406064575A46E2324038656EBE119D4F408000193A76E8324090992842EA9A4F4050D026874FEA3240281DACFF739A4F404031957EC2E53240B8E0F08288984F40107CB779E3C83240B0ECF483BA944F406028D2FD9CC6324008D6E3BED5944F4070B950F9D7C2324028327381CB954F40307D5A457FC03240500ABABDA4974F4010A96A82A8BF324060492BBEA1984F40E0421EC18DC0324070730E9E09994F40605B9544F6C13240607094BC3A994F40909D7FBBECC33240607094BC3A994F4050BC9179E4C7324098088D60E3984F40700EBA8443CB3240A005137F14994F4030ED7F80B5CA324030AE635C71994F40802040868EC93240E8BE805EB8994F40302A8D98D9C73240A0FC4FFEEE994F40C0012EC896C5324078A2EBC20F9A4F40107E703E75BC3240E8B5BDDD929A4F40E0C551B989BA3240E8B5BDDD929A4F40C0DAFCBFEAB83240909CF7FF719A4F40B0A52BD846B832407867D13B159A4F40B083674293B83240686DC5FEB2994F40207156444DBC3240F8E4284014964F40C050A4FB39BD324000A0C37C79954F40E0488446B0A53240203E7782FD914F40F0A9F23D239132403841B8020A8F4F4030D8463CD96132406028D2FD9C864F400026AAB7064A3240500ABABDA47F4F4050B3CEF8BE583240A85FE97C787E4F40405FD042025E324028DB87BCE57E4F40007976F9D66332400009C380257F4F4050C554FA096732400009C380257F4F404077D84466863240E8AC33BE2F7E4F40C0073E062B8A3240305FD042027E4F40201B4982708D3240E0CDFE40B97D4F406037177FDB8F3240605260014C7D4F400094BF7B47913240A8716F7EC37C4F40D0C77C40A0933240D8C77C40A07B4F4070A7CAF78C9432408854C37E4F7A4F40B0E7A4F78D933240D8EE5701BE794F4090F755B95079324058FB743C666E4F40F020CB82897732408096E7C1DD6D4F402096CE8767353240602B137EA9634F40206211C30E3332400015C78157634F40D0B2B5BE48203240B0A10DC006624F4020ED0DBE3015324008DFA63FFB634F40F04BC5C6BC1A324010DC65BFEE664F4060C1E10511213240883FFCFCF7664F40A0FDD7B96923324030F38FBE49674F4040ED0DBE30253240E0D38041D2674F40B004FD851E253240B0E0F08288684F40E034EF384523324000E2E7BF07694F40F0D03FC1C512324030E78BBD176B4F40D0C1FA3F8709324058793BC2696B4F4080A86DC328FC3140080F45813E694F4000990F0874FA3140582E54FEB5684F40E0C1FA3F87F931405837177FDB674F40001B498270ED3140D8F4D901D76B4F4020F38FBE49DF3140B8E3310395754F4040D505BCCCDC3140E0BB783F6E774F4070BC9179E4D73140804B00FE297B4F4060431B800DD431400009C380257F4F4070C2137AFDD13140B0BC5642777F4F40E0C77C40A0B33140D8BB783F6E7F4F405055A18158B23140883FFCFCF77E4F40709065C1C4B33140B0DA6E826F7E4F40C0FE7A8505BB3140A8BF97C2837C4F40602E54FEB5C03140F8E769C0207B4F4020A0C37C79C531408854C37E4F7A4F4070C763062ACB3140908AE3C0AB794F40F0488446B0D53140B8BC564277774F40A0EF3504C7E1314058465C001A714F4060AD4CF8A5FE3140587FBDC2825D4F40F0A9F23D23013240306BD443345A4F4090ABAE4335013240382F3201BF584F40F028EB3713FF314048431B800D544F4060B60F79CBFD314010C79E3D97534F40B06BED7DAAFA3140806308008E534F4040DB87BCE5F63140B8BF97C283544F40901A3048FAF4314000CD203EB0554F40D053E57B46F231406031957EC2554F4080ABAE4335E1314000CD203EB0554F40D04E0647C9DF3140080341800C554F40702E54FEB5E0314010BEDBBC71544F40A0E67283A1E2314000DFA63FFB534F40D036FE4465F7314078ABAE4335514F40007CB779E308324078C9C6832D504F40602B137EA90B3240E0D38041D24F4F40307156444D0C3240B09ECC3FFA4C4F40407A19C5720B324060793BC2694B4F40E0B837BF61FA3140A8A44E4013474F4070BC9179E4D731405876FA415D3E4F40A01B62BCE6D53140D8FA5B02F03D4F40D034EF3845D33140D0CDFE40B93D4F405037177FDBCF314030327381CB3D4F40B0073E062BCA3140B09B8BBFED3F4F40E0D38041D2C73140B8B393C151404F4070D6A88768C43140109D82FC6C404F40200F45813EB931405037177FDB3F4F40D03C80457EB13140C809A1832E3F4F40009C508880AF3140508E0244C13E4F40B0EAE5779AA8314000240C03963C4F40E040F33977A731408815E0BBCD3B4F4040F911BF62A93140B8E67283A13A4F40306893C327AD3140588BC1C3B4394F40A0F5B704E0AB3140D000DE0209384F4050DC2A88819E3140808461C092374F4050E78BBD179B3140B0E9B303AE374F40109D82FC6C90314038172AFF5A384F40002DCF83BB8B3140E8A9F23D23394F409074B0FECF89314028266F8099394F40D036FE446587314010D061BEBC3A4F40C0E7A4F78D833140E0031F83153D4F40D0A9F23D23813140B0AD11C1383E4F40D0C1FA3F877931408093A641D1404F409021E4BCFF6F3140D0F4D901D7434F4080A86DC3286C3140B0716F7EC3444F4050B3CEF8BE68314088397AFCDE444F4080129F3BC1663140905A457F68444F40B068ACFD9D553140783FFCFCF73E4F40100C040132543140089700FC533E4F401015C7815753314010A0C37C793D4F40E0A6B1BD165C31409048BF7D1D2E4F4090F1D3B8375F3140D0066003222A4F4050CAA48636603140D0C1FA3F87294F4090A52C431C773140303E7782FD214F409056B5A4A3803140F096395D16214F406007B29E5A8D314040622D3E05204F40A0DB1324B693314030682101A31F4F40C06E2EFEB69F31403829B000A61E4F4050CDE50643A53140D87FD6FCF81D4F40A009DCBA9BA73140A8E33103951D4F40009700FC53A63140E088997D1E1D4F4080AA0B78999931406034D6FECE1A4F4060DC2A88818E314000E2E7BF07194F40E0420246978B314080ABAE4335194F40808AE3C0AB893140908AE3C0AB194F40F02E6D382C8931408054C37E4F1A4F40F0548847E2893140D882177D051B4F401051137D3E8E314070E2AB1DC51B4F40A0CC3FFA2691314098FC3383F81C4F4030959A3DD08E314060944BE3171E4F40B04A3FE1EC8A3140F8264D83A21D4F40207156444D883140286B9BE2711D4F40304BADF71B853140C040BB438A1D4F40507D923B6C823140B89140834D1D4F4080C823B89182314090BDA59C2F1A4F40102043C70E823140F80C8CBCAC194F40C0B1F677B67B3140082159C004104F40002A8E03AF7631409093A641D1004F40C0C77C40A073314058853FC39BFF4E4040B81E85EB713140A8A44E4013FF4E40A017EFC7ED6F31402829B000A6FE4E40101B4982706D3140B0DA6E826FFE4E4050E78BBD176B3140E076137CD3FE4E40C0EAE5779A6831403041B8020AFF4E403077D84466663140888D2441B8FE4E4040895E46B164314060499D8026FE4E40C06BED7DAA5A3140D8EE5701BEF94E40F0C1FA3F8759314038E109BDFEF84E402018080264583140D0C43BC093F64E4070C422861D563140582E54FEB5E84E40002EC901BB62314008C765DCD4E04E40502E54FEB5703140080341800CDD4E40704F1F813F783140D0CDFE40B9DD4E40A0F5B704E07B3140500438BD8BDD4E4070AD4CF8A57E314030ED0DBE30DD4E40000000000080314058888043A8DC4E4050E44A3D0B863140B074B0FECFD94E4050E44A3D0B86314058465C001AD94E40D0B2B5BE4880314000D9243FE2D14E40B06E2EFEB67F314038F911BF62D14E40A0FA96395D7E3140282F3201BFD04E4090ECF483BA7C314080C9C6832DD04E40A0073E062B7A3140909C69C2F6CF4E4060C2137AFD7131405001F73C7FD04E4010763579CA6E314000301004C8D04E4070BEA085046C3140B874B0FECFD14E40B0622AFD846B3140F81D8A027DD24E40E025AAB7066A3140002DCF83BBD34E40007976F9D6633140889C69C2F6D74E4070B950F9D7623140A8656B7D91D84E40304CC2853C5E3140C0499A3FA6D94E4020382EE3A65A314070FA5E4370DA4E4050DB87BCE5563140604CDE0033DB4E4050B08D78B253314060FEB5BC72DB4E40A0F5B704E03B3140E0BEB9BF7ADC4E4090E0F0828838314028232E008DDC4E401077D8446626314038F6D03E56DC4E40B07A32FFE8233140A8A78FC01FDC4E4070D6A8876824314060FEB5BC72DB4E4080AEEFC341263140D0FD9C82FCDA4E40A0E0F082882831404807793D98DA4E400029EB37132F314030F04E3E3DDA4E4030D8463CD9313140D8B837BF61DA4E4040ED0DBE30353140B853E57B46DA4E400018080264383140B8A10DC006DA4E40C0D03FC1C5423140507C7C4276D84E40200341800C453140E08558FD11D84E4020809BC58B453140D0BB783F6ED74E4090716F7EC3443140D0C43BC093D64E402015C78157433140901B62BCE6D54E40F04543C6A3303140A85CA8FC6BD14E4090FA96395D2E314090457EFD10D14E40B0F5B704E02B31408018213CDAD04E40A0E0F08288283140C87C957CECD04E400096CE8767253140A8AAD0402CD14E4010301004C8203140303E7782FDD14E40F00E45813E193140306893C327CD4E4070499D80261E314080A52C431CC74E40808AE3C0AB293140E0D03FC1C5C24E40C0FE7A85052B314030F04E3E3DC24E40D05D4BC807393140B0656B7D91B84E40404F1F813F383140883FFCFCF7B64E406028D2FD9C363140B0DA6E826FB64E40B0F5B704E02B3140B09509BFD4B54E40C040F33977273140C8F19881CAB64E40D03FC1C58A26314008BB9A3C65B74E40A09065C1C4233140386E15C440B74E4050BEA085041C3140D00CE2033BB44E40D06BED7DAA1A314000C79E3D97B34E4060D026874F1A31406834D6FECEB24E406034D6FECE1A3140C806600322B24E40B004FD851E25314030327381CBAD4E4060D6A8876834314088A2EBC20FAA4E40102A8E03AF363140808AE3C0ABA94E40D02B2CB81F343140302CF180B2A34E4090FA96395D2E314028172AFF5A984E40204B033FAA293140E07FD6FCF8854E40D03FC1C58A263140285C8FC2F5784E402021CB82892731400018080264784E40D0C77C40A0333140B0B6D4415E754E40F0CDFE40B93D3140B06BED7DAA724E4050AD4CF8A53E314078A2EBC20F724E40002A8E03AF463140A87A32FFE86B4E40B0EAE5779A483140E0D03FC1C5624E40C05D4BC80749314000CD203EB05D4E40C05FE97C7846314000C45DBD8A564E40E0A6B1BD165C3140383E7782FD514E401063997E89603140E84EB0FF3A4F4E406031957EC2653140B8E0F08288504E40A09C69C2F66731408818213CDA504E4040CDE506438531408054C37E4F524E4060499D80268E31405855A18158524E4070431B800D943140903CBB7CEB514E4050DEC83CF29B3140D07C957CEC504E40C0D03FC1C5A23140D809A1832E4F4E40009700FC53A6314078AEEFC3414E4E40C04D637B2DA83140000341800C4D4E40C0F27684D3A63140905A457F684C4E40603A58FFE7A4314010DFA63FFB4B4E4070BEA085049C3140D8D03FC1C54A4E40B0073E062B9A31408854C37E4F4A4E4020F04E3E3D9A314030266F8099494E40D0420246979B3140E009A1832E474E40E0A6B1BD169C31408860C77F81464E40E0A9F23D23A13140B8984A3FE1424E40201E8A027DA231404855A18158424E40C05626FC52A73140D0F71A82E3404E40D0C1FA3F87A931406001F73C7F404E4010763579CAAE3140E0D38041D23F4E40B05CA8FC6BB131403820ED7F803F4E4050C763062ABB314010DC65BFEE3E4E40C0E3310395BD3140D009A1832E3F4E4090035ABA82BD31402838F581E43F4E4090A86DC328BC3140E8A9F23D23414E4050D026874FBA31404855A18158424E40F0548847E2B93140D8FD9C82FC424E402073F4F8BDB9314008BEDBBC71444E402083DC4598BA3140505260014C454E40502B137EA9BB314008E5284014464E40801B62BCE6C5314050465C001A494E40C0E9B303AED73140A8622AFD844B4E40B05CA8FC6BE13140905A457F684C4E40F02B2CB81FE43140A8BF97C2834C4E408017EFC7EDEF314038232E008D4C4E40506C06B820F3314000BEDBBC714C4E40D0B5F63E55F5314058431B800D4C4E4080A52C431CF7314008C79E3D974B4E408000193A76F83140306211C30E4B4E40201286014BFE31400021CB8289474E4060AA0B7899193240383E7782FD394E4090F27684D3363240B87A32FFE82B4E4060D026874F3A3240B853E57B462A4E4060BEA085043C3240B074B0FECF294E40D0DA6E826F3E3240B8A10DC0062A4E40B0656B7D914032404855A181582A4E40406BD44334423240B8984A3FE12A4E4080F4143944443240080C0401322C4E40901B62BCE6453240A0ECF483BA2C4E40D03730B951483240A89ECC3FFA2C4E4020938D075B503240505260014C2D4E40E0C43BC0936E324088423D7D042C4E40402E54FEB5703240E0C77C40A02B4E40201E8A027D723240A8B915C26A2A4E40206E15C440773240109700FC53264E400082397AFC9232400000000000204E40D0548847E2993240B077F17EDC1E4E40D0420246979B32405076FA415D1E4E4070C763062A9B3240B0E33103951D4E40000F45813E993240306893C3271D4E40D0BEB9BF7A943240B0ECF483BA1C4E40C0C43BC0938E3240B0ECF483BA1C4E40809C69C2F6873240000341800C1D4E40B0E0F0828878324000E52840141E4E4080992842EA723240F8298E03AF1E4E4020301004C8703240A0A44E40131F4E4060B5DD04DF6C3240909C69C2F61F4E4090FDD7B969633240D88BDAFD2A224E408017EFC7ED5F324038E78BBD17234E40C06BED7DAA5A324088CC07043A254E400015C7815753324008D3A23EC9274E40602E54FEB5503240306552431B284E40D0B2B5BE48503240B85626FC52274E4020938D075B503240D8C43BC093264E402096CE8767653240B0E67283A11A4E4040DEC83CF26B3240809C69C2F6174E4000FA7DFFE6813240B040BB438A134E40406552431B88324008C79E3D97134E40E0B2B5BE48A03240B06BED7DAA124E4060B08D78B2A33240381DACFF73124E4070C422861DB632400818080264104E40A0F27684D3C63240E0AC33BE2F0E4E4050E109BDFED0324020F6D03E560C4E40C0656B7D91D03240886308008E0B4E40C0656B7D91D0324008068200190A4E4050E109BDFED03240805D86FF74094E4050CF83BBB3D23240F820CB8289074E401082397AFCE23240D0AF743E3CFB4D4020895E46B1E43240B8A10DC006FA4D40B0E9B303AEE73240A0B393C151F84D40207CB779E3E8324008D3A23EC9F74D40505FD04202EE32406076FA415DF64D406001309E41F3324090C3995FCDF54D4060809A5AB6F6324090C3995FCDF54D4050D8463CD901334000D6E3BED5F44D40602B137EA90B334030E78BBD17F34D4080A2EBC20F12334000D9243FE2F14D4060B81E85EB1133400015C78157EB4D40D03C80457E1133406082FE428FEA4D4010301004C810334008D9243FE2E94D400009C380250F334068F833BC59E94D4050BFD2F9F00C33405873B9C150E94D40D0B837BF610A334000274D83A2E94D405028D2FD9C0633409081204086EA4D40A09811DE1EF832400094313ECCEE4D4030861DC6A4EF3240905704FF5BEF4D40E03A71395EDD324048499D8026E64D4030F38FBE49EF324060F5F23B4DE44D40A09C69C2F6F7324060F5F23B4DE44D4070992842EA12334028E78BBD17E34D407087A2409F143340B0E67283A1E24D40100341800C153340583D997FF4E14D40A01A3048FA143340000F45813EE14D40F034EF3845133340D8F19881CADE4D4060B81E85EB113340E0AC33BE2FDE4D40704F1F813F08334080A86DC328DC4D4050B60F79CBFD3240002DCF83BBDB4D409014AE47E1FA3240002DCF83BBDB4D40D02B2CB81FF4324080A86DC328DC4D40E036FE4465D73240504CDE0033DB4D40A077F17EDCBE3240904E417E36D84D408009DCBA9BB73240D0FA5B02F0D54D40A0EF3504C7B132405807793D98D24D40504CDE0033B3324020F04E3E3DD24D40A0116DC7D4B532405855A18158D24D408081204086BA3240D8D03FC1C5D24D40201B498270BD3240D8D03FC1C5D24D4060AD4CF8A5BE324020F04E3E3DD24D4020DEC83CF2BB3240385C8FC2F5D04D403083DC4598AA3240282CF180B2CB4D4050CDE50643A532408854C37E4FCA4D40A018213CDA603240E0F4D901D7BB4D40201286014B5E3240382CF180B2BB4D4070ABAE43355132407887A2409FBC4D409009DCBA9B473240889FAA4203BD4D4050CDE5064345324038D505BCCCBC4D40302D40DB6A42324068F833BC59B94D40302D40DB6A423240D07C957CECB84D40B0F27684D346324008A0C37C79B54D40206552431B483240303B3602F1B44D40A074B0FECF493240D8BEB9BF7AB44D40C0ECF483BA4C3240000C040132B44D40D0DDAF027C533240889065C1C4B34D40B0FB3905F955324060FEB5BC72B34D404077D84466563240E0D03FC1C5B24D40D05147C7D554324028F04E3E3DB24D40101E8A027D523240B8A10DC006B24D4040861DC6A44F3240B8A10DC006B24D4050D505BCCC2C3240B07A32FFE8B34D4020F04E3E3D2A3240D80CE2033BB44D40405C8FC2F5283240B0716F7EC3B44D4080AA0B7899293240101B498270B54D40605260014C2D3240009700FC53B64D4030EACC3D24303240009700FC53B64D4020CF83BBB3323240C87FD6FCF8B54D4050ADBEBA2A3432406870067FBFB64D40D0E07EC003333240F0E7DB82A5B84D40908C0E48C23232400812BF620DB94D40008BFCFA21323240B053E57B46BA4D405037177FDB2F3240001E8A027DBA4D406037177FDB1F3240286BD44334BA4D40C0E33103951D3240383E7782FDB94D4040BB5F05F8163240909C69C2F6B74D40E0488446B015324038F38FBE49B74D4080AD4CF8A50E32400006820019B24D4090129F3BC11632405040DAFF00AF4D40E036FE44651732405834D6FECEAA4D40904C4F58E201324050AA61BF27AC4D40A0F8F884ECF03140881EA33CF3AA4D4070B60F79CBED3140386211C30EAB4D408014AE47E1EA31401015C78157AB4D40A0116DC7D4E5314090423D7D04AC4D4040DEC83CF2DB3140A8E3310395AD4D4030ED0DBE30D53140908D2441B8AE4D40C0F8F884ECD031403020ED7F80AF4D40406893C327CD314030172AFF5AB04D401018080264C83140A874B0FECFB14D4040B08D78B2C33140A8B0524145B34D4040C2137AFDC13140D8BEB9BF7AB44D4050B81E85EBC13140D0FA5B02F0B54D40D053E57B46C23140888D2441B8B64D40A0E9B303AEC7314058499D8026BE4D40E0C1FA3F87C9314010D3A23EC9BF4D401083DC4598CA3140B0E0F08288C04D40505260014CCD3140F8D8243FE2C14D4020E109BDFED03140D0D03FC1C5C24D40E040F33977D73140C8C77C40A0C34D400018080264D83140E00CE2033BC44D40B0E67283A1D231406055A18158CA4D40C0F8F884ECD03140786308008ECB4D401009C38025CF314088423D7D04CC4D40307D5A457FC03140D8EE5701BED14D409009DCBA9BB73140503A58FFE7D44D4030F911BF62B93140382CF180B2D34D40207CB779E3B8314038EACC3D24D04D40C0D38041D2B7314008BB9A3C65CF4D40901B62BCE6B53140686D37C137CF4D40C0BEB9BF7AA4314030266F8099D14D40E006EE409D9A31408072DBBE47D34D408009DCBA9B97314008DFA63FFBD34D40E02E6D382C993140A8BF97C283D44D40B0622AFD849B3140B0ECF483BAD44D40F02F1004C8A03140A8716F7EC3D44D40A07A32FFE8A33140503A58FFE7D44D40C0FB3905F9A5314090CC07043AD54D4070C554FA09A73140E07FD6FCF8D54D40A033863941A73140A053C90050D74D40E040F33977A73140A07A32FFE8DB4D40B007E8BE9CA13140A8560A815CE44D40F02F1004C8A03140A09ECC3FFAE44D40306552431B98314038F38FBE49E74D40A05FE97C789631406040DAFF00E74D40D03FC1C58A963140B8E3310395E54D40D0AC33BE2F963140B0716F7EC3E44D40F095CE8767953140B07A32FFE8E34D4040F6D03E56943140884B00FE29E34D40306211C30E9331408081204086E24D407014AE47E18A3140B09B8BBFEDDF4D408093A641D188314050853FC39BDF4D40C0E7A4F78D833140885704FF5BDF4D4050CF83BBB372314050499D8026DE4D4050D8463CD971314008C45DBD8AD64D4040CF83BBB3823140884B00FE29CB4D40E0B5F63E55853140D006600322CA4D4060C554FA09873140808AE3C0ABC94D40F02E6D382C893140000F45813EC94D40F0C16C020C8B3140B834B74258C94D4020809BC58B85314080AEEFC341CE4D40E05A0A48FB833140488BC1C3B4D14D4080FDD7B9698331409015E0BBCDD34D40A053E57B46823140D000DE0209D84D40406BD44334823140282F3201BFD84D4080069B3A8F823140E0C1FA3F87D94D401015C78157833140B0B915C26ADA4D4060AA0B7899893140D0CDFE40B9DD4D4080129F3BC1963140109700FC53DE4D4080AA0B7899993140109700FC53DE4D4020240C03969C314008E5284014DE4D40101286014B9E3140B868ACFD9DDD4D4020763579CA9E3140A89ECC3FFADC4D40F0CDFE40B99D314000E2E7BF07D94D40D07614E7A88F3140A805A1BC8FD54D404041F0F8F6963140F89672BED8D14D40800F5EBBB4B131405831957EC2CD4D40505FD04202BE314008C79E3D97CB4D4030D8463CD9C1314008D061BEBCCA4D40D0BEB9BF7AC43140D87C957CECC84D4020F911BF62C9314000240C0396C44D40305C8FC2F5C83140909065C1C4C34D40C0ECF483BABC314080ABAE4335B94D4050C763062ABB3140D0CABDC0ACB84D40C03730B951B83140D0CABDC0ACB84D40605260014C8D314008C45DBD8ABE4D40F0AF743E3C8B314010DC65BFEEBE4D40B05FE97C788631400818080264C04D4050ED0DBE30853140E07C957CECC04D40B0B64604E3843140A053C90050C14D4020895E46B1843140B0C2D84290C14D404031957EC28531407854C37E4FC24D4040EFAA07CC8B314048B071FDBBC44D40A001BC0512803140E0031F8315C54D40A0035ABA827D3140001B498270C54D40D03DB2B96A723140B05626FC52C74D40E0B2B5BE48703140A86E2EFEB6C74D40602E54FEB5603140381A6B7F67CD4D40C0BB783F6E5F3140D8FA5B02F0CD4D40F057C9C7EE5E31405828D2FD9CCE4D40A077F17EDC5E3140A85626FC52CF4D4070B950F9D76231400015C78157D34D40306BD44334623140E0F4D901D7D34D4030EACC3D24603140A8DDAF027CD34D40406552431B583140B86E2EFEB6CF4D4010990F08745A3140B8E3310395CD4D40F057C9C7EE5E3140B0E67283A1CA4D40306E15C440673140D076137CD3C64D40306552431B683140B0AD11C138C64D40C0EAE5779A683140580438BD8BC54D4000904C874E6B3140B8A44E4013BF4D40209A417C606B31404876FA415DBE4D40B0FE7A85056B3140B0E3310395BD4D40305C8FC2F568314050431B800DBC4D4060C422861D66314050431B800DBC4D401015C78157533140A05FE97C78BE4D40106211C30E433140A8656B7D91C04D40207497C45941314000E2E7BF07C14D40C0BB783F6E2F3140383B3602F1C44D40305FD042021E31408048BF7D1DC64D40B05CA8FC6B113140A8E3310395C54D405037177FDB0F3140080341800CC54D4010857AFA0808314060888043A8C44D40603A58FFE7043140B8716F7EC3C44D40206C06B820F33040A8E3310395C54D40A0656B7D91F03040901B62BCE6C54D40C037DC476EDD30405876887FD8CA4D40B0E7A4F78DD3304088992842EACA4D4050D9E90775C930400021CB8289C74D4010F911BF62A9304050499D8026C64D40A000193A76A83040908D2441B8C64D40109C5088809F3040381DACFF73CA4D4060B60F79CB9D304088992842EACA4D40602E54FEB5903040D07FD6FCF8CD4D40705260014C8D304060499D8026CE4D40F04BC5C6BC8A3040385FD04202CE4D40C0CABDC0AC88304010CD203EB0CD4D40209D82FC6C80304030F6D03E56CC4D40B077F17EDC7E3040889065C1C4CB4D4070D367075C7F304000E869C020CB4D4020809BC58B853040B8AAD0402CC94D406034D6FECE8A3040D8D38041D2C74D4090A86DC3288C304028F38FBE49C74D40A015E0BBCD8B30408860C77F81C64D4030E78BBD178B3040B868ACFD9DC54D40A074B0FECF893040A89ECC3FFAC44D40D050A4FB397D30403011A8FE41C04D40205C8FC2F5783040B8E9B303AEBF4D40E0BEB9BF7A543040D87954FCDFBB4D40C0E33103952D3040B8622AFD84BB4D4050C763062A2B3040886308008EBB4D40D025AAB7061A304058F5F23B4DBC4D40E040F3397717304008240C0396BC4D4020E109BDFE1030406831957EC2BD4D4000904C874E0B30402841B8020ABF4D4040465C001A093040D8BB783F6EBF4D40D03FC1C58A063040B06E2EFEB6BF4D4040ED0DBE30053040905704FF5BBF4D40D0488446B0053040F8298E03AFBE4D40102A8E03AF0630408848BF7D1DBE4D40B06BED7DAA0A304030232E008DBC4D40B0F8F884EC1030405807793D98BA4D40B0E67283A1123040D88BDAFD2ABA4D40F05147C7D5143040E873D2FBC6B94D40603D997FF4193040D8A9F23D23B94D4050BFD2F9F01C3040D8F71A82E3B84D4010904C874E2B3040B0B393C151B84D40B0DA6E826F2E3040504F1F813FB84D4090992842EA423040F8C9DFBDA3B84D40000FB743C346304010751F80D4B84D40305FD042024E304000274D83A2B94D4000938D075B50304030D8463CD9B94D405031957EC2553040B0A10DC006BA4D40A093A641D1A83040600DFB3DB1BC4D40A0622AFD84AB304030232E008DBC4D402069C53714AE3040D00CE2033BBC4D40E04E0647C9AF30409015E0BBCDBB4D40402E54FEB5B03040584CDE0033BB4D401015C78157B33040D88BDAFD2ABA4D40F0FFFFFFFFBF3040081286014BB64D4090FA96395DCE3040283E7782FDB14D40C001BC0512D03040D8C1FA3F87B14D40C0E67283A1D2304088ABAE4335B14D40708D2441B8DE30408093A641D1B04D40C046753A90E130409018213CDAB04D40207976F9D6E3304080457EFD10B14D408087A2409FE43040803CBB7CEBB14D40503A58FFE7E43040104BE7C3B3B24D4050D6A88768E43040009A417C60B34D4050CF83BBB3E23040D0F4D901D7B34D40A0ECF483BADC3040E07954FCDFB34D40B074B0FECFD9304078A86DC328B44D40A009DCBA9BD7304038232E008DB44D40F028EB3713CF304000E5284014B64D405034D6FECECA3040B877F17EDCB64D400026AAB706BA304080A2EBC20FBA4D40B0E67283A1B230409015E0BBCDBB4D40107497C459B1304028F6D03E56BC4D40D03C80457EB13040283B3602F1BC4D40F00B040132D4304020DB87BCE5BE4D40A0A52C431CD730403829B000A6BE4D40A0F755B950D9304078AEEFC341BE4D405031957EC2E53040E0F4D901D7BB4D40A00C1D3BA8EC3040B0A10DC006BA4D40F09B508880EF3040D8A9F23D23B94D40108BFCFA21F23040206552431BB84D4020F6D03E56F430406040DAFF00B74D4070C422861DF6304028327381CBB54D4000240C03961C3140B09B8BBFEDAF4D40900C1D3BA82C3140104E2844C0AF4D40D0D38041D24731400848A643A7AD4D40E03A71395E4D3140080341800CAD4D40009C5088804F314060888043A8AC4D4010301004C8503140A8A78FC01FAC4D401094BF7B47513140B8DDAF027CAB4D40A0F8F884EC503140B06BED7DAAAA4D407037177FDB4F3140883CBB7CEBA94D40A0FA96395D4E314030F911BF62A94D40307156444D4C314088457EFD10A94D40908AE3C0AB493140E07C957CECA84D40D0E7A4F78D43314090CC07043AA54D40207D5A457F4031408881204086A24D4050E109BDFE403140D8A9F23D23A14D4060D9E90775493140200C207C28A14D40C04BC5C6BC4A3140D07C957CECA04D4090035ABA825D3140D0D38041D29F4D4050CAA48636603140A0E9B303AE9F4D40E034EF384563314058853FC39B9F4D40801B62BCE6653140B06E2EFEB69F4D40F095CE876765314020172AFF5AA04D4070B950F9D7623140B05CA8FC6BA14D40F0A9F23D2361314000D9243FE2A14D40C050A4FB395D3140A8DDAF027CA34D40C0F5B704E05B3140B0ECF483BAA44D407014AE47E15A314020E44A3D0BA64D4050D9E90775593140282F3201BFA84D40C074B0FECF593140E0C1FA3F87A94D40900C1D3BA85C3140B0C2D84290A94D401073F4F8BD693140889C69C2F6A74D40207497C4597131405840DAFF00A74D40C0E0F08288783140C8FA5B02F0A54D40A0FB3905F9953140B0A78FC01FA44D4090035ABA82BD3140001E8A027DA24D40007CB779E3D8314030D8463CD9A14D409000193A76E8314020E44A3D0BA64D4010301004C8F03140B0E0F08288A84D40A0069B3A8FF23140305C8FC2F5A84D40503D997FF4F93140B0B915C26AAA4D4070BEA08504FC314010D061BEBCAA4D401009C38025FF3140B8E67283A1AA4D4090F4143944043240080F45813EA94D40A0129F3BC1063240E07C957CECA84D40101B4982700D32406001F73C7FA84D40306C06B820133240B0E0F08288A84D40306BD44334223240502E54FEB5A84D40801A3048FA343240D08BDAFD2AAA4D40B09FC6BDF93D3240907B9E3F6DAC4D4070CAA48636403240B0B6D4415EAD4D40E0488446B04532403029B000A6AE4D4050D2C43BC0473240783FFCFCF7AE4D4020068200194A3240C809A1832EAF4D40100F45813E59324008D3A23EC9AF4D4060D6A88768643240C809A1832EAF4D40D05626FC5267324008DC65BFEEAE4D40B0656B7D91703240F81A498270AD4D4050D8463CD9713240603A58FFE7AC4D40F08AFD65F7703240C849287D21AC4D404037177FDB6F3240E87954FCDFAB4D40F05640A19E6E3240186C5CFFAEAB4D4040D367075C6F3240386211C30EAB4D4050D6A88768743240D8B837BF61AA4D40D040F33977773240C053E57B46AA4D4030F911BF627932405834D6FECEAA4D4080812040867A3240806308008EAB4D4020990F08747A32405070784144AC4D40909C69C2F6773240D8F19881CAAE4D40C034EF3845733240301DACFF73B24D40D0DA6E826F6E3240801B62BCE6B54D40A0E33103956D32408060C77F81B64D40A0E33103956D3240686D37C137B74D4070F1D3B8376F32402820ED7F80B74D4090073E062B7A3240B86E2EFEB6B74D40908461C0927F324078A52C431CB74D40801B62BCE6853240801B62BCE6B54D408009DCBA9B873240101B498270B54D40D0420246979B324048853FC39BAF4D4060B5DD04DF9C324080A52C431CAF4D40907A32FFE8A33240089A417C60AB4D4030E44A3D0BA63240E0C1FA3F87A94D40C05FE97C78A632408018213CDAA84D40C068ACFD9DA532408021E4BCFFA74D40809065C1C4A33240808461C092A74D40B05CA8FC6BA13240905704FF5BA74D40E0D38041D29732406828D2FD9CA64D40D0488446B08532408096E7C1DDA54D40D0C77C40A06332403829B000A6A64D40C0656B7D91603240808D2441B8A64D4070812040865A324070A52C431CA74D40809C69C2F6573240905704FF5BA74D4090116DC7D4553240F84D2844C0A74D40B05FE97C78563240507C7C4276A84D40502BA1BB2456324048CEFBFF38A94D4090D844662E54324098B7955E9BA94D4010274D83A2513240A0A10DC006AA4D4040BB5F05F846324010D3A23EC9A74D40701A3048FA443240E0B837BF61A24D4060D367075C4F3240B8A78FC01F9C4D40A06E2EFEB64F3240305C8FC2F5904D40801EA33CF33A3240D009A1832E8F4D40D0CABDC0AC383240803FFCFCF78E4D40B07A32FFE8233240D0C77C40A08B4D4010A0C37C79053240A8B6D4415E854D40E0B5F63E55E53140F8BDDBBC71744D4050A7CAF78CE4314000C79E3D97734D40100C040132E43140D0D03FC1C5724D4020F6D03E56E431403038F581E46F4D40100341800CE53140D0FA5B02F06D4D401006820019CA3140682E54FEB5784D40A00F5EBBB4C131406055A18158824D40D05147C7D5C43140B059677C5F8C4D4040895E46B1C4314000C45DBD8A8E4D40A0F4143944C43140606D37C1378F4D40A09065C1C4C331405037177FDB8F4D407055A18158C23140884E417E36904D4060C763062AAB3140505260014C954D40603D997FF4A93140500438BD8B954D40E04E0647C99F3140C8C1FA3F87894D4020240C03969C314030ED0DBE30854D4020917EFB3A9C3140905A457F68844D40B0ECF483BA9C3140809065C1C4834D40405FD042029E3140E8AF743E3C834D4020EACC3D24A03140F805820019824D4020E109BDFEA0314000C11C3D7E814D402088BB7A159D3140B8716F7EC37C4D40F064FF3C0D943140204B033FAA794D40C036FE4465973140F82F1004C8784D40C05CA8FC6BA13140D888997D1E754D4040C1E10511A1314028F6D03E56744D40E0B2B5BE48A0314050FEB5BC72734D40D0B5F63E55953140B8ECF483BA6C4D40000C040132943140D80CE2033B6C4D4060AA0B7899593140E8B2B5BE48604D401096CE8767453140109700FC535E4D40000F45813E393140607FBDC2825D4D40406552431B28314038327381CB5D4D40909C69C2F617314038266F8099614D40F0B5F63E55153140C8EE5701BE614D400018080264083140E08558FD11604D40D05626FC5207314050853FC39B5F4D40B0EAE5779A083140B8A44E40135F4D40100341800C15314030232E008D5C4D405055A1815822314000D9243FE2594D4070CDE5064325314000274D83A2594D40A087A2409F243140D07C957CEC584D4070FDD7B969233140D8B2B5BE48584D40A093A641D1083140A8C2D84290514D4060D026874FEA3040903FFCFCF74E4D4020D2C43BC0E73040B877F17EDC4E4D4020895E46B1E4304000DC65BFEE4E4D40B0073E062BCA3040D8D38041D24F4D40E0DDCB7D72BC304068C18BBE82504D4080035ABA82AD3040D0C1FA3F87514D4050C422861D763040B07A32FFE8534D40C06E2EFEB66F304070A86DC328544D40708AE3C0AB69304030F6D03E56544D40D059677C5F4C304080397AFCDE544D40405FD042023E3040D0031F8315554D409015E0BBCD3B304080397AFCDE544D40E046753A90313040B8B393C151504D4040E78BBD174B304010C45DBD8A4E4D40A077F17EDC5E304008A0C37C794D4D4020F911BF626930408060C77F814E4D40808D2441B86E304008274D83A2514D40E04E0647C96F30401006820019524D40A0AEEFC341A63040E0BB783F6E4F4D40C0FB3905F9B530400048A643A74D4D4090073E062BBA304088397AFCDE4C4D4060C554FA09C73040A8B915C26A4A4D40D0CDFE40B9ED30403041B8020A3F4D40D0B2B5BE48F03040E07FD6FCF83D4D40C0488446B0D53040205C8FC2F5384D4070B08D78B2D33040886649809A384D402009C38025CF304038EACC3D24384D40D0A9F23D23C13040903FFCFCF7364D4050B5DD04DFBC3040B877F17EDC364D401073F4F8BD99304088ABAE4335394D40D05A0A48FB933040508BC1C3B4394D4060E2C80391913040D0224DBC033A4D40E04334BA838C3040A06BED7DAA3A4D40D03730B95188304058FEB5BC723B4D40809065C1C483304088A86DC3283C4D400009C380257F304008D6E3BED53C4D400073F4F8BD793040301A6B7F673D4D40109C5088806F3040081B4982703D4D4060BFD2F9F06C3040D0B5F63E553D4D40E04BC5C6BC6A3040D0031F83153D4D40C074B0FECF693040A8716F7EC33C4D4030CF83BBB392304000D3A23EC9374D404040DAFF00AF3040F8230C0396344D4020274D83A2B1304008BEDBBC71344D405031957EC2B53040502B137EA9334D40B004FD851EC530405040DAFF002F4D40503D997FF4C93040080F45813E294D40406C06B820D33040D8C1FA3F87194D4090FDD7B969D330406028D2FD9C164D40D0A3FE7A85CD3040806F0C01C0114D4090BD175FB4C33040B8928FDD05104D40001C98DC28BE304048B3791C060B4D40500455A357BB3040B083BC1E4C064D40A001BC0512C0304008274D83A2014D40A0FA96395DBE3040B8AAD0402C014D4010E7E104A6A3304050FB743C66FE4C4050D367075C9F304000C45DBD8AFE4C40106893C3279D3040089700FC53FE4C4080F1D3B8379F3040E0FA5B02F0FD4C406076A4FACEA73040F86987BF26FD4C4060BEA08504AC304010A0C37C79FD4C40808AE3C0ABB93040580DFB3DB1FC4C40602B137EA9BB304068F5F23B4DFC4C40001B498270BD304008E869C020FB4C4060DC2A8881BE3040303E7782FDF94C4020494A7A18BE3040A8A70183A4F94C40B0FB3905F9C53040B8AD11C138F64C40208E3D7B2EC7304008CD203EB0F54C40A0E9B303AEC73040100341800CF54C4070CDE50643C5304080ABAE4335F14C40C0E7A4F78DC3304000301004C8F04C406037177FDBBF30408821E4BCFFEF4C409096E7C1DDBD3040A0E9B303AEEF4C40D0622AFD84BB3040B86E2EFEB6EF4C4040B3CEF8BEA8304090457EFD10F14C4030F38FBE499F3040483D997FF4F14C402088BB7A159D3040286BD44334F24C4020F04E3E3D9A30408848BF7D1DF64C4040C763062A9B3040A8DA6E826FF64C4040D026874F9A304038172AFF5AF84C40C0716F7EC384304048853FC39BFF4C4040CF83BBB38230400021CB8289FF4C40702E54FEB5803040586D37C137FF4C4010861DC6A47F3040508E0244C1FE4C40B077F17EDC7E304050499D8026FE4C40E0C43BC0937E3040B8B6D4415EFD4C4000B0027CB7853040183526C45CF04C40601E15FF77903040D8B5F63E55ED4C40F03A71395EAD3040303E7782FDE14C40D03C80457EB130406001F73C7FE04C4050431B800DB43040D8BB783F6EDF4C40801CEA7761B330403011363CBDDE4C4080ABAE4335B13040D8C43BC093DE4C4070F1D3B837AF30405840DAFF00DF4C40B0DA6E826F9E304010D061BEBCE24C40B0E33103959D30401015C78157E34C40D04334BA839C304060888043A8E44C4040D026874F9A3040D0CDFE40B9E54C40208E3D7B2E973040508E0244C1E64C4030861DC6A48F3040E0A9F23D23E94C40205FD042028E304038266F8099E94C4070C763062A6B30405855A18158F24C40E0AF743E3C6B3040A0C2D84290F14C40202DCF83BB6B3040385C8FC2F5F04C40A04737C2A2763040A8CB9BC3B5EC4C40C0328CBB41783040C828CFBC1CEC4C40C039B187F679304040E0810184EB4C40C02E6EA30198304018BD5301F7E24C4010A0353FFE9A3040C0CB457C27E24C4070465C001AA93040B077F17EDCDE4C4080ABAE4335B13040885A457F68DC4C4060B08D78B2B33040109A417C60DB4C4070116DC7D4B53040B053E57B46DA4C402077D84466B6304030266F8099D94C4030EACC3D24A03040B05626FC52CF4C4050B81E85EBA13040F0298E03AFC64C40209D82FC6CB030408848BF7D1DBE4C40D03C80457EB1304010D6E3BED5BC4C40D03C80457EB1304058431B800DBC4C40A0F5B704E0AB3040F8230C0396B44C40A0073E062BAA304080A86DC328B44C4040BC9179E4A73040D0F4D901D7B34C40206211C30EA3304010C79E3D97B34C4020D8463CD9A130408018213CDAB04C40D046753A90A13040604F1F813FB04C40F04E0647C99F3040B09B8BBFEDAF4C40C074B0FECF993040A8B393C151B04C4040E109BDFE90304088457EFD10B14C404069C537148E304058465C001AB14C40A015E0BBCD8B30408018213CDAB04C40F04BC5C6BC8A3040604F1F813FB04C40007CB779E3783040306893C327A54C40A009DCBA9B77304048793BC269A34C4050BB5F05F876304038D8463CD9A14C409087A2409F743040B853E57B469A4C4060A7CAF78C743040808AE3C0AB994C4060CDE50643753040D876137CD3964C4080116DC7D4753040001B498270954C40A009DCBA9B77304068F5F23B4D944C40C0E7A4F78D8330405840DAFF008F4C40B0FB3905F9853040F8DB65BFEE8E4C4050D2C43BC087304030F38FBE498F4C4030F04E3E3D8A3040D8BB783F6E8F4C40A015E0BBCD8B3040883FFCFCF78E4C4060CAA4863690304080423D7D048C4C4040809BC58B953040089700FC53864C40D0488446B0953040B068ACFD9D854C40209D82FC6C803040500DFB3DB1844C4040499D80267E3040789FAA4203854C4030F6D03E56743040C053E57B467A4C4000301004C8703040B8B915C26A724C40B050A4FB396D304000DFA63FFB6B4C401018080264683040A89509BFD4654C407021E4BCFF5F304060707841445C4C40B077F17EDC4E3040D0F4D901D7534C4050BFD2F9F04C30405070784144544C40D0B837BF614A3040A859677C5F544C406031957EC245304060431B800D544C40C0F8F884EC403040F84AE7C3B3524C40A05626FC52373040D0CDFE40B94D4C40B06E2EFEB61F304028E78BBD173B4C40305FD042021E3040A8C2D84290394C40A06BED7DAA1A3040B85FE97C78364C40008E3D7B2E1730405882FE428F324C40405FD042020E304030EACC3D24284C4050E78BBD170B3040A8B915C26A224C40008BFCFA21023040E87954FCDF1B4C40E0EA56CF49FF2F40B06BED7DAA1A4C4040C763062ABB2F407815E0BBCD0B4C40E0989EB0C4932F40009700FC530E4C408050A4FB398D2F4080992842EA124C40407497C459512F4038DB87BCE5164C40206BD44334322F40E07C957CEC184C40C0E1934E24C02E40908AE3C0AB114C4000C87C40A0732E400015C78157134C40C0035ABA822D2E40D0BEB9BF7A144C40206BD44334B22D4050888043A8144C40C0F1D3B8376F2D40600DFB3DB1144C4040895E46B1642D409087A2409F144C40603E3C4B90612D40F80B040132144C40E08C9AAF925F2D40886308008E134C4080BEA085045C2D40385C8FC2F5104C4040FEF0F3DF5B2D40E0BB783F6E0F4C40606893C3275D2D40D0F19881CA0E4C40E08C9AAF925F2D4080AEEFC3410E4C40C0C64ACCB3622D40B89509BFD40D4C40C0622AFD846B2D40386893C3270D4C40A076BF0AF06D2D40500DFB3DB10C4C40E094490D6D802D40580ABABDA4074C40A04E95EF19892D4060888043A8044C4000E9297288882D40E87954FCDF034C40C01D71C8067A2D4030F911BF62014C40204E7CB5A3702D40D000DE0209004C4020CDE50643452D40305C8FC2F5004C40009F20B1DD3D2D40889065C1C4034C40000341800C352D403029B000A6064C40C051D66F261E2D40B05626FC52074C4060D026874F1A2D40B0A44E4013074C40E0E4D4CE30152D40F8C35DBD8A064C40E00373F4F8052D4028D505BCCC044C40206893C327BD2C4000D061BEBCFA4B40C04E95EF19A92C40A09B8BBFEDF74B4080BB5F05F8862C40B85CA8FC6BF14B40C05A99F04B7D2C40903FFCFCF7EE4B40C085048C2E772C40789FAA4203ED4B4080F1D3B8376F2C40C053E57B46EA4B4020B937BF616A2C408021E4BCFFE74B40E0D38041D2672C406076FA415DE64B40202A8E03AF662C4010A0C37C79E54B4020895E46B1642C408815E0BBCDE34B40A079008BFC622C40E006600322E24B40800F5EBBB4612C40F8DB65BFEEDE4B40C0CF0D4DD9612C40A868ACFD9DDD4B40603579CA6A622C40583A58FFE7DC4B4080D6A88768642C40D8C77C40A0DB4B40006552431B682C40081E8A027DDA4B40A0A48977806F2C40D87C957CECD84B4080B60F79CB8D2C402835B401D8D24B40C06DFC89CAAE2C4080A2EBC20FCA4B40C01D71C806BA2C402829B000A6C64B4000EC6AF294BD2C4000A0C37C79C54B40A077F17EDCBE2C4010D6E3BED5C44B40E0A7E33103BD2C4058431B800DC44B40C0F755B950B92C4080992842EAC24B40E059677C5FAC2C4038EACC3D24C04B40A021E4BCFF9F2C40101286014BBE4B40208B187618632C407039D0436DB14B4000E6E8F17B532C40E0CABDC0ACB04B4000965D30B83E2C40B0656B7D91B04B400052D66F261E2C40A85CA8FC6BB14B40A05417F032132C4028D8463CD9B14B40603579CA6A022C4030DEC83CF2B34B40809BC6F65AF02B40901B62BCE6B54B40E008C38025DF2B40606D37C137B74B40E0A16131EAD22B400821CB8289B74B40E017080264C82B403020ED7F80B74B40C0DB114E0B762B40B85FE97C78B64B400023DA8EA96B2B40001286014BB64B4040E9297288482B40001B498270B54B4080B08D78B2432B4088CC07043AB54B40E077F17EDCFE2A40C87C957CECB04B4080DC2A8881EE2A40C8D38041D2AF4B4040BEA08504DC2A401048A643A7AD4B40E0AC33BE2FD62A40E088997D1EAD4B4020B3B5BE48C02A40B8622AFD84AB4B40607D5A457FB02A4060793BC269AB4B40801D71C8069A2A40D8C77C40A0AB4B4020BFB9BF7A942A40809065C1C4AB4B40E0D24ECDE5F62940B0B0524145B34B40E0DB114E0BD62940283B3602F1C44B40A0E4D4CE30D529401048A643A7C54B40000C040132D42940909C69C2F6C74B40E0ED974F56D429401018080264C84B40A0E4D4CE30D52940282F3201BFC84B40802FF7C951D82940A0C2D84290C94B4000F52D73BADC2940E0B837BF61CA4B400023DA8EA9EB2940602B137EA9CB4B40A0129F3BC1F62940580DFB3DB1CC4B4040F86EF3C6112A405037177FDBCF4B40E0716F7EC3142A40A8B393C151D04B4080C554FA09172A40305C8FC2F5D04B400052D66F261E2A4000D6E3BED5D44B40C094490D6D202A40B05626FC52D74B406021E4BCFF1F2A40A8E9B303AED74B40E0C43BC0931E2A40602E54FEB5D84B4040C763062ADB294060F833BC59E94B404015C78157D32940A8B0524145EB4B4060B5DD04DF5C2940B09B8BBFED074C40E0989EB0C453294088A2EBC20F0A4C4040A7CAF78C44294030ED0DBE300D4C40E0BB783F6E3F294028327381CB0D4C408014AE47E13A2940305FD042020E4C40804D637B2D382940081286014B0E4C4000C2FA3F87292940E006600322124C4020A5A2B1F6E72840500438BD8B254C40406E15C440E728409048BF7D1D264C40C059677C5FEC2840D8AC33BE2F264C4000EFAB72A1F2284030E44A3D0B264C40C082C30B22422940E0A9F23D23214C4020B937BF614A2940109D82FC6C204C408083BEF4F66F2940582250FD831C4C40206211C30E93294010BEDBBC711C4C40A0129F3BC196294028232E008D1C4C406083DC45989A294090397AFCDE1C4C40E094490D6DA0294030327381CB1D4C40200473F4F8A5294008DC65BFEE1E4C40C089E76C01A929401000000000204C40A074B0FECFA92940E8B2B5BE48204C40C091088D60AB294010E2E7BF07214C4080622AFD84AB2940A874B0FECF214C40008A592F86AA2940301DACFF73224C40809885764E7B2940D0031F83152D4C40E0DB114E0B762940305FD042022E4C40E0EEAB72A1722940A05FE97C782E4C40001077F52A5A2940806649809A304C40A07A32FFE8532940E0CABDC0AC304C4020068200194A2940080F45813E314C40200473F4F8452940F8264D83A2314C40A0656B7D914029405007793D98324C40A077F17EDC3E2940504CDE0033334C4000C53BC0933E2940A8ECF483BA344C40E0251B0FB64029405876FA415D364C40C0CF0D4DD9412940586D37C137374C4040DF6B088E432940B09B8BBFED374C40809E077767452940786649809A384C40201808026448294058465C001A394C408000193A765829400815C781573B4C40A0BEA085045C2940282CF180B23B4C4040274D83A2712940D0F4D901D73B4C4060C554FA09772940D0F4D901D73B4C40C08C9AAF927F2940B0DDAF027C3B4C40A05DDA705892294008274D83A2394C40E0AC33BE2F9629406073B9C150394C408021E4BCFF9F2940382F3201BF384C4020B937BF61AA2940E8B2B5BE48384C4080DE718A8EB42940D8F10A444F384C4020F52D73BABC29405801F73C7F384C4080656B7D91C02940F02F1004C8384C4060D6A88768C42940E0A9F23D23394C40A032384A5ECD294080812040863A4C40C05DDA7058D22940889065C1C43B4C40E0DB114E0BD6294080CC07043A3D4C40207156444DDC294038EACC3D24404C40A021E4BCFFDF2940084BE7C3B3424C40A06E2EFEB6DF294088A86DC328444C40E09E20B1DDDD2940600438BD8B454C4040B5DD04DFDC2940E8AC33BE2F464C408068ACFD9DD5294078A2EBC20F4A4C406077D84466C62940508BC1C3B4514C40A018213CDAC0294008D061BEBC524C40C0A7E33103BD2940306211C30E534C4020895E46B1A429405070784144544C40E094490D6DA0294060431B800D544C40A0B81E85EB912940D8B837BF61524C408023F3C81F842940803CBB7CEB514C404015C7815773294010D9243FE2514C40C017EFC7ED6F29406055A18158524C406038BA4A7757294010C45DBD8A564C40201077F52A3A294058853FC39B5F4C40E05417F032332940886308008E634C40A05DDA70583229405870784144644C4000D13FC1C53229408096E7C1DD654C40C07A32FFE8332940788D2441B8664C40E05417F032332940D0BB783F6E674C40A0B81E85EB312940306552431B684C4060573F36C92F294008CADFBDA3684C40E0CABDC0AC282940B853E57B466A4C4080116DC7D425294010D061BEBC6A4C40C04D637B2DF828408818213CDA704C4040573F36C9EF284008274D83A2714C40A0DB114E0BD628403835B401D8724C404015C78157B32840000341800C754C4060B81E85EBB128401048A643A7754C40E05417F032B3284080A86DC3287C4C40201E8A027D92284078A86DC328844C40C0CF0D4DD981284050499D8026864C40A06ABB09BE792840580ABABDA4874C40C03BFBCA834C28400821CB8289974C40E0DE52CE174B2840306552431B984C40802FF7C9513828400800000000A04C40601A3048FA442840B8B0524145A34C40E0A6B1BD164C284010DFA63FFBA34C40C0035ABA824D2840B0716F7EC3A44C40A06BED7DAA4A2840888461C092A74C40604E7CB5A33028403029B000A6B64C40009F20B1DD1D2840306BD44334BA4C4040D026874F1A28406007793D98BA4C40E05FE97C781628402035B401D8BA4C4020A26131EA122840081E8A027DBA4C40400473F4F8052840908461C092B74C4040634337FB03284030DB87BCE5B64C40A079008BFC02284030E44A3D0BB64C4080D6A8876804284060888043A8B44C4040634337FB032840D0F4D901D7B34C402083DC4598FA2740D0BEB9BF7AAC4C40A0737E8AE3F82740302CF180B2AB4C40C0B5F63E55F5274008DFA63FFBAB4C40C0C64ACCB3E2274028EACC3D24B04C40A01B62BCE6D52740B8DDAF027CB34C40606002B7EECE2740385FD04202B64C4080035ABA82CD27405828D2FD9CB64C4080CAA48636D02740903CBB7CEBC14C40A0FCA5457DD2274048BC033C69C34C4000C87C40A0D32740602B137EA9C34C4000321F10E8D42740885A457F68C44C40C04D637B2DD8274090C9C6832DC84C4000C87C40A0D32740F8C35DBD8ACE4C40206BD44334D22740C809A1832ECF4C40200AF5F411D0274000D3A23EC9CF4C40E0622AFD84CB2740B09B8BBFEDCF4C4020356090F4C927401009C38025CF4C4060AA0B7899B9274030327381CBCD4C40405C8FC2F5A8274058888043A8D44C4020F52D73BABC274078A52C431CD74C404048FAB48AC627409093A641D1D84C40C0B2B5BE4880274080C9C6832DD84C40404B3B35977B274030EACC3D24D84C4000CBBDC0AC682740302F3201BFD84C40C0116DC7D4652740100F45813ED94C4020B728B341662740D0C77C40A0DB4C40206BD44334722740B05626FC52E74C4000DC114E0B5627404870784144EC4C40E0B2B5BE486027408818213CDAF04C40C0FDD7B9696327405873B9C150F14C404021CB8289672740A0C2D84290F14C40A059677C5F6C2740A074B0FECFF14C40404B3B35977B2740286BD44334F24C4040B08D78B28327403835B401D8F24C40C05626FC52972740F02F1004C8004D4060D026874F9A2740009A417C60034D40205DC136E299274088397AFCDE044D40A02634492C992740B068ACFD9D054D40C08EC70C5496274060499D8026064D4000C4094CA78D27407081CB63CD064D4000C4094CA78D274060853FC39B074D408009DCBA9B972740000C0401320C4D40600C1D3BA8AC27408815E0BBCD134D4000EC6AF294BD2740487C7C4276184D408079008BFCC2274038266F8099194D40801A3048FAC42740B853E57B461A4D400051BD35B0C5274000E869C0201B4D4060E2AC889A982740282F3201BF284D40802FF7C951782740A8A10DC0062A4D40E05DDA705872274008068200192A4D40C077F17EDC3E27400015C78157234D4040C554FA0937274000274D83A2214D40607D5A457F302740D0CABDC0AC204D40201E8A027D12274008A0C37C791D4D4080035ABA820D2740587FBDC2821D4D40606552431B08274010CD203EB01D4D4000EC6AF294FD2640A8AD11C1381E4D4020861DC6A4CF2640B05CA8FC6B214D4040895E46B1C42640B89B8BBFED274D40C01D71C8067A2640805A457F682C4D4020AE65321C67264000E869C020334D4060E2AC889A782640E0CABDC0AC404D40C082C30B2282264000C45DBD8A464D4080B08D78B283264028F38FBE49474D402018080264882640D08BDAFD2A4A4D402051BD35B0852640D87C957CEC504D40605A80B6D584264008274D83A2514D40E0A9F23D2381264000C79E3D97534D40A077F17EDC7E264070A86DC328544D400023DA8EA96B26405840DAFF00574D4020240C03965C2640D0D03FC1C55A4D4040C763062A5B2640089A417C605B4D402083DC45985A2640580438BD8B5D4D4000A8E331035D2640A86E2EFEB65F4D4020FBAF73D36626405882FE428F624D4020861DC6A46F2640A859677C5F644D4020B6F63E55752640281A6B7F67654D40A0C98B4CC0772640385FD04202664D40E0737E8AE3782640A077F17EDC664D40C05626FC52772640B0E67283A16A4D40A05FE97C78762640000C0401326C4D40A0FDD7B969632640001B498270754D40E0B5F63E55552640109700FC53764D4080DF6B088E432640A86E2EFEB6774D404038A110013F2640306552431B784D40A09885764E3B26406001F73C7F784D4080129F3BC136264020266F8099794D40A01D71C8063A2640607C7C4276804D4020A8E331033D2640B0A10DC006824D40E08B868C47412640F899417C60834D4000E5D4CE30552640504F1F813F884D40802FF7C95158264000301004C8884D40C08C9AAF925F264028266F8099894D4020E9297288682640D88BDAFD2A8A4D40C0A4A2B1F687264080423D7D048C4D40E08B868C47A12640B09ECC3FFA8C4D406077D84466A62640600DFB3DB18C4D40C050A4FB39AD2640789065C1C48B4D40005517F032B326406034D6FECE8A4D400009C38025BF26408060C77F81864D4000C4094CA7CD264008274D83A2814D40A0129F3BC1D62640002A8E03AF7E4D40E06BED7DAADA2640786D533C2E7E4D400069C70DBFDB2640601CCEFC6A7E4D4060E2AC889AD826406028D2FD9C764D40A000193A76D8264038327381CB754D4060AA0B7899D9264000C79E3D97734D40201077F52ADA26403035B401D8724D40E006B47405DB26408054C37E4F724D40406893C327DD2640D0EE5701BE714D40C018213CDAE026405873B9C150714D4000FBAF73D3E62640D8A9F23D23714D40C07F828B15ED264048465C001A714D40E01186014BFE2640100F45813E714D4000D68F4DF22B2740D0D03FC1C5724D40404B75012F332740E8067C7E18734D40C051D66F263E27408815E0BBCD734D40C018213CDA402740B059677C5F744D40E0656B7D91802740886308008E8B4D40603E3C4B90812740F8BDDBBC718C4D40C0D8D0CDFE802740306893C3278D4D40E051D66F267E2740A8DA6E826F8E4D4080BEA085047C27402841B8020A8F4D402083DC45987A2740B0E9B303AE8F4D402083DC45987A2740D0B2B5BE48904D40A094490D6D802740089700FC53964D40E053E57B46822740D88558FD11984D4040895E46B1842740508BC1C3B4994D402021CB828987274028E78BBD179B4D4060787B10028A2740C8559E40D89B4D4000F86EF3C691274000A0C37C799D4D400007D2C5A695274058F295404A9E4D40A085048C2E9727405028D2FD9C9E4D4040B3CEF8BE98274008BB9A3C659F4D40406684B70799274030E109BDFEA04D40C07C410B09982740E0AF743E3CA34D40E0311F10E8942740D876137CD3A64D4040013274EC902740B0C2D84290A94D4060A148F7737A27406040DAFF00B74D40C01B62BCE6552740F82CCF83BBCB4D40000D36751E552740B0AD11C138CC4D40602CB6494583274068F833BC59D14D40006E15C440872740488BC1C3B4D14D4060CAA48636902740B053E57B46D24D40208D9AAF929F27406034D6FECED24D408023F3C81FA42740286211C30ED34D40206552431BA8274058FEB5BC72D34D40C01EA33CF3CA2740305C8FC2F5D84D40E050A4FB39CD2740D0EE5701BED94D40802975C938CE27405007793D98DA4D4080DC2A8881CE2740100C040132DC4D40A0FA96395DCE27408860C77F81DE4D40602618CE35CC27404816A243E0E24D40C01EA33CF3CA274008BEDBBC71E44D40C05758703FC82740C8CDFE40B9E54D40200473F4F8C52740101286014BE64D40406C06B820C3274030DB87BCE5E64D40206893C327BD27403038F581E4E74D4080B05582C5A12740A0923A014DEC4D402090DB2F9FB4274078AEEFC341EE4D40C094490D6DC02740905704FF5BEF4D4000356090F4E927406034D6FECEF24D4020861DC6A4EF274090992842EAF24D4020295C8FC2F52740004BE7C3B3F24D400038A11001FF2740303E7782FDF14D40C0F4143944042840D0EE5701BEF14D404045B9347E112840A85CA8FC6BF14D40C0D24ECDE536284038F911BF62F14D40A03579CA6A422840E0C1FA3F87F14D4000F2ECF2AD472840608BC1C3B4F14D4000E6E8F17B5328406034D6FECEF24D40C053E57B46622840B8BF97C283F44D40E077F17EDC9E284088423D7D04FC4D406051BD35B0A52840A09ECC3FFAFC4D40803BFBCA83EC284030EACC3D24084E40200C040132F42840E073D2FBC6094E4080A148F773FA284000240C03960C4E4020A8E33103FD2840B8AD11C1380E4E400052D66F26FE284088A52C431C0F4E400009C38025FF2840889C69C2F60F4E40C05CA8FC6B0129408081204086124E40A0703D0AD703294010CD203EB0154E40A023F3C81F042940B05FE97C78164E4080F414394404294038F38FBE49174E4060634337FB03294008301004C8184E40E053E57B46022940781EA33CF31A4E40C02975C9380E2940E0D03FC1C52A4E404015C7815713294088423D7D042C4E40005A80B6D52429400018080264304E40A076BF0AF02D294028E78BBD17334E40A0B81E85EB31294060FB743C66364E40C08FDB2F9F342940C8CABDC0AC384E40A0C554FA09372940504CDE00333B4E40C05626FC5237294008DFA63FFB3B4E40E0AC33BE2F362940001B4982703D4E40809BC6F65A302940D08BDAFD2A424E40C0CCCCCCCC2C294050793BC269434E40E079008BFC02294010CADFBDA3504E4060AA0B7899D9284090992842EA5A4E404051BD35B0C52840286552431B604E40A0C2137AFDC128406073B9C150614E406054FEB5BCBA2840809065C1C4634E40400341800CB528405076FA415D664E4020999EB0C4B328406040DAFF00674E40E0A6B1BD16AC2840E0FD9C82FC6A4E40405FD042029E2840B0C2D84290714E40E0AF743E3C8B284058465C001A794E40C0CDFE40B97D284038232E008D7C4E40C009DCBA9B772840500438BD8B7D4E40A0F1D3B8376F284078A52C431C7F4E4080BFD2F9F06C2840A0E9B303AE7F4E40A0622AFD846B2840B0B393C151804E4080FA96395D6E2840D8F71A82E3804E40A0B81E85EB71284020F911BF62814E40A077F17EDC7E2840C8B837BF61824E402020990E9D962840809065C1C4834E40402A8E03AFC62840A05FE97C78864E40E02F1004C8D0284020DB87BCE5864E40201B498270DD2840803FFCFCF7864E40E089592F86EA284020DB87BCE5864E4000E2934E240029409060C77F81864E40803579CA6A22294058499D8026864E40C0ED974F563429404876FA415D864E4040E3A7716F3E2940E0F19881CA864E40C02497FF90462940F096E4805D874E40C085048C2E572940D8AF743E3C8B4E40E091088D608B2940488BC1C3B4994E4060BC9179E4972940905704FF5B9F4E40E0C1FA3F87A92940809C69C2F6A74E40A08EC70C54B6294068FB743C66AE4E40A088450C3B8C2940D0031F8315B54E4040D367075C0F2940607C7C4276C84E406015E0BBCD0B2940886649809AC84E40C05FE97C78F62840D8F71A82E3C84E4040573F36C9EF2840D07C957CECC84E4080B08D78B2E3284008301004C8C84E40607156444DDC2840D8F71A82E3C84E4040CAA48636D0284028F911BF62C94E40C04E95EF19C928408854C37E4FCA4E4000356090F4492840D0F4D901D7DB4E40A06E2EFEB63F2840785182FE42DD4E4040274D83A2512840D8A6B1BD16EC4E4060C554FA09572840507C7C4276F04E4000A8E331035D284040D505BCCCF44E406048FAB48A6628403014E97E4EFB4E406069C537146E284000301004C8004F4060D6A8876884284028F04E3E3D124F40E0B0170AD8962840C02231410D214F40C038BA4A7797284008C11C3D7E214F4000B6F63E55952840B8984A3FE1224F40C01EA33CF38A2840D0BB783F6E274F40A02CB6494583284008D9243FE2294F40408A90BA9D7D2840905182FE422B4F40A0622AFD846B2840903CBB7CEB314F40E0B628B3416628409015E0BBCD334F40E0E2A7716F5E284078AEEFC341364F40A04D637B2D582840D000DE0209384F408059677C5F4C284090992842EA3A4F40A091088D602B2840F82CCF83BB434F40A02FF7C951182840B8622AFD844B4F4060BC9179E4172840286893C327554F4040CDE50643252840E0C77C40A05B4F4080B60F79CB2D2840A89B8BBFED5F4F40C082C30B22222840C8F19881CA664F40A06ABB09BE192840089A417C606B4F40C06DFC89CA0E284028F04E3E3D724F40009F20B1DD1D2840B8E3310395754F40801D71C8063A28409015E0BBCD7B4F408032384A5E4D2840B89B8BBFED7F4F40C08EC70C54562840A8A10DC006824F40C074B0FECF49284038327381CB854F4020A26131EA12284078AEEFC341964F4060DEE34C130E28401818247D5A974F4000BC783F6EDF27402835B401D8A24F40E0BB783F6EFF2740885D86FF74A94F40606552431B282840608BC1C3B4B14F4000B728B3414628402838F581E4B74F40E0703D0AD76328409048BF7D1DBE4F40407A19C5725B2840A8C2D84290C14F40603F373465472840D0D03FC1C5CA4F40E06DFC89CA4E284088A86DC328CC4F406045B9347EB12840605260014CDD4F40206BD44334F22840B06BED7DAAEA4F4020573F36C90F2940A06E2EFEB6EF4F4040A7CAF78C442940D0CABDC0ACF84F40006893C3275D29409015E0BBCDFB4F40A0129F3BC196294070BE4A3E7600504000274D83A2B129409026DE019E015040C0B2B5BE48E0294074BB09BE69035040C01D71C806FA2940ACA78FC01F045040407D5A457F102A402C232E008D045040A09E077767452A4040B665C059055040606C06B820632A405431957EC205504000295C8FC2752A40583D997FF4055040A0E4D4CE30952A4044C269C18B0550404020990E9DF62B4004D6E3BED5005040C01D71C806FA2B4048AA61BF27015040C0DE52CE174B2C40FCE769C0200B5040A0F1D3B8374F2C402C38F581E40B5040A0035ABA824D2C403CB665C059155040800C1D3BA84C2C40F8E4284014165040204B3B35973B2C406C06F1811D1E5040604E7CB5A3102C40D8AF743E3C1F5040C050A4FB39CD2B40D4BEB9BF7A20504020634337FBA32B4000D9243FE2215040C05A99F04B5D2B4030232E008D24504000C87C40A0532B40407D04FEF0245040A05417F032532B40585260014C25504020BFB9BF7A542B40DCEE5701BE2550404083DC45985A2B401C99B9C0E5265040205A80B6D5642B40D4B2B5BE48285040C0E7154F3D6A2B403C7D04FEF028504040DAC70A7E732B40A85016BEBE29504020B937BF61AA2B4004DC65BFEE2E5040A082C30B22C22B4044B665C059315040C0F0D8CF62E92B40F05DF58079355040806DFC89CA2E2C402C2F3201BF3C50408000193A76782C4004E869C020435040A095B6B8C6972C407C42AF3F8946504080EA573A1F9E2C40CC586DFE5F47504060DF6B088EA32C40ACB393C15148504020E9297288A82C40C02500FF94495040C08EC70C54B62C4040B665C0594D504080B5DD04DFBC2C4008D3A23EC94F5040604278B471FC2C40BC438A0112545040606893C327FD2C4070FD2D01F856504000F52D73BAFC2C40C864E3C11658504040EC6AF294FD2C4094239D81915C5040C0C43BC093FE2C4000E2E7BF07615040C0B2B5BE48002D40EC7E4E417E655040607D5A457F102D4028232E008D6C504040B81E85EB112D40A49ECC3FFA6C5040E00B040132142D40B0B6D4415E6D5040E05CA8FC6B212D40FCE769C0206F5040C07F828B152D2D40E87B0DC171705040C0E4D4CE30352D40EC7E4E417E7150400052D66F263E2D40C040498105735040C0FDD7B969432D405470784144745040801A3048FA442D40C03AC780EC74504000CA8B4CC0372D40C464E3C116785040004F95EF19292D40EC84D041977B504040DF6B088E232D40B0716F7EC37C5040A0716F7EC3142D40D8BEB9BF7A80504000F86EF3C6112D409826DE019E815040C074B0FECF092D40080341800C85504040895E46B1042D40FC14C7815787504060069B3A8F022D40DCBEB9BF7A88504060A48977806F2D40189F3BC1FE885040E05FE97C78F62D403CC269C18B89504060BFD2F9F00C2E4028266F809989504040861DC6A4EF2E40B8490C022B925040A02C280CCAE42E4090239D8191945040A07F828B15CD2E4018A27C410B9A5040A051D66F26BE2E4040C269C18B9D5040A06ABB09BEB92E40848D2441B89E5040A02975C9380E2F40AC6E2EFEB6A35040A094490D6D402F40D8D03FC1C5A65040C08EC70C54762F40DCF4D901D7AB5040A0069B3A8F02304098E1783E03B950403083DC45985A3040DCA9F23D23C1504050BC9179E4673040301DACFF73CA5040D0AC33BE2F663040E857738060CB5040D04334BA835C3040586D37C137CF50402077D84466563040540DFB3DB1D05040206211C30E4330407C6308008ED350408000193A76383040BC46CB811ED5504070D6A8876834304028266F8099D5504030F911BF62293040D0D03FC1C5D65040D0DDAF027C23304090205C0185D75040C0393FC5711C30402C232E008DD85040A06BED7DAA1A30408493A641D1D8504050BB5F05F816304068CD8FBFB4D95040A0AEEFC341163040ACA10DC006DA5040C0FB3905F91530405855A18158DA5040A0ABAE43353130400000000000E05040B0716F7EC334304048A7203F1BE0504060B81E85EB613040189F3BC1FEE05040406E15C4406730406CFAEC80EBE15040208BFCFA21823040E83F6B7EFCE6504050C2137AFD91304014A27C410BEA504040B08D78B293304044C5AA4198EA5040D03FC1C58A963040602B137EA9EB504020763579CA9E3040AC77F17EDCEE504020F38FBE49AF30407C5182FE42F550402006820019BA30403CC269C18BF9504050CAA48636303140EC3C2AFEEF0151401060AE450B3C3140F47EDC7EF9035140A0868C47A9403140D4D03FC1C504514030E44A3D0B4631402C327381CB055140A0E9B303AE9731406CD993C0E601514050C422861DA63140543A58FFE700514040499D8026AE3140DCB2B5BE48005140F01186014BBE3140BC40498105FF5040505260014CCD31406CCD8FBFB4FD504040B81E85EBD13140040F45813EFD5040A0716F7EC3D43140FCE1E7BF07FD5040602B137EA9DB3140502E54FEB5FC50405055A18158E23140C00166BE83FC5040D0656B7D91F031405C37177FDBFF504030CF83BBB32232409026DE019E09514040D2C43BC0273240BC28417FA10A51403083DC45981A3240BC3D0801F9115140B0FB3905F915324030F6D03E56145140B0EF3504C7113240106C5CFFAE16514040CC423BA70D324004E2E7BF07195140102DCF83BB0B324048ADA23F341A5140B077F17EDC0E324098EA3BBF281C5140503A58FFE71432406CBB09BE691F5140206E15C44017324044BF28417F205140809CDB847B19324068855B3E9220514080AEEFC341263240AC9ECC3FFA205140502B137EA95B32408060C77F81225140800C1D3BA89C3240A8B915C26A1E5140909065C1C4F33240546D37C1371F5140A074B0FECF6933402835B401D81A5140E0AF743E3C8B3340C42500FF941951408009DCBA9BB733405C37177FDB175140307156444DDC334044B9A64066165140B0FB3905F9E5334014967840D9155140D04334BA83EC33403CC269C18B155140C001BC0512F0334030266F809915514020CF83BBB3F23340A874B0FECF155140603A58FFE7F4334098E4B9BE0F16514090F27684D3F63340DCB837BF61165140E025AAB706FA334004E869C020175140900F5EBBB4013440041808026418514020D2C43BC0073440E851F17F47195140307156444D0C3440B074B0FECF19514070FDD7B969133440E8818FC18A1A51407034D6FECE2A34407C5A457F681C5140809FAA42032D3440D8CABDC0AC1C514060B950F9D73234409426DE019E1D51401096CE8767353440281DACFF731E514030E44A3D0B363440B077F17EDC1E5140D03FC1C58A16344044A7203F1B205140C05147C7D5F433405C34D6FECE22514040EACC3D241034405873B9C150255140F03A71395E2D3440301A6B7F67295140207976F9D6333440D4B837BF612A5140A09FAA42033D3440544F1F813F2C514010938D075B50344048B324404D305140A08AE3C0AB5934405855A18158325140D0656B7D9150344068BB09BE693B5140306893C3273D34404080457EFD3D51408093A641D1183440188DB5BFB3425140E05D4BC80789344068C70DBF9B435140504C50C3B79434406C361D01DC435140D06BED7DAA9A3440E478CC4065435140F0565D876AA63440D4B22781CD42514050DC2A8881BE34403C80457EFD415140A06BED7DAACA3440F07E4E417E415140F0CABDC0ACD83440A8716F7EC34051409096E7C1DDDD3440ACB393C151405140E03DB2B96AE23440D4F4D901D73F5140E0CABDC0ACE83440B0A44E40133F5140F0CDFE40B9ED344090111780463E514020763579CAEE3440C43D0801F93D514010938D075BF03440D4B5F63E553D514050CAA48636F03440AC9ECC3FFA3C514080FA96395DEE344094239D81913C5140E0B837BF61EA3440ACA78FC01F3C5140B0E7A4F78DE3344044B0E3BF403B5140A0A2EBC20FE23440301DACFF733A514040C2137AFDE1344008068200193A5140C0DDAF027CE33440E85DF5807939514040ED0DBE30E5344030ED0DBE30395140F040F33977E73440449E5DBEF538514070D026874FEA3440282F3201BF38514020D8463CD9F13440785A457F68385140D068ACFD9DF53440A8B393C15138514030CC423BA7FD3440D4B2B5BE48385140F09600FC5306354098EA3BBF283851400029EB37130F35402C38F581E4375140D05147C7D5143540BCFE243E7737514020ED0DBE3035354068BE4A3E76345140D040F33977373540F04EB0FF3A345140602B137EA96B35405055A181582E514050B950F9D7723540EC4EB0FF3A2C5140B07A32FFE8733540149CFA40F22B5140208E3D7B2E773540F078CC40652B514050D505BCCC7C354064FD2D01F82A514050CAA48636803540D0D03FC1C52A514050BFD2F9F08C35405455A181582A514070116DC7D49535404C499D80262A5140F0548847E29935403C80457EFD295140F09B5088809F3540BC04A73E9029514080A7CAF78CA43540C046CB811E295140D0C77C40A0B33540106F9D7FBB27514080116DC7D4B535403020ED7F80275140A0F27684D3B63540544CDE003327514040E44A3D0BB635405834D6FECE265140701B62BCE6B53540C01C3D7E6F26514050BC9179E4B73540B49509BFD4255140407156444DBC35403CB665C05925514070B81E85EBC13540C03AC780EC245140C0FB3905F9C53540AC716F7EC32451400009C38025CF3540BC0166BE83245140'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('SZ','CH','CHE','756','Switzerland','4000','7424389','150','155','7.908','46.861','0106000020E6100000010000000103000000020000001502000077137CD3F4C91E40530438BD8BC54740FE0B040132141F40D576137CD3C6474088F2052D24A01F40D4BB783F6EC74740BA313D6189A71F402BDB87BCE5C6474055BFD2F9F0AC1F40508E0244C1C647404ED026874FBA1F40FA298E03AFC6474051C1E10511112040D009A1832EC74740AB59677C5F2C2040FD4D2844C0C7474084F1D3B8372F20402638F581E4C74740286211C30E332040FC17080264C84740D3BEB9BF7A342040272F3201BFC84740C9E4D4CE303520407AABAE4335C94740AC5626FC52372040A9A10DC006CA474057B3CEF8BE382040D4B837BF61CA4740A777F17EDC5E20405340DAFF00CF4740A379008BFC622040A5BC564277CF47407B116DC7D46520407F8461C092CF4740FE0E45813E6920407F8461C092CF47405B9885764E7B204028F38FBE49CF474051C1E10511912040AB5FE97C78CE474008E6E8F17B932040FD1186014BCE4740F6285C8FC2952040530438BD8BCD4740286552431BC8204028F04E3E3DCA4740FF08C38025DF2040AB5CA8FC6BC947402B69C53714EE2040D388997D1ECD4740D3BEB9BF7AF420405376FA415DCE47402F51BD35B0052140F92F1004C8D04740C9E7154F3D0A2140A8AAD0402CD14740030AF5F4111021402AE109BDFED04740DC9E20B1DD1D2140FED2A23EC9CF4740F52EDE8FDB1F2140FB20CB8289CF4740753E3C4B902121402829B000A6CE4740FAB836548C232140153944DC9CCC47404985B18520272140F2EA1C03B2CB4740A46DFC89CA2E2140A7ECF483BACC4740247D5A457F3021407B9FAA4203CD4740A182C30B22422140FD4AE7C3B3D24740A379008BFC4221407F4B00FE29D34740AC53E57B46422140D2C77C40A0D34740CBD8D0CDFE402140FCDEA63FFBD34740DC9E20B1DD3D21407F87A2409FD44740A181583673382140103FFF3D78D54740FE0E45813E292140A8E3310395D547404ED026874F1A2140530438BD8BD547407638BA4A77172140FC1A498270D54740DCA16131EA122140000341800CD5474083FA96395D0E2140D7A6B1BD16D44740AD50A4FB390D2140562B137EA9D34740C7F0D8CF620921407F4B00FE29D3474007EC6AF294FD20402635B401D8D2474008E6E8F17BF320405534D6FECED247404DD9E90775D92040FFCC203EB0D54740D2C77C40A0D32040D576137CD3D64740247D5A457FD02040A4C2D84290D947404FCAA48636D02040FF05820019DA4740AF5DDA7058F2204028F04E3E3DE24740DD989EB0C4F320405182FE428FE247409E978A8D79F52040AB984A3FE1E24740D2C43BC0931E2140556D37C137E74740CCCF0D4DD921214028F38FBE49E747408109DCBA9B372140FDDB65BFEEE647402E54FEB5BC3A2140A777F17EDCE6474007EFAB72A152214052499D8026E64740F437A110015F2140520DFB3DB1E44740772FF7C9517821407D5D86FF74E1474083F755B950792140FCE1E7BF07E1474083F755B950792140AA656B7D91E04740772FF7C951782140FE99417C60DB474056BC9179E47721402635B401D8DA474056815A0C1E762140C9552C7E53DA4740D4B5F63E55752140FF05820019DA47402CB81FF0C0702140BA490C022BD9474007EC6AF2947D2140295C8FC2F5D847407B116DC7D48521407B6649809AD8474097E65608AB992140CCEEC9C342D74740800C1D3BA88C21407C992842EADA4740F722DA8EA98B21402B14E97E4EDB47409F91088D608B2140D3F4D901D7DB4740782975C9388E2140A5BF97C283DC474058AA0B78999921408048BF7D1DDE4740F92CCF83BB9B21405376FA415DDE4740B151D66F269E2140D6AC33BE2FDE4740F722DA8EA9AB2140A77A32FFE8DB4740D6AC33BE2FB621407D5D86FF74D94740D32D3BC43FC42140355F251FBBD34740B14E95EF19C92140FE99417C60D347404ED367075CCF2140D5AF743E3CD347407E1B62BCE6D52140A7B0524145D34740FD1186014BDE214000C79E3D97D347404FCDE50643E521407AA86DC328D44740AF5DDA7058F22140FC1A498270D547404CE2AC889AF821408048BF7D1DD64740FD1186014BFE2140FDDB65BFEED6474081069B3A8F0222407E5704FF5BD74740AB59677C5F0C2240D200DE0209D84740F6285C8FC21522407EC9C6832DD84740286552431B282240FED2A23EC9D74740753BFBCA832C2240A7E9B303AED74740594C6C3EAE8522402635B401D8D4474025EA059FE6F42240382F4E7CB5C9474074B7EBA529222340950B957F2DC54740C03FA54A941D2340B7EF517FBDC04740D2C43BC0931E23407C9C69C2F6BF4740F52EDE8FDB1F23407F8461C092BF474081069B3A8F222340A777F17EDCBE4740782975C9382E2340FE0B040132BC47404FCAA486363023402BDEC83CF2BB4740782634492C39234081423D7D04BC4740D5AF743E3C4B23407C992842EABA47407632384A5E4D2340A96BED7DAABA474058AD4CF8A54E23407E54C37E4FBA474057B3CEF8BE582340D482177D05B347404CE2AC889A5823405182FE428FB2474054C554FA09572340FA264D83A2B14740D3BEB9BF7A5423407D93A641D1B04740A27F828B154D2340FD4D2844C0AF474008E92972884823407E5704FF5BAF4740772CB649454323407AA52C431CAF47409F94490D6D4023405340DAFF00AF47404ACE893DB43F2340FFB1101D02AF47402383DC45983A23402541B8020AAF47407E1B62BCE6352340FCE4284014AE4740286211C30E332340D4B5F63E55AD4740D3BEB9BF7A142340AB59677C5FA44740A051BAF42F11234011A8FE4124A34740D6A9F23D23012340A968ACFD9D9D4740304B3B3597FB22407C6308008E9B474057B3CEF8BEF82240FA264D83A299474056BC9179E4F722407B6649809A984740A27C410B09F822405340DAFF009747402E54FEB5BCFA224029ED0DBE30954740C8EA56CF49FF2240562B137EA993474056B950F9D7022340823CBB7CEB9147407B116DC7D40523407F8461C0928F47403048FAB48A062340295FD042028E47402577D84466062340FED5E3BED58C47404FCDE50643052340D3F4D901D78B47406FF1F09E03F3224090F63FC05A8747408200193A76F82240D0D38041D2874740772CB64945032340D5B2B5BE4888474008E6E8F17B132340295C8FC2F5884740CCD24ECDE5162340295C8FC2F58847405F7B6649803223408AABCABE2B884740A4703D0AD7432340266E15C4408747405A9BC6F65A702340A9DA6E826F86474007EC6AF294BD234021205F4205834740D5B2B5BE48C0234028BA2EFCE0824740D1CABDC0ACC82340A19E3E027F804740FE0E45813EC923404F22C2BF08804740313F373465C723407C2AA73D257F4740A379008BFCC22340A1A17F828B7D4740D5B2B5BE48C023404D2EC6C03A7C4740FF08C38025BF2340234DBC033C7B4740C8EA56CF49BF23407A6CCB80B37A4740AA656B7D91C023402502D53F88784740AC53E57B46C22340CCEB884336784740DD955D30B8DE2340FED5E3BED5744740B151D66F261E24402BDB87BCE56E4740A27C410B09382440FED5E3BED56C4740A777F17EDC3E2440A8716F7EC36C4740D0D38041D2472440253B3602F16C474010B056ED9A482440395FECBDF86C47407632384A5E4D2440276893C3276D4740AC5626FC52572440D1CDFE40B96D4740FC1D8A027D7224407D21E4BCFF6F4740AB5FE97C787624405401F73C7F7047409F94490D6DA024402920ED7F8077474024809BC58BA524407E54C37E4F7A474051C1E10511B1244079AEEFC3417E4740000341800CB524407E5704FF5B7F4740CCD24ECDE5B62440520ABABDA47F47405A9E077767C524402B172AFF5A804740B05758703FC82440527C7C4276804740AD50A4FB39CD244029EACC3D24804740D9B0A6B228DC2440D47FD6FCF87D474058AA0B7899F92440D200DE0209784740B22D03CE52FA2440F0C34142947747400C76C3B645F12440C022BF7E886F4740020D36751EE524407E8AE3C0AB61474051C1E10511F1244027F911BF625147402C6684B707F9244028F38FBE494F4740782634492CF92440508E0244C14E4740A3737E8AE3F82440A8A78FC01F4C47408200193A76F8244000C79E3D974B474008E6E8F17BF324407D21E4BCFF474740D9B3E73235F124405628D2FD9C464740782975C938EE2440D3FA5B02F0454740F6CFD38041EA2440AF7D01BD70454740D8B628B341E624407B9FAA4203454740800C1D3BA8AC2440FF9600FC53464740314278B4719C24402BDB87BCE54647405AA148F7739A2440FF08C38025474740DD955D30B87E2440FFCF61BEBC4A4740D1CDFE40B97D24407F4B00FE294B474007EC6AF2947D2440562B137EA94B474008E3A7716F7E2440A7ECF483BA4C4740753E3C4B90812440D2C43BC0934E4740A182C30B228224407AA52C431C4F4740CCCF0D4DD9812440520ABABDA44F4740F92CCF83BB7B244001C11C3D7E514740021077F52A7A2440D673D2FBC65147407638BA4A77772440823CBB7CEB51474006F52D73BA5C2440D47C957CEC504740DBA7E331033D244079AEEFC3414E47407B14AE47E11A2440527FBDC282454740A56ABB09BE192440D388997D1E454740CCD24ECDE5162440D47C957CEC404740F71F990E9D162440FD4D2844C03F47407F129F3BC1162440A9A10DC0063A474054C554FA0917244001C11C3D7E39474056BC9179E417244080457EFD10394740782634492C192440552E54FEB5384740314278B4711C2440286552431B384740763579CA6A2224407E5704FF5B3747407632384A5E2D2440FD1186014B36474059A48977802F2440D6AC33BE2F364740A46DFC89CA4E2440533D997FF43147402E54FEB5BC5A2440AB984A3FE12247404ED026874F5A24405055A18158224740772FF7C951582440D47C957CEC204740CCD24ECDE5562440AA656B7D91204740286552431B4824407D96E7C1DD1D474059A7CAF78C442440505260014C1D474081069B3A8F422440D1031F83151D4740B05758703F282440D00CE2033B1C47404FCDE50643252440FE0B0401321C4740A182C30B2222244056F5F23B4D1C4740D5B2B5BE48202440A5BF97C2831C4740AF5A99F04B1D244029ED0DBE301D4740FC1A498270FD2340D4B5F63E5525474054C554FA09F72340A6B915C26A2A47407F129F3BC1F623402635B401D82A4740304B3B3597FB2340AB59677C5F2C474006F52D73BAFC2340A6B6D4415E2D474004FEF0F3DFFB234027327381CB2D4740AD4D637B2DF82340FF9600FC532E47402577D84466E62340A8E0F08288304740772CB64945E3234000CADFBDA3304740FC1D8A027DD2234080457EFD103147404ED367075CCF2340FCE1E7BF07314740DE8FDB2F9FB42340AC5626FC522F4740D5B2B5BE48A023407D96E7C1DD2D4740DF89592F868A2340CCB22781CD2B47402B69C537146E2340508E0244C1264740A96BED7DAA6A2340D6AC33BE2F2647402D5A80B6D56423402AE44A3D0B264740F52EDE8FDB3F2340A6B6D4415E254740F4346090F4292340295FD04202264740AD4D637B2D1823407AA52C431C274740F6285C8FC215234028F38FBE492747407E1EA33CF30A2340D47C957CEC284740F52B9D0FCFEA2240FE0E45813E314740A774B0FECFE92240FA264D83A23147403048FAB48AE622405628D2FD9C364740295C8FC2F5E82240D3BEB9BF7A3C4740A777F17EDCBE2240295C8FC2F540474057B3CEF8BEB8224052465C001A4147402E54FEB5BC9A22407B6649809A404740A27C410B099822405401F73C7F404740A77A32FFE8932240D200DE02094047405A9BC6F65A902240A5BC5642773F4740D7A6B1BD168C2240A9DA6E826F3E4740F52EDE8FDB7F224055F833BC5939474000000000008022402B172AFF5A384740753E3C4B90812240A5BC5642773747404CDF6B088E832240556D37C137374740F722DA8EA98B2240D576137CD336474023861DC6A48F2240D6AC33BE2F364740247D5A457F9022405531957EC2354740A27C410B0998224029ED0DBE302D4740772FF7C95198224051888043A82C4740D6AC33BE2F962240A774B0FECF2947409E978A8D7995224055F833BC59294740CEC3094CA78D2240FC1A498270254740EA094B3CA07C22406E5166834C1E4740021077F52A7A2240527FBDC2821D4740CBD8D0CDFE6022402638F581E4174740314278B4715C2240FDDB65BFEE1647402E54FEB5BC5A22402829B000A6164740D9B3E73235512240D47FD6FCF8154740AD889AE8F349224011902FA18215474057B08D78B2432240A5BF97C283144740A96BED7DAA2A22402920ED7F800F4740AF5DDA7058122240AC5626FC5207474008E9297288082240AB984A3FE1024740F437A11001FF2140000341800CFD4640FD1186014BFE2140FB230C0396FC4640295C8FC2F50822407E18213CDAF84640CDCCCCCCCC0C2240FED2A23EC9F746405A9BC6F65A102240266E15C440F74640A182C30B22222240FD1186014BF64640D1CABDC0AC2822407DCC07043AF54640DE921CB0AB2922402CD505BCCCF446407F15E0BBCD2B224054FEB5BC72F346407F15E0BBCD2B224029E78BBD17F346407E1EA33CF32A2240A7E67283A1F24640D0D03FC1C5122240D5AF743E3CEB4640FF08C38025FF2140D28BDAFD2AEA464051BB5F05F8E62140FE0B040132EC4640C8EA56CF49DF2140556D37C137EF4640DF8C9AAF92DF2140A86E2EFEB6EF4640D4BB783F6EDF2140514F1F813FF046405AA148F773DA21402B14E97E4EF34640CDCCCCCCCCCC2140A4C2D84290F94640DF89592F86CA21405055A18158FA4640266E15C440A72140D47FD6FCF8FD4640D5B2B5BE48A0214000C45DBD8AFE4640AC53E57B46A2214052431B800D0447402F51BD35B0A521407F87A2409F044740B05417F032B32140813FFCFCF7064740D3BEB9BF7AB4214028F38FBE49074740F4311F10E8B42140D0D38041D207474008E6E8F17BB32140D00F2384470947403145B9347EB12140D1066003220A47404FCAA48636B02140FC1D8A027D0A4740F722DA8EA9AB214054FEB5BC720B474051BB5F05F8A62140AB59677C5F0C4740A379008BFCA2214082397AFCDE0C4740D2C43BC0937E21402920ED7F800F47405A0D897B2C75214049DA8D3EE60D4740FC1D8A027D722140527FBDC2820D47402B69C537146E2140D388997D1E0D474051BB5F05F8662140543A58FFE70C4740AC53E57B46622140AA9ECC3FFA0C4740267156444D3C214002BB9A3C650F47404ED026874F3A2140520ABABDA40F47407F15E0BBCDEB20407D96E7C1DD1D47407923F3C81FE42040A5BC5642771F47404CDF6B088EE32040D0D38041D21F4740FD1186014BDE20407E5182FE42254740DD955D30B8DE204027327381CB254740A379008BFCE220407B6649809A284740020D36751EE5204027F911BF62294740A96BED7DAAEA2040D0D03FC1C52A47404DDC2A8881EE20407AA52C431C2F474058AD4CF8A5EE2040D5B2B5BE48304740AB59677C5FEC2040D3F71A82E3384740AA622AFD84EB2040FDD8243FE2394740266E15C440E72040AB984A3FE13A4740020D36751EE52040FBE769C0203B4740D4BB783F6EDF20402B14E97E4E3B4740267156444DDC2040A7B05241453B47400307B47405BB20407BA2EBC20F3A4740CCD24ECDE5B6204029266F809939474006F52D73BA9C20405376FA415D3647400307B474059B2040FCE428401436474058AA0B7899992040D1CDFE40B935474006F2ECF2AD472040253B3602F11C4740DE921CB0AB492040A8A78FC01F1C474051C1E105115120407EC9C6832D184740FA264D83A2512040FF08C38025174740257497C4595120405628D2FD9C16474055BFD2F9F04C204000C79E3D97134740A088450C3B4C2040FBE769C020134740FB20CB8289072040508BC1C3B40147404DD6A8876804204080457EFD10014740E76F422102FE1F40D5B2B5BE480047404DD6A88768E41F4051853FC39BFF4640CDCCCCCCCCCC1F40266E15C440FF46407A1A3048FAA41F40266E15C440FF4640D9B0A6B2289C1F40A777F17EDCFE46401B9DF3531C871F40276893C327FD4640800F5EBBB4811F40D3BEB9BF7AFC46405F96766A2E771F4027F911BF62F9464029417FA1476C1F4065A9F57EA3F5464086C954C1A8641F40AB048BC399F54640CEC64ACCB3221F40A7AD11C138F64640782634492CF91E40AC5626FC52F74640179CC1DF2FD61E40272F3201BFF8464006F52D73BA9C1E40FC1A498270FD464054C554FA09971E40A8E3310395FD464024809BC58B251E40FE47A643A7FD4640BE13B35E0CD51D40527C7C4276F84640A27C410B09B81D40813FFCFCF7F646408FE1B19FC5921D407E5182FE42F546402C634337FB831D40D1031F8315F546400307B474055B1D40AB9509BFD4F5464049D576137C331D4079AEEFC341F6464058AD4CF8A52E1D4052499D8026F64640FF058200192A1D40295FD04202F646407F15E0BBCDEB1C407E1EA33CF3F24640DE921CB0ABC91C40D47C957CECF04640D6A9F23D23C11C40A8E0F08288F04640257A19C572BB1C40A8E0F08288F04640354069A851781C40272F3201BFF04640EC51B81E856B1C40D47C957CECF046403A22DFA5D4651C4052465C001AF14640AF5A99F04B5D1C4029266F8099F1464023861DC6A44F1C405534D6FECEF2464016A243E048401C40AB59677C5FF446408DEDB5A0F7261C4028F38FBE49F74640C8EA56CF491F1C40FBE769C020FB46401E8B6D52D1081C407F8461C092FF464045F30016F9051C40AA9B8BBFEDFF4640257A19C572BB1B40A9A44E4013074740A777F17EDC7E1B40A7B05241450B474010CCD1E3F7261B40276BD44334124740CEC64ACCB3221B407E1EA33CF3124740F52EDE8FDB1F1B402CD505BCCC144740DF8C9AAF921F1B407E5182FE42154740B05417F032331B40FE9C82FC6C3047401B65FD66623A1B4052103CBEBD33474011C64FE3DE3C1B40276893C327354740B83D4162BB3B1B40A8E33103953547409F8EC70C54361B40508E0244C136474049D576137C331B407AA52C431C37474015A8C5E0612A1B407F8461C09237474049D576137CF31A40D00F23844739474023861DC6A4CF1A40276BD443343A47401E8B6D52D1881A4053793BC2693B474014AE47E17A141A40D0D03FC1C53A47402079E750860A1A405307793D983A47408CDAFD2AC0F71940253E7782FD3947404FCAA48636501940D7A6B1BD1634474091D5AD9E933E1940FE99417C6033474058AD4CF8A52E19402A1DACFF73324740E481C8224DFC184027327381CB2D4740782634492CF91840FC1A4982702D4740DAAA24B20FF21840A8A78FC01F2C4740EC51B81E85EB1840FFCF61BEBC2A474010CCD1E3F7E61840D00F238447294740D3C1FA3F87E91840D47C957CEC28474011FE45D098F91840CEC7B5A162284740AB5FE97C78161940D3C1FA3F87214740257A19C572FB18402BDEC83CF21B4740800F5EBBB4C11840D6AC33BE2F164740FD1186014BBE18407D96E7C1DD15474046ED7E15E09B1840562B137EA91347401E8B6D52D1881840FBE769C02013474091D5AD9E937E18407E1EA33CF3124740E481C8224DFC17405534D6FECE12474008E3A7716FDE17402CD8463CD9194740AF5A99F04BDD1740AC53E57B461A4740DC9E20B1DDDD17405534D6FECE1A4740C8EA56CF49DF1740514CDE00331B474055BFD2F9F0EC17407D5A457F681C4740C7F0D8CF62091840D3FA5B02F01D47401F85EB51B81E18402BDB87BCE51E4740FD1186014B3E1840D38558FD1120474087F8872D3D4A18407C9C69C2F61F474014AE47E17A5418407F8461C0921F4740C4E9245B5D6E1840FC17080264204740A27C410B0978184055F833BC59214740382EE3A6067A18402CD8463CD92147406284F068E37818407E54C37E4F224740BC3E73D6A76C1840BAF59A1E14264740F6285C8FC27518407AA52C431C2747400ED8D5E4297B1840AA9B8BBFED274740DC9E20B1DD9D1840AB5FE97C782E47403546EBA86AA218407E5704FF5B2F4740A182C30B22A218405437177FDB2F4740CBD8D0CDFEA01840D5B2B5BE483047409C8713984E9B18407D5D86FF7431474097AB1F9BE4971840D4EE5701BE31474047E7FC14C771184001BEDBBC713447401E8B6D52D1481840D2C43BC0933647406D5512D907591840D3C1FA3F873947402079E750868A1840D1031F83154547406F490ED8D5841840A7E67283A14A4740AC53E57B46821840D2FD9C82FC4A474056B950F9D7821840AA622AFD844B4740020D36751E8518402BDEC83CF24B4740D2C77C40A013194002BB9A3C65574740618A7269FC621940286211C30E5B4740EC51B81E856B194054FEB5BC725B47407638BA4A77771940D00CE2033B5C4740BB2BBB6070BD1940FCE1E7BF0761474023861DC6A4CF1940FBE769C02063474014AE47E17AD419402BDEC83CF2634740EB573A1F9ED51940A5BF97C283644740DE921CB0ABC9194054FEB5BC726B4740ED45B41D53D71940A96BED7DAA7247401C977153031D1A40AB59677C5F7C47402C634337FB431A40FC1A4982707D4740B83D4162BB7B1A4028F38FBE497F47406F490ED8D5841A40520ABABDA47F47407920B248138F1A40A8E0F08288804740B6300BED9CB61A40AB59677C5F844740A088450C3BCC1A407EC9C6832D884740AB59677C5F2C1B40272F3201BF904740CDE506431D661B4091990B5C1E9547400307B474055B1B40FD9FC37C799547409A99999999591B407E1B62BCE695474046ED7E15E05B1B40A7AD11C138964740618A7269FCE21B40A6B6D4415EA54740C007AF5DDA001C407E8D2441B8AE4740AB59677C5FEC1B40FD1186014BAE4740A56ABB09BEB91B40D3FA5B02F0AD4740D8B628B341861B40FFCC203EB0AD4740020D36751E851B408048BF7D1DAE4740D8B628B341861B40FA298E03AFAE4740DE921CB0AB891B40A86E2EFEB6AF47409F8EC70C54F61B40520ABABDA4BF47409A99999999191C40FCE1E7BF07C14740D9EBDD1FEF951C4010786000E1BF4740B6300BED9CB61C4080457EFD10B947407D21E4BCFFBF1C407B6649809AB84740CCD24ECDE5F61C40295FD04202B6474011C64FE3DEFC1C407D96E7C1DDB54740EC4B361E6C011D40295FD04202B6474043FF04172B1A1D407E5704FF5BB74740B83D4162BB3B1D402B172AFF5AB847406D5512D907591D40514F1F813FB84740F52EDE8FDB5F1D4029EACC3D24B8474061FA5E43706C1D403A747ADE8DB7474058AD4CF8A56E1D402920ED7F80B7474048E17A14AE871D407E5704FF5BB747408DD47B2AA78D1D407F8461C092B74740D3C1FA3F87A91D402AE109BDFEB84740A29BFD8172BB1D407E1EA33CF3BA474023861DC6A4CF1D407AA86DC328BC474011C64FE3DEFC1D407E5704FF5BBF4740AC53E57B46021E40D38558FD11C04740276893C327FD1D40FFCC203EB0C5474091D5AD9E93FE1D4052499D8026C64740EC4B361E6C011E40AB5FE97C78C647407632384A5E0D1E40266E15C440C74740179CC1DF2F161E40520ABABDA4C74740AB7823F3C82F1E40FC17080264C84740F33AE2900D341E40D673D2FBC6C94740E2934E24983A1E40A6B915C26ACA47406F490ED8D5441E40FD4AE7C3B3CA47406D5512D907591E40AB984A3FE1CA4740212235ED625A1E4042959A3DD0CA4740392861A6ED8F1E40505260014CCD474007EFAB72A1B21E40A968ACFD9DCD4740C9E4D4CE30B51E407E5182FE42CD474044F9821612B01E40D28BDAFD2ACA47402B69C53714AE1E40D673D2FBC6C94740A96BED7DAAAA1E4001C11C3D7EC9474051BEA085047C1E40D0D38041D2C74740F52EDE8FDB9F1E40AB5FE97C78C6474077137CD3F4C91E40530438BD8BC547400C00000016A4198BA66B2140ABCB290131D947409F91088D606B2140FC1D8A027DDA4740A96BED7DAA6A21407E1EA33CF3DA4740295C8FC2F5682140A7B0524145DB47407B116DC7D4652140FD14C78157DB4740A56ABB09BE592140514CDE0033DB4740AC5626FC52572140D482177D05DB4740A185048C2E5721405182FE428FDA4740A7ECF483BA582140FF23D3A1D3D947402D5DC136E2592140D00F238447D947404F75C8CD705B21405D70067FBFD8474016A4198BA66B2140ABCB290131D94740'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('TU','TR','TUR','792','Turkey','76963','72969723','142','145','35.179','39.061','0106000020E61000000500000001030000000100000015000000E05A0A48FB133A40B0923A014DE4434060DBBE47FD113A40D8F4D901D7E3434070D367075C0F3A40787B1002F2E343402093533BC3043A40583448C153E6434080A86DC328FC3940B8380EBC5AE8434060D158FB3BFB3940D8CABDC0ACE84340A01133FB3CFA39404873B9C150E94340208C9FC6BDF93940E0EE5701BEE9434090C3B64599F93940788D96033DEA4340A01133FB3CFA3940F0083543AAEA4340004B598638FE3940A89BFD8172EB4340104E9A0645033A40D0F4D901D7EB434080CC79C6BE083A4028179CC1DFEB4340A0B262B83A0C3A40E0B22781CDEB4340406BD44334123A4098C85A43A9EB4340C016838769133A40B0DDAF027CEB4340E0488446B0153A40F0083543AAEA434050C422861D163A40788D96033DEA434050C422861D163A40808AE3C0ABE94340100341800C153A40100341800CE54340E05A0A48FB133A40B0923A014DE4434001030000000100000014000000206211C30ED3394058732B84D50C444010904C874EBB3940309C16BCE80B44400037C478CDAB394078A52C431C0F44400006820019AA3940B0A70183A40F4440F05E7D3CF4A9394080C9C6832D104440102DCF83BBAB39405037894160134440C0393FC571AC3940A8C85A43A913444000938D075BB039402026E1421E15444090A52C431CB73940606D37C137174440A0F27684D3C63940D8E847C3291B4440A00A7F8637EF39402899D53BDC1E444010301004C8F039402899D53BDC1E4440F05F200890F13940D0C43BC0931E444090992842EA023A40A0BF97C283144440B0DDAF027C033A4088A86DC328144440B0DDAF027C033A40A8C85A43A913444070D2FBC6D7023A408881204086124440201B498270FD3940B09E3E027F10444070CDE50643F53940A841D13C800F4440206211C30ED3394058732B84D50C44400103000000010000001B000000407A19C5729B3B40080F45813E494440103F5585069A3B4078ABAE4335494440F0CDFE40B98D3B4000E869C0204B4440406552431B883B4028232E008D4C444030780AB952873B4048732B84D54C4440406E15C440873B40B0B6D4415E4D4440003483F8C0863B4008274D83A2514440A0F27684D3863B40888D96033D524440809C69C2F6873B40D0FD9C82FC52444090CC79C6BE883B40A8B05241455344402083DC45988A3B40202CF180B253444070D87DC7F08C3B4080008BFCFA534440E04718062C993B404870784144544440101B4982709D3B407893180456544440F0298E03AFA63B40A0A78FC01F544440209694BBCFA93B4080008BFCFA534440901A3048FAB43B40604CDE0033534440E04BC5C6BCBA3B400812F8C3CF514440D04CF73AA9BB3B40A8C2D8429051444080B262B83ABC3B4088ABAE4335514440005DDF8783BC3B40382F3201BF504440D04CF73AA9BB3B40A0A70183A44F4440C010018750B93B40D8F19881CA4E4440406E15C440B73B40B098BC01664E4440C04F38BBB5A03B40D8066003224A4440F05CDF87839C3B40A01AF67B62494440407A19C5729B3B40080F45813E494440010300000001000000FF060000087C293C688C41407884D38217FB4440909065C1C48B414088A52C431CF74440787B1002F28B414058499D8026F64440B0923A014D8C4140585260014CF5444050D7DAFB548D4140D0B22781CDF3444060E3DEFC8691414038B7ED7BD4ED4440584CDE00339B4140B8E67283A1E24440C85E7D3CF4A14140D05B3CBCE7DC4440A0AA4203B1A44140B0B0524145DB4440B8B915C26ABA4140B0C85A43A9D34440B8B6D4415EBD4140D8D03FC1C5D24440D0A6954220BF4140A8FCDD3B6AD244408893A641D1C04140788AE3C0ABD14440503448C153C64140382F3201BFD044400812F8C3CFC941402850FD8348D044405076FA415DCE4140D0CABDC0ACD04440888461C092CF4140D8B56801DAD04440B8B915C26AD24140605E64027ED14440B83E90BC73E24140506A6803B0D54440F87B293C68E44140A8AD11C138D64440D0EB884336F04140608BC1C3B4D944408887A2409FF44140B0B0524145DB44402899D53BDCF6414030232E008DDC4440908461C092F74140808A558330DD4440808AE3C0ABF94140201D1EC2F8DD4440D0F10A444FFA414010E5284014DE444038232E008DFC4140D8CDFE40B9DD44404861A5828A064240F802B34291D84440E0D38041D2074240004E2844C0D744408003CC7C070942402099D53BDCD6444078A2EBC20F0A4240E0B8A981E6D54440E0E506431D0E4240F87E6ABC74D14440D8DC43C2F70E4240B0380EBC5AD04440382F3201BF10424098AA4203B1CC44408093A641D110424098C85A43A9CB444058465C001A114240508E0244C1C64440807E5182FE10424000240C0396C4444050DD5CFC6D0F4240606DA983BCC244402041B8020A0F424028111AC1C6C14440D8F19881CA0E4240C8CABDC0ACC04440908D2441B80E4240808461C092BF4440D8DC43C2F70E42402829B000A6BE4440F0603601860F424000B2BB4049BD44408087140324104240000C040132BC4440382F3201BF104240A09BFD8172BB4440D8E506431D164240586A6803B0B54440588E0244C11E4240A8E3310395AD444078A86DC3282C42406070784144A44440486DA983BC32424008301004C8A04440382CF180B23342402850FD8348A0444080FD497CEE364240A8A44E40139F4440F820CB82893742407878CF81E59E444008E869C0203B4240D8F19881CA9E4440087C293C683C424088FD497CEE9E4440E0E506431D3E42408090D783499F4440889C69C2F63F424088C9C6832DA0444060431B800D444240F8F02C4146A24440303B3602F1444240B0D11DC4CEA24440181ADD41EC484240506A6803B0A54440D00F238447494240305FD04202A64440A898BC01664E424050E09D7C7AAC4440D0BBEA01F3524240285FD04202AE4440001B4982705542406076FA415DAE44407084D382175B4240808D2441B8AE4440385FD042025E424000FD304278AE4440B8E9B303AE674240607FBDC282AD4440606A6803B06D4240585B238271AC4440B841D13C806F4240289C16BCE8AB44401009C38025774240483ACAC16CA84440D0D38041D27F42402844F98216A44440E00F2384478142400015C78157A34440E0FD9C82FC824240888D96033DA24440D0B22781CD834240B0AAD0402CA1444070008BFCFA834240E0EB884336A04440D8F4D901D7834240587FBDC2829D4440302CF180B283424028179CC1DF9B4440302CF180B283424000F12C41469A4440D8F4D901D78342406073B9C1509944405870784144844240306552431B984440A0AA4203B184424058DD5CFC6D974440A0A17F828B85424000FD304278964440A098BC0166864240D8B8A981E695444058DD5CFC6D874240001B4982709544400021CB82898F4240D8FD9C82FC924440A8C2D84290914240B0A4C00298924440605E64027E934240F8E159828C92444000FD3042789E424078A2EBC20F924440301D1EC2F8A5424048E3DEFC86914440403D0B4279B54240C8F10A444F8A44403838F581E4BF4240B0B6D4415E8544406037894160C3424028179CC1DF834440F80EB743C3C442405064E6029783444000E5284014C64240B0C85A43A9834440B8B915C26ACA424088724D81CC84444020327381CBCD4240D8E506431D86444000FD304278CE424028145B41D3864440806649809AD04240202922C32A8A4440D8F4D901D7D342401899D53BDC8E444080A86DC328D44240606D37C1378F444050499D8026D64240E0CABDC0AC90444050DD5CFC6DD7424008FAEFC16B914440D8BE2B82FFD7424098C2D84290914440587C7C4276E04240386E15C4408F444050888043A8E44240E0D6C1C1DE8C4440F87B293C68E44240F87B293C688C4440309C16BCE8E3424050E3DEFC8689444020179CC1DFE34240787E5182FE884440000C040132E44240808714032488444050732B84D5E4424088FD497CEE864440B0E3310395E5424028B7ED7BD4854440386552431BE84240E0C77C40A0834440A89E3E027FE842400815C78157834440708D96033DF2424038327381CB7D444088992842EAF24240606A6803B07D444060853FC39BF74240F881AB3C817E4440081B498270FD4240A8DA6E826F7E4440F820CB8289FF42409898BC01667E4440D0F4D901D70B4340F8FF71C2847B4440080341800C0D4340D8E847C3297B444068361D01DC0E4340B0923A014D7A444058E09D7C7A14434060E3DEFC86794440D0B56801DA284340281D1EC2F8754440286211C30E2B4340306893C32775444050732B84D52C43407887A2409F74444078AEEFC3412E4340F87B293C6874444030B7ED7BD4354340080FB743C374444050DA1B7C6142434020327381CB75444038BA2EFCE05A434028266F8099794440305FD042025E4340B0B05241457B4440D8E2C5C210614340809FAA42037D44406082FE428F62434088AEEFC3417E4440A8C85A43A9634340586D37C1377F4440203B3602F16443401000000000804440507C7C4276684340D80F238447814440081286014B764340D8EEC9C342854440F820CB828977434080CC07043A8544405070EA03C97F434088724D81CC844440806649809A804340D80CE2033B844440D80F238447814340A8A78FC01F844440D061BEBC00874340D8EEC9C342854440F8230C03968C43400882AB3C81864440E058FB3BDB8F4340F0F36DC1528744409081204086924340286552431B8844400015C78157934340D0CABDC0AC8844409015E0BBCD93434008BB9A3C65894440E0D6C1C1DE9443406082FE428F8A4440B0E33103959543406082FE428F8A4440586DA983BC9A434030266F8099894440204DBC033C9B4340A81AF67B62894440B8B6D4415E9D4340B8BC564277874440F81186014B9E4340D8DC43C2F7864440201ADD41ECA043405876FA415D86444058DA1B7C61A2434080AEEFC341864440B0C85A43A9A343405876FA415D86444080CC07043AA5434028145B41D38644400012F8C3CFA94340587C7C4276884440D0EEC9C342AD434030111AC1C6894440E0CABDC0ACB043408084D382178B4440303E7782FDB14340082DCF83BB8B444048431B800DB44340D0031F83158D444078724D81CCB44340506A6803B08D444050D7DAFB54B543408896E7C1DD8D4440D8B8A981E6B54340305FD042028E444028C0B0FCF9BC4340889FAA42038D4440204A7B832FBE43408087A2409F8C4440E009A1832EBF434088A86DC3288C4440305FD04202C64340E009A1832E874440B8A44E4013C74340204A7B832F864440F817080264D84340001808026480444080724D81CCF44340A83E90BC737A4440A0B915C26A0A4440281D1EC2F8754440306893C3270D4440081B49827075444060499D80260E444058D7DAFB5475444060BF44BC75104440605260014C754440504CDE003313444020327381CB75444000DCD7817322444050404CC2857A4440504CDE00332B444020118C834B7D4440888A5583302D4440F881AB3C817E4440C0B6627FD92D4440B871FDBB3E7F4440808192020B2E4440F09C6681767F4440F86393FC882F444028473A0323814440505E64027E31444088A2EBC20F824440001BD7BFEB31444060CD018239824440D8FD9C82FC32444038085740A182444030085740A13A4440101B498270854440906308008E3B4440F805F4C29D854440B0AA4203B13C4440B8E331039585444098C519C39C3E4440505260014C854440D8F10A444F4A444030FF05820087444008274D83A251444080A2EBC20F8A4440F8D89601675D444048E3DEFC8691444080DCF0BBE9624440585260014C954440B0E67283A16A4440189F573CF598444058BC033C696B44406869FCC22B994440A00B5C1E6B6C44406869FCC22B994440F8230C03966C44406869FCC22B994440086493FC886D4440C8BBEA01F3984440787E5182FE70444088871403249844402844F98216744440D8D38041D2974440F8EDEBC0397544405070EA03C9974440D809A1832E774440C0BE2B82FF974440F805F4C29D854440503D0B42799D4440207EE200FA954440104240BE84A44440B0CEF8BEB89A4440881799805FA74440D0C16C020C9D44408803CC7C07A944403841B8020A9F4440D0C4AD8218AA44408803CC7C07A94440A8B0C403CAAE44405037894160AB444048438D4292AF4440B0923A014DAC4440080C76C3B6AF4440D0A623809BAF444048438D4292AF444038266F8099B14440786F0C01C0AF444090DE701FB9B14440A014CAC2D7AF4440302922C32AB24440F8EAAA402DB044407893180456B44440B8A10DC006B2444008D9960167B54440C8BBEA01F3B2444078A52C431CBF4440E0D6C1C1DEBC4440F802B34291C04440A898BC0166BE4440787214200AC444406894675E0EC34440E0B56801DAC84440E0F10A444FC24440080FB743C3DC44403041B8020ABF4440080F45813EE1444078008BFCFABB4440E0E2C5C210E94440B041D13C80B7444088A2EBC20FEA4440D061BEBC00B7444008093543AAEA444030145B41D3B64440304DBC033CEB44407878CF81E5B644408803CC7C07F1444008093543AABA44405037894160F34440888A558330BD444018179CC1DFF3444000E5284014BE4440B8B6D4415EF544400079E8BB5BBF44405073B9C150F9444000274D83A2C14440788D96033DFA44400806820019C24440A8B0524145FB4440B0B915C26AC24440209C16BCE8FB4440A83E90BC73C24440B0B6D4415EFD4440E0F10A444FC24440A8BF97C2830C4540385C8FC2F5C04440B0B6D4415E154540385C8FC2F5C044400879E8BB5B174540385C8FC2F5C0444080992842EA22454080FD497CEEBE444078724D81CC244540A898BC0166BE444038BD6F7CED274540889FAA4203BD4440D8DC43C2F72E454080992842EABA4440F8F02C41463A4540A0A70183A4B74440605B2382713C4540B8BC564277B744408896E7C1DD3D4540286552431BB84440F881AB3C814645405058E20165BF4440B8B393C151484540D8E2C5C210C14440806308008E4B4540D806600322CA4440B0BF97C2834C4540B8E67283A1CA444048499D80264E4540386211C30ECB444060793BC26953454028179CC1DFCB4440606D37C137574540A8A78FC01FCC4440607C7C427668454000E869C020CB4440D8D90242EB69454020BA2EFCE0CA44404865FCFB8C6B4540D0C4AD8218CA444008F12C4146724540D8F71A82E3C0444088A2EBC20F8245406055A18158B24440D0031F83158545402838F581E4AF4440F8EAAA402D904540385C8FC2F5A84440E0B8A981E69D4540B0380EBC5A984440000FB743C3AC454080758E01D9994440F8F36DC152AF4540D85E7D3CF4994440A8C2D84290B14540808AE3C0AB9944400082AB3C81B64540080C76C3B6974440888461C092B74540988FF9804097444078758E01D9B94540D8B8A981E6954440808D96033DBA45400006F4C29D9544406082FE428FBA4540E0EEC9C34295444030232E008DBC4540E0F10A444F924440080FB743C3BC4540D0D90242EB914440D8D6C1C1DEBC4540007F6ABC74914440A8AA4203B1BC4540305C8FC2F5904440307DE882FABA4540A85C8C81758E4440808D96033DBA4540F80241800C8D44400806820019BA4540605B2382718C44400806820019BA4540906308008E8B44402026E1421EBD4540E0C77C40A083444050D7DAFB54BD4540304DBC033C834440C8E506431DBE4540B0E67283A1824440582B85402EBF4540282922C32A82444088FD497CEEC64540786F0C01C07F4440908461C092C74540908461C0927F4440E0F71A82E3C8454050DD5CFC6D7F4440D8C7B5A162CA4540B09201A08A7F4440B0D11DC4CECA4540908461C0927F44405064E60297CB4540A0BC5642777F4440200ED940BACC45402841B8020A7F4440F005F4C29DCD4540F881AB3C817E4440201D1EC2F8D54540C8F19881CA764440304A7B832FD64540A098BC01667644402041B8020ADF4540B0A4C00298624440D058FB3BDBDF45400000000000604440584F1F813FE04540808D2441B85E44407878CF81E5DE454058D7DAFB54554440C882FB010FDC4540A06BD102B44F4440002DCF83BBDB4540B08FF980404F44406064E60297D34540E0DF84420444444020179CC1DFCB45407887140324404440B0E67283A1CA4540E0EE5701BE394440586A6803B0CD4540606D37C1372F4440A8AA4203B1D44540F8E769C020234440482EC6C03ADC4540B8B6D4415E154440F0F6AE415FDC4540D05B3CBCE7144440F0F6AE415FDC4540585B238271144440A8A78FC01FDC4540D8DF84420414444000E869C020DB4540D0C77C40A0134440B0A4C00298DA4540A0DDAF027C1344407090D78349D74540F8FF71C28413444030B7ED7BD4D54540D0BBEA01F3124440C83D0801F9D44540B03D7AC37D124440F80B040132D4454088FA08FCE1114440284DBC033CD34540A0CB9BC3B5104440E0FD9C82FCD2454008EBAA402D10444080992842EAD24540F80B76C3B60F4440286211C30ED3454008F46DC1520F444088A86DC328D44540E0B8A981E60D44400806F4C29DD545402826E1421E0D4440B8AD11C138D64540D85B3CBCE70C444070724D81CCF4454058DA1B7C610244400021CB8289F74540C8EE5701BE0144407893180456FC4540981AF67B62014440B8A78FC01F044640E0B56801DA004440888A55833005464058465C001A014440784B72C0AE064640808AE3C0AB014440D8F4D901D7234640D0B8A981E6054440B8BF97C283244640D0B8A981E6054440505B2382712C4640386211C30E034440B8E33103952D4640B8E67283A10244408084D38217334640507C7C4276004440A8DA6E826F3E4640284DBC033CFB4340204A7B832F464640F00EB743C3F44340002A8E03AF464640286211C30EF343403029B000A6464640A0A4C00298F24340D061BEBC00474640D8EE5701BEF14340000C76C3B64746400003B34291F04340D8C77C40A04B4640B8E67283A1EA434058431B800D4C4640D8F10A444FEA434020473A03235146406058E20165E74340206211C30E5346406076FA415DE64340B041D13C805F4640507FBDC282DD4340700C01C0B1634640B8B915C26ADA43402826E1421E654640B0957B8159D94340E0C43BC09366464060853FC39BD74340D0F19881CA664640A88FF98040D74340B09E3E027F684640F0083543AAD243403023A0C211684640F0ED5D83BED04340804221020E5F4640B8EC82C135D94340B0A17F828B5D4640F8DBD78173DA4340A8AD11C1384E4640886308008EE34340A8A17F828B4D4640289C16BCE8E34340785166834C3C4640501CB28174D94340F88AE07F2B3D464040FE0B0401D243407890D7834937464070ABAE4335B94340A0A44E40133746409823B9FC87B84340A898BC01663646408890D78349B74340D0EEC9C342354640B01D37FC6EB64340E0DF84420434464070698A00A7B5434000093543AA324640785DF8C1F9B44340806308008E2B464028085740A1B24340F05AD07B6328464028266F8099B14340D8F1D1E28C2746402045813E91B14340F881AB3C8126464060E3DEFC86B14340583D0B427925464028266F8099B1434020145B41D31E4640786F7EC344B34340A88C2AC3B81D46407866BB421FB44340F0B73D41621D464020E17B7F83B44340D0EEC9C3421D4640C8A96400A8B44340A8AA4203B11C46404825034015B54340309C16BCE81B4640B8B6D4415EB5434040490F43AB194640B8B6D4415EB5434030205F42050B4640D8D6C1C1DEB44340887E5182FE084640A0AA4203B1B44340A8B393C1510846408093180456B44340283B3602F104464098AD8383BDB1434000F7AE415F044640E00F238447B1434000F7AE415F044640806649809AB04340B06E675F790446400885251E50B04340806F0C01C00746402826E1421EAD4340B0C2D8429009464020205F4205AB4340D8C77C40A01B4640B0A10DC006924340A8B30584D61B46402032E54350914340082DCF83BB1B4640A823B9FC87904340E0C7D11C5919464020C05B2041874340F805F4C29D154640D0D90242EB8143405046CEC29E144640305C8FC2F580434048197101681446401850FD8348804340B0BF97C28314464000DF1802807F4340204A7B832F164640309C16BCE87B434030085740A11A464008093543AA724340D04065FCFB1A464088A2EBC20F724340200B98C0AD1F464088FD497CEE6E4340507C7C42762046403029B000A66E4340F8EA1C03B2234640D0C43BC0936E434000240C0396244640B098BC01666E4340E0EEC9C342254640788192020B6E4340808192020B264640C85B3CBCE76C434018145B41D3264640A0D11DC4CE6A43402841B8020A274640F85AD07B63684340D0C43BC093264640E0DC43C2F7664340F8264D83A2214640C8C16C020C5D4340A01AF67B6221464000F7AE415F5C4340D8CDFE40B92546401844F9821654434080637AC212274640483789416053434070DF313CF6274640D8F10A444F524340F8EAAA402D284640F8264D83A2514340786649809A28464000FD3042784E4340000F45813E29464018A5D93C0E434340000F45813E294640083CA24275414340000F45813E2946406073B9C150414340C8F71A82E3284640D8DC43C2F73E4340D0EB884336284640D0D6C1C1DE3C43403078B5DC9927464028AB06616E3B434088A52C431C27464000F12C41463A4340508E0244C1264640F82F1004C838434080637AC212274640806F7EC344334340D0C4742156274640500ABABDA4314340886CE7FBA9274640A80DDC813A31434070DF313CF6274640C8B56801DA304340382F3201BF284640F802B34291304340F0264D83A2294640005BD07B63304340981403249A2A4640005BD07B63304340506DA983BC2A4640005BD07B63304340B0A70183A437464028085740A1324340208A3BDEE4374640D83043E389324340483ACAC16C3846405055A181583243408096E7C1DD3D4640889FAA42032D4340201D1EC2F83D4640582EC6C03A2C434078543541D43D4640A09BFD81722B434028EA93DC613D464040A4DFBE0E2A4340B0897780273D464098957B815929434048732B84D53C4640302F3201BF284340F8F6AE415F3C4640E0EB884336284340B0EDD11BEE3B464000C74961DE27434028C632FD1233464080D2DEE00B1B4340B01AF67B62294640505B2382710C4340D8C43BC0931E464080992842EAFA4240B0282504AB1C46403095456117F34240607FBDC2822546405070EA03C9EF4240605E64027E494640C8F10A444FE24240282922C32A4A4640383E7782FDE1424078A52C431C4F4640A089778027DD424008F46DC1524F4640505B238271DC4240302C6343374F4640B0C85A43A9DB42402829B000A64E46406055A18158DA4240D8A96400A84C4640583ACAC16CD84240B0D11DC4CE4A4640D8C43BC093CE424020205F42054B464088758E01D9B9424008CFD902424B4640586DA983BCB84240D0D3F203574B464000D655815AB8424020179CC1DF4B4640805AB741EDB74240D8A96400A84C4640A8A70183A4B74240782D05A4FD4D4640A8A70183A4B74240B0C519C39C4E4640A8A70183A4B74240B09E3E027F5046406058E20165B7424018205F4205534640588E0244C1B64240B0C519C39C664640B8AAD0402CA9424008D655815A68464078637AC212A74240D8F71A82E3684640A8CEDC43C2A542402032E54350694640F0F6AE415FA4424080ABAE4335694640806CCB80B3A24240D0B56801DA6846400006820019A24240483D0B4279654640A898BC0166964240F072D87DC7644640D0E847C329934240906308008E63464020C0B0FCF9944240D0E847C329634640605260014C95424088A2EBC20F624640E0CDFE40B9954240B8BC5642775F4640603448C153964240606DA983BC524640504F1F813F984240888AE3C0AB514640D0BE2B82FF974240B0D11DC4CE4A4640709FAA420395424050DA1B7C614A4640F80EB743C3944240F80E45813E49464020179CC1DF9342402023A0C211484640B83E90BC739242403841B8020A47464000FAEFC16B914240D0B8A981E6454640A8E0F08288904240E0F19881CA3E4640804EB340BB8B4240100C0401323C46404855A181588A4240E058FB3BDB3746402823A0C211884240F80EB743C32C4640D05B3CBCE7844240B0C85A43A92B4640D0B56801DA80424058465C001A294640F87B293C687C4240786649809A284640582EC6C03A7C424018473A0323214640888192020B7E4240E0CABDC0AC204640081286014B7E4240A0C2D84290194640C8D03FC1C58A4240205C8FC2F5184640707B1002F28B4240302F3201BF18464048732B84D58C4240D8E2C5C21019464030327381CB8D424038C0B0FCF91C4640906308008E934240281D1EC2F81D464020179CC1DF93424018473A032321464038232E008D944240F8264D83A2214640200ED940BA944240A8A10DC006224640709FAA420395424008F12C4146224640081B498270954240B0B915C26A224640305FD042029642405055A18158224640385C8FC2F5984240D0D90242EB214640F8EDEBC0399D4240505E64027E214640E0DC43C2F79E4240D0F71A82E3204640B0E9B303AE9F4240D0FA5B02F01D46407884D38217A34240D0031F83151D4640E0C77C40A0A342400821CB82890F4640B8B393C151A842407878CF81E50E4640A09E3E027FA84240B0923A014D0C4640786649809AA8424010B4024356094640A09E3E027FA8424058499D8026064640000F45813EA942400012F8C3CF0146407803CC7C07A94240B09E3E027F004640B8B393C151A84240E0D03FC1C5FA4540A0AA4203B1A44240B83E90BC73FA45408093180456A44240A08CB80034FA454080B130444EA34240D85E7D3CF4F945403035B401D8A2424030BD6F7CEDF74540604F1F813FA04240D0CDFE40B9F545401048A643A79D4240B03B4F3C67F54540585260014C9D424060888043A8F44540A8AA4203B19C4240A0C85A43A9F34540F8F6AE415F9C4240B09E3E027FE84540F07B293C689C4240886F0C01C0CF4540001B4982709D424000F46DC152BF4540889C69C2F69F4240C8E506431DBE4540B8380EBC5AA042401844F98216944540E058FB3BDBAF42400003B34291804540080072C284AB4240808714032480454078B130444EAB4240303B3602F17C454080758E01D9A9424088992842EA7A45405831074147A94240D8F10A444F7A4540000F45813EA94240808AE3C0AB7945405831074147A94240001286014B764540D85E7D3CF4A94240F81D8A027D724540C8BBEA01F3AA42400812F8C3CF694540A8B6D4415EAD4240585E64027E694540A8AD11C138AE4240A81AF67B62694540B0A70183A4AF4240100F45813E694540386552431BB04240205C8FC2F5684540503ACAC16CB04240F81708026468454058672783A3B0424008EEEBC039654540100F45813EB142408887A2409F64454080ABAE4335B14240889065C1C4634540302F3201BFB0424020C094810362454050E0810184AF4240000FB743C35C4540000341800CAD42405064E602974B4540A88FF98040974240C8BBEA01F34A4540E0CDFE40B9954240E0D03FC1C54A45408087A2409F944240B83E90BC734A4540906308008E934240B8A10DC0064A454078B130444E934240F87E6ABC74494540584CDE003393424048431B800D44454038BA2EFCE0924240584F1F813F3045403841B8020A8F4240F8FF71C2842D4540C88B4CC0AF8D4240D0CDFE40B92D4540A0A70183A48F4240606A6803B02D4540A8C2D84290914240583D0B42792D4540300ED940BA9C4240B8B6D4415E2D4540B0897780279D4240383B3602F12C4540E0FA5B02F09D4240100C0401322C45406061A5828A9E4240506A6803B02545408081204086A24240D8C77C40A01B4540080341800CA542401009C38025174540808A558330A5424058793BC269134540505E64027EA14240F8083543AA124540D0F71A82E3A0424000093543AA0A454000093543AA9A42407890D78349074540D0CABDC0AC9842405858E20165FF4440D0E506431D964240906308008EEB444060672783A390424000F46DC152C74440386211C30E8B4240809FAA4203C54440C8D03FC1C58A424038B7ED7BD4BD444000F12C41468A4240D006600322BA444000068200198A4240A098BC0166AE444020266F809989424008F7AE415F9C444058465C001A894240282CF180B29B444030473A03238942406055A181589A444020111AC1C68942400009C380258F444048E09D7C7A8C42403041B8020A774440706649809A9042400015C78157734440607C7C4276904240B08FF98040674440300B98C0AD8F4240F8083543AA62444080A52C431C8F4240100F45813E594440000FB743C38C4240C861BEBC00574440282CF180B28B42402829B000A656444048378941608B4240303B3602F1544440B0B915C26A8A424058310741475144408893A641D1884240B8B915C26A424440504CDE0033834240301ADD41EC404440606DA983BC824240A0CEDC43C23D444000093543AA8242406055A181583A4440808D96033D8242402850FD8348384440888AE3C0AB814240A88977802735444008EBAA402D804240D8B22781CD2344402899D53BDC76424018111AC1C6214440780C01C0B1754240A89BFD81721B4440F8083543AA724240887E5182FE0044402050FD8348684240C8CABDC0ACF84340483D0B4279654240304A7B832FF6434050888043A8644240E0EE5701BEE94340302F3201BF604240B0E9B303AEE7434088C9C6832D604240B0B0524145CB4340D0DF8442045C4240E00CE2033BB84340C8B3AF3C48594240A841D13C80A7434020145B41D3564240807E5182FEA04340607FBDC282554240001B4982709D4340286893C327554240100C0401329C4340286893C3275542405055A181589A4340808A5583305542403099D53BDC964340583D0B4279554240D0031F8315954340201D1EC2F8554240A0CB9BC3B5904340B841D13C8057424078931804568C43408003CC7C07594240A8C2D84290894340D85E7D3CF459424088AEEFC341864340A8A4C002985A4240D0D6C1C1DE844340004BE7C3B35A4240007F6ABC74814340B8E67283A15A4240B0E0F0828880434000F12C41465A4240A8DA6E826F7E4340E0EE5701BE594240A8C85A43A97B434078ABAE433559424000E5284014764340887E5182FE58424058732B84D5744340305C8FC2F5584240E0E847C329634340A0957B8159594240603448C1535E4340808AE3C0AB594240F005F4C29D5D4340E0EE5701BE594240F87B293C685C434070A2EBC20F5A4240D0FD9C82FC5A4340E0D03FC1C55A4240908461C092574340D0D6C1C1DE5C4240483ACAC16C504340D0F10A444F624240603448C15346434058793BC2696B4240000C040132444340A8ECF483BA6C4240D8EE5701BE41434030B7ED7BD46D42406058E20165374340A0957B8159714240087F6ABC74314340D0FD9C82FC724240889C69C2F61F434028C0B0FCF9744240306E15C4401F4340080341800C754240001B4982701D4340E05B3CBCE7744240D809A1832E174340887B1002F2734240386893C3270D43408887140324704240080C0401320C4340104E2844C06F424078B130444E0B434000F46DC1526F424088A52C431C074340D8D6C1C1DE6C4240C05E61C1FD02434008F4893C496A42400009C38025FF4240A0C2D84290694240000072C284FB4240F802B34291684240100F45813EF94240F820CB82896742405876FA415DF64240506A6803B0654240F8230C0396F4424050732B84D56442400006820019F2424078008BFCFA63424000F7AE415FE44240D8D38041D25F4240A8DDAF027CE34240A8E9B303AE5F4240A0C2D84290E14240A0A70183A45F4240A8AD11C138DE4240000C76C3B65F424058431B800DDC4240809C69C2F65F424020111AC1C6D9424060853FC39B5F4240D0CDFE40B9D542405876FA415D5E424088FA08FCE1C94240588BC1C3B4594240B09E3E027FC8424030473A0323594240888D2441B8C642403050FD83485842404870784144C44240508E0244C15642409093A641D1B04240302CF180B253424058853FC39BAF424088008BFCFA53424060499D8026AE424080A86DC328544240101E8A027DA24240100341800C554240D858FB3BDB9F4240E0031F8315554240B8B393C151904240F8F6AE415F544240607FBDC282854240A89BFD81725B4240383B3602F184424078A86DC3285C42406064E60297834240A83B4F3C675D42407890D783497F4240A09E3E027F60424008FD3042787E4240E0E2C5C21061424038C0B0FCF97C4240D8EE5701BE614240B041D13C807742404864E60297634240D85E7D3CF4594240202922C32A6A4240B8AD11C138564240A8D11DC4CE6A4240B01C210379544240982C6002B76A4240D05B3CBCE7544240585E64027E69424030C0B0FCF954424028BD6F7CED674240585B238271544240B0DA6E826F664240286211C30E4B424008F46DC1524F4240B098BC0166464240D861BEBC003F4240101286014B4642408096E7C1DD3D4240607C7C4276484240081286014B364240886649809A4842408896E7C1DD35424050465C001A494240D0031F8315354240A0A4C002984A424030BA2EFCE032424040A79201A054424090D21742CE2742408887140324584240080341800C254240B0E0F08288584240E00CE2033B244240B0CB9BC3B5584240F80B76C3B61F4240786649809A584240B0C519C39C1E4240B8380EBC5A584240A0AD11C1381E424050853FC39B5742401048A643A71D4240E0F19881CA5642402826E1421E1D4240583448C153564240283B3602F11C4240587C7C42765042402844F982161C42407890D783494F424078008BFCFA1B4240D0FA5B02F04D424088A86DC3281C4240908AE3C0AB494240306893C3271D424028232E008D44424058499D80261E4240D8B56801DA4042408896E7C1DD1D4240286BD4433432424088B130444E1B42401823A0C21130424008F46DC152174240789C69C2F62F4240888D2441B8164240789C69C2F62F4240204A7B832F164240B0B393C15130424008E52840140E4240587C7C42763042402026E1421E0D4240301ADD41EC304240D8F4D901D70B4240A0C2D84290314240F8083543AA0A424050465C001A314240309C16BCE8034240C09481035A3042400800000000004240A8EAC9FCA32F4240B0BC564277FF414058FB743C66264240A0A78FC01FFC414020327381CB1D4240D0F4D901D7FB4140885182FE421D4240202CF180B2FB414050431B800D1C424088992842EAFA4140109A417C601B4240306BD44334FA4140089D82FC6C184240A89509BFD4F541408821E4BCFF174240383B3602F1F44140A8E9B303AE174240B87A32FFE8F34140F820CB8289174240089A417C60F34140805704FF5B174240806649809AF04140805704FF5B174240001B498270ED4140E0C43BC093164240A0C2D84290E94140D07FD6FCF81542408818213CDAE84140587FBDC28215424010CADFBDA3E84140080C04013214424010CADFBDA3E84140A01DA9BEF3134240F8517FBDC2E84140381DACFF73124240084BE7C3B3EA41400018080264104240D0031F8315ED414008E52840140E424078AEEFC341EE4140B0A10DC006024240904B00FE29F34140D842908312F6414048CB48BDA7F64140E8FD2AC077FD4140A819E0826CFF4140789FAA4203FD4140100F45813E014240888D96033DFA4140A89E3E027F0842400003B34291F84140100C0401320C424050732B84D5EC4140E0DF8442041C4240386893C327E54140F8F6AE415F2442404870784144E44140E0FA5B02F0254240000C040132E44140B841D13C802742407893180456E44140C0BE2B82FF27424058732B84D5E44140D8B56801DA2842409093A641D1E84140101B4982702D42407896E7C1DDF54140E00F2384473942402899D53BDCF64140D8066003223A424050888043A8044240E0B22781CD434240C8FA5B02F0054240B0BF97C283444240D0E847C329134240584CDE00334B4240A8923A014D14424058378941604B4240586A6803B015424070B130444E4B4240081286014B16424058378941604B42400079E8BB5B174240382CF180B24B424088C9C6832D1842402844F982164C424008301004C818424080724D81CC4C4240787E5182FE18424090CC07043A4D4240D8C77C40A01B4240606DA983BC52424020179CC1DF1B4240D8F4D901D753424020179CC1DF1B42408093180456544240B03E90BC731A424030111AC1C66142405855A181581A424008093543AA624240302F3201BF184240A8B6D4415E654240485260014C15424080A2EBC20F6A4240D00F2384471142408096E7C1DD6D424030BD6F7CED0F424088A52C431C6F424088758E01D9094240E0C77C40A073424038BD6F7CED074240080341800C754240E0DF844204044240101286014B764240A8D11DC4CE024240D0C43BC093764240202922C32A024240D0C43BC09376424000274D83A2014240B8DA6E826F764240D8EB8843360042409096E7C1DD754240F8E769C020FB4140C8BBEA01F3724240283E7782FDF94140D80660032272424030BD6F7CEDF7414090C9C6832D704240B8BF97C283F44140B0923A014D6C424000E869C020F3414018205F42056B424078758E01D9E94140809065C1C4634240D8E2C5C210E94140B8B0524145634240D0E506431DE64140888D96033D624240D8031F8315E5414070FA08FCE16142405070784144DC41407893A641D160424028BA2EFCE0DA4140807E5182FE604240D8F10A444FDA4140B0AAD0402C614240D0D90242EBD94140F8F9EFC16B614240F82F1004C8D8414030111AC1C6614240D0D03FC1C5D24140607C7C4276604240E0F10A444FD241402850FD8348604240305FD04202CE4140D8FA5B02F05D4240B85B920376C941405861A5828A5A4240D00F238447C9414070A2EBC20F5A4240D00F238447C94140F8264D83A259424058E3DEFC86C94140D0EB884336584240508BC1C3B4C941405070EA03C9574240306BD44334CA4140B0E9B303AE574240A8AD11C138CE4140D000DE0209584240F8F9EFC16BD1414000F46DC152574240908AE3C0ABD14140182922C32A524240585E64027ED1414078A52C431C4F4240B0957B8159D14140B0C519C39C4E424020473A0323D1414060499D80264E4240B09E3E027FD04140081B4982704D42408878CF81E5CE4140F87B293C684C4240A8A17F828BCD4140F02CCF83BB4B42400003B34291C84140C8066003224A4240809C69C2F6C7414080A2EBC20F4A4240286E15C440C74140C8066003224A4240204A7B832FC6414090812040864A424030327381CBC54140D8D03FC1C54A424080A86DC328C44140F87B293C684C4240281ADD41ECC04140888192020B4E4240507C7C4276C0414078AEEFC3414E4240D858FB3BDBBF4140603448C1534E42408096E7C1DDBD41401048A643A74D424080724D81CCB44140F8F02C41464A424060D7DAFB54AD41400882AB3C81464240F0FF71C284AB4140789FAA42034542407878CF81E596414058853FC39B4F424020205F4205834140808AE3C0AB5942408090D783497F4140080072C2845B424028B7ED7BD47D414078A86DC3285C424028232E008D7C4140007C293C685C4240807E5182FE784140F80EB743C35C424078FD497CEE76414088724D81CC5C4240808A55833075414028232E008D5C4240A8ECF483BA74414078931804565C4240D0EE5701BE734140D091CEC0C85B4240206BD44334724140A8A44E40135F42400012F8C3CF7141403838F581E45F42408893A641D170414088ABAE4335614240004E2844C06F4140D0066003226242402844F982166C414038232E008D64424088FA08FCE169414028327381CB654240B0DDAF027C634140A841D13C8067424018145B41D35E4140D0BE2B82FF674240B8B6D4415E5D4140386552431B684240D8F10A444F5A4140D0D38041D2674240F87B293C68544140A0A44E4013674240000F45813E49414078B130444E634240908461C092474140D0F10A444F624240889FAA42033D4140D8F10A444F5A4240A0DA6E826F2E414000274D83A2514240080C0401322C4140F802B342915042405073B9C150294140D0F19881CA4E4240D0031F8315254140F02CCF83BB4B4240202922C32A224140585E64027E494240302F3201BF204140504F1F813F48424060DD5CFC6D1F41407878CF81E5464240305FD042021E414028C0B0FCF944424080CC07043A1D4140D0E847C3294342408087A2409F1C4140B83E90BC73424240D8C77C40A01B4140F87E6ABC74414240F8FF71C28413414030205F42053B4240507C7C427610414008FAEFC16B394240A8E67283A10A41408087A2409F34424030111AC1C6094140000072C284334240087F6ABC740941409081204086324240A81AF67B62094140D05E7D3CF43142405873B9C150094140B0B393C151304240F8F9EFC16B0941408090D783492F424028266F8099094140483448C1532E424058431B800D044140D8F19881CA2642405861A5828AFE4040886308008E23424038BD6F7CEDF7404030179CC1DF234240104E2844C0F74040100C04013224424058499D8026F640400006F4C29D2542408803CC7C07F14040C0BE2B82FF274240587C7C4276F0404090C9C6832D284240004E2844C0EF4040D0EB8843362842405076FA415DEE404050853FC39B274240305FD04202EE40408890D78349274240607C7C4276E84040A01AF67B622142406058E20165DF4040B8B915C26A1A424008F12C4146DA4040D0DC43C2F7164240809065C1C4D34040D0BE2B82FF1742404882FE428FD240402850FD8348184240D8E506431DCE404008F46DC152174240F805F4C29DCD4040E009A1832E17424088CC07043AC5404078FA08FCE1114240A8DA6E826FAE404008274D83A2114240080FB743C3A4404030BD6F7CED0F424028327381CB854040A0C85A43A90B4240F8264D83A2794040F8F6AE415F0C424078C9C6832D784040585B2382710C424050853FC39B774040F8F6AE415F0C42402829B000A66E4040282F3201BF084240D00F23844769404078724D81CC0442400021CB8289674040B8B0524145034240D0D03FC1C5624040382CF180B2034240E0CDFE40B9554040889FAA420305424060DA1B7C614A404008F12C41460A4240303E7782FD49404088812040860A4240C87F2C448748404038F99FFCDD0B424050431B800D444040D8F4D901D70B4240808D96033D424040D8DF8442040C424058672783A3404040B8BF97C2830C4240B0A70183A43F4040383B3602F10C42408890D783492F404080AEEFC34116424078FD497CEE2E4040E0C43BC09316424078B130444E2340405055A18158224240386BD443341A4040D0DF8442042C424038266F8099194040B0AA4203B12C42408887140324184040D8DC43C2F72E4240E0DC43C2F7164040383E7782FD314240E0FA5B02F0154040A09BFD81723342407884D38217134040D0DC43C2F7364240506A6803B00D404030232E008D3C42402850FD8348084040000682001942424038BA2EFCE0024040B0B6D4415E454240D85E7D3CF401404028B7ED7BD4454240305C8FC2F5004040D8E506431D464240081808026400404048499D8026464240A01342075DFE3F40586A6803B0454240B0F06778B3D23F40A8DDAF027C4B4240305FD04202BE3F40080F45813E514240A09FAA4203BD3F40007F6ABC74514240A00EF27A30953F4030473A0323594240A0E67283A1623F40000C0401326442409014747B495F3F4078CC07043A654240C0FFACF9F15B3F4078AEEFC341664240909C69C2F6573F40D0DC43C2F766424080A86DC3284C3F40B0B393C151684240404F1F813F483F40806649809A684240A0FFACF9F10B3F40A0AA4203B16C4240104B598638FE3E4050D7DAFB546D4240B0E0F08288F83E40607FBDC2826D4240F014C78157E33E40C8EEC9C3426D4240D0DDAF027CD33E40B0923A014D6C424040861DC6A4CF3E4080A86DC3286C4240C016838769C33E4050431B800D6C4240A0ECF483BABC3E40B03B4F3C676D4240A0F5B704E0BB3E400848A643A76D424090C1A73979B53E405070EA03C96F4240A01F46088FB23E40887E5182FE70424050CAA48636B03E40D80F238447714240308FE046CAAE3E404873B9C150714240F03E558506AA3E403050FD8348704240D03FC1C58AA63E406058E201656F4240D05147C7D5A43E408078CF81E56E4240908461C0929F3E40D05B3CBCE76C424070C8957A169C3E40206211C30E6B4240E05E7D3CF4993E4000274D83A26942408087A2409F943E40888192020B664240209BE447FC923E40D85B3CBCE764424060DBBE47FD913E40B8A78FC01F644240A08461C0928F3E40303B3602F15C4240E0CDFE40B98D3E4028145B41D34E4240306E15C440873E408890D783493F424060D158FB3B7B3E402029B000A636424040D9E90775793E40C8F10A444F32424040D9E90775793E405873B9C150314240307B4B395F7C3E400882AB3C812E424070DD5CFC6D7F3E4008F7AE415F2C424070D2FBC6D7823E40B0DDAF027C2B4240B002EE79FE803E407803CC7C07294240D0CDFE40B96D3E40306893C3271D42408093A641D1683E4050DA1B7C611A4240406F47382D683E4080A2EBC20F1A4240206E15C440673E4078758E01D919424080B8E4B853663E40A8E67283A11A424050431B800D643E40D0E506431D1E4240C0ED26F8A65D3E40007F6ABC74214240F04718062C493E40201D1EC2F8254240003483F8C0463E40A8DA6E826F264240704CDE0033433E402899D53BDC264240B0F92AF9D8413E4070FD497CEE264240E036FE4465373E4070FD497CEE264240C016838769333E402899D53BDC26424080CFBA46CB2D3E4088AEEFC34126424040D7DAFB54253E40E0031F83152542402093533BC3243E40D8D6C1C1DE24424030895E46B1243E40B8BF97C28324424040D7DAFB54253E40002DCF83BB234240208A90BA9D253E40D8FD9C82FC22424040D7DAFB54253E40282F3201BF204240F05147C7D5243E40B8380EBC5A204240207D5A457F203E4000F46DC1521F4240002BC0779B173E40D0E506431D1E4240209694BBCFF93D408084D382171B42401081CD3978C63D4050793BC26913424070D7DAFB54C53D40786308008E134240D0393FC571BC3D4058888043A8144240407A19C572BB3D40B8ECF483BA144240002BC0779BB73D40F8230C0396144240C0FC6B79E5B63D40007C293C681442402043C879FFAF3D40808AE3C0AB11424010541C075EAD3D401009C380250F4240A0F8F884ECA03D4020B7ED7BD415424070DBBE47FD913D4050E3DEFC8619424070CBD6FA22813D40C8F10A444F1A424060E3DEFC86593D40B0E33103951D4240E04F38BBB5503D40B0A70183A41F4240D00391459A483D40A0D11DC4CE22424030D13C8045423D408096E7C1DD254240D061BEBC002F3D40B8A10DC0062A424060E3DEFC86293D4060378941602B424030809BC58B253D4058888043A82C4240A00DC00644243D40386893C3272D4240405FD042021E3D40D8E2C5C21031424050465C001A193D40585B2382713C4240405C8FC2F5183D4030C0B0FCF93C42408017EFC7ED1F3D40603789416043424050CAA48636203D40D80CE2033B444240C001BC0512203D40F80EB743C3444240109012BBB61F3D40788A55833045424080BB2539601B3D402899D53BDC46424040895E46B1143D400021CB8289474240B016838769133D40B041D13C8047424010541C075E0D3D40D8DC43C2F746424000240C03960C3D40002A8E03AF464240507B4B395F0C3D40101286014B464240909FAA42030D3D40A83B4F3C6745424090A86DC3280C3D40386893C32745424090BB2539600B3D403026E1421E4542409069FCC22B053D4060AFE94141454240C00DC00644043D40B0A17F828B45424040C422861D063D4000093543AA4A4240E036FE4465073D40888A5583304D4240E00391459A083D400082AB3C814E4240F05D4BC807093D408878CF81E54E424020068200190A3D40A0A44E40134F4240A0B8E4B853163D40D8EB884336504240001B4982700D3D40D009A1832E57424050CAA48636F03C4088FD497CEE5E4240B0ECF483BAEC3C40888461C0925F42404098A3C7EFDD3C4090C9C6832D584240705260014CDD3C40D858FB3BDB574240003F558506DA3C408093180456544240308C9FC6BDD93C4088008BFCFA534240004087F9F2CA3C40D8B8A981E6554240306F47382DA83C4088992842EA5A424080C6F7C5A59E3C404882FE428F6242400037C478CD9B3C4028145B41D36642400096CE8767753C40D8CABDC0AC704240B00DC00644743C408893A641D17042401096CE8767653C406061A5828A6E424040E09D7C7A643C40583448C1536E4240A002EE79FE603C4078724D81CC6C424010938D075B603C40585B2382716C424070D4997B48603C4088008BFCFA6B424080B5A33847613C40504CDE00336B4240901F46088F623C406082FE428F6A4240E00050C58D633C4098A4C002986A4240B00EF27A30653C407884D382176B4240B0F3A8F8BF673C40284DBC033C6B4240F0420246976B3C40B0B915C26A6A424060BEA085046C3C40383E7782FD6942400037C478CD6B3C4028266F8099694240E055BABBCE6A3C40E058FB3BDB67424040780AB952673C40B0ECF483BA644240C0F27684D3663C407093180456644240B0052FFA0A663C4058431B800D64424070DBBE47FD613C4078008BFCFA63424020301004C8603C40B8A78FC01F644240808461C0924F3C40608BC1C3B4694240E0548847E2493C40B0A78FC01F6C4240B0E9B303AE473C40585B2382716C424060E09D7C7A443C4050E09D7C7A6C424010274D83A2413C4030179CC1DF6B424040861DC6A43F3C4078992842EA6A4240B01342075D3E3C4000274D83A269424080D87DC7F03C3C40D0D38041D267424090B262B83A3C3C408878CF81E5664240C0FFACF9F13B3C40B0DA6E826F66424060BEA085043C3C40E0B8A981E665424070D367075C3F3C4088A2EBC20F624240A01A3048FA443C408090D783495F4240C049B6BA9C463C40B0B6D4415E5D4240C008707A173B3C4000FAEFC16B594240C002EE79FE103C40A8DDAF027C4B4240A0F5B704E0FB3B40608E0244C1464240F02AC0779BF73B40F07E6ABC74494240C0488446B0F53B40807B1002F24B424090C1A73979F53B40F87B293C684C4240E052793BC2F53B40080FB743C34C424030840EBA84FB3B402826E1421E4D4240E03C80457E013C40B0ECF483BA4C4240809065C1C4033C4058E09D7C7A4C424020809BC58B053C402844F982164C424050BB5F05F8063C402844F982164C4240A09FAA42030D3C40A8BF97C2834C424070A2EBC20F123C40686D37C1374F4240D0488446B0153C40E00F23844751424060CE177B2F163C40608BC1C3B4514240103D4679E6153C40182922C32A52424040861DC6A40F3C40B8AD11C138564240307A19C5720B3C40D000DE0209584240200F45813E093C400818080264584240D0CABDC0AC083C40D000DE0209584240A019C40776083C40B841D13C8057424060465C001A093C40A8C519C39C564240505C8FC2F5083C4010E5284014564240309E25C808083C408096E7C1DD5542401093533BC3043C40A0A17F828B554240B0DDAF027C033C40607FBDC282554240307288B839FD3B40D8B8A981E6554240F036FE4465F73B40001286014B564240102A8E03AFF63B40A8C519C39C564240003483F8C0F63B40F878E8BB5B57424090AF21382EF73B405070EA03C957424080C3B64599F93B403050FD8348584240D04F38BBB5003C40485E64027E594240F0548847E2093C4080812040865A424010895E46B1143C40B8E67283A15A4240B0FB3905F9153C40D85E7D3CF459424080A52C431C173C4080758E01D9594240306F47382D183C4078FA08FCE1594240900A7F86371F3C403044F982165C4240209012BBB61F3C4060E09D7C7A5C4240E058FB3BDB1F3C40605260014C654240808461C0921F3C40B0CEDC43C2654240201286014B1E3C40B0DA6E826F664240605260014C1D3C40B0C519C39C664240209E25C808183C40E0C43BC093664240406E15C440173C40A898BC016666424090D2FBC6D7123C408087A2409F64424060D9E90775093C40B03E90BC7362424080A2EBC20F023C407803CC7C0761424090FFACF9F1FB3B402850FD8348604240E0393FC571EC3B40B8DA6E826F5E4240207A19C572EB3B405876FA415D5E4240A014AE47E1EA3B40608E0244C15E42407081204086EA3B40084E2844C05F424050D9E90775E93B4030BD6F7CED5F424080ABAE4335D13B40181ADD41EC60424060B5DD04DFCC3B40285C8FC2F5604240B0ECF483BABC3B40181ADD41EC604240A01133FB3CBA3B4008301004C8604240406E15C440B73B40E0EB884336604240F052793BC2B53B40A0A70183A45F4240000C040132B43B400882AB3C815E424060CAA48636B03B405064E602975B424080A99F3715AD3B40B0E0F08288584240306211C30E833B40583448C1535642403099D53BDC7E3B4088CC07043A55424050C763062A7B3B40D0B22781CD534240808AE3C0AB793B40504CDE003353424070CBD6FA22613B40F808C38025574240808D2441B85E3B40889C69C2F657424080A86DC3285C3B4038266F80995942401037C478CD5B3B40B8A10DC0065A42401037C478CD5B3B40081E8A027D5A4240B0E0F08288783B40E000DE020960424050D9E90775793B403838F581E45F4240F061BEBC007F3B40B8BC5642775F4240D0F6E978CCBC3B40906308008E63424070D158FB3BEB3B401048A643A7654240D049B6BA9C063C405073B9C150694240C002EE79FE103C40A8E9B303AE774240604CDE0033333C40D85B3CBCE77C4240206211C30E533C40E0FD9C82FC824240409221C7D6533C40B0B0524145834240000C040132543C4000240C03968442401045D7851F543C40C8031F831585424080D2FBC6D7523C40A8CEDC43C285424090ACE0B721523C4030B7ED7BD4854240103D4679E6453C40A8E331039585424080116DC7D4353C40100341800C8542409093A641D1083C40E0E847C329834240200F45813ED93B40286BD44334824240206893C327AD3B40504F1F813F804240409221C7D6833B40A8A44E40137F4240306893C3276D3B40F8FF71C284834240A0F5B704E06B3B406064E60297834240504F1F813F583B400806820019824240A0FB3905F9553B400012F8C3CF814240A017B5FB55543B40E00F238447814240000C040132543B4000301004C880424050CE177B2F563B40D0D38041D27F4240F049B6BA9C563B405058E201657F424090E67283A1523B40A8A17F828B7D424030861DC6A44F3B40F87B293C687C424010541C075E4D3B40B0C85A43A97B424050D026874F4A3B40306211C30E7B4240E0488446B0453B405855A181587A424070B81E85EB413B40584CDE00337B4240D04543C6A3403B40E0F4D901D77B424090812040863A3B40A0BF97C283844240408C9FC6BD393B403829B000A6864240908AE3C0AB393B40D009A1832E874240C0FFACF9F13B3B405073B9C150894240C0393FC5713C3B40C8EE5701BE89424090E67283A1523B40A09BFD8172934240B016838769533B40F82CCF83BB934240201286014B5E3B40A0B0524145934240704F1F813F683B402850FD834890424030874F3A91703B40A83B4F3C678D4240D0F6E978CC8C3B40D8B56801DA9042400018080264983B40B0CEDC43C29D424010938D075B903B4030205F4205A34240A0C1A73979853B40505E64027EA14240507B4B395F7C3B40788D96033DA24240309694BBCF693B40002A8E03AFA64240E0599E0777673B400021CB8289A74240209C16BCE8633B4008274D83A2A94240B0DDAF027C633B40B0A10DC006AA4240A0F06778B3623B40A89BFD8172AB4240F01D8A027D623B4020C0B0FCF9AC424050EFAA07CC6B3B40D8EB884336B4424000068200196A3B4030232E008DB44240306E15C440673B409087A2409FB44240B00BB1FA23603B4060793BC269B34240C00A7F86375F3B40E0E847C329B34240307B4B395F5C3B407887140324B0424000904C874E5B3B405058E20165AF4240A004FD851E553B40788A558330AD424050D4997B48503B40D8B22781CDAB4240B01342075D3E3B40D0FD9C82FCAA4240507288B8393D3B40F8E769C020AB4240A01F46088F323B40B0AA4203B1AC4240F0264D83A2313B40D85B3CBCE7AC424010314278B4313B40A03B4F3C67AD424080D53C47E4373B4050888043A8B44240C01AF67B62393B4000240C0396BC424080DEFFC709373B40001E8A027DCA4240E049B6BA9C363B4080992842EACA424090C1A73979353B40D0C77C40A0CB4240F0264D83A2313B40A0B6D4415ECD4240908AE3C0AB393B40604CDE0033DB4240C0ED26F8A63D3B40386893C327DD424040861DC6A43F3B40888D2441B8DE424060D4997B48403B4098A70183A4DF4240406211C30E433B40D8CDFE40B9E54240F0C77C40A0433B402838F581E4E74240209BE447FC423B4070ABAE4335F14240F0C77C40A0433B40A8C2D84290F1424090C075C58C443B4058DA1B7C61F2424040C422861D463B4028B7ED7BD4F5424090AEEFC341463B405876FA415DF6424040C422861D463B402099D53BDCF64240E05147C7D5443B400812F8C3CFF9424090C075C58C443B40C8F10A444FFA42409017EFC7ED3F3B4038232E008DFC424070DC2A88813E3B40306893C327FD4240A0E33103953D3B40B83B4F3C67FD4240A0B262B83AFC3A40B0380EBC5A084340A008707A17FB3A40A09E3E027F084340108C9FC6BDF93A400803B34291084340F03C80457EF13A40D0EB884336084340207156444DEC3A40889C69C2F6074340407E8CB96BD13A4020179CC1DF134340D0488446B0C53A40606DA983BC1A4340000C040132C43A4088B130444E1B4340704CDE0033C33A40B8DDAF027C1B4340307D5A457FC03A40F8FF71C2841B4340B01342075DAE3A400012F8C3CF194340D04F38BBB5A03A4058431B800D144340409012BBB69F3A4080A2EBC20F124340307B4B395F9C3A4080CC07043A0D434000904C874E9B3A40080341800C0D434020780AB952973A40789FAA42030D4340A0FB3905F9953A40D8031F83150D434040BEA085048C3A40608E0244C10E434010904C874E8B3A403841B8020A0F4340A0052FFA0A863A40508BC1C3B4114340306893C3277D3A40888192020B16434000938D075B703A40204DBC033C1B4340D0420246976B3A40002DCF83BB1B4340C0CDFE40B95D3A4078724D81CC1C4340E0548847E2593A4000240C03961C434060DEFFC709573A4060888043A81C4340A087A2409F543A40D05B3CBCE71C4340A0F8F884EC503A4038327381CB1D4340D049B6BA9C463A4080758E01D92143402077D84466463A4028232E008D24434070CC79C6BE483A4060707841442C434070C3B64599493A408878CF81E52E434050DA1B7C614A3A40D809A1832E2F4340407D5A457F503A4028BD6F7CED2F4340207E8CB96B513A405870EA03C92F434040431B800D543A4058D7DAFB542D4340E05A0A48FB533A40B0ECF483BA2C4340C00050C58D533A4070931804562C4340C0F92AF9D8513A40D8B22781CD2B434090B5A33847513A40A09BFD81722B434060C1E10511513A40D8BBEA01F32A4340F05F200890513A4090812040862A43402075C93846523A40888D96033D2A4340D05E7D3CF4593A40B8B393C151284340C0C43BC0935E3A40E009A1832E2743408017EFC7ED5F3A4080A52C431C274340F0D03FC1C5723A402844F982162C434060C93846B2733A4070931804562C4340002A8E03AF763A40483D0B42792D4340E05E7D3CF4793A400809C380252F4340D04E0647C97F3A40284DBC033C334340F0565D876A823A40D8CDFE40B9354340C0F06778B3823A40284A7B832F364340E0D03FC1C5823A40E0F19881CA364340306BD44334823A400009C3802537434090BB2539607B3A40000F45813E39434070C3B64599793A40588BC1C3B4394340A017EFC7ED6F3A40D0F4D901D73B43407096E7C1DD6D3A40080C0401323C4340005DDF87836C3A4050707841443C434070C763062A6B3A40080C0401323C434060DA1B7C616A3A40209C16BCE83B434000068200196A3A40A89BFD81723B4340E03E5585066A3A4058DA1B7C613A434080C3B64599693A40303E7782FD394340F00241800C653A40E0B56801DA38434070C93846B2633A40D0F71A82E33843407055A18158623A40B0C2D84290394340F02CCF83BB5B3A40B09E3E027F484340100F45813E593A40B8A44E40134F434020956247E3583A4050672783A3504340808AE3C0AB593A40004BE7C3B352434050D026874F5A3A40E0C77C40A0534340B0F5B704E05B3A40080C040132544340808D2441B85E3A40A8ECF483BA544340A0FB3905F9653A40B0B6D4415E554340C0ED26F8A66D3A409096E7C1DD554340208DD13AAA7A3A40587FBDC282554340002DCF83BB7B3A4060D7DAFB54554340A0052FFA0A863A408003CC7C075143408017EFC7ED8F3A40080FB743C34C4340307D5A457F903A40087C293C684C4340A0ECF483BA9C3A40D8B22781CD43434060CBD6FA22A13A40B8E67283A13A4340B019C40776983A40303E7782FD394340801A3048FAA43A40584CDE00332B4340203483F8C0A63A40D0066003222A4340F0393FC571AC3A40A8E9B303AE27434080C6F7C5A5AE3A400879E8BB5B2743400043C879FFAF3A408090D7834927434080ABAE4335B13A4050DD5CFC6D27434070992842EAB23A4030BD6F7CED2743401015C78157B33A40B0380EBC5A284340B0FE7A8505CB3A40D0EEC9C3422D4340E052793BC2D53A40D0F19881CA2E4340102BC0779BE73A40E058FB3BDB2F4340103483F8C0163B40D0BBEA01F3324340F0548847E2193B40B09BFD8172334340D0CDFE40B91D3B40B0923A014D34434060D367075C1F3B4078724D81CC34434070D9E90775293B408893A641D1384340A08AE3C0AB293B40000F45813E394340100F45813E293B40F8264D83A239434090D53C47E4273B40D8F10A444F3A434090DEFFC709273B40A8B915C26A3A43400037C478CD0B3B4028205F42053B434060D026874F0A3B4028205F42053B4340C001BC0512003B40A8B915C26A3A4340D061BEBC00FF3A40788D96033D3A4340C01C058882FD3A40808AE3C0AB394340001E8A027DF23A40B0E0F08288384340307E8CB96BE13A40B8B393C151404340203A05F9D9C03A40F878E8BB5B4F4340206893C327BD3A405073B9C15051434050BEA08504BC3A40B8A10DC006524340B008707A17BB3A40F8083543AA524340B0E0F08288B83A40B0C85A43A95B434020956247E3B83A40B8A78FC01F5C4340207A19C572BB3A40483D0B42795D4340407B4B395FBC3A40506A6803B05D4340B0E67283A1D23A40B8E0F08288604340F05A0A48FBD33A40F802B3429160434070C422861DE63A40D0EB884336684340A0FC6B79E5E63A40A89E3E027F68434090992842EA023B40A0C519C39C6E4340209C16BCE8033B40D8F19881CA6E434030895E46B1043B400882AB3C816E4340200341800C053B40503D0B42796D434080116DC7D4053B40808A5583306D434080DEFFC709073B40808A5583306D4340206552431B083B4060D7DAFB546D4340A014747B490F3B40586D37C1376F43401043C879FF0F3B40B041D13C806F4340407D5A457F103B4030BD6F7CED6F4340F04F38BBB5103B40583ACAC16C7043400009C380250F3B4028327381CB7543403099D53BDC0E3B4080AEEFC34176434090E33103950D3B4080FD497CEE76434020990F08740A3B40B0BC56427777434040809BC58BF53A40D0BE2B82FF774340000C040132F43A4028BD6F7CED77434090A86DC328EC3A40B0BC564277774340B008707A17EB3A4008F46DC152774340504CDE0033E33A4038B7ED7BD4754340E0C43BC093DE3A40B0AA4203B1744340F0393FC571DC3A4000F7AE415F744340307A19C572DB3A40485B238271744340C01C058882CD3A40202922C32A7A434090D87DC7F0CC3A4088812040867A43401037C478CDCB3A40F07B293C687C434000904C874ECB3A40C8FA5B02F07D434000904C874ECB3A40F881AB3C817E4340A0FFACF9F1CB3A405882FE428F824340D0393FC571CC3A40806308008E834340705260014CDD3A400021CB828987434010301004C8E03A4030BD6F7CED8743400060200890E13A40C8EB884336884340E0D03FC1C5E23A40E0F71A82E3884340101E8A027DE23A40B01AF67B628943400009C38025DF3A4078A86DC3288C434070499D8026DE3A40E05B3CBCE78C4340A010018750D93A402050FD8348904340409E25C808D83A40385C8FC2F590434090A2EBC20FD23A400015C78157934340004B598638CE3A40080FB743C3944340C0D6338463C23A4080C9C6832D9643402083DC4598BA3A4080931804569C4340200341800CA53A40808AE3C0ABA14340C01133FB3CAA3A405861A5828AA64340409012BBB6CF3A40386211C30EB34340B004FD851EE53A40B0AA4203B1BC4340908D2441B8EE3A40F805F4C29DBD4340F04E0647C9EF3A40A0CEDC43C2BD434020874F3A91F03A40788192020BBE434080C93846B2F33A4078AEEFC341C64340D0C77C40A0F33A40588E0244C1C64340B0F92AF9D8F13A40483ACAC16CC8434090BE66B96CF03A4028266F8099C94340308FE046CAEE3A40D806600322CA4340105DDF8783EC3A408881204086CA434090C075C58CE43A40182922C32ACA434090DBBE47FDE13A40303E7782FDC9434060D4997B48E03A40505E64027EC9434080B5A33847D13A402838F581E4C74340409BE447FCC23A40D809A1832EC74340A0EF3504C7B13A40B8A44E4013C74340307A19C572AB3A403041B8020AC743409093A641D1A83A40B0C519C39CC64340D05147C7D5943A40605B238271C44340E0548847E2893A40D8B22781CDC3434090B8E4B853363A40806308008EBB43402096CE8767353A4078B130444EBB43405085B18520333A4028205F4205BB43402075C93846223A40283E7782FDB9434010301004C8203A40283E7782FDB94340A01342075D1E3A40708D96033DBA4340E05E7D3CF4193A4088992842EABA434020895E46B1143A40E0B22781CDBB434070EFFE78AF123A4008D3307C44BC434020274D83A2113A4058732B84D5BC434080ABAE4335113A4028B7ED7BD4BD434070B5A33847113A40B098BC0166BE4340D0F92AF9D8113A400079E8BB5BBF4340E05E7D3CF4193A40A83E90BC73CA434020840EBA841B3A40A0C85A43A9CB434090ACE0B721223A4038327381CBCD4340406E15C440273A40B0E0F08288D04340209E25C808283A4000FAEFC16BD14340E05D4BC807293A4080008BFCFAD34340208C9FC6BD293A40C858FB3BDBD74340C019C40776283A4030473A0323E943401021CB8289273A4050DA1B7C61F2434060CE177B2F263A40000C040132F44340A0052FFA0A263A4058D7DAFB54F543401021CB8289273A402050FD8348F8434050465C001A293A4080A2EBC20FFA4340B0ECF483BA2C3A40B8B6D4415EFD43402043C879FF2F3A40A8A70183A4FF4340107E8CB96B313A403050FD8348004440104E9A0645333A40202F3201BF0044402096CE8767353A40F82F1004C80044400021CB8289373A40483ACAC16C004440B019C40776383A4090C9C6832D004440F05E7D3CF4393A40788461C092FF434060B5DD04DF3C3A4078FD497CEEFE4340409012BBB63F3A403099D53BDCFE434090073E062B4A3A40D8CABDC0AC004440B016838769533A4058DA1B7C61024440B004FD851E553A4088992842EA02444080AEEFC341563A4098C85A43A9034440001E8A027D623A402826E1421E0D4440C0052FFA0A663A40D8D90242EB114440E057C9C7EE6E3A40B0E0F08288184440E03C80457E713A40B0CB9BC3B5184440F058FB3BDB7F3A40C8D03FC1C51A444090C93846B2833A40E0C77C40A01B44400096CE8767853A4080A86DC3281C4440102DCF83BB9B3A406070784144244440005DDF87839C3A4038232E008D244440408FE046CAAE3A4088931804562C444060DD5CFC6DAF3A40A8AA4203B12C4440D00050C58DB33A40080C76C3B62F4440100341800CB53A40D80F23844731444050D367075CCF3A40F8083543AA324440406211C30EE33A40B8E67283A1324440A004FD851EF53A4060465C001A314440A0E9B303AEF73A40281ADD41EC304440C0F27684D3063B4078A2EBC20F32444080CFBA46CB0D3B40505260014C35444070DC2A88810E3B40002A8E03AF364440F0419605130F3B403841B8020A374440E0488446B0153B4088ABAE4335394440103483F8C0163B40B01AF67B62394440A01342075D1E3B40D85E7D3CF4394440F0C77C40A0433B40104BE7C3B33A4440505FD042024E3B4060431B800D34444000240C03964C3B40A8A78FC01F34444010840EBA844B3B40707B1002F2334440B0FFACF9F14B3B40F8FF71C28433444060499D80264E3B40007F6ABC74314440908D2441B84E3B4060465C001A3144405085B18520633B40787B1002F22B4440B0FC6B79E5663B4020205F42052B4440A096E7C1DD6D3B40585E64027E2944402018080264783B4080C9C6832D28444070C3B64599793B40D800DE02092844405075C93846823B400809C3802527444080C93846B2833B40A8A44E4013274440605260014C8D3B40D0F19881CA264440D04F38BBB5903B40686D37C137274440406ADAC534933B4088E49D4319284440B0ED26F8A6AD3B4058853FC39B274440F0CDFE40B9BD3B40B8E9B303AE274440E052793BC2C53B403023A0C21128444080DEFFC709C73B4080C9C6832D284440306552431BC83B40B0B393C151284440F05E7D3CF4C93B4000301004C82844400009C38025DF3B40E0F19881CA2E44400043C879FFDF3B40B8A44E40132F444090B5A33847E13B405070EA03C92F4440F05F200890E13B40604F1F813F304440C03C80457EE13B4050672783A3304440A0BE66B96CE03B40E0B56801DA30444090AEEFC341D63B40C8D03FC1C5324440B0DDAF027CD33B4090992842EA32444080ABAE4335D13B40F8083543AA32444090D87DC7F0CC3B40E05E7D3CF4314440102DCF83BBCB3B4088758E01D93144409081204086CA3B40E05E7D3CF4314440408C9FC6BDC93B4008F12C414632444020938D075BB03B40E0CDFE40B93D4440D04E0647C9AF3B40206E15C4403F4440309012BBB6AF3B40B0A70183A43F4440B004FD851EB53B40608BC1C3B441444050D9E90775B93B4020205F420543444010990F0874BA3B40284DBC033C434440D04CF73AA9BB3B400015C78157434440F04543C6A3C03B40789065C1C4434440B0F92AF9D8C13B40E0F4D901D743444090BB253960DB3B4030BA2EFCE0424440407E8CB96B013C40686D37C1373F4440E05B3CBCE7043C40608E0244C13E4440E03FC1C58A063C40A8AD11C1383E4440B0F3A8F8BF073C40507FBDC2823D444070D53C47E4073C40C8F4D901D73B444090AEEFC341063C40104BE7C3B33A44406055A18158023C40D00F238447394440F04A598638FE3B4030BD6F7CED374440C00A7F8637EF3B40303B3602F13444401037C478CDEB3B40B8BF97C28334444050D9E90775E93B405070784144344440B0FB3905F9E53B40F8083543AA324440308A90BA9DE53B40386BD4433432444040809BC58BE53B4020266F8099314440D03FC1C58AE63B408893A641D1304440A014AE47E1EA3B40E0DC43C2F72E44407082700514EE3B40A098BC01662E4440C0E67283A1F23B40B0CEDC43C22D44402096CE8767F53B400006F4C29D2D4440104818062C093C40306E15C4402F4440F04D9A0645133C40806649809A304440A014AE47E11A3C40D0EE5701BE314440407288B8391D3C40303E7782FD31444050780AB952273C40586DA983BC324440F04A5986382E3C40D0BBEA01F3324440103A05F9D9303C4028BA2EFCE0324440204FCC7A31343C40A83B33C170324440C0DA6E826F3E3C40E0C77C40A0334440F058FB3BDB3F3C40A0C85A43A9334440002DCF83BB7B3C40586DA983BC3244407055A18158823C40B0A4C00298324440202E01F8A7AC3C406061A5828A2E444050CAA48636C03C40E05E7D3CF431444010575D876AC23C4008F12C4146324440D05D4BC807C93C405882FE428F324440A0A86DC328CC3C40808120408632444050D6A88768D43C40302922C32A324440908461C092DF3C40A8957B815931444000274D83A2E13C40281ADD41EC304440D05A0A48FBE33C40C8BE2B82FF2F444060E3DEFC86E93C40D8C43BC0932E44401037C478CDEB3C40B8AD11C1382E44407017EFC7EDEF3C40285FD042022E4440308DD13AAAFA3C40D8CDFE40B92D444090B262B83AFC3C40486A6803B02D444090BB2539600B3D40A8C519C39C2E44409096E7C1DD0D3D4020145B41D32E44409017EFC7ED0F3D40D009A1832E2F44402093533BC3243D40002A8E03AF36444030809BC58B253D40D8DC43C2F7364440F03C4679E6253D4050DD5CFC6D374440E05B3CBCE7243D40E0EB884336384440104E9A0645233D4008301004C8384440308A90BA9D153D4020C0B0FCF93C44400015C78157133D40605260014C3D444050C763062A0B3D40F005F4C29D3D4440A0FC6B79E5063D40B8E33103953D444090C075C58C043D40605260014C3D4440A09FAA4203FD3C4078A86DC3283C4440309694BBCFF93C4028205F42053B4440F00391459AF83C4088992842EA3A444050780AB952F73C40C8BBEA01F33A4440D055BABBCEEA3C40887B1002F23B444090C3B64599E93C403044F982163C4440A017B5FB55E43C40000341800C3D444080DEFFC709C73C403835B401D84244402081CD3978C63C40504CDE0033434440002A8E03AFC63C40302CF180B243444090AF21382EC73C40B0A78FC01F444440C042024697CB3C40D8C43BC093464440A096E7C1DDCD3C40A8BC564277474440C058FB3BDBCF3C40D858FB3BDB474440B01133FB3CDA3C40888AE3C0AB494440F05B3CBCE7E43C401015C781574B4440B0973446EBE83C40D0D90242EB4B444070C075C58CF43C40809C69C2F64F444060D9E90775F93C40A8C2D84290514440F05CDF8783FC3C40282922C32A52444000938D075B003D40A8B915C26A524440202BC0779B273D4078A86DC32854444090BE66B96C403D4080724D81CC544440309BE447FC623D40D8D90242EB594440100C040132643D40383E7782FD59444050CDE50643653D400012F8C3CF59444080A279008B6C3D409050FA42C8574440E04BC5C6BC7A3D40F80B0401325C4440107E8CB96B813D40D8CDFE40B95D4440B0F06778B3823D4020327381CB5D4440A016838769833D40507FBDC2825D4440F04718062C893D40B8B915C26A5A4440407156444D8C3D40206552431B584440A0A99F37158D3D40D0D38041D2574440101286014B8E3D40A0E9B303AE57444020861DC6A48F3D40F80B76C3B6574440D067CEFA94B33D40703123BC3D5A44409087A2409FE43D40284DBC033C5B4440305C8FC2F5E83D40B8B05241455B4440A0ECF483BAEC3D40000072C2845B4440208FE046CAEE3D4078008BFCFA5B4440A00BB1FA23F03D4050888043A85C4440D04F38BBB5F03D400806F4C29D5D444020301004C8F03D40606D37C1375F4440C00A7F8637EF3D40A8957B8159614440D04BC5C6BCEA3D40505E64027E614440D0548847E2B93D403035B401D8624440105A9E0777973D40B0B0524145634440A017EFC7ED8F3D40004BE7C3B36244409087A2409F843D40A83E90BC7362444070C3B64599693D40888120408662444080DEFFC709573D40508E0244C166444050D7DAFB54553D40D058FB3BDB67444040D026874F4A3D4020232E008D6C444090B5A33847413D400809C380256F4440A0AEEFC341263D406064E6029773444070CBD6FA22213D40F80241800C754440B008707A170B3D4028232E008D7C4440E03FC1C58A063D40007C293C6884444020ED7F80B50A3D4050E3C2819086444010D2C5A695163D40084B75012F8F444010D2C5A695163D40C8C83D5DDD91444090E67283A1123D4088008BFCFA934440F00050C58D133D4048732B84D594444040895E46B1143D40A8E3310395954440209E25C808183D408890D78349974440C0EF3504C7213D408884D382179B4440A01F46088F223D4060378941609B4440F036FE4465273D4060E09D7C7A9C444090812040862A3D40789FAA42039D4440E03FC1C58A363D40503448C1539E444070D53C47E4373D405876FA415D9E44409010018750393D40101286014B9E444040D026874F4A3D40788A5583309D4440D00391459A783D407803CC7C07994440C0BA2BBB60943D4038A704C424964440002DCF83BB9B3D40D8B8A981E695444080D87DC7F09C3D40285FD042029644404098A3C7EF9D3D40B8AD11C13896444060D367075C9F3D4018145B41D396444010301004C8A03D40508E0244C196444090ABAE4335C13D40D8D6C1C1DE944440506A4C88B9DC3D40E8976C3CD8924440B0DA6E826FDE3D40F8083543AA924440207E8CB96BE13D405882FE428F92444050D158FB3BFB3D4080FA08FCE1914440C0F6E978CCFC3D4088758E01D991444080D53C47E4273E40303E7782FD914440A010018750293E40A8A10DC00692444060B81E85EB313E405037894160934440409BE447FC423E40786649809A98444020956247E3483E40B0E67283A19A4440206211C30E533E4070A2EBC20F9A4440900DC00644543E40E0D90242EB994440205C8FC2F5583E408093A641D1984440F05E7D3CF4593E40D000DE020998444090BB2539605B3E4058DD5CFC6D974440F0531C075E5D3E40E0DC43C2F7964440407D5A457F603E40A098BC0166964440A032E202D06C3E407006F1811D954440005DDF87837C3E40386211C30E934440B00BB1FA23803E40A0E67283A1924440C017B5FB55843E405055A1815892444050C763062A9B3E4018473A0323914440A08461C092BF3E4060793BC2698B444010314278B4C13E4020205F42058B4440406211C30EC33E4080992842EA8A444090ABAE4335E13E4078758E01D9894440D061BEBC00EF3E40A0C2D84290894440C058518369F43E40A8A17F828B894440F03F87F9F2FA3E4030266F8099894440D0D03FC1C5123F40B0A10DC0068A444050C763062A3B3F4058378941608B4440407B4B395F3C3F40A8DDAF027C8B4440005DDF87834C3F40D8C43BC0938E4440C0FB3905F9553F40A01AF67B62914440002A8E03AF563F40D0EE5701BE91444040EAB0C22D573F4070AEEFC341924440900BB1FA23603F4030B7ED7BD495444080A52C431C673F40B8AAD0402C994440100F45813E693F40E0D03FC1C59A4440208C9FC6BD693F40E0B22781CD9B444050BEA085046C3F40A8DDAF027CA344402037C478CD6B3F40807B1002F2A3444090B262B83A8C3F40583448C153AE444080C6F7C5A58E3F406061A5828AAE4440002DCF83BB9B3F40A0B393C151B04440E061BEBC009F3F408093A641D1B04440D057C9C7EEBE3F40F8F36DC152B744409017EFC7EDBF3F400021CB8289B74440505FD04202FE3F40001B498270C54440909065C1C4134040587FBDC282CD44405870784144144040D0CDFE40B9CD44402026E1421E15404080AEEFC341CE4440E0DC43C2F7164040E0E2C5C210D1444080992842EA224040A8C85A43A9DB4440B8A78FC01F244040A0BF97C283DC444018179CC1DF434040908461C092E7444080B130444E4B4040B0A10DC006EA4440C85B3CBCE74C40409081204086EA4440204A7B832F4E404008093543AAEA4440E0A623809B57404028F0DC7BB8EA444058672783A3584040A09BFD8172EB444088931804565C4040B0AA4203B1EC444090992842EA62404038B7ED7BD4ED444050499D8026664040D0FA5B02F0ED4440283E7782FD694040281D1EC2F8ED4440080FB743C3744040D0BE2B82FFEF4440588BC1C3B4794040E00F238447F1444088CC07043A7D404000093543AAF244400848A643A77D404080992842EAF24440285FD042027E4040B0B0524145F344405876FA415D7E4040D00CE2033BF444403029B000A67E40409087A2409FF44440B0A44E40137F4040D05B3CBCE7F444403038F581E4874040D858FB3BDBF7444030266F80998940403050FD8348F84440A8A78FC01F9C404028C0B0FCF9FC4440182922C32AAA4040B83E90BC73024540586DA983BCAA4040A8A4C00298024540E00CE2033BAC40405082FE428F02454028205F4205B34040282922C32A0245409087A2409FC44040382F3201BF0045406061A5828AC64040B8B393C15100454090C9C6832DC84040000C76C3B6FF44405082FE428FCA40403841B8020AFF444058888043A8CC4040908D2441B8FE4440181ADD41ECD0404088AEEFC341FE444000FD304278DE4040A83B4F3C67FD44407084D38217E34040286893C327FD44402035B401D8EA404088724D81CCFC444070AEEFC341F6404028232E008DFC4440586D37C137FF4040A0E3310395FD4440100341800C0D4140303B3602F1FC4440B0D11DC4CE1A4140A0D11DC4CEFA4440909C69C2F61F4140A01AF67B62F94440087F6ABC7421414078ABAE4335F94440B8380EBC5A284140483ACAC16CF844403029B000A62E4140282F3201BFF84440D061BEBC00474140A8957B8159F94440002A8E03AF4E4140B8380EBC5AF8444010068200195241403050FD8348F844405864E602975B414050672783A3F844408890D783495F4140A8AAD0402CF94440F8230C0396644140788D96033DFA4440101286014B664140B8E67283A1FA44406082FE428F6A4140707B1002F2FB4440D85B3CBCE76C4140B0B6D4415EFD444080FA08FCE17141406073B9C150014540B03B4F3C67754140B0AA4203B10445407803CC7C07794140F802B3429108454000FAEFC16B794140A0C2D84290094540285C8FC2F578414030BA2EFCE00A4540285C8FC2F578414060793BC2690B454058465C001A794140309C16BCE80B4540A8A4C002987A414018179CC1DF0B4540505260014C7D4140789065C1C40B45407893A641D180414020205F42050B4540000072C284834140383E7782FD094540888192020B864140A8380EBC5A084540E0DC43C2F78E4140A8E0F0828800454000FD3042788E4140000C76C3B6FF4440809FAA42038D4140B8BF97C283FC4440087C293C688C41407884D38217FB4440010300000001000000470100009004FD851E653B407803CC7C07014540205C8FC2F5683B40B8BC564277FF4440408C9FC6BD693B40C809A1832EFF4440B0F8F884EC703B40080341800CFD4440C01342075D8E3B4030232E008DF4444050C1E10511913B40100C040132F44440F01D8A027D923B40B0A78FC01FF44440D0C77C40A0933B40100C040132F444409087A2409F943B40F07B293C68F44440E05B3CBCE7943B40D8D6C1C1DEF44440B019C40776983B40F84D2844C0F74440B0F8F884ECA03B40A0A10DC006FA44401015C78157A33B40F8083543AAFA444040895E46B1B43B401826E1421EFD444090C075C58CD43B4088C9C6832D004540E0488446B0D53B40584F1F813F004540705260014CDD3B40A8CB9BC3B500454080C6F7C5A5DE3B40A8CB9BC3B500454030780AB952E73B40F8F36DC152FF4440F00391459AF83B40301D1EC2F8FD44402015C78157033C40D0CDFE40B9FD4440206E15C440073C40C8BE2B82FFF744401051DB8651083C40F8F6AE415FF4444080A2EBC20F023C40E006600322F24440B00A7F8637FF3B40B03E90BC73F244402098A3C7EFFD3B40B03E90BC73F2444060B5DD04DFFC3B40E0F10A444FF244409008707A17FB3B400012F8C3CFF1444070D026874FFA3B40087F6ABC74F14440B019C40776F83B4080C9C6832DF0444060BB5F05F8F63B40F8298E03AFEE4440E049B6BA9CF63B40F847A643A7ED44400021CB8289F73B40081E8A027DEA444080D53C47E4F73B4030266F8099E94440E0C77C40A0133C4080992842EAD24440A0AF21382E173C408093A641D1D04440B0F92AF9D8213C4060431B800DCC4440207497C459313C4050D7DAFB54C54440F0C77C40A0333C40F8F6AE415FC444400021CB8289373C4018205F4205C3444070499D80263E3C4020473A0323C1444030410DDFC2423C40E0915CFE43C0444020956247E3483C40F8298E03AFBE444080A99F37154D3C40506A6803B0BD4440901A3048FA543C402844F98216BC444070CDE50643753C40586A6803B0B544409014AE47E1CA3C40888192020BA64440D052793BC2D53C40B8A78FC01FA44440B00BB1FA23F03C4008301004C8A0444050D6A88768043D402899D53BDC9E444090A52C431C073D40D8F19881CA9E4440309E25C808083D40D061BEBC009F4440003F5585060A3D40E0EB884336A044402037C478CD0B3D40D0CABDC0ACA04440909FAA42030D3D40302F3201BFA04440308A90BA9D153D40084E2844C09F444090D53C47E4173D408090D783499F4440A0812040861A3D40B8DA6E826F9E4440E0420246971B3D40D0CDFE40B99D4440A0FFACF9F11B3D40505260014C9D4440A0FFACF9F11B3D4058732B84D59C4440E0420246971B3D4050793BC2699B444080BB2539601B3D4038BA2EFCE09A4440C09FA9D72D123D4028D5777E51964440408386FE090A3D409093C2BCC7934440203EE94482113D4030F0C000C28F4440104B5986380E3D406082FE428F8A4440003F5585060A3D40F0F36DC152874440B0E0F08288083D402829B000A686444090DEFFC709E73C40286893C3277D4440202A8E03AFD63C40B0A4C002987A444090C075C58CD43C40D8F10A444F7A444020205F4205D33C40A071E140487A444020301004C8D03C4008F12C41467A4440F04F38BBB5A03C40D0BBEA01F37A4440F055BABBCE9A3C40B8DDAF027C7B4440908AE3C0AB993C40002DCF83BB7B4440A025AB22DC983C4048250340157D4440A025AB22DC983C404025AE635C7D44402069A9BC1D993C40687C43E1B37D44401044C02154993C402057957D577E444060D9E90775993C40487C7C427680444040956247E3983C406073B9C1508144401096CE8767953C40587FBDC282854440801A3048FA943C40D8FA5B02F08544404075C93846923C40504F1F813F88444070CBD6FA22913C40205C8FC2F5884440B014747B498F3C4050E3DEFC86894440809FAA42038D3C40383E7782FD894440F0599E0777873C40F8F02C41468A44404077D84466863C40C8066003228A4440A01AF67B62893C4028BD6F7CED874440A014AE47E18A3C40084E2844C0874440505260014C8D3C40D0D38041D287444090C6F7C5A58E3C40A0A70183A4874440C00A7F86378F3C408090D78349874440207497C459913C40C8BBEA01F3824440207497C459913C40081E8A027D824440804221020E8D3C40B841D13C807F4440F0C682C2A08C3C4028F38FBE497F4440D05E7D3CF4893C40B0AD11C1387E4440306E15C440873C40503448C1537E4440A0FB3905F9853C40F881AB3C817E4440309C16BCE8833C40D861BEBC007F4440200F45813E793C40E0D90242EB8144401077D84466763C40304DBC033C834440E0C77C40A0733C4060431B800D844440A0EF3504C7713C40F8230C0396844440B01342075D6E3C40505260014C85444020990F08746A3C409096E7C1DD85444070D4997B48603C40D8DC43C2F786444070499D80263E3C40C8066003228A4440E03FC1C58A363C40F8F02C41468A4440F055BABBCE2A3C40B0A10DC0068A4440C0052FFA0A263C400812F8C3CF894440C0EF3504C7213C40B0AAD0402C894440002D7AA7021E3C40A8380EBC5A884440D0488446B0153C4028BD6F7CED874440D03C80457E113C400079E8BB5B874440F0D03FC1C5023C4020232E008D844440A017EFC7EDFF3B40209C16BCE8834440101B498270FD3B40306211C30E834440A0ECF483BAFC3B40F84AE7C3B382444060D158FB3BFB3B4070ABAE43358144409014AE47E1FA3B4090C9C6832D80444000990F0874FA3B4050853FC39B7F444060CDE50643F53B40087C293C687C4440107E8CB96BF13B40289C16BCE87B4440E061BEBC00EF3B40D8F4D901D77B44401015C78157E33B40289C16BCE87B44404098A3C7EFDD3B4080A86DC3287C4440307A19C572DB3B4028232E008D7C444060D026874FDA3B40E0EEC9C3427D4440206552431BD83B40B0AD11C1387E4440F05A0A48FBD33B40586D37C1377F44400021CB8289C73B4070ABAE4335814440C0052FFA0AC63B40A0957B815981444070CFBA46CBBD3B40508BC1C3B4814440405C8FC2F5B83B40605E64027E81444040861DC6A4AF3B40201ADD41EC804440E0C77C40A0833B40285FD042027E4440001E8A027D823B40D8B8A981E67D4440307D5A457F803B40A0A17F828B7D44403099D53BDC7E3B4030C0B0FCF97C4440B0F6E978CC7C3B40D8F4D901D77B4440F0420246977B3B40D8FD9C82FC7A4440103D4679E6753B40283B3602F1744440209221C7D6733B40808D96033D724440F0D03FC1C5723B40D8E506431D6E4440406BD44334723B40000341800C6D444020274D83A2713B408087A2409F6C4440207156444D4C3B40202922C32A5A4440405C8FC2F5483B4050465C001A594440307288B8392D3B40D8B56801DA504440E00644882B233B4070E597C1184F4440F0BAB72231053B408815E0BBCD4B4440B019C40776F83A40D861BEBC00474440003A05F9D9E03A40F80B040132444440B008707A17BB3A40507FBDC2823D44400051DB8651B83A40C8D6C1C1DE3C444080C6F7C5A5AE3A40F8058200193A4440305FD04202AE3A40E0EE5701BE394440B01C058882AD3A40000F45813E3944405082700514AE3A40583ACAC16C38444060DD5CFC6DAF3A408090D7834937444040861DC6A4AF3A4030145B41D33644400009C38025AF3A40503448C153364440101B4982709D3A40A8E33103952D444050D7DAFB54953A40D8D90242EB29444050E09D7C7A943A4000274D83A2294440909FAA42038D3A40686D37C137274440D04F38BBB5703A40B098BC01661E4440405C8FC2F5583A40608BC1C3B4114440F0565D876A523A40E0B8A981E60D4440A093A641D1383A4088FD497CEE064440F03383F8C0363A40A0C519C39C064440901342075D2E3A4030327381CB054440106893C3272D3A4030327381CB054440B0073E062B2A3A40788192020B064440E05D4BC807293A4080AEEFC341064440C019C40776283A40A0C519C39C064440504F1F813F283A40B0A44E40130744401018080264283A40908461C09207444020956247E3283A402023A0C211084440C0F6E978CC3C3A40B8B6D4415E154440E04E0647C93F3A40A8C519C39C1644403075C93846423A40305C8FC2F5184440F0D03FC1C5423A40007F6ABC7419444050D6A88768443A40282CF180B21B44408087A2409F443A40E00CE2033B1C444070116DC7D4453A40E000DE0209204440100341800C453A408093A641D1204440004E9A0645433A4078FA08FCE1214440F08F4C874E3B3A40B0C519C39C264440C0488446B0353A40886649809A28444050D7DAFB54353A40787E5182FE28444090F27684D3363A40908AE3C0AB2944402098A3C7EF3D3A40886308008E2B4440A0FE7A85056B3A40D0C43BC09336444060A088450C8B3A408836397CD23D4440F04718062C993A4000301004C8404440D0393FC5719C3A40B0AAD0402C4144401043C879FF9F3A405873B9C15041444020809BC58BA53A40D8E2C5C210414440306893C327AD3A4050465C001A414440407D5A457FB03A40F8F9EFC16B41444060BB5F05F8C63A400009C3802547444080A86DC328CC3A40E0CABDC0AC484440106211C30ED33A40D0D03FC1C54A4440809065C1C4D33A4000E869C0204B444070C93846B2D33A402044F982164C44407085B18520D33A40C85B3CBCE74C444050499D8026CE3A4038266F809951444060D158FB3BCB3A400815C78157534440108C9FC6BDC93A4080008BFCFA534440A093A641D1C83A40D80CE2033B544440F0599E0777C73A40007C293C6854444040895E46B1C43A4038232E008D54444070B54E5C8EC33A4060E09D7C7A544440E0D03FC1C5B23A40283E7782FD514440009C508880AF3A4008274D83A2514440F036C478CDAB3A4058E3DEFC86514440106211C30EA33A4000FAEFC16B51444070C075C58C943A40D8B56801DA504440A00BB1FA23703A4088FD497CEE4E444040BEA085045C3A407896E7C1DD4D4440D00391459A583A400848A643A74D44402075C93846523A40080C0401324C4440D057C9C7EE4E3A40289C16BCE84B4440E05E7D3CF4493A40C8B22781CD4B4440A0052FFA0A263A40C8B22781CD4B4440C04543C6A3203A4088008BFCFA4B444040C8957A161C3A40F0F6AE415F4C444070CE177B2F163A40B0B6D4415E4D4440809065C1C4133A4088AEEFC3414E444060DBBE47FD113A408890D783494F4440208FE046CA0E3A40A89BFD8172534440E0C43BC0930E3A4028179CC1DF534440407A19C5720B3A40304A7B832F5E444050CDE506430D3A4000000000005E444080ABAE4335113A40201D1EC2F85D444080AF21382E173A40B8AD11C1385E4440F0420246971B3A40F8298E03AF5E4440001286014B1E3A4058DD5CFC6D5F44409017EFC7ED1F3A40000000000060444090B5A33847213A4098CB9BC3B5604440407B4B395F2C3A40F02F1004C8684440002A8E03AF363A402850FD834870444060D4997B48403A40D8EE5701BE71444070C3B64599493A40A09BFD817273444040BEA085045C3A4088758E01D9794440105DDF87835C3A405055A181587A4440B00BB1FA23603A4098D11DC4CE824440C001BC0512603A40A8B0524145834440209012BBB65F3A40B0C85A43A9834440505FD042025E3A405070784144844440A0992842EA523A40309C16BCE88B4440404CDE0033533A40788192020B9E4440F02CCF83BB5B3A40D8F71A82E3A04440901342075D5E3A40A8E0F08288A0444090ABAE4335613A40503ACAC16CA04440001E8A027D623A40503ACAC16CA0444070D026874F6A3A4088ABAE4335A14440A0812040869A3A40182922C32AAA4440005DDF87839C3A405882FE428FAA444050499D80269E3A4008E869C020AB444010314278B4A13A40D05B3CBCE7AC44404075C93846A23A40B8B6D4415EAD4440B0E67283A1A23A40E0FA5B02F0AD4440309BE447FCA23A40E0DC43C2F7AE44407085B18520A33A40507C7C4276B04440309BE447FCA23A407893180456B4444080992842EAA23A40505260014CB54440C0D03FC1C5A23A40D0CDFE40B9B54440D04BC5C6BC9A3A40D8B8A981E6C5444080DBBE47FD913A4080AEEFC341CE4440A01A3048FA843A4050465C001AD14440A0FB3905F9653A40503ACAC16CD84440C0BFCFB8705C3A40B8E07EC003DB4440A008707A175B3A40989BFD8172DB444010083BC5AA593A40E81B98DC28DC4440D0F3A8F8BF573A402026E1421EDD44400096CE8767553A40F881AB3C81DE4440000341800C553A408078CF81E5DE4440A01A3048FA543A40D858FB3BDBDF4440A00EF27A30553A400818080264E0444060DEFFC709573A40D8E847C329E34440C019C40776583A4098AA4203B1E44440808AE3C0AB593A40B0A17F828BE544408017EFC7ED5F3A40D8B56801DAE84440F04543C6A3603A4088ABAE4335E9444020314278B4613A40A0957B8159E94440F00B040132643A40F87E6ABC74E944406055A18158723A4030266F8099E94440B0F3A8F8BF773A40605E64027EE9444060D026874F7A3A40605E64027EE94440406E15C440873A40E0EE5701BEE94440208C9FC6BD893A4080758E01D9E94440D055BABBCE8A3A40283E7782FDE9444040840EBA848B3A406055A18158EA444070C8957A168C3A40D8D03FC1C5EA4440F057C9C7EE8E3A40709FAA4203ED4440203A05F9D9903A40F820CB8289EF4440C095B37746933A40B8E3DBBB06F34440E05DD905838F3A40E0B7AF03E7F64440B002EE79FE903A40A8A70183A4F74440E06932E36D913A408815E0BBCDF74440C0E67283A1923A40604F1F813FF84440F0419605139F3A4028232E008DFC4440104B598638EE3A40E0F71A82E3004540209C508880EF3A40E0F71A82E300454050868E1D54F63A40982958E36C004540409E25C808083B40B8B915C26A0A4540A0FE7A85050B3B40E0FD9C82FC0A454090DBBE47FD113B40000072C2840B4540F04CF73AA93B3B4010E52840140E45400051DB8651483B40D0031F83150D4540808AE3C0AB493B40D8D6C1C1DE0C4540E055BABBCE4A3B4050888043A80C454050827005144E3B40807B1002F20B454060CAA48636503B40A09BFD81720B454020240C03965C3B40B0B393C151084540307288B8395D3B40909C69C2F6074540B0E33103955D3B40888461C092074540109C5088805F3B403026E1421E054540C017B5FB55643B40A0957B81590145409004FD851E653B407803CC7C07014540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('UK','GB','GBR','826','United Kingdom','24193','60244834','150','154','-1.6','53','0106000020E6100000300000000103000000010000000E000000C0633E20D02919C0A8716F7EC3F4484040560DC2DC3E19C0600DFB3DB1F4484000282A1BD64419C0B0ECF483BAF4484080EB51B81E4519C0306893C327F54840C0583508733B19C038DB87BCE5F6484000630CACE33819C030F38FBE49F74840C05D85949F3419C03820ED7F80F748408047E17A142E19C00821CB8289F7484040666666662619C0803FFCFCF7F64840004F594DD72319C06828D2FD9CF6484080630795B81E19C08096E7C1DDF54840007D3CF4DD1D19C0A868ACFD9DF5484080BC7328432519C0B09ECC3FFAF44840C0633E20D02919C0A8716F7EC3F448400103000000010000001800000000A14D0E9FF4F0BF8821E4BCFF57494000E10CFE7EB1F2BF080341800C4D494000067DE9ED0FF3BF00DFA63FFB4B494000C61858C771F3BF884B00FE294B4940005C5837DEDDF3BF5082FE428F4A494000EC51B81E85F4BF00068200194A4940007B14AE47E1F5BFE009A1832E4F494000D2122BA391F7BF08240C03965449400022DFA5D4E5F7BF301A6B7F6755494000E0438996FCF7BFB0E331039555494000AB24B20F32F8BFA868ACFD9D5549400028EE78935FF8BF081B49827055494000A9B69BE09BF8BF283B3602F154494000662FDB4E1BF9BF88A86DC3285449400085EB51B81EF9BF38232E008D54494000EC884336D0F8BFB0DA6E826F5649400028EE78935FF8BF30E109BDFE5849400082919735F1F4BF004BE7C3B3624940005F7B6649C0F4BF5834D6FECE62494000A0168387A9F4BF10D061BEBC624940008C31B08EE3F1BF58FB743C665E494000FCA5457DD2F1BF8048BF7D1D5E4940004487C09180F1BFC80CE2033B5C494000A14D0E9FF4F0BF8821E4BCFF5749400103000000010000000D000000003E78EDD206EEBFA8622AFD84634940003EBFEFDFBCEEBF00E869C02063494000960854FF20EFBF0815C78157634940008FC2F5285CF0BFF8230C03966449400070067FBF58F0BF080341800C6549400011548D5E4DF0BFB0B6D4415E6549400072AB20063AEFBFB053E57B466A494000161C5E1011EFBF5855A181586A4940004CB9C2BBDCEEBF306BD443346A49400028EE78935FEEBFD00F238447694940006A8995D148EEBFE0F71A82E3684940009E4D0E9FF4EDBFB87A32FFE8634940003E78EDD206EEBFA8622AFD846349400103000000010000000D00000000662FDB4E9B12C0805A457F68944940001059A489A712C05070784144944940801E4E603AAD12C0805A457F68944940C023D5777EB112C060888043A894494080CDC7B5A1B212C0206893C327954940C07133DC80AF12C0B86E2EFEB6974940C0E175FD82AD12C0602E54FEB598494000A0168387A912C0285C8FC2F598494000A5660FB4A212C0285C8FC2F598494000D1217024A012C0706649809A98494000FA7DFFE69512C0080341800C954940003E05C0789612C0F8230C039694494000662FDB4E9B12C0805A457F6894494001030000000100000019000000001A3F8D7BF3EC3FA89509BFD4AD4940008E54DFF9C5EC3FD0CDFE40B9AD494000CC3B873254EC3F9096E7C1DDAD4940003833333333E93F20F38FBE49AF49400076F17EDCFEE83FD0BB783F6EAF494000644337FB83E83F286552431BB049400094E4805D4DE83F382F3201BFB0494000B68D3F51D9E73F081E8A027DB2494000845968E7B4E73FE8AF743E3CB3494000EC51B81E85E73F4870784144B44940006E1B7FA2B2E73F6040DAFF00B7494000B26A10E6F6E73F00301004C8B8494000CA3B873254E83FD07C957CECB8494000341004C850E93FB0B393C151B8494000B2D826158DEC3FD0FA5B02F0B5494000EAE3A1EFEEEC3FB068ACFD9DB54940003856629E15ED3FA8B6D4415EB54940002284471BC7ED3F306211C30EB3494000C087122DF9ED3FD0B837BF61B2494000C041B45634EE3FD00F238447B1494000BC1E85EB51EE3F607C7C4276B0494000CA3B873254EE3F809C69C2F6AF49400094E4805D4DEE3F3020ED7F80AF4940005A8FC2F528EE3F286E15C440AF4940001A3F8D7BF3EC3FA89509BFD4AD494001030000000100000014000000402DB1321A4912C008C45DBD8A9E4A4080C2F5285C4F12C0A05FE97C789E4A4000E275FD826D12C0F82F1004C8A04A4040F6234564A812C0C8C77C40A0A34A4040C3F01131B512C0E87954FCDFA34A408058350873BB12C028232E008DA44A40C015A4198BC612C0D0C43BC093A64A40C085E63A8DC412C008DC65BFEEA64A400049D74CBEB912C0D8CABDC0ACA84A4040B16A10E6B612C080457EFD10A94A40001C261AA4B012C0E0A9F23D23A94A40C0ED79FEB48112C058F833BC59A94A4040022846967C12C0E0A9F23D23A94A4040758D96035D12C038E44A3D0BA64A40804E5E64023E12C088457EFD10A14A4040A46B26DF3C12C0A8656B7D91A04A4040A46B26DF3C12C0C88558FD11A04A4080F0A1444B3E12C0F020CB82899F4A4000880E81234112C00009C380259F4A40402DB1321A4912C008C45DBD8A9E4A400103000000010000001F00000080758D96039D10C080397AFCDE9C4A4040C972124ADF10C000274D83A2994A400011548D5E4D11C05082FE428F924A4040B29C84D26711C0B09B8BBFED8F4A4080CB9A58E09B11C0286552431B904A40C0A7C5E061EA11C05828D2FD9C964A40C0AE42CA4FFA11C0504F1F813F984A4080EB51B81E4512C0D8FD9C82FCA24A4080D9CBB6D34612C0908AE3C0ABB14A40C085E63A8D4412C01006820019B24A40400AD7A3703D12C0D8D03FC1C5B24A4080A23EC91DE611C0B0E3310395B54A40C016D68D77B711C0F89600FC53B64A408081919735B111C060FB743C66B64A4080E49D4319AA11C060FB743C66B64A40402A52616C4111C0B0ECF483BAB44A400052B81E852B11C088A86DC328B44A40802407EC6A2211C0D8C77C40A0B34A4080295778971B11C0E0FD9C82FCB24A4000AE47E17A1411C0D8EE5701BEB14A4080CEF9298EE310C0B8AAD0402CA94A400090BDDEFD8110C0104E2844C0A74A408046AF06287D10C0B09B8BBFEDA74A40400F27309D7610C07821E4BCFFA74A40001C261AA47010C0809C69C2F6A74A40000AD7A3703D10C088A52C431CA74A4080355B79C92F10C0D076137CD3A64A40007233DC802F10C05876FA415DA64A40408FC2F5285C10C008CADFBDA3A04A4000B29C84D26710C0B06E2EFEB69F4A4080758D96039D10C080397AFCDE9C4A400103000000010000000B01000000643E20D06919C0A8DA6E826F9E4B4080EB51B81E0519C008E869C0209B4B40403883BF5FAC18C008DFA63FFB9B4B40C0332E1C089918C068F5F23B4D9C4B400016DBA4A29118C0100C0401329C4B4000A8C5E0616A18C090992842EA9A4B4000F94B8BFA6418C0004BE7C3B39A4B4000C2BE9D444418C0D0F71A82E3984B4080F0A1444B3E18C030EACC3D24984B4080666666662618C0600DFB3DB1944B40802407EC6A2218C0E0F4D901D7934B404061DF4E222218C02814E97E4E934B400052B81E852B18C0386893C3278D4B4080CDC7B5A13218C0884B00FE298B4B40C0F84B8BFA2418C0F8BA9A3C65874B400015A930B66017C0104BE7C3B3724B4000A8C5E0612A17C0A89ECC3FFA6C4B404015A930B62017C0001B4982706D4B4080DD205A2B1A17C0607FBDC2826D4B4080A46B26DFFC16C0805182FE426D4B40008940F50FF216C000D6E3BED56C4B40C0E175FD82ED16C000240C03966C4B4000E8F7FD9BD716C0B8E67283A16A4B4040F2CEA10CD516C0C053E57B466A4B40C06BB1DB67C516C0889C69C2F6674B40004487C091C016C0D809A1832E674B4040272F3201BF16C0504C50C3B7624B4000560DC2DCBE16C0903CBB7CEB614B40C0FFFFFFFFBF16C0B05CA8FC6B614B40C039B01C21C316C000301004C8604B4080D11C59F9C516C0504F1F813F604B40402DB1321AC916C06037177FDB5F4B40402C7FBE2DD816C05828D2FD9C5E4B4000CB9D9960F816C0B8162D40DB5C4B40C058350873FB16C0B8ECF483BA5C4B4080ED7BD45FFF16C0306B6281AF5C4B4040CDC820771117C0306B6281AF5C4B408078EC67B12417C0A0A78FC01F5C4B40C0415F7AFB4317C0801EA33CF35A4B4040CFF412634917C008D061BEBC5A4B4040333333337317C0B8656B7D91584B40C09CBCC8047C17C09021E4BCFF574B40C039B01C218317C0885704FF5B574B40C0B2976DA78D17C05876FA415D564B40800E2C47C89017C0D8FA5B02F0554B40008940F50FB217C0E8A9F23D23514B404033333333B317C0806649809A504B400061DF4E22A217C0301A6B7F674D4B4080C1C3B46F9E17C0D0031F83154D4B40C0893BDEE49717C0203B3602F14C4B40802A89EC838C17C090CC07043A4D4B40402502D53F8817C0487FBDC2824D4B4040EB51B81E8517C0781B62BCE64D4B40C05DBC1FB77F17C0B85626FC524F4B40403883BF5F6C17C028266F8099514B40C0415F7AFB4317C0B87A32FFE8534B40406DE34F543617C060888043A8544B408019FCFD62F616C0186CEA3C2A564B404045B75ED3F316C0D07F812040564B4040675E0EBBEF16C0101286014B564B4040C2BE9D448416C0783FFCFCF7564B40805EB7088C6516C008DC65BFEE564B40005D8AABCA4E16C0D8F19881CA564B4040CFF412634916C0D0C43BC093564B4000B29C84D22716C0909065C1C4534B40801281EA1F2416C050FEB5BC72534B400061DF4E222216C0D082177D05534B40C00F2219721C16C008CADFBDA3504B4040EC4CA1F3EA15C058888043A8444B4000AC1A84B9BD15C03029B000A63E4B4000630CACE3B815C05876FA415D3E4B40405B5D4E09B815C0881B62BCE63D4B4000AC1A84B9BD15C0881EA33CF33A4B4040560DC2DCBE15C0B0B915C26A3A4B40002C7FBE2DD815C068F833BC59314B40C092E34EE90016C0E869F981AB2E4B4040207BBDFB0316C07815191D902E4B40802502D53F0816C008C45DBD8A2E4B40004031B2640E16C0B0D47ABFD12E4B40408C65FA251216C0F0608BDD3E2F4B40C01B28F04E2E16C040A7CB6262334B40C07133DC802F16C038779FE3A3334B40C009A2EE033016C058FBE6FEEA334B408079E2395B3016C048C5C6BC8E344B4040B39602D22E16C000D68EE21C354B4080355D4F742D16C060F71DC363354B40404D2D5BEB2B16C09886A8C29F354B4040B7EC10FF2016C0B0D7F4A0A0364B40002EAC1BEF2E16C0B0E0F08288384B40404A09C1AA2A16C0785D86FF74394B4000A01683872916C0583D997FF4394B4000DAC69FA82C16C0080341800C3D4B4040333333333316C03838F581E43F4B4040C3F011313516C0B8B393C151404B408046AF06283D16C0B0A10DC006424B4040F850A2253F16C0A8B915C26A424B40802FD978B04516C0F8E769C020434B40C0A23EC91D6616C0A8B6D4415E454B40C05C8AABCA8E16C0888461C092474B4000698EACFCA216C05001F73C7F484B40C0620CACE3B816C068F833BC59494B40C06BB1DB67C516C000274D83A2494B40008196AE60CB16C010C11C3D7E494B400011548D5ECD16C008E2E7BF07494B404016DBA4A2D116C058F5F23B4D444B408019FED30DB416C0801EA33CF3424B40007233DC80AF16C0E0D03FC1C5424B4080EE9062809416C018C3D501103F4B400037DE1D194B16C0A8410A9E42304B4000037AE1CE4516C0A87D737FF52E4B4040B96DDFA33E16C030772D211F2C4B40C0C8CB9A584016C0B8F81400E32B4B4080022846963C16C088CC07043A254B40C05DBC1FB73F16C0E00CE2033B244B408091EA3BBF5816C0883CBB7CEB214B40C02DAC1BEF6E16C0889C69C2F61F4B40C0E7F7FD9B9716C0C8031F83151D4B4080758D96039D16C090397AFCDE1C4B40802407EC6AA216C0B09ECC3FFA1C4B4080A23EC91DA616C0585260014C1D4B4040EC4CA1F3AA16C010E52840141E4B4080A46B26DFBC16C088A52C431C1F4B4000D4449F8FC216C0B85626FC521F4B40807138F3ABC916C0D0BB783F6E1F4B40C0953FDF16EC16C0B0E9B303AE1F4B40C09CBCC804FC16C0104E2844C01F4B4000D7A3703D4A17C0508E0244C11E4B4080C2F5285C4F17C0D8C43BC0931E4B40C0953FDF166C17C020ED0DBE301D4B40805D85949F7417C048888043A81C4B40404E5E64027E17C02814E97E4E1B4B4000560DC2DC7E17C038F04E3E3D1A4B4080A46B26DF7C17C0E00F238447194B40400F27309D7617C0D800DE0209184B40800778D2C27517C0F820CB8289174B40805D85949F7417C0D0FA5B02F0154B4000CB9F6F0B7617C038D505BCCC144B40C0D6A3703D8A17C030DB87BCE50E4B4000FA7DFFE69517C0A0ECF483BA0C4B404039B5334C9D17C060431B800D0C4B4000C8409E5DAE17C0D0FD9C82FC0A4B40806BB6F292DF17C090C9C6832D084B40809DEE3CF12C18C078423D7D04044B40006CB1DB674518C0886308008E034B4000ABE80FCD4C18C0B0622AFD84034B40006AC020E95318C0D0C77C40A0034B40C02DAC1BEF6E18C048888043A8044B40002EAC1BEFAE18C0D0F71A82E3084B40C08618AF79B518C038266F8099094B4040F0A1444BBE18C0604CDE00330B4B4000282A1BD6C418C028DEC83CF20B4B4000CFF41263C918C0080C0401320C4B40C0643909A5CF18C0A859677C5F0C4B40C065F7E4611119C040102043C70C4B4080963AC8EB1119C0080341800C0D4B4080A3703D0A1719C0101B4982700D4B404039B5334C1D19C0D0CDFE40B90D4B40401059A4892719C0881B62BCE60D4B4040E5CFB7055B19C0D8F19881CA0E4B4080A23EC91D6619C0D8F19881CA0E4B400052B81E856B19C05828D2FD9C0E4B40001C261AA47019C0101286014B0E4B4000DD2571567419C0881B62BCE60D4B4000CB9F6F0B7619C0587FBDC2820D4B4040B16A10E67619C0D088997D1E0D4B40000F27309D7619C0A0ECF483BA0C4B4000D7A3703DCA19C0A8BC564277074B4040EB51B81E451AC09060C77F81064B40003883BF5F6C1AC000CD203EB0054B40808B683BA66E1AC0301A6B7F67054B4000F3C98AE17A1AC0A0716F7EC3044B400000000000801AC0809FAA4203054B40C0BF9657AE871AC038327381CB054B4000C972124A9F1AC030172AFF5A084B408079E2395BF01AC02020ED7F80174B408054E0641B681BC040D505BCCC244B4080AAED26F8661BC0B0B6D4415E254B40C0F2C98AE17A1BC0F899417C602B4B4000880E8123811BC0000C0401322C4B40008E90813CAB1BC0D0D38041D22F4B4040C3F01131B51BC0B8E0F08288304B40C000FBE8D4E51BC060793BC269334B40803BDD79E2191CC0B8B6D4415E354B40806BB6F2921F1CC0F89FC37C79354B4040BC732843251CC0301A6B7F67354B40001C5DA5BB3B1CC0D0BEB9BF7A344B404078EC67B1A41CC028E78BBD172B4B408077BAF3C4B31CC0789FAA4203254B40C0AD47E17A941CC0E8A9F23D23214B4080963AC8EB911CC0282F3201BF204B40400E2C47C8901CC0A8B393C151204B400094128255951CC008D6E3BED51C4B40406BB6F2921F1DC09021E4BCFF0F4B408000FBE8D4251DC060853FC39B0F4B4040E6CAA0DA401DC068FB743C660E4B40805A626534521DC0B05FE97C780E4B4040A46B26DF3C1EC0584F1F813F104B40001C261AA4701EC028F04E3E3D124B4000F3C98AE17A1EC0104BE7C3B3124B4000B4C9E1937E1EC0306211C30E134B4040F850A2257F1EC0B07A32FFE8134B40404E5E64027E1EC080397AFCDE144B40409A94826E7F1EC0605260014C154B40C0976C3CD8821EC0E0CDFE40B9154B40407138F3ABC91EC0903CBB7CEB194B4080C2F5285CCF1EC0903CBB7CEB194B4040AC1A84B9FD1EC000274D83A2194B40C039B01C21431FC010C11C3D7E194B40402502D53F481FC010C11C3D7E194B4040B29C84D2671FC0804B00FE291B4B4040CDC7B5A1721FC0A87A32FFE81B4B40801E85EB51781FC0600DFB3DB11C4B40800CFFE9067A1FC0A8E33103951D4B4080AE42CA4F7A1FC00818080264204B40005EBC1FB77F1FC080A86DC328244B40404487C091801FC0F8230C0396244B40003AB01C21831FC0789FAA4203254B40803BDD79E2991FC00048A643A7254B4080415F7AFBC31FC0089700FC53264B40E082A5BA800F20C0E0CDFE40B92D4B40206420CF2E1720C078AEEFC3412E4B4060022846961C20C028DB87BCE52E4B40001D588E902120C0B06E2EFEB62F4B40C0A8C0C9365020C028EACC3D24384B40600569C6A25120C0A8656B7D91384B4080AB1F9BE45720C0A0261763603B4B40005B5D4E091820C0D87C957CEC404B40C0B2976DA7CD1FC0B8A78FC01F444B4000583A1F9E551FC028DB87BCE5464B40403201BF46021FC0E0A6B1BD164C4B40408FC2F5281C1FC0604F1F813F504B40C000FBE8D4651FC000E2E7BF07514B4000F4FBFECD6B1FC0080F45813E514B40C0D0217024A01FC0080341800C554B4000B29C84D2A71FC0881B62BCE6554B40400778D2C2B51FC0905D86FF74594B40C0B392567CB31FC008D9243FE2594B4040C972124A5F1FC0801B62BCE65D4B400016DBA4A2511FC060499D80265E4B404067614F3B4C1FC0385FD042025E4B4080D9CBB6D3461FC0B8E33103955D4B400021AD31E8F41EC0801EA33CF35A4B40000F27309D361EC000274D83A2614B4000EFC8586DEE1DC0806F9A3E3B6A4B4040F2CEA10CD51DC030327381CB6D4B40C015A4198BC61DC0285C8FC2F5704B40C0D0217024A01DC0B0A10DC0067A4B40801803EB384E1DC038327381CB854B40000BEC3191021DC07021C84109894B4040EB51B81E051DC008E5284014864B4040880E8123011DC0901B62BCE6854B40C07A14AE47611CC0A8ECF483BA844B40008196AE604B1CC000D6E3BED5844B40C0ED79FEB4411CC038ED0DBE30854B40C0C0C8CB9A381CC000CD203EB0854B40001C261AA4301CC0F81186014B864B40007D3CF4DD1D1CC0B09B8BBFED874B4040EA1F4432141CC020E109BDFE884B40C00CFFE906FA1BC09048BF7D1D8E4B40801F80D426DE1BC010DFA63FFB934B4000FFCD8B138F1BC000A0C37C79954B40802A89EC834C1BC0507FBDC282954B4000F4FBFECDEB1AC0B8A44E4013974B408019FED30D741AC088812040869A4B40C0067DE9ED0F1AC0A89509BFD49D4B40402A52616C8119C06028D2FD9C9E4B4000643E20D06919C0A8DA6E826F9E4B400103000000010000001000000080DF4DB7ECB018C0587FBDC282A54B4080C8772975B918C0803CBB7CEBA14B408046AF0628BD18C0905D86FF74A14B4000E6CAA0DAC018C0000F45813EA14B4080D79E5912F018C0505260014CA54B40006F10AD150D19C0386893C327A54B4000102219721C19C080CC07043AA54B40C07A14AE472119C0201A6B7F67A54B4000D12170242019C0D8FA5B02F0A54B40006F10AD150D19C030DB87BCE5A64B4040D4449F8F0219C010BB9A3C65A74B40C05D85949FF418C02820ED7F80A74B40C07D37DDB2C318C0908D2441B8A64B40000F27309DB618C05876FA415DA64B40806F0B96EAB218C000E5284014A64B4080DF4DB7ECB018C0587FBDC282A54B400103000000010000002500000080E49D43196A14C028EACC3D24B84B40C0D79E5912B014C0803FFCFCF7B64B40C0F84B8BFAE414C02841B8020AB74B40401E4E603AED14C0B0A44E4013B74B4040CDC7B5A1F214C028F38FBE49B74B404061DF4E222215C078ABAE4335B94B4000F4FBFECD2B15C0E0EE5701BEB94B40C00F2219725C15C040D505BCCCBC4B4080C1C3B46F5E15C0D8031F8315BD4B40C083B9DDCB6D15C0A8E0F08288C04B40C03BDD79E29915C090397AFCDECC4B40807F643A749A15C0E0FA5B02F0CD4B40C03BDD79E29915C0B8A44E4013CF4B4000FA7DFFE69515C06001F73C7FD04B40409544F6418615C0B8E3310395D54B40C039B01C218315C0D07FD6FCF8D54B40401C5DA5BB7B15C03029B000A6D64B40C0963AC8EB5115C0A8C2D84290D94B400011548D5E4D15C038D8463CD9D94B4040C8409E5D2E15C0F82CCF83BBDB4B4080067DE9ED0F15C09015E0BBCDDB4B400090BDDEFD0115C0682B137EA9DB4B404021AD31E8F414C00015C78157DB4B40C0633E20D0E914C080992842EADA4B4000BD6E1118CB14C000C11C3D7ED94B4040AC1A84B9BD14C0D0CABDC0ACD84B40C0953FDF16AC14C0908461C092D74B40801281EA1FA414C000DC65BFEED64B4040C1C3B46F9E14C0D8AC33BE2FD64B408024D060535714C0386E15C440C74B40C0F97DFFE65514C0D0F19881CAC64B40802A89EC834C14C03814E97E4EBB4B400067614F3B4C14C0E0D03FC1C5BA4B4000B3976DA74D14C0B853E57B46BA4B40400E2C47C85014C010D9243FE2B94B40806BB6F2925F14C0B0E0F08288B84B4080E49D43196A14C028EACC3D24B84B4001030000000100000017000000800E2C47C81014C0905A457F68DC4B4000E8F7FD9B1714C030F6D03E56DC4B4040272F32011F14C000BEDBBC71DC4B4080CEF9298E2314C0480DFB3DB1DC4B404049D74CBE7914C0A0DDAF027CE34B4040A46B26DF7C14C0D07954FCDFE34B40008196AE60CB14C03838F581E4EF4B40C010548D5ECD14C0B8B393C151F04B40C0BFCDE2C5D214C0E08BDAFD2AF24B4000A69883A0D314C0A86BED7DAAF24B40400455A357D314C0F8E769C020F34B40C00CFFE906BA14C0507FBDC282F54B4040C3F01131B514C05831957EC2F54B40808B683BA6AE14C0A868ACFD9DF54B4080B4C4CA68A414C0386893C327F54B40405A6265345214C0584F1F813FF04B4080BC7328432514C0D8AF743E3CEB4B40002DB1321A0914C0D00CE2033BE44B40802FD978B00514C0F814C78157E34B40006CB1DB670514C0A853E57B46E24B40807B0F971C0714C0507FBDC282DD4B4000CFF412630914C0000341800CDD4B40800E2C47C81014C0905A457F68DC4B400103000000010000004200000080022846967C18C05801F73C7FF04B4040A01683876918C0E0D38041D2E74B4040F62345646818C0B85626FC52E74B40004F594DD76318C0D87FD6FCF8E54B40406BB6F2925F18C0D888997D1EE54B40807F643A745A18C028F6D03E56E44B40C010548D5E4D18C0B8622AFD84E34B4080A46B26DF3C18C03035B401D8E24B40008718AF793518C0286BD44334E24B4040333333333318C0B874B0FECFE14B4000272F32011F18C0D80CE2033BDC4B4000D671FC501918C01009C38025D74B40408FC2F5281C18C0608E0244C1D64B40C04C3107412718C05831957EC2D54B4080BA46CB814E18C0604CDE0033D34B40C0A7C5E061EA18C08815E0BBCDCB4B4000342E1C081919C05073B9C150C94B408077BAF3C43319C028D8463CD9C94B4000282A1BD64419C0281DACFF73CA4B400011548D5E4D19C038E78BBD17CB4B4080C2F5285C4F19C050FEB5BC72CB4B40407138F3AB4919C0508E0244C1CE4B4080C745B5884819C0606D37C137CF4B404078EC67B12419C09081204086DA4B40C039B01C210319C0D0EE5701BEE14B4040880E81230119C0286BD44334E24B40402A52616C0119C000D061BEBCE24B40C085E63A8D0419C0804B00FE29E34B4000CFF412630919C058793BC269E34B40C0643909A50F19C0886308008EE34B40C06E10AD154D19C078423D7D04E44B4040A69883A05319C078423D7D04E44B40803BDD79E25919C0D07954FCDFE34B40C0BE9B6ED96119C0504CDE0033E34B408078EC67B16419C000D061BEBCE24B40C03AAB05F66819C000D9243FE2E14B40809DEE3CF16C19C000E2E7BF07E14B4080819197357119C0D800DE0209E04B40801E85EB517819C0E076137CD3DE4B4000282A1BD68419C028ED0DBE30DD4B4080FCA5457D9219C09015E0BBCDDB4B404078EC67B1A419C01006820019DA4B400067614F3BCC19C0B0A44E4013D74B40C077B5DC99D919C080AEEFC341D64B408078EC67B1E419C05831957EC2D54B40C01B261AA4F019C0B8E3310395D54B40007592AD2EF719C0F8CC203EB0D54B40802A52616C011AC0D8AC33BE2FD64B4080EB51B81E051AC05828D2FD9CD64B4040CFF41263091AC0B05626FC52D74B4000D7A3703D0A1AC00018080264D84B40C0FFFFFFFFFF19C030F6D03E56DC4B4040B6F1272AFB19C0801B62BCE6DD4B40802A89EC83CC19C08887A2409FEC4B4040C2BE9D44C419C0805182FE42ED4B4040726A67987A19C020F38FBE49EF4B40C046AF06283D19C010C45DBD8AEE4B4000282A1BD6C418C0605260014CF54B4040AAED26F8A618C0888D2441B8F64B408052B3075A9118C02820ED7F80F74B4000C51D6FF28B18C058853FC39BF74B40C085E63A8D8418C02820ED7F80F74B4040A46B26DF7C18C028DB87BCE5F64B4040C87729757918C0E07FD6FCF8F54B4000AC1A84B97D18C05082FE428FF24B4080022846967C18C05801F73C7FF04B40010300000001000000100000000016A4198BC618C0002DCF83BB034C4040ABE80FCDCC18C010C79E3D97034C40406DE34F54F618C0D8A6B1BD16044C40C010548D5E0D19C08887A2409F044C40C0355B79C9EF18C008D9243FE2094C4040E49D4319EA18C06007793D980A4C4000E8F7FD9BD718C048707841440C4C4080C2F5285CCF18C080397AFCDE0C4C4040B16A10E6B618C0A85FE97C780E4C40C0C51858C7B118C0608E0244C10E4C40801803EB388E18C0888461C0920F4C40C0D11C59F98518C0B0BC5642770F4C4000282A1BD68418C06040DAFF000F4C40006DE34F54B618C0789FAA4203054C40403201BF46C218C030DEC83CF2034C400016A4198BC618C0002DCF83BB034C4001030000000100000026000000407138F3ABC917C030F04E3E3DEA4B40000BD28C45E317C0503A58FFE7E44B40C0CB9A58E01B18C0D0B5F63E55E54B40007B14AE472118C0607FBDC282E54B40006DE34F543618C0A8DA6E826FE64B40004487C0914018C038DB87BCE5E64B40402502D53F4818C0A8BC564277E74B40008196AE604B18C02838F581E4E74B40C010548D5E4D18C00818080264E84B4040B06F27115118C0B074B0FECFE94B40C0DD205A2B5A18C0B8B393C151F04B40C03BDD79E25918C09018213CDAF04B40403E05C0785618C0301DACFF73F24B40400E2C47C85018C0B07A32FFE8F34B4000C972124ADF17C0D082177D05034C4000C0CDE2C5D217C0B87A32FFE8034C4000D1217024A017C0B8BC564277074C4000662FDB4E9B17C000D3A23EC9074C4040022846963C17C028E44A3D0B0E4C4080EB51B81E0517C090457EFD10114C4000F3C98AE1FA16C030266F8099114C4040CEC29E76D816C0E0AF743E3C134C4080FCA5457DD216C02814E97E4E134C40407B0F971CC716C03835B401D8124C40000AD7A370BD16C0386552431B104C4080A46B26DFBC16C058853FC39B0F4C4080A46B26DFBC16C03041B8020A0F4C4000B4C9E193BE16C0A85FE97C780E4C40C0DBF3FC69C316C00048A643A70D4C4040C2F5285CCF16C058888043A80C4C4040F2CEA10CD516C058F5F23B4D0C4C40401F80D426DE16C060FEB5BC720B4C40C0F3FBFECDEB16C0283E7782FD094C40C09CBCC804FC16C038EACC3D24084C400090BDDEFD0117C020F38FBE49074C404061DF4E226217C0C8C1FA3F87F94B40407D3CF4DD9D17C0285C8FC2F5F04B40407138F3ABC917C030F04E3E3DEA4B4001030000000100000012000000001C261AA4F016C0D00CE2033B144C40C01E85EB51F816C0D00CE2033B144C40804E5E6402FE16C000BEDBBC71144C4000000000000017C008D6E3BED5144C40C00CFFE906FA16C01048A643A7154C404081919735F116C0588E0244C1164C4080415F7AFBC316C0D0F71A82E3184C40404E5E6402BE16C000E2E7BF07194C40005B5D4E09B816C0E07C957CEC184C40C0B392567CB316C0A8656B7D91184C40408940F50FB216C0884E417E36184C40C0C51858C7B116C0B0E9B303AE174C40C0C51858C7B116C058499D8026164C408019FED30DB416C008CD203EB0154C4040AC1A84B9BD16C028ED0DBE30154C4040C2F5285CCF16C050888043A8144C40C07F643A74DA16C0885A457F68144C40001C261AA4F016C0D00CE2033B144C400103000000010000000C00000080EB51B81E8516C078ABAE4335194C400011548D5E8D16C02838F581E4174C4040A69883A09316C0D000DE0209184C40C0E7F7FD9B9716C0D0B2B5BE48184C40C04C310741A716C0484CDE00331B4C4040FED2A23EA916C0C8C77C40A01B4C4040A69883A09316C0F02F1004C8204C408052B3075A9116C06073B9C150214C4080D79E59127016C0285C8FC2F5204C40C09DEE3CF16C16C0B8656B7D91204C4040FEB5BC726D16C01000000000204C4080EB51B81E8516C078ABAE4335194C4001030000000100000011000000C016D68D777716C0A8B915C26A224C4000AC1A84B97D16C0306BD44334224C40C0D11C59F98516C08854C37E4F224C40401B2B31CF8A16C05082FE428F224C40C0E7F7FD9B9716C0587FBDC282254C4000F2CEA10C9516C010C45DBD8A264C4000C0CDE2C59216C0883FFCFCF7264C40C0D11C59F98516C0587C7C4276284C4040A46B26DF7C16C090457EFD10294C4000C3F011317516C050465C001A294C40C0CB9A58E05B16C0D8A9F23D23294C40C0F97DFFE65516C0D07C957CEC284C4000583A1F9E5516C01018080264284C408024D060535716C06037177FDB274C4040A01683876916C0F82CCF83BB234C40C0CFEFFB376F16C0D0FD9C82FC224C40C016D68D777716C0A8B915C26A224C400103000000010000000E00000080C1C3B46F9E19C0B877F17EDC264C40004F594DD7A319C02829B000A6264C40403883BF5FAC19C0002A8E03AF264C40C058350873BB19C0B0BC564277274C4040560DC2DCBE19C0084E2844C0274C40C0A7C5E061AA19C0B8B915C26A2A4C40400455A3579319C0602B137EA92B4C40006F10AD158D19C09015E0BBCD2B4C40407B0F971C8719C0D0C77C40A02B4C4080D11C59F98519C0584CDE00332B4C4080BA46CB818E19C05873B9C150294C40C0BFCDE2C59219C0089D82FC6C284C40C021A81ABD9A19C0E009A1832E274C4080C1C3B46F9E19C0B877F17EDC264C400103000000010000000B00000000DAC69FA82C16C028E109BDFE304C4000CB9F6F0B3616C00818080264304C40403E05C0785616C0E07C957CEC304C408091EA3BBF5816C0D80F238447314C40C03BDD79E25916C0B074B0FECF314C40C0E7F7FD9B5716C0386BD44334324C40006CB1DB674516C000DFA63FFB334C40002EAC1BEF2E16C0805A457F68344C40C0D6A3703D0A16C08887A2409F344C4080BC7328432516C0F8264D83A2314C4000DAC69FA82C16C028E109BDFE304C400103000000010000001100000000643E20D0A918C0B0DDAF027C3B4C408001F6D1A9CB18C0104BE7C3B33A4C4000C8409E5DEE18C0A8622AFD843B4C4000DD257156F418C0682B137EA93B4C40002DB1321A0919C0386893C3273D4C40C0D6A3703D0A19C010CD203EB03D4C40C0698995D10819C060499D80263E4C400017D68D77F718C0A85626FC523F4C40802B84D558F218C0888461C0923F4C4080A23EC91DE618C03038F581E43F4C4080D349B6BADC18C0B86E2EFEB63F4C40C0963AC8EBD118C0A85626FC523F4C408008AA46AFA618C010D6E3BED53C4C4040CEF9298EA318C0B0BF97C2833C4C40001D588E90A118C0E8A6B1BD163C4C4080B4C4CA68A418C0E0C77C40A03B4C4000643E20D0A918C0B0DDAF027C3B4C40010300000001000000180000004021AD31E8F41AC0B0A10DC006424C40C0698995D1081BC0A074B0FECF414C408091EA3BBF181BC0B0A10DC006424C4040F6234564281BC0503D997FF4414C40C02DAC1BEF2E1BC008D9243FE2414C404021AD31E8341BC0908AE3C0AB414C4040C8772975391BC0885D86FF74414C40802A52616C811BC040D505BCCC3C4C40407B0F971C871BC088423D7D043C4C40805A626534921BC020EACC3D24384C404033333333B31BC0B8B393C151384C4080CEF9298EE31BC000C11C3D7E394C40000F27309DF61BC038F38FBE493F4C40C0DC257156F41BC0084E2844C03F4C404078EC67B1E41BC008E2E7BF07414C4040F2CEA10CD51BC0908AE3C0AB414C40801803EB380E1BC0E8AC33BE2F464C40402502D53F081BC0001286014B464C4000D4449F8F021BC010E5284014464C4040726A6798FA1AC0301A6B7F67454C40002EAC1BEFEE1AC038DEC83CF2434C40404A09C1AAEA1AC0F8E769C020434C40C0A7C5E061EA1AC05807793D98424C404021AD31E8F41AC0B0A10DC006424C4001030000000100000062000000C02407EC6A2217C0D8A9F23D23414C40C0CB9A58E0DB16C0485260014C3D4C40C021A81ABD9A16C0E0EE5701BE394C4000CEC29E769816C08093A641D1384C40008A3BDEE49716C008D3A23EC9374C40802407EC6AA216C010C79E3D97334C4040AAED26F8A616C0B8E67283A1324C40005D8AABCACE16C0E07FD6FCF82D4C40C0CB9A58E0DB16C0100341800C2D4C40809CBCC8043C17C0F8C9DFBDA3284C40C00F2219725C17C0F820CB8289274C40C00AD28C456317C0E0BB783F6E274C40001C261AA47017C0084E2844C0274C4080A46B26DF7C17C0784E417E36284C40C039B01C218317C08818213CDA284C404060E4654D7C17C000274D83A2294C40400F27309D7617C000D9243FE2294C408079E2395B7017C06082FE428F2A4C40C0A7C5E0616A17C060793BC2692B4C40C0B94BE2AC6817C0D87954FCDF2B4C40C03AAB05F66817C0A8BF97C2832C4C40008E90813C6B17C0A8716F7EC32C4C4080DF4DB7EC7017C0100341800C2D4C40C0C0C8CB9A7817C0E088997D1E2D4C4080BF9657AE8717C0100341800C2D4C40805A6265349217C0600DFB3DB12C4C4000D0EFFB37EF17C000301004C8284C40806CE8667F1018C06040DAFF00274C40C0FECD8B130F19C0E0A9F23D23214C4080698995D14819C0A874B0FECF214C4040ABE80FCD4C19C0D006600322224C4080295778975B19C0009A417C60234C40C02407EC6A6219C058431B800D244C408078EC67B16419C0905A457F68244C4040B16A10E67619C0F820CB8289274C40C07492AD2E7719C0D08558FD11284C4000DD2571567419C038F04E3E3D2A4C408008AA46AF6619C0F0E769C0202B4C4080295778975B19C060793BC2692B4C4040DF4DB7EC3019C0D0C77C40A02B4C4040A01683872919C0B8622AFD842B4C40007365506D2019C0D882177D052B4C4080D349B6BA1C19C0B86BED7DAA2A4C40403E05C0781619C0903CBB7CEB294C40C0E175FD82ED18C0302F3201BF284C40C0DBF3FC694318C0081B4982702D4C40C0CB9A58E01B18C0588E0244C12E4C4040E048A0C11618C02841B8020A2F4C4080402D060F1318C0B85626FC522F4C40405A6265341218C0889C69C2F62F4C4040A69883A01318C0009D82FC6C304C40003E05C0781618C0F82F1004C8304C40408FC2F5281C18C028E109BDFE304C40C00AD28C452318C0E07C957CEC304C40400E2C47C85018C03820ED7F802F4C40408E90813C6B18C0A8DA6E826F2E4C40400F27309D7618C010E52840142E4C40801E4E603AAD18C0B0E33103952D4C40000AD7A370BD18C01048A643A72D4C40009544F641C618C078AEEFC3412E4C40008196AE60CB18C0B8A44E40132F4C40C0067DE9EDCF18C00818080264304C40006F10AD15CD18C008C11C3D7E314C4040FCA5457D9218C0D8F19881CA364C4040F2CEA10C5518C0D8CABDC0AC384C4000CFF412634918C058465C001A394C400015A930B62018C05034D6FECE3A4C4000FA7DFFE61518C03014E97E4E3B4C40006F10AD150D18C0D0F4D901D73B4C40407B0F971C0718C0500DFB3DB13C4C40C02FD978B00518C0386893C3273D4C40403201BF460218C0888D2441B83E4C4080976C3CD80218C0286E15C4403F4C400016A4198B0618C02820ED7F803F4C4000BCE9961D1218C0C06114048F3F4C4080BC7328436518C0B8E33103953D4C4000630CACE37818C0F8230C03963C4C40802A52616C8118C058888043A83C4C40807B0F971C8718C010D6E3BED53C4C40C06E10AD154D19C0F80241800C454C40803BDD79E25919C0E07FD6FCF8454C40401B2B31CF4A19C030D505BCCC4C4C40C0BF9657AE4719C038ED0DBE304D4C4000F850A225BF18C09054C37E4F524C4080067DE9ED8F18C0806308008E534C40402DB1321A8918C0E0C77C40A0534C400017D68D777718C0D0AF743E3C534C40C015A4198B4618C0D873D2FBC6514C40C0AE42CA4F3A18C030F911BF62514C4040F62345642818C0A86E2EFEB64F4C40809CBCC804FC17C0B06BED7DAA4A4C40C0620CACE3F817C030F04E3E3D4A4C40C000FBE8D4E517C09060C77F81464C40C02407EC6AE217C008CD203EB0454C40809DEE3CF16C17C0301DACFF73424C404077BAF3C43317C0D8EE5701BE414C40C09DEE3CF12C17C000274D83A2414C40C02407EC6A2217C0D8A9F23D23414C400103000000010000001700000000662FDB4E5B1AC030F04E3E3D4A4C40000F27309DB61AC078A52C431C474C4040F0A1444BBE1AC0386E15C440474C40407B0F971CC71AC0D0F71A82E3484C408001F6D1A9CB1AC030F04E3E3D4A4C40C0698995D1C81AC0B06BED7DAA4A4C40C05D85949F741AC070ABAE4335514C408001F6D1A94B1AC0E0C77C40A0534C40002EAC1BEF2E1AC0905182FE42554C4080137CD3F4091AC0A85626FC52574C4000282A1BD6041AC00021CB8289574C40C004508C2CF919C0789C69C2F6574C4080D349B6BADC19C088C9C6832D584C4040EA1F4432D419C0804E417E36584C40C052B3075AD119C0D0D38041D2574C4080067DE9EDCF19C0805704FF5B574C40C052B3075AD119C030DB87BCE5564C40C01B261AA4F019C0E0EE5701BE514C40C004508C2CF919C008CADFBDA3504C40802A52616C011AC07821E4BCFF4F4C404067614F3B4C1AC0881EA33CF34A4C40800E2C47C8501AC0B06BED7DAA4A4C4000662FDB4E5B1AC030F04E3E3D4A4C400103000000010000001400000040EA1F44329418C0805704FF5B6F4C4000698EACFCA218C0286E15C4406F4C40006DE34F54B618C0084E2844C06F4C4040CEC29E76D818C0A0C2D84290714C40C021A81ABDDA18C0203E7782FD714C408029577897DB18C0286211C30E734C40C0CB9A58E0DB18C000C79E3D97734C40C0DD205A2BDA18C0E0A6B1BD16744C4000AE47E17AD418C0503A58FFE7744C40C02407EC6AA218C0089D82FC6C784C40C0D571FC509918C0385C8FC2F5784C4040ABE80FCD8C18C0582E54FEB5784C40C0DC2571567418C0905704FF5B774C408047E17A146E18C02029B000A6764C40C08B683BA66E18C0801B62BCE6754C40008718AF797518C0A8E67283A1724C4080726A67987A18C0E0A9F23D23714C4080F0A1444B7E18C008301004C8704C40801803EB388E18C00021CB82896F4C4040EA1F44329418C0805704FF5B6F4C400103000000010000001A00000080EB51B81E4519C0808461C092774C400011548D5E4D19C0808461C092774C4040FCA5457D5219C0004E2844C0774C4080CDC7B5A17219C0D8A9F23D23794C4040BD6E1118CB19C05037177FDB7F4C40C0FECD8B13CF19C0E8B2B5BE48804C4080BA46CB81CE19C0F82F1004C8804C4000A0168387A919C0080C040132844C40C0BFCDE2C59219C0B068ACFD9D854C4000CFF412638919C050499D8026864C40404F594DD76319C0D8F19881CA864C400055DB4DF04D19C000DC65BFEE864C40C0CB9A58E01B19C0500438BD8B854C4000F2CEA10C1519C0D8B5F63E55854C40C0C41D6FF20B19C0F8D5E3BED5844C4040C2BE9D440419C0D0A6B1BD16844C40C05DBC1FB7FF18C03814E97E4E834C4040F850A225FF18C02835B401D8824C40400AD7A370FD18C0D0BB783F6E7F4C4080EB51B81E0519C058793BC2697B4C40807B0F971C0719C0881EA33CF37A4C4040B06F27111119C0B874B0FECF794C4040758D96031D19C0D0F71A82E3784C4080C51858C73119C0909C69C2F6774C40804E5E64023E19C058853FC39B774C4080EB51B81E4519C0808461C092774C4001030000000100000012000000801F80D426DE1DC0089D82FC6C784C404008AA46AFE61DC0089D82FC6C784C4080643909A50F1EC0582E54FEB5784C4000C972124A1F1EC08018213CDA784C40C0B392567C331EC0E00F238447794C4040A46B26DF3C1EC0E073D2FBC6794C40804E5E64023E1EC08054C37E4F7A4C40000AD7A3703D1EC090992842EA7A4C4040B16A10E6361EC0302CF180B27B4C40402502D53FC81DC080A52C431C874C40003201BF46C21DC0903FFCFCF7864C4040DAC69FA8AC1DC0B068ACFD9D854C40C0B94BE2ACA81DC0505260014C854C40003AB01C21831DC0D8CDFE40B97D4C4000880E8123811DC0805182FE427D4C408046AF0628BD1DC0385C8FC2F5784C40C0ED79FEB4C11DC0E0CABDC0AC784C40801F80D426DE1DC0089D82FC6C784C400103000000010000000D00000000F850A225FF19C0002A8E03AF864C40C0402D060F531AC0B068ACFD9D854C40803AAB05F6681AC0D8FA5B02F0854C4040B29C84D2671AC010C45DBD8A864C40406BB6F2925F1AC03841B8020A874C40C0620CACE3381AC05801F73C7F884C4080CDC7B5A1321AC0602E54FEB5884C4040DAC69FA82C1AC000CADFBDA3884C40005EBC1FB7FF19C0809C69C2F6874C40800CFFE906FA19C0084E2844C0874C40C0B8196EC0F719C0B05626FC52874C40C0F2C98AE1FA19C000DC65BFEE864C4000F850A225FF19C0002A8E03AF864C400103000000010000001700000000EE79FEB4C117C008C79E3D97A34C4080698995D1C817C0906308008EA34C40C0D0217024E017C0E0F4D901D7A34C4000F4FBFECDEB17C0000C040132A44C408060E4654DFC17C0583A58FFE7A44C4080C745B5880818C028327381CBA54C4080FCA5457D1218C0E076137CD3A64C4040A69883A01318C008BB9A3C65A74C40405A6265341218C03038F581E4A74C4080C2F5285C0F18C0504F1F813FA84C4080D11C59F90518C000301004C8A84C40C0B392567CF317C000E2E7BF07A94C4040A69883A0D317C000301004C8A84C40C06E10AD15CD17C0806649809AA84C408060E4654DBC17C03038F581E4A74C40C01E85EB51B817C0500ABABDA4A74C40C02DAC1BEFAE17C008C45DBD8AA64C4000DAC69FA8AC17C08848BF7D1DA64C40C0F3FBFECDAB17C0F847A643A7A54C40003883BF5FAC17C0000341800CA54C40C023D5777EB117C06070784144A44C40406DE34F54B617C020DEC83CF2A34C4000EE79FEB4C117C008C79E3D97A34C400103000000010000002300000080B4C4CA68E41CC0504CDE0033AB4C4040DAC69FA8EC1CC05807793D98AA4C40C09CBCC804FC1CC0603D997FF4A94C40003201BF46021DC0B874B0FECFA94C40402DB1321A091DC000D9243FE2A94C40801281EA1F241DC0D882177D05AB4C4080AAED26F8261DC0E00F238447A94C4000CFF41263091DC0B0622AFD84934C4080CB9A58E0DB1CC02829B000A68E4C40C00F221972DC1CC08848BF7D1D8E4C40C04C310741E71CC0905A457F688C4C4000F4FBFECDEB1CC0B8A78FC01F8C4C40C0067DE9ED0F1DC0885182FE428D4C40C0A23EC91D261DC0B0E33103958D4C40400F27309D361DC0B0E33103958D4C4000583A1F9E551DC038D505BCCC8C4C4040DAC69FA86C1DC0480DFB3DB18C4C404077BAF3C4731DC038D505BCCC8C4C400016A4198B861DC0801B62BCE68D4C4000C51D6FF28B1DC0F8298E03AF8E4C40C0963AC8EB911DC08821E4BCFF8F4C40C0573A1F9E951DC0D8F71A82E3904C400052B81E85AB1DC0885704FF5B974C40809DEE3CF1AC1DC02838F581E4974C40002EAC1BEFAE1DC028DEC83CF29B4C404033333333B31DC0E07C957CECB04C408079E2395BB01DC05073B9C150B14C4080A23EC91DA61DC010D9243FE2B14C4000630CACE3781DC0009A417C60B34C40C0E7F7FD9B571DC0B06BED7DAAB24C404078EC67B1241DC0F82F1004C8B04C40403E05C078161DC0D000DE0209B04C404016DBA4A2111DC0600ABABDA4AF4C40C000FBE8D4E51CC0082DCF83BBAB4C4080B4C4CA68E41CC0504CDE0033AB4C4001030000000100000018000000400455A357131DC0386211C30EB34C400061DF4E22221DC0B8984A3FE1B24C4040880E8123411DC0904B00FE29B34C404083BEF4F6471DC0009A417C60B34C40003AB01C21831DC030327381CBB54C400011548D5E8D1DC080AEEFC341B64C4040C1C3B46F9E1DC0B8656B7D91B84C40C00AD28C45A31DC028F911BF62B94C40404F594DD7A31DC008D9243FE2B94C40C0D0217024A01DC048793BC269BB4C40407D3CF4DD9D1DC0D87954FCDFBB4C40803BDD79E2991DC0000C040132BC4C4040C8409E5D6E1DC08060C77F81BE4C40401059A489671DC02829B000A6BE4C408077BAF3C4331DC0801B62BCE6BD4C400022A81ABD1A1DC0507FBDC282BD4C40800CFFE906FA1CC0B89ECC3FFABC4C404016DBA4A2D11CC0D0FD9C82FCBA4C4080C2F5285CCF1CC05082FE428FBA4C4000FFCD8B13CF1CC0B068ACFD9DB54C408052B3075AD11CC0D088997D1EB54C4040C3F01131F51CC0582B137EA9B34C4040726A6798FA1CC0B8DDAF027CB34C40400455A357131DC0386211C30EB34C400103000000010000001600000080295778971B18C080A2EBC20FAA4C4000DD2571563418C0E0C1FA3F87A94C4040AC1A84B93D18C0A0C2D84290A94C40007E37DDB24318C0E873D2FBC6A94C4080D11C59F94518C0E006600322AA4C40C052B3075A5118C048888043A8AC4C400016DBA4A25118C020ED0DBE30AD4C4080A8C0C9365018C0381DACFF73B24C40001B2B31CF4A18C080A52C431CB74C40C0976C3CD84218C0E0EE5701BEB94C4040880E81234118C0306BD44334BA4C40407365506D2018C0883FFCFCF7BE4C40C00F2219721C18C030F38FBE49BF4C40003AB01C210318C048465C001AC14C400052B81E85EB17C0B0BC564277BF4C4080F6234564E817C03041B8020ABF4C408054E0641BE817C08060C77F81BE4C40400778D2C2F517C030D505BCCCAC4C4080AE42CA4FFA17C0D07954FCDFAB4C40C046AF0628FD17C0A0DDAF027CAB4C400016A4198B0618C0A8984A3FE1AA4C4080295778971B18C080A2EBC20FAA4C400103000000010000000D00000040272F3201DF17C080992842EAC24C4040A5660FB4E217C0603D997FF4C14C4000643E20D0E917C0A8A10DC006C24C40805D85949FF417C038E78BBD17C34C4000CB9F6F0BF617C0886308008EC34C40000F27309DF617C090CC07043AC54C400084B9DDCBED17C08021E4BCFFC74C4080B9145795DD17C05073B9C150C94C408091EA3BBFD817C020266F8099C94C4000C0CDE2C5D217C0785D86FF74C94C40400E2C47C8D017C0F8E1E7BF07C94C40C0A8C0C936D017C0806649809AC84C4040272F3201DF17C080992842EAC24C4001030000000100000072000000000455A3579318C0682E54FEB5C84C4000C51D6FF28B18C0305FD04202BE4C40009CC1DF2F9618C00048A643A7B54C404024D060539718C0002DCF83BBB34C4080137CD3F48918C0D08558FD11A84C40403201BF468218C0D809A1832EA74C408091EA3BBF9817C0903FFCFCF79E4C40C0C41D6FF28B17C05828D2FD9C9E4C4040EB51B81E8517C0908D2441B89E4C4040941282555517C0607C7C4276A04C40000455A3571317C02035B401D8A24C40404487C0910017C00015C78157A34C4000630CACE3F816C03014E97E4EA34C40C091EA3BBF9816C0D00F238447A14C40C0573A1F9E9516C09018213CDAA04C4040BC732843A516C0E0D03FC1C59A4C4000B29C84D2A716C030F04E3E3D9A4C4040C8409E5DAE16C0B0C2D84290994C4000B16A10E63617C0F8DB65BFEE8E4C40C0415F7AFB4317C08848BF7D1D8E4C40C05C8AABCA4E17C01048A643A78D4C4040F2CEA10C5517C0507FBDC2828D4C40404F594DD76317C000A0C37C798D4C40C0355B79C96F17C0D87954FCDF8B4C4080BA46CB818E17C088C9C6832D884C4080FCA5457D9217C0D8D38041D2874C40406DE34F54B617C0303B3602F1844C400090BDDEFDC117C028232E008D844C400052B81E85EB17C060FEB5BC72834C4040F0A1444BFE17C0C882177D05834C404067614F3B0C18C02835B401D8824C4080B06F27111118C0904B00FE29834C4000B7EC10FF2018C09048BF7D1D864C4040CEF9298E2318C04840DAFF00874C404061DF4E222218C0B8BC564277874C40000F27309DF617C0081286014B8E4C40C05EB7088CE517C0C8CABDC0AC904C4000C972124A1F18C0808D2441B8964C40008196AE604B18C080C9C6832D904C40C0FECD8B134F18C03038F581E48F4C4000E8F7FD9B5718C08821E4BCFF8F4C40C0688EACFC6218C0089D82FC6C904C400021AD31E8B418C0A89509BFD4954C40C08FBDDEFD4119C080A86DC328944C40C0D11C59F94519C0885A457F68944C40407138F3ABC919C0508BC1C3B4A14C4040C2F5285CCF19C0081E8A027DA24C40004A09C1AAEA19C05076FA415DA64C40C09DEE3CF1EC19C0D0F19881CAA64C40003883BF5FEC19C0785704FF5BA74C40C0DC257156B419C05807793D98AA4C40C0355B79C9AF19C03035B401D8AA4C4080AAED26F8A619C0A8984A3FE1AA4C40008A3BDEE49719C080A2EBC20FAA4C4000560DC2DC7E19C0504F1F813FA84C404061DF4E226219C0F8298E03AFA64C404024D060535719C0D0AC33BE2FA64C408052B3075A5119C028E44A3D0BA64C4000EE79FEB44119C000E5284014A64C4000AC1A84B93D19C060FB743C66A64C40C046AF06283D19C0F8DB65BFEEA64C4080295778971B1AC060431B800DB44C404061DF4E22221AC05070784144B44C40008196AE604B1AC0A0AAD0402CB14C40008196AE604B1AC0306552431BB04C400090BDDEFD411AC0585260014CAD4C4000E6CAA0DA401AC008D6E3BED5AC4C4040880E8123411AC0D00CE2033BAC4C40C0272A1BD6441AC0504CDE0033AB4C4080BF9657AE471AC0A8984A3FE1AA4C400011548D5E4D1AC0B86BED7DAAAA4C4040508BC1C3541AC000D061BEBCAA4C400000000000801AC050431B800DAC4C40C0ED79FEB4C11AC0E0AC33BE2FAE4C4040ABE80FCDCC1AC0D8C43BC093AE4C4040E048A0C1D61AC088A52C431CAF4C404061DF4E22E21AC028EACC3D24B04C40801281EA1FE41AC0A8656B7D91B04C4080A23EC91DE61AC0B0C2D84290B14C408000FBE8D4E51AC0582B137EA9B34C408024D06053171BC0488E0244C1B64C4000662FDB4E1B1BC0B0A44E4013B74C40C0B91457951D1BC0C8BB783F6EB74C404078EC67B1241BC050465C001AB94C4080CEF9298E231BC030266F8099B94C40400AD7A370FD1AC0A8A44E4013BF4C4040ABE80FCD8C1AC0587FBDC282CD4C4040AC1A84B97D1AC0500438BD8BCD4C40400F27309D761AC0281A6B7F67CD4C40C083B9DDCB6D1AC088397AFCDECC4C4040CEC29E76581AC01015C78157CB4C4080A8C0C936501AC0B8E67283A1CA4C4080137CD3F4491AC0583D997FF4C94C40C039B01C21431AC0282F3201BFC84C400090BDDEFD411AC00009C38025C74C4000E6CAA0DA401AC0F0298E03AFC64C4040726A67983A1AC0E0FA5B02F0C54C40807F643A74DA19C0D8A9F23D23C14C40C01E85EB51B819C010CADFBDA3C04C40004487C0918019C038E78BBD17C34C4040941282559519C0286893C327CD4C4000C8409E5DAE19C0000F45813ED14C40C07133DC80AF19C038266F8099D14C40801E4E603AAD19C0E08BDAFD2AD24C4040B7EC10FFA019C0306211C30ED34C40C0BE9B6ED96119C0500ABABDA4D74C40C016D68D773719C0D0D38041D2D74C40C0295778971B19C028E44A3D0BD64C400049D74CBEB918C03029B000A6CE4C4080CDC7B5A1B218C0881B62BCE6CD4C4040AAED26F8A618C010BEDBBC71CC4C40C0BE9B6ED9A118C0582B137EA9CB4C40C0573A1F9E9518C020266F8099C94C40000455A3579318C0682E54FEB5C84C400103000000010000002000000000880E8123C11CC0909C69C2F6D74C40006F10AD154D1CC0306BD44334D24C4040EB51B81E451CC038266F8099D14C40C0DBF3FC69431CC080457EFD10D14C4080A3703D0A971CC0903CBB7CEBC14C40C0B91457959D1CC080ABAE4335C14C40003883BF5FAC1CC000E2E7BF07C14C4000D0EFFB37EF1CC0587C7C4276C04C40003201BF46421DC0B8E0F08288C04C40002DB1321A491DC0D0CABDC0ACC04C400055DB4DF04D1DC030E109BDFEC04C4080C2F5285C4F1DC0B8622AFD84C34C40C06E10AD154D1DC01048A643A7C54C40C01281EA1F641DC09060C77F81C64C40C05EB7088CA51DC0682E54FEB5C84C4080FCA5457DD21DC090C9C6832DC84C4040272F3201DF1DC0B89B8BBFEDC74C4040F6234564E81DC08021E4BCFFC74C4080C51858C7F11DC0507C7C4276C84C4080BC732843251EC0D082177D05CB4C4040FED2A23E291EC0A8B0524145CB4C40003883BF5F2C1EC0E0C77C40A0CB4C40003883BF5F2C1EC0E00CE2033BCC4C40007592AD2EF71DC008D061BEBCD24C40C07133DC80EF1DC060FEB5BC72D34C40801281EA1FE41DC0C8F4D901D7D34C4000F3C98AE1BA1DC0D8C77C40A0D34C400078B5DC99191DC088423D7D04D44C4000583A1F9E151DC0905A457F68D44C4040726A6798FA1CC02829B000A6D64C4080137CD3F4C91CC0A89B8BBFEDD74C4000880E8123C11CC0909C69C2F6D74C400103000000010000000F00000040CFF41263C91CC000D9243FE2D94C408052B3075AD11CC030D8463CD9D94C4000B7EC10FFE01CC0A8A10DC006DA4C40407365506DE01CC05807793D98DA4C40803BDD79E2D91CC00015C78157DB4C40C08096AE60CB1CC0A8716F7EC3DC4C40403201BF46C21CC0585260014CDD4C40408940F50FB21CC0781B62BCE6DD4C40004A09C1AAAA1CC020E44A3D0BDE4C40004F594DD7A31CC0D87FD6FCF8DD4C4040EA1F4432941CC09087A2409FDC4C4040508BC1C3941CC080423D7D04DC4C40C077B5DC99991CC0082DCF83BBDB4C40C0630795B89E1CC0B8622AFD84DB4C4040CFF41263C91CC000D9243FE2D94C400103000000010000000C000000804F72874D1C21C008D3A23EC9E74C408008AA46AF2621C0B0AD11C138E64C4000D7A3703D2A21C088AEEFC341E64C40206DE34F543621C05040DAFF00E74C4000D671FC503921C0586D37C137E74C402030F2B2263E21C06073B9C150E94C4080D349B6BA3C21C0E0EE5701BEE94C40201B2B31CF2A21C0905D86FF74E94C40001D588E902121C0D87C957CECE84C40E09CBCC8041C21C0607C7C4276E84C40C0321AF9BC1A21C088C9C6832DE84C40804F72874D1C21C008D3A23EC9E74C400103000000010000000E0000000016A4198B061CC09093A641D1F04C40008196AE604B1CC028172AFF5AF04C40C0643909A54F1CC0F8C9DFBDA3F04C4080BA46CB814E1CC0B053E57B46F24C40008196AE604B1CC0084BE7C3B3F24C40001D588E90211CC028ED0DBE30F54C40408FC2F5281C1CC0A0B6D4415EF54C40C01D537765071CC0D8CDFE40B9F54C40009A94826EFF1BC06831957EC2F54C4040C8772975F91BC0B0E3310395F54C40C00CFFE906FA1BC0B09ECC3FFAF44C40400AD7A370FD1BC0B0A10DC006F24C4040560DC2DCFE1BC0A0C2D84290F14C400016A4198B061CC09093A641D1F04C400103000000010000000F000000008718AF79351BC0283E7782FD194D4040E5CFB7055B1BC038D8463CD9194D40800CFFE9067A1BC000068200191A4D40804E5E64027E1BC0A8B915C26A1A4D40C01803EB388E1BC038F38FBE491F4D4080C2F5285C8F1BC0D0D38041D21F4D4000FFCD8B138F1BC0B0B393C151204D4040D9CBB6D3861BC0A0E0F08288204D4080DF4DB7EC701BC038EACC3D24204D40404A09C1AA6A1BC00800000000204D40C046AF06283D1BC0905182FE421D4D40C0E175FD822D1BC0B07A32FFE81B4D4000A8C5E0612A1BC0081E8A027D1A4D40C0E175FD822D1BC0B8A10DC0061A4D40008718AF79351BC0283E7782FD194D40010300000001000000B100000080B06F2711D118C0A8E33103952D4D40C047E17A14EE18C0E0CABDC0AC284D4080C1C3B46F1E19C008D6E3BED5244D408001F6D1A94B19C0D8EE5701BE214D4000FCA71B285019C0E03C9CC0741E4D404023D6E2535019C0F8997ADD221E4D40003D0B42794F19C000CAA65CE11D4D40C06E10AD154D19C0508CD7BCAA1D4D40C0490A2C804919C030629F008A1D4D4000EB5223F42319C07000E143891C4D40C034289A072019C000DCD781731C4D40C0295778971B19C0F0AE25E4831C4D40402C7FBE2D1819C04898141F9F1C4D40008C67D0D00F19C0F0D58EE21C1D4D400061DF4E22E218C0881B62BCE61D4D4000583A1F9ED518C0E876137CD31E4D40C01B261AA4B018C078457EFD10214D4000F4FBFECDAB18C068F833BC59214D40404F594DD7A318C0100F45813E214D40C0E7F7FD9B9718C008301004C8204D40003E05C0789618C028172AFF5A204D404061DF4E22A218C028DEC83CF21B4D4080F6234564A818C0884B00FE291B4D40C079E2395BB018C0081E8A027D1A4D4080A23EC91DE618C03020ED7F80174D40009EEDD11B0E19C0F096AB1F9B164D40C0035779025119C09847702365174D40C016D68D777719C068F5F23B4D144D40C05DBC1FB77F19C060F833BC59114D400090BDDEFD8119C0D0F71A82E3104D40C01D5377658719C0806649809A104D40C046AF0628FD19C0D0BEB9BF7A0C4D404081919735311AC0809065C1C40B4D40001059A489671AC0A8984A3FE10A4D4040B6F1272A7B1AC0001E8A027D0A4D40C00CFFE9067A1AC0B0A10DC0060A4D4040B7EC10FF601AC0B0A10DC0060A4D4040A46B26DFFC19C0584CDE00330B4D4000C8409E5DAE19C0D0031F83150D4D40801281EA1FA419C0507FBDC2820D4D40408FC2F5289C19C0600438BD8B0D4D4000583A1F9E9519C0301A6B7F670D4D40C0067DE9ED8F19C07887A2409F0C4D40C0A7C5E0616A19C0D80CE2033B044D40801E4E603A6D19C0D0F4D901D7034D40008196AE608B19C0B8AAD0402C014D4040508BC1C3D419C0B87A32FFE8FB4C4080BC732843E519C038F911BF62F94C40C01281EA1FE419C08018213CDAF84C4080BC732843E519C038172AFF5AF84C4040AAED26F8261AC0585260014CF54C40801E4E603A2D1AC0E088997D1EF54C40402502D53F481AC050888043A8F44C4040C2F5285C4F1AC008240C0396F44C40C09CBCC8047C1AC0100341800CF54C40003AB01C21831AC0306893C327F54C4040D349B6BA9C1AC06831957EC2F54C40C0A23EC91DA61AC0001286014BF64C4000A8C5E061AA1AC03829B000A6F64C408085E63A8DC41AC0B8E67283A1FA4C40008196AE60CB1AC0D8F4D901D7FB4C404016DBA4A2D11AC0F81186014BFE4C40C069C020E9D31AC05037177FDBFF4C4080402D060FD31AC0285C8FC2F5004D4000D7A3703DCA1AC008D061BEBC024D40407B0F971CC71AC000E869C020034D408008AA46AFA61AC010CD203EB0054D4000698EACFCA21AC0D07FD6FCF8054D4000102219729C1AC0D8AC33BE2F064D40C085E63A8D841AC0D8AC33BE2F064D4080A46B26DF7C1AC09048BF7D1D064D40800778D2C2751AC0881B62BCE6054D40C0F84B8BFA641AC028327381CB054D40400DFAD2DB5F1AC0D8FA5B02F0054D4000102219725C1AC068FB743C66064D40C01C588E90611AC0888D2441B8064D404008AA46AF661AC028DB87BCE5064D4000C8409E5D6E1AC06040DAFF00074D408047E17A14AE1AC0E0BB783F6E074D40000F27309DB61AC0B0BC564277074D4040A46B26DFBC1AC0805704FF5B074D40C0ED79FEB4C11AC03841B8020A074D404001F6D1A90B1BC008D3A23EC9FF4C40C04C310741E71AC0D08BDAFD2AFA4C40801281EA1FE41AC0D0EE5701BEF94C40C0D0217024E01AC008C11C3D7EF94C40405A626534D21AC078ABAE4335F94C40402DB1321AC91AC008CADFBDA3F84C40000AD7A370BD1AC050853FC39BF74C40405B5D4E09B81AC0D876137CD3F64C40400778D2C2B51AC0A05FE97C78F64C4000BA4BE2ACA81AC0B8B0524145F34C40C0B4C4CA68A41AC0100F45813EF14C40C0A23EC91DA61AC0582E54FEB5F04C4080DF4DB7ECF01AC0508BC1C3B4E94C40C0893BDEE4D71BC0E088997D1EDD4C4080D349B6BADC1BC078397AFCDEDC4C40004F594DD7E31BC0A8716F7EC3DC4C40C0633E20D0E91BC0503A58FFE7DC4C40007233DC80EF1BC090CC07043ADD4C4000F3C98AE17A1CC0804E417E36E84C40404E5E64027E1CC000CADFBDA3E84C40409A94826E7F1CC080457EFD10E94C4000EE79FEB4811CC0A86BED7DAAEA4C4000A243E048801CC0E8AF743E3CEB4C400005508C2C791CC0A8B0524145EB4C40C0A7C5E0616A1CC028E78BBD17EB4C4080C1C3B46F5E1CC06007793D98EA4C4000583A1F9E551CC0A8C2D84290E94C40C0DBF3FC69431CC080457EFD10E94C4080B91457951D1CC07881204086EA4C40405A626534521BC02814E97E4EF34C40009CC1DF2F561BC0602B137EA9F34C408085E63A8D841BC0905704FF5BF74C40400AD7A370BD1BC0B0C2D84290F94C40C0698995D1C81BC0603D997FF4F94C40C01B261AA4F01BC05834D6FECEFA4C4080C0C8CB9AF81BC0D0D03FC1C5FA4C40003E05C078161CC040D8463CD9F94C4040C1C3B46F1E1CC0F8D8243FE2F94C4080B4C4CA68241CC0A8A10DC006FA4C40006F10AD154D1CC0504CDE0033FB4C40C0B392567C731CC0E0FA5B02F0FD4C40C05D85949F741CC05876FA415DFE4C40009CC1DF2F561CC010E2E7BF07014D40C0620CACE3381CC06007793D98024D4080B6F1272A3B1CC058888043A8044D4000D1217024601CC008E2E7BF07094D4000EE79FEB4811CC010D3A23EC90F4D4000DCF3FC69831CC0E0CABDC0AC104D40C039B01C21831CC0080F45813E114D400015A930B6601CC028F38FBE49174D4040022846963C1CC0080C0401321C4D40C0620CACE3381CC0F8230C03961C4D4000A0168387291CC09096E7C1DD1D4D404015A930B6201CC0B05FE97C781E4D40802502D53F081CC09048BF7D1D1E4D4000880E8123011CC0385FD042021E4D40C083B9DDCBAD1BC0682B137EA91B4D40C0BE9B6ED9A11BC0D0AF743E3C1B4D40406BB6F2929F1BC02835B401D81A4D40C0BE9B6ED9A11BC0D8B837BF611A4D4040C8409E5DAE1BC088A2EBC20F1A4D4000B4C9E193BE1BC0E08558FD11184D4000F850A2257F1BC0A0AD11C1380E4D40C0620CACE3781BC0B0E33103950D4D4080CDC7B5A1721BC0605260014C0D4D40C01B261AA4701BC0B09509BFD40D4D408022A5D93C7E1BC0B025AB22DC164D40402E71E481381BC00833182312194D404013B70A62001BC000FDF7E0B5174D4040A911FA99FA1AC050EF54C03D194D40007D76C075251BC00097E4805D1D4D40C0583508733B1BC0100F45813E214D40006CB1DB67451BC0E0F4D901D7234D40003AB01C21431BC000BEDBBC71244D4040DF4DB7EC301BC0F8298E03AF264D408081919735B11AC0580DFB3DB12C4D404061DF4E22A21AC0A8ECF483BA2C4D4080CB9A58E09B1AC09087A2409F2C4D40403E05C078961AC0909065C1C42B4D4040AC1A84B93D1AC038E44A3D0B2E4D40C0B392567C331AC08860C77F812E4D4000F4FBFECD6B19C04882FE428F3A4D40804E5E64023E19C0D0B5F63E553D4D4000F4FBFECD2B19C07860C77F813E4D40C0295778971B19C090457EFD10414D4040E048A0C11619C060F833BC59414D40C052B3075A1119C028266F8099414D4040137CD3F40919C000274D83A2414D40C039B01C210319C010C11C3D7E414D40C0AE42CA4FFA18C060465C001A414D408079E2395BF018C0B8E0F08288404D404078EC67B1E418C0F820CB82893F4D4080E49D4319AA18C0B8DA6E826F364D4000643E20D0A918C0B89509BFD4354D4080B06F2711D118C0A8E33103952D4D40010300000001000000A808000080758D96039D10C080397AFCDE9C4A400011548D5E8D10C0301A6B7F679D4A40409544F6418610C0301A6B7F679D4A4000F4FBFECD6B10C0E088997D1E9D4A40C0415F7AFB4310C0B09ECC3FFA9C4A40C0402D060F1310C058FB743C669E4A40C039B01C210310C0803FFCFCF79E4A4000D89942E7D50EC0805A457F68A44A4080D349B6BADC0DC0286893C327A54A4080B81E85EBD10DC0383B3602F1A44A4000D7A3703D8A0DC028232E008DA44A4000EE74E789E70CC0002DCF83BBA34A400080643A74DA0CC08815E0BBCDA34A400053AEF02EB70CC0A8A78FC01FA44A408023D5777EB10BC010E2E7BF07A94A400022A81ABD1A0BC0F8DEA63FFBAB4A4000AAED26F8E60AC060F5F23B4DAC4A4000DF4DB7ECB00AC008BEDBBC71AC4A4000F2CEA10C950AC008BEDBBC71AC4A4080EB51B81E850AC0A859677C5FAC4A408023D5777EB109C008E5284014A64A40005FB2F1600B09C0305C8FC2F5A04A4080C0C8CB9AF808C0507C7C4276A04A40807397C459D108C0B06E2EFEB69F4A4080AA7B6473B508C01051F70148A14A4000B0743E3CAB08C0E073D2FBC6A14A40804C310741A708C030F04E3E3DA24A40005C8FC2F5A808C010D061BEBCA24A4080101D02470209C038266F8099A94A4000FA78E8BB3B09C0F8230C0396AC4A4000301004C85009C0B8E3310395AD4A4080C3EBFA055B09C0B89509BFD4AD4A4000FED2A23E6909C0B8DA6E826FAE4A4000BC783F6E7F09C0A89B8BBFEDAF4A4000746039428609C008301004C8B04A4000505436AC8909C068F833BC59B14A4000BC783F6E7F09C080A2EBC20FB24A4000819197357109C0084BE7C3B3B24A40805B5837DE5D09C0E0AF743E3CB34A4080C610001C9B08C0B83176C24BB44A40804F9143C48D08C098FF024180B44A408049D3A0687E08C08097361C96B44A4080675E0EBB6F08C020DBF97E6AB44A4080E3A3C5196308C0E81B98DC28B44A40806ABA9EE85A08C0587347FFCBB34A408020AE9CBD5308C030B75F3E59B34A408014AC71363D08C068BBED4273B14A40005837DE1D3908C0B0B393C151B04A400086E12362EA07C06040DAFF00AF4A4080D6A3703D8A07C0104E2844C0A74A40801B295B246D07C0100C923EADA64A4000ACE3F8A13207C0809FAA4203A54A4000C2F5285C0F07C0B8BF97C283A44A4000DF162CD5E506C0100C040132A44A4000CB9F6F0B3606C0001B498270A54A4080D6A3703D0A06C0D8F19881CAA64A4080976C3CD80206C088A52C431CA74A400085EB51B89E05C030F6D03E56AC4A4000662FDB4E9B05C010D6E3BED5AC4A4000A5660FB4A205C0D088997D1EAD4A4080675C3810B205C080CC07043AAD4A40000AD7A370BD05C0D088997D1EAD4A4080C972124A1F06C0682B137EA9AB4A408058FE7C5B3006C0604CDE0033AB4A40000F27309D3606C05034D6FECEAA4A4080B6F1272A3B06C0D0B837BF61AA4A40000C040132D406C010E2E7BF07A94A4080CEF9298EE306C058465C001AA94A40806793C327FD06C000C11C3D7EA94A40004B04AA7F1007C010D9243FE2A94A40801C588E90A107C09048BF7D1DAE4A4000CB9F6F0BB607C0A8A44E4013AF4A4000A8C29FE10D08C0B86B26DF6CB54A40800CFE7E311B08C09008FF2268B64A40808FC2F528DC08C05828D2FD9CC64A400080643A74DA08C0B86E2EFEB6C74A408094128255D508C088C9C6832DC84A40805DBC1FB7BF08C0E873D2FBC6C94A40803656629E9508C038232E008DCC4A40000873BB97DB07C00018080264D84A40800B040132D407C0F82F1004C8D84A4000BD6E1118CB07C010E2E7BF07D94A40804F5436AC8907C0B0E67283A1DA4A40809735B1C03707C0D80CE2033BDC4A4080DF4DB7EC3007C028232E008DDC4A408047E17A142E07C0789FAA4203DD4A4080BB41B4563407C0201A6B7F67DD4A4080FA78E8BB3B07C00048A643A7DD4A40002502D53F4807C0B89509BFD4DD4A40009B8F6B436507C0385FD04202DE4A4000207BBDFB8307C030E44A3D0BDE4A4080726A6798BA07C0881B62BCE6DD4A400081919735F107C030327381CBDD4A40006F10AD150D08C000E5284014DE4A40003883BF5F2C08C0002A8E03AFDE4A4080490ED8D54408C060853FC39BDF4A4080402D060F5308C0504F1F813FE04A4000FED2A23E6908C008D9243FE2E14A40802DAC1BEF6E08C04882FE428FE24A4000B16A10E67608C038DEC83CF2E34A4000D026874F7A08C0B89ECC3FFAE44A4000D026874F7A08C0F8E4284014E64A4000DAC69FA86C08C028DEC83CF2F34A40800D315EF36A08C0805A457F68F44A4080F3C473B66008C0505260014CF54A40807397C4595108C0881B62BCE6F54A4000333333333308C010C45DBD8AF64A4000295C8FC27507C0908AE3C0ABF94A40007C0A80F12C07C05837177FDBFF4A4080AF743E3CAB06C0B8984A3FE10A4B4000D7A3703D8A06C0B053E57B46124B4080101D02478206C0A0BF97C2831C4B4080425A63D06907C0D87954FCDF134B4080583508737B07C0F899417C60134B40809735B1C03709C0101E8A027D0A4B40009735B1C0B709C0E00CE2033B0C4B408020B24813CF09C08887A2409F0C4B4000272F3201DF09C080CC07043A0D4B40805FB2F1600B0BC028F38FBE491F4B4000D21C59F9450BC050793BC269234B408001F6D1A94B0BC060F5F23B4D244B400088450C3B4C0BC0805182FE42254B4080C0C8CB9A780BC038232E008D2C4B4080726A6798BA0BC0587C7C4276304B4000C61858C7F10BC0D0C77C40A0334B4080ABE3F8A1320CC000C45DBD8A364B40005D85949F740CC030F911BF62394B4000EE74E789E70CC0F8C35DBD8A3E4B40804F5436AC090DC0382F3201BF404B40009EE925C6120DC0D0C1FA3F87414B40808E8B6A11110DC0283E7782FD414B4000B3976DA78D0CC030F04E3E3D524B40002EAC1BEF6E0BC00818080264684B400061DF4E22220BC090C9C6832D704B40002A89EC830C0BC070ABAE4335714B4000D89942E7550AC0A89B8BBFED774B4000BD6E11184B0AC088C9C6832D784B40005C8FC2F5280AC05001F73C7F784B4080AF743E3CAB09C0D0C1FA3F87794B40803BA6EECA8E09C030266F8099794B40801F7BBDFB8309C0B05CA8FC6B794B408014AE47E17A09C050465C001A794B400038BA4A777709C0886649809A784B4000EA245B5D6E09C01018080264784B408045B41D531709C0686D37C137774B40800BCD751A0909C0686D37C137774B4000C87C40A0D308C0F820CB8289774B4080CA9F6F0B3608C008E2E7BF07794B4000333333333308C0D0C1FA3F87794B4080CFEFFB372F08C0D00CE2033B7C4B40005EBC1FB73F08C008D6E3BED57C4B4000508BC1C35408C0605260014C7D4B4000F7C951806808C0403BC43F6C7D4B4000986C3CD88208C008D6E3BED57C4B40006F10AD158D08C0600DFB3DB17C4B4080C422861D2609C0B8622AFD847B4B408077BAF3C43309C0B8622AFD847B4B400003232F6BE20AC028F6D03E567C4B4000986C3CD8020BC0D0BEB9BF7A7C4B40800DFAD2DB1F0BC0600DFB3DB17C4B4080067DE9ED8F0BC078AEEFC3417E4B408015DBA4A2910CC0D876137CD37E4B4080B4C4CA68A40CC0B859677C5F7C4B4000C422861DA60CC09015E0BBCD7B4B40801E4E603AED0CC0C800DE0209704B400083BEF4F6070DC0B8B393C151704B4000986C3CD8820DC0F02F1004C8704B400016DBA4A2910DC0F02F1004C8704B4080BB783F6E7F0EC060888043A86C4B4000E5D4CE30F50EC0B8A44E4013674B4000D9D0CDFEA00FC038F04E3E3D624B40801E85EB51B80FC0483D997FF4614B4000D89942E7D50FC0483D997FF4614B40C0BE9B6ED96110C0B053E57B46624B4000BD6E11188B10C0804B00FE29634B404078EC67B16411C030327381CB6D4B4000FED2A23E6911C08048BF7D1D6E4B4040880E81238111C0A8E0F08288704B40C0D11C59F98511C0000F45813E714B40807B0F971C8711C0E0EE5701BE714B40C085E63A8D8411C088992842EA724B4000282A1BD68411C050793BC269734B40C015A4198B8611C0D0F4D901D7734B4000D7A3703D8A11C078A86DC328744B4040FCA5457D9211C0D80CE2033B744B40C0E7F7FD9B9711C088423D7D04744B408023D5777EB111C010E2E7BF07714B404077BAF3C4B311C000CADFBDA3704B40C016D68D77B711C0600ABABDA46F4B40C07492AD2EB711C000C45DBD8A6E4B40006DE34F54B611C08048BF7D1D6E4B4000F94B8BFAA411C0588BC1C3B4694B408079E2395B7011C0084BE7C3B3624B40C02407EC6A6211C0E082177D055B4B40001D588E906111C078812040865A4B40C0B4C4CA686411C000C11C3D7E594B40003883BF5F6C11C0D88558FD11584B40800778D2C27511C0B0A44E4013574B4040E6CAA0DA8011C06028D2FD9C564B40802A89EC838C11C0B05FE97C78564B4080CB9A58E09B11C03029B000A6564B404060E4654DFC11C0905D86FF74594B40409544F6410612C0503D997FF4594B4080AE42CA4F3A12C060FB743C665E4B408060E4654D3C12C0D0F19881CA5E4B40400AD7A3703D12C000D3A23EC95F4B4040F850A2253F12C0784E417E36604B4000F94B8BFA6412C0D87954FCDF634B400005508C2CB912C04876FA415D664B40406DE34F54F612C0A8AAD0402C694B40C079E2395B3013C038ED0DBE306D4B40C0C0C8CB9A3813C0A89509BFD46D4B40C0ED79FEB44113C0F81186014B6E4B400011548D5E4D13C03029B000A66E4B4000BA4BE2AC6813C0D009A1832E6F4B40000455A3579313C0080341800C6D4B4040C8409E5DAE13C050FEB5BC726B4B40000F27309DB613C03035B401D86A4B40804E5E6402BE13C0386BD443346A4B40002C7FBE2DD813C0808D2441B8664B40C0332E1C08D913C08848BF7D1D664B40C0A3703D0AD713C0B0E3310395654B40C01D537765C713C038F04E3E3D624B40C000FBE8D4A513C0F82CCF83BB5B4B40C077B5DC999913C0E0EE5701BE594B4080A8C0C9369013C088ABAE4335594B4000D7A3703D8A13C038E109BDFE584B4000EE79FEB48113C0607C7C4276584B4080B6F1272A7B13C0A06E2EFEB6574B400005508C2C7913C0885704FF5B574B40403883BF5F6C13C08893A641D1504B40C0CFEFFB376F13C038172AFF5A504B404021AD31E87413C0D0B2B5BE48504B40C01B261AA4B013C0303E7782FD514B40C0F2C98AE1BA13C0101E8A027D524B40C07D37DDB2C313C0386211C30E534B4040BD6E1118CB13C0C8C77C40A0534B40C05C8AABCACE13C060431B800D544B40C0E7F7FD9BD713C0E0AC33BE2F564B40C07F643A74DA13C0B0A44E4013574B40C021A81ABDDA13C00021CB8289574B40C091EA3BBFD813C09021E4BCFF574B408052B3075AD113C0602E54FEB5584B4000B3976DA7CD13C008274D83A2594B40C069C020E9D313C0B0BF97C2835C4B40C0A3703D0AD713C088397AFCDE5C4B4040EB51B81E0514C0608BC1C3B4614B40801281EA1F2414C0B0A78FC01F644B40802A89EC834C14C00009C38025674B40803AAB05F66814C0A8AAD0402C694B404019FED30D7414C0D8066003226A4B40C0F2C98AE17A14C05834D6FECE6A4B40407B0F971C8714C0100C0401326C4B404016DBA4A29114C0D0CDFE40B96D4B40C047E17A14AE14C088A2EBC20F724B40805D85949FB414C0A8B0524145734B4000B9196EC0B714C0D80CE2033B744B4080A46B26DFBC14C0D07FD6FCF8754B400041649126BE14C0C08905BEA2774B40404E5E6402BE14C0D800DE0209784B40400F27309DB614C0D8C43BC0937E4B40802B84D558B214C0C88558FD11804B4080A23EC91DA614C0D0A9F23D23814B4080CB9A58E09B14C008C11C3D7E814B40C051B81E856B14C0386211C30E834B400017D68D773714C0D87FD6FCF8854B40406DE34F543614C0D0C43BC093864B404055DB4DF00D14C08818213CDA904B408001F6D1A90B14C05873B9C150914B4000F850A225FF13C0D88BDAFD2A924B4040BC732843E513C0E0F4D901D7934B40000AD7A370BD13C0B077F17EDC964B400005508C2C7913C050431B800D9C4B40406DE34F547613C010BEDBBC719C4B40C05D85949F7413C0383B3602F19C4B40801281EA1F6413C0081E8A027DA24B4000662FDB4E5B13C000D3A23EC9A74B40C07F643A745A13C0D8F71A82E3A84B4000E8F7FD9B5713C0D00F238447A94B40C0A143E0480013C0B059677C5FB44B408002284696FC12C0A8ECF483BAB44B4000A8C5E061EA12C038327381CBB54B400022A81ABDDA12C058FB743C66B64B4000F3C98AE1BA12C00821CB8289B74B40007365506DA012C02838F581E4B74B40C07F643A749A12C0D000DE0209B84B40800E2C47C89012C06001F73C7FB84B40006F10AD158D12C08093A641D1B84B40805D85949F7412C080AEEFC341BE4B404019FED30D7412C0805704FF5BBF4B4080A46B26DF7C12C0A8C2D84290C14B4000560DC2DC7E12C0203E7782FDC14B40C00AD28C45A312C0B89B8BBFEDC74B4080F0A1444BBE12C05870784144CC4B4040880E8123C112C0580DFB3DB1CC4B4080BF9657AEC712C0B8B6D4415ECD4B40008196AE60CB12C000CD203EB0CD4B4040508BC1C3D412C0B8AD11C138CE4B4040EC4CA1F3EA12C0B8A44E4013CF4B4040A69883A01313C0507C7C4276D04B4040880E81234113C0B8E67283A1D24B40C023D5777E7113C030E44A3D0BD64B4040E6CAA0DA8013C038F38FBE49D74B40C0B91457959D13C0E0B2B5BE48D84B40C0633E20D0A913C088ABAE4335D94B4040EC4CA1F3AA13C0306BD44334DA4B40409544F6418613C0C05626FC52F74B40C0272A1BD68413C0D0D38041D2F74B4040880E81238113C080C9C6832DF84B40404A0856D54B13C04053211E89F94B4000A11001873013C080DF313CF6F94B4040FED0CC932B13C0A877D503E6F94B40402827DA552813C0B0D1393FC5F94B4000B7EC10FF2013C0302C634337F94B4000EE79FEB40113C048465C001AF94B40807F643A74DA12C058853FC39BF74B40C0402D060FD312C02820ED7F80F74B404083BEF4F64712C0801B62BCE6F54B4000E8F7FD9B1712C0B0E3310395F54B40801E4E603AED11C0801B62BCE6F54B404021AD31E8F411C008C45DBD8AF64B4040880E81230112C000DC65BFEEF64B40403201BF468212C000E2E7BF07F94B40803505323B1B13C0E848D92269FD4B40006B2BF6973D13C0F89CD843FBFC4B4040137B681F6B13C0607FF62345FE4B4040A4164A267713C0A844847F11044C40408C800A477013C010B2101D02094C40007E3848886213C0C813B35E0C0B4C40C0135D177E5013C0F80E0C207C0E4C4040E36C3A027813C0C810E4A0840D4C40C0300BED9C8613C0A8F57EA31D094C40005C902DCB9713C090D8EE1EA0FD4B4000E884D041A713C0B813B35E0CFB4B4080747973B8B613C0F03FDD4081F74B40C0332E1C08D913C000CADFBDA3F04B40C0A7C5E061EA13C0A077F17EDCEE4B40001C261AA4F013C0002A8E03AFEE4B40C07492AD2EF713C03029B000A6EE4B40C02A89EC830C14C0903FFCFCF7EE4B40C07F643A741A14C0B05626FC52EF4B40C01B261AA47014C008C79E3D97F34B40C023D5777EB114C000DC65BFEEF64B400013286211D314C00052465C00F64B4000BC5983F7E514C0288D0A9C6CF34B40C0345F251FEB14C058B9347EE1EF4B4040F2CEA10CD514C0D8A6B1BD16EC4B40C0643909A5CF14C0004BE7C3B3EA4B40C052B3075AD114C0D806600322EA4B4040F2CEA10CD514C0E073D2FBC6E94B40C0CB9A58E0DB14C0588BC1C3B4E94B400052B81E852B15C0E0BEB9BF7AEC4B40000F27309D3615C088397AFCDEEC4B4040726A67983A15C0505260014CED4B40C021A81ABD5A15C02035B401D8F24B40C00F2219725C15C03014E97E4EF34B4080D349B6BA5C15C0C8F4D901D7F34B4080758D96035D15C008C45DBD8AF64B40006893C3273D15C0A8B393C151004C4000F85278D03C15C0385CE49EAE004C4040F0A31AF63B15C0305C8FC2F5004C408060E124CD1F15C0F0EB6B5D6A044C40407F66101F1815C0A0C6681D55054C40C0643909A5CF14C06040DAFF000F4C40008196AE60CB14C0805704FF5B0F4C4040137CD3F44914C0B89B8BBFED174C40C05EB7088CE513C07896E7C1DD1D4C4000D8D64FFFC913C01000000000204C408081919735B113C0803CBB7CEB214C4000963FDF16AC13C0104BE7C3B3224C40C08B683BA6AE13C0F8E769C020234C40400778D2C2B513C0306211C30E234C4040B7EC10FF2014C06031957EC21D4C40C0BFCDE2C5D214C0A0C2D84290114C40C05D85949FF414C0686D37C1370F4C40402DB1321A0915C010CD203EB00D4C40409869FB572615C0C810AB3FC20A4C40C07F65A5493915C02899D53BDC084C40805EB873614415C0005471E316074C4080B3CC22145B15C028F9F5436C044C4000DAC69FA86C15C0388C497F2F034C4080A8C0C9369015C00000000000004C408024D060539715C0B89B8BBFEDFF4B40007D3CF4DD9D15C0889C69C2F6FF4B408023D5777EB115C0009D82FC6C004C40007592AD2EB715C008CADFBDA3004C40C00CFFE906BA15C028E109BDFE004C40C09DEE3CF1AC15C058431B800DF44B4080EB51B81E8515C0D800DE0209E04B40007D3CF4DD9D15C078AEEFC341DE4B40807B0F971CC715C0A86BED7DAADA4B4000D7A3703DCA15C0B053E57B46DA4B40C0A8C0C936D015C0A89B8BBFEDD74B40C069C020E9D315C060853FC39BD74B40C0D0217024E015C0B8E3310395D54B40408940F50FF215C09054C37E4FD24B404059F78F853816C090C360FE0AB54B40801281EA1F2416C0D8FD9C82FCB24B40C01C588E902116C0A0E67283A1B24B40C0A8C0C9361016C0588E0244C1AE4B4000FFCD8B130F16C0081286014BAE4B4000E8F7FD9B1716C0D0031F8315AD4B40801281EA1F2416C000C79E3D97AB4B40C085E63A8D4416C0A8E0F08288A84B400061DF4E226216C00809C38025A74B4080B392567CF316C0201A6B7F67A54B4040D4449F8F0217C0B0B6D4415EA54B4080A8C0C9361017C0B8E3310395A54B40008FC2F5281C17C0D07FD6FCF8A54B408078EC67B12417C0C8C43BC093A64B408008AA46AF2617C03841B8020AA74B40803AAB05F62817C09021E4BCFFA74B4040C8409E5D2E17C08848BF7D1DAE4B40C02DAC1BEF2E17C010D3A23EC9AF4B408047E17A142E17C0A85CA8FC6BB14B4040DAC69FA82C17C0603D997FF4B14B408008AA46AF2617C000D061BEBCB24B4040CFF412630917C0001B498270B54B40803AAB05F6E816C0606D37C137B74B40802407EC6AE216C02838F581E4B74B4000D1217024E016C030172AFF5AB84B40C0B9145795DD16C0905D86FF74B94B4040C972124ADF16C0783CBB7CEBC14B4080BA46CB81CE16C01015C78157CB4B40801E4E603AAD16C0500DFB3DB1D44B4000C8409E5D6E16C048465C001AE14B4040CDC7B5A17216C0E00F238447E14B40C0A3703D0A9716C078423D7D04E44B40C079E2395BB016C0A877F17EDCE64B40802B84D558B216C028F38FBE49E74B40C0CDC5DFF6B416C01854FF2092F14B40406534F279B516C0B829029CDEF14B408045B58828B616C050D7F7E120F34B4040E7FA3E1CB416C0F0ABAB02B5F44B40002B86AB03B016C0386893C327F54B40402827DA55A816C0488CD7BCAAF54B40800AD6389B9E16C03059DC7F64F64B4080698995D18816C0602B137EA9FB4B4000A69883A05316C008C11C3D7E014C40806CE8667F5016C010D9243FE2014C40402502D53F4816C0B8716F7EC3044C404055DB4DF04D16C088397AFCDE044C4040508BC1C35416C028D505BCCC044C40004F594DD76316C0A8A78FC01F044C40404487C0918016C0B8E67283A1024C408085E7A562A316C06079C9FFE4FD4B40807361A417A516C0E8FAB0DEA8FD4B40C0953FDF16AC16C078DF6A9DB8FC4B40003D0CAD4EAE16C0B0A19BFD81FC4B40C0D79C8367B216C0C0FE243E77FC4B4080D5743DD1B516C060B532E197FC4B40400C01C0B1B716C028F30181CEFC4B40C0A36FD234B816C05846CEC29EFE4B40005B5D4E09B816C038DB87BCE5FE4B4040E7FA3E1CB416C090CC9541B5FF4B404016DBA4A29116C0587FBDC282054C40C0BF9657AE8716C03029B000A6064C4040B29C84D26716C0D873D2FBC6094C4040E6CAA0DA4016C08060C77F810E4C4000583A1F9E1516C008D6E3BED5144C40400455A3571316C0A0B6D4415E154C40C0C41D6FF20B16C0386E15C440174C404067614F3B0C16C010D3A23EC9174C4080B06F27111116C08021E4BCFF174C404024D060531716C0E0D38041D2174C4040B7EC10FF2016C0905704FF5B174C408060E4654D3C16C008CD203EB0154C404001F6D1A94B16C0D0BEB9BF7A144C40C01281EA1F6416C000BEDBBC71144C40C0688EACFC6216C030172AFF5A204C4040A5660FB46216C0B85CA8FC6B214C40C08096AE604B16C0A0C2D84290294C4080D9CBB6D34616C0001E8A027D2A4C40C021A81ABD1A16C0E0D38041D22F4C40C0DD205A2B1A16C0D0F71A82E3304C40C0332E1C081916C038F911BF62314C4000583A1F9E1516C040D8463CD9314C40803CD862B7BF15C088936DE00E364C408094111780B615C0D84961DEE3364C40C08B683BA6AE15C0B019E0826C374C40802B836A835315C03065A71FD4374C4000DAC70A7E4B15C0180055DCB8374C4040F0A31AF63B15C0F8AEB321FF364C400017D68D77F714C05037177FDB374C408023D5777EF114C0104E2844C0374C400061DF4E22E214C008D3A23EC9374C4000E8F7FD9BD714C090C9C6832D384C4080BA46CB81CE14C0682E54FEB5384C4080D11C59F9C514C030F911BF62394C40401B2B31CF8A14C000E52840143E4C40C0583508737B14C0E0BB783F6E3F4C4040C8409E5D6E14C030E109BDFE404C40409544F6414614C0B85626FC52474C40C0415F7AFB4314C0004E2844C0474C40807B0F971C4714C0D000DE0209484C400055DB4DF04D14C0889C69C2F6474C4000C0CDE2C55214C0500ABABDA4474C40C077B5DC995914C0883FFCFCF7464C404061DF4E226214C0D8CDFE40B9454C4000A8C5E0616A14C0809065C1C4434C40006DE34F547614C000274D83A2414C40007E37DDB2C314C000E869C0203B4C40C0067DE9EDCF14C0D0066003223A4C40C029577897DB14C038D8463CD9394C4000A8C5E061EA14C0508BC1C3B4394C4040DF4DB7ECF014C0E0EE5701BE394C400005508C2C7915C0503DD2E0B63C4C4000FA7B293C9815C0E8E2A8DC443D4C4000151BF33A8215C0A8AD9FFEB3424C4080D05E7D3C7415C0F0783E03EA414C40406B2920ED5F15C008D0285DFA414C4080CE33F6255B15C030622D3E05424C40C0F4673F525415C000A0FCDD3B424C40003AB01C210315C0B0DA6E826F464C4040F850A225FF14C0588E0244C1464C408060E4654DFC14C00009C38025474C40C058350873FB14C0B06E2EFEB6474C40003AB01C210315C0B06E2EFEB6474C404085EAE6E23F15C07027D87F9D474C40003AB01C214315C0286B9BE271474C40C083BC1E4C4A15C0C84961DEE3464C40C0D24F38BB5515C08863416150464C4080A46C91B45B15C00842B28009464C4080C64ACCB36215C05804E3E0D2454C4000B29C84D26715C05804E3E0D2454C40804A0515556F15C00842B28009464C40C002249A408115C0489BC76130474C40C0F75278D07C15C000D0285DFA474C40402502D53F8815C0B8E67283A14A4C40403201BF464215C060431B800D544C40405B5D4E09F814C0804B00FE295B4C40805D85949FB414C0E00F238447614C40402DB1321A8914C0001B498270654C40C0D11C59F98514C0A89509BFD4654C4040022846967C14C0D000DE0209684C40C0F2C98AE17A14C0B0E0F08288684C40401F80D4269E14C0001286014B664C40402A52616CC114C0089A417C60634C4080355B79C9EF14C00009C380255F4C408019FED30D7415C0B8ECF483BA544C40402A52616C4116C028ED0DBE30454C4040272F32015F16C038E78BBD17434C4080F62345646816C0001E8A027D424C4040C3F01131B516C0686D37C1373F4C40003201BF46C216C0B0AAD0402C414C40C0D6A3703DCA16C0D8EE5701BE414C4040A01683872917C080397AFCDE444C40C0BA46CB814E17C0301A6B7F67454C4000CFF412638917C0D876137CD3464C4040F2CEA10C9517C030F38FBE49474C4000630CACE3B817C0E07C957CEC484C40006CB1DB67C517C0B874B0FECF494C40001C5DA5BBFB17C088AEEFC3414E4C40C01D5377650718C028F38FBE494F4C408001F6D1A90B18C0E08558FD11504C40008196AE600B18C0A0656B7D91504C4080C745B5880818C038266F8099514C4000E6CAA0DA0018C09054C37E4F524C40C0C0C8CB9AF817C0B8984A3FE1524C400033333333F317C000E869C020534C40C0A23EC91DE617C0009A417C60534C40803AAC70CB8717C060431B800D544C40C0C41D6FF2CB16C010BB9A3C65574C40002C7FBE2D9816C0A8A44E4013574C4000333333337316C038F38FBE49574C4080C87729753916C0084E2844C0574C40C047E17A142E16C0286552431B584C4080D79E59123016C0B8656B7D91584C40C05D85949F3416C08818213CDA584C4000C3F01131F516C038E78BBD175B4C40802A89EC830C17C0F8E769C0205B4C4040EA1F44321417C0E0FD9C82FC5A4C40801F80D4261E17C05807793D985A4C4000F4FBFECD2B17C0E873D2FBC6594C4000D0F0660D4E17C0184240BE84584C40409A95ED435E17C05810AE8042574C4000954561176517C090D2DEE00B574C40401E4E603AAD17C080AEEFC341564C40C0415F7AFBC318C06040DAFF00574C40009CC1DF2FD618C0888461C092574C4080A23EC91DE618C0D8F71A82E3584C40403883BF5FEC18C030266F8099594C40001C261AA4F018C080992842EA5A4C4040DF4DB7ECF018C0B8622AFD845B4C40001C261AA4F018C058431B800D5C4C4000C8409E5DEE18C0D0BEB9BF7A5C4C400016A4198BC618C0B06E2EFEB65F4C4080976C3CD8C218C00000000000604C4080C2F5285C8F18C028E109BDFE604C40801F80D426DE17C0E87954FCDF634C40406CE8667FD017C050431B800D644C40C08096AE60CB17C0D8F4D901D7634C40C0976C3CD8C217C0B0B0524145634C4080630795B89E17C08018213CDA604C40C01E85EB517817C0B8A44E40135F4C4000643E20D06917C0883FFCFCF75E4C404061DF4E226217C058853FC39B5F4C40C0C51858C73117C0809FAA4203654C4000630CACE33817C000CD203EB0654C4080295778975B17C0A877F17EDC664C4080A23EC91D6617C000BB9A3C65674C40809DEE3CF16C17C0E08558FD11684C4000D0EFFB376F17C0F89C82FC6C684C40C07133DC806F17C010E2E7BF07694C40808B683BA66E17C0A8C2D84290694C4040EC4CA1F36A17C0583D997FF4694C4080666666666617C0C88BDAFD2A6A4C40005708ABB12417C0F09C6681766B4C4000DCF3FC690317C0D0F4D901D76B4C4000F3C98AE1FA16C0889065C1C46B4C40808B683BA6EE16C050793BC2696B4C4040C972124ADF16C060FEB5BC726B4C40C0B94BE2ACA816C0002A8E03AF6E4C408078EC67B1A416C0506D37C1376F4C4040AAED26F8A616C0888461C0926F4C40001C261AA4B016C038EACC3D24704C40C05D85949FF416C0D0B837BF61724C408002284696FC16C0B8B915C26A724C4080963AC8EB1117C028F04E3E3D724C40C02FD978B04517C050F833BC59714C4000CB9F6F0B7617C0B8656B7D91704C40007E37DDB28317C0607C7C4276704C404067614F3B8C17C0B8656B7D91704C40408E90813CAB17C0B05CA8FC6B714C4080D79E5912B017C0908AE3C0AB714C404016DBA4A25117C0306552431B804C40807138F3AB4917C0F82F1004C8804C4040C87729753917C0905D86FF74814C40401E4E603A2D17C0E0EE5701BE814C40C02DAD86C40D17C0F0E192E34E814C4040880E81230117C0F8DE180280814C4080FCA4DAA7F316C02836035C90814C40006F0D6C95F016C048CB811E6A814C40403881E9B4EE16C080BD892139814C408054DE8E70EA16C0705E807D74804C40007B12D89CE316C0B026FA7C947F4C4080137CD3F4C916C06028D2FD9C7E4C40C0355B79C9AF16C0281A6B7F677D4C4000F94B8BFAA416C0383B3602F17C4C4000CEC29E769816C0B8BF97C2837C4C4000C0CDE2C59216C0B059677C5F7C4C4000282A1BD68416C030232E008D7C4C4040B06F27115116C0001B4982707D4C40007E37DDB24316C0D8CDFE40B97D4C4040AAED26F82616C03829B000A67E4C4040CEC29E761816C0606D37C1377F4C4040508BC1C31416C00821CB82897F4C4040E048A0C11616C0889C69C2F67F4C4080C1C3B46F1E16C0B09B8BBFED7F4C40001C261AA43016C000BB9A3C657F4C404049D74CBE3916C0A877F17EDC7E4C4080D9CBB6D34616C0082A8E03AF7E4C4000B16A10E67616C038E44A3D0B7E4C400016A4198B8616C010E52840147E4C4080B91457959D16C0803FFCFCF77E4C40402C7FBE2D1817C0A09509BFD4854C4000698EACFC2217C0089700FC53864C40C0A23EC91D2617C03029B000A6864C404054E0641B2817C080A52C431C874C40401059A4892717C060853FC39B874C408078EC67B12417C0602E54FEB5884C404039B5334C1D17C0203E7782FD894C40403E05C0781617C0A86BED7DAA8A4C40C0A23EC91DE616C0A85FE97C788E4C40C015A6EF35C416C0006DC83F338E4C40C058349D9D9C16C07015C440D78E4C40800C0055DC9816C058B83A00E28E4C40009A94826E7F16C0B0AA97DF698E4C404021AB5B3D7716C0C00AF0DDE68D4C40005D876A4A7216C0C810397D3D8D4C4040C2F5285C4F16C0D8BEB9BF7A8C4C4080A46B26DF3C16C0E0F4D901D78B4C4000643E20D02916C00015C781578B4C400061DF4E222216C0E8AF743E3C8B4C4080FCA5457D1216C0B8B05241458B4C4000D671FC509915C0600438BD8B8D4C40807F643A749A15C028E44A3D0B8E4C40C0B91457959D15C060FB743C668E4C40001D588E90A115C02829B000A68E4C40C02DAC1BEFAE15C0A0A44E40138F4C40009544F641C615C00809C380258F4C4040EA1F4432D415C0F8DB65BFEE8E4C40801E4E603AED15C05076FA415D8E4C40C0B392567C3316C028DB87BCE58E4C400084B872F68E16C0808DEBDFF5934C40C0573A1F9E9516C0B84C4D8237944C4040DD2230D69716C0489B8E006E944C40807C40A0339916C0805AF0A2AF944C4080C3EDD0B09816C0100341800C954C40C0573A1F9E9516C008E52840149E4C40405A61FA5E7316C058BBB4E1B09E4C4040067E54C36E16C0E86305BF0D9F4C4040C9737D1F3E16C0E8F76F5E9CA04C40805A61FA5E3316C018B7D100DEA04C40005D8940F52F16C008301004C8A04C4000643E20D02916C0109337C0CC9F4C408095438B6C2716C0E003ADC0909F4C4040726A6798FA15C0D0C43BC0939E4C4040DAC69FA8EC15C0B068ACFD9D9D4C40404F594DD7E315C0206893C3279D4C40C02A89EC83CC15C038F6D03E569C4C40000F27309DB615C0B87A32FFE89B4C4080D79E5912B015C0A8A78FC01F9C4C40800DFAD2DB9F15C0B0B6D4415E9D4C40007D3CF4DD9D15C05831957EC29D4C4000F4FA93F80C16C088C0914083A34C40C0378600E04816C048C8409E5DA44C40007EA99F376516C0A8E4805D4DAA4C40C0A08499B64F16C0B81C210379AA4C400074CFBA464B16C088B454DE8EAA4C4040F2CEA10C1516C0D87FD6FCF8AD4C40801E85EB51F815C0A8BC564277AF4C40803BDD79E2D915C0D8C1FA3F87B14C40C0F97DFFE6D515C0883CBB7CEBB14C4080643909A5CF15C0004BE7C3B3B24C40C08096AE60CB15C000D6E3BED5B44C4040BD6E1118CB15C0101B498270B54C40C06E10AD15CD15C030327381CBB54C4000508BC1C3D415C0D07FD6FCF8B54C40C0D571FC50D915C06031957EC2B54C40C0DBF3FC690316C00815C78157B34C40008E93C2BC8716C0D0BB783F6EAF4C4040880E81230117C030DEC83CF2AB4C40006AC020E91317C0B8622AFD84AB4C4040D349B6BA1C17C0886308008EAB4C40401059A4892717C078423D7D04AC4C408085E63A8D4417C0B8AD11C138AE4C4080D9CBB6D34617C0D8C43BC093AE4C40001C261AA47017C0508BC1C3B4B94C4000B9196EC07717C0D87954FCDFBB4C404060E4654D7C17C0D8B5F63E55BD4C4080583508737B17C000DC65BFEEBE4C40C00CFFE9067A17C02820ED7F80BF4C40001059A4896717C08048BF7D1DC64C4080A23EC91D6617C06028D2FD9CC64C4080CB9A58E05B17C05073B9C150C94C40008196AE604B17C0A0A10DC006CA4C4080EB51B81E4517C0386BD44334CA4C4040F0A1444B3E17C0D08BDAFD2ACA4C40C0295778971B17C0305C8FC2F5C84C4000A243E0480017C0808D2441B8C64C40005EBC1FB7FF16C01048A643A7C54C4000C972124A9F16C080ABAE4335C14C4080DD205A2B9A16C000E2E7BF07C14C40405A6265349216C048465C001AC14C40C0F2C98AE17A16C0804B00FE29C34C40406BB6F2921F16C0D0C77C40A0C34C40C0C41D6FF20B16C050431B800DC44C40C0698995D10816C0F8BDDBBC71C44C40805A6265341216C010E5284014C64C40009CC1DF2F1616C0109700FC53C64C40801281EA1F2416C0F0298E03AFC64C4080402D060F9316C0F0298E03AFC64C400039B5334C9D16C0E8AC33BE2FC64C40C0D0217024A016C08096E7C1DDC54C408066666666A616C0D8CDFE40B9C54C40801E4E603AAD16C08096E7C1DDC54C40802B84D558B216C058499D8026C64C40802502D53FC816C050853FC39BC74C4000AC1A84B93D17C008274D83A2D14C4040560DC2DC3E17C0F805820019D24C4080EB51B81E4517C0786649809AE84C4040C2BE9D444417C0B8AAD0402CE94C4000B16A10E63617C0386893C327ED4C40402B84D5583217C0101B498270ED4C40C052B3075A1117C0002A8E03AFEE4C4080EB51B81E0517C03041B8020AEF4C40401F80D426DE16C038F38FBE49EF4C40C022DC6454C916C030ED0DBE30ED4C40802FDB4E5BC316C070DCF0BBE9EC4C40801C5BCF10BE16C0A874E95F92EC4C40C02C7C7DADBB16C070E55E6056EC4C404046B1DCD2BA16C0B0D4415E0FEC4C4080F6234564A816C0E0B5F63E55E54C40C05EB7088CA516C08887A2409FE44C40406CE8667F9016C0386211C30EE34C40008718AF797516C0883CBB7CEBE14C400084B9DDCB6D16C0583D997FF4E14C40803AAB05F66816C0386BD44334E24C4040EA1F44325416C000CADFBDA3E84C40C0BFCDE2C55216C0E0A9F23D23E94C4040FCA5457D5216C028F04E3E3DEA4C4040508BC1C35416C0A86BED7DAAEA4C40004F594DD76316C010DFA63FFBEB4C404054E0641B6816C060F5F23B4DEC4C40404487C0918016C0D8031F8315ED4C40C0666325E68916C010871744A4EE4C40805D86FF749316C028450F7C0CF04C40003E0796239416C0909675FF58F04C4040EFAA07CC9316C070637AC212F14C4080E7FBA9F19216C0988A389D64F14C40C069C020E99316C0804B00FE29F34C40401B2B31CF8A16C028F6D03E56F44C40003AB01C218316C0889FAA4203F54C4080C51858C77116C0B8AD11C138F64C4000AE47E17AD415C0D0FA5B02F0ED4C4040A46B26DFBC15C0E0FD9C82FCF24C4000630CACE3B815C02814E97E4EF34C400033333333B315C0B8622AFD84F34C40C021A81ABD5A15C08096E7C1DDF54C4080630795B8DE14C02814E97E4EF34C4000D4449F8F8214C038F38FBE49EF4C4080CDC7B5A17214C0385FD04202EE4C4040FED2A23E6914C0583A58FFE7EC4C408078EC67B16414C078A52C431CEF4C400090BDDEFDC114C038F911BF62F94C4040137CD3F4C914C0303E7782FDF94C40C0067DE9EDCF14C0386BD44334FA4C40C06E10AD150D15C068F5F23B4DFC4C4000E8F7FD9B9715C0F8DEA63FFB034D4000EC4CA1F3AA15C008A0C37C79054D40401B2B31CFCA15C0B0656B7D91084D4080B06F2711D115C05873B9C150094D40405A626534D215C0E873D2FBC6094D40400E2C47C8D015C08054C37E4F0A4D4000C51D6FF2CB15C0E0AF743E3C0B4D40C02FD978B0C515C080423D7D040C4D4000880E8123C115C028F6D03E560C4D400021AD31E8B415C07887A2409F0C4D40401E4E603AAD15C0A8BF97C2830C4D400061DF4E22A215C050431B800D0C4D4000CFF412638915C0084BE7C3B30A4D4080A46B26DF7C15C0D8EE5701BE094D40407B0F971C4715C0504F1F813F084D4040F0A1444B3E15C088C9C6832D084D40C01B261AA43015C0A0E0F08288084D408054E0641B2815C030E109BDFE084D40404F594DD72315C028F911BF62094D40C0D02170242015C0D8EE5701BE094D4040C1C3B46F1E15C0286BD443340A4D4000CEC29E761815C05840DAFF000F4D4000342E1C081915C0D082177D05134D4000643E20D02915C0386211C30E134D40C01B261AA43015C02014E97E4E134D4000FA7DFFE69515C03841B8020A1F4D4040CEC29E769815C03038F581E41F4D408091EA3BBF9815C0089D82FC6C204D4000583A1F9E9515C0D07C957CEC204D400016DBA4A29115C088ABAE4335214D40C0C41D6FF28B15C0B05CA8FC6B214D40C09CBCC8047C15C0D00F238447214D4040B16A10E67615C078457EFD10214D40806CE8667FD014C0286552431B204D4040CFF412634914C008D9243FE2214D40C010548D5E4D14C0286BD44334224D4040EA1F44325414C0B8B915C26A224D40802A52616C8114C038D505BCCC244D40C0B94BE2ACA814C0F8264D83A2294D40406F0B96EAB214C030D505BCCC2C4D40809DEE3CF1AC14C0788D2441B82E4D40C0D79E59127014C090457EFD10414D40C0272A1BD60414C000D3A23EC94F4D4040F0A1444BFE13C09021E4BCFF4F4D4000E048A0C11613C0785182FE424D4D4040FCA5457D1213C0789FAA42034D4D4080BA46CB81CE12C03020ED7F80474D404021AD31E8B412C008E869C020434D40005D8AABCACE12C0E00F238447414D4040272F3201DF12C030F38FBE493F4D40C08096AE600B13C0E873D2FBC6394D400055DB4DF00D13C088ABAE4335394D40C05C8AABCA0E13C0302F3201BF384D4080D9CBB6D30613C000CADFBDA3384D40007592AD2EF712C028F911BF62394D40C0953FDF16AC12C07860C77F813E4D4000A8C5E0616A12C0D8FD9C82FC424D4000F94B8BFA6412C0D8F4D901D7434D40000BD28C456312C020F6D03E56444D4080B4C4CA686412C0E0FA5B02F0454D4000B29C84D26712C0A877F17EDC464D4080A23EC91D6612C0D0BB783F6E474D40007B14AE476112C0A0B393C151484D400022A81ABD5A12C088457EFD10494D40C0A8C0C9365012C0D8C1FA3F87494D4040D4449F8F4212C0E0EE5701BE494D4040C87729753912C0808AE3C0AB494D4040D9CBB6D30612C0D8CABDC0AC484D40001059A489E711C0E0D38041D2474D40C0DBF3FC69C311C0D0C43BC093464D4040726A6798BA11C0D87FD6FCF8454D40C07492AD2EB711C0E0031F8315454D4080CB9A58E01B11C068F5F23B4D444D4080FCA5457D5210C0B0A44E4013474D4080EA1A2D073A0FC0A8BC564277474D4080F0D8CF62C90EC0B0E9B303AE474D40002502D53F480EC0B0E0F08288484D40000AD7A3703D0EC0202F3201BF484D4000E8F7FD9BD70DC0E07954FCDF4B4D40800E27309DB60DC0386893C3274D4D40003883BF5FAC0DC0201A6B7F674D4D40802502D53F480DC0B05626FC524F4D4080ED7E15E09B0CC060853FC39B4F4D40001E4E603A6D0CC0D07FD6FCF84D4D40806793C327FD0AC050707841444C4D408051B81E85EB0AC0080C0401324C4D400047AAEFFCE20AC0B0BF97C2834C4D40805B5837DEDD0AC0A89ECC3FFA4C4D4080A8C0C936D00AC068FB743C664E4D4000DC2A8881CE0AC0B877F17EDC4E4D40805FE97C78D60AC0E009A1832E4F4D4080230C0396FC0AC0B8B393C151504D4000508BC1C3D40AC038232E008D544D4000FED2A23E6909C0F8E769C020534D4000BB41B4563408C0B0984A3FE1524D4080170802642808C0B0E67283A1524D408094490D6D2008C08854C37E4F524D4000ED7E15E01B08C080457EFD10514D4080C51858C77108C0E08BDAFD2A3A4D4080583508737B08C0100F45813E394D4000F3C473B6E008C07818213CDA304D400049D74CBEF908C028F38FBE492F4D400085EB51B89E09C0D8BB783F6E274D4080AF743E3CAB09C0883FFCFCF7264D408032333333B30AC058FEB5BC72234D4080C77C40A0D30AC058FEB5BC72234D4080F3C473B6E00AC02814E97E4E234D4000425A63D0E90AC0286211C30E234D4080F61E2E390E0BC008D9243FE2214D4080D349B6BA5C0BC0E009A1832E1F4D40804F5436AC890BC0000341800C1D4D40005A626534920BC060431B800D1C4D40807F9BC58BA50BC0D8B837BF611A4D400033333333B30BC038266F8099194D40005C5837DEDD0BC0F8BA9A3C65174D4080012D5DC1160CC0D888997D1E154D4000C972124A1F0CC030D505BCCC144D4080FB6EBA65870CC0B874B0FECF114D408048D74CBE790DC0A8DDAF027C0B4D4080F5285C8FC20EC05082FE428F024D400049D74CBEF90FC0888AE3C0ABF94C40C0C41D6FF20B10C03829B000A6F64C4080F9821612F00FC0A8BF97C283F44C4080A59D9ACBED0FC058FEB5BC72F34C4040C2F5285C0F10C0A8A44E4013EF4C40801E4E603A6D10C0000341800CED4C40C0F2C98AE17A10C0583A58FFE7EC4C4000630CACE3F810C008BB9A3C65EF4C40C0CFEFFB376F11C05807793D98F24C40007592AD2E7711C0E0AF743E3CF34C40003AB01C218311C0602B137EA9F34C400016DBA4A29111C0D87954FCDFF34C40406CE8667F9011C0A8984A3FE1F24C40004A09C1AA6A11C060FB743C66EE4C4000BF9B6ED96111C08896E7C1DDED4C40001C261AA43011C030F6D03E56EC4C404061DF4E222211C058431B800DEC4C4000D671FC509910C008274D83A2E94C4080BD6DA6422C10C0603123BC3DE84C4000FED2A23E690FC0885704FF5BE74C4000BC783F6EFF0EC030172AFF5AE84C400055DB4DF0CD0EC0285C8FC2F5E84C4000FA78E8BBBB0EC0A8C2D84290E94C4080C0914083AD0EC08854C37E4FEA4C4000758D96039D0EC0000C040132EC4C4080067DE9ED8F0EC0B89ECC3FFAEC4C4000AC1A84B97D0EC0B068ACFD9DED4C40000D315EF36A0EC000E5284014EE4C4080DC2A88814E0EC0A8AD11C138EE4C400033333333330EC0801B62BCE6ED4C4000D0EFFB372F0EC0303B3602F1EC4C4080620CACE3380EC010DFA63FFBEB4C4000B8E7F9D3860EC0885704FF5BE74C40003656629E950EC06028D2FD9CE64C4080DAC69FA8EC0EC0D8B837BF61E24C4080B2976DA78D0FC09015E0BBCDDB4C4000BA1457959D0FC0504CDE0033DB4C40805DBC1FB7BF0FC0903CBB7CEBD94C4000FCA5457DD20FC020F911BF62D94C4080FDD2A23EE90FC030E109BDFED84C4040880E81230110C0582E54FEB5D84C4040355EBA490C10C068F833BC59D94C4040DD2406811510C07030D46185D94C4040F2CCCB611710C0E043A67C08DA4C40C045B6F3FD1410C028382EE3A6DA4C40C01801158E1010C0A8B3CC2214DB4C40400E2C47C81010C028F6D03E56DC4C40006AC020E91310C028ED0DBE30DD4C40800DFAD2DB1F10C0A868ACFD9DDD4C404024D060535710C0203B3602F1DC4C40C01281EA1F6410C050888043A8DC4C40C0355B79C92F11C0009700FC53D64C4000A8C5E061AA11C0789FAA4203CD4C4040F0A1444BBE11C020266F8099C94C40C08618AF79B511C0F8E1E7BF07C94C4000BA4BE2ACA811C05073B9C150C94C4000DCF3FC698311C0B8DDAF027CCB4C40800DFAD2DB5F11C030327381CBCD4C40805A6265345211C0586D37C137CF4C40C0FFFFFFFF3F11C00018080264D04C40807138F3AB0911C0E07954FCDFD34C40009A94826EFF10C0905A457F68D44C4040FED2A23EE910C0D088997D1ED54C4080415F7AFBC310C0D0FA5B02F0D54C40C0F1D077B75210C0500A2C8029D54C4080355B79C92F10C0B853E57B46D24C40408940F50F7210C000240C0396CC4C40C0B8196EC0B710C08021E4BCFFC74C40C0893BDEE4D710C09087A2409FC44C4000A8C5E061EA10C0383E7782FDC14C40406DE34F54F610C00800000000C04C40C01B261AA4F010C00809C38025BF4C408008AA46AFE610C05028D2FD9CBE4C4080DD205A2BDA10C0A8AD11C138BE4C4040CFF41263C910C0D0AC33BE2FBE4C400017D68D77B710C02829B000A6BE4C4040A5660FB4A210C0888461C092BF4C4000A8C5E0612A10C010DC65BFEEC64C40804C3107412710C0B85626FC52C74C4000A1BDFA78080EC0F060C43E01D04C4000BA1457951D0DC0A8B915C26AD24C4080A5660FB4220DC0B0A10DC006D24C4000703D0AD7230DC0885D86FF74D14C4080ED7E15E01B0DC0B8AAD0402CD14C408077F17EDCFE0CC0285C8FC2F5D04C4000698995D1C80CC0B85CA8FC6BD14C40004E5E6402BE0CC0A8C2D84290D14C4000C09140832D0CC0583A58FFE7D44C40806E10AD150D0CC0A8AD11C138D64C4000B8E7F9D3060CC008C45DBD8AD64C400049D74CBEF90BC008BB9A3C65D74C408090EF52EAF20BC0B0B393C151D84C4000E5D4CE30F50BC000301004C8D84C4080D026874FFA0BC080ABAE4335D94C40006893C327FD0BC0608BC1C3B4D94C408014AE47E1FA0BC0286BD44334DA4C4000EE74E789E70BC06034D6FECEDA4C40809735B1C0B70AC008240C0396DC4C40802F1004C8500AC0503A58FFE7DC4C40007E37DDB2430AC0600DFB3DB1DC4C40000AD7A3703D0AC050F5F23B4DDC4C40008718AF79350AC0B8622AFD84DB4C4000022D5DC1160AC0286BD44334DA4C40807C410B09F809C020F911BF62D94C4000F1D8CF62C909C0B8E0F08288D84C4000240C0396FC08C0C87FD6FCF8D54C4000809BC58BA508C030ED0DBE30D54C4080D89942E75508C0B0716F7EC3D44C4080E17A14AE4708C010D6E3BED5D44C408047E17A142E08C0386893C327D54C400086E12362EA07C0081286014BD64C408009D7A370BD07C0A8A44E4013D74C4080D6A3703D8A07C0504F1F813FD84C4080CEF9298E6307C080ABAE4335D94C4000D0EFFB372F07C0001E8A027DDA4C4080FCA5457DD206C05855A18158DA4C4080402D060F5306C0903CBB7CEBD94C4080B1A19BFD4106C030D8463CD9D94C40006BED7DAA2A05C0D08558FD11D84C4000C2F5285C8F04C06040DAFF00D74C4000AE47E17A1404C0C87FD6FCF8D54C4000F71E2E398E03C0480438BD8BD54C400077BAF3C43303C0605260014CD54C40802CB649452303C0605260014CD54C40806793C3277D01C0B8E3310395D54C4000BF9B6ED96101C05831957EC2D54C40805FE97C785601C0305FD04202D64C4000C972124A1F01C01018080264D84C40006F10AD150D01C030E109BDFED84C4000295C8FC2F500C0E00F238447D94C408021A81ABD9A00C0C8C1FA3F87D94C4080C09140832D00C09093A641D1D84C4000F3052D24E0FEBF608E0244C1D64C4000E00CFE7EB1FEBFB89509BFD4D54C4000F6285C8FC2FDBF0021CB8289CF4C40004A72C0AE26FDBF78A2EBC20FCA4C40004487C09180FCBF582E54FEB5C04C400046AAEFFC62FCBFE076137CD3BE4C400027EE78935FFCBFB0E67283A1BA4C4000E10CFE7EB1FDBF386211C30EB34C4000E7F7FD9B57FFBF6082FE428FAA4C40002C4833168DFFBF30E109BDFEA84C4000F94B8BFAA4FFBF80C9C6832DA84C40002EAC1BEF6E00C000DFA63FFB9B4C4080F0A1444B7E00C0D8066003229A4C4080B7E7F9D38600C00818080264984C4000999999999900C0089A417C60934C4000022D5DC19600C0B0B915C26A924C40804F5436AC8900C080ABAE4335914C4080D66CE525BF00C038E109BDFE884C4080D89942E75501C0E08558FD11804C40002FD978B08501C0A0716F7EC37C4C40805A6265349201C0784B00FE297B4C4080AD47E17A9401C000E2E7BF07794C40009EE925C69201C0806649809A784C408064027E8D8401C0905704FF5B774C4000583508737B01C028E44A3D0B764C4080AC1A84B97D01C0507FBDC282754C4080B2976DA78D01C0B8622AFD84734C4080B1A19BFDC101C0A8A44E40136F4C4000746039428602C088AEEFC341664C40008A3BDEE49702C0B868ACFD9D654C4000698995D1C802C0805A457F68644C408084EB51B81E03C0D0D03FC1C5624C4000FCA5457D5203C060465C001A614C4080402D060FD303C0906308008E5B4C408077BAF3C4B303C0E0A9F23D23594C4000E36E10AD9503C0906308008E594C40003656629E9503C0A0E0F08288584C408045B41D539703C0789C69C2F6574C4080B94BE2ACE803C06028D2FD9C4E4C40009735B1C03704C078A2EBC20F4A4C40802502D53F4804C0A85CA8FC6B494C4000FED2A23E6904C080C9C6832D484C408094490D6D2005C0A8984A3FE1424C4080C2BE9D44C405C0E0C43BC0933E4C4000A01683872907C0009A417C603B4C4000B0743E3CAB07C0D0B837BF613A4C408078E750864A08C0E08BDAFD2A3A4C40000873BB975B08C028F04E3E3D3A4C408086E123626A08C028F04E3E3D3A4C4000067DE9ED8F08C038D8463CD9394C4000809BC58BA508C0B85CA8FC6B394C4000A7936C75390AC06831957EC22D4C4000416491261E0AC058F5F23B4D2C4C4000EB51B81E050AC030232E008D2C4C40805FB2F1608B09C0C8FA5B02F02D4C40804387C0918009C08848BF7D1D2E4C4080B16A10E6F607C0809FAA4203354C4080E4D4CE307507C0D8CABDC0AC384C400080643A745A07C0D8C1FA3F87394C4000643909A54F07C0508BC1C3B4394C4080FFC874E83407C010D9243FE2394C4000E370E6571307C0D873D2FBC6394C4080285C8FC2F506C0D8C1FA3F87394C40802FD978B08506C030172AFF5A384C4000C1C8CB9A7806C090C9C6832D384C40002EAC1BEF6E06C0F8BA9A3C65374C40005708ABB16406C0A8E3310395354C408002232F6B6206C0E0031F8315354C4080DE162CD56506C000240C0396344C4080DAC69FA86C06C0A8A78FC01F344C408048D74CBE7906C0D0D03FC1C5324C40802FD978B08506C0E0D38041D22F4C4080CC9541B58106C0A8DA6E826F2E4C40002EAC1BEF6E06C0885A457F682C4C4000EE74E7896706C0E0A6B1BD162C4C4000F4FBFECD2B06C06082FE428F2A4C400094490D6D2006C0C8B837BF612A4C408070067FBFD805C0A0C2D84290294C4000F1D8CF62C905C0885D86FF74294C400061DF4E22A205C0A0C2D84290294C4080AAED26F86605C020F911BF62294C40803BDD79E25905C0100F45813E294C4080C422861D2605C0B8E0F08288284C40003106D6711C05C0B0B393C151284C400016DBA4A21105C0D800DE0209284C40001477BCC9AF04C030F6D03E56244C400018080264A804C088423D7D04244C4080C972124A9F04C0604CDE0033234C4080A0168387A904C08854C37E4F224C408023D5777EB104C0283E7782FD214C400047AAEFFC6205C0909065C1C41B4C4080DAC69FA86C05C0B0622AFD841B4C4080B16A10E67605C03814E97E4E1B4C400055DB4DF04D06C08021E4BCFF174C4080C2F5285C8F06C0808461C092174C40807C0A80F1AC06C03820ED7F80174C400016A4198BC606C05837177FDB174C4080D349B6BADC06C038172AFF5A184C4080FFFFFFFFFF06C0A85CA8FC6B194C40801A2B31CF0A07C0888AE3C0AB194C4000DE205A2B1A07C040D8463CD9194C4080941282555507C030F04E3E3D1A4C408019FED30D7407C0C053E57B461A4C4000D48041D2A707C0F8D8243FE2194C408020B24813CF07C0E07C957CEC184C40003656629E1509C008C45DBD8A0E4C4000703D0AD72309C0B89509BFD40D4C40008718AF793509C028DEC83CF20B4C4000630CACE33809C0B0DDAF027C0B4C4000FA78E8BB3B09C0801EA33CF30A4C4080B6F1272ABB0AC030E78BBD17034C4000D21C59F9C50AC0B8984A3FE1024C4080703D0AD7230BC0A85CA8FC6B014C408023D5777E310BC060F833BC59014C408015A4198B460BC020266F8099014C4000FC6EBA65870BC0381DACFF73024C408014AE47E1FA0BC0805A457F68044C40805A626534920CC0A877F17EDC064C40005C8FC2F5A80CC03841B8020A074C4000B1A19BFDC10DC0286E15C440074C4000DF162CD5E50DC080A52C431C074C4000301004C8D00DC030DEC83CF2034C400011548D5ECD0DC0B0622AFD84034C40008D959867C50DC0A8B0524145034C4000508BC1C3540DC0E07C957CEC004C400001F6D1A94B0DC0282F3201BF004C4000B0743E3C2B0DC008CADFBDA3004C40802CB64945A30BC0803FFCFCF7FE4B4000505436AC090AC0B059677C5FFC4B4080BB41B456B408C068F833BC59F94B4080D6A3703D8A08C0D8F71A82E3F84B4000DAC69FA86C08C000301004C8F84B4080F84B8BFA2408C0C8C1FA3F87F94B408014AE47E17A07C0E0A6B1BD16FC4B40009B8F6B436507C0D0BEB9BF7AFC4B40002502D53F4807C028ED0DBE30FD4B4080A143E0484007C0001B498270FD4B4080E49D43192A07C000C45DBD8AFE4B40001E4E603AED06C010D061BEBC024C40804C689258F206C0E0C77C40A0034C4000963FDF16EC06C0D8A6B1BD16044C4080F3FBFECDAB06C0F8C35DBD8A064C4080067DE9ED8F06C020F38FBE49074C40807F643A745A06C0A06E2EFEB6074C4080B1A19BFD4106C04837177FDB074C4080B1A19BFD4105C0580ABABDA4074C40802A89EC830C05C05040DAFF00074C400055DB4DF0CD04C0500438BD8B054C408064027E8D0404C030172AFF5A004C40004487C0910003C0001E8A027DFA4B4080F2CEA10C1502C0B0E3310395F54B40001B2B31CF0A01C028F911BF62F14B40802CB64945A300C05040DAFF00EF4B4080F2CEA10C9500C0805182FE42ED4B4000A339B2F28B00C0E0BEB9BF7AEC4B40006893C3277D00C0B0622AFD84EB4B40003883BF5F2C00C0D009A1832EE74B4080ED7E15E01B00C06831957EC2E54B4000CC9541B50100C0D07954FCDFE34B400047E17A14AEFFBF8818213CDAE04B40006AC020E993FFBF904E417E36E04B4000C872124A9FFDBFA8A78FC01FD44B4000FDDCD0941DFDBFA0AAD0402CD14B4000E8C072840CFDBFD0F71A82E3D04B4000707495EEEEFCBF202F3201BFD04B400084B4C6A0D3FCBF8893A641D1D04B400096766A2EB7FCBFD8C1FA3F87D14B400092AE997CF3FBBF8021E4BCFFCF4B4000D6A3703D0AFBBF607FBDC282CD4B40004450357A35FABFA8E67283A1CA4B4000B5C4CA6824FABF5055A18158CA4B400010548D5E4DF9BF50499D8026BE4B4000F19716F549F9BF0048A643A7BD4B4000F4BA45602CF9BFD8CDFE40B9B54B40004350357A35F9BF00240C0396B44B4000586C938A46F9BFD0C77C40A0B34B400018D1764C5DF9BFD0D03FC1C5B24B400025CB49287DF9BFE006600322B24B400003ECA35397F9BF38F911BF62B14B40006AC020E993F9BFD0F71A82E3B04B400070CFF3A70DF9BFB0716F7EC3A44B4000C93B873254F8BF889FAA4203954B40000AD7A3703DF8BF804B00FE29934B4000F6285C8FC2F7BFB0DDAF027C8B4B4000E10CFE7EB1F7BF6007793D988A4B400022A81ABD9AF6BFB89B8BBFED7F4B4000DD205A2B1AF6BFB09ECC3FFA7C4B4000A4703D0AD7F5BF608E0244C1764B4000FB6EBA6587F5BF0021CB82896F4B4000E466B801DFF4BF00D061BEBC624B4000F5285C8FC2F4BFD8EE5701BE614B4000F94B8BFAA4F2BF904B00FE29534B400059350873FBF0BF5840DAFF004F4B400076BAF3C4B3F0BFA05FE97C784E4B40003E78EDD206ECBF30E109BDFE484B40009E2ADF3312E2BFF81A4982703D4B4000D0EFFB37AFE0BFF8264D83A2394B400036E84B6F7FE0BFE07C957CEC384B4000E07A14AE47DDBF504F1F813F304B40003C9B1C3EE9DBBF10D6E3BED52C4B400058B39597FCDABF90812040862A4B400000DC2C5E2CD9BF90992842EA224B4000608A39083AD9BF381DACFF73224B4000A425564623D9BFB8A10DC006224B4000D0393FC571D8BF682E54FEB5204B4000CCCCCCCCCCD0BF009700FC53164B400028732CEFAAC9BFC8B81B446B134B4000F07002D369C3BF1006820019124B4000A076BF0AF0BDBFD87C957CEC104B400080EB51B81EB5BF586D37C1370F4B40009032A9A10DB4BF00DC65BFEE0E4B40003033333333B3BF089700FC530E4B40000041D5E8D5B4BFB8E33103950D4B4000D0CCCCCCCCBCBFF8230C03960C4B400020D0D2156CC1BFE00CE2033B0C4B4000D081E50819C2BF60431B800D0C4B4000480306499FC4BFA8B05241450B4B40002011A8FE41C6BF381DACFF730A4B4000982C27A1F4C9BF5040DAFF00074B4000004BE7C3B3CABFE0AC33BE2F064B40002014E97E4ECBBF00240C0396044B4000D8326E6AA0CBBF58793BC269034B400028A77686A9CBBFA8984A3FE1024B4000E051B81E85CBBF903CBB7CEB014B4000E8BE2A172ACBBF90457EFD10014B4000287E1AF7E6C5BFD07FD6FCF8F54A4000F095CE8767C5BF386893C327F54A4000B01E85EB51C0BFD0C43BC093EE4A400050B5DD04DFBCBF90397AFCDEEC4A400090C8772975B9BFB8DDAF027CEB4A4000803AC95697ABBFD0F19881CAE64A40008021A81ABD8ABFD0B837BF61E24A400020DAE4F049AF3FB853E57B46DA4A4000707B9E3F6DB03F803CBB7CEBD94A400078C9C6832DC03F5007793D98D24A4000900DDDEC0FC23FD8B2B5BE48D04A4000C04A22FB20C33FF8298E03AFCE4A400038A77686A9C33F301A6B7F67CD4A4000B88F87BEBBC33F503A58FFE7CC4A40006869A7E672C33F809065C1C4CB4A4000F82B9D0FCFC23FB0984A3FE1CA4A4000582C62D861C23F001E8A027DCA4A4000E8A02FBDFDC13FC806600322CA4A4000D01803EB38BE3F504F1F813FC84A400050B5DD04DFBC3FD88558FD11C84A4000B05F5AD427BD3FA0E0F08288C84A400010B4C9E193BE3F68F833BC59C94A4000908461C092BF3F908AE3C0ABC94A4000D85BCAF962C13F584CDE0033CB4A4000F00DA2B5A2C13F382CF180B2CB4A40002063601DC7C13F6070784144CC4A4000987A4FE5B4C13FA8716F7EC3CC4A4000F0251B0FB6C03F8896E7C1DDCD4A400070CD565EF2BB3F386E15C440CF4A400000E204A6D3B63F904E417E36D04A4000F07A14AE47B13F90457EFD10D14A40000020990E9DA63FB874B0FECFD14A4000C0E2A7716F9E3F883CBB7CEBD14A4000007497C459913F40D8463CD9D14A400080012D5DC1863FD0EE5701BED14A40000000000000000030B75F3E59D14A400040E7FC14C7A1BFD08558FD11D04A40008090D61874AABF004E2844C0CF4A4000504BAC8C46B2BFB8E9B303AECF4A4000A003CB1132B4BF10D3A23EC9CF4A4000F0F97DFFE6B5BFB89B8BBFEDCF4A400070D619DF17BBBF8018213CDAD04A400028C901BB9AC0BF0806820019D24A400088EE92382BC2BF881EA33CF3D24A4000B8662B2FF9C5BFA8DA6E826FD64A4000B8D39D279ECDBFA859677C5FDC4A40007017EFC7EDCFBF201A6B7F67DD4A40003C0AD7A370D1BF48499D8026DE4A4000D8E9CE13CFD2BF101286014BDE4A400020658BA4DDD6BF587FBDC282DD4A4000DC66F16261D8BF28F0879FFFDC4A400084FB010F0CDBBF009772BED8DB4A40005A21ACC692E1BFD8B837BF61DA4A400090300C58F2E1BFE0D03FC1C5DA4A4000CC5EB69D36E2BF0815C78157DB4A400024CB49287DE2BFA859677C5FDC4A40006C1ADB6BC1E2BF789FAA4203DD4A4000CE3AE3FB62E3BF201A6B7F67DD4A400092533BC3D4E3BF101B498270DD4A4000FAB9A1293BE4BFD8B5F63E55DD4A400006228B34F1E4BFF8D5E3BED5DC4A40005C21ACC692E5BF60431B800DDC4A4000E2E82ADDDDE5BFE0C77C40A0DB4A4000880E812301E7BFA8C2D84290D94A40003A9CC074DAE6BF682E54FEB5D84A40007CC9C6832DE6BFD8D38041D2D74A400060200890A1E0BFA86E2EFEB6D74A400084E3F90C28E0BF48551344DDD74A4000B00CAA0D4EDDBF58465C001AD94A40007C0BB265F9D8BF483750E09DDA4A40002CC6C03A8ED3BF0815C78157DB4A4000F8DD74CB0ED3BFD0AF743E3CDB4A400088A06AF46AD2BFF84AE7C3B3DA4A4000E4E786A6ECD0BFF89C82FC6CD84A400040E141B3EBCEBF607FBDC282D54A4000C0F2E7DB82CDBFD0C77C40A0D34A4000582250FD83CCBF101E8A027DD24A40007881204086CABF282F3201BFD04A4000205FD04202BEBF001E8A027DCA4A4000905B0531D0B9BF68F833BC59C94A4000C04B3B35979B3F000F45813EC14A400080116DC7D4B53F88AEEFC341BE4A400010AB06616EBF3FB8716F7EC3BC4A4000F073435376C03F580DFB3DB1BC4A400048B81E85EBC13F603A58FFE7BC4A4000F82B9D0FCFC23FB8716F7EC3BC4A4000805F950B95C53FA0984A3FE1BA4A400028882CD2C4CB3FA8B6D4415EB54A40004030F2B226CE3FF8E769C020B34A400040E17A14AECF3F602E54FEB5B04A4000BC1E85EB51D03FA8A44E4013AF4A4000E07A14AE47D13F30F6D03E56AC4A400060FE7C5BB0D53F78AEEFC3419E4A40002063601DC7D53FB09509BFD49D4A4000885A0C1EA6D63F909C69C2F6974A4000DCE9CE13CFD63FE0C43BC093964A40009C4EB2D5E5D63FF8230C0396944A40000424D3A1D3D63FE082177D05934A4000A09410ACAAD63F38D8463CD9914A4000D0C743DFDDD53F50707841448C4A400018A9BEF38BD53F089A417C608B4A40000CFB761211D53F10D061BEBC8A4A400054DCF126BFD43F5882FE428F8A4A4000803881E9B4D13FA8656B7D91884A4000D881E50819CA3F00C79E3D97834A4000A02897C62FC63FB0AAD0402C814A4000806CE8667FA03F281A6B7F67754A400000D0F484255E3FD861BEBC00714A40000000530E66033FB82500FF94704A4000005876C1E07A3F109700FC53704A400040D349B6BA9C3F282F3201BF704A400040DBF81395AD3FB074B0FECF714A4000E00DA2B5A2B13FA0A10DC006724A4000C01B446B45B33F78A2EBC20F724A400000BCE9961DB63F10D9243FE2714A400010DAE4F049BF3FA8B393C151704A40008014AE47E1C23FD009A1832E6F4A4000281BBAD91FC43FF0298E03AF6E4A4000C85F5AD427C53F8048BF7D1D6E4A4000B0662B2FF9C53F001B4982706D4A400098BB24CE8AC63F600DFB3DB16C4A40007017EFC7EDC73FE0AF743E3C6B4A4000F8E44526E0CB3F30F38FBE49674A400070F22213F0CD3F60499D8026664A4000B0BB24CE8ACE3F801B62BCE6654A4000506D37C137CF3F28327381CB654A4000B4230ED940D73FD87954FCDF634A40001CF4A5B73FD83F88423D7D04644A400094C2F5285CDB3FE00F238447694A40002CC6C03A8EDB3F908AE3C0AB694A400090558330B7DB3F08068200196A4A4000C08BF7E3F6DB3F08E869C0206B4A400080F0DAA50DDC3FD00CE2033B6C4A4000380F60915FDC3F00C45DBD8A6E4A400038E84B6F7FDC3FB8A44E40136F4A4000D45D126745DF3FC809A1832E774A4000CCF09F6EA0DF3F9021E4BCFF774A400022F301814EE13FB0DDAF027C7B4A40007E82C47677E13F682B137EA97B4A40003AC478CDABE13F809065C1C47B4A40007EA5F3E159E53F283B3602F17C4A4000C064E3C116EC3FE07954FCDF7B4A40001AF4A5B73FEC3F7815E0BBCD7B4A4000D6355A0E74EC3F906308008E7B4A4000721ADB6BC1EC3F6007793D987A4A4000D8A3703D0AED3F283E7782FD794A4000F6BA45602CED3F08D9243FE2794A40004C72C0AE26EE3F508BC1C3B4794A4000C8866EF607EF3F38266F8099794A400094533BC3D4EF3FE0EE5701BE794A4000CE0358E417F03F503D997FF4794A400083919735F1F23F88C9C6832D784A4000624337FB83F43F908D2441B8764A40009BD024B1E4F43FD07FD6FCF8754A4000723D0AD7A3F53F10BEDBBC71744A4000B36A10E6F6F53FB0622AFD84734A400000378B174BF63FD8B837BF61724A4000CCA99D61EAF63F889C69C2F66F4A4000BD783F6E7FF73FB8B6D4415E6D4A40007E6E68CA0EF83F504CDE00336B4A40005B6C938A46F83FB8B915C26A6A4A4000356ABE4A7EF83F00274D83A2694A4000422D060F53FA3F104BE7C3B3624A4000DC34B6D782FA3FA874B0FECF614A400055DB4DF0CDFA3F084E2844C05F4A40005A350873FBFA3F101286014B5E4A400009D7A3703DFB3FE0C77C40A05B4A4000311004C850FB3FD8B837BF615A4A4000941CB0AB89FB3F6028D2FD9C564A4000ABED26F8E6FB3FD8B2B5BE48504A400084919735F1FB3F08BB9A3C654F4A400092300C58F2FB3FF8DB65BFEE4E4A4000B0B48CD4FBFB3F080FD3BEB9434A4000EEE2FDB8FDFB3F5055A181583A4A4000D1EFFB37AFFB3F50888043A8344A4000B532E197BAFB3F8854C37E4F324A4000D711876CA0FB3F9018213CDA304A400031630AD6F8FA3F584F9143C4294A4000AF47E17A14FA3F38E109BDFE184A400060B2F1600BFA3F805704FF5B174A40000100000000FA3FB0AD11C138164A400010315EF36AF93F881EA33CF30A4A4000388DEDB560F93F88812040860A4A40005A6C938A46F93FE073D2FBC6094A400095E524943EF63F78A86DC328FC494000EAF7FD9B57F53F08DC65BFEEF6494000B2A19BFD41F53FD076137CD3F64940003756629E15F53FF82F1004C8F8494000336ABE4A7EF43F30327381CBFD49400047AAEFFC62F43F8060C77F81FE49400083C8224D3CF43F3841B8020AFF494000A6936C75B9F23F2814E97E4E034A4000E82E89B3A2F23FB8B0524145034A40004A04AA7F90F23FE0FD9C82FC024A4000941CB0AB89F23F9081204086024A4000D8DAFB5455F33F508BC1C3B4F9494000D4B7CCE972F43F00301004C8F04940001C2B31CF8AF43F282F3201BFF0494000CA72124A9FF43FA8656B7D91F0494000F1AB72A1B2F43FA8B393C151F0494000A7936C75B9F43FB85626FC52EF494000F1CEA10C95F43F081B498270ED4940009EBCC8047CF43FA8716F7EC3EC494000B3A19BFD41F43F60793BC269EB4940006CC020E993F33FF820CB8289E7494000D8DAFB5455F33F68FB743C66E6494000AC24B20F32F33F881B62BCE6E5494000ABED26F8E6F23FD8031F8315E5494000FFDCD0941DF23F60FEB5BC72E349400034A14962C9F13FD0FD9C82FCE24940008522DDCF69F13FB0E67283A1E2494000CCCCCCCCCCF03FB0E67283A1E2494000118B187698F03F88992842EAE2494000A439B2F28BF03FA8B0524145E349400052B81E85EBEF3F00D3A23EC9E74940005C21ACC692EF3FD8EE5701BEE9494000422D060F53EF3FD0C1FA3F87E9494000C087122DF9ED3F08BB9A3C65E7494000681B7FA2B2ED3F28DB87BCE5E6494000B6D0CE6996EB3FE082177D05E3494000F6BA45602CE73F809FAA4203DD494000867D3B8988E63F10BEDBBC71DC4940005649641F64E63FD8A6B1BD16DC494000768368AD68E63F582B137EA9DB494000566C938A46E83F6001F73C7FD84940000E04013274E83FC804A73E90D8494000C8F484259EEB3F30E78BBD17DB49400064D520CCEDEB3FB8DDAF027CDB4940005C8FC2F528EC3F48431B800DDC494000B092C83EC8EC3F2005C1E3DBDD494000D8D64FFFD9EC3FE86F422102DE4940004693C492F2EC3F408908FF22DE494000EE74E78967ED3FD8F19881CADE494000E82E89B3A2ED3F508E0244C1DE49400064F84F37D0ED3F00C45DBD8ADE494000A22ADF3312EE3F285FD04202DE49400094E4805D4DEE3F90397AFCDEDC494000C2F5285C8FEE3F5828D2FD9CCE4940007860394286EE3F00E5284014CE49400098C151F26AEE3FB068ACFD9DCD4940008AEB51B81EED3FA8B915C26ACA494000141D024702EC3FD8D38041D2C7494000484F914344EA3F28232E008DC4494000C8AA4198DBE93FD8F4D901D7C3494000C240102043E93F30E78BBD17C3494000EEE3A1EFEEE83F5834D6FECEC2494000A2BB24CE8AE83F10D061BEBCC24940002484471BC7E53FA8A78FC01FC4494000285C8FC2F5E43FA8ECF483BAC44940008237DDB2C3E43F580DFB3DB1C4494000FC285C8FC2DD3F0818080264C0494000B06BB41CE8DC3FF84D2844C0BF4940003CE84B6F7FD83F908AE3C0ABB9494000FCD61533C2D83F00D9960167B9494000E4A128D027D93F80ABAE4335B9494000482C62D861DA3F80ABAE4335B94940007C8368AD68DC3FB874B0FECFB94940002C5C8FC2F5DC3FB053E57B46BA494000241631EC30DD3F5807793D98BA49400058FE7C5BB0DD3FE0F4D901D7BB494000942C27A1F4DD3F30D505BCCCBC4940004C72C0AE26DE3F28ED0DBE30BD494000805A0C1EA6DE3FD8CDFE40B9BD49400014D21A834EDF3F285FD04202BE494000D48041D227E13FA05FE97C78BE4940004A04AA7F90E13FA05FE97C78BE4940000E45BA9FD3E23FA05FE97C78BE494000F6DD74CB0EE33F58FB743C66BE494000B81E85EB51E63F5870784144BC494000845A0C1EA6E63FE0F4D901D7BB494000CEA99D61EAE63F2814E97E4EBB494000D8A3703D0AE73FD882177D05BB4940004850357A35E73FB053E57B46BA494000A60227DB40E73F30D8463CD9B9494000C440102043E73F20F911BF62B94940004850357A35E73F8818213CDAB8494000960854FF20E73F089D82FC6CB84940009A2B836A03E73F386552431BB8494000CEEFFB37AFE63FD0D38041D2B7494000F0BFCE4D1BE63FB06E2EFEB6B7494000184031B2E4E53F004E2844C0B74940001EF301814EE53F784E417E36B849400064200890A1E43F587C7C4276B849400016AE47E17AE43FD8B2B5BE48B8494000CAAA4198DBE13F8087A2409FB449400056DB4DF0CDE13FD80CE2033BB4494000F4052D24E0E13FC8F4D901D7B3494000A22ADF3312E23F884B00FE29B3494000562635B481E23F803CBB7CEBB149400060200890A1E23F08274D83A2B1494000DCE9CE13CFE23F885D86FF74B149400092533BC3D4E33F10E2E7BF07B1494000867D3B8988E63FB8B393C151B0494000285C8FC2F5EC3FE0C77C40A0AB494000D48041D227ED3F10C79E3D97AB494000EC74E78967EF3FE00CE2033BAC494000C487122DF9EF3FB8BF97C283AC494000AC24B20F32F03F080341800CAD4940000C0E2F8888F03F089700FC53AE4940002B7FBE2DD8F03F5040DAFF00AF494000870E812301F13F586D37C137AF494000FDDCD0941DF13F20F38FBE49AF4940009F2ADF3312F33F607C7C4276B04940006EACC43C2BF63F08274D83A2B1494000A5703D0AD7F63FD8B837BF61AA4940006CC020E993F63FE0EE5701BE994940001D2B31CF8AF63F286552431B984940004587C09180F63F903FFCFCF796494000AE7E6C925FF63FA89ECC3FFA9449400095E524943EF63F002DCF83BB93494000ABED26F8E6F53F30F911BF6291494000B532E197BAF53F507C7C42769049400017080264A8F53F884E417E36904940003533333333F43F809FAA42038D4940000E68E90AB6F33F503A58FFE78C494000FE6EBA6587F33FA8716F7EC38C49400024A81ABD9AF13FB05CA8FC6B894940005549641F64F13F00301004C888494000B732E197BAF03F009700FC538649400015AE47E17AF03F78CC07043A85494000A7CAF78C04F03FD8D03FC1C5824940008636397CD2EF3F1006820019824940003CE7A7388EEF3FD87C957CEC80494000422D060F53EF3F908461C0927F494000940854FF20EF3F9048BF7D1D7E494000C8866EF607EF3F080341800C7D49400056B77A4EFAEE3F28DEC83CF27B494000DCA3703D0AEF3F28E109BDFE784940003833333333EF3F28F38FBE4977494000FE91E9D069EB3FB85FE97C787649400070CFF3A70DEA3F50853FC39B77494000D23AE3FB62E93FE0D38041D2774940008A0E812301E93F104E2844C077494000DCC69FA8ECE63FD8F4D901D773494000026E162F96E63F78992842EA72494000A4703D0AD7E53FB8E0F0828870494000ACB69BE09BE53FB89B8BBFED6F494000221631EC30E53F30F38FBE496F4940004C72C0AE26E23FA8BF97C2836C494000409B1C3EE9DF3FB8B05241456B49400054969350FADC3F08D061BEBC6A494000684293C492DB3FD0B837BF616A494000E00DA2B5A2D93FD0C1FA3F876949400064FC34EECDD73F5801F73C7F6849400024F25D4A5DD63F2820ED7F80674940002CA77686A9D33FB87A32FFE86349400034799109F8D23FD0FD9C82FC6249400028F25D4A5DD23F803CBB7CEB61494000B8B45373B9D13F884E417E366049400084A5F3E159D13FA8BC5642775F4940006CF7AB00DFD03F38DB87BCE55E49400024F4A5B73FD03F00C45DBD8A5E494000A02F682101CF3FB85FE97C785E494000D85F5AD427CD3F3829B000A65E49400038C6C03A8ECB3F08DC65BFEE5E494000908461C092BF3F78ABAE433561494000401EFB592CB93FB853E57B4662494000406893C327AD3F28DEC83CF263494000A04D637B2DB8BFB86E2EFEB6674940002082AAD1ABC1BF302F3201BF68494000D0A6B1BD16C4BFE0A9F23D2369494000B0FF3A376DC8BF508BC1C3B469494000482C62D861CABFA874B0FECF69494000B81E85EB51D0BFD073D2FBC6694940000291459A78E2BF30327381CB654940006666666666E4BFB0716F7EC364494000AAB69BE09BE5BF00DFA63FFB634940007E37DDB2C3E6BF306211C30E63494000F0052D24E0E7BFB8A10DC00662494000E22F2DEA93E8BF30172AFF5A60494000847D3B8988E8BF788461C0925F494000847D3B8988E8BF88A52C431C5F49400032C51C049DE8BF10E52840145E4940002A7FBE2DD8E8BFC8B5F63E555D49400048969350FAE8BFD888997D1E5D494000960854FF20E9BF383B3602F15C4940009CBCC8047CE9BF00D6E3BED55C49400046E17A14AEE9BFE0031F83155D494000B68C9B1AE8ECBF9054C37E4F62494000960854FF20EDBF2835B401D862494000C2633F8B25EDBF0815C78157634940002639605713EDBF889065C1C463494000500306499FECBF080341800C6549400034E84B6F7FECBF505260014C6549400066F84F37D0EBBF30327381CB65494000865968E7B4EBBF9048BF7D1D66494000E62E89B3A2EBBF8060C77F816649400034C478CDABEBBF4840DAFF0067494000245D33F9E6EBBF0021CB82896749400024A77686A9EDBF58FEB5BC726B494000BE745AB7C1EDBF5861C1FD806B49400070CFF3A70DEEBFD8C77C40A06B49400055A4C2D882F1BF60707841446C4940008B9FC6BD79F2BF58431B800D6C4940002B4833168DF2BFD87954FCDF6B494000108B187698F2BFA8DDAF027C6B494000A439B2F28BF2BF20E78BBD176B49400070067FBF58F2BFD0B837BF616A4940008C31B08EE3F1BFA89B8BBFED67494000D449B6BADCF1BF0021CB8289674940003C9CC074DAF1BFA8A44E4013674940007A14AE47E1F1BF5828D2FD9C664940004F95EF1909F2BFB0716F7EC364494000169AEB3412F2BFA859677C5F644940000CFAD2DB1FF2BF60431B800D644940009C853DED30F2BF889065C1C463494000C2BE9D4444F2BFE0C77C40A063494000F81400E359F2BFA8622AFD846349400011548D5E4DF5BF505260014C65494000FC6EBA6587F6BFB06BED7DAA624940009DBCC8047CF9BF580DFB3DB15C49400084B4C6A0D3F9BF281A6B7F675D494000416491269EFABF58FB743C665E494000B2A19BFDC1FABF6001F73C7F5E49400092AE997CF3FABFD0C43BC0935E494000630CACE338FBBF109700FC535E494000077DE9ED0FFDBF30232E008D5C4940000AA01859F2FEBFE0AF743E3C5B494000E370E6571300C0B0622AFD845B494080E49D43192A00C0E87954FCDF5B4940801E85EB513800C010BEDBBC715C494080828769DF3C00C090397AFCDE5C4940002A52616C4100C06031957EC25D494080346090F44900C0D87FD6FCF85D494080D89942E75500C0E0FA5B02F05D494080736039428600C0F8C69E3D975B4940005FB2F1608B00C0B0B05241455B494080A5660FB4A200C0888AE3C0AB5949408008AA46AFA600C0E00F238447594940802CB64945A300C08018213CDA58494000118B187698FFBF28327381CB554940009ACC785B69FFBF682AC423F15449400084B01A4B58FFBF7824D0605355494000739B70AF4CFFBF408F519E79554940007D3B89083FFFBFC86A48DC6355494000620CACE338FFBFA0B94E232D554940004350357A35FFBFF8D808C4EB544940003A799109F8FEBF30D8463CD951494000D6DAFB5455FFBF8887A2409F4C4940006566666666FFBFA859677C5F4C494000326ABE4A7EFFBF50707841444C494080FDD2A23E6900C0D0FD9C82FC4A494000295C8FC27500C0801EA33CF34A49408048D74CBEF900C0D0CDFE40B94D4940805A6265341201C08060C77F814E494080170802642801C0903FFCFCF74E4940006AC020E99301C038EACC3D245049400022A81ABD1A03C0C8066003225249408008AA46AF2603C0C8066003225249400091EF52EA7203C0D00F238447514940809EE925C69203C088C9C6832D5049408053AEF02EB703C0F8230C03964C49408009D7A370BD03C0A8622AFD844B494080EA1A2D07BA03C010D061BEBC4A494000B0743E3CAB03C038266F809949494080DE162CD56503C0B0E9B303AE47494080B72572C17903C068A6ED5F594549408000892650A403C0F8DE5163424649408003763579AA03C0C0C72764E747494080805B77F3F403C0B0DDE8633E4C494000880E81238104C0D07C957CEC5049408001F6D1A94B05C0E8AC33BE2F5649400022A81ABD9A05C0B89B8BBFED57494000490ED8D5C405C0282F3201BF58494000F4FBFECD2B06C0084BE7C3B35A4940003656629E9506C0100C0401325C494000FED2A23EE906C088CC07043A5D494000067DE9ED0F07C0A8E33103955D4940002A52616C4107C08096E7C1DD5D494080DE162CD56507C000CD203EB05D494080819197357107C0607FBDC2825D494000F71E2E398E07C000240C03965C4940807C0A80F1AC07C0E0AF743E3C5B494080402D060FD307C0B0B915C26A5A4940002A52616CC108C0806649809A5849408017D1764C5D09C030EACC3D2458494000FED2A23E6909C0D08558FD115849400019FED30DF409C0009700FC5356494000C745B588080AC0305FD042025649408078E750864A0BC0B877F17EDC4E494080BB783F6E7F0BC0101B4982704D494000B0743E3CAB0BC008C79E3D974B4940801E85EB51B80BC088992842EA4A49408019FED30DF40BC0E0FA5B02F0454940004487C091000CC000240C039644494000FED2A23E690CC0286552431B384940001E4E603A6D0CC0B05FE97C783649408053AEF02E370DC0B8E33103951D49400066666666660DC0080C0401321C4940804C310741A70DC02835B401D81A494000FA78E8BBBB0DC0381DACFF731A494000508BC1C3D40DC0A8B915C26A1A4940802F1004C8500EC0884B00FE291B494080DAC69FA86C0EC050793BC2691B494080CC9541B5810EC08015E0BBCD1B4940006BED7DAAAA0EC0D8031F83151D4940809735B1C0B70EC0C8CDFE40B91D494080F5285C8FC20EC0B05FE97C781E494000301004C8D00EC0804E417E3620494000986C3CD8020FC0E0F4D901D72349408083BEF4F6070FC0000C04013224494080B7E7F9D3860FC08021E4BCFF27494000E370E657930FC0604F1F813F28494000BA1457959D0FC0081808026428494000B0743E3CAB0FC0081808026428494000DC2A8881CE0FC080C9C6832D2849408002232F6BE20FC05837177FDB27494080EB51B81E0510C0D809A1832E274940C0C41D6FF20B10C008C45DBD8A26494080BA46CB810E10C0E8AC33BE2F2649408024D060531710C008CD203EB025494080D349B6BA1C10C0507FBDC282254940C02407EC6A2210C000A0C37C79254940C0CA9F6F0B3610C08896E7C1DD25494040560DC2DC3E10C060FB743C66264940408940F50F7210C0C053E57B462A494040A0168387A910C0F8BA9A3C652F49404033333333B310C030172AFF5A30494080EB51B81E8511C0D0C43BC0932E49404077BAF3C4B311C088CC07043A2D49408060E4654DBC11C0A8ECF483BA2C4940C03C484F91C311C02044F982162C494000B3976DA7CD11C008E869C0202B4940C0A8C0C936D011C0D0D03FC1C52A494080B9145795DD11C0D8066003222A494040C8409E5DEE11C0588BC1C3B4294940001B2B31CF0A12C0E00F238447294940003883BF5F2C12C0080F45813E29494040508BC1C39412C0A85CA8FC6B29494040B16A10E6B612C0588BC1C3B429494040ABE80FCD0C13C05837177FDB274940C047E17A146E13C00048A643A71D494080643909A5CF13C0382F3201BF18494040819197353114C0901B62BCE615494080A46B26DF3C14C0B074B0FECF114940C06E10AD154D14C03835B401D80A494080698995D14814C06082FE428F0A4940409544F6414614C0286BD443340A4940405B5D4E093814C0A89B8BBFED07494000B16A10E63614C0B0BC56427707494000630CACE33814C05076FA415D06494080A46B26DF3C14C0101B498270054940003AB01C214314C040D505BCCC044940402C7FBE2D5814C088992842EA02494000698EACFCA214C0B8656B7D9100494080A23EC91DA614C0584F1F813F0049404021AD31E8B414C030327381CBFD484080C8772975B914C0A89ECC3FFAFC4840802FD978B0C514C0C053E57B46FA48404001F6D1A9CB14C09054C37E4FFA4840C0643909A5CF14C05007793D98FA484040E49D4319EA14C000240C0396FC48400033333333F314C0A8E3310395FD4840C0D11C59F90515C0286552431B004940C01D5377650715C0A8E0F08288004940807B0F971C0715C038E109BDFE00494040880E81230115C06055A1815802494040E6CAA0DA0015C0801EA33CF302494000DCF3FC690315C0D0F4D901D7034940C0652FDB4E1B15C0500ABABDA407494000BA4BE2AC2815C0D8F71A82E3084940C0573A1F9E5515C0382CF180B20B4940C0BE9B6ED9E115C08021E4BCFF0F4940C047E17A14EE15C0604F1F813F10494040C3F01131F515C0D8B2B5BE4810494000880E81230116C028EACC3D241049408001F6D1A90B16C05837177FDB0F4940406BB6F2921F16C070A52C431C0F494040666666662616C09060C77F810E4940C0A7C5E0612A16C0B0E33103950D494000EC4CA1F32A16C0889FAA42030D494040AAED26F82616C038E78BBD170B49404008AA46AF2616C06082FE428F0A494040F62345642816C0885D86FF74094940809DEE3CF12C16C0886649809A08494040C3F011313516C058853FC39B07494080022846963C16C06040DAFF00074940C0272A1BD64416C010C45DBD8A06494040508BC1C35416C09048BF7D1D06494080B91457959D16C0500DFB3DB104494040CEF9298EA316C0F8230C0396044940404A09C1AAAA16C058888043A804494000CB9F6F0BB616C0303B3602F1044940C0FFFFFFFFBF16C0A8B6D4415E0549400078B5DC99D916C0B877F17EDC06494080630795B8DE16C058853FC39B074940400DFAD2DBDF16C0D08558FD11084940400DFAD2DBDF16C0886649809A084940C0A3703D0AD716C0B0E0F0828810494040C745B588C816C010C79E3D97134940004487C091C016C0A8A78FC01F144940C07133DC802F16C0B853E57B461A4940C0C41D6FF20B16C050793BC2691B4940001C5DA5BBFB15C0889065C1C41B494000D0EFFB37EF15C0A8622AFD841B4940C0A7C5E061EA15C03014E97E4E1B494040BC732843E515C05082FE428F1A4940C02407EC6AE215C0808AE3C0AB194940C0D0217024E015C06073B9C15019494080DD205A2BDA15C0E0A9F23D23194940C08FBDDEFDC115C000CADFBDA318494040B6F1272ABB15C0D8CABDC0AC184940C0CA9F6F0BB615C08093A641D118494040FCA5457D1215C0286211C30E23494080B91457959D14C0D8F4D901D72B4940803BDD79E29914C080A86DC3282C494000C3F011313514C030E44A3D0B364940008940F50F3214C068FB743C66364940801E4E603A2D14C0506D37C13737494000342E1C081914C0082DCF83BB3B494040CEC29E761814C0000C0401323C4940C0CB9A58E01B14C0F80241800C3D494040F62345642814C0B0BC5642773F494040B29C84D22714C0D800DE020940494000583A1F9E1514C0286893C327454940C01803EB380E14C06031957EC2454940C0633E20D0A913C010D9243FE249494080A3703D0A9713C000068200194A494040560DC2DC7E13C000068200194A4940805D85949F3413C060FEB5BC724B49408078EC67B12413C0E07954FCDF4B4940C0D02170242013C0E8A6B1BD164C4940009CC1DF2F1613C0080341800C4D494000C51D6FF20B13C0002A8E03AF4E494000EE79FEB40113C0100682001952494040C8772975F912C0081B498270554940C0B2976DA7CD12C0386552431B58494080E5CFB7059B12C0886308008E5B4940403201BF464212C0C882177D05634940C0583508733B12C0282CF180B263494000B16A10E63612C0B0BF97C28364494040CDC7B5A13212C0908D2441B8664940C01B261AA43012C05801F73C7F684940C079E2395B3012C030266F8099694940007233DC802F12C0381A6B7F676D494080355B79C92F12C0D0FA5B02F06D49408023D5777E3112C05076FA415D6E4940003883BF5F2C12C03829B000A6764940C0CB9A58E01B12C0D00F238447814940402C7FBE2D1812C0503D997FF48149400016DBA4A21112C0B0A10DC0068249408000FBE8D4E511C0A874B0FECF814940C0620CACE3B811C0D00F238447814940402B84D558B211C0B0AAD0402C814940C000FBE8D4A511C028172AFF5A804940802A52616C8111C0A077F17EDC7E494000C8409E5D6E11C03029B000A67E4940C0295778975B11C0D8F19881CA7E4940802A89EC834C11C010BB9A3C657F494040B16A10E63611C0A8E0F08288804940007592AD2EF710C0B0E33103958549404019FED30DF410C0B89509BFD485494080355B79C9EF10C0A8AD11C1388649408091EA3BBFD810C000E2E7BF07894940C0F97DFFE6D510C010C11C3D7E894940001D588E90E110C058499D80268E4940408E90813CEB10C04837177FDB97494040B29C84D2E710C0804E417E3698494000583A1F9ED510C080457EFD10994940C08096AE60CB10C028F911BF629949400017D68D777710C0884B00FE299B494040CFF412634910C0F899417C609B494000F3C473B6E00FC0809065C1C49B4940805A626534120FC0500DFB3DB19C494000A4703D0A570EC05028D2FD9C9E494080DD205A2B9A0DC0081B4982709D4940003BA6EECA0E0DC0B07A32FFE89B49400091EF52EAF20CC0F82CCF83BB9B49408015A4198BC60CC0000C0401329C49400033333333B30CC0F0230C03969C4940805512D907990CC0605260014C9D49400074603942860CC0F847A643A79D4940003656629E150CC058888043A89C49408083BEF4F6070CC0A8BF97C2839C494080D6A3703D8A0BC0104BE7C3B39A4940004487C091800BC0081E8A027D9A49400049D74CBE790BC028F04E3E3D9A49408047AAEFFC620BC0602E54FEB59849408094128255550BC0D88558FD1198494000490ED8D5440BC060853FC39B97494000C09140832D0BC0286E15C4409749400085EB51B81E0BC0E009A1832E974940806CE34F54F60AC0E009A1832E97494080FDD2A23E690AC0E009A1832E97494080EA1A2D073A08C0D0B837BF619A494080E270E6571308C0909C69C2F69F494000662FDB4E1B08C000301004C8A0494080758D96031D08C0100F45813EA1494000662FDB4E1B08C080992842EAA2494000F71E2E390E08C0B85626FC52A749400047E17A14AE07C09021E4BCFFAF494080FCA5457DD206C0D07C957CECB8494080E49D43192A06C06828D2FD9CBE494080EA1A2D073A05C088C9C6832DC8494080B91457951D05C00006820019CA494000DAC69FA86C04C0B0A78FC01FD4494080D11C59F9C503C0A8ECF483BADC4940803783BF5FAC03C010A0C37C79DD49408021A81ABD9A03C0A89509BFD4DD494000EA245B5D6E03C0089700FC53DE494000A243E0484003C0082A8E03AFDE494000CB9F6F0B3603C0A877F17EDCDE494080A5660FB42203C0306E15C440DF4940006AC020E91303C03838F581E4DF494080D6A3703D0A03C0682E54FEB5E049408083BEF4F60703C06073B9C150E1494000505436AC0903C0D873D2FBC6E14940006F10AD150D03C0306BD44334E2494080CEC29E761803C088992842EAE249400094490D6D2003C0604CDE0033E34940003883BF5F2C03C0009A417C60E3494080CFEFFB37AF03C0908461C092DF4940001D588E90A104C0588E0244C1D6494080C745B5880805C0281DACFF73D2494000B81E85EB5105C0888D2441B8CE494000DF162CD56505C010CD203EB0CD49400046B41D539705C060FEB5BC72CB4940009735B1C0B705C06055A18158CA4940802502D53FC806C06031957EC2C5494080B4C4CA682407C0383B3602F1C44940003BDD79E25907C000D6E3BED5C44940002CB64945A307C0E0031F8315C5494080B6F1272ABB07C0E0B5F63E55C5494080AF743E3C2B08C0D8AF743E3CC3494080DAC69FA8EC08C0808D2441B8BE49400049D74CBEF908C010E5284014BE4940802FD978B00509C0585260014CBD4940800E27309D3609C0383E7782FDB94940802502D53F4809C0909C69C2F6B7494080490ED8D54409C02820ED7F80B74940007E37DDB24309C03041B8020AB7494080490ED8D54409C0D0FA5B02F0B5494000BD6E11184B09C0583A58FFE7B4494080643909A54F09C008BEDBBC71B4494000508BC1C35409C058431B800DB4494000425A63D06909C028E78BBD17B34940009DBCC8047C09C0B0E67283A1B24940807F9BC58B250AC0602E54FEB5B049408058FE7C5B300AC0786649809AB0494080490ED8D5C40AC0607C7C4276B0494080AF3DB324E00AC0607C7C4276B0494000EB1A2D073A0BC0786649809AB04940804F8BC1C3540BC0602E54FEB5B0494080ED7E15E09B0BC0000F45813EB1494080B94BE2ACE80BC0803CBB7CEBB1494080A3703D0A570CC088992842EAB2494000583508737B0CC0B07A32FFE8B3494000AF3DB324600DC050888043A8BC49400077F17EDCFE0DC0D8AF743E3CC34940000C01C0B1070EC010D3307C44C4494000022D5DC1160EC000CD203EB0C5494000E6CAA0DA400EC000CADFBDA3C8494000D0EFFB37AF0EC0286E15C440CF494000630CACE3B80EC0B0BC564277CF4940805512D907990FC0B0DA6E826FCE494000A7936C75B90FC030E44A3D0BCE4940C06E10AD15CD10C0F81A498270C54940C0FECD8B13CF10C010BEDBBC71C4494040FCA5457DD210C0A8A78FC01FC4494000CEC29E76D810C060431B800DC4494080C1C3B46FDE10C0080C040132C4494080C0C8CB9AF810C088CC07043AC54940C00F2219721C11C0306E15C440C74940C0953FDF162C11C0D088997D1ECD4940C0953FDF162C11C00048A643A7CD494080E49D43192A11C09048BF7D1DCE4940404487C0910011C0587C7C4276D0494000E275FD82ED10C008E2E7BF07D1494000CEC29E76D810C0784E417E36D0494000630CACE3B810C0A0E9B303AECF494040CDC7B5A1B210C0500ABABDA4CF49404066666666A610C000D3A23EC9CF4940C07492AD2E7710C0B0AAD0402CD14940C0067DE9ED4F10C0084BE7C3B3D2494040ABE80FCD4C10C0D882177D05D34940003AB01C214310C0B0ECF483BAD44940802A52616C4110C090CC07043AD5494040D4449F8F4210C0D8CDFE40B9D54940C01649BBD14710C0A0380EBC5AD64940C02A89EC834C10C0F8298E03AFD6494000D7A3703DCA10C010DC65BFEED64940C02A89EC830C11C03829B000A6D64940C0B3C9E193BE11C05876FA415DDE49400067614F3B4C12C0D87FD6FCF8DD4940C0DBF3FC698312C0505260014CDD494040941282559512C0809FAA4203DD4940008E90813CAB12C0E0BEB9BF7ADC49408019FED30DB412C090423D7D04DC494000F3C98AE1BA12C01015C78157DB494000B4C9E193BE12C0D8B837BF61DA494040F850A225BF12C0604F1F813FD84940C0976C3CD8C212C0D0B5F63E55D5494000583A1F9ED512C0E0AF743E3CD34940807F643A74DA12C0286211C30ED349404061DF4E222213C0D8F71A82E3D04940C0B94BE2AC2813C030E109BDFED049400084B9DDCB2D13C080ABAE4335D1494040726A67983A13C0383E7782FDD14940C0643909A54F13C06082FE428FD24940403E05C0785613C0B86BED7DAAD24940C00F2219725C13C05807793D98D2494040CDC7B5A17213C0B0A10DC006D24940007592AD2E7713C030D8463CD9D14940C0643909A58F13C0504F1F813FD04940C0415F7AFBC313C058431B800DCC4940006CB1DB670514C0B068ACFD9DCD4940C051B81E852B14C000DC65BFEECE4940C05D85949F3414C008BB9A3C65CF4940407F68E6C91514C0B0E3310395D54940806BB41CE8E113C060BE2EC37FD64940C0630795B89E13C078ABAE4335D9494000A69883A09313C0E0C1FA3F87D9494080C51858C77113C03814E97E4EDB4940405B5D4E097813C0B8BF97C283DC4940407138F3AB8913C0908461C092DF494040C2F5285C8F13C030327381CBDD494080067DE9ED8F13C0B8716F7EC3DC494080963AC8EB9113C068F5F23B4DDC494000342E1C089913C0C8C77C40A0DB4940007D3CF4DD9D13C0089A417C60DB4940804C310741A713C0D082177D05DB494000698D41270414C018C616821CDA4940804259F8FA0A14C038207BBDFBD9494080A2410A9E4214C030F04E3E3DDA4940007E37DDB2C314C010D061BEBCDA494040E49D4319EA14C028232E008DDC494040A46B26DFFC14C010A0C37C79DD4940C0F84B8BFAA414C0A8C2D84290E14940C021A81ABD9A14C0803CBB7CEBE1494000508BC1C39414C0283E7782FDE1494000F850A2257F14C0583D997FF4E14940806F0B96EA7214C0D006600322E2494040C8409E5D6E14C06055A18158E2494040EC4CA1F36A14C0A86BED7DAAE2494080F62345646814C0282CF180B2E3494080F62345646814C0D80CE2033BE44940C08618AF797514C0B8B915C26AEA4940000F27309D7614C080992842EAEA4940C0F2C98AE17A14C0D00CE2033BEC494040A46B26DF7C14C050888043A8EC4940403201BF468214C0A8B6D4415EED4940008196AE608B14C08896E7C1DDED4940C00CFFE906BA14C0386E15C440EF494000E6CAA0DAC014C0905704FF5BEF4940807F643A74DA14C0D8BB783F6EEF4940402DB1321A0915C0D8BB783F6EEF49404021AD31E8F414C0585260014CF5494080F62345646814C02835B401D8FA4940000BD28C456314C0306211C30EFB494000A69883A05314C010D6E3BED5FC49400016DBA4A25114C0905182FE42FD4940C0BA46CB814E14C02820ED7F80FF49400015A930B66013C0E873D2FBC6014A4080EA1F44325413C0503D997FF4014A4080A8C0C9365013C0286BD44334024A40405A6265341213C0604F1F813F084A4040CFF412630913C060F833BC59094A40809CBCC804FC12C0886308008E0B4A4040CDC7B5A1F212C0805182FE420D4A40C01281EA1FE412C0B85FE97C780E4A40C0E175FD82AD12C0D8CABDC0AC104A40003E05C0789612C0B8AAD0402C114A40806CE8667F9012C0000F45813E114A40C0ED79FEB48112C0B8AAD0402C114A4040D349B6BA5C12C07818213CDA104A40C0CB9A58E01B12C0382F3201BF104A4000000000000012C0905D86FF74114A4080B6F1272AFB11C0F0264D83A2114A4040EC4CA1F32A11C0D8BEB9BF7A1C4A40401E4E603AED10C05837177FDB1F4A40409544F641C610C0089A417C60234A4080FCA5457D9210C028E109BDFE284A4080D11C59F98510C02835B401D82A4A408078EC67B16410C0E0F71A82E3304A40007B14AE476110C008D9243FE2314A40401F80D4265E10C080992842EA324A40C046AF06283D10C0E0AC33BE2F3E4A40C0B3C9E1933E10C0F82F1004C8404A4080FCA5457D5210C0E876137CD3464A4000560DC2DC7E10C08087A2409F4C4A40402A52616C8110C0889FAA42034D4A4000D4449F8F8210C000A0C37C794D4A4040880E81238110C0305FD042024E4A40809DEE3CF16C10C02814E97E4E534A40000F27309D3610C0002DCF83BB5B4A4040E6CAA0DA4010C0580DFB3DB15C4A40802FD978B08510C0906308008E634A4000583A1F9E9510C028327381CB654A40008A3BDEE49710C0D0AC33BE2F664A4000342E1C089910C02829B000A6664A4000342E1C089910C0D809A1832E674A408001F6D1A98B10C0884E417E36704A40C0D6A3703D8A10C0F82F1004C8704A40802502D53F8810C0A8AAD0402C714A40C0ED79FEB48110C0583D997FF4714A40C004508C2C7910C0101E8A027D724A40C0698995D18810C0080341800C754A40C02DAC1BEFEE10C0D888997D1E754A4080A46B26DF3C11C0B87A32FFE8734A4080415F7AFB4311C0889065C1C4734A408054E0641BA811C0080F45813E714A40003AB01C21C311C0B0E9B303AE6F4A40C0B94BE2ACE811C0001B4982706D4A4000A243E0480012C0D88BDAFD2A6A4A4040F62345642812C0507FBDC282654A4040FED2A23EE912C088423D7D04644A40000F27309DF612C020DEC83CF2634A40400AD7A370FD12C058431B800D644A40009544F6410613C038232E008D644A4000F296AB1F0B13C0183F7100FD644A40403201BF460213C030F38FBE49674A4000B16A10E6F612C0D8F71A82E3684A40000BD28C45E312C0D882177D056B4A40C021A81ABD9A12C0D8C1FA3F87714A400049D74CBE7912C0A859677C5F744A40002C7FBE2D5812C088AEEFC341764A40C0CA9F6F0B3612C030DB87BCE5764A4000FED2A23E2912C080A52C431C774A40C0652FDB4E1B12C000D3A23EC9774A4080D11C59F90512C058465C001A794A400078B5DC99D911C0000C0401327C4A4000C3F011317511C0109A417C60834A408047E17A146E11C080423D7D04844A40408E90813C6B11C0885A457F68844A4080AAED26F86611C0D0B5F63E55854A40C07A14AE476111C0D000DE0209884A40007365506D6011C008CADFBDA3884A40805A6265345211C05876FA415D8E4A40002DB1321AC910C0C8B837BF619A4A4080758D96039D10C080397AFCDE9C4A40010300000001000000140000008070067FBF5807C000CD203EB05D4D4000207BBDFB8307C0001B4982705D4D40003656629E9507C0607FBDC2825D4D4080A0168387A907C038E44A3D0B5E4D40007E37DDB2C307C0803FFCFCF75E4D4080A3703D0AD707C0D000DE0209604D408001F6D1A94B08C0602E54FEB5684D4080490ED8D54408C080457EFD10694D4000B6F1272A3B08C058F833BC59694D4000AE47E17A1408C0301DACFF736A4D40800BCD751A0908C0B0E67283A16A4D408088450C3BCC07C080992842EA6A4D40800B0401325407C0F899417C606B4D408023D5777E3107C03014E97E4E6B4D40804C3107412707C0F8E769C0206B4D400046B41D531707C0081E8A027D6A4D40002FD978B00507C000C11C3D7E694D4080DBF3FC690307C038E109BDFE684D4000643909A54F07C0E0FA5B02F05D4D408070067FBF5807C000CD203EB05D4D4001030000000100000016000000003BDD79E2D909C0A8B0524145634D4080643909A54F0AC0A8B0524145634D40005C5837DE5D0AC00815C78157634D400033FCA71B680AC010C79E3D97634D400091EF52EA720BC0F820CB82896F4D4000B16A10E6760BC0909C69C2F66F4D4000B16A10E6760BC05001F73C7F704D40802B7FBE2D580BC0082DCF83BB734D400088450C3B4C0BC030232E008D744D4080CFEFFB372F0BC0301A6B7F67754D4000BD6E1118CB0AC03829B000A6764D4080CFEFFB37AF0AC0808D2441B8764D408017D1764CDD09C0A0C2D84290714D4000C87C40A0D309C0E00F238447714D40009735B1C0B709C03038F581E46F4D408045B41D531709C000DC65BFEE664D408069C020E91309C08860C77F81664D4080CEC29E761809C0500DFB3DB1644D408060DF4E222209C008BEDBBC71644D40802502D53F4809C000DFA63FFB634D40804C6892587209C0002DCF83BB634D40003BDD79E2D909C0A8B0524145634D4001030000000100000025000000002C7FBE2D5806C0E073D2FBC6794D4000A339B2F20B06C010A0C37C79754D4000CEC29E769806C05001F73C7F704D400019FED30DF406C05055A18158724D4080F5285C8FC207C0604F1F813F784D40008F8B6A111108C0A8B393C151784D4080E4D4CE307508C008D3A23EC9774D408002232F6BE208C0E0F19881CA764D4000E5D4CE30F508C0E0AC33BE2F764D4000E5D4CE30F508C00848A643A7754D4080F3C473B66009C000240C0396744D4080CC9541B58109C0D0BEB9BF7A744D4080C2F5285C8F09C09087A2409F744D40801E4E603A6D0AC088457EFD10794D4080CC9541B5810AC020266F8099794D40007E37DDB2C30AC0E0C77C40A07B4D4080CEF9298EE30AC05040DAFF007F4D4080EE74E789E70AC0C8BB783F6E7F4D4000C61858C7F10AC0D00F238447814D4000C61858C7F10AC0A874B0FECF814D4080643909A5CF0AC0A068ACFD9D8D4D400011548D5ECD0AC010E52840148E4D4000D7A3703D8A0AC0A8656B7D91904D4080620CACE3380AC0883CBB7CEB914D4080C09140832D0AC00006820019924D4000FED2A23EE909C0004BE7C3B3924D4080A143E048C009C0D082177D05934D400085EB51B89E09C0D082177D05934D40008F8B6A119109C03035B401D8924D4000BA1457959D08C0808461C0928F4D40803656629E9508C0306E15C4408F4D4000240C0396FC07C0D07C957CEC884D40806CE34F54F607C0B8E0F08288884D408038BA4A77F707C00809C38025874D408069C020E99307C000D3A23EC97F4D40007497C459D106C088397AFCDE7C4D40002C7FBE2D5806C0E073D2FBC6794D400103000000010000001800000080D576137C7305C080457EFD10994D4080230C03967C05C0908461C092974D408064027E8D8405C03838F581E4974D4080C745B5888805C0B8B393C151984D40002A89EC838C05C0D00F238447994D4000D7A3703D8A05C088992842EA9A4D4000746039428605C060FEB5BC729B4D408048D74CBE7905C048707841449C4D40004E5E6402BE04C028ED0DBE30A54D4080C51858C77104C0E0F19881CAA64D400016A4198B4604C02841B8020AA74D40802F1004C85003C028EACC3D24A84D4080B1A19BFD4103C078C9C6832DA84D40809735B1C03703C0D000DE0209A84D4000333333333303C0A86E2EFEB6A74D4080C09140832D03C0D876137CD3A64D4080C972124A1F03C0D00CE2033BA44D408084EB51B81E03C09015E0BBCDA34D4080B16A10E6F603C0805704FF5B9F4D40808E8B6A119104C06040DAFF009F4D4000416491269E04C06040DAFF009F4D4080B16A10E6F604C0A8AD11C1389E4D4000000000000005C0801B62BCE69D4D4080D576137C7305C080457EFD10994D400103000000010000001A0000000085EB51B81E07C038327381CBA54D408088450C3BCC06C08054C37E4FA24D4080402D060FD306C0A89B8BBFED9F4D4000EB51B81E0507C0905182FE429D4D40009DBCC804FC06C0504F1F813FA04D40009DBCC804FC06C000301004C8A04D40801F7BBDFB0307C050465C001AA14D4080F0A1444B7E07C050F5F23B4DA44D4000B0743E3CAB07C008D6E3BED5A44D4000A7936C75B907C078397AFCDEA44D400016A4198BC607C0A8716F7EC3A44D4080643909A5CF07C000BEDBBC71A44D4000BD6E1118CB07C080423D7D04A44D4000301004C8D007C080992842EAA24D4080EE74E789E707C0B874B0FECFA14D4080F9821612F007C010C11C3D7EA14D4080F0A1444BFE07C0B05CA8FC6BA14D4000B8E7F9D30608C0D8EE5701BEA14D4080EA1A2D073A08C0D0BEB9BF7AA44D4000022D5DC19608C008C11C3D7EA94D400022A81ABD9A08C0883CBB7CEBA94D40803106D6719C08C0B0B915C26AAA4D40009EE925C69208C0B0B915C26AAA4D40801281EA1F6408C0D806600322AA4D4080C09140832D07C06076FA415DA64D400085EB51B81E07C038327381CBA54D400103000000010000006600000000C64FE3DEBCF4BFA877F17EDC3E4E40007BDD223096F4BF68F5F23B4D3C4E4000C872124A9FF2BFD88BDAFD2A3A4E4000A0168387A9F0BF80ABAE4335394E4000118B187698F0BF8818213CDA384E400021A81ABD9AF0BFB0B393C151384E40007E6E68CA0EF1BFA09509BFD42D4E4000416491269EF1BF2814E97E4E234E40005281936DA0F2BF90457EFD10214E400090F98040A7F2BFE0C1FA3F87214E4000EFE2FDB8FDF2BF8881204086224E400084EB51B81EF3BFB86BED7DAA224E40008B683BA62EF3BFA853E57B46224E40004450357A35F3BF608BC1C3B4214E40006CACC43C2BF3BF282F3201BF204E400039799109F8F2BF507FBDC2821D4E40008B31B08EE3F2BF38D505BCCC1C4E4000EC51B81E85F2BFD87C957CEC184E4000A6CAF78C04F2BF50793BC269134E4000111D024702F2BF88992842EA124E40007D6E68CA0EF2BF381DACFF73124E400070067FBF58F2BFC8F71A82E3104E40004D27D9EA72F2BF10E2E7BF07114E4000A9B69BE09BF2BF38266F8099114E40002EA2ED98BAF2BFB0C2D84290114E400077F17EDCFEF2BFE8B2B5BE48104E4000DE57E54265F3BF286893C3270D4E4000FC6EBA6587F3BFB0984A3FE1024E4000E49D43192AF4BF5076FA415DEE4D40003333333333F4BF8896E7C1DDED4D400088450C3B4CF4BF283B3602F1EC4D4000BA0A293FE9F4BF6831957EC2ED4D400092AE997CF3F5BFD806600322F24D4000E7C072840CF6BFB8DDAF027CF34D40005FB2F1600BF6BF90423D7D04F44D400099620E824EF5BF60853FC39BFF4D4000FE06EDD547F5BF0800000000004E4000630CACE338F5BFB8656B7D91004E40005C8FC2F528F5BF205C8FC2F5004E4000077DE9ED0FF5BFE0A9F23D23014E400059350873FBF4BF8818213CDA004E400063D520CCEDF4BFE0A9F23D23014E400099D024B1E4F4BF08274D83A2014E400000378B174BF4BF08DFA63FFB0B4E40004350357A35F4BF00CD203EB00D4E4000035ABA822DF4BFD876137CD30E4E4000E49D43192AF4BF2838F581E40F4E40001477BCC92FF4BF202F3201BF104E4000C3F5285C8FF4BF70A86DC3281C4E4000A0168387A9F4BF28DB87BCE51E4E40005BC64D0D74F6BF282F3201BF204E40004B04AA7F90F6BF10CADFBDA3204E40005181936DA0F6BF484F1F813F204E40004B04AA7F90F6BFB89B8BBFED1F4E40003233333333F6BF5076FA415D1E4E40007497C459D1F5BF381A6B7F671D4E4000805A0C1EA6F5BF08D061BEBC1A4E40003E4162BBBBF5BF00CADFBDA3184E4000035ABA822DF7BF0815C78157134E4000B1A19BFD41F7BFA8622AFD84134E4000B48D3F51D9F7BF08A0C37C79154E4000412D060F53F8BF586D37C137174E4000B5FB55806FF8BFA89B8BBFED174E4000C51858C771F8BF109D82FC6C184E40001E4E603A6DF8BFE0F71A82E3184E4000301004C850F8BFD8EE5701BE194E4000963FDF166CF9BFD8C77C40A01B4E400017D1764C5DFABFA8716F7EC31C4E400014AE47E17AFABF283B3602F11C4E4000E72E89B3A2FABF600438BD8B1D4E4000361FD786CAFABF2829B000A61E4E4000B48D3F51D9FABFF820CB82891F4E4000BF64E3C116FBBF8815E0BBCD234E40003556629E15FBBF28F6D03E56244E4000067DE9ED0FFBBF503A58FFE7244E4000B13385CEABFABF6076FA415D264E40009CBCC8047CFABFE0F19881CA264E400070CFF3A70DFABFB85626FC52274E4000A339B2F28BF9BFD0BB783F6E274E4000B5FB55806FF9BF606D37C137274E4000108B187698F7BFA8B393C151284E4000A4A7C82122F7BFF82F1004C8284E400092533BC3D4F6BFE8A9F23D23294E4000857D3B8988F5BFA8622AFD842B4E40000CFAD2DB1FF5BFB068ACFD9D2D4E4000A4A7C82122F7BF901EA33CF33A4E40004F95EF1909F8BFB0A78FC01F3C4E40004B3B3597DBF8BF90397AFCDE3C4E4000717495EEEEF8BF30232E008D3C4E4000D7A3703D0AF9BF30232E008D3C4E40006D1ADB6BC1F9BF600DFB3DB13C4E4000AD105663C9F9BF809FAA42033D4E4000F5285C8FC2F9BFA068ACFD9D3D4E400025CB49287DF9BF28E109BDFE404E40005E7B6649C0F8BFF8230C0396444E400017080264A8F6BF081B4982704D4E4000D3122BA391F6BF10CD203EB04D4E400093533BC3D4F4BF10C11C3D7E514E40003D4162BBBBF4BF100F45813E514E4000FFC874E8B4F4BF00301004C8504E40009A99999999F4BF8060C77F814E4E4000C64FE3DEBCF4BFA877F17EDC3E4E4001030000000100000019000000000491459A78F0BFA8BC5642773F4E4000BFD2F9F0ACF1BF58499D80263E4E4000D6A3703D0AF2BF70AEEFC3413E4E40000AD7A3703DF2BF3829B000A63E4E4000698995D148F2BF2841B8020A3F4E4000A7936C75B9F2BFB8DDAF027C434E400052B81E85EBF2BF78A86DC3284C4E4000F9821612F0F2BF386893C3274D4E4000AAED26F8E6F2BFD0D38041D24F4E4000E466B801DFF2BF385C8FC2F5504E40001A62BCE6D5F2BF10C11C3D7E514E4000F5285C8FC2F1BF603A58FFE75C4E40006AC020E993F1BFF81A4982705D4E400013AE47E17AF1BFB868ACFD9D5D4E400006B474055BF1BF0848A643A75D4E4000BB0A293FE9F0BF500438BD8B5D4E4000124031B2E4EFBFB8716F7EC35C4E400096766A2EB7EFBF80A86DC3285C4E40003E0AD7A370EFBFA87A32FFE8534E40004E27D9EA72EFBF109A417C60534E40006A8995D148F0BF101E8A027D424E400098620E824EF0BF883CBB7CEB414E400028EE78935FF0BF0818080264404E4000778368AD68F0BF5037177FDB3F4E40000491459A78F0BFA8BC5642773F4E400103000000010000001000000000FAB9A1293BEABF90C9C6832D584E40001E85EB51B8EABFE8AC33BE2F564E400074F22213F0EDBF109700FC53564E4000BED2F9F0ACEEBF905704FF5B574E40009A4EB2D5E5EEBFE08558FD11584E40000C68E90AB6EEBF386211C30E5B4E400060B2F1600BEEBF10CD203EB0654E40002A11A8FE41ECBF9015E0BBCD6B4E4000ECBFCE4D1BECBFE0A6B1BD166C4E400044BE4BA9CBE9BF00C79E3D976B4E40002EA2ED98BAE8BFE0B837BF616A4E4000D2122BA391E8BF10068200196A4E40002C11A8FE41E8BFD0CABDC0AC684E4000FAB9A1293BE8BF80C9C6832D684E4000B4FB55806FE8BF480438BD8B654E4000FAB9A1293BEABF90C9C6832D584E40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('UP','UA','UKR','804','Ukraine','57935','46917544','150','151','31.388','49.016','0106000020E61000000400000001030000000100000012000000386893C327854040007F6ABC74014740E0E2C5C210814040080F45813E014740F0EDEBC0397D404048E3DEFC86014740C8D3F2035773404048C5C6BC8E02474078ABAE43356140409087A2409F044740200ED940BA6C4040A07AA4C16D074740101B4982706D4040A8BC56427707474060BF44BC757040408890D78349074740806308008E7B4040583448C153064740F8F6AE415F7C4040B8AD11C138064740081286014B864040F8F6AE415F0447400079E8BB5B87404030179CC1DF034740E0A623809B874040F8FF71C284034740000C76C3B687404028A5D93C0E034740F820CB8289874040F8083543AA024740602B85402E874040E0F10A444F024740204A7B832F86404088758E01D9014740386893C327854040007F6ABC740147400103000000010000001B0000003026E1421E1D4140805AB741ED07474058310741471941405070EA03C90747400003B3429118414078DF313CF607474080A52C431C174140202F3201BF084740F805F4C29D15414070A2EBC20F0A47405846CEC29E1441407084D382170B4740A8923A014D144140209C16BCE80B4740602EC6C03A144140D0D6C1C1DE0C4740A8923A014D14414008D99601670D4740E0A96400A81441405861A5828A0E4740705DF8C1F9144140D8DC43C2F70E4740302FA4C3431C4140200B98C0AD174740B0AA4203B11C414080DF313CF6174740A07422C1541D4140E043A67C08184740708192020B1E4140F8F62004E4174740F8298E03AF1E4140D0C7EE0225174740D0C7EE02251F4140303526C45C164740D8EE5701BE214140A81AF67B6211474078758E01D9214140309F573CF510474088FA08FCE121414050BF44BC7510474080ABAE4335214140C8BBEA01F30A474020473A0323214140A03E90BC730A4740301ADD41EC204140D85E7D3CF409474080C9C6832D20414078ABAE433509474098B0C403CA1E4140F05AD07B63084740D8D0B1834A1E4140F8EAAA402D0847403026E1421E1D4140805AB741ED0747400103000000010000002E000000583D0B427915404008093543AA124740300516C094154040A0B915C26A12474058378941600B404050732B84D51447405876FA415D064040D83D247CEF15474020335184D4F53F402050FD834818474050711C78B5E03F400012F8C3CF194740202DCF83BBDB3F40E0066003221A4740C0F5B704E0CB3F40A8D11DC4CE1A474000575D876AC23F40E0E847C3291B4740E0F10A444FBA3F40302CF180B21B4740F0F57D3848B03F4078724D81CC1C474020809BC58B953F40483ACAC16C20474090DBBE47FD913F4030473A0323214740104C8BFA248F3F40E05E7D3CF4214740200516C0948D3F4060C5C6BC8E224740E055BABBCE8A3F40209C16BCE823474080B8E4B853863F402899D53BDC26474070D2FBC6D7823F40A8C2D842902947401060200890813F40506DA983BC2A474070D4997B48803F40283B3602F12C47401000000000803F40603448C1532E474070D4997B48803F4080FD497CEE2E4740B0EF3504C7813F40E0A623809B2F474080992842EA823F40886F0C01C02F4740200C040132843F4050438D42922F474030895E46B1843F40602B85402E2F474080B8E4B853863F4080698A00A72D4740105A9E0777873F40A07DE5417A2C4740409E25C808883F40D8C77C40A02B4740C0E0F08288883F40306BD443342A474070CC79C6BE883F40584F1F813F284740A010018750893F405858E2016527474090A99F37158D3F40D8EEC9C342254740E0419605138F3F4050707841442447401015C78157933F40E0D03FC1C52247406058E20165973F40C8EE5701BE214740909FAA42039D3F400803B3429120474070BD3445809F3F4090C9C6832D204740204AED45B4B13F4078543541D41D4740E0F78C4468B43F4050C2853C821D4740F04A598638BE3F40287EFE7BF01C4740B0FE7A8505DB3F40A0C85A43A91B474088DCF0BBE90A4040B0C519C39C164740282FA4C3430C4040081286014B164740B09E3E027F10404080724D81CC144740583D0B427915404008093543AA124740010300000001000000830A0000B8BC564277B54040C87F48BF7D2D4A4000274D83A2C1404038D8463CD9294A40789FAA4203CD4040081E8A027D2A4A40E09D60FF75D04040F0B1497EC42B4A40D08E1B7E37D7404030327381CB2D4A4020473A0323D94040101286014B2E4A400818080264E04040482B85402E2F4A40586DA983BCE24040D88E1B7E372F4A40382F3201BFE84040D8DC43C2F72E4A408854C37E4FEA4040002A8E03AF2E4A40F899417C60EB404050499D80262E4A40A88FF98040074140E873D2FBC6194A408818213CDA084140109D82FC6C184A40A0BF97C2830C4140A89BFD8172134A40503A58FFE70C414038085740A1124A4008D6E3BED50C4140802766BD18124A40D88BDAFD2A0A4140E08558FD11104A40608BC1C3B4094140E0DC43C2F70E4A4068F833BC59094140B06E2EFEB6074A4010C11C3D7E09414030F38FBE49074A40286BD443340A4140B0E3310395054A40504CDE00330B4140E0DF844204044A403802D53F88104140A8AD11C138FE494058137D3ECA1E4140C8A96400A8F4494028BA2EFCE02A414020327381CBED494038FF93BF7B2B4140507FBDC282ED4940D8CA4BFE2731414058FBE6FEEAEB4940E0CDFE40B9354140F820CB8289E74940D897DEFE5C364140009700FC53E649408039ECBE63384140A08CB80034E2494050ECA17DAC38414058F833BC59E1494058672783A3384140B8B393C151E049407887140324384140B84A94BDA5DE4940B0BC564277374140A053573ECBDD4940B068ACFD9D354140C8A96400A8DC4940B07A32FFE833414088008BFCFADB4940B8A10DC006324140B0622AFD84DB4940786649809A3041401015C78157DB4940D0CABDC0AC20414050103CBEBDD94940E0949D7E5019414028CCB4FD2BD94940F0298E03AF0E4140882AA73D25D74940487FBDC2820D4140588E0244C1D64940306893C3270D4140F89600FC53D64940600DFB3DB10C4140D0EEC9C342D54940B84412BD8C0C4140B84DD53DB2D34940203B3602F10C414030BA2EFCE0D24940D0B5F63E550D414010A304FD85D24940D0D6C1C1DE144140002A8E03AFCE494050EFE2FDB81D414050FB743C66C64940C87FD6FCF81D4140D07FD6FCF8C54940A8AD11C1381E4140D888997D1EC5494078A52C431C1F4140303E7782FDC1494060DD5CFC6D1F414078C9C6832DC04940A841D13C801F4140C88E1B7E37BF494058137D3ECA1E4140D0D38041D2B7494098C519C39C1E4140608E0244C1B64940201ADD41EC304140D8EE5701BEA149403044F98216344140D8EE5701BEA14940F8FC3042784641408896E7C1DD9D4940B0CEDC43C2554140D8DC43C2F7964940D097DEFE5C564140F8AE08FEB7964940886CCB80B35A4140101286014B96494008E52840145E414008E5284014964940D006600322624140601C40BFEF9549405861A5828A664140B0AD11C13896494008D9243FE269414058137D3ECA96494010A0C37C797541408030293E3E994940E0E506431D76414000FAEFC16B994940F8F36DC15277414058DA1B7C619A4940E070033E3F784140D8C77C40A09B49405831074147794140F8C95180289C494038085740A17A4140485B2382719C494088724D81CC7C414008A986FD9E9C4940989BFD8172894140C8D7497D599C494038C9737D1F8A4140388908FF229C4940E070033E3F8E4140E8154F3DD29A49407069FCC22B8F4140C84C4D82379A494030E4BCFF8F8F414038B9A6406699494028FCC401F48F41400866DAFE95974940B05F5B3FFD8F4140C064E3C116974940B05F5B3FFD8F4140F0094B3CA09649403032E543508F4140E85AB4006D934940D0C16C020C9341403856293DD3894940B0A17F828B93414098C360FE0A894940B083674293944140909FC6BDF9874940D058FB3BDB954140C0E07EC003874940D0ACA580B497414098B14CBF44864940D80CE2033B9A41406085CD001786494038FC523F6F9C4140304DD87E32864940100F45813E9F4140E0006C4084864940083FE3C281A44140B0E331039587494088A8FB00A4A64140B0CEDC43C2874940E857E542E5AD41403087C1FC15864940F0662AC423AF4140A086A8C29F854940686743FE99AF414078F4F8BD4D85494068ACA8C134B0414050C5C6BC8E8449401075914259B04140A00854FF2084494038C2DB8310B0414070274A4222834940D818028063AF41403093C5FD47824940E857E542E5AD414020170E846481494018698D4127AC4140B0353FFED280494030682101A3A74140504F9143C47D494068880E8123A74140201ADD41EC7A4940686A847EA6AC4140D076F700DD774940B040BB438AAD4140D031923D42774940086F0F4240AE4140002522FC8B764940E84E22C2BFAE4140489259BDC375494040BCE7C072BA4140C0DAFCBFEA624940509B1C3EE9BA4140C0AAECBB2262494040B324404DBB414038B39602D260494070AF05BD37BE41406097E13FDD56494098F37002D3B5414088E76C01A15349403826FDBD14B44140C0E3DBBB0653494080E15CC30CB34140C07F2C448752494088C954C1A8B24140C0EC9E3C2C524940B8169F0260B24140E00C8CBCAC51494000D3307C44B2414008A8FE4124514940605E807D74B8414010C0064488414940382C0DFCA8BA4140B81C2103793E494050BC033C69CB4140B0380EBC5A304940008B6EBDA6CD414028F38FBE492F494010A304FD85D24140E0B5F63E552D494030FC523F6FD64140585B2382712C49408021E4BCFFD74140F8F6AE415F2C4940508F183DB7D84140801E15FF772C4940A0C519C39CDE414080457EFD10314940580ABABDA4DF4140A8C2D8429031494090457EFD10E941409096E7C1DD354940A8D11DC4CEEA414038FC523F6F36494008D6E3BED5EC4140B877F17EDC364940D876137CD3EE4140902AA73D25374940A83E90BC73F24140B8BC56427737494000AF08FEB7F641406070EA03C9374940D8EEC9C342FD4140A88636001B38494030E109BDFE004240E0EB884336384940D8A623809B074240280B98C0AD374940F8B1497EC40B4240E009A1832E374940A874B0FECF11424038FC523F6F3649406007793D9812424080AEEFC341364940E0B22781CD134240A0CEDC43C2354940580ABABDA4174240B0C85A43A9334940A88636001B1842407036AB3E57334940A8380EBC5A184240801EA33CF3324940A8380EBC5A184240283E7782FD31494000B58AFED0184240B0CB9BC3B5304940F8F02C41461A4240A877F17EDC2E4940D8C77C40A01B4240001B4982702D4940A883F57F0E23424058499D8026264940805A457F6824424090CC07043A25494008E5284014264240885A457F68244940508E0244C1264240802DE8BD31244940B8AAD0402C294240D87954FCDF2349405082FE428F2A4240E0DF844204244940785A457F682C4240D0BEB9BF7A24494048499D80262E42408024253D0C254940A88FF980402F424000A0C37C7925494008301004C830424078AEEFC341264940B0CEDC43C235424000EBAA402D28494048250340153D4240D8C43BC0932649407878CF81E5464240D87954FCDF2349400021CB8289474240A8C85A43A9234940A88636001B484240109A417C60234940E09D60FF75484240D882177D05234940E09D60FF75484240D0A3E2FF8E224940E0EB884336484240383E7782FD2149405858E20165474240C80F23844721494080AEEFC341464240D08558FD11204940D07FD6FCF845424010A6457D921F4940D07FD6FCF8454240A0C519C39C1E494038FC523F6F464240B053573ECB1D4940608E0244C1464240783C2D3F701D494080A52C431C47424058250340151D49409021E4BCFF47424060E09D7C7A1C494088ABAE433549424080008BFCFA1B494030BA2EFCE04A4240B0C85A43A91B4940D8A96400A84C4240009A417C601B494078A52C431C4F4240D0E847C3291B4940603D997FF4514240604CDE00331B4940504CDE003353424030FF93BF7B1B494050E960FD9F5342405016BEBED61B4940000FB743C354424020B7ED7BD41D4940B03B4F3C67554240608E0244C11E4940E0E506431D56424060853FC39B1F49405070EA03C957424008E2E7BF0721494050103CBEBD594240D88BDAFD2A2249405816BEBED65B4240E0E847C329234940B06E2EFEB6674240D8EB88433628494078ABAE4335714240601F813FFC2A494030E78BBD17734240089A417C602B49407845F0BF957C4240C8A96400A82C4940D0EEC9C3427D4240300ED940BA2C4940D07C957CEC804240C8A96400A82C4940089A417C6083424080A86DC3282C4940E0FA5B02F0854240504CDE00332B4940508E0244C186424008E869C0202B49408893A641D18842407836AB3E572B4940A8CB9BC3B590424000240C03962C494000B2497EC49B4240F8F36DC1522F4940F0298E03AF9E4240584F1F813F304940884E417E36A04240807E5182FE304940B06BED7DAAA24240A8B915C26A324940805182FE42A54240A84412BD8C344940B868ACFD9DA5424028C0B0FCF9344940D058FB3BDBA74240E0C43BC093364940109D82FC6CA8424058137D3ECA364940301DACFF73AA4240A8A44E4013374940300516C094B542401823A0C211384940886CCB80B3BA42402850FD834838494000E869C020BB424000BE4D7FF63749401015C78157BB42408042AF3F8937494008E869C020D34240F8A5457D9217494020B7ED7BD4DD4240284DBC033C0B4940A88FF98040DF42405855A181580A4940587C7C4276E04240A074B0FECF094940600438BD8BE542408818213CDA08494038F911BF62E942403038F581E4074940D8B5F63E55F54240F82CCF83BB03494038FC523F6FF64240D0E847C329034940B877F17EDCF642402835B401D802494080724D81CCFC4240A05C1ABFF0FC48409060C77F81FE4240484CDE0033FB4840D0EE5701BE014340D8A623809BF74840E06740BD1903434048C5AA4198F34840905182FE420D43408887140324F84840D809A1832E17434000BE4D7FF607494008A6457D921743408039ECBE63084940B88636001B184340B0656B7D91084940F8B48AFED0184340F8C9DFBDA3084940B04A94BDA5264340885D86FF740949405858E20165274340885D86FF7409494038E109BDFE284340B0AAD0402C094940802766BD182A4340886649809A084940F8A204FD852A43402050FD8348084940C8E847C3292B434008A6457D9207494020179CC1DF2B43405076FA415D06494070A86DC3282C4340587FBDC282054940E0D6C1C1DE2C4340009A417C600349408024253D0C2D4340081E8A027D024940E07FD6FCF82D4340607C7C42760049407860C77F812E4340A06E2EFEB6FF4840788714032430434050FB743C66FE48408054C37E4F324340A8CEDC43C2FD484030C632FD123F434078A2EBC20FFA4840D058FB3BDB3F434088758E01D9F94840283E7782FD414340E073D2FBC6F9484028E44A3D0B464340A88CB80034FA4840A853E57B464A434080B130444EFB4840802DE8BD314C4340C8C77C40A0FB48403829B000A64E4340089A417C60FB484038FF93BF7B53434010D061BEBCFA4840E0EB884336584340F00B76C3B6F74840588BC1C3B4694340F8B48AFED0F0484030DB87BCE56E434028BD6F7CEDEF4840A874B0FECF71434078A52C431CEF484038BA2EFCE072434008C45DBD8AEE484060E960FD9F7343408896E7C1DDED4840887B1002F2734340507FBDC282ED48408896E7C1DD754340801EA33CF3EA48405058E20165774340D8CABDC0ACE848406022C2BF0878434008BE4D7FF6E74840787E5182FE784340885704FF5BE74840B874B0FECF794340B08FF98040E7484088B130444E7B4340B08FF98040E7484028D8B8FE5D7D43405858E20165E74840D0A623809B8743408039ECBE63E848409018213CDA884340D8CABDC0ACE84840503D997FF489434080457EFD10E9484038BA2EFCE08A4340808AE3C0ABE9484008B2497EC48B4340D0B837BF61EA4840E0A623809B8F4340380516C094ED4840F8FF71C284974340600DFB3DB1F0484048ECA17DAC984340A8380EBC5AF0484050103CBEBD9943405870EA03C9EF48405007793D989A4340882AA73D25EF484090992842EA9A434058137D3ECAEE4840089700FC539E434010A6457D92E748407878CF81E59E4340881B62BCE6E54840A0BC5642779F4340B04DD53DB2E34840C800DE0209A0434008A304FD85E2484058465C001AA14340785D86FF74E14840E082177D05A34340604F1F813FE04840D8FA5B02F0A54340C88E1B7E37DF484080A2EBC20FAA4340109700FC53DE4840D0B5F63E55AD4340A853573ECBDD4840588E0244C1AE434030B7ED7BD4DD4840B88636001BB04340501C40BFEFDD4840303E7782FDB14340109700FC53DE4840502EC6C03AB44340802AA73D25DF4840F0EDEBC039B54340200B98C0ADDF4840D0BB783F6EB74340806649809AE04840E0D90242EBB9434060465C001AE14840D09A1F7F69BB434088457EFD10E1484028C0B0FCF9BC4340F82F1004C8E048405055A18158CA4340A0A17F828BDD4840A883F57F0ECB4340D8D6C1C1DEDC484018D236FE44CB434050E09D7C7ADC4840502EC6C03ACC4340B03E90BC73DA4840B85FE97C78CE4340380516C094D54840300B98C0ADCF434060103CBEBDD14840E08558FD11D04340A87D737FF5D048407818213CDAD04340D8D38041D2CF484010D9243FE2D1434058137D3ECACE48402835B401D8D2434050499D8026CE4840E0A96400A8D44340A83B4F3C67CD4840285FD04202E6434048137D3ECAC64840D0A623809BE7434030FC523F6FC64840B8AAD0402CE94340109700FC53C6484038622D3E05EE434040A79201A0C64840C8FD9C82FCF24340D8A623809BC74840E07FD6FCF8F543408839ECBE63C84840D8EB884336F84340A0AAD0402CC94840608BC1C3B4F94340303E7782FDC948405807793D98FA4340B06BED7DAACA484008CA518028FC4340D8915CFE43CC484010A0C37C79FD4340505260014CCD4840E0DC43C2F7FE43407848BF7D1DCE484008CADFBDA30044403029B000A6CE484008A0C37C7905444008DC65BFEECE4840382F3201BF084440B05FE97C78CE4840781805C1E3114440381D3A3DEFCC4840901EA33CF31244407884D38217CB4840504CDE0033134440D8B837BF61CA4840504CDE003313444008C11C3D7EC9484078992842EA1244408893A641D1C8484080A2EBC20F12444000A6457D92C74840F8B48AFED0104440A8C519C39CC64840905182FE420D4440001B498270C54840D8D03FC1C50A4440885A457F68C44840D0C1FA3F8709444050FEB5BC72C348409021E4BCFF074440E873D2FBC6C14840902AA73D25074440280B98C0ADBF484030145B41D306444000E5284014BE484058137D3ECA06444000EEEBC039BD484000DC65BFEE064440F87B293C68BC484050DD5CFC6D074440501F813FFCBA4840F899417C600B4440D897DEFE5CB6484028E44A3D0B0E4440B04DD53DB2B34840E0066003221244408887140324B04840D8DF844204144440808D2441B8AE48408096E7C1DD154440001B498270AD484070AEEFC34116444008D6E3BED5AC4840508E0244C1164440E09A1F7F69AB48405840DAFF0017444028D8463CD9A94840580438BD8B154440886649809AA04840B8B6D4415E154440D8D38041D29F484018DF347D760A44401003CFBD8797484000DC65BFEE064440001286014B96484058465C001A014440F8B1497EC4934840600ABABDA4FF4340881EA33CF392484088AEEFC341FE4340303E7782FD914840302CF180B2FB4340E058FB3BDB8F484058103CBEBDF9434028327381CB8D48407839ECBE63F84340E0DF8442048C4840A08636001BF84340901EA33CF38A4840D070033E3FF8434080A2EBC20F8A4840787E5182FEF84340E09D60FF75884840806649809AF843405858E2016587484000EBAA402DF843403841B8020A874840A85FE97C78F643408060C77F81864840605B238271F443405876FA415D86484030F911BF62E94340002A8E03AF8648404882FE428FDA4340500DFB3DB184484030C3F17C06DA4340B0BF97C283844840585E64027ED94340F8BA0CFFE982484038CCB4FD2BD9434030F911BF62814840A8CB9BC3B5D84340803C2D3F707D48406019FF3EE3D84340B04412BD8C7C4840A88CB80034E24340B84DD53DB2734840886308008EE34340584CDE0033734840286893C327E543406834D6FECE72484028266F8099F943403841B8020A6F4840C8EE5701BE01444078758E01D9714840586DA983BC024440D0B837BF61724840E07954FCDF034440786CCB80B3724840B0B6D4415E054440A06BED7DAA724840D8DC43C2F7064440F8F02C4146724840E0EB884336084440E873D2FBC671484008E2E7BF0709444020473A032371484008274D83A2094440089D82FC6C704840A874B0FECF0944409021E4BCFF6F484038D8463CD909444030C632FD126F4840A874B0FECF094440A0C519C39C6E484080457EFD10094440583A58FFE76C4840382F3201BF084440505B2382716C4840300B98C0AD07444000E869C0206B4840D8031F831505444020E109BDFE684840204DBC033C0344405070EA03C967484030F04E3E3D024440B08FF9804067484010C45DBD8AEE4340B07D737FF5684840F8D5E3BED5EC4340D80F238447694840381DACFF73EA4340A8C2D84290694840D873D2FBC6E94340D8C1FA3F8769484008BE4D7FF6E7434028473A03236948408078CF81E5E64340D8CABDC0AC684840782DE8BD31E44340508E0244C16648405825034015DD4340B0C2D84290614840C806600322DA434078008BFCFA5B48403044F98216D4434008DC65BFEE4E4840B87A32FFE8D34340E0FA5B02F04D4840A8923A014DD44340D888997D1E4D4840F0AF027CB7D54340606D37C1374B4840B0CEDC43C2DD43405882FE428F4A484060F833BC59E143405882FE428F4A4840D8DF844204E44340D0D03FC1C54A484088AEEFC341E64340B8E67283A14A4840A86E2EFEB6E74340386BD443344A4840C8F71A82E3E84340888AE3C0AB49484000DFA63FFBEB43408021E4BCFF474840603A58FFE7EC4340905704FF5B47484008EEEBC039ED4340D861BEBC00474840A83B4F3C67ED4340B0C519C39C46484028B7ED7BD4ED4340585260014C454840D061BEBC00EF43405001F73C7F404840D05E7D3CF4F54340B0897780272F4840D858FB3BDBFF434028E44A3D0B264840087F6ABC74F94340D8915CFE431C4840D079C6BE64F7434080B130444E1B4840703C2D3F70F5434030F911BF6219484030EA3E00A9F34340306E15C440174840C0D3F20357E34340009A417C60034840A86EA0C03BE34340881EA33CF30248408021567F84E343405007793D98024840803C2D3F70E54340E07C957CEC004840F878E8BB5BE743408890D78349FF474078DF313CF6E74340D8C43BC093FE4740C8F71A82E3E84340F8E159828CFC4740189F573CF5E843407866BB421FFC4740201ADD41ECE84340D0C77C40A0FB47408890D78349E74340E0EB884336F04740C8C7EE0225E74340300B98C0ADEF47408078CF81E5E6434080A52C431CEF4740E0FA5B02F0E54340D0CDFE40B9ED474088008BFCFAE34340E0B22781CDEB4740E0F10A444FE24340A8B915C26AEA4740A8957B8159E1434078FA08FCE1E94740D8C43BC093DE4340209F573CF5E84740D8A96400A8DC4340202F3201BFE8474008301004C8D8434078ABAE4335E94740101286014BD64340808AE3C0ABE94740D8F10A444FD24340B0A4C00298EA4740284A7B832FCE4340D8D3F20357EB4740A0AA4203B1CC4340A89BFD8172EB474008D9960167BD4340A89BFD8172EB4740F8F36DC152B74340A8B915C26AEA474008E5284014B64340788D96033DEA4740A0AA4203B1B44340386BD44334EA4740D09DD2C1FAB34340A8B915C26AEA4740D0BBEA01F3B24340D84065FCFBEA474098AD8383BDB14340887B1002F2EB474098CB9BC3B5B04340B0BF97C283EC4740A098BC0166AE4340D0C16C020CED4740C8CA2F8331AC4340788A558330ED474008274D83A2A1434008EEEBC039ED474040438D42929F43403026E1421EED4740D0EB884336984340209C16BCE8EB4740D8D03FC1C59243402835B401D8EA4740087F6ABC74914340586DA983BCEA4740D0D38041D28F4340D84065FCFBEA4740F0FC3042788E434058BC033C69EB474018D82AC1E284434068F46A80D2EE4740203526C45C764340D8C7EE0225EF47402835B401D8724340D8C7EE0225EF4740D0A623809B6F4340A0B0C403CAEE4740B098BC01666E43400882AB3C81EE4740E0EEC9C3426D4340204A7B832FEE474080B130444E6B4340206893C327ED474078A2EBC20F6A43407066BB421FEC47400803B3429168434048404CC285EA47402026E1421E654340F8EA1C03B2E34740706CCB80B362434078E272BC02DD474058404CC285624340000072C284DB4740A8A10DC006624340F8F9EFC16BD94740585E64027E614340F0D555815AD84740886649809A604340706F0C01C0D747403023A0C211604340086493FC88D74740082A8E03AF4E4340B8A10DC006D24740A0A17F828B4D434050490F43ABD14740D8D90242EB494340189F573CF5D04740F00EB743C3444340F05AD07B63D0474060672783A3404340584F1F813FD047400882AB3C813E43403050FD8348D04740586DA983BC3A43400803B34291D04740401CB28174394340403ACAC16CD0474070637AC2122F43406061A5828ACE47408896E7C1DD2D434088AEEFC341CE474080724D81CC2C43408096E7C1DDCD4740A09BFD81722B434030C0B0FCF9CC474030145B41D3264340F0DE180280C74740204A7B832F264340B0C519C39CC64740887B1002F223434008301004C8C047400867D47C951C4340000072C284AB47405861A5828A2643405861A5828AA64740A89E3E027F204340808A5583309D47400006F4C29D1D43405864E602979B4740A802603C831C4340B0B915C26A9A4740A0C85A43A91B4340281ADD41EC984740B09BFD81721B434000D655815A98474060BC033C691B43404858E20165974740D8D6C1C1DE1C434008D655815A904740284A7B832F1E434028A298BC018E4740F8F9EFC16B114340D0A623809B8747404852D2C3D0104340B8B393C15188474058E3DEFC860943407066BB421F8C4740382F3201BF084340D0CA2F83318C4740E0D03FC1C5F24240505B2382718C4740808192020BEE4240007C293C688C4740E04065FCFBEA424028179CC1DF8B4740B0C519C39CE64240A8B915C26A8A4740A0A4C00298E24240B01AF67B62894740E0EB884336E04240201ADD41EC8847407078CF81E5DE4240F02F1004C8884740D8FD9C82FCD2424038266F809989474018A298BC01CE4240D84065FCFB8A4740585E64027EC94240D0D3F203578B47407887140324C8424078B130444E8B4740D0DC43C2F7C6424028205F42058B4740C8B8A981E6C54240A8A4C002988A474028C0B0FCF9C4424088A2EBC20F8A4740885776C1E0BA424008FAEFC16B81474050DA1B7C61B24240585E64027E794740F87E6ABC74A9424038085740A1724740A0957B8159A942408884D382177347407803CC7C07A94240A89BFD8172734740A8E0F08288A84240F0EA1C03B27347405073B9C150A142403041B8020A7747402823A0C211A04240B0BC564277774740A8C519C39C9E424050438D4292774740F0F02C41469A42402099D53BDC7647407887140324984240D8E506431D764740B8A10DC0068A42402832E54350714740206211C30E854240E07954FCDF6F474078A52C431C7F4240A8CEDC43C26D474030327381CB754240E05E7D3CF4694740D0D6C1C1DE744240A01AF67B62694740D843A67C08704240285FD0420266474058499D80266E4240605B23827164474030111AC1C6614240788714032460474060853FC39B5F4240908AE3C0AB61474080AEEFC3415E424080A2EBC20F6247406055A181585A42403835B401D8624740D03AE3FBE258424088DCF0BBE96247405061A5828A4E4240284DBC033C63474098D11DC4CE424240886649809A604740C8E2C5C21041424080C9C6832D60474058D7DAFB54354240200ED940BA5C474030085740A1324240D8B22781CD5B47401823A0C211304240506DA983BC5A474030327381CB2D42402832E5435059474028C0B0FCF92C4240A089E942AC5847408078CF81E51E42405052D2C3D0504740D0D0B1834A1E4240505E64027E514740A8C85A43A91B4240202FA4C343544740B8B05241451B42400867D47C95544740585E64027E194240505260014C55474080DF313CF6174240F81A49827055474050672783A308424030327381CB5547407866BB421FF44140D8D3F20357534740D0CABDC0ACE8414000DF1802804F4740D0C7EE0225E741403099D53BDC4E4740D0F10A444FE24140F07B293C684C47400018080264E0414050378941604B4740606A6803B0DD4140908AE3C0AB494740D0D6C1C1DEDC41408803CC7C07494740505E64027ED94140E0CDFE40B9454740A086A8C29FD34140A09E3E027F404740606DA983BCD24140785AB741ED3F4740005BD07B63D04140A0C519C39C3E4740A8A4C00298CA4140505B2382713C47400879E8BB5BC74140A8B05241453B4740D0C16C020CC54140806CCB80B33A4740204DBC033CC34140A0776341613A474008FAEFC16BC14140A08CB800343A4740A08FF98040BF4140481CB28174394740283526C45CBE4140D83AE3FBE2384740B089778027BD4140F0F62004E4374740D8031F8315AD4140B83E90BC732A4740E05D6743FEA3414080E42B8194204740D0F10A444F9A4140E0D6C1C1DE144740988026C2869941402844F982161447408072BF435198414018A5D93C0E134740503448C153964140F8F9EFC16B114740303B3602F1944140886649809A104740A020787C7B9341403838F581E40F4740805AB741ED8F4140B098BC01660E4740B0957B8159814140B0C2D84290094740E0EB884336804140D80F238447094740F8E7DB82A57E4140F87E6ABC74094740D8E506431D7E4140588BC1C3B4094740787500C45D7D414058DA1B7C610A4740787500C45D7D41402835B401D80A4740B0A17F828B7D414058BC033C690B47400806F4C29D854140605E64027E114740F8E42840148641400812F8C3CF11474050438D4292874140F8DBD78173124740A0CB9BC3B5884140D8D03FC1C512474030A298BC018E4140309C16BCE8134740302922C32A924140F00EB743C3144740B0AA4203B19441402826E1421E154740D8DC43C2F7964140E0CDFE40B915474050BF44BC75984140A898BC016616474030111AC1C6994140386E15C44017474040404CC2859A414080DF313CF6174740886F0C01C09F41408096E7C1DD1D4740604F1F813FA241402012A27C41214740D0B22781CDA34140D8F10A444F2247409087A2409FA44140C8BBEA01F3224740A03E90BC73AA414008301004C828474000E869C020AB4140A8C2D84290294740A87DE5417AAC414078008BFCFA2B4740E0A96400A8AC414000E259828C2C47405046CEC29EAC4140C8C16C020C2D4740007C293C68AC4140081B4982702D474098957B8159994140F0ED5D83BE384740B020787C7B9B4140808A558330354740F02CCF83BB9B4140A8B30584D6334740D04065FCFB9A41405055A1815832474030266F8099994140F8ED5D83BE30474000F46DC1528F4140503448C15326474090C9C6832D8E4140A0A70183A4254740F80B76C3B6874140B0C2D84290214740B0B0C403CA8641408003CC7C07214740E0D6C1C1DE844140D0EB884336204740D8B22781CD834140E0D38041D21F4740D0BE2B82FF674140302C634337174740D0D90242EB5941400082AB3C81164740D0CABDC0AC504140D0D6C1C1DE0C4740D8E2C5C210514140A8A4C002980A4740301ADD41EC504140B0C2D84290094740D0CABDC0AC504140D0E2C5C210094740604CDE00334B414058672783A3004740D85E7D3CF44941408878CF81E5FE464058465C001A494140603448C153FE46403838F581E4474140F8E4284014FE4640E0FA5B02F0454140E0B8A981E6FD4640B8BF97C283444140D83D247CEFFD4640604F1F813F404140D0D0B1834AFE46403026E1421E3541403023A0C2110047404019710168344140484F1F813F004740786308008E334140C8B56801DA00474058BC033C6933414028111AC1C6014740A020787C7B33414008F12C4146024740F82CCF83BB334140D0D03FC1C5024740B09E3E027F384140D0DF8442040C474068DC9BDF303B41403096CD1C920C4740C88EC6A17E3D4140C00DF8FC300E4740B0AAECBB223E414048197101680E474020CFA0A17F3E414048197101680E4740386211C30E414140D897DEFE5C0E4740B03A394371414140807E18213C0E474040897AC1A741414028BDE13E720D474010F775E09C41414088E7DEC3250D4740787B1002F243414078931804560C4740F8F6AE415F444140080072C2840B4740D8D6C1C1DE444140184DBC033C0B47400006F4C29D4541407084D382170B4740B0AD11C138464140D0E847C3290B4740484C50C3B746414060378941600B474088A52C431C474140F82CCF83BB0B4740B08636001B48414028C0B0FCF90C474048672783A3484140D0B8A981E60D4740807E5182FE484140F8DE1802800F474008274D83A2494140D8BBEA01F312474038266F809949414050BC033C69134740605E64027E494140B0B30584D6134740B8AAD0402C494140282FA4C343144740082A8E03AF464140A0A44E4013174740181D1EC2F8454140F80B76C3B6174740001B498270454140D0BE2B82FF174740A0AA4203B1444140E043A67C081847407866BB421F444140F8F62004E41747405037894160434140D0C7EE0225174740B8FE08C3803D41402893FE5E0A154740E8851F9C4F3D414030C32ADEC8144740204850FC183D414060855B3E921447404813EF004F3C41408820CEC3091447403092CB7F483B4140902023A0C2134740F8DBD781733A414028CF6740BD134740086C0723F6394140D8E2FE23D3134740302922C32A2A414028327381CB154740E061BEBC001F4140D8D6C1C1DE1C4740603448C1531E4140A0A17F828B1D4740A0776341611A4140A0AAD0402C214740200E4B033F184140586DA983BC224740002A8E03AF164140F0FF71C284234740280ED940BA14414078A86DC328244740D8DF8442041441407066BB421F244740F8FF71C284134140209C16BCE823474000D655815A104140A8776341611A47408078CF81E50E4140605260014C15474020F64201DB0F4140200ED940BA14474000EBAA402D10414000F7AE415F144740A023B9FC87104140906308008E134740F8264D83A2114140A88636001B104740B0C2D84290114140C8A623809B0F4740F0ED5D83BE10414088FD497CEE0E4740B88636001B1041402899D53BDC0E4740A8BC5642770F414088FD497CEE0E474000F7AE415F044140181ADD41EC104740807B1002F203414088ABAE4335114740A0A70183A4FF4040888A558330154740D0C43BC093FE4040A8AD11C138164740280516C094FD40402050FD8348184740A87422C154FD404020473A0323194740F0E159828CFC404008F12C41461A4740282CF180B2FB4040885776C1E01A474050404CC285FA40401015C781571B4740584F9143C4E34040806F0C01C01F474028205F4205E340405070EA03C91F4740101E8A027DE24040806F0C01C01F4740704E250340D74040F8F6AE415F1C474020A298BC01D64040202FA4C3431C474080698A00A7D54040289C16BCE81B4740506A6803B0D54040B09BFD81721B4740A8AD11C138D64040886CCB80B31A474080FA08FCE1D9404080698A00A7154740D0D03FC1C5DA4040F866D47C95144740A0AA4203B1DC4040C8FD9C82FC12474010E5284014DE4040D00660032212474098C85A43A9E34040B08FF980400F4740789FAA4203E54040482B85402E0F4740587FBDC282E54040B07AA4C16D0F474080AEEFC341E640408087140324104740D0C43BC093E64040B0AAD0402C114740608E0244C1E64040506DA983BC124740A0B0C403CAE64040582EC6C03A144740A0C519C39CE64040A089778027154740002A8E03AFE6404060499D8026164740502B85402EE74040A898BC01661647406070EA03C9E74040304A7B832F164740200247020DEC4040D8A96400A8144740A07DE5417AEC404000F7AE415F14474080ABAE4335F14040588BC1C3B40947402032E54350F14040000F45813E094740E00F238447F14040584F1F813F084740A823B9FC87F040400821CB8289074740504CDE0033F34040383B3602F10447405882FE428FFA404008F12C4146024740A8B0524145FB40400806820019024740E0A96400A8FC4040E00660032202474008EEEBC039FD4040E0F10A444F024740D0C43BC093FE4040D8E847C329034740488E0244C1FE4040F8EA1C03B2034740505260014CFF4040F0B12D03CE0847408090D78349FF4040189F573CF50847407878CF81E5FE4040D80F238447094740A87422C154FD4040B0C2D84290094740A077634161FA4040808AE3C0AB094740281ADD41ECF84040B8A10DC0060A474000EBAA402DF84040F0083543AA0A4740D843A67C08F840407084D382170B474000EBAA402DF84040806308008E0B4740483ACAC16CF84040280247020D0C4740E0B56801DAF8404078931804560C4740D0D90242EBF94040280ED940BA0C4740D8E847C329FB4040E05B3CBCE70C4740488E0244C1FE4040D0D6C1C1DE0C47402850FD8348004140F80EB743C30C4740D8B56801DA0041405046CEC29E0C47402035B401D8024140806308008E0B4740F8094B3CA00E4140889F71E140024740C8C7EE02250F4140D0EEC9C342FD4640F881AB3C810E4140A089778027FD4640303526C45C0E4140A8AA4203B1FC4640808D2441B80E414020179CC1DFFB4640A08FF980400F4140F8E769C020FB464008FAEFC16B11414060672783A3F8464008F12C4146124140D043A67C08F84640A820787C7B13414028F64201DBF7464088543541D4154140E0EB884336F84640E0EB884336184140A8CB9BC3B5F84640C8CD70033E194140E0E2C5C210F94640508BC1C3B4194140A81AF67B62F94640283E7782FD1941400812F8C3CFF94640D0066003221A41403835B401D8FA4640D85E7D3CF4194140282FA4C343FC4640A8C2D842901941400082AB3C81FE46402832E543501941405058E20165FF46408069FCC22B194140806F0C01C0FF4640C0D7F4A0A01C4140D812F241CF004740E8429083121C4140688B6B7C2601474008789961A3184140E0730B5D89024740B8BF2500FF164140C89750C1E1034740F82422FC8B164140D8915CFE4304474078D3669C86164140C004A73E90044740E8815660C816414008C1E3DBBB044740A0FFC9DFBD174140F0C682C2A0044740B07DE5417A2C414080DCF0BBE90247400006F4C29D2D414008DCD78173024740082A8E03AF2E4140007F6ABC74014740D8B56801DA304140E061BEBC00FF4640200ED940BA3441405855A18158FA4640D8EEC9C34235414008274D83A2F94640485260014C35414028473A0323F946403026E1421E3541400003B34291F84640209C16BCE83341402899D53BDCF64640A020787C7B3341405861A5828AF64640A8B915C26A324140204A7B832FF646407803CC7C0731414048499D8026F64640B023B9FC87304140E03D247CEFF54640D8D38041D22F4140D8EEC9C342F5464088543541D42D4140F0264D83A2F14640606A6803B02D4140B8AAD0402CF1464028A298BC012E41405052D2C3D0F04640D8C43BC0933E4140D8D38041D2EF464000F46DC1523F41405070EA03C9EF464008180802644041408887140324F04640A8CB9BC3B5484140A889778027F5464028473A0323494140101B498270F54640605E64027E49414030327381CBF54640A8AD8383BD494140101286014BF64640605E64027E494140E009A1832EF74640D00F23844749414058438D4292F74640382F3201BF4841408072BF4351F84640001B498270454140584CDE0033FB464048D7DAFB54454140D8C77C40A0FB4640D0B8A981E6454140484F9143C4FB464000E8DB82A5464140F02CCF83BBFB4640E0C43BC0934E4140A81AF67B62F94640D8E2C5C210514140B023B9FC87F84640087F6ABC74514140200E4B033FF8464058490F43AB514140D0D38041D2F74640488BC1C3B45141400879E8BB5BF746402032E54350514140203526C45CF646402850FD83485041404819710168F44640F0FC3042784E4140F0264D83A2F146409096E7C1DD4D4140F82F1004C8F04640789FAA42034D41402823A0C211F04640A020787C7B4B4140A8BC564277EF46407896E7C1DD454140D0B22781CDEB4640284DBC033C3B414050BC033C69E346403835B401D83A414020205F4205E34640786CCB80B33A4140A0A4C00298E24640D8BBEA01F33A4140B08CB80034E24640382CF180B23B4140C806600322E246408084D3821753414038232E008DE44640B0BF97C283644140E0C77C40A0DB4640785DF8C1F9744140000FB743C3D44640D8D0B1834A7E4140D83AE3FBE2D04640282F3201BF8841407078CF81E5C64640A8957B8159894140204A7B832FC64640F8083543AA8A4140B0B30584D6C34640E04065FCFB8A414048404CC285C24640087C293C688C41408093180456BC464080931804568C4140D0B22781CDBB4640404F9143C48B4140885776C1E0BA464060BC033C698B414050404CC285BA4640A0AD8383BD8941401832E54350B94640504C50C3B7864140D843A67C08B84640C8C16C020C854140D8A623809BB74640A0A4C00298824140302C634337B74640C806600322824140C8DC43C2F7B64640D8EE5701BE814140B0C519C39CB64640585E64027E814140D0E506431DB6464050E3DEFC8681414078698A00A7B546402099D53BDC864140182C634337AF464000EBAA402D884140603448C153AE46403829B000A68E414058DA1B7C61AA4640D0EB884336904140A8AD8383BDA946408003CC7C0791414038266F8099A94640A020787C7B934140806CCB80B3AA4640D0C16C020C954140706F7EC344AB4640D0CDFE40B995414078B130444EAB46408090D783499741408884D38217AB4640D8D3F20357AB41408887A2409FA44640209C16BCE8AB41405082FE428FAA4640A88C2AC3B89D414098CB9BC3B5B84640A0D11DC4CE924140080072C284C34640787B1002F28B4140286BD44334CA4640F81D8A027D8A4140000072C284CB4640B0BC564277874140300516C094CD4640A01D37FC6E864140D8C43BC093CE46402850FD834880414030A298BC01D64640A0CEDC43C27D41403032E54350D94640A87422C1547D4140C8C4AD8218DA46409859BDC3ED7A4140288CBB41B4DE464030473A0323794140A0E0F08288E04640E0DFD91EBD734140C0A354C213E84640408CBB41B46E4140A0205C0185EE464010691B7FA26C4140B82B2D23F5F24640808AE3C0AB614140303E7782FD014740D8B56801DA604140A8957B8159014740B8B393C151604140A8AAD0402C014740A8A70183A45F4140E00F238447014740584F9143C45B4140787B1002F203474050490F43AB594140E0FA5B02F0054740605260014C55414058DA1B7C610A4740080FB743C354414000E869C0200B474078E272BC02554140E0C77C40A00B4740A8B6D4415E55414080008BFCFA0B47408896E7C1DD554140D0CA2F83310C4740A0A17F828B5D414088543541D40D4740B0AD11C1385E41409096E7C1DD0D474040E7525C55664140B80DDC813A0B474000705E9CF8684140D09D279EB309474088FA08FCE1694140C8F71A82E3084740888A5583306D4140386552431B004740808D2441B86E4140584CDE0033FB4640E80F069E7B7341401045F30016F14640302026E142784140F83C2AFEEFE84640787500C45D7D4140503ACAC16CE04640F0240681957D4140A06B5F402FE046402899D53BDC7E41409096E7C1DDDD46408878CF81E5864140F8EA1C03B2D34640483ACAC16C884140D0D90242EBD14640608BC1C3B4894140A023B9FC87D046403038F581E49F41407069FCC22BB946402838F581E4A741408803CC7C07B1464080758E01D9A94140B0BC564277AF4640788192020BAE4140303B3602F1AC4640807E5182FEB04140D0D3F20357AB4640D8C4AD8218BA4140F8FC304278A6464008E869C020BB4140D8FA5B02F0A5464050732B84D5BC4140E0EEC9C342A5464058499D8026BE4140D0D6C1C1DEA44640E0DC43C2F7BE4140A8ECF483BAA446400818080264C04140A0AA4203B1A4464088543541D4C54140607FBDC282A546408887140324D84140A8AD8383BDA94640A877634161DA41406055A18158AA464000FD304278EE4140484F9143C4B34640505E64027EF14140202922C32AB246405858E20165F741405058E20165AF464088ABAE4335F94140608E0244C1AE464078B130444EFB4140A8AD11C138AE4640203526C45CFE41408896E7C1DDAD46406070EA03C9FF414080543541D4AD464050465C001A014240C8B8A981E6AD4640D8D03FC1C5024240603448C153AE464030232E008D044240006493FC88AF46408096E7C1DD054240B0AAD0402CB146407890D78349074240886308008EB3464078DF313CF60742402826E1421EB5464098CB9BC3B5084240F881AB3C81B64640D0E2C5C2100942403099D53BDCB6464060E3DEFC86094240C8C7EE0225B74640F8F36DC1520F4240D0D90242EBB94640A0957B8159114240D0D03FC1C5BA464078FA08FCE1114240D0BBEA01F3BA4640604CDE003313424030205F4205BB464088CC07043A254240806308008EBB4640E0E506431D3E4240A89E3E027FB846404846CEC29E4C4240B8AD11C138B64640A8A17F828B4D424078698A00A7B54640588E0244C14E4240502EC6C03AB44640007F6ABC74514240886649809AB0464098C2D842905142407887140324B0464098C2D84290514240D8EEC9C342AD4640505E64027E514240302FA4C343AC4640D83AE3FBE2504240D0D3F20357AB46403023A0C211504240806CCB80B3AA4640D0DC43C2F74E4240A8B915C26AAA4640E0CDFE40B94D424000F12C4146AA4640888D96033D4A42406055A18158AA4640D0B56801DA48424048404CC285AA4640503448C1534642406037894160AB464088543541D4454240B0C85A43A9AB4640D0C16C020C454240E0B22781CDAB4640806308008E434240887B1002F2AB46408093A641D1404240209C16BCE8AB4640A8A70183A43F4240F0EA1C03B2AB464000E8DB82A53E4240706F7EC344AB46408096E7C1DD3D424048404CC285AA46404858E20165374240204DBC033CA34640D0DC43C2F7364240302922C32AA2464000E259828C344240A0C2D8429099464020179CC1DF334240283B3602F1944640D8B22781CD334240A89BFD8172934640309C16BCE833424048404CC285924640200ED940BA344240309F573CF5904640507FBDC28235424030F64201DB8F4640805AB741ED374240D0C16C020C8D464018473A03233942407866BB421F8C4640A8776341613A42403035B401D88A4640101E8A027D3A424060DA1B7C618A4640B0B915C26A3A424080FA08FCE1894640D8066003223A4240A01AF67B6289464028111AC1C63942408003CC7C078946402050FD8348384240F85AD07B638846408896E7C1DD1D424000301004C880464000E259828C1C4240A0CB9BC3B5804640D85E7D3CF4114240B07763416182464050BF44BC75104240706CCB80B3824640B0AAD0402C014240087F6ABC74814640B8E0F08288004240886649809A8046406070EA03C9FF41403038F581E47F46402099D53BDCFE41405058E201657F4640F805F4C29DFD4140A88FF980407F4640506A6803B0ED414078AEEFC3417E46408066BB421FEC414008FD3042787E46403835B401D8EA41402099D53BDC7E4640E006600322EA4140F820CB82897F4640780987DEE2E941400800000000804640D0CABDC0ACE84140F0F02C4146824640D0C7EE0225E74140E0DF84420484464020C0B0FCF9E4414000FD3042788646403044F98216E441402841B8020A874640503448C153DE414088758E01D9894640D8DF844204DC4140C8D03FC1C58A4640F0298E03AFD6414048732B84D58C4640202922C32AD2414088AEEFC3418E4640189C16BCE8CB4140B08FF980408F4640807E5182FEC84140B07AA4C16D8F4640D8DC43C2F7C64140B07AA4C16D8F4640A8923A014DC44140F8F36DC1528F464028A5D93C0EC34140D8C7EE02258F4640E05E7D3CF4C141402899D53BDC8E46408878CF81E5B64140505E64027E894640A8A17F828BB54140B0CB9BC3B58846402844F98216B441407090D78349874640D0E847C329B34140285FD0420286464040404CC285B24140F8F6AE415F844640909C69C2F69F414098776341617A4640706F7EC344934140D8F10A444F7246402835B401D8924140B8A10DC006724640B0AD8383BD914140209F573CF5704640A023B9FC879041408890D783496F4640E0D38041D28F414038327381CB6D464048438D42928F4140300ED940BA6C464000FD3042788E414028266F8099694640F8EDEBC0398D4140602B85402E67464080A86DC3288C4140888192020B66464088B130444E8B4140483D0B427965464028111AC1C6894140E0D6C1C1DE644640080F45813E894140B8ECF483BA644640C8D38041D2874140F00EB743C36446403041B8020A874140D85B3CBCE7644640E0B8A981E6854140A8B6D4415E65464008240C0396844140504C50C3B76646400003B34291804140F0F02C41466A4640280B98C0AD7F41403035B401D86A4640203526C45C7E4140284DBC033C6B464058BC033C697B4140989BFD81726B4640A0A17F828B5D4140D0D38041D2674640A0B30584D65B41400079E8BB5B674640A8776341614241408090D783495F464020179CC1DF3B4140F0E159828C5C4640B8B915C26A3A414028179CC1DF5B464080ABAE4335394140C8BBEA01F35A4640886F0C01C0374140505E64027E59464028205F420533414088B130444E534640584F1F813F30414050438D42924F4640788192020B2E4140807B1002F24B4640B09BFD81722B414030145B41D346464080DCF0BBE92A4140D0B8A981E6454640101E8A027D2A4140B8E331039545464020266F8099114140D8EB884336384640080C76C3B60F4140386E15C440374640605E64027E01414000093543AA324640D8F10A444FFA404008301004C8304640B8A44E4013F74040B023B9FC87304640C8C16C020CED4040785776C1E0324640E8EA1C03B2EB404020205F4205334640C0BBEA01F3EA404030A5D93C0E334640A8AD8383BDE94040785776C1E0324640002A8E03AFE64040A8AD8383BD314640E05B3CBCE7E44040A81AF67B623146405846CEC29EDC4040B0A10DC00632464008E869C020DB4040D0F10A444F32464050404CC285DA404058404CC28532464028266F8099D9404030A5D93C0E33464030F64201DBCF404080FA08FCE1394640789FAA4203CD4040785DF8C1F93C4640988C2AC3B8CB4040C08EFF02413E4640386BD44334CA404088A52C431C3F4640485E64027EC94040988FF980403F46408093A641D1C84040282C6343373F4640484C50C3B7C640406061A5828A3E4640809FAA4203C54040E0E506431D3E4640B8BF97C283C4404010E52840143E4640504CDE0033C34040B01D37FC6E3E46406064E60297BB4040000F45813E41464080A2EBC20FBA4040B8A10DC00642464048404CC285B2404030145B41D34646400803B34291B04040583ACAC16C484640E0DC43C2F7AE4040D0066003224A4640508E0244C1AE404040404CC2854A46403099D53BDCAE4040D8BBEA01F34A4640C8C7EE0225AF404050BC033C694B4640D8D38041D2AF404050BC033C694B464050672783A3B0404078B130444E4B4640B020787C7BBB4040888A5583304D4640E0DC43C2F7C64040D0D38041D24F4640383B3602F1C4404010E5284014564640F81D8A027DC24040F82CCF83BB63464048C5C6BC8EC24040D80CE2033B644640F8EA1C03B2C34040281D1EC2F8654640808A558330C54040888AE3C0AB694640A8CEDC43C2C540406082FE428F6A4640508E0244C1C6404000EB1C03B26B4640D0A623809BC74040B0923A014D6C464050672783A3C84040A0AA4203B16C464028179CC1DFCB4040383B3602F16C4640E05B3CBCE7CC4040585260014C6D4640D8EEC9C342CD4040486A6803B06D4640D0B8A981E6CD4040A08FF980406F4640086493FC88CF40408093180456744640A0A70183A4CF40409096E7C1DD754640501630815BCF4040202C6343377746403029B000A6CE40406055A181587A464050499D8026CE40403044F982167C4640B8AAD0402CC9404008F12C41468A4640A89E3E027FC84040B09BFD81728B4640282C634337C7404088724D81CC8C464000FD304278C64040F81A4982708D4640B8B6D4415EC54040503448C1538E4640608BC1C3B4C140400003B342919046405861A5828AB64040184A7B832F964640E0B22781CDB34040B0BC56427797464058DA1B7C61B240405870EA03C9974640D03AE3FBE2B04040F8F62004E49746408078CF81E5AE4040886F0C01C09746408096E7C1DDAD40400079E8BB5B9746405037894160AB4040081286014B96464038232E008DA4404020179CC1DF934640B8B0524145A34040F82CCF83BB9346407003CC7C07A1404078A86DC328944640484C50C3B7964040D8EB884336984640284A7B832F96404060BF44BC75984640586DA983BC924040A8D11DC4CE9A4640806F0C01C08F4040B07422C1549D4640286BD443348A4040888AE3C0ABA14640A0E0F082888840403035B401D8A24640605E64027E814040D8DC43C2F7A64640805AB741ED774040504F9143C4AB464000F46DC15277404080008BFCFAAB4640481630815B6F404080698A00A7AD464080543541D46D4040C8B8A981E6AD464078931804566C404020A298BC01AE46402835B401D86A404000E5284014AE4640C8C7EE02255F404080698A00A7AD46402826E1421E5D4040B0A17F828BAD464000E259828C5C404000D9960167AD46406064E602975B4040303B3602F1AC4640F8ED5D83BE584040A020787C7BAB46400079E8BB5B57404008093543AAAA46400082AB3C8156404088A2EBC20FAA464000EEEBC03955404050BF44BC75A8464058732B84D55440408087140324A84640504F9143C4534040786F0C01C0A74640A8B915C26A524040000C76C3B6A74640D0D90242EB494040D8CABDC0ACA8464078DF313CF647404088ABAE4335A94640100F45813E414040A020787C7BAB464080698A00A73D4040286BD44334B2464058C2853C823D404000093543AAB246408878CF81E53E40400806F4C29DB54640F820CB82893F4040A098BC0166B64640706CCB80B3424040B0AD8383BDB9464050888043A84440405037894160BB4640007F6ABC74494040A8CEDC43C2BD464060672783A3504040D00F238447C14640B0D11DC4CE6A4040081B498270CD464020205F420573404008F12C4146D24640981D37FC6E76404030179CC1DFD3464078DF313CF6774040B07DE5417AD44640805776C1E0824040C0BE2B82FFD7464040438D42929740405861A5828ADE4640005E11FC6F9D404078637AC212DF4640204A7B832F9E40403841B8020ADF464050465C001AA14040000C76C3B6DF4640D0DC43C2F7A64040D8EE5701BEE14640A89E3E027FA840405855A18158E24640201D1EC2F8AD404080724D81CCE4464018F64201DBAF404028327381CBE5464048490F43ABB1404070637AC212E74640706F7EC344B34040F85AD07B63E846407893180456B44040505E64027EE94640788A558330B54040D0C4AD8218EA46400879E8BB5BB74040A0D11DC4CEEA464058C2853C82BD4040F8E159828CEC4640403ACAC16CC84040001286014BEE4640706F0C01C0CF40407072BF4351F04640D8F10A444FE24040200516C094F54640A0D11DC4CEE2404088543541D4F546407084D38217E3404080AEEFC341F64640D84065FCFBE24040002A8E03AFF64640A8B915C26AE2404050DD5CFC6DF7464030473A0323E140408072BF4351F84640F8FFFFFFFFDF404008301004C8F8464000E8DB82A5DE404028473A0323F9464078AEEFC341D6404058404CC285FA464080724D81CCD440404882FE428FFA4640506DA983BCD24040282FA4C343FC46402850FD8348D0404050438D4292FF46402023A0C211D04040909C69C2F6FF4640583ACAC16CD04040584F1F813F0847409851103CBECF404028179CC1DF0F474088FD497CEECE404048490F43AB11474080AEEFC341CE40403835B401D8124740280516C094CD4040000072C284134740F0E159828CCC4040200247020D144740D0E847C329CB4040A0923A014D144740A8A4C00298CA40408066BB421F144740404F9143C4C34040F8F36DC1520F474060BC033C69C34040D8DC43C2F70E4740885776C1E0C2404028A298BC010E474080DCF0BBE9C24040B0A17F828B0D4740A01AF67B62C14040586DA983BC0A47405058E20165BF4040A89E3E027F084740200ED940BABC4040A8B0C403CA064740000C76C3B6B74040D8CDFE40B90547407878CF81E5B6404078543541D405474088698A00A7B5404088AEEFC34106474020111AC1C6B14040981AF67B6209474000FAEFC16BB14040184DBC033C0B4740F82F1004C8B04040209C16BCE80B4740F8D555815AB04040602EC6C03A0C4740483ACAC16CA84040785AB741ED0F4740F8DBD78173A24040D00660032212474048672783A3984040200ED940BA144740A8A70183A4974040282FA4C343144740604F1F813F904040D0B56801DA104740F80B76C3B68F4040A8CB9BC3B510474000E259828C74404080AEEFC3410E4740284DBC033C73404050499D80260E4740B8B915C26A72404080AEEFC3410E4740A0923A014D6C4040501630815B0F4740B8B393C151684040A09E3E027F104740F8DE180280674040886649809A10474000E869C02063404060672783A310474000F46DC1525F4040808714032410474088ABAE4335514040301D1EC2F80D4740D0BBEA01F34A4040A8923A014D0C4740285FD04202464040A8A4C002980A474090CC07043A454040C8D90242EB094740080FB743C3444040588BC1C3B4094740B020787C7B434040485E64027E09474080ABAE433541404038266F80990947408878CF81E53E4040C8D90242EB094740A87DE5417A344040F82CCF83BB0B4740504CDE00332B404088543541D40D4740B08CB80034224040D043A67C08104740788AE3C0AB2140402850FD834810474098957B815921404060672783A3104740D8C7EE02251F404060499D8026164740A020787C7B0340408893A641D1204740601C075E2DEB3F400054388254244740003C1405FAE43F408887A2409F24474030895E46B1E43F4078A86DC328244740F05A0A48FBE33F40E0B22781CD234740605E64027EE13F405064E602972347403093533BC3D43F40A89BFD8172234740F0304278B4D13F40F0FF71C284234740508B338639CD3F40A0B30584D6234740F04BC5C6BCCA3F40E00CE2033B244740209694BBCFC93F40B0BF97C2832447407087A2409FC43F40A0B0C403CA26474000575D876AC23F406070EA03C9274740A0E67283A1C23F40E0EB884336284740504CDE0033C33F40D0CABDC0AC284740B0FB3905F9C53F40F87E6ABC74294740209C508880CF3F40706F7EC3442B474090EF3504C7D13F40B0C85A43A92B474020AE64C746D83F4008B2497EC42B4740501938A0A5DB3F40B8C5E061DA2B4740402F87DD77E03F40803656629E2B4740E06DC2BD32E33F4038747ADE8D2B474070779E78CEEA3F40906308008E2B4740C0957B8159F13F40309C16BCE82B4740005A9E0777F73F40A07DE5417A2C4740C01858C7F1FB3F40306893C3272D4740D8C7EE02250740408803CC7C0731474058438D4292074040B0957B815931474030F64201DB07404028111AC1C631474058438D429207404000093543AA32474078637AC21207404048BC033C6933474050499D8026064040B07DE5417A344740283E7782FD0140400803B34291384740D80F238447014040D0CD70033E394740A89E3E027F004040B0AD8383BD394740C0A70183A4FF3F4088758E01D9394740005A9E0777F73F40303E7782FD39474080BEBC00FBD03F40C0344580D33D4740C014747B49CF3F4008E52840143E4740106E15C440C73F40D8C7EE02253F4740100C040132C43F40202C6343373F47405091B58652B73F4078637AC2123F4740101D1EC2F8B53F403841B8020A3F47406086E3F90CB43F40002A8E03AF3E474020274D83A2B13F40586A6803B03D4740A023B9FC87A83F4080931804563C474050D026874F9A3F40607C7C42764047401051DB8651883F40F8298E03AF46474030809BC58B853F40E043A67C0848474070DBBE47FD813F40286BD443344A4740C0D03FC1C5823F40B8B915C26A4A474060431B800D843F40286BD443344A4740B0052FFA0A863F40908AE3C0AB494740C0E0F08288883F40302F3201BF484740C0FFACF9F18B3F4070637AC212474740E0D6C1C1DE8C3F4098B0C403CA464740A001BC0512903F40888192020B464740F044D7851F943F40507FBDC2824547408093A641D1983F4080CC07043A454740308FE046CA9E3F40386893C327454740409694BBCFA93F40507FBDC282454740F007043A93AE3F40888192020B464740F02F1004C8B03F40A898BC0166464740F0578FFB56B33F40E0C43BC09346474080D87DC7F0BC3F408878CF81E5464740B0B1F677B6BF3F40D0DC43C2F7464740F0D03FC1C5C23F408878CF81E5464740B00DC00644C43F40588E0244C14647404077D84466D63F40D8B22781CD434740B0EC66463FDA3F40F0B7AF03E742474090C1A73979E53F409877634161424740B0B30584D60B4040000F45813E414740D009A1832E1740407878CF81E53E474050BC033C69234040C89DD2C1FA3B4740301ADD41EC28404000E869C0203B4740989BFD81722B4040A0D11DC4CE3A474078698A00A72D4040586DA983BC3A474008EEEBC039354040204A7B832F3E474008E5284014364040488E0244C13E4740203526C45C364040202C6343373F4740D8E506431D36404060853FC39B3F4740586A6803B03540403838F581E43F4740B0BF97C283344040B8B393C15140474080A86DC328344040D8CABDC0AC404740707B1002F2334040E0E2C5C210414740C89DD2C1FA33404030266F8099414740B0BF97C283344040304DBC033C43474088724D81CC344040B0C85A43A9434740301D1EC2F8354040B8ECF483BA44474048FB58C16F394040984ECFBBB146474028145B41D33E4040908AE3C0AB494740D8C43BC0934640408066BB421F4C4740604F1F813F4840404046CEC29E4C4740A820787C7B4B4040C0C16C020C4D47401826E1421E4D4040300516C0944D4740788192020B4E4040C8E506431D4E4740F8F36DC1524F40402841B8020A4F474048404CC285524040F8264D83A25147402835B401D852404078A2EBC20F524740081E8A027D524040B0B915C26A524740D85E7D3CF4514040F8083543AA52474088ABAE4335514040806CCB80B352474060672783A350404050404CC285524740B0776341614240408096E7C1DD4D474098776341613A40403835B401D84A4740E03D247CEF354040302F3201BF484740604CDE003333404028F64201DB474740D843A67C083040400079E8BB5B474740A8B30584D62B4040602B85402E474740B03E90BC732A4040D0C7EE0225474740608BC1C3B4294040602B85402E474740A08636001B284040A87AA4C16D47474080FD497CEE2640403038F581E44747400806F4C29D254040302F3201BF484740F00EB743C3244040B0957B8159494740584CDE0033234040A0A4C002984A4740382F3201BF204040987DE5417A4C47406070EA03C91F4040809FAA42034D4740D8D0B1834A1E4040888A5583304D474088698A00A71D4040C8031F83154D4740A8A70183A41740405855A181584A474018205F420513404028F64201DB47474050404CC285124040E0A623809B4747400012F8C3CF11404050438D4292474740E00F238447114040D0D38041D247474048404CC2850240400803B34291504740305C8FC2F5004040F811F8C3CF514740004C8BFA24FF3F40D8E847C3295347407095287B4BFD3F40602EC6C03A544740D00D863AACF83F400003B34291584740F05AD07B63F83F40807E5182FE584740305D33F966F73F4088C00303085D4740B020787C7BF33F40A01D37FC6E5E4740408E740646F23F40D809A1832E5F47406070EA03C9EF3F40A0C2D84290614740E0FE40B96DEF3F40A8A10DC006624740B00A7F8637EF3F40A09BFD8172634740B00A7F8637EF3F40403D0B4279654740E0FE40B96DEF3F40F881AB3C81664740C0B1F677B6EF3F4070A52C431C674740E0ECBAB722F13F40B0E0F08288684740D00050C58DF33F4060E3DEFC8669474070766C04E2F93F40806308008E6B4740002DCF83BBFB3F4070724D81CC6C4740104B598638FE3F40202C6343376F47408003CC7C07014040B0B30584D673474060E3DEFC8601404000E5284014764740A0957B8159014040C861BEBC00774740C0211B4817FB3F40305C8FC2F580474090DEFFC709D73F40E061BEBC00974740A0F8F884ECC03F4090C9C6832DA04740407ADFF8DABF3F40583ACAC16CA04740B0923A014DBC3F401000000000A04740506DA983BCBA3F40F8F36DC1529F4740D004C3B986B93F40B01D37FC6E9E47407089247A19B93F40D03D247CEF9D474070D66EBBD0B83F40B07422C1549D474040956247E3B83F40D8D6C1C1DE9C4740408C9FC6BDB93F40300247020D9C4740D0211B4817BB3F4050378941609B4740C0BAB9F8DBBE3F40788D96033D9A4740E0C77C40A0C33F40A01AF67B62994740B01133FB3CCA3F40281ADD41EC984740308FE046CACE3F40C8BE2B82FF97474060CAA48636D03F4000F46DC152974740C012D6C6D8D13F40A0AD11C138964740208FE046CADE3F40706F7EC3448B47400042960513DF3F402835B401D88A47400042960513DF3F4080758E01D9894740004B598638DE3F40309F573CF5884740A023B9FC87D83F40181D1EC2F8854740003483F8C0D63F4060888043A8844740C0052FFA0AD63F405864E60297834740F0E506431DD63F400806820019824740A0AF21382ED73F40E0B56801DA8047406088F2052DD83F402823A0C211804740C0151747E5E63F40002A8E03AF764740A019C40776E83F40708192020B764740D0211B4817EB3F4080698A00A775474040A298BC01EE3F4080698A00A7754740409737876BF13F4060499D8026764740C016838769F33F402829B000A6764740E0151747E5F63F40A8A44E40137747404088F2052DF83F402099D53BDC7647406089247A19F93F40E0C43BC09376474070C3B64599F93F40204A7B832F76474030956247E3F83F40B0BF97C28374474030145B41D3F63F40E0D90242EB7147407085B18520F33F403029B000A66E4740B0CE4E0647F13F40F0D89601676D474040A0FA0791F03F40809FAA42036D4740E007043A93EE3F40F8E159828C6C474030895E46B1E43F4080DCF0BBE96A4740D0D90242EBE13F40D8066003226A4740409012BBB6DF3F408003CC7C07694740F0C43BC093DE3F408887140324684740300516C094DD3F40582B85402E674740809FAA4203DD3F40808192020B664740F0D6C1C1DEDC3F40487FBDC282654740A0A99F3715DD3F4030232E008D6447402098A3C7EFDD3F40B8B0524145634740207D5A457FE03F4078758E01D9614740900DC00644E43F40302F3201BF60474090B8E4B853E63F40F80B76C3B65F4740C00C54C6BFE73F40E0C43BC0935E4740D0CABDC0ACE83F40D8EEC9C3425D4740408C9FC6BDE93F40A87DE5417A54474060D9E90775E93F40209C16BCE85347401051DB8651E83F4028A5D93C0E534740E06261889CE63F4008DCD7817352474090CA6ABA9EE43F40E05E7D3CF451474070E1404816DC3F40483ACAC16C50474020874F3A91D03F4020145B41D34E4740004C8BFA24CF3F40A8B0C403CA4E4740B089778027BD3F403050FD8348504740A0AEEFC341B63F4050490F43AB514740F0ECBAB722B13F4008DCD78173524740A0C8CC052EA73F405864E602975347401045D7851FA43F40A0C85A43A953474010429605139F3F40204DBC033C534740E00F9546CC9C3F4090992842EA524740E04BC5C6BC9A3F40101E8A027D524740F0548847E2993F40386BD443345247400051DB8651983F4060E3DEFC8651474070AF21382E973F400803B3429150474080AEEFC341963F403099D53BDC4E4740B004FD851E953F40201D1EC2F84D4740104FCC7A31943F40D8CDFE40B94D474070992842EA923F4078698A00A74D474080ABAE4335913F40D8CDFE40B94D4740F0E847C3297B3F4058BF44BC7550474010494A7A187A3F40B0CB9BC3B5504740A01AF67B62793F40D0E2C5C2105147405089247A19793F40505E64027E514740F04718062C793F40A0A10DC006524740606DA983BC7A3F4060BC033C69534740909BFD81727B3F40584F9143C4534740505B2382717C3F40D8DF844204544740B0F8F884EC803F40A0AA4203B1544740201E8A027D823F40B0B6D4415E554740209C16BCE8833F40D8E506431D56474080D87DC7F08C3F40D0DF8442045C474050465C001A993F40889FAA420365474070D53C47E4973F402841B8020A67474070D7DAFB54853F40504C50C3B75E474020274D83A2813F40582EC6C03A5C474020301004C8803F40584CDE00335B4740E00D863AAC783F40A8CEDC43C255474080DF313CF6773F4008D9960167554740605B2382716C3F403050FD834850474090BAF3C4736A3F40E0D38041D24F4740F017080264583F40C8031F83154D474060745DF8C1553F40203B3602F14C4740901F46088F523F40C8031F83154D47409087A2409F443F4078543541D44D4740608C65FA253E3F40001286014B4E4740C0D4D006603B3F40A8C519C39C4E4740F01C59F965303F40C85B2041F14F4740705260014C2D3F402823A0C21150474060DF313CF6273F40E0D38041D24F4740D0D03FC1C5123F403829B000A64E4740300516C0940D3F40583448C1534E4740409C16BCE8033F40D0EEC9C3424D4740301ADD41ECF03E406082FE428F4A4740A00EF27A30D53E40184A7B832F464740B0E9B303AEC73E40F805F4C29D3D474050C763062ACB3E40A01AF67B6239474040D158FB3BCB3E40281ADD41EC384740C0FE7A8505CB3E407072BF435138474050D6A88768C43E40289F573CF53047401015C78157C33E403023A0C21130474020956247E3A83E408003CC7C0721474030145B41D3A63E402838F581E41F47406055A18158823E4078931804560C474090BE66B96C403E40D0EB884336F04640E006D2C5A63D3E40987AA4C16DEF4640D0548847E2293E40206BD44334EA4640003C1405FA243E408003CC7C07E9464090F8F884EC103E40A898BC0166E64640209C5088800F3E405076FA415DE64640C0ECF483BA0C3E40200B98C0ADE7464040840EBA840B3E40F85AD07B63E8464080C4E8B9850A3E40A8AAD0402CE94640D00391459A083E4008F12C4146EA464070DEFFC709073E40885776C1E0EA464020895E46B1043E4080B130444EEB4640407D5A457F003E40584F9143C4EB464020179CC1DFFB3D407866BB421FEC464090C4E8B985FA3D402044F98216EC46401051DB8651F83D40002DCF83BBEB46407082700514EE3D40E0CABDC0ACE846404098A3C7EFCD3D40483448C153DE464090A99F3715CD3D40788192020BDE4640705B238271CC3D4080698A00A7DD4640F036C478CDCB3D400067D47C95DC464090F5B704E0CB3D40806308008EDB4640A0A86DC328CC3D4000E869C020DB464090ECF483BACC3D40E0D03FC1C5DA4640608E740646D23D40B08636001BD84640504CDE0033D33D40D8D38041D2D7464050745DF8C1D53D40A0BC564277D74640F0FBFF3861DA3D40F8F36DC152D74640F0230C0396DC3D402899D53BDCD64640508B338639DD3D406061A5828AD64640400516C094DD3D40E0E506431DD6464080A99F3715DD3D4070698A00A7D5464090B130444EDB3D402026E1421ED5464020085740A1D23D40D8FD9C82FCD2464070CC79C6BEC83D4098CB9BC3B5D04640002A8E03AFC63D402050FD8348D04640B00A7F8637BF3D407890D78349CF464080E272BC02BD3D4058BF44BC75D046404082700514AE3D40D03AE3FBE2D846403098A3C7EFAD3D40A0957B8159D94640408B338639AD3D40D8E506431DDE4640A01C058882AD3D40202C634337DF46402099D53BDCAE3D4088ABAE4335E14640B014747B49AF3D40488BC1C3B4E1464070672783A3B03D40F8DBD78173E24640B08CB80034B23D408084D38217E3464040085740A1B23D406064E60297E346400061527C7CB23D4058431B800DE446402099D53BDCAE3D40504C50C3B7E6464020A298BC01AE3D4028FF058200E74640B00DC00644A43D4080ABAE4335E946406085B18520A33D402032E54350E94640C08CB80034A23D4060465C001AE9464020111AC1C6A13D40F002B34291E846409093A641D1983D40D043A67C08D84640C023B9FC87983D40A0BC564277D74640604F1F813F983D40283526C45CD64640E00C54C6BF973D40F820CB8289C7464070D53C47E4973D4070637AC212C7464070DC2A88819E3D40A81D37FC6EBE464020240C0396AC3D405864E60297BB4640506DA983BCBA3D40585B238271BC4640F0DF844204BC3D40F8F6AE415FBC4640A0C24A0515BD3D407866BB421FBC464040874F3A91C03D40E05E7D3CF4B9464070C1E10511C13D40B0C2D84290B94640207497C459C13D4050672783A3B84640F0D03FC1C5C23D4058E3DEFC86A94640901F46088FC23D40309F573CF5A84640102DCF83BBBB3D40B0897780279D464030205F4205BB3D40080FB743C39C464070B7B24467B53D4088B130444E9B464040179CC1DFAB3D403835B401D89A4640B01133FB3CAA3D40D8BBEA01F39A464030B8AE9811AA3D40F018575C1C9B464040BEA08504AC3D40D8F10A444FA2464090A86DC328AC3D405037894160A34640F02CCF83BBAB3D4070724D81CCA44640D055BABBCEAA3D40A0C519C39CA64640B0E9B303AEA73D40D85E7D3CF4A94640B004FD851EA53D40D0F4D901D7AB4640306211C30EA33D4058732B84D5AC464020990F08749A3D40504F1F813FB04640B0FC6B79E5963D40B0957B8159B1464000575D876A923D40808D96033DB2464030895E46B1843D4098923A014DB44640203A05F9D9803D4050732B84D5B44640A010018750693D405870EA03C9B74640409BE447FC523D40D0EB884336B8464000274D83A2513D4078C9C6832DB84640F0548847E2393D403829B000A6B64640102BC0779B373D404876FA415DB64640D0D38041D2F73C4058465C001AA94640200F45813ED93C40A0C519C39CA64640A0ECF483BACC3C4020145B41D39E4640A0290307B4CC3C4060D905836B9E464050C8957A16CC3C40808192020B9E4640D05D4BC807C93C40001B4982709D4640707D2079E7B43C4008CA5180289C46405088B9A46AB33C4008CA5180289C4640703D7C9928B23C4008CA5180289C4640C012D6C6D8B13C4008CA5180289C4640E0EB884336B03C40282FA4C3439C46404085B18520933C4080637AC2129F4640D0EB884336603C40F8FC304278A6464090D53C47E4573C40085BD07B63A8464040895E46B1543C4038266F8099A9464050C1E10511513C40604CDE0033AB4640E058FB3BDB4F3C40209C16BCE8AB464030A1F485904F3C4080573D601EAC4640D0CDFE40B94D3C40101B498270AD4640207A19C5724B3C405058E20165AF4640808AE3C0AB493C40787E5182FEB04640F05D4BC807493C4078758E01D9B14640F0CABDC0AC483C40A8D11DC4CEB24640007CD45FAF483C40D004357C0BB3464060CC79C6BE483C405819710168B44640109F573CF5483C40805DF8C1F9B44640F0CABDC0AC483C40D03D247CEFB54640809C69C2F6473C40B0B0C403CAB64640005A9E0777473C40C8C7EE0225B7464020335184D4453C40806F0C01C0B74640303048FAB43A3C4030116F9D7FB9464060DF313CF6373C4028266F8099B9464060DF15C1FF363C406839D0436DB94640D0DC43C2F7363C4028A5D93C0EBB46405091B58652373C405864E60297BB4640103F5585063A3C409898BC0166BE464080D87DC7F03C3C40583ACAC16CC04640B01342075D3E3C4028473A0323C14640A001BC0512403C40508BC1C3B4C1464070A2EBC20F423C40A08CB80034C246401077D84466463C40C8BBEA01F3C24640F0CABDC0AC483C40304DBC033CC3464070D158FB3B4B3C4058BC033C69C34640B002EE79FE503C40080072C284C34640B019C40776583C40C8BBEA01F3C2464090CFBA46CB5D3C4000F12C4146C24640607D2079E7643C4038266F8099C14640400B98C0AD673C4000FAEFC16BC14640303317B83C7A3C408093A641D1C04640C0C24A05157D3C40D8B56801DAC04640F03905F9D9803C40B8AAD0402CC14640306211C30E833C4058E3DEFC86C1464010335184D4853C4000F12C4146C246403081CD3978863C4008093543AAC24640E0D38041D2873C4058431B800DC44640C0F3A8F8BF873C40302922C32AD24640306E15C440873C4050404CC285D24640D03FC1C58A863C40885776C1E0D24640409221C7D6833C40F8EA1C03B2D3464020A298BC017E3C40300ED940BAD446407095287B4B7D3C402026E1421ED54640400516C0947D3C40607FBDC282D5464070AEEFC341863C4028205F4205DB4640A0B7B24467953C40908AE3C0ABE146401051DB8651983C40B077634161E2464070779E78CE9A3C40A0A4C00298E24640300B98C0ADA73C40785776C1E0E246402037C478CDAB3C4030A5D93C0EE34640D0D6C1C1DEAC3C40284DBC033CE34640308FE046CAAE3C40082DCF83BBE34640A0B471C45AB03C4000F7AE415FE44640604CDE0033C33C40B07DE5417AEC46402093533BC3C43C40B01D37FC6EEE4640F05147C7D5C43C40E0DC43C2F7EE4640C017B5FB55C43C402038F581E4EF4640207497C459C13C4088724D81CCF4464010938D075BC03C40D8E506431DF64640F0FE40B96DBF3C4088FD497CEEF64640D0F44BC45BBF3C4048BF44BC75F84640607ADFF8DABF3C4008274D83A2F94640203A05F9D9C03C4058404CC285FA4640E03C80457EC13C40785776C1E0FA464010575D876AC23C40F8E769C020FB4640F0488446B0C53C40382CF180B2FB464090A99F3715CD3C40A07DE5417AFC4640B017B5FB55D43C4000EEEBC039FD464040809BC58BE53C40B0B0C403CAFE464090CA6ABA9EF43C403023A0C211004740409E25C808F83C40B8E0F0828800474070D66EBBD0F83C40C8B56801DA004740103F558506FA3C40888AE3C0AB01474050D026874F0A3D40180E4B033F18474090C4E8B9850A3D405852D2C3D018474040DA1B7C610A3D402032E54350194740F0548847E2093D40A0AD8383BD194740106361889C063D4050378941601B474070E09D7C7A043D4088931804561C4740604CDE0033F33C40D0C16C020C254740C007043A93EE3C40A8CEDC43C235474060C6F7C5A5EE3C4020145B41D336474080C7293A92EF3C405070EA03C93747405088F2052DF83C4048378941603B4740102DCF83BBFB3C40A87DE5417A3C4740E007043A93FE3C4008EEEBC0393D474030956247E3083D405858E201653F4740C0FE7A85050B3D40786F0C01C03F4740F05CDF87832C3D40D0031F83154547400060AE450B343D40E8AEEC82C14547404088F2052D383D40D0CA2F8331444740004818062C393D40785776C1E042474070C3B64599393D40F87E6ABC7441474070BAF3C4733A3D40788192020B3E4740608061F9F3393D40B8B6D4415E354740D004C3B986393D40D8D6C1C1DE344740D0D38041D2373D406064E60297334740F0325184D4353D40F0DBD78173324740F00182397A343D40608BC1C3B4314740209221C7D6333D402032E54350314740C016838769333D405852D2C3D0304740D00050C58D333D407872BF4351304740F00182397A343D40F0DE1802802F4740509A780778363D4028FF0582002F4740C01AF67B62393D40588E0244C12E474060779E78CE3A3D40B0B0C403CA2E474070E272BC023D3D40D0C7EE02252F4740E006D2C5A64D3D40E0E847C32933474050DC2A88814E3D40A820787C7B334740204C8BFA244F3D4030179CC1DF33474070DD5CFC6D4F3D40585B238271344740204C8BFA244F3D40F8D8960167354740201286014B4E3D40484C50C3B7364740E006D2C5A64D3D4048438D4292374740309694BBCF593D4000CA5180283C474090BAF3C4737A3D40D8DC43C2F73E474000541C075E7D3D40D061BEBC003F4740A0BAB9F8DB7E3D402899D53BDC3E4740203A05F9D9803D40203526C45C3E47401060200890813D4028A298BC013E474050B81E85EB813D40280516C0943D474090A2EBC20F823D401826E1421E3D4740C0EF3504C7813D40F0E159828C3C4740E0FD0E45817E3D40D0D90242EB39474090D9AF3BDD7D3D40E0B56801DA38474020A298BC017E3D4000D655815A3847400039D384ED7F3D4000F46DC152374740C05D4BC807993D4060BF44BC75304740D0F23CB83B9B3D40D0BE2B82FF2F4740D057C9C7EE9E3D405058E201652F4740A0BE66B96CA03D40A88FF980402F4740E0C77C40A0A33D40D0C7EE02252F474020335184D4A53D40F0DE1802802F4740F004C3B986A93D40F802B34291304740406EDBF7A8BB3D40280E4B033F3847404094F6065FBC3D4050672783A3384740F04D9A0645D33D40602B85402E2F474070CFBA46CBDD3D4078931804562C4740108C9FC6BDE93D40B09E3E027F3047405064E60297EB3D40E03AE3FBE23047407082700514EE3D4048465C001A314740105A9E0777F73D40806649809A304740E041960513FF3D40B09E3E027F304740605B2382710C3E40B09E3E027F304740E0D38041D2173E40A0CB9BC3B53047401083DC45981A3E40E03AE3FBE23047402098A3C7EF1D3E40F8F9EFC16B314740B014747B491F3E40202922C32A324740B0F8F884EC203E40A820787C7B334740E0349A5C8C213E40A017D2E121344740E012D6C6D8213E40585B23827134474050E9EE3A1B223E40B85510035D354740102DCF83BB1F3E40C052CF8250364740D01858C7F11B3E403099D53BDC364740A01133FB3C1A3E40E0DC43C2F736474090AF21382E173E40D861BEBC00374740F03905F9D9103E40080C76C3B6374740F05D4BC807093E40B0CB9BC3B5384740A0EF3504C7013E4008DCD781733A4740F0CDFE40B9ED3D40D8CABDC0AC4047406088F2052DE83D402035B401D8424740D01EDAC70AE63D40B0B30584D643474070B7B24467E53D40B8ECF483BA44474070B7B24467E53D40B0C519C39C4647406082C5E1CCE73D4020B4571F0F4747404083DC4598EA3D4050438D429247474030179CC1DFEB3D40280B98C0AD474740D00182397AF43D40D0D38041D247474050A33B889DF53D40D0BE2B82FF474740509A780778F63D40B0B393C151484740400B98C0ADF73D4020473A0323494740409E25C808F83D4000274D83A2494740507F2F8507F93D4020A298BC015E4740A019C40776F83D40885AB741ED5F4740604CDE0033F33D40D0EB884336684740F060527C7CF23D40B0E0F0828868474060672783A3F03D4060465C001A694740307497C459E13D40F81A4982706D4740C01D37FC6EDE3D4088AEEFC3416E4740D0DF844204DC3D403029B000A66E4740D00F9546CCBC3D40D85E7D3CF47147402015C78157933D40A0CB9BC3B578474070D2FBC6D7923D40300588821979474080992842EA923D4000274D83A2794740105A9E0777973D40886CCB80B382474070D53C47E4973D40204DBC033C834740408E740646923D40B0A10DC006924740E0091346B3923D4058404CC28592474090CDAB3AAB993D4000F12C4146A24740308C9FC6BD993D4098D11DC4CEA2474090CDAB3AAB993D40E0B22781CDA34740C023B9FC87983D40385FD04202A6474080AF21382E973D40000C76C3B6A74740204FCC7A31943D4080A2EBC20FAA4740106BD44334923D408084D38217AB474090B471C45A903D40A8C85A43A9AB47407096E7C1DD8D3D402844F98216AC474060D6A88768843D4000F7AE415FAC474050CAA48636803D40582EC6C03AAC474000429605137F3D40200247020DAC4740004B5986387E3D40082DCF83BBAB4740F05D11FC6F7D3D40786CCB80B3AA4740901C0588827D3D40B0AAD0402CA94740300ED940BA7C3D40A87AA4C16DA7474090B130444E7B3D40788192020BA64740A0A4C002987A3D4080698A00A7A547405058E20165773D40D0C16C020CA54740C006D2C5A66D3D408887A2409FA447403083DC45986A3D40E05B3CBCE7A44740D0D38041D2673D40A0CEDC43C2A54740908CB80034623D40503ACAC16CA8474020301004C8603D4000274D83A2A9474060672783A3603D40D8C4AD8218AA474030111AC1C6613D408893180456AC474010314278B4613D40A8B6D4415EAD4740107497C459613D4028327381CBAD4740A0F5B704E05B3D40483ACAC16CB04740102E01F8A74C3D40808192020BB64740C04543C6A3403D4000F12C4146BA4740B0B1F677B63F3D405082FE428FBA4740A01342075D3E3D40506DA983BCBA4740C00F9546CC3C3D40806CCB80B3BA4740606EDBF7A83B3D4048404CC285BA4740308C9FC6BD393D408060394206BA4740005BD07B63383D405831074147B94740106361889C363D40C0BE2B82FFB74740B017B5FB55343D40A8A70183A4B7474080DCF0BBE9323D4048438D4292B74740409737876B313D40080C76C3B6B747406070EA03C92F3D407072BF4351B84740B00A7F86372F3D40B0CB9BC3B5B8474030809BC58B253D40607C7C4276C04740D0C77C40A0233D4050C5C6BC8EC24740A01F46088F223D40A8B30584D6C34740D0D90242EB213D40B0ECF483BAC4474000274D83A2213D4080698A00A7C5474000274D83A2213D40304A7B832FC64740E0091346B3223D4070637AC212C7474060431B800D243D4020F64201DBC747405088F2052D283D40E006600322CA4740309694BBCF293D40D0D03FC1C5CA474090957B8159313D40300516C094CD4740D0091346B3323D40283526C45CCE474000314278B4413D40A8957B8159E14740A0A2EBC20F423D4070758E01D9E1474090ACE0B721423D40A877634161E24740A0EF3504C7413D40A8D11DC4CEE24740200516C0942D3D404034BA83D8F94740C0923A014D2C3D4050C5C6BC8EFA4740E0DC43C2F7263D40B07422C154FD4740A0AEEFC341263D405828B682A6FD4740C017B5FB55243D40806C3D4338FE4740D0D03FC1C5223D40283526C45CFE4740102E01F8A71C3D40283526C45CFE4740F050DB8651183D40B06B5F402FFE4740A0CA6ABA9E143D40E8F09E03CBFD474080D2FBC6D7123D40C0AC174339FD474090ACE0B721123D40D0940F41D5FC4740F05F200890113D40C8B5DAC35EFC4740D0ECBAB722113D40A86EA0C03BFB4740A0B471C45A103D40784BE48233FA4740C014747B490F3D402032E54350F947409096E7C1DD0D3D40F0C000C287F8474080E14048160C3D40D0BE2B82FFF74740E05E7D3CF4093D404801DBC188F74740F0325184D4053D40D0B2994352F74740A0E67283A1023D40481630815BF74740105E11FC6FFD3C40A8654F029BF74740A0CDAB3AABF93C40180E4B033FF8474030446B459BF73C40F8ED5D83BEF84740A0B437F8C2F43C40F8E49A0299F94740E05AD07B63E83C40A08C2AC3B8FD4740A0CA6ABA9EE43C40581630815BFF4740C0F92AF9D8E13C40682E54FEB5004840405E64027EE13C4078ABAE4335014840A0B1683A3BE13C40C816BB7D56014840503A58FFE7D43C4000A0C37C790D4840504CDE0033D33C40B0C519C39C0E48407037177FDBCF3C40D0D38041D20F484070035ABA82CD3C402050FD8348104840D0F6E978CCBC3C4058103CBEBD11484070E09D7C7AA43C40A8C85A43A913484090ABAE4335913C40D8D6C1C1DE14484000A6457D928F3C40D8D6C1C1DE144840406893C3278D3C40B84412BD8C144840307D5A457F803C40B0AAD0402C1148405070EA03C96F3C40B86BED7DAA12484030FF93BF7B633C4030C0B0FCF9144840505260014C5D3C405070EA03C9174840C077F17EDC5E3C40E06740BD19194840C06E2EFEB65F3C40C8D03FC1C51A484000A6457D925F3C40C8B22781CD1B484050DC2A88815E3C4060250340151D4840300516C0945D3C40881B62BCE61D4840809FAA42035D3C4088AEEFC3411E484080B130444E5B3C40A877F17EDC1E4840902766BD185A3C4080A52C431C1F48401018080264583C40C809A1832E1F4840E0DC43C2F7563C4080A52C431C1F4840C0622AFD844B3C40F8FC3042781E4840100F45813E493C4030E44A3D0B1E484080069B3A8F423C40602EC6C03A1C484080D87DC7F03C3C405882FE428F1A4840F036C478CD3B3C4060DA1B7C611A4840A07D737FF5383C4008F12C41461A48400045D7851F343C405007793D981A4840306F47382D183C4020D8B8FE5D1D4840B0F27684D3163C4098A17F828B1D484050E44A3D0B163C409096E7C1DD1D4840B004FD851E153C40B04A94BDA51E4840F03B1405FA143C40782AA73D251F4840F0E506431D163C4058F833BC59214840C08636001B183C40584CDE003323484060B3CEF8BE183C40283B3602F12448401018080264183C40801B62BCE6254840202A8E03AF163C403041B8020A274840901B62BCE6153C40805704FF5B274840F03B1405FA143C40500ABABDA4274840A0F8F884EC103C4030EACC3D24284840809065C1C4033C40B8E0F082882848404061A5828AF63B4030266F809929484080D2FBC6D7F23B40286BD443342A484070C6F7C5A5EE3B40504CDE00332B484000ACC77DABE93B40B84412BD8C2C4840B0716F7EC3E43B4078AEEFC3412E4840B016838769E33B40E0DC43C2F72E48402075C93846E23B40F00B76C3B62F4840109D82FC6CE03B4088758E01D931484020AF08FEB7DE3B40D8FD9C82FC324840B0F6E978CCDC3B40806308008E334840D0B5F63E55C53B40C8949D7E50394840C05CA8FC6BC13B40D873D2FBC639484060C8957A168C3B40887B1002F23B4840309E4143FF843B40F0240681953B4840C00DC00644743B402850FD834838484020AF08FEB73E3B40C88E1B7E372F484020179CC1DF3B3B4020C632FD122F4840F0E847C329FB3A4038327381CB2D4840E057C9C7EECE3A40A8E67283A12A48403002D53F88B83A40E0066003222A484060CE177B2FB63A40D0C77C40A02B4840607CEE04FBB33A4038C9737D1F2C484000BB0CFFE9B23A40A87A32FFE82B484000C4CF7F0FB23A406064E602972B48400021CB8289A73A40B877F17EDC264840D0E506431DA63A4060499D802626484000A986FD9EA43A4038D505BCCC24484010BB0CFFE9A23A402835B401D8224840E061DBA2CCA23A40288C2D0439224840901F46088FA23A40C0DAFCBFEA204840307497C459913A4048E09D7C7A1C4840207CB779E3883A40806CCB80B31A48408009DCBA9B873A405882FE428F1A4840E0AC33BE2F863A4020085740A11A484040431B800D843A4030E78BBD171B48405070EA03C97F3A40806308008E1B484050E3DEFC86793A4028179CC1DF1B48407061A5828A763A40C8B22781CD1B48401048C2BE9D503A4078543541D417484010301004C8503A40E0DC43C2F7164840D009A1832E513A4040B08EE387164840F046753A90513A40C8E506431D16484070069B3A8F523A40D0B5F63E5515484070069B3A8F523A4078724D81CC144840E0488446B0453A4060103CBEBD09484040085740A1323A40A8656B7D91004840B0F92AF9D8313A40884E417E360048406083A279002F3A40A07AA4C16DFF474050779E78CE2A3A40581FF30181FE47404077D84466263A40A08C2AC3B8FD4740001B4982701D3A40F048BC3C9DFD474080F0A1444B1A3A40E8FAB0DEA8FD474060E3DEFC86093A40D8B8A981E6FD474080E1404816EC3940080FB743C3FC474080D53C47E4D73940989BFD8172FB474050D7DAFB54D53940504CDE0033FB474090ABAE4335D13940F0F02C4146FA4740E04BC5C6BCCA394008D655815AF84740A0E0F08288C8394080DF313CF6F74740A0FB3905F9C53940280B98C0ADF74740A0B7B24467A53940F0DE180280F74740102A8E03AF963940E0A623809BF74740405E64027E9139405870EA03C9F747402077D84466863940B0A70183A4F74740A0BE66B96C803940B0BC564277F74740005A9E0777573940507FBDC282F54740A020787C7B533940A089778027F5474080B5A33847413940282922C32AF24740F0D6C1C1DE3C394098957B8159F14740104087F9F23A39404852D2C3D0F0474080DF313CF6373940B8BC564277EF47403098A3C7EF2D3940788D96033DEA4740F02CCF83BB2B3940B0E0F08288E84740B01AF67B6229394088AEEFC341E647404088F2052D283940583D0B4279E54740B0FB3905F9253940087C293C68E44740309012BBB61F394028111AC1C6E14740A0A86DC3281C394058672783A3E04740203D4679E61539407890D78349DF4740002E01F8A70C39408896E7C1DDDD4740002BC0779B07394028118C834BDD474000280EA0DFFF3840281D5723BBDC474020857AFA08F8384000BEDBBC71DC4740E02B2CB81FF43840E0A6B1BD16DC4740D0B22781CDED3840B8B3AF3C48DB4740109A417C60EB384020E78BBD17DB4740206552431BE83840E8AF743E3CDB474090129F3BC1E6384060793BC269DB4740801A3048FAE4384010DFA63FFBDB474030F6D03E56E4384030F6D03E56DC4740809FAA4203DD3840E00F238447E14740A004FD851ED5384010E5284014E64740C0E67283A1D23840D0BB783F6EE7474030E109BDFED03840E08558FD11E84740C001BC0512D03840A8B393C151E8474090035ABA82CD3840D8CABDC0ACE8474050ED0DBE30C5384010E2E7BF07E9474090F755B950B93840C882177D05EB47405031957EC2B53840582B137EA9EB474020274D83A2B13840500DFB3DB1EC47401088BB7A15AD38409048BF7D1DEE4740702B137EA9AB3840D8F19881CAEE4740D0AF743E3CAB3840586D37C137EF4740A0FE7A8505AB3840A8E9B303AEEF474060C763062AAB3840E0B2B5BE48F04740A059677C5FAC3840508BC1C3B4F14740F04334BA83AC3840B053E57B46F2474010917EFB3AAC3840D8D03FC1C5F24740A0FE7A8505AB3840A8DDAF027CF34740F057C9C7EE9E384078A52C431CF7474090A86DC3289C3840A09B8BBFEDF747407028D2FD9C96384090457EFD10F9474060DC2A8881923840C822BF7E88F94740C0DA6E826F8E3840383E7782FDF94740F00B040132743840084BE7C3B3FA4740F057C9C7EE6E38403035B401D8FA474090035ABA826D3840D0D03FC1C5FA474080AA0B7899693840E0B837BF61FA474050B08D78B253384028DB87BCE5F647407017EFC7ED3F3840F82CCF83BBF3474050DC2A88813E3840682B137EA9F34740406211C30E233840D8BEB9BF7AF44740F046753A90213840F0230C0396F4474050EACC3D24203840B8ECF483BAF4474050B60F79CB1D3840306893C327F5474060BEA085041C3840E0CDFE40B9F54740D0CABDC0AC1838402020ED7F80F7474030DB87BCE5163840D08558FD11F847401073F4F8BD09384038F04E3E3DFA4740A0F27684D3063840001E8A027DFA4740604F1F813FF83740286211C30EFB4740A0992842EAD23740909065C1C4FB4740305DA5BBEB9037408021E4BCFFFF4740A0698A00A78337406058A9A0A2FE4740306C06B820833740E0AC33BE2FFE47406055A181588237408096E7C1DDFD4740E0BB783F6E7F374090CC07043AFD474040D505BCCC7C3740C8031F8315FD4740B0FE7A85057B3740D888997D1EFD4740E05D4BC807693740E08558FD11004840E0E847C3295B3740806CCB80B302484080AD4CF8A54E3740D088997D1E054840800C1D3BA84C3740B068ACFD9D0548408015E0BBCD4B3740D8FA5B02F005484070C763062A4B3740101286014B06484010857AFA08483740000F45813E09484030DB87BCE5463740B0A10DC0060A4840007976F9D643374078B130444E0B484000274D83A241374008B2497EC40B484070499D80262E374038B7ED7BD40D484090FE7A85052B3740801B62BCE60D4840406F47382D283740E0CDFE40B90D484000335184D4253740D8B5F63E550D484080ABAE433521374010DFA63FFB0B4840B06E2EFEB61F374078B130444E0B484040DC2A88811E3740081E8A027D0A4840307288B8391D374050465C001A094840307B4B395F1C3740D8DC43C2F7064840F055BABBCE1A3740D8031F8315054840D0C1FA3F87193740B04DD53DB203484050780AB952173740B8A10DC006024840D068ACFD9D153740A85CA8FC6B01484050E78BBD170B374088A52C431CFF47402069C53714EE3640901EA33CF3FA47402096CE8767E536400806820019FA47407054FCDF11E53640A85CE15D2EFA474050DEC83CF2DB3640606D37C137FF4740D046753A90E13640C8D03FC1C5024840309BE447FCE236401844F98216044840A083F57F0EE33640580DFB3DB104484070B950F9D7E23640206893C327054840D0D90242EBE13640385FD042020648400094BF7B47E136405876FA415D064840C074B0FECFD9364028F04E3E3D0A4840F03D5DDDB1D8364098AB58FCA60A4840306F47382DD836402035B401D80A484090A86DC328CC3640F8298E03AF0E484050C763062ACB364000DC65BFEE0E4840308C9FC6BDC9364028C632FD120F4840406F47382DC836403041B8020A0F4840E0D6C1C1DEBC36402829B000A60E4840803F6EBF7CB23640B89ECC3FFA0C4840A0336ABE4AAE3640E064FF3C0D0C4840D04CF73AA9AB36407815E0BBCD0B48405061A5828AA63640807B1002F20B4840B04198DBBDA43640A87D3A1E330C48406007B29E5AA13640384D66BCAD0C4840B0E07EC0039F3640C07FBA81020D48403075745C8D9C36406067EE21E10D484000369204E19A3640A85FE97C780E484030F04E3E3D9A3640E076137CD30E4840A02766BD189A3640D89D60FF75104840002F6D382C993640B8B915C26A12484030956247E398364080992842EA124840306C06B820933640F0BD4D7FF617484070C2137AFD8136405858E201651F4840E0A9F23D23813640300B98C0AD1F48401000000000803640100C59DDEA1F48407079AD84EE7E364038EACC3D2420484000541C075E7D3640804E417E3620484060C8957A167C3640D88558FD11204840F0F78C4468743640C809A1832E1F4840208BFCFA21623640B08FF980401F4840A0F8F884EC60364050DD5CFC6D1F4840D05D4BC807593640584CDE003323484040ED0DBE3045364010E52840142E4840901A3048FA4436405834D6FECE324840F095CE876745364030D236FE4433484010A0C37C79453640002DCF83BB334840D05147C7D544364030C9737D1F344840B0A4C002983A3640B0B6D4415E354840102BC0779B373640280516C094354840F0A886FD9E34364010A0C37C79354840B03BA583F52B3640781536035C344840903D25E7C4263640F8CC04C3B934484010BE4D7FF6273640502E54FEB5484840704F1F813F283640B074B0FECF494840D0CABDC0AC283640C053E57B464A4840506DA983BC2A364030D236FE444B4840405B2382712C364030179CC1DF4B484080B262B83A3C364008BE4D7FF64F484060B950F9D7523640E009A1832E574840A02DE8BD3154364028BD6F7CED574840A0716F7EC354364020D5777E51584840504CDE0033633640A8E3310395654840E0C77C40A063364038E44A3D0B664840E0C77C40A06336402841B8020A674840B0F6E978CC6C364078758E01D9714840F0E506431D76364048E3DEFC86794840E040F3397787364008DC65BFEE7E484070B3CEF8BE88364088A52C431C7F4840D0C1FA3F8789364058DD5CFC6D7F4840703D997FF48936402038F581E47F4840207288B8398D36408824253D0C854840B077F17EDC8E3640E08BDAFD2A8A4840B001BC051290364030BA2EFCE08A48402082397AFC923640D8C77C40A08B4840901B62BCE69536404816BEBED68B4840307156444D983640109C33A2B48B484060465C001A993640A8C85A43A98B4840E0D6C1C1DEBC364030E44A3D0B864840F03E558506DA3640786649809A80484060D158FB3BDB3640F89C82FC6C80484030FC523F6FDE3640584F1F813F804840C001BC0512E03640E8B2B5BE4880484020D6E3BED5E23640A859677C5F804840A0336ABE4ADE3640A84DD53DB2834840307288B839DD3640303B3602F1844840D04334BA83DC364028B7ED7BD48548407097FE25A9DC3640F89925016A86484060BFD2F9F0DC36400021CB828987484070D4997B48E03640A8E67283A18A4840D04F38BBB5E036408084D382178B484070D4997B48E03640000072C2848B484040D026874FDA3640600438BD8B8D4840F08D3D7B2EC7364018D236FE44934840B0A17F828BB53640D8D6C1C1DE944840A06CAE9AE7B43640D8D6C1C1DE9448401045D7851FB43640D8D6C1C1DE944840104E9A0645B33640808A558330954840604CDE0033B33640D8CDFE40B9954840A016838769B33640B8AD11C13896484050E09D7C7AB4364088A52C431C974840103F558506BA364028179CC1DF9B484080ABAE4335C13640786CCB80B3A2484080069B3A8FC236402844F98216A44840A0E67283A1C2364028327381CBA54840D07344BE4BBD3640505E64027EB14840F0C08EFF02BD3640583D997FF4B14840F05CDF8783BC3640D8B837BF61B24840F0AB5626FCBA36403880F0A144B34840506DA983BCBA3640D89A1F7F69B3484040111AC1C6B13640508BC1C3B4B9484000BE4D7FF6A7364010A304FD85C24840C0F3A8F8BFA736406064E60297C34840B019C40776A8364000240C0396C4484070A99F3715AD36406001F73C7FC84840A0336ABE4AAE3640D80F238447C9484020D50627A2AF3640B0D7BB3FDEC94840202BC0779BB73640B0B6D4415ECD4840B0E9B303AEC7364060FB743C66D64840307B4B395F1C374030F04E3E3DFA484090B7B2446725374028B7ED7BD4FD48409030293E3E393740500438BD8B0549406064E602973B374060FB743C66064940E0CDFE40B94D3740503A58FFE70C49409083F57F0E533740588E0244C10E4940F020CB8289573740604F1F813F1049402051853FC357374068C405A0511049408018213CDA603740904B00FE29134940D061BEBC007F3740D0915CFE431C494060D026874F8A3740E893DC61131F494010274D83A2913740302F3201BF20494030780AB952973740B03E90BC73224940505260014CAD3740E0C1FA3F872949403090D959F4AE374090E123624A2A4940D0F44BC45BAF3740B06BED7DAA2A494040C8CF46AEAF374068AFE941412B4940002D246074B13740E08DCC237F2E494020274D83A2B13740D076137CD32E4940901F46088FB23740786F0C01C02F4940A02DE8BD31B43740F89C82FC6C304940B00EF27A30B53740B0CB9BC3B53049404048179B56B63740B8CB7EDDE9304940B0EAE5779AB83740D0949D7E50314940006D567DAEBA3740D885CABF96314940D03C80457EC13740081E8A027D324940E04BC5C6BCCA3740080072C284334940307D5A457FD03740887B1002F2334940A093A641D1D83740E064FF3C0D344940108ECBB8A9E137403838F581E43349401098A3C7EFED3740B0C85A43A933494040E3DEFC86F93740E0B22781CD33494010B8CB7EDDFD374028C9737D1F344940E058FB3BDBFF3740500DFB3DB13449401094BF7B47013840A83B4F3C67354940E04334BA831C3840A8656B7D91484940D06D1805C11B38409048BF7D1D504940307A19C5721B384050465C001A514940F01D8A027D123840D8E2C5C210594940A09065C1C403384000AF08FEB75E49409024253D0CF53740A859677C5F644940D0F78C4468F43740B0716F7EC3644940209221C7D6F33740D0CDFE40B9654940C0533A58FFF33740B08FC01F7E664940D064FF3C0DF43740608E0244C1664940F03B1405FAF43740B8B393C151684940F09FC37C79F5374008301004C8684940A0FC6B79E5F63740D0C1FA3F87694940707F2F8507F93740203E7782FD694940407288B839FD3740D0B837BF616A49408039252026053840A0AED2DD756A4940A0A2EBC20F063840382F87DD776A4940201B4982700D3840A0B915C26A6A494060B08D78B2133840E08BDAFD2A6A4940E03A71395E1D3840A0B915C26A6A4940307E8CB96B21384030BA2EFCE06A4940F03DB2B96A223840F8E769C0206B4940F03B1405FA243840200ED940BA6C49409024253D0C25384038B7ED7BD46D494050D6A88768243840A8AD11C1386E4940B0F3A8F8BF17384000301004C8704940D05FE97C78163840787E5182FE704940B06246787B1038407842AF3F897149405040DAFF000F384010ACC77DAB714940E0AF743E3C0B384008F12C414672494050465C001A0938406034D6FECE7249405058E20165073840E09A1F7F6973494010C18EFF02FD3740D009A1832E7749406058E20165F73740007F6ABC74794940103483F8C0F6374080758E01D9794940F0D3F19881EE374050EF54C03D7F4940D0D38041D2E73740B8E0F082888849400021CB8289E73740D8F71A82E388494030861DC6A4CF3740B068ACFD9D954940800F5EBBB4C1374058E3DEFC8699494090BB253960BB374030FF93BF7B9B4940F041960513AF3740203B3602F1A4494050499D8026AE37403841B8020AAF494090C6F7C5A5AE3740B041D13C80AF494080B5A33847B13740584CDE0033B34940407E8CB96BB13740D8B22781CDB34940C0EAE5779AA83740D0EEC9C342BD4940F02A16BF29A837401836035C90BD4940E040F33977A7374020E44A3D0BBE494050E09D7C7AA43740109700FC53BE494050198EE733A43740109700FC53BE494090F8F884ECA03740109700FC53BE4940900BCEE0EF9F374068A032FE7DBE494030861DC6A49F37404861A5828ABE49409096E7C1DD9D3740D009A1832EBF494070BE9F1A2F9D3740E024068195BF4940605B2382719C3740009D82FC6CC049401015713AC99A3740A0A17F828BC3494020BB0CFFE9A23740B0B915C26AC2494060D6A88768A4374060DA1B7C61C2494070B7B24467A53740B06BED7DAAC24940F052793BC2A53740805A457F68C44940506A6803B0A53740383B3602F1C44940A00F5EBBB4A1374058F833BC59C94940A06E2EFEB69F3740B083F57F0ECB494000429605139F3740D09A1F7F69CB4940605B2382719C374030F6D03E56CC4940B0FFACF9F19B3740B0716F7EC3CC4940D04CF73AA99B374000EEEBC039CD49409015E0BBCD9B374020B7ED7BD4CD4940400ED940BA9C3740608E0244C1CE4940D03A71395E9D3740902AA73D25CF49406040DAFF009F3740D0D38041D2CF4940802DE8BD31A4374050465C001AD149405061A5828AA63740D0C1FA3F87D14940B06BED7DAAAA3740383E7782FDD1494020B8CB7EDDBD3740109A417C60D34940A0F8F884ECC03740000072C284D3494020895E46B1C43740A09BFD8172D3494030809BC58BE5374020F911BF62D14940D0DC43C2F7E6374080ABAE4335D14940104818062CE93740A0CB9BC3B5D049405064E60297EB3740F80B76C3B6CF494050BFD2F9F0EC3740D0DC43C2F7CE494060E61F7D93EE37405831957EC2CD49408021E4BCFFEF3740B0BF97C283CC4940F04F38BBB5F03740D8C77C40A0CB494010274D83A2F1374078B130444ECB4940902DE8BD31F4374038BA2EFCE0CA4940E06740BD19F93740E082177D05CB4940A089778027FD374030FF93BF7BCB494050B81E85EB013840A0923A014DCC4940B0FE7A85050B38409048BF7D1DCE494090A2EBC20F1238408821E4BCFFCF49400021CB828947384028FC523F6FDE4940000F45813E49384088A52C431CDF4940D0548847E2493840B041D13C80DF49408015E0BBCD4B384058F833BC59E14940505B2382714C384058DA1B7C61E24940B080B4FF014E384080698A00A7E54940A08D2441B84E384028BD6F7CEDE7494070CAA48636503840C80F238447E949408018213CDA503840908AE3C0ABE9494050CBD6FA226138403802D53F88F04940802DE8BD3164384060F833BC59F1494040809BC58B653840505E64027EF1494000B58AFED068384028266F8099F14940004E9A0645B33840B0B915C26AF24940100516C094BD384000D9243FE2F14940A02DE8BD31E43840504CDE0033F3494040780AB952E73840089A417C60F349403098A3C7EFFD3840300ED940BAF44940505260014C0D3940F8F36DC152F74940909C69C2F6173940786649809AF84940C06BED7DAA2A394008D061BEBCFA49403098A3C7EF2D39402835B401D8FA4940F0D6C1C1DE3C394088992842EAFA4940D0FD0E45813E394098D11DC4CEFA4940F081397AFC4239406055A18158FA494070C554FA09473940D873D2FBC6F949401039D384ED4F39403050FD8348F84940F0D38041D2573940B0A44E4013F74940605B2382715C39403029B000A6F6494060672783A370394038E44A3D0BF64940002DCF83BB8B3940601C40BFEFF54940509B00C3F28B3940D843A67C08F64940A001BC0512903940A8CEDC43C2F54940E02E6D382C993940B868ACFD9DF5494090A99F3715AD3940A880B4FF01F64940A0ACE0B721B23940E0E506431DF64940209694BBCFB93940B85FE97C78F6494070CFBA46CBBD394008DC65BFEEF64940007976F9D6C3394008BE4D7FF6F74940F049B6BA9CC63940D0EB884336F84940605E64027ED139405070EA03C9F7494030DB87BCE5063A40B8BF97C283F4494080C93846B2233A40281ADD41ECF0494080AEEFC341263A40F8BD4D7FF6EF494040840EBA842B3A403829B000A6EE4940A0336ABE4A2E3A4078AEEFC341EE4940C00EF27A30353A408896E7C1DDED494060D026874F4A3A40F8EDEBC039ED4940100516C0944D3A40605260014CED4940202A8E03AF563A406831957EC2ED4940407288B8395D3A40D0FA5B02F0ED4940C0923A014D6C3A408896E7C1DDED4940D058FB3BDB6F3A4008CD203EB0ED4940301ADD41EC703A40B83B4F3C67ED4940A00BB1FA23703A406082FE428FEA4940A00BB1FA23703A4010C11C3D7EE94940F09C82FC6C703A4008E2E7BF07E94940D0F92AF9D8713A40B0B393C151E84940A024253D0C753A406022C2BF08E84940C0A70183A47F3A4028BD6F7CEDE7494060BC9179E4873A40A88636001BE84940206BD44334923A40302F3201BFE84940F04CF73AA99B3A4050465C001AE94940901F46088FA23A4050465C001AE94940009700FC53A63A4030E109BDFEE84940A0A86DC328AC3A40B0B393C151E84940C07D737FF5B83A40F8AE08FEB7E649406031957EC2C53A40F8230C0396E44940F08AFCFA21D23A4038BA2EFCE0E24940B004FD851EE53A40682E54FEB5E04940A09BFD8172EB3A4020EACC3D24E04940F057C9C7EEEE3A40809C69C2F6DF4940B0F06778B3F23A40D058FB3BDBDF4940C0EAE5779AF83A40E8B2B5BE48E04940009D82FC6C003B40803CBB7CEBE1494050D6A88768043B4058DA1B7C61E24940E040F33977073B40081E8A027DE2494020895E46B1143B40806CCB80B3E24940E05D4BC807293B40283E7782FDE14940C080B4FF012E3B4008274D83A2E14940D03DB2B96A323B40E0A9F23D23E14940A016838769333B409018213CDAE0494030895E46B1343B40F8A5457D92DF4940E05B3CBCE7343B4088A52C431CDF494030895E46B1343B40F8F6AE415FDC4940E064FF3C0D343B4080B130444EDB4940309BE447FC323B40D858FB3BDBD74940D0D03FC1C5323B40B8AD11C138D64940604CDE0033333B4020327381CBD54940901B62BCE6453B40386893C327CD49402021CB8289473B40B0BF97C283CC4940F05D4BC807493B4030F6D03E56CC494000369204E14A3B40D0915CFE43CC4940A06BED7DAA6A3B4060E09D7C7ACC494000C4CF7F0F723B40303B3602F1CC4940401D1EC2F8753B40A8B6D4415ECD494040800D8810833B4020C022BF7ED0494040956247E3983B40E076137CD3CE49401039D384EDAF3B40B89ECC3FFACC494060CE177B2FB63B4008F7AE415FCC4940D070033E3FB83B405016BEBED6CB494000ACC77DABB93B40F8E769C020CB4940D0F10A444FBA3B40506DA983BCCA4940408DD13AAABA3B408854C37E4FCA4940408DD13AAABA3B40D873D2FBC6C9494090BAF3C473BA3B4088ABAE4335C9494070E3DEFC86B93B40584F1F813FC84940D00A0DC4B2B53B40189C6C0377C649404069C53714AE3B4030F38FBE49BF4940D057C9C7EEAE3B40E0DC43C2F7BE494070CFBA46CBBD3B40082DCF83BBBB4940C00A7F8637BF3B406064E60297BB4940009D82FC6CC03B4000B2497EC4BB4940E04E0647C9CF3B40D8E847C329C349402094BF7B47D13B40B87A32FFE8C3494020274D83A2D13B4010BEDBBC71C44940900F5EBBB4D13B40607FBDC282C54940107497C459D13B40B041D13C80C7494060CBD6FA22D13B409021E4BCFFC749402039D384EDCF3B40D00F238447C9494070D367075CCF3B40306BD44334CA4940E04E0647C9CF3B408836AB3E57CB4940B0F8F884ECD03B40D0915CFE43CC4940F034EF3845D33B40D8B5F63E55CD494090129F3BC1D63B4098C519C39CCE4940603D997FF4D93B405058E20165CF4940507B4B395FDC3B406070EA03C9CF49404098A3C7EFDD3B40D0D38041D2CF4940101E8A027DE23B400079E8BB5BCF494060D7DAFB54E53B40A85FE97C78CE494000ACC77DABE93B40583A58FFE7CC494090A86DC328EC3B40B07A32FFE8CB4940E061BEBC00EF3B40B083F57F0ECB494070C075C58CF43B4038266F8099C9494020ACC77DABF93B40D8CABDC0ACC84940C080B4FF01FE3B40F8EAAA402DC84940D046753A90013C4008BE4D7FF6C74940E0D90242EB113C40F8EAAA402DC849406061A5828A163C40B8B393C151C84940E04BC5C6BC1A3C40602E54FEB5C84940A0897780271D3C4080457EFD10C94940A01F46088F223C40B853E57B46CA4940802DE8BD31243C40501F813FFCCA4940E03730B951283C4000E5284014CE494080A86DC3282C3C40F802B34291D04940C0ED26F8A62D3C4068F833BC59D1494060D4997B48303C408054C37E4FD24940D049B6BA9C363C406016BEBED6D34940D0D38041D2373C40E0DF844204D44940507288B8393D3C40B84412BD8CD44940406BD44334423C4000A986FD9ED4494080FDD7B969433C4000F7AE415FD4494050431B800D443C40E0DF844204D44940C0EF3504C7513C40D09A1F7F69CB4940D057C9C7EE6E3C40D09D60FF75C84940301D1EC2F8753C4060103CBEBDC94940208C9FC6BD793C40306BD44334CA4940400ED940BA7C3C40D0B837BF61CA494040FC523F6F7E3C40D0B837BF61CA494070D367075C9F3C40382F3201BFC84940B0656B7D91A03C405801F73C7FC84940307E8CB96BA13C40F8EAAA402DC8494050C2137AFDA13C404870EA03C9C74940C08CB80034A23C40F8F36DC152C7494080A2EBC20FA23C40D0CDFE40B9C5494030111AC1C6A13C40286893C327C54940F0D90242EBA13C4030C9737D1FC4494050B950F9D7A23C40D0EE5701BEC14940C016838769A33C408893A641D1C0494090129F3BC1A63C40A87A32FFE8BB49402021CB8289A73C40A883F57F0EBB494060465C001AA93C4078758E01D9B9494090A86DC328AC3C40B09E3E027FB84940300516C094BD3C40D85B3CBCE7B44940208FE046CABE3C40500DFB3DB1B44940E04543C6A3C03C4008A986FD9EB4494050D8463CD9C13C4080724D81CCB44940F07876F9D6C33C40A8B6D4415EB5494060431B800DC43C40581C40BFEFB54940801A3048FAC43C40B0957B8159B94940206211C30EC33C40E0DF844204BC4940604CDE0033C33C405025034015BD4940002C2CB81FC43C4020E44A3D0BBE494030E44A3D0BC63C4000F46DC152BF4940A0FE7A8505CB3C4078A2EBC20FC24940009C508880CF3C40805A457F68C44940F02B2CB81FD43C40D8FA5B02F0C549402018080264D83C4008DC65BFEEC64940001B4982700D3D4000301004C8D04940A0069B3A8F123D40885D86FF74D14940D0B5F63E55153D40608BC1C3B4D1494050C554FA09173D4058103CBEBDD14940C031AEB8381E3D40D0C1FA3F87D14940E04718062C293D40E09D60FF75D0494050DA1B7C612A3D40504F1F813FD0494020FC523F6F2E3D4078A52C431CCF494010541C075E3D3D4088698A00A7C5494080336ABE4A3E3D4000D6E3BED5C44940A001BC0512403D40F8264D83A2C1494060CAA48636403D40806649809AC04940C0A70183A43F3D40A8BC564277BF4940809FAA42034D3D40884B00FE29B3494050D367075C4F3D4008274D83A2B1494030EACC3D24503D40D00F238447B149400082397AFC523D408039ECBE63B0494090F27684D3563D40786F0C01C0AF49400018080264583D404870EA03C9AF4940D02500FF945A3D4080C45A7C0AB0494030956247E3683D40906308008EB34940802AA73D259F3D4008AF08FEB7BE494080B471C45AA03D408078CF81E5BE4940A09BFD8172AB3D40D858FB3BDBBF494050E61F7D93AE3D40889C69C2F6BF4940C0A17F828BB53D40E0D38041D2BF4940C0F3A8F8BFB73D4030F38FBE49BF494010956247E3B83D404861A5828ABE4940F03E558506BA3D40B0CEDC43C2BD4940A0BB253960BB3D4028E17B7F83BC4940102DCF83BBBB3D402844F98216BC4940F0DF844204BC3D40F0E769C020BB4940300ED940BABC3D40F8F02C4146BA4940D07344BE4BBD3D4000D9243FE2B9494000AF08FEB7BE3D4030CCB4FD2BB949406055A18158C23D40E09D60FF75B84940200C040132C43D407839ECBE63B84940B068ACFD9DD53D40F802B34291B84940A00F5EBBB4E13D403835B401D8BA494020F911BF62E93D4028E17B7F83BC4940102DCF83BBFB3D4078AEEFC341BE4940306C06B820033E40A8C519C39CBE4940C0FE7A85050B3E40588E0244C1BE494040E09D7C7A243E40802AA73D25BF494060D9E90775293E40802AA73D25BF4940B0897780272D3E40E0DC43C2F7BE4940C061BEBC002F3E40B077F17EDCBE49409036AB3E57333E4088336ABE4ABE4940103483F8C0363E40A0A17F828BBD4940B08636001B583E4078A86DC328B4494070465C001A593E4020179CC1DFB349408030293E3E593E40009A417C60B34940D0C1FA3F87593E40B85CA8FC6BB1494010ACC77DAB593E409096E7C1DDAD4940F0DC43C2F7763E406831957EC2A54940908EC877298D3E4070D05E7D3CA04940B0F8F884EC903E406831957EC2A54940B05CA8FC6B913E40001286014BA64940208BFCFA21923E40A04A94BDA5A64940705B2382719C3E40D80F238447A94940A077F17EDC9E3E40F8264D83A2A94940B02AC3B81BA43E40C80DF8FC30AA4940F05B3CBCE7A43E405007793D98AA4940D05147C7D5A43E40D8DC43C2F7AE4940B0716F7EC3A43E40B8BC564277AF4940D0E506431D963E40A8C519C39CBE494050B60F79CB8D3E40B0B6D4415EC54940D04543C6A3903E405855A18158D2494030861DC6A49F3E40D08BDAFD2ADA49407018213CDAA03E40A083F57F0EDB4940A008707A17AB3E40381A6B7F67E5494040840EBA84AB3E40D8FA5B02F0E54940B0FE7A8505AB3E4028145B41D3E64940B010018750A93E408821E4BCFFE74940E05D4BC807A93E40089D82FC6CE8494050465C001AA93E40A87D737FF5E8494070E3DEFC86A93E40885D86FF74E94940D0F10A444FAA3E4030D8463CD9E94940B00A7F8637BF3E405007793D98F24940404CDE0033D33E405831074147F94940D068ACFD9DE53E40A089778027FD494000A0C37C79F53E40286552431B004A40903045B934EE3E4040957EC2D9034A40501405FA44EE3E4028BAA0BE65044A40902AA73D25EF3E40B06E2EFEB6074A40F0A5457D92EF3E40B88636001B084A4030FD4CBD6EF13E40805A290472094A4070D7DAFB54F53E40206BD443340A4A406061A5828AF63E40E0B837BF610A4A4030F911BF62F93E405007793D980A4A4060D158FB3B1B3F40A883F57F0E0B4A40D0F92AF9D8213F40A883F57F0E0B4A404083DC45984A3F405007793D980A4A402088BB7A154D3F40A0C85A43A90B4A4080992842EA523F40001B4982700D4A4040780AB952573F4058FB743C660E4A40A074B0FECF593F40788D2441B80E4A40A00C1D3BA85C3F4008DC65BFEE0E4A4080ABAE4335613F4088A52C431C0F4A4090A86DC3286C3F40F078E8BB5B0F4A40502E54FEB5803F402841B8020A0F4A4030E44A3D0B863F4038DB87BCE50E4A4030F38FBE499F3F40E0FA5B02F00D4A4050C8957A16BC3F40280516C0940D4A40F0CABDC0ACC83F4030B7ED7BD40D4A4000274D83A2D13F4088AEEFC3410E4A40703A58FFE7D43F4088AEEFC3410E4A40E0CABDC0ACD83F4038E44A3D0B0E4A40D0ED26F8A6DD3F40280516C0940D4A407036AB3E57E33F4030D505BCCC0C4A4000335184D4E53F40B0923A014D0C4A40B0F3A8F8BFE73F40002DCF83BB0B4A40D0CABDC0ACE83F4028BA2EFCE00A4A40D0CABDC0ACE83F40D0F71A82E3084A405079AD84EEFE3F40D0DC43C2F7064A40D097DEFE5C0E4040600438BD8B054A4028BD6F7CED0F4040A868ACFD9D054A403802D53F8810404028327381CB054A4088724D81CC1C4040D08BDAFD2A0A4A40B0716F7EC3244040286893C3270D4A40081286014B264040A880B4FF010E4A4050137D3ECA264040E097DEFE5C0E4A40901EA33CF32A404028C9737D1F144A4008E869C0202B4040500DFB3DB1144A40901EA33CF32A4040A889778027154A405807793D982A404008A0C37C79154A40A8A10DC0062A404080AEEFC341164A40383E7782FD294040608E0244C1164A408096E7C1DD2D4040180B98C0AD274A408048BF7D1D2E4040D0EB884336284A4088A52C431C2F4040D8C1FA3F87294A40B841D13C802F404010D9243FE2294A40A0AAD0402C3140404807793D982A4A40A83E90BC73324040F8BA0CFFE92A4A40E05B3CBCE7344040801EA33CF32A4A4028FF93BF7B434040D8C1FA3F87294A4000AF08FEB7464040B07D737FF5284A40A0D11DC4CE4A4040600ABABDA4274A40D8FA5B02F04D404000FD304278264A40A874B0FECF5140409024253D0C254A40608BC1C3B45940405055A18158224A4078698A00A75D4040805D86FF74214A4060465C001A61404030E109BDFE204A4058E09D7C7A744040806F0C01C01F4A40B8AD11C138764040500ABABDA41F4A403802D53F887840405001F73C7F204A40087C293C687C404000BB0CFFE9224A40D0D6C1C1DE844040802AA73D25274A40807E5182FE984040F0EAAA402D304A40A08CB800349A4040886649809A304A40B883F57F0E9B40402802D53F88304A40D09D60FF75B04040908D2441B82E4A40C8438A0112B540400085ECBC8D2D4A40B8BC564277B54040C87F48BF7D2D4A40'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('SM','SM','SMR','674','San Marino','6.12','30214','150','39','12.46','43.942','0106000020E61000000100000001030000000100000018000000037CB779E3D428404489963C9EFA4540FA298E03AFE628402A1A6B7F67FD4540FC17080264E82840FE47A643A7FD4540CDCCCCCCCCEC28402AE44A3D0BFE45403145B9347EF12840FF9600FC53FE4540267156444DFC28405628D2FD9CFE454056B950F9D702294000C45DBD8AFE4540020D36751E052940FF9600FC53FE45404FCDE5064305294027327381CBFD4540040473F4F8052940272F3201BFF845405A9E0777670529407F4E417E36F84540B151D66F26FE2840D6AC33BE2FF64540FC1A498270FD2840D1031F8315F54540A56ABB09BEF928402BDEC83CF2F34540DCA16131EAF228402635B401D8F24540A376BF0AF0ED2840A7E67283A1F24540CADE52CE17EB2840FD4AE7C3B3F24540C9E4D4CE30D528407F15E0BBCDF34540286211C30ED32840FCDEA63FFBF34540BA2D910BCED0284048DDCEBEF2F44540A46DFC89CACE28405628D2FD9CF645404ED367075CCF284027F911BF62F94540257497C459D1284028F04E3E3DFA4540037CB779E3D428404489963C9EFA4540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('RB','RS','SRB','688','Serbia','10235','9863026','150','39','20.806','44.032','0106000020E6100000010000000103000000010000008C020000A52E19C7481234405C7347FFCB47454029E78BBD171B3440AC53E57B46524540FE99417C601B3440D0D03FC1C5524540257A19C5721B34407E9065C1C4534540D925AAB7061A3440D3BEB9BF7A544540AD4D637B2D183440000341800C55454052B81E85EB11344079AEEFC341564540D2393FC5710C3440508E0244C1564540AB5FE97C780634402BDB87BCE5564540A77A32FFE8033440FF08C3802557454055C2137AFD01344051853FC39B5745407E1EA33CF3FA3340D673D2FBC659454028F04E3E3DFA3340FF058200195A45407E8AE3C0ABF933405182FE428F5A4540FF05820019FA33407C6308008E5B45407E1EA33CF3FA33407D5A457F685C45402DCC423BA7FD33407D96E7C1DD5D4540037976F9D6033440A7B393C151604540FF058200190A34407BA2EBC20F62454051C1E105111134407E1EA33CF3624540D2C77C40A0133440286211C30E634540FA298E03AF163440D482177D05634540CF4BC5C6BC1A34405307793D9862454052B5DD04DF1C344028F04E3E3D624540FE99417C603B3440AB5CA8FC6B614540D6A9F23D23613440A96BED7DAA6A454055C2137AFD6134407E1EA33CF36A4540247D5A457F603440520DFB3DB16C454083F755B9505934407D5D86FF7471454056BC9179E45734407BA2EBC20F7245407AA86DC3284C3440D2C43BC0937645404DD9E907754934407E5704FF5B774540FC1D8A027D423440A8E0F082887845402DCC423BA72D3440D3F4D901D77B4540D925AAB7062A344056F5F23B4D7C4540008E3D7B2E27344001BEDBBC717C45405531957EC2253440AB59677C5F7C454028F38FBE490F3440552E54FEB5804540D82E6D382C093440A8716F7EC3844540514F1F813FF8334000C79E3D978B4540D042024697EB3340A968ACFD9D8D4540ABEAE5779AC833407E1EA33CF3924540FF93BF7B47B133407D96E7C1DD954540F92CCF83BBAB3340FF9600FC53964540286552431BA83340D4F19881CA9645407B116DC7D4A53340266E15C44097454027F6D03E56A43340D0D38041D2974540A4FB3905F9953340A7AD11C1389E45404FCAA486369033407D93A641D1A04540D4BB783F6E8F3340508BC1C3B4A145405340DAFF008F33405307793D98A24540AB59677C5F8C3340D3BEB9BF7AA4454059A7CAF78C8433407B6649809AA84540286211C30E8333407AABAE4335A94540800F5EBBB4713340D0D38041D2AF4540FB20CB8289473340A4C2D84290B945407AABAE4335413340AB984A3FE1BA4540CC07043A933A3340B7EC10FFB0C1454058AA0B7899493340FE47A643A7C54540ABEAE5779A6833405534D6FECECA4540A4FE7A85057B3340D6A9F23D23C94540A9DA6E826F7E3340A7B0524145CB4540D0D03FC1C58233405340DAFF00D74540A7E67283A1823340AA656B7D91D84540FC1D8A027D823340FA264D83A2D94540AB5CA8FC6B81334081423D7D04DC45404FCAA48636803340D3FA5B02F0DD45407F8461C0927F3340508E0244C1DE454052499D80267E3340527C7C4276E045402CD505BCCC7C3340508BC1C3B4E145407E8AE3C0AB7933407C992842EAE245407D21E4BCFF6F3340A9DA6E826FE64540027FF8F9EF5D3340295FD04202EE45408411FB0450403340B8AD2D3C2FFB4540D787F546AD3C33401E3526C45C004640D787F546AD3C3340187B2FBE68014640505260014C3D3340A774B0FECF014640A64412BD8C3E3340AEB6627FD901464003603C83864E3340F511F8C3CFFF454023861DC6A44F334051853FC39BFF4540029CDEC5FB593340D9092FC1A9FD45407E1EA33CF35A33402A1A6B7F67FD4540D7A6B1BD165C3340520DFB3DB1FC45402DCC423BA75D334052431B800DFC4540CF4E0647C95F334000C79E3D97FB45401B4AED45B46D334094DE37BEF6FA454000917EFB3A7C3340FFCF61BEBCFA4540BA6B09F9A08333408F8AFF3BA2FA4540C4AF58C345863340F2ED5D83BEFA45402654707841883340B8AD2D3C2FFB45409FAD8383BD9D33402B86AB0320024640D2C43BC0939E3340A6B915C26A02464025CCB4FD2B9F3340E690D442C9024640F1F3DF83D79E334021AE9CBD3306464058AD4CF8A59E3340FA298E03AF064640419E5DBEF59D3340C7A01342070746407D93A641D1983340A86E2EFEB6074640AB59677C5F7C334002BB9A3C650F4640AD8905BEA25B3340EAB12D03CE1A4640FC1A4982703D3340823CBB7CEB214640DEE8633E203C3340B1DD3D40F7214640FA980F08742A33407D5A457F682446408599B67F65293340ECA529029C2446408200193A76283340543A58FFE7244640257497C4592133407EC9C6832D28464022895E46B1203340C861307F85284640CF4BC5C6BC1A3340530438BD8B2D4640A4FE7A85051B33407F4E417E36304640D0420246971F33408F352383DC414640B5705985CD203340EC3026FDBD4246401615713AC9223340836C59BE2E4346409E0B23BDA8313340E04BE141B3474640D5B2B5BE48503340276BD443345A46402AE44A3D0B563340520ABABDA45F464025CFF57D38583340A165DD3F16624640A8E0F082885833402A1DACFF7362464055C2137AFD613340AB5FE97C786E4640226FB9FAB16133409F3BC1FEEB6E4640D828EB37135F3340A774B0FECF714640D4BB783F6E4F334056F5F23B4D744640800C1D3BA84C3340A5BF97C28374464029EACC3D24303340D6AC33BE2F764640D63A71395E2D3340A7AD11C138764640A4FE7A85052B3340D3FA5B02F07546405340DAFF001F3340FE99417C60734640A3073E062B0A334079AEEFC3416E4640AC5626FC52073340D1CABDC0AC70464052431B800D0433402CD8463CD9714640D53DB2B96A023340FC1D8A027D7246407AABAE4335013340D5AF743E3C734640D6A9F23D230133407E9065C1C4734640D446753A90013340FE0B040132744640D0D03FC1C50233407B9FAA4203754640A9DDAF027C033340D4B5F63E55754640D63730B951083340FF08C3802577464027F911BF620933407E5704FF5B774640A4FE7A85050B3340266E15C4407746407B9FAA42030D3340D4F19881CA764640A8E33103951D3340D7A6B1BD16844640A96BED7DAA1A3340AB59677C5F8C4640CE548847E22933407F4B00FE299B46407F15E0BBCD2B3340282CF180B29B46407D21E4BCFF2F33407E9065C1C49B46406D72F8A41335334029E78BBD179B464056BC9179E4373340EA5A7B9FAA9A46407AA86DC3283C33407D5D86FF7499464028F38FBE493F3340520ABABDA49746404FCAA4863640334002BB9A3C659746400282397AFC423340A9A44E401397464028F04E3E3D5A3340D6AC33BE2F964640FE0E45813E69334055FB743C66964640FA980F08746A33407C60C77F8196464000917EFB3A6C33402541B8020A974640800C1D3BA86C33407F4E417E369846400188BB7A156D3340AB984A3FE19A4640D44334BA836C3340543A58FFE79C464029E78BBD176B33402AE44A3D0B9E4640C85BAE7E6C663340D6AC33BE2F9E464002637D0393633340780C8FFD2C9E4640FC8F4C874E5B3340D47FD6FCF89D4640B9C7D2872E5833407EC34483149E464023A298BC015233406AC18BBE829E4640AC3AAB05F6483340DACA4BFE279F4640D5EB1681B14233407E8AE3C0AB9F464022895E46B1303340F9872D3D9AA24640A9DDAF027C2333402CD505BCCCA446402CD505BCCC1C334052499D8026A646400188BB7A15FD3240A5BC564277AF4640E17B7F83F6FA324088BD50C076B04640D4B837BF61FA3240FDD8243FE2B14640D828EB3713FF32407D96E7C1DDBD464005DCF3FC69FF3240B537F8C264BE46400000000000003340D576137CD3BE4640CC24EA059F023340E2CAD93BA3BF4640D9D0CDFE4005334076543541D4BF4640219221C7D6073340AB5CA8FC6BBF46407B14AE47E10A3340FA298E03AFBE4640AD50A4FB390D3340FD1186014BBE46405F0CE544BB0E3340BCCB457C27BE46407C992842EA123340A7AD11C138BE4640F660527C7C163340CEA96400A8BE4640A9328CBB41183340F7CC920035BF46400B24287E8C193340D47FD6FCF8BF4640DFE2E13D071A33407C2AA73D25C1464070067FBF981933409702D2FE07C24640068195438B18334044317903CCC24640FF9600FC530633405437177FDBC74640D9D0CDFE400533402D05A4FD0FC84640D2C77C40A00333407EC9C6832DC846402AE109BDFE0033407D21E4BCFFC746403D7D04FEF0FF3240051555BFD2C7464084F1D3B837FF3240D4BB783F6EC746405D514A0856F93240F2B1BB4049C546409BABE63922F7324000FDBE7FF3C44640F4E159828CF432403DEFC682C2C446409FE925C632F1324000FDBE7FF3C446404F948444DAEE3240481630815BC54640037CB779E3EC3240A8A78FC01FC646404FE960FD9FE73240A4C519C39CC8464054C554FA09E732402AE109BDFEC846405628D2FD9CE63240823CBB7CEBC94640CE70033E3FE832400C21E7FD7FCE4640E8154F3DD2E832407D5D86FF74CF464058AA0B7899E93240FED2A23EC9CF46405340DAFF00EF3240D200DE0209D04640FE9C82FC6CF03240272F3201BFD046407E1B62BCE6F53240F92CCF83BBD3464049DA8D3EE6F7324095D8B5BDDDD44640286552431BF83240FC1A498270D54640A62897C62FF8324034BC5983F7D54640FB95CE8767F53240562B137EA9E346409D47C5FF1DF53240D7A6B1BD16E4464059A7CAF78CF4324001BEDBBC71E44640800C1D3BA8EC3240AA9B8BBFEDE74640D1CABDC0ACE83240D3F71A82E3E84640AC5626FC52E732402AE109BDFEE846407E9065C1C4E3324029266F8099E946407BA2EBC20FE23240FF05820019EA46404FCDE50643D532405437177FDBEF46406C96CB46E7D43240C4AF58C345F046408C2D043928D1324072361D01DCF44640A4FB3905F9D532407F87A2409FF44640A5F5B704E0DB32407F87A2409FF44640A777F17EDCFE3240823CBB7CEBF94640800F5EBBB4013340FE99417C60FB4640D734EF384503334081423D7D04FC46407F87A2409F143340276BD44334024740AB5FE97C78163340FFCF61BEBC024740D1CABDC0AC183340FBE769C020034740AA622AFD841B33402B14E97E4E0347404DDC2A88811E3340514CDE0033034740A86E2EFEB61F3340D482177D05034740AB5CA8FC6B2133405182FE428F0247407C992842EA223340823CBB7CEB0147402AE44A3D0B263340FDDB65BFEEFE46407F129F3BC1263340D2C43BC093FE46402DD2C43BC02733405376FA415DFE4640FE0E45813E293340FD1186014BFE4640286552431B4833407C60C77F81FE464083F755B9504933402829B000A6FE46407E1B62BCE675334001C11C3D7E0947408109DCBA9B7733407BA2EBC20F0A47407C992842EA823340FD1186014B0E4740D3BEB9BF7A843340FDDB65BFEE0E4740CE5147C7D584334002BB9A3C650F4740D3BEB9BF7A8433405437177FDB0F4740FA264D83A28133407AABAE4335114740D6A9F23D2381334029266F8099114740D13C80457E8133407BA2EBC20F124740276BD44334823340A6B915C26A1247404ED367075C8F3340295FD042021647407BA2EBC20F923340A7AD11C138164740CC5D4BC807A93340556D37C13717474000917EFB3AAC3340FF08C38025174740878A71FE26B4334055A357039416474058AD4CF8A5BE3340A8716F7EC3144740A7E9B303AED7334029E78BBD17134740A8E0F08288D83340FE99417C601347407E8AE3C0ABD933407C6308008E134740D7A6B1BD16DC3340D57954FCDF1347402AE44A3D0BF633407D96E7C1DD154740A7ECF483BA1C3440FC1A498270154740FD1186014B1E3440A6B6D4415E15474082FDD7B969333440FE99417C601347404DD6A887683434407F4B00FE2913474055C2137AFD4134407AA52C431C0F47409A780778D24234407A6CCB80B30E47404DDC2A88814E3440D4EE5701BE094740AC53E57B4652344029EACC3D2408474028F04E3E3D5A3440A9DDAF027C03474080812040865A3440D482177D050347404ED026874F5A34405473B9C1500147407B14AE47E15A3440FC17080264004740AB59677C5F5C3440FF08C38025FF4640FD1186014B5E3440FCE4284014FE4640F92F1004C860344029ED0DBE30FD4640FA264D83A28134407DCC07043AF54640CD5A0A48FB83344082397AFCDEF44640A6F27684D3863440A8716F7EC3F44640562B137EA98B34402CD505BCCCF446405437177FDB8F3440D3BEB9BF7AF44640FE0B040132943440D2C77C40A0F34640D540F339779734402A1DACFF73F24640A7E9B303AEA73440FFCF61BEBCEA4640AD4D637B2DA834405055A18158EA4640AD4D637B2DA83440D38558FD11E8464052465C001AA934402829B000A6E64640D925AAB706AA3440AB9509BFD4E546405531957EC2B534402920ED7F80DF46405628D2FD9CB63440556D37C137DF464057B3CEF8BEB83440D4F19881CADE464028F04E3E3DBA34407E8D2441B8DE46400188BB7A15BD3440A777F17EDCDE4640D4BB783F6EBF3440D009A1832EDF464055C2137AFDC13440D200DE0209E04640D2C77C40A0C33440FE0E45813EE14640D3BEB9BF7AC43440D106600322E246407E1B62BCE6C534405534D6FECEE246402BDB87BCE5C63440D482177D05E34640FC17080264C83440286211C30EE346400473F4F8BDC934407E1EA33CF3E24640F92CCF83BBCB34402A1DACFF73E24640276893C327CD3440A774B0FECFE14640027FF8F9EFCD3440D47C957CECE04640295FD04202CE3440266E15C440DF4640D44334BA83CC344052431B800DD446407F15E0BBCDCB3440FBE769C020D34640D0D38041D2C7344029266F8099D146405531957EC2C53440A8E0F08288D0464022895E46B1C43440A86E2EFEB6CF464027F6D03E56C43440266E15C440CF464084F4143944C43440FCE4284014CE464022895E46B1C43440D1031F8315CD4640FC8F4C874ECB34402AE109BDFEC04640CD57C9C7EECE3440505260014CBD4640FB230C0396FC34405470784144AC4640D44334BA830C35405401F73C7FA84640D3BEB9BF7A44354027327381CB9D46407F129F3BC14635402A1A6B7F679D4640533D997FF4593540D57954FCDF9B4640A7E9B303AE673540562B137EA99B4640A96BED7DAA6A3540A9DDAF027C9B464053E8BCC62E793540DD5D6743FE974640D0420246977B35402920ED7F80974640A9DDAF027C833540FD14C78157934640A77A32FFE88335407C992842EA924640D82B2CB81F843540FDD8243FE2914640D2C77C40A0833540514F1F813F904640D734EF3845833540FED2A23EC98F4640AB5CA8FC6B713540A777F17EDC864640A6EF3504C7613540D2FD9C82FC824640D4BB783F6E5F3540A96BED7DAA824640D2C43BC0935E3540D4B837BF61824640295FD042025E3540253E7782FD814640027FF8F9EF5D354080457EFD108146405340DAFF005F3540D5B2B5BE48804640D5B2B5BE486035407F8461C0927F4640D0D38041D2673540FB230C03967C4640D1CABDC0AC68354056F5F23B4D7C4640295FD042026E354029E78BBD177B4640A5F8F884EC7035407C992842EA7A464024809BC58B75354054FEB5BC727B4640A8E0F08288783540A7B05241457B46400473F4F8BD79354029E78BBD177B46407AA52C431C8735407E18213CDA784640FA980F08748A354029EACC3D2478464051BEA085048C3540FB20CB8289774640276893C3278D3540D4F19881CA764640A9DA6E826F8E3540A8E331039575464028F38FBE498F354056F5F23B4D74464028F38FBE498F3540A7B05241457346405340DAFF008F3540FD4AE7C3B3724640FD1186014B8E35405055A1815872464082035ABA828D3540A9A10DC006724640D2393FC5718C35402CD8463CD9714640AA656B7D918035407B6649809A7046402383DC45987A3540D200DE0209704640AB5FE97C78763540AA9B8BBFED6F4640A6EF3504C77135407EC9C6832D7046404ED026874F6A3540A7B393C151704640AB5FE97C786635407D21E4BCFF6F4640FA9B5088805F3540D009A1832E6F4640D1CDFE40B95D35402829B000A66E464055BFD2F9F05C3540185A9D9CA16A46400A2DEBFEB15C35403677F4BF5C694640CA367007EA64354040683D7C996446404162BB7B80663540787B1002F2634640D175E107E767354085D21742CE634640D82B2CB81F74354053793BC269634640D3C1FA3F877935407C6308008E63464079AEEFC341863540D2C77C40A0634640A4FE7A85058B3540FE99417C60634640F92F1004C8903540D0D03FC1C56246405628D2FD9C963540508BC1C3B4614640D63730B951983540D6A9F23D236146407E8AE3C0AB993540527C7C4276604640A96BED7DAA9A3540A7E9B303AE5F46404BC8073D9B9D35407D96E7C1DD5B464056B60F79CB9D35407C992842EA5A4640D63A71395E9D3540D00F238447594640D63A71395E9D35407B6649809A584640FC1A4982709D354029EACC3D24584640FD1186014B9E3540D576137CD3564640D4BB783F6E9F35402AE44A3D0B5646402CD8463CD9A13540D388997D1E5546407E9065C1C4A33540FB230C039654464079AEEFC341A63540FE0B040132544640D0D38041D2A73540D7A6B1BD165446405534D6FECEBA35407F15E0BBCD5346400188BB7A15BD3540D7A6B1BD16544640ABEAE5779AC83540A7ECF483BA54464057B3CEF8BEE83540FBE769C020534640276893C327FD3540D3C1FA3F87514640A9DA6E826FFE354055F833BC59514640FB928D075B003640F92F1004C85046402AE109BDFE003640527C7C4276504640D540F3397707364081423D7D044C4640E8A38CB8000836401FBDE13E724B4640A8E0F08288083640514F1F813F48464052465C001A0936407E5704FF5B474640FF058200190A36405628D2FD9C464640A968ACFD9D153640FC17080264404640AC5626FC52173640FED2A23EC93F4640FC8F4C874E1B3640508E0244C13E4640A5F8F884EC203640A968ACFD9D3D4640FD9FC37C79253640D4B5F63E553D4640D5AF743E3C2B36407E5182FE423D4640505260014C2D3640FFCC203EB03D46407A17EFC7ED2F3640556D37C1373F4640276BD443344236407C992842EA4A4640A4FB3905F9453640D4B5F63E554D464000917EFB3A4C364027F911BF62514640D1CDFE40B94D3640A96BED7DAA5246405340DAFF004F3640FE0B040132544640D5B2B5BE485036407B9FAA42035546407BA2EBC20F523640530438BD8B554640D2393FC5716C36407C992842EA5A46404DDC2A88816E36402B14E97E4E5B4640A86E2EFEB66F364054FEB5BC725B464029ED0DBE3075364000C79E3D975B4640514F1F813F783640FD14C781575B4640A96BED7DAA7A36407C992842EA5A4640FC1A4982707D3640A9A10DC0065A464084F1D3B8377F3640295C8FC2F55846407BA2EBC20F823640520ABABDA4574640000341800C8536405376FA415D564640A4FE7A85058B364056F5F23B4D544640286211C30E933640D4EE5701BE514640A7E9B303AE973640FC170802645046405534D6FECE9A3640520ABABDA44F4640D7A6B1BD169C3640D4BB783F6E4F464028F38FBE499F3640556D37C1374F46407A1A3048FAA43640D009A1832E4F4640037CB779E3A836407E5704FF5B4F464051BEA08504AC3640556D37C1374F46405531957EC2B53640FE47A643A74D46407F129F3BC1B636402A1A6B7F674D46408109DCBA9BB73640D388997D1E4D4640A38FF98040C33640F27B9BFEEC47464078F01307D0C33640462234828D474640EFE53E390AC43640CEE2C5C210474640B9196EC0E7C3364062855B3E924646404AB8904770C3364040A4DFBE0E464640342E1C08C9C23640944A7842AF454640D6A9F23D23C13640D1031F8315454640D731AEB838BE36407D5A457F68444640D7A6B1BD16BC364052431B800D44464024809BC58BB53640286211C30E434640ACC5A70018B3364063B83A00E24246403B56293DD3AF364038656EBE11434640D63A71395EAD3640A9DDAF027C4346407E1EA33CF3AA3640A77A32FFE84346404FCDE50643A53640527FBDC28245464052B81E85EBA13640A7AD11C138464640D828EB37139F364000C45DBD8A46464051BEA085049C3640FA298E03AF4646407AA52C431C973640FD1186014B464640000341800C9536407E1B62BCE6454640D13FC1C58A763640295FD042023E46405531957EC2753640D1CDFE40B93D4640AE6186C613753640494C50C3B73C4640AE6186C613753640E78D93C2BC3B4640B62BF4C132763640DBC1887D023A46405628D2FD9C76364029266F8099394640A7E9B303AE873640FE0B0401322C46404DD9E90775893640286211C30E2B4640A7ECF483BA8C364055F833BC592946407AABAE4335913640A5BC564277274640A9DDAF027C9336405340DAFF00274640FB20CB82899736407C60C77F81264640643A747ADE9D36401C08C90226264640D82B2CB81FA43640FE47A643A7254640FC17080264A8364029ED0DBE3025464000917EFB3AAC364051888043A8244640FD1186014BAE36407AA86DC3282446407D21E4BCFFAF36407C6308008E234640A5F8F884ECB03640D0D03FC1C522464051C1E10511B13640A774B0FECF2146408A592F8672AE364073309B00C31C4640276893C327AD3640A8716F7EC31C4640266E15C440A7364054FEB5BC721B4640AB5FE97C78A63640FBE769C0201B46404DDC2A88819E36405531957EC2154640FC1A4982709D36407F8461C0920F4640D63A71395E9D36402541B8020A0F464082035ABA828D36407EC9C6832D0846404DD9E9077589364002BB9A3C65074640D0420246976B36407AABAE4335014640CF4BC5C6BC6A3640D3F71A82E3004640295FD042025E36402CD8463CD9E94540286552431B68364082397AFCDEDC4540D925AAB7066A36405534D6FECEDA454083F755B950893640530438BD8BBD454029E78BBD178B3640D3BEB9BF7ABC454055BFD2F9F08C36402BDEC83CF2BB4540F92F1004C8A03640FF08C38025B74540FC8F4C874EAB36407DCC07043AB545407C9C69C2F6B73640FE99417C60B3454027F911BF62B93640514CDE0033B34540286211C30EC3364029266F8099B1454084F4143944C4364027F911BF62B14540514CDE0033D33640286211C30EAB45404FCDE50643D53640FF05820019AA45405531957EC2D53640508BC1C3B4A94540FC17080264D83640D4B5F63E55A545408200193A76D8364082397AFCDEA44540037CB779E3D83640D3BEB9BF7AA44540D3C1FA3F87D93640A8A78FC01FA44540FB20CB8289E73640530438BD8B9D4540D63730B951E836407E5182FE429D4540F92F1004C8F036407E1EA33CF39A4540FF93BF7B47013740D1CABDC0AC98454083FA96395DFE3640D106600322924540A8E3310395FD3640FCE1E7BF07914540D236FE4465F736407B9FAA42038D4540A777F17EDCBE3640D4B837BF61724540027FF8F9EFBD3640D106600322724540F92CCF83BBBB3640FDD8243FE2714540D3C1FA3F87A93640272F3201BF704540A7E9B303AEA73640D00F238447714540FC1A4982709D364080812040867245402383DC45989A3640FD4AE7C3B3724540A4FB3905F9953640AC53E57B467245402577D84466863640527C7C4276704540D4B5F63E55853640D5B2B5BE48704540D2C77C40A0833640FD4D2844C06F4540D0D03FC1C5723640A774B0FECF6945407AABAE4335713640A8AAD0402C6945407E18213CDA703640F92F1004C8684540552E54FEB5703640D5B2B5BE48684540FC1D8A027D723640A7ECF483BA4C4540A6F27684D37636407D93A641D1484540037CB779E3783640A7B393C1514845405531957EC2853640FCDEA63FFB434540FE99417C608B3640253E7782FD414540800C1D3BA88C36405473B9C150414540D828EB37138F364055FB743C663E4540A777F17EDC8E3640D4B5F63E553D45400473F4F8BD8936407E8D2441B836454083F755B950893640D6AC33BE2F364540CF488446B0853640A9DDAF027C3345407A1A3048FA84364029E78BBD17334540A968ACFD9D753640AB5FE97C782E4540D82E6D382C6936407C992842EA2A454082035ABA825D36407D5D86FF742945407E1B62BCE6553640530438BD8B2D454029ED0DBE305536407D96E7C1DD2D4540286211C30E53364079AEEFC3412E45405340DAFF004F36408048BF7D1D2E45407D93A641D1383640F92CCF83BB2B45407C9C69C2F6373640A9DDAF027C2B4540D236FE44653736407F4B00FE292B45407F129F3BC1363640FD4AE7C3B32A4540AB5FE97C78363640D28BDAFD2A2A4540A4FB3905F9353640D4EE5701BE294540A8716F7EC3343640295C8FC2F52845407C992842EA3236405401F73C7F28454052B81E85EB3136402B172AFF5A28454028F38FBE492F36407EC9C6832D284540D4B5F63E55153640AB5FE97C78264540FC1D8A027D123640AB5FE97C782645405437177FDB0F3640FA298E03AF2645402AE44A3D0B063640AA656B7D91284540A4FE7A8505DB3540D4B837BF612A45407E8AE3C0ABD935405055A181582A4540D236FE4465D73540A9A10DC0062A45404DDC2A8881CE3540D576137CD3264540A7ECF483BACC3540FE47A643A7254540FE99417C60CB3540562B137EA9234540D5AF743E3CCB354029E78BBD17234540CE548847E2C93540508BC1C3B4214540D236FE4465C73540D3F71A82E32045407B9FAA4203BD354055FB743C661E4540D1CABDC0ACB8354027327381CB1D4540A4FB3905F9B53540D1CDFE40B91D45404DD6A88768B4354027327381CB1D4540A9DA6E826FAE3540FA298E03AF1E454058AD4CF8A59E3540A8E0F08288204540FE99417C607B3540AC53E57B46224540D540F33977773540A9A10DC0062245405531957EC275354029266F809921454052465C001A593540FCE1E7BF07194540AD4D637B2D583540552E54FEB518454083FA96395D4E3540FE99417C601345402B69C537144E35407C992842EA124540ABEAE5779A3835405307793D981245407AA52C431C373540514CDE003313454027F6D03E5624354055F833BC59194540276BD44334223540D673D2FBC61945407E18213CDA203540823CBB7CEB194540027FF8F9EF1D3540823CBB7CEB1945405534D6FECE1A35407D5D86FF7419454028F04E3E3DEA34407E5704FF5B0F454004763579CACE3440AA622AFD840B45407F15E0BBCDCB34407C992842EA0A45407E1EA33CF3CA34405182FE428F0A4540295C8FC2F5C83440A4C2D84290094540A968ACFD9DC534407C60C77F81064540000341800CC53440FD9FC37C790545405055A18158C23440FF08C38025FF4440D53DB2B96AC23440A968ACFD9DFD44400282397AFCC23440A7ECF483BAFC4440008E3D7B2EC73440A8AAD0402CF94440D236FE4465C73440286552431BF84440266E15C440C734405340DAFF00F7444051BB5F05F8C63440AB5FE97C78F6444050C422861DC63440A968ACFD9DF544404DDC2A8881BE34402638F581E4EF4440562B137EA9BB3440D2C43BC093EE4440533D997FF4B934408048BF7D1DEE4440D13FC1C58AB63440FE47A643A7ED4440037976F9D6B33440A8E3310395ED4440800F5EBBB4A13440530438BD8BED44407F8461C0929F34407E1B62BCE6ED444082035ABA829D344055FB743C66EE4440A4FE7A85059B3440266E15C440EF4440195932C7F29634406AFAEC80EBF0444022895E46B194344052431B800DF44440A8716F7EC3943440A968ACFD9DF544404FCDE506439534402AE44A3D0BF64440FA298E03AF9634407E8D2441B8F64440FC1708026498344028F38FBE49F74440D44334BA839C34407D21E4BCFFF7444052499D80269E3440A8E0F08288F8444084F1D3B8379F3440D106600322FA4440A86E2EFEB69F34402B14E97E4EFB44407F8461C0929F34407E9065C1C4FB4440FC17080264983440A8E3310395054540FA298E03AF86344029E78BBD171B4540D6AC33BE2F86344054FEB5BC721B4540AC53E57B46823440FD9FC37C791D4540EBFD463B6E783440C576F700DD2145404FCDE50643753440FBE769C02023454082FDD7B969733440D2C77C40A0234540286211C30E633440FDDB65BFEE2645403B014D840D5B344017BA1281EA27454052B81E85EB41344027F911BF62294540AA656B7D91403440D3C1FA3F8729454058AD4CF8A53E34407BA2EBC20F2A454083FA96395D3E3440FC1D8A027D2A45402CD505BCCC3C3440D388997D1E2D454052B5DD04DF3C3440FE47A643A72D4540D1CDFE40B93D34405628D2FD9C2E4540027FF8F9EF3D3440556D37C1372F454027F911BF62393440D6AC33BE2F364540A8E0F08288383440A5BC56427737454050C763062A2B3440D3F71A82E34045404DD9E9077529344001C11C3D7E4145408200193A76283440508BC1C3B4414540FC8F4C874E1B3440D3F4D901D7434540295C8FC2F5183440A7ECF483BA444540A52E19C7481234405C7347FFCB474540'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('VT','VA','VAT','336','Holy See (Vatican City)','0.044','783','150','39','12.451','41.904','0106000020E6100000010000000103000000010000000400000060DD3DE1E2E328405841DE5A99F344404041451B3FE7284060C511FC38F44440C043A75CCFE9284050EC8FED61F3444060DD3DE1E2E328405841DE5A99F34440'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('GK','GG','GGY','831','Guernsey','7.8','65228','150','154','-2.576','49.459','0106000020E6100000010000000103000000010000001200000000EB1A2D07BA04C008E5284014B64840009DF3531CC704C008E5284014B64840003F00A94D3C05C08860C77F81B6484080C77C40A05305C0D8F19881CAB64840807F643A745A05C080A52C431CB7484080D349B6BA5C05C0908461C092B74840807F643A745A05C0286552431BB84840005EBC1FB73F05C0301DACFF73BA4840009735B1C03705C008D061BEBCBA48408060DF4E22A204C0E076137CD3BE484000A9C0C9365004C0385C8FC2F5C04840008D9598674504C0D8A9F23D23C1484000DCF3FC690304C030E109BDFEC04840804387C0910004C00000000000C04840000F27309D3604C0908D2441B8B64840004E5E64023E04C0B8DA6E826FB6484080C51858C77104C0D8AC33BE2FB6484000EB1A2D07BA04C008E5284014B64840'); +INSERT INTO "data"."europe_borders" ("fips","iso2","iso3","un","name","area","pop2005","region","subregion","lon","lat",geom) VALUES ('JE','JE','JEY','832','Jersey','11.6','90812','150','154','-2.129','49.219','0106000020E6100000010000000103000000010000001A0000000085EB51B81E00C050793BC2699B484080AF743E3C2B00C0082A8E03AF964840804F8BC1C35400C010E5284014964840800BCD751A8900C010A0C37C79954840800E27309DB600C0D009A1832E9748400058350873FB00C088457EFD10994840004B04AA7F1001C0A05CA8FC6B99484080AF743E3C2B01C0D8C1FA3F87994840009735B1C03701C0A05CA8FC6B99484080E17A14AE4701C0C8F71A82E39848400088450C3B4C01C06001F73C7F984840805D85949F7401C0788461C09297484000B5C4CA68A401C0F808C3802597484000643909A5CF01C0E8B2B5BE489848408014AE47E1FA01C0A89B8BBFED9F484000D026874FFA01C00018080264A0484080DAC69FA8EC01C008E2E7BF07A148408002232F6BE201C0B0AAD0402CA148408094128255D501C088ABAE4335A1484000FA78E8BB3B01C0B85CA8FC6BA14840804F8BC1C35400C0586D37C1379F484000698995D14800C0A8A44E40139F484080D38041D22700C008E52840149E484080D8D0CDFE2000C05831957EC29D48408094490D6D2000C080CC07043A9D48400085EB51B81E00C050793BC2699B4840'); +UPDATE data.europe_borders SET area = st_area(st_transform(geom,2154))/10000000 WHERE area = 0; +COMMIT; diff --git a/CONST_create_template/mapserver/demo.map.tmpl b/CONST_create_template/mapserver/demo.map.tmpl new file mode 100644 index 000000000..410b890a3 --- /dev/null +++ b/CONST_create_template/mapserver/demo.map.tmpl @@ -0,0 +1,262 @@ +# This file is used to render the examples layers, it can be deleted. + +# Layer without any restriction +LAYER + NAME "borders" + TYPE POLYGON + STATUS ON + TOLERANCE 10 + TOLERANCEUNITS pixels + TEMPLATE fooOnlyForWMSGetFeatureInfo # For GetFeatureInfo + EXTENT -31 27 45 71 # Useful for better performance but not mandatory + CONNECTIONTYPE postgis + PROCESSING "CLOSE_CONNECTION=DEFER" # For performance + CONNECTION "host=${PGHOST_SLAVE} port=${PGPORT_SLAVE} sslmode=${PGSSLMODE} user=${PGUSER} password=${PGPASSWORD} dbname=${PGDATABASE}" + DATA "geom FROM (SELECT geo.* FROM data.europe_borders as geo) as foo USING unique gid USING srid=4326" + + PROJECTION + "init=epsg:4326" + END + + METADATA + "wms_title" "Borders of Europe" # For WMS + "wms_srs" "EPSG:2056" # For WMS + + "wfs_enable_request" "*" # Enable WFS for this layer + "gml_include_items" "all" # For GetFeatureInfo and WFS GetFeature (QueryBuilder) + "ows_geom_type" "multipolygon" # For returning geometries in GetFeatureInfo + "ows_geometries" "geom" # For returning geometries in GetFeatureInfo + + "wms_metadataurl_href" "https://www.example.com/bar" # For metadata URL + "wms_metadataurl_format" "text/html" # For metadata URL + "wms_metadataurl_type" "TC211" # For metadata URL + END + + CLASS + NAME "borders" + STYLE + OUTLINECOLOR 0 0 0 + END + END +END + +# Layer with restriction area +LAYER + NAME "density" + TYPE POLYGON + STATUS ON + TOLERANCE 10 + TOLERANCEUNITS pixels + TEMPLATE fooOnlyForWMSGetFeatureInfo # For GetFeatureInfo + EXTENT -31 27 45 71 + CONNECTIONTYPE postgis + PROCESSING "CLOSE_CONNECTION=DEFER" # For performance + CONNECTION "host=${PGHOST_SLAVE} port=${PGPORT_SLAVE} sslmode=${PGSSLMODE} user=${PGUSER} password=${PGPASSWORD} dbname=${PGDATABASE}" + DATA "geom FROM (SELECT geo.*, (pop2005/(area*10)) AS density FROM data.europe_borders AS geo WHERE ARRAY[%role_ids%]::integer[] && ARRAY(${MAPSERVER_DATA_NOAREA_SUBSELECT} 'density')) as foo USING unique gid USING srid=4326" + + PROJECTION + "init=epsg:4326" + END + + VALIDATION + # For secured layers + "default_role_ids" "" + # Or + # "default_role_ids" "" + "role_ids" "^-?[0-9,]*$" + END + + METADATA + "wms_title" "Density of population" # For WMS + "wms_srs" "EPSG:2056" # For WMS + + "wfs_enable_request" "*" # Enable WFS for this layer + "gml_include_items" "all" # For GetFeatureInfo and WFS GetFeature (QueryBuilder) + "ows_geom_type" "multipolygon" # For returning geometries in GetFeatureInfo + "ows_geometries" "geom" # For returning geometries in GetFeatureInfo + + "wms_metadataurl_href" "https://www.example.com/bar" # For metadata URL + "wms_metadataurl_format" "text/html" # For metadata URL + "wms_metadataurl_type" "TC211" # For metadata URL + END + + LABELITEM "name" + + CLASS + NAME "[ 6 - 50 [" + EXPRESSION ([density] < 49.73) + STYLE + OUTLINECOLOR 0 0 0 + COLOR 254 229 217 + END + LABEL + COLOR 0 0 0 + FONT "noto_bold" + TYPE truetype + SIZE 8 + OUTLINEWIDTH 2 + POSITION AUTO + PARTIALS FALSE + OUTLINECOLOR 253 247 244 + MINFEATURESIZE 8 + MINDISTANCE 1000 + BUFFER 10 + END + LEADER + GRIDSTEP 400 # number of pixels between positions that are tested + MAXDISTANCE 300 # distance in pixels that leader text can be drawn + STYLE # normal line styles are supported + COLOR 255 255 255 + WIDTH 3 + END + STYLE # normal line styles are supported + COLOR 0 0 0 + WIDTH 1 + END + END + END + CLASS + NAME "[ 50 - 92 [" + EXPRESSION ([density] >= 49.73 AND [density] < 91.94) + STYLE + OUTLINECOLOR 0 0 0 + COLOR 252 174 145 + END + LABEL + COLOR 0 0 0 + FONT "noto_bold" + TYPE truetype + SIZE 8 + OUTLINEWIDTH 2 + POSITION AUTO + PARTIALS FALSE + OUTLINECOLOR 252 223 213 + MINFEATURESIZE 8 + MINDISTANCE 1000 + BUFFER 10 + END + LEADER + GRIDSTEP 400 # number of pixels between positions that are tested + MAXDISTANCE 300 # distance in pixels that leader text can be drawn + STYLE # normal line styles are supported + COLOR 255 255 255 + WIDTH 3 + END + STYLE # normal line styles are supported + COLOR 0 0 0 + WIDTH 1 + END + END + END + CLASS + NAME "[ 92 - 115 [" + EXPRESSION ([density] >= 91.94 AND [density] < 115.08) + STYLE + OUTLINECOLOR 0 0 0 + COLOR 251 106 74 + END + LABEL + COLOR 0 0 0 + FONT "noto_bold" + TYPE truetype + SIZE 8 + OUTLINEWIDTH 2 + POSITION AUTO + PARTIALS FALSE + OUTLINECOLOR 251 220 213 + MINFEATURESIZE 8 + MINDISTANCE 1000 + BUFFER 10 + END + LEADER + GRIDSTEP 40 # number of pixels between positions that are tested + MAXDISTANCE 300 # distance in pixels that leader text can be drawn + STYLE # normal line styles are supported + COLOR 255 255 255 + WIDTH 3 + END + STYLE # normal line styles are supported + COLOR 0 0 0 + WIDTH 1 + END + END + END + CLASS + NAME "[ 115 - 210 [" + EXPRESSION ([density] >= 115.08 AND [density] < 210.11) + STYLE + OUTLINECOLOR 0 0 0 + COLOR 222 45 38 + END + LABEL + COLOR 0 0 0 + FONT "noto_bold" + TYPE truetype + SIZE 8 + OUTLINEWIDTH 2 + POSITION AUTO + PARTIALS FALSE + OUTLINECOLOR 237 189 187 + MINFEATURESIZE 8 + MINDISTANCE 1000 + BUFFER 10 + END + LEADER + GRIDSTEP 40 # number of pixels between positions that are tested + MAXDISTANCE 300 # distance in pixels that leader text can be drawn + STYLE # normal line styles are supported + COLOR 255 255 255 + WIDTH 3 + END + STYLE # normal line styles are supported + COLOR 0 0 0 + WIDTH 1 + END + END + END + CLASS + NAME "[ 210 - 18 475 ]" + EXPRESSION ([density] >= 210 AND [density] <= 18475) + STYLE + OUTLINECOLOR 0 0 0 + COLOR 165 15 21 + END + LABEL + COLOR 0 0 0 + FONT "noto_bold" + TYPE truetype + SIZE 8 + OUTLINEWIDTH 2 + POSITION AUTO + PARTIALS FALSE + OUTLINECOLOR 208 184 185 + MINFEATURESIZE 8 + MINDISTANCE 1000 + BUFFER 10 + END + LEADER + GRIDSTEP 40 # number of pixels between positions that are tested + MAXDISTANCE 300 # distance in pixels that leader text can be drawn + STYLE # normal line styles are supported + COLOR 255 255 255 + WIDTH 3 + END + STYLE # normal line styles are supported + COLOR 0 0 0 + WIDTH 1 + END + END + END +END + +# Raster layer (with a tile index) +LAYER + NAME 'topo' + GROUP 'plan' + TYPE RASTER + STATUS ON + PROCESSING "RESAMPLE=AVERAGE" + TILEINDEX "raster/topo" + TILEITEM "LOCATION" + MINSCALEDENOM 25000 +END diff --git a/CONST_create_template/mapserver/fonts.conf b/CONST_create_template/mapserver/fonts.conf new file mode 100644 index 000000000..10c429b93 --- /dev/null +++ b/CONST_create_template/mapserver/fonts.conf @@ -0,0 +1,12 @@ +arial fonts/Arial.ttf +arial_bold fonts/Arialbd.ttf + +verdana_bold fonts/Verdanab.ttf +verdana_italic fonts/Verdanai.ttf +verdana fonts/Verdana.ttf +verdana_bold_italic fonts/Verdanaz.ttf + +noto Noto_Sans/NotoSans-Regular.ttf +noto_bold Noto_Sans/NotoSans-Bold.ttf +noto_italic Noto_Sans/NotoSans-Italic.ttf +noto_bold_italic Noto_Sans/NotoSans-BoldItalic.ttf diff --git a/CONST_create_template/mapserver/fonts/Arial.ttf b/CONST_create_template/mapserver/fonts/Arial.ttf new file mode 100644 index 000000000..7ff88f228 Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Arial.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Arialbd.ttf b/CONST_create_template/mapserver/fonts/Arialbd.ttf new file mode 100644 index 000000000..c2eb3ddd5 Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Arialbd.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Arialbi.ttf b/CONST_create_template/mapserver/fonts/Arialbi.ttf new file mode 100644 index 000000000..c816eddbe Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Arialbi.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Ariali.ttf b/CONST_create_template/mapserver/fonts/Ariali.ttf new file mode 100644 index 000000000..563b7d269 Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Ariali.ttf differ diff --git a/CONST_create_template/mapserver/fonts/NotoSans-Bold.ttf b/CONST_create_template/mapserver/fonts/NotoSans-Bold.ttf new file mode 100644 index 000000000..6e00cdce1 Binary files /dev/null and b/CONST_create_template/mapserver/fonts/NotoSans-Bold.ttf differ diff --git a/CONST_create_template/mapserver/fonts/NotoSans-BoldItalic.ttf b/CONST_create_template/mapserver/fonts/NotoSans-BoldItalic.ttf new file mode 100644 index 000000000..51b7b2956 Binary files /dev/null and b/CONST_create_template/mapserver/fonts/NotoSans-BoldItalic.ttf differ diff --git a/CONST_create_template/mapserver/fonts/NotoSans-Italic.ttf b/CONST_create_template/mapserver/fonts/NotoSans-Italic.ttf new file mode 100644 index 000000000..dc93fea6c Binary files /dev/null and b/CONST_create_template/mapserver/fonts/NotoSans-Italic.ttf differ diff --git a/CONST_create_template/mapserver/fonts/NotoSans-Regular.ttf b/CONST_create_template/mapserver/fonts/NotoSans-Regular.ttf new file mode 100644 index 000000000..9dd10199b Binary files /dev/null and b/CONST_create_template/mapserver/fonts/NotoSans-Regular.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Verdana.ttf b/CONST_create_template/mapserver/fonts/Verdana.ttf new file mode 100644 index 000000000..754a9b7b3 Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Verdana.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Verdanab.ttf b/CONST_create_template/mapserver/fonts/Verdanab.ttf new file mode 100644 index 000000000..a668f13ba Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Verdanab.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Verdanai.ttf b/CONST_create_template/mapserver/fonts/Verdanai.ttf new file mode 100644 index 000000000..fedb5134d Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Verdanai.ttf differ diff --git a/CONST_create_template/mapserver/fonts/Verdanaz.ttf b/CONST_create_template/mapserver/fonts/Verdanaz.ttf new file mode 100644 index 000000000..8be20913b Binary files /dev/null and b/CONST_create_template/mapserver/fonts/Verdanaz.ttf differ diff --git a/CONST_create_template/mapserver/mapserver.map.tmpl b/CONST_create_template/mapserver/mapserver.map.tmpl new file mode 100644 index 000000000..acaab8bb0 --- /dev/null +++ b/CONST_create_template/mapserver/mapserver.map.tmpl @@ -0,0 +1,96 @@ +# +# MapServer Mapfile +# +# Test requests: +# +# WMS GetCapabilities: +# /mapserv?service=wms&version=1.1.1&request=getcapabilities +# +# WMS GetMap: +# /mapserv?service=wms&version=1.1.1&request=getmap&bbox=-180,-90,180,90&layers=countries&width=600&height=400&srs=EPSG:4326&format=image/png +# +# WMS GetFeatureInfo: +# /mapserv?service=wms&version=1.1.1&request=getfeatureinfo&bbox=-180,-90,180,90&layers=countries&query_layers=countries&width=600&height=400&srs=EPSG:4326&format=image/png&x=180&y=90&info_format=application/vnd.ogc.gml +# + +MAP + NAME "geoportailv3" + + # For Windows users: uncomment this line and adapt it to your + # own mapserver's nad folder (use regular slash "/") + # CONFIG "PROJ_LIB" "C:/path/to/ms4w/proj/nad" + + EXTENT 2489246.40 1078873.38 2837119.80 1296543.09 ## should be defined for better performance + UNITS METERS + + # RESOLUTION and DEFRESOLUTION default to 96. If you + # change RESOLUTION to some other value, also change + # DEFRESOLUTION. See + # https://mapserver.org/development/rfc/ms-rfc-55.html + RESOLUTION 96 ## Also set in Openlayers especially for legends + DEFRESOLUTION 96 + + # MAXSIZE should not be less than 5000 for MF print on A3 + MAXSIZE 5000 + + IMAGECOLOR 255 255 255 + STATUS ON + + FONTSET "fonts.conf" + #SYMBOLSET "symbole.sym" + + CONFIG "CPL_VSIL_CURL_USE_CACHE" "TRUE" + CONFIG "CPL_VSIL_CURL_CACHE_SIZE" "128000000" + CONFIG "CPL_VSIL_CURL_USE_HEAD" "FALSE" + CONFIG "GDAL_DISABLE_READDIR_ON_OPEN" "TRUE" + + OUTPUTFORMAT + NAME jpeg + DRIVER "AGG/JPEG" + MIMETYPE "image/jpeg" + IMAGEMODE RGB + EXTENSION "jpeg" + FORMATOPTION "QUALITY=75,PROGRESSIVE=TRUE" + END + + OUTPUTFORMAT + NAME png + DRIVER AGG/PNG + MIMETYPE "image/png" + IMAGEMODE RGBA + EXTENSION "png" + FORMATOPTION "INTERLACE=OFF" + FORMATOPTION "QUANTIZE_DITHER=OFF" + FORMATOPTION "QUANTIZE_FORCE=ON" + FORMATOPTION "QUANTIZE_COLORS=256" + END + + PROJECTION + "init=epsg:2056" + END + + WEB + METADATA + "wms_title" "changeme" + "wms_abstract" "changeme" + "ows_onlineresource" "${VISIBLE_WEB_PROTOCOL}://${VISIBLE_WEB_HOST}${VISIBLE_ENTRY_POINT}mapserv_proxy?ogcserver=source%20for%20image%2Fpng" + "wms_srs" "EPSG:2056" + "wms_encoding" "UTF-8" + "wms_enable_request" "*" + "wfs_enable_request" "!*" + "wfs_encoding" "UTF-8" + END + END + + LEGEND + LABEL + ENCODING "UTF-8" + TYPE TRUETYPE + FONT "Arial" + SIZE 9 + END + END + + INCLUDE "demo.map" + +END diff --git a/CONST_create_template/mapserver/tinyows.xml b/CONST_create_template/mapserver/tinyows.xml new file mode 100644 index 000000000..ec4df14ae --- /dev/null +++ b/CONST_create_template/mapserver/tinyows.xml @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/CONST_create_template/mapserver/tinyows.xml.tmpl b/CONST_create_template/mapserver/tinyows.xml.tmpl new file mode 100644 index 000000000..247854933 --- /dev/null +++ b/CONST_create_template/mapserver/tinyows.xml.tmpl @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/A3_Landscape.jrxml b/CONST_create_template/print/print-apps/geoportailv3/A3_Landscape.jrxml new file mode 100644 index 000000000..5802be3ba --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/A3_Landscape.jrxml @@ -0,0 +1,194 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/A3_Portrait.jrxml b/CONST_create_template/print/print-apps/geoportailv3/A3_Portrait.jrxml new file mode 100644 index 000000000..7856f09d0 --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/A3_Portrait.jrxml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/A4_Landscape.jrxml b/CONST_create_template/print/print-apps/geoportailv3/A4_Landscape.jrxml new file mode 100644 index 000000000..67debd9b8 --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/A4_Landscape.jrxml @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/A4_Portrait.jrxml b/CONST_create_template/print/print-apps/geoportailv3/A4_Portrait.jrxml new file mode 100644 index 000000000..09d049a5c --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/A4_Portrait.jrxml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/config.yaml b/CONST_create_template/print/print-apps/geoportailv3/config.yaml new file mode 100644 index 000000000..8cc47261d --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/config.yaml @@ -0,0 +1,166 @@ +--- + +throwErrorOnExtraParameters: true +defaultToSvg: true + +allowedReferers: + - !hostnameMatch + host: + - !localMatch {} + +templates: + 1 A4 portrait: !template + reportTemplate: A4_Portrait.jrxml + attributes: + title: + !string &title + default: "" + comments: + !string &comments + default: "" + debug: + !boolean &debug + default: false + legend: !legend &legend {} + map: + !map &map + maxDpi: 254 + dpiSuggestions: [254] + zoomLevels: + !zoomLevels + scales: [100, 250, 500, 2500, 5000, 10000, 25000, 50000, 100000, 500000] + width: 555 + height: 675 + northArrow: + !northArrow &northArrow + size: 40 + default: + graphic: "file:///north.svg" + scalebar: + !scalebar &scalebar + width: 150 + height: 20 + default: + fontSize: 8 + datasource: + !datasource &datasource + attributes: + title: !string {} + table: !table {} + + processors: &processors + - !reportBuilder # compile all reports in current directory + directory: '.' + - !configureHttpRequests &configureHttpRequests + httpProcessors: + ## For internal print + ## - !mapUri + ## mapping: + ## https?://tiles(.*): "tiles$1" + ## - !mapUri + ## mapping: + ## https?://(.*): "$1" + ## - !forwardHeaders + ## matchers: + ## - !hostnameMatch + ## host: + ## port: + - !forwardHeaders + matchers: + - !hostnameMatch + host: + port: + headers: + - Cookie + ## - Host + - !forwardHeaders + headers: + - Referer + - X-Request-ID + - Forwarded + - !restrictUris + matchers: + - !localMatch + reject: true + ## For internal print + ## - !hostnameMatch + ## host: + ## port: + ## - !hostnameMatch + ## host: + ## port: + - !ipMatch + ip: 10.0.0.0 + mask: 255.0.0.0 + reject: true + - !ipMatch + ip: 172.16.0.0 + mask: 255.240.0.0 + reject: true + - !ipMatch + ip: 192.168.0.0 + mask: 255.255.0.0 + reject: true + - !acceptAll {} + - !prepareLegend + maxWidth: 185 + template: legend.jrxml + - !createMap {} + - !createNorthArrow {} + - !createScalebar {} + - !createDataSource + processors: + - !prepareTable + dynamic: true + columns: + icon: !urlImage + urlExtractor: (.*) + urlGroup: 1 + + 2 A4 landscape: !template + reportTemplate: A4_Landscape.jrxml + attributes: + title: *title + comments: *comments + debug: *debug + legend: *legend + map: !map + <<: *map + width: 800 + height: 441 + northArrow: *northArrow + scalebar: *scalebar + datasource: *datasource + processors: *processors + + 3 A3 portrait: !template + reportTemplate: A3_Portrait.jrxml + attributes: + title: *title + comments: *comments + debug: *debug + legend: *legend + map: !map + <<: *map + width: 800 + height: 1000 + northArrow: *northArrow + scalebar: *scalebar + datasource: *datasource + processors: *processors + + 4 A3 landscape: !template + reportTemplate: A3_Landscape.jrxml + attributes: + title: *title + comments: *comments + debug: *debug + legend: *legend + map: !map + <<: *map + width: 1150 + height: 673 + northArrow: *northArrow + scalebar: *scalebar + datasource: *datasource + processors: *processors diff --git a/CONST_create_template/print/print-apps/geoportailv3/config.yaml.tmpl b/CONST_create_template/print/print-apps/geoportailv3/config.yaml.tmpl new file mode 100644 index 000000000..88a85b44a --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/config.yaml.tmpl @@ -0,0 +1,166 @@ +--- + +throwErrorOnExtraParameters: true +defaultToSvg: true + +allowedReferers: + - !hostnameMatch + host: ${VISIBLE_WEB_HOST} + - !localMatch {} + +templates: + 1 A4 portrait: !template + reportTemplate: A4_Portrait.jrxml + attributes: + title: + !string &title + default: "" + comments: + !string &comments + default: "" + debug: + !boolean &debug + default: false + legend: !legend &legend {} + map: + !map &map + maxDpi: 254 + dpiSuggestions: [254] + zoomLevels: + !zoomLevels + scales: [100, 250, 500, 2500, 5000, 10000, 25000, 50000, 100000, 500000] + width: 555 + height: 675 + northArrow: + !northArrow &northArrow + size: 40 + default: + graphic: "file:///north.svg" + scalebar: + !scalebar &scalebar + width: 150 + height: 20 + default: + fontSize: 8 + datasource: + !datasource &datasource + attributes: + title: !string {} + table: !table {} + + processors: &processors + - !reportBuilder # compile all reports in current directory + directory: '.' + - !configureHttpRequests &configureHttpRequests + httpProcessors: + ## For internal print + ## - !mapUri + ## mapping: + ## https?://${VISIBLE_WEB_HOST_RE_ESCAPED}${VISIBLE_ENTRY_POINT_RE_ESCAPED}tiles(.*): "${TILECLOUDCHAIN_INTERNAL_URL}${VISIBLE_ENTRY_POINT}tiles$1" + ## - !mapUri + ## mapping: + ## https?://${VISIBLE_WEB_HOST_RE_ESCAPED}${VISIBLE_ENTRY_POINT_RE_ESCAPED}(.*): "${GEOPORTAL_INTERNAL_URL}${VISIBLE_ENTRY_POINT}$1" + ## - !forwardHeaders + ## matchers: + ## - !hostnameMatch + ## host: ${GEOPORTAL_INTERNAL_HOST} + ## port: ${GEOPORTAL_INTERNAL_PORT} + - !forwardHeaders + matchers: + - !hostnameMatch + host: ${VISIBLE_WEB_HOST} + port: ${VISIBLE_WEB_PORT} + headers: + - Cookie + ## - Host + - !forwardHeaders + headers: + - Referer + - X-Request-ID + - Forwarded + - !restrictUris + matchers: + - !localMatch + reject: true + ## For internal print + ## - !hostnameMatch + ## host: ${GEOPORTAL_INTERNAL_HOST} + ## port: ${GEOPORTAL_INTERNAL_PORT} + ## - !hostnameMatch + ## host: ${TILECLOUDCHAIN_INTERNAL_HOST} + ## port: ${TILECLOUDCHAIN_INTERNAL_PORT} + - !ipMatch + ip: 10.0.0.0 + mask: 255.0.0.0 + reject: true + - !ipMatch + ip: 172.16.0.0 + mask: 255.240.0.0 + reject: true + - !ipMatch + ip: 192.168.0.0 + mask: 255.255.0.0 + reject: true + - !acceptAll {} + - !prepareLegend + maxWidth: 185 + template: legend.jrxml + - !createMap {} + - !createNorthArrow {} + - !createScalebar {} + - !createDataSource + processors: + - !prepareTable + dynamic: true + columns: + icon: !urlImage + urlExtractor: (.*) + urlGroup: 1 + + 2 A4 landscape: !template + reportTemplate: A4_Landscape.jrxml + attributes: + title: *title + comments: *comments + debug: *debug + legend: *legend + map: !map + <<: *map + width: 800 + height: 441 + northArrow: *northArrow + scalebar: *scalebar + datasource: *datasource + processors: *processors + + 3 A3 portrait: !template + reportTemplate: A3_Portrait.jrxml + attributes: + title: *title + comments: *comments + debug: *debug + legend: *legend + map: !map + <<: *map + width: 800 + height: 1000 + northArrow: *northArrow + scalebar: *scalebar + datasource: *datasource + processors: *processors + + 4 A3 landscape: !template + reportTemplate: A3_Landscape.jrxml + attributes: + title: *title + comments: *comments + debug: *debug + legend: *legend + map: !map + <<: *map + width: 1150 + height: 673 + northArrow: *northArrow + scalebar: *scalebar + datasource: *datasource + processors: *processors diff --git a/CONST_create_template/print/print-apps/geoportailv3/legend.jrxml b/CONST_create_template/print/print-apps/geoportailv3/legend.jrxml new file mode 100644 index 000000000..6f88331b5 --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/legend.jrxml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/logo.png b/CONST_create_template/print/print-apps/geoportailv3/logo.png new file mode 100644 index 000000000..f7d414663 Binary files /dev/null and b/CONST_create_template/print/print-apps/geoportailv3/logo.png differ diff --git a/CONST_create_template/print/print-apps/geoportailv3/north.svg b/CONST_create_template/print/print-apps/geoportailv3/north.svg new file mode 100644 index 000000000..091feeab4 --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/north.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + N + + + + diff --git a/CONST_create_template/print/print-apps/geoportailv3/results.jrxml b/CONST_create_template/print/print-apps/geoportailv3/results.jrxml new file mode 100644 index 000000000..1d25b9c09 --- /dev/null +++ b/CONST_create_template/print/print-apps/geoportailv3/results.jrxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CONST_create_template/project.yaml b/CONST_create_template/project.yaml new file mode 100644 index 000000000..13300c432 --- /dev/null +++ b/CONST_create_template/project.yaml @@ -0,0 +1,18 @@ +--- +project_folder: geoportailv3 +project_package: geoportailv3 +application_url: https://localhost:8484/ +checker_url: https://172.17.0.1:8484/c2c/health_check?max_level=9 +managed_files: [] +unmanaged_files: [] +template_vars: + package: geoportailv3 + srid: 2056 + extent: 2489246.40,1078873.38,2837119.80,1296543.09 + authtkt_secret: aed4ma7pah7Riph9paMoow3raeB5ooSa2ayee4fooQuohT7Etinohshah7eib4Re +env: + files: + - env.default + - env.project + required_args: 0 + help: No arguments needed. diff --git a/CONST_create_template/pyproject.toml b/CONST_create_template/pyproject.toml new file mode 100644 index 000000000..c2691b0ab --- /dev/null +++ b/CONST_create_template/pyproject.toml @@ -0,0 +1,3 @@ +[tool.black] +line-length = 110 +target-version = ['py38'] diff --git a/CONST_create_template/qgisserver/geomapfish.yaml.tmpl b/CONST_create_template/qgisserver/geomapfish.yaml.tmpl new file mode 100644 index 000000000..ab37c16e6 --- /dev/null +++ b/CONST_create_template/qgisserver/geomapfish.yaml.tmpl @@ -0,0 +1,29 @@ +--- +vars: + schema: '${PGSCHEMA}' + schema_static: '{PGSCHEMA_STATIC}' + sqlalchemy.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE}?sslmode={PGSSLMODE} + sqlalchemy_slave.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST_SLAVE}:{PGPORT_SLAVE}/{PGDATABASE}?sslmode={PGSSLMODE} + srid: 2056 + sqlalchemy: + pool_recycle: 30 + pool_size: 5 + max_overflow: 25 + use_batch_mode: true +environment: + - PGUSER + - PGPASSWORD + - PGHOST + - PGHOST_SLAVE + - name: PGPORT + default: 5432 + - name: PGPORT_SLAVE + default: 5432 + - name: PGSSLMODE + default: prefer + - PGDATABASE + - name: PGSCHEMA_STATIC + default: main_static +interpreted: {} +no_interpreted: [] +postprocess: [] diff --git a/CONST_create_template/qgisserver/pg_service.conf.tmpl b/CONST_create_template/qgisserver/pg_service.conf.tmpl new file mode 100644 index 000000000..5b556b91b --- /dev/null +++ b/CONST_create_template/qgisserver/pg_service.conf.tmpl @@ -0,0 +1,15 @@ +[geoportailv3] +host=${PGHOST_SLAVE} +port=${PGPORT_SLAVE} +#sslmode=${PGSSLMODE} +user=${PGUSER} +password=${PGPASSWORD} +dbname=${PGDATABASE} + +[geoportailv3_master] +host=${PGHOST} +port=${PGPORT} +#sslmode=${PGSSLMODE} +user=${PGUSER} +password=${PGPASSWORD} +dbname=${PGDATABASE} diff --git a/CONST_create_template/run_alembic.sh b/CONST_create_template/run_alembic.sh new file mode 100644 index 000000000..fcc36f12d --- /dev/null +++ b/CONST_create_template/run_alembic.sh @@ -0,0 +1,13 @@ +#!/bin/bash -eu +# Upgrade the DB. +# +# Mostly useful in a Docker environment. + +for ini in *alembic*.ini +do + if [[ -f $ini ]] + then + echo "$ini ===========================" + alembic -c $ini upgrade head + fi +done diff --git a/CONST_create_template/scripts/publish-docker b/CONST_create_template/scripts/publish-docker new file mode 100755 index 000000000..cbfd262e9 --- /dev/null +++ b/CONST_create_template/scripts/publish-docker @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +import argparse +import os.path +import subprocess +import sys + + +def main(): + parser = argparse.ArgumentParser(description="Publish Docker images") + parser.add_argument("--image", dest="images", action="append", help="The image to be exported") + parser.add_argument( + "--service", default="dockerhub", help="Used repository", + ) + parser.add_argument( + "--no-trigger", + dest="trigger", + action="store_false", + help="Disable triggerring OpenShift for an image update", + ) + args = parser.parse_args() + + ref = os.environ["GITHUB_REF"].split("/") + + if ref[1] != "heads": + print("Not a branch") + sys.exit(0) + + version = "/".join(ref[2:]) + + if version not in os.environ.get("HELM_RELEASE_NAMES", "").split(","): + print("Not a release branch") + sys.exit(0) + + env = {} + with open(".env") as open_file: + for line in open_file: + if line and line[0] != "#": + try: + index = line.index("=") + env[line[:index].strip()] = line[index + 1 :].strip() + except ValueError: + # Ignore lines that don't have a '=' + pass + + print("Deploying images for tag {}".format(version)) + sys.stdout.flush() + + cmd = ["docker", "login"] + if args.service == "dockerhub": + login = subprocess.check_output(["gopass", "gs/ci/dockerhub/username"]).decode() + password = subprocess.check_output(["gopass", "gs/ci/dockerhub/password"]) + prefix = "" + elif args.service == "github": + cmd += ["ghcr.io"] + login = subprocess.check_output(["gopass", "gs/ci/github/username"]).decode() + password = subprocess.check_output(["gopass", "gs/ci/github/token/gopass"]) + prefix = "ghcr.io/" + else: + print("Unknown service '{}'".format(args.service)) + sys.exit(1) + + cmd += ["--username=" + login, "--password-stdin"] + process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + output, output_err = process.communicate(input=password) + if process.returncode != 0: + if output: + print(output.decode()) + if output_err: + print(output_err.decode()) + sys.exit(1) + + for image in args.images: + full_image = "{}-{}".format(env.get("DOCKER_BASE", "camptocamp/geomapfish"), image) + src_image = "{}:{}".format(full_image, env.get("DOCKER_TAG", "latest")) + dest_image = "{}{}:{}".format(prefix, full_image, version) + subprocess.check_call(["docker", "tag", src_image, dest_image]) + subprocess.check_call(["docker", "push", dest_image]) + + if args.trigger: + openshift_version = "3.11.0" + openshift_hash = "0cbc58b" + openshift_version_name = "openshift-origin-client-tools-v{}-{}-linux-64bit".format( + openshift_version, openshift_hash + ) + openshift_file = openshift_version_name + ".tar.gz" + openshift_url = "https://github.com/openshift/origin/releases/download/v{}/{}".format( + openshift_version, openshift_file + ) + subprocess.check_call(["wget", "--quiet", openshift_url], cwd="/tmp") + subprocess.check_call(["tar", "xfz", openshift_file], cwd="/tmp") + oc = "/tmp/{}/oc".format(openshift_version_name) # pylint: disable=invalid-name + + subprocess.check_call( + [ + oc, + "login", + subprocess.check_output( + ["gopass", "gs/ci/openshift/{}/url".format(os.environ["OPENSHIFT_PROJECT"])] + ).decode(), + "--token=" + + subprocess.check_output( + ["gopass", "gs/ci/openshift/{}/token".format(os.environ["OPENSHIFT_PROJECT"])] + ).decode(), + ] + ) + for image in args.images: + openshift_image_ref = "{version}-c2cgeoportal-{image}:{version}".format( + version=version, image=image + ) + subprocess.check_call( + [ + oc, + "import-image", + openshift_image_ref, + "--scheduled=true", + "--reference-policy=local", + "--namespace=" + os.environ["OPENSHIFT_PROJECT"], + ] + ) + + +if __name__ == "__main__": + main() diff --git a/CONST_create_template/setup.cfg b/CONST_create_template/setup.cfg new file mode 100644 index 000000000..5eb7a1865 --- /dev/null +++ b/CONST_create_template/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +ignore = E121,E123,E126,E226,E24,E704 +max-line-length = 110 diff --git a/CONST_create_template/spell-ignore-words.txt b/CONST_create_template/spell-ignore-words.txt new file mode 100644 index 000000000..2fbe53211 --- /dev/null +++ b/CONST_create_template/spell-ignore-words.txt @@ -0,0 +1 @@ +oder diff --git a/CONST_create_template/tilegeneration/config.yaml.tmpl b/CONST_create_template/tilegeneration/config.yaml.tmpl new file mode 100644 index 000000000..9209f0053 --- /dev/null +++ b/CONST_create_template/tilegeneration/config.yaml.tmpl @@ -0,0 +1,169 @@ +grids: + # grid name, I just recommends to add the min resolution because it's common to not generate all the layers at the same resolution. + swissgrid_05: + # resolutions [required] + # Resolutions from eCH-0056 - WMTS-07 + # https://www.ech.ch/dokument/473ea824-bbcd-43fa-ad0a-c7c84edfa1b8 + resolutions: [4000, 2000, 1000, 500, 250, 100, 50, 20, 10, 5, 2.5, 1, 0.5, 0.25, 0.1, 0.05] + # bbox [required] + bbox: [2420000, 1030000, 2900000, 1350000] + # srs [required] + srs: EPSG:2056 + +caches: + local: + type: filesystem + folder: /var/sig/tiles + # for GetCapabilities + http_url: ${VISIBLE_WEB_PROTOCOL}://${VISIBLE_WEB_HOST}${VISIBLE_ENTRY_POINT} + s3: + type: s3 + bucket: ${TILEGENERATION_S3_BUCKET} + folder: '' + # for GetCapabilities + http_url: ${VISIBLE_WEB_PROTOCOL}://${VISIBLE_WEB_HOST}${VISIBLE_ENTRY_POINT} + cache_control: 'public, max-age=14400' + host: ${AWS_S3_ENDPOINT} + +# this defines some defaults values for all the layers +defaults: + layer: &layer + type: wms + grid: swissgrid_05 + # The minimum resolution to seed, useful to use with mapcache, optional. + # min_resolution_seed: 1 + # the URL of the WMS server to used + url: ${MAPSERVER_URL} + # Set the headers to get the right virtual host, and don't get any cached result + headers: + Host: '${VISIBLE_WEB_HOST}' + Cache-Control: no-cache, no-store + Pragma: no-cache + # file name extension + extension: png + # the bbox there we want to generate tiles + #bbox: [493000, 114000, 586000, 204000] + + # mime type used for the WMS request and the WMTS capabilities generation + mime_type: image/png + wmts_style: default + # the WMTS dimensions definition [default to []] + #dimensions: + # - name: DATE + # # the default value for the WMTS capabilities + # default: '2012' + # # the generated values + # generate: ['2012'] + # # all the available values in the WMTS capabilities + # values: ['2012'] + # the meta tiles definition [default to off] + meta: on + # the meta tiles size [default to 8] + meta_size: 5 + # the meta tiles buffer [default to 128] + meta_buffer: 128 + # connexion an sql to get geometries (in column named geom) where we want to generate tiles + # Warn: too complex result can slow down the application +# connection: host=localhost port=5432 user=www-data password=www-data dbname= +# geoms: +# - sql: AS geom FROM + # size and hash used to detect empty tiles and metatiles [optional, default to None] + empty_metatile_detection: + size: 740 + hash: 3237839c217b51b8a9644d596982f342f8041546 + empty_tile_detection: + size: 921 + hash: 1e3da153be87a493c4c71198366485f290cad43c + +layers: + plan: + <<: *layer + layers: plan + ortho: + <<: *layer + layers: ortho + extension: jpeg + mime_type: image/jpeg + # no buffer needed on rater sources + meta_buffer: 0 + empty_metatile_detection: + size: 66163 + hash: a9d16a1794586ef92129a2fb41a739451ed09914 + empty_tile_detection: + size: 1651 + hash: 2892fea0a474228f5d66a534b0b5231d923696da + +generation: + default_cache: s3 + +redis: + url: 'redis://${REDIS_HOST}:${REDIS_PORT}/${REDIS_DB}' + +# Not used if the previous redis section is not commented out +sqs: + # The region where the SQS queue is + region: eu-west-1 + # The SQS queue name, it should already exists + queue: '${TILEGENERATION_SQS_QUEUE}' + +server: + wmts_path: tiles + static_path: tiles/static + admin_path: tiles/admin + expires: 8 # 8 hours + mapcache_internal: True + predefined_commands: + - name: Generation all layers + command: generate_tiles --role=master + - name: Generation layer plan + command: generate_tiles --role=master --layer=plan + - name: Generation layer ortho + command: generate_tiles --role=master --layer=ortho + +process: + optipng_test: + - cmd: optipng -o7 -simulate %(in)s + optipng: + - cmd: optipng %(args)s -zc9 -zm8 -zs3 -f5 %(in)s + arg: + default: '-q' + quiet: '-q' + jpegoptim: + - cmd: jpegoptim %(args)s --strip-all --all-normal -m 90 %(in)s + arg: + default: '-q' + quiet: '-q' + +openlayers: + # srs, center_x, center_y [required] + srs: EPSG:2056 + center_x: 2600000 + center_y: 1200000 + +metadata: + title: Some title + abstract: Some abstract + servicetype: OGC WMTS + keywords: + - some + - keywords + fees: None + access_constraints: None + +provider: + name: The provider name + url: The provider URL + contact: + name: The contact name + position: The position name + info: + phone: + voice: +41 11 222 33 44 + fax: +41 11 222 33 44 + address: + delivery: Address delivery + city: Berne + area: BE + postal_code: 3000 + country: Switzerland + email: info@example.com diff --git a/CONST_create_template/yamllint.yaml b/CONST_create_template/yamllint.yaml new file mode 100644 index 000000000..1725f94ba --- /dev/null +++ b/CONST_create_template/yamllint.yaml @@ -0,0 +1,11 @@ +--- +extends: default + +rules: + line-length: + max: 110 + indentation: + spaces: 2 + truthy: disable + comments: + min-spaces-from-content: 1 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..57e604033 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,87 @@ +FROM camptocamp/geomapfish-tools:2.5.0.139 as builder + +ENV LANGUAGES="en fr de lb" +ENV VARS_FILE=vars.yaml +ENV CONFIG_VARS sqlalchemy.url sqlalchemy.pool_recycle sqlalchemy.pool_size sqlalchemy.max_overflow \ + sqlalchemy.use_batch_mode sqlalchemy_slave.url sqlalchemy_slave.pool_recycle sqlalchemy_slave.pool_size \ + sqlalchemy_slave.max_overflow sqlalchemy_slave.use_batch_mode schema schema_static enable_admin_interface \ + default_locale_name servers layers available_locale_names cache admin_interface getitfixed functionalities \ + raster shortener hide_capabilities tinyowsproxy resourceproxy print_url print_get_redirect \ + checker check_collector default_max_age package srid \ + reset_password fulltextsearch global_headers headers authorized_referers hooks stats db_chooser \ + dbsessions urllogin host_forward_host smtp c2c.base_path welcome_email \ + lingua_extractor interfaces_config interfaces devserver_url api authentication intranet metrics pdfreport + +# Custom config vars +ENV CONFIG_VARS ${CONFIG_VARS} \ + authorized_ips \ + default_mymaps_role \ + elastic \ + exclude_theme_layer_search \ + excluded_themes_from_search \ + https_proxy \ + ldap \ + lidar \ + mailer \ + modify_notification \ + referrer \ + reverse_geocode \ + routing \ + sync_ms_path \ + anf age age_crues casipo pag pds + +COPY . /tmp/config/ +RUN mkdir -p /tmp/config/geoportal/geoportailv3_geoportal/static + +RUN \ + for lang in ${LANGUAGES}; \ + do \ + node /usr/bin/compile-catalog \ + /opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal/locale/${lang}/LC_MESSAGES/ngeo.po \ + /opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal/locale/${lang}/LC_MESSAGES/gmf.po \ + /tmp/config/geoportal/geoportailv3_geoportal/locale/${lang}/LC_MESSAGES/geoportailv3_geoportal-client.po \ + /tmp/config/geoportal/geoportailv3_geoportal/locale/${lang}/LC_MESSAGES/geoportailv3_geoportal-tooltips.po \ + /tmp/config/geoportal/geoportailv3_geoportal/locale/${lang}/LC_MESSAGES/geoportailv3_geoportal-legends.po \ + > /tmp/config/geoportal/geoportailv3_geoportal/static/${lang}.json; \ + done && \ + rm -rf /tmp/config/geoportal/geoportailv3_geoportal/locale + +RUN \ + cd /tmp/config/geoportal/ && \ + c2c-template --vars ${VARS_FILE} \ + --get-config geoportailv3_geoportal/config.yaml \ + ${CONFIG_VARS} && \ + pykwalify --data-file geoportailv3_geoportal/config.yaml \ + --schema-file CONST_config-schema.yaml && \ + rm CONST_* vars.yaml + +############################################################################### + +FROM camptocamp/geomapfish-config:2.5.0.139 + +ARG PGSCHEMA +ENV PGSCHEMA=$PGSCHEMA + +COPY --from=builder /tmp/config/ /tmp/config/ + +RUN \ + if [ -e /tmp/config/mapserver ]; then mv /tmp/config/mapserver /etc/; fi && \ + if [ -e /tmp/config/tilegeneration ]; then mv /tmp/config/tilegeneration /etc/; fi && \ + if [ -e /tmp/config/qgisserver ]; then mv /tmp/config/qgisserver /etc/qgisserver; fi && \ + mkdir --parent /usr/local/tomcat/webapps/ROOT/ && \ + if [ -e /tmp/config/print ]; then mv /tmp/config/print/print-apps /usr/local/tomcat/webapps/ROOT/; fi && \ + mv /tmp/config/geoportal/geoportailv3_geoportal/ /etc/geomapfish/ && \ + chmod g+w -R /etc /usr/local/tomcat/webapps && \ + adduser www-data root && \ + sed 's#bind :80#bind *:443 ssl crt /etc/haproxy_dev/localhost.pem#g' /etc/haproxy/haproxy.cfg.tmpl \ + > /etc/haproxy_dev/haproxy.cfg.tmpl && \ + echo ' http-request set-header X-Forwarded-Proto https' >> /etc/haproxy_dev/haproxy.cfg.tmpl + +VOLUME /etc/geomapfish \ + /etc/mapserver \ + /etc/qgisserver \ + /etc/tilegeneration \ + /usr/local/tomcat/webapps/ROOT/print-apps \ + /etc/gunicorn \ + /etc/haproxy_dev \ + /etc/haproxy diff --git a/Makefile b/Makefile index 0e20a3187..04911732a 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,6 @@ DOCKER_TAG ?= latest GIT_HASH ?= $(shell git rev-parse HEAD) PACKAGE ?= geoportailv3 - UTILITY_HELP = -e "- update-translations Synchronize the translations with Transifex (host)" \ "\n- pull-translations Pull the translation (host)" \ "\n- recreate-search-poi Recreate the ElasticSearch POI Index (docker)" \ @@ -36,10 +35,8 @@ help: .PHONY: build -build: docker-build-geoportal docker-build-config docker-build-print docker-build-ldap - -.PHONY: build-prod -build-prod: docker-build-geoportal docker-build-config +build: docker-build-ldap + ./build .PHONY: docker-build-geoportal docker-build-geoportal: @@ -57,16 +54,15 @@ docker-build-print: docker-build-ldap: cd ldap && docker build --tag=lux-dev-ldap --build-arg=HTTP_PROXY_URL=$(http_proxy) --build-arg=HTTPS_PROXY_URL=$(https_proxy) . -DOCKER_COMPOSE_PROJECT ?= luxembourg +DOCKER_COMPOSE_PROJECT ?= geoportailv3 DOCKER_CONTAINER ?= $(DOCKER_COMPOSE_PROJECT)_geoportal_1 -APP_JS_FILES = $(shell find geoportal/$(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.js' 2> /dev/null) -APP_HTML_FILES += $(shell find geoportal/$(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.html' 2> /dev/null) -APP_HTML_FILES += geoportal/$(PACKAGE)_geoportal/static-ngeo/js/apps/main.html.ejs +APP_JS_FILES = $(shell find $(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.js' 2> /dev/null) +APP_HTML_FILES += $(shell find $(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.html' 2> /dev/null) +APP_HTML_FILES += $(PACKAGE)_geoportal/static-ngeo/js/apps/main.html.ejs PRINT_CONFIG_FILE ?= print/print-apps/$(PACKAGE)/config.yaml.tmpl I18N_SOURCE_FILES += \ - geoportal/development.ini \ - geoportal/print-config.yaml.tmpl \ + pot-create.ini \ $(APP_HTML_FILES) \ $(APP_JS_FILES) @@ -75,19 +71,20 @@ I18N_SOURCE_FILES += \ update-pots: echo "This target must be run inside Luxembourg internal network" # Handle client.pot - docker cp ./config/print/print-apps/geoportailv3/config.yaml.tmpl $(DOCKER_CONTAINER):/app/geoportal/print-config.yaml.tmpl + #docker cp ./config/print/print-apps/geoportailv3/config.yaml.tmpl $(DOCKER_CONTAINER):/app/geoportal/print-config.yaml.tmpl docker exec $(DOCKER_CONTAINER) pot-create --config lingua-client.cfg --output /tmp/client.pot $(I18N_SOURCE_FILES) docker cp $(DOCKER_CONTAINER):/tmp/client.pot geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-client.pot # Handle server.pot docker exec $(DOCKER_CONTAINER) pot-create --config lingua-server.cfg --output /tmp/server.pot $(SERVER_LOCALISATION_SOURCES_FILES) docker cp $(DOCKER_CONTAINER):/tmp/server.pot geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-server.pot # Handle legends.pot - docker exec $(DOCKER_CONTAINER) pot-create --config lingua-legends.cfg --output /tmp/legends.pot geoportal/development.ini + docker exec $(DOCKER_CONTAINER) pot-create --config lingua-legends.cfg --output /tmp/legends.pot geoportal/pot-create.ini docker cp $(DOCKER_CONTAINER):/tmp/legends.pot geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-legends.pot # Handle tooltips.pot - docker exec $(DOCKER_CONTAINER) pot-create --config lingua-tooltips.cfg --output /tmp/tooltips.pot geoportal/development.ini + docker exec $(DOCKER_CONTAINER) pot-create --config lingua-tooltips.cfg --output /tmp/tooltips.pot geoportal/pot-create.ini docker cp $(DOCKER_CONTAINER):/tmp/tooltips.pot geoportal/geoportailv3_geoportal/locale/geoportailv3_geoportal-tooltips.pot + OUTPUT_DIR = geoportal/geoportailv3_geoportal/static/build .PHONY: update-translations @@ -121,8 +118,7 @@ run: build dev: build echo "Once the composition is up open the following URL:" echo "browse http://localhost:8080/dev/main.html" - docker-compose -f docker-compose.yaml -f docker-compose-dev.yaml down - docker-compose -f docker-compose.yaml -f docker-compose-dev.yaml up + docker-compose down; docker-compose up .PHONY: attach attach: @@ -140,4 +136,4 @@ reload: .PHONY: rebuild-js-api rebuild-js-api: - docker-compose exec geoportal /app/apiv3/jsapi/rebuild_api.sh + docker-compose exec geoportal /app/jsapi/rebuild_api.sh diff --git a/README.md b/README.md index 0d4edd343..306ac06ef 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,6 @@ Build ```bash cd geoportailv3 -# Create symlink to the env you want to use -# You can create a custom env if you need to -ln -s env-localdev .env make build ``` diff --git a/bge.mk b/bge.mk deleted file mode 100644 index 58d3545fd..000000000 --- a/bge.mk +++ /dev/null @@ -1,5 +0,0 @@ -INSTANCE_ID = bge -VARS_FILE = vars_c2cdev.yaml -DISABLE_BUILD_RULES += print apache - -include geoportailv3.mk diff --git a/build b/build new file mode 100755 index 000000000..ad0560d2d --- /dev/null +++ b/build @@ -0,0 +1,156 @@ +#!/usr/bin/env python3 + +import argparse +import os +import os.path +import platform +import re +import stat +import subprocess +import sys +import urllib.request + +import yaml + + +def call(verbose, arguments, **kwargs): + if verbose: + print_args = [a.replace(" ", "\\ ") for a in arguments] + print_args = [a.replace('"', '\\"') for a in print_args] + print_args = [a.replace("'", "\\'") for a in print_args] + print(" ".join(print_args)) + subprocess.check_call(arguments, **kwargs) + + +def load_env(env_files): + """ + Parse env files and return environment as dict + """ + env = {} + for env_file in env_files: + with open(env_file) as f: + for line in f: + if line and line[0] != "#": + try: + index = line.index("=") + env[line[:index].strip()] = line[index + 1 :].strip() + except ValueError: + # Ignore lines that don't have a '=' + pass + return env + + +def main(): + parser = argparse.ArgumentParser(description="Build the project") + parser.add_argument("--verbose", help="Display the docker build commands") + parser.add_argument("--config", action="store_true", help="Build only the configuration image") + parser.add_argument("--geoportal", action="store_true", help="Build only the geoportal image") + parser.add_argument("--upgrade", help="Start upgrading the project to version") + parser.add_argument("env", nargs="*", help="The environment config") + args = parser.parse_args() + + if args.upgrade: + major_version = args.upgrade + match = re.match(r"^([0-9]+\.[0-9]+)\.[0-9]+$", args.upgrade) + if match is not None: + major_version = match.group(1) + match = re.match(r"^([0-9]+\.[0-9]+)\.[0-9]+\.[0-9]+$", args.upgrade) + if match is not None: + major_version = match.group(1) + full_version = args.upgrade if args.upgrade != "master" else "latest" + with open("upgrade", "w") as f: + result = urllib.request.urlopen( + "https://raw.githubusercontent.com/camptocamp/c2cgeoportal/{}/scripts/upgrade".format( + major_version + ) + ) + if result.code != 200: + print("ERROR:") + print(result.read()) + sys.exit(1) + f.write(result.read().decode()) + os.chmod("upgrade", os.stat("upgrade").st_mode | stat.S_IXUSR) + try: + if platform.system() == "Windows": + subprocess.check_call(["python", "upgrade", full_version]) + else: + subprocess.check_call(["./upgrade", full_version]) + except subprocess.CalledProcessError: + sys.exit(1) + sys.exit(0) + + with open("project.yaml") as project_file: + project_env = yaml.load(project_file, Loader=yaml.SafeLoader)["env"] + if len(args.env) != project_env["required_args"]: + print(project_env["help"]) + sys.exit(1) + env_files = [e.format(*args.env) for e in project_env["files"]] + print("Use env files: {}".format(", ".join(env_files))) + for env_file in env_files: + if not os.path.exists(env_file): + print("Error: the env file '{}' does not exist.".format(env_file)) + sys.exit(1) + env = load_env(env_files) + + base = env["DOCKER_BASE"] if "DOCKER_BASE" in env else "camptocamp/geoportailv3" + tag = ":" + env["DOCKER_TAG"] if "DOCKER_TAG" in env else "" + schema = env["PGSCHEMA"] + http_proxy = "" + https_proxy = "" + if "http_proxy" in env: + http_proxy = env["http_proxy"] + if "https_proxy" in env: + https_proxy = env["https_proxy"] + + default = not (args.config or args.geoportal) + + if default or args.config: + call( + args.verbose, + [ + "docker", + "build", + "--tag={}-config{}".format(base, tag), + "--build-arg=PGSCHEMA=" + schema, + "--build-arg=HTTP_PROXY_URL=" + http_proxy, + "--build-arg=HTTPS_PROXY_URL=" + https_proxy, + ".", + ], + ) + if default or args.geoportal: + git_hash = subprocess.check_output(["git", "rev-parse", "HEAD"]).strip().decode() + call( + args.verbose, + [ + "docker", + "build", + "--tag={}-geoportal{}".format(base, tag), + "--build-arg=PGSCHEMA=" + schema, + "--build-arg=GIT_HASH=" + git_hash, + "--build-arg=HTTP_PROXY_URL=" + http_proxy, + "--build-arg=HTTPS_PROXY_URL=" + https_proxy, + "geoportal", + ], + ) + call( + args.verbose, + [ + "docker", + "build", + "--target=builder", + "--tag={}-geoportal-dev{}".format(base, tag), + "--build-arg=HTTP_PROXY_URL=" + http_proxy, + "--build-arg=HTTPS_PROXY_URL=" + https_proxy, + "geoportal", + ], + ) + + with open(".env", "w") as dest: + for file_ in env_files: + with open(file_) as src: + dest.write(src.read() + "\n") + dest.write("# Used env files: {}\n".format(" ".join(env_files))) + + +if __name__ == "__main__": + main() diff --git a/compare_packages.py b/compare_packages.py new file mode 100755 index 000000000..6047d8a81 --- /dev/null +++ b/compare_packages.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# This script compares the npm packages version in the Luxembourg +# project with the ones in ngeo. +# Make sure to call "npm i" in the geoportal directory before running the script. + +import json + +with open('./geoportal/package.json') as json_file: + lux_deps = json.load(json_file)['devDependencies'] + with open('./geoportal/node_modules/ngeo/package.json') as ngeo_file: + ngeo_deps = json.load(ngeo_file)['devDependencies'] + for name, version in lux_deps.items(): + if name in ngeo_deps: + ngeo_version = ngeo_deps[name] + if ngeo_version != version: + print(name, version, '->', ngeo_version) diff --git a/config/.dockerignore b/config/.dockerignore deleted file mode 100644 index 709f6722f..000000000 --- a/config/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!bin/ -!print/print-apps/ diff --git a/config/Dockerfile b/config/Dockerfile deleted file mode 100644 index fba7395ba..000000000 --- a/config/Dockerfile +++ /dev/null @@ -1,28 +0,0 @@ -FROM debian:stretch -LABEL maintainer Camptocamp "info@camptocamp.com" -ARG HTTP_PROXY_URL -ENV http_proxy $HTTP_PROXY_URL -ARG HTTPS_PROXY_URL -ENV https_proxy $HTTPS_PROXY_URL - -RUN \ - apt-get update && \ - apt-get install --assume-yes --no-install-recommends gettext-base python3 && \ - apt-get clean && \ - rm --recursive --force /var/lib/apt/lists/* - -COPY . /tmp/config/ - -RUN mv /tmp/config/bin/* /usr/bin/ && \ - mkdir --parent /usr/local/tomcat/webapps/ROOT/ && \ - if [ -e /tmp/config/print ]; then mv /tmp/config/print/print-apps /usr/local/tomcat/webapps/ROOT/; fi && \ - chmod g+w -R /etc /usr/local/tomcat/webapps && \ - adduser www-data root - -VOLUME \ - /usr/local/tomcat/webapps/ROOT/print-apps -ENV VISIBLE_ENTRY_POINT / -ENV VISIBLE_WEB_HOST localhost:8080 - -RUN eval-templates -ENTRYPOINT [ "/usr/bin/entrypoint" ] diff --git a/config/bin/entrypoint b/config/bin/entrypoint deleted file mode 100755 index f9216ff86..000000000 --- a/config/bin/entrypoint +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -e - -eval-templates - -exec "$@" diff --git a/config/bin/eval-templates b/config/bin/eval-templates deleted file mode 100755 index 095b8a530..000000000 --- a/config/bin/eval-templates +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env python3 - -import glob -import os -import re -import urllib.parse -import subprocess - -os.environ["VISIBLE_WEB_HOST_RE_ESCAPED"] = re.escape(os.environ.get('VISIBLE_WEB_HOST')) -os.environ["VISIBLE_ENTRY_POINT_RE_ESCAPED"] = re.escape(os.environ.get('VISIBLE_ENTRY_POINT')) - -SCHEME_PORT = { - "http": 80, - "https": 443, -} -for name in ("GEOPORTAL", "TILECLOUDCHAIN"): - if name + "_INTERNAL_URL" in os.environ: - url = urllib.parse.urlparse(os.environ[name + "_INTERNAL_URL"]) - os.environ[name + "_INTERNAL_HOST"] = url.hostname - os.environ[name + "_INTERNAL_PORT"] = str(url.port or SCHEME_PORT.get(url.scheme, "NULL")) - - -def evaluate(filename): - print("Evaluate: " + filename) - with open(filename) as in_: - with open(filename[:-5], "w") as out: - subprocess.check_call(["envsubst"], stdin=in_, stdout=out) - - -for filename in glob.glob("/etc/**/*.tmpl", recursive=True): - evaluate(filename) - -for filename in glob.glob("/usr/local/tomcat/webapps/**/*.tmpl", recursive=True): - evaluate(filename) diff --git a/config/print/WEB-INF/classes/logback.xml b/config/print/WEB-INF/classes/logback.xml deleted file mode 100644 index 221418503..000000000 --- a/config/print/WEB-INF/classes/logback.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - build/logs/logFile.log - - - build/logs/logFile.%d{yyyy-MM-dd}.log - - - 30 - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - - - - - - - - - - - - diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml deleted file mode 100644 index 341fda2d9..000000000 --- a/docker-compose-dev.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- - -# The project Docker compose file for development. - -version: '2' - -services: - - webpack-dev-server: - image: camptocamp/geoportailv3-geoportal:latest - volumes: - - ./geoportal/geoportailv3_geoportal/static-ngeo:/app/geoportailv3_geoportal/static-ngeo:ro - command: - - node_modules/.bin/webpack-dev-server - - --mode=development - - --host=webpack-dev-server - - --port=8080 - - --debug - - --watch - - --progress - environment: - - VISIBLE_ENTRY_POINT - - VISIBLE_WEB_HOST - - VISIBLE_WEB_PROTOCOL - - DEVSERVER_HOST - - C2C_REDIS_URL - - INTERFACE=main diff --git a/docker-compose-lib.yaml b/docker-compose-lib.yaml new file mode 100644 index 000000000..0e052fbc3 --- /dev/null +++ b/docker-compose-lib.yaml @@ -0,0 +1,311 @@ +--- + +version: '2.0' + +services: + config: + image: ${DOCKER_BASE}-config:${DOCKER_TAG} + user: www-data + environment: + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - VISIBLE_ENTRY_POINT + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - GEOPORTAL_INTERNAL_URL + - GEOPORTAL_INTERNAL_HOST + - GEOPORTAL_INTERNAL_PORT + - TILECLOUDCHAIN_INTERNAL_URL + - TILECLOUDCHAIN_INTERNAL_HOST + - TILECLOUDCHAIN_INTERNAL_PORT + - MAPSERVER_URL + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - TILEGENERATION_SQS_QUEUE + - TILEGENERATION_S3_BUCKET + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + + print: + image: camptocamp/mapfish_print:3.22 + user: www-data + restart: unless-stopped + environment: + - CATALINA_OPTS + - PGOPTIONS + + mapserver: + image: camptocamp/mapserver:7.4 + user: www-data + restart: unless-stopped + entrypoint: [] + environment: + - PGOPTIONS + + qgisserver: + image: camptocamp/geomapfish-qgisserver:gmf2.5-qgis${QGIS_VERSION} + user: www-data + restart: unless-stopped + environment: + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - CPL_VSIL_CURL_USE_CACHE + - CPL_VSIL_CURL_CACHE_SIZE + - CPL_VSIL_CURL_USE_HEAD + - GDAL_DISABLE_READDIR_ON_OPEN + - QGIS_SERVER_LOG_LEVEL=2 + - LOG_LEVEL=INFO + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - OTHER_LOG_LEVEL + + tinyows: + image: camptocamp/tinyows:master + user: www-data + restart: unless-stopped + + redis: + image: redis:5 + user: www-data + restart: unless-stopped + command: + - redis-server + - --save + - '' + - --appendonly + - 'no' + - --maxmemory + - 512mb + - --maxmemory-policy + - volatile-lru + - --tcp-keepalive + - '30' + + tilecloudchain: + image: camptocamp/tilecloud-chain:1.13 + user: www-data + restart: unless-stopped + environment: + - GUNICORN_PARAMS + - VISIBLE_ENTRY_POINT + - C2C_REDIS_URL + - TILEGENERATION_CONFIGFILE=/etc/tilegeneration/config.yaml + - C2C_BASE_PATH=/tiles/c2c + - C2C_BROADCAST_PREFIX=broadcast_tilecloudchain_ + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_SECRET + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + + tilegeneration_slave: + image: camptocamp/tilecloud-chain:1.13 + user: www-data + restart: unless-stopped + entrypoint: + - generate_tiles + - --role=slave + - --daemon + environment: + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + + geoportal: + image: ${DOCKER_BASE}-geoportal:${DOCKER_TAG} + user: www-data + restart: unless-stopped + environment: + - VISIBLE_ENTRY_POINT + - PACKAGE=geoportailv3 + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - GUNICORN_PARAMS + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - AUTHTKT_TIMEOUT + - AUTHTKT_REISSUE_TIME + - AUTHTKT_MAXAGE + - AUTHTKT_SECRET + - AUTHTKT_COOKIENAME + - AUTHTKT_HTTP_ONLY + - AUTHTKT_SECURE + - AUTHTKT_SAMESITE + - BASICAUTH + - TINYOWS_URL + - MAPSERVER_URL + - QGISSERVER_URL + - PRINT_URL + - DEVSERVER_HOST + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SECRET + - LOG_LEVEL + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - GUNICORN_LOG_LEVEL + - OTHER_LOG_LEVEL + - DOGPILECACHE_LOG_LEVEL + - LOG_TYPE + + tools: + image: camptocamp/geomapfish-tools:2.5.0.139 + restart: unless-stopped + environment: + - PGSCHEMA + # From geoportal + - VISIBLE_ENTRY_POINT + - PACKAGE=geoportailv3 + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - GUNICORN_PARAMS + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - AUTHTKT_TIMEOUT + - AUTHTKT_REISSUE_TIME + - AUTHTKT_MAXAGE + - AUTHTKT_SECRET + - AUTHTKT_COOKIENAME + - AUTHTKT_HTTP_ONLY + - AUTHTKT_SECURE + - AUTHTKT_SAMESITE + - BASICAUTH + - TINYOWS_URL + - MAPSERVER_URL + - QGISSERVER_URL + - PRINT_URL + - DEVSERVER_HOST + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SECRET + - LOG_LEVEL + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - GUNICORN_LOG_LEVEL + - OTHER_LOG_LEVEL + - DOGPILECACHE_LOG_LEVEL + - LOG_TYPE + + alembic: + image: ${DOCKER_BASE}-geoportal:${DOCKER_TAG} + user: www-data + entrypoint: [] + command: + - alembic + - --name=static + - upgrade + - head + environment: + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - LOG_TYPE + + front: + image: haproxy:1.9 + restart: unless-stopped + volumes: + - /dev/log:/dev/log:rw + command: + - haproxy + - -f + - /etc/${FRONT_CONFIG} + ports: + - ${DOCKER_PORT}:${FRONT_INNER_PORT} + + webpack_dev_server: + image: ${DOCKER_BASE}-geoportal-dev:${DOCKER_TAG} + volumes: + - ./geoportal/geoportailv3_geoportal/static-ngeo:/app/geoportailv3_geoportal/static-ngeo + environment: + - VISIBLE_ENTRY_POINT + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + + pytree: + image: camptocamp/pytree + environment: + - DEPLOY_ENV=PROD + volumes: + - ./lidar/data:/home/pytree/data/processed + - ./lidar/pytree.yml:/home/pytree/pytree.yml + diff --git a/docker-compose.override.sample.yaml b/docker-compose.override.sample.yaml new file mode 100644 index 000000000..cb71912c9 --- /dev/null +++ b/docker-compose.override.sample.yaml @@ -0,0 +1,184 @@ +--- +# This file can be renamed as `docker-compose.override.yaml` and uncomment the desired lines for +# development. The file `docker-compose.override.yaml` is ignored by Git by default. + +# yamllint disable rule:line-length + +version: '2.0' + +services: + alembic: + volumes: + # For Python project development. + # - ./geoportal/geoportailv3_geoportal:/app/geoportailv3_geoportal + - ./geoportal/geoportailv3_geoportal/views:/app/geoportailv3_geoportal/views:ro + - ./geoportal/geoportailv3_geoportal/routing:/app/geoportailv3_geoportal/routing:ro + - ./geoportal/c2cgeoportal/geoportal/c2cgeoportal_geoportal/routing:/app/c2cgeoportal/geoportal/c2cgeoportal_geoportal/routing:ro + - ./geoportal/c2cgeoportal/geoportal/c2cgeoportal_geoportal/templates:/app/c2cgeoportal/geoportal/c2cgeoportal_geoportal/templates:ro + - ./geoportal/geoportailv3_geoportal/templates:/app/geoportailv3_geoportal/templates:ro + - ./geoportal/geoportailv3_geoportal/scripts:/app/geoportailv3_geoportal/scripts:ro + - ./geoportal/geoportailv3_geoportal/lib:/app/geoportailv3_geoportal/lib:ro + - ./geoportal/geoportailv3_geoportal/static-ngeo/js:/app/geoportailv3_geoportal/static-ngeo/js:ro + - ./geoportal/geoportailv3_geoportal/static-ngeo/less:/app/geoportailv3_geoportal/static-ngeo/less:ro + # - ./geoportal/jsapi:/app/apiv3/jsapi:ro + geoportal: + user: root + volumes: + # For Python project development. + - ./geoportal/geoportailv3_geoportal:/app/geoportailv3_geoportal + # For Python c2cgeportal development. + # - ./../c2cgeoportal/commons/c2cgeoportal_commons:/opt/c2cgeoportal/commons/c2cgeoportal_commons + # - ./../c2cgeoportal/geoportal/c2cgeoportal_geoportal:/opt/c2cgeoportal/geoportal/c2cgeoportal_geoportal + # - ./../c2cgeoportal/admin/c2cgeoportal_admin:/opt/c2cgeoportal/admin/c2cgeoportal_admin + environment: + - GUNICORN_CMD_ARGS=--reload + - C2CWSGIUTILS_CONFIG=/app/development.ini + # - PRINT_URL=http://print:8080/print/ + ports: + - 5678:5678 # For remote debugging using Visual Studio Code + + # Also uncomment the PRINT_URL in geoportal + # print: + # extends: + # file: docker-compose-lib.yaml + # service: print + # volumes_from: + # - config:ro + + # qgisserver: + # # volumes: + # # - './../c2cgeoportal/docker/qgisserver/geomapfish_qgisserver/:/var/www/plugins/geomapfish_qgisserver/' + # # - './../c2cgeoportal/commons/c2cgeoportal_commons:/opt/c2cgeoportal/commons/c2cgeoportal_commons/' + # environment: + # - QGIS_SERVER_LOG_LEVEL=0 + + # For Javascript project development. + # The debug application will be availavble at ``https:////dev/.html``. + webpack_dev_server: + # Uncomment these lines when you want to debug respectively the project js, ngeo js and/or the gmf contrib js. + # Adapt the path for ngeo / gmf contrib to point where you have checkouted the code. + # volumes: + # - ./geoportal/geoportailv3_geoportal/static-ngeo:/app/geoportailv3_geoportal/static-ngeo + # - ./../ngeo/src:/usr/lib/node_modules/ngeo/src + # - ./../ngeo/contribs:/usr/lib/node_modules/ngeo/contribs + volumes_from: + - config:rw + extends: + file: docker-compose-lib.yaml + service: webpack_dev_server + command: + [ "webpack-dev-server", "--mode=development", "--debug", "--watch", "--progress", "--no-inline" ] + environment: + - CASIPO_STAGING_URL + - PAG_OWNCLOUD_PASSWORD + - LDAP_PASSWD + - FAKE_REVERSE_GEOCODING=1 + - PAG_OWNCLOUD_INTERNAL_URL + - FAKE_PRINT_URLS=http://print:8080/print/geoportailv3,http://print:8080/print/geoportailv3 + - PAG_FME_TOKEN + - SHORTENER_BASE_URL + - ROUTING_MAPQUEST_API_KEY + - LOG_LEVEL=INFO + - AUTHTKT_SECURE=false + - CASIPO_OWNCLOUD_EXTERNAL_URL + - LDAP_BIND + - DB_MYMAPS + - FAKE_CMSSEARCH=1 + - DHM_DEM_FILE=/var/luxdata/dem500.tif + - ANF_EMAIL + - GUNICORN_ACCESS_LOG_LEVEL=INFO + - PGSCHEMA + - PAG_PROD_URL + - IGNORE_I18N_ERRORS=TRUE + - SQL_LOG_LEVEL=INFO + - AGE_CRUES_EMAIL + - CASIPO_SMTP_SERVER + - LDAP_URL + - LDAP_FILTER_TMPL + - PDS_BCC_ADDRESS + - PAG_OWNCLOUD_USER + - FAKE_FULLTEXT_SEARCH=1 + - AGE_CRUES_LAYERS + - CASIPO_PROD_URL + - CASIPO_OWNCLOUD_INTERNAL_URL + - C2CGEOPORTAL_LOG_LEVEL=INFO + - PAG_OWNCLOUD_EXTERNAL_URL + - ANF_MAP_ID + - ELASTIC_SERVERS + - DB_ECADASTRE + - DB_POI + - CASIPO_OWNCLOUD_USER + - DHM_DEM_TYPE=gdal + - PAG_STAGING_URL + - PDS_PROD_URL + - CASIPO_BCC_ADDRESS + - AGE_CRUES_SHOW_LINK + - SHORTENER_ALLOWED_HOST + - DEBUG_TOOLBAR=1 + - GUNICORN_LOG_LEVEL=INFO + - AGE_CRUES_ROLES + - PDS_SMTP_SERVER + - CASIPO_FME_TOKEN + - FAKE_LAYERSEARCH=0 + - OTHER_LOG_LEVEL=WARN + - CASIPO_OWNCLOUD_PASSWORD + - PAG_SMTP_SERVER + - DEFAULT_MYMAPS_ROLE + - GUNICORN_PARAMS=--bind=:8080 --threads=10 --timeout=60 --reload --forwarded-allow-ips=* + - DB_PGROUTE + - MAILER_DIRECTORY + - AGE_CRUES_MAP_ID + - PDS_STAGING_URL + - C2CWSGIUTILS_CONFIG=/app/development.ini + - PAG_BCC_ADDRESS + - ELASTIC_INDEX + - LDAP_BASE_DN + - PAG_FILE_SERVER + - ROUTING_GRAPHHOPPER_API_KEY + - GUNICORN_CMD_ARGS=--reload + - VISIBLE_ENTRY_POINT + - PACKAGE=geoportailv3 + - PGHOST + - PGHOST_SLAVE + - PGPORT + - PGPORT_SLAVE + - PGUSER + - PGPASSWORD + - PGDATABASE + - PGSSLMODE + - PGSCHEMA_STATIC + - PGOPTIONS + - AWS_ACCESS_KEY_ID + - AWS_SECRET_ACCESS_KEY + - AWS_DEFAULT_REGION + - AWS_S3_ENDPOINT + - VISIBLE_WEB_HOST + - VISIBLE_WEB_PROTOCOL + - AUTHTKT_TIMEOUT + - AUTHTKT_REISSUE_TIME + - AUTHTKT_MAXAGE + - AUTHTKT_SECRET + - AUTHTKT_COOKIENAME + - AUTHTKT_HTTP_ONLY + - AUTHTKT_SAMESITE + - BASICAUTH + - TINYOWS_URL + - MAPSERVER_URL + - QGISSERVER_URL + - PRINT_URL + - DEVSERVER_HOST + - REDIS_HOST + - REDIS_PORT + - REDIS_DB + - C2C_REDIS_URL + - C2C_BROADCAST_PREFIX + - C2C_LOG_VIEW_ENABLED=TRUE + - C2C_SQL_PROFILER_ENABLED=TRUE + - C2C_DEBUG_VIEW_ENABLED=TRUE + - C2C_SECRET + - C2CGEOPORTAL_LOG_LEVEL + - SQL_LOG_LEVEL + - DOGPILECACHE_LOG_LEVEL + - LOG_TYPE + - C2CWSGIUTILS_LOG_LEVEL=WARN + diff --git a/docker-compose.yaml b/docker-compose.yaml index c3a7d357d..0901f4c1a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -2,21 +2,18 @@ # The project Docker compose file for development. -version: '2' +version: '2.0' services: config: - image: camptocamp/geoportailv3-config:${DOCKER_TAG} -# user: www-data - environment: - - VISIBLE_WEB_HOST - - VISIBLE_WEB_PROTOCOL - - VISIBLE_ENTRY_POINT - - GEOPORTAL_INTERNAL_URL + extends: + file: docker-compose-lib.yaml + service: config print: - image: camptocamp/mapfish_print:3.18.4 - user: www-data + extends: + file: docker-compose-lib.yaml + service: print volumes_from: - config:ro ports: @@ -24,73 +21,97 @@ services: environment: - CATALINA_OPTS=-Xmx1024m - PGOPTIONS=-c statement_timeout=30000 -# - DEFAULT_LOG_LEVEL=DEBUG -# - TOMCAT_LOG_LEVEL=DEBUG -# - LOG_LEVEL=DEBUG -# - SPRING_LOG_LEVEL=DEBUG -# - JASPER_LOG_LEVEL=DEBUG -# - APACHE_LOG_LEVEL=DEBUG -# - SQL_LOG_LEVEL=DEBUG + + redis: + extends: + file: docker-compose-lib.yaml + service: redis geoportal: - command: ./bin/lux_c2cwsgiutils_run.sh - image: camptocamp/geoportailv3-geoportal:${DOCKER_TAG} -# user: www-data + extends: + file: docker-compose-lib.yaml + service: geoportal + volumes_from: + - config:ro volumes: - /var/sig:/var/sig:ro - ./data:/var/luxdata:ro - - ./geoportal/geoportailv3_geoportal/views:/app/geoportailv3_geoportal/views:ro - - ./geoportal/geoportailv3_geoportal/routing:/app/geoportailv3_geoportal/routing:ro - - ./geoportal/c2cgeoportal/geoportal/c2cgeoportal_geoportal/routing:/app/c2cgeoportal/geoportal/c2cgeoportal_geoportal/routing:ro - - ./geoportal/c2cgeoportal/geoportal/c2cgeoportal_geoportal/templates:/app/c2cgeoportal/geoportal/c2cgeoportal_geoportal/templates:ro - - ./geoportal/geoportailv3_geoportal/templates:/app/geoportailv3_geoportal/templates:ro - - ./geoportal/geoportailv3_geoportal/scripts:/app/geoportailv3_geoportal/scripts:ro - - ./geoportal/geoportailv3_geoportal/lib:/app/geoportailv3_geoportal/lib:ro - - ./geoportal/geoportailv3_geoportal/static-ngeo/js:/app/geoportailv3_geoportal/static-ngeo/js:ro - - ./geoportal/geoportailv3_geoportal/static-ngeo/less:/app/geoportailv3_geoportal/static-ngeo/less:ro - - ./geoportal/jsapi:/app/apiv3/jsapi:ro -# entrypoint: ['/usr/local/bin/alembic', '--config', '/app/alembic.ini', '--name', 'main', 'heads'] environment: - - PGAPPNAME - - AUTHTKT_TIMEOUT - - AGE_CRUES_EMAIL - - AGE_CRUES_MAP_ID - - AGE_CRUES_SHOW_LINK - - AGE_CRUES_LAYERS - - AGE_CRUES_ROLES - - PAG_STAGING_URL - - PAG_PROD_URL - - PAG_FME_TOKEN - - PAG_OWNCLOUD_INTERNAL_URL - - PAG_OWNCLOUD_EXTERNAL_URL - - PAG_OWNCLOUD_USER + - CASIPO_STAGING_URL - PAG_OWNCLOUD_PASSWORD - - PAG_SMTP_SERVER - - PAG_BCC_ADDRESS - - PAG_FILE_SERVER - - PDS_STAGING_URL - - PDS_PROD_URL - - PDS_SMTP_SERVER + - LDAP_PASSWD + - FAKE_REVERSE_GEOCODING=1 + - PAG_OWNCLOUD_INTERNAL_URL + - FAKE_PRINT_URLS=http://print:8080/print/geoportailv3,http://print:8080/print/geoportailv3 + - PAG_FME_TOKEN + - SHORTENER_BASE_URL + - ROUTING_MAPQUEST_API_KEY + - LOG_LEVEL=INFO + - AUTHTKT_SECURE=false + - CASIPO_OWNCLOUD_EXTERNAL_URL + - LDAP_BIND + - DB_MYMAPS + - FAKE_CMSSEARCH=1 + - DHM_DEM_FILE=/var/luxdata/dem500.tif + - ANF_EMAIL + - GUNICORN_ACCESS_LOG_LEVEL=INFO + - PGSCHEMA + - PAG_PROD_URL + - IGNORE_I18N_ERRORS=TRUE + - SQL_LOG_LEVEL=INFO + - AGE_CRUES_EMAIL + - CASIPO_SMTP_SERVER + - LDAP_URL + - LDAP_FILTER_TMPL - PDS_BCC_ADDRESS - - CASIPO_STAGING_URL + - PAG_OWNCLOUD_USER + - FAKE_FULLTEXT_SEARCH=1 + - AGE_CRUES_LAYERS - CASIPO_PROD_URL - - CASIPO_FME_TOKEN - CASIPO_OWNCLOUD_INTERNAL_URL - - CASIPO_OWNCLOUD_EXTERNAL_URL + - C2CGEOPORTAL_LOG_LEVEL=INFO + - PAG_OWNCLOUD_EXTERNAL_URL + - ANF_MAP_ID + - ELASTIC_SERVERS + - DB_ECADASTRE + - DB_POI - CASIPO_OWNCLOUD_USER - - CASIPO_OWNCLOUD_PASSWORD - - CASIPO_SMTP_SERVER + - DHM_DEM_TYPE=gdal + - PAG_STAGING_URL + - PDS_PROD_URL + - AUTHTKT_SECRET=a_super_secret_for_auth_at_least_64_characters_long_for_sha512_algo_otherwise_not_good - CASIPO_BCC_ADDRESS - - ANF_EMAIL - - ANF_MAP_ID + - AGE_CRUES_SHOW_LINK + - SHORTENER_ALLOWED_HOST - DEBUG_TOOLBAR=1 - - DB_MYMAPS + - GUNICORN_LOG_LEVEL=INFO + - AGE_CRUES_ROLES + - PDS_SMTP_SERVER + - CASIPO_FME_TOKEN + - FAKE_LAYERSEARCH=0 + - OTHER_LOG_LEVEL=WARN + - CASIPO_OWNCLOUD_PASSWORD + - PAG_SMTP_SERVER + - DEFAULT_MYMAPS_ROLE + - GUNICORN_PARAMS=--bind=:8080 --threads=10 --timeout=60 --reload --forwarded-allow-ips=* --limit-request-line=8190 - DB_PGROUTE - - DB_ECADASTRE - - DB_POI - - VISIBLE_ENTRY_POINT - - VISIBLE_WEB_HOST - - VISIBLE_WEB_PROTOCOL + - MAILER_DIRECTORY + - AGE_CRUES_MAP_ID + - PDS_STAGING_URL + - C2CWSGIUTILS_CONFIG=/app/development.ini + - PAG_BCC_ADDRESS + - ELASTIC_INDEX + - LDAP_BASE_DN + - PAG_FILE_SERVER + - ROUTING_GRAPHHOPPER_API_KEY + ports: + - 8080:8080 + + alembic: + extends: + file: docker-compose-lib.yaml + service: alembic + environment: - PGHOST - PGHOST_SLAVE - PGPORT @@ -100,88 +121,41 @@ services: - PGSCHEMA - PGSCHEMA_STATIC - PGOPTIONS - - PRINT_URL - - GUNICORN_PARAMS=--bind=:8080 --threads=10 --timeout=60 --reload --forwarded-allow-ips=* --limit-request-line=0 - - LOG_LEVEL=INFO - - C2CGEOPORTAL_LOG_LEVEL=INFO - - C2CWSGIUTILS_CONFIG=/app/development.ini - - SQL_LOG_LEVEL=INFO - - GUNICORN_LOG_LEVEL=INFO - - GUNICORN_ACCESS_LOG_LEVEL=INFO - - IGNORE_I18N_ERRORS=TRUE - - OTHER_LOG_LEVEL=WARN - - DEVSERVER_HOST - - REDIS_HOST - - REDIS_PORT - - C2C_REDIS_URL - - LDAP_BASE_DN - - LDAP_BIND - - LDAP_PASSWD - - LDAP_URL - - LDAP_FILTER_TMPL - - MAILER_DIRECTORY - - DEFAULT_MYMAPS_ROLE - - DHM_DEM_FILE=/var/luxdata/dem500.tif - - DHM_DEM_TYPE=gdal - - FAKE_REVERSE_GEOCODING=1 - - FAKE_FULLTEXT_SEARCH=1 - - FAKE_LAYERSEARCH=0 - - FAKE_CMSSEARCH=1 - - FAKE_PRINT_URLS=http://print:8080/print/geoportailv3,http://print:8080/print/geoportailv3 - - SHORTENER_BASE_URL - - SHORTENER_ALLOWED_HOST - - ELASTIC_SERVERS - - ELASTIC_INDEX - - ROUTING_GRAPHHOPPER_API_KEY - - ROUTING_MAPQUEST_API_KEY - - AUTHTKT_SECURE=false - - AUTHTKT_SECRET=a_super_secret_for_auth_at_least_64_characters_long_for_sha512_algo_otherwise_not_good - - ARCGIS_TOKEN_URL - - ARCGIS_TOKEN_VALIDITY=600 - - ARCGIS_TOKEN_REFERER=https://map.geoportail.lu - - ARCGIS_USER - - ARCGIS_PASS - ports: - - 8080:8080 + command: ./bin/alembic_upgrade_all.sh - redis: - image: redis:3.2 - user: www-data - restart: unless-stopped - command: - - redis-server - - --save - - '' - - --appendonly - - 'no' - - --maxmemory - - 512mb - - --maxmemory-policy - - allkeys-lru + # front: + # extends: + # file: docker-compose-lib.yaml + # service: front + # volumes_from: + # - config:ro - ldap: - image: lux-dev-ldap + # Rich image for project development with e.-g. vim, tree, awscli, psql, ... + tools: + volumes_from: + - config:rw + volumes: + - .:/src + extends: + file: docker-compose-lib.yaml + service: tools + # lux specific additions elasticsearch: - image: elasticsearch:5.6.16 + image: elasticsearch:5.0 environment: ES_JAVA_OPTS: -Xmx512m -Xms512m volumes: - - ./config/elasticsearch-config:/usr/share/elasticsearch/config:ro + - ./elasticsearch-config:/usr/share/elasticsearch/config:ro ports: - 9200:9200 - alembic: - image: camptocamp/geoportailv3-geoportal:${DOCKER_TAG} -# user: www-data - command: ./bin/alembic_upgrade_all.sh - environment: - - PGHOST - - PGHOST_SLAVE - - PGPORT - - PGUSER - - PGPASSWORD - - PGDATABASE - - PGSCHEMA - - PGSCHEMA_STATIC - - PGOPTIONS + pytree: + extends: + file: docker-compose-lib.yaml + service: pytree + ports: + - "5000:5000" + + ldap: + image: lux-dev-ldap diff --git a/docker-run b/docker-run deleted file mode 100755 index eddbfbd34..000000000 --- a/docker-run +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import configparser -import netifaces -import os -import subprocess -import sys - - -def main(): - is_windows = os.name == "nt" - - config_parser = configparser.ConfigParser() - if os.path.exists(".config"): - config_parser.read(".config") - if "docker-run" not in config_parser: - config_parser["docker-run"] = {} - config = config_parser["docker-run"] - - parser = argparse.ArgumentParser(description="Run docker build.") - parser.add_argument("--root", action="store_true", help="Be root in the container") - parser.add_argument("--home", action="store_true", help="Mount the home directory") - parser.add_argument("-ti", action="store_true", help="Use -ti docker run option") - parser.add_argument("--env", action='append', default=[], help="A variable environment to pass or set") - parser.add_argument("--share", action='append', default=[], help="A folder to share as a volume") - parser.add_argument( - "--mount", action='append', default=[], help="Attach a filesystem mount to the container") - parser.add_argument( - "-v", "--volume", action='append', default=[], help="Bind mount a volume (default [])") - parser.add_argument( - "--image", default=config.get("image", "camptocamp/geomapfish-build-dev"), - help="The docker image to use" - ) - parser.add_argument( - "--version", default=config.get("version", "2.3"), - help="The docker image version to use" - ) - parser.add_argument("--hash", metavar="hash", help="The docker image hash to run") - parser.add_argument("cmd", metavar="CMD", help="The command to run") - parser.add_argument("args", metavar="...", nargs=argparse.REMAINDER, help="The command arguments") - options = parser.parse_args() - - docker_cmd = ['docker', 'run'] - - if options.ti or options.hash: - docker_cmd.append("-ti") - - for share in options.share: - docker_cmd.append("--volume={}:{}".format(share, share)) - - dir_path = os.path.dirname(os.path.realpath(__file__)) - build_volume_name = dir_path.replace(":", "-").replace("\\", "-") \ - if is_windows else dir_path[1:].replace("/", "-") - - try: - git_branch = \ - os.environ['TRAVIS_BRANCH'] if 'TRAVIS_BRANCH' in os.environ else \ - subprocess.check_output([ - "git", "rev-parse", "--abbrev-ref", "HEAD" - ]).decode("utf-8").strip() - git_hash = subprocess.check_output([ - "git", "rev-parse", "HEAD" - ]).decode("utf-8").strip() - except subprocess.CalledProcessError as e: - git_branch = "unknown" - git_hash = "unknown" - - try: - login = os.getlogin() - except FileNotFoundError: - # workaround on strange error - import pwd - login = pwd.getpwuid(os.getuid())[0] - except OSError: - # workaround on strange error - import pwd - login = pwd.getpwuid(os.getuid())[0] - - docker_cmd.extend([ - "--rm", - "--volume={socket}:{socket}".format( - socket="//./pipe/docker_engine" if is_windows else "/var/run/docker.sock" - ), - "--volume={}:/build".format(build_volume_name), - "--volume={pwd}:/src".format(pwd=os.getcwd()), - "--env=USER_NAME={}".format(login), - "--env=USER_ID={}".format(os.getuid() if os.name == "posix" else 1000), - "--env=GROUP_ID={}".format(os.getgid() if os.name == "posix" else 1000), - "--env=GIT_BRANCH={}".format(git_branch), - "--env=GIT_HASH={}".format(git_hash), - ]) - - if options.home: - internal_home = "/home/{login}".format(login=login) if is_windows else os.environ["HOME"] - external_home = os.environ["USERPROFILE"] if is_windows else os.environ["HOME"] - - if options.root: - docker_cmd.append("--volume={}:/root".format(external_home)) - docker_cmd.append("--volume={}:{}".format(internal_home, external_home)) - else: - docker_cmd.append("--volume={}:/home".format(build_volume_name + "-home")) - - if "SSH_AUTH_SOCK" in os.environ: - docker_cmd.extend([ - "--volume={ssh}:{ssh}".format(ssh=os.environ["SSH_AUTH_SOCK"]), - "--env=SSH_AUTH_SOCK", - ]) - - for env in ["CI"] + options.env: - docker_cmd.append("--env={}".format(env)) - - for mount in options.mount: - docker_cmd.append("--mount={}".format(mount)) - - for volume in options.volume: - docker_cmd.append("--volume={}".format(volume)) - - if is_windows: - import winreg - - def get_connection_name_from_guid(iface_guid): - reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - reg_key = winreg.OpenKey( - reg, r'SYSTEM\CurrentControlSet\Control\Network\{4d36e972-e325-11ce-bfc1-08002be10318}' - ) - try: - reg_subkey = winreg.OpenKey(reg_key, iface_guid + r'\Connection') - return winreg.QueryValueEx(reg_subkey, 'Name')[0] - except FileNotFoundError: - return None - - for x in netifaces.interfaces(): - if get_connection_name_from_guid(x) == 'Ethernet': - docker_adrs = netifaces.ifaddresses(x)[2][0]['addr'] - break - elif 'docker0' in netifaces.interfaces(): - docker_adrs = netifaces.ifaddresses('docker0')[2][0]['addr'] - else: - # For Jenkins slave in Docker - docker_adrs = netifaces.gateways()[netifaces.AF_INET][0][0] - # We needs the user HOME directory to correctly create the user in Docker - docker_cmd.append("--env=HOME_DIR={}".format( - "/home/" + login if is_windows else os.environ["HOME"])) - docker_cmd.append("--env=DOCKER_HOST_={}".format(docker_adrs)) - docker_cmd.append("--env=BUILD_VOLUME_NAME={}".format(build_volume_name)) - docker_cmd.append("--env=PROJECT_DIRECTORY={}".format(os.getcwd())) - ifaddresses = [netifaces.ifaddresses(iface) for iface in netifaces.interfaces()] - # IP v4 - adrs = [e[2][0]['addr'] for e in ifaddresses if 2 in e] - # IP v6 - adrs += [e[10][0]['addr'].split('%')[0] for e in ifaddresses if 10 in e] - docker_cmd.append("--env=ADDRESSES={}".format(' '.join(adrs))) - docker_cmd.append("--env=EXTERNAL_PYTHON_VERSION_MAJOR={}".format(sys.version_info.major)) - docker_cmd.append("--env=EXTERNAL_PYTHON_VERSION_MINOR={}".format(sys.version_info.minor)) - - if options.root: - docker_cmd.extend(["--entrypoint", options.cmd]) - - if options.hash: - docker_cmd.append(options.hash) - else: - docker_cmd.append("{}:{}".format(options.image, options.version)) - - if not options.root: - docker_cmd.append(options.cmd) - - docker_cmd.extend(options.args) - try: - subprocess.check_call(docker_cmd) - except subprocess.CalledProcessError: - exit(2) - - -if __name__ == "__main__": - main() diff --git a/config/elasticsearch-config/elasticsearch.yml b/elasticsearch-config/elasticsearch.yml similarity index 100% rename from config/elasticsearch-config/elasticsearch.yml rename to elasticsearch-config/elasticsearch.yml diff --git a/config/elasticsearch-config/log4j2.properties b/elasticsearch-config/log4j2.properties similarity index 100% rename from config/elasticsearch-config/log4j2.properties rename to elasticsearch-config/log4j2.properties diff --git a/config/elasticsearch-config/scripts/README b/elasticsearch-config/scripts/README similarity index 100% rename from config/elasticsearch-config/scripts/README rename to elasticsearch-config/scripts/README diff --git a/env.default b/env.default new file mode 100644 index 000000000..9af37dbee --- /dev/null +++ b/env.default @@ -0,0 +1,49 @@ +# Default values for c2cgeoportal +COMPOSE_PROJECT_NAME=geoportailv3 +DOCKER_PORT=8484 +DOCKER_BASE=camptocamp/geoportailv3 +DOCKER_TAG=latest +VISIBLE_WEB_HOST=localhost:8484 +VISIBLE_WEB_PROTOCOL=https +VISIBLE_ENTRY_POINT=/ +AUTHTKT_TIMEOUT=86400 +AUTHTKT_REISSUE_TIME=9000 +AUTHTKT_MAXAGE=86400 +AUTHTKT_SECRET=aed4ma7pah7Riph9paMoow3raeB5ooSa2ayee4fooQuohT7Etinohshah7eib4Re +AUTHTKT_COOKIENAME=auth_tkt_geoportailv3 +AUTHTKT_HTTP_ONLY=True +AUTHTKT_SECURE=True +AUTHTKT_SAMESITE=Lax +BASICAUTH=False +GEOPORTAL_INTERNAL_URL=http://geoportal:8080 +# For internal print +GEOPORTAL_INTERNAL_HOST=geoportal +GEOPORTAL_INTERNAL_PORT=8080 +TILECLOUDCHAIN_INTERNAL_URL=http://tilecloudchain:8080 +# For internal print +TILECLOUDCHAIN_INTERNAL_HOST=tilecloudchain +TILECLOUDCHAIN_INTERNAL_PORT=8080 +MAPSERVER_URL=http://mapserver:8080/ +TINYOWS_URL=http://tinyows:8080/ +QGISSERVER_URL=http://qgisserver:8080/ +QGIS_VERSION=3.10 +REDIS_HOST=redis +REDIS_PORT=6379 +REDIS_DB=0 +GUNICORN_PARAMS=--bind=:8080 --worker-class=gthread --threads=10 --workers=5 --timeout=60 --max-requests=1000 --max-requests-jitter=100 --config=/etc/gunicorn/config.py --worker-tmp-dir=/dev/shm +DEVSERVER_HOST=webpack_dev_server:8080 +C2C_REDIS_URL=redis://redis:6379/0 +PGOPTIONS=-c statement_timeout=30000 +CATALINA_OPTS=-Xmx1024m +C2C_BROADCAST_PREFIX=broadcast_geoportal_ +LOG_LEVEL=INFO +C2CGEOPORTAL_LOG_LEVEL=INFO +SQL_LOG_LEVEL=WARN +GUNICORN_LOG_LEVEL=WARN +OTHER_LOG_LEVEL=WARN +DOGPILECACHE_LOG_LEVEL=WARN +LOG_TYPE=console +CPL_VSIL_CURL_USE_CACHE=TRUE +CPL_VSIL_CURL_CACHE_SIZE=128000000 +CPL_VSIL_CURL_USE_HEAD=FALSE +GDAL_DISABLE_READDIR_ON_OPEN=TRUE diff --git a/env-localdev b/env.project similarity index 68% rename from env-localdev rename to env.project index 2fbca2c32..7fe4be4ea 100644 --- a/env-localdev +++ b/env.project @@ -1,32 +1,57 @@ -DB_ECADASTRE=postgresql://172.17.0.1:5433/dummy -DB_MYMAPS=postgresql://172.17.0.1:5433/lux -DB_PGROUTE=postgresql://172.17.0.1:5433/dummy -DB_POI=postgresql://172.17.0.1:5433/dummy -DOCKER_TAG=latest -VISIBLE_WEB_HOST=localhost:8080 -VISIBLE_WEB_PROTOCOL=http -VISIBLE_ENTRY_POINT=/ +# Custom project values + +# Database +PGDATABASE=lux +PGSCHEMA=geov3 +PGSCHEMA_STATIC=geov3_static +# To use the mutualised database. +# PGHOST=pg-gs.camptocamp.com +# PGHOST_SLAVE=pg-gs.camptocamp.com +# PGPORT=30100 +# PGPORT_SLAVE=30101 +# PGUSER= +# PGPASSWORD= +# # Should be set to 'prefer' to be able to connect to a local database +# PGSSLMODE=require +# To use a database on the host PGHOST=172.17.0.1 PGHOST_SLAVE=172.17.0.1 PGPORT=5433 +PGPORT_SLAVE=5433 PGUSER=www-data PGPASSWORD=www-data -PGDATABASE=lux -PGSCHEMA=geov3 -PGSCHEMA_STATIC=geov3_static -PGOPTIONS=-c statement_timeout=30000 -GEOPORTAL_INTERNAL_URL=http://geoportal:8080 +PGSSLMODE=prefer + +# Use the mutualised print, ask Camptocamp to configure your project. +# PRINT_URL=https://mutualized-print.apps.openshift-ch-1.camptocamp.com/print/geoportailv3/ +# To use the internal print: PRINT_URL=http://print:8080/print/ -DEVSERVER_HOST=webpack-dev-server:8080 -REDIS_HOST=redis -REDIS_PORT=6379 -C2C_REDIS_URL=redis://redis:6379 + +TILEGENERATION_SQS_QUEUE= +TILEGENERATION_S3_BUCKET= + +# For production +# FRONT_INNER_PORT=80 +# FRONT_CONFIG=haproxy +# For development (front in https) +FRONT_INNER_PORT=443 +FRONT_CONFIG=haproxy_dev + +C2C_SECRET=c2crulez + +DB_ECADASTRE=postgresql://172.17.0.1:5433/dummy +DB_MYMAPS=postgresql://172.17.0.1:5433/lux +DB_PGROUTE=postgresql://172.17.0.1:5433/dummy +DB_POI=postgresql://172.17.0.1:5433/dummy + LDAP_PASSWD=test1234 LDAP_URL=ldap://ldap:389 LDAP_BIND=login=c2c,ou=portail,dc=act,dc=lu LDAP_FILTER_TMPL=(login=%%(login)s) + SHORTENER_BASE_URL=http://localhost:8080/s/ SHORTENER_ALLOWED_HOST=localhost + ELASTIC_SERVERS=elasticsearch:9200 ELASTIC_INDEX=index # Guillaume's routing keys diff --git a/geoportailv3_geoportal b/geoportailv3_geoportal new file mode 120000 index 000000000..3635bf639 --- /dev/null +++ b/geoportailv3_geoportal @@ -0,0 +1 @@ +geoportal/geoportailv3_geoportal/ \ No newline at end of file diff --git a/geoportal/.dockerignore b/geoportal/.dockerignore index 7a4a0df36..09c6f06dc 100644 --- a/geoportal/.dockerignore +++ b/geoportal/.dockerignore @@ -1,31 +1,5 @@ -* -!*_requirements.txt -!package.json -!alembic.ini -!webpack.apps.js -!webpack.config.js -!config.yaml -!CONST_config-schema.yaml -!alembic.yaml -!production.ini -!ng_locale_downloader.sh -!generate_i18n.sh -!development.ini -!setup.cfg -!setup.py -!geoportailv3_geoportal -!LUX_alembic -!c2cgeoportal/commons -!c2cgeoportal/geoportal -!c2cgeoportal/admin -!.tx -!lingua-client.cfg -!lingua-server.cfg -!lingua-tooltips.cfg -!lingua-legends.cfg -!print-config.yaml.tmpl -!fix-db.sh -!tools -!jsapi -!bin/* -!alembic_upgrade_heads.sh +Dockerfile +vars*.yaml +CONST_vars.yaml +CONST_config-schema.yaml +geoportailv3_geoportal/static diff --git a/geoportal/.eslintrc b/geoportal/.eslintrc index 301bd74f4..8f145b91c 100644 --- a/geoportal/.eslintrc +++ b/geoportal/.eslintrc @@ -1,12 +1,19 @@ -extends: /usr/lib/node_modules/ngeo/.eslintrc.yaml +extends: + - openlayers globals: 'geoportailv3': false - 'olcs': false - 'JSZip': false - 'Fuse': false +env: + jquery: true +parserOptions: + ecmaVersion: 2017 rules: - 'prefer-arrow-callback': 0 - 'indent': 0 - 'no-var': 0 - 'prefer-template': 0 - 'prefer-const': 0 + no-console: 0 + comma-dangle: 0 + import/no-unresolved: 0 + valid-jsdoc: 0 + max-len: + - error + - code: 110 + ignoreComments: true + prettier/prettier: 0 + sort-imports-es6-autofix/sort-imports-es6: 0 diff --git a/geoportal/CONST_Makefile b/geoportal/CONST_Makefile new file mode 100644 index 000000000..47c375314 --- /dev/null +++ b/geoportal/CONST_Makefile @@ -0,0 +1,135 @@ +export PACKAGE = geoportailv3 + +TEMPLATE_EXCLUDE += $(PACKAGE)_geoportal/static/lib +FIND_OPTS = $(foreach ELEM, $(TEMPLATE_EXCLUDE),-path ./$(ELEM) -prune -o) -type f + +ifneq ($(NGEO_INTERFACES), "") +DEFAULT_WEB_RULE += $(NGEO_OUTPUT_FILES) +endif +#ifneq ($(NGEO_API), "") +#DEFAULT_WEB_RULE += $(NGEO_API_OUTPUT_FILES) +#endif + +MO_FILES ?= $(addprefix geoportailv3_geoportal/locale/,$(addsuffix /LC_MESSAGES/geoportailv3_geoportal-client.mo, $(LANGUAGES))) + +WEB_RULE ?= $(DEFAULT_WEB_RULE) + +DEFAULT_BUILD_RULES ?= $(WEB_RULE) \ + alembic.ini \ + alembic.yaml \ + build-api \ + $(MO_FILES) + + +# Make rules +BUILD_RULES ?= $(filter-out $(DISABLE_BUILD_RULES),$(DEFAULT_BUILD_RULES)) + +OUTPUT_DIR = $(PACKAGE)_geoportal/static/build + +# ngeo +NODE_ENV ?= production +export NODE_ENV +NO_DEV_SERVER ?= TRUE +export NO_DEV_SERVER +APP_OUTPUT_DIR = /etc/static-ngeo +GCC_JS_FILES = $(shell find /usr/lib/node_modules/openlayers/src/ol /usr/lib/node_modules/ngeo/src /usr/lib/node_modules/ol-cesium/src -type f -name '*.js' 2> /dev/null) +APP_JS_FILES = $(shell find $(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.js' 2> /dev/null) +HTML_FILES += $(shell find $(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.html' 2> /dev/null) +SASS_FILES += $(shell find $(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.scss' 2> /dev/null) +CSS_FILES += $(shell find $(PACKAGE)_geoportal/static-ngeo/js -type f -name '*.css' 2> /dev/null) +ANGULAR_LOCALES_FILES = $(addprefix $(APP_OUTPUT_DIR)/angular-locale_, $(addsuffix .js, $(LANGUAGES))) +NGEO_OUTPUT_FILES = $(ANGULAR_LOCALES_FILES) + +NGEO_API_OUTPUT_JS_FILE ?= $(APP_OUTPUT_DIR)/api.js.tmpl +NGEO_API_OUTPUT_FILES += $(NGEO_API_OUTPUT_JS_FILE) $(APP_OUTPUT_DIR)/api.css + + +ifdef CI +WEBPACK_ARGS ?= --debug +else +WEBPACK_ARGS ?= --progress --debug +endif + +VALIDATE_PY_FOLDERS = admin/$(PACKAGE)_admin \ + $(PACKAGE)_geoportal/*.py $(PACKAGE)_geoportal/lib \ + $(PACKAGE)_geoportal/scripts $(PACKAGE)_geoportal/views +VALIDATE_PY_TEST_FOLDERS = $(PACKAGE)_geoportal/tests + +PY_FILES = $(shell find $(PACKAGE) -type f -name '*.py' -print 2> /dev/null) + +# Templates + + +# Disabling Make built-in rules to speed up execution time +.SUFFIXES: + +.PHONY: build +build: $(BUILD_RULES) + +.PHONY: checks +checks: flake8 eslint + +.PHONY: flake8 +flake8: + flake8 $(PACKAGE) + +.PHONY: eslint +eslint: $(APP_JS_FILES) + eslint $? + +.PHONY: eslint-fix +eslint-fix: $(APP_JS_FILES) + eslint --fix $? + +# Server localisation + +.PRECIOUS: %.mo +%.mo: %.po + msgfmt -o $@ $< + +# ngeo + +.PHONY: build-ngeo +build-ngeo: $(NGEO_OUTPUT_FILES) + +$(APP_OUTPUT_DIR)/angular-locale_%.js: /usr/lib/node_modules/ngeo/package.json language_mapping + mkdir --parent $(dir $@) + rm --force $@ + cp /opt/angular-locale/angular-locale_`(grep $* language_mapping || echo $*) | cut --delimiter = --fields 2 | tr --delete '\r\n'`.js $@ + +$(APP_OUTPUT_DIR)/images/: /usr/lib/node_modules/jquery-ui/themes/base/images + mkdir --parent $@ + cp -r $ /etc/apt/sources.list.d/nodesource.list && \ - curl --silent https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes --no-install-recommends \ - nodejs && \ - apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes --no-install-recommends \ - ghostscript \ - libgs-dev \ - imagemagick && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN sed -i 's/rights="none" pattern="PDF"/rights="read" pattern="PDF"/g' /etc/ImageMagick-6/policy.xml - WORKDIR /app +RUN mv /etc/apt/sources.list.d/nodesource.list /etc/apt/sources.list.d/nodesource.list.disabled +RUN apt-get update +RUN apt-get -y upgrade +RUN apt-get install -y ca-certificates +RUN mv /etc/apt/sources.list.d/nodesource.list.disabled /etc/apt/sources.list.d/nodesource.list +RUN apt update && apt-get install libgnutls30 +RUN apt update && apt install git -y && apt-get dist-upgrade -y +COPY package.json /app +RUN npm set progress=false && \ + npm-packages --src=/app/package.json --dst=/tmp/npm-packages && \ + npm install --no-optional --global --unsafe-perm --no-package-lock `cat /tmp/npm-packages` && \ + npm cache clear --force -# Install python dependencies -RUN \ - curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && \ - python3 get-pip.py pip==19.0.3 wheel==0.33.1 setuptools==40.8.0 - -COPY upstream_requirements.txt /app/ -RUN pip install --disable-pip-version-check --no-cache-dir --requirement upstream_requirements.txt - -COPY luxembourg_requirements.txt /app/ -RUN pip install --disable-pip-version-check --no-cache-dir --requirement luxembourg_requirements.txt - -COPY setup.py /app/ -RUN \ - python3 setup.py install && \ - # for mypy - touch /usr/local/lib/python3.6/dist-packages/zope/__init__.py && \ - touch /usr/local/lib/python3.6/dist-packages/c2c/__init__.py && \ - rm --recursive --force /tmp/* /var/tmp/* /root/.cache/* - - -COPY bin/* /usr/bin/ +COPY webpack.*.js Makefile CONST_Makefile /app/ +COPY geoportailv3_geoportal/static-ngeo /app/geoportailv3_geoportal/static-ngeo +RUN rm -rf /usr/lib/node_modules/ngeo +RUN mv /app/geoportailv3_geoportal/static-ngeo/ngeo /usr/lib/node_modules/ngeo -RUN mkdir -p /app/geoportailv3_geoportal/admin -COPY geoportailv3_geoportal/admin/package.json /app/geoportailv3_geoportal/admin -RUN cd /app/geoportailv3_geoportal/admin && npm install --global && npm cache clear --force +COPY . /app -COPY package.json /app +# jsapi generation +ADD ./jsapi /etc/apiv3/ +WORKDIR /etc/apiv3 +RUN node --version RUN npm install --no-optional && npm cache clear --force +RUN /etc/apiv3/rebuild_api.sh - -# jsapi generation -RUN mkdir /app/apiv3 -WORKDIR /app/apiv3 -RUN mkdir -p /app/apiv3/.build/externs -RUN wget -O /app/apiv3/.build/externs/angular-1.6.js https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/angular-1.6.js +WORKDIR /app +# sad fix, to allow webpack's file-loader to find files with query string & hash added +RUN ln -s /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.eot?#iefix && \ + ln -s /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.svg#fontawesome && \ + ln -s /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.eot?#iefix && \ + ln -s /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg /usr/lib/node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.svg#fontawesome -RUN wget -O /app/apiv3/.build/externs/angular-1.6-q_templated.js https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/angular-1.6-q_templated.js +# RUN make checks +RUN make build +RUN make apps +RUN mv webpack.apps.js webpack.apps.js.tmpl +# put Cesium build in static-ngeo +RUN mkdir /etc/static-ngeo/Cesium && cp -r /usr/lib/node_modules/cesium/Build/Cesium/* /etc/static-ngeo/Cesium/ +ENTRYPOINT [ "/usr/bin/eval-templates" ] +CMD [ "webpack-dev-server", "--mode=development", "--debug", "--watch", "--progress", "--no-inline" ] -RUN wget -O /app/apiv3/.build/externs/angular-1.6-http-promise_templated.js https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/angular-1.6-http-promise_templated.js +############################################################################### +FROM camptocamp/geomapfish:2.5 as runner -RUN wget -O /app/apiv3/.build/externs/jquery-1.9.js https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/jquery-1.9.js -COPY ./jsapi/package.json /app/apiv3/ -RUN npm install --no-optional && npm cache clear --force - -WORKDIR /app +ARG HTTP_PROXY_URL +ENV http_proxy $HTTP_PROXY_URL +ARG HTTPS_PROXY_URL +ENV https_proxy $HTTPS_PROXY_URL +RUN mv /etc/apt/sources.list.d/nodesource.list /etc/apt/sources.list.d/nodesource.list.disabled +RUN apt-get update +RUN apt-get -y upgrade +RUN apt-get install -y ca-certificates +RUN mv /etc/apt/sources.list.d/nodesource.list.disabled /etc/apt/sources.list.d/nodesource.list +RUN apt update && apt install vim -y +RUN apt-get update && \ + DEBIAN_FRONTEND=noninteractive apt-get install --assume-yes --no-install-recommends \ + ghostscript \ + libgs-dev \ + imagemagick \ + gdal-bin \ + libgdal-dev \ + build-essential \ + python3.7-dev && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* +RUN sed -i 's/rights="none" pattern="PDF"/rights="read" pattern="PDF"/g' /etc/ImageMagick-6/policy.xml +ENV CPLUS_INCLUDE_PATH=/usr/include/gdal +ENV C_INCLUDE_PATH=/usr/include/gdal +COPY luxembourg_requirements.txt /tmp/requirements.txt RUN \ - node_modules/.bin/svg2ttf node_modules/ngeo/contribs/gmf/fonts/gmf-icons.svg \ - node_modules/ngeo/contribs/gmf/fonts/gmf-icons.ttf && \ - node_modules/.bin/ttf2eot node_modules/ngeo/contribs/gmf/fonts/gmf-icons.ttf \ - node_modules/ngeo/contribs/gmf/fonts/gmf-icons.eot && \ - node_modules/.bin/ttf2woff node_modules/ngeo/contribs/gmf/fonts/gmf-icons.ttf \ - node_modules/ngeo/contribs/gmf/fonts/gmf-icons.woff - -COPY ./ng_locale_downloader.sh /app -RUN \ - mkdir --parents /opt/angular-locale && \ - for LANG in en de fr lb; \ - do \ - ./ng_locale_downloader.sh $LANG; \ - done && \ - adduser www-data root - - -RUN mkdir -p /app/geoportailv3_geoportal -COPY ./geoportailv3_geoportal/static-ngeo/ /app/geoportailv3_geoportal/static-ngeo/ -COPY ./webpack.apps.js ./webpack.config.js /app/ -#RUN INTERFACE=main NODE_ENV=development node_modules/.bin/webpack --mode=development --debug -RUN INTERFACE=main NODE_ENV=production node_modules/.bin/webpack --mode=production --debug + python3 -m pip install --upgrade pip && \ + python3 -m pip install setuptools==50.3.2 && \ + python3 -m pip install --disable-pip-version-check --no-cache-dir --requirement=/tmp/requirements.txt && \ + rm --recursive --force /tmp/* /var/tmp/* /root/.cache/* +WORKDIR /app COPY . /app +COPY --chown=www-data:www-data --from=builder /app/geoportailv3_geoportal/locale/ /app/geoportailv3_geoportal/locale/ +#COPY --chown=www-data:www-data --from=builder /usr/lib/node_modules/ngeo/dist/* /etc/static-ngeo/ +COPY --chown=www-data:www-data --from=builder /etc/static-ngeo/ /etc/static-ngeo/ +COPY --chown=www-data:www-data --from=builder /etc/static-ngeo/build/ /etc/static-ngeo/d7c6c320f7be4834954b8bf063492442/build/ +COPY --chown=www-data:www-data --from=builder /etc/static-ngeo/build/ /etc/static-ngeo/4742262ea36e4a48827009c4d591e875/build/ +COPY --chown=www-data:www-data --from=builder /etc/static-ngeo/build/ /etc/static-ngeo/not_used/build/ +COPY --chown=www-data:www-data --from=builder /etc/static-ngeo/build/ /etc/static-ngeo/NO_CACHE/build/ + +#COPY --from=builder /etc/apiv3/* /etc/apiv3/ +RUN mkdir -p /app/geoportailv3_geoportal/jsapi/build/ +COPY --from=builder /app/geoportailv3_geoportal/jsapi/build/apidoc /app/geoportailv3_geoportal/jsapi/build/apidoc +COPY --from=builder /app/geoportailv3_geoportal/jsapi/webfonts /app/geoportailv3_geoportal/jsapi/webfonts +COPY --chown=www-data:www-data --from=builder /app/alembic.ini /app/alembic.yaml ./ + +#RUN chmod go+w /etc/static-ngeo/ \ +# /app/geoportailv3_geoportal/locale/ \ +# /app/geoportailv3_geoportal/locale/*/LC_MESSAGES/geoportailv3_geoportal-client.po -RUN cd /app/geoportailv3_geoportal/static-ngeo && ln -s ../../node_modules - -RUN ./generate_i18n.sh - -RUN pykwalify --data-file config.yaml --schema-file CONST_config-schema.yaml - -RUN \ - ls -1 geoportailv3_geoportal/static-ngeo/build/*.html|while read file; do mv ${file} ${file}.tmpl; done && \ - ls -1 geoportailv3_geoportal/static-ngeo/build/*.css|while read file; do mv ${file} ${file}.tmpl; done +RUN pip install --disable-pip-version-check --no-cache-dir --editable=/app/ && \ + python3 -m compileall -q /usr/local/lib/python3.7 \ + -x '/usr/local/lib/python3.7/dist-packages/(pydevd|ptvsd|pipenv)/' && \ + python3 -m compileall -q /app/geoportailv3_geoportal -x /app/geoportailv3_geoportal/static.* -# For webpack-dev server -RUN mv webpack.apps.js webpack.apps.js.tmpl +COPY ./bin/eval-templates /usr/bin/ ARG GIT_HASH +RUN c2cwsgiutils_genversion.py ${GIT_HASH} -RUN pip install --disable-pip-version-check --no-cache-dir --editable=/app/ && \ - python3 -m compileall -q /app/geoportailv3_geoportal -x /app/geoportailv3_geoportal/static.* && \ - c2cwsgiutils_genversion.py $GIT_HASH +ARG PGSCHEMA +ENV PGSCHEMA=${PGSCHEMA} -COPY ./tools/ /app/tools -RUN ln -s . geoportal - -WORKDIR /app/apiv3 -ADD ./jsapi /app/apiv3/jsapi -RUN /app/apiv3/jsapi/rebuild_api.sh -WORKDIR /app -ENTRYPOINT ["/usr/bin/eval-templates" ] +ENTRYPOINT [ "/usr/bin/eval-templates" ] CMD ["c2cwsgiutils_run"] +RUN ln -s . geoportal +ENV VISIBLE_ENTRY_POINT=/ \ + AUTHTKT_TIMEOUT=86400 \ + AUTHTKT_REISSUE_TIME=9000 \ + AUTHTKT_MAXAGE=86400 \ + AUTHTKT_COOKIENAME=auth_tkt \ + AUTHTKT_HTTP_ONLY=True \ + AUTHTKT_SECURE=True \ + AUTHTKT_SAMESITE=Lax \ + BASICAUTH=False \ + LOG_LEVEL=INFO \ + C2CGEOPORTAL_LOG_LEVEL=INFO \ + C2CWSGIUTILS_LOG_LEVEL=INFO \ + GUNICORN_LOG_LEVEL=INFO \ + SQL_LOG_LEVEL=WARN \ + DOGPILECACHE_LOG_LEVEL=INFO \ + OTHER_LOG_LEVEL=WARN diff --git a/geoportal/LUX_alembic/versions/1cb8168b89d8_finalize_c2c_23_upgrade.py b/geoportal/LUX_alembic/versions/1cb8168b89d8_finalize_c2c_23_upgrade.py index edf753747..e1cf82614 100644 --- a/geoportal/LUX_alembic/versions/1cb8168b89d8_finalize_c2c_23_upgrade.py +++ b/geoportal/LUX_alembic/versions/1cb8168b89d8_finalize_c2c_23_upgrade.py @@ -35,7 +35,6 @@ """ from alembic import op -from c2cgeoportal_commons.config import config # revision identifiers, used by Alembic. revision = '1cb8168b89d8' diff --git a/geoportal/LUX_alembic/versions/6f66f0579702_set_url_to_config_wmsproxy_in_ogcserver_.py b/geoportal/LUX_alembic/versions/6f66f0579702_set_url_to_config_wmsproxy_in_ogcserver_.py new file mode 100644 index 000000000..2ecad2aca --- /dev/null +++ b/geoportal/LUX_alembic/versions/6f66f0579702_set_url_to_config_wmsproxy_in_ogcserver_.py @@ -0,0 +1,27 @@ +"""Set url to config://wmsproxy in OGCServer Internal WMS + +Revision ID: 6f66f0579702 +Revises: 19e97a222003 +Create Date: 2020-10-28 16:59:09.383314 +""" + +from alembic import op + +# revision identifiers, used by Alembic. +revision = '6f66f0579702' +down_revision = '19e97a222003' +branch_labels = None +depends_on = None + + +def upgrade(): + # OGCServer needs an real URL + op.execute( + "UPDATE geov3.ogc_server SET url = 'config://proxywms' WHERE url = '';" + ) + + +def downgrade(): + op.execute( + "UPDATE geov3.ogc_server SET url = '' WHERE url = 'config://proxywms';" + ) diff --git a/geoportal/Makefile b/geoportal/Makefile new file mode 100644 index 000000000..6b9ffdb24 --- /dev/null +++ b/geoportal/Makefile @@ -0,0 +1,10 @@ +# Language provided by the application +LANGUAGES ?= en fr de lb +NGEO_INTERFACES ?= main +NGEO_API ?= "" +CI ?= TRUE +DISABLE_BUILD_RULES = build-api + +MO_FILES = $(foreach I18_TYPE, client server tooltips legends, $(addprefix geoportailv3_geoportal/locale/,$(addsuffix /LC_MESSAGES/geoportailv3_geoportal-$(I18_TYPE).mo, $(LANGUAGES)))) + +include CONST_Makefile diff --git a/geoportal/alembic.ini b/geoportal/alembic.ini index a39288cc1..7465ace70 100644 --- a/geoportal/alembic.ini +++ b/geoportal/alembic.ini @@ -1,15 +1,19 @@ [DEFAULT] app.cfg = %(here)s/alembic.yaml -script_location = c2cgeoportal_commons:alembic +script_location = /opt/alembic version_table = alembic_version [main] type = main -version_locations = c2cgeoportal_commons:alembic/main/ +version_locations = /opt/alembic/main/ [static] type = static -version_locations = c2cgeoportal_commons:alembic/static/ +version_locations = /opt/alembic/static/ + +[getitfixed] +script_location = getitfixed:alembic +version_locations = getitfixed:alembic/versions/ [lux] type = main @@ -22,7 +26,8 @@ schema = geov3 keys = root,sqlalchemy,alembic [handlers] -keys = console +keys = console, json +handlers = %(LOG_TYPE)s [formatters] keys = generic @@ -48,6 +53,11 @@ args = (sys.stderr,) level = NOTSET formatter = generic +[handler_json] +class = c2cwsgiutils.pyramid_logging.JsonLogHandler +args = (sys.stdout,) +level = NOTSET + [formatter_generic] format = %(levelname)-5.5s [%(name)s] %(message)s datefmt = %H:%M:%S diff --git a/geoportal/alembic.yaml b/geoportal/alembic.yaml index 975574f7c..b7aa77944 100644 --- a/geoportal/alembic.yaml +++ b/geoportal/alembic.yaml @@ -1,36 +1,19 @@ -environment: -- {default: localhost, name: VISIBLE_WEB_HOST} -- {default: https, name: VISIBLE_WEB_PROTOCOL} -- {default: /, name: VISIBLE_ENTRY_POINT} -- {name: PGHOST} -- {name: PGHOST_SLAVE} -- {default: '5432', name: PGPORT} -- {name: PGUSER} -- {name: PGPASSWORD} -- {default: geomapfish, name: PGDATABASE} -- {default: main, name: PGSCHEMA} -- {default: main_static, name: PGSCHEMA_STATIC} -- {default: 'http://tinyows:8080/', name: TINYOWS_URL} -- {default: 'http://mapserver:8080/', name: MAPSERVER_URL} -- {default: 'http://print:8080/print/', name: PRINT_URL} -- {default: 'http://mapcache:8080/', name: MAPCACHE_URL} -- {default: 'webpack-dev-server:8080', name: DEVSERVER_HOST} -- {default: redis, name: REDIS_HOST} -- {default: '6372', name: REDIS_PORT} -- {default: memcached, name: MEMCACHED_HOST} -- {default: '11211', name: MEMCACHED_PORT} -- {default: queue_name, name: TILEGENERATION_SQS_QUEUE} -interpreted: {} -no_interpreted: [] -postprocess: -- expression: int({}) - vars: [cache.arguments.port] +--- vars: - cache: - arguments: {db: 0, distributed_lock: true, host: '{REDIS_HOST}', port: '{REDIS_PORT}', - redis_expiration_time: 86400} - backend: dogpile.cache.redis - schema: geov3 + schema: '{PGSCHEMA}' schema_static: '{PGSCHEMA_STATIC}' - sqlalchemy.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE} - srid: 2169 + sqlalchemy.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE}?sslmode={PGSSLMODE} + srid: 2056 +environment: + - name: PGHOST + - name: PGPORT + default: '5432' + - name: PGUSER + - name: PGPASSWORD + - name: PGDATABASE + - name: PGSSLMODE + default: prefer + - name: PGSCHEMA + default: main + - name: PGSCHEMA_STATIC + default: main_static diff --git a/geoportal/bin/alembic_upgrade_all.sh b/geoportal/bin/alembic_upgrade_all.sh index 8c6c3890d..450fcc4c7 100755 --- a/geoportal/bin/alembic_upgrade_all.sh +++ b/geoportal/bin/alembic_upgrade_all.sh @@ -1,4 +1,4 @@ #!/bin/bash -ex alembic --name=main upgrade head; alembic --name=static upgrade head; -alembic --name=lux upgrade head; +alembic --name=lux upgrade heads; diff --git a/geoportal/bin/eval-templates b/geoportal/bin/eval-templates index 18bfda5b1..9b6dcb5a5 100755 --- a/geoportal/bin/eval-templates +++ b/geoportal/bin/eval-templates @@ -1,11 +1,52 @@ -#!/bin/bash -e +#!/bin/bash -eu -export DOLLAR=$ +export CACHE_VERSION=$RANDOM -find /app/ -name '*.tmpl' -print |grep -v jsdoc| grep -v node_modules | while read file +function evaluate { + file=$1 + echo "Evaluate: ${file}" + DOLLAR=$ envsubst < ${file} > ${file%.tmpl} + if [ `id -u` == 0 ] + then + chmod --reference=${file} ${file%.tmpl} + chown --reference=${file} ${file%.tmpl} + fi +} + +if [ "${TEST}" == true ] +then + find /opt/c2cgeoportal/ -name '*.tmpl' -print | grep -v jsdoc | grep -v node_modules | while read file + do + evaluate $file + done +fi + +find /app/ -name '*.tmpl' -print | grep -v jsdoc | grep -v node_modules | while read file +do + evaluate $file +done + +find /etc/static-ngeo/ -name '*.tmpl' -print | grep -v jsdoc | grep -v node_modules | while read file +do + evaluate $file +done + +find /etc/static-ngeo/ \( -name '*.js' -or -name '*.css' -or -name '*.html' \) -print | while read file do echo "Evaluate: ${file}" - envsubst < ${file} > ${file%.tmpl} + sed --in-place --expression="s#\.__ENTRY_POINT__#${VISIBLE_ENTRY_POINT}#g" "${file}" done exec "$@" + +# #!/bin/bash -e + +# export DOLLAR=$ + +# find /app/ -name '*.tmpl' -print | grep -v jsdoc| grep -v node_modules | while read file +# do +# echo "Evaluate: ${file}" +# envsubst < ${file} > ${file%.tmpl} +# done + +# exec "$@" diff --git a/geoportal/config.yaml b/geoportal/config.yaml deleted file mode 100644 index 123617f6f..000000000 --- a/geoportal/config.yaml +++ /dev/null @@ -1,508 +0,0 @@ -environment: -- {default: 'ou=portail,dc=act,dc=lu', name: LDAP_BASE_DN} -- {default: 'cn=system,dc=act,dc=lu', name: LDAP_BIND} -- {default: to_be_defined, name: LDAP_PASSWD} -- {default: 'ldap://willie.geoportal.lu:3890', name: LDAP_URL} -- {name: LDAP_FILTER_TMPL} -- {default: localhost, name: VISIBLE_WEB_HOST} -- {default: https, name: VISIBLE_WEB_PROTOCOL} -- {default: /, name: VISIBLE_ENTRY_POINT} -- {default: '999', name: DEFAULT_MYMAPS_ROLE} -- {name: AUTHTKT_SECURE} -- {name: AUTHTKT_SECRET} -- {name: ARCGIS_TOKEN_URL} -- {name: ARCGIS_TOKEN_VALIDITY} -- {name: ARCGIS_TOKEN_REFERER} -- {name: ARCGIS_USER} -- {name: ARCGIS_PASS} -- {name: DB_MYMAPS} -- {name: DB_PGROUTE} -- {name: DB_ECADASTRE} -- {name: DB_POI} -- {name: PGHOST} -- {name: PGHOST_SLAVE} -- {default: '5432', name: PGPORT} -- {name: PGUSER} -- {name: PGPASSWORD} -- {default: geomapfish, name: PGDATABASE} -- {default: main, name: PGSCHEMA} -- {default: main_static, name: PGSCHEMA_STATIC} -- {default: 'http://tinyows:8080/', name: TINYOWS_URL} -- {default: 'http://mapserver:8080/', name: MAPSERVER_URL} -- {default: 'http://print:8080/print/', name: PRINT_URL} -- {default: 'http://mapcache:8080/', name: MAPCACHE_URL} -- {default: 'webpack-dev-server:8080', name: DEVSERVER_HOST} -- {default: redis, name: REDIS_HOST} -- {default: '6372', name: REDIS_PORT} -- {default: memcached, name: MEMCACHED_HOST} -- {default: '11211', name: MEMCACHED_PORT} -- {default: queue_name, name: TILEGENERATION_SQS_QUEUE} -- {default: /var/sig/bt.shp, name: DHM_DEM_FILE} -- {default: shp_index, name: DHM_DEM_TYPE} -- {name: SHORTENER_ALLOWED_HOST} -- {name: SHORTENER_BASE_URL} -- {name: ELASTIC_SERVERS} -- {name: ELASTIC_INDEX} -- {name: ANF_MAP_ID} -- {name: ANF_EMAIL} -- {name: AGE_CRUES_EMAIL, default: ''} -- {name: AGE_CRUES_MAP_ID, default: ''} -- {name: AGE_CRUES_SHOW_LINK, default: 'false'} -- {name: AGE_CRUES_LAYERS, default: ''} -- {name: AGE_CRUES_ROLES, default: ''} -- {name: AGE_EMAIL, default: ''} -- {name: AGE_MAP_IDS, default: ''} -- {name: AGE_SHOW_LINK, default: 'false'} -- {name: AGE_LAYERS, default: ''} -- {default: null, name: ROUTING_GRAPHHOPPER_API_KEY} -- {default: null, name: ROUTING_MAPQUEST_API_KEY} -- {name: HTTPS_PROXY_UNAUTHORIZED_IPS, default: '10.0.0.0/8, 127.0.0.1'} -- {name: HTTPS_PROXY_AUTHORIZED_HOSTS, default: 'ws.geoportal.lu, ws.geoportail.lu, wms.inspire.geoportail.lu, wms.inspire.geoportal.lu, wmts1.geoportail.lu, wmts1.geoportal.lu'} -- {name: REVERSE_GEOCODE_API_KEY, default: ''} -- {name: REVERSE_GEOCODE_URL, default: 'http://open.mapquestapi.com/nominatim/v1/reverse.php'} -- {name: PAG_STAGING_URL} -- {name: PAG_PROD_URL} -- {name: PAG_FME_TOKEN} -- {name: PAG_OWNCLOUD_INTERNAL_URL} -- {name: PAG_OWNCLOUD_EXTERNAL_URL} -- {name: PAG_OWNCLOUD_USER} -- {name: PAG_OWNCLOUD_PASSWORD} -- {name: PAG_SMTP_SERVER} -- {name: PAG_BCC_ADDRESS} -- {name: PAG_FILE_SERVER} -- {name: PDS_STAGING_URL} -- {name: PDS_PROD_URL} -- {name: PDS_SMTP_SERVER} -- {name: PDS_BCC_ADDRESS} -- {name: CASIPO_STAGING_URL} -- {name: CASIPO_PROD_URL} -- {name: CASIPO_FME_TOKEN} -- {name: CASIPO_OWNCLOUD_INTERNAL_URL} -- {name: CASIPO_OWNCLOUD_EXTERNAL_URL} -- {name: CASIPO_OWNCLOUD_USER} -- {name: CASIPO_OWNCLOUD_PASSWORD} -- {name: CASIPO_SMTP_SERVER} -- {name: CASIPO_BCC_ADDRESS} -- {name: AUTHTKT_TIMEOUT} -- {name: PROXYWMSURL, default: 'https://wmsproxy.geoportail.lu/ogcproxywms'} -- {name: GEONETWORK_BASE_URL, default: 'https://geocatalogue.geoportail.lu/geonetwork/srv'} -- {name: WMTSURL, default: ''} -interpreted: {} -no_interpreted: [] -postprocess: -- expression: int({}) - vars: [cache.arguments.port] -vars: - admin_interface: - available_functionalities: [default_basemap, default_theme, print_template, mapserver_substitution, - filterable_layers, preset_layer_filter, open_panel] - available_metadata: - - {name: is_expanded, type: boolean} - - {name: linked_layers} - - {name: service_metadata_id} - - {name: dataportaldatasetid} - - {name: attribution} - - {name: bg_layer} - - {name: bg_opacity, type: float} - - {name: css} - - {name: display_in_switcher, type: boolean} - - {name: exclusion} - - {name: fake_scales, type: list} - - {name: hasRetina, type: boolean} - - {name: is_queryable, type: boolean} - - {name: legend_name} - - {name: link, type: url} - - {name: link_title} - - {name: max_dpi, type: float} - - {name: metadata_id} - - {name: ogc_info_format} - - {name: ogc_info_srs} - - {name: ogc_query_layers} - - {name: page_title} - - {name: print_img} - - {name: print_long_txt_de} - - {name: print_long_txt_en} - - {name: print_long_txt_fr} - - {name: print_long_txt_lu} - - {name: print_scales, type: list} - - {name: print_short_txt_de} - - {name: print_short_txt_en} - - {name: print_short_txt_fr} - - {name: print_short_txt_lu} - - {name: resolutions, type: list} - - {name: show_in_mobile, type: boolean} - - {name: start_layers, type: list} - - {name: start_opacity, type: float} - - {name: start_x, type: float} - - {name: start_y, type: float} - - {name: start_zoom, type: float} - layer_tree_max_nodes: 1000 - map_x: 740000 - map_y: 5860000 - map_zoom: 10 - authorized_ips: null - authorized_referers: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}/'] - available_locale_names: [en, de, fr, lb] - c2c.base_path: /c2c - cache: - arguments: {db: 0, distributed_lock: true, host: '{REDIS_HOST}', port: '{REDIS_PORT}', - redis_expiration_time: 86400} - backend: dogpile.cache.redis - pds: - staging_url: '{PDS_STAGING_URL}' - prod_url: '{PDS_PROD_URL}' - fme_token: - owncloud_internal_url: - owncloud_external_url: - owncloud_user: - owncloud_password: - smtp_server: '{PDS_SMTP_SERVER}' - bcc_address: '{PDS_BCC_ADDRESS}' - casipo: {bcc_address: '{CASIPO_BCC_ADDRESS}', fme_token: '{CASIPO_FME_TOKEN}', owncloud_external_url: '{CASIPO_OWNCLOUD_EXTERNAL_URL}', owncloud_internal_url: '{CASIPO_OWNCLOUD_INTERNAL_URL}', - owncloud_password: '{CASIPO_OWNCLOUD_PASSWORD}', owncloud_user: '{CASIPO_OWNCLOUD_USER}', prod_url: '{CASIPO_PROD_URL}', smtp_server: '{CASIPO_SMTP_SERVER}', - staging_url: '{CASIPO_STAGING_URL}'} - check_collector: - hosts: - - {display: Main, url: '{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}{VISIBLE_ENTRY_POINT}'} - level: 10 - max_level: 1 - checker: - fulltextsearch: {level: 1, search: bat} - lang: - files: [ngeo, cgxp-api] - level: 1 - phantomjs: - disable: [] - routes: - - level: 3 - name: desktop - params: {no_redirect: 'true'} - - level: 3 - name: mobile - params: {no_redirect: 'true'} - print: - level: 3 - spec: - attributes: - description: Carte exemple - legend: {} - map: - bbox: [668126, 6368118, 689717, 6389761] - dpi: 128 - layers: [] - projection: EPSG:3857 - rotation: 0 - name: Exemple - qrimage: http://dev.geoportail.lu/shorten/qr?url=http://g-o.lu/0mf4r - scale: 60000 - scalebar: {projection: 'EPSG:2169'} - url: http://g-o.lu/0mf4r - layout: A4 portrait - outputFormat: pdf - routes: - disable: [] - routes: - - {level: 3, name: apijs} - - {level: 3, name: xapijs} - - {level: 3, name: printproxy_capabilities} - - display_name: mapserverproxy_wms - level: 3 - name: mapserverproxy - params: {REQUEST: GetCapabilities, SERVICE: WMS, VERSION: 1.1.1} - - display_name: mapserverproxy_wfs - level: 3 - name: mapserverproxy - params: {REQUEST: GetCapabilities, SERVICE: WFS, VERSION: 1.1.0} - themes: - interfaces: {} - level: 1 - params: {version: '2'} - db_chooser: - master: [GET /short/.*] - slave: [\w+ /printproxy/.*] - dbsessions: - db_ecadastre: {url: '{DB_ECADASTRE}'} - ecadastre: {url: '{DB_ECADASTRE}'} - mymaps: {url: '{DB_MYMAPS}'} - pgroute: {url: '{DB_PGROUTE}'} - poi: {url: '{DB_POI}'} - default_interface: main - default_locale_name: fr - default_max_age: 864000 - devserver_url: http://{DEVSERVER_HOST}{VISIBLE_ENTRY_POINT} - enable_admin_interface: true - exclude_theme_layer_search: null - excluded_themes_from_search: API_ONLY - fulltextsearch: - defaultlimit: 30 - languages: {de: german, en: english, fr: french} - maxlimit: 200 - functionalities: - anonymous: - default_basemap: plan - default_theme: null - print_template: [1 A4 portrait, 2 A3 landscape] - available_in_templates: [ - default_basemap, default_theme, filterable_layers, print_template, - preset_layer_filter, open_panel] - registered: {} - global_headers: - - headers: { - Referrer-Policy: origin, - X-Content-Type-Options: nosniff - } - pattern: ^/apihelp.html - - headers: { - Content-Security-Policy: 'default-src ''self''; script-src ''self'' - ''unsafe-inline''; style-src ''self'' ''unsafe-inline''; img-src * data:; - worker-src ''self'' blob:', Referrer-Policy: same-origin} - pattern: ^/admin/.* - headers: - api: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - config: - access_control_allow_origin: [ - '{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - csvecho: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - echo: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - error: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - exportgpxkml: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - fulltextsearch: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - index: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - layers: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - login: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}'] - access_control_max_age: 600 - cache_control_max_age: 600 - mapserver: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - print: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - profile: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - raster: - access_control_allow_origin: ['*'] - access_control_max_age: 600 - cache_control_max_age: 600 - shortener: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - themes: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - tinyows: - access_control_allow_origin: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}', - '*'] - access_control_max_age: 600 - cache_control_max_age: 600 - hide_capabilities: false - hooks: {} - host: '{VISIBLE_WEB_HOST}' - host_forward_host: [] - poi_server: '' - https_proxy: - unauthorized_ips: '{HTTPS_PROXY_UNAUTHORIZED_IPS}' - authorized_hosts: '{HTTPS_PROXY_AUTHORIZED_HOSTS}' - interfaces: [main] - interfaces_config: - main: - tree_params: {version: '2', catalogue: 'true', min_levels: '1'} - constants: - appAuthtktCookieName: auth_tkt_main - appExcludeThemeLayerSearch: [] - appOverviewMapBaseLayer: basemap_2015_global - appOverviewMapShow: false - showAnfLink: false - showAgeLink: '{AGE_SHOW_LINK}' - showCruesLink: '{AGE_CRUES_SHOW_LINK}' - showCruesRoles: '{AGE_CRUES_ROLES}' - ageLayerIds: '{AGE_LAYERS}' - ageCruesLayerIds: '{AGE_CRUES_LAYERS}' - bboxLidar: [46602, 53725, 106944, 141219] - bboxSrsLidar: 'EPSG:2169' - defaultExtent: [425152.9429259216, 6324465.99999133, 914349.9239510496, 6507914.867875754] - defaultLang: en - defaultTheme: main - fulltextsearch_param: {} - gmfExternalOGCServers: [] - gmfSearchActions: [] - lidarDemoUrl: https://lidar.geoportail.lu - maxExtent: [2.6, 47.7, 8.6, 51] - remoteProxyWms: false - requestScheme: https - sentryUrl: '' - tags: {interface: main, service: js} - tiles3dLayers: - - name: wintermesh - show: true - - name: buildings25d - show: false - - name: buildings3d - show: false - - name: bridges3d - show: false - tiles3dUrl: https://3dtiles.geoportail.lu/3dtiles/ - proxyWmsUrl: '{PROXYWMSURL}' - geonetworkBaseUrl: '{GEONETWORK_BASE_URL}' - wmtsUrl: '{WMTSURL}' - fulltextsearch_params: { - assetsBaseUrl: 'geoportailv3_geoportal:static-ngeo/', - authenticationBaseUrl: base, fulltextsearchUrl: fulltextsearch, gmfLayersUrl: layers_root, - gmfProfileCsvUrl: profile.csv, gmfRasterUrl: raster, gmfShortenerCreateUrl: shortener_create, - limit: 30, - partitionlimit: 5 - } - routes: { - ping: ping, - arrowUrl: get_arrow_color, authenticationBaseUrl: base, casipoUrl: casipo_url, - cmsSearchServiceUrl: cmssearch, downloadmeasurementUrl: download_measurement, - downloadresourceUrl: download_resource, downloadsketchUrl: download_sketch, - echocsvUrl: echocsv, elevationServiceUrl: raster, exportgpxkmlUrl: exportgpxkml, - geocodingServiceUrl: geocode, getHtmlLegendUrl: get_html, getInfoServiceUrl: getfeatureinfo, - getPngLegendUrl: get_png, getRemoteTemplateServiceUrl: getremotetemplate, - getRouteUrl: getroute, getuserinfoUrl: getuserinfo, gmfLayersUrl: layers_root, - gmfPrintUrl: printproxy, gmfProfileCsvUrl: profile.csv, gmfProfileJsonUrl: profile.json, - gmfRasterUrl: raster, gmfShortenerCreateUrl: shortener_create, httpsProxyUrl: https_proxy, - isThemePrivateUrl: isthemeprivate, layerSearchServiceUrl: layersearch, loginUrl: login, - logoutUrl: logout, mymapsImageUrl: mymaps_image, mymapsMapsUrl: mymaps_getmaps, - mymapsUrl: mymaps, pagUrl: pag_url, pdsUrl: pds_url, poiSearchServiceUrl: fulltextsearch, - postFeedbackAnfUrl: feedbackanf, postFeedbackAgeUrl: feedbackage,postFeedbackCruesUrl: feedbackcrues, - postFeedbackUrl: feedback, predefinedWmsUrl: predefined_wms, previewMesurementUrl: preview_measurement, - printServiceUrl: printproxy, profileServiceUrl: profile.json, featureSearchServiceUrl: featuresearch, - qrServiceUrl: qr, reverseGeocodingServiceUrl: reverse_geocode, routingServiceUrl: getremoteroute, - shorturlServiceUrl: shortener_create, uploadvtstyleUrl: upload_vt_style, deletevtstyleUrl: delete_vt_style, - getvtstyleUrl: get_vt_style, downloadPdfUrl: download_pdf - } - static: { - appImagesPath: 'geoportailv3_geoportal:static-ngeo/images/', - appQueryTemplatesPath: 'geoportailv3_geoportal:static-ngeo/js/query/', - arrowModelUrl: 'geoportailv3_geoportal:static-ngeo/models/arrow5.glb', - assetsBaseUrl: 'geoportailv3_geoportal:static-ngeo/', - cesiumURL: 'geoportailv3_geoportal:static-ngeo/node_modules/cesium/Build/Cesium/Cesium.js' - } - wfs_permalink: - defaultFeatureNS: http://mapserver.gis.umn.edu/mapserver - defaultFeaturePrefix: feature - wfsTypes: - - {featureType: fuel, label: display_name} - - {featureType: osm_scale, label: display_name} - jsbuild: {config: /src/jsbuild/app.cfg, root_dir: /src} - layers: {geometry_validation: true} - ldap: { - base_dn: '{LDAP_BASE_DN}', - bind: '{LDAP_BIND}', - passwd: '{LDAP_PASSWD}', - filter_tmpl: '{LDAP_FILTER_TMPL}', - url: '{LDAP_URL}' - } - default_mymaps_role: '{DEFAULT_MYMAPS_ROLE}' - lidar: {demo_url: '', maxx: 81500, maxy: 108600, minx: 71500, miny: 98600, srs: 'EPSG:2169'} - lingua_extractor: {} - mailer: {message.encoding: UTF-8, transport.host: server-relay.mail.etat.lu, transport.use: smtp} - mapserverproxy: {default_ogc_server: source for image/jpeg} - modify_notification: {admin_email: null, email_cc: null, url: null} - no_proxy: localhost - ogcproxy_enable: false - sync_ms_path: /app/scripts/sync_ms.sh - temp_mapfile: /mapfile - overview_map: {base_layer: basemap_2015_global, show: true} - package: geoportailv3 - anf: - email: '{ANF_EMAIL}' - map_id: '{ANF_MAP_ID}' - age: - email: '{AGE_EMAIL}' - map_ids: '{AGE_MAP_IDS}' - show_link: '{AGE_SHOW_LINK}' - layers: '{AGE_LAYERS}' - age_crues: - email: '{AGE_CRUES_EMAIL}' - map_id: '{AGE_CRUES_MAP_ID}' - show_link: '{AGE_CRUES_SHOW_LINK}' - layers: '{AGE_CRUES_LAYERS}' - roles: '{AGE_CRUES_ROLES}' - pag: { - bcc_address: '{PAG_BCC_ADDRESS}', file_server: '{PAG_FILE_SERVER}', fme_token: '{PAG_FME_TOKEN}', owncloud_external_url: '{PAG_OWNCLOUD_EXTERNAL_URL}', - owncloud_internal_url: '{PAG_OWNCLOUD_INTERNAL_URL}', owncloud_password: '{PAG_OWNCLOUD_PASSWORD}', owncloud_user: '{PAG_OWNCLOUD_USER}', prod_url: '{PAG_PROD_URL}', - smtp_server: '{PAG_SMTP_SERVER}', staging_url: '{PAG_STAGING_URL}'} - print_url: '{PRINT_URL}' - print_urls: null - proxy_wms_url: null - raster: - dhm: {file: '{DHM_DEM_FILE}', round: 0.01, type: '{DHM_DEM_TYPE}'} - referrer: null - reset_password: {email_body: 'unused', email_from: info@camptocamp.com, email_subject: unused} - resourceproxy: - targets: {} - routing: - graphhopper: {api_key: '{ROUTING_GRAPHHOPPER_API_KEY}', url: 'https://graphhopper.com/api/1/route'} - mapquest: {api_key: '{ROUTING_MAPQUEST_API_KEY}', url: 'http://open.mapquestapi.com/directions/v2/route'} - reverse_geocode: {api_key: '{REVERSE_GEOCODE_API_KEY}', url: '{REVERSE_GEOCODE_URL}'} - schema: geov3 - schema_static: '{PGSCHEMA_STATIC}' - servers: {my_maps: 'https://ws.geoportail.lu/mymaps', mapserver: 'https://ws.geoportail.lu'} - shortener: - allowed_hosts: ['{SHORTENER_ALLOWED_HOST}', 'map.geoportail.lu', 'maps.geoportail.lu', 'maps.geoportal.lu', 'map.geoportal.lu', 'map.app.geoportail.lu', 'vt-staging.geoportail.lu', 'devrm.geoportail.lu', 'migration.geoportail.lu', 'nextprod.geoportail.lu'] - base_url: '{SHORTENER_BASE_URL}' - email_body: 'unused' - email_from: unused - email_subject: unused - smtp: {host: echo 'no-set', password: not-set, ssl: true, user: not-set} - sqlalchemy.max_overflow: 25 - sqlalchemy.pool_recycle: 30 - sqlalchemy.pool_size: 5 - sqlalchemy.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST}:{PGPORT}/{PGDATABASE} - sqlalchemy.use_batch_mode: true - sqlalchemy_slave.max_overflow: 25 - sqlalchemy_slave.pool_recycle: 30 - sqlalchemy_slave.pool_size: 5 - sqlalchemy_slave.url: postgresql://{PGUSER}:{PGPASSWORD}@{PGHOST_SLAVE}:{PGPORT}/{PGDATABASE} - sqlalchemy_slave.use_batch_mode: true - srid: 2169 - stats: {} - tiles_url: ['{VISIBLE_WEB_PROTOCOL}://{VISIBLE_WEB_HOST}/main/tiles/'] - tinyowsproxy: {tinyows_url: '{TINYOWS_URL}'} - urllogin: {} - welcome_email: {email_body: 'unused', email_from: info@camptocamp.com, email_subject: unused} - elastic.servers: '{ELASTIC_SERVERS}' - elastic.index: '{ELASTIC_INDEX}' diff --git a/geoportal/development.ini b/geoportal/development.ini index 11dc0397f..3735892eb 100644 --- a/geoportal/development.ini +++ b/geoportal/development.ini @@ -1,5 +1,6 @@ [app:app] use = egg:geoportailv3_geoportal +filter-with = proxy-prefix pyramid.reload_templates = true pyramid.debug_authorization = false pyramid.debug_notfound = true @@ -7,32 +8,40 @@ pyramid.debug_routematch = false pyramid.debug_templates = true pyramid.includes = pyramid_debugtoolbar +debugtoolbar.hosts = 0.0.0.0/0 mako.directories = geoportailv3_geoportal:templates c2cgeoportal_geoportal:templates -authtkt_http_only = False -#authtkt_timeout = %(AUTHTKT_TIMEOUT)s -authtkt_timeout = 21600 -#authtkt_secure = %(AUTHTKT_SECURE)s -#authtkt_secret = %(AUTHTKT_SECRET)s -authtkt_secure = false -authtkt_secret = the_secret_key -authtkt_cookie_name = auth_tkt_main -arcgis_token_url = dummy_url -arcgis_token_validity = 600 -arcgis_token_referer = https://map.geoportail.lu -arcgis_token_username = dummy_user -arcgis_token_password = dummy_pass -app.cfg = %(here)s/config.yaml +authtkt_secret = %(AUTHTKT_SECRET)s +authtkt_cookie_name = %(AUTHTKT_COOKIENAME)s +authtkt_timeout = %(AUTHTKT_TIMEOUT)s +authtkt_max_age = %(AUTHTKT_MAXAGE)s +authtkt_reissue_time = %(AUTHTKT_REISSUE_TIME)s +authtkt_http_only = %(AUTHTKT_HTTP_ONLY)s +authtkt_secure = %(AUTHTKT_SECURE)s +authtkt_samesite = %(AUTHTKT_SAMESITE)s +basicauth = %(BASICAUTH)s + +app.cfg = /etc/geomapfish/config.yaml + +[server:main] +use = egg:waitress#main +listen = 0.0.0.0:8080 + +[filter:proxy-prefix] +use = egg:PasteDeploy#prefix +prefix = %(VISIBLE_ENTRY_POINT)s [pipeline:main] pipeline = app +### # logging configuration -# http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/logging.html +# https://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/logging.html +### [loggers] -keys = root, sqlalchemy, gunicorn.access, gunicorn.error, c2cgeoportal_commons, c2cgeoportal_geoportal, c2cgeoportal_admin, geoportailv3_geoportal, c2cwsgiutils +keys = root, sqlalchemy, gunicorn, c2cgeoportal_commons, c2cgeoportal_geoportal, c2cgeoportal_admin, geoportailv3_geoportal, c2cwsgiutils, dogpilecache [handlers] keys = console @@ -41,7 +50,7 @@ keys = console keys = generic [logger_root] -level = WARN +level = %(OTHER_LOG_LEVEL)s handlers = console [logger_c2cgeoportal_commons] @@ -65,28 +74,28 @@ handlers = qualname = geoportailv3_geoportal [logger_c2cwsgiutils] -level = %(LOG_LEVEL)s +level = %(C2CWSGIUTILS_LOG_LEVEL)s handlers = qualname = c2cwsgiutils -[logger_gunicorn.access] -level = INFO -handlers = -qualname = gunicorn.access - -[logger_gunicorn.error] -level = INFO +[logger_gunicorn] +level = %(GUNICORN_LOG_LEVEL)s handlers = -qualname = gunicorn.error +qualname = gunicorn [logger_sqlalchemy] -level = WARN +level = %(SQL_LOG_LEVEL)s handlers = qualname = sqlalchemy.engine # "level = INFO" logs SQL queries. # "level = DEBUG" logs SQL queries and results. # "level = WARN" logs neither. (Recommended for production systems.) +[logger_dogpilecache] +level = %(DOGPILECACHE_LOG_LEVEL)s +handlers = +qualname = dogpile.cache + [handler_console] class = StreamHandler args = (sys.stderr,) @@ -94,4 +103,4 @@ level = NOTSET formatter = generic [formatter_generic] -format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s +format = %(levelname)-5.5s [%(name)s] %(message)s diff --git a/geoportal/generate_i18n.sh b/geoportal/generate_i18n.sh index 7109ef6f3..4cb33f209 100755 --- a/geoportal/generate_i18n.sh +++ b/geoportal/generate_i18n.sh @@ -1,6 +1,6 @@ #!/bin/bash -e -APP_OUTPUT_DIR=geoportailv3_geoportal/static-ngeo/build +APP_OUTPUT_DIR=/etc/geomapfish/static LOCALE=geoportailv3_geoportal/locale LANGS="en fr lb de" @@ -21,9 +21,10 @@ create_ui_jsons() { do prefix="`prefix $lang`" c2cprefix="$prefix/geoportailv3_geoportal" - files="$c2cprefix-client.po $c2cprefix-tooltips.po $prefix/ngeo.po" + files="$c2cprefix-client.po $c2cprefix-tooltips.po $prefix/ngeo.po" echo "-> $APP_OUTPUT_DIR/$lang.json" - node node_modules/.bin/compile-catalog $files > $APP_OUTPUT_DIR/$lang.json + mkdir -p $APP_OUTPUT_DIR + node /usr/bin/compile-catalog $files > $APP_OUTPUT_DIR/$lang.json done } diff --git a/geoportal/geoportailv3_geoportal/__init__.py b/geoportal/geoportailv3_geoportal/__init__.py index 47a0a1d69..0e432bfb2 100644 --- a/geoportal/geoportailv3_geoportal/__init__.py +++ b/geoportal/geoportailv3_geoportal/__init__.py @@ -6,11 +6,11 @@ from pyramid.config import Configurator from pyramid.events import NewRequest from c2cgeoportal_geoportal import locale_negotiator, add_interface, \ - INTERFACE_TYPE_NGEO, INTERFACE_TYPE_NGEO_CATALOGUE, set_user_validator + INTERFACE_TYPE_NGEO, set_user_validator # from c2cgeoportal_geoportal.lib.authentication import create_authentication from geoportailv3_geoportal.resources import Root -from geoportal.geoportailv3_geoportal.lib.lux_authentication import create_authentication +from geoportailv3_geoportal.lib.lux_authentication import create_authentication from pyramid.renderers import JSON from pyramid_mako import add_mako_renderer @@ -27,6 +27,7 @@ import sentry_sdk from sentry_sdk.integrations.pyramid import PyramidIntegration +from c2cgeoportal_geoportal.lib import C2CPregenerator mailer = None @@ -89,6 +90,8 @@ def main(global_config, **settings): # Workaround to not have the error: distutils.errors.DistutilsArgError: no commands supplied distutils.core._setup_stop_after = 'config' + config.add_route("lux_themes", "/themes", request_method="GET", pregenerator=C2CPregenerator(role=True)) + config.add_route( "lux_get_thumbnail", "/printproxy/thumbnail", @@ -128,7 +131,7 @@ def main(global_config, **settings): config.add_translation_dirs('geoportailv3_geoportal:locale/') - add_interface(config, 'main', INTERFACE_TYPE_NGEO_CATALOGUE, default=True) + add_interface(config, 'main', INTERFACE_TYPE_NGEO, default=True) # ping routes config.add_route( @@ -215,6 +218,11 @@ def main(global_config, **settings): "/mymaps/update/{map_id}", request_method="PUT" ) + config.add_route( + "convert_geojson", + "/helper/convert_geojson", + request_method="POST" + ) config.add_route( "get_gpx", "/mymaps/get_gpx/{map_id}", @@ -424,7 +432,7 @@ def main(global_config, **settings): # jsapi routes config.add_route( 'jsapiloader', - '/apiv3loader.js' + '/apiv4loader.js' ) config.add_route( 'jsapiexample', @@ -445,6 +453,7 @@ def main(global_config, **settings): config.add_route("echocsv", "/profile/echocsv", request_method="POST") config.add_route('getuserinfo', '/getuserinfo') + config.add_route('login', '/login') config.add_route('wms', '/ogcproxywms') config.add_route('wmspoi', '/wmspoi') config.add_route('https_proxy', '/httpsproxy') @@ -463,19 +472,23 @@ def main(global_config, **settings): config.add_route('upload_vt_style', '/uploadvtstyle') config.add_route('delete_vt_style', '/deletevtstyle') config.add_route('get_vt_style', '/getvtstyle') + config.add_route('profile.csv', '/profile.csv') # Service worker config.add_route('sw', '/sw.js') config.add_static_view('proj/{version}', path='geoportailv3_geoportal:jsapi/') - + config.add_static_view('static-ngeo', path='geoportailv3_geoportal:static-ngeo/') + config.override_asset(to_override='geoportailv3_geoportal:static-ngeo/', + override_with='/etc/static-ngeo/') + # Appcache manifest config.add_route( 'appcache', '/geoportailv3.appcache' ) config.include("pyramid_assetviews") - config.add_asset_views("geoportailv3_geoportal:static-ngeo/build/", filenames=['apiv3-full-async.js', 'apiv3.css']) + config.add_asset_views("/etc/static-ngeo/build/", filenames=['apiv4.js', 'apiv4.css']) # ldap from geoportailv3_geoportal.views.authentication import ldap_user_validator, \ get_user_from_request @@ -500,7 +513,7 @@ def main(global_config, **settings): scope=ldap.SUBTREE, ) - config.set_request_property( + config.add_request_method( get_user_from_request, name='user', reify=True @@ -526,40 +539,6 @@ def main(global_config, **settings): mailer = Mailer(mail_config) mailer.start() - # Add custom table in admin interace, that means re-add all normal table - - from c2cgeoform.routes import register_models - - from c2cgeoportal_commons.models.main import ( - Role, LayerWMS, LayerWMTS, Theme, LayerGroup, LayerV1, Interface, OGCServer, - Functionality, RestrictionArea) - from c2cgeoportal_commons.models.static import User - from geoportailv3_geoportal.models import LuxDownloadUrl, \ - LuxMeasurementLoginCommune, LuxMeasurementDirectory, LuxGetfeatureDefinition, \ - LuxPrintServers, LuxPredefinedWms, LuxLayerExternalWMS, LuxLayerInternalWMS - - register_models(config, ( - ('themes', Theme), - ('layer_groups', LayerGroup), - # ('layers_wms', LayerWMS), removed we use LuxLayerExternalWMS and LuxLayerInternalWMS instead - ('layers_wmts', LayerWMTS), - ('layers_v1', LayerV1), - ('ogc_servers', OGCServer), - ('restriction_areas', RestrictionArea), - ('users', User), - ('roles', Role), - ('functionalities', Functionality), - ('interfaces', Interface), - ('lux_download_url', LuxDownloadUrl), - ('lux_measurement_login_commune', LuxMeasurementLoginCommune), - ('lux_measurement_directory', LuxMeasurementDirectory), - ('lux_getfeature_definition', LuxGetfeatureDefinition), - ('lux_print_servers', LuxPrintServers), - ('lux_predefined_wms', LuxPredefinedWms), - ('lux_layer_external_wms', LuxLayerExternalWMS), - ('lux_layer_internal_wms', LuxLayerInternalWMS), - ), 'admin') - # scan view decorator for adding routes config.scan() diff --git a/geoportal/geoportailv3_geoportal/admin/__init__.py b/geoportal/geoportailv3_geoportal/admin/__init__.py index 40a96afc6..a52089758 100644 --- a/geoportal/geoportailv3_geoportal/admin/__init__.py +++ b/geoportal/geoportailv3_geoportal/admin/__init__.py @@ -1 +1,11 @@ # -*- coding: utf-8 -*- +# flake8: noqa + +from geoportailv3_geoportal.admin.view.lux_download_url import LuxDownloadUrl +from geoportailv3_geoportal.admin.view.lux_measurement_login_commune import LuxMeasurementLoginCommune +from geoportailv3_geoportal.admin.view.lux_measurement_directory import LuxMeasurementDirectory +from geoportailv3_geoportal.admin.view.lux_getfeature_definition import LuxGetfeatureDefinition +from geoportailv3_geoportal.admin.view.lux_print_servers import LuxPrintServers +from geoportailv3_geoportal.admin.view.lux_predefined_wms import LuxPredefinedWms +from geoportailv3_geoportal.admin.view.lux_layer_external_wms import LuxLayerExternalWMS +from geoportailv3_geoportal.admin.view.lux_layer_internal_wms import LuxLayerInternalWMS diff --git a/geoportal/geoportailv3_geoportal/admin/view/lux_layer_external_wms.py b/geoportal/geoportailv3_geoportal/admin/view/lux_layer_external_wms.py index 44b07f873..0851cb370 100644 --- a/geoportal/geoportailv3_geoportal/admin/view/lux_layer_external_wms.py +++ b/geoportal/geoportailv3_geoportal/admin/view/lux_layer_external_wms.py @@ -71,8 +71,8 @@ def index(self): def grid(self): return super().grid() - def _item_actions(self, item): - actions = super()._item_actions(item) + def _item_actions(self, item, readonly=False): + actions = super()._item_actions(item, readonly) if inspect(item).persistent: actions.insert(next((i for i, v in enumerate(actions) if v.name() == 'delete')), ItemAction( name='convert_to_wmts', diff --git a/geoportal/geoportailv3_geoportal/admin/view/lux_layer_internal_wms.py b/geoportal/geoportailv3_geoportal/admin/view/lux_layer_internal_wms.py index 6e97e5840..3bc7ad165 100644 --- a/geoportal/geoportailv3_geoportal/admin/view/lux_layer_internal_wms.py +++ b/geoportal/geoportailv3_geoportal/admin/view/lux_layer_internal_wms.py @@ -76,8 +76,8 @@ def index(self): def grid(self): return super().grid() - def _item_actions(self, item): - actions = super()._item_actions(item) + def _item_actions(self, item, readonly=False): + actions = super()._item_actions(item, readonly) if inspect(item).persistent: actions.insert(next((i for i, v in enumerate(actions) if v.name() == 'delete')), ItemAction( name='convert_to_wmts', diff --git a/geoportal/geoportailv3_geoportal/lib/lingua_extractor.py b/geoportal/geoportailv3_geoportal/lib/lingua_extractor.py index e6009d694..b7ba2a948 100644 --- a/geoportal/geoportailv3_geoportal/lib/lingua_extractor.py +++ b/geoportal/geoportailv3_geoportal/lib/lingua_extractor.py @@ -11,14 +11,845 @@ from geojson import loads as geojson_loads from sqlalchemy.exc import NoSuchTableError, OperationalError, ProgrammingError from lingua.extractors import Extractor, Message - +from pyramid.paster import bootstrap from c2cgeoportal_geoportal import init_dbsessions -from c2cgeoportal_commons.config import config from c2cgeoportal_geoportal.lib.bashcolor import RED, colorize +import c2cgeoportal_commons + +import json +import os +import re +import subprocess +import traceback +from typing import Dict, List, Optional, Set, cast +from urllib.parse import urlsplit +from xml.dom import Node +from xml.parsers.expat import ExpatError + +import requests +import sqlalchemy +import yaml +from bottle import MakoTemplate, template # pylint: disable=wrong-import-order,useless-suppression +from c2c.template.config import config +from defusedxml.minidom import parseString +from geoalchemy2.types import Geometry +from lingua.extractors import Extractor, Message +from mako.lookup import TemplateLookup +from mako.template import Template +from owslib.wms import WebMapService +from sqlalchemy.exc import NoSuchTableError, OperationalError, ProgrammingError +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.orm.properties import ColumnProperty +from sqlalchemy.orm.util import class_mapper + +import c2cgeoportal_commons.models +import c2cgeoportal_geoportal +from c2cgeoportal_geoportal.lib.bashcolor import RED, colorize +from c2cgeoportal_geoportal.lib.caching import init_region +from c2cgeoportal_geoportal.views.layers import Layers, get_layer_class + +config = c2cgeoportal_commons.configuration import logging log = logging.getLogger(__name__) +def add_url_params(url, params): + if len(params.items()) == 0: + return url + return add_spliturl_params(urlparse.urlsplit(url), params) +def add_spliturl_params(spliturl, params): + query = dict([(k, v[-1]) for k, v in urlparse.parse_qs(_encode(spliturl.query)).items()]) + for key, value in params.items(): + query[_encode(key)] = _encode(value) + + return urlparse.urlunsplit(( + spliturl.scheme, spliturl.netloc, spliturl.path, + urllib.urlencode(query), spliturl.fragment + )) +def get_url2(name, url, request, errors) -> Optional[str]: + url_split = urllib.parse.urlsplit(url) + if url_split.scheme == "": + if url_split.netloc == "" and url_split.path not in ("", "/"): + # Relative URL like: /dummy/static/url or dummy/static/url + return urllib.parse.urlunsplit(url_split) + errors.add("{}='{}' is not an URL.".format(name, url)) + return None + if url_split.scheme in ("http", "https"): + if url_split.netloc == "": + errors.add("{}='{}' is not a valid URL.".format(name, url)) + return None + return urllib.parse.urlunsplit(url_split) + if url_split.scheme == "static": + if url_split.path in ("", "/"): + errors.add("{}='{}' cannot have an empty path.".format(name, url)) + return None + proj = url_split.netloc + package = request.registry.settings["package"] + if proj in ("", "static"): + proj = "/etc/geomapfish/static" + elif ":" not in proj: + if proj == "static-ngeo": + errors.add( + "{}='{}' static-ngeo shouldn't be used out of webpack because it don't has " + "cache bustering.".format(name, url) + ) + proj = "{}_geoportal:{}".format(package, proj) + return request.static_url("{}{}".format(proj, url_split.path)) + if url_split.scheme == "config": + if url_split.netloc == "": + errors.add("{}='{}' cannot have an empty netloc.".format(name, url)) + return None + server = request.registry.settings.get("servers", {}).get(url_split.netloc) + if server is None: + errors.add( + "{}: The server '{}' ({}) is not found in the config: [{}]".format( + name, + url_split.netloc, + url, + ", ".join(request.registry.settings.get("servers", {}).keys()), + ) + ) + return None + if url_split.path != "": + if server[-1] != "/": + server += "/" + url = urllib.parse.urljoin(server, url_split.path[1:]) + else: + url = server + return url if not url_split.query else "{}?{}".format(url, url_split.query) + + +class _Registry: # pragma: no cover + settings = None + + def __init__(self, settings): + self.settings = settings + + +class _Request: # pragma: no cover + params: Dict[str, str] = {} + matchdict: Dict[str, str] = {} + GET: Dict[str, str] = {} + + def __init__(self, settings=None): + self.registry: _Registry = _Registry(settings) + + @staticmethod + def static_url(*args, **kwargs): + del args + del kwargs + return "" + + @staticmethod + def static_path(*args, **kwargs): + del args + del kwargs + return "" + + @staticmethod + def route_url(*args, **kwargs): + del args + del kwargs + return "" + + @staticmethod + def current_route_url(*args, **kwargs): + del args + del kwargs + return "" + + +class GeomapfishAngularExtractor(Extractor): # pragma: no cover + """ + GeoMapFish angular extractor + """ + + extensions = [".js", ".html"] + + def __init__(self) -> None: + super().__init__() + if os.path.exists("/etc/geomapfish/config.yaml"): + config.init("/etc/geomapfish/config.yaml") + self.config = config.get_config() + else: + self.config = None + self.tpl = None + + def __call__(self, filename, options, fileobj=None, lineno=0): + del fileobj, lineno + + init_region({"backend": "dogpile.cache.memory"}, "std") + init_region({"backend": "dogpile.cache.memory"}, "obj") + + int_filename = filename + if re.match("^" + re.escape("./{}/templates".format(self.config["package"])), filename): + try: + empty_template = Template("") # nosec + + class Lookup(TemplateLookup): + @staticmethod + def get_template(uri): + del uri # unused + return empty_template + + class MyTemplate(MakoTemplate): + tpl = None + + def prepare(self, **kwargs): + options.update({"input_encoding": self.encoding}) + lookup = Lookup(**kwargs) + if self.source: + self.tpl = Template(self.source, lookup=lookup, **kwargs) # nosec + else: + self.tpl = Template( # nosec + uri=self.name, filename=self.filename, lookup=lookup, **kwargs + ) + + try: + processed = template( + filename, + { + "request": _Request(self.config), + "lang": "fr", + "debug": False, + "extra_params": {}, + "permalink_themes": "", + "fulltextsearch_groups": [], + "wfs_types": [], + "_": lambda x: x, + }, + template_adapter=MyTemplate, + ) + int_filename = os.path.join(os.path.dirname(filename), "_" + os.path.basename(filename)) + with open(int_filename, "wb") as file_open: + file_open.write(processed.encode("utf-8")) + except Exception: + print( + colorize("ERROR! Occurred during the '{}' template generation".format(filename), RED) + ) + print(colorize(traceback.format_exc(), RED)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") == "TRUE": + # Continue with the original one + int_filename = filename + else: + raise + except Exception: + print(traceback.format_exc()) + + message_str = subprocess.check_output( + ["node", "./tools/extract-messages.js", int_filename] + ).decode("utf-8") + if int_filename != filename: + os.unlink(int_filename) + try: + messages = [] + for contexts, message in json.loads(message_str): + for context in contexts.split(", "): + assert message is not None + messages.append(Message(None, message, None, [], "", "", context.split(":"))) + return messages + except Exception: + print(colorize("An error occurred", RED)) + print(colorize(message_str, RED)) + print("------") + raise + + +class GeomapfishConfigExtractor(Extractor): # pragma: no cover + """ + GeoMapFish config extractor (raster layers, and print templates) + """ + + extensions = [".yaml", ".tmpl"] + + def __call__(self, filename, options, fileobj=None, lineno=0): + del fileobj, lineno + init_region({"backend": "dogpile.cache.memory"}, "std") + init_region({"backend": "dogpile.cache.memory"}, "obj") + + with open(filename) as config_file: + gmf_config = yaml.load(config_file, Loader=yaml.BaseLoader) # nosec + # For application config (config.yaml) + if "vars" in gmf_config: + return self._collect_app_config(filename) + # For the print config + if "templates" in gmf_config: + return self._collect_print_config(gmf_config, filename) + raise Exception("Not a known config file") + def _collect_app_config(self, filename): + config.init(filename) + settings = config.get_config() + assert not [ + raster_layer for raster_layer in list(settings.get("raster", {}).keys()) if raster_layer is None + ] + # Collect raster layers names + raster = [ + Message(None, raster_layer, None, [], "", "", (filename, "raster/{}".format(raster_layer))) + for raster_layer in list(settings.get("raster", {}).keys()) + ] + + # Init db sessions + + class R: + settings = None + + class C: + registry = R() + + def get_settings(self): + return self.registry.settings + + def add_tween(self, *args, **kwargs): + pass + + config_ = C() + config_.registry.settings = settings + + c2cgeoportal_geoportal.init_dbsessions(settings, config_) + + # Collect layers enum values (for filters) + + from c2cgeoportal_commons.models import DBSessions # pylint: disable=import-outside-toplevel + from c2cgeoportal_commons.models.main import Metadata # pylint: disable=import-outside-toplevel + + enums = [] + enum_layers = settings.get("layers", {}).get("enum", {}) + for layername in list(enum_layers.keys()): + layerinfos = enum_layers.get(layername, {}) + attributes = layerinfos.get("attributes", {}) + for fieldname in list(attributes.keys()): + values = self._enumerate_attributes_values(DBSessions, Layers, layerinfos, fieldname) + for (value,) in values: + if isinstance(value, str) and value != "": + msgid = value + location = "/layers/{}/values/{}/{}".format( + layername, + fieldname, + value.encode("ascii", errors="replace").decode("ascii"), + ) + assert msgid is not None + enums.append(Message(None, msgid, None, [], "", "", (filename, location))) + + metadata_list = [] + defs = config["admin_interface"]["available_metadata"] # pylint: disable=unsubscriptable-object + names = [e["name"] for e in defs if e.get("translate", False)] + + if names: + engine = sqlalchemy.create_engine(config["sqlalchemy.url"]) + Session = sqlalchemy.orm.session.sessionmaker() # noqa + Session.configure(bind=engine) + session = Session() + + query = session.query(Metadata).filter(Metadata.name.in_(names)) # pylint: disable=no-member + for metadata in query.all(): + location = "metadata/{}/{}".format(metadata.name, metadata.id) + assert metadata.value is not None + metadata_list.append(Message(None, metadata.value, None, [], "", "", (filename, location))) + + interfaces_messages = [] + for interface, interface_config in config["interfaces_config"].items(): + for ds_index, datasource in enumerate( + interface_config.get("constants", {}).get("gmfSearchOptions", {}).get("datasources", []) + ): + for a_index, action in enumerate(datasource.get("groupActions", [])): + location = ( + "interfaces_config/{}/constants/gmfSearchOptions/datasources[{}]/" + "groupActions[{}]/title".format(interface, ds_index, a_index) + ) + assert action["title"] is not None + interfaces_messages.append( + Message(None, action["title"], None, [], "", "", (filename, location)) + ) + + for merge_tab in ( + interface_config.get("constants", {}) + .get("gmfDisplayQueryGridOptions", {}) + .get("mergeTabs", {}) + .keys() + ): + location = "interfaces_config/{}/constants/gmfDisplayQueryGridOptions/mergeTabs/{}/".format( + interface, merge_tab + ) + assert merge_tab is not None + interfaces_messages.append(Message(None, merge_tab, None, [], "", "", (filename, location))) + + return raster + enums + metadata_list + interfaces_messages + + @staticmethod + def _enumerate_attributes_values(dbsessions, layers, layerinfos, fieldname): + dbname = layerinfos.get("dbsession", "dbsession") + translate = layerinfos.get("attributes").get(fieldname, {}).get("translate", True) + if not translate: + return [] + try: + dbsession = dbsessions.get(dbname) + return layers.query_enumerate_attribute_values(dbsession, layerinfos, fieldname) + except Exception as e: + table = layerinfos.get("attributes").get(fieldname, {}).get("table") + print( + colorize( + "ERROR! Unable to collect enumerate attributes for " + "db: {}, table: {}, column: {} ({})".format(dbname, table, fieldname, e), + RED, + ) + ) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") == "TRUE": + return [] + raise + + @staticmethod + def _collect_print_config(print_config, filename): + result = [] + for template_ in list(print_config.get("templates").keys()): + assert template_ is not None + result.append( + Message(None, template_, None, [], "", "", (filename, "template/{}".format(template_))) + ) + assert not [ + attribute + for attribute in list(print_config["templates"][template_]["attributes"].keys()) + if attribute is None + ] + result += [ + Message( + None, + attribute, + None, + [], + "", + "", + (filename, "template/{}/{}".format(template_, attribute)), + ) + for attribute in list(print_config["templates"][template_]["attributes"].keys()) + ] + return result + + +class GeomapfishThemeExtractor(Extractor): # pragma: no cover + """ + GeoMapFish theme extractor + """ + + # Run on the development.ini file + extensions = [".ini"] + featuretype_cache: Dict[str, Optional[Dict]] = {} + wmscap_cache: Dict[str, WebMapService] = {} + + def __init__(self) -> None: + super().__init__() + if os.path.exists("/etc/geomapfish/config.yaml"): + config.init("/etc/geomapfish/config.yaml") + self.config = config.get_config() + else: + self.config = None + self.env = None + + def __call__(self, filename, options, fileobj=None, lineno=0): + del fileobj, lineno + messages: List[Message] = [] + + try: + self.env = bootstrap(filename) + engine = sqlalchemy.engine_from_config(self.config, "sqlalchemy_slave.") + factory = sqlalchemy.orm.sessionmaker(bind=engine) + db_session = sqlalchemy.orm.scoped_session(factory) + c2cgeoportal_commons.models.DBSession = db_session + c2cgeoportal_commons.models.Base.metadata.bind = engine + + try: + from c2cgeoportal_commons.models.main import ( # pylint: disable=import-outside-toplevel + FullTextSearch, + LayerGroup, + LayerWMS, + LayerWMTS, + Theme, + ) + + self._import(Theme, messages) + self._import(LayerGroup, messages) + self._import(LayerWMS, messages, self._import_layer_wms) + self._import(LayerWMTS, messages, self._import_layer_wmts) + + for (layer_name,) in db_session.query(FullTextSearch.layer_name).distinct().all(): + if layer_name is not None and layer_name != "": + assert layer_name is not None + messages.append( + Message( + None, + layer_name, + None, + [], + "", + "", + ("fts", layer_name.encode("ascii", errors="replace")), + ) + ) + + for (actions,) in db_session.query(FullTextSearch.actions).distinct().all(): + if actions is not None and actions != "": + for action in actions: + assert action["data"] is not None + messages.append( + Message( + None, + action["data"], + None, + [], + "", + "", + ("fts", action["data"].encode("ascii", errors="replace")), + ) + ) + except ProgrammingError as e: + print( + colorize( + "ERROR! The database is probably not up to date " + "(should be ignored when happen during the upgrade)", + RED, + ) + ) + print(colorize(e, RED)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + except NoSuchTableError as e: + print( + colorize( + "ERROR! The schema didn't seem to exists " + "(should be ignored when happen during the deploy)", + RED, + ) + ) + print(colorize(e, RED)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + except OperationalError as e: + print( + colorize( + "ERROR! The database didn't seem to exists " + "(should be ignored when happen during the deploy)", + RED, + ) + ) + print(colorize(e, RED)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + + return messages + + @staticmethod + def _import(object_type, messages, callback=None): + from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel + + items = DBSession.query(object_type) + for item in items: + assert item.name is not None + messages.append( + Message( + None, + item.name, + None, + [], + "", + "", + (item.item_type, item.name.encode("ascii", errors="replace")), + ) + ) + + if callback is not None: + callback(item, messages) + + def _import_layer_wms(self, layer, messages): + server = layer.ogc_server + url = server.url_wfs or server.url + if url is None: + return + if layer.ogc_server.wfs_support: + for wms_layer in layer.layer.split(","): + self._import_layer_attributes(url, wms_layer, layer.item_type, layer.name, messages) + if layer.geo_table is not None and layer.geo_table != "": + try: + cls = get_layer_class(layer, with_last_update_columns=True) + for column_property in class_mapper(cls).iterate_properties: + if isinstance(column_property, ColumnProperty) and len(column_property.columns) == 1: + column = column_property.columns[0] + if not column.primary_key and not isinstance(column.type, Geometry): + if column.foreign_keys: + if column.name == "type_id": + name = "type_" + elif column.name.endswith("_id"): + name = column.name[:-3] + else: + name = column.name + "_" + else: + name = column_property.key + assert name is not None + messages.append( + Message( + None, + name, + None, + [], + "", + "", + (".".join(["edit", layer.item_type, str(layer.id)]), layer.name), + ) + ) + except NoSuchTableError: + print( + colorize( + "ERROR! No such table '{}' for layer '{}'.".format(layer.geo_table, layer.name), RED + ) + ) + print(colorize(traceback.format_exc(), RED)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + + def _import_layer_wmts(self, layer, messages): + from c2cgeoportal_commons.models import DBSession # pylint: disable=import-outside-toplevel + from c2cgeoportal_commons.models.main import OGCServer # pylint: disable=import-outside-toplevel + + layers = [d.value for d in layer.metadatas if d.name == "queryLayers"] + if not layers: + layers = [d.value for d in layer.metadatas if d.name == "wmsLayer"] + server = [d.value for d in layer.metadatas if d.name == "ogcServer"] + if server and layers: + layers = [layer for ls in layers for layer in ls.split(",")] + for wms_layer in layers: + try: + db_server = DBSession.query(OGCServer).filter(OGCServer.name == server[0]).one() + if db_server.wfs_support: + self._import_layer_attributes( + db_server.url_wfs or db_server.url, + wms_layer, + layer.item_type, + layer.name, + messages, + ) + except NoResultFound: + print( + colorize( + "ERROR! the OGC server '{}' from the WMTS layer '{}' does not exist.".format( + server[0], layer.name + ), + RED, + ) + ) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + + def _import_layer_attributes(self, url, layer, item_type, name, messages): + attributes, layers = self._layer_attributes(url, layer) + for sub_layer in layers: + assert sub_layer is not None + messages.append( + Message( + None, + sub_layer, + None, + [], + "", + "", + (".".join([item_type, name]), sub_layer.encode("ascii", "replace")), + ) + ) + for attribute in attributes: + assert attribute is not None + messages.append( + Message( + None, + attribute, + None, + [], + "", + "", + (".".join([item_type, name]), layer.encode("ascii", "replace")), + ) + ) + + def _build_url(self, url): + url_split = urlsplit(url) + hostname = url_split.hostname + host_map = self.config.get("lingua_extractor", {}).get("host_map", {}) + if hostname in host_map: + map_ = host_map[hostname] + if "netloc" in map_: + url_split = url_split._replace(netloc=map_["netloc"]) + if "scheme" in map_: + url_split = url_split._replace(scheme=map_["scheme"]) + kwargs = {"verify": map_["verify"]} if "verify" in map_ else {} + return url_split.geturl(), map_.get("headers", {}), kwargs + return url, {}, {} + + def _layer_attributes(self, url, layer): + errors: Set[str] = set() + + request = _Request() + request.registry.settings = self.config + # Static schema will not be supported + url = get_url2("Layer", url, request, errors) + if errors: + print("\n".join(errors)) + return [], [] + url, headers, kwargs = self._build_url(url) + + if url not in self.wmscap_cache: + print("Get WMS GetCapabilities for URL: {}".format(url)) + self.wmscap_cache[url] = None + + wms_getcap_url = add_url_params( + url, + { + "SERVICE": "WMS", + "VERSION": "1.1.1", + "REQUEST": "GetCapabilities", + "ROLE_IDS": "0", + "USER_ID": "0", + }, + ) + try: + print( + "Get WMS GetCapabilities for URL {},\nwith headers: {}".format( + wms_getcap_url, + " ".join( + [ + "{}={}".format(h, v if h not in ("Authorization", "Cookies") else "***") + for h, v in headers.items() + ] + ), + ) + ) + response = requests.get(wms_getcap_url, headers=headers, **kwargs) + + try: + self.wmscap_cache[url] = WebMapService(None, xml=response.content) + except Exception as e: + print( + colorize( + "ERROR! an error occurred while trying to " "parse the GetCapabilities document.", + RED, + ) + ) + print(colorize(str(e), RED)) + print("URL: {}\nxml:\n{}".format(wms_getcap_url, response.text)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + except Exception as e: # pragma: no cover + print(colorize(str(e), RED)) + print( + colorize( + "ERROR! Unable to GetCapabilities from URL: {},\nwith headers: {}".format( + wms_getcap_url, + " ".join( + [ + "{}={}".format(h, v if h not in ("Authorization", "Cookies") else "***") + for h, v in headers.items() + ] + ), + ), + RED, + ) + ) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") != "TRUE": + raise + + wmscap = self.wmscap_cache[url] + + if url not in self.featuretype_cache: + print("Get WFS DescribeFeatureType for URL: {}".format(url)) + self.featuretype_cache[url] = None + + wfs_descrfeat_url = add_url_params( + url, + { + "SERVICE": "WFS", + "VERSION": "1.1.0", + "REQUEST": "DescribeFeatureType", + "ROLE_IDS": "0", + "USER_ID": "0", + }, + ) + try: + response = requests.get(wfs_descrfeat_url, headers=headers, **kwargs) + except Exception as e: # pragma: no cover + print(colorize(str(e), RED)) + print( + colorize( + "ERROR! Unable to DescribeFeatureType from URL: {}".format(wfs_descrfeat_url), RED + ) + ) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") == "TRUE": + return [], [] + raise + + if not response.ok: # pragma: no cover + print( + colorize( + "ERROR! DescribeFeatureType from URL {} return the error: {:d} {}".format( + wfs_descrfeat_url, response.status_code, response.reason + ), + RED, + ) + ) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") == "TRUE": + return [], [] + raise Exception("Aborted") + + try: + describe = parseString(response.text) + featurestype: Optional[Dict[str, Node]] = {} + self.featuretype_cache[url] = featurestype + for type_element in describe.getElementsByTagNameNS( + "http://www.w3.org/2001/XMLSchema", "complexType" + ): + cast(Dict[str, Node], featurestype)[type_element.getAttribute("name")] = type_element + except ExpatError as e: + print( + colorize( + "ERROR! an error occurred while trying to " "parse the DescribeFeatureType document.", + RED, + ) + ) + print(colorize(str(e), RED)) + print("URL: {}\nxml:\n{}".format(wfs_descrfeat_url, response.text)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") == "TRUE": + return [], [] + raise + except AttributeError: + print( + colorize( + "ERROR! an error occurred while trying to " + "read the Mapfile and recover the themes.", + RED, + ) + ) + print("URL: {}\nxml:\n{}".format(wfs_descrfeat_url, response.text)) + if os.environ.get("IGNORE_I18N_ERRORS", "FALSE") == "TRUE": + return [], [] + raise + else: + featurestype = self.featuretype_cache[url] + + if featurestype is None: + return [], [] + + layers = [layer] + if wmscap is not None and layer in list(wmscap.contents): + layer_obj = wmscap[layer] + if layer_obj.layers: + layers = [layer.name for layer in layer_obj.layers] + + attributes = [] + for sub_layer in layers: + # Should probably be adapted for other king of servers + type_element = featurestype.get("{}Type".format(sub_layer)) + if type_element is not None: + for element in type_element.getElementsByTagNameNS( + "http://www.w3.org/2001/XMLSchema", "element" + ): + if not element.getAttribute("type").startswith("gml:"): + attributes.append(element.getAttribute("name")) + + return attributes, layers class LuxembourgExtractor(Extractor): # pragma: no cover """ @@ -251,12 +1082,17 @@ def _get_external_data(self, url, bbox=None, layer=None): query = '%s%s%s' % (url, separator, urllib.parse.urlencode(body)) try: + content = "" print('Requesting %s' % query) result = urllib.request.urlopen(query, None, self.TIMEOUT) content = result.read() esricoll = geojson_loads(content) - except: - traceback.print_exc(file=sys.stdout) + except Exception as e: + log.error("-----------------------------") + log.error(query) + log.error(content) + log.exception(e) + log.error("-----------------------------") return [] if 'fieldAliases' not in esricoll: print(("Error with the layer: %s using query : %s response: %s" @@ -335,10 +1171,15 @@ def _ogc_getfeatureinfo(self, session, url, x, y, width, height, return [] try: ogc_features = geojson_loads(content) - return (dict((key, key) - for key, value in ogc_features['features'][0]['properties'].items())) + if 'features' in ogc_features and len(ogc_features['features']) > 0 and 'properties' in ogc_features['features'][0]: + return (dict((key, key) + for key, value in ogc_features['features'][0]['properties'].items())) except Exception as e: + log.error("-----------------------------") + log.error(query) + log.error(content) log.exception(e) + log.error("-----------------------------") return [] return [] diff --git a/geoportal/geoportailv3_geoportal/lib/lux_authentication.py b/geoportal/geoportailv3_geoportal/lib/lux_authentication.py index 8348cabec..54108b629 100644 --- a/geoportal/geoportailv3_geoportal/lib/lux_authentication.py +++ b/geoportal/geoportailv3_geoportal/lib/lux_authentication.py @@ -1,13 +1,10 @@ -from pyramid.authentication import CallbackAuthenticationPolicy, AuthTktCookieHelper, \ - BasicAuthAuthenticationPolicy, AuthTktAuthenticationPolicy +from pyramid.authentication import BasicAuthAuthenticationPolicy, AuthTktAuthenticationPolicy from pyramid_multiauth import MultiAuthenticationPolicy from pyramid.interfaces import IAuthenticationPolicy from c2cgeoportal_geoportal.resources import defaultgroupsfinder from zope.interface import implementer -import time -import math import logging @@ -22,16 +19,30 @@ def create_authentication(settings): http_only = http_only.lower() in ("true", "yes", "1") secure = settings.get("authtkt_secure", "True") secure = secure.lower() in ("true", "yes", "1") - cookie_authentication_policy = AppAwareAuthTktAuthenticationPolicy( + + # AuthenticationPolicy for login via the mobile app ('app=true' in the request params) + app_authentication_policy = ConditionalAuthTktAuthenticationPolicy( + settings["authtkt_secret"], + callback=defaultgroupsfinder, + cookie_name=settings["authtkt_cookie_name"] + "_app", + timeout=None, max_age=None, reissue_time=None, + hashalg="sha512", http_only=http_only, secure=secure, + parent_domain=True, + condition=lambda params: params.get('app', 'false').lower() == 'true' + ) + + # AuthenticationPolicy for login not via the mobile app ('app=false' in the request params) + non_app_authentication_policy = ConditionalAuthTktAuthenticationPolicy( settings["authtkt_secret"], callback=defaultgroupsfinder, cookie_name=settings["authtkt_cookie_name"], timeout=timeout, max_age=timeout, reissue_time=reissue_time, hashalg="sha512", http_only=http_only, secure=secure, - parent_domain=True + parent_domain=True, + condition=lambda params: params.get('app', 'false').lower() == 'false' ) basic_authentication_policy = BasicAuthAuthenticationPolicy(c2cgeoportal_check) - policies = [cookie_authentication_policy, basic_authentication_policy] + policies = [app_authentication_policy, non_app_authentication_policy, basic_authentication_policy] return MultiAuthenticationPolicy(policies) @@ -42,19 +53,14 @@ def c2cgeoportal_check(username, password, request): # pragma: no cover @implementer(IAuthenticationPolicy) -class AppAwareAuthTktAuthenticationPolicy(AuthTktAuthenticationPolicy): - def remember(self, request, userid, **kw): - """ Accepts the following kw args: ``max_age=, - ``tokens=``. - - Return a list of headers which will set appropriate cookies on - the response. +class ConditionalAuthTktAuthenticationPolicy(AuthTktAuthenticationPolicy): + def __init__(self, *args, **kwargs): + self.condition = kwargs['condition'] + del kwargs['condition'] + super().__init__(*args, **kwargs) - """ - is_app = request.params.get('app', 'false').lower() == 'true' - if is_app: - # Force any cookie to be set with a big expiration time - # when login is done from the Android or iOS apps - kw['max_age'] = math.ceil(time.time() + (10 * 365 * 24 * 60 * 60)) - - return super().remember(request, userid, **kw) + def remember(self, request, userid, **kw): + if self.condition(request.params): + return super().remember(request, userid, **kw) + else: + return [] diff --git a/geoportal/geoportailv3_geoportal/lib/search.py b/geoportal/geoportailv3_geoportal/lib/search.py index 4af778b32..da6b67602 100644 --- a/geoportal/geoportailv3_geoportal/lib/search.py +++ b/geoportal/geoportailv3_geoportal/lib/search.py @@ -7,15 +7,16 @@ with open(SETTINGS_FILE) as json_file: settings = json.load(json_file) +def get_host(): + return os.environ['ELASTIC_SERVERS'] if 'ELASTIC_SERVERS' in os.environ else 'localhost:9200' + def get_elasticsearch(request): - elastichost = \ - request.registry.settings.get('elastic.servers', 'localhost:9200') - return Elasticsearch(hosts=elastichost, timeout=60) + return Elasticsearch(hosts=get_host(), timeout=60) def get_index(request): - return request.registry.settings.get('elastic.index', 'index') + return os.environ['ELASTIC_INDEX'] if 'ELASTIC_INDEX' in os.environ else 'index' def ensure_index(client, index, recreate=False): diff --git a/geoportal/geoportailv3_geoportal/lib/sw_helper.py b/geoportal/geoportailv3_geoportal/lib/sw_helper.py index cab4c516d..3ce9ff995 100644 --- a/geoportal/geoportailv3_geoportal/lib/sw_helper.py +++ b/geoportal/geoportailv3_geoportal/lib/sw_helper.py @@ -2,22 +2,24 @@ import glob import time -UNUSED = '/static-ngeo/UNUSED_CACHE_VERSION/build/' -BUILD_PATH = '/app/geoportailv3_geoportal/static-ngeo/build' +UNUSED = '/static-ngeo/' +BUILD_PATH = '/etc/static-ngeo/' def get_built_filenames(pattern): - return [os.path.basename(name) for name in glob.glob(BUILD_PATH + '/' + pattern)] + return [os.path.basename(name) for name in glob.glob( + os.path.join(BUILD_PATH, pattern) + )] def get_urls(request): - main_js_url = UNUSED + get_built_filenames('main.*.js')[0] - main_css_url = UNUSED + get_built_filenames('main.*.css')[0] - gov_light_url = UNUSED + get_built_filenames('gov-light.*.png')[0] + main_js_url = UNUSED + get_built_filenames('main*.js')[0] + main_css_url = UNUSED + get_built_filenames('main*.css')[0] + gov_light_url = UNUSED + get_built_filenames('gov-light*.png')[0] urls = [ '/', - '/dynamic.js?interface=main', + '/dynamic.json?interface=main', '/getuserinfo', '/themes?version=2&background=background&interface=main&catalogue=true&min_levels=1', request.static_path('geoportailv3_geoportal:static-ngeo/images/arrow.png'), @@ -31,11 +33,8 @@ def get_urls(request): urls.append('/dev/main.css') urls.append('/dev/main.js') - woffs = glob.glob('/app/geoportailv3_geoportal/static-ngeo/build/*.woff') + woffs = glob.glob('/etc/static-ngeo/*.woff') for stuff in get_built_filenames('*.woff'): urls.append(UNUSED + stuff) - for lang in ['fr', 'en', 'lb', 'de']: - urls.append(request.static_path('geoportailv3_geoportal:static-ngeo/build/' + lang + '.json')) - return urls diff --git a/geoportal/geoportailv3_geoportal/mymaps.py b/geoportal/geoportailv3_geoportal/mymaps.py index a9eb6c366..94df7fba1 100644 --- a/geoportal/geoportailv3_geoportal/mymaps.py +++ b/geoportal/geoportailv3_geoportal/mymaps.py @@ -293,7 +293,7 @@ def todict(self): @staticmethod def belonging_to(user, session): user_role = session.query(Role).get( - getattr(user, 'mymaps_role', user.role.id)) + getattr(user, 'mymaps_role', user.settings_role.id)) try: categories = user_role.categories\ if user_role.categories is not None else [] diff --git a/geoportal/geoportailv3_geoportal/resources.py b/geoportal/geoportailv3_geoportal/resources.py index 8025e7898..c68279b13 100644 --- a/geoportal/geoportailv3_geoportal/resources.py +++ b/geoportal/geoportailv3_geoportal/resources.py @@ -1,12 +1,10 @@ # -*- coding: utf-8 -*- -from pyramid.security import Allow, ALL_PERMISSIONS +from pyramid.security import ALL_PERMISSIONS, Allow class Root: - __acl__ = [ - (Allow, 'role_admin', ALL_PERMISSIONS), - ] + __acl__ = [(Allow, "role_admin", ALL_PERMISSIONS)] def __init__(self, request): self.request = request diff --git a/geoportal/geoportailv3_geoportal/scripts/layers2es.py b/geoportal/geoportailv3_geoportal/scripts/layers2es.py index 20058e1e6..978a03561 100644 --- a/geoportal/geoportailv3_geoportal/scripts/layers2es.py +++ b/geoportal/geoportailv3_geoportal/scripts/layers2es.py @@ -141,7 +141,7 @@ def __init__(self, options): self.layers = [] settings = {} - with open("config.yaml") as f: + with open("/etc/geomapfish/config.yaml") as f: settings = yaml.load(f) self.languages = settings["vars"]["available_locale_names"] @@ -333,11 +333,6 @@ def _layer_visible(self, layer, role): return False def _add_layer(self, layer, interface, role): - from c2cgeoportal_commons.models.main import LayerV1 - - if isinstance(layer, LayerV1): - return False - if role is None: fill = layer.public and interface in layer.interfaces else: diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid.png index 8f700bd26..f342324f6 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_retina.png index 84ed5c7f4..221be3fd4 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm.png index 142a57753..b4ef21058 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm_retina.png index 1d845a797..a0668b774 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/hybrid_sm_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto.png index 4b940a3b9..b17b973c0 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_retina.png index e43040e7a..856b9635a 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_sm_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_sm_retina.png index 8fc35d710..24b0503a4 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_sm_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/orthophoto_sm_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere.png index 787f97e83..35417935b 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_retina.png index 5af101893..6b16fddfa 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm.png index d80916f9f..ccbea4d50 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm_retina.png index d1725c3ca..e53a6d66c 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/routiere_sm_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo.png index ce9dd37fc..6fe06383f 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_retina.png index 11c59ee62..16d871ce5 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm.png index 6d90f23a3..3573b31e1 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm_retina.png index 2ced70da3..7fa092adc 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_nb_sm_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_retina.png index b9d5eb464..e238cb184 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm.png index 2e1173696..135fc9728 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm_retina.png b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm_retina.png index 9fc2118d7..b459a887d 100644 Binary files a/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm_retina.png and b/geoportal/geoportailv3_geoportal/static-ngeo/images/backgroundselector/topo_sm_retina.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/CoordinateMatch.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/CoordinateMatch.js index 606325590..f24692505 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/CoordinateMatch.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/CoordinateMatch.js @@ -32,7 +32,7 @@ export function matchCoordinate(searchString, mapEpsgCode, maxExtent, coordinate epsgCode: 'EPSG:2169' }, 'EPSG:2169:V2': { - regex: /(\d{4,6})\s*([E|N])?[\,\.]\s*(\d{4,6})\s*([E|N])?/, + regex: /(\d{4,6})\s*([E|N])?[\,\.](\d{4,6})\s*([E|N])?/, label: 'LUREF', epsgCode: 'EPSG:2169' }, diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/LayerPermalinkManager.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/LayerPermalinkManager.js index 5d61fa8c3..999941e97 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/LayerPermalinkManager.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/LayerPermalinkManager.js @@ -175,7 +175,7 @@ exports.prototype.listenPropertyChange = function(layers) { * @private */ exports.prototype.onLayerUpdate_ = function(layers_) { - let layers = layers_.filter(l => !l.get('metadata').hidden); + let layers = layers_.filter(l => l.get('metadata') && !l.get('metadata').hidden); // Check if a layer is added or removed; if (layers.length !== this.layersListenerKeys_.length) { diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/LocationControl.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/LocationControl.js index ec80b99b5..c962cc95a 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/LocationControl.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/LocationControl.js @@ -7,226 +7,239 @@ */ import appNotifyNotificationType from './NotifyNotificationType.js'; -import {inherits} from 'ol/index.js'; import {CLASS_CONTROL, CLASS_UNSELECTABLE} from 'ol/css.js'; import olControlControl from 'ol/control/Control.js'; import {listen} from 'ol/events.js'; import olFeature from 'ol/Feature.js'; import olGeomPoint from 'ol/geom/Point.js'; import olGeolocation from 'ol/Geolocation.js'; -import olGeolocationProperty from 'ol/GeolocationProperty.js'; import {getChangeEventType} from 'ol/Object.js'; /** - * @constructor - * @extends {ol.control.Control} - * @param {app.LocationControlOptions} options Location Control - * options. - * @ngInject + * @enum {string} */ -const exports = function(options) { - var className = (options.className !== undefined) ? options.className : - 'location-button'; - /** - * @type {angular.$window} - * @private - */ - this.window_ = options.window; +const olGeolocationProperty = { + ACCURACY: 'accuracy', + ACCURACY_GEOMETRY: 'accuracyGeometry', + ALTITUDE: 'altitude', + ALTITUDE_ACCURACY: 'altitudeAccuracy', + HEADING: 'heading', + POSITION: 'position', + PROJECTION: 'projection', + SPEED: 'speed', + TRACKING: 'tracking', + TRACKING_OPTIONS: 'trackingOptions' +}; +class LocationControl extends olControlControl { /** - * @type {angular.Scope} - * @private + * @constructor + * @extends {ol.control.Control} + * @param {app.LocationControlOptions} options Location Control + * options. + * @ngInject */ - this.scope_ = options.scope; + constructor(options) { + var label = (options.label !== undefined) ? options.label : 'L'; + var tipLabel = (options.tipLabel !== undefined) ? + options.tipLabel : 'Location'; + + var button = document.createElement('BUTTON'); + button.appendChild(document.createTextNode(label)); + button.setAttribute('type', 'button'); + button.setAttribute('title', tipLabel); + + var className = (options.className !== undefined) ? options.className : + 'location-button'; + + var cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + + CLASS_CONTROL + ' ' + 'tracker-off'; + + /** + * @type {!Element} + */ + var element = document.createElement('DIV'); + element.setAttribute('class', cssClasses); + element.appendChild(button); + super({ + element: element, + target: options.target + }); + + /** + * @type {angular.$window} + * @private + */ + this.window_ = options.window; + + /** + * @type {angular.Scope} + * @private + */ + this.scope_ = options.scope; + + /** + * @type {angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = options.gettextCatalog; + + /** + * @type {app.Notify} + * @private + */ + this.notify_ = options.notify; + + /** + * @type {ol.Feature} + * @private + */ + this.accuracyFeature_ = new olFeature(); + + /** + * @type {ol.Feature} + * @private + */ + this.positionFeature_ = new olFeature(); + + /** + * @type {ol.Geolocation} + * @private + */ + this.geolocation_ = null; + + /** + * @type {ngeo.map.FeatureOverlay} + * @private + */ + this.featureOverlay_ = options.featureOverlayMgr.getFeatureOverlay(); + + listen(button, 'click', + this.handleClick_, this); + + listen(button, 'mouseout', function() { + this.blur(); + }); + }; - /** - * @type {angularGettext.Catalog} - * @private - */ - this.gettextCatalog_ = options.gettextCatalog; /** - * @type {app.Notify} + * @param {ol.MapBrowserEvent} event The event to handle * @private */ - this.notify_ = options.notify; + handleClick_(event) { + event.preventDefault(); + if (this.window_.location.protocol !== 'https:') { + this.scope_['mainCtrl']['showRedirect'] = true; + } else { + this.handleCenterToLocation(); + } + }; - /** - * @type {ol.Feature} - * @private - */ - this.accuracyFeature_ = new olFeature(); /** - * @type {ol.Feature} - * @private + * Active or unactive the tracking. */ - this.positionFeature_ = new olFeature(); + handleCenterToLocation() { + if (this.geolocation_ === null) { + this.initGeoLocation_(); + } + if (!this.geolocation_.getTracking()) { + this.initFeatureOverlay_(); + this.getMap().getView().setZoom(17); + this.geolocation_.setTracking(true); + } else { + this.clearFeatureOverlay_(); + this.geolocation_.setTracking(false); + } + }; + /** - * @type {ol.Geolocation} + * * @private */ - this.geolocation_ = null; + initGeoLocation_() { + + this.geolocation_ = new olGeolocation({ + projection: this.getMap().getView().getProjection(), + trackingOptions: /** @type {GeolocationPositionOptions} */ ({ + enableHighAccuracy: true, + maximumAge: 60000, + timeout: 7000 + }) + }); + + listen(this.geolocation_, + getChangeEventType(olGeolocationProperty.TRACKING), + /** + * @param {ol.Object.Event} e Object event. + */ + function(e) { + if (this.geolocation_.getTracking()) { + this.element.classList.remove('tracker-off'); + this.element.classList.add('tracker-on'); + } else { + this.element.classList.remove('tracker-on'); + this.element.classList.add('tracker-off'); + } + }, this); + + listen(this.geolocation_, + getChangeEventType(olGeolocationProperty.POSITION), + /** + * @param {ol.Object.Event} e Object event. + */ + function(e) { + var position = /** @type {ol.Coordinate} */ + (this.geolocation_.getPosition()); + this.positionFeature_.setGeometry(new olGeomPoint(position)); + this.getMap().getView().setCenter(position); + }, this); + + listen(this.geolocation_, + getChangeEventType(olGeolocationProperty.ACCURACY_GEOMETRY), + /** + * @param {ol.Object.Event} e Object event. + */ + function(e) { + this.accuracyFeature_.setGeometry( + this.geolocation_.getAccuracyGeometry()); + }, this); + + listen(this.geolocation_, + 'error', + function(e) { + this.featureOverlay_.clear(); + if (e.message && e.message.length > 0) { + var msg = this.gettextCatalog_.getString( + 'Erreur lors de l\'acquisition de la position :'); + msg = msg + e.message; + this.notify_(msg, appNotifyNotificationType.ERROR); + } + }.bind(this)); + + }; + /** - * @type {ngeo.map.FeatureOverlay} * @private */ - this.featureOverlay_ = options.featureOverlayMgr.getFeatureOverlay(); - - var label = (options.label !== undefined) ? options.label : 'L'; - var tipLabel = (options.tipLabel !== undefined) ? - options.tipLabel : 'Location'; - - var button = document.createElement('BUTTON'); - button.appendChild(document.createTextNode(label)); - button.setAttribute('type', 'button'); - button.setAttribute('title', tipLabel); + initFeatureOverlay_() { + this.featureOverlay_.clear(); + this.accuracyFeature_.setGeometry(null); + this.positionFeature_.setGeometry(null); + this.featureOverlay_.addFeature(this.accuracyFeature_); + this.featureOverlay_.addFeature(this.positionFeature_); + }; - var cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + - CLASS_CONTROL + ' ' + 'tracker-off'; /** - * @type {!Element} + * @private */ - this.element = document.createElement('DIV'); - this.element.setAttribute('class', cssClasses); - this.element.appendChild(button); - - listen(button, 'click', - this.handleClick_, this); - - listen(button, 'mouseout', function() { - this.blur(); - }); - olControlControl.call(this, { - element: this.element, - target: options.target - }); - -}; - -inherits(exports, olControlControl); - - -/** - * @param {ol.MapBrowserEvent} event The event to handle - * @private - */ -exports.prototype.handleClick_ = function(event) { - event.preventDefault(); - if (this.window_.location.protocol !== 'https:') { - this.scope_['mainCtrl']['showRedirect'] = true; - } else { - this.handleCenterToLocation(); - } -}; - - -/** - * Active or unactive the tracking. - */ -exports.prototype.handleCenterToLocation = function() { - if (this.geolocation_ === null) { - this.initGeoLocation_(); - } - if (!this.geolocation_.getTracking()) { - this.initFeatureOverlay_(); - this.getMap().getView().setZoom(17); - this.geolocation_.setTracking(true); - } else { - this.clearFeatureOverlay_(); - this.geolocation_.setTracking(false); - } -}; - - -/** - * - * @private - */ -exports.prototype.initGeoLocation_ = function() { - - this.geolocation_ = new olGeolocation({ - projection: this.getMap().getView().getProjection(), - trackingOptions: /** @type {GeolocationPositionOptions} */ ({ - enableHighAccuracy: true, - maximumAge: 60000, - timeout: 7000 - }) - }); - - listen(this.geolocation_, - getChangeEventType(olGeolocationProperty.TRACKING), - /** - * @param {ol.Object.Event} e Object event. - */ - function(e) { - if (this.geolocation_.getTracking()) { - this.element.classList.remove('tracker-off'); - this.element.classList.add('tracker-on'); - } else { - this.element.classList.remove('tracker-on'); - this.element.classList.add('tracker-off'); - } - }, this); - - listen(this.geolocation_, - getChangeEventType(olGeolocationProperty.POSITION), - /** - * @param {ol.Object.Event} e Object event. - */ - function(e) { - var position = /** @type {ol.Coordinate} */ - (this.geolocation_.getPosition()); - this.positionFeature_.setGeometry(new olGeomPoint(position)); - this.getMap().getView().setCenter(position); - }, this); - - listen(this.geolocation_, - getChangeEventType(olGeolocationProperty.ACCURACY_GEOMETRY), - /** - * @param {ol.Object.Event} e Object event. - */ - function(e) { - this.accuracyFeature_.setGeometry( - this.geolocation_.getAccuracyGeometry()); - }, this); - - listen(this.geolocation_, - 'error', - function(e) { - this.featureOverlay_.clear(); - if (e.message && e.message.length > 0) { - var msg = this.gettextCatalog_.getString( - 'Erreur lors de l\'acquisition de la position :'); - msg = msg + e.message; - this.notify_(msg, appNotifyNotificationType.ERROR); - } - }.bind(this)); - -}; - - -/** - * @private - */ -exports.prototype.initFeatureOverlay_ = function() { - this.featureOverlay_.clear(); - this.accuracyFeature_.setGeometry(null); - this.positionFeature_.setGeometry(null); - this.featureOverlay_.addFeature(this.accuracyFeature_); - this.featureOverlay_.addFeature(this.positionFeature_); -}; - - -/** - * @private - */ -exports.prototype.clearFeatureOverlay_ = function() { - this.featureOverlay_.clear(); -}; - + clearFeatureOverlay_() { + this.featureOverlay_.clear(); + }; +} -export default exports; +export default LocationControl; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/Map.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/Map.js index eeb19768f..11b18d68d 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/Map.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/Map.js @@ -7,50 +7,9 @@ */ import olMap from 'ol/Map.js'; -import {MapBoxLayerRenderer} from '@geoblocks/mapboxlayer-legacy'; - -class ExtendedMapBoxLayerRenderer extends MapBoxLayerRenderer { - - constructor(...args) { - super(...args); - } - - /** - * Create a layer renderer. - * @param {import("../Map.js").default} _ The map renderer. - * @param {import("../../layer/Layer.js").default} layer The layer to be rendererd. - * @return {MapBoxLayerRenderer} The layer renderer. - */ - static create(_, layer) { - return new ExtendedMapBoxLayerRenderer(/** @type {MapBoxLayer} */ (layer)); - } - - /** - * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. - * @param {import("../../PluggableMap.js").FrameState} frameState Frame state. - * @param {number} hitTolerance Hit tolerance in pixels. - * @param {function(import("../../Feature.js").FeatureLike, import("../../layer/Layer.js").default): T} callback Feature callback. - * @param {Array} declutteredFeatures Decluttered features. - * @return {T|void} Callback result. - * @template T - */ - forEachFeatureAtCoordinate( - coordinate, - frameState, - hitTolerance, - callback, - declutteredFeatures - ) {} -}; const exports = class extends olMap { - constructor(...args) { - super(...args); - this.getRenderer().registerLayerRenderers([ - ExtendedMapBoxLayerRenderer - ]); - } /** * Currently the zIndex is used to order the layers. * Rremoving a layer does not reset the zindex. diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/Routing.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/Routing.js index 53ebea778..cd0230dd1 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/Routing.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/Routing.js @@ -169,13 +169,13 @@ exports.prototype.reorderRoute = function() { this.routesOrder.splice(0, this.routesOrder.length); var idx = 1; - this.features.forEach(function(curFeature) { + this.features.forEach((curFeature) => { this.routesOrder.push(idx - 1); if (curFeature.getGeometry() !== undefined) { curFeature.set('name', '' + idx); idx++; } - }, this); + }); }; /** diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/Themes.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/Themes.js index 9317fb43d..fc8793b9e 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/Themes.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/Themes.js @@ -11,11 +11,11 @@ import appModule from './module.js'; import {extend as arrayExtend} from 'ol/array.js'; -import olEventsEventTarget from 'ol/events/EventTarget.js'; +import olEventsEventTarget from 'ol/events/Target.js'; import olSourceVector from 'ol/source/Vector.js'; import appEventsThemesEventType from './events/ThemesEventType.js'; -import {inherits} from 'ol/index.js'; -import MapBoxLayer from '@geoblocks/mapboxlayer-legacy'; +import MapBoxLayer from '@geoblocks/mapboxlayer/src/MapBoxLayer.js'; + function hasLocalStorage() { return 'localStorage' in window && localStorage; @@ -53,6 +53,7 @@ function replaceWithMVTLayer(bgLayers, target, styleConfigs) { }); mvtLayer.setSource(source); } + mvtLayer.set('role', 'mapboxBackground'); bgLayers[i] = mvtLayer; } }); @@ -71,64 +72,242 @@ function replaceWithMVTLayer(bgLayers, target, styleConfigs) { * @param {app.Mvtstyling} appMvtStylingService The mvt styling service. * @ngInject */ -const exports = function($window, $http, gmfTreeUrl, isThemePrivateUrl, +class Themes extends olEventsEventTarget { + + constructor($window, $http, gmfTreeUrl, isThemePrivateUrl, appGetWmtsLayer, appBlankLayer, appGetDevice, appMvtStylingService) { - olEventsEventTarget.call(this); + super() + + /** + * @type {angular.$http} + * @private + */ + this.$http_ = $http; + + /** + * @type {boolean} + * @private + */ + this.isHiDpi_ = appGetDevice.isHiDpi(); + + /** + * @type {app.GetWmtsLayer} + * @private + */ + this.getWmtsLayer_ = appGetWmtsLayer; + + /** + * @type {app.backgroundlayer.BlankLayer} + * @private + */ + this.blankLayer_ = appBlankLayer; + + /** + * @type {string} + * @private + */ + this.treeUrl_ = gmfTreeUrl; + + /** + * @type {string} + * @private + */ + this.isThemePrivateUrl_ = isThemePrivateUrl; + + /** + * @type {?angular.$q.Promise} + * @private + */ + this.promise_ = null; + + this.flatCatalog = null; + this.layers3D = []; + + /** + * @type {app.Mvtstyling} + * @private + */ + this.appMvtStylingService_ = appMvtStylingService; + + } - /** - * @type {angular.$http} - * @private - */ - this.$http_ = $http; /** - * @type {boolean} - * @private + * Get background layers. + * @return {Promise} Promise. */ - this.isHiDpi_ = appGetDevice.isHiDpi(); + getBgLayers(map) { + console.assert(this.promise_); + console.assert(map); + if (!this.getBgLayersPromise_) { + this.getBgLayersPromise_ = this.promise_.then( + /** + * @param {app.ThemesResponse} data The "themes" web service response. + * @return {Array.} Array of background layer objects. + */ + data => { + var bgLayers = data['background_layers'].map(item => { + var hasRetina = !!item['metadata']['hasRetina'] && this.isHiDpi_; + console.assert('name' in item); + console.assert('imageType' in item); + var layer = this.getWmtsLayer_( + item['name'], item['imageType'], hasRetina + ); + layer.set('metadata', item['metadata']); + if ('attribution' in item['metadata']) { + var source = layer.getSource(); + source.setAttributions( + item['metadata']['attribution'] + ); + } + return layer; + }); + + // add the blank layer + bgLayers.push(this.blankLayer_.getLayer()); + + // add MVT layer + const bothPromises = Promise.all([ + onFirstTargetChange(map), + this.appMvtStylingService_.getBgStyle() + ]); + return bothPromises.then(([target, styleConfigs]) => { + replaceWithMVTLayer(bgLayers, target, styleConfigs); + return bgLayers; + }); + }); + } + return this.getBgLayersPromise_; + }; /** - * @type {app.GetWmtsLayer} - * @private + * Get a theme object by its name. + * @param {string} themeName Theme name. + * @return {angular.$q.Promise} Promise. */ - this.getWmtsLayer_ = appGetWmtsLayer; + getThemeObject(themeName) { + console.assert(this.promise_ !== null); + return this.promise_.then( + /** + * @param {app.ThemesResponse} data The "themes" web service response. + * @return {Object} The theme object for themeName, or null if not found. + */ + function(data) { + var themes = data['themes']; + return Themes.findTheme_(themes, themeName); + }); + }; + /** - * @type {app.backgroundlayer.BlankLayer} - * @private + * Get the promise resolving to the themes root object. + * @return {angular.$q.Promise} Promise. */ - this.blankLayer_ = appBlankLayer; + getThemesPromise() { + console.assert(this.promise_ !== null); + return this.promise_; + }; + /** - * @type {string} - * @private + * @param {?number} roleId The role id to send in the request. + * Load themes from the "themes" service. + * @return {?angular.$q.Promise} Promise. */ - this.treeUrl_ = gmfTreeUrl; + loadThemes(roleId) { + var url = new URL(this.treeUrl_); + url.searchParams.set('background', 'background'); + this.promise_ = this.$http_.get(url.toString(), { + params: (roleId !== undefined) ? {'role': roleId} : {}, + cache: false + }).then((resp) => { + const root = /** @type {app.ThemesResponse} */ (resp.data); + const themes = root.themes; + const flatCatalogue = []; + for (var i = 0; i < themes.length; i++) { + const theme = themes[i]; + const children = this.getAllChildren_(theme.children, theme.name, root.ogcServers); + arrayExtend(flatCatalogue, children); + } + + this.flatCatalog = flatCatalogue; + + this.dispatchEvent(appEventsThemesEventType.LOAD); + return root; + }); + return this.promise_; + }; + /** - * @type {string} - * @private + * @param {string} themeId The theme id to send in the request. + * checks if the theme is protected or not. + * @return {angular.$q.Promise} Promise. */ - this.isThemePrivateUrl_ = isThemePrivateUrl; + isThemePrivate(themeId) { + return this.$http_.get(this.isThemePrivateUrl_, { + params: {'theme': themeId}, + cache: false + }); + }; + /** - * @type {?angular.$q.Promise} + * @param {Array} element The element. + * @param {string} theme Theme name. + * @param {Object} ogcServers All OGC servers definitions. + * @param {Object} lastOgcServer The last OGC server. + * @return {Array} array The children. * @private */ - this.promise_ = null; + getAllChildren_(elements, theme, ogcServers, lastOgcServer) { + var array = []; + for (var i = 0; i < elements.length; i++) { + const element = elements[i]; + if (element.hasOwnProperty('children')) { + if (element.name !== '3d Layers') { + arrayExtend(array, this.getAllChildren_( + element.children, theme, ogcServers, element.ogcServer || lastOgcServer)); + } else { + arrayExtend(this.layers3D, this.getAllChildren_( + element.children, theme, ogcServers, element.ogcServer || lastOgcServer)); + } + } else { + // Rewrite url to match the behaviour of c2cgeoportal 1.6 + const ogcServer = element.ogcServer || lastOgcServer; + if (ogcServer) { + const def = ogcServers[ogcServer]; + if (def === undefined) { + element.url = null; + } else { + element.url = def.credential ? null : def.url; + } + } + element.theme = theme; + array.push(element); + } + } + return array; + }; - this.flatCatalog = null; - this.layers3D = []; /** - * @type {app.Mvtstyling} - * @private + * get the flat catlog + * @return {angular.$q.Promise} Promise. */ - this.appMvtStylingService_ = appMvtStylingService; + getFlatCatalog() { + return this.promise_.then(() => this.flatCatalog); + }; -}; + /** + * get the flat catlog + * @return {angular.$q.Promise} Promise. + */ + get3DLayers() { + return this.promise_.then(() => this.layers3D); + }; -inherits(exports, olEventsEventTarget); +} /** @@ -138,7 +317,7 @@ inherits(exports, olEventsEventTarget); * @return {Object} The object. * @private */ -exports.findObjectByName_ = function(objects, objectName) { +Themes.findObjectByName_ = function(objects, objectName) { var obj = objects.find(function(object) { return object['name'] === objectName; }); @@ -156,186 +335,13 @@ exports.findObjectByName_ = function(objects, objectName) { * @return {Object} The theme object. * @private */ -exports.findTheme_ = function(themes, themeName) { - var theme = exports.findObjectByName_(themes, themeName); +Themes.findTheme_ = function(themes, themeName) { + var theme = Themes.findObjectByName_(themes, themeName); return theme; }; -/** - * Get background layers. - * @return {Promise} Promise. - */ -exports.prototype.getBgLayers = function(map) { - console.assert(this.promise_); - console.assert(map); - if (!this.getBgLayersPromise_) { - this.getBgLayersPromise_ = this.promise_.then( - /** - * @param {app.ThemesResponse} data The "themes" web service response. - * @return {Array.} Array of background layer objects. - */ - data => { - var bgLayers = data['background_layers'].map(item => { - var hasRetina = !!item['metadata']['hasRetina'] && this.isHiDpi_; - console.assert('name' in item); - console.assert('imageType' in item); - var layer = this.getWmtsLayer_( - item['name'], item['imageType'], hasRetina - ); - layer.set('metadata', item['metadata']); - if ('attribution' in item['metadata']) { - var source = layer.getSource(); - source.setAttributions( - item['metadata']['attribution'] - ); - } - return layer; - }); - - // add the blank layer - bgLayers.push(this.blankLayer_.getLayer()); - - // add MVT layer - const bothPromises = Promise.all([ - onFirstTargetChange(map), - this.appMvtStylingService_.getBgStyle() - ]); - return bothPromises.then(([target, styleConfigs]) => { - replaceWithMVTLayer(bgLayers, target, styleConfigs); - return bgLayers; - }); - }); - } - return this.getBgLayersPromise_; -}; - -/** - * Get a theme object by its name. - * @param {string} themeName Theme name. - * @return {angular.$q.Promise} Promise. - */ -exports.prototype.getThemeObject = function(themeName) { - console.assert(this.promise_ !== null); - return this.promise_.then( - /** - * @param {app.ThemesResponse} data The "themes" web service response. - * @return {Object} The theme object for themeName, or null if not found. - */ - function(data) { - var themes = data['themes']; - return exports.findTheme_(themes, themeName); - }); -}; - - -/** - * Get the promise resolving to the themes root object. - * @return {angular.$q.Promise} Promise. - */ -exports.prototype.getThemesPromise = function() { - console.assert(this.promise_ !== null); - return this.promise_; -}; - - -/** - * @param {?number} roleId The role id to send in the request. - * Load themes from the "themes" service. - * @return {?angular.$q.Promise} Promise. - */ -exports.prototype.loadThemes = function(roleId) { - this.promise_ = this.$http_.get(this.treeUrl_, { - params: (roleId !== undefined) ? {'role': roleId} : {}, - cache: false - }).then((resp) => { - const root = /** @type {app.ThemesResponse} */ (resp.data); - const themes = root.themes; - const flatCatalogue = []; - for (var i = 0; i < themes.length; i++) { - const theme = themes[i]; - const children = this.getAllChildren_(theme.children, theme.name, root.ogcServers); - arrayExtend(flatCatalogue, children); - } - - this.flatCatalog = flatCatalogue; - - this.dispatchEvent(appEventsThemesEventType.LOAD); - return root; - }); - return this.promise_; -}; - - -/** - * @param {string} themeId The theme id to send in the request. - * checks if the theme is protected or not. - * @return {angular.$q.Promise} Promise. - */ -exports.prototype.isThemePrivate = function(themeId) { - return this.$http_.get(this.isThemePrivateUrl_, { - params: {'theme': themeId}, - cache: false - }); -}; - - -/** - * @param {Array} element The element. - * @param {string} theme Theme name. - * @param {Object} ogcServers All OGC servers definitions. - * @param {Object} lastOgcServer The last OGC server. - * @return {Array} array The children. - * @private - */ -exports.prototype.getAllChildren_ = function(elements, theme, ogcServers, lastOgcServer) { - var array = []; - for (var i = 0; i < elements.length; i++) { - const element = elements[i]; - if (element.hasOwnProperty('children')) { - if (element.name !== '3d Layers') { - arrayExtend(array, this.getAllChildren_( - element.children, theme, ogcServers, element.ogcServer || lastOgcServer)); - } else { - arrayExtend(this.layers3D, this.getAllChildren_( - element.children, theme, ogcServers, element.ogcServer || lastOgcServer)); - } - } else { - // Rewrite url to match the behaviour of c2cgeoportal 1.6 - const ogcServer = element.ogcServer || lastOgcServer; - if (ogcServer) { - const def = ogcServers[ogcServer]; - if (def === undefined) { - element.url = null; - } else { - element.url = def.credential ? null : def.url; - } - } - element.theme = theme; - array.push(element); - } - } - return array; -}; - - -/** - * get the flat catlog - * @return {angular.$q.Promise} Promise. - */ -exports.prototype.getFlatCatalog = function() { - return this.promise_.then(() => this.flatCatalog); -}; - -/** - * get the flat catlog - * @return {angular.$q.Promise} Promise. - */ -exports.prototype.get3DLayers = function() { - return this.promise_.then(() => this.layers3D); -}; - -appModule.service('appThemes', exports); +appModule.service('appThemes', Themes); -export default exports; +export default Themes; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/UserManager.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/UserManager.js index b162db197..19724ffac 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/UserManager.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/UserManager.js @@ -20,16 +20,10 @@ import ngeoOfflineServiceManager from 'ngeo/offline/ServiceManager.js'; * @param {string} getuserinfoUrl The url to get information about the user. * @param {app.Notify} appNotify Notify service. * @param {angularGettext.Catalog} gettextCatalog Gettext service. - * @param {string} appAuthtktCookieName The authentication cookie name. * @ngInject */ const exports = function($http, $rootScope, loginUrl, logoutUrl, - getuserinfoUrl, appNotify, gettextCatalog, appAuthtktCookieName) { - /** - * @type {string} - * @private - */ - this.appAuthtktCookieName_ = appAuthtktCookieName; + getuserinfoUrl, appNotify, gettextCatalog) { /** * @type {ngeo.offline.Mode} @@ -142,7 +136,17 @@ exports.prototype.authenticate = function(username, password) { return this.http_.post(this.loginUrl_, req, config).then( response => { if (response.status == 200) { - this.getUserInfo(); + this.setUserInfo( + response.data['login'], + response.data['role'], + response.data['role_id'], + response.data['mail'], + response.data['sn'], + response.data['mymaps_role'], + response.data['is_admin'], + response.data['typeUtilisateur'] + ); + this.$rootScope.$broadcast('authenticated'); var msg = this.gettextCatalog.getString( 'Vous êtes maintenant correctement connecté.'); this.notify_(msg, appNotifyNotificationType.INFO); @@ -208,7 +212,8 @@ exports.prototype.getUserInfo = function() { response.data['mail'], response.data['sn'], response.data['mymaps_role'], - response.data['is_admin'] + response.data['is_admin'], + response.data['typeUtilisateur'] ); this.$rootScope.$broadcast('authenticated'); } else { @@ -231,7 +236,7 @@ exports.prototype.isAuthenticated = function() { return true; } - if (this.hasCookie(this.appAuthtktCookieName_)) { + if (this.getUsername()) { return this.username.length > 0; } @@ -245,7 +250,7 @@ exports.prototype.isAuthenticated = function() { * of error. */ exports.prototype.clearUserInfo = function() { - this.setUserInfo('', undefined, null, undefined, undefined, null, false); + this.setUserInfo('', undefined, null, undefined, undefined, null, false, 'prive'); }; @@ -257,9 +262,10 @@ exports.prototype.clearUserInfo = function() { * @param {string|undefined} name Name. * @param {?number} mymapsRole The role used by mymaps. * @param {boolean} isAdmin True if is a mymaps admin. + * @param {string|undefined} typeUtilisateur type of user. */ exports.prototype.setUserInfo = function( - username, role, roleId, mail, name, mymapsRole, isAdmin) { + username, role, roleId, mail, name, mymapsRole, isAdmin, typeUtilisateur) { if (username !== undefined) { this.username = username; this.role = role; @@ -268,6 +274,7 @@ exports.prototype.setUserInfo = function( this.name = name; this.mymapsRole = mymapsRole; this.isMymapsAdmin = isAdmin; + this.typeUtilisateur = typeUtilisateur; } else { this.clearUserInfo(); } @@ -287,6 +294,13 @@ exports.prototype.getEmail = function() { return this.email; }; +/** + * @return {string|undefined} The user type. + */ +exports.prototype.getUserType = function() { + return this.typeUtilisateur; +}; + /** * @return {?number} The Role Id. */ @@ -308,25 +322,6 @@ exports.prototype.getMymapsAdmin = function() { return this.isMymapsAdmin; }; -/** - * @param {string} cname The cookie name. - * @return {boolean} True if the cookie exists. - */ -exports.prototype.hasCookie = function(cname) { - var name = cname + '='; - var ca = document.cookie.split(';'); - for (var i = 0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0) === ' ') { - c = c.substring(1); - } - if (c.indexOf(name) === 0) { - return true; - } - } - return false; -}; - appModule.service('appUserManager', exports); diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/MainController.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/MainController.js index 6ec0de549..043b620d7 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/MainController.js +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/MainController.js @@ -41,6 +41,9 @@ import {transform, transformExtent} from 'ol/proj.js'; import {toRadians} from 'ol/math.js'; import {listen} from 'ol/events.js'; import {isValidSerial} from '../utils.js'; +import MaskLayer from 'ngeo/print/Mask.js'; + +import bootstrapApp from './bootstrap.js'; import '../../less/geoportailv3.less'; @@ -876,7 +879,7 @@ const MainController = function( * @type {function} */ this.selectedLayersLength = function() { - return this.selectedLayers.filter(l => !l.get('metadata').hidden).length + return this.selectedLayers.filter(l => l.get('metadata') && !l.get('metadata').hidden).length } /** @@ -1317,6 +1320,10 @@ MainController.prototype.enable3dCallback_ = function(active) { } this.appMvtStylingService.publishIfSerial(this.map_); + var piwik = /** @type {Piwik} */ (this.window_['_paq']); + piwik.push(['setDocumentTitle', 'enable3d']); + piwik.push(['trackPageView']); + this['drawOpen'] = false; this['drawOpenMobile'] = false; this['measureOpen'] = false; @@ -1387,6 +1394,7 @@ MainController.prototype.createMap_ = function() { minZoom: 8, enableRotation: true, extent: this.maxExtent_, + constrainResolution: true, rotation, }) }); @@ -1482,6 +1490,9 @@ MainController.prototype.manageSelectedLayers_ = if (layer instanceof LayerGroup && layer.get('groupName') === 'background') { return false; } + if (layer instanceof MaskLayer) { + return false; + } return this.map_.getLayers().getArray().indexOf(layer) !== 0; }.bind(this) ); @@ -1707,10 +1718,10 @@ MainController.prototype.initMymaps_ = function() { size: /** @type {ol.Size} */ (this.map_.getSize()) }); } - var layer = this.drawnFeatures_.getLayer(); - if (this.map_.getLayers().getArray().indexOf(layer) === -1) { - this.map_.addLayer(layer); - } + // var layer = this.drawnFeatures_.getLayer(); + // if (this.map_.getLayers().getArray().indexOf(layer) === -1) { + // this.map_.addLayer(layer); + // } }.bind(this)); } else { this.appMymaps_.clear(); @@ -1816,5 +1827,6 @@ MainController.prototype.isDisconnectedOrOffline = function() { appModule.controller('MainController', MainController); +bootstrapApp(appModule); export default MainController; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/bootstrap.js b/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/bootstrap.js new file mode 100644 index 000000000..2022677b0 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/bootstrap.js @@ -0,0 +1,73 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018-2021 Camptocamp SA +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import $ from 'jquery'; +import angular from 'angular'; + +/** + * @private + * @hidden + * @param {angular.IModule} module The module + */ +function bootstrap(module) { + // Hack to make the bootstrap type check working with polyfill.io + const oldObjectToString = Object.prototype.toString; + if (!oldObjectToString.toString().includes('[native code]')) { + Object.prototype.toString = function () { + if (this === null) { + return '[object Null]'; + } + if (this === undefined) { + return '[object Undefined]'; + } + return oldObjectToString.call(this); + }; + } + + const interface_ = $('meta[name=interface]')[0].getAttribute('content'); + const dynamicUrl_ = $('meta[name=dynamicUrl]')[0].getAttribute('content'); + const dynamicUrl = `${dynamicUrl_}?interface=${interface_}&path=${encodeURIComponent(document.location.pathname)}`; + const request = $.ajax(dynamicUrl, { + 'dataType': 'json', + 'xhrFields': { + withCredentials: false, + }, + }); + request.fail((jqXHR, textStatus) => { + window.alert(`Failed to get the dynamic: ${textStatus}`); + }); + request.done((dynamic) => { + if (dynamic.doRedirect) { + const small_screen = window.matchMedia ? window.matchMedia('(max-width: 1024px)') : false; + if (small_screen && 'ontouchstart' in window) { + window.location.href = dynamic.redirectUrl; + } + } + + for (const name in dynamic.constants) { + module.constant(name, dynamic.constants[name]); + } + + angular.bootstrap(document, [`App${interface_}`]); + }); +} + +export default bootstrap; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/main.html.ejs b/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/main.html.ejs index 09b784d75..f084a401b 100644 --- a/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/main.html.ejs +++ b/geoportal/geoportailv3_geoportal/static-ngeo/js/apps/main.html.ejs @@ -1,5 +1,5 @@ - + @@ -9,6 +9,8 @@ + + " /> <% for (var css in htmlWebpackPlugin.files.css) { %> @@ -453,7 +455,6 @@ <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> <% } %> - + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/Controller.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/Controller.js new file mode 100644 index 000000000..55a7344b8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/Controller.js @@ -0,0 +1,194 @@ +/** + * @module app.desktop_alt.Controller + */ +/** + * Application entry point. + * + * This file includes `goog.require`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import gmfControllersAbstractDesktopController from 'gmf/controllers/AbstractDesktopController.js'; +import './less/main.less'; +import appBase from '../appmodule.js'; +import gmfImportModule from 'gmf/import/module.js'; +import ngeoGooglestreetviewModule from 'ngeo/googlestreetview/module.js'; +import ngeoRoutingModule from 'ngeo/routing/module.js'; +import ngeoProjEPSG2056 from 'ngeo/proj/EPSG2056.js'; +import ngeoProjEPSG21781 from 'ngeo/proj/EPSG21781.js'; +import ngeoStatemanagerWfsPermalink from 'ngeo/statemanager/WfsPermalink.js'; +import * as olBase from 'ol/index.js'; +import {Circle, Fill, Stroke, Style} from 'ol/style'; +import Raven from 'raven-js/src/raven.js'; +import RavenPluginsAngular from 'raven-js/plugins/angular.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. Sie werden weitergeleitet.'); + window.location = 'http://geomapfish.org/'; +} + +/** + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @param {ngeo.misc.File} ngeoFile The file service. + * @param {gettext} gettext The gettext service + * @param {angular.$q} $q Angular $q. + * @constructor + * @extends {gmf.controllers.AbstractDesktopController} + * @ngInject + * @export + */ +const exports = function($scope, $injector, ngeoFile, gettext, $q) { + gmfControllersAbstractDesktopController.call(this, { + srid: 21781, + mapViewConfig: { + center: [632464, 185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {Array.} + * @export + */ + this.searchCoordinatesProjections = [ngeoProjEPSG21781, ngeoProjEPSG2056, 'EPSG:4326']; + + /** + * @type {number} + * @export + */ + this.searchDelay = 500; + + /** + * @type {boolean} + * @export + */ + this.showInfobar = true; + + /** + * @type {!Array.} + * @export + */ + this.scaleSelectorValues = [250000, 100000, 50000, 20000, 10000, 5000, 2000, 1000, 500, 250, 100, 50]; + + /** + * @type {Array.} + * @export + */ + this.elevationLayers = ['srtm']; + + /** + * @type {Object.} + * @export + */ + this.elevationLayersConfig = {}; + + /** + * @type {Object.} + * @export + */ + this.profileLinesconfiguration = { + 'srtm': {} + }; + + /** + * @type {Array.} + * @export + */ + this.mousePositionProjections = [{ + code: 'EPSG:2056', + label: 'CH1903+ / LV95', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:21781', + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + /** + * @type {gmfx.GridMergeTabs} + * @export + */ + this.gridMergeTabs = { + 'OSM_time_merged': ['osm_time', 'osm_time2'], + 'transport (merged)': ['fuel', 'parking'], + 'Learning [merged]': ['information', 'bus_stop'] + }; + + const radius = 5; + const fill = new Fill({color: [255, 255, 255, 0.6]}); + const stroke = new Stroke({color: [255, 0, 0, 1], width: 2}); + const image = new Circle({fill, radius, stroke}); + const default_search_style = new Style({ + fill, + image, + stroke + }); + + /** + * @type {Object.} Map of styles for search overlay. + * @export + */ + this.searchStyles = { + 'default': default_search_style + }; + + // Allow angular-gettext-tools to collect the strings to translate + /** @type {angularGettext.Catalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + gettextCatalog.getString('OSM_time_merged'); + gettextCatalog.getString('OSM_time (merged)'); + gettextCatalog.getString('Learning [merged]'); + gettextCatalog.getString('Add a theme'); + gettextCatalog.getString('Add a sub theme'); + gettextCatalog.getString('Add a layer'); + + /** + * @type {string} + * @export + */ + this.bgOpacityOptions = 'Test aus Olten'; + + if ($injector.has('sentryUrl')) { + const options = $injector.has('sentryOptions') ? $injector.get('sentryOptions') : undefined; + const raven = new Raven(); + raven.config($injector.get('sentryUrl'), options) + .addPlugin(RavenPluginsAngular) + .install(); + } +}; + +olBase.inherits(exports, gmfControllersAbstractDesktopController); + + +/** + * @param {jQuery.Event} event keydown event. + * @export + */ +exports.prototype.onKeydown = function(event) { + if (event.ctrlKey && event.key === 'p') { + this.printPanelActive = true; + event.preventDefault(); + } +}; + + +exports.module = angular.module('Appdesktop_alt', [ + appBase.module.name, + gmfControllersAbstractDesktopController.module.name, + gmfImportModule.name, + ngeoRoutingModule.name, + ngeoGooglestreetviewModule.name, + ngeoStatemanagerWfsPermalink.module.name, +]); + +exports.module.controller('AlternativeDesktopController', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/background-layer-button.png b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/background-layer-button.png new file mode 100644 index 000000000..46767ce30 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/background-layer-button.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/favicon.ico b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/favicon.ico new file mode 100644 index 000000000..2eb150037 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/favicon.ico differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/logo.png b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/logo.png new file mode 100644 index 000000000..a07d43d5b Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/image/logo.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/index.html.ejs b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/index.html.ejs new file mode 100644 index 000000000..fcbc8607a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/index.html.ejs @@ -0,0 +1,369 @@ + + + + GeoMapFish + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + +
+ +
+
+ +
+
+
+ + + + + + + + + +
+
+
+ + + +
+
+
+
+
+ {{'Login' | translate}} + × +
+ + +
+
+
+
+
+ {{'Print' | translate}} + × +
+ + +
+ +
+
+
+
+
+
+
+
+ {{'Draw and Measure'|translate}} + × +
+ + +
+
+
+
+
+ {{'Filter'|translate}} + × +
+ + +
+
+
+
+
+ {{'Editing'|translate}} + × +
+
+
+ {{'In order to use the editing tool, you must log in first.' | translate}} +
+ + +
+
+
+
+
+
+ {{'Profile'|translate}} + × +
+
+

+ +

+

+ + Draw a line on the map to display the corresponding elevation profile. + Use double-click to finish the drawing. + +

+
+
+
+
+
+
+ {{'Street View'|translate}} + × +
+ + +
+
+
+
+
+ {{'Import Layer'|translate}} + × +
+ + +
+
+
+
+
+ {{'Routing'|translate}} + × +
+ + +
+
+
+
+
+ + + +
+
+ + + +
+
+ + +
+
+ + + + + +
+ + + + + + + +
+
+ + + + + +
+ + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/less/main.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/less/main.less new file mode 100644 index 000000000..23c2259df --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/less/main.less @@ -0,0 +1,17 @@ +@import '~gmf/controllers/desktop.less'; + +.gmf-theme-selector li { + flex-direction: column; +} + +.gmf-layertree-node .gmf-layertree-legend { + border: none; + background-color: transparent; +} + +div .ngeo-displaywindow { + @displaywindow-min-height: 24rem; + left: @app-margin + @left-panel-width + @displaywindow-min-height / 2; + right: initial; + top: @topbar-height + @app-margin + 3 * @map-tools-size; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/less/theme.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/less/theme.less new file mode 100644 index 000000000..b6e5300df --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/less/theme.less @@ -0,0 +1,6 @@ +@import '~gmf/controllers/desktop-theme.less'; + +@brand-primary: #9FB6CC; +@brand-secondary: #D3DBE3; + +@theme-selector-columns: 3; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/simple.kml b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/simple.kml new file mode 100644 index 000000000..0eb90bc43 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/desktop_alt/simple.kml @@ -0,0 +1,17 @@ + + + + + + + 6.56021,46.51320,300 + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/Controller.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/Controller.js new file mode 100644 index 000000000..f5a88f356 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/Controller.js @@ -0,0 +1,79 @@ +/** + * @module app.mobile.Controller + */ +/** + * Application entry point. + * + * This file includes `goog.require`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import gmfControllersAbstractMobileController from 'gmf/controllers/AbstractMobileController.js'; +import 'gmf/controllers/mobile.less'; +import appBase from '../appmodule.js'; +import ngeoProjEPSG2056 from 'ngeo/proj/EPSG2056.js'; +import ngeoProjEPSG21781 from 'ngeo/proj/EPSG21781.js'; +import * as olBase from 'ol/index.js'; +import Raven from 'raven-js/src/raven.js'; +import RavenPluginsAngular from 'raven-js/plugins/angular.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. Sie werden weitergeleitet.'); + window.location = 'http://geomapfish.org/'; +} + +/** + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @constructor + * @extends {gmf.controllers.AbstractMobileController} + * @ngInject + * @export + */ +const exports = function($scope, $injector) { + gmfControllersAbstractMobileController.call(this, { + autorotate: false, + srid: 21781, + mapViewConfig: { + center: [632464, 185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {Array.} + * @export + */ + this.elevationLayersConfig = [ + {name: 'aster', unit: 'm'}, + {name: 'srtm', unit: 'm'} + ]; + + /** + * @type {Array.} + * @export + */ + this.searchCoordinatesProjections = [ngeoProjEPSG21781, ngeoProjEPSG2056, 'EPSG:4326']; + + if ($injector.has('sentryUrl')) { + const options = $injector.has('sentryOptions') ? $injector.get('sentryOptions') : undefined; + const raven = new Raven(); + raven.config($injector.get('sentryUrl'), options) + .addPlugin(RavenPluginsAngular) + .install(); + } +}; + +olBase.inherits(exports, gmfControllersAbstractMobileController); + +exports.module = angular.module('Appmobile', [ + appBase.module.name, + gmfControllersAbstractMobileController.module.name, +]); + +exports.module.controller('MobileController', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/image/favicon.ico b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/image/favicon.ico new file mode 100644 index 000000000..2eb150037 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/image/favicon.ico differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/index.html.ejs b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/index.html.ejs new file mode 100644 index 000000000..7d2cbbaa0 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile/index.html.ejs @@ -0,0 +1,188 @@ + + + + GeoMapFish + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + +
+ + + +
+
+
+
+ + + + +
+
+
+ + +
+ + +
+
+ + + + + + + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/Controller.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/Controller.js new file mode 100644 index 000000000..090693602 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/Controller.js @@ -0,0 +1,117 @@ +/** + * @module app.mobile_alt.Controller + */ +/** + * Application entry point. + * + * This file includes `goog.require`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import gmfControllersAbstractMobileController from 'gmf/controllers/AbstractMobileController.js'; +import './less/main.less'; +import appBase from '../appmodule.js'; +import ngeoProjEPSG2056 from 'ngeo/proj/EPSG2056.js'; +import ngeoProjEPSG21781 from 'ngeo/proj/EPSG21781.js'; +import * as olBase from 'ol/index.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleRegularShape from 'ol/style/RegularShape.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; +import Raven from 'raven-js/src/raven.js'; +import RavenPluginsAngular from 'raven-js/plugins/angular.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. Sie werden weitergeleitet.'); + window.location = 'http://geomapfish.org/'; +} + +/** + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @constructor + * @extends {gmf.controllers.AbstractMobileController} + * @ngInject + * @export + */ +const exports = function($scope, $injector) { + gmfControllersAbstractMobileController.call(this, { + autorotate: true, + mapPixelRatio: 1, + srid: 21781, + mapViewConfig: { + center: [632464, 185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {Array.} + * @export + */ + this.elevationLayersConfig = [ + {name: 'aster', unit: 'm'}, + {name: 'srtm', unit: 'm'} + ]; + + /** + * @type {number} + * @export + */ + this.searchDelay = 50; + + /** + * @type {Array.} + * @export + */ + this.searchCoordinatesProjections = [ngeoProjEPSG21781, ngeoProjEPSG2056, 'EPSG:4326']; + + + /** + * @type {ol.style.Style} + * @export + */ + this.customMeasureStyle = new olStyleStyle({ + fill: new olStyleFill({ + color: 'rgba(255, 128, 128, 0.2)' + }), + stroke: new olStyleStroke({ + color: 'rgba(255, 0, 0, 0.5)', + lineDash: [10, 10], + width: 2 + }), + image: new olStyleRegularShape({ + stroke: new olStyleStroke({ + color: 'rgba(255, 0, 0, 0.7)', + width: 2 + }), + points: 4, + radius: 8, + radius2: 0, + angle: 0 + }) + }); + + if ($injector.has('sentryUrl')) { + const options = $injector.has('sentryOptions') ? $injector.get('sentryOptions') : undefined; + const raven = new Raven(); + raven.config($injector.get('sentryUrl'), options) + .addPlugin(RavenPluginsAngular) + .install(); + } +}; + +olBase.inherits(exports, gmfControllersAbstractMobileController); + + +exports.module = angular.module('Appmobile_alt', [ + appBase.module.name, + gmfControllersAbstractMobileController.module.name, +]); + +exports.module.controller('AlternativeMobileController', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/image/favicon.ico b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/image/favicon.ico new file mode 100644 index 000000000..2eb150037 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/image/favicon.ico differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/index.html.ejs b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/index.html.ejs new file mode 100644 index 000000000..6c179c916 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/index.html.ejs @@ -0,0 +1,183 @@ + + + + GeoMapFish + + + + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + +
+ + + +
+
+
+
+ + + + +
+
+
+ + +
+ + +
+
+ + + + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/less/main.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/less/main.less new file mode 100644 index 000000000..42e9f962b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/mobile_alt/less/main.less @@ -0,0 +1,11 @@ +@import '~gmf/controllers/mobile.less'; + +#themes .gmf-theme-selector { + display: flex; + flex-wrap: wrap; + + li { + flex-direction: column; + flex-basis: 50%; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/Controller.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/Controller.js new file mode 100644 index 000000000..3f73afd11 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/Controller.js @@ -0,0 +1,240 @@ +/** + * @module app.oeedit.Controller + */ +/** + * Application entry point. + * + * This file includes `goog.require`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import gmfControllersAbstractDesktopController from 'gmf/controllers/AbstractDesktopController.js'; +import './less/main.less'; +import appBase from '../appmodule.js'; +import gmfObjecteditingModule from 'gmf/objectediting/module.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoProjEPSG2056 from 'ngeo/proj/EPSG2056.js'; +import ngeoProjEPSG21781 from 'ngeo/proj/EPSG21781.js'; +import * as olBase from 'ol/index.js'; +import olCollection from 'ol/Collection.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olSourceVector from 'ol/source/Vector.js'; +import Raven from 'raven-js/src/raven.js'; +import RavenPluginsAngular from 'raven-js/plugins/angular.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. Sie werden weitergeleitet.'); + window.location = 'http://geomapfish.org/'; +} + +/** + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @param {angular.$timeout} $timeout Angular timeout service. + * @constructor + * @extends {gmf.controllers.AbstractDesktopController} + * @ngInject + * @export + */ +const exports = function($scope, $injector, $timeout) { + + /** + * @type {boolean} + * @export + */ + this.oeEditActive = false; + + gmfControllersAbstractDesktopController.call(this, { + srid: 21781, + mapViewConfig: { + center: [632464, 185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * The ngeo ToolActivate manager service. + * @type {ngeo.misc.ToolActivateMgr} + */ + const ngeoToolActivateMgr = $injector.get('ngeoToolActivateMgr'); + + ngeoToolActivateMgr.unregisterGroup('mapTools'); + + const oeEditToolActivate = new ngeoMiscToolActivate(this, 'oeEditActive'); + ngeoToolActivateMgr.registerTool('mapTools', oeEditToolActivate, true); + + const queryToolActivate = new ngeoMiscToolActivate(this, 'queryActive'); + ngeoToolActivateMgr.registerTool('mapTools', queryToolActivate, false); + + // Set edit tool as default active one + $timeout(() => { + this.oeEditActive = true; + }); + + /** + * @type {ol.source.Vector} + * @private + */ + this.vectorSource_ = new olSourceVector({ + wrapX: false + }); + + /** + * @type {ol.layer.Vector} + * @private + */ + this.vectorLayer_ = new olLayerVector({ + source: this.vectorSource_ + }); + + /** + * @type {ol.Collection.} + * @export + */ + this.sketchFeatures = new olCollection(); + + /** + * @type {ol.layer.Vector} + * @private + */ + this.sketchLayer_ = new olLayerVector({ + source: new olSourceVector({ + features: this.sketchFeatures, + wrapX: false + }) + }); + + /** + * @type {gmf.theme.Themes} gmfObjectEditingManager The gmf theme service + */ + const gmfThemes = $injector.get('gmfThemes'); + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + // Add layer vector after + this.map.addLayer(this.vectorLayer_); + this.map.addLayer(this.sketchLayer_); + } + }); + + /** + * @type {gmf.objectediting.Manager} gmfObjectEditingManager The gmf + * ObjectEditing manager service. + */ + const gmfObjectEditingManager = $injector.get('gmfObjectEditingManager'); + + /** + * @type {string|undefined} + * @export + */ + this.oeGeomType = gmfObjectEditingManager.getGeomType(); + + /** + * @type {number|undefined} + * @export + */ + this.oeLayerNodeId = gmfObjectEditingManager.getLayerNodeId(); + + /** + * @type {?ol.Feature} + * @export + */ + this.oeFeature = null; + + gmfObjectEditingManager.getFeature().then((feature) => { + this.oeFeature = feature; + if (feature) { + this.vectorSource_.addFeature(feature); + } + }); + + /** + * @type {Array.} + * @export + */ + this.searchCoordinatesProjections = [ngeoProjEPSG21781, ngeoProjEPSG2056, 'EPSG:4326']; + + /** + * @type {!Array.} + * @export + */ + this.scaleSelectorValues = [250000, 100000, 50000, 20000, 10000, 5000, 2000, 1000, 500, 250, 100, 50]; + + /** + * @type {Array.} + * @export + */ + this.elevationLayers = ['aster', 'srtm']; + + /** + * @type {string} + * @export + */ + this.selectedElevationLayer = this.elevationLayers[0]; + + /** + * @type {Object.} + * @export + */ + this.profileLinesconfiguration = { + 'aster': {color: '#0000A0'}, + 'srtm': {color: '#00A000'} + }; + + /** + * @type {Array.} + * @export + */ + this.mousePositionProjections = [{ + code: ngeoProjEPSG2056, + label: 'CH1903+ / LV95', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: ngeoProjEPSG21781, + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + // Allow angular-gettext-tools to collect the strings to translate + /** @type {angularGettext.Catalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + gettextCatalog.getString('Add a theme'); + gettextCatalog.getString('Add a sub theme'); + gettextCatalog.getString('Add a layer'); + + if ($injector.has('sentryUrl')) { + const options = $injector.has('sentryOptions') ? $injector.get('sentryOptions') : undefined; + const raven = new Raven(); + raven.config($injector.get('sentryUrl'), options) + .addPlugin(RavenPluginsAngular) + .install(); + } +}; + +olBase.inherits(exports, gmfControllersAbstractDesktopController); + +exports.module = angular.module('Appoeedit', [ + appBase.module.name, + gmfControllersAbstractDesktopController.module.name, + gmfObjecteditingModule.name, +]); + +exports.module.value('gmfContextualdatacontentTemplateUrl', 'gmf/contextualdata'); +exports.module.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/contextualdata', require('./contextualdata.html')); +}); + +exports.module.value('gmfPermalinkOptions', /** @type {gmfx.PermalinkOptions} */ ({ + pointRecenterZoom: 10 +})); + +exports.module.controller('OEEditController', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/contextualdata.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/contextualdata.html new file mode 100644 index 000000000..e45bae255 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/contextualdata.html @@ -0,0 +1,43 @@ +
+ + + + + + + + + + + + + + + + + + + + +
+ Swiss grid (LV03) + + {{coord_21781|ngeoNumberCoordinates:0:'{x} / {y}'}} +
+ Wgs Coord. + + {{coord_4326|ngeoNumberCoordinates:2:'{y} / {x}'}} +
+ Wgs Coord. DMS + + {{coord_4326|ngeoDMSCoordinates:0:'{y} {x}'}} +
+ Elevation (SRTM) + + {{srtm | number}} [m] +
+ Elevation (Aster) + + {{aster | number}} [m] +
+Google StreetView diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/background-layer-button.png b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/background-layer-button.png new file mode 100644 index 000000000..46767ce30 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/background-layer-button.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/favicon.ico b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/favicon.ico new file mode 100644 index 000000000..2eb150037 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/favicon.ico differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/logo.png b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/logo.png new file mode 100644 index 000000000..a07d43d5b Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/image/logo.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/index.html.ejs b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/index.html.ejs new file mode 100644 index 000000000..df53979f6 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/index.html.ejs @@ -0,0 +1,185 @@ + + + + GeoMapFish + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + +
+ +
+
+ +
+
+
+ + +
+
+
+
+
+
+ {{'Query' | translate}} + × +
+ Query +
+
+
+
+
+ {{'Object Editing' | translate}} + × +
+ + +
+
+
+
+
+ + +
+
+ + + +
+
+ + +
+ + +
+ + + + + +
+ + + +
+
+ + +
+ + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/less/main.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/less/main.less new file mode 100644 index 000000000..aa8ecd865 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeedit/less/main.less @@ -0,0 +1,14 @@ +@import '~gmf/controllers/desktop.less'; + +.gmf-displayquerywindow { + width: 36rem; + max-width: 36rem; +} + +.gmf-displayquerywindow .details { + overflow-x: auto; +} + +::-webkit-scrollbar { + height: @half-app-margin; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/Controller.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/Controller.js new file mode 100644 index 000000000..b0697747b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/Controller.js @@ -0,0 +1,126 @@ +/** + * @module app.oeview.Controller + */ +/** + * Application entry point. + * + * This file includes `goog.require`'s for all the components/directives used + * by the HTML page and the controller to provide the configuration. + */ + +import gmfControllersAbstractDesktopController from 'gmf/controllers/AbstractDesktopController.js'; +import './less/main.less'; +import appBase from '../appmodule.js'; +import ngeoProjEPSG2056 from 'ngeo/proj/EPSG2056.js'; +import ngeoProjEPSG21781 from 'ngeo/proj/EPSG21781.js'; +import * as olBase from 'ol/index.js'; +import Raven from 'raven-js/src/raven.js'; +import RavenPluginsAngular from 'raven-js/plugins/angular.js'; + +if (!window.requestAnimationFrame) { + alert('Your browser is not supported, please update it or use another one. You will be redirected.\n\n' + + 'Votre navigateur n\'est pas supporté, veuillez le mettre à jour ou en utiliser un autre. Vous allez être redirigé.\n\n' + + 'Ihr Browser wird nicht unterstützt, bitte aktualisieren Sie ihn oder verwenden Sie einen anderen. Sie werden weitergeleitet.'); + window.location = 'http://geomapfish.org/'; +} + +/** + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @constructor + * @extends {gmf.controllers.AbstractDesktopController} + * @ngInject + * @export + */ +const exports = function($scope, $injector) { + gmfControllersAbstractDesktopController.call(this, { + srid: 21781, + mapViewConfig: { + center: [632464, 185457], + zoom: 3, + resolutions: [250, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05] + } + }, $scope, $injector); + + /** + * @type {Array.} + * @export + */ + this.searchCoordinatesProjections = [ngeoProjEPSG21781, ngeoProjEPSG2056, 'EPSG:4326']; + + /** + * @type {!Array.} + * @export + */ + this.scaleSelectorValues = [250000, 100000, 50000, 20000, 10000, 5000, 2000, 1000, 500, 250, 100, 50]; + + /** + * @type {Array.} + * @export + */ + this.elevationLayers = ['aster', 'srtm']; + + /** + * @type {string} + * @export + */ + this.selectedElevationLayer = this.elevationLayers[0]; + + /** + * @type {Object.} + * @export + */ + this.profileLinesconfiguration = { + 'aster': {color: '#0000A0'}, + 'srtm': {color: '#00A000'} + }; + + /** + * @type {Array.} + * @export + */ + this.mousePositionProjections = [{ + code: ngeoProjEPSG2056, + label: 'CH1903+ / LV95', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: ngeoProjEPSG21781, + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates::{x}, {y} m' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + // Allow angular-gettext-tools to collect the strings to translate + /** @type {angularGettext.Catalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + gettextCatalog.getString('Add a theme'); + gettextCatalog.getString('Add a sub theme'); + gettextCatalog.getString('Add a layer'); + + if ($injector.has('sentryUrl')) { + const options = $injector.has('sentryOptions') ? $injector.get('sentryOptions') : undefined; + const raven = new Raven(); + raven.config($injector.get('sentryUrl'), options) + .addPlugin(RavenPluginsAngular) + .install(); + } +}; + +olBase.inherits(exports, gmfControllersAbstractDesktopController); + +exports.module = angular.module('Appoeview', [ + appBase.module.name, + gmfControllersAbstractDesktopController.module.name, +]); + +exports.module.value('gmfContextualdatacontentTemplateUrl', 'gmf/contextualdata'); +exports.module.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/contextualdata', require('./contextualdata.html')); +}); + +exports.module.controller('DesktopController', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/contextualdata.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/contextualdata.html new file mode 100644 index 000000000..e45bae255 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/contextualdata.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + +
+ Swiss grid (LV03) + + {{coord_21781|ngeoNumberCoordinates:0:'{x} / {y}'}} +
+ Wgs Coord. + + {{coord_4326|ngeoNumberCoordinates:2:'{y} / {x}'}} +
+ Wgs Coord. DMS + + {{coord_4326|ngeoDMSCoordinates:0:'{y} {x}'}} +
+ Elevation (SRTM) + + {{srtm | number}} [m] +
+ Elevation (Aster) + + {{aster | number}} [m] +
+Google StreetView diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/background-layer-button.png b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/background-layer-button.png new file mode 100644 index 000000000..46767ce30 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/background-layer-button.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/favicon.ico b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/favicon.ico new file mode 100644 index 000000000..2eb150037 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/favicon.ico differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/logo.png b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/logo.png new file mode 100644 index 000000000..a07d43d5b Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/image/logo.png differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/index.html.ejs b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/index.html.ejs new file mode 100644 index 000000000..54d594056 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/index.html.ejs @@ -0,0 +1,142 @@ + + + + GeoMapFish + + " /> + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + + +
+ +
+
+ +
+ + +
+
+ + + +
+
+ + +
+ + +
+ + + + + +
+ + + +
+
+ + +
+ + <% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + + <% } %> + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/less/main.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/less/main.less new file mode 100644 index 000000000..5075aa9c5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/apps/oeview/less/main.less @@ -0,0 +1 @@ +@import '~gmf/controllers/desktop.less'; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/css/reset.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/css/reset.css new file mode 100644 index 000000000..3ff35882a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/css/reset.css @@ -0,0 +1,48 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section, main { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/cursors/grab.cur b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/cursors/grab.cur new file mode 100644 index 000000000..c72cd91a0 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/cursors/grab.cur differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/cursors/grabbing.cur b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/cursors/grabbing.cur new file mode 100644 index 000000000..123dc2d34 Binary files /dev/null and b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/cursors/grabbing.cur differ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/.eslintrc.yaml b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/.eslintrc.yaml new file mode 100644 index 000000000..d535c4e37 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/.eslintrc.yaml @@ -0,0 +1,26 @@ +plugins: + - googshift + +rules: + googshift/no-duplicate-requires: error + + googshift/no-missing-requires: + - warn + - prefixes: [gmf, ngeo, ol] + + googshift/no-unused-requires: warn + + googshift/one-provide-or-module: + - warn + - entryPoints: [gmf] + root: src + + googshift/requires-first: error + + googshift/valid-provide-and-module: + - warn + - entryPoints: [gmfapp, ngeo] + root: fakeroot + replace: ../contribs/gmf/examples|gmfapp + + googshift/valid-requires: error diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.css new file mode 100644 index 000000000..fcba4bc1f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.css @@ -0,0 +1,5 @@ +gmf-authentication { + display: block; + padding: 10px; + width: 300px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.html new file mode 100644 index 000000000..9f2079097 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.html @@ -0,0 +1,17 @@ + + + + GeoMapFish Authentication example + + + + + +

+ This example shows how to use the gmf-authentication + directive to insert an authentication panel in a GeoMapFish page. +

+ + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.js new file mode 100644 index 000000000..84a8e21a3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/authentication.js @@ -0,0 +1,57 @@ +/** + * @module gmfapp.authentication + */ +const exports = {}; + +import './authentication.css'; +import gmfAuthenticationModule from 'gmf/authentication/module.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfAuthenticationModule.name +]); + + +exports.module.value( + 'authenticationBaseUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi'); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {angularGettext.Catalog} gettextCatalog Gettext catalog. + * @constructor + * @ngInject + */ +exports.MainController = function(gettextCatalog) { + /** + * A password validator that check if the password as: + * - A minimal length of 8 characteres. + * - At least one lowercase letter. + * - At least one Uppercase letter. + * - At least one digit. + * - At least one special character. + * @type {gmfx.PasswordValidator} the password validator + * @export + */ + this.passwordValidator = { + isPasswordValid: function(value) { + return ( + value.length > 8 && /\d/.test(value) && + /[a-z]/.test(value) && /[A-Z]/.test(value) && + /\W/.test(value) + ); + }, + notValidMessage: gettextCatalog.getString('The new password must have at least 8 characters,' + + 'including capital letter, small letter, digit and special character.') + }; +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.css new file mode 100644 index 000000000..317fccad9 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.css @@ -0,0 +1,31 @@ +gmf-map > div { + width: 50rem; + height: 30rem; +} +.gmf-backgroundlayerselector { + list-style: none; + margin: 0; + padding: 0; + width: 20rem; +} +.gmf-backgroundlayerselector li { + cursor: pointer; + margin: 0.2rem 0; + display: flex; + align-items: center; + padding: 0.5rem; + border: 0.1rem solid lightgrey; +} +.gmf-text { + flex: 1; +} +.gmf-thumb { + height: 60px; +} +li.gmf-backgroundlayerselector-active { + border: 0.1rem solid blue; +} +.gmf-backgroundlayerselector-active::after { + content: ' X'; + color: blue; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.html new file mode 100644 index 000000000..d52f63626 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.html @@ -0,0 +1,21 @@ + + + + GeoMapFish's background layer selector example + + + + + +

This example shows how to use the + gmf-backgroundlayerselector + directive to select the map background layer.

+
+ + +
+ + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.js new file mode 100644 index 000000000..916212d0e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/backgroundlayerselector.js @@ -0,0 +1,63 @@ +/** + * @module gmfapp.backgroundlayerselector + */ +const exports = {}; + +import './backgroundlayerselector.css'; +import gmfBackgroundlayerselectorModule from 'gmf/backgroundlayerselector/module.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfBackgroundlayerselectorModule.name, + gmfMapComponent.name, + gmfThemeThemes.module.name, +]); + + +exports.module.value( + 'gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?' + + 'version=2&background=background'); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {gmf.theme.Themes} gmfThemes Themes service. + * @constructor + * @ngInject + */ +exports.MainController = function(gmfThemes) { + + gmfThemes.loadThemes(); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [], + view: new olView({ + center: [632464, 185457], + projection: EPSG21781, + minZoom: 3, + zoom: 3 + }) + }); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/common_dependencies.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/common_dependencies.js new file mode 100644 index 000000000..bbe01498f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/common_dependencies.js @@ -0,0 +1,15 @@ +import 'jquery'; +import 'angular'; +import 'angular-gettext'; + +import 'ol/ol.css'; +import 'bootstrap/dist/css/bootstrap.css'; + +/* + * Auto redirect to https to prevent CORS exceptions + */ +if (window.location.protocol == 'http:' && window.location.hostname != 'localhost') { + const restOfUrl = window.location.href.substr(5); + /** @type {Location} */ + window.location = `https:${restOfUrl}`; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.css new file mode 100644 index 000000000..0197cd3fd --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.css @@ -0,0 +1,12 @@ +gmf-map > div { + width: 600px; + height: 400px; +} + +.gmf-contextualdata { + font-size: 0.8em; + width: 300px; +} +.gmf-contextualdata table { + width: 100%; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.html new file mode 100644 index 000000000..a5e2bd9ba --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.html @@ -0,0 +1,14 @@ + + + + Contextual Data GeoMapFish example + + + + + + +

This example shows how to use the gmf-contextualdata directive to display coordinates or data related to the point after a right click on the map.

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.js new file mode 100644 index 000000000..88ee01c70 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/contextualdata.js @@ -0,0 +1,81 @@ +/** + * @module gmfapp.contextualdata + */ +const exports = {}; + +import './contextualdata.css'; +/** @suppress {extraRequire} */ +import gmfContextualdataModule from 'gmf/contextualdata/module.js'; + +import gmfMapComponent from 'gmf/map/component.js'; +import ngeoMiscFilters from 'ngeo/misc/filters.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfContextualdataModule.name, + gmfMapComponent.name, + ngeoMiscFilters.name, +]); + + +exports.module.value( + 'gmfRasterUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/raster'); + +exports.module.value( + 'gmfContextualdatacontentTemplateUrl', + 'partials/contextualdata.html'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [600000, 200000], + zoom: 3 + }) + }); +}; + + +/** + * @param {ol.Coordinate} coordinate The coordinate for the right-clicked + * point. + * @param {Object} data The data received from the raster service. + * @return {Object} The additional data to add to the scope for the + * contextualdata popover. + */ +exports.MainController.prototype.onRasterData = function(coordinate, data) { + return { + 'elelvation_diff': data['srtm'] - data['aster'] + }; +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/example.gpx b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/example.gpx new file mode 100644 index 000000000..a65ca1c1b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/example.gpx @@ -0,0 +1,6871 @@ + + + + + + + Morning Run + + + 431.1 + + + + 431.0 + + + + 431.0 + + + + 430.9 + + + + 430.8 + + + + 430.7 + + + + 430.6 + + + + 430.6 + + + + 430.5 + + + + 430.5 + + + + 430.5 + + + + 430.4 + + + + 430.4 + + + + 430.3 + + + + 430.3 + + + + 430.1 + + + + 430.0 + + + + 429.8 + + + + 429.6 + + + + 429.3 + + + + 429.0 + + + + 428.7 + + + + 428.5 + + + + 428.2 + + + + 427.9 + + + + 427.7 + + + + 427.6 + + + + 427.6 + + + + 427.5 + + + + 427.6 + + + + 427.6 + + + + 427.6 + + + + 427.6 + + + + 427.7 + + + + 427.7 + + + + 427.7 + + + + 427.8 + + + + 427.8 + + + + 427.8 + + + + 428.0 + + + + 428.1 + + + + 428.3 + + + + 428.5 + + + + 428.8 + + + + 429.0 + + + + 429.2 + + + + 429.4 + + + + 429.5 + + + + 429.5 + + + + 429.6 + + + + 429.8 + + + + 429.9 + + + + 430.1 + + + + 430.1 + + + + 430.2 + + + + 430.5 + + + + 430.7 + + + + 430.4 + + + + 430.1 + + + + 429.9 + + + + 429.6 + + + + 429.4 + + + + 429.1 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.1 + + + + 429.4 + + + + 429.7 + + + + 429.9 + + + + 430.1 + + + + 430.3 + + + + 430.4 + + + + 430.6 + + + + 430.8 + + + + 431.0 + + + + 431.1 + + + + 431.4 + + + + 431.5 + + + + 431.7 + + + + 431.9 + + + + 432.1 + + + + 432.4 + + + + 432.5 + + + + 432.7 + + + + 432.8 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.3 + + + + 433.7 + + + + 434.1 + + + + 434.4 + + + + 434.7 + + + + 435.0 + + + + 435.2 + + + + 435.6 + + + + 436.0 + + + + 436.0 + + + + 435.9 + + + + 436.1 + + + + 436.4 + + + + 436.9 + + + + 437.2 + + + + 437.5 + + + + 437.7 + + + + 437.9 + + + + 438.1 + + + + 438.2 + + + + 438.3 + + + + 438.6 + + + + 438.7 + + + + 438.4 + + + + 437.9 + + + + 437.8 + + + + 437.8 + + + + 437.9 + + + + 438.1 + + + + 438.1 + + + + 438.0 + + + + 438.0 + + + + 437.9 + + + + 437.5 + + + + 437.2 + + + + 436.9 + + + + 436.5 + + + + 436.4 + + + + 436.2 + + + + 436.0 + + + + 435.8 + + + + 435.5 + + + + 435.2 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 434.9 + + + + 435.2 + + + + 435.2 + + + + 435.1 + + + + 434.9 + + + + 434.8 + + + + 434.5 + + + + 434.3 + + + + 434.1 + + + + 434.0 + + + + 433.9 + + + + 433.8 + + + + 433.7 + + + + 433.7 + + + + 433.7 + + + + 433.9 + + + + 434.1 + + + + 434.4 + + + + 434.9 + + + + 435.3 + + + + 435.6 + + + + 435.9 + + + + 436.4 + + + + 436.6 + + + + 436.8 + + + + 437.0 + + + + 437.1 + + + + 435.4 + + + + 433.6 + + + + 433.7 + + + + 433.9 + + + + 434.1 + + + + 434.3 + + + + 434.3 + + + + 434.4 + + + + 434.5 + + + + 434.6 + + + + 434.7 + + + + 434.8 + + + + 436.4 + + + + 436.9 + + + + 437.2 + + + + 437.5 + + + + 438.0 + + + + 438.0 + + + + 438.1 + + + + 438.1 + + + + 438.1 + + + + 438.0 + + + + 438.0 + + + + 437.8 + + + + 437.6 + + + + 437.5 + + + + 437.4 + + + + 437.3 + + + + 437.1 + + + + 436.9 + + + + 436.7 + + + + 436.6 + + + + 436.1 + + + + 435.7 + + + + 435.2 + + + + 434.9 + + + + 434.6 + + + + 434.0 + + + + 433.7 + + + + 433.7 + + + + 433.7 + + + + 433.9 + + + + 434.0 + + + + 434.2 + + + + 434.4 + + + + 434.6 + + + + 434.8 + + + + 435.0 + + + + 435.1 + + + + 435.2 + + + + 435.3 + + + + 435.1 + + + + 435.1 + + + + 435.0 + + + + 435.2 + + + + 435.5 + + + + 436.0 + + + + 436.2 + + + + 436.2 + + + + 436.3 + + + + 436.3 + + + + 436.4 + + + + 436.4 + + + + 436.5 + + + + 436.5 + + + + 436.5 + + + + 436.5 + + + + 436.5 + + + + 436.6 + + + + 436.6 + + + + 436.8 + + + + 437.0 + + + + 437.0 + + + + 437.4 + + + + 438.1 + + + + 438.3 + + + + 438.4 + + + + 438.5 + + + + 438.5 + + + + 438.6 + + + + 438.7 + + + + 438.8 + + + + 438.9 + + + + 439.0 + + + + 438.7 + + + + 438.1 + + + + 437.8 + + + + 437.5 + + + + 437.0 + + + + 436.8 + + + + 436.7 + + + + 436.6 + + + + 436.5 + + + + 436.4 + + + + 436.3 + + + + 436.1 + + + + 435.9 + + + + 435.8 + + + + 435.6 + + + + 435.4 + + + + 435.2 + + + + 435.0 + + + + 434.9 + + + + 434.8 + + + + 434.6 + + + + 434.4 + + + + 434.1 + + + + 433.9 + + + + 433.7 + + + + 433.6 + + + + 433.5 + + + + 433.4 + + + + 433.3 + + + + 433.2 + + + + 433.1 + + + + 433.0 + + + + 432.9 + + + + 432.8 + + + + 432.7 + + + + 432.6 + + + + 432.5 + + + + 432.4 + + + + 432.3 + + + + 432.2 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.2 + + + + 432.2 + + + + 432.3 + + + + 432.3 + + + + 432.4 + + + + 432.5 + + + + 432.5 + + + + 432.6 + + + + 432.7 + + + + 432.8 + + + + 432.9 + + + + 432.9 + + + + 432.9 + + + + 432.9 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 432.9 + + + + 432.9 + + + + 432.8 + + + + 432.8 + + + + 432.8 + + + + 432.7 + + + + 432.7 + + + + 432.5 + + + + 432.5 + + + + 432.4 + + + + 432.3 + + + + 432.2 + + + + 432.1 + + + + 432.0 + + + + 431.9 + + + + 431.8 + + + + 431.7 + + + + 431.6 + + + + 431.5 + + + + 431.3 + + + + 431.3 + + + + 431.2 + + + + 431.2 + + + + 431.1 + + + + 431.1 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.1 + + + + 431.1 + + + + 431.1 + + + + 431.1 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.4 + + + + 431.4 + + + + 431.4 + + + + 431.4 + + + + 431.4 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.3 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.2 + + + + 431.1 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 430.9 + + + + 430.9 + + + + 430.8 + + + + 430.8 + + + + 430.7 + + + + 430.7 + + + + 430.5 + + + + 430.4 + + + + 430.3 + + + + 430.2 + + + + 430.1 + + + + 430.1 + + + + 430.1 + + + + 430.0 + + + + 430.5 + + + + 430.9 + + + + 431.2 + + + + 431.5 + + + + 432.0 + + + + 433.0 + + + + 433.0 + + + + 432.8 + + + + 432.6 + + + + 432.4 + + + + 432.1 + + + + 431.8 + + + + 431.6 + + + + 431.3 + + + + 431.1 + + + + 430.9 + + + + 430.8 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.8 + + + + 430.9 + + + + 430.9 + + + + 431.0 + + + + 431.1 + + + + 431.2 + + + + 431.3 + + + + 431.4 + + + + 431.5 + + + + 431.7 + + + + 431.9 + + + + 432.1 + + + + 432.5 + + + + 432.8 + + + + 432.9 + + + + 433.0 + + + + 433.1 + + + + 433.2 + + + + 433.1 + + + + 433.0 + + + + 432.8 + + + + 432.6 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 431.9 + + + + 431.7 + + + + 431.5 + + + + 431.3 + + + + 431.0 + + + + 430.9 + + + + 430.7 + + + + 430.5 + + + + 430.4 + + + + 430.2 + + + + 430.0 + + + + 429.8 + + + + 429.6 + + + + 429.4 + + + + 429.3 + + + + 429.3 + + + + 429.3 + + + + 429.3 + + + + 429.4 + + + + 430.0 + + + + 430.0 + + + + 430.0 + + + + 430.4 + + + + 431.4 + + + + 430.8 + + + + 430.0 + + + + 429.4 + + + + 427.4 + + + + 425.7 + + + + 425.5 + + + + 425.3 + + + + 425.6 + + + + 426.3 + + + + 426.4 + + + + 426.1 + + + + 425.7 + + + + 425.2 + + + + 425.0 + + + + 424.8 + + + + 424.7 + + + + 424.8 + + + + 424.6 + + + + 424.3 + + + + 424.0 + + + + 424.2 + + + + 424.5 + + + + 424.9 + + + + 426.1 + + + + 427.2 + + + + 427.9 + + + + 428.5 + + + + 428.9 + + + + 429.2 + + + + 429.4 + + + + 429.5 + + + + 429.6 + + + + 429.7 + + + + 429.8 + + + + 430.0 + + + + 430.3 + + + + 430.0 + + + + 429.9 + + + + 429.6 + + + + 429.3 + + + + 429.2 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.1 + + + + 429.2 + + + + 429.3 + + + + 429.4 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.4 + + + + 429.4 + + + + 429.3 + + + + 429.1 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 429.0 + + + + 428.8 + + + + 428.8 + + + + 428.7 + + + + 428.6 + + + + 428.5 + + + + 428.4 + + + + 428.3 + + + + 428.1 + + + + 428.0 + + + + 427.8 + + + + 427.8 + + + + 427.7 + + + + 427.7 + + + + 427.6 + + + + 427.6 + + + + 427.5 + + + + 427.5 + + + + 427.4 + + + + 427.3 + + + + 427.2 + + + + 427.2 + + + + 427.1 + + + + 427.1 + + + + 427.1 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.0 + + + + 427.1 + + + + 427.2 + + + + 427.3 + + + + 427.4 + + + + 427.4 + + + + 427.5 + + + + 427.5 + + + + 427.6 + + + + 427.6 + + + + 427.7 + + + + 427.7 + + + + 427.8 + + + + 427.9 + + + + 427.9 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.1 + + + + 428.1 + + + + 428.2 + + + + 428.3 + + + + 428.3 + + + + 428.4 + + + + 428.5 + + + + 428.6 + + + + 428.7 + + + + 428.8 + + + + 429.1 + + + + 429.3 + + + + 429.5 + + + + 429.6 + + + + 429.9 + + + + 430.1 + + + + 430.2 + + + + 430.4 + + + + 430.6 + + + + 430.7 + + + + 430.8 + + + + 431.1 + + + + 431.2 + + + + 431.4 + + + + 431.5 + + + + 431.7 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.2 + + + + 432.2 + + + + 432.2 + + + + 432.2 + + + + 432.3 + + + + 432.3 + + + + 432.4 + + + + 432.5 + + + + 432.6 + + + + 432.7 + + + + 432.7 + + + + 432.8 + + + + 432.8 + + + + 432.9 + + + + 432.9 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 432.9 + + + + 432.9 + + + + 432.9 + + + + 432.9 + + + + 432.9 + + + + 432.8 + + + + 432.8 + + + + 432.8 + + + + 432.8 + + + + 432.7 + + + + 432.7 + + + + 432.7 + + + + 432.7 + + + + 432.6 + + + + 432.6 + + + + 432.6 + + + + 432.6 + + + + 432.6 + + + + 432.5 + + + + 432.5 + + + + 432.5 + + + + 432.4 + + + + 432.4 + + + + 432.4 + + + + 432.4 + + + + 432.3 + + + + 432.3 + + + + 432.2 + + + + 432.2 + + + + 432.1 + + + + 432.0 + + + + 431.9 + + + + 431.8 + + + + 431.7 + + + + 431.6 + + + + 431.5 + + + + 431.4 + + + + 431.3 + + + + 431.2 + + + + 431.1 + + + + 430.9 + + + + 430.9 + + + + 430.8 + + + + 430.8 + + + + 430.7 + + + + 430.7 + + + + 430.6 + + + + 430.6 + + + + 430.5 + + + + 430.4 + + + + 430.4 + + + + 430.3 + + + + 430.2 + + + + 430.2 + + + + 430.1 + + + + 430.1 + + + + 430.0 + + + + 429.9 + + + + 429.9 + + + + 429.9 + + + + 429.8 + + + + 429.8 + + + + 429.7 + + + + 429.7 + + + + 429.6 + + + + 429.6 + + + + 429.5 + + + + 429.3 + + + + 429.2 + + + + 429.1 + + + + 429.0 + + + + 428.8 + + + + 428.6 + + + + 428.5 + + + + 428.4 + + + + 428.2 + + + + 428.1 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.0 + + + + 428.1 + + + + 428.1 + + + + 428.1 + + + + 428.1 + + + + 428.2 + + + + 428.2 + + + + 428.2 + + + + 428.2 + + + + 428.2 + + + + 428.2 + + + + 428.3 + + + + 428.3 + + + + 428.3 + + + + 428.3 + + + + 428.3 + + + + 428.3 + + + + 428.3 + + + + 428.4 + + + + 428.4 + + + + 428.4 + + + + 428.4 + + + + 428.4 + + + + 428.5 + + + + 428.5 + + + + 428.5 + + + + 428.5 + + + + 428.6 + + + + 428.6 + + + + 428.6 + + + + 428.7 + + + + 428.7 + + + + 428.8 + + + + 428.8 + + + + 428.8 + + + + 428.9 + + + + 429.0 + + + + 429.1 + + + + 429.1 + + + + 429.1 + + + + 429.1 + + + + 429.1 + + + + 429.2 + + + + 429.2 + + + + 429.2 + + + + 429.2 + + + + 429.2 + + + + 429.2 + + + + 429.3 + + + + 429.3 + + + + 429.3 + + + + 429.4 + + + + 429.4 + + + + 429.4 + + + + 429.4 + + + + 429.4 + + + + 429.4 + + + + 429.4 + + + + 429.4 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.5 + + + + 429.6 + + + + 429.6 + + + + 429.6 + + + + 429.6 + + + + 429.6 + + + + 429.6 + + + + 429.6 + + + + 429.7 + + + + 429.7 + + + + 429.7 + + + + 429.7 + + + + 429.7 + + + + 429.8 + + + + 429.8 + + + + 429.8 + + + + 429.8 + + + + 429.8 + + + + 429.9 + + + + 429.9 + + + + 429.9 + + + + 429.9 + + + + 429.9 + + + + 430.0 + + + + 430.0 + + + + 430.1 + + + + 430.4 + + + + 430.7 + + + + 430.8 + + + + 430.9 + + + + 430.7 + + + + 430.5 + + + + 430.4 + + + + 430.2 + + + + 430.0 + + + + 429.9 + + + + 429.7 + + + + 429.5 + + + + 429.4 + + + + 429.3 + + + + 429.1 + + + + 428.8 + + + + 428.5 + + + + 428.2 + + + + 428.0 + + + + 427.8 + + + + 427.6 + + + + 427.4 + + + + 427.3 + + + + 427.1 + + + + 427.0 + + + + 427.1 + + + + 427.3 + + + + 427.6 + + + + 427.8 + + + + 428.1 + + + + 428.3 + + + + 428.5 + + + + 428.6 + + + + 428.8 + + + + 428.9 + + + + 429.1 + + + + 429.4 + + + + 429.6 + + + + 429.8 + + + + 430.0 + + + + 430.1 + + + + 430.1 + + + + 430.2 + + + + 430.2 + + + + 430.2 + + + + 430.2 + + + + 430.2 + + + + 430.2 + + + + 430.2 + + + + 430.2 + + + + 430.1 + + + + 430.0 + + + + 430.0 + + + + 430.0 + + + + 430.1 + + + + 430.2 + + + + 430.3 + + + + 430.4 + + + + 430.5 + + + + 430.6 + + + + 430.6 + + + + 430.7 + + + + 430.8 + + + + 430.9 + + + + 430.9 + + + + 431.0 + + + + 431.1 + + + + 431.2 + + + + 431.3 + + + + 431.4 + + + + 431.6 + + + + 431.8 + + + + 432.0 + + + + 432.1 + + + + 432.2 + + + + 432.2 + + + + 432.3 + + + + 432.3 + + + + 432.4 + + + + 432.5 + + + + 432.6 + + + + 432.7 + + + + 432.7 + + + + 432.8 + + + + 432.9 + + + + 432.7 + + + + 432.5 + + + + 432.2 + + + + 432.1 + + + + 432.0 + + + + 431.9 + + + + 431.8 + + + + 431.8 + + + + 431.7 + + + + 431.7 + + + + 431.6 + + + + 431.5 + + + + 431.5 + + + + 431.4 + + + + 431.3 + + + + 431.3 + + + + 431.2 + + + + 431.2 + + + + 431.1 + + + + 431.1 + + + + 431.0 + + + + 431.2 + + + + 431.5 + + + + 431.8 + + + + 432.1 + + + + 432.4 + + + + 432.5 + + + + 432.9 + + + + 432.9 + + + + 432.8 + + + + 432.7 + + + + 432.7 + + + + 432.6 + + + + 432.6 + + + + 432.5 + + + + 432.5 + + + + 432.4 + + + + 432.3 + + + + 432.3 + + + + 432.2 + + + + 432.2 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.0 + + + + 432.0 + + + + 432.1 + + + + 432.1 + + + + 432.2 + + + + 432.2 + + + + 432.3 + + + + 432.3 + + + + 432.4 + + + + 432.4 + + + + 432.5 + + + + 432.5 + + + + 432.6 + + + + 432.6 + + + + 432.7 + + + + 432.7 + + + + 432.8 + + + + 432.8 + + + + 432.8 + + + + 432.9 + + + + 432.9 + + + + 433.0 + + + + 433.0 + + + + 433.1 + + + + 433.1 + + + + 433.1 + + + + 433.2 + + + + 433.2 + + + + 433.2 + + + + 433.3 + + + + 433.3 + + + + 433.4 + + + + 433.4 + + + + 433.4 + + + + 433.5 + + + + 433.5 + + + + 433.5 + + + + 433.5 + + + + 433.5 + + + + 433.6 + + + + 433.6 + + + + 433.6 + + + + 433.7 + + + + 433.7 + + + + 433.7 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 433.9 + + + + 433.8 + + + + 433.8 + + + + 433.7 + + + + 433.6 + + + + 433.6 + + + + 433.5 + + + + 433.4 + + + + 433.4 + + + + 433.3 + + + + 433.3 + + + + 433.3 + + + + 433.2 + + + + 433.1 + + + + 433.0 + + + + 433.0 + + + + 432.9 + + + + 432.8 + + + + 432.8 + + + + 432.7 + + + + 432.7 + + + + 432.6 + + + + 432.6 + + + + 432.6 + + + + 432.5 + + + + 432.5 + + + + 432.4 + + + + 432.4 + + + + 432.3 + + + + 432.2 + + + + 432.2 + + + + 432.1 + + + + 432.1 + + + + 431.4 + + + + 431.3 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.2 + + + + 431.7 + + + + 432.0 + + + + 432.0 + + + + 431.8 + + + + 431.6 + + + + 431.4 + + + + 431.3 + + + + 431.3 + + + + 431.5 + + + + 431.6 + + + + 431.8 + + + + 431.8 + + + + 431.9 + + + + 431.9 + + + + 432.0 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.0 + + + + 432.0 + + + + 431.9 + + + + 431.8 + + + + 431.7 + + + + 431.7 + + + + 431.6 + + + + 431.4 + + + + 431.3 + + + + 431.2 + + + + 431.1 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.0 + + + + 431.1 + + + + 431.6 + + + + 431.8 + + + + 432.1 + + + + 432.3 + + + + 432.5 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 432.3 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.7 + + + + 430.8 + + + + 430.8 + + + + 430.8 + + + + 430.8 + + + + 430.9 + + + + 430.9 + + + + 431.0 + + + + 431.1 + + + + 431.1 + + + + 431.2 + + + + 431.3 + + + + 431.3 + + + + 431.4 + + + + 431.4 + + + + 431.5 + + + + 431.5 + + + + 431.6 + + + + 431.6 + + + + 431.7 + + + + 431.8 + + + + 431.9 + + + + 432.0 + + + + 432.2 + + + + 432.4 + + + + 432.8 + + + + 433.1 + + + + 433.4 + + + + 433.7 + + + + 433.8 + + + + 433.9 + + + + 434.0 + + + + 434.0 + + + + 434.1 + + + + 434.2 + + + + 434.2 + + + + 434.3 + + + + 434.3 + + + + 434.4 + + + + 434.5 + + + + 434.5 + + + + 434.6 + + + + 434.6 + + + + 434.7 + + + + 434.8 + + + + 434.9 + + + + 434.9 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 434.9 + + + + 434.9 + + + + 434.8 + + + + 434.8 + + + + 434.7 + + + + 434.7 + + + + 434.6 + + + + 434.6 + + + + 434.5 + + + + 434.4 + + + + 434.4 + + + + 434.3 + + + + 434.3 + + + + 434.3 + + + + 434.2 + + + + 434.2 + + + + 434.2 + + + + 434.1 + + + + 434.1 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 433.9 + + + + 433.8 + + + + 433.8 + + + + 433.7 + + + + 433.7 + + + + 433.6 + + + + 433.5 + + + + 433.4 + + + + 433.4 + + + + 433.3 + + + + 433.3 + + + + 433.3 + + + + 433.2 + + + + 433.2 + + + + 433.2 + + + + 433.1 + + + + 433.1 + + + + 433.0 + + + + 433.0 + + + + 433.1 + + + + 433.1 + + + + 433.2 + + + + 433.3 + + + + 433.3 + + + + 433.4 + + + + 433.5 + + + + 433.6 + + + + 433.7 + + + + 433.7 + + + + 433.8 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.7 + + + + 433.7 + + + + 433.7 + + + + 433.6 + + + + 433.6 + + + + 433.6 + + + + 433.6 + + + + 433.5 + + + + 433.5 + + + + 433.5 + + + + 433.4 + + + + 433.4 + + + + 433.4 + + + + 433.4 + + + + 433.3 + + + + 433.3 + + + + 433.2 + + + + 433.2 + + + + 433.1 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.1 + + + + 433.2 + + + + 433.4 + + + + 433.6 + + + + 433.8 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.8 + + + + 433.7 + + + + 433.6 + + + + 433.5 + + + + 433.3 + + + + 433.2 + + + + 433.0 + + + + 432.9 + + + + 432.8 + + + + 432.7 + + + + 432.7 + + + + 432.7 + + + + 432.8 + + + + 432.9 + + + + 433.1 + + + + 433.5 + + + + 433.9 + + + + 434.4 + + + + 434.7 + + + + 435.0 + + + + 435.1 + + + + 435.0 + + + + 434.9 + + + + 434.7 + + + + 434.6 + + + + 434.5 + + + + 434.3 + + + + 434.1 + + + + 434.0 + + + + 433.8 + + + + 433.7 + + + + 433.5 + + + + 433.4 + + + + 433.1 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.0 + + + + 433.1 + + + + 433.3 + + + + 433.5 + + + + 433.6 + + + + 433.7 + + + + 433.9 + + + + 434.1 + + + + 434.2 + + + + 434.4 + + + + 434.7 + + + + 434.8 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 434.8 + + + + 434.6 + + + + 434.4 + + + + 434.2 + + + + 434.0 + + + + 433.8 + + + + 433.6 + + + + 433.5 + + + + 433.3 + + + + 433.2 + + + + 433.1 + + + + 432.9 + + + + 432.8 + + + + 432.6 + + + + 432.5 + + + + 432.3 + + + + 432.1 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.0 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.1 + + + + 432.2 + + + + 432.3 + + + + 432.4 + + + + 432.4 + + + + 432.5 + + + + 432.6 + + + + 432.6 + + + + 432.8 + + + + 432.8 + + + + 433.1 + + + + 433.3 + + + + 433.4 + + + + 433.5 + + + + 433.5 + + + + 433.7 + + + + 433.7 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 433.9 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 433.9 + + + + 433.9 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 433.7 + + + + 433.7 + + + + 433.7 + + + + 433.6 + + + + 433.6 + + + + 433.5 + + + + 433.5 + + + + 433.5 + + + + 433.5 + + + + 433.4 + + + + 433.4 + + + + 433.4 + + + + 433.3 + + + + 433.3 + + + + 433.3 + + + + 433.2 + + + + 433.2 + + + + 433.2 + + + + 433.1 + + + + 433.1 + + + + 433.1 + + + + 433.3 + + + + 433.4 + + + + 433.4 + + + + 433.5 + + + + 433.6 + + + + 433.6 + + + + 434.4 + + + + 434.2 + + + + 434.1 + + + + 434.0 + + + + 433.9 + + + + 433.8 + + + + 433.6 + + + + 433.4 + + + + 433.4 + + + + 433.5 + + + + 433.7 + + + + 433.9 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.1 + + + + 434.1 + + + + 434.2 + + + + 434.2 + + + + 434.3 + + + + 434.3 + + + + 434.4 + + + + 434.5 + + + + 434.6 + + + + 434.7 + + + + 434.8 + + + + 434.9 + + + + 434.9 + + + + 435.0 + + + + 434.9 + + + + 434.6 + + + + 434.4 + + + + 434.2 + + + + 434.1 + + + + 434.0 + + + + 434.0 + + + + 433.6 + + + + 433.1 + + + + 433.3 + + + + 433.4 + + + + 433.5 + + + + 433.6 + + + + 433.3 + + + + 433.0 + + + + 432.7 + + + + 432.6 + + + + 432.5 + + + + 432.4 + + + + 432.4 + + + + 432.4 + + + + 432.6 + + + + 432.8 + + + + 433.1 + + + + 433.4 + + + + 433.7 + + + + 434.0 + + + + 434.0 + + + + 434.1 + + + + 434.1 + + + + 434.1 + + + + 434.1 + + + + 433.9 + + + + 433.8 + + + + 433.8 + + + + 433.8 + + + + 434.0 + + + + 434.0 + + + + 434.0 + + + + 434.1 + + + + 434.1 + + + + 434.2 + + + + 434.2 + + + + 434.3 + + + + 434.4 + + + + 434.4 + + + + 434.5 + + + + 434.6 + + + + 434.6 + + + + 434.6 + + + + 434.7 + + + + 434.7 + + + + 434.8 + + + + 434.8 + + + + 434.9 + + + + 435.0 + + + + 435.4 + + + + 435.9 + + + + 436.3 + + + + 436.5 + + + + 436.8 + + + + 437.2 + + + + 437.3 + + + + 437.5 + + + + 437.6 + + + + 437.8 + + + + 437.9 + + + + 438.0 + + + + 437.8 + + + + 437.7 + + + + 437.6 + + + + 437.5 + + + + 437.5 + + + + 437.4 + + + + 437.3 + + + + 437.2 + + + + 437.2 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.0 + + + + 437.1 + + + + 437.1 + + + + 437.2 + + + + 437.3 + + + + 437.8 + + + + 438.3 + + + + 438.6 + + + + 438.9 + + + + 439.1 + + + + 439.1 + + + + 439.1 + + + + 439.0 + + + + 439.0 + + + + 438.9 + + + + 438.8 + + + + 438.5 + + + + 438.2 + + + + 437.9 + + + + 437.6 + + + + 437.2 + + + + 437.0 + + + + 437.0 + + + + 436.9 + + + + 436.5 + + + + 436.1 + + + + 435.7 + + + + 435.2 + + + + 435.0 + + + + 434.7 + + + + 434.2 + + + + 434.1 + + + + 434.2 + + + + 434.3 + + + + 434.3 + + + + 434.4 + + + + 434.5 + + + + 434.6 + + + + 434.6 + + + + 434.7 + + + + 434.8 + + + + 434.8 + + + + 434.8 + + + + 434.9 + + + + 435.1 + + + + 435.2 + + + + 435.4 + + + + 435.5 + + + + 435.7 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 435.9 + + + + 435.7 + + + + 435.5 + + + + 435.3 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.1 + + + + 435.1 + + + + 435.1 + + + + 435.1 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.2 + + + + 435.3 + + + + 435.3 + + + + 435.4 + + + + 435.4 + + + + 435.5 + + + + 435.6 + + + + 435.6 + + + + 435.7 + + + + 435.7 + + + + 435.8 + + + + 435.8 + + + + 435.8 + + + + 435.9 + + + + 435.9 + + + + 435.9 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 436.0 + + + + 435.9 + + + + 435.7 + + + + 435.5 + + + + 435.4 + + + + 435.3 + + + + 435.1 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 435.0 + + + + 434.9 + + + + 434.9 + + + + 434.8 + + + + 434.8 + + + + 434.7 + + + + 434.7 + + + + 434.6 + + + + 434.5 + + + + 434.4 + + + + 434.4 + + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/example.kml b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/example.kml new file mode 100644 index 000000000..0364581c4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/example.kml @@ -0,0 +1 @@ +OpenLayers exportExported on Wed Oct 04 2017 16:01:25 GMT+0200 (CEST)Un titreNo description available10#FF66006.634692260376488,46.788677686167915Un titreNo description available#3366FF46.627846793656496,46.78665011783712 6.64441505242028,46.786586826582514 6.649182839585482,46.78297662148377Un titreNo description availabletrue#ff0000156.6364823610389445,46.77874998524745 6.636492021526314,46.77875105518408 6.636501341989487,46.77875310230045 6.636510114225162,46.77875608086758 6.636518142276416,46.778759924349245 6.636525246810043,46.77876454688864 6.636531269122524,46.77876984522606 6.636536074685225,46.77877570100553 6.636539556149531,46.7787819834189 6.636541635744878,46.7787885521274 6.636542267016052,46.778795260397125 6.63654143586096,46.77880195837637 6.6365391608456985,46.778808496443375 6.636535492789864,46.77881472854838 6.636530513631377,46.77882051547637 6.636524334596144,46.77882572795678 6.636517093713494,46.77883024955118 6.636508952732835,46.77883397925455 6.636500093510424,46.778836833751136 6.636490713947003,46.77883874927624 6.6364810235669704,46.77883968304 6.636471238837926,46.77883961418358 6.636461578335087,46.77883854424526 6.63645225785864,46.77883649712561 6.636443485613067,46.77883351855408 6.6364354575561695,46.778829675067165 6.6364283530216595,46.77882505252224 6.6364223307131285,46.77881975417942 6.636417525158863,46.77881389839514 6.636414043706729,46.778807615978145 6.636411964126204,46.778801047267294 6.636411332871189,46.77879433899688 6.636412164042343,46.7787876410186 6.636414439072139,46.7787811029541 6.63641810713969,46.77877487085297 6.636423086306036,46.7787690839298 6.636429265344568,46.778763871454885 6.6364365062256665,46.77875934986596 6.636444647200065,46.778755620167814 6.636453506412056,46.77875276567542 6.636462885961826,46.778750850153386 6.6364725763261925,46.778749916391156 6.6364823610389445,46.77874998524745Un titreNo description availabletruetrue#3399662593true#339966#3399666.6389037185087165,46.77349221517152 6.640049348860649,46.7736190797271 6.641154671451875,46.77386182812112 6.642195001410742,46.774215039264085 6.6431471041150765,46.77467082506868 6.643989713803907,46.77521900647298 6.644704008384789,46.77584734060734 6.64527402985115,46.77654179404884 6.645687040921641,46.77728685608087 6.645933809920134,46.77806588497881 6.64600881750162,46.778861479605325 6.6459103805612,46.77965586802651 6.645640690503493,46.780431304478064 6.64520576495801,46.78117046581513 6.644615313959653,46.78185683858726 6.643882523529983,46.782475088082165 6.643023761450306,46.78301140108049 6.642058211770059,46.78345379464643 6.641007446202666,46.783792384036936 6.639894941988887,46.784019603724126 6.638745557020897,46.78413037657427 6.63758497399045,46.784122227388934 6.636439126028405,46.78399533826064 6.635333616723811,46.78375254450011 6.634293147538634,46.783399271227935 6.633340965465911,46.78294341205184 6.632498343318837,46.78239515255314 6.631784104296839,46.781766742540526 6.631214201469824,46.781072222179 6.6308013615775225,46.78032710813138 6.630554801086129,46.779548046743955 6.630480020813877,46.77875244204111 6.630578683668252,46.77795806685183 6.6308485781711815,46.77718266576489 6.631283668527302,46.776443558782745 6.63187423005756,46.77575725452629 6.632607066919157,46.77513908161973 6.633465807205101,46.7746028464773 6.634431268802421,46.77416052511703 6.635481887824255,46.77382199586601 6.63659420005105,46.77359481890861 6.637743364649525,46.773484067581855 6.6389037185087165,46.77349221517152HelloNo description availabletrue#FF9900176.634647621542136,46.78728301207339 diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/metadata.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/metadata.html new file mode 100644 index 000000000..283ab8fac --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/data/metadata.html @@ -0,0 +1,9 @@ +

+ Here's some metadata for the layers with some html +

+

+Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. +

+

+Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32. +

diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.css new file mode 100644 index 000000000..5b3bfe8ad --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.css @@ -0,0 +1,23 @@ +li { + margin: 20px; + list-style: none; +} +.ngeo-datepicker-end-date { + display: inline-block; +} +.ngeo-datepicker-start-date { + display: inline-block; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.html new file mode 100644 index 000000000..c9d9f748f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.html @@ -0,0 +1,33 @@ + + + + GeoMapFish Datepicker example + + + + + +

This example shows how to use the ngeo-date-picker directive with the gmf WMS time service in order to format the date for WMS.

+
    +
  • Select a period with a datepicker + +
  • +
  • + Date formatted for a WMS request (resolution set on 'day'): +
    +          {{ctrl.rangeValue}}
    +        
    +
  • +
  • Select a single date with a datepicker + +
  • +
  • + Date formatted for a WMS request (resolution set on 'month'): +
    +          {{ctrl.value}}
    +        
    +
  • +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.js new file mode 100644 index 000000000..73bd649d0 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/datepicker.js @@ -0,0 +1,92 @@ +/** + * @module gmfapp.datepicker + */ +const exports = {}; + +import './datepicker.css'; +import ngeoMiscDatepickerComponent from 'ngeo/misc/datepickerComponent.js'; + +import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + ngeoMiscDatepickerComponent.name, + ngeoMiscWMSTime.module.name, +]); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {!angular.Scope} $scope Angular scope. + * @param {!ngeo.misc.WMSTime} ngeoWMSTime wmstime service. + * @ngInject + */ +exports.MainController = function($scope, ngeoWMSTime) { + + /** + * @type {ngeo.misc.WMSTime} + * @private + */ + this.ngeoWMSTime_ = ngeoWMSTime; + + /** + * @type {ngeox.TimeProperty} + * @export + */ + this.wmsTimeRangeMode = { + widget: /** @type {ngeox.TimePropertyWidgetEnum} */ ('datepicker'), + maxValue: '2013-12-31T00:00:00Z', + minValue: '2006-01-01T00:00:00Z', + maxDefValue: null, + minDefValue: null, + resolution: /** @type {ngeox.TimePropertyResolutionEnum}*/ ('day'), + mode: /** @type {ngeox.TimePropertyModeEnum} */ ('range'), + interval: [0, 1, 0, 0] + }; + + /** + * @type {ngeox.TimeProperty} + * @export + */ + this.wmsTimeValueMode = { + widget: /** @type {ngeox.TimePropertyWidgetEnum} */ ('datepicker'), + maxValue: '2015-12-31T00:00:00Z', + minValue: '2014-01-01T00:00:00Z', + maxDefValue: null, + minDefValue: null, + resolution: /** @type {ngeox.TimePropertyResolutionEnum}*/ ('month'), + mode: /** @type {ngeox.TimePropertyModeEnum} */ ('value'), + interval: [0, 1, 0, 0] + }; + + /** + * @type {string} + * @export + */ + this.value; + + /** + * @type {string} + * @export + */ + this.rangeValue; + + this.onDateSelected = function(date) { + this.value = this.ngeoWMSTime_.formatWMSTimeParam(this.wmsTimeValueMode, date); + }; + + this.onDateRangeSelected = function(date) { + this.rangeValue = this.ngeoWMSTime_.formatWMSTimeParam(this.wmsTimeRangeMode, date); + }; + +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.css new file mode 100644 index 000000000..510b465ee --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.css @@ -0,0 +1,180 @@ +gmf-map, +#tree-container { + float: left; +} +.clear-left { + clear: left; +} +gmf-map > div { + width: 600px; + height: 400px; +} + +/* DisplayQueryGrid */ +.gmf-displayquerygrid { + padding: .5rem; + border-top: solid 1px black; + background-color: white; + height: 25rem; +} + +.ngeo-grid-table-container { + height: 18rem; + overflow: auto; +} + +.table { + background-color: white; + width: 100%; +} + +.table th { + cursor: pointer; + white-space: nowrap; + font-weight: bold; +} + +.table > tbody > tr.active > td { + background-color: #C9C9C9; +} + +.nav-pills { + height: 3rem; +} + +.nav-pills > li > a { + padding: 2px 7px; + margin-right: 0px; +} + +.navbar { + height: 3rem; + padding-top: .5rem; +} + +.navbar-right { + margin-right: 0; +} +.navbar-text { + padding: 1px 5px; + margin: 0; + line-height: 1.5; +} + +table>tbody>tr>td, +table>tbody>tr>th, +table>tfoot>tr>td, +table>tfoot>tr>th, +table>thead>tr>td, +table>thead>tr>th { + padding: 2px; +} + +/* Layertree */ +ul { + list-style-type: none; +} +gmf-layertree a{ + color: black; + text-decoration: none; + padding-right: 5px; +} +gmf-layertree .gmf-layertree-metadata a:before { + font-family: FontAwesome; + content: "\f129"; +} +gmf-layertree .gmf-layertree-layer-icon { + display: inline-flex; + width: 20px; + height: 10px; +} +gmf-layertree .gmf-layertree-zoom { + display: none; +} +gmf-layertree .gmf-layertree-zoom:hover { + cursor: pointer; +} +gmf-layertree .gmf-layertree-zoom:before { + font-family: FontAwesome; + content: "\f18e"; +} +gmf-layertree .outOfResolution .gmf-layertree-legend { + display: none; +} +gmf-layertree .gmf-layertree-legend-button a:after { + font-family: FontAwesome; + content: "\f036"; +} +gmf-layertree .gmf-layertree-legend img { + padding-left: 15px; +} +gmf-layertree .noSource { + opacity: 0.3; +} +gmf-layertree .noSource:after { + content: "(source not available)"; +} +gmf-layertree .outOfResolution { + opacity: 0.6; +} +gmf-layertree .outOfResolution .gmf-layertree-zoom { + display: inline; +} +gmf-layertree .gmf-layertree-state { + font-family: FontAwesome; + font-weight: lighter; +} +gmf-layertree .on .gmf-layertree-state:before { + content: "\f14a"; +} +gmf-layertree .off .gmf-layertree-state:before { + content: "\f096"; +} +gmf-layertree .indeterminate .gmf-layertree-state:before { + content: "\f147"; +} +[ngeo-popup] { + top: 20px; + max-width: 350px; + width: 350px; + margin-left: -175px; + left: 50%; + right: 50%; + max-height: 400px; + position: fixed; +} +[ngeo-popup] .popover-content { + overflow: auto; + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(400px - 38px); +} +@media (max-width: 768px) { + #map { + height: 200px; + width: 200px; + } + [ngeo-popup] { + position: fixed; + top: 0; + left: auto; + right: auto; + max-width: 100%; + width: calc(100% - 20px); + height: calc(100% - 20px); + max-height: none; + margin: 10px; + } +} +@media (max-width: 768px) { + [ngeo-popup] .popover-content { + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(100% - 32px); + -webkit-overflow-scrolling: touch; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.html new file mode 100644 index 000000000..08566f6ca --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.html @@ -0,0 +1,50 @@ + + + + GeoMapFish Map Query example + + + + + + + + + +
+
+ Theme: + + +
+ + +
+ +
+ +

+ TODO +

+ + Query-Tool active + + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.js new file mode 100644 index 000000000..02f6faab3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerygrid.js @@ -0,0 +1,189 @@ +/** + * @module gmfapp.displayquerygrid + */ +const exports = {}; + +import './displayquerygrid.css'; +import gmfDatasourceManager from 'gmf/datasource/Manager.js'; + +import gmfLayertreeComponent from 'gmf/layertree/component.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +/** @suppress {extraRequire} */ +import gmfQueryGridComponent from 'gmf/query/gridComponent.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoGridModule from 'ngeo/grid/module.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import ngeoMiscBtnComponent from 'ngeo/misc/btnComponent.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import ngeoQueryBboxQueryComponent from 'ngeo/query/bboxQueryComponent.js'; +import ngeoQueryMapQueryComponent from 'ngeo/query/mapQueryComponent.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfDatasourceManager.module.name, + gmfLayertreeComponent.name, + gmfMapComponent.name, + gmfQueryGridComponent.name, + gmfThemeThemes.module.name, + ngeoGridModule.name, + ngeoMapModule.name, // for ngeo.map.FeatureOverlay, perhaps remove me + ngeoMiscBtnComponent.name, + ngeoQueryBboxQueryComponent.name, + ngeoQueryMapQueryComponent.name, +]); + + +exports.module.constant('ngeoQueryOptions', { + 'limit': 20, + 'queryCountFirst': true +}); + + +exports.module.constant( + 'gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?' + + 'version=2&background=background'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * Demo, NOT USED. + * A sample component to display the result. + * + * @type {!angular.Component} + */ +exports.queryresultComponent = { + controller: 'gmfappQueryresultController', + template: require('./partials/queryresult.html') +}; + +exports.module.component('gmfappQueryresult', exports.queryresultComponent); + + +/** + * Demo, NOT USED. + * @param {ngeox.QueryResult} ngeoQueryResult Query service. + * @constructor + * @ngInject + */ +exports.QueryresultController = function(ngeoQueryResult) { + + /** + * @type {ngeox.QueryResult} + * @export + */ + this.result = ngeoQueryResult; + +}; + + +exports.module.controller('gmfappQueryresultController', exports.QueryresultController); + + +/** + * @constructor + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.datasource.Manager} gmfDataSourcesManager The gmf + * data sources manager service. + * @param {ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr The ngeo feature + * overlay manager service. + * @ngInject + */ +exports.MainController = function(gmfThemes, gmfDataSourcesManager, + ngeoFeatureOverlayMgr) { + + gmfThemes.loadThemes(); + + const fill = new olStyleFill({color: [255, 170, 0, 0.6]}); + const stroke = new olStyleStroke({color: [255, 170, 0, 1], width: 2}); + + /** + * FeatureStyle used by the displayquerygrid directive + * @type {ol.style.Style} + * @export + */ + this.featureStyle = new olStyleStyle({ + fill: fill, + image: new olStyleCircle({ + fill: fill, + radius: 5, + stroke: stroke + }), + stroke: stroke + }); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); + + // Init the datasources with our map. + gmfDataSourcesManager.setDatasourceMap(this.map); + + /** + * @type {Array.|undefined} + * export + */ + this.themes = undefined; + + /** + * @type {Object|undefined} + * @export + */ + this.treeSource = undefined; + + /** + * @type {boolean} + * @export + */ + this.queryActive = true; + + /** + * @type {boolean} + * @export + */ + this.queryGridActive = true; + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + this.themes = themes; + this.treeSource = themes[3]; + } + }); + + ngeoFeatureOverlayMgr.init(this.map); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.css new file mode 100644 index 000000000..55d7ecbb6 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.css @@ -0,0 +1,120 @@ +gmf-map, +#tree-container { + float: left; +} +.clear-left { + clear: left; +} +gmf-map > div { + width: 600px; + height: 400px; +} + +/* Layertree */ +ul { + list-style-type: none; +} +gmf-layertree a{ + color: black; + text-decoration: none; + padding-right: 5px; +} +gmf-layertree .gmf-layertree-metadata a:before { + font-family: FontAwesome; + content: "\f129"; +} +gmf-layertree .gmf-layertree-layer-icon { + display: inline-flex; + width: 20px; + height: 10px; +} +gmf-layertree .gmf-layertree-zoom { + display: none; +} +gmf-layertree .gmf-layertree-zoom:hover { + cursor: pointer; +} +gmf-layertree .gmf-layertree-zoom:before { + font-family: FontAwesome; + content: "\f18e"; +} +gmf-layertree .outOfResolution .gmf-layertree-legend { + display: none; +} +gmf-layertree .gmf-layertree-legend-button a:after { + font-family: FontAwesome; + content: "\f036"; +} +gmf-layertree .gmf-layertree-legend img { + padding-left: 15px; +} +gmf-layertree .noSource { + opacity: 0.3; +} +gmf-layertree .noSource:after { + content: "(source not available)"; +} +gmf-layertree .outOfResolution { + opacity: 0.6; +} +gmf-layertree .outOfResolution .gmf-layertree-zoom { + display: inline; +} +gmf-layertree .gmf-layertree-state { + font-family: FontAwesome; + font-weight: lighter; +} +gmf-layertree .on .gmf-layertree-state:before { + content: "\f14a"; +} +gmf-layertree .off .gmf-layertree-state:before { + content: "\f096"; +} +gmf-layertree .indeterminate .gmf-layertree-state:before { + content: "\f147"; +} +[ngeo-popup] { + top: 20px; + max-width: 350px; + width: 350px; + margin-left: -175px; + left: 50%; + right: 50%; + max-height: 400px; + position: fixed; +} +[ngeo-popup] .popover-content { + overflow: auto; + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(400px - 38px); +} +@media (max-width: 768px) { + #map { + height: 200px; + width: 200px; + } + [ngeo-popup] { + position: fixed; + top: 0; + left: auto; + right: auto; + max-width: 100%; + width: calc(100% - 20px); + height: calc(100% - 20px); + max-height: none; + margin: 10px; + } +} +@media (max-width: 768px) { + [ngeo-popup] .popover-content { + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(100% - 32px); + -webkit-overflow-scrolling: touch; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.html new file mode 100644 index 000000000..e41431290 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.html @@ -0,0 +1,59 @@ + + + + GeoMapFish Map Query example + + + + + + + + + +
+
+ Theme: + + +
+ + +
+ +
+ +

+ This example shows how to use the ngeo-map-query + directive in combination with the + gmf.datasource.Manager. + The DataSourcesManager fetches the themes returned by the theme + service and adds one DataSource, which is used by the querent service + per layer definition found. In this example, the layer tree is + responsible of creating the layer. You can switch theme and turn + on/off layers to see the impact it has on results returned by the + query service. To display results, this example use the + gmf-displayquerywindow component. Here, this last + directive uses a custom style to display all selected features. +

+ + Query-Tool active + + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.js new file mode 100644 index 000000000..7dfe8b122 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/displayquerywindow.js @@ -0,0 +1,180 @@ +/** + * @module gmfapp.displayquerywindow + */ +const exports = {}; + +import './displayquerywindow.css'; +import gmfDatasourceManager from 'gmf/datasource/Manager.js'; + +import gmfLayertreeComponent from 'gmf/layertree/component.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +/** @suppress {extraRequire} */ +import gmfQueryWindowComponent from 'gmf/query/windowComponent.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoMiscBtnComponent from 'ngeo/misc/btnComponent.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import ngeoQueryBboxQueryComponent from 'ngeo/query/bboxQueryComponent.js'; +import ngeoQueryMapQueryComponent from 'ngeo/query/mapQueryComponent.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; +import ngeoMapModule from 'ngeo/map/module.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfDatasourceManager.module.name, + gmfLayertreeComponent.name, + gmfMapComponent.name, + gmfQueryWindowComponent.name, + gmfThemeThemes.module.name, + ngeoMapModule.name, // for ngeo.map.FeatureOverlay, perhaps remove me + ngeoMiscBtnComponent.name, + ngeoQueryBboxQueryComponent.name, + ngeoQueryMapQueryComponent.name, +]); + + +exports.module.value('ngeoQueryOptions', { + 'limit': 20 +}); + + +exports.module.value( + 'gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?' + + 'version=2&background=background'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * Demo, NOT USED. + * A sample component to display the result. + * + * @type {!angular.Component} + */ +exports.queryresultComponent = { + controller: 'AppQueryresultController', + template: require('./partials/queryresult.html') +}; + +exports.module.component('appQueryresult', exports.queryresultComponent); + + +/** + * Demo, NOT USED. + * @param {ngeox.QueryResult} ngeoQueryResult Query service. + * @constructor + * @ngInject + */ +exports.QueryresultController = function(ngeoQueryResult) { + + /** + * @type {ngeox.QueryResult} + * @export + */ + this.result = ngeoQueryResult; + +}; + + +exports.module.controller('AppQueryresultController', exports.QueryresultController); + + +/** + * @constructor + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.datasource.Manager} gmfDataSourcesManager The gmf + * data sources manager service. + * @param {ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr The ngeo feature + * overlay manager service. + * @ngInject + */ +exports.MainController = function(gmfThemes, gmfDataSourcesManager, + ngeoFeatureOverlayMgr) { + + gmfThemes.loadThemes(); + + const fill = new olStyleFill({color: [255, 170, 0, 0.6]}); + const stroke = new olStyleStroke({color: [255, 170, 0, 1], width: 2}); + + /** + * FeatureStyle used by the gmf.query.windowComponent + * @type {ol.style.Style} + * @export + */ + this.featureStyle = new olStyleStyle({ + fill: fill, + image: new olStyleCircle({ + fill: fill, + radius: 5, + stroke: stroke + }), + stroke: stroke + }); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); + + // Init the datasources with our map. + gmfDataSourcesManager.setDatasourceMap(this.map); + + /** + * @type {Array.|undefined} + * export + */ + this.themes = undefined; + + /** + * @type {Object|undefined} + * @export + */ + this.treeSource = undefined; + + /** + * @type {boolean} + * @export + */ + this.queryActive = true; + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + this.themes = themes; + this.treeSource = themes[3]; + } + }); + + ngeoFeatureOverlayMgr.init(this.map); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.css new file mode 100644 index 000000000..f2f7ffdcf --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.css @@ -0,0 +1,164 @@ +gmf-map > div { + width: 600px; + height: 400px; +} + +/* gmf-drawfeature */ + +gmf-drawfeature { + display: block; + margin: 20px; + width: 400px; +} + +.ngeo-drawfeature-actionbuttons { + float: right; + position: relative; +} + +.gmf-drawfeature-featurelist li:hover { + background-color: #ADD8E6; + cursor: pointer; +} + +.gmf-eol { + clear: both; +} + +gmf-featurestyle { + display: block; + margin: 10px 0 0 0; +} + +.gmf-drawfeature-featurelist { + margin: 10px 0 0 0; + padding: 0; + list-style: none; +} + +/* drawfeature */ + +ngeo-drawfeature { + border-bottom: 1px solid #333; + margin: 0 0 10px 0; + padding: 0 0 20px 0; +} + +.gmf-icon-circle:before { + content: "Circle"; +} +.gmf-icon-line:after { + content: 'Line'; +} +.gmf-icon-point:after { + content: 'Point'; +} +.gmf-icon-polygon:after { + content: 'Polygon'; +} +.gmf-icon-rectangle:after { + content: 'Rectangle'; +} +.gmf-icon-text:after { + content: 'Text'; +} + +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; +} +.ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; +} +.ngeo-tooltip-static { + display: none; +} +.ngeo-tooltip-measure:before, +.ngeo-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} +.ngeo-tooltip-static:before { + border-top-color: #ffcc33; +} + +/* featurestyle */ + +gmf-featurestyle .form-horizontal .control-label { + text-align: left; +} +.gmf-featurestyle-name { + font-weight: bold; + font-size: 16pt; +} +.gmf-featurestyle-name:not(:focus) { + border: none; + box-shadow: none; + -webkit-box-shadow: none; + padding: 0; +} +gmf-featurestyle input[type=range] { + padding: 6px 12px; +} +.ngeo-colorpicker-palette { + border-collapse: separate; + border-spacing: 0px; +} +.ngeo-colorpicker-palette tr { + cursor: default; +} +.ngeo-colorpicker-palette td { + position: relative; + padding: 0px; + text-align: center; + vertical-align: middle; + font-size: 1px; + cursor: pointer; +} +.ngeo-colorpicker-palette td > div { + position: relative; + height: 12px; + width: 12px; + border: 1px solid #fff; + box-sizing: content-box; +} +.ngeo-colorpicker-palette td:hover > div::after { + display: block; + content: ''; + background: inherit; + position: absolute; + width: 28px; + height: 28px; + top: -10px; + left: -10px; + border: 2px solid #fff; + -webkit-box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + -webkit-box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + z-index: 11; +} +.ngeo-colorpicker-palette td.ngeo-colorpicker-selected > div::after { + border: 2px solid #444; + margin: 0; + content: ''; + display: block; + width: 14px; + height: 14px; + position: absolute; + left: -3px; + top: -3px; + box-sizing: content-box; + z-index: 10; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.html new file mode 100644 index 000000000..6b878ea85 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.html @@ -0,0 +1,39 @@ + + + + Draw Feature Example + + + + + + + + + + + + + + + +

Draw & Measure

+ + + + +

+ This example shows how to use the gmf-drawfeature + directive to create, modify and delete vector features on a map and + style them as we please. +

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.js new file mode 100644 index 000000000..c78113c43 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/drawfeature.js @@ -0,0 +1,149 @@ +/** + * @module gmfapp.drawfeature + */ +const exports = {}; + +import './drawfeature.css'; +import 'jquery-ui/ui/widgets/tooltip.js'; +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfDrawingModule from 'gmf/drawing/module.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoFormatFeatureProperties from 'ngeo/format/FeatureProperties.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfDrawingModule.name, + gmfMapComponent.name, + ngeoMapModule.name, // for ngeo.map.FeatureOverlay, perhaps remove me + ngeoMiscFeatureHelper.module.name, + ngeoMiscToolActivateMgr.module.name, +]); + + +exports.module.value('ngeoExportFeatureFormats', [ + ngeoMiscFeatureHelper.FormatType.KML, + ngeoMiscFeatureHelper.FormatType.GPX +]); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {!angular.Scope} $scope Angular scope. + * @param {ngeo.misc.FeatureHelper} ngeoFeatureHelper Gmf feature helper service. + * @param {ol.Collection.} ngeoFeatures Collection of features. + * @param {ngeo.misc.ToolActivateMgr} ngeoToolActivateMgr Ngeo ToolActivate manager + * service. + * @param {ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr Ngeo FeatureOverlay + * manager + * @constructor + * @ngInject + */ +exports.MainController = function($scope, ngeoFeatureHelper, ngeoFeatures, + ngeoToolActivateMgr, ngeoFeatureOverlayMgr) { + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + const view = new olView({ + center: [0, 0], + zoom: 3 + }); + + ngeoFeatureHelper.setProjection(googAsserts.assert(view.getProjection())); + + const featureOverlay = ngeoFeatureOverlayMgr.getFeatureOverlay(); + featureOverlay.setFeatures(ngeoFeatures); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: view + }); + + /** + * @type {boolean} + * @export + */ + this.drawFeatureActive = true; + + const drawFeatureToolActivate = new ngeoMiscToolActivate( + this, 'drawFeatureActive'); + ngeoToolActivateMgr.registerTool( + 'mapTools', drawFeatureToolActivate, true); + + /** + * @type {boolean} + * @export + */ + this.pointerMoveActive = false; + + const pointerMoveToolActivate = new ngeoMiscToolActivate( + this, 'pointerMoveActive'); + ngeoToolActivateMgr.registerTool( + 'mapTools', pointerMoveToolActivate, false); + + $scope.$watch( + () => this.pointerMoveActive, + (newVal) => { + if (newVal) { + this.map.on('pointermove', this.handleMapPointerMove_, this); + } else { + this.map.un('pointermove', this.handleMapPointerMove_, this); + $('#pointermove-feature').html(''); + } + } + ); + + // initialize tooltips + $('[data-toggle="tooltip"]').tooltip({ + container: 'body', + trigger: 'hover' + }); +}; + + +/** + * @param {ol.MapBrowserEvent} evt MapBrowser event + * @private + */ +exports.MainController.prototype.handleMapPointerMove_ = function(evt) { + const pixel = evt.pixel; + + const feature = this.map.forEachFeatureAtPixel(pixel, feature => feature); + + $('#pointermove-feature').html( + (feature) ? feature.get(ngeoFormatFeatureProperties.NAME) : 'None' + ); + + this.scope_.$apply(); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.css new file mode 100644 index 000000000..68d960268 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.css @@ -0,0 +1,20 @@ +body { + padding: 0.5rem; +} +gmf-map > div { + width: 60rem; + height: 40rem; +} +.panel { + display: block; + width: 30rem; +} +.no-feature:before { + content: "No feature"; +} +.pending:before { + content: "Query in progress..."; +} +.form { + margin: 1rem 0 0 0; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.html new file mode 100644 index 000000000..94de45a0e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.html @@ -0,0 +1,63 @@ + + + + EditFeature GeoMapFish example + + + + + + +

+ This example shows how to use the gmf.editing.EditFeature + service to insert, update and delete features from a layer using + a GeoMapFish server. First, you must log in. Then, you can either + click on the Insert button to insert a random feature, or + click on a feature on the map to either Update or + Delete it. +

+ + + +
+
+ Insert + Update + Delete +
+
+
+ + + + + {{ ctrl.feature.getId() }} + +
+
+
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.js new file mode 100644 index 000000000..c222832dd --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeature.js @@ -0,0 +1,304 @@ +/** + * @module gmfapp.editfeature + */ +const exports = {}; + +import './editfeature.css'; +import 'jquery-ui/ui/widgets/tooltip.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; + +import gmfAuthenticationModule from 'gmf/authentication/module.js'; +import gmfEditingEditFeature from 'gmf/editing/EditFeature.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import olFeature from 'ol/Feature.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import * as olExtent from 'ol/extent.js'; +import olGeomMultiPoint from 'ol/geom/MultiPoint.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olLayerImage from 'ol/layer/Image.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olSourceImageWMS from 'ol/source/ImageWMS.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfAuthenticationModule.name, + gmfEditingEditFeature.module.name, + gmfMapComponent.name, +]); + + +exports.module.value( + 'authenticationBaseUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi'); + + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {!angular.Scope} $scope Angular scope. + * @param {gmf.editing.EditFeature} gmfEditFeature Gmf edit feature service. + * @param {gmfx.User} gmfUser User. + * @constructor + * @ngInject + */ +exports.MainController = function($scope, gmfEditFeature, gmfUser) { + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {gmf.editing.EditFeature} + * @export + */ + this.editFeature_ = gmfEditFeature; + + /** + * @type {gmfx.User} + * @export + */ + this.gmfUser = gmfUser; + + /** + * @type {ol.source.ImageWMS} + * @private + */ + this.wmsSource_ = new olSourceImageWMS({ + url: 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/mapserv_proxy', + params: {'LAYERS': 'point'} + }); + + /** + * @type {ol.layer.Image} + * @private + */ + this.wmsLayer_ = new olLayerImage({ + source: this.wmsSource_ + }); + + /** + * @type {number} + * @private + */ + this.pixelBuffer_ = 10; + + /** + * @type {number} + * @private + */ + this.layerId_ = 113; + + /** + * @type {ol.Feature} + * @export + */ + this.feature = null; + + /** + * @type {boolean} + * @export + */ + this.pending = false; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }), + this.wmsLayer_ + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 2 + }) + }); + + this.map.on('singleclick', this.handleMapSingleClick_.bind(this)); + + // initialize tooltips + $('[data-toggle="tooltip"]').tooltip({ + container: 'body', + trigger: 'hover' + }); +}; + + +/** + * @param {ol.MapBrowserEvent} evt MapBrowser event + * @private + */ +exports.MainController.prototype.handleMapSingleClick_ = function(evt) { + + // (1) Launch query to fetch new features + const coordinate = evt.coordinate; + const map = this.map; + const view = map.getView(); + const resolution = view.getResolution(); + const buffer = resolution * this.pixelBuffer_; + const extent = olExtent.buffer( + [coordinate[0], coordinate[1], coordinate[0], coordinate[1]], + buffer + ); + + this.editFeature_.getFeaturesInExtent([this.layerId_], extent).then( + this.handleGetFeatures_.bind(this)); + + // (2) Clear any previously selected feature + this.feature = null; + + // (3) Pending + this.pending = true; + + this.scope_.$apply(); +}; + + +/** + * @param {Array.} features Features. + * @private + */ +exports.MainController.prototype.handleGetFeatures_ = function(features) { + this.pending = false; + + if (features.length) { + this.feature = features[0]; + } +}; + + +/** + * Insert a new feature at a random location. + * @export + */ +exports.MainController.prototype.insertFeature = function() { + + this.pending = true; + + // (1) Create a randomly located feature + const map = this.map; + const view = map.getView(); + const resolution = view.getResolution(); + const buffer = resolution * -50; // 50 pixel buffer inside the extent + const size = /** @type {!Array.} */ (map.getSize()); + const extent = olExtent.buffer( + view.calculateExtent(size), + buffer + ); + const bottomLeft = olExtent.getBottomLeft(extent); + const topRight = olExtent.getTopRight(extent); + const left = bottomLeft[0]; + const bottom = bottomLeft[1]; + const right = topRight[0]; + const top = topRight[1]; + const deltaX = right - left; + const deltaY = top - bottom; + const coordinate = [ + left + Math.random() * deltaX, + bottom + Math.random() * deltaY + ]; + + const feature = new olFeature({ + 'geometry': new olGeomMultiPoint([coordinate]), + 'name': 'New point' + }); + + this.feature = null; // clear selected feature + + // (2) Launch request + this.editFeature_.insertFeatures( + this.layerId_, + [feature] + ).then( + this.handleEditFeature_.bind(this) + ); +}; + + +/** + * Update the currently selected feature with a new name. + * @export + */ +exports.MainController.prototype.updateFeature = function() { + + console.assert(this.feature); + + this.pending = true; + + // (1) Update name + this.feature.set('name', 'Updated name'); + + // (2) Launch request + this.editFeature_.updateFeature( + this.layerId_, + this.feature + ).then( + this.handleEditFeature_.bind(this) + ); +}; + + +/** + * Delete currently selected feature. + * @export + */ +exports.MainController.prototype.deleteFeature = function() { + + console.assert(this.feature); + + // (1) Launch request + this.editFeature_.deleteFeature( + this.layerId_, + this.feature + ).then( + this.handleEditFeature_.bind(this) + ); + + // (2) Reset selected feature + this.feature = null; +}; + + +/** + * Called after an insert, update or delete request. + * @param {angular.$http.Response} resp Ajax response. + * @private + */ +exports.MainController.prototype.handleEditFeature_ = function(resp) { + this.pending = false; + this.refreshWMSLayer_(); +}; + + +/** + * @private + */ +exports.MainController.prototype.refreshWMSLayer_ = function() { + this.wmsSource_.updateParams({ + 'random': Math.random() + }); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.css new file mode 100644 index 000000000..50188a98c --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.css @@ -0,0 +1,63 @@ +body { + padding: 1rem; +} +.panel { + display: block; + float: left; + margin: 0 1rem 0 0; + width: 35rem; +} +gmf-map > div { + width: 60rem; + height: 40rem; +} +gmf-editfeatureselector { + display: block; + width: 30rem; +} +gmf-editfeature { + display: block; +} +.gmf-editfeatureselector-stopediting { + float: right; +} +ngeo-attributes { + border-top: 0.1rem solid black; + display: block; + padding: 1rem 0; +} +.gmf-editfeature-btn-delete { + float: right; +} + +/* measure tooltips */ +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; +} +.ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; +} +.ngeo-tooltip-static { + display: none; +} +.ngeo-tooltip-measure:before, +.ngeo-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} +.ngeo-tooltip-static:before { + border-top-color: #ffcc33; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.html new file mode 100644 index 000000000..7d2a1727c --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.html @@ -0,0 +1,56 @@ + + + + GeoMapFish EditFeature selector example + + + + + + + +

+ This example shows how to use the gmf-editfeatureselector + directive to edit vector features from editable layers that are defined + in the GeoMapFish themes. First, you need to login. Then, select the + layer you wish to edit. Finally, you can either click on an existing + feature on map to modify or delete it, or you can create a new one using + the "Draw" button. +

+ +

Note: After logging it, you need to refresh the page

+ + + + + + + +
+ + + + + + + + + + +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.js new file mode 100644 index 000000000..425cbfa84 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/editfeatureselector.js @@ -0,0 +1,187 @@ +/** + * @module gmfapp.editfeatureselector + */ +const exports = {}; + +import './editfeatureselector.css'; +import 'jquery-ui/ui/widgets/tooltip.js'; +import gmfAuthenticationModule from 'gmf/authentication/module.js'; + +/** @suppress {extraRequire} */ +import gmfEditingEditFeatureSelectorComponent from 'gmf/editing/editFeatureSelectorComponent.js'; + +import gmfLayertreeComponent from 'gmf/layertree/component.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olCollection from 'ol/Collection.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olSourceVector from 'ol/source/Vector.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfAuthenticationModule.name, + gmfEditingEditFeatureSelectorComponent.name, + gmfLayertreeComponent.name, + gmfLayertreeTreeManager.module.name, + gmfMapComponent.name, + gmfThemeThemes.module.name, + ngeoMiscFeatureHelper.module.name, + ngeoMiscToolActivateMgr.module.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + + +exports.module.value( + 'authenticationBaseUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi'); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('defaultTheme', 'Edit'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {!angular.Scope} $scope Angular scope. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.layertree.TreeManager} gmfTreeManager gmf Tree Manager service. + * @param {gmfx.User} gmfUser User. + * @param {ngeo.misc.FeatureHelper} ngeoFeatureHelper Ngeo feature helper service. + * @param {ngeo.misc.ToolActivateMgr} ngeoToolActivateMgr Ngeo ToolActivate manager + * service. + * @ngInject + * @constructor + */ +exports.MainController = function($scope, gmfThemes, gmfTreeManager, gmfUser, + ngeoFeatureHelper, ngeoToolActivateMgr) { + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {gmfx.User} + * @export + */ + this.gmfUser = gmfUser; + + /** + * @type {ngeo.misc.FeatureHelper} + * @private + */ + this.featureHelper_ = ngeoFeatureHelper; + + gmfThemes.loadThemes(); + + /** + * @type {gmf.layertree.TreeManager} + * @export + */ + this.gmfTreeManager = gmfTreeManager; + + + /** + * @type {ol.layer.Vector} + * @export + */ + this.vectorLayer = new olLayerVector({ + source: new olSourceVector({ + wrapX: false, + features: new olCollection() + }), + style: (feature, resolution) => ngeoFeatureHelper.createEditingStyles(feature) + }); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 2 + }) + }); + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + // Add 'Edit' theme, i.e. the one with id 73 + for (let i = 0, ii = themes.length; i < ii; i++) { + if (themes[i].id === 73) { + this.gmfTreeManager.setFirstLevelGroups(themes[i].children); + break; + } + } + + // Add layer vector after + this.map.addLayer(this.vectorLayer); + } + }); + + /** + * @type {boolean} + * @export + */ + this.editFeatureSelectorActive = true; + + const editFeatureSelectorToolActivate = new ngeoMiscToolActivate( + this, 'editFeatureSelectorActive'); + ngeoToolActivateMgr.registerTool( + 'mapTools', editFeatureSelectorToolActivate, true); + + /** + * @type {boolean} + * @export + */ + this.dummyActive = false; + + const dummyToolActivate = new ngeoMiscToolActivate( + this, 'dummyActive'); + ngeoToolActivateMgr.registerTool( + 'mapTools', dummyToolActivate, false); + + // initialize tooltips + $('[data-toggle="tooltip"]').tooltip({ + container: 'body', + trigger: 'hover' + }); + +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.css new file mode 100644 index 000000000..b2b22d133 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.css @@ -0,0 +1,4 @@ +gmf-map > div { + width: 600px; + height: 400px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.html new file mode 100644 index 000000000..55479031d --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.html @@ -0,0 +1,48 @@ + + + + GMF elevation indicator example + + + + + + + + + + + +
+ Elevation: {{elevationValue}} + Loading +
+
+ +
+ +

This example shows how to use the gmf-elevation directive to get elevation under the mouse position.

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.js new file mode 100644 index 000000000..a4fdbc14a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/elevation.js @@ -0,0 +1,73 @@ +/** + * @module gmfapp.elevation + */ +const exports = {}; + +import './elevation.css'; +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfRasterModule from 'gmf/raster/module.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapComponent.name, + gmfRasterModule.name, +]); + + +exports.module.value( + 'gmfRasterUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/raster'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + /** + * @type {Array.} + * @export + */ + this.elevationLayers = ['aster', 'srtm']; + + /** + * @type {string} + * @export + */ + this.selectedElevationLayer = this.elevationLayers[0]; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [600000, 200000], + zoom: 3 + }) + }); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.css new file mode 100644 index 000000000..af97ca31e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.css @@ -0,0 +1,75 @@ +gmf-map > div { + width: 600px; + height: 400px; +} +gmf-featurestyle { + display: block; + margin: 20px; + width: 260px; +} +gmf-featurestyle .form-horizontal .control-label { + text-align: left; +} +.gmf-featurestyle-name { + font-weight: bold; + font-size: 16pt; +} +.gmf-featurestyle-name:not(:focus) { + border: none; + box-shadow: none; + -webkit-box-shadow: none; + padding: 0; +} +gmf-featurestyle input[type=range] { + padding: 6px 12px; +} +.ngeo-colorpicker-palette { + border-collapse: separate; + border-spacing: 0px; +} +.ngeo-colorpicker-palette tr { + cursor: default; +} +.ngeo-colorpicker-palette td { + position: relative; + padding: 0px; + text-align: center; + vertical-align: middle; + font-size: 1px; + cursor: pointer; +} +.ngeo-colorpicker-palette td > div { + position: relative; + height: 12px; + width: 12px; + border: 1px solid #fff; + box-sizing: content-box; +} +.ngeo-colorpicker-palette td:hover > div::after { + display: block; + content: ''; + background: inherit; + position: absolute; + width: 28px; + height: 28px; + top: -10px; + left: -10px; + border: 2px solid #fff; + -webkit-box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + -webkit-box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + z-index: 11; +} +.ngeo-colorpicker-palette td.ngeo-colorpicker-selected > div::after { + border: 2px solid #444; + margin: 0; + content: ''; + display: block; + width: 14px; + height: 14px; + position: absolute; + left: -3px; + top: -3px; + box-sizing: content-box; + z-index: 10; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.html new file mode 100644 index 000000000..e4dfa1df3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.html @@ -0,0 +1,23 @@ + + + + Feature Style Example + + + + + + + + + + +

+ This example shows how to use the gmf-featurestyle + directive to style a vector feature. Click on a feature to show the + directive. +

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.js new file mode 100644 index 000000000..e8914781f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/featurestyle.js @@ -0,0 +1,225 @@ +/** + * @module gmfapp.featurestyle + */ +const exports = {}; + +import './featurestyle.css'; +import gmfDrawingFeatureStyleComponent from 'gmf/drawing/featureStyleComponent.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import googAsserts from 'goog/asserts.js'; +import ngeoFormatFeatureProperties from 'ngeo/format/FeatureProperties.js'; +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; +import olFeature from 'ol/Feature.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olGeomCircle from 'ol/geom/Circle.js'; +import olGeomLineString from 'ol/geom/LineString.js'; +import olGeomPoint from 'ol/geom/Point.js'; +import olGeomPolygon from 'ol/geom/Polygon.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olSourceVector from 'ol/source/Vector.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfDrawingFeatureStyleComponent.name, + gmfMapComponent.name, + ngeoMiscFeatureHelper.module.name, +]); + + +exports.module.value('ngeoMeasureDecimals', 2); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {!angular.Scope} $scope Angular scope. + * @param {ngeo.misc.FeatureHelper} ngeoFeatureHelper Gmf feature helper service. + * @ngInject + */ +exports.MainController = function($scope, ngeoFeatureHelper) { + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {ngeo.misc.FeatureHelper} + * @private + */ + this.featureHelper_ = ngeoFeatureHelper; + + // create features + const features = []; + + const pointProperties = { + geometry: new olGeomPoint([-8458215, 6672646]) + }; + pointProperties[ngeoFormatFeatureProperties.COLOR] = '#009D57'; + pointProperties[ngeoFormatFeatureProperties.NAME] = 'Point1'; + pointProperties[ngeoFormatFeatureProperties.SIZE] = '6'; + features.push(new olFeature(pointProperties)); + + const textProperties = { + geometry: new olGeomPoint([-8007848, 6209744]) + }; + textProperties[ngeoFormatFeatureProperties.ANGLE] = '0'; + textProperties[ngeoFormatFeatureProperties.COLOR] = '#000000'; + textProperties[ngeoFormatFeatureProperties.IS_TEXT] = true; + textProperties[ngeoFormatFeatureProperties.NAME] = 'Text 1'; + textProperties[ngeoFormatFeatureProperties.SIZE] = '16'; + textProperties[ngeoFormatFeatureProperties.STROKE] = '2'; + features.push(new olFeature(textProperties)); + + const lineProperties = { + geometry: new olGeomLineString([ + [-8321240, 6523441], + [-8103547, 6726458], + [-8091318, 6408480], + [-7973910, 6631065] + ]) + }; + lineProperties[ngeoFormatFeatureProperties.COLOR] = '#0BA9CC'; + lineProperties[ngeoFormatFeatureProperties.NAME] = 'LineString 1'; + lineProperties[ngeoFormatFeatureProperties.STROKE] = '4'; + features.push(new olFeature(lineProperties)); + + const poly1Properties = { + geometry: new olGeomPolygon([ + [ + [-8512027, 6359560], + [-8531595, 6080718], + [-8267428, 6031798], + [-8238077, 6247045], + [-8512027, 6359560] + ] + ]) + }; + poly1Properties[ngeoFormatFeatureProperties.COLOR] = '#4186F0'; + poly1Properties[ngeoFormatFeatureProperties.NAME] = 'Polygon 1'; + poly1Properties[ngeoFormatFeatureProperties.OPACITY] = '0.5'; + poly1Properties[ngeoFormatFeatureProperties.SHOW_MEASURE] = true; + poly1Properties[ngeoFormatFeatureProperties.STROKE] = '1'; + features.push(new olFeature(poly1Properties)); + + const poly2Properties = { + geometry: new olGeomPolygon([ + [ + [-7952508, 6096617], + [-8051570, 5959642], + [-7848554, 5926621], + [-7754383, 6025683], + [-7952508, 6096617] + ] + ]) + }; + poly2Properties[ngeoFormatFeatureProperties.COLOR] = '#CCCCCC'; + poly2Properties[ngeoFormatFeatureProperties.NAME] = 'Polygon 2'; + poly2Properties[ngeoFormatFeatureProperties.OPACITY] = '1'; + poly2Properties[ngeoFormatFeatureProperties.STROKE] = '3'; + features.push(new olFeature(poly2Properties)); + + const rectProperties = { + geometry: olGeomPolygon.fromExtent([-7874848, 6496535, -7730535, 6384020]) + }; + rectProperties[ngeoFormatFeatureProperties.COLOR] = '#000000'; + rectProperties[ngeoFormatFeatureProperties.IS_RECTANGLE] = true; + rectProperties[ngeoFormatFeatureProperties.NAME] = 'Rectangle 1'; + rectProperties[ngeoFormatFeatureProperties.OPACITY] = '0.5'; + rectProperties[ngeoFormatFeatureProperties.STROKE] = '2'; + features.push(new olFeature(rectProperties)); + + const circleProperties = { + geometry: olGeomPolygon.fromCircle( + new olGeomCircle([-7691093, 6166327], 35000), 64) + }; + circleProperties[ngeoFormatFeatureProperties.COLOR] = '#000000'; + circleProperties[ngeoFormatFeatureProperties.IS_CIRCLE] = true; + circleProperties[ngeoFormatFeatureProperties.NAME] = 'Circle 1'; + circleProperties[ngeoFormatFeatureProperties.OPACITY] = '0.5'; + circleProperties[ngeoFormatFeatureProperties.STROKE] = '2'; + features.push(new olFeature(circleProperties)); + + const view = new olView({ + center: [-8174482, 6288627], + zoom: 6 + }); + + ngeoFeatureHelper.setProjection(googAsserts.assert(view.getProjection())); + + // set style + features.forEach((feature) => { + ngeoFeatureHelper.setStyle(feature); + }); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }), + new olLayerVector({ + source: new olSourceVector({ + wrapX: false, + features: features + }) + }) + ], + view: view + }); + + /** + * @type {?ol.Feature} + * @export + */ + this.selectedFeature = null; + + this.map.on('singleclick', this.handleMapSingleClick_, this); +}; + + +/** + * @param {ol.MapBrowserEvent} evt MapBrowser event + * @private + */ +exports.MainController.prototype.handleMapSingleClick_ = function(evt) { + const pixel = evt.pixel; + + const feature = this.map.forEachFeatureAtPixel(pixel, feature => feature); + + if (this.selectedFeature) { + this.featureHelper_.setStyle(this.selectedFeature); + } + + if (feature) { + if (this.selectedFeature !== feature) { + this.selectedFeature = feature; + this.featureHelper_.setStyle(feature, true); + } + } else { + this.selectedFeature = null; + } + + this.scope_.$apply(); + +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.css new file mode 100644 index 000000000..b351a1b14 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.css @@ -0,0 +1,183 @@ +body { + padding: 0; +} +.panel { + display: block; + width: 35rem; +} +gmf-map > div { + width: 71rem; + height: 40rem; +} +gmf-map > div, +.panel { + float: left; + margin: 0.5rem; +} +gmf-filterselector { + display: block; + width: 30rem; +} + +/* Override to allow the layer tree to be fully visible */ +.collapse { + display: block; +} + +/* drawfeature */ + +.gmf-icon-circle:before { + content: "Circle"; +} +.gmf-icon-line:after { + content: 'Line'; +} +.gmf-icon-point:after { + content: 'Point'; +} +.gmf-icon-polygon:after { + content: 'Polygon'; +} +.gmf-icon-rectangle:after { + content: 'Rectangle'; +} +.gmf-icon-text:after { + content: 'Text'; +} + +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; +} +.ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; +} +.ngeo-tooltip-static { + display: none; +} +.ngeo-tooltip-measure:before, +.ngeo-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} +.ngeo-tooltip-static:before { + border-top-color: #ffcc33; +} + +/* CSS for filter */ + +.gmf-filterselector-separator { + margin: 1.5rem 0 0.5rem 0; +} + +.gmf-filterselector-savefilter-desc { + color: #999999; +} + + +.ngeo-filter-condition-button, +.ngeo-filter-condition-button:hover, +.ngeo-filter-condition-button:focus { + text-decoration: none; +} + +.ngeo-filter-condition-criteria-header { + color: #999999; + padding: 0.3rem 2rem; +} + +.ngeo-filter-condition-criteria { + opacity: 0; +} + +.ngeo-filter-condition-criteria-active { + opacity: 1; +} + +.ngeo-filter-rule-custom-rm-btn { + float: right; + margin: 0.4rem 0; +} + +hr.ngeo-filter-separator-rules { + margin: 1rem 0; +} + +hr.ngeo-filter-separator-criteria { + margin: 0.5rem 0; +} + + +ngeo-rule { + display: block; + margin: 1rem 2.5rem 1rem 0; +} + +.ngeo-rule-operators-list { + margin: 0 0 1rem 0; +} + +ngeo-rule .dropdown > a.btn { + display: block; + text-align: left; +} + +ngeo-rule .dropdown > a.btn > span.caret { + position: absolute; + right: 1rem; + top: 1.4rem; +} + +ngeo-rule .dropdown-menu { + padding: 1rem; +} + +.ngeo-rule-btns { + float: right; +} + +.ngeo-rule-type-select label { + width: 13.5rem; +} + +.ngeo-rule-value { + border: 0.1rem solid #aaa; + border-radius: 0 0 0.3rem 0.3rem; + border-top: 0; + color: #999999; + padding: 0.4rem 0.3rem 0.2rem 0.5rem; + margin: -0.2rem 0 0 0; +} + +.ngeo-rule-value a.btn { + color: #999999; + float: right; +} + +.ngeo-rule-value a.btn:hover, +.ngeo-rule-value a.btn:focus { + color: #666666; +} + +ngeo-rule ngeo-date-picker { + display: block; + text-align: right; +} + +.ngeo-rule-type-geometry-instructions { + font-size: 9pt; + font-style: italic; + margin: 0.5rem; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.html new file mode 100644 index 000000000..4e3b9a970 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.html @@ -0,0 +1,61 @@ + + + + GeoMapFish Filter selector example + + + + + + + + + + + + + + +
+

+ This example shows how to use the gmf-filterselector + directive to apply filters on the layers on the map. +

+

+ You can also issue queries on the map by clicking on it or use the + Ctrl key to draw boxes on the map. +

+
+ +
+ + + + + + + + +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.js new file mode 100644 index 000000000..c1633d6b8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/filterselector.js @@ -0,0 +1,187 @@ +/** + * @module gmfapp.filterselector + */ +const exports = {}; +// Todo - use the 'Filter' theme instead if the 'Edit' theme + +import './filterselector.css'; +import 'jquery-ui/ui/widgets/tooltip.js'; +import gmfAuthenticationModule from 'gmf/authentication/module.js'; + +/** @suppress {extraRequire} */ +import gmfDatasourceManager from 'gmf/datasource/Manager.js'; + +import gmfFiltersModule from 'gmf/filters/module.js'; +import gmfLayertreeComponent from 'gmf/layertree/component.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoDatasourceDataSources from 'ngeo/datasource/DataSources.js'; +import ngeoQueryBboxQueryComponent from 'ngeo/query/bboxQueryComponent.js'; +import ngeoQueryMapQueryComponent from 'ngeo/query/mapQueryComponent.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfAuthenticationModule.name, + gmfDatasourceManager.module.name, + gmfLayertreeComponent.name, + gmfLayertreeTreeManager.module.name, + gmfFiltersModule.name, + gmfMapComponent.name, + gmfThemeThemes.module.name, + ngeoDatasourceDataSources.module.name, + ngeoMiscToolActivateMgr.module.name, + ngeoQueryBboxQueryComponent.name, + ngeoQueryMapQueryComponent.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + + +exports.module.value( + 'authenticationBaseUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi'); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('defaultTheme', 'Filters'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +exports.MainController = class { + + /** + * @param {!angular.Scope} $scope Angular scope. + * @param {gmf.datasource.Manager} gmfDataSourcesManager The gmf + * data sources manager service. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.layertree.TreeManager} gmfTreeManager gmf Tree Manager service. + * @param {ngeo.datasource.DataSources} ngeoDataSources Ngeo data sources service. + * @param {ngeo.misc.ToolActivateMgr} ngeoToolActivateMgr Ngeo ToolActivate manager + * service. + * @ngInject + */ + constructor($scope, gmfDataSourcesManager, gmfThemes, gmfTreeManager, + ngeoDataSources, ngeoToolActivateMgr + ) { + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + gmfThemes.loadThemes(); + + /** + * @type {gmf.layertree.TreeManager} + * @export + */ + this.gmfTreeManager = gmfTreeManager; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 2 + }) + }); + + // Init the datasources with our map. + gmfDataSourcesManager.setDatasourceMap(this.map); + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + // Set 'Filters' theme, i.e. the one with id 175 + for (let i = 0, ii = themes.length; i < ii; i++) { + if (themes[i].id === 175) { + this.gmfTreeManager.setFirstLevelGroups(themes[i].children); + break; + } + } + } + }); + + /** + * @type {string} + * @export + */ + this.toolGroup = 'mapTools'; + + /** + * @type {boolean} + * @export + */ + this.filterSelectorActive = true; + + const filterSelectorToolActivate = new ngeoMiscToolActivate( + this, 'filterSelectorActive'); + ngeoToolActivateMgr.registerTool( + 'dummyTools', filterSelectorToolActivate, true); + + /** + * @type {boolean} + * @export + */ + this.dummyActive = false; + + const dummyToolActivate = new ngeoMiscToolActivate( + this, 'dummyActive'); + ngeoToolActivateMgr.registerTool( + 'dummyTools', dummyToolActivate, false); + + /** + * @type {boolean} + * @export + */ + this.queryActive = true; + + const queryToolActivate = new ngeoMiscToolActivate( + this, 'queryActive'); + ngeoToolActivateMgr.registerTool( + this.toolGroup, queryToolActivate, true); + + // initialize tooltips + $('[data-toggle="tooltip"]').tooltip({ + container: 'body', + trigger: 'hover' + }); + + } +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.css new file mode 100644 index 000000000..478d852c3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.css @@ -0,0 +1,291 @@ +/** + * Fonts definition + */ +@font-face { + font-family: "gmf-icons"; + src: url("../fonts/gmf-icons.eot"); + src: url("../fonts/gmf-icons.eot?#iefix") format("embedded-opentype"), + url("../fonts/gmf-icons.woff") format("woff"), + url("../fonts/gmf-icons.ttf") format("truetype"), + url("../fonts/gmf-icons.svg#gmf-icons") format("svg"); + font-weight: normal; + font-style: normal; +} + + +/* CSS stolen from https://github.com/bassjobsen/typeahead.js-bootstrap-css/ */ +span.twitter-typeahead .tt-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +span.twitter-typeahead .tt-suggestion { + display: block; + padding: 3px 20px; + margin-bottom: 0px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +span.twitter-typeahead .tt-suggestion.tt-cursor, +span.twitter-typeahead .tt-suggestion:hover, +span.twitter-typeahead .tt-suggestion:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +span.twitter-typeahead .tt-suggestion button { + background: none; + border: 0; + float: right; +} +span.twitter-typeahead { + width: 100%; +} +.input-group span.twitter-typeahead { + display: block !important; +} +.input-group span.twitter-typeahead .tt-menu { + top: 32px !important; +} +.input-group.input-group-lg span.twitter-typeahead .tt-menu { + top: 44px !important; +} +.input-group.input-group-sm span.twitter-typeahead .tt-menu { + top: 28px !important; +} + + +/* CSS for this example */ + +body { + padding: 0; +} +.panel { + display: block; + width: 60rem; +} +gmf-map > div { + width: 71rem; + height: 40rem; +} +gmf-map > div, +.panel { + float: left; + margin: 0.5rem; +} +gmf-filterselector { + display: block; + width: 30rem; +} + +/* GMF Layer Tree */ +gmf-layertree ul { + list-style-type: none; +} +gmf-layertree a{ + color: black; + text-decoration: none; + padding-right: 5px; +} +gmf-layertree .gmf-layertree-metadata a:before { + font-family: FontAwesome; + content: "\f129"; +} +gmf-layertree .gmf-layertree-layer-icon { + display: inline-flex; + width: 20px; + height: 10px; +} +gmf-layertree .gmf-layertree-zoom { + display: none; +} +gmf-layertree .gmf-layertree-zoom:hover { + cursor: pointer; +} +gmf-layertree .gmf-layertree-zoom:before { + font-family: FontAwesome; + content: "\f18e"; +} +gmf-layertree .outOfResolution .gmf-layertree-legend { + display: none; +} +gmf-layertree .gmf-layertree-legend-button a:after { + font-family: FontAwesome; + content: "\f036"; +} +gmf-layertree .gmf-layertree-legend img { + padding-left: 15px; +} +gmf-layertree .noSource { + opacity: 0.3; +} +gmf-layertree .noSource:after { + content: "(source not available)"; +} +gmf-layertree .outOfResolution { + opacity: 0.6; +} +gmf-layertree .outOfResolution .gmf-layertree-zoom { + display: inline; +} +gmf-layertree .gmf-layertree-state { + font-family: FontAwesome; + font-weight: lighter; +} +gmf-layertree .on .gmf-layertree-state:before { + content: "\f14a"; +} +gmf-layertree .off .gmf-layertree-state:before { + content: "\f096"; +} +gmf-layertree .indeterminate .gmf-layertree-state:before { + content: "\f147"; +} +gmf-layertree .on { + color: green; +} +gmf-layertree .off { + color: red; +} +gmf-layertree .indeterminate { + color: orange; +} +gmf-layertree a.gmf-layertree-expand-node.fa { + display: inline-block; +} +gmf-layertree a.gmf-layertree-expand-node.fa::before { + content: "\f054"; +} +gmf-layertree a.gmf-layertree-expand-node.fa[aria-expanded="true"]::before { + content: "\f078"; +} + +/* ImportDataSource */ +gmf-importdatasource input[type=file] { + display: none; +} + +gmf-wmscapabilitylayertreenode { + display: block; +} + +gmf-wmscapabilitylayertreenode a { + color: black; + text-decoration: none; +} + +gmf-wmscapabilitylayertreenode a:focus, +gmf-wmscapabilitylayertreenode a:hover { + text-decoration: none; +} + +gmf-wmscapabilitylayertreenode ul { + margin: 0; + padding: 0; +} + +gmf-wmscapabilitylayertreenode li { + list-style: none; +} + +gmf-wmscapabilitylayertreenode > ul > li > gmf-wmscapabilitylayertreenode { + margin: 0 0 0 2.5rem; +} + +.gmf-importdatasource-layers > gmf-wmscapabilitylayertreenode { + border: 0.1rem solid #ccc; + max-height: 20rem; + padding: 1rem 1rem 1rem 3rem; + overflow-y: auto; +} + +a.gmf-wmscapabilitylayertreenode-expand-node.fa { + display: inline-block; +} +a.gmf-wmscapabilitylayertreenode-expand-node.fa::before { + content: "\f054"; +} +a.gmf-wmscapabilitylayertreenode-expand-node.fa[aria-expanded="true"]::before { + content: "\f078"; +} + +.gmf-wmscapabilitylayertreenode-group:before { + content: "\e600"; + font-family: gmf-icons; +} + +.gmf-wmscapabilitylayertreenode-popover-content ul { + margin: 0; + padding: 0; +} + +.gmf-wmscapabilitylayertreenode-popover-content li { + list-style: none; +} + +.gmf-wmscapabilitylayertreenode-popover-content a { + cursor: pointer; +} + +.gmf-wmscapabilitylayertreenode-actions { + cursor: pointer; + opacity: 0; + margin: 0 0 0 -2rem; +} + +.gmf-wmscapabilitylayertreenode-header:hover > span > .gmf-wmscapabilitylayertreenode-actions { + opacity: 1; +} + +.gmf-wmscapabilitylayertreenode-no-icon { + font-size: 0.8rem; + vertical-align: middle; +} + +.gmf-wmscapabilitylayertreenode-description { + background-color: #fafafa; + border: 0.1rem solid #ddd; + padding: 1rem; +} + +.gmf-wmscapabilitylayertreenode-description a { + color: #929292; + cursor: pointer; + font-size: 9pt; +} + +.gmf-wmscapabilitylayertreenode-description a:hover { + text-decoration: underline; +} + +.gmf-wmscapabilitylayertreenode-description-toggle { + /* display: none; */ + display: block; + text-align: right; +} + +/* +.gmf-wmscapabilitylayertreenode-description:hover .gmf-wmscapabilitylayertreenode-description-toggle { + display: block; +} +*/ diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.html new file mode 100644 index 000000000..e532d0ade --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.html @@ -0,0 +1,47 @@ + + + + GeoMapFish Import DataSource example + + + + + + + + +
+

+ This example shows how to use the gmf-importdatasource + component, which allows the addition of external WMS/WMTS layers + in the map. It also supports the addition of files, such as + KML and GPX. +

+

+ You can also issue queries on the map by clicking on it or use the + Ctrl key to draw boxes on the map. +

+
+ + + + +
+ + +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.js new file mode 100644 index 000000000..0c50e42c2 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/importdatasource.js @@ -0,0 +1,157 @@ +/** + * @module gmfapp.importdatasource + */ +const exports = {}; +// Todo - use the 'Filter' theme instead if the 'Edit' theme + +import './importdatasource.css'; +import 'jquery-ui/ui/widgets/tooltip.js'; +/** @suppress {extraRequire} */ +import gmfDatasourceManager from 'gmf/datasource/Manager.js'; + +import gmfImportImportdatasourceComponent from 'gmf/import/importdatasourceComponent.js'; +import gmfLayertreeComponent from 'gmf/layertree/component.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoDatasourceDataSources from 'ngeo/datasource/DataSources.js'; + +/** @suppress {extraRequire} */ +import ngeoQueryBboxQueryComponent from 'ngeo/query/bboxQueryComponent.js'; + +import ngeoQueryMapQueryComponent from 'ngeo/query/mapQueryComponent.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfDatasourceManager.module.name, + gmfImportImportdatasourceComponent.name, + gmfLayertreeComponent.name, + gmfLayertreeTreeManager.module.name, + gmfMapComponent.name, + gmfThemeThemes.module.name, + ngeoDatasourceDataSources.module.name, + ngeoQueryBboxQueryComponent.name, + ngeoQueryMapQueryComponent.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.value('gmfExternalOGCServers', [{ + 'name': 'Swiss Topo WMS', + 'type': 'WMS', + 'url': 'https://wms.geo.admin.ch/?lang=fr' +}, { + 'name': 'ASIT VD', + 'type': 'WMTS', + 'url': 'https://ows.asitvd.ch/wmts/1.0.0/WMTSCapabilities.xml' +}, { + 'name': 'Swiss Topo WMTS', + 'type': 'WMTS', + 'url': 'https://wmts.geo.admin.ch/1.0.0/WMTSCapabilities.xml?lang=fr' +}]); + +exports.module.constant('defaultTheme', 'Filters'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +exports.MainController = class { + + /** + * @param {!angular.Scope} $scope Angular scope. + * @param {gmf.datasource.Manager} gmfDataSourcesManager The gmf + * data sources manager service. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.layertree.TreeManager} gmfTreeManager gmf Tree Manager service. + * @param {ngeo.datasource.DataSources} ngeoDataSources Ngeo data sources service. + * @ngInject + */ + constructor($scope, gmfDataSourcesManager, gmfThemes, gmfTreeManager, + ngeoDataSources + ) { + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + gmfThemes.loadThemes(); + + /** + * @type {gmf.layertree.TreeManager} + * @export + */ + this.gmfTreeManager = gmfTreeManager; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 2 + }) + }); + + // Init the datasources with our map. + gmfDataSourcesManager.setDatasourceMap(this.map); + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + // Set 'Filters' theme, i.e. the one with id 175 + for (let i = 0, ii = themes.length; i < ii; i++) { + if (themes[i].id === 175) { + this.gmfTreeManager.setFirstLevelGroups(themes[i].children); + break; + } + } + } + }); + + /** + * @type {boolean} + * @export + */ + this.queryActive = true; + + // initialize tooltips + $('[data-toggle="tooltip"]').tooltip({ + container: 'body', + trigger: 'hover' + }); + + } +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.css new file mode 100644 index 000000000..04723cb89 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.css @@ -0,0 +1,148 @@ +gmf-map > div { + width: 600px; + height: 400px; +} +ul { + list-style-type: none; +} +gmf-layertree a{ + color: black; + text-decoration: none; + padding-right: 5px; +} +gmf-layertree .gmf-layertree-metadata a:before { + font-family: FontAwesome; + content: "\f129"; +} +gmf-layertree .gmf-layertree-layer-icon { + display: inline-flex; + width: 20px; + height: 10px; +} +gmf-layertree .gmf-layertree-zoom { + display: none; +} +gmf-layertree .gmf-layertree-zoom:hover { + cursor: pointer; +} +gmf-layertree .gmf-layertree-zoom:before { + font-family: FontAwesome; + content: "\f18e"; +} +gmf-layertree .outOfResolution .gmf-layertree-legend { + display: none; +} +gmf-layertree .gmf-layertree-legend-button a:after { + font-family: FontAwesome; + content: "\f036"; +} +gmf-layertree .gmf-layertree-legend img { + padding-left: 15px; +} +gmf-layertree .noSource { + opacity: 0.3; +} +gmf-layertree .noSource:after { + content: "(source not available)"; +} +gmf-layertree .outOfResolution { + opacity: 0.6; +} +gmf-layertree .outOfResolution .gmf-layertree-zoom { + display: inline; +} +gmf-layertree .gmf-layertree-state { + font-family: FontAwesome; + font-weight: lighter; +} +gmf-layertree .on .gmf-layertree-state:before { + content: "\f14a"; +} +gmf-layertree .off .gmf-layertree-state:before { + content: "\f096"; +} +gmf-layertree .indeterminate .gmf-layertree-state:before { + content: "\f147"; +} +gmf-layertree .on { + color: green; +} +gmf-layertree .off { + color: red; +} +gmf-layertree .indeterminate { + color: orange; +} +[ngeo-popup] { + top: 20px; + max-width: 350px; + width: 350px; + margin-left: -175px; + left: 50%; + right: 50%; + max-height: 400px; + position: fixed; +} +[ngeo-popup] .popover-content { + overflow: auto; + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(400px - 38px); +} +@media (max-width: 768px) { + #map { + height: 200px; + width: 200px; + } + [ngeo-popup] { + position: fixed; + top: 0; + left: auto; + right: auto; + max-width: 100%; + width: calc(100% - 20px); + height: calc(100% - 20px); + max-height: none; + margin: 10px; + } +} +@media (max-width: 768px) { + [ngeo-popup] .popover-content { + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(100% - 32px); + -webkit-overflow-scrolling: touch; + } +} +#desc, #selections { + margin-bottom: 20px; +} +gmf-layertree a.gmf-layertree-expand-node.fa { + display: inline-block; +} +gmf-layertree a.gmf-layertree-expand-node.fa::before { + content: "\f054"; +} +gmf-layertree a.gmf-layertree-expand-node.fa[aria-expanded="true"]::before { + content: "\f078"; +} + +/** Disclaimer */ +gmf-disclaimer { + position: absolute; + bottom: 0.5rem; + left: 0.5rem; + width: 30rem; +} +gmf-disclaimer .alert { + padding: 0.5rem 1rem; + margin: 0 0 0.5rem 0; +} +gmf-disclaimer .alert-dismissable .close, +gmf-disclaimer .alert-dismissible .close { + right: -0.5rem; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.html new file mode 100644 index 000000000..aba77d9b8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.html @@ -0,0 +1,29 @@ + + + + GeoMapFish Layer Tree Example + + + + + +
+ + + +
+

This example shows how to use the gmf.Layertree directive. This layertree needs a source object (that can change) that describes layers like the c2cgeoportal themes service. The wmsUrl is used by internals WMS layers but you can use WMS externals layers and WMTS layers too.

+
+
New Theme
+
New Group
+
New Layer
+
Remove a tree
+
+ + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.js new file mode 100644 index 000000000..d83e07213 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertree.js @@ -0,0 +1,215 @@ +/** + * @module gmfapp.layertree + */ +const exports = {}; + +import './layertree.css'; +import gmfDisclaimerModule from 'gmf/disclaimer/module.js'; + +import gmfLayertreeComponent from 'gmf/layertree/component.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfThemeManager from 'gmf/theme/Manager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import ngeoStatemanagerLocation from 'ngeo/statemanager/Location.js'; +import ngeoLayertreeModule from 'ngeo/layertree/module.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfLayertreeComponent.name, + gmfLayertreeTreeManager.module.name, + gmfMapComponent.name, + gmfThemeManager.module.name, + gmfThemeThemes.module.name, + ngeoStatemanagerLocation.module.name, + ngeoLayertreeModule.name, + gmfDisclaimerModule.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background&interface=desktop'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {gmf.layertree.TreeManager} gmfTreeManager gmf Tree Manager service. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.theme.Manager} gmfThemeManager gmf Theme Manager service. + * @param {ngeo.statemanager.Location} ngeoLocation ngeo location service. + * @ngInject + */ +exports.MainController = function(gmfTreeManager, gmfThemes, gmfThemeManager, ngeoLocation) { + + gmfThemes.loadThemes(); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); + + // How should disclaimer message be displayed: in modals or alerts + const modal = ngeoLocation.getParam('modal'); + + /** + * @type {boolean} + * @export + */ + this.modal = modal === 'true'; + + /** + * @type {gmf.layertree.TreeManager} + * @export + */ + this.gmfTreeManager = gmfTreeManager; + + /** + * @type {gmf.theme.Manager} + * @export + */ + this.gmfThemeManager = gmfThemeManager; + + /** + * @type {Array.} + * @export + */ + this.themes = []; + + /** + * @type {Array.} + * @export + */ + this.groups = []; + + /** + * @type {Array.} + * @export + */ + this.layers = []; + + /** + * @param {gmfThemes.GmfTheme|undefined} value A theme or undefined to get Themes. + * @return {Array.} All themes. + * @export + */ + this.getSetTheme = function(value) { + if (value) { + this.gmfThemeManager.addTheme(value); + } + return this.themes; + }; + + /** + * @param {gmfThemes.GmfGroup|undefined} value A group or undefined to get groups. + * @return {Array.} All groups in all themes. + * @export + */ + this.getSetGroup = function(value) { + if (value !== undefined) { + this.gmfTreeManager.setFirstLevelGroups([value]); + } + return this.groups; + }; + + /** + * @param {gmfThemes.GmfLayer|undefined} value A group or undefined to get groups. + * @return {Array.} All groups in all themes. + * @export + */ + this.getSetLayers = function(value) { + if (value !== undefined) { + this.gmfTreeManager.addGroupByLayerName(value.name); + } + return this.layers; + }; + + /** + * @param {gmfThemes.GmfGroup|undefined} value A GeoMapFish group, or undefined + * to get the groups of the tree manager. + * @return {Array.} All groups in the tree manager. + * @export + */ + this.getSetRemoveTree = function(value) { + if (value !== undefined) { + this.gmfTreeManager.removeGroup(value); + } + return this.gmfTreeManager.root.children; + }; + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + this.themes = themes; + + // Get an array with all nodes entities existing in "themes". + const flatNodes = []; + this.themes.forEach((theme) => { + theme.children.forEach((group) => { + this.groups.push(group); // get a list of all groups + this.getDistinctFlatNodes_(group, flatNodes); + }); + }); + flatNodes.forEach((node) => { + // Get an array of all layers + if (node.children === undefined) { + this.layers.push(node); + } + }); + } + }); + + /** + * Just for this example + * @param {gmfThemes.GmfTheme|gmfThemes.GmfGroup|gmfThemes.GmfLayer} node A theme, group or layer node. + * @param {Array.} nodes An Array of nodes. + * @export + */ + this.getDistinctFlatNodes_ = function(node, nodes) { + let i; + const children = node.children; + if (children !== undefined) { + for (i = 0; i < children.length; i++) { + this.getDistinctFlatNodes_(children[i], nodes); + } + } + let alreadyAdded = false; + nodes.some((n) => { + if (n.id === node.id) { + return alreadyAdded = true; + } + }); + if (!alreadyAdded) { + nodes.push(node); + } + }; +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.css new file mode 100644 index 000000000..04723cb89 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.css @@ -0,0 +1,148 @@ +gmf-map > div { + width: 600px; + height: 400px; +} +ul { + list-style-type: none; +} +gmf-layertree a{ + color: black; + text-decoration: none; + padding-right: 5px; +} +gmf-layertree .gmf-layertree-metadata a:before { + font-family: FontAwesome; + content: "\f129"; +} +gmf-layertree .gmf-layertree-layer-icon { + display: inline-flex; + width: 20px; + height: 10px; +} +gmf-layertree .gmf-layertree-zoom { + display: none; +} +gmf-layertree .gmf-layertree-zoom:hover { + cursor: pointer; +} +gmf-layertree .gmf-layertree-zoom:before { + font-family: FontAwesome; + content: "\f18e"; +} +gmf-layertree .outOfResolution .gmf-layertree-legend { + display: none; +} +gmf-layertree .gmf-layertree-legend-button a:after { + font-family: FontAwesome; + content: "\f036"; +} +gmf-layertree .gmf-layertree-legend img { + padding-left: 15px; +} +gmf-layertree .noSource { + opacity: 0.3; +} +gmf-layertree .noSource:after { + content: "(source not available)"; +} +gmf-layertree .outOfResolution { + opacity: 0.6; +} +gmf-layertree .outOfResolution .gmf-layertree-zoom { + display: inline; +} +gmf-layertree .gmf-layertree-state { + font-family: FontAwesome; + font-weight: lighter; +} +gmf-layertree .on .gmf-layertree-state:before { + content: "\f14a"; +} +gmf-layertree .off .gmf-layertree-state:before { + content: "\f096"; +} +gmf-layertree .indeterminate .gmf-layertree-state:before { + content: "\f147"; +} +gmf-layertree .on { + color: green; +} +gmf-layertree .off { + color: red; +} +gmf-layertree .indeterminate { + color: orange; +} +[ngeo-popup] { + top: 20px; + max-width: 350px; + width: 350px; + margin-left: -175px; + left: 50%; + right: 50%; + max-height: 400px; + position: fixed; +} +[ngeo-popup] .popover-content { + overflow: auto; + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(400px - 38px); +} +@media (max-width: 768px) { + #map { + height: 200px; + width: 200px; + } + [ngeo-popup] { + position: fixed; + top: 0; + left: auto; + right: auto; + max-width: 100%; + width: calc(100% - 20px); + height: calc(100% - 20px); + max-height: none; + margin: 10px; + } +} +@media (max-width: 768px) { + [ngeo-popup] .popover-content { + /* + * popup's height - popover-title's height + * should be computed using bootstrap variables + */ + max-height: calc(100% - 32px); + -webkit-overflow-scrolling: touch; + } +} +#desc, #selections { + margin-bottom: 20px; +} +gmf-layertree a.gmf-layertree-expand-node.fa { + display: inline-block; +} +gmf-layertree a.gmf-layertree-expand-node.fa::before { + content: "\f054"; +} +gmf-layertree a.gmf-layertree-expand-node.fa[aria-expanded="true"]::before { + content: "\f078"; +} + +/** Disclaimer */ +gmf-disclaimer { + position: absolute; + bottom: 0.5rem; + left: 0.5rem; + width: 30rem; +} +gmf-disclaimer .alert { + padding: 0.5rem 1rem; + margin: 0 0 0.5rem 0; +} +gmf-disclaimer .alert-dismissable .close, +gmf-disclaimer .alert-dismissible .close { + right: -0.5rem; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.html new file mode 100644 index 000000000..aba77d9b8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.html @@ -0,0 +1,29 @@ + + + + GeoMapFish Layer Tree Example + + + + + +
+ + + +
+

This example shows how to use the gmf.Layertree directive. This layertree needs a source object (that can change) that describes layers like the c2cgeoportal themes service. The wmsUrl is used by internals WMS layers but you can use WMS externals layers and WMTS layers too.

+
+
New Theme
+
New Group
+
New Layer
+
Remove a tree
+
+ + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.js new file mode 100644 index 000000000..ec747eaa6 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/layertreeadd.js @@ -0,0 +1,215 @@ +/** + * @module gmfapp.layertreeadd + */ +const exports = {}; + +import './layertreeadd.css'; +import gmfDisclaimerModule from 'gmf/disclaimer/module.js'; + +import gmfLayertreeComponent from 'gmf/layertree/component.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +/** @suppress {extraRequire} */ +import gmfThemeThemes from 'gmf/theme/Themes.js'; + +import gmfThemeManager from 'gmf/theme/Manager.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import ngeoStatemanagerLocation from 'ngeo/statemanager/Location.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfLayertreeComponent.name, + gmfLayertreeTreeManager.module.name, + gmfMapComponent.name, + gmfThemeManager.module.name, + gmfThemeThemes.module.name, + ngeoStatemanagerLocation.module.name, + gmfDisclaimerModule.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background&interface=desktop'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('gmfTreeManagerModeFlush', false); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {gmf.layertree.TreeManager} gmfTreeManager gmf Tree Manager service. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.theme.Manager} gmfThemeManager gmf Tree Manager service. + * @param {ngeo.statemanager.Location} ngeoLocation ngeo location service. + * @ngInject + */ +exports.MainController = function(gmfTreeManager, gmfThemes, gmfThemeManager, ngeoLocation) { + + gmfThemes.loadThemes(); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); + + // How should disclaimer message be displayed: in modals or alerts + const modal = ngeoLocation.getParam('modal'); + + /** + * @type {boolean} + * @export + */ + this.modal = modal === 'true'; + + /** + * @type {gmf.layertree.TreeManager} + * @export + */ + this.gmfTreeManager = gmfTreeManager; + + /** + * @type {gmf.theme.Manager} + * @export + */ + this.gmfThemeManager = gmfThemeManager; + + /** + * @type {Array.} + * @export + */ + this.themes = []; + + /** + * @type {Array.} + * @export + */ + this.groups = []; + + /** + * @type {Array.} + * @export + */ + this.layers = []; + + /** + * @param {gmfThemes.GmfTheme|undefined} value A theme or undefined to get Themes. + * @return {Array.} All themes. + * @export + */ + this.getSetTheme = function(value) { + if (value) { + this.gmfThemeManager.addTheme(value); + } + return this.themes; + }; + + /** + * @param {gmfThemes.GmfGroup|undefined} value A group or undefined to get groups. + * @return {Array.} All groups in all themes. + * @export + */ + this.getSetGroup = function(value) { + if (value !== undefined) { + this.gmfTreeManager.addFirstLevelGroups([value]); + } + return this.groups; + }; + + /** + * @param {gmfThemes.GmfLayer|undefined} value A group or undefined to get groups. + * @return {Array.} All groups in all themes. + * @export + */ + this.getSetLayers = function(value) { + if (value !== undefined) { + this.gmfTreeManager.addGroupByLayerName(value.name); + } + return this.layers; + }; + + /** + * @param {gmfThemes.GmfGroup|undefined} value A GeoMapFish group node, or undefined + * to get the groups of the tree manager. + * @return {Array.} All groups in the tree manager. + * @export + */ + this.getSetRemoveTree = function(value) { + if (value !== undefined) { + this.gmfTreeManager.removeGroup(value); + } + return this.gmfTreeManager.root.children; + }; + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + this.themes = themes; + + // Get an array with all nodes entities existing in "themes". + const flatNodes = []; + this.themes.forEach((theme) => { + theme.children.forEach((group) => { + this.groups.push(group); // get a list of all groups + this.getDistinctFlatNodes_(group, flatNodes); + }); + }); + flatNodes.forEach((node) => { + // Get an array of all layers + if (node.children === undefined) { + this.layers.push(node); + } + }); + } + }); + + /** + * Just for this example + * @param {gmfThemes.GmfTheme|gmfThemes.GmfGroup|gmfThemes.GmfLayer} node A theme, group or layer node. + * @param {Array.} nodes An Array of nodes. + * @export + */ + this.getDistinctFlatNodes_ = function(node, nodes) { + let i; + const children = node.children; + if (children !== undefined) { + for (i = 0; i < children.length; i++) { + this.getDistinctFlatNodes_(children[i], nodes); + } + } + let alreadyAdded = false; + nodes.some((n) => { + if (n.id === node.id) { + return alreadyAdded = true; + } + }); + if (!alreadyAdded) { + nodes.push(node); + } + }; +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.css new file mode 100644 index 000000000..4a5088db4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.css @@ -0,0 +1,59 @@ +gmf-map > div { + width: 80rem; + height: 40rem; +} +#gmf-lidarprofile-container { + position: relative; + overflow: hidden; + padding: 2rem; + border-top: solid 1px black; + background-color: white; + height: 35rem; + display: flex; +} + +#gmf-lidarprofile-container .lidarprofile { + width: 60rem; + background-color: #f5f5f5; +} + +#gmf-lidarprofile-container .lidar-legend { + list-style-type: none; + width: 15rem; + padding: 2rem; +} + +#gmf-lidarprofile-container .close { + display: none; +} + +#gmf-lidarprofile-container .lidar-error { + visibility: hidden; + position: absolute; + color: #4b717f; + padding-left: 100px; + padding-top: 100px; + z-index: 10; + font-size: 1.5em; + opacity: 1; + background: #e1f1f7; + width: 90%; + height: 100%; +} + +#gmf-lidarprofile-container .lod-info { + max-height: 90px; + overflow-y: auto; +} + +.gmf-lidarprofile-automatic-width { + color: gray; +} + +.gmf-lidarprofile-chart-active main { + height: 60rem; +} + +.gmf-tooltip-measure { + font-weight: bold; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.html new file mode 100644 index 000000000..d2a1948bb --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.html @@ -0,0 +1,28 @@ + + + + GMF profile example + + + + + +
+ +

This example shows how to use the gmf-lidarprofile with the gmf-lidar-panel.

+ + + +
+
+ + +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.js new file mode 100644 index 000000000..a1df0b219 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/lidarprofile.js @@ -0,0 +1,70 @@ +/** + * @module gmfapp.lidarprofile + */ +const exports = {}; + +import './lidarprofile.css'; +import gmfMapComponent from 'gmf/map/component.js'; +import gmfLidarprofileModule from 'gmf/lidarprofile/module.js'; +import EPSG2056 from 'ngeo/proj/EPSG2056.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapComponent.name, + gmfLidarprofileModule.name, + ngeoMapModule.name, // for ngeo.map.FeatureOverlay, perhaps remove me +]); + + +exports.module.value('pytreeLidarprofileJsonUrl', 'https://sitn.ne.ch/pytree/pytree_dev/'); + + +/** + * @param {angular.Scope} $scope Angular scope. + * @constructor + * @ngInject + */ +exports.MainController = function($scope) { + /** + * @type {ol.geom.LineString} + * @export + */ + this.profileLine = null; + + /** + * @type {boolean} + * @export + */ + this.panelActivated = false; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG2056, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [2551894, 1202362], + zoom: 3 + }) + }); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.css new file mode 100644 index 000000000..c3cf29d76 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.css @@ -0,0 +1,40 @@ +gmf-map > div { + width: 800px; + height: 400px; + max-width:100%; +} +[ngeo-btn-group] { + padding: 5px; +} +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; +} +.ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; +} +.ngeo-tooltip-static { + background-color: #ffcc33; + color: black; + border: 1px solid white; +} +.ngeo-tooltip-measure:before, +.ngeo-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} +.ngeo-tooltip-static:before { + border-top-color: #ffcc33; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.html new file mode 100644 index 000000000..d9da0ea9c --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.html @@ -0,0 +1,44 @@ + + + + Mobile Measure Example + + + + + + + +
+ Length + Point +
+
+
+
+
+ +

+ This example shows how to use the gmf-mobile-measure-length + and gmf-mobile-measure-point directives in combination with + ngeo.interaction.MobileDraw interaction objects to allow + mobile users to measure distances and know the center coordinate on + their devices. The point measure also uses the gmfRaster + service to also obtain the height of the location as well. +

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.js new file mode 100644 index 000000000..196411e9a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mobilemeasure.js @@ -0,0 +1,100 @@ +/** + * @module gmfapp.mobilemeasure + */ +const exports = {}; + +import './mobilemeasure.css'; +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +/** @suppress {extraRequire} */ +import gmfPermalinkPermalink from 'gmf/permalink/Permalink.js'; + +import gmfMobileMeasureLengthComponent from 'gmf/mobile/measure/lengthComponent.js'; +import gmfMobileMeasurePointComponent from 'gmf/mobile/measure/pointComponent.js'; +import ngeoMiscBtnComponent from 'ngeo/misc/btnComponent.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olControlScaleLine from 'ol/control/ScaleLine.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapComponent.name, + gmfPermalinkPermalink.module.name, + gmfMobileMeasureLengthComponent.name, + gmfMobileMeasurePointComponent.name, + ngeoMiscBtnComponent.name, +]); + + +exports.module.value( + 'gmfRasterUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/raster'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {gmf.permalink.Permalink} gmfPermalink The gmf permalink service. + * @constructor + * @ngInject + */ +exports.MainController = function(gmfPermalink) { + + const center = gmfPermalink.getMapCenter() || [537635, 152640]; + const zoom = gmfPermalink.getMapZoom() || 3; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: center, + zoom: zoom + }) + }); + + this.map.addControl(new olControlScaleLine()); + + /** + * @type {boolean} + * @export + */ + this.measureLengthActive = false; + + /** + * @type {Object.} + * @export + */ + this.measurePointLayersConfig = [ + {name: 'aster', unit: 'm', decimals: 2}, + {name: 'srtm', unit: 'm'} + ]; + + /** + * @type {boolean} + * @export + */ + this.measurePointActive = false; + +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.css new file mode 100644 index 000000000..221dd1083 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.css @@ -0,0 +1,20 @@ +gmf-map > div { + width: 600px; + height: 400px; +} +gmf-mouseposition>div { + min-width: 260px; +} +.dropdown-menu { + min-width: 260px; +} +.gmf-mouseposition-control { + display: inline-block; + min-width: 200px; +} +.footer { + text-align: right; + min-height: 30px; + background-color: rgba(224, 224, 224, 0.8); + width: 600px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.html new file mode 100644 index 000000000..7f53058e4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.html @@ -0,0 +1,21 @@ + + + + GeoMapFish Mouse Position Example + + + + + +
+ + +
+

This example shows how to use the gmf.mouseposition directive.

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.js new file mode 100644 index 000000000..fe4364040 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/mouseposition.js @@ -0,0 +1,74 @@ +/** + * @module gmfapp.mouseposition + */ +const exports = {}; + +import './mouseposition.css'; +/** @suppress {extraRequire} */ +import gmfMapModule from 'gmf/map/module.js'; + +import EPSG2056 from 'ngeo/proj/EPSG2056.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapModule.name, +]); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + + const epsg2056template = 'Coordinates (m): {x}, {y}'; + + /** + * @type {Array.} + * @export + */ + this.projections = [{ + code: EPSG2056, + label: 'CH1903+ / LV95', + filter: `ngeoNumberCoordinates:0:${epsg2056template}` + }, { + code: EPSG21781, + label: 'CH1903 / LV03', + filter: 'ngeoNumberCoordinates:2:[{x} E; {y} N]' + }, { + code: 'EPSG:4326', + label: 'WGS84', + filter: 'ngeoDMSCoordinates:2' + }]; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + center: [828042, 5933739], + zoom: 8 + }) + }); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.css new file mode 100644 index 000000000..79e4e4be3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.css @@ -0,0 +1,52 @@ +gmf-map > div { + width: 600px; + height: 400px; +} +gmf-objectediting { + border: 1px solid #ddd; + display: block; + margin: 10px 0; + padding: 4px; + width: 400px; +} +gmf-objecteditingtools { + border-bottom: 0.1rem solid #595959; + display: block; + margin: 0 0 1rem 0; + padding: 0 0 1rem 0; +} +gmf-layertree { + display: none; +} + +/* measure tooltips */ +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; +} +.ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; +} +.ngeo-tooltip-static { + display: none; +} +.ngeo-tooltip-measure:before, +.ngeo-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; +} +.ngeo-tooltip-static:before { + border-top-color: #ffcc33; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.html new file mode 100644 index 000000000..ba433ae2a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.html @@ -0,0 +1,55 @@ + + + + ObjectEditing example + + + + + + + + + + + + + + + + +

ObjectEditing

+ + + + +

+ This example shows how to use the gmf-objectediting + directive to edit a single feature with advanced editing tools. +

+

+ In order for this example to work properly, you must: +

+

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.js new file mode 100644 index 000000000..da2c25dc2 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objectediting.js @@ -0,0 +1,188 @@ +/** + * @module gmfapp.objectediting + */ +const exports = {}; + +import './objectediting.css'; +import gmfLayertreeComponent from 'gmf/layertree/component.js'; + +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +/** @suppress {extraRequire} */ +import gmfObjecteditingComponent from 'gmf/objectediting/component.js'; + +import gmfObjecteditingManager from 'gmf/objectediting/Manager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import * as olProj from 'ol/proj.js'; +import olCollection from 'ol/Collection.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olSourceVector from 'ol/source/Vector.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfLayertreeComponent.name, + gmfLayertreeTreeManager.module.name, + gmfMapComponent.name, + gmfObjecteditingComponent.name, + gmfObjecteditingManager.module.name, + gmfThemeThemes.module.name, + ngeoMiscToolActivateMgr.module.name, +]); + +exports.module.constant('defaultTheme', 'ObjectEditing'); +exports.module.constant('gmfLayersUrl', 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); +exports.module.constant('gmfTreeUrl', 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); +exports.module.constant('gmfObjectEditingToolsOptions', { + regularPolygonRadius: 150 +}); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {gmf.objectediting.Manager} gmfObjectEditingManager The gmf + * ObjectEditing manager service. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.layertree.TreeManager} gmfTreeManager gmf Tree Manager service. + * @param {ngeo.misc.ToolActivateMgr} ngeoToolActivateMgr Ngeo ToolActivate manager + * service. + * @constructor + * @ngInject + */ +exports.MainController = function(gmfObjectEditingManager, gmfThemes, + gmfTreeManager, ngeoToolActivateMgr) { + + /** + * @type {gmf.layertree.TreeManager} + * @private + */ + this.gmfTreeManager_ = gmfTreeManager; + + gmfThemes.loadThemes(); + + const projection = olProj.get(EPSG21781); + projection.setExtent([485869.5728, 76443.1884, 837076.5648, 299941.7864]); + + /** + * @type {ol.source.Vector} + * @private + */ + this.vectorSource_ = new olSourceVector({ + wrapX: false + }); + + /** + * @type {ol.layer.Vector} + * @private + */ + this.vectorLayer_ = new olLayerVector({ + source: this.vectorSource_ + }); + + /** + * @type {ol.Collection.} + * @export + */ + this.sketchFeatures = new olCollection(); + + /** + * @type {ol.layer.Vector} + * @private + */ + this.sketchLayer_ = new olLayerVector({ + source: new olSourceVector({ + features: this.sketchFeatures, + wrapX: false + }) + }); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 2 + }) + }); + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + // Add layer vector after + this.map.addLayer(this.vectorLayer_); + this.map.addLayer(this.sketchLayer_); + } + }); + + /** + * @type {string|undefined} + * @export + */ + this.objectEditingGeomType = gmfObjectEditingManager.getGeomType(); + + /** + * @type {number|undefined} + * @export + */ + this.objectEditingLayerNodeId = gmfObjectEditingManager.getLayerNodeId(); + + /** + * @type {boolean} + * @export + */ + this.objectEditingActive = true; + + const objectEditingToolActivate = new ngeoMiscToolActivate( + this, 'objectEditingActive'); + ngeoToolActivateMgr.registerTool( + 'mapTools', objectEditingToolActivate, true); + + /** + * @type {boolean} + * @export + */ + this.dummyActive = false; + + const dummyToolActivate = new ngeoMiscToolActivate( + this, 'dummyActive'); + ngeoToolActivateMgr.registerTool( + 'mapTools', dummyToolActivate, false); + + /** + * @type {?ol.Feature} + * @export + */ + this.objectEditingFeature = null; + + gmfObjectEditingManager.getFeature().then((feature) => { + this.objectEditingFeature = feature; + if (feature) { + this.vectorSource_.addFeature(feature); + } + }); + +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.css new file mode 100644 index 000000000..a567e992a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.css @@ -0,0 +1,4 @@ +.gmf-oe-hub-form { + padding: 10px; + width: 300px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.html new file mode 100644 index 000000000..4a246c511 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.html @@ -0,0 +1,82 @@ + + + + ObjectEditing - Hub + + + + + + +

+ This example serves as a hub for other examples and applications + that uses the ObjectEditing tools. You need to be logged in too. +

+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.js new file mode 100644 index 000000000..8203b77d4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/objecteditinghub.js @@ -0,0 +1,478 @@ +/** + * @module gmfapp.objecteditinghub + */ +const exports = {}; + +import './objecteditinghub.css'; +import googAsserts from 'goog/asserts.js'; + +import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes.js'; +import gmfObjecteditingManager from 'gmf/objectediting/Manager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import olFormatWFS from 'ol/format/WFS.js'; +import ngeoFormatXSDAttribute from 'ngeo/format/XSDAttribute.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfEditingXSDAttributes.module.name, + gmfObjecteditingManager.module.name, + gmfThemeThemes.module.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {angular.$http} $http Angular $http service. + * @param {angular.$q} $q Angular $q service. + * @param {!angular.Scope} $scope Angular scope. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.editing.XSDAttributes} gmfXSDAttributes The gmf XSDAttributes service. + * @constructor + * @ngInject + */ +exports.MainController = function($http, $q, $scope, gmfThemes, gmfXSDAttributes) { + + /** + * @type {angular.$http} + * @private + */ + this.http_ = $http; + + /** + * @type {angular.$q} + * @private + */ + this.q_ = $q; + + /** + * @type {gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + /** + * @type {gmf.editing.XSDAttributes} + * @private + */ + this.gmfXSDAttributes_ = gmfXSDAttributes; + + /** + * @type {Array.} List of example and application urls that contain + * ObjectEditing tools. + * @export + */ + this.urls = [ + { + 'name': 'oeedit app. (hosted)', + 'url': 'apps/oeedit/' + }, + { + 'name': 'oeedit app. (dev)', + 'url': '../apps/oeedit/' + }, + { + 'name': 'example', + 'url': 'objectediting.html' + } + ]; + + /** + * @type {string} OE viewer application base url when developping. + * @private + */ + this.viewerUrlDev_ = '../apps/oeview/'; + + /** + * @type {string} OE viewer application base url when hosted. + * @private + */ + this.viewerUrlHosted_ = 'apps/oeview/'; + + /** + * @type {Object.} + * @export + */ + this.selectedUrl = this.urls[0]; + + /** + * @type {gmfThemes.GmfOgcServers} ogcServers OGC servers. + * @private + */ + this.gmfServers_; + + /** + * @type {gmfThemes.GmfOgcServer} ogcServer OGC server to use. + * @private + */ + this.gmfServer_; + + /** + * @type {Array.} + * @export + */ + this.gmfLayerNodes = []; + + /** + * @type {?gmfThemes.GmfLayerWMS} + * @export + */ + this.selectedGmfLayerNode = null; + + /** + * @type {Object.>} + * @export + */ + this.featuresCache_ = {}; + + /** + * @type {Array.} + * @export + */ + this.features = null; + + /** + * @type {?ol.Feature} + * @export + */ + this.selectedFeature = null; + + /** + * @type {Object.} + * @private + */ + this.geomTypeCache_ = {}; + + /** + * @type {string|undefined} + * @export + */ + this.selectedGeomType = undefined; + + $scope.$watch( + () => this.selectedGmfLayerNode, + (newVal, oldVal) => { + this.selectedFeature = null; + + if (newVal) { + this.getFeatures_(newVal).then( + this.handleGetFeatures_.bind(this, newVal) + ); + this.getGeometryType_(newVal).then( + this.handleGetGeometryType_.bind(this, newVal) + ); + } + } + ); + + /** + * @type {string} + * @export + */ + this.themeName = 'ObjectEditing'; + + this.gmfThemes_.loadThemes(); + + this.gmfThemes_.getOgcServersObject().then((ogcServers) => { + + // (1) Set OGC servers + this.gmfServers_ = ogcServers; + + this.gmfThemes_.getThemesObject().then((themes) => { + if (!themes) { + return; + } + + let i, ii; + + // (2) Find OE theme + let theme; + for (i = 0, ii = themes.length; i < ii; i++) { + if (themes[i].name === this.themeName) { + theme = themes[i]; + break; + } + } + + if (!theme) { + return; + } + + // (3) Get first group node + const groupNode = theme.children[0]; + + // (4) Set OGC server, which must support WFS for this example to work + googAsserts.assert(groupNode.ogcServer); + const gmfServer = this.gmfServers_[groupNode.ogcServer]; + if (gmfServer && gmfServer.wfsSupport === true && gmfServer.urlWfs) { + this.gmfServer_ = gmfServer; + } else { + return; + } + + const gmfLayerNodes = []; + for (i = 0, ii = groupNode.children.length; i < ii; i++) { + if (groupNode.children[i].metadata.identifierAttributeField) { + gmfLayerNodes.push(groupNode.children[i]); + } + } + + // (5) Set layer nodes + this.gmfLayerNodes = gmfLayerNodes; + + // (6) Select 'polygon' for the purpose of simplifying the demo + this.selectedGmfLayerNode = this.gmfLayerNodes[1]; + + }); + }); + +}; + + +/** + * @export + */ +exports.MainController.prototype.runEditor = function() { + + const geomType = this.selectedGeomType; + const feature = this.selectedFeature; + const layer = this.selectedGmfLayerNode.id; + const property = this.selectedGmfLayerNode.metadata.identifierAttributeField; + googAsserts.assert(property !== undefined); + const id = feature.get(property); + + const params = {}; + params[gmfObjecteditingManager.Param.GEOM_TYPE] = geomType; + params[gmfObjecteditingManager.Param.ID] = id; + params[gmfObjecteditingManager.Param.LAYER] = layer; + params[gmfObjecteditingManager.Param.THEME] = this.themeName; + params[gmfObjecteditingManager.Param.PROPERTY] = property; + + const url = exports.MainController.appendParams(this.selectedUrl['url'], params); + window.open(url); +}; + + +/** + * @export + */ +exports.MainController.prototype.runViewerDev = function() { + this.runViewer_(this.viewerUrlDev_); +}; + + +/** + * @export + */ +exports.MainController.prototype.runViewerHosted = function() { + this.runViewer_(this.viewerUrlHosted_); +}; + + +/** + * @param {string} baseUrl Base url of the viewer. + * @private + */ +exports.MainController.prototype.runViewer_ = function(baseUrl) { + + const node = this.selectedGmfLayerNode; + const nodeId = node.id; + const nodeName = node.name; + const nodeIdAttrFieldName = node.metadata.identifierAttributeField; + googAsserts.assert(nodeIdAttrFieldName !== undefined); + const ids = []; + + const features = this.featuresCache_[nodeId]; + for (let i = 0, ii = features.length; i < ii; i++) { + ids.push( + features[i].get(nodeIdAttrFieldName) + ); + } + + const params = {}; + params['wfs_layer'] = nodeName; + params[`wfs_${nodeIdAttrFieldName}`] = ids.join(','); + + const url = exports.MainController.appendParams(baseUrl, params); + window.open(url); +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @return {angular.$q.Promise} The promise attached to the deferred object. + * @private + */ +exports.MainController.prototype.getFeatures_ = function(gmfLayerNode) { + + this.getFeaturesDeferred_ = this.q_.defer(); + + const features = this.getFeaturesFromCache_(gmfLayerNode); + + if (features) { + this.getFeaturesDeferred_.resolve(); + } else { + this.issueGetFeatures_(gmfLayerNode); + } + + return this.getFeaturesDeferred_.promise; +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @private + */ +exports.MainController.prototype.issueGetFeatures_ = function(gmfLayerNode) { + + const id = gmfLayerNode.id; + + const url = exports.MainController.appendParams( + this.gmfServer_.urlWfs, + { + 'SERVICE': 'WFS', + 'REQUEST': 'GetFeature', + 'VERSION': '1.1.0', + 'TYPENAME': gmfLayerNode.layers + } + ); + + this.http_.get(url).then((response) => { + const features = new olFormatWFS().readFeatures(response.data); + this.featuresCache_[id] = features; + this.getFeaturesDeferred_.resolve(); + }); +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @private + */ +exports.MainController.prototype.handleGetFeatures_ = function(gmfLayerNode) { + const features = /** @type Array. */ ( + this.getFeaturesFromCache_(gmfLayerNode)); + this.features = features; + this.selectedFeature = this.features[0]; +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @return {?Array.} List of features + * @private + */ +exports.MainController.prototype.getFeaturesFromCache_ = function(gmfLayerNode) { + const id = gmfLayerNode.id; + const features = this.featuresCache_[id] || null; + return features; +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @return {angular.$q.Promise} The promise attached to the deferred object. + * @private + */ +exports.MainController.prototype.getGeometryType_ = function(gmfLayerNode) { + + this.getGeometryTypeDeferred_ = this.q_.defer(); + + const geomType = this.getGeometryTypeFromCache_(gmfLayerNode); + + if (geomType) { + this.getGeometryTypeDeferred_.resolve(); + } else { + this.issueGetAttributesRequest_(gmfLayerNode); + } + + return this.getGeometryTypeDeferred_.promise; +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @private + */ +exports.MainController.prototype.issueGetAttributesRequest_ = function( + gmfLayerNode +) { + + this.gmfXSDAttributes_.getAttributes(gmfLayerNode.id).then( + function(gmfLayerNode, attributes) { + // Get geom type from attributes and set + const geomAttr = ngeoFormatXSDAttribute.getGeometryAttribute(attributes); + if (geomAttr && geomAttr.geomType) { + this.geomTypeCache_[gmfLayerNode.id] = geomAttr.geomType; + this.getGeometryTypeDeferred_.resolve(); + } + }.bind(this, gmfLayerNode) + ); + +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @private + */ +exports.MainController.prototype.handleGetGeometryType_ = function(gmfLayerNode) { + const geomType = this.getGeometryTypeFromCache_(gmfLayerNode); + this.selectedGeomType = geomType; +}; + + +/** + * @param {gmfThemes.GmfLayerWMS} gmfLayerNode Layer node. + * @return {string|undefined} The type of geometry. + * @private + */ +exports.MainController.prototype.getGeometryTypeFromCache_ = function( + gmfLayerNode +) { + const id = gmfLayerNode.id; + const geomType = this.geomTypeCache_[id]; + return geomType; +}; + + +/** + * Appends query parameters to a URI. + * + * @param {string} uri The original URI, which may already have query data. + * @param {!Object} params An object where keys are URI-encoded parameter keys, + * and the values are arbitrary types or arrays. + * @return {string} The new URI. + */ +exports.MainController.appendParams = function(uri, params) { + const keyParams = []; + // Skip any null or undefined parameter values + Object.keys(params).forEach((k) => { + if (params[k] !== null && params[k] !== undefined) { + keyParams.push(`${k}=${encodeURIComponent(params[k])}`); + } + }); + const qs = keyParams.join('&'); + // remove any trailing ? or & + uri = uri.replace(/[?&]$/, ''); + // append ? or & depending on whether uri has existing parameters + uri = uri.indexOf('?') === -1 ? `${uri}?` : `${uri}&`; + return uri + qs; +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/partials/contextualdata.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/partials/contextualdata.html new file mode 100644 index 000000000..29ffe62c5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/partials/contextualdata.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + +
+ Swiss grid (LV03) + + {{coord_21781|ngeoNumberCoordinates:0:'{x} / {y}'}} +
+ Wgs Coord. + + {{coord_4326|ngeoNumberCoordinates:2:'{y} / {x}'}} +
+ Elevation (SRTM) + + {{srtm | number}} [m] +
+ Elevation (Aster) + + {{aster | number}} [m] +
+ Delta (SRTM - Aster) + + {{elelvation_diff}} [m] +
+Google StreetView diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/partials/queryresult.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/partials/queryresult.html new file mode 100644 index 000000000..d1fbc139f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/partials/queryresult.html @@ -0,0 +1,38 @@ +

Total: {{ $ctrl.result.total }}

+ + + +
+ +
+
+

{{ ::feature.get('display_name') }}

+
+ + : + + +
+
+
+
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.css new file mode 100644 index 000000000..27f2a4f38 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.css @@ -0,0 +1,10 @@ +gmf-map > div { + width: 600px; + height: 400px; +} +.ngeo-popover .popover-content { + padding: 1px 2px; +} +.gmf-permalink-tooltip { + padding: 9px 14px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.html new file mode 100644 index 000000000..a465b2756 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.html @@ -0,0 +1,39 @@ + + + + GeoMapFish Permalink example + + + + + + + + +

+ This example demonstrates the use of the gmf-permalink + service, which is injected inside the gmf-map directive. + The following links demonstrate the different features: +

    +
  • + map_crosshair=true + When set, a marker is added either at the location of the + map_x and map_y if those parameters + are set, otherwise it is added at the center of the map. +
  • +
  • + map_tooltip=hello + When set, a tooltip is added with the content equal to the value + set either at the location of the map_x and + map_y if those parameters are set, otherwise it is + added at the center of the map. +
  • +
  • no param
  • +
+ This example also demonstrates the use of the + gmfPermalinkOptions to customize the permalink crosshair + feature style. +

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.js new file mode 100644 index 000000000..5a9fa3b28 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/permalink.js @@ -0,0 +1,73 @@ +/** + * @module gmfapp.permalink + */ +const exports = {}; + +import './permalink.css'; +/** @suppress {extraRequire} */ +import gmfMapModule from 'gmf/map/module.js'; + +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olStyleRegularShape from 'ol/style/RegularShape.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapModule.name, +]); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +exports.module.value('gmfPermalinkOptions', + /** @type {gmfx.PermalinkOptions} */ ({ + crosshairStyle: new olStyleStyle({ + image: new olStyleRegularShape({ + stroke: new olStyleStroke({ + color: 'rgba(0, 0, 255, 1)', + width: 2 + }), + points: 4, + radius: 8, + radius2: 0, + angle: 0 + }) + }) + })); + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.css new file mode 100644 index 000000000..e015a26ae --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.css @@ -0,0 +1,143 @@ +gmf-map, +#tree-container { + float: left; +} +.clear-left { + clear: left; +} +gmf-map > div { + width: 600px; + height: 400px; +} +.printpanel { + width: 250px; + margin: 10px; + padding: 10px; + background-color: #D3E5D7; +} +.tools-content-heading { + border-bottom: solid 1px; +} +.tools-content-heading .close { + line-height: 0; +} +input[type=range] { + -webkit-appearance: none; + width: 100%; + padding-right: 0 !important; + padding-left: 0 !important; +} +input[type=range]:focus { + outline: none; +} +input[type=range]::-webkit-slider-runnable-track { + width: 100%; + height: 5px; + cursor: pointer; + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0); + background: rgba(148, 172, 154, 0.78); + border-radius: 1px; + border: 0.2px solid rgba(1, 1, 1, 0.2); +} +input[type=range]::-webkit-slider-thumb { + box-shadow: 0.9px 0.9px 1px rgba(0, 0, 49, 0.2), 0px 0px 0.9px rgba(0, 0, 75, 0.2); + border: 1px solid rgba(0, 0, 30, 0.2); + height: 20px; + width: 10px; + border-radius: 5px; + background: #ffffff; + cursor: pointer; + -webkit-appearance: none; + margin-top: -7.7px; +} +input[type=range]:focus::-webkit-slider-runnable-track { + background: rgba(205, 217, 208, 0.78); +} +input[type=range]::-moz-range-track { + width: 100%; + height: 5px; + cursor: pointer; + box-shadow: 1px 1px 1px rgba(0, 0, 0, 0), 0px 0px 1px rgba(13, 13, 13, 0); + background: rgba(148, 172, 154, 0.78); + border-radius: 1px; + border: 0.2px solid rgba(1, 1, 1, 0.2); +} +input[type=range]::-moz-range-thumb { + box-shadow: 0.9px 0.9px 1px rgba(0, 0, 49, 0.2), 0px 0px 0.9px rgba(0, 0, 75, 0.2); + border: 1px solid rgba(0, 0, 30, 0.2); + height: 20px; + width: 10px; + border-radius: 5px; + background: #ffffff; + cursor: pointer; +} +/* Layertree */ +ul { + list-style-type: none; +} +gmf-layertree a{ + color: black; + text-decoration: none; + padding-right: 5px; +} +gmf-layertree .gmf-layertree-metadata a:before { + font-family: FontAwesome; + content: "\f129"; +} +gmf-layertree .gmf-layertree-layer-icon { + display: inline-flex; + width: 20px; + height: 10px; +} +gmf-layertree .gmf-layertree-zoom { + display: none; +} +gmf-layertree .gmf-layertree-zoom:hover { + cursor: pointer; +} +gmf-layertree .gmf-layertree-zoom:before { + font-family: FontAwesome; + content: "\f18e"; +} +gmf-layertree .outOfResolution .gmf-layertree-legend { + display: none; +} +gmf-layertree .gmf-layertree-legend-button a:after { + font-family: FontAwesome; + content: "\f036"; +} +gmf-layertree .gmf-layertree-legend img { + padding-left: 15px; +} +gmf-layertree .noSource { + opacity: 0.3; +} +gmf-layertree .noSource:after { + content: "(source not available)"; +} +gmf-layertree .outOfResolution { + opacity: 0.6; +} +gmf-layertree .outOfResolution .gmf-layertree-zoom { + display: inline; +} +gmf-layertree .gmf-layertree-state { + font-family: FontAwesome; + font-weight: lighter; +} +gmf-layertree .on .gmf-layertree-state:before { + content: "\f14a"; +} +gmf-layertree .off .gmf-layertree-state:before { + content: "\f096"; +} +gmf-layertree .indeterminate .gmf-layertree-state:before { + content: "\f147"; +} + +@media (max-width: 768px) { + #map { + height: 200px; + width: 200px; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.html new file mode 100644 index 000000000..9220a31ef --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.html @@ -0,0 +1,110 @@ + + + + GeoMapFish Print example + + + + + + + + +
+
+ Theme: + + +
+ + +
+ +
+ +

+ This example shows how to use the gmf.print.component. + Component that generates layout information and manages tools to print with a + MapFishPrint v3. +

+ + +
+
+
+
+ Print + × +
+ +
+ +
+ +
+
+ + +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
+
+
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.js new file mode 100644 index 000000000..34037d674 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/print.js @@ -0,0 +1,121 @@ +/** + * @module gmfapp.print + */ +const exports = {}; + +import './print.css'; +import gmfLayertreeComponent from 'gmf/layertree/component.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +/** @suppress {extraRequire} */ +import gmfPrintComponent from 'gmf/print/component.js'; + +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfLayertreeComponent.name, + gmfMapComponent.name, + gmfPrintComponent.name, + gmfThemeThemes.module.name, + ngeoMapModule.name //for ngeo.map.FeatureOverlay, perhaps remove me +]); + + +exports.module.value( + 'gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?' + + 'version=2&background=background'); + + +exports.module.value('gmfPrintUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/printproxy'); + + +exports.module.value( + 'authenticationBaseUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi' +); + + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr The ngeo feature + * overlay manager service. + * @ngInject + */ +exports.MainController = function(gmfThemes, ngeoFeatureOverlayMgr) { + + gmfThemes.loadThemes(); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); + + /** + * @type {Object.} + * @export + */ + this.defaulPrintFieldstValues = { + 'comments': 'Default comments example', + 'legend': true + }; + + /** + * @type {Array.|undefined} + * @export + */ + this.themes = undefined; + + /** + * @type {Object|undefined} + * @export + */ + this.treeSource = undefined; + + gmfThemes.getThemesObject().then((themes) => { + if (themes) { + this.themes = themes; + this.treeSource = themes[3]; + } + }); + + ngeoFeatureOverlayMgr.init(this.map); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.css new file mode 100644 index 000000000..384731557 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.css @@ -0,0 +1,42 @@ +gmf-map > div { + width: 80rem; + height: 40rem; +} +.gmf-profile-container { + display: flex; +} +.gmf-profile-container .ngeo-profile { + display: inline-block; + width: calc(100% - 15rem); + height: 20rem; +} +.gmf-profile-container .gmf-profile-legend { + display: inline-block; + vertical-align: top; + list-style-type: none; + padding: 0; + width: 13rem; +} +.tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 0.5rem; + color: white; + padding: 0.5rem 1rem; + opacity: 0.7; + white-space: nowrap; +} +.ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; +} +.ngeo-tooltip-measure:before { + border-top: 0.5rem solid rgba(0, 0, 0, 0.5); + border-right: 0.5rem solid transparent; + border-left: 0.5rem solid transparent; + content: ""; + position: absolute; + bottom: -0.5rem; + margin-left: -0.5rem; + left: 50%; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.html new file mode 100644 index 000000000..92ed1cfcf --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.html @@ -0,0 +1,29 @@ + + + + GMF profile example + + + + + + + + + +

This example shows how to use the gmf-profile. + The draw tool and hover feedback on the map are completely independent of + the gmf-profile components. This profile relies on the ngeo.profile (d3) and + ngeo.ProfileDirective. It passes a custom css through the optional + gmf-profile-options attribute

+ + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.js new file mode 100644 index 000000000..c465f8906 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/profile.js @@ -0,0 +1,159 @@ +/** + * @module gmfapp.profile + */ +const exports = {}; + +import './profile.css'; +/** @suppress {extraRequire} */ +import gmfPermalinkPermalink from 'gmf/permalink/Permalink.js'; + +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfProfileModule from 'gmf/profile/module.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olCollection from 'ol/Collection.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olInteractionDraw from 'ol/interaction/Draw.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfPermalinkPermalink.module.name, + gmfMapComponent.name, + gmfProfileModule.name, + ngeoMapModule.name // for ngeo.map.FeatureOverlay, perhaps remove me +]); + + +exports.module.value( + 'gmfProfileJsonUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/profile.json'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {angular.Scope} $scope Angular scope. + * @param {ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr Feature overlay + * manager. + * @constructor + * @ngInject + */ +exports.MainController = function($scope, ngeoFeatureOverlayMgr) { + /** + * @type {ol.geom.LineString} + * @export + */ + this.profileLine = null; + + /** + * @type {Object.} + * @export + */ + this.profileLinesconfiguration = { + 'aster': { + 'color': '#0404A0' + }, + 'srtm': { + 'color': '#04A004' + } + }; + + this.profileOptions = { + styleDefs: 'svg {background-color: #D3E5D7};' + }; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [600000, 200000], + zoom: 3 + }) + }); + + const lineStyle = new olStyleStyle({ + stroke: new olStyleStroke({ + color: '#ffcc33', + width: 2 + }) + }); + + /** + * @type {ol.Collection.} + */ + const features = new olCollection(); + + const overlay = ngeoFeatureOverlayMgr.getFeatureOverlay(); + overlay.setFeatures(features); + overlay.setStyle(lineStyle); + + + // Initialize the feature overlay manager with the map. + ngeoFeatureOverlayMgr.init(this.map); + + /** + * Draw line interaction. + * @type {ol.interaction.Draw} + * @export + */ + this.drawLine = new olInteractionDraw({ + type: /** @type {ol.geom.GeometryType} */ ('LineString'), + features: features + }); + + this.drawLine.setActive(false); + this.map.addInteraction(this.drawLine); + + /** + * Toggle activation of the draw line interaction. + * @export + */ + this.toggleDrawLineActive = function() { + if (this.drawLine.getActive()) { + this.drawLine.setActive(false); + this.clear_(); + } else { + this.drawLine.setActive(true); + } + }; + + this.clear_ = function() { + features.clear(); // For the draw overlay. + this.profileLine = null; // To reset the profile. + }; + + this.drawLine.on('drawstart', () => { + this.clear_(); + }); + + this.drawLine.on('drawend', (e) => { + // Update the profile with the new geometry + this.profileLine = e.feature.getGeometry(); + $scope.$digest(); + }); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.css new file mode 100644 index 000000000..3cd2f73d3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.css @@ -0,0 +1,138 @@ +#message { + width: 300px; +} +.ngeo-colorpicker-palette { + border-collapse: separate; + border-spacing: 0; +} +.ngeo-colorpicker-palette td { + position: relative; + padding: 0; + text-align: center; + vertical-align: middle; + font-size: 1px; +} +.ngeo-colorpicker-palette td > div { + position: relative; + height: 12px; + width: 12px; + border: 1px solid #fff; + box-sizing: content-box; +} +.ngeo-colorpicker-palette td:hover > div::after { + display: block; + content: ''; + background: inherit; + position: absolute; + width: 28px; + height: 28px; + top: -10px; + left: -10px; + border: 2px solid #fff; + -webkit-box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + z-index: 11; +} +.ngeo-colorpicker-palette td.ngeo-colorpicker-selected > div::after { + border: 2px solid #444; + margin: 0; + content: ''; + display: block; + width: 14px; + height: 14px; + position: absolute; + left: -3px; + top: -3px; + box-sizing: content-box; + z-index: 10; +} + +gmf-map > div { + width: 600px; + height: 400px; +} +span.twitter-typeahead { + width: 300px; +} +.gmf-search > * { + float: left; +} +.gmf-search > .gmf-clear-button{ + margin-left: -15px; + padding: 3px 0 2px; + position: relative; +} +.gmf-search > .gmf-clear-button:hover{ + cursor: pointer; +} +.gmf-search > .gmf-clear-button:after{ + content: 'x'; +} +/* CSS stolen from https://github.com/bassjobsen/typeahead.js-bootstrap-css/ */ +span.twitter-typeahead .tt-menu { + position: absolute; + top: 100%; + width: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} +span.twitter-typeahead .header { + background-color: #CCDDEE; + padding: 4px 0; +} +span.twitter-typeahead .tt-suggestion { + display: block; + padding: 3px 20px; + margin-bottom: 0px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333333; + white-space: nowrap; +} +span.twitter-typeahead .tt-suggestion:hover, +span.twitter-typeahead .tt-suggestion:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #428bca; +} +span.twitter-typeahead .tt-suggestion.tt-cursor { + color: #ffffff; + background-color: #428bca; +} +span.twitter-typeahead .tt-suggestion button { + background: none; + border: 0; + float: right; +} +.input-group span.twitter-typeahead { + display: block !important; +} +.input-group span.twitter-typeahead .tt-menu { + top: 32px !important; +} +.input-group.input-group-lg span.twitter-typeahead .tt-menu { + top: 44px !important; +} +.input-group.input-group-sm span.twitter-typeahead .tt-menu { + top: 28px !important; +} +#desc { + clear: left; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.html new file mode 100644 index 000000000..ba4c8e886 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.html @@ -0,0 +1,31 @@ + + + + Search GeoMapFish example + + + + + +
+ + + +

This example shows how to use the gmf-search directive, which + is based on Twitter's typeahead component.

+

You typed: {{ctrl.inputValue}}

+
+
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.js new file mode 100644 index 000000000..5eb9272e8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/search.js @@ -0,0 +1,143 @@ +/** + * @module gmfapp.search + */ +const exports = {}; + +import './search.css'; +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import gmfSearchModule from 'gmf/search/module.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoMessageNotification from 'ngeo/message/Notification.js'; +import ngeoMessageMessage from 'ngeo/message/Message.js'; +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapComponent.name, + gmfSearchModule.name, + gmfThemeThemes.module.name, + ngeoMapModule.name, // for ngeo.map.FeatureOverlay, perhaps remove me + ngeoMessageNotification.module.name, +]); + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + +exports.module.value('fulltextsearchUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/fulltextsearch?limit=30&partitionlimit=5&interface=desktop'); + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {gmf.theme.Themes} gmfThemes Themes service. + * @param {ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr The ngeo feature overlay manager service. + * @param {ngeo.message.Notification} ngeoNotification Ngeo notification service. + * @constructor + * @ngInject + */ +exports.MainController = function(gmfThemes, ngeoFeatureOverlayMgr, ngeoNotification) { + + gmfThemes.loadThemes(); + + ngeoFeatureOverlayMgr.init(this.map); + + /** + * @type {Array.} + * @export + */ + this.searchDatasources = [{ + groupValues: ['osm', 'district'], + groupActions: [], + labelKey: 'label', + projection: EPSG21781, + bloodhoundOptions: { + remote: { + rateLimitWait: 250 + } + }, + url: 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/fulltextsearch' + }]; + + const fill = new olStyleFill({color: [255, 255, 255, 0.6]}); + const stroke = new olStyleStroke({color: [255, 0, 0, 1], width: 2}); + /** + * @type {Object.} Map of styles for search overlay. + * @export + */ + this.searchStyles = { + 'osm': new olStyleStyle({ + fill: fill, + image: new olStyleCircle({ + fill: fill, + radius: 5, + stroke: stroke + }), + stroke: stroke + }) + }; + + /** + * @type {TypeaheadOptions} + * @export + */ + this.searchOptions = { + minLength: 2 + }; + + /** + * @type {string} + * @export + */ + this.inputValue = ''; + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + center: [0, 0], + zoom: 4 + }) + }); + + /** + * @type {function()} + * @export + */ + this.searchIsReady = () => { + ngeoNotification.notify({ + msg: 'gmf-search initialized', + target: angular.element('#message'), + type: ngeoMessageMessage.Type.SUCCESS + }); + }; +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.css new file mode 100644 index 000000000..9410a797e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.css @@ -0,0 +1,7 @@ +.share { + margin: 3rem 0; + width: 20vw; + display: flex; + justify-content: space-between; + align-items: baseline; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.html new file mode 100644 index 000000000..2e2d7161f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.html @@ -0,0 +1,37 @@ + + + + GMF Share permalink example + + + + + +

This example shows how to use the gmf-share directive to get a shorten permalink

+ + + + + + + + + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.js new file mode 100644 index 000000000..81ecaa146 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/share.js @@ -0,0 +1,51 @@ +/** + * @module gmfapp.share + */ +const exports = {}; + +import './share.css'; +/** @suppress {extraRequire} */ +import gmfPermalinkShareComponent from 'gmf/permalink/shareComponent.js'; + +/** @suppress {extraRequire} */ +import ngeoMessageModalComponent from 'ngeo/message/modalComponent.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + ngeoMessageModalComponent.name, + gmfPermalinkShareComponent.name, +]); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); +exports.module.constant('gmfShortenerCreateUrl', 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/short/create'); + + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + + /** + * Model attached to the modal to toggle it + * @type {boolean} + * @export + */ + this.modalShareWithEmailShown = false; + + /** + * Model attached to the modal to toggle it + * @type {boolean} + * @export + */ + this.modalShareShown = false; + +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.css new file mode 100644 index 000000000..b2b22d133 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.css @@ -0,0 +1,4 @@ +gmf-map > div { + width: 600px; + height: 400px; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.html new file mode 100644 index 000000000..f73393863 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.html @@ -0,0 +1,14 @@ + + + + Simple GeoMapFish example + + + + + + +

This example shows how to use the gmf-map directive to insert an OpenLayers map in a GeoMapFish page.

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.js new file mode 100644 index 000000000..cd9ce6a48 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/simple.js @@ -0,0 +1,53 @@ +/** + * @module gmfapp.simple + */ +const exports = {}; + +import './simple.css'; +/** @suppress {extraRequire} */ +import gmfMapComponent from 'gmf/map/component.js'; + +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapComponent.name, +]); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + center: [0, 0], + zoom: 4 + }) + }); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.css new file mode 100644 index 000000000..13b2eff42 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.css @@ -0,0 +1,27 @@ +.gmf-theme-selector { + list-style: none; + margin: 0; + padding: 0; + width: 300px; +} +.gmf-theme-selector li { + cursor: pointer; + margin: 10px; + display: flex; + align-items: center; + border: 0.1rem solid black; +} +.gmf-text { + flex: 1; +} +.gmf-thumb { + height: 60px; +} +li.gmf-theme-selector-active { + border: 0.1rem solid blue; +} +.gmf-theme-selector-active::after { + color: blue; + content: 'X'; + margin: 0 1rem 0 0; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.html new file mode 100644 index 000000000..5777001f7 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.html @@ -0,0 +1,18 @@ + + + + GeoMapFish Theme Selector Example + + + + + +
+ +
The theme selected is {{ctrl.manager.getThemeName()}}
+ +
+

This example shows how to use the gmf.themeselector directive from a c2c geoportal theme service.

+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.js new file mode 100644 index 000000000..98dea19e8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/themeselector.js @@ -0,0 +1,56 @@ +/** + * @module gmfapp.themeselector + */ +const exports = {}; + +import './themeselector.css'; +/** @suppress {extraRequire} */ +import gmfThemeModule from 'gmf/theme/module.js'; + +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfLayertreeTreeManager.module.name, + gmfThemeModule.name, +]); + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {angular.$http} $http Angular's $http service. + * @param {gmf.theme.Themes} gmfThemes Themes service. + * @param {gmf.theme.Manager} gmfThemeManager gmf Tree Manager service. + * @ngInject + */ +exports.MainController = function($http, gmfThemes, gmfThemeManager) { + + /** + * @param {gmfThemes.GmfTheme} theme Theme. + * @return {boolean} Theme is 'Enseignement' + * @export + */ + this.filter = function(theme) { + return theme.name !== 'Enseignement'; + }; + + /** + * @type {gmf.theme.Manager} + * @export + */ + this.manager = gmfThemeManager; + + gmfThemes.loadThemes(); +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.css new file mode 100644 index 000000000..2ae8ae912 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.css @@ -0,0 +1,9 @@ +ul { + width: 50%; +} +li { + list-style: none; +} +.tooltip { + min-width: 6.5rem; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.html new file mode 100644 index 000000000..ab17777aa --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.html @@ -0,0 +1,39 @@ + + + + GeoMapFish Timeslider example + + + + + +

This example shows how to use the gmf-time-slider directive.

+
    +
  • + Select a period with a timeslider +
  • +
  • + +
  • +
  • + Date formatted for a WMS request (resolution set on 'day'): +
    +          {{ctrl.sliderRangeValue}}
    +        
    +
  • +
  • + Select a single date with a timeslider +
  • +
  • + +
  • +
  • + Date formatted for a WMS request (resolution set on 'year'): +
    +          {{ctrl.sliderValue}}
    +        
    +
  • +
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.js new file mode 100644 index 000000000..4244f22bc --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/timeslider.js @@ -0,0 +1,94 @@ +/** + * @module gmfapp.timeslider + */ +const exports = {}; + +import './timeslider.css'; +import gmfLayertreeTimeSliderComponent from 'gmf/layertree/timeSliderComponent.js'; + +import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfLayertreeTimeSliderComponent.name, + ngeoMiscWMSTime.module.name, +]); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @param {!angular.Scope} $scope Angular scope. + * @param {!ngeo.misc.WMSTime} ngeoWMSTime wmstime service. + * @ngInject + */ +exports.MainController = function($scope, ngeoWMSTime) { + + /** + * @type {ngeo.misc.WMSTime} + * @private + */ + this.ngeoWMSTime_ = ngeoWMSTime; + + /** + * @type {ngeox.TimeProperty} + * @export + */ + this.wmsTimeRangeMode = { + widget: /** @type {ngeox.TimePropertyWidgetEnum} */ ('slider'), + maxValue: '2013-12-31T00:00:00Z', + minValue: '2006-01-01T00:00:00Z', + maxDefValue: null, + minDefValue: null, + resolution: /** @type {ngeox.TimePropertyResolutionEnum}*/ ('day'), + mode: /** @type {ngeox.TimePropertyModeEnum} */('range'), + interval: [0, 1, 0, 0] + }; + + /** + * @type {ngeox.TimeProperty} + * @export + */ + this.wmsTimeValueMode = { + widget: /** @type {ngeox.TimePropertyWidgetEnum} */ ('slider'), + maxValue: '2015-12-31T00:00:00Z', + minValue: '2014-01-01T00:00:00Z', + maxDefValue: null, + minDefValue: null, + resolution: /** @type {ngeox.TimePropertyResolutionEnum}*/ ('year'), + mode: /** @type {ngeox.TimePropertyModeEnum} */ ('value'), + interval: [0, 0, 1, 0] + }; + + /** + * @type {string} + * @export + */ + this.sliderValue; + + /** + * @type {string} + * @export + */ + this.sliderRangeValue; + + this.onDateSelected = function(date) { + this.sliderValue = this.ngeoWMSTime_.formatWMSTimeParam(this.wmsTimeValueMode, date); + $scope.$digest(); + }; + + this.onDateRangeSelected = function(date) { + this.sliderRangeValue = this.ngeoWMSTime_.formatWMSTimeParam(this.wmsTimeRangeMode, date); + $scope.$digest(); + }; + +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.css new file mode 100644 index 000000000..a3668f61c --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.css @@ -0,0 +1,145 @@ +gmf-map > div { + width: 600px; + height: 400px; +} + +/* Display queries */ +.gmf-displayquerywindow { + max-height: 400px; + width: 350px; + max-width: 350px; + margin-left: -175px; + position: fixed; + top: 20px; + right: 0px; +} +.gmf-displayquerywindow button { + background: none; + border: none; + font-family: FontAwesome; + width: 32px; +} +.gmf-displayquerywindow button.close { + padding: 5px 5px 0 0; +} +.gmf-displayquerywindow .collapse-button { + background-color: white; + border: solid 1px black; + border-bottom-width: 0; + border-radius: 4px 4px 0 0; + line-height: 0.5; + height: 28px; + width: 48px; + margin-left: calc(50% - 24px); +} +.collapse-button-up:after { + content: "\f077"; +} +.collapse-button-down:after { + content: "\f078"; +} +.windowcontainer { + background-color: white; + border: solid 1px black; +} +.animation-container { + position: relative; + overflow: hidden; + height: 60px; + margin: 0 15px; + transition: 0.3s ease-in all; +} +.animation-container-detailed { + height: 160px; +} +.animation-container .slide-animation { + height: 100%; + padding: 5px 5px 0; + text-align: left; + white-space: nowrap; + overflow: hidden; + position: absolute; + top: 0; + left: 0; + right: 0; +} +.slide-animation.ng-enter, .slide-animation.ng-leave { + transition: 0.3s ease-in all; +} +/* Left to right animation */ +.next .slide-animation.ng-enter { + left: 100%; +} +.next .slide-animation.ng-enter-active { + left: 0; +} +.next .slide-animation.ng-leave { + left: 0; +} +.next .slide-animation.ng-leave-active { + left: -100%; +} +/* Right to left animation */ +.previous .slide-animation.ng-enter { + left: -100%; +} +.previous .slide-animation.ng-enter-active { + left: 0; +} +.previous .slide-animation.ng-leave { + left: 0; +} +.previous .slide-animation.ng-leave-active { + left: 100%; +} +.title { + font-weight: bold; +} +.subtitle { + margin-left: 10px; + height: 2ex; +} +.details { + height: 65%; + overflow-x: hidden; + overflow-y: auto; + margin-left: 10px; + padding-bottom: 10px +} +.details table { + font-size: 0.9em; +} +.details-key { + padding-right: 25px; +} +.slide-animation.ng-enter-active .details-value { + white-space: nowrap; +} +.navigate { + border-top: solid 1px black; + text-align: center; + margin-top: 10px; + padding-top: 5px; + height: 32px; +} +.navigate .previous { + float: left; +} +.navigate .previous:after { + content: "\f053"; +} +.navigate .next { + float: right; +} +.navigate .next:after { + content: "\f054"; +} +@media (max-width: 768px) { + .gmf-displayquerywindow { + width: 100%; + max-width: 100%; + margin-left: -50%; + top: initial; + bottom: 0; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.html new file mode 100644 index 000000000..612894790 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.html @@ -0,0 +1,52 @@ + + + + GeoMapFish WFS Permalink example + + + + + + + + +

+ This example demonstrates the use of the ngeoWfsPermalink + service, which is injected inside the gmf-map directive. + The following links demonstrate the different features: +

+

+ + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.js new file mode 100644 index 000000000..6e81d6d03 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/wfspermalink.js @@ -0,0 +1,93 @@ +/** + * @module gmfapp.wfspermalink + */ +const exports = {}; + +import './wfspermalink.css'; +/** @suppress {extraRequire} */ +import gmfMapModule from 'gmf/map/module.js'; + +/** @suppress {extraRequire} */ +import gmfQueryWindowComponent from 'gmf/query/windowComponent.js'; +import ngeoStatemanagerWfsPermalink from 'ngeo/statemanager/WfsPermalink.js'; + +import EPSG21781 from 'ngeo/proj/EPSG21781.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olSourceOSM from 'ol/source/OSM.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleCircle from 'ol/style/Circle.js'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfMapModule.name, + gmfQueryWindowComponent.name, + ngeoStatemanagerWfsPermalink.module.name, +]); + +exports.module.value('ngeoWfsPermalinkOptions', + /** @type {ngeox.WfsPermalinkOptions} */ ({ + url: 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/mapserv_proxy', + wfsTypes: [ + {featureType: 'fuel', label: 'display_name'}, + {featureType: 'osm_scale', label: 'display_name'} + ], + defaultFeatureNS: 'http://mapserver.gis.umn.edu/mapserver', + defaultFeaturePrefix: 'feature' + })); + +exports.module.constant('defaultTheme', 'Demo'); +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @constructor + * @ngInject + */ +exports.MainController = function() { + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + layers: [ + new olLayerTile({ + source: new olSourceOSM() + }) + ], + view: new olView({ + projection: EPSG21781, + resolutions: [200, 100, 50, 20, 10, 5, 2.5, 2, 1, 0.5], + center: [537635, 152640], + zoom: 3 + }) + }); + + const fill = new olStyleFill({color: [255, 170, 0, 0.6]}); + const stroke = new olStyleStroke({color: [255, 170, 0, 1], width: 2}); + + /** + * FeatureStyle used by the gmf.query.windowComponent + * @type {ol.style.Style} + * @export + */ + this.featureStyle = new olStyleStyle({ + fill: fill, + image: new olStyleCircle({ + fill: fill, + radius: 5, + stroke: stroke + }), + stroke: stroke + }); +}; + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.css b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.css new file mode 100644 index 000000000..aca256e83 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.css @@ -0,0 +1,3 @@ +.layers-list { + max-width: 100%; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.html new file mode 100644 index 000000000..99623a202 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.html @@ -0,0 +1,46 @@ + + + + XSD Attributes in GeoMapFish example + + + + + + +
+
+
+

+ This example shows how to use the gmf.editing.XSDAttributes + service, which is used to obtain the attributes from a GeoMapFish + server using a given layer id. The attributes received are read + and transformed into a form using the ngeo-attributes + directive. +

+ +
+ Geometry type: + {{ ctrl.getGeomType() }} +
+
+
+
+ + +
+
+
+
+ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.js new file mode 100644 index 000000000..aa5069c6f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/examples/xsdattributes.js @@ -0,0 +1,179 @@ +/** + * @module gmfapp.xsdattributes + */ +const exports = {}; + +import './xsdattributes.css'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; + +import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes.js'; +import ngeoEditingAttributesComponent from 'ngeo/editing/attributesComponent.js'; +import ngeoFormatXSDAttribute from 'ngeo/format/XSDAttribute.js'; +import olFeature from 'ol/Feature.js'; +import 'jquery-datetimepicker/jquery.datetimepicker.css'; + + +/** @type {!angular.Module} **/ +exports.module = angular.module('gmfapp', [ + 'gettext', + gmfEditingXSDAttributes.module.name, + gmfThemeThemes.module.name, + ngeoEditingAttributesComponent.name, +]); + + +exports.module.value('gmfTreeUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/themes?version=2&background=background'); + +exports.module.value('gmfLayersUrl', + 'https://geomapfish-demo.camptocamp.com/2.3/wsgi/layers/'); + +exports.module.constant('angularLocaleScript', '../build/angular-locale_{{locale}}.js'); + + +/** + * @param {angular.$timeout} $timeout Angular timeout service. + * @param {gmf.theme.Themes} gmfThemes The gmf themes service. + * @param {gmf.editing.XSDAttributes} gmfXSDAttributes The gmf XSDAttributes service. + * @constructor + * @ngInject + */ +exports.MainController = function($timeout, gmfThemes, gmfXSDAttributes) { + + /** + * @type {angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {gmf.editing.XSDAttributes} + * @private + */ + this.xsdAttributes_ = gmfXSDAttributes; + + /** + * @type {?Array.} + * @export + */ + this.attributes = null; + + /** + * @type {?ol.Feature} + * @export + */ + this.feature = null; + + /** + * @type {Array.} + * @export + */ + this.layers = []; + + // TMP - The list of layer names to use. We'll keep this until we can use + // those that are editable. + const layerNames = ['line', 'point', 'polygon']; + + gmfThemes.loadThemes(); + + gmfThemes.getThemesObject().then((themes) => { + if (!themes) { + return; + } + // Get an array with all nodes entities existing in "themes". + const flatNodes = []; + themes.forEach((theme) => { + theme.children.forEach((group) => { + this.getDistinctFlatNodes_(group, flatNodes); + }); + }); + flatNodes.forEach((node) => { + // Get an array of all layers + if (node.children === undefined && layerNames.indexOf(node.name) !== -1) { + this.layers.push(node); + } + }); + + }); +}; + + +/** + * @param {gmfThemes.GmfLayer|undefined} value A layer or undefined to get layers. + * @return {Array.} All layers in all themes. + * @export + */ +exports.MainController.prototype.getSetLayers = function(value) { + if (value !== undefined && value !== null) { + this.xsdAttributes_.getAttributes(value.id).then(attr => this.setAttributes_(attr)); + } + return this.layers; +}; + + +/** + * @param {Array.} attributes Attributes. + * @export + */ +exports.MainController.prototype.setAttributes_ = function(attributes) { + + // (1) Reset first + this.feature = null; + this.attributes = null; + + // (2) Then set + this.timeout_(() => { + this.feature = new olFeature(); + this.attributes = attributes; + }, 0); +}; + + +/** + * @return {string} Type of geometry. + * @export + */ +exports.MainController.prototype.getGeomType = function() { + let type = 'N/A'; + if (this.attributes) { + const geomAttr = ngeoFormatXSDAttribute.getGeometryAttribute( + this.attributes + ); + if (geomAttr && geomAttr.geomType) { + type = geomAttr.geomType; + } + } + return type; +}; + + +/** + * Just for this example + * @param {gmfThemes.GmfTheme|gmfThemes.GmfGroup|gmfThemes.GmfLayer} node A theme, group or layer node. + * @param {Array.} nodes An Array of nodes. + * @export + */ +exports.MainController.prototype.getDistinctFlatNodes_ = function(node, nodes) { + let i; + const children = node.children; + if (children !== undefined) { + for (i = 0; i < children.length; i++) { + this.getDistinctFlatNodes_(children[i], nodes); + } + } + let alreadyAdded = false; + nodes.some((n) => { + if (n.id === node.id) { + return alreadyAdded = true; + } + }); + if (!alreadyAdded) { + nodes.push(node); + } +}; + + +exports.module.controller('MainController', exports.MainController); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/externs/gmf-themes.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/externs/gmf-themes.js new file mode 100644 index 000000000..aa496ffea --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/externs/gmf-themes.js @@ -0,0 +1,719 @@ +/** + * Externs for the GeoMapFish "themes" web service. + * + * @externs + */ + + +/** + * @type {Object} + */ +let gmfThemes; + +/** + * @constructor + * @struct + */ +gmfThemes.GmfThemesResponse = function() {}; + +/** + * @type !Array. + */ +gmfThemes.GmfThemesResponse.prototype.background_layers; + +/** + * @type !Array. + */ +gmfThemes.GmfThemesResponse.prototype.errors; + +/** + * @type !gmfThemes.GmfOgcServers + */ +gmfThemes.GmfThemesResponse.prototype.ogcServers; + +/** + * @type !Array. + */ +gmfThemes.GmfThemesResponse.prototype.themes; + + +/** + * @constructor + * @struct + */ +gmfThemes.GmfRootNode = function() {}; + + +/** + * @type {!Array.} + */ +gmfThemes.GmfRootNode.prototype.children; + +/** + * Contains the common element of all the elements of the GeoMapFish layer tree. + * @constructor + * @struct + */ +gmfThemes.GmfBaseNode = function() {}; + + +/** + * @type {number} + */ +gmfThemes.GmfBaseNode.prototype.id; + + +/** + * The related metadata. + * @type {!gmfThemes.GmfMetaData} + */ +gmfThemes.GmfBaseNode.prototype.metadata; + + +/** + * @type {string} + */ +gmfThemes.GmfBaseNode.prototype.name; + + +/** + * The element we can select in the theme selector. + * @constructor + * @struct + * @extends gmfThemes.GmfBaseNode + */ +gmfThemes.GmfTheme = function() {}; + + +/** + * The first level layer groups. + * @type {!Array.} + */ +gmfThemes.GmfTheme.prototype.children; + + +/** + * The Functionalities related to the theme. + * @type {!gmfThemes.GmfFunctionalities} + */ +gmfThemes.GmfTheme.prototype.functionalities; + + +/** + * A GeoMapFish group + * not an OpenLayers group + * neither a WMS group. + * This represent « first level group » (Block in the layer tree), + * or all sub nodes that's not al leaf. + * @constructor + * @struct + * @extends gmfThemes.GmfBaseNode + */ +gmfThemes.GmfGroup = function() {}; + + +/** + * @type {!Array.} + */ +gmfThemes.GmfGroup.prototype.children; + + +/** + * The dimensions managed by the OpenLayers layer, if the value is null we will take the dimension from the application. + * This is present only on non mixed first level group. + * @type {!ngeox.Dimensions} + */ +gmfThemes.GmfGroup.prototype.dimensions; + + +/** + * A mixed group is a group on which one the layers comes from different sources, + * then all the sub GeoMapFish layers (leaf) will be an OpenLayers layer. + * By opposition a non mixed first level group contains only GeoMapFish layers WMS + * from the same server, then we have only one OpenLayers layer for all the first level group. + * All the group child will have the same value of his parent, + * In other word, all the group of a first level group will have the same value. + * @type {boolean} + */ +gmfThemes.GmfGroup.prototype.mixed; + + +/** + * On non mixed first level group it is the ogc server to use. + * @type {string|undefined} + */ +gmfThemes.GmfGroup.prototype.ogcServer; + + +/** + * On non mixed first level group with more then one time layer, it is the time information. + * @type {ngeox.TimeProperty|undefined} + */ +gmfThemes.GmfGroup.prototype.time; + + +/** + * A GeoMapFish layer + * not an OpenLayers layer + * neither a WMS layer. + * This is also the leaf of the tree. + * @constructor + * @struct + * @extends gmfThemes.GmfBaseNode + */ +gmfThemes.GmfLayer = function() {}; + + +/** + * The dimensions managed by the layer, if the value is null we will take the dimension from the application. + * Present only on layer in a mixed group. + * @type {!ngeox.Dimensions} + */ +gmfThemes.GmfLayer.prototype.dimensions; + + +/** + * The dimensions applied by filters on the layer configuration, if the value + * is null we will take the dimension from the application. + * @type {!ngeox.DimensionsFiltersConfig} + */ +gmfThemes.GmfLayer.prototype.dimensionsFilters; + + +/** + * @type {boolean|undefined} + */ +gmfThemes.GmfLayer.prototype.editable; + + +/** + * @type {string|undefined} + */ +gmfThemes.GmfLayer.prototype.style; + + +/** + * WMS or WMTS. + * @type {string} + */ +gmfThemes.GmfLayer.prototype.type; + + +/** + * @constructor + * @struct + * @extends gmfThemes.GmfLayer + */ +gmfThemes.GmfLayerWMS = function() {}; + + +/** + * @type {!Array.} + */ +gmfThemes.GmfLayerWMS.prototype.childLayers; + +/** + * The comma separated list of WMS layers or groups. + * @type {string} + */ +gmfThemes.GmfLayerWMS.prototype.layers; + + +/** + * The max resolution where the layer is visible. + * @type {number} + */ +gmfThemes.GmfLayerWMS.prototype.maxResolutionHint; + + +/** + * The min resolution where the layer is visible. + * @type {number} + */ +gmfThemes.GmfLayerWMS.prototype.minResolutionHint; + + +/** + * @type {string|undefined} + */ +gmfThemes.GmfLayerWMS.prototype.ogcServer; + + +/** + * The time information if the layer directly manage it, see + * also {gmfThemes.GmfGroup.time}. + * @type {ngeox.TimeProperty|undefined} + */ +gmfThemes.GmfLayerWMS.prototype.time; + + +/** + * @constructor + * @struct + * @extends gmfThemes.GmfLayer + */ +gmfThemes.GmfLayerWMTS = function() {}; + + +/** + * 'image/png' or 'image/jpeg'. + * @type {string} + */ +gmfThemes.GmfLayerWMTS.prototype.imageType; + + +/** + * @type {string} + */ +gmfThemes.GmfLayerWMTS.prototype.layer; + + +/** + * @type {string} + */ +gmfThemes.GmfLayerWMTS.prototype.matrixSet; + + +/** + * @type {string} + */ +gmfThemes.GmfLayerWMTS.prototype.url; + + +/** + * Additional attributes related on a WMS layers (or WFS features type). + * @constructor + * @struct + */ +gmfThemes.GmfLayerChildLayer = function() {}; + + +/** + * The min resolution where the layer is visible. + * @type {number} + */ +gmfThemes.GmfLayerChildLayer.prototype.maxResolutionHint; + + +/** + * The max resolution where the layer is visible. + * @type {number} + */ +gmfThemes.GmfLayerChildLayer.prototype.minResolutionHint; + + +/** + * @type {string} + */ +gmfThemes.GmfLayerChildLayer.prototype.name; + + +/** + * @type {boolean} + */ +gmfThemes.GmfLayerChildLayer.prototype.queryable; + + +/** + * @typedef {!Object} + */ +gmfThemes.GmfOgcServers; + + +/** + * @constructor + * @struct + */ +gmfThemes.GmfOgcServer = function() {}; + + +/** + * @type {boolean} + */ +gmfThemes.GmfOgcServer.prototype.credential; + +/** + * 'image/png' or 'image/jpeg'. + * @type {string} + */ +gmfThemes.GmfOgcServer.prototype.imageType; + + +/** + * @type {boolean} + */ +gmfThemes.GmfOgcServer.prototype.isSingleTile; + + +/** + * 'mapserver', 'qgisserver', 'geoserver' or 'other'. + * @type {string} + */ +gmfThemes.GmfOgcServer.prototype.type; + + +/** + * @type {string} + */ +gmfThemes.GmfOgcServer.prototype.url; + + +/** + * The WFS URL. + * @type {string} + */ +gmfThemes.GmfOgcServer.prototype.urlWfs; + + +/** + * @type {boolean} + */ +gmfThemes.GmfOgcServer.prototype.wfsSupport; + +/** + * @constructor + * @struct + */ +gmfThemes.GmfFunctionalities = function() {}; + + +/** + * The default base map. + * @type {!Array.} + */ +gmfThemes.GmfFunctionalities.prototype.default_basemap; + + +/** + * When set, contains the name of the panel to open upon loading an application. + * Note: although this is a list, only one can be defined. + * @type {Array.|undefined} + */ +gmfThemes.GmfFunctionalities.prototype.open_panel; + + +/** + * Name of the layer (data source) that should be toggled in the filter tool + * upon loading an application. + * Note: although this is a list, only one can be defined. + * @type {Array.|undefined} + */ +gmfThemes.GmfFunctionalities.prototype.preset_layer_filter; + + +/** + * @constructor + * @struct + */ +gmfThemes.GmfMetaData = function() {}; + + +/** + * Names of layers on which the geometry can be copied to (in the edition mode). + * For WMS layers and only for CGXP ! (Use "copyable" in NGEO.) + * @type {Array.|undefined} + */ +gmfThemes.GmfMetaData.prototype.copy_to; + + +/** + * Whether the geometry from this data source can be copied to other data + * sources or not. Defaults to false. + * Default to false. + * For WMS layers. + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.copyable; + + +/** + * List of attribute names which should have rules already ready when using + * the filter tools. + * For WMS layers. + * @type {Array.|undefined} + */ +gmfThemes.GmfMetaData.prototype.directedFilterAttributes; + + +/** + * The disclaimer text for this element. + * For WMS and WMTS layers, layer groups and themes. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.disclaimer; + + +/** + * List of attribute names which have enumerated attribute values (for filters + * purpose). + * For WMS layers. + * @type {Array.|undefined} + */ +gmfThemes.GmfMetaData.prototype.enumeratedAttributes; + + +/** + * Whether geometries must be validated by PostgreSQL on edition. + * Default to false. + * For WMS layers. + * Also working in CGXP. + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.geometry_validation; + + +/** + * The URL of the icon to display in the layer tree. + * For WMS and WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.iconUrl; + + +/** + * The field used in the 'display query window' as feature title. + * For WMS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.identifierAttributeField; + + +/** + * Is the layer checked by default. + * Default to false. + * For WMS and WMTS layers. + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.isChecked; + + +/** + * Whether the layer group is expanded by default. + * Default to false. + * For layer groups (only). + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.isExpanded; + +/** + * Whether the print should rotate the symbols. + * Default to true. + * For layer groups (only). + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.printNativeAngle; + + +/** + * Whether the legend is expanded by default. + * Default to false. + * For WMS and WMTS layers. + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.isLegendExpanded; + + +/** + * 'Date' column that will be automatically updated after editing an element. + * For WMS layers. + * Also working in CGXP. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.lastUpdateDateColumn; + + +/** + * 'User' column that will be automatically updated after editing an element. + * For WMS layers. + * Also working in CGXP. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.lastUpdateUserColumn; + + + +/** + * Display the legend of this layers. + * Default to false. + * For WMS and WMTS layers. + * @type {boolean|undefined} + */ +gmfThemes.GmfMetaData.prototype.legend; + + +/** + * The URL to the image used as a legend in the layer tree. + * For WMS and WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.legendImage; + + +/** + * The WMS 'RULE' parameter used to display the icon in the layer tree. + * "Short version" of the 'iconURL' metadata for WMS layers. + * For WMS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.legendRule; + + +/** + * The max resolution where the layer is visible. + * For WMS layers. + * On WMTS layers it will have effect on the node in the layertree but not on + * the layertree directly. + * @type {number|undefined} + */ +gmfThemes.GmfMetaData.prototype.maxResolution; + + +/** + * The URL to the information on this layer. + * For WMS and WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.metadataUrl; + + +/** + * The min resolution where the layer is visible. + * For WMS layers. + * On WMTS layers it will have effect on the node in the layertree but not on + * the layer directly. + * @type {number|undefined} + */ +gmfThemes.GmfMetaData.prototype.minResolution; + + +/** + * The corresponding OGC server for a WMTS layer. + * For WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.ogcServer; + + +/** + * Layer opacity. + * Default to 1.0 (fuly visible, 0 means invisible) + * For WMS and WMTS layers. + * @type {number|undefined} + */ +gmfThemes.GmfMetaData.prototype.opacity; + + +/** + * A WMS layer that will be used instead of the WMTS layers in the print. Used + * to increase quality of printed WMTS layers. + * For WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.printLayers; + + +/** + * The WMS layers used as references to query the WMTS layers. + * For WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.queryLayers; + + +/** + * The icon visible in the background selector. + * For WMS and WMTS layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.thumbnail; + + +/** + * The name of the time attribute. + * For WMS(-T) layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.timeAttribute; + + +/** + * The snapping configuration for the leaf. If set, the leaf's layer is + * considered to be "snappable", even if the config itself is empty. + * Example of value: {'tolerance': 50, 'edge': false} + * For WMS layers. + * @type {gmfThemes.GmfSnappingConfig|undefined} + */ +gmfThemes.GmfMetaData.prototype.snappingConfig; + + +/** + * A corresponding WMS layer for a WMTS layers. Used to query the WMTS layers + * and to print it. (See also printLayers and queryLayers metadata for more + * granularity). + * For WMTS Layers. + * @type {string|undefined} + */ +gmfThemes.GmfMetaData.prototype.wmsLayers; + + +/** + * @constructor + * @struct + */ +gmfThemes.GmfSnappingConfig = function() {}; + + +/** + * Determines whethers the edges of features from the node layer can be snapped + * or not. Defaults to `true`. + * @type {boolean|undefined} + */ +gmfThemes.GmfSnappingConfig.prototype.edge; + + +/** + * The tolerance in pixels the snapping should occur for the node layer. + * Defaults to `10`. + * @type {number|undefined} + */ +gmfThemes.GmfSnappingConfig.prototype.tolerance; + + +/** + * Determines whethers the vertices of features from the node layer can be + * snapped or not. Defaults to `true`. + * @type {boolean|undefined} + */ +gmfThemes.GmfSnappingConfig.prototype.vertex; + + +/** + * @record + * @struct + */ +gmfThemes.GmfLayerAttributeValuesResponse = function() {}; + + +/** + * @type {Array.} + */ +gmfThemes.GmfLayerAttributeValuesResponse.prototype.items; + + +/** + * @record + * @struct + */ +gmfThemes.GmfLayerAttributeValue = function() {}; + + +/** + * @type {string} + */ +gmfThemes.GmfLayerAttributeValue.prototype.label; + + +/** + * @type {string} + */ +gmfThemes.GmfLayerAttributeValue.prototype.value; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/externs/lidarprofile.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/externs/lidarprofile.js new file mode 100644 index 000000000..15addcbbd --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/externs/lidarprofile.js @@ -0,0 +1,189 @@ +/** + * Externs for a LIDARD profile web service. + * + * @externs + */ + + +/** + * @type {Object} + */ +let lidarprofileServer; + + +/** + * @typedef {Object.} + */ +lidarprofileServer.ConfigClassifications; + +/** + * @constructor + * @struct + */ +lidarprofileServer.ConfigClassification = function() {}; + +/** + * @type string + */ +lidarprofileServer.ConfigClassification.prototype.color; + +/** + * @type string + */ +lidarprofileServer.ConfigClassification.prototype.name; + +/** + * @type string + */ +lidarprofileServer.ConfigClassification.prototype.value; + +/** + * @type boolean + */ +lidarprofileServer.ConfigClassification.prototype.visible; + + +/** + * @typedef {!Object} + */ +lidarprofileServer.ConfigLevels; + +/** + * @constructor + * @struct + */ +lidarprofileServer.ConfigLevel = function() {}; + +/** + * @type number + */ +lidarprofileServer.ConfigLevel.prototype.max; + +/** + * @type number + */ +lidarprofileServer.ConfigLevel.prototype.width; + + +/** + * @typedef {Object.} + */ +lidarprofileServer.ConfigPointAttributes; + +/** + * @constructor + * @struct + */ +lidarprofileServer.ConfigPointAttribute = function() {}; + +/** + * @type number + */ +lidarprofileServer.ConfigPointAttribute.prototype.bytes; + +/** + * @type number + */ +lidarprofileServer.ConfigPointAttribute.prototype.elements; + +/** + * @type string + */ +lidarprofileServer.ConfigPointAttribute.prototype.name; + +/** + * @type string + */ +lidarprofileServer.ConfigPointAttribute.prototype.value; + +/** + * @type number + */ +lidarprofileServer.ConfigPointAttribute.prototype.visible; + + +/** + * @constructor + * @struct + */ +lidarprofileServer.Config = function() {}; + +/** + * @type Object. + */ +lidarprofileServer.Config.prototype.classes_names_normalized; + +/** + * @type Object. + */ +lidarprofileServer.Config.prototype.classes_names_standard; + +/** + * @type lidarprofileServer.ConfigClassifications + */ +lidarprofileServer.Config.prototype.classification_colors; + +/** + * @type boolean + */ +lidarprofileServer.Config.prototype.debug; + +/** + * @type string + */ +lidarprofileServer.Config.prototype.default_attribute; + +/** + * @type string + */ +lidarprofileServer.Config.prototype.default_color; + +/** + * @type string + */ +lidarprofileServer.Config.prototype.default_point_attribute; + +/** + * @type string + */ +lidarprofileServer.Config.prototype.default_point_cloud; + +/** + * @type number + */ +lidarprofileServer.Config.prototype.initialLOD; + +/** + * @type lidarprofileServer.ConfigLevels + */ +lidarprofileServer.Config.prototype.max_levels; + +/** + * @type number + */ +lidarprofileServer.Config.prototype.max_point_number; + +/** + * @type number + */ +lidarprofileServer.Config.prototype.minLOD; + +/** + * @type lidarprofileServer.ConfigPointAttributes + */ +lidarprofileServer.Config.prototype.point_attributes; + +/** + * @type number + */ +lidarprofileServer.Config.prototype.point_size; + +/** + * @type number + */ +lidarprofileServer.Config.prototype.vertical_pan_tolerance; + +/** + * @type number + */ +lidarprofileServer.Config.prototype.width; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/fonts/README.md b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/fonts/README.md new file mode 100644 index 000000000..7c8af142e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/fonts/README.md @@ -0,0 +1,12 @@ +# Fonts + +The `gmf-icons` symbols font can be extended with new icons. + +In order to do so, you can add new glyphs to the `svg` file. + +Then the `.ttf`, `.woff` and `.eot` files should be generated with the +following command: + +``` +make generate-gmf-fonts +``` diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/fonts/gmf-icons.svg b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/fonts/gmf-icons.svg new file mode 100644 index 000000000..c874fcf92 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/fonts/gmf-icons.svg @@ -0,0 +1,24 @@ + + + +Icons for GeoMapfish + + + + + + + + + + + + + + + + + + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/options/gmfx.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/options/gmfx.js new file mode 100644 index 000000000..13d0ea51a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/options/gmfx.js @@ -0,0 +1,877 @@ +/** + * This file contains the typedefs of the options of the methods. + * It can be included as extern if you want to prevent renaming. + * @externs + */ + + +/** + * @type {Object} + */ +let gmfx; + + +/** + * @typedef {{ + * operator: (string), + * property: (string), + * value: (string) + * }} + */ +gmfx.ComparisonFilter; + + +/** + * The type of operator for the comparison filter. + * @type {string} + */ +gmfx.ComparisonFilter.prototype.operator; + + +/** + * The name of the property for the comparison filter. + * @type {string} + */ +gmfx.ComparisonFilter.prototype.property; + + +/** + * The value for the comparison filter that must match the combinaison of + * the operator and property. + * @type {string} + */ +gmfx.ComparisonFilter.prototype.value; + + +/** + * A part of the application config. + * @typedef {{ + * srid: (number), + * positionFeatureStyle: (ol.style.Style|undefined), + * accuracyFeatureStyle: (ol.style.Style|undefined), + * geolocationZoom: (number|undefined), + * autorotate: (boolean|undefined), + * mapViewConfig: (olx.ViewOptions|undefined), + * mapControls: (ol.Collection.|Array.|undefined), + * mapInteractions: (ol.Collection.|Array.|undefined), + * mapPixelRatio: (number|undefined) + * }} + */ +gmfx.Config; + + +/** + * The definition of an external OGC server + * @typedef {{ + * name: (string), + * type: (string), + * url: (string) + * }} + */ +gmfx.ExternalOGCServer; + + +/** + * Configuration for a grid tab. + * @typedef {{ + * configuration: ngeo.grid.Config, + * source: ngeox.QueryResultSource + * }} + */ +gmfx.GridSource; + + +/** + * Configuration used to initialize a grid. + * @type {ngeo.grid.Config} + */ +gmfx.GridSource.prototype.configuration; + + +/** + * Results of the query source. + * @type {ngeox.QueryResultSource} + */ +gmfx.GridSource.prototype.source; + + +/** + * Configuration option for {@link gmf.query.gridComponent} to merge + * grid tabs. + * + * E.g. `'two_wheels_park': ['velo_park', 'moto_park']}` merges the sources + * with label `velo_park` and `moto_park` into a new source `two_wheels_park`. + * + * @typedef {Object>} + */ +gmfx.GridMergeTabs; + + +/** + * The object containing all points in profile + * @typedef {{ + * autoWidth: (boolean|undefined), + * margin: (Object.|undefined), + * pointAttributes: (gmfx.LidarPointAttributeList|undefined), + * pointSum: (number|undefined), + * tolerance: (number|undefined) + * }} + */ +gmfx.LidarprofileClientConfig; + + +/** + * The object containing all points in profile + * @typedef {{ + * distance: (Array.|undefined), + * altitude: (Array.|undefined), + * color_packed: (Array.>|undefined), + * intensity: (Array.|undefined), + * classification: (Array.|undefined), + * coords: (Array.>|undefined) + * }} + */ +gmfx.LidarprofilePoints; + + +/** + * Profile point after measure or after parsing of the binary array returned by Pytree + * @typedef {{ + * distance: (number|undefined), + * altitude: (number|undefined), + * color_packed: (Array.|undefined), + * coords: (Array.|undefined), + * intensity: (number|undefined), + * classification: (number|undefined), + * set: (boolean|undefined) + * }} + */ +gmfx.LidarPoint; + + +/** + * The lidar point attribute list width default option + * @typedef {{ + * availableOptions: (Array.|undefined), + * selectedOption: (lidarprofileServer.ConfigPointAttributes|undefined) + * }} + */ +gmfx.LidarPointAttributeList; + +/** + * Projection object for the MousePositionDirective. Define a label and a filter + * to use to display coordinates for a projection. + * @typedef {{ + * code: string, + * label: string, + * filter: string + * }} + */ +gmfx.MousePositionProjection; + + +/** + * The epsg name of a projection. + * @type {string} + */ +gmfx.MousePositionProjection.prototype.code; + + +/** + * The label to display with this projection. + * @type {string} + */ +gmfx.MousePositionProjection.prototype.label; + + +/** + * The filter function to use to format this projection. Arguments can be passed + * with colon as separator (example: MyFilter:args1:args2:...) + * @type {string} + */ +gmfx.MousePositionProjection.prototype.filter; + + +/** + * @typedef {{ + * ogcServer: (gmfThemes.GmfOgcServer), + * layerNode: (gmfThemes.GmfLayerWMS) + * }} + */ +gmfx.ObjectEditingQueryableLayerInfo; + + +/** + * @type {gmfThemes.GmfOgcServer} + */ +gmfx.ObjectEditingQueryableLayerInfo.prototype.ogcServer; + + +/** + * @type {gmfThemes.GmfLayerWMS} + */ +gmfx.ObjectEditingQueryableLayerInfo.prototype.layerNode; + + +/** + * Additional configuration options for the object editing tools directive. + * @typedef {{ + * regularPolygonRadius: (number|undefined) + * }} + */ +gmfx.ObjectEditingToolsOptions; + + +/** + * The radius of the shapes created by the regular polygon radius creation + * tool. Default value is `100`. The value is in map units. + * @type {number|undefined} + */ +gmfx.ObjectEditingToolsOptions.prototype.regularPolygonRadius; + + +/** + * Password validator function with an error message. + * Configuration options for the permalink service. + * @typedef {{ + * isPasswordValid: function(string): string, + * notValidMessage: string + * }} + */ +gmfx.PasswordValidator; + + +/** + * Configuration options for the permalink service. + * @typedef {{ + * crosshairStyle: (Array<(null|ol.style.Style)>|null|ol.FeatureStyleFunction|ol.style.Style|undefined), + * crosshairEnabledByDefault: (boolean|undefined), + * projectionCodes: (Array.|undefined), + * useLocalStorage: (boolean|undefined), + * pointRecenterZoom: (number|undefined) + * }} + */ +gmfx.PermalinkOptions; + + +/** + * An alternate style for the crosshair feature added by the permalink service. + * @type {Array<(null|ol.style.Style)>|null|ol.FeatureStyleFunction|ol.style.Style|undefined} + */ +gmfx.PermalinkOptions.prototype.crosshairStyle; + + +/** + * Display the crosshair, gets overridden by the map_crosshair parameter. Default is `false`. + * @type {boolean|undefined} + */ +gmfx.PermalinkOptions.prototype.crosshairEnabledByDefault; + + +/** + * EPSG codes (e.g. 'EPSG:3857' or '3857'). The permalink service + * will accept coordinates in these projections and try to detect which projection + * the given coordinates are in. + * @type {Array.|undefined} + */ +gmfx.PermalinkOptions.prototype.projectionCodes; + + +/** + * Store the values in the local storage. Default is `false`. + * @type {boolean|undefined} + */ +gmfx.PermalinkOptions.prototype.useLocalStorage; + + +/** + * Zoom level to use when result is a single point feature. If not set the map + * is not zoomed to a specific zoom level. + * @type {number|undefined} + */ +gmfx.PermalinkOptions.prototype.pointRecenterZoom + + +/** + * Fields that can come from a print v3 server and can be used in the partial + * of the gmf print panel. + * @typedef {{ + * simpleAttributes: (Array.|undefined), + * attributes: (Array), + * dpi: (number|undefined), + * dpis: (Array.|undefined), + * formats: (Object.|undefined), + * layout: (string|undefined), + * layouts: (Array.|undefined), + * legend: (boolean|undefined), + * scale: (number|undefined), + * scales: (Array.|undefined) + * }} + */ +gmfx.PrintLayoutInfo; + +/** + * Custom print layoutInfo. + * @type {Array.|undefined} + */ +gmfx.PrintLayoutInfo.prototype.simpleAttributes; + + +/** + * The selected 'dpi'. + * @type {number|undefined} + */ +gmfx.PrintLayoutInfo.prototype.dpi; + + +/** + * The list of 'dpis'. + * @type {Array.|undefined} + */ +gmfx.PrintLayoutInfo.prototype.dpis; + + +/** + * The list of active 'formats' (png, pdf, ...). + * @type {Object.|undefined} + */ +gmfx.PrintLayoutInfo.prototype.formats; + + +/** + * The selected 'layout'. + * @type {string|undefined} + */ +gmfx.PrintLayoutInfo.prototype.layout; + + +/** + * The list of 'layouts'. + * @type {Array.|undefined} + */ +gmfx.PrintLayoutInfo.prototype.layouts; + + +/** + * The legend checkbox. + * @type {boolean|undefined} + */ +gmfx.PrintLayoutInfo.prototype.legend; + + +/** + * The selected 'scale'. + * @type {number|undefined} + */ +gmfx.PrintLayoutInfo.prototype.scale; + + +/** + * The list of 'scales' + * @type {Array.|undefined} + */ +gmfx.PrintLayoutInfo.prototype.scales; + + +/** + * Object that can be used to generate a form field. + * @typedef {{ + * default: (string|boolean|number|undefined), + * name: string, + * type: string + * }} + */ +gmfx.PrintSimpleAttributes; + + +/** + * Default value of the form field. + * @type {(string|boolean|number|undefined)} + */ +gmfx.PrintSimpleAttributes.prototype.default; + + +/** + * Name of the form field. + * @type {string} + */ +gmfx.PrintSimpleAttributes.prototype.name; + + +/** + * Type of the field. + * Can be 'String', 'Boolean' or 'Number'. + * @type {string} + */ +gmfx.PrintSimpleAttributes.prototype.type; + + +/** + * Configuration object for one profile's line. + * @typedef {{ + * color: (string|undefined), + * zExtractor: (function(Object): number|undefined) + * }} + */ +gmfx.ProfileLineConfiguration; + + +/** + * Color of the line (hex color string). + * @type {(string|undefined)} + */ +gmfx.ProfileLineConfiguration.prototype.color; + + +/** + * Extract the elevation of a point (an item of the elevation data array). + * @type {(function(Object): number|undefined)} + */ +gmfx.ProfileLineConfiguration.prototype.zExtractor; + + +/** + * Information to display for a given point in the profile. The point is + * typically given by the profile's hover. + * @typedef {{ + * coordinate: (ol.Coordinate|undefined), + * distance: (number|undefined), + * elevations: (Object.|undefined), + * xUnits: (string|undefined), + * yUnits: (string|undefined) + * }} + */ +gmfx.ProfileHoverPointInformations; + + +/** + * Coordinate of the point. + * @type {ol.Coordinate|undefined} + */ +gmfx.ProfileHoverPointInformations.prototype.coordinate; + + +/** + * distance of the point on the line. Can be in meters or kilometers. + * @type {number|undefined} + */ +gmfx.ProfileHoverPointInformations.prototype.distance; + + +/** + * Elevations of the point (example: {aster: 556.5, srtm: 560}). + * @type {Object.|undefined} + */ +gmfx.ProfileHoverPointInformations.prototype.elevations; + + +/** + * Units of the x axis. + * @type {string|undefined} + */ +gmfx.ProfileHoverPointInformations.prototype.xUnits; + + +/** + * Units of the y axis. + * @type {string|undefined} + */ +gmfx.ProfileHoverPointInformations.prototype.yUnits; + + +/** + * Datasource configuration options for the search directive. + * @typedef {{ + * bloodhoundOptions: (BloodhoundOptions|undefined), + * labelKey: string, + * groupValues: (Array.|undefined), + * groupActions: (Array.|undefined), + * projection: (string|undefined), + * typeaheadDatasetOptions: (TypeaheadDataset|undefined), + * url: string + * }} + */ +gmfx.SearchComponentDatasource; + + +/** + * The optional Bloodhound configuration for this data set. + * See: https://github.com/twitter/typeahead.js/blob/master/doc/bloodhound.md + * @type {BloodhoundOptions|undefined} + */ +gmfx.SearchComponentDatasource.prototype.bloodhoundOptions; + + +/** + * The name of a corresponding GeoJSON property key in the current dataset. + * The bound value of this property key will be used as label. + * @type {string|undefined} + */ +gmfx.SearchComponentDatasource.prototype.labelKey; + + +/** + * Possible values for the 'layer_name' key. + * Used to define groups of dataset. + * @type {Array.|undefined} + */ +gmfx.SearchComponentDatasource.prototype.groupValues; + + +/** + * List of allowed actions. The list may contain a combination of + * `add_theme`, `add_group` or `add_layer` + * @type {Array.|undefined} + */ +gmfx.SearchComponentDatasource.prototype.groupActions; + + +/** + * The geometry's projection for this set of data. + * @type {string|undefined} + */ +gmfx.SearchComponentDatasource.prototype.projection; + + +/** + * The optional Typeahead configuration for this dataset. + * See: https://github.com/twitter/typeahead.js/blob/master/ + * doc/jquery_typeahead.md#datasets + * @type {TypeaheadDataset|undefined} + */ +gmfx.SearchComponentDatasource.prototype.typeaheadDatasetOptions; + + +/** + * Url of the search service. Must contain a '%QUERY' term that will be + * replaced by the input string. + * @type {string} + */ +gmfx.SearchComponentDatasource.prototype.url; + + +/** + * @typedef {Object.>} + */ +gmfx.StylesObject; + + +/** + * @typedef {{ + * children: (Object.|undefined), + * isChecked: (boolean|undefined), + * isExpanded: (boolean|undefined), + * isLegendExpanded: (boolean|undefined) + * }} + */ +gmfx.TreeManagerFullState; + + +/** + * Availables functionalities. + * @typedef {{ + * default_basemap: Array., + * default_theme: Array., + * filtrable_layers: (Array.|undefined), + * location: Array. + * }} + */ +gmfx.AuthenticationFunctionalities; + + +/** + * Base maps to use by default. + * @type {Array.} + */ +gmfx.AuthenticationFunctionalities.prototype.default_basemap; + + +/** + * Theme to use by default. + * @type {Array.} + */ +gmfx.AuthenticationFunctionalities.prototype.default_theme; + + +/** + * A list of layer names that can be filtered. + * @type {Array.|undefined} + */ +gmfx.AuthenticationFunctionalities.prototype.filtrable_layers; + + +/** + * Availables locations. + * @type {Array.} + */ +gmfx.AuthenticationFunctionalities.prototype.location; + +/** + * @typedef {{ + * functionalities: (gmfx.AuthenticationFunctionalities|null), + * is_password_changed: (boolean|null), + * role_id: (number|null), + * role_name: (string|null), + * username: (string|null) + * }} + */ +gmfx.User; + + +/** + * Configured functionalities of the user. + * @type {gmfx.AuthenticationFunctionalities|null} + */ +gmfx.User.prototype.functionalities; + + +/** + * True if the password of the user has been changed. False otherwise. + * @type {boolean|null} + */ +gmfx.User.prototype.is_password_changed; + + +/** + * the role id of the user. + * @type {number|null} + */ +gmfx.User.prototype.role_id; + + +/** + * The role name of the user. + * @type {string|null} + */ +gmfx.User.prototype.role_name; + + +/** + * The name of the user. + * @type {string|null} + */ +gmfx.User.prototype.username; + + +/** + * @typedef {{ + * data: gmfx.ShortenerAPIResponseData, + * status: number + * }} + */ +gmfx.ShortenerAPIResponse; + + +/** + * Response payload to the shortener API + * @type {gmfx.ShortenerAPIResponseData} + */ +gmfx.ShortenerAPIResponse.data; + + +/** + * HTTP status + * @type {number|undefined} + */ +gmfx.ShortenerAPIResponse.status; + + +/** + * @typedef {{ + * short_url: string + * }} + */ +gmfx.ShortenerAPIResponseData; + + +/** + * @typedef {{ + * url: string, + * email: (string|undefined), + * message : (string|undefined) + * }} + */ +gmfx.ShortenerAPIRequestParams; + +/** + * Configuration options for the themes service. + * @typedef {{ + * addBlankBackgroundLayer: (boolean|undefined) + * }} + */ +gmfx.ThemesOptions; + + +/** + * Whether to add a blank background layer to the list of available backgrounds. + * @type {boolean|undefined} + */ +gmfx.ThemesOptions.prototype.addBlankBackgroundLayer; + + +/** + * Static function to create a popup with an iframe. + * @param {string} url an url. + * @param {string} title (text). + * @param {string=} opt_width CSS width. + * @param {string=} opt_height CSS height. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + */ +gmfx.openIframePopup; + + +/** + * Static function to create a popup with html content. + * @param {string} content (text or html). + * @param {string} title (text). + * @param {string=} opt_width CSS width. + * @param {string=} opt_height CSS height. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + */ +gmfx.openTextPopup; + + +/** + * Namespace. + * @type {Object} + */ +gmfx.datasource; + + +/** + * @typedef {ol.Collection.} + */ +gmfx.datasource.DataSources; + + +/** + * @typedef {{ + * dataSource : (gmf.datasource.OGC|null) + * }} + */ +gmfx.datasource.DataSourceBeingFiltered; + + +/** + * The options required to create a `gmf.datasource.OGC`. + * @record + * @struct + * @extends ngeox.datasource.OGCOptions + */ +gmfx.datasource.OGCOptions; + + +/** + * A reference to the GMF layer node that was used to create the data source. + * It may contains additional information, such as metadata, about the data + * source. + * @type {gmfThemes.GmfLayer} + */ +gmfx.datasource.OGCOptions.prototype.gmfLayer; + + +/** + * @typedef {{ + * columns : Array., + * data : Array.> + * }} + */ +gmfx.datasource.DataSourceTableObject; + + +/** + * @typedef {{ + * title : string, + * table : gmfx.datasource.DataSourceTableObject + * }} + */ +gmfx.datasource.DataSourcePrintReportObject; + + +/** + * @typedef {{ + * layerObj: (!ol.layer.Tile), + * unregister: Function + * }} + */ +gmfx.datasource.ExternalDataSourcesManagerWMTSCacheItem; + + +/** + * @typedef {Object<(number|string), gmfx.datasource.ManagerTreeCtrlCacheItem>} + */ +gmfx.datasource.ManagerTreeCtrlCache; + + +/** + * @typedef {{ + * filterRulesWatcherUnregister: (Function), + * stateWatcherUnregister: (Function), + * timeLowerValueWatcherUnregister: (Function|undefined), + * timeUpperValueWatcherUnregister: (Function|undefined), + * treeCtrl: (ngeo.layertree.Controller), + * wmsLayer: (ol.layer.Image|undefined) + * }} + */ +gmfx.datasource.ManagerTreeCtrlCacheItem; + + +/** + * @type {Object} + */ +let cgxp; + + +/** + * @type {Object} + */ +cgxp.tools; + + +/** + * Static function to create a popup with an iframe. + * @param {string} url an url. + * @param {string} title (text). + * @param {string=} opt_width CSS width. + * @param {string=} opt_height CSS height. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + */ +cgxp.tools.openInfoWindow; + + +/** + * @param {ngeo.message.Popup!} popup a ngeoPopup. + * @param {string} title (text). + * @param {string=} opt_width CSS width. + * @param {string=} opt_height CSS height. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + */ +gmfx.openPopup_; + + +/** + * @typedef {ngeo.CustomEvent.<{ + * user: gmfx.User + * }>} + */ +gmfx.AuthenticationEvent; + + +/** + * @typedef {{ + * functionalities: (gmfx.AuthenticationFunctionalities|undefined), + * is_password_changed: (boolean|undefined), + * role_id: (number|undefined), + * role_name: (string|undefined), + * username: (string|undefined) + * }} + */ +gmfx.AuthenticationLoginResponse; + + +/** + * @typedef {{ + * success: boolean + * }} + */ +gmfx.AuthenticationDefaultResponse; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/.eslintrc-googshift.yaml b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/.eslintrc-googshift.yaml new file mode 100644 index 000000000..1c267adeb --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/.eslintrc-googshift.yaml @@ -0,0 +1,25 @@ +plugins: + - googshift +rules: + googshift/no-duplicate-requires: error + + googshift/no-missing-requires: + - error + - prefixes: [gmf, ngeo, ol] + + googshift/no-unused-requires: warn + + googshift/one-provide-or-module: + - error + - entryPoints: [ngeo] + root: src + + googshift/requires-first: error + + googshift/valid-provide-and-module: + - error + - entryPoints: [ngeo] + root: src/module + replace: ../../contribs/gmf/src|gmf + + googshift/valid-requires: error diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/.eslintrc.yaml b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/.eslintrc.yaml new file mode 100644 index 000000000..5c5775fca --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/.eslintrc.yaml @@ -0,0 +1,25 @@ +plugins: + - googshift +rules: + googshift/no-duplicate-requires: error + + googshift/no-missing-requires: + - error + - prefixes: [gmf, ngeo, ol] + + googshift/no-unused-requires: warn + + googshift/one-provide-or-module: + - error + - entryPoints: [ngeo] + root: src + + googshift/requires-first: error + + googshift/valid-provide-and-module: + - warn + - entryPoints: [ngeo] + root: src/module + replace: ../../contribs/gmf/src|gmf + + googshift/valid-requires: error diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/Service.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/Service.js new file mode 100644 index 000000000..f258b533a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/Service.js @@ -0,0 +1,250 @@ +/** + * @module gmf.authentication.Service + */ +import ngeoCustomEvent from 'ngeo/CustomEvent.js'; +import olEventsEventTarget from 'ol/events/EventTarget.js'; + +/** + * An "authentication" service for a GeoMapFish application. Upon loading, it + * launches a request to determine whether a user is currently logged in or + * not. + * + * The possible API requests it supports, which are all self-explanatory, are: + * + * - changePassword + * - login + * - logout + * - resetPassword + * + * @extends {ol.events.EventTarget} + */ +const exports = class extends olEventsEventTarget { + + /** + * @param {angular.$http} $http Angular http service. + * @param {angular.$injector} $injector Main injector. + * @param {angular.Scope} $rootScope The directive's scope. + * @param {string} authenticationBaseUrl URL to "authentication" web service. + * @param {gmfx.User} gmfUser User. + * @ngInject + */ + constructor($http, $injector, $rootScope, authenticationBaseUrl, gmfUser) { + + super(); + + /** + * @type {angular.$http} + * @private + */ + this.$http_ = $http; + + /** + * @type {angular.Scope} + * @private + */ + this.$rootScope_ = $rootScope; + + /** + * The authentication url without trailing slash + * @type {string} + * @private + */ + this.baseUrl_ = authenticationBaseUrl.replace(/\/$/, ''); + + /** + * @type {gmfx.User} + * @private + */ + this.user_ = gmfUser; + + /** + * Don't request a new user object from the back-end after + * logging out if the logged-in user's role has this role. + * @type {?string} + * @private + */ + this.noReloadRole_ = $injector.has('gmfAuthenticationNoReloadRole') + ? $injector.get('gmfAuthenticationNoReloadRole') + : null; + + this.load_(); + } + + /** + * Load the authentication service, which sends an asynch request to + * determine whether the user is currently connected or not. + * @private + */ + load_() { + const url = `${this.baseUrl_}/${exports.RouteSuffix.IS_LOGGED_IN}`; + this.$http_.get(url, {withCredentials: true}).then( + this.handleLogin_.bind(this, true) + ); + } + + /** + * @param {string} oldPwd Old password. + * @param {string} newPwd New password. + * @param {string} confPwd New password confirmation. + * @return {angular.$q.Promise} Promise. + * @export + */ + changePassword(oldPwd, newPwd, confPwd) { + const url = `${this.baseUrl_}/${exports.RouteSuffix.CHANGE_PASSWORD}`; + + return this.$http_.post(url, $.param({ + 'oldPassword': oldPwd, + 'newPassword': newPwd, + 'confirmNewPassword': confPwd + }), { + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + withCredentials: true + }).then(((response) => { + this.user_.is_password_changed = true; + })); + } + + /** + * @param {string} login Login name. + * @param {string} pwd Password. + * @return {angular.$q.Promise} Promise. + * @export + */ + login(login, pwd) { + const url = `${this.baseUrl_}/${exports.RouteSuffix.LOGIN}`; + + return this.$http_.post(url, $.param({'login': login, 'password': pwd}), { + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + withCredentials: true + }).then( + this.handleLogin_.bind(this, false)); + } + + /** + * @return {angular.$q.Promise} Promise. + * @export + */ + logout() { + const noReload = this.user_['role_name'] === this.noReloadRole_; + const url = `${this.baseUrl_}/${exports.RouteSuffix.LOGOUT}`; + return this.$http_.get(url, {withCredentials: true}).then(() => { + this.resetUser_(noReload); + }); + } + + /** + * @param {string} login Login name. + * @return {angular.$q.Promise} Promise. + * @export + */ + resetPassword(login) { + const url = `${this.baseUrl_}/${exports.RouteSuffix.RESET_PASSWORD}`; + + /** + * @param {angular.$http.Response} resp Ajax response. + * @return {gmfx.AuthenticationDefaultResponse} Response. + */ + const successFn = function(resp) { + const respData = /** @type gmfx.AuthenticationDefaultResponse} */ ( + resp.data); + return respData; + }.bind(this); + + return this.$http_.post(url, $.param({'login': login}), { + headers: {'Content-Type': 'application/x-www-form-urlencoded'} + }).then(successFn); + } + + /** + * @return {?gmfx.AuthenticationFunctionalities} The role functionalities. + */ + getFunctionalities() { + return this.user_.functionalities; + } + + /** + * @return {number|null} The role ID. + */ + getRoleId() { + return this.user_.role_id; + } + + /** + * @param {boolean} checkingLoginStatus Checking the login status? + * @param {angular.$http.Response} resp Ajax response. + * @return {angular.$http.Response} Response. + * @private + */ + handleLogin_(checkingLoginStatus, resp) { + const respData = /** @type {gmfx.AuthenticationLoginResponse} */ (resp.data); + this.setUser_(respData, !checkingLoginStatus); + if (checkingLoginStatus) { + /** @type {gmfx.AuthenticationEvent} */ + const event = new ngeoCustomEvent('ready', {user: this.user_}); + this.dispatchEvent(event); + } + return resp; + } + + /** + * @param {gmfx.AuthenticationLoginResponse} respData Response. + * @param {boolean} emitEvent Emit a login event? + * @private + */ + setUser_(respData, emitEvent) { + for (const key in respData) { + this.user_[key] = respData[key]; + } + if (emitEvent && respData.username !== undefined) { + /** @type {gmfx.AuthenticationEvent} */ + const event = new ngeoCustomEvent('login', {user: this.user_}); + this.dispatchEvent(event); + } + } + + /** + * @private + * @param {boolean} noReload Don't request a new user object from + * the back-end after logging out, defaults to false. + */ + resetUser_(noReload) { + noReload = noReload || false; + for (const key in this.user_) { + this.user_[key] = null; + } + /** @type {gmfx.AuthenticationEvent} */ + const event = new ngeoCustomEvent('logout', {user: this.user_}); + this.dispatchEvent(event); + if (!noReload) { + this.load_(); + } + } +}; + +/** + * @enum {string} + */ +exports.RouteSuffix = { + CHANGE_PASSWORD: 'loginchange', + IS_LOGGED_IN: 'loginuser', + LOGIN: 'login', + LOGOUT: 'logout', + RESET_PASSWORD: 'loginresetpassword' +}; + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfAuthenticationService', []); +exports.module.service('gmfAuthenticationService', exports); + +exports.module.value('gmfUser', { + 'functionalities': null, + 'is_password_changed': null, + 'role_id': null, + 'role_name': null, + 'username': null +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/component.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/component.html new file mode 100644 index 000000000..a8ecc65dc --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/component.html @@ -0,0 +1,151 @@ +
+
+ {{'Logged in as' | translate}} + {{ ::$ctrl.gmfUser.username }}. +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+ +
+
+ +
+ +
+ {{ $ctrl.infoMessage }} +
+ +
+
+ +
+
+ +
+
+ +
+ +
+ +
+ + + + + + + +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/component.js new file mode 100644 index 000000000..f65359b7e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/component.js @@ -0,0 +1,457 @@ +/** + * @module gmf.authentication.component + */ +import gmfAuthenticationService from 'gmf/authentication/Service.js'; +import ngeoMessageMessage from 'ngeo/message/Message.js'; +import ngeoMessageNotification from 'ngeo/message/Notification.js'; + +/** @suppress {extraRequire} */ +import ngeoMessageModalComponent from 'ngeo/message/modalComponent.js'; + +/** + * @type {angular.Module} + */ +const exports = angular.module('gmfAuthentication', [ + gmfAuthenticationService.module.name, + ngeoMessageNotification.module.name, + ngeoMessageModalComponent.name, +]); + + +/** + * @param {angular.JQLite} element Element. + * @param {angular.Attributes} attrs Attributes. + * @return {string} Template URL. + */ +exports.gmfAuthenticationTemplateUrl_ = (element, attrs) => { + const templateUrl = attrs['gmfAuthenticationTemplateurl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/authentication'; +}; + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/authentication', require('./component.html')); +}); + + +/** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.JQLite, !angular.Attributes): string} gmfAuthenticationTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfAuthenticationTemplateUrl($element, $attrs, gmfAuthenticationTemplateUrl) { + return gmfAuthenticationTemplateUrl($element, $attrs); +} + + +/** + * An "authentication" component for a GeoMapFish application. With the + * use of the "authentication" service, it features a complete interface + * for the user to be able to login, logout, change or reset his or her + * password. The `gmfUser` angular value is also used to keep track of + * the user information. When empty, that means that the user isn't connected + * yet. + * + * While not logged in, the "login" form is shown, which allows the user to + * either log in or ask for a password reset. + * + * Once logged in, the "logout" form is shown, which allows the user to either + * log out or change his or her password. + * + * Example: + * + * + * + * + * @htmlAttribute {boolean} gmf-authentication-allow-password-reset Whether to + * show the password forgotten link. Default to true. + * @htmlAttribute {boolean|function} gmf-authentication-allow-password-change Whether to + * show the change password button. Default to true. You can also specify a gmfx.PasswordValidator Object + * to add constraint on user's new password. + * @htmlAttribute {gmfx.PasswordValidator} gmf-authentication-password-validator A gmfx.PasswordValidator + * Object to add constraint on user's new password. The gmf-authentication-allow-password-change. To use + * it you must also allow the user to change its password. + * @htmlAttribute {boolean} gmf-authentication-force-password-change Force the + * user to change its password. Default to false. If you set it to true, you + * should also allow the user to change its password. Don't add this option alone, use + * it in a dedicated authentication component, in a ngeo-modal, directly in + * your index.html (see example 2.) + * @htmlAttribute {string} gmf-authentication-info-message Message to show above the authentication form. + * + * Example 2: + * + * + * + * + * + * + * @ngdoc component + * @ngname gmfAuthentication + */ +exports.component_ = { + bindings: { + 'allowPasswordReset': ' { + this.changePasswordReset(); + this.setError_( + [gettextCatalog.getString('Your password has successfully been changed.')], + ngeoMessageMessage.Type.INFORMATION + ); + }) + .catch((err) => { + this.setError_(gettextCatalog.getString('Incorrect old password.')); + }); + } + } + } + + /** + * Calls the authentication service login method. + * @export + */ + login() { + const gettextCatalog = this.gettextCatalog; + + const errors = []; + if (this.loginVal === '') { + errors.push(gettextCatalog.getString('The username is required.')); + } + if (this.pwdVal === '') { + errors.push(gettextCatalog.getString('The password is required.')); + } + if (errors.length) { + this.setError_(errors); + } else { + const error = gettextCatalog.getString('Incorrect credentials or disabled account.'); + this.gmfAuthenticationService_.login(this.loginVal, this.pwdVal).then( + this.resetError_.bind(this), + this.setError_.bind(this, error)); + } + } + + /** + * Calls the authentication service logout method. + * @export + */ + logout() { + const gettextCatalog = this.gettextCatalog; + const error = gettextCatalog.getString('Could not log out.'); + this.gmfAuthenticationService_.logout().then( + this.resetError_.bind(this), + this.setError_.bind(this, error)); + } + + /** + * Calls the authentication service resetPassword method. + * @export + */ + resetPassword() { + const gettextCatalog = this.gettextCatalog; + + if (!this.loginVal) { + this.setError_(gettextCatalog.getString('Please, input a login...')); + return; + } + + const error = gettextCatalog.getString('An error occurred while resetting the password.'); + + /** + * @param {gmfx.AuthenticationDefaultResponse} respData Response. + */ + const resetPasswordSuccessFn = function(respData) { + this.resetPasswordModalShown = true; + this.resetError_(); + }.bind(this); + + this.gmfAuthenticationService_.resetPassword(this.loginVal).then( + resetPasswordSuccessFn, + this.setError_.bind(this, error) + ); + } + + + // OTHER METHODS + + /** + * Reset the changePassword values and error. + * @export + */ + changePasswordReset() { + this.resetError_(); + this.changingPassword = false; + this.oldPwdVal = ''; + this.newPwdVal = ''; + this.newPwdConfVal = ''; + } + + /** + * @param {string|Array.} errors Errors. + * @param {ngeoMessageMessage.Type} [messageType] Type. + * @private + */ + setError_(errors, messageType) { + if (messageType == undefined) { + messageType = ngeoMessageMessage.Type.ERROR; + } + if (this.error) { + this.resetError_(); + } + + this.error = true; + + const container = this.$element_.find('.gmf-authentication-error'); + + if (!Array.isArray(errors)) { + errors = [errors]; + } + + errors.forEach(function(error) { + this.notification_.notify({ + msg: error, + target: container, + type: messageType + }); + }, this); + } + + /** + * @private + */ + resetError_() { + this.notification_.clear(); + this.error = false; + } +}; + +exports.controller('GmfAuthenticationController', + exports.AuthenticationController_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/module.js new file mode 100644 index 000000000..6a84c3147 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/authentication/module.js @@ -0,0 +1,18 @@ +/** + * @module gmf.authentication.module + */ +import gmfAuthenticationComponent from 'gmf/authentication/component.js'; + +/** @suppress {extraRequire} */ +import gmfAuthenticationService from 'gmf/authentication/Service.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfAuthenticationModule', [ + gmfAuthenticationComponent.name, + gmfAuthenticationService.module.name +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/component.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/component.html new file mode 100644 index 000000000..e6d5838a5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/component.html @@ -0,0 +1,20 @@ +
    +
  • + + {{layer.get("label") | translate}} + +
  • + + +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/component.js new file mode 100644 index 000000000..57d36868e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/component.js @@ -0,0 +1,248 @@ +/** + * @module gmf.backgroundlayerselector.component + */ +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import ngeoMapBackgroundLayerMgr from 'ngeo/map/BackgroundLayerMgr.js'; +import * as olEvents from 'ol/events.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfBackgroundlayerselector', [ + gmfThemeThemes.module.name, + ngeoMapBackgroundLayerMgr.module.name, +]); + + +exports.value('gmfBackgroundlayerselectorTemplateUrl', + /** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} Template URL. + */ + ($element, $attrs) => { + const templateUrl = $attrs['gmfBackgroundlayerselectorTemplateurl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/backgroundlayerselector'; + } +); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/backgroundlayerselector', require('./component.html')); +}); + + +/** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.JQLite, !angular.Attributes): string} gmfBackgroundlayerselectorTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfBackgroundlayerselectorTemplateUrl($element, $attrs, gmfBackgroundlayerselectorTemplateUrl) { + return gmfBackgroundlayerselectorTemplateUrl($element, $attrs); +} + + +/** + * Provide a "background layer selector" component. + * + * Example: + * + * + * + * + * Used UI metadata: + * + * * thumbnail: The URL used for the icon. + * + * @htmlAttribute {ol.Map=} gmf-backgroundlayerselector-map The map. + * @htmlAttribute {string} gmf-backgroundlayer-opacity-options The opacity slider options. + * @htmlAttribute {Function} gmf-backgroundlayerselector-select Function called + * when a layer was selected by the user. + * + * @ngdoc component + * @ngname gmfBackgroundlayerselector + */ +exports.component_ = { + controller: 'GmfBackgroundlayerselectorController as ctrl', + bindings: { + 'map': '=gmfBackgroundlayerselectorMap', + 'opacityOptions': '=gmfBackgroundlayerOpacityOptions', + 'select': '&?gmfBackgroundlayerselectorSelect' + }, + templateUrl: gmfBackgroundlayerselectorTemplateUrl +}; + + +exports.component('gmfBackgroundlayerselector', + exports.component_); + + +/** + * @constructor + * @private + * @struct + * @param {!angular.Scope} $scope Angular scope. + * @param {!ngeo.map.BackgroundLayerMgr} ngeoBackgroundLayerMgr Background layer manager. + * @param {!gmf.theme.Themes} gmfThemes Themes service. + * @ngInject + * @ngdoc controller + * @ngname GmfBackgroundlayerselectorController + */ +exports.Controller_ = function($scope, ngeoBackgroundLayerMgr, gmfThemes) { + + /** + * @type {?ol.Map} + * @export + */ + this.map; + + /** + * @type {!string|undefined} + * @export + */ + this.opacityOptions; + + /** + * Function called when a layer was selected by the user. + * @type {?Function} + * @export + */ + this.select; + + /** + * @type {?ol.layer.Base} + * @export + */ + this.bgLayer; + + /** + * @type {?Array.} + * @export + */ + this.bgLayers; + + /** + * @type {ol.layer.Base} + * @export + */ + this.opacityLayer; + + /** + * @type {!gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + /** + * @type {!Array.} + * @private + */ + this.listenerKeys_ = []; + + this.listenerKeys_.push(olEvents.listen(gmfThemes, 'change', this.handleThemesChange_, this)); + + /** + * @type {!ngeo.map.BackgroundLayerMgr} + * @private + */ + this.backgroundLayerMgr_ = ngeoBackgroundLayerMgr; + + this.listenerKeys_.push(olEvents.listen(this.backgroundLayerMgr_, 'change', + /** + * @param {!ngeox.BackgroundEvent} event Event. + */ + (event) => { + this.bgLayer = event.detail.current; + })); + + $scope.$on('$destroy', this.handleDestroy_.bind(this)); +}; + + +/** + * Initialise the controller. + */ +exports.Controller_.prototype.$onInit = function() { + this.handleThemesChange_(); +}; + + +/** + * Called when the themes changes. Set (or reset) the backround layers. + * @private + */ +exports.Controller_.prototype.handleThemesChange_ = function() { + this.gmfThemes_.getBgLayers().then((layers) => { + this.bgLayers = layers; + + if (this.opacityOptions !== undefined) { + const opacityLayer = layers.find(layer => layer.get('label') === this.opacityOptions); + if (opacityLayer !== undefined) { + this.setOpacityBgLayer(opacityLayer); + this.opacityLayer = opacityLayer; + + // Reorder for the UI the bgArray copy with the opacity layer at the end + this.bgLayers = this.bgLayers.slice(); + const indexOpa = this.bgLayers.findIndex(layer => layer === this.opacityLayer); + this.bgLayers.splice(indexOpa, 1); + this.bgLayers.push(opacityLayer); + } + } + }); +}; + +/** + * Getter/setter for background layer overlay, used by opacity slider. + * @param {?number} val The opacity. + * @returns {number} The background layer opacity. + * @export + */ +exports.Controller_.prototype.getSetBgLayerOpacity = function(val) { + if (val !== undefined) { + this.opacityLayer.setOpacity(val); + } + return this.opacityLayer.getOpacity(); +}; + +/** + * @param {ol.layer.Base} layer Layer. + * @param {boolean=} opt_silent Do not notify listeners. + * @export + */ +exports.Controller_.prototype.setLayer = function(layer, opt_silent) { + this.bgLayer = layer; + this.backgroundLayerMgr_.set(this.map, layer); + if (!opt_silent && this.select) { + this.select(); + } +}; + +/** + * Set a background layer overlay, used by the opacity slider. + * @param {ol.layer.Base} layer The opacity background layer. + * @export + */ +exports.Controller_.prototype.setOpacityBgLayer = function(layer) { + this.backgroundLayerMgr_.setOpacityBgLayer(this.map, layer); +}; + +/** + * @private + */ +exports.Controller_.prototype.handleDestroy_ = function() { + this.listenerKeys_.forEach(olEvents.unlistenByKey); + this.listenerKeys_.length = 0; +}; + + +exports.controller('GmfBackgroundlayerselectorController', + exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/module.js new file mode 100644 index 000000000..ca8589fee --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/backgroundlayerselector/module.js @@ -0,0 +1,14 @@ +/** + * @module gmf.backgroundlayerselector.module + */ +import gmfBackgroundlayerselectorComponent from 'gmf/backgroundlayerselector/component.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfBackgroundlayerselectorModule', [ + gmfBackgroundlayerselectorComponent.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/component.js new file mode 100644 index 000000000..e234afcba --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/component.js @@ -0,0 +1,297 @@ +/** + * @module gmf.contextualdata.component + */ +import gmfRasterRasterService from 'gmf/raster/RasterService.js'; +import googAsserts from 'goog/asserts.js'; +import olOverlay from 'ol/Overlay.js'; +import * as olProj from 'ol/proj.js'; +import * as olEvents from 'ol/events.js'; +import * as olObj from 'ol/obj.js'; + +/** + * @type {angular.Module} + */ +const exports = angular.module('gmfContextualdata', [ + gmfRasterRasterService.module.name, +]); + + +/** + * Provide a directive responsible of displaying contextual data after a right + * click on the map. + * + * This directive doesn't require being rendered in a visible DOM element. + * It's usually added to the element where the map directive is also added. + * + * Example: + * + * + * + * The content of the popover is managed in a partial that must be defined + * using the `gmfContextualdatacontentTemplateUrl` value. See + * {@link gmf.contextualdatacontentDirective} for more details. + * + * One can also provide a `gmf-contextualdata-callback` attribute in order to + * do some additional computing on the coordinate or the values received for + * the raster service. The callback function is called with the coordinate of + * the clicked point and the response data from the server. It is intended to + * return an object of additional properties to add to the scope. + * + * See the [../examples/contribs/gmf/contextualdata.html](../examples/contribs/gmf/contextualdata.html) example for a usage sample. + * + * @htmlAttribute {ol.Map} map The map. + * @htmlAttribute {Array} projections The list of projections. + * @htmlAttribute {Function} callback A function called after server + * (raster) data is received in case some additional computing is required. + * Optional. + * @return {angular.Directive} The directive specs. + * @ngdoc directive + * @ngname gmfContextualdata + */ +exports.directive_ = function() { + return { + restrict: 'A', + scope: false, + controller: 'GmfContextualdataController as cdCtrl', + bindToController: { + 'map': ' { + controller.init(); + } + }; +}; + +exports.directive('gmfContextualdata', + exports.directive_); + + +/** + * + * @param {angular.$compile} $compile Angular compile service. + * @param {angular.$timeout} $timeout Angular timeout service. + * @param {!angular.Scope} $scope Scope. + * @param {gmf.raster.RasterService} gmfRaster Gmf Raster service + * @param {angular.$injector} $injector Angular injector service. + * + * @constructor + * @private + * @ngdoc controller + * @ngInject + */ +exports.Controller_ = function($compile, $timeout, $scope, gmfRaster, $injector) { + + /** + * @type {ol.Map} + * @export + */ + this.map; + + /** + * @type {Array} + * @export + */ + this.projections; + + /** + * @type {function(ol.Coordinate, Object):Object} + * @export + */ + this.callback; + + /** + * @type {ol.Overlay} + * @private + */ + this.overlay_; + + /** + * @type {angular.$compile} + * @private + */ + this.$compile_ = $compile; + + /** + * @type {angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {angular.Scope} + * @private + */ + this.$scope_ = $scope; + + /** + * @type {gmf.raster.RasterService} + * @private + */ + this.gmfRaster_ = gmfRaster; + + /** + * @type {Object} + * @private + */ + this.gmfContextualdataOptions_ = $injector.has('gmfContextualdataOptions') ? + $injector.get('gmfContextualdataOptions') : {}; + + angular.element('body').on('mousedown', this.hidePopover.bind(this)); +}; + +/** + * + */ +exports.Controller_.prototype.init = function() { + this.preparePopover_(); + + const mapDiv = this.map.getTargetElement(); + googAsserts.assertElement(mapDiv); + + olEvents.listen(mapDiv, 'contextmenu', + this.handleMapContextMenu_, this); +}; + +/** + * @param {!Event} event Event. + * @private + */ +exports.Controller_.prototype.handleMapContextMenu_ = function(event) { + this.$scope_.$apply(() => { + const pixel = this.map.getEventPixel(event); + const coordinate = this.map.getCoordinateFromPixel(pixel); + this.setContent_(coordinate); + event.preventDefault(); + this.hidePopover(); + this.showPopover(); + + // Use timeout to let the popover content to be rendered before displaying it. + this.timeout_(() => { + this.overlay_.setPosition(coordinate); + }); + }); +}; + +exports.Controller_.prototype.setContent_ = function(coordinate) { + const scope = this.$scope_.$new(true); + this.$compile_(this.content_)(scope); + + const mapProjection = this.map.getView().getProjection().getCode(); + this.projections.forEach((proj) => { + const coord = olProj.transform(coordinate, mapProjection, `EPSG:${proj}`); + scope[`coord_${proj}`] = coord; + scope[`coord_${proj}_eastern`] = coord[0]; + scope[`coord_${proj}_northern`] = coord[1]; + }); + + const getRasterSuccess = function(resp) { + olObj.assign(scope, resp); + if (this.callback) { + olObj.assign(scope, this.callback.call(this, coordinate, resp)); + } + }.bind(this); + const getRasterError = function(resp) { + console.error('Error on getting the raster.'); + }; + this.gmfRaster_.getRaster(coordinate, this.gmfContextualdataOptions_.rasterParams).then( + getRasterSuccess, + getRasterError + ); +}; + + +/** + * @private + */ +exports.Controller_.prototype.preparePopover_ = function() { + + const container = document.createElement('DIV'); + container.classList.add('popover'); + container.classList.add('bottom'); + container.classList.add('gmf-contextualdata'); + angular.element(container).css('position', 'relative'); + const arrow = document.createElement('DIV'); + arrow.classList.add('arrow'); + container.appendChild(arrow); + this.content_ = document.createElement('DIV'); + this.content_.setAttribute('gmf-contextualdatacontent', ''); + this.content_.classList.add('popover-content'); + container.appendChild(this.content_); + + this.overlay_ = new olOverlay({ + element: container, + stopEvent: true, + autoPan: true, + autoPanAnimation: /** @type {olx.animation.PanOptions} */ ({ + duration: 250 + }), + positioning: 'top-center' + }); + this.map.addOverlay(this.overlay_); +}; + +exports.Controller_.prototype.showPopover = function() { + const element = /** @type {Object} */ (this.overlay_.getElement()); + angular.element(element).css('display', 'block'); +}; + +exports.Controller_.prototype.hidePopover = function() { + const element = /** @type {Object} */ (this.overlay_.getElement()); + angular.element(element).css('display', 'none'); +}; + +exports.controller('GmfContextualdataController', exports.Controller_); + + +/** + * Provide a directive responsible of formatting the content of the popover for + * the contextual data directive. + * + * Its main purpose is to configure the template to be used. + * Integrators should ensure that the template values match the configuration + * of the contextual data directive. + * + * For each projection the following expressions can be used (replace xxxx by + * the relevant projection code: + * - {{coord_xxxx}}, + * - {{coord_xxxx_eastern}}, + * - {{coord_xxxx_northern}} + * + * Tip: one should use the `ngeoNumberCoordinates` and `ngeoDMSCoordinates`. + * + * The raster service is requested to query additional information. The + * integrators can also use `{{xxxx}}` where `xxxx` will be replaced by + * the name of the raster layers (for example 'srtm'). + * + * See the [../examples/contribs/gmf/contextualdata.html](../examples/contribs/gmf/contextualdata.html) example for a usage sample. + * + * @param {string} gmfContextualdatacontentTemplateUrl Url to template. + * @return {angular.Directive} The Directive Definition Object. + * @ngInject + * @ngdoc directive + * @ngname gmfContextualdatacontent + */ +exports.contentDirective_ = function( + gmfContextualdatacontentTemplateUrl) { + return { + restrict: 'A', + scope: true, + templateUrl: gmfContextualdatacontentTemplateUrl + }; +}; + +exports.directive('gmfContextualdatacontent', exports.contentDirective_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/contextualdata.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/contextualdata.less new file mode 100644 index 000000000..0561c0925 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/contextualdata.less @@ -0,0 +1,15 @@ +@import "~gmf/less/vars.less"; + +.popover.gmf-contextualdata { + width: 40rem; + font-size: @font-size-small; + + table { + width: 100%; + tr { + td { + white-space: nowrap; + } + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/module.js new file mode 100644 index 000000000..d43802acd --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/contextualdata/module.js @@ -0,0 +1,16 @@ +/** + * @module gmf.contextualdata.module + */ +import gmfContextualdataComponent from 'gmf/contextualdata/component.js'; + +import './contextualdata.less'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfContextualdataModule', [ + gmfContextualdataComponent.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractAppController.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractAppController.js new file mode 100644 index 000000000..2ac90880d --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractAppController.js @@ -0,0 +1,798 @@ +/** + * @module gmf.controllers.AbstractAppController + */ +import 'jquery'; +import 'angular'; +import 'angular-gettext'; +import 'angular-dynamic-locale'; +import gmfAuthenticationModule from 'gmf/authentication/module.js'; + +import gmfBackgroundlayerselectorComponent from 'gmf/backgroundlayerselector/component.js'; +import gmfDatasourceModule from 'gmf/datasource/module.js'; +import gmfDisclaimerComponent from 'gmf/disclaimer/component.js'; +import gmfFiltersModule from 'gmf/filters/module.js'; +import gmfLayertreeModule from 'gmf/layertree/module.js'; +import gmfMapModule from 'gmf/map/module.js'; +import gmfQueryExtraModule from 'gmf/query/extraModule.js'; +import gmfSearchModule from 'gmf/search/module.js'; +import gmfThemeModule from 'gmf/theme/module.js'; +import ngeoMessageDisplaywindowComponent from 'ngeo/message/displaywindowComponent.js'; +import ngeoMiscExtraModule from 'ngeo/misc/extraModule.js'; +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoQueryMapQuerent from 'ngeo/query/MapQuerent.js'; +import ngeoQueryMapQueryComponent from 'ngeo/query/mapQueryComponent.js'; +import ngeoStatemanagerModule from 'ngeo/statemanager/module.js'; +import ngeoStatemanagerWfsPermalink from 'ngeo/statemanager/WfsPermalink.js'; +import googAsserts from 'goog/asserts.js'; +import * as olArray from 'ol/array.js'; +import * as olEvents from 'ol/events.js'; +import olMap from 'ol/Map.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; +import gmfThemeManager from 'gmf/theme/Manager.js'; + +/** + * Application abstract controller. + * + * This file includes `goog.require` for base components/directives used + * by the HTML page and the controller to provide the configuration. + * + * @param {gmfx.Config} config A part of the application config. + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @constructor + * @ngdoc controller + * @ngInject + * @export + */ +const exports = function(config, $scope, $injector) { + + /** + * Location service + * @type {ngeo.statemanager.Location} + */ + this.ngeoLocation = $injector.get('ngeoLocation'); + if (this.ngeoLocation.hasParam('debug')) { + // make the injector globally available + window.injector = $injector; + } + + googAsserts.assertInstanceof(this.map, olMap); + + /** + * Ngeo FeatureHelper service + * @type {ngeo.misc.FeatureHelper} + */ + const ngeoFeatureHelper = $injector.get('ngeoFeatureHelper'); + ngeoFeatureHelper.setProjection(googAsserts.assert(this.map.getView().getProjection())); + + /** + * @type {gmf.theme.Manager} + * @export + */ + this.gmfThemeManager = $injector.get('gmfThemeManager'); + + /** + * @type {gmf.layertree.TreeManager} + * @private + */ + this.gmfTreeManager_ = $injector.get('gmfTreeManager'); + + /** + * Themes service + * @type {gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = $injector.get('gmfThemes'); + + /** + * Permalink service + * @type {gmf.permalink.Permalink} + * @private + */ + this.permalink_ = $injector.get('gmfPermalink'); + + /** + * Authentication service + * @type {gmf.authentication.Service} + */ + const gmfAuthentication = $injector.get('gmfAuthenticationService'); + + /** + * @type {boolean} + * @export + */ + this.hasEditableLayers = false; + + /** + * @private + */ + this.updateHasEditableLayers_ = function() { + this.gmfThemes_.hasEditableLayers().then((hasEditableLayers) => { + this.hasEditableLayers = hasEditableLayers; + }); + }; + + /** + * Url to redirect to after login success. + * @type {?string} + */ + this.loginRedirectUrl = null; + + /** + * Information message for the login form. + * @type {?string} + */ + this.loginInfoMessage = null; + + /** + * @type {boolean} + * @export + */ + this.userMustChangeItsPassword = false; + + $scope.$on('authenticationrequired', (event, args) => { + /** @type {angularGettext.Catalog} */ + const gettextCatalog = $injector.get('gettextCatalog'); + this.loginInfoMessage = gettextCatalog.getString( + 'Some layers in this link are not accessible to unauthenticated users. ' + + 'Please log in to see whole data.'); + this.loginRedirectUrl = args.url; + this.loginActive = true; + + const unbind = $scope.$watch(() => this.loginActive, () => { + if (!this.loginActive) { + this.loginInfoMessage = null; + this.loginRedirectUrl = null; + unbind(); + } + }); + }); + + /** + * @param {gmfx.AuthenticationEvent} evt Event. + */ + const userChange = (evt) => { + if (this.loginRedirectUrl) { + window.location = this.loginRedirectUrl; + return; + } + const user = evt.detail.user; + const roleId = (user.username !== null) ? user.role_id : undefined; + + const functionalities = this.gmfUser.functionalities; + + // Enable filter tool in toolbar + if (functionalities && + 'filterable_layers' in functionalities && + functionalities['filterable_layers'].length > 0) { + this.filterSelectorEnabled = true; + } + + // Open filter panel if 'open_panel' is set in functionalities and + // has 'layer_filter' as first value + this.gmfThemes_.getThemesObject().then((themes) => { + if (functionalities && + functionalities.open_panel && + functionalities.open_panel[0] === 'layer_filter') { + this.filterSelectorActive = true; + } + }); + + // Reload theme when login status changes. + const previousThemeName = this.gmfThemeManager.getThemeName(); + this.gmfThemeManager.setThemeName('', true); + + // Reload themes and background layer when login status changes. + this.gmfThemes_.loadThemes(roleId); + + if (evt.type !== 'ready') { + const themeName = this.permalink_.defaultThemeNameFromFunctionalities(); + this.gmfThemeManager.updateCurrentTheme(themeName, previousThemeName, true); + } + this.setDefaultBackground_(null); + this.updateHasEditableLayers_(); + }; + + olEvents.listen(gmfAuthentication, 'ready', userChange); + olEvents.listen(gmfAuthentication, 'login', userChange); + olEvents.listen(gmfAuthentication, 'logout', userChange); + + /** + * @type {Array.} + * @export + */ + this.searchDatasources = [{ + labelKey: 'label', + groupValues: /** @type {Array.} **/ ($injector.get('gmfSearchGroups')), + groupActions: /** @type {Array.} **/ ($injector.get('gmfSearchActions')), + projection: `EPSG:${config.srid || 21781}`, + url: /** @type {string} **/ ($injector.get('fulltextsearchUrl')) + }]; + + /** + * @type {!Object.} + * @export + */ + this.dimensions = {}; + + // watch any change on dimensions object to refresh the url + this.permalink_.setDimensions(this.dimensions); + + // Injecting the gmfDataSourcesManager service creates the data sources + const gmfDataSourcesManager = $injector.get('gmfDataSourcesManager'); + // Init the datasources with our map. + gmfDataSourcesManager.setDatasourceMap(this.map); + // Give the dimensions to the gmfDataSourcesManager + gmfDataSourcesManager.setDimensions(this.dimensions); + + if ($injector.has('gmfDefaultDimensions')) { + // Set defaults + const defaultDimensions = $injector.get('gmfDefaultDimensions'); + for (const dim in defaultDimensions) { + if (this.dimensions[dim] === undefined) { + this.dimensions[dim] = defaultDimensions[dim]; + } + } + } + + /** + * @type {ngeo.map.BackgroundLayerMgr} + * @private + */ + this.backgroundLayerMgr_ = $injector.get('ngeoBackgroundLayerMgr'); + + // watch any change on dimensions object to refresh the background layer + $scope.$watchCollection(() => this.dimensions, () => { + this.backgroundLayerMgr_.updateDimensions(this.map, this.dimensions); + }); + + this.backgroundLayerMgr_.on('change', () => { + this.backgroundLayerMgr_.updateDimensions(this.map, this.dimensions); + }); + + /** + * @type {boolean} + * @export + */ + this.leftNavVisible = false; + + /** + * @type {boolean} + * @export + */ + this.rightNavVisible = false; + + const queryFill = new olStyleFill({color: [255, 170, 0, 0.6]}); + const queryStroke = new olStyleStroke({color: [255, 170, 0, 1], width: 2}); + + /** + * FeatureStyle used by the gmf.query.windowComponent + * @type {ol.style.Style} + * @export + */ + this.queryFeatureStyle = new olStyleStyle({ + fill: queryFill, + image: new olStyleCircle({ + fill: queryFill, + radius: 5, + stroke: queryStroke + }), + stroke: queryStroke + }); + + /** + * @type {boolean} + * @export + */ + this.filterSelectorEnabled = false; + + /** + * @type {boolean} + * @export + */ + this.filterSelectorActive = false; + + /** + * The active state of the ngeo query directive. + * @type {boolean} + * @export + */ + this.queryActive = true; + + /** + * Set the clearing of the ngeoQuery after the deactivation of the query + * @type {boolean} + * @export + */ + this.queryAutoClear = true; + + /** + * @type {boolean} + * @export + */ + this.printPanelActive = false; + + /** + * @type {boolean} + * @export + */ + this.printActive = false; + + /** + * @type {ngeo.query.MapQuerent} + * @private + */ + this.ngeoMapQuerent_ = $injector.get('ngeoMapQuerent'); + + // Don't deactivate ngeoQuery on print activation + $scope.$watch(() => this.printPanelActive, (newVal) => { + // Clear queries if another panel is open but not if user go back to the + // map form the print. + if (!newVal && !this.queryActive) { + this.ngeoMapQuerent_.clear(); + } + this.queryAutoClear = !newVal; + this.printActive = newVal; + }); + + /** + * The active state of the directive responsible of point measurements. + * @type {boolean} + * @export + */ + this.measurePointActive = false; + + /** + * The active state of the directive responsible of length measurements. + * @type {boolean} + * @export + */ + this.measureLengthActive = false; + + /** + * @type {boolean} + * @export + */ + this.drawFeatureActive = false; + + /** + * @type {boolean} + * @export + */ + this.drawProfilePanelActive = false; + + /** + * @type {gmfx.User} + * @export + */ + this.gmfUser = $injector.get('gmfUser'); + $scope.$watch( + () => this.gmfUser.is_password_changed, + (value) => { + this.userMustChangeItsPassword = value === false; + } + ); + + /** + * @type {ngeox.miscGetBrowserLanguage} + */ + this.getBrowserLanguage = $injector.get('ngeoGetBrowserLanguage'); + + /** + * @type {ngeo.statemanager.Service} + */ + this.stateManager = $injector.get('ngeoStateManager'); + + /** + * @type {tmhDynamicLocale} + */ + this.tmhDynamicLocale = $injector.get('tmhDynamicLocale'); + + /** + * @type {angular.Scope} + */ + this.$scope = $scope; + + /** + * @type {string} + * @export + */ + this.lang; + + /** + * Default language + * @type {string} + */ + this.defaultLang = $injector.get('defaultLang'); + + /** + * Languages URL + * @type {!Object.} + */ + this.langUrls = $injector.get('langUrls'); + + /** + * The gettext catalog + * @type {angularGettext.Catalog} + */ + this.gettextCatalog = $injector.get('gettextCatalog'); + + this.initLanguage(); + + const mapTools = 'mapTools'; + + /** + * @type {string} + * @export + */ + this.mapToolsGroup = mapTools; + + /** + * The ngeo feature overlay manager service + * @type {ngeo.map.FeatureOverlayMgr} + */ + const ngeoFeatureOverlayMgr = $injector.get('ngeoFeatureOverlayMgr'); + ngeoFeatureOverlayMgr.init(this.map); + + /** + * The ngeo ToolActivate manager service. + * @type {ngeo.misc.ToolActivateMgr} + */ + const ngeoToolActivateMgr = $injector.get('ngeoToolActivateMgr'); + + const queryToolActivate = new ngeoMiscToolActivate(this, 'queryActive'); + ngeoToolActivateMgr.registerTool(mapTools, queryToolActivate, true); + + const measurePointActivate = new ngeoMiscToolActivate(this, 'measurePointActive'); + ngeoToolActivateMgr.registerTool(mapTools, measurePointActivate, false); + + const measureLengthActivate = new ngeoMiscToolActivate(this, 'measureLengthActive'); + ngeoToolActivateMgr.registerTool(mapTools, measureLengthActivate, false); + + const drawFeatureActivate = new ngeoMiscToolActivate(this, 'drawFeatureActive'); + ngeoToolActivateMgr.registerTool(mapTools, drawFeatureActivate, false); + + const drawProfilePanelActivate = new ngeoMiscToolActivate(this, 'drawProfilePanelActive'); + ngeoToolActivateMgr.registerTool(mapTools, drawProfilePanelActivate, false); + + const printPanelActivate = new ngeoMiscToolActivate(this, 'printPanelActive'); + ngeoToolActivateMgr.registerTool(mapTools, printPanelActivate, false); + + $scope.$root.$on(gmfThemeManager.EventType.THEME_NAME_SET, (event, name) => { + this.gmfThemes_.getThemeObject(name).then((theme) => { + this.setDefaultBackground_(theme); + }); + }); + + /** + * @param {boolean} skipPermalink If True, don't use permalink + * background layer. + * @private + */ + this.updateCurrentBackgroundLayer_ = function(skipPermalink) { + this.gmfThemes_.getBgLayers().then((layers) => { + let background; + if (!skipPermalink) { + // get the background from the permalink + background = this.permalink_.getBackgroundLayer(layers); + } + if (!background) { + // get the background from the user settings + const functionalities = this.gmfUser.functionalities; + if (functionalities) { + const defaultBasemapArray = functionalities.default_basemap; + if (defaultBasemapArray.length > 0) { + const defaultBasemapLabel = defaultBasemapArray[0]; + background = olArray.find(layers, layer => layer.get('label') === defaultBasemapLabel); + } + } + } + if (!background && layers[1]) { + // fallback to the layers list, use the second one because the first + // is the blank layer + background = layers[1]; + } + + if (background) { + this.backgroundLayerMgr_.set(this.map, background); + } + }); + }.bind(this); + + this.updateCurrentBackgroundLayer_(false); + + // Static "not used" functions should be in the window because otherwise + // closure remove them. "export" tag doesn't work on static function below, + // we "export" them as externs in the gmfx options file. + const gmfx = window.gmfx || {}; + /** + * @export + */ + window.gmfx = gmfx; + + /** + * Static function to create a popup with an iframe. + * @param {string} url an url. + * @param {string} title (text). + * @param {number=} opt_width CSS width. + * @param {number=} opt_height CSS height. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + * @export + */ + gmfx.openIframePopup = ( + url, title, opt_width, opt_height, opt_apply + ) => { + this.displaywindowUrl = url; + gmfx.openPopup_(title, opt_width, opt_height, opt_apply); + }; + + /** + * Static function to create a popup with html content. + * @param {string} content (text or html). + * @param {string} title (text). + * @param {number=} opt_width CSS width in pixel. + * @param {number=} opt_height CSS height in pixel. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + * @export + */ + gmfx.openTextPopup = ( + content, title, opt_width, opt_height, opt_apply + ) => { + this.displaywindowContent = content; + gmfx.openPopup_(title, opt_width, opt_height, opt_apply); + }; + + /** + * @param {string} title (text). + * @param {number=} opt_width CSS width in pixel. + * @param {number=} opt_height CSS height in pixel. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + */ + gmfx.openPopup_ = (title, opt_width, opt_height, opt_apply) => { + + this.displaywindowTitle = title; + this.displaywindowOpen = true; + + if (opt_width) { + this.displaywindowWidth = `${opt_width}px`; + } + if (opt_height) { + this.displaywindowHeight = `${opt_height}px`; + } + if (opt_apply !== false) { + this.$scope.$apply(); + } + }; + + /** + * Whether to update the size of the map on browser window resize. + * @type {boolean} + * @export + */ + this.manageResize = false; + + /** + * The duration (milliseconds) of the animation that may occur on the div + * containing the map. Used to smoothly resize the map while the animation + * is in progress. + * @type {number|undefined} + * @export + */ + this.resizeTransition; + + const cgxp = window.cgxp || {}; + /** + * @export + */ + window.cgxp = cgxp; + /** + * @export + */ + cgxp.tools = window.cgxp.tools || {}; + /** + * Static function to create a popup with an iframe. + * @param {string} url an url. + * @param {string} title (text). + * @param {number=} opt_width CSS width in pixel. + * @param {number=} opt_height CSS height in pixel. + * @param {boolean=} opt_apply If true, trigger the Angular digest loop. Default to true. + * @export + */ + cgxp.tools.openInfoWindow = function(url, title, opt_width, opt_height, opt_apply) { + gmfx.openIframePopup(url, title, opt_width, opt_height, opt_apply); + }; + + /** + * @type {?string} + * @export + */ + this.displaywindowContent = null; + + /** + * @type {string} + * @export + */ + this.displaywindowDraggableContainment = '.gmf-map'; + + /** + * @type {?string} + * @export + */ + this.displaywindowHeight = '50vh'; + + /** + * @type {boolean} + * @export + */ + this.displaywindowOpen = false; + + /** + * @type {?string} + * @export + */ + this.displaywindowTitle = null; + + /** + * @type {?string} + * @export + */ + this.displaywindowUrl = null; + + /** + * @type {?string} + * @export + */ + this.displaywindowWidth = '50vw'; +}; + + +/** + * @param {Array.} layers Layers list. + * @param {Array.} labels default_basemap list. + * @return {ol.layer.Base} layer or null + */ +exports.getLayerByLabels = function(layers, labels) { + if (labels && labels.length > 0) { + return olArray.find(layers, layer => layer.get('label') === labels[0]); + } + return null; +}; + + +/** + * @param {string} lang Language code. + * @export + */ +exports.prototype.switchLanguage = function(lang) { + googAsserts.assert(lang in this.langUrls); + this.gettextCatalog.setCurrentLanguage(lang); + this.gettextCatalog.loadRemote(this.langUrls[lang]); + this.tmhDynamicLocale.set(lang); + this.lang = lang; +}; + + +/** + */ +exports.prototype.initLanguage = function() { + this.$scope.$watch(() => this.lang, (newValue) => { + this.stateManager.updateState({ + 'lang': newValue + }); + }); + + const browserLanguage = /** @type {string|undefined} */ + (this.getBrowserLanguage(Object.keys(this.langUrls))); + const urlLanguage = /** @type {string|undefined} */ + (this.stateManager.getInitialValue('lang')); + + if (urlLanguage !== undefined && urlLanguage in this.langUrls) { + this.switchLanguage(urlLanguage); + return; + } else if (browserLanguage !== undefined && browserLanguage in this.langUrls) { + this.switchLanguage(browserLanguage); + return; + } else { + // if there is no information about language preference, + // fallback to default language + + this.switchLanguage(this.defaultLang); + return; + } +}; + + +/** + * @param {gmfThemes.GmfTheme} theme Theme. + * @private + */ +exports.prototype.setDefaultBackground_ = function(theme) { + this.gmfThemes_.getBgLayers().then((layers) => { + let layer; + + // get the background from the permalink + layer = this.permalink_.getBackgroundLayer(layers); + + if (!layer && this.gmfUser.functionalities) { + // get the background from the user settings + layer = exports.getLayerByLabels(layers, this.gmfUser.functionalities.default_basemap); + } + + if (!layer && theme) { + // get the background from the theme + layer = exports.getLayerByLabels(layers, theme.functionalities.default_basemap); + } + + if (!layer) { + // fallback to the layers list, use the second one because the first is the blank layer. + layer = layers[layers.length > 1 ? 1 : 0]; + } + + googAsserts.assert(layer); + this.backgroundLayerMgr_.set(this.map, layer); + }); +}; + + +/** + * @protected + * @return {Element} Span element with font-awesome inside of it + */ +exports.prototype.getLocationIcon = function() { + const arrow = document.createElement('span'); + arrow.className = 'fa fa-location-arrow'; + arrow.style.transform = 'rotate(-0.82rad)'; + const arrowWrapper = document.createElement('span'); + arrowWrapper.appendChild(arrow); + return arrowWrapper; +}; + + +exports.module = angular.module('GmfAbstractAppControllerModule', [ + 'gettext', + 'tmh.dynamicLocale', + gmfAuthenticationModule.name, + gmfBackgroundlayerselectorComponent.name, + gmfDatasourceModule.name, + gmfDisclaimerComponent.name, + gmfFiltersModule.name, + gmfLayertreeModule.name, + gmfMapModule.name, + gmfQueryExtraModule.name, + gmfSearchModule.name, + gmfThemeModule.name, + ngeoMessageDisplaywindowComponent.name, + ngeoMiscExtraModule.name, + ngeoMiscFeatureHelper.module.name, + ngeoQueryMapQuerent.module.name, + ngeoQueryMapQueryComponent.name, + ngeoStatemanagerModule.name, + ngeoStatemanagerWfsPermalink.module.name, +]); + + +exports.module.controller('AbstractController', exports); + + +exports.module.value('ngeoExportFeatureFormats', [ + ngeoMiscFeatureHelper.FormatType.KML, + ngeoMiscFeatureHelper.FormatType.GPX +]); + +exports.module.config(['tmhDynamicLocaleProvider', 'angularLocaleScript', + /** + * @param {tmhDynamicLocaleProvider} tmhDynamicLocaleProvider angular-dynamic-locale provider. + * @param {string} angularLocaleScript the script. + */ + function(tmhDynamicLocaleProvider, angularLocaleScript) { + // configure the script URL + tmhDynamicLocaleProvider.localeLocationPattern(angularLocaleScript); + } +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractDesktopController.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractDesktopController.js new file mode 100644 index 000000000..57a2c4e2e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractDesktopController.js @@ -0,0 +1,258 @@ +/** + * @module gmf.controllers.AbstractDesktopController + */ +import gmfControllersAbstractAppController from 'gmf/controllers/AbstractAppController.js'; +import gmfContextualdataModule from 'gmf/contextualdata/module.js'; +import gmfDrawingModule from 'gmf/drawing/module.js'; +import gmfEditingModule from 'gmf/editing/module.js'; +import gmfPermalinkShareComponent from 'gmf/permalink/shareComponent.js'; +import gmfPrintComponent from 'gmf/print/component.js'; +import gmfProfileModule from 'gmf/profile/module.js'; +import gmfRasterComponent from 'gmf/raster/component.js'; +import ngeoDrawFeatures from 'ngeo/draw/features.js'; +import ngeoMapResizemap from 'ngeo/map/resizemap.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoQueryBboxQueryComponent from 'ngeo/query/bboxQueryComponent.js'; +import gmfImportModule from 'gmf/import/module.js'; +import * as olBase from 'ol/index.js'; +import * as olProj from 'ol/proj.js'; +import * as olObj from 'ol/obj.js'; +import olCollection from 'ol/Collection.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olControlScaleLine from 'ol/control/ScaleLine.js'; +import olControlZoom from 'ol/control/Zoom.js'; +import olControlRotate from 'ol/control/Rotate.js'; +import * as olInteraction from 'ol/interaction.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olSourceVector from 'ol/source/Vector.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; +import olStyleText from 'ol/style/Text.js'; + +/** + * Desktop application abstract controller. + * + * This file includes `goog.require`'s for desktop components/directives used + * by the HTML page and the controller to provide the configuration. + * + * @param {gmfx.Config} config A part of the application config. + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @constructor + * @extends {gmf.controllers.AbstractAppController} + * @ngdoc controller + * @ngInject + * @export + */ +const exports = function(config, $scope, $injector) { + + const viewConfig = { + projection: olProj.get(`EPSG:${config.srid || 21781}`) + }; + olObj.assign(viewConfig, config.mapViewConfig || {}); + + const arrow = gmfControllersAbstractAppController.prototype.getLocationIcon(); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + pixelRatio: config.mapPixelRatio, + layers: [], + view: new olView(viewConfig), + controls: config.mapControls || [ + new olControlScaleLine({ + target: document.getElementById('scaleline') + }), + new olControlZoom({ + zoomInTipLabel: '', + zoomOutTipLabel: '' + }), + new olControlRotate({ + label: arrow, + tipLabel: '' + }) + ], + interactions: config.mapInteractions || olInteraction.defaults({ + pinchRotate: true, + altShiftDragRotate: true + }), + loadTilesWhileAnimating: true, + loadTilesWhileInteracting: true + }); + + /** + * @type {boolean} + * @export + */ + this.loginActive = false; + + /** + * @type {boolean} + * @export + */ + this.toolsActive = false; + + /** + * @type {boolean} + * @export + */ + this.modalShareShown = false; + + /** + * @type {boolean} + * @export + */ + this.editFeatureActive = false; + + /** + * @type {boolean} + * @export + */ + this.routingfeatureActive = false; + + /** + * @type {boolean} + * @export + */ + this.googleStreetViewActive = false; + + /** + * @type {!ol.style.Style} + * @export + */ + this.googleStreetViewStyle = new olStyleStyle({ + text: new olStyleText({ + fill: new olStyleFill({color: '#279B61'}), + font: 'normal 30px FontAwesome', + offsetY: -15, + stroke: new olStyleStroke({color: '#ffffff', width: 3}), + text: '\uf041' + }) + }); + + /** + * @type {boolean} + * @export + */ + this.importDataSourceActive = false; + + const body = $('body'); + + // initialize tooltips + body.tooltip({ + container: 'body', + trigger: 'hover', + selector: '[data-toggle="tooltip"]' + }); + + // deactivate tooltips on touch device + body.on('touchstart.detectTouch', () => { + body.tooltip('destroy'); + body.off('touchstart.detectTouch'); + }); + + /** + * Collection of features for the draw interaction + * @type {ol.Collection.} + */ + const ngeoFeatures = $injector.get('ngeoFeatures'); + + /** + * @type {ngeo.map.FeatureOverlay} + * @export + */ + this.drawFeatureLayer = $injector.get('ngeoFeatureOverlayMgr') + .getFeatureOverlay(); + this.drawFeatureLayer.setFeatures(ngeoFeatures); + + const ngeoFeatureHelper = $injector.get('ngeoFeatureHelper'); + + /** + * @type {ol.layer.Vector} + * @export + */ + this.editFeatureVectorLayer = new olLayerVector({ + source: new olSourceVector({ + wrapX: false, + features: new olCollection() + }), + style: (feature, resolution) => ngeoFeatureHelper.createEditingStyles(feature) + // style: ngeoFeatureHelper.createEditingStyles.bind(ngeoFeatureHelper) + }); + this.editFeatureVectorLayer.setMap(this.map); + + /** + * The ngeo ToolActivate manager service. + * @type {ngeo.misc.ToolActivateMgr} + */ + const ngeoToolActivateMgr = $injector.get('ngeoToolActivateMgr'); + + const editFeatureActivate = new ngeoMiscToolActivate(this, 'editFeatureActive'); + ngeoToolActivateMgr.registerTool('mapTools', editFeatureActivate, false); + + const googleStreetViewActivate = new ngeoMiscToolActivate( + this, + 'googleStreetViewActive' + ); + ngeoToolActivateMgr.registerTool('mapTools', googleStreetViewActivate, false); + + /** + * @type {ngeox.ScaleselectorOptions} + * @export + */ + this.scaleSelectorOptions = { + dropup: true + }; + + /** + * @type {ol.geom.LineString} + * @export + */ + this.profileLine = null; + + gmfControllersAbstractAppController.call(this, config, $scope, $injector); + + // Close the login panel on successful login. + $scope.$watch(() => this.gmfUser.username, (newVal) => { + if (newVal !== null && this.loginActive) { + this.loginActive = false; + } + }); +}; + +olBase.inherits(exports, gmfControllersAbstractAppController); + +exports.module = angular.module('GmfAbstractDesktopControllerModule', [ + gmfControllersAbstractAppController.module.name, + gmfContextualdataModule.name, + gmfDrawingModule.name, + gmfEditingModule.name, + gmfPermalinkShareComponent.name, + gmfPrintComponent.name, + gmfProfileModule.name, + gmfRasterComponent.name, + ngeoDrawFeatures.name, + ngeoMapResizemap.name, + ngeoQueryBboxQueryComponent.name, + gmfImportModule.name, +]); + +exports.module.controller( + 'AbstractDesktopController', + exports); + +exports.module.value('isDesktop', true); + +exports.module.value('ngeoQueryOptions', { + 'limit': 20 +}); + +exports.module.value('ngeoMeasurePrecision', 3); +exports.module.value('ngeoMeasureDecimals', 0); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractMobileController.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractMobileController.js new file mode 100644 index 000000000..6870e9078 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/AbstractMobileController.js @@ -0,0 +1,245 @@ +/** + * @module gmf.controllers.AbstractMobileController + */ +import gmfControllersAbstractAppController from 'gmf/controllers/AbstractAppController.js'; +import gmfMobileMeasureModule from 'gmf/mobile/measure/module.js'; +import gmfMobileNavigationModule from 'gmf/mobile/navigation/module.js'; +import gmfQueryWindowComponent from 'gmf/query/windowComponent.js'; +import ngeoGeolocationMobile from 'ngeo/geolocation/mobile.js'; +import * as olBase from 'ol/index.js'; +import * as olObj from 'ol/obj.js'; +import * as olProj from 'ol/proj.js'; +import olMap from 'ol/Map.js'; +import olView from 'ol/View.js'; +import olControlScaleLine from 'ol/control/ScaleLine.js'; +import olControlZoom from 'ol/control/Zoom.js'; +import olControlRotate from 'ol/control/Rotate.js'; +import * as olInteraction from 'ol/interaction.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + +/** + * Mobile application abstract controller. + * + * This file includes `goog.require`'s mobile components/directives used + * by the HTML page and the controller to provide the configuration. + * + * @param {gmfx.Config} config A part of the application config. + * @param {angular.Scope} $scope Scope. + * @param {angular.$injector} $injector Main injector. + * @constructor + * @extends {gmf.controllers.AbstractAppController} + * @ngdoc controller + * @ngInject + * @export + */ +const exports = function(config, $scope, $injector) { + + /** + * @type {boolean} + * @export + */ + this.leftNavVisible = false; + + /** + * @type {boolean} + * @export + */ + this.rightNavVisible = false; + + /** + * @type {boolean} + * @export + */ + this.searchOverlayVisible = false; + + /** + * @type {ngeox.SearchDirectiveListeners} + * @export + */ + this.searchListeners = /** @type {ngeox.SearchDirectiveListeners} */ ({ + open: function() { + this.searchOverlayVisible = true; + }.bind(this), + close: function() { + this.searchOverlayVisible = false; + }.bind(this) + }); + + const positionFeatureStyle = config.positionFeatureStyle || new olStyleStyle({ + image: new olStyleCircle({ + radius: 6, + fill: new olStyleFill({color: 'rgba(230, 100, 100, 1)'}), + stroke: new olStyleStroke({color: 'rgba(230, 40, 40, 1)', width: 2}) + }) + }); + + const accuracyFeatureStyle = config.accuracyFeatureStyle || new olStyleStyle({ + fill: new olStyleFill({color: 'rgba(100, 100, 230, 0.3)'}), + stroke: new olStyleStroke({color: 'rgba(40, 40, 230, 1)', width: 2}) + }); + + /** + * @type {ngeox.MobileGeolocationDirectiveOptions} + * @export + */ + this.mobileGeolocationOptions = { + positionFeatureStyle: positionFeatureStyle, + accuracyFeatureStyle: accuracyFeatureStyle, + zoom: config.geolocationZoom, + autorotate: config.autorotate + }; + + const viewConfig = { + projection: olProj.get(`EPSG:${config.srid || 21781}`) + }; + olObj.assign(viewConfig, config.mapViewConfig || {}); + + const arrow = gmfControllersAbstractAppController.prototype.getLocationIcon(); + + /** + * @type {ol.Map} + * @export + */ + this.map = new olMap({ + pixelRatio: config.mapPixelRatio, + layers: [], + view: new olView(viewConfig), + controls: config.mapControls || [ + new olControlScaleLine(), + new olControlZoom({ + zoomInTipLabel: '', + zoomOutTipLabel: '' + }), + new olControlRotate({ + label: arrow, + tipLabel: '' + }) + ], + interactions: + config.mapInteractions || + olInteraction.defaults({pinchRotate: true}) + }); + + gmfControllersAbstractAppController.call(this, config, $scope, $injector); + + this.manageResize = true; + this.resizeTransition = 500; + + // Close right nave on successful login. + $scope.$watch(() => this.gmfUser.username, (newVal) => { + if (newVal !== null && this.navIsVisible()) { + this.rightNavVisible = false; + } + }); + + /** + * @const {string} + * @export + */ + this.redirectUrl = $injector.get('redirectUrl'); +}; + +olBase.inherits(exports, gmfControllersAbstractAppController); + + +/** + * @export + */ +exports.prototype.toggleLeftNavVisibility = function() { + this.leftNavVisible = !this.leftNavVisible; +}; + + +/** + * @export + */ +exports.prototype.toggleRightNavVisibility = function() { + this.rightNavVisible = !this.rightNavVisible; +}; + + +/** + * Hide both navigation menus. + * @export + */ +exports.prototype.hideNav = function() { + this.leftNavVisible = this.rightNavVisible = false; +}; + + +/** + * @return {boolean} Return true if one of the navigation menus is visible, + * otherwise false. + * @export + */ +exports.prototype.navIsVisible = function() { + return this.leftNavVisible || this.rightNavVisible; +}; + + +/** + * Hide search overlay. + * @export + */ +exports.prototype.hideSearchOverlay = function() { + this.searchOverlayVisible = false; +}; + + +/** + * @return {boolean} Return true if the left navigation menus is visible, + * otherwise false. + * @export + */ +exports.prototype.leftNavIsVisible = function() { + return this.leftNavVisible; +}; + + +/** + * @return {boolean} Return true if the right navigation menus is visible, + * otherwise false. + * @export + */ +exports.prototype.rightNavIsVisible = function() { + return this.rightNavVisible; +}; + + +/** + * Open the menu with corresponding to the data-target attribute value. + * @param {string} target the data-target value. + * @export + */ +exports.prototype.openNavMenu = function(target) { + const navElements = document.getElementsByClassName('gmf-mobile-nav-button'); + for (let i = 0; i < navElements.length; i++) { + const element = navElements[i]; + if (element.dataset && element.dataset.target === target) { + element.click(); + } + } +}; + + +exports.module = angular.module('GmfAbstractMobileControllerModule', [ + gmfControllersAbstractAppController.module.name, + gmfMobileMeasureModule.name, + gmfMobileNavigationModule.name, + gmfQueryWindowComponent.name, + ngeoGeolocationMobile.name, +]); + +exports.module.controller('AbstractMobileController', exports); + +exports.module.value('isMobile', true); + +exports.module.value('ngeoQueryOptions', { + 'tolerance': 10 +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/desktop-theme.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/desktop-theme.less new file mode 100644 index 000000000..01a3396ea --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/desktop-theme.less @@ -0,0 +1,12 @@ +@map-tools-size: 3rem; +@button-size: 4rem; +@left-panel-width: 32rem; +@right-panel-width: 28rem; +@topbar-height: 4.5rem; +@border-color: darken(@brand-primary, @standard-variation); +@search-width: 8 * @map-tools-size; +@font-size-base: 13px; +@padding-base-vertical: 5px; +@padding-base-horizontal: 10px; +@form-group-margin-bottom: 10px; +@search-results-max-height: calc(~"100vh -" @topbar-height + @map-tools-size + (2 * @app-margin)); diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/desktop.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/desktop.less new file mode 100644 index 000000000..d674bc2e5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/desktop.less @@ -0,0 +1,750 @@ +/** + * Entry point for all styles required for the desktop application. + */ +@import '~gmf/less/vars.less'; +@import '~gmf/less/font.less'; +@import '~gmf/less/base.less'; +@import '~gmf/less/map.less'; +@import '~gmf/less/icons.less'; +@import '~gmf/less/input-range.less'; +@import '~gmf/less/popover.less'; +@import '~gmf/less/datepicker.less'; +@import '~gmf/less/fullscreenpopup.less'; + +@import '~gmf/layertree/desktop.less'; + +html, body { + position: relative; + height: 100%; + li { + list-style: none; + } +} + +body { + padding-top: @topbar-height; +} + +header { + position: fixed; + top: 0; + right: 0; + left: 0; + height: @topbar-height; + z-index: @zindex-navbar-fixed; + .logo { + height: 100%; + line-height: @topbar-height; + margin-left: @app-margin; + img { + height: 100%; + vertical-align: bottom; + } + } +} + +main { + position: relative; + height: 100%; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAAAAABzHgM7AAAAAnRSTlMAAHaTzTgAAAARSURBVHgBY3iKBFEAOp/+MgB+UQnYeBZPWAAAAABJRU5ErkJggg=='); + overflow: hidden; +} + +@footer-height: @input-height-base + 2 * @padding-base-vertical; + +.gmf-app-map-container { + width: auto; + height: 100%; + overflow: hidden; + position: relative; + display: block; + border-top-color: @btn-default-border; + border-top-width: 1px; + border-top-style: solid; + .gmf-map, + .gmf-map > div { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + .gmf-app-footer { + padding: @padding-small-vertical; + position: absolute; + z-index: 2; + bottom: -@footer-height; + // prevent footer to be displayed on 2 lines when screen width is small + max-height: @footer-height; + background-color: fade(@main-bg-color, 90%); + width: 100%; + /* cancel default navbar bottom margin */ + margin-bottom: 0; + /* buttons or inputs in bar are supposed to be '-sm' */ + transition: 0.2s ease-out all; + border: solid @border-color; + border-width: 1px 0 0; + &.gmf-app-active { + bottom: 0; + } + > div { + display: inline-block; + } + + button.gmf-app-map-info { + position: absolute; + /* button is supposed to be .btn-sm */ + bottom: @footer-height - 1; + background-color: fade(@main-bg-color, 80%); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + padding: 0; + left: 50%; + @width: 4rem; + width: @width; + margin-left: -(@width / 2); + border-bottom: 0; + border: solid @border-color; + border-width: 1px 1px 0 1px; + } + } + + [ngeo-scaleselector] .btn > span { + min-width: 8rem; + display: inline-block; + } + + #scaleline { + vertical-align: middle; + .ol-scale-line, .ol-scale-line-inner { + background-color: transparent; + bottom: auto; + position: relative; + } + } + + gmf-mouseposition { + display: inline-block; + } + .gmf-mouseposition-control { + display: inline-block; + min-width: 18rem; + } + gmf-elevationwidget { + display: inline-block; + } + .gmf-elevationwidget-value { + display: inline-block; + min-width: 8rem; + } +} + +gmf-search { + position: absolute; + left: 2 * @app-margin + @map-tools-size; + + .gmf-clear-button { + top: 0; + } + + span.twitter-typeahead { + &::before { + // magnifier + font-size: 1.5rem; + } + + .tt-menu { + border-radius: @border-radius-base; + + .gmf-search-header { + padding: @app-margin; + display: block; + font-size: @font-size-small; + background-color: #eee; + text-transform: uppercase; + color: #666; + } + + .gmf-search-group { + display: none; + } + } + } +} + +.ol-zoom { + left: @app-margin; + top: @app-margin; +} + +.ol-rotate { + right: @app-margin; + top: @app-margin; +} + +.gmf-app-data-panel { + display: block; + float: left; + background-color: @brand-secondary; + width: @left-panel-width; + height: 100%; + display: flex; + flex-flow: column; + + .gmf-app-header { + flex: 0 1 auto; + padding: @app-margin @app-margin 0 @app-margin; + } + + .gmf-app-content { + flex: 1 1 auto; + overflow-y: auto; + position: relative; + margin-top: @app-margin; + margin-bottom: @app-margin; + } + +} + +gmf-themeselector { + width: 1.5 * @left-panel-width; + max-height: 1.5 * @left-panel-width; + overflow: hidden; + overflow-y: auto; +} +gmf-backgroundlayerselector { + width: 25rem; +} +gmf-themeselector, +gmf-backgroundlayerselector { + padding: @half-app-margin !important; +} + +@theme-selector-columns: 2; +.gmf-theme-selector li { + float: left; + width: ~"calc((100% - @{theme-selector-columns} * 2 * @{half-app-margin}) / @{theme-selector-columns})"; +} +.gmf-backgroundlayerselector { + margin-bottom: 0; +} + +.gmf-theme-selector, +.gmf-backgroundlayerselector { + li { + margin: @half-app-margin; + } +} + +.gmf-app-tools { + display: block; + float: right; + background-color: @brand-secondary; + + .gmf-app-tools-content { + width: @right-panel-width; + margin-right: -@right-panel-width; + transition: margin-right 0.2s ease, width 0.001s ease; + float: right; + height: 100%; + overflow: auto; + + & > div { + height: 100%; + & > div { + height: 100%; + } + } + + &.gmf-app-active { + margin-right: 0; + } + + .close { + padding: 0; + line-height: @half-app-margin; + margin-bottom: @app-margin; + } + + textarea { + resize: vertical; + } + + .gmf-app-tools-content-heading { + @color: lighten(@text-color, @standard-variation); + color: @color; + padding-bottom: @app-margin; + margin-bottom: @app-margin; + margin-top: @grid-gutter-width / 2; + border-bottom: 1px solid @color; + } + + &.gmf-app-googlestreetview-active { + width: 43rem; + } + } + + .gmf-app-bar { + background-color: @brand-primary; + border-left: 1px solid @border-color; + + float: right; + height: 100%; + position: relative; + z-index: 2; + + > .btn + .btn { + margin-top: -1px; + } + + .btn { + width: 100%; + border-width: 0; + background-color: @brand-primary; + margin-left: 0; + border-radius: 0 !important; + &:hover { + background-color: lighten(@brand-primary, @standard-variation); + } + } + + .btn-group-vertical { + width: 100%; + .btn { + border: 1px solid @border-color; + border-right-width: 0; + border-left-width: 0; + + &.active, + &:active { + box-shadow: none; + } + &.active { + background-color: @brand-secondary; + border-left: 1px solid @brand-secondary; + margin-left: -1px; + } + } + } + } +} + +.gmf-app-data-panel, +.gmf-app-tools { + height: 100%; + position: relative; +} + + +::-webkit-scrollbar-track { + background: @main-bg-color; +} + +::-webkit-scrollbar { + width: @half-app-margin; +} +::-webkit-scrollbar-thumb { + background: @brand-primary; +} + + +/** + * GMF DrawFeature directive + */ +.gmf-app-map-messages h2 { + display: none; +} + +.gmf-eol { + clear: both; +} + +hr.gmf-drawfeature-separator { + border-color: @color; + margin: 10px 0; +} + +.gmf-drawfeature-featurelist { + margin-top: @app-margin; +} + + +/** + * NGEO DrawFeature directive & map tooltips + */ +.ngeo-drawfeature-actionbuttons { + float: right; + position: relative; +} + +.ol-viewport { + .tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.7; + white-space: nowrap; + } + .ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; + } + .ngeo-tooltip-static { + display: none; + } + .ngeo-tooltip-measure:before, + .ngeo-tooltip-static:before { + border-top: 6px solid rgba(0, 0, 0, 0.5); + border-right: 6px solid transparent; + border-left: 6px solid transparent; + content: ""; + position: absolute; + bottom: -6px; + margin-left: -7px; + left: 50%; + } + .ngeo-tooltip-static:before { + border-top-color: #ffcc33; + } +} + + +/** + * GMF FeatureStyle directive + */ +gmf-featurestyle { + display: block; + margin-top: @app-margin; +} + + +/** + * Color palette within GMF FeatureStyle directive + */ +.ngeo-colorpicker-palette { + border-collapse: separate; + border-spacing: 0px; + + tr { + cursor: default; + } + + td { + position: relative; + padding: 0px; + text-align: center; + vertical-align: middle; + font-size: 1px; + cursor: pointer; + + & > div { + position: relative; + height: 12px; + width: 12px; + border: 1px solid #fff; + box-sizing: content-box; + } + + &:hover { + & > div::after { + display: block; + content: ''; + background: inherit; + position: absolute; + width: 28px; + height: 28px; + top: -10px; + left: -10px; + border: 2px solid #fff; + box-shadow: rgba(0,0,0,0.3) 0 1px 3px 0; + z-index: 11; + } + } + + &.ngeo-colorpicker-selected > div::after { + border: 2px solid #444; + margin: 0; + content: ''; + display: block; + width: 14px; + height: 14px; + position: absolute; + left: -3px; + top: -3px; + box-sizing: content-box; + z-index: 10; + } + } +} + + +/** + * Notifications + */ +.ngeo-notification { + left: 50%; + margin: 0 0 0 -10rem; + position: absolute; + top: 0; + width: 20rem; + z-index: 999; +} + + +/** + * Controls at the bottom of the map + */ +.gmf-app-map-bottom-controls { + .gmf-app-infobar-active & { + bottom: @footer-height; + } + transition: 0.2s ease-out bottom; + position: absolute; + bottom: 0; + z-index: 1; + width: 100%; +} + +/** + * Background layer button (selector) + */ +.gmf-backgroundlayerbutton { + position: absolute; + bottom: @app-margin; + left: @app-margin; + + button { + padding: @padding-small-vertical; + } + + button, + gmf-backgroundlayerselector { + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + } +} + +div.gmf-displayquerywindow { + position: absolute; + right: @app-margin; +} + +/** ngeo-displayquery-window */ +main div.ngeo-displaywindow { + top: @topbar-height + 2 * @app-margin + 2 * @map-tools-size; + left: @nav-width + @app-margin; + right: inherit +} + +/** Disclaimer */ +@bgselector-image-size: 48px; +.gmf-app-map-messages { + position: absolute; + vertical-align: bottom; + left: ~"calc(2 * @{app-margin} + @{bgselector-image-size} + 2 * @{padding-small-vertical})"; +} + + +/** + * GMF EditFeature directive + */ +gmf-editfeature > div { + border-top: 1px solid #333; + margin-top: 1rem; + padding-top: 1rem; +} + + +/** + * GMF ObjectEditingTools directive + */ +gmf-objecteditingtools { + border-bottom: 0.1rem solid #595959; + display: block; + margin: 0 0 1rem 0; + padding: 0 0 1rem 0; +} + + +/** + * GMF FilterSelector component + */ +.gmf-filterselector-separator { + margin: 1.5rem 0 0.5rem 0; + border-color: @color; +} + +.gmf-filterselector-savefilter-desc { + color: #999999; +} + +.gmf-filterselector-savedfilters { + z-index: 1; + + a.dropdown-toggle { + padding: 0.6rem 0; + position: absolute; + right: 0; + } + + ul.dropdown-menu { + right: 0; + top: 3rem; + + a { + overflow: hidden; + max-width: 25rem; + text-overflow: ellipsis; + } + } +} + +.gmf-filterselector-managefilter-modal { + .modal-body { + padding: 0 1.5rem; + + ul { + margin: 0; + + li { + border-bottom: 1px solid #dddddd; + padding: 0.5rem; + + &:last-child { + border-bottom: none; + } + + a { + float: right; + } + + span { + float: left; + max-width: 48rem; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + } + } + } +} + + +/** + * Ngeo Filter component + */ + +.ngeo-filter-condition-button, +.ngeo-filter-condition-button:hover, +.ngeo-filter-condition-button:focus { + text-decoration: none; +} + +.ngeo-filter-condition-criteria-header { + color: #999999; + padding: 0.3rem 2rem; +} + +.ngeo-filter-condition-criteria { + opacity: 0; +} + +.ngeo-filter-condition-criteria-active { + opacity: 1; +} + +.ngeo-filter-rule-custom-rm-btn { + float: right; + margin: 0.4rem 0; +} + +hr.ngeo-filter-separator-rules { + margin: 1rem 0; +} + +hr.ngeo-filter-separator-criteria { + margin: 0.5rem 0; +} + +hr.ngeo-filter-separator-criteria, +hr.ngeo-filter-separator-rules { + border-color: @color; +} + +/** + * Ngeo Rule component + */ +ngeo-rule { + display: block; + margin: 1rem 2.5rem 1rem 0; + + .dropdown > a.btn { + display: block; + text-align: left; + + span.caret { + position: absolute; + right: 1rem; + top: 1.4rem; + } + } + + .dropdown-menu { + padding: 1rem; + } + + .ngeo-rule-operators-list { + margin: 0 0 1rem 0; + } + + .ngeo-rule-btns { + float: right; + } + + .ngeo-rule-type-select label { + width: 13.5rem; + } + + .ngeo-rule-value { + border: 0.1rem solid #aaa; + border-radius: 0 0 0.3rem 0.3rem; + border-top: 0; + color: #999999; + padding: 0.4rem 0.3rem 0.2rem 0.5rem; + margin: -0.2rem 0 0 0; + + a.btn { + color: #999999; + float: right; + } + + a.btn:hover, + a.btn:focus { + color: #666666; + } + + ngeo-date-picker { + display: block; + text-align: right; + } + } + + .ngeo-rule-type-geometry-instructions { + font-size: 9pt; + font-style: italic; + margin: 0.5rem; + } +} + + +/** + * Ngeo Google Street View Component + */ +ngeo-googlestreetview { + display: block; + height: ~"calc(100% - 6rem)"; + width: 40rem; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile-nav.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile-nav.less new file mode 100644 index 000000000..8b421444d --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile-nav.less @@ -0,0 +1,321 @@ +/** + * Styles for mobile navigation menus (side menus). + */ + +@duration: 0.3s; +@nav-bar-height: @map-tools-size + @app-margin; +@nav-back-width: 1.5 * @map-tools-size; +@menu-item-height: @nav-bar-height; +@back-color: darken(@nav-bg, @standard-variation); + +main { + position: fixed; + background-color: @main-bg-color; + box-shadow: 0 0 @app-margin black; + width: 100%; + height: 100%; + z-index: @content-index; + text-align: center; + + transform: translateZ(0); + transition: transform @duration; + will-change: transform; + .gmf-mobile-nav-left-is-visible & { + transform: translateX(@nav-width); + } + .gmf-mobile-nav-right-is-visible & { + transform: translateX(-@nav-width); + } + + &.dragging { + transition: none; + } + + .overlay { + /* shadow layer visible when navigation is active */ + position: absolute; + z-index: @above-search-index; + height: 100vh; + width: 100vw; + top: 0; + left: 0; + cursor: pointer; + background-color: fade(@color, 40%); + visibility: hidden; + opacity: 0; + + .transition(opacity @duration, visibility @duration;); + .backface-visibility(hidden); + + .gmf-mobile-nav-is-visible & { + visibility: visible; + opacity: 1; + } + } +} + +.gmf-search-overlay { + /* shadow layer visible when search is active */ + position: absolute; + z-index: @above-menus-index; + height: 100vh; + width: 100vw; + top: 0; + left: 0; + cursor: pointer; + background-color: white; + visibility: hidden; + opacity: 0; + + .transition(opacity @duration, visibility @duration;); + .backface-visibility(hidden); + + @media (max-width: @screen-xs-max) { + .gmf-search-is-active & { + visibility: visible; + opacity: 1; + } + } +} + +@nav-bar-height: 50px; + +.gmf-mobile-nav-left-is-visible nav.gmf-mobile-nav-right, +.gmf-mobile-nav-right-is-visible nav.gmf-mobile-nav-left { + display: none; +} + +.gmf-mobile-nav-left-is-visible nav.gmf-mobile-nav-left, +.gmf-mobile-nav-right-is-visible nav.gmf-mobile-nav-right { + visibility: visible; +} + +nav.gmf-mobile-nav-left, +nav.gmf-mobile-nav-right { + position: fixed; + top: 0; + width: @nav-width; + height: 100%; + background-color: @nav-bg; + overflow-x: hidden; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + z-index: @below-content-index; + visibility: hidden; + + header { + display: block; + height: @nav-bar-height; + line-height: @nav-bar-height; + background-color: @nav-header-bg; + + .gmf-mobile-nav-go-back { + position: absolute; + left: 0; + z-index: 2; + transition: opacity 1s; + will-change: opacity, visibility; + opacity: 0; + visibility: hidden; + height: @nav-bar-height; + width: @nav-back-width; + padding-left: 24px; + color: @back-color; + + &.gmf-mobile-nav-active { + opacity: 1; + visibility: visible; + } + + &::before, &::after { + transform-origin: 1px 50%; + left: @app-margin; + } + } + + + > nav { + position: absolute; + width: @nav-width; + left: @nav-width; + transform: translateX(0); + transition: transform @duration, opacity @duration; + will-change: transform, opacity; + opacity: 0; + text-align: center; + + + &.gmf-mobile-nav-active { + transform: translateX(-100%); + opacity: 1; + } + &.gmf-mobile-nav-slide-out { + transform: translateX(-120%); + opacity: 0; + } + } + + &.gmf-mobile-nav-back { + > nav { + transform: translate(-120%); + } + > nav.gmf-mobile-nav-active { + transform: translateX(-100%); + } + > nav.gmf-mobile-nav-slide-out { + transform: translateX(0); + } + } + } + + a[data-toggle] { + position: relative; + padding-right: @map-tools-size; + + &::before, &::after { + /* arrow goes on the right side - children navigation */ + right: 0; + transform-origin: 9px 50%; + } + } + + .gmf-mobile-nav-go-back, + a[data-toggle=slide-in] { + &::before, &::after { + /* arrow icon in CSS - for element with nested unordered lists */ + content: ''; + position: absolute; + top: 50%; + margin-top: -1px; + display: inline-block; + height: 2px; + width: @app-margin; + background: @back-color; + .backface-visibility(hidden); + } + + &::before { + transform: rotate(45deg); + } + &::after { + transform: rotate(-45deg); + } + } + + .gmf-mobile-nav-slide { + position: fixed; + height: ~"calc(100% - @{nav-bar-height})"; + width: @nav-width; + transform: translateX(100%); + transition: transform @duration, opacity @duration; + will-change: transform, opacity; + opacity: 0; + overflow-y: auto; + & > * { + padding: @app-margin; + margin: 0; + // make it so tags like "gmf-layertree" are correctly displayed + // (ie. that padding and margin correctly apply) + display: block; + } + + &.gmf-mobile-nav-active { + transform: translateX(0%); + opacity: 1; + } + &.gmf-mobile-nav-slide-out { + transform: translateX(-20%); + opacity: 0; + } + } +} + +// For small devices (in portrait mode) we want the navigation menus to take +// 90% of the viewport width +@media (max-width: @screen-xs-max) { + main { + .gmf-mobile-nav-left-is-visible & { + transform: translateX(90vw); + } + .gmf-mobile-nav-right-is-visible & { + transform: translateX(-90vw); + } + } + nav.gmf-mobile-nav-left, + nav.gmf-mobile-nav-right { + width: 90vw; + .gmf-mobile-nav-slide { + width: 90vw; + } + + header > nav { + width: 90vw; + left: 90vw; + } + } +} + +.gmf-mobile-nav-left { + left: 0; + right: auto; +} + +.gmf-mobile-nav-right { + right: 0; +} + +/** + * Buttons to open right and left navigation menus + */ +.gmf-mobile-nav-trigger { + top: @app-margin; + background-color: @map-tools-bg-color; + color: @map-tools-color; + z-index: @above-search-index; + height: @map-tools-size; + border: 1px solid @border-color; + .fa, .gmf-icon { + font-size: 2rem; + } +} + +.gmf-mobile-nav-left-trigger { + left: @app-margin; + border-right: none; +} + +.gmf-mobile-nav-right-trigger { + right: @app-margin; + border-left: none; +} + +/** + * Buttons for tool buttons (for example measure tools) + */ +.gmf-mobile-nav-button { + display: block; + padding: @app-margin 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + &:hover { + text-decoration: none; + } +} + + +//For tablet only +@media (min-width: @screen-sm-min) { + main button:hover{ + background-color: @onhover-color; + } + + .gmf-mobile-nav-trigger { + margin: 0; + border: solid 1px @border-color; + } + + .gmf-mobile-nav-right-trigger { + left: auto; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile-theme.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile-theme.less new file mode 100644 index 000000000..e69de29bb diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile.less new file mode 100644 index 000000000..4668aa9ad --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/controllers/mobile.less @@ -0,0 +1,177 @@ +/** + * Entry point for all styles required for the mobile application. + */ +@import '~gmf/less/font.less'; +@import '~gmf/less/base.less'; +@import '~gmf/less/map.less'; +@import '~gmf/less/icons.less'; +@import '~gmf/less/input-range.less'; +@import '~gmf/less/fullscreenpopup.less'; +@import '~gmf/less/iphone.less'; +@import '~gmf/controllers/mobile-nav.less'; +@import '~gmf/search/mobile.less'; + +@import '~gmf/layertree/mobile.less'; + +/** + * Mobile specific css only ! + * Please, use shared less files to describe desktop-mobile shared css + */ + +main>* { + position: absolute; +} + +main button { + height: @map-tools-size; + width: @map-tools-size; + padding: 0; + border-radius: @border-radius-base; +} + +gmf-map { + position: static; + > div { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } +} + +.gmf-mobile-measure { + bottom: @app-margin; + right: @app-margin; + a { + display: block; + float: left; + margin-left: @micro-app-margin; + } +} + +gmf-map { + .tooltip { + position: relative; + background: rgba(0, 0, 0, 0.5); + border-radius: @border-radius-base; + color: white; + padding: @half-app-margin @app-margin; + opacity: 0.7; + white-space: nowrap; + } + .ngeo-tooltip-measure { + opacity: 1; + font-weight: bold; + z-index: @content-index; + } + .ngeo-tooltip-static { + background-color: #ffcc33; + color: @color; + border: 1px solid white; + } + .ngeo-tooltip-measure::before, + .ngeo-tooltip-static::before { + border-top: @half-app-margin solid @border-color; + border-right: @half-app-margin solid transparent; + border-left: @half-app-margin solid transparent; + content: ""; + position: absolute; + bottom: -@half-app-margin; + margin-left: -@half-app-margin; + left: 50%; + } + .ngeo-tooltip-static::before { + border-top-color: #ffcc33; + } +} + +.ol-rotate { + top: 4 * @map-tools-size + 2 * @app-margin + 3 * @micro-app-margin; + right: @app-margin; + left: auto; + .ol-rotate-reset { + font-size: 2rem; + border-radius: @border-radius-base; + } +} + +.ol-zoom { + top: @app-margin + @map-tools-size + @app-margin; + right: @app-margin; + left: auto; + .ol-zoom-in, .ol-zoom-out { + font-size: 2rem; + border-radius: @border-radius-base; + } +} + +.ol-rotate, +.ol-zoom { + button { + &:hover { + background-color: @map-tools-bg-color; + } + } +} + +.ol-scale-line { + bottom: @app-margin; + left: @app-margin; +} + +button[ngeo-mobile-geolocation] { + right: @app-margin; + top: 3 * @map-tools-size + 2 * @app-margin + 2 * @micro-app-margin; +} + +.ngeo-notification { + left: 50%; + margin: 0 0 0 -10rem; + position: absolute; + top: 0; + width: 20rem; + z-index: 2; +} + +// Overrides for tablet devices and up +@media (min-width: @screen-sm-min) { + .gmf-mobile-measure { + right: 2 * @app-margin + @map-tools-size; + } + .ol-rotate { + top: @app-margin + @map-tools-size + @micro-app-margin; + } + .ol-zoom { + top: auto; + bottom: @app-margin + @map-tools-size; + } + button[ngeo-mobile-geolocation] { + top: auto; + bottom: @app-margin; + } +} + +/** Disclaimer, and tablet redirect */ +main .gmf-app-map-messages { + text-align: left; + + button { + height: 1.5rem; + width: 1.5rem; + } +} + +/** ngeo-displayquery-window */ +main div.ngeo-displaywindow { + top: @map-tools-size + 2 * @app-margin; + left: @app-margin; + right: initial; +} +gmf-search { + span.twitter-typeahead { + &::before { + font-size: 2rem; + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/DataSourceBeingFiltered.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/DataSourceBeingFiltered.js new file mode 100644 index 000000000..4382391e5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/DataSourceBeingFiltered.js @@ -0,0 +1,17 @@ +/** + * @module gmf.datasource.DataSourceBeingFiltered + */ +const exports = {}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfDataSourceBeingFiltered', []); +// type gmfx.datasource.DataSourceBeingFiltered +exports.module.value('gmfDataSourceBeingFiltered', { + dataSource: null +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/ExternalDataSourcesManager.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/ExternalDataSourcesManager.js new file mode 100644 index 000000000..e99aa02d6 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/ExternalDataSourcesManager.js @@ -0,0 +1,696 @@ +/** + * @module gmf.datasource.ExternalDataSourcesManager + */ +// TODO - MaxScaleDenominator +// TODO - MinScaleDenominator + +import gmfBase from 'gmf/index.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoMapLayerHelper from 'ngeo/map/LayerHelper.js'; +import ngeoMiscFile from 'ngeo/misc/File.js'; +import ngeoDatasourceDataSources from 'ngeo/datasource/DataSources.js'; +import ngeoDatasourceFile from 'ngeo/datasource/File.js'; +import ngeoDatasourceFileGroup from 'ngeo/datasource/FileGroup.js'; +import ngeoDatasourceOGC from 'ngeo/datasource/OGC.js'; +import ngeoDatasourceOGCGroup from 'ngeo/datasource/OGCGroup.js'; +import ngeoDatasourceWMSGroup from 'ngeo/datasource/WMSGroup.js'; +import * as olBase from 'ol/index.js'; +import {isEmpty} from 'ol/extent.js'; +import * as olEvents from 'ol/events.js'; +import olCollection from 'ol/Collection.js'; +import olFormatGPX from 'ol/format/GPX.js'; +import olFormatKML from 'ol/format/KML.js'; + +const exports = class { + + /** + * External data sources come remote online resources, such as WMS/WMTS + * servers, and also files such as KML/GPX. This service is responsible of + * creating, storing and managing them. + * + * @param {!angularGettext.Catalog} gettextCatalog service. + * @param {!angular.$injector} $injector Main injector. + * @param {!angular.$q} $q The Angular $q service. + * @param {!angular.Scope} $rootScope The rootScope provider. + * @param {!ngeo.datasource.DataSources} ngeoDataSources Ngeo data sources service. + * @param {!ngeo.misc.File} ngeoFile Ngeo file. + * @param {!ngeo.map.LayerHelper} ngeoLayerHelper Ngeo layer helper service + * @struct + * @ngInject + * @ngdoc service + * @ngname gmfExternalDataSourcesManager + */ + constructor(gettextCatalog, $injector, $q, $rootScope, ngeoDataSources, + ngeoFile, ngeoLayerHelper) { + + // === Injected properties === + + /** + * @type {!angular.$injector} + * @private + */ + this.injector_ = $injector; + + /** + * @type {!angular.$q} + * @private + */ + this.q_ = $q; + + /** + * @type {!angular.Scope} + * @private + */ + this.rootScope_ = $rootScope; + + /** + * The collection of DataSources from ngeo. When this service creates + * a data source, its gets added to that collection. + * @type {!ngeox.datasource.DataSources} + * @private + */ + this.dataSources_ = ngeoDataSources.collection; + + /** + * @type {!ngeo.misc.File} + * @private + */ + this.ngeoFile_ = ngeoFile; + + /** + * @type {!ngeo.map.LayerHelper} + * @private + */ + this.ngeoLayerHelper_ = ngeoLayerHelper; + + + // === Inner properties === + + /** + * All external data sources that are created are stored here. The key + * is the data source id. + * + * Note: This cache is never cleaned and elements are never removed from it. + * If a data source with an id already exists in this cache, it is used + * instead of being re-created. + * + * @type {Object.} + * @private + */ + this.extDataSources_ = {}; + + /** + * File external data sources, with the key being the file name. + * @type {Object.} + * @private + */ + this.files_ = {}; + + /** + * @type {?ol.Map} + * @private + */ + this.map_ = null; + + /** + * Group that contains file data sources. + * @type {!ngeo.datasource.FileGroup} + * @private + */ + this.fileGroup_ = new ngeoDatasourceFileGroup({ + dataSources: [], + injector: this.injector_, + title: gettextCatalog.getString('Local files') + }); + + /** + * Collection of WMS groups. + * @type {!ol.Collection.} + * @private + */ + this.wmsGroupsCollection_ = new olCollection(); + + /** + * Collection of groups for WMTS data sources. + * @type {!ol.Collection.} + * @private + */ + this.wmtsGroupsCollection_ = new olCollection(); + + /** + * Cache that stores the information of a WMTS data source. The key is the + * data source id. + * @type {!Object.} + * @private + */ + this.wmtsCache_ = {}; + + olEvents.listen(this.dataSources_, 'remove', this.handleDataSourcesRemove_, this); + } + + + // === File Group === + + /** + * @return {!ngeo.datasource.FileGroup} File group. + * @export + */ + get fileGroup() { + return this.fileGroup_; + } + + + // === WMS Groups === + + /** + * @param {!ngeo.datasource.WMSGroup} wmsGroup WMS group. + * @private + */ + addWMSGroup_(wmsGroup) { + this.wmsGroupsCollection.push(wmsGroup); + } + + /** + * @param {!ngeo.datasource.WMSGroup} wmsGroup WMS group. + * @private + */ + removeWMSGroup_(wmsGroup) { + this.wmsGroupsCollection.remove(wmsGroup); + } + + /** + * @param {string} url Online resource url + * @return {?ngeo.datasource.WMSGroup} WMS group. + */ + getWMSGroup(url) { + let found = null; + for (const wmsGroup of this.wmsGroups) { + if (wmsGroup.url === url) { + found = wmsGroup; + break; + } + } + return found; + } + + /** + * @return {!Array.} List of WMS groups. + * @export + */ + get wmsGroups() { + return this.wmsGroupsCollection_.getArray(); + } + + /** + * @return {!ol.Collection.} Collection of WMS + * groups. + * @export + */ + get wmsGroupsCollection() { + return this.wmsGroupsCollection_; + } + + + // === WMTS Groups === + + /** + * @param {!ngeo.datasource.OGCGroup} wmtsGroup Group for WMTS data sources. + * @private + */ + addWMTSGroup_(wmtsGroup) { + this.wmtsGroupsCollection.push(wmtsGroup); + } + + /** + * @param {!ngeo.datasource.OGCGroup} wmtsGroup Group for WMTS data sources. + * @private + */ + removeWMTSGroup_(wmtsGroup) { + this.wmtsGroupsCollection.remove(wmtsGroup); + } + + /** + * @param {string} url Online resource url + * @return {?ngeo.datasource.OGCGroup} WMTS group. + */ + getWMTSGroup(url) { + let found = null; + for (const wmtsGroup of this.wmtsGroups) { + if (wmtsGroup.url === url) { + found = wmtsGroup; + break; + } + } + return found; + } + + /** + * @return {!Array.} List of groups for WMTS data + * sources. + * @export + */ + get wmtsGroups() { + return this.wmtsGroupsCollection_.getArray(); + } + + /** + * @return {!ol.Collection.} Collection of groups + * for WMTS data sources. + * @export + */ + get wmtsGroupsCollection() { + return this.wmtsGroupsCollection_; + } + + + // === Other methods === + + /** + * @param {!ngeo.datasource.DataSource} dataSource Data source + * @return {boolean} Whether the given data source is external or not. To + * be considered external, it needs to be in the external data source + * hash (cache). + */ + isExternalDataSource(dataSource) { + return !!this.extDataSources_[dataSource.id]; + } + + /** + * @return {ol.layer.Group} Layer group where to push layers created by + * this service. + */ + get layerGroup() { + const map = this.map_; + googAsserts.assert(map); + return this.ngeoLayerHelper_.getGroupFromMap( + map, + gmfBase.EXTERNALLAYERGROUP_NAME + ); + } + + /** + * @param {?ol.Map} map Map + */ + set map(map) { + this.map_ = map; + } + + /** + * @param {ol.layer.Layer} layer Layer. + * @private + */ + addLayer_(layer) { + this.layerGroup.getLayers().push(layer); + } + + /** + * @param {ol.layer.Layer} layer Layer. + * @private + */ + removeLayer_(layer) { + this.layerGroup.getLayers().remove(layer); + } + + /** + * @param {!Object} layer WMS Capability Layer object. + * @param {!Object} capabilities WMS Capabilities definition + * @param {string} url The WMS service url. + * @export + */ + createAndAddDataSourceFromWMSCapability(layer, capabilities, url) { + + const id = exports.getId(layer); + const service = capabilities['Service']; + + url = service['OnlineResource'] || url; + + let dataSource; + + // (1) Get data source from cache if it exists, otherwise create it + if (this.extDataSources_[id]) { + dataSource = this.extDataSources_[id]; + } else { + const req = capabilities['Capability']['Request']; + + // ogcImageType + const formats = req['GetMap']['Format']; + const imagePngType = 'image/png'; + const ogcImageType = formats.includes(imagePngType) ? + imagePngType : formats[0]; + + // wmsInfoFormat + const infoFormats = req['GetFeatureInfo']['Format']; + const wmsInfoFormat = infoFormats.includes( + ngeoDatasourceOGC.WMSInfoFormat.GML + ) ? ngeoDatasourceOGC.WMSInfoFormat.GML : undefined; + + // queryable + const queryable = layer['queryable'] === true && + wmsInfoFormat !== undefined; + + // TODO - MaxScaleDenominator + // TODO - MinScaleDenominator + dataSource = new ngeoDatasourceOGC({ + id: id, + name: layer['Title'], + ogcImageType: ogcImageType, + ogcLayers: [{ + name: layer['Name'], + queryable: queryable + }], + ogcType: ngeoDatasourceOGC.Type.WMS, + visible: true, + wmsInfoFormat: wmsInfoFormat, + wmsUrl: url + }); + + // Keep a reference to the external data source in the cache + this.extDataSources_[id] = dataSource; + } + + + // (2) Add data source in WMS group, unless it's already in there. + // Will also add the data source to the `ngeo.DataSources` collection. + // If the group is created, its inner OL layer is also added to the map. + let wmsGroup = this.getWMSGroup(url); + if (wmsGroup) { + if (!wmsGroup.dataSources.includes(dataSource)) { + wmsGroup.addDataSource(dataSource); + this.dataSources_.push(dataSource); + } + } else { + wmsGroup = new ngeoDatasourceWMSGroup({ + dataSources: [dataSource], + injector: this.injector_, + title: service['Title'], + url: url + }, this.ngeoLayerHelper_); + this.addLayer_(wmsGroup.layer); + this.addWMSGroup_(wmsGroup); + this.dataSources_.push(dataSource); + } + } + + /** + * @param {!Object} layer WTMS Capability Layer object. + * @param {!Object} capabilities WMTS Capabilities definition + * @param {string} wmtsUrl The WMTS capabilities url + * @export + */ + createAndAddDataSourceFromWMTSCapability(layer, capabilities, wmtsUrl) { + const id = exports.getId(layer); + + // (1) No need to do anything if there's already a WMTS data source (and its + // layer in the map) + if (this.wmtsCache_[id]) { + return; + } + + let dataSource; + + // (2) Get data source from cache if it exists, otherwise create it + if (this.extDataSources_[id]) { + dataSource = this.extDataSources_[id]; + } else { + + const name = googAsserts.assertString(layer['Title']); + const wmtsLayer = googAsserts.assertString(layer['Identifier']); + + // TODO - MaxScaleDenominator + // TODO - MinScaleDenominator + dataSource = new ngeoDatasourceOGC({ + id: id, + name: name, + ogcType: ngeoDatasourceOGC.Type.WMTS, + visible: true, + wmtsLayer: wmtsLayer, + wmtsUrl: wmtsUrl + }); + + // Keep a reference to the external data source in the cache + this.extDataSources_[id] = dataSource; + } + + // (3) Get/Create group, then add data source to group + let wmtsGroup = this.getWMTSGroup(wmtsUrl); + if (!wmtsGroup) { + wmtsGroup = new ngeoDatasourceOGCGroup({ + dataSources: [], + title: capabilities['ServiceIdentification']['Title'], + url: wmtsUrl + }); + this.addWMTSGroup_(wmtsGroup); + } + wmtsGroup.addDataSource(dataSource); + + // (4) Create and add the OL layer + const layerObj = this.ngeoLayerHelper_.createWMTSLayerFromCapabilititesObj( + capabilities, + layer + ); + this.addLayer_(layerObj); + + // (5) Add data source to ngeo collection + this.dataSources_.push(dataSource); + + // (6) Create and set WMTS cache item + this.wmtsCache_[id] = { + layerObj: layerObj, + // This watcher synchronizes the data source visible property to + // the OL layer object visible property + unregister: this.rootScope_.$watch( + () => dataSource.visible, + this.handleWMTSDataSourceVisibleChange_.bind(this, layerObj) + ) + }; + } + + /** + * @param {!File} file File. + * @param {function(boolean):*?} opt_callback Callback called with true if the file is loaded and added. + * Otherwise with false. + * @export + */ + createAndAddDataSourceFromFile(file, opt_callback) { + this.getFileDataSource_(file).then( + (dataSource) => { + let success = true; + const fileGroup = this.fileGroup_; + + // Look if the extent is valid (and so at least one geometry) + if (isEmpty(dataSource.extent)) { + success = false; + + } else { + // (1) No need to do anything if the file has already been added... + if (fileGroup.dataSources.includes(dataSource)) { + return; + } + + // (2) Okay, we need to add this data source. First, add its layer to the map. + this.addLayer_(dataSource.layer); + + // (3) Add it to the file group + fileGroup.addDataSource(dataSource); + + // (4) Recenter the map view onto its extent if there is at least one geometry (and so a valid extent) + this.map_.getView().fit(dataSource.extent); + + // (5) Finally, add it to the ngeo collection + this.dataSources_.push(dataSource); + } + // Call the callback. + if (opt_callback) { + opt_callback(success); + } + }, + (rejections) => { + console.error(`Failed to load file: ${file.name}`); + if (opt_callback) { + opt_callback(false); + } + } + ); + } + + /** + * Get file data source from cache, else create, store and return a new one. + * @param {!File} file File. + * @return {!angular.$q.Promise} Promise + * @private + */ + getFileDataSource_(file) { + + const defer = this.q_.defer(); + + if (this.files_[file.name]) { + defer.resolve(this.files_[file.name]); + } else { + const ngeoFile = this.ngeoFile_; + ngeoFile.read(file).then((content) => { + let features; + const readOptions = { + featureProjection: this.map_.getView().getProjection() + }; + + if (ngeoFile.isKml(content)) { + features = new olFormatKML({extractStyles: false}).readFeatures(content, readOptions); + } else if (ngeoFile.isGpx(content)) { + features = new olFormatGPX().readFeatures(content, readOptions); + } + + if (features) { + const id = exports.getId(file); + + const dataSource = new ngeoDatasourceFile({ + features: new olCollection(features), + id: id, + name: file.name, + visible: true + }); + + // Keep a reference if both caches + this.files_[file.name] = dataSource; + this.extDataSources_[id] = dataSource; + + defer.resolve(dataSource); + } else { + defer.reject(); + } + }); + } + + return defer.promise; + } + + /** + * @param {!ol.layer.Tile} layer WMTS layer + * @param {boolean|undefined} value Current visible property of the DS + * @param {boolean|undefined} oldValue Old visible property of the DS + * @private + */ + handleWMTSDataSourceVisibleChange_(layer, value, oldValue) { + if (value !== undefined && value !== oldValue) { + layer.setVisible(value); + } + } + + /** + * Called when a data source is removed from the collection of ngeo data + * sources. If it's an external data source, remove it from its WMS Group + * + * @param {ol.Collection.Event} evt Collection event. + * @private + */ + handleDataSourcesRemove_(evt) { + const dataSource = evt.element; + if (this.extDataSources_[dataSource.id] === dataSource) { + if (dataSource instanceof ngeoDatasourceFile) { + this.removeFileDataSource_(dataSource); + } else if (dataSource instanceof ngeoDatasourceOGC) { + this.removeOGCDataSource_(dataSource); + } + } + } + + /** + * Remove a data source from its group. Remove its layer from the map as well. + * + * Note: it is expected that the data source has already been removed + * from the ngeo collection. + * + * @param {!ngeo.datasource.File} dataSource External File data source. + * @private + */ + removeFileDataSource_(dataSource) { + this.removeLayer_(dataSource.layer); + this.fileGroup_.removeDataSource(dataSource); + } + + /** + * Remove the data source from its group. If the group no longer has + * any data source in it, it is removed then destroyed and its layer is + * removed from the map. + * + * Note: it is expected that the data source has already been removed + * from the ngeo collection. + * + * @param {!ngeo.datasource.OGC} dataSource External OGC data source. + * @private + */ + removeOGCDataSource_(dataSource) { + if (dataSource.ogcType === ngeoDatasourceOGC.Type.WMS) { + // WMS data source + const url = dataSource.wmsUrl; + googAsserts.assert(url); + + const wmsGroup = this.getWMSGroup(url); + if (wmsGroup && wmsGroup.dataSources.includes(dataSource)) { + // Remove from group + wmsGroup.removeDataSource(dataSource); + + // In case we removed the last data source from the group, then remove + // and destroy the group, and remove the layer from the map as well. + if (!wmsGroup.dataSources.length) { + this.removeLayer_(wmsGroup.layer); + wmsGroup.destroy(); + this.removeWMSGroup_(wmsGroup); + } + } + } else if (dataSource.ogcType === ngeoDatasourceOGC.Type.WMTS) { + // WMTS data source + const url = dataSource.wmtsUrl; + googAsserts.assert(url); + + const wmtsGroup = this.getWMTSGroup(url); + if (wmtsGroup && wmtsGroup.dataSources.includes(dataSource)) { + // Remove from group + wmtsGroup.removeDataSource(dataSource); + + // Remove the cache item, in addition to removing the layer from the + // map and unregister the watcher + const id = dataSource.id; + this.removeLayer_(this.wmtsCache_[id].layerObj); + this.wmtsCache_[id].unregister(); + delete this.wmtsCache_[id]; + + // In case we removed the last data source from the group, then remove + // and destroy the groug. + if (!wmtsGroup.dataSources.length) { + wmtsGroup.destroy(); + this.removeWMTSGroup_(wmtsGroup); + } + } + } + } +}; + + +/** + * Get the data source id from a WMS or WMTS Capability Layer object, or + * from a File object. + * + * Please, note that this is used to generate a unique id for the created + * external data sources and since a WMS/WMTS Capability Layer objects don't + * natively contains an id by themselves, then it is programmatically generated + * using the `ol.getUid` method, plus a million. + * + * @param {!Object} layer WMS/WMTS Capability Layer object. + * @return {number} Data source id. + * @export + */ +exports.getId = function(layer) { + return olBase.getUid(layer) + 1000000; +}; + + +exports.module = angular.module('gmfExternalDataSourcesManager', [ + ngeoMapLayerHelper.module.name, + ngeoMiscFile.module.name, + ngeoDatasourceDataSources.module.name, +]); +exports.module.service('gmfExternalDataSourcesManager', + exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/Helper.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/Helper.js new file mode 100644 index 000000000..1951c429b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/Helper.js @@ -0,0 +1,145 @@ +/** + * @module gmf.datasource.Helper + */ +import gmfEditingEnumerateAttribute from 'gmf/editing/EnumerateAttribute.js'; +import ngeoDatasourceHelper from 'ngeo/datasource/Helper.js'; +import ngeoFormatAttributeType from 'ngeo/format/AttributeType.js'; +import * as olArray from 'ol/array.js'; + +const exports = class { + + /** + * A service that provides utility methods to manipulate or get GMF data + * sources. + * + * @struct + * @param {angular.$q} $q The Angular $q service. + * @param {gmf.editing.EnumerateAttribute} gmfEnumerateAttribute The Gmf enumerate + * attribute service. + * @param {ngeo.datasource.Helper} ngeoDataSourcesHelper Ngeo data + * source helper service. + * @ngdoc service + * @ngname gmfDataSourcesHelper + * @ngInject + */ + constructor($q, gmfEnumerateAttribute, ngeoDataSourcesHelper) { + + // === Injected properties === + + /** + * @type {angular.$q} + * @private + */ + this.q_ = $q; + + /** + * @type {gmf.editing.EnumerateAttribute} + * @private + */ + this.gmfEnumerateAttribute_ = gmfEnumerateAttribute; + + /** + * @type {ngeo.datasource.Helper} + * @private + */ + this.ngeoDataSourcesHelper_ = ngeoDataSourcesHelper; + + + // === Other properties === + + /** + * @type {gmfx.datasource.DataSources} + * @protected + */ + this.collection_; + + /** + * @type {Object.} + * @protected + */ + this.cache_; + } + + /** + * @return {gmfx.datasource.DataSources} Data sources collection. + * @export + */ + get collection() { + return /** @type {gmfx.datasource.DataSources} */ ( + this.ngeoDataSourcesHelper_.collection + ); + } + + /** + * Return a data source using its id. + * @param {number} id Data source id. + * @return {?gmf.datasource.OGC} Data source. + * @export + */ + getDataSource(id) { + return /** @type {?gmf.datasource.OGC} */ ( + this.ngeoDataSourcesHelper_.getDataSource(id) + ); + } + + /** + * @param {gmf.datasource.OGC} dataSource Filtrable data source. + * @return {angular.$q.Promise} Promise. + * @export + */ + prepareFiltrableDataSource(dataSource) { + + const prepareFiltrableDataSourceDefer = this.q_.defer(); + + // (1) Get the attributes. The first time, they will be asynchronously + // obtained using a WFS DescribeFeatureType request. + this.ngeoDataSourcesHelper_.getDataSourceAttributes( + dataSource + ).then((attributes) => { + // (2) The attribute names that are in the `enumeratedAttributes` + // metadata are the ones that need to have their values fetched. + // Do that once then set the type to SELECT and the choices. + const meta = dataSource.gmfLayer.metadata || {}; + const enumAttributes = meta.enumeratedAttributes; + if (enumAttributes && enumAttributes.length) { + const promises = []; + for (const attribute of attributes) { + if (olArray.includes(enumAttributes, attribute.name) && + attribute.type !== ngeoFormatAttributeType.SELECT && + (!attribute.choices || !attribute.choices.length)) { + promises.push( + this.gmfEnumerateAttribute_.getAttributeValues( + dataSource, attribute.name + ).then((values) => { + const choices = values.map(choice => choice.value); + attribute.type = ngeoFormatAttributeType.SELECT; + attribute.choices = choices; + }) + ); + } + } + return this.q_.all(promises).then( + prepareFiltrableDataSourceDefer.resolve(dataSource) + ); + } else { + prepareFiltrableDataSourceDefer.resolve(dataSource); + } + }); + + return prepareFiltrableDataSourceDefer.promise; + } + +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfDataSourcesHelper', [ + ngeoDatasourceHelper.module.name, + gmfEditingEnumerateAttribute.module.name, +]); +exports.module.service('gmfDataSourcesHelper', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/Manager.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/Manager.js new file mode 100644 index 000000000..ab3e06c41 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/Manager.js @@ -0,0 +1,954 @@ +/** + * @module gmf.datasource.Manager + */ +import gmfDatasourceOGC from 'gmf/datasource/OGC.js'; +import gmfDatasourceWFSAliases from 'gmf/datasource/WFSAliases.js'; +import gmfLayertreeSyncLayertreeMap from 'gmf/layertree/SyncLayertreeMap.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import googAsserts from 'goog/asserts.js'; + +/** @suppress {extraRequire} */ +import ngeoDatasourceDataSources from 'ngeo/datasource/DataSources.js'; + +import ngeoDatasourceOGC from 'ngeo/datasource/OGC.js'; + +/** @suppress {extraRequire} */ +import ngeoFilterRuleHelper from 'ngeo/filter/RuleHelper.js'; + +import ngeoMapBackgroundLayerMgr from 'ngeo/map/BackgroundLayerMgr.js'; +import ngeoMapLayerHelper from 'ngeo/map/LayerHelper.js'; +import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js'; +import * as olBase from 'ol/index.js'; +import * as olEvents from 'ol/events.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import * as olObj from 'ol/obj.js'; +import olLayerImage from 'ol/layer/Image.js'; +import olSourceImageWMS from 'ol/source/ImageWMS.js'; +import olSourceTileWMS from 'ol/source/TileWMS.js'; + +const exports = class { + + /** + * The GeoMapFish DataSources Manager is responsible of listenening to the + * c2cgeoportal's themes to create instances of `ngeo.datasource.DataSource` + * objects with the layer definitions found and push them in the + * `ngeox.datasource.DataSources` collection. The Manager must be initialized + * with the app's map using the setDatasourcseMap() method. + * + * When changing theme, these data sources are cleared then re-created. + * + * @struct + * @param {angular.$q} $q Angular q service + * @param {!angular.Scope} $rootScope Angular rootScope. + * @param {angular.$timeout} $timeout Angular timeout service. + * @param {gmf.theme.Themes} gmfThemes The gmf Themes service. + * @param {gmf.layertree.TreeManager} gmfTreeManager The gmf TreeManager service. + * @param {!ngeo.map.BackgroundLayerMgr} ngeoBackgroundLayerMgr Background layer + * manager. + * @param {ngeo.datasource.DataSources} ngeoDataSources Ngeo data sources service. + * data sources service. + * @param {!ngeo.map.LayerHelper} ngeoLayerHelper Ngeo Layer Helper. + * @param {!ngeo.filter.RuleHelper} ngeoRuleHelper Ngeo rule helper service. + * @param {!ngeo.misc.WMSTime} ngeoWMSTime wms time service. + * @param {!gmf.datasource.WFSAliases} gmfWFSAliases Gmf WFS aliases service. + * @ngInject + * @ngdoc service + * @ngname gmfDataSourcesManager + */ + constructor($q, $rootScope, $timeout, gmfThemes, gmfTreeManager, + ngeoBackgroundLayerMgr, ngeoDataSources, ngeoLayerHelper, ngeoRuleHelper, + ngeoWMSTime, gmfWFSAliases + ) { + + // === Injected properties === + + /** + * @type {angular.$q} + * @private + */ + this.q_ = $q; + + /** + * @type {!angular.Scope} + * @private + */ + this.rootScope_ = $rootScope; + + /** + * @type {angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + /** + * @type {gmf.layertree.TreeManager} + * @private + */ + this.gmfTreeManager_ = gmfTreeManager; + + /** + * @type {!ngeo.map.BackgroundLayerMgr} + * @private + */ + this.ngeoBackgroundLayerMgr_ = ngeoBackgroundLayerMgr; + + /** + * @type {ngeo.datasource.DataSources} + * @private + */ + this.ngeoDataSources_ = ngeoDataSources; + + /** + * The collection of DataSources from ngeo, which gets updated by this + * service. When the theme changes, first we remove all data sources, then + * the 'active' data source are added here. + * @type {ngeox.datasource.DataSources} + * @private + */ + this.dataSources_ = ngeoDataSources.collection; + + /** + * @type {!ngeo.map.LayerHelper} + * @private + */ + this.ngeoLayerHelper_ = ngeoLayerHelper; + + /** + * @type {!ngeo.filter.RuleHelper} + * @private + */ + this.ngeoRuleHelper_ = ngeoRuleHelper; + + /** + * @type {!ngeo.misc.WMSTime} + * @private + */ + this.ngeoWMSTime_ = ngeoWMSTime; + + /** + * @type {!gmf.datasource.WFSAliases} + * @private + */ + this.gmfWFSAliases_ = gmfWFSAliases; + + + // === Inner properties === + + /** + * While loading a new theme, this is where all of the created data sources + * are put using the id as key for easier find in the future. + * @type {Object.} + * @private + */ + this.dataSourcesCache_ = {}; + + /** + * A reference to the dimensions object. + * @type {ngeox.Dimensions|undefined} + * @private + */ + this.dimensions_; + + /** + * The function to call to unregister the `watch` event on the dimensions + * object properties. + * @type {?Function} + * @private + */ + this.dimensionsWatcherUnregister = null; + + /** + * The cache of layertree leaf controller, i.e. those that are added to + * the tree manager. When treeCtrl is added in this cache, it's given + * a reference to its according data source. + * @type {gmfx.datasource.ManagerTreeCtrlCache} + * @private + */ + this.treeCtrlCache_ = {}; + + /** + * The function to call to unregister the `watchCollection` event on + * the root layer tree controller children. + * @type {?Function} + * @private + */ + this.treeCtrlsUnregister_ = null; + + // === Events === + + olEvents.listen( + this.ngeoBackgroundLayerMgr_, + 'change', + this.handleNgeoBackgroundLayerChange_, + this + ); + olEvents.listen(this.gmfThemes_, 'change', this.handleThemesChange_, this); + } + + + /** + * Set the map to use with your datasources. + * @param {!ol.Map} map The map to use. + * @export + */ + setDatasourceMap(map) { + this.ngeoDataSources_.map = map; + } + + /** + * @param {!ngeox.Dimensions} dimensions A reference to the dimensions + * object to keep a reference of in this service. + */ + setDimensions(dimensions) { + if (this.dimensionsWatcherUnregister) { + this.dimensionsWatcherUnregister(); + } + + this.dimensions_ = dimensions; + + this.dimensionsWatcherUnregister = this.rootScope_.$watch( + () => this.dimensions_, + this.handleDimensionsChange_.bind(this), + true + ); + this.handleDimensionsChange_(); + } + + /** + * Called when the dimensions change. Update all affected layer's filters. + * @private + */ + handleDimensionsChange_() { + + // Create a layer list to update each one only once + const layers = []; + const layerIds = []; + + const dataSources = this.dataSources_.getArray(); + for (const dataSource of dataSources) { + if (dataSource.dimensionsFiltersConfig) { + for (const key in dataSource.dimensionsFiltersConfig) { + if (dataSource.dimensionsFiltersConfig[key].value === null) { + const layer = this.getDataSourceLayer_(dataSource); + if (layer == undefined) { + return; + } + const id = olBase.getUid(layer); + if (layerIds.indexOf(id) == -1) { + layers.push(layer); + layerIds.push(id); + } + } + } + } + } + + layers.forEach(this.updateLayerFilter_.bind(this)); + } + + /** + * Called when the themes change. Remove any existing data sources first, + * then create and add data sources from the loaded themes. + * @private + */ + handleThemesChange_() { + // (1) Clear + this.clearDataSources_(); + if (this.treeCtrlsUnregister_) { + this.treeCtrlsUnregister_(); + } + this.clearTreeCtrlCache_(); + + // (2) Re-create data sources and event listeners + this.gmfThemes_.getOgcServersObject().then((ogcServers) => { + const promiseThemes = this.gmfThemes_.getThemesObject().then((themes) => { + // Create a DataSources for each theme + for (const theme of themes) { + for (const child of theme.children) { + googAsserts.assert(child); + this.createDataSource_(child, child, ogcServers); + } + } + }); + + const promiseBgLayers = this.gmfThemes_.getBackgroundLayersObject().then( + (backgroundLayers) => { + // Create a DataSource for each background layer + for (const backgroundLayer of backgroundLayers) { + this.createDataSource_(null, backgroundLayer, ogcServers); + } + } + ); + + // Then add the data sources that are active in the ngeo collection + this.q_.all([promiseThemes, promiseBgLayers]).then(() => { + this.treeCtrlsUnregister_ = this.rootScope_.$watchCollection( + () => { + if (this.gmfTreeManager_.rootCtrl) { + return this.gmfTreeManager_.rootCtrl.children; + } + }, + this.handleTreeManagerRootChildrenChange_.bind(this) + ); + }); + }); + } + + /** + * Called when the list of tree controllers within the tree manager + * root controller changes. In other words, this method is called + * after nodes are being added added or removed from the tree, + * i.e. from the child nodes collection. + * + * A timeout is required because the collection event is fired before + * the leaf nodes are created and they are the ones we're looking for here. + * + * This method handles the registration/unregistration of tree nodes that + * are added or removed, pushing it to the cache or removing it from the + * cache. + * + * @param {Array.|undefined} value List of tree + * controllers. + * @private + */ + handleTreeManagerRootChildrenChange_(value) { + + this.timeout_(() => { + + // (1) No need to do anything if the value is not set + if (!value) { + return; + } + + // (2) Collect 'leaf' treeCtrls + const newTreeCtrls = []; + const visitor = (treeCtrls, treeCtrl) => { + const node = /** @type {!gmfThemes.GmfGroup|!gmfThemes.GmfLayer} */ ( + treeCtrl.node); + const children = node.children; + if (!children) { + treeCtrls.push(treeCtrl); + } + }; + for (let i = 0, ii = value.length; i < ii; i++) { + value[i].traverseDepthFirst(visitor.bind(this, newTreeCtrls)); + } + + // (3) Add new 'treeCtrls' + for (let i = 0, ii = newTreeCtrls.length; i < ii; i++) { + const newTreeCtrl = newTreeCtrls[i]; + const cacheItem = this.getTreeCtrlCacheItem_(newTreeCtrl); + if (!cacheItem) { + this.addTreeCtrlToCache_(newTreeCtrl); + } + } + + // (4) Remove treeCtrls that are no longer in the newTreeCtrl + const cache = this.treeCtrlCache_; + for (const id in this.treeCtrlCache_) { + const item = cache[id]; + if (!newTreeCtrls.includes(item.treeCtrl)) { + this.removeTreeCtrlCacheItem_(item); + } + } + }); + } + + /** + * Remove the data sources from the ngeo collection that are in the cache, + * i.e. those created by this service, then clear the cache. + * @private + */ + clearDataSources_() { + + // (1) Remove data sources from ngeo collection + const dataSources = this.dataSources_.getArray(); + for (let i = dataSources.length - 1, ii = 0; i >= ii; i--) { + if (this.dataSourcesCache_[dataSources[i].id]) { + // Use the `remove` method of the `ol.Collection` object for it + // to update its length accordingly and trigger the REMOVE event as + // well. + this.dataSources_.remove(dataSources[i]); + } + } + + // (2) Clear the cache + olObj.clear(this.dataSourcesCache_); + } + + /** + * Create a data source using the information on the node, group node + * and OGC servers. If the node has children, then we loop in those to get + * leaf nodes. Only leaf nodes end up creating a data source. If a data + * source with the same id already exists, then the node is skipped. + * + * Once a data source is created, it is added to the data sources cache. + * + * @param {gmfThemes.GmfGroup} firstLevelGroup The first level group node. + * @param {!gmfThemes.GmfGroup|!gmfThemes.GmfLayer} node The node, which + * may have children or not. + * @param {!gmfThemes.GmfOgcServers} ogcServers OGC servers. + * @private + */ + createDataSource_(firstLevelGroup, node, ogcServers) { + + const children = node.children; + + // (1) Group node (node that has children). Loop in the children + // individually and create a data source for each one of them. The + // group node itself is **skipped**. + if (children) { + for (const child of children) { + googAsserts.assert(child); + this.createDataSource_(firstLevelGroup, child, ogcServers); + } + return; + } + + // From there on, the node is a layer node. + const gmfLayer = /** @type gmfThemes.GmfLayer */ (node); + + // (2) Skip layer node if a data source with the same id exists + const id = olBase.getUid(gmfLayer); + if (this.dataSourcesCache_[id]) { + return; + } + + // From there on, a data source will be created + const meta = gmfLayer.metadata; + const ogcType = gmfLayer.type; + let maxResolution; + let minResolution; + let ogcLayers; + let ogcServer; + let wmtsLayer; + let wmtsUrl; + let ogcImageType; + let timeProperty; + + if (ogcType === gmfThemeThemes.NodeType.WMTS) { + // (3) Manage WMTS + const gmfLayerWMTS = /** @type {gmfThemes.GmfLayerWMTS} */ (gmfLayer); + + // Common options for WMTS + wmtsLayer = gmfLayerWMTS.layer; + wmtsUrl = gmfLayerWMTS.url; + maxResolution = meta.maxResolution; + minResolution = meta.minResolution; + + // OGC Layers + const layers = meta.queryLayers || meta.wmsLayers; + if (layers) { + ogcLayers = layers.split(',').map((layer) => { + return { + maxResolution: maxResolution, + minResolution: minResolution, + name: layer, + queryable: true + }; + }); + } + + // OGC Server + if (meta.ogcServer && ogcServers[meta.ogcServer]) { + ogcServer = ogcServers[meta.ogcServer]; + } + ogcImageType = gmfLayerWMTS.imageType; + } else if (ogcType === gmfThemeThemes.NodeType.WMS) { + // (4) Manage WMS + const gmfLayerWMS = /** @type {gmfThemes.GmfLayerWMS} */ (gmfLayer); + + // Common options for WMS + maxResolution = gmfLayerWMS.maxResolutionHint; + minResolution = gmfLayerWMS.minResolutionHint; + + // OGC Layers + ogcLayers = gmfLayerWMS.childLayers.map((childLayer) => { + return { + maxResolution: childLayer.maxResolutionHint, + minResolution: childLayer.minResolutionHint, + name: childLayer.name, + queryable: childLayer.queryable + }; + }); + + // OGC Server + const ogcServerName = (!firstLevelGroup || firstLevelGroup.mixed) ? + gmfLayerWMS.ogcServer : firstLevelGroup.ogcServer; + googAsserts.assert(ogcServerName); + ogcServer = ogcServers[ogcServerName]; + ogcImageType = ogcServer.imageType; + + // Time property + if (gmfLayerWMS.time) { + timeProperty = gmfLayerWMS.time; + } else if (firstLevelGroup && firstLevelGroup.time) { + timeProperty = firstLevelGroup.time; + } + } + + // (5) ogcServer + const ogcServerType = ogcServer ? ogcServer.type : undefined; + const wmsIsSingleTile = ogcServer ? ogcServer.isSingleTile : undefined; + const wfsUrl = ogcServer && ogcServer.wfsSupport ? + ogcServer.urlWfs : undefined; + const wmsUrl = ogcServer ? ogcServer.url : undefined; + + let wfsOutputFormat = ngeoDatasourceOGC.WFSOutputFormat.GML3; + // qgis server only supports GML2 output + if (ogcServerType === ngeoDatasourceOGC.ServerType.QGISSERVER) { + wfsOutputFormat = ngeoDatasourceOGC.WFSOutputFormat.GML2; + } + + // (6) Snapping + const snappable = !!meta.snappingConfig; + const snappingTolerance = meta.snappingConfig ? + meta.snappingConfig.tolerance : undefined; + const snappingToEdges = meta.snappingConfig ? + meta.snappingConfig.edge : undefined; + const snappingToVertice = meta.snappingConfig ? + meta.snappingConfig.vertex : undefined; + + // (7) Dimensions + const dimensions = this.dimensions_; + const dimensionsConfig = node.dimensions || firstLevelGroup.dimensions; + const dimensionsFiltersConfig = node.dimensionsFilters; + + // (8) Time values (lower or lower/upper) + let timeLowerValue; + let timeUpperValue; + if (timeProperty) { + const timeValues = this.ngeoWMSTime_.getOptions(timeProperty)['values']; + if (Array.isArray(timeValues)) { + timeLowerValue = timeValues[0]; + timeUpperValue = timeValues[1]; + } else { + timeLowerValue = timeValues; + } + } + + // (9) Common options + const copyable = meta.copyable; + const identifierAttribute = meta.identifierAttributeField; + const name = gmfLayer.name; + const timeAttributeName = meta.timeAttribute; + const visible = meta.isChecked === true; + + // Create the data source and add it to the cache + this.dataSourcesCache_[id] = new gmfDatasourceOGC({ + copyable, + dimensions, + dimensionsConfig, + dimensionsFiltersConfig, + gmfLayer, + id, + identifierAttribute, + maxResolution, + minResolution, + name, + ogcImageType, + ogcLayers, + ogcServerType, + ogcType, + snappable, + snappingTolerance, + snappingToEdges, + snappingToVertice, + timeAttributeName, + timeLowerValue, + timeProperty, + timeUpperValue, + visible, + wfsOutputFormat, + wfsUrl, + wmsIsSingleTile, + wmsUrl, + wmtsLayer, + wmtsUrl + }); + } + + /** + * If the given Layertree controller is a 'leaf', add it to the cache. + * Also, set its according data source. Finally, add the data source to + * the ngeo collection. + * + * @param {ngeo.layertree.Controller} treeCtrl Layertree controller to add + * @private + */ + addTreeCtrlToCache_(treeCtrl) { + + const id = olBase.getUid(treeCtrl.node); + const dataSource = this.dataSourcesCache_[id]; + googAsserts.assert(dataSource, 'DataSource should be set'); + treeCtrl.setDataSource(dataSource); + + const stateWatcherUnregister = this.rootScope_.$watch( + () => treeCtrl.getState(), + this.handleTreeCtrlStateChange_.bind(this, treeCtrl) + ); + + const filterRulesWatcherUnregister = this.rootScope_.$watch( + () => { + const hasFilters = dataSource.filterRules !== null; + const isVisible = dataSource.visible; + return hasFilters && isVisible; + }, + this.handleDataSourceFilterRulesChange_.bind(this, dataSource) + ); + + // Watch for time values change to update the WMS layer + let timeLowerValueWatcherUnregister; + let timeUpperValueWatcherUnregister; + let wmsLayer; + if (dataSource.timeProperty && + dataSource.ogcType === ngeoDatasourceOGC.Type.WMS + ) { + timeLowerValueWatcherUnregister = this.rootScope_.$watch( + () => dataSource.timeLowerValue, + this.handleDataSourceTimeValueChange_.bind(this, dataSource) + ); + + if (dataSource.timeProperty.mode === 'range') { + timeUpperValueWatcherUnregister = this.rootScope_.$watch( + () => dataSource.timeUpperValue, + this.handleDataSourceTimeValueChange_.bind(this, dataSource) + ); + } + + wmsLayer = googAsserts.assertInstanceof( + gmfLayertreeSyncLayertreeMap.getLayer(treeCtrl), + olLayerImage + ); + } + + this.treeCtrlCache_[id] = { + filterRulesWatcherUnregister, + stateWatcherUnregister, + timeLowerValueWatcherUnregister, + timeUpperValueWatcherUnregister, + treeCtrl, + wmsLayer + }; + + this.dataSources_.push(dataSource); + + this.gmfWFSAliases_.describe(dataSource); + } + + /** + * Remove a treeCtrl cache item. Unregister event listeners and remove the + * data source from the ngeo collection. + * + * @param {gmfx.datasource.ManagerTreeCtrlCacheItem} item Layertree + * controller cache item + * @private + */ + removeTreeCtrlCacheItem_(item) { + + // (1) Remove data source + const dataSource = item.treeCtrl.getDataSource(); + googAsserts.assert(dataSource, 'DataSource should be set'); + this.dataSources_.remove(dataSource); + + // (2) Remove item and clear event listeners + item.treeCtrl.setDataSource(null); + item.filterRulesWatcherUnregister(); + item.stateWatcherUnregister(); + if (item.timeLowerValueWatcherUnregister) { + item.timeLowerValueWatcherUnregister(); + } + if (item.timeUpperValueWatcherUnregister) { + item.timeUpperValueWatcherUnregister(); + } + delete this.treeCtrlCache_[olBase.getUid(item.treeCtrl.node)]; + } + + /** + * Clears the layer tree controller cache. At the same time, each item gets + * its data source reference unset and state watcher unregistered. + * + * The data source gets also removed from the ngeo data sources collection. + * @private + */ + clearTreeCtrlCache_() { + for (const id in this.treeCtrlCache_) { + this.removeTreeCtrlCacheItem_(this.treeCtrlCache_[id]); + } + } + + /** + * Called when the state of a 'leaf' layertree controller changes. + * Update the `visible` property of the data source according to the + * state of the layertree controller. + * + * Note: The possible states can only be 'on' or 'off', because the + * layertree controller being a 'leaf'. + * + * @param {ngeo.layertree.Controller} treeCtrl The layer tree controller + * @param {string|undefined} newVal New state value + * @private + */ + handleTreeCtrlStateChange_(treeCtrl, newVal) { + const treeDataSource = treeCtrl.getDataSource(); + googAsserts.assert(treeDataSource, 'DataSource should be set'); + const visible = newVal === 'on'; + treeDataSource.visible = visible; + + // In GMF, multiple data sources can be combined into one ol.layer.Layer + // object. When changing the state of a data source, we need to make + // sure that the FILTER param match order of the current LAYERS param. + const layer = this.getDataSourceLayer_(treeDataSource); + if (layer == undefined) { + return; + } + this.updateLayerFilter_(layer); + } + + /** + * Returns a layertree controller cache item, if it exists. + * + * @param {ngeo.layertree.Controller} treeCtrl The layer tree controller + * @return {gmfx.datasource.ManagerTreeCtrlCacheItem} Cache item + * @private + */ + getTreeCtrlCacheItem_(treeCtrl) { + return this.treeCtrlCache_[olBase.getUid(treeCtrl.node)] || null; + } + + /** + * Return the layer corresponding to the data source. + * @param {!ngeo.DataSource} dataSource The data source. + * @return {ol.layer.Base|undefined} The layer. + * @private + */ + getDataSourceLayer_(dataSource) { + dataSource = /** @type {!gmf.DataSource} */ (dataSource); + if (dataSource.gmfLayer == undefined) { + return; + } + const id = olBase.getUid(dataSource.gmfLayer); + if (id == undefined) { + return; + } + const item = this.treeCtrlCache_[id]; + if (item == undefined) { + return; + } + const treeCtrl = item.treeCtrl; + return gmfLayertreeSyncLayertreeMap.getLayer(treeCtrl); + } + + /** + * Update layer filter parameter according to data sources filter rules + * and dimensions filters. + * @param {ol.layer.Base} layer The layer to update. + * @private + */ + updateLayerFilter_(layer) { + googAsserts.assert( + layer instanceof olLayerImage || + layer instanceof olLayerTile + ); + + const source = layer.getSource(); + if (!(source instanceof olSourceImageWMS || + source instanceof olSourceTileWMS)) { + return; + } + + const params = source.getParams(); + const layersParam = params['LAYERS']; + const layersList = layersParam.split(','); + googAsserts.assert(layersList.length >= 1); + + const filterParam = 'FILTER'; + const filterParamValues = []; + let hasFilter = false; + for (const wmsLayerName of layersList) { + let filterParamValue = '()'; + + const dataSources = this.dataSources_.getArray(); + for (const dataSource of dataSources) { + const dsLayer = this.getDataSourceLayer_(dataSource); + if (dsLayer == undefined) { + continue; + } + if (olBase.getUid(dsLayer) == olBase.getUid(layer) && + layer.get('querySourceIds').indexOf(dataSource.id) >= 0 && + dataSource.gmfLayer.layers.split(',').indexOf(wmsLayerName) >= 0) { + + const id = olBase.getUid(dataSource.gmfLayer); + const item = this.treeCtrlCache_[id]; + googAsserts.assert(item); + const treeCtrl = item.treeCtrl; + const projCode = treeCtrl.map.getView().getProjection().getCode(); + + const filterString = dataSource.visible ? + this.ngeoRuleHelper_.createFilterString({ + dataSource: dataSource, + projCode: projCode, + incDimensions: true + }) : + null; + if (filterString) { + filterParamValue = `(${filterString})`; + hasFilter = true; + } + } + } + + filterParamValues.push(filterParamValue); + } + + source.updateParams({ + [filterParam]: hasFilter ? filterParamValues.join('') : null + }); + } + + /** + * Called when both the 'visible' and 'filterRules' properties of a data + * source change. + * + * If the data source is filtrable, then make sure that when it gets rules + * set to apply them as OGC filters to the OpenLayers layer, more precisely + * as a `FILTER` parameter in the layer's source parameters. + * + * @param {!gmf.datasource.OGC} dataSource Data source. + * @private + */ + handleDataSourceFilterRulesChange_(dataSource) { + + // Skip data sources that are not filtrables OR those that do not have + // the WMS ogcType, i.e. those that do not have an OpenLayers layer + // to update + if (dataSource.filtrable !== true || + dataSource.ogcType !== ngeoDatasourceOGC.Type.WMS + ) { + return; + } + + const layer = this.getDataSourceLayer_(dataSource); + if (layer === undefined) { + return; + } + this.updateLayerFilter_(layer); + } + + /** + * Called when either the `timeLowerValue` or `timeUpperValue` property of a + * data source changes. + * + * Get the range value from the data source, then update the WMS layer + * thereafter. + * + * @param {!gmf.datasource.OGC} dataSource Data source. + * @private + */ + handleDataSourceTimeValueChange_(dataSource) { + + const id = olBase.getUid(dataSource.gmfLayer); + const item = this.treeCtrlCache_[id]; + googAsserts.assert(item); + const wmsLayer = googAsserts.assert(item.wmsLayer); + const wmsSource = googAsserts.assertInstanceof( + wmsLayer.getSource(), + olSourceImageWMS + ); + + const timeProperty = googAsserts.assert(dataSource.timeProperty); + let timeParam; + const range = dataSource.timeRangeValue; + if (range) { + timeParam = this.ngeoWMSTime_.formatWMSTimeParam(timeProperty, range); + } + + // No need to update the TIME param if already the same value; + const params = wmsSource.getParams(); + const currentTimeParam = params['TIME']; + if (currentTimeParam === timeParam) { + return; + } + + // The `timeParam` can be undefined, which means that the TIME property + // gets reset. + this.ngeoLayerHelper_.updateWMSLayerState( + wmsLayer, + wmsSource.getParams()['LAYERS'], + timeParam + ); + } + + /** + * Called when the background layer changes. Add/Remove the according data + * sources to/from the ngeo data sources collection. Update the data source + * `visible` property as well. + * + * The `querySourceIds` property in the layer is used to determine the + * data sources that are bound to the layer. + * + * @param {!ngeox.BackgroundEvent} evt Event. + * @private + */ + handleNgeoBackgroundLayerChange_(evt) { + + const previousBackgroundLayer = evt.detail.previous; + const currentBackgroundLayer = evt.detail.current; + const cache = this.dataSourcesCache_; + + // Remove data sources linked to previous background layer + if (previousBackgroundLayer) { + const ids = previousBackgroundLayer.get('querySourceIds'); + if (Array.isArray(ids)) { + for (const id of ids) { + const dataSource = cache[id]; + if (dataSource) { + dataSource.visible = false; + this.dataSources_.remove(dataSource); + } + } + } + } + + // Add data sources linked to current background layer + if (currentBackgroundLayer) { + const ids = currentBackgroundLayer.get('querySourceIds'); + if (Array.isArray(ids)) { + for (const id of ids) { + const dataSource = cache[id]; + if (dataSource) { + dataSource.visible = true; + this.dataSources_.push(dataSource); + } + } + } + } + } +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfDataSourcesManager', [ + gmfDatasourceWFSAliases.module.name, + gmfLayertreeSyncLayertreeMap.module.name, + gmfLayertreeTreeManager.module.name, + gmfThemeThemes.module.name, + ngeoFilterRuleHelper.module.name, + ngeoDatasourceDataSources.module.name, + ngeoMapBackgroundLayerMgr.module.name, + ngeoMapLayerHelper.module.name, + ngeoMiscWMSTime.module.name, +]); +exports.module.service('gmfDataSourcesManager', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/OGC.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/OGC.js new file mode 100644 index 000000000..412d61543 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/OGC.js @@ -0,0 +1,42 @@ +/** + * @module gmf.datasource.OGC + */ +import ngeoDatasourceOGC from 'ngeo/datasource/OGC.js'; + +const exports = class extends ngeoDatasourceOGC { + + /** + * A `gmf.datasource.OGC` extends a `ngeo.datasource.OGC` and + * adds some properties that are proper to GMF only. + * + * @struct + * @param {gmfx.datasource.OGCOptions} options Options. + */ + constructor(options) { + + super(options); + + // === STATIC properties (i.e. that never change) === + + /** + * @type {gmfThemes.GmfLayer} + * @private + */ + this.gmfLayer_ = options.gmfLayer; + + } + + // === Static property getters/setters === + + /** + * @return {gmfThemes.GmfLayer} GMF layer + * @export + */ + get gmfLayer() { + return this.gmfLayer_; + } + +}; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/WFSAliases.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/WFSAliases.js new file mode 100644 index 000000000..afbc9b506 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/WFSAliases.js @@ -0,0 +1,55 @@ +/** + * @module gmf.datasource.WFSAliases + */ +import ngeoDatasourceHelper from 'ngeo/datasource/Helper.js'; + +const exports = class { + + /** + * Service that provides methods to get additional information and actions + * when performing WFS requests. + * + * @struct + * @param {ngeo.datasource.Helper} ngeoDataSourcesHelper Ngeo data + * source helper service. + * @ngdoc service + * @ngname gmfWFSAliases + * @ngInject + */ + constructor(ngeoDataSourcesHelper) { + + // === Injected properties === + + /** + * @type {ngeo.datasource.Helper} + * @private + */ + this.ngeoDataSourcesHelper_ = ngeoDataSourcesHelper; + } + + + /** + * @param {ngeo.datasource.OGC} dataSource Data source. + * @export + */ + describe(dataSource) { + // Only QGIS Server supports WFS aliases + if (dataSource.ogcServerType === 'qgisserver' && + dataSource.wfsUrl_ && + dataSource.getOGCLayerNames().length == 1 && + !dataSource.attributes) { + // Trigger an additional WFS DescribeFeatureType request to get + // datasource attributes, including aliases. + this.ngeoDataSourcesHelper_.getDataSourceAttributes(dataSource); + } + } +}; + + +exports.module = angular.module('gmfDatasourceWFSAliases', [ + ngeoDatasourceHelper.module.name, +]); +exports.module.service('gmfWFSAliases', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/module.js new file mode 100644 index 000000000..a399fad33 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/datasource/module.js @@ -0,0 +1,22 @@ +/** + * @module gmf.datasource.module + */ +import gmfDatasourceDataSourceBeingFiltered from 'gmf/datasource/DataSourceBeingFiltered.js'; +import gmfDatasourceExternalDataSourcesManager from 'gmf/datasource/ExternalDataSourcesManager.js'; +import gmfDatasourceHelper from 'gmf/datasource/Helper.js'; +import gmfDatasourceManager from 'gmf/datasource/Manager.js'; +import gmfDatasourceWFSAliases from 'gmf/datasource/WFSAliases.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfDatasourceModule', [ + gmfDatasourceDataSourceBeingFiltered.module.name, + gmfDatasourceExternalDataSourcesManager.module.name, + gmfDatasourceHelper.module.name, + gmfDatasourceManager.module.name, + gmfDatasourceWFSAliases.module.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/disclaimer/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/disclaimer/component.js new file mode 100644 index 000000000..2d917de17 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/disclaimer/component.js @@ -0,0 +1,366 @@ +/** + * @module gmf.disclaimer.component + */ +import * as olBase from 'ol/index.js'; +import * as olEvents from 'ol/events.js'; +import olLayerBase from 'ol/layer/Base.js'; +import olLayerGroup from 'ol/layer/Group.js'; +import gmfBase from 'gmf/index.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoMapLayerHelper from 'ngeo/map/LayerHelper.js'; +import ngeoMessageMessage from 'ngeo/message/Message.js'; +import ngeoMessageDisclaimer from 'ngeo/message/Disclaimer.js'; +import ngeoMiscEventHelper from 'ngeo/misc/EventHelper.js'; + +import 'angular-sanitize'; + +/** + * @type {angular.Module} + */ +const exports = angular.module('gmfDisclaimer', [ + 'ngSanitize', + ngeoMapLayerHelper.module.name, + ngeoMessageDisclaimer.module.name, + ngeoMiscEventHelper.module.name, +]); + + +/** + * @constructor + * @private + * @param {!angular.JQLite} $element Element. + * @param {!angular.Scope} $scope Angular scope. + * @param {!angular.$sce} $sce Angular sce service. + * @param {!angular.$timeout} $timeout Angular timeout service. + * @param {!angularGettext.Catalog} gettextCatalog Gettext catalog. + * @param {!ngeox.PopupFactory} ngeoCreatePopup Popup service. + * @param {!ngeo.message.Disclaimer} ngeoDisclaimer Ngeo Disclaimer service. + * @param {!ngeo.misc.EventHelper} ngeoEventHelper Ngeo Event Helper. + * @param {!ngeo.map.LayerHelper} ngeoLayerHelper Ngeo Layer Helper. + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfDisclaimerController + */ +exports.Controller_ = function($element, $scope, $sce, $timeout, + gettextCatalog, ngeoCreatePopup, ngeoDisclaimer, ngeoEventHelper, ngeoLayerHelper) { + + /** + * @type {?ol.Map} + * @export + */ + this.map; + + /** + * @type {boolean|undefined} + * @export + */ + this.external; + + /** + * @type {boolean|undefined} + * @export + */ + this.popup; + + /** + * Visibility that is set to true when a new msg is there. + * @type {boolean} + * @export + */ + this.visibility = false; + + /** + * Trusted html messages that can be displayed as html. + * @type {string|undefined} + * @export + */ + this.msg; + + /** + * @type {!Array} + * @export + */ + this.msgs_ = []; + + /** + * @type {!angular.$sce} + * @private + */ + this.sce_ = $sce; + + /** + * @type {!angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {!angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = gettextCatalog; + + /** + * @type {!angular.JQLite} + * @private + */ + this.element_ = $element; + + /** + * @type {!ngeox.PopupFactory} + * @private + */ + this.createPopup_ = ngeoCreatePopup; + + /** + * @type {!ngeo.message.Disclaimer} + * @private + */ + this.disclaimer_ = ngeoDisclaimer; + + /** + * @type {!ngeo.misc.EventHelper} + * @private + */ + this.eventHelper_ = ngeoEventHelper; + + /** + * @type {!ngeo.map.LayerHelper} + * @private + */ + this.ngeoLayerHelper_ = ngeoLayerHelper; + + /** + * @type {?ol.layer.Group} + * @private + */ + this.dataLayerGroup_ = null; +}; + + +/** + * Initialise the controller. + */ +exports.Controller_.prototype.$onInit = function() { + this.dataLayerGroup_ = this.ngeoLayerHelper_.getGroupFromMap(this.map, + gmfBase.DATALAYERGROUP_NAME); + this.registerLayer_(this.dataLayerGroup_); +}; + +/** + * @param {ol.Collection.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleLayersAdd_ = function(evt) { + this.timeout_(() => { + const layer = evt.element; + googAsserts.assertInstanceof(layer, olLayerBase); + this.registerLayer_(layer); + }); +}; + + +/** + * @param {ol.Collection.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleLayersRemove_ = function(evt) { + const layer = evt.element; + googAsserts.assertInstanceof(layer, olLayerBase); + this.unregisterLayer_(layer); +}; + + +/** + * @param {ol.layer.Base} layer Layer. + * @private + */ +exports.Controller_.prototype.registerLayer_ = function(layer) { + + const layerUid = olBase.getUid(layer); + + if (layer instanceof olLayerGroup) { + + // (1) Listen to added/removed layers to this group + this.eventHelper_.addListenerKey( + layerUid, + olEvents.listen( + layer.getLayers(), + 'add', + this.handleLayersAdd_, + this + ) + ); + this.eventHelper_.addListenerKey( + layerUid, + olEvents.listen( + layer.getLayers(), + 'remove', + this.handleLayersRemove_, + this + ) + ); + + // (2) Register existing layers in the group + layer.getLayers().forEach((layer) => { + this.registerLayer_(layer); + }); + + } else { + + // Show disclaimer messages for this layer + const disclaimers = layer.get('disclaimers'); + if (disclaimers && Array.isArray(disclaimers)) { + disclaimers.forEach((disclaimer) => { + this.showDisclaimerMessage_(disclaimer); + }); + } + } +}; + + +/** + * @param {ol.layer.Base} layer Layer. + * @private + */ +exports.Controller_.prototype.unregisterLayer_ = function(layer) { + + const layerUid = olBase.getUid(layer); + + if (layer instanceof olLayerGroup) { + + // (1) Clear event listeners + this.eventHelper_.clearListenerKey(layerUid); + + // (2) Unregister existing layers in the group + layer.getLayers().forEach(layer => this.unregisterLayer_(layer)); + + } else { + + // Close disclaimer messages for this layer + const disclaimers = layer.get('disclaimers'); + if (disclaimers && Array.isArray(disclaimers)) { + disclaimers.forEach((disclaimer) => { + this.closeDisclaimerMessage_(disclaimer); + }); + } + } + +}; + + +exports.Controller_.prototype.$onDestroy = function() { + this.unregisterLayer_(this.dataLayerGroup_); +}; + + +/** + * @param {string} msg Disclaimer message. + * @private + */ +exports.Controller_.prototype.showDisclaimerMessage_ = function(msg) { + msg = this.gettextCatalog_.getString(msg); + if (this.external) { + if (this.msgs_.indexOf(msg) < 0) { + this.msgs_.push(msg); + } + this.msg = `${this.sce_.trustAsHtml(this.msgs_.join('
'))}`; + this.visibility = true; + } else { + this.disclaimer_.alert({ + popup: this.popup, + msg: msg, + target: this.element_, + type: ngeoMessageMessage.Type.WARNING + }); + } +}; + + +/** + * @param {string} msg Disclaimer message. + * @private + */ +exports.Controller_.prototype.closeDisclaimerMessage_ = function(msg) { + msg = this.gettextCatalog_.getString(msg); + if (this.external) { + this.visibility = false; + this.msgs_.length = 0; + this.msg = ''; + } else { + this.disclaimer_.close({ + popup: this.popup, + msg: msg, + target: this.element_, + type: ngeoMessageMessage.Type.WARNING + }); + } +}; + + +/** + * Provide a "disclaimer" component for GeoMapFish that is bound to the + * layers added and removed from a map. + * + * Example: + * + * + * + * + * You can also display the disclaimer messages in popups or use them in another + * context. The example below show you how to display the disclaimer messages + * in a ngeo-modal window (external case). + * + * Example: + * + * + * + * + * + * + * + * + * @htmlAttribute {boolean} gmf-disclaimer-popup Whether to show the disclaimer + * messages in popups or not. Defaults to `false`. + * @htmlAttribute {boolean?} gmf-disclaimer-external Whether to use disclaimer + * messages elsewhere or not. Default to `false`. If true, you should use + * the gmf-disclaimer-external-msg and the + * gmf-disclaimer-external-visibility too. + * @htmlAttribute {boolean?} gmf-disclaimer-external-visibility variable that + * will be set to true if the disclaimers contain a new message. To uses it, + * you must set the gmf-disclaimer-external to true. + * @htmlAttribute {string?} gmf-disclaimer-external-msg variable that will + * contains the disclaimer messages. To uses it, you must set the + * gmf-disclaimer-external to true. + * @htmlAttribute {ol.Map=} gmf-disclaimer-map The map. + * + * @ngdoc component + * @ngname gmfDisclaimer + */ +exports.component_ = { + controller: exports.Controller_, + bindings: { + 'popup': ' + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + +
+ +
+ +
+ +
+
+ +
+ +
+ + +
+ + +
+ +
+ + + +
+ +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/drawFeatureComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/drawFeatureComponent.js new file mode 100644 index 000000000..29dd89ae5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/drawFeatureComponent.js @@ -0,0 +1,753 @@ +/** + * @module gmf.drawing.drawFeatureComponent + */ + +/** @suppress {extraRequire} */ +import gmfDrawingFeatureStyleComponent from 'gmf/drawing/featureStyleComponent.js'; + +import googAsserts from 'goog/asserts.js'; +import ngeoGeometryType from 'ngeo/GeometryType.js'; +import ngeoMenu from 'ngeo/Menu.js'; + +/** @suppress {extraRequire} */ +import ngeoEditingExportfeaturesComponent from 'ngeo/editing/exportfeaturesComponent.js'; + +/** @suppress {extraRequire} */ +import ngeoMiscBtnComponent from 'ngeo/misc/btnComponent.js'; + +/** @suppress {extraRequire} */ +import ngeoDrawComponent from 'ngeo/draw/component.js'; + +import ngeoFormatFeatureProperties from 'ngeo/format/FeatureProperties.js'; +import ngeoInteractionModify from 'ngeo/interaction/Modify.js'; +import ngeoInteractionRotate from 'ngeo/interaction/Rotate.js'; +import ngeoInteractionTranslate from 'ngeo/interaction/Translate.js'; +import ngeoMiscDecorate from 'ngeo/misc/decorate.js'; +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; +import * as olBase from 'ol/index.js'; +import * as olArray from 'ol/array.js'; +import * as olEvents from 'ol/events.js'; +import olCollection from 'ol/Collection.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStyle from 'ol/style/Style.js'; +import olStyleText from 'ol/style/Text.js'; + +import 'bootstrap/js/dropdown.js'; + + +/** + * @type {!angular.Module} + */ +const exports = angular.module('GmfDrawFeatureComponent', [ + gmfDrawingFeatureStyleComponent.name, + ngeoEditingExportfeaturesComponent.name, + ngeoMiscBtnComponent.name, + ngeoDrawComponent.name, + ngeoMiscFeatureHelper.module.name, + ngeoMiscToolActivateMgr.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/drawing/drawFeatureComponent', require('./drawFeatureComponent.html')); +}); + + +/** + * Directive used to create, modify and delete vector features on a map with + * the addition of changing their style. + * Example: + * + * + * + * + * @htmlAttribute {boolean} gmf-drawfeature-active Whether the directive is + * active or not. + * @htmlAttribute {ol.Map} gmf-drawfeature-map The map. + * @return {angular.Directive} The directive specs. + * @ngInject + * @ngdoc directive + * @ngname gmfDrawfeature + */ +exports.component_ = function() { + return { + controller: 'GmfDrawfeatureController as efCtrl', + scope: { + 'active': '=gmfDrawfeatureActive', + 'map': '} ngeoFeatures Collection of features. + * @param {!ngeo.misc.ToolActivateMgr} ngeoToolActivateMgr Ngeo ToolActivate manager + * service. + * @constructor + * @private + * @ngInject + * @ngdoc controller + * @ngname GmfDrawfeatureController + */ +exports.Controller_ = function($scope, $timeout, gettextCatalog, + ngeoFeatureHelper, ngeoFeatures, ngeoToolActivateMgr) { + + /** + * @type {!ol.Map} + * @export + */ + this.map; + + /** + * @type {boolean} + * @export + */ + this.active; + + if (this.active === undefined) { + this.active = false; + } + + /** + * @type {boolean} + * @export + */ + this.drawActive = false; + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.drawToolActivate = new ngeoMiscToolActivate(this, 'drawActive'); + + /** + * @type {boolean} + * @export + */ + this.mapSelectActive = true; + + /** + * @type {number?} + * @private + */ + this.longPressTimeout_ = null; + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.mapSelectToolActivate = new ngeoMiscToolActivate(this, 'mapSelectActive'); + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {!angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {!ngeo.misc.FeatureHelper} + * @private + */ + this.featureHelper_ = ngeoFeatureHelper; + + /** + * @type {!ol.Collection.} + * @export + */ + this.features = ngeoFeatures; + + /** + * @type {!ngeo.misc.ToolActivateMgr} + * @private + */ + this.ngeoToolActivateMgr_ = ngeoToolActivateMgr; + + /** + * @type {?ol.Feature} + * @export + */ + this.selectedFeature = null; + + /** + * @type {!ol.Collection.} + * @export + */ + this.selectedFeatures = new olCollection(); + + + /** + * @type {!ol.Collection} + * @private + */ + this.interactions_ = new olCollection(); + + /** + * @type {!ngeo.interaction.Modify} + * @private + */ + this.modify_ = new ngeoInteractionModify({ + features: this.selectedFeatures, + style: ngeoFeatureHelper.getVertexStyle(false) + }); + this.interactions_.push(this.modify_); + + /** + * @type {?ngeo.Menu} + * @private + */ + this.menu_ = null; + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.modifyToolActivate = new ngeoMiscToolActivate(this.modify_, 'active'); + + /** + * @type {!ngeo.interaction.Translate} + * @private + */ + this.translate_ = new ngeoInteractionTranslate({ + features: this.selectedFeatures, + style: new olStyleStyle({ + text: new olStyleText({ + text: '\uf047', + font: 'normal 18px FontAwesome', + fill: new olStyleFill({ + color: '#7a7a7a' + }) + }) + }) + }); + this.interactions_.push(this.translate_); + + /** + * @type {!ngeo.interaction.Rotate} + * @private + */ + this.rotate_ = new ngeoInteractionRotate({ + features: this.selectedFeatures, + style: new olStyleStyle({ + text: new olStyleText({ + text: '\uf01e', + font: 'normal 18px FontAwesome', + fill: new olStyleFill({ + color: '#7a7a7a' + }) + }) + }) + }); + this.interactions_.push(this.rotate_); + + this.initializeInteractions_(); + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.rotateToolActivate = new ngeoMiscToolActivate(this.rotate_, 'active'); + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.translateToolActivate = new ngeoMiscToolActivate(this.translate_, 'active'); + + /** + * @type {!Array.} + * @private + */ + this.listenerKeys_ = []; + + /** + * Flag used to determine whether the selection of a feature was made + * from the selection of an item from the list or not (the map, contextual + * menu, etc.) + * @type {boolean} + * @private + */ + this.listSelectionInProgress_ = false; + + $scope.$watch( + () => this.active, + this.handleActiveChange_.bind(this) + ); + + $scope.$watch( + () => this.drawActive, + (active) => { + if (active) { + this.selectedFeature = null; + } + } + ); + + $scope.$watch( + () => this.selectedFeature, + (newFeature, previousFeature) => { + this.selectedFeatures.clear(); + if (previousFeature) { + this.featureHelper_.setStyle(previousFeature); + this.unregisterInteractions_(); + } + if (newFeature) { + this.featureHelper_.setStyle(newFeature, true); + this.selectedFeatures.push(newFeature); + this.registerInteractions_(); + if (this.listSelectionInProgress_) { + this.featureHelper_.panMapToFeature(newFeature, this.map); + this.listSelectionInProgress_ = false; + } + } else if (this.menu_) { + this.map.removeOverlay(this.menu_); + this.menu_ = null; + } + } + ); + + $scope.$watch( + () => this.mapSelectActive, + this.handleMapSelectActiveChange_.bind(this) + ); + + /** + * @type {string} + * @export + */ + this.nameProperty = ngeoFormatFeatureProperties.NAME; + + /** + * @private + */ + this.gettextCatalog_ = gettextCatalog; +}; + + +/** + * Initialize interactions by setting them inactive and decorating them + * @private + */ +exports.Controller_.prototype.initializeInteractions_ = function() { + this.interactions_.forEach((interaction) => { + interaction.setActive(false); + ngeoMiscDecorate.interaction(interaction); + }); +}; + + +/** + * Register interactions by adding them to the map + * @private + */ +exports.Controller_.prototype.registerInteractions_ = function() { + this.interactions_.forEach((interaction) => { + this.map.addInteraction(interaction); + }); +}; + + +/** + * Register interactions by removing them to the map + * @private + */ +exports.Controller_.prototype.unregisterInteractions_ = function() { + this.interactions_.forEach((interaction) => { + this.map.removeInteraction(interaction); + }); +}; + + +/** + * Called when the active property of the this directive changes. Manage + * the activation/deactivation accordingly (event management, etc.) + * @param {boolean} active Whether the directive is active or not. + * @private + */ +exports.Controller_.prototype.handleActiveChange_ = function(active) { + + const keys = this.listenerKeys_; + const drawUid = ['draw-', olBase.getUid(this)].join('-'); + const otherUid = ['other-', olBase.getUid(this)].join('-'); + const toolMgr = this.ngeoToolActivateMgr_; + + if (active) { + // when activated + + keys.push( + olEvents.listen(this.features, 'add', this.handleFeaturesAdd_, this), + olEvents.listen(this.features, 'remove', this.handleFeaturesRemove_, this) + ); + + keys.push(olEvents.listen(this.translate_, + 'translateend', + this.handleTranslateEnd_, this)); + + keys.push(olEvents.listen(this.rotate_, 'rotateend', this.handleRotateEnd_, this)); + + toolMgr.registerTool(drawUid, this.drawToolActivate, false); + toolMgr.registerTool(drawUid, this.mapSelectToolActivate, true); + + toolMgr.registerTool(otherUid, this.drawToolActivate, false); + toolMgr.registerTool(otherUid, this.modifyToolActivate, true); + toolMgr.registerTool(otherUid, this.translateToolActivate, false); + toolMgr.registerTool(otherUid, this.rotateToolActivate, false); + + this.mapSelectActive = true; + this.modify_.setActive(true); + } else { + // when deactivated + + keys.forEach(olEvents.unlistenByKey); + keys.length = 0; + + toolMgr.unregisterTool(drawUid, this.drawToolActivate); + toolMgr.unregisterTool(drawUid, this.mapSelectToolActivate); + + toolMgr.unregisterTool(otherUid, this.drawToolActivate); + toolMgr.unregisterTool(otherUid, this.modifyToolActivate); + toolMgr.unregisterTool(otherUid, this.translateToolActivate); + toolMgr.unregisterTool(otherUid, this.rotateToolActivate); + + this.drawActive = false; + this.modify_.setActive(false); + this.mapSelectActive = false; + this.selectedFeature = null; + + if (this.menu_) { + this.map.removeOverlay(this.menu_); + this.menu_ = null; + } + } + +}; + + +/** + * Method called when a selection occurs from the list, i.e. when an item in + * the list of features is clicked. Called from the template, so no need to + * update Angular's scope. + * @param {!ol.Feature} feature Feature to select. + * @export + */ +exports.Controller_.prototype.selectFeatureFromList = function(feature) { + this.listSelectionInProgress_ = true; + this.selectedFeature = feature; + this.drawActive = false; +}; + + +/** + * @return {!Array.} Array. + * @export + */ +exports.Controller_.prototype.getFeaturesArray = function() { + return this.features.getArray(); +}; + + +/** + * @export + */ +exports.Controller_.prototype.clearFeatures = function() { + const gettextCatalog = this.gettextCatalog_; + const msg = gettextCatalog.getString( + 'Do you really want to delete all the features?'); + if (confirm(msg)) { + this.features.clear(); + } +}; + + +/** + * @param {!ol.Feature} feature The feature to remove from the selection. + * @export + */ +exports.Controller_.prototype.removeFeature = function(feature) { + const gettextCatalog = this.gettextCatalog_; + const msg = gettextCatalog.getString( + 'Do you really want to delete the selected feature?'); + if (confirm(msg)) { + this.features.remove(feature); + } +}; + + +/** + * @param {!ol.Collection.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleFeaturesAdd_ = function(evt) { + // timeout to prevent double-click to zoom the map + this.timeout_(() => { + this.selectedFeature = /** @type {ol.Feature} */ (evt.element); + this.drawActive = false; + this.scope_.$apply(); + }); +}; + + +/** + * @param {!ol.Collection.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleFeaturesRemove_ = function(evt) { + this.selectedFeature = null; +}; + + +/** + * Called when the mapSelectActive property changes. + * @param {boolean} active Whether the map select is active or not. + * @private + */ +exports.Controller_.prototype.handleMapSelectActiveChange_ = function( + active) { + + const mapDiv = this.map.getViewport(); + googAsserts.assertElement(mapDiv); + + if (active) { + olEvents.listen(this.map, 'click', + this.handleMapClick_, this); + + olEvents.listen(mapDiv, 'contextmenu', + this.handleMapContextMenu_, this); + + olEvents.listen(mapDiv, 'touchstart', + this.handleMapTouchStart_, this); + + olEvents.listen(mapDiv, 'touchmove', + this.handleMapTouchEnd_, this); + + olEvents.listen(mapDiv, 'touchend', + this.handleMapTouchEnd_, this); + + } else { + olEvents.unlisten(this.map, 'click', + this.handleMapClick_, this); + + olEvents.unlisten(mapDiv, 'contextmenu', + this.handleMapContextMenu_, this); + + olEvents.unlisten(mapDiv, 'touchstart', + this.handleMapTouchStart_, this); + + olEvents.unlisten(mapDiv, 'touchmove', + this.handleMapTouchEnd_, this); + + olEvents.unlisten(mapDiv, 'touchend', + this.handleMapTouchEnd_, this); + } +}; + + +/** + * @param {!ol.MapBrowserEvent} evt Event. + * @private + */ +exports.Controller_.prototype.handleMapClick_ = function(evt) { + + const pixel = evt.pixel; + + let feature = this.map.forEachFeatureAtPixel( + pixel, + (feature) => { + let ret = false; + if (olArray.includes(this.features.getArray(), feature)) { + ret = feature; + } + return ret; + }, + { + hitTolerance: 5 + } + ); + + feature = feature ? feature : null; + + // do not do any further action if feature is null or already selected + if (feature === this.selectedFeature) { + return; + } + + this.selectedFeature = feature; + + this.scope_.$apply(); +}; + + +/** + * @param {!Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleMapTouchStart_ = function(evt) { + this.longPressTimeout_ = setTimeout(() => { + this.handleMapContextMenu_(evt); + }, 500); +}; + + +/** + * @param {!Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleMapTouchEnd_ = function(evt) { + clearTimeout(this.longPressTimeout_); +}; + + +/** + * @param {!Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleMapContextMenu_ = function(evt) { + const gettextCatalog = this.gettextCatalog_; + const pixel = this.map.getEventPixel(evt); + const coordinate = this.map.getCoordinateFromPixel(pixel); + + let feature = this.map.forEachFeatureAtPixel( + pixel, + (feature) => { + let ret = false; + if (olArray.includes(this.features.getArray(), feature)) { + ret = feature; + } + return ret; + }, + { + hitTolerance: 7 + } + ); + + feature = feature ? feature : null; + + // show contextual menu when clicking on certain types of features + if (feature) { + let actions = []; + + const type = this.featureHelper_.getType(feature); + if (type == ngeoGeometryType.CIRCLE || + type == ngeoGeometryType.LINE_STRING || + type == ngeoGeometryType.POLYGON || + type == ngeoGeometryType.RECTANGLE) { + actions = actions.concat([{ + cls: 'fa fa-arrows', + label: gettextCatalog.getString('Move'), + name: 'move' + }, { + cls: 'fa fa-rotate-right', + label: gettextCatalog.getString('Rotate'), + name: 'rotate' + }]); + } + + actions = actions.concat([{ + cls: 'fa fa-trash-o', + label: gettextCatalog.getString('Delete'), + name: 'delete' + }]); + + this.menu_ = new ngeoMenu({ + actions + }); + + olEvents.listen(this.menu_, 'actionclick', + this.handleMenuActionClick_, this); + this.map.addOverlay(this.menu_); + + this.menu_.open(coordinate); + + evt.preventDefault(); + evt.stopPropagation(); + } + + // do not do any further action if feature is null or already selected + if (feature === this.selectedFeature) { + return; + } + + this.modify_.setActive(true); + + this.selectedFeature = feature; + + this.scope_.$apply(); +}; + + +/** + * @param {!ngeox.MenuEvent} evt Event. + * @private + */ +exports.Controller_.prototype.handleMenuActionClick_ = function(evt) { + const action = evt.detail.action; + + switch (action) { + case 'delete': + googAsserts.assert( + this.selectedFeature, 'Selected feature should be truthy'); + this.removeFeature(this.selectedFeature); + this.scope_.$apply(); + break; + case 'move': + this.translate_.setActive(true); + this.scope_.$apply(); + break; + case 'rotate': + this.rotate_.setActive(true); + this.scope_.$apply(); + break; + default: + // FIXME + console.log(`FIXME - support: ${action}`); + break; + } +}; + + +/** + * @param {!ol.interaction.Translate.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleTranslateEnd_ = function(evt) { + this.translate_.setActive(false); + this.scope_.$apply(); +}; + + +/** + * @param {!ngeox.RotateEvent} evt Event. + * @private + */ +exports.Controller_.prototype.handleRotateEnd_ = function(evt) { + this.rotate_.setActive(false); + this.scope_.$apply(); +}; + + +exports.controller('GmfDrawfeatureController', + exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/featureStyleComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/featureStyleComponent.html new file mode 100644 index 000000000..0353e4f4d --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/featureStyleComponent.html @@ -0,0 +1,154 @@ +
+
+ +
+
+ + +
+
+ + + + ({{ fsCtrl.measure }}) + +
+
+
+ +
+
+
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
+ +
+ +
+
+ +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/featureStyleComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/featureStyleComponent.js new file mode 100644 index 000000000..9d83a1bc9 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/featureStyleComponent.js @@ -0,0 +1,324 @@ +/** + * @module gmf.drawing.featureStyleComponent + */ +import googAsserts from 'goog/asserts.js'; +import * as olEvents from 'ol/events.js'; +import ngeoFormatFeatureProperties from 'ngeo/format/FeatureProperties.js'; + +/** @suppress {extraRequire} */ +import ngeoMiscColorpickerComponent from 'ngeo/misc/colorpickerComponent.js'; + +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfDrawingFeatureStyle', [ + ngeoMiscColorpickerComponent.name, + ngeoMiscFeatureHelper.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/drawing/featureStyleComponent', require('./featureStyleComponent.html')); +}); + + +/** + * Directive used to set the style of a vector feature. The options depend + * on the type of geometry. + * Example: + * + * + * + * + * @htmlAttribute {ol.Feature} gmf-featurestyle-feature The feature. + * @return {angular.Directive} The directive specs. + * @ngInject + * @ngdoc directive + * @ngname gmfFeaturestyle + */ +exports.directive_ = function() { + return { + controller: 'GmfFeaturestyleController as fsCtrl', + scope: { + 'feature': '=gmfFeaturestyleFeature' + }, + bindToController: true, + templateUrl: 'gmf/drawing/featureStyleComponent' + }; +}; + + +exports.directive('gmfFeaturestyle', + exports.directive_); + + +/** + * @param {!angular.Scope} $scope Angular scope. + * @param {ngeo.misc.FeatureHelper} ngeoFeatureHelper Gmf feature helper service. + * @constructor + * @private + * @ngInject + * @ngdoc controller + * @ngname GmfFeaturestyleController + */ +exports.Controller_ = function($scope, ngeoFeatureHelper) { + + /** + * @type {?ol.Feature} + * @export + */ + this.feature; + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {ngeo.misc.FeatureHelper} + * @private + */ + this.featureHelper_ = ngeoFeatureHelper; + + /** + * @type {string|undefined} + * @export + */ + this.color = undefined; + + /** + * @type {string|undefined} + * @export + */ + this.label = undefined; + + /** + * @type {string|undefined} + * @export + */ + this.measure = undefined; + + $scope.$watch( + () => this.color, + this.handleColorSet_.bind(this) + ); + + /** + * @type {Array.} + * @private + */ + this.featureListenerKeys_ = []; + + /** + * @type {string|undefined} + * @export + */ + this.type; + + $scope.$watch( + () => this.feature, + this.handleFeatureSet_.bind(this) + ); + +}; + + +/** + * Called when a new feature is set, which can also be null. + * @param {?ol.Feature} newFeature New feature or null value. + * @param {?ol.Feature} previousFeature Previous feature or null value. + * @private + */ +exports.Controller_.prototype.handleFeatureSet_ = function( + newFeature, previousFeature) { + + const keys = this.featureListenerKeys_; + + if (previousFeature) { + keys.forEach(olEvents.unlistenByKey); + keys.length = 0; + this.type = undefined; + this.color = undefined; + this.measure = undefined; + this.label = undefined; + } + + if (newFeature) { + [ + ngeoFormatFeatureProperties.ANGLE, + ngeoFormatFeatureProperties.COLOR, + ngeoFormatFeatureProperties.NAME, + ngeoFormatFeatureProperties.SHOW_LABEL, + ngeoFormatFeatureProperties.OPACITY, + ngeoFormatFeatureProperties.SHOW_MEASURE, + ngeoFormatFeatureProperties.SIZE, + ngeoFormatFeatureProperties.STROKE + ].forEach(function(propName) { + keys.push( + olEvents.listen( + newFeature, + `change:${propName}`, + this.handleFeatureChange_, + this + ) + ); + }, this); + + const geometry = newFeature.getGeometry(); + googAsserts.assert(geometry, 'Geometry should be thruthy'); + + keys.push( + olEvents.listen( + geometry, + 'change', + this.handleGeometryChange_, + this + ) + ); + + this.type = this.featureHelper_.getType(newFeature); + this.color = this.featureHelper_.getColorProperty(newFeature); + this.measure = this.featureHelper_.getMeasure(newFeature); + } +}; + + +/** + * @param {string|undefined} newColor Color. + * @private + */ +exports.Controller_.prototype.handleColorSet_ = function( + newColor) { + if (this.feature && newColor) { + const currentColor = this.feature.get(ngeoFormatFeatureProperties.COLOR); + if (currentColor !== newColor) { + this.feature.set(ngeoFormatFeatureProperties.COLOR, newColor); + } + } +}; + + +/** + * @param {number|undefined} value A name value to set or undefined to get. + * @return {number} The angle of the feature. + * @export + */ +exports.Controller_.prototype.getSetAngle = function(value) { + return googAsserts.assertNumber(this.getSetProperty_(ngeoFormatFeatureProperties.ANGLE, value)); +}; + + +/** + * @param {string|undefined} value A name value to set or undefined to get. + * @return {string} The name of the feature. + * @export + */ +exports.Controller_.prototype.getSetName = function(value) { + return googAsserts.assertString(this.getSetProperty_(ngeoFormatFeatureProperties.NAME, value)); +}; + +/** + * @param {boolean|undefined} value A value to set or undefined for the + * purpose of showing the attribute labels or not. + * @return {boolean} Whether to show the labels or not. + * @export + */ +exports.Controller_.prototype.getSetShowLabel = function(value) { + return googAsserts.assertBoolean(this.getSetProperty_(ngeoFormatFeatureProperties.SHOW_LABEL, value)); +}; + +/** + * @param {number|undefined} value A stroke value to set or undefined to get. + * @return {number} The stroke of the feature. + * @export + */ +exports.Controller_.prototype.getSetOpacity = function(value) { + return googAsserts.assertNumber(this.getSetProperty_(ngeoFormatFeatureProperties.OPACITY, value)); +}; + + +/** + * @param {boolean|undefined} value A value to set or undefined to get for the + * purpose of showing the geometry measurements or not. + * @return {boolean} Whether to show the measurements or not. + * @export + */ +exports.Controller_.prototype.getSetShowMeasure = function(value) { + return googAsserts.assertBoolean(this.getSetProperty_(ngeoFormatFeatureProperties.SHOW_MEASURE, value)); +}; + + +/** + * @param {number|undefined} value A size value to set or undefined to get. + * @return {number} The size of the feature. + * @export + */ +exports.Controller_.prototype.getSetSize = function(value) { + return googAsserts.assertNumber(this.getSetProperty_(ngeoFormatFeatureProperties.SIZE, value)); +}; + + +/** + * @param {number|undefined} value A stroke value to set or undefined to get. + * @return {number} The stroke of the feature. + * @export + */ +exports.Controller_.prototype.getSetStroke = function(value) { + return googAsserts.assertNumber(this.getSetProperty_(ngeoFormatFeatureProperties.STROKE, value)); +}; + + +/** + * @param {string} key The property name. + * @param {boolean|number|string|undefined} value A value to set or undefined + * to get. + * @return {boolean|number|string} The property value of the feature. + * @private + */ +exports.Controller_.prototype.getSetProperty_ = function(key, value) { + if (value !== undefined) { + this.feature.set(key, value); + } + return /** @type {boolean|number|string} */ (this.feature.get(key)); +}; + + +/** + * @private + */ +exports.Controller_.prototype.handleFeatureChange_ = function() { + const feature = this.feature; + + if (!feature) { + return; + } + + this.featureHelper_.setStyle(feature, true); +}; + + +/** + * @private + */ +exports.Controller_.prototype.handleGeometryChange_ = function() { + googAsserts.assert(this.feature); + this.measure = this.featureHelper_.getMeasure(this.feature); + + const showMeasure = this.featureHelper_.getShowMeasureProperty(this.feature); + if (showMeasure) { + this.handleFeatureChange_(); + } + + this.scope_.$apply(); +}; + + +exports.controller('GmfFeaturestyleController', + exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/module.js new file mode 100644 index 000000000..6e642a793 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/drawing/module.js @@ -0,0 +1,16 @@ +/** + * @module gmf.drawing.module + */ +import gmfDrawingDrawFeatureComponent from 'gmf/drawing/drawFeatureComponent.js'; +import gmfDrawingFeatureStyleComponent from 'gmf/drawing/featureStyleComponent.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfDrawingModule', [ + gmfDrawingDrawFeatureComponent.name, + gmfDrawingFeatureStyleComponent.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/EditFeature.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/EditFeature.js new file mode 100644 index 000000000..5fe5979d9 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/EditFeature.js @@ -0,0 +1,155 @@ +/** + * @module gmf.editing.EditFeature + */ +import olFormatGeoJSON from 'ol/format/GeoJSON.js'; +import * as olUri from 'ol/uri.js'; + +/** + * Service that provides methods to get, insert, update and delete vector + * features with the use of a GeoMapFish Protocol as back-end. + * + * The GeoJSON format is used when obtaining or sending features. + * + * @constructor + * @struct + * @param {angular.$http} $http Angular http service. + * @param {string} gmfLayersUrl Url to the GeoMapFish layers service. + * @ngInject + */ +const exports = function($http, gmfLayersUrl) { + + /** + * @type {angular.$http} + * @private + */ + this.http_ = $http; + + /** + * Url to the GeoMapFish layers service. Required in applications that use: + * - the editfeature tools + * - the objectediting tools + * + * @type {string} + * @private + */ + this.baseUrl_ = gmfLayersUrl; + +}; + + +/** + * Build a query to the MapFish protocol to fetch features from a list + * of layer ids inside a specified extent. + * + * @param {Array.} layerIds List of layer ids to get the features from. + * @param {ol.Extent} extent The extent where to get the features from. + * @return {angular.$q.Promise} Promise. + * @export + */ +exports.prototype.getFeaturesInExtent = function(layerIds, extent) { + const url = olUri.appendParams( + `${this.baseUrl_}/${layerIds.join(',')}`, + { + 'bbox': extent.join(',') + } + ); + return this.http_.get(url).then(this.handleGetFeatures_.bind(this)); +}; + + +/** + * Build a query to the MapFish protocol to fetch features from a list + * of layer ids and a list of comparison filters. + * + * This method is called in the ObjectEditing service, which is injected in + * the permalink service, i.e. it's always called. Since we don't have to + * define the url to the GMF Protocol (layers) a dummy promise returns an + * empty array of features if the url is not defined. + * + * @param {!Array.} layerIds List of layer ids to get the features from. + * @param {!Array.} filters List of comparison filters + * @return {angular.$q.Promise} Promise. + */ +exports.prototype.getFeaturesWithComparisonFilters = function( + layerIds, filters +) { + const properties = []; + const params = {}; + + for (const filter of filters) { + params[`${filter.property}__${filter.operator}`] = filter.value; + properties.push(filter.property); + } + + params['queryable'] = properties.join(','); + + const url = olUri.appendParams(`${this.baseUrl_}/${layerIds.join(',')}`, params); + return this.http_.get(url).then(this.handleGetFeatures_.bind(this)); +}; + + +/** + * @param {angular.$http.Response} resp Ajax response. + * @return {Array.} List of features. + * @private + */ +exports.prototype.handleGetFeatures_ = function(resp) { + return new olFormatGeoJSON().readFeatures(resp.data); +}; + + +/** + * @param {number} layerId The layer id that contains the feature. + * @param {Array.} features List of features to insert. + * @return {angular.$q.Promise} Promise. + * @export + */ +exports.prototype.insertFeatures = function(layerId, features) { + const url = `${this.baseUrl_}/${layerId}`; + const geoJSON = new olFormatGeoJSON().writeFeatures(features); + return this.http_.post(url, geoJSON, { + headers: {'Content-Type': 'application/json'}, + withCredentials: true + }); +}; + + +/** + * @param {number} layerId The layer id that contains the feature. + * @param {ol.Feature} feature The feature to update. + * @return {angular.$q.Promise} Promise. + * @export + */ +exports.prototype.updateFeature = function(layerId, feature) { + const url = `${this.baseUrl_}/${layerId.toString()}/${feature.getId()}`; + const geoJSON = new olFormatGeoJSON().writeFeature(feature); + return this.http_.put(url, geoJSON, { + headers: {'Content-Type': 'application/json'}, + withCredentials: true + }); +}; + + +/** + * @param {number} layerId The layer id that contains the feature. + * @param {ol.Feature} feature The feature to delete. + * @return {angular.$q.Promise} Promise. + * @export + */ +exports.prototype.deleteFeature = function(layerId, feature) { + const url = `${this.baseUrl_}/${layerId.toString()}/${feature.getId()}`; + return this.http_.delete(url, { + headers: {'Content-Type': 'application/json'}, + withCredentials: true + }); +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfEditFeature', []); +exports.module.service('gmfEditFeature', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/EnumerateAttribute.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/EnumerateAttribute.js new file mode 100644 index 000000000..366d00dba --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/EnumerateAttribute.js @@ -0,0 +1,78 @@ +/** + * @module gmf.editing.EnumerateAttribute + */ +const exports = class { + + /** + * The EnumerateAttribute is responsible of fetching all possible of a given + * attribute of a given data source (gmf layer). + * + * @struct + * @param {angular.$http} $http Angular $http service. + * @param {string} gmfLayersUrl Url to the GeoMapFish layers service. + * @ngInject + * @ngdoc service + * @ngname gmfEnumerateAttribute + */ + constructor($http, gmfLayersUrl) { + + // === Injected services === + + /** + * @type {angular.$http} + * @private + */ + this.http_ = $http; + + /** + * @type {string} + * @private + */ + this.baseUrl_ = gmfLayersUrl; + + /** + * @type {Object.} + * @private + */ + this.promises_ = {}; + } + + /** + * @param {gmf.datasource.OGC} dataSource Data source. + * @param {string} attribute Attribute name. + * @return {angular.$q.Promise} Promise. + */ + getAttributeValues(dataSource, attribute) { + const promiseId = `${dataSource.id}_${attribute}`; + const name = dataSource.name; + if (!this.promises_[promiseId]) { + const url = `${this.baseUrl_}/${name}/values/${attribute}`; + this.promises_[promiseId] = this.http_.get(url).then( + this.handleGetAttributeValues_.bind(this)); + } + return this.promises_[promiseId]; + } + + /** + * @param {angular.$http.Response} resp Ajax response. + * @return {Array.} List of the attribute + * values. + * @export + */ + handleGetAttributeValues_(resp) { + const data = /** @type {gmfThemes.GmfLayerAttributeValuesResponse} */ ( + resp.data); + return data.items; + } + +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfEnumerateAttribute', []); +exports.module.service('gmfEnumerateAttribute', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/Snapping.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/Snapping.js new file mode 100644 index 000000000..3aeccfcde --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/Snapping.js @@ -0,0 +1,584 @@ +/** + * @module gmf.editing.Snapping + */ +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoLayertreeController from 'ngeo/layertree/Controller.js'; +import * as olBase from 'ol/index.js'; +import * as olEvents from 'ol/events.js'; +import olCollection from 'ol/Collection.js'; +import olFormatWFS from 'ol/format/WFS.js'; +import olInteractionSnap from 'ol/interaction/Snap.js'; + +/** + * The snapping service of GMF. Responsible of collecting the treeCtrls that + * support snapping and store them here. As soon as a treeCtrl state becomes + * 'on', a WFS GetFeature request is issued to collect the features at the + * map view location. A new request is sent every time the map is panned or + * zoomed for each treeCtrl that are still 'on'. + * + * Features returned by these requests get bound to a `ol.interaction.Snap`, + * which allows the snapping to occur on other places where vector + * features are drawn or modified. + * + * @constructor + * @param {angular.$http} $http Angular $http service. + * @param {angular.$q} $q The Angular $q service. + * @param {!angular.Scope} $rootScope Angular rootScope. + * @param {angular.$timeout} $timeout Angular timeout service. + * @param {gmf.theme.Themes} gmfThemes The gmf Themes service. + * @param {gmf.layertree.TreeManager} gmfTreeManager The gmf TreeManager service. + * @ngInject + * @ngdoc service + * @ngname gmfSnapping + */ +const exports = function($http, $q, $rootScope, $timeout, gmfThemes, + gmfTreeManager) { + + // === Injected services === + + /** + * @type {angular.$http} + * @private + */ + this.http_ = $http; + + /** + * @type {angular.$q} + * @private + */ + this.q_ = $q; + + /** + * @type {!angular.Scope} + * @private + */ + this.rootScope_ = $rootScope; + + /** + * @type {angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + /** + * @type {gmf.layertree.TreeManager} + * @private + */ + this.gmfTreeManager_ = gmfTreeManager; + + + // === Properties === + + /** + * A cache containing all available snappable items, in which the listening + * of the state of the `treeCtrl` is registered and unregistered. + * @type {gmf.editing.Snapping.Cache} + * @private + */ + this.cache_ = {}; + + /** + * @type {!Array.} + * @private + */ + this.listenerKeys_ = []; + + /** + * @type {?ol.Map} + * @private + */ + this.map_ = null; + + /** + * Reference to the promise taking care of calling all GetFeature requests + * of the currently active cache items after the map view changed. Used + * to cancel if the map view changes often within a short period of time. + * @type {?angular.$q.Promise} + * @private + */ + this.mapViewChangePromise_ = null; + + /** + * A reference to the OGC servers loaded by the theme service. + * @type {gmfThemes.GmfOgcServers|null} + * @private + */ + this.ogcServers_ = null; + +}; + + +/** + * In order for a `ol.interaction.Snap` to work properly, it has to be added + * to the map after any draw interactions or other kinds of interactions that + * ineracts with features on the map. + * + * This method can be called to make sure the Snap interactions are on top. + * + * @export + */ +exports.prototype.ensureSnapInteractionsOnTop = function() { + const map = this.map_; + googAsserts.assert(map); + + let item; + for (const uid in this.cache_) { + item = this.cache_[+uid]; + if (item.active) { + googAsserts.assert(item.interaction); + map.removeInteraction(item.interaction); + map.addInteraction(item.interaction); + } + } +}; + + +/** + * Bind the snapping service to a map + * @param {?ol.Map} map Map + * @export + */ +exports.prototype.setMap = function(map) { + + const keys = this.listenerKeys_; + + if (this.map_) { + this.treeCtrlsUnregister_(); + this.unregisterAllTreeCtrl_(); + keys.forEach(olEvents.unlistenByKey); + keys.length = 0; + } + + this.map_ = map; + + if (map) { + this.treeCtrlsUnregister_ = this.rootScope_.$watchCollection(() => { + if (this.gmfTreeManager_.rootCtrl) { + return this.gmfTreeManager_.rootCtrl.children; + } + }, (value) => { + // Timeout required, because the collection event is fired before the + // leaf nodes are created and they are the ones we're looking for here. + this.timeout_(() => { + if (value) { + this.unregisterAllTreeCtrl_(); + this.gmfTreeManager_.rootCtrl.traverseDepthFirst(this.registerTreeCtrl_.bind(this)); + } + }, 0); + }); + + keys.push( + olEvents.listen(this.gmfThemes_, 'change', this.handleThemesChange_, this), + olEvents.listen(map, 'moveend', this.handleMapMoveEnd_, this) + ); + } +}; + + +/** + * Called when the themes change. Get the OGC servers, then listen to the + * tree manager Layertree controllers array changes. + * @private + */ +exports.prototype.handleThemesChange_ = function() { + this.ogcServers_ = null; + this.gmfThemes_.getOgcServersObject().then((ogcServers) => { + this.ogcServers_ = ogcServers; + }); +}; + + +/** + * Registers a newly added Layertree controller 'leaf'. If it's snappable, + * create and add a cache item with every configuration required to do the + * snapping. It becomes active when its state is set to 'on'. + * + * @param {ngeo.layertree.Controller} treeCtrl Layertree controller to register + * @private + */ +exports.prototype.registerTreeCtrl_ = function(treeCtrl) { + + // Skip any Layertree controller that has a node that is not a leaf + let node = /** @type {gmfThemes.GmfGroup|gmfThemes.GmfLayer} */ (treeCtrl.node); + if (node.children) { + return; + } + + // If treeCtrl is snappable and supports WFS, listen to its state change. + // When it becomes visible, it's added to the list of snappable tree ctrls. + node = /** @type {gmfThemes.GmfLayer} */ (treeCtrl.node); + const snappingConfig = gmfThemeThemes.getSnappingConfig(node); + if (snappingConfig) { + const wfsConfig = this.getWFSConfig_(treeCtrl); + if (wfsConfig) { + const uid = olBase.getUid(treeCtrl); + + const stateWatcherUnregister = this.rootScope_.$watch( + () => treeCtrl.getState(), + this.handleTreeCtrlStateChange_.bind(this, treeCtrl) + ); + + // Todo: some of the properties here are hardcoded, but could come from + // the node metadata at some point. + this.cache_[uid] = { + active: false, + featureNS: 'http://mapserver.gis.umn.edu/mapserver', + featurePrefix: 'feature', + features: new olCollection(), + geometryName: 'geom', + interaction: null, + maxFeatures: 50, + requestDeferred: null, + snappingConfig: snappingConfig, + treeCtrl: treeCtrl, + wfsConfig: wfsConfig, + stateWatcherUnregister: stateWatcherUnregister + }; + + // This extra call is to initialize the treeCtrl with its current state + this.handleTreeCtrlStateChange_(treeCtrl, treeCtrl.getState()); + } + } +}; + + +/** + * Unregisters all removed layertree controllers 'leaf'. Remove the according + * cache item and deactivate it as well. Unregister events. + * + * @private + */ +exports.prototype.unregisterAllTreeCtrl_ = function() { + for (const uid in this.cache_) { + const item = this.cache_[+uid]; + if (item) { + item.stateWatcherUnregister(); + this.deactivateItem_(item); + delete this.cache_[+uid]; + } + } +}; + + +/** + * Get the configuration required to do WFS requests (for snapping purpose) + * from a Layertree controller that has a leaf node. + * + * The following requirements must be met in order for a treeCtrl to be + * considered supporting WFS: + * + * 1) ogcServers objects are loaded + * 2) its node `type` property is equal to `WMS` + * 3) in its node `childLayers` property, the `queryable` property is set + * to `true` + * 4) if its node `mixed` property is: + * a) true: then the node must have an `ogcServer` property set + * b) false: then the first parent node must have an `ogcServer` property set + * 5) the ogcServer defined in 3) has the `wfsSupport` property set to `true`. + * + * @param {ngeo.layertree.Controller} treeCtrl The layer tree controller + * @return {?gmf.editing.Snapping.WFSConfig} The configuration object. + * @private + */ +exports.prototype.getWFSConfig_ = function(treeCtrl) { + + // (1) + if (this.ogcServers_ === null) { + return null; + } + + const gmfLayer = /** @type {gmfThemes.GmfLayer} */ (treeCtrl.node); + + // (2) + if (gmfLayer.type !== gmfThemeThemes.NodeType.WMS) { + return null; + } + + const gmfLayerWMS = /** @type {gmfThemes.GmfLayerWMS} */ (gmfLayer); + + // (3) + const featureTypes = []; + for (let i = 0, ii = gmfLayerWMS.childLayers.length; i < ii; i++) { + if (gmfLayerWMS.childLayers[i].queryable) { + featureTypes.push(gmfLayerWMS.childLayers[i].name); + } + } + if (!featureTypes.length) { + return null; + } + + // (4) + let ogcServerName; + const gmfGroup = /** @type {gmfThemes.GmfGroup} */ (treeCtrl.parent.node); + if (gmfGroup.mixed) { + ogcServerName = gmfLayerWMS.ogcServer; + } else { + const firstTreeCtrl = ngeoLayertreeController.getFirstParentTree(treeCtrl); + const firstNode = /** @type {gmfThemes.GmfGroup} */ (firstTreeCtrl.node); + ogcServerName = firstNode.ogcServer; + } + if (!ogcServerName) { + return null; + } + + // (5) + const ogcServer = this.ogcServers_[ogcServerName]; + if (!ogcServer.wfsSupport) { + return null; + } + + // At this point, every requirements have been met. + // Create and return the configuration. + const urlWfs = ogcServer.urlWfs; + googAsserts.assert(urlWfs, 'urlWfs should be defined.'); + + return { + featureTypes: featureTypes.join(','), + url: urlWfs + }; +}; + + +/** + * @param {ngeo.layertree.Controller} treeCtrl The layer tree controller + * @param {string|undefined} newVal New state value + * @private + */ +exports.prototype.handleTreeCtrlStateChange_ = function(treeCtrl, newVal) { + + const uid = olBase.getUid(treeCtrl); + const item = this.cache_[uid]; + + // Note: a snappable treeCtrl can only be a leaf, therefore the only possible + // states are: 'on' and 'off'. + if (newVal === 'on') { + this.activateItem_(item); + } else { + this.deactivateItem_(item); + } +}; + + +/** + * Activate a cache item by adding a Snap interaction to the map and launch + * the initial request to get the features. + * + * @param {gmf.editing.Snapping.CacheItem} item Cache item. + * @private + */ +exports.prototype.activateItem_ = function(item) { + + // No need to do anything if item is already active + if (item.active) { + return; + } + + const map = this.map_; + googAsserts.assert(map); + + const interaction = new olInteractionSnap({ + edge: item.snappingConfig.edge, + features: item.features, + pixelTolerance: item.snappingConfig.tolerance, + vertex: item.snappingConfig.vertex + }); + + map.addInteraction(interaction); + + item.interaction = interaction; + item.active = true; + + // Init features + this.loadItemFeatures_(item); +}; + + +/** + * Deactivate a cache item by removing the snap interaction and clearing any + * existing features. + * + * @param {gmf.editing.Snapping.CacheItem} item Cache item. + * @private + */ +exports.prototype.deactivateItem_ = function(item) { + + // No need to do anything if item is already inactive + if (!item.active) { + return; + } + + const map = this.map_; + googAsserts.assert(map); + + const interaction = item.interaction; + map.removeInteraction(interaction); + + item.interaction = null; + item.features.clear(); + + // If a previous request is still running, cancel it. + if (item.requestDeferred) { + item.requestDeferred.resolve(); + item.requestDeferred = null; + } + + item.active = false; +}; + + +/** + * @private + */ +exports.prototype.loadAllItems_ = function() { + this.mapViewChangePromise_ = null; + let item; + for (const uid in this.cache_) { + item = this.cache_[+uid]; + if (item.active) { + this.loadItemFeatures_(item); + } + } +}; + + +/** + * Manually refresh all features + */ +exports.prototype.refresh = function() { + this.loadAllItems_(); +}; + + +/** + * For a specific cache item, issue a new WFS GetFeatures request. The returned + * features set in the item collection of features (they replace any existing + * ones first). + * + * @param {gmf.editing.Snapping.CacheItem} item Cache item. + * @private + */ +exports.prototype.loadItemFeatures_ = function(item) { + + // If a previous request is still running, cancel it. + if (item.requestDeferred) { + item.requestDeferred.resolve(); + } + + const map = this.map_; + googAsserts.assert(map); + + const view = map.getView(); + const size = map.getSize(); + googAsserts.assert(size); + + const extent = view.calculateExtent(size); + const projCode = view.getProjection().getCode(); + const featureTypes = item.wfsConfig.featureTypes.split(','); + + const getFeatureOptions = { + srsName: projCode, + featureNS: item.featureNS, + featurePrefix: item.featurePrefix, + featureTypes: featureTypes, + outputFormat: 'GML3', + bbox: extent, + geometryName: item.geometryName, + maxFeatures: item.maxFeatures + }; + + const wfsFormat = new olFormatWFS(); + const xmlSerializer = new XMLSerializer(); + const featureRequestXml = wfsFormat.writeGetFeature(getFeatureOptions); + const featureRequest = xmlSerializer.serializeToString(featureRequestXml); + const url = item.wfsConfig.url; + + item.requestDeferred = this.q_.defer(); + + this.http_.post(url, featureRequest, {timeout: item.requestDeferred.promise}) + .then((response) => { + // (1) Unset requestDeferred + item.requestDeferred = null; + + // (2) Clear any previous features in the item + item.features.clear(); + + // (3) Read features from request response and add them to the item + const readFeatures = new olFormatWFS().readFeatures(response.data); + if (readFeatures) { + item.features.extend(readFeatures); + } + }); + +}; + + +/** + * Called when the map view changes. Load all active cache items after a small + * delay. Cancel any currently delayed call, if required. + * @private + */ +exports.prototype.handleMapMoveEnd_ = function() { + if (this.mapViewChangePromise_) { + this.timeout_.cancel(this.mapViewChangePromise_); + } + this.mapViewChangePromise_ = this.timeout_( + this.loadAllItems_.bind(this), + 400 + ); +}; + + +/** + * @typedef {Object} + */ +exports.Cache; + + +/** + * @typedef {{ + * active: (boolean), + * featureNS: (string), + * featurePrefix: (string), + * features: (ol.Collection.), + * geometryName: (string), + * interaction: (?ol.interaction.Snap), + * maxFeatures: (number), + * requestDeferred: (?angular.$q.Deferred), + * snappingConfig: (gmfThemes.GmfSnappingConfig), + * stateWatcherUnregister: (Function), + * treeCtrl: (ngeo.layertree.Controller), + * wfsConfig: (gmf.editing.Snapping.WFSConfig) + * }} + */ +exports.CacheItem; + + +/** + * @typedef {{ + * featureTypes: (string), + * url: (string) + * }} + */ +exports.WFSConfig; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfSnapping', [ + gmfLayertreeTreeManager.module.name, + gmfThemeThemes.module.name, + ngeoLayertreeController.module.name, +]); +exports.module.service('gmfSnapping', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/XSDAttributes.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/XSDAttributes.js new file mode 100644 index 000000000..fdc8b17e5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/XSDAttributes.js @@ -0,0 +1,70 @@ +/** + * @module gmf.editing.XSDAttributes + */ +import ngeoFormatXSDAttribute from 'ngeo/format/XSDAttribute.js'; + +/** + * An service used to fetch the XSD attribute definition of layers using their + * id from a GeoMapFish server. + * + * @constructor + * @struct + * @param {angular.$http} $http Angular http service. + * @param {string} gmfLayersUrl Url to the GeoMapFish layers service. + * @ngInject + */ +const exports = function($http, gmfLayersUrl) { + + /** + * @type {angular.$http} + * @private + */ + this.http_ = $http; + + /** + * @type {string} + * @private + */ + this.baseUrl_ = gmfLayersUrl; + + /** + * @type {Object.} + * @private + */ + this.promises_ = {}; + +}; + + +/** + * @param {number} id Layer id. + * @return {angular.$q.Promise} Promise. + * @export + */ +exports.prototype.getAttributes = function(id) { + if (!this.promises_[id]) { + const url = `${this.baseUrl_}/${id}/md.xsd`; + this.promises_[id] = this.http_.get(url).then( + this.handleGetAttributes_.bind(this)); + } + return this.promises_[id]; +}; + +/** + * @param {angular.$http.Response} resp Ajax response. + * @return {Array.} List of attributes. + * @export + */ +exports.prototype.handleGetAttributes_ = function(resp) { + return new ngeoFormatXSDAttribute().read(resp.data); +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfXSDAttributes', []); +exports.module.service('gmfXSDAttributes', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureComponent.html new file mode 100644 index 000000000..561eaebda --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureComponent.html @@ -0,0 +1,133 @@ +
+ + + + + + + + + + +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureComponent.js new file mode 100644 index 000000000..3d1b33380 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureComponent.js @@ -0,0 +1,1300 @@ +/** + * @module gmf.editing.editFeatureComponent + */ +import gmfEditingEditFeature from 'gmf/editing/EditFeature.js'; + +/** @suppress {extraRequire} */ +import gmfEditingSnapping from 'gmf/editing/Snapping.js'; + +import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes.js'; +import gmfLayertreeSyncLayertreeMap from 'gmf/layertree/SyncLayertreeMap.js'; +import googAsserts from 'goog/asserts.js'; +import DateFormatter from 'ngeo/misc/php-date-formatter.js'; +import 'jquery-datetimepicker/jquery.datetimepicker.js'; +import 'jquery-datetimepicker/jquery.datetimepicker.css'; + + +/** @suppress {extraRequire} */ +import ngeoEditingAttributesComponent from 'ngeo/editing/attributesComponent.js'; + +/** @suppress {extraRequire} */ +import ngeoEditingCreatefeatureComponent from 'ngeo/editing/createfeatureComponent.js'; + +import ngeoUtils from 'ngeo/utils.js'; +import ngeoFormatXSDAttribute from 'ngeo/format/XSDAttribute.js'; +import ngeoGeometryType from 'ngeo/GeometryType.js'; +import ngeoInteractionRotate from 'ngeo/interaction/Rotate.js'; +import ngeoInteractionTranslate from 'ngeo/interaction/Translate.js'; +import ngeoMapLayerHelper from 'ngeo/map/LayerHelper.js'; +import ngeoMenu from 'ngeo/Menu.js'; + +/** @suppress {extraRequire} */ +import ngeoMessageModalComponent from 'ngeo/message/modalComponent.js'; + +/** @suppress {extraRequire} */ +import ngeoMiscBtnComponent from 'ngeo/misc/btnComponent.js'; + +import ngeoMiscDecorate from 'ngeo/misc/decorate.js'; +import ngeoMiscEventHelper from 'ngeo/misc/EventHelper.js'; +import ngeoMiscFeatureHelper from 'ngeo/misc/FeatureHelper.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; + +/** @suppress {extraRequire} */ +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; + +import * as olBase from 'ol/index.js'; +import * as olArray from 'ol/array.js'; +import olCollection from 'ol/Collection.js'; +import * as olEvents from 'ol/events.js'; +import * as olExtent from 'ol/extent.js'; +import olFeature from 'ol/Feature.js'; +import olFormatGeoJSON from 'ol/format/GeoJSON.js'; +import olInteractionModify from 'ol/interaction/Modify.js'; +import olLayerImage from 'ol/layer/Image.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStyle from 'ol/style/Style.js'; +import olStyleText from 'ol/style/Text.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('GmfEditingFeatureComponent', [ + gmfEditingEditFeature.module.name, + gmfEditingSnapping.module.name, + gmfEditingXSDAttributes.module.name, + ngeoEditingAttributesComponent.name, + ngeoEditingCreatefeatureComponent.name, + ngeoMapLayerHelper.module.name, + ngeoMessageModalComponent.name, + ngeoMiscBtnComponent.name, + ngeoMiscEventHelper.module.name, + ngeoMiscFeatureHelper.module.name, + ngeoMiscToolActivateMgr.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/editing/editFeatureComponent', require('./editFeatureComponent.html')); +}); + + +/** + * Directive used to insert, modify and delete features from a single layer. + * It allows you to modify the geometry of the feature in addition to its + * attributes. + * + * In order to modify or delete a feature, you must click on the map at the + * location of the feature to select it first. + * + * In order to create a new feature, you use the "Draw" button and digitize + * the feature on the map. + * + * Example: + * + * + * gmf-editfeature-closeaftersave="::ctrl.closeaftersave"> + * + * + * @htmlAttribute {boolean} gmf-editfeature-dirty Flag that is toggled as soon + * as the feature changes, i.e. if any of its properties change, which + * includes the geometry. + * @htmlAttribute {ngeo.layertree.Controller} gmf-editfeature-editabletreectrl + * A reference to the editable Layertree controller, which contains a + * a reference to the node and WMS layer. + * @htmlAttribute {ol.Map} gmf-editfeature-map The map. + * @htmlAttribute {string} gmf-editfeature-state The state property shared + * with the `gmf-editfeatureselector` directive. For more info, see in + * that directive. + * @htmlAttribute {number|undefined} gmf-editfeatureselector-tolerance The + * buffer in pixels to use when making queries to get the features. + * @htmlAttribute {ol.layer.Vector} gmf-editfeature-vector The vector layer in + * which to draw the vector features. + * @htmlAttribute {boolean} gmf-editfeatureselector-closeaftersave If true, + * immediately return to the main edit panel after save. Default is false. + * @return {angular.Directive} The directive specs. + * @ngdoc directive + * @ngname gmfEditfeature + */ +exports.component_ = function() { + return { + controller: 'GmfEditfeatureController as efCtrl', + scope: { + 'dirty': '=gmfEditfeatureDirty', + 'editableTreeCtrl': '=gmfEditfeatureEditabletreectrl', + 'map': ' this.feature, + this.handleFeatureChange_.bind(this) + ); + + /** + * @type {number|string|undefined} + * @export + */ + this.featureId = undefined; + + /** + * @type {ol.Collection} + * @export + */ + this.features; + + /** + * @type {ol.Collection} + * @private + */ + this.interactions_ = new olCollection(); + + /** + * @type {ol.interaction.Modify} + * @private + */ + this.modify_; + + /** + * @type {ngeo.misc.ToolActivate} + * @export + */ + this.modifyToolActivate; + + /** + * @type {ngeo.Menu} + * @private + */ + this.menu_ = new ngeoMenu({ + actions: [{ + cls: 'fa fa-arrows', + label: gettextCatalog.getString('Move'), + name: 'move' + }, { + cls: 'fa fa-rotate-right', + label: gettextCatalog.getString('Rotate'), + name: 'rotate' + }] + }); + + /** + * @type {ngeo.interaction.Translate} + * @private + */ + this.translate_; + + /** + * @type {ngeo.interaction.Rotate} + * @private + */ + this.rotate_; + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.rotateToolActivate; + + /** + * @type {!ngeo.misc.ToolActivate} + * @export + */ + this.translateToolActivate; + + /** + * @type {!Array.} + * @private + */ + this.listenerKeys_ = []; + + /** + * @type {?Array.} + * @export + */ + this.attributes = null; + + /** + * @type {string|undefined} + * @export + */ + this.geomType; + + /** + * @type {boolean} + * @export + */ + this.showServerError = false; + + /** + * @type {?string} + * @export + */ + this.serverErrorMessage = null; + + /** + * @type {?string} + * @export + */ + this.serverErrorType = null; +}; + + +/** + * Called on initialization of the controller. + */ +exports.Controller_.prototype.$onInit = function() { + const lang = this.gettextCatalog_.getCurrentLanguage(); + $.datetimepicker.setLocale(lang); + $.datetimepicker.setDateFormatter(new DateFormatter()); + + // (1) Set default values and other properties + this.dirty = this.dirty === true; + this.editableNode_ = /** @type {gmfThemes.GmfLayer} */ ( + this.editableTreeCtrl.node); + this.features = this.vectorLayer.getSource().getFeaturesCollection(); + this.tolerance = this.tolerance !== undefined ? this.tolerance : 10; + + // (1.1) Set editable WMS layer + const layer = gmfLayertreeSyncLayertreeMap.getLayer(this.editableTreeCtrl); + googAsserts.assert( + layer instanceof olLayerImage || layer instanceof olLayerTile); + this.editableWMSLayer_ = layer; + + // (1.2) Create, set and initialize interactions + this.modify_ = new olInteractionModify({ + deleteCondition: ngeoUtils.deleteCondition, + features: this.features, + style: this.ngeoFeatureHelper_.getVertexStyle(false) + }); + this.interactions_.push(this.modify_); + + this.rotate_ = new ngeoInteractionRotate({ + features: this.features, + style: new olStyleStyle({ + text: new olStyleText({ + text: '\uf01e', + font: 'normal 18px FontAwesome', + fill: new olStyleFill({ + color: '#7a7a7a' + }) + }) + }) + }); + this.interactions_.push(this.rotate_); + + this.translate_ = new ngeoInteractionTranslate({ + features: this.features, + style: new olStyleStyle({ + text: new olStyleText({ + text: '\uf047', + font: 'normal 18px FontAwesome', + fill: new olStyleFill({ + color: '#7a7a7a' + }) + }) + }) + }); + this.interactions_.push(this.translate_); + + this.initializeInteractions_(); + + this.modifyToolActivate = new ngeoMiscToolActivate(this.modify_, 'active'); + this.rotateToolActivate = new ngeoMiscToolActivate(this.rotate_, 'active'); + this.translateToolActivate = new ngeoMiscToolActivate(this.translate_, 'active'); + + // (1.3) Add menu to map + this.map.addOverlay(this.menu_); + + + // (2) Watchers and event listeners + this.scope_.$watch( + () => this.createActive, + (newVal, oldVal) => { + if (newVal) { + this.gmfSnapping_.ensureSnapInteractionsOnTop(); + } + } + ); + + this.scope_.$on('$destroy', this.handleDestroy_.bind(this)); + + const uid = olBase.getUid(this); + this.ngeoEventHelper_.addListenerKey( + uid, + olEvents.listen( + this.features, + 'add', + this.handleFeatureAdd_, + this + ) + ); + + this.scope_.$watch( + () => this.mapSelectActive, + this.handleMapSelectActiveChange_.bind(this) + ); + + this.scope_.$watch( + () => this.state, + (newValue, oldValue) => { + const state = exports.State; + if (newValue === state.STOP_EDITING_PENDING) { + this.confirmCancel().then(() => { + this.state = state.STOP_EDITING_EXECUTE; + }); + } else if (newValue === state.DEACTIVATE_PENDING) { + this.confirmCancel().then(() => { + this.state = state.DEACTIVATE_EXECUTE; + }); + } + } + ); + + this.scope_.$watch( + () => this.unsavedModificationsModalShown, + (newValue, oldValue) => { + // Reset stop request when closing the confirmation modal + if (oldValue && !newValue) { + this.state = exports.State.IDLE; + } + } + ); + + + // (3) Get attributes + this.gmfXSDAttributes_.getAttributes(this.editableNode_.id).then( + this.setAttributes_.bind(this)); + + + // (4) Toggle + this.toggle_(true); + +}; + + +/** + * Save the currently selected feature modifications. + * @export + */ +exports.Controller_.prototype.save = function() { + googAsserts.assert(this.attributes); + + const feature = this.feature.clone(); + feature.setId(this.feature.getId()); + const id = this.featureId; + + this.pending = true; + + const dateFormatter = new DateFormatter(); + for (const attribute of this.attributes) { + if (attribute.format) { + if (this.feature.get(attribute.name)) { + const name = this.feature.get(attribute.name); + googAsserts.assertString(name); + const value = dateFormatter.parseDate(name, attribute.format); + let jsonFormat = 'Y-m-d\\TH:i:s'; + if (attribute.type === 'date') { + jsonFormat = 'Y-m-d'; + } else if (attribute.type === 'time') { + jsonFormat = 'H:i:s'; + } else if (attribute.type === 'datetime') { + // Time zone correction + value.setMinutes(value.getMinutes() + value.getTimezoneOffset()); + } + feature.set(attribute.name, dateFormatter.formatDate(value, jsonFormat)); + } else { + // Shouldn't be set to an empty string + feature.set(attribute.name, null); + } + } + } + + const promise = id ? + this.gmfEditFeature_.updateFeature( + this.editableNode_.id, + feature + ) : + this.gmfEditFeature_.insertFeatures( + this.editableNode_.id, + [feature] + ); + promise.then( + (response) => { + this.dirty = false; + this.pending = false; + this.handleEditFeature_(response); + this.gmfSnapping_.refresh(); + if (this.closeAfterSave) { + this.cancel(); + } + }, + (response) => { + this.showServerError = true; + this.pending = false; + this.serverErrorType = `error type : ${response.data['error_type']}`; + this.serverErrorMessage = `error message : ${response.data['message']}`; + } + ); +}; + + +/** + * @export + */ +exports.Controller_.prototype.cancel = function() { + this.dirty = false; + this.feature = null; + this.features.clear(); + this.menu_.close(); + this.unsavedModificationsModalShown = false; +}; + + +/** + * Check if there are unsaved modifications. If there aren't, then cancel. + * Used by the 'cancel' button in the template. + * @return {angular.$q.Promise} The promise attached to the confirm deferred + * object. + * @export + */ +exports.Controller_.prototype.confirmCancel = function() { + return this.checkForModifications_().then(() => { + this.cancel(); + }); +}; + + +/** + * Check if there's a feature selected and if it contains modifications + * (a.k.a. is dirty), then the confirmation modal is shown. + * @param {boolean=} scopeApply Whether to force scope to refresh or not. + * when the confirm modal is not dismissed. + * @return {angular.$q.Promise} The promise attached to the confirm deferred + * object. + * @private + */ +exports.Controller_.prototype.checkForModifications_ = function( + scopeApply) { + this.confirmDeferred_ = this.q_.defer(); + if (this.feature && this.dirty) { + this.unsavedModificationsModalShown = true; + if (scopeApply) { + this.scope_.$apply(); + } + } else { + this.confirmDeferred_.resolve(); + } + + return this.confirmDeferred_.promise; +}; + + +/** + * @export + */ +exports.Controller_.prototype.continueWithoutSaving = function() { + this.cancel(); + this.confirmDeferred_.resolve(); +}; + + +/** + * @export + */ +exports.Controller_.prototype.delete = function() { + const msg = this.gettextCatalog_.getString( + 'Do you really want to delete the selected feature?'); + // Confirm deletion first + if (confirm(msg)) { + this.pending = true; + + // (1) Launch request + this.gmfEditFeature_.deleteFeature( + this.editableNode_.id, + this.feature + ).then( + (response) => { + this.dirty = false; + this.pending = false; + this.ngeoLayerHelper_.refreshWMSLayer(this.editableWMSLayer_); + + // (2) Reset selected feature + this.cancel(); + }, + (response) => { + this.showServerError = true; + this.pending = false; + this.serverErrorType = `error type : ${response.data['error_type']}`; + this.serverErrorMessage = `error message : ${response.data['message']}`; + } + ); + + } +}; + + +/** + * Called when the modal 'save' button is clicked. Do as if the user had + * clicked on the 'save' input button in the form, which allows the form + * to be validated. + * @export + */ +exports.Controller_.prototype.submit = function() { + // Use timeout to prevent the digest already in progress + // due to clicking on the modal button to throw an error. + this.timeout_(() => { + this.element_.find('input[type="submit"]').click(); + }, 0); +}; + +/** + * Called after an insert, update or delete request. + * @param {angular.$http.Response} resp Ajax response. + * @private + */ +exports.Controller_.prototype.handleEditFeature_ = function(resp) { + const features = new olFormatGeoJSON().readFeatures(resp.data); + if (features.length) { + this.feature.setId(features[0].getId()); + this.ngeoLayerHelper_.refreshWMSLayer(this.editableWMSLayer_); + } + if (this.confirmDeferred_) { + this.confirmDeferred_.resolve(); + } +}; + + +/** + * @param {!Array.} attributes Attributes. + * @private + */ +exports.Controller_.prototype.setAttributes_ = function(attributes) { + // Set attributes + this.attributes = attributes; + for (const attribute of attributes) { + if (attribute.type == 'date') { + attribute.format = 'Y-m-d'; + attribute.mask = '9999-19-39'; + } else if (attribute.type == 'time') { + attribute.format = 'H:i'; + attribute.mask = '29:59'; + } else if (attribute.type == 'datetime') { + attribute.format = 'Y-m-d H:i'; + attribute.mask = '9999-19-39 29:59'; + } + } + + // Get geom type from attributes and set + const geomAttr = ngeoFormatXSDAttribute.getGeometryAttribute( + this.attributes + ); + if (geomAttr && geomAttr.geomType) { + this.geomType = geomAttr.geomType; + } +}; + + +/** + * @param {ol.Collection.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleFeatureAdd_ = function(evt) { + this.feature = null; + this.timeout_(() => { + googAsserts.assert(this.attributes); + const feature = evt.element; + googAsserts.assertInstanceof(feature, olFeature); + const dateFormatter = new DateFormatter(); + for (const attribute of this.attributes) { + if (attribute.format) { + if (feature.get(attribute.name)) { + let value; + if (attribute.type === 'datetime') { + value = new Date(feature.get(attribute.name)); + // Time zone correction + value.setMinutes(value.getMinutes() - value.getTimezoneOffset()); + } else { + let jsonFormat = ''; + if (attribute.type === 'date') { + jsonFormat = 'Y-m-d'; + } else if (attribute.type === 'time') { + jsonFormat = 'H:i:s'; + } + const name = feature.get(attribute.name); + googAsserts.assertString(name); + value = dateFormatter.parseDate(name, jsonFormat); + } + feature.set(attribute.name, dateFormatter.formatDate(value, attribute.format)); + } else { + // Shouldn't be set to an empty string + feature.set(attribute.name, null); + } + } + } + this.feature = feature; + this.createActive = false; + if (!feature.getId()) { + this.dirty = true; + } + this.scope_.$apply(); + }, 0); +}; + + +/** + * Activate or deactivate this directive. + * @param {boolean} active Whether to activate this directive or not. + * @private + */ +exports.Controller_.prototype.toggle_ = function(active) { + + const keys = this.listenerKeys_; + const createUid = ['create-', olBase.getUid(this)].join('-'); + const otherUid = ['other-', olBase.getUid(this)].join('-'); + const toolMgr = this.ngeoToolActivateMgr_; + + if (active) { + + // FIXME + //this.registerInteractions_(); + + keys.push(olEvents.listen(this.menu_, 'actionclick', + this.handleMenuActionClick_, this)); + + keys.push(olEvents.listen(this.translate_, + 'translateend', + this.handleTranslateEnd_, this)); + + keys.push(olEvents.listen(this.rotate_, 'rotateend', this.handleRotateEnd_, this)); + + toolMgr.registerTool(createUid, this.createToolActivate, false); + toolMgr.registerTool(createUid, this.mapSelectToolActivate, true); + + toolMgr.registerTool(otherUid, this.createToolActivate, false); + toolMgr.registerTool(otherUid, this.modifyToolActivate, true); + toolMgr.registerTool(otherUid, this.translateToolActivate, false); + toolMgr.registerTool(otherUid, this.rotateToolActivate, false); + + } else { + + // FIXME + //this.unregisterInteractions_(); + + keys.forEach(olEvents.unlistenByKey); + keys.length = 0; + + toolMgr.unregisterTool(createUid, this.createToolActivate); + toolMgr.unregisterTool(createUid, this.mapSelectToolActivate); + + toolMgr.unregisterTool(otherUid, this.createToolActivate); + toolMgr.unregisterTool(otherUid, this.modifyToolActivate); + toolMgr.unregisterTool(otherUid, this.translateToolActivate); + toolMgr.unregisterTool(otherUid, this.rotateToolActivate); + + this.createActive = false; + this.cancel(); + } + + this.modify_.setActive(active); + this.mapSelectActive = active; + this.editableTreeCtrl.properties['editing'] = active; + +}; + + +/** + * Called when the mapSelectActive property changes. + * @param {boolean} active Whether the map select is active or not. + * @private + */ +exports.Controller_.prototype.handleMapSelectActiveChange_ = function( + active) { + + const mapDiv = this.map.getViewport(); + googAsserts.assertElement(mapDiv); + + if (active) { + olEvents.listen(this.map, 'click', + this.handleMapClick_, this); + + olEvents.listen(mapDiv, 'contextmenu', + this.handleMapContextMenu_, this); + + } else { + olEvents.unlisten(this.map, 'click', + this.handleMapClick_, this); + + olEvents.unlisten(mapDiv, 'contextmenu', + this.handleMapContextMenu_, this); + } +}; + + +/** + * Called when the map is clicked. + * + * (1) If a vector feature was clicked, don't do anything (i.e. allow the + * interactions to do their bidings without selecting a new feature). + * + * (2) Otherwise, if there is a feature being edited and has unsaved + * modifications, show the confirmation modal asking the user what to do + * about it. + * + * (3) If there's no feature selected or we have one without unsaved + * modifications or with modifications that were canceled, launch a query + * to fetch the features at the clicked location. + * + * @param {ol.MapBrowserEvent} evt Event. + * @private + */ +exports.Controller_.prototype.handleMapClick_ = function(evt) { + const coordinate = evt.coordinate; + const pixel = evt.pixel; + + // (1) Check if we clicked on an existing vector feature, i.e the one + // selected. In that case, no need to do any further action. + const feature = this.map.forEachFeatureAtPixel( + pixel, + (feature) => { + let ret = false; + if (olArray.includes(this.features.getArray(), feature)) { + ret = feature; + } + return ret; + }, + { + hitTolerance: 5 + } + ); + + if (feature) { + return; + } + + // (2) If a feature is being edited and has unsaved changes, show modal + // to let the user decide what to do + this.checkForModifications_(true).then(() => { + + const map = this.map; + const view = map.getView(); + const resolution = view.getResolution(); + const buffer = resolution * this.tolerance; + const extent = olExtent.buffer( + [coordinate[0], coordinate[1], coordinate[0], coordinate[1]], + buffer + ); + + // (3) Launch query to fetch features + this.gmfEditFeature_.getFeaturesInExtent( + [this.editableNode_.id], + extent + ).then(this.handleGetFeatures_.bind(this)); + + // (4) Clear any previously selected feature + this.cancel(); + + // (5) Pending + this.pending = true; + }); +}; + + +/** + * @param {Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleMapContextMenu_ = function(evt) { + const pixel = this.map.getEventPixel(evt); + const coordinate = this.map.getCoordinateFromPixel(pixel); + + let feature = this.map.forEachFeatureAtPixel( + pixel, + (feature) => { + let ret = false; + if (olArray.includes(this.features.getArray(), feature)) { + ret = feature; + } + return ret; + }, + { + hitTolerance: 7 + } + ); + + feature = feature ? feature : null; + + // show contextual menu when clicking on certain types of features + if (feature) { + const type = this.ngeoFeatureHelper_.getType(feature); + if (type === ngeoGeometryType.POLYGON || type === ngeoGeometryType.MULTI_POLYGON || + type === ngeoGeometryType.LINE_STRING || type === ngeoGeometryType.MULTI_LINE_STRING) { + this.menu_.open(coordinate); + } + evt.preventDefault(); + evt.stopPropagation(); + } +}; + + +/** + * @param {Array.} features Features. + * @private + */ +exports.Controller_.prototype.handleGetFeatures_ = function(features) { + this.pending = false; + + this.timeout_(() => { + if (features.length) { + const feature = features[0]; + this.feature = feature; + this.features.push(feature); + } + }, 0); +}; + + +/** + * Initialize interactions by setting them inactive and decorating them + * @private + */ +exports.Controller_.prototype.initializeInteractions_ = function() { + this.interactions_.forEach((interaction) => { + interaction.setActive(false); + ngeoMiscDecorate.interaction(interaction); + }); +}; + + +/** + * Register interactions by adding them to the map + * @private + */ +exports.Controller_.prototype.registerInteractions_ = function() { + this.interactions_.forEach((interaction) => { + this.map.addInteraction(interaction); + }); +}; + + +/** + * Unregister interactions, i.e. set them inactive and remove them from the map + * @private + */ +exports.Controller_.prototype.unregisterInteractions_ = function() { + this.interactions_.forEach((interaction) => { + this.map.removeInteraction(interaction); + }); +}; + + +/** + * @param {?ol.Feature} newFeature The new feature. + * @param {?ol.Feature} oldFeature The old feature. + * @private + */ +exports.Controller_.prototype.handleFeatureChange_ = function( + newFeature, oldFeature +) { + + let geom; + if (oldFeature) { + olEvents.unlisten(oldFeature, 'propertychange', this.handleFeaturePropertyChange_, this); + geom = oldFeature.getGeometry(); + googAsserts.assert(geom); + olEvents.unlisten( + geom, + 'change', + this.handleFeatureGeometryChange_, + this + ); + this.unregisterInteractions_(); + } + + if (newFeature) { + this.featureId = newFeature.getId(); + olEvents.listen(newFeature, 'propertychange', this.handleFeaturePropertyChange_, this); + geom = newFeature.getGeometry(); + googAsserts.assert(geom); + olEvents.listen( + geom, + 'change', + this.handleFeatureGeometryChange_, + this + ); + this.registerInteractions_(); + + this.gmfSnapping_.ensureSnapInteractionsOnTop(); + + // The `ui-date` triggers an unwanted change, i.e. it converts the text + // to Date, which makes the directive dirty when it shouldn't... to + // bypass this, we reset the dirty state here. We do so only if we're + // editing an existing feature + if (this.featureId) { + this.timeout_(() => { + this.dirty = false; + this.scope_.$apply(); + }, 0); + } + } else { + this.featureId = undefined; + } + +}; + + +/** + * @private + */ +exports.Controller_.prototype.handleFeaturePropertyChange_ = function() { + this.dirty = true; +}; + + +/** + * @private + */ +exports.Controller_.prototype.handleFeatureGeometryChange_ = function() { + this.dirty = true; + this.scope_.$apply(); +}; + + +/** + * @param {ngeox.MenuEvent} evt Event. + * @private + */ +exports.Controller_.prototype.handleMenuActionClick_ = function(evt) { + const action = evt.detail.action; + + switch (action) { + case 'move': + this.translate_.setActive(true); + this.scope_.$apply(); + break; + case 'rotate': + this.rotate_.setActive(true); + this.scope_.$apply(); + break; + default: + break; + } +}; + + +/** + * @param {ol.interaction.Translate.Event} evt Event. + * @private + */ +exports.Controller_.prototype.handleTranslateEnd_ = function(evt) { + this.translate_.setActive(false); + this.scope_.$apply(); +}; + + +/** + * @param {!ngeox.RotateEvent} evt Event. + * @private + */ +exports.Controller_.prototype.handleRotateEnd_ = function(evt) { + this.rotate_.setActive(false); + this.scope_.$apply(); +}; + + +/** + * @private + */ +exports.Controller_.prototype.handleDestroy_ = function() { + this.features.clear(); + this.handleFeatureChange_(null, this.feature); + this.feature = null; + const uid = olBase.getUid(this); + this.ngeoEventHelper_.clearListenerKey(uid); + this.toggle_(false); + this.handleMapSelectActiveChange_(false); + this.unregisterInteractions_(); +}; + + +exports.controller('GmfEditfeatureController', + exports.Controller_); + + +/** + * The different possible values of the `state` inner property. + * @enum {string} + */ +exports.State = { + /** + * The default state. While idle, nothing happens. + * @type {string} + */ + IDLE: 'idle', + /** + * The state active after the deactivation of the editing tools and the + * unsaved modifications were saved or discarded. + * @type {string} + */ + DEACTIVATE_EXECUTE: 'deactivate_execute', + /** + * The state active when the deactivation of the editing tools is in + * progress while there are unsaved modifications. + * @type {string} + */ + DEACTIVATE_PENDING: 'deactivate_pending', + /** + * Final state set after the "stop editing" button has been clicked while + * no unsaved modifications were made or if the user saved them or confirmed + * to continue without saving. + * @type {string} + */ + STOP_EDITING_EXECUTE: 'stop_editing_execute', + /** + * The state that is active while when the "stop editing" button has been + * clicked but before any confirmation has been made to continue. + * @type {string} + */ + STOP_EDITING_PENDING: 'stop_editing_pending' +}; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureSelectorComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureSelectorComponent.html new file mode 100644 index 000000000..6384c04f2 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureSelectorComponent.html @@ -0,0 +1,45 @@ +
+ +
+ + No editable layer available! +
+ +
+
+
+ Currently editing: + {{ efsCtrl.selectedEditableTreeCtrl.node.name | translate }} + +
+ +
+
+ + + + +
+ +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureSelectorComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureSelectorComponent.js new file mode 100644 index 000000000..e423f0e41 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/editFeatureSelectorComponent.js @@ -0,0 +1,295 @@ +/** + * @module gmf.editing.editFeatureSelectorComponent + */ +import googAsserts from 'goog/asserts.js'; + +/** @suppress {extraRequire} */ +import gmfEditingEditFeatureComponent from 'gmf/editing/editFeatureComponent.js'; + +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('GmfEditingFeatureSelectorComponent', [ + gmfEditingEditFeatureComponent.name, + gmfLayertreeTreeManager.module.name, + gmfThemeThemes.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/editing/editFeatureSelectorComponent', require('./editFeatureSelectorComponent.html')); +}); + + +/** + * Directive that uses the GMF Theme service to collect the editable layers + * and create a drop-down list out of them. When the user selects one of the + * layer from the list, a `gmf-editfeature` directive is created and shown, + * which allows the user to edit that layer. + * + * Example: + * + * + * + * + * @htmlAttribute {boolean} gmf-editfeatureselector-active Whether the + * directive is active or not. + * @htmlAttribute {ol.Map} gmf-editfeatureselector-map The map. + * @htmlAttribute {number|undefined} gmf-editfeatureselector-tolerance The + * buffer in pixels to use when making queries to get the features. + * @htmlAttribute {ol.layer.Vector} gmf-editfeatureselector-vector The vector + * layer where the selected or created features are drawn. + * @htmlAttribute {ngeo.layertree.Controller} gmf-editfeatureselector-tree The + * layertree controller handling the selectable editable layers list. + * @htmlAttribute {boolean} gmf-editfeatureselector-closeaftersave If true, + * immediately return to the main edit panel after save. Default is false. + * @return {angular.Directive} The directive specs. + * @ngdoc directive + * @ngname gmfEditfeatureselector + */ +exports.component_ = function() { + return { + controller: 'GmfEditfeatureselectorController as efsCtrl', + scope: { + 'active': '=gmfEditfeatureselectorActive', + 'map': ' this.active, + this.handleActiveChange_.bind(this) + ); + + /** + * @type {ol.Map} + * @export + */ + this.map; + + /** + * @type {number|undefined} + * @export + */ + this.tolerance; + + /** + * @type {ol.layer.Vector} + * @export + */ + this.vectorLayer; + + /** + * @type {boolean} + * @export + */ + this.closeAfterSave; + + // === Injected services === + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {angular.$timeout} + * @private + */ + this.$timeout_ = $timeout; + + /** + * @type {gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + /** + * @type {gmf.layertree.TreeManager} + * @private + */ + this.gmfTreeManager_ = gmfTreeManager; + + /** + * @param {Array.} value First level controllers. + */ + const updateEditableTreeCtrls = function(value) { + // Timeout required, because the collection event is fired before the + // leaf nodes are created and they are the ones we're looking for here. + this.$timeout_(() => { + if (value) { + const editables = this.editableTreeCtrls; + + editables.length = 0; + this.gmfTreeManager_.rootCtrl.traverseDepthFirst((treeCtrl) => { + if (treeCtrl.node.editable) { + googAsserts.assert(treeCtrl.children.length === 0); + editables.push(treeCtrl); + } + }); + } + }, 0); + }; + + /** + * @type {function()} + * @private + */ + this.treeCtrlsWatcherUnregister_ = $scope.$watchCollection(() => { + if (gmfTreeManager.rootCtrl) { + return gmfTreeManager.rootCtrl.children; + } + }, updateEditableTreeCtrls.bind(this)); + + + // === Other inner properties === + + /** + * Flag shared with the `gmf-editfeature` directive used to determine if it + * has unsaved changes or not. + * @type {boolean} + * @export + */ + this.dirty = false; + + /** + * List of editable Layertree controllers. + * @type {Array.} + * @export + */ + this.editableTreeCtrls = []; + + /** + * The currently selected Layertree controller. + * @type {?ngeo.layertree.Controller} + * @export + */ + this.selectedEditableTreeCtrl = null; + + $scope.$watch( + () => this.selectedEditableTreeCtrl, + (newValue, oldValue) => { + this.dirty = false; + this.state = gmfEditingEditFeatureComponent.State.IDLE; + } + ); + + /** + * The state of this directive shared with the `gmf-editfeature` directive. + * This property allows the proper management of the "stop editing" button. + * When clicked, the according state is set and the `gmf-editfeature` + * directive checks if it has unsaved changes and allow this directive to + * continue the action that was made or not. + * @type {string} + * @export + */ + this.state = gmfEditingEditFeatureComponent.State.IDLE; + + $scope.$watch( + () => this.state, + (newValue, oldValue) => { + if (newValue === gmfEditingEditFeatureComponent.State.STOP_EDITING_EXECUTE || + newValue === gmfEditingEditFeatureComponent.State.DEACTIVATE_EXECUTE) { + this.selectedEditableTreeCtrl = null; + } + if (newValue === gmfEditingEditFeatureComponent.State.DEACTIVATE_EXECUTE) { + this.active = false; + } + } + ); + + $scope.$on('$destroy', this.handleDestroy_.bind(this)); + +}; + + +/** + * Called when the 'stop editing' button is clicked. Set the 'state' + * variable to 'pending' allow the editfeature directive to check if it can + * stop or if it requires confirmation due to unsaved modifications. + * @export + */ +exports.Controller_.prototype.stopEditing = function() { + this.state = gmfEditingEditFeatureComponent.State.STOP_EDITING_PENDING; +}; + + +/** + * Called when the active property of the this directive changes. Manage + * the activation/deactivation accordingly. + * @param {boolean} active Whether the directive is active or not. + * @private + */ +exports.Controller_.prototype.handleActiveChange_ = function(active) { + if (!active) { + if (!this.dirty) { + this.stopEditing(); + } else { + // There are unsaved modifications. Prevent the deactivation and + // set the state accordingly for the `gmf-editfeature` directive + // to manage the unsaved modifications. + // The changes are made inside a $timeout to be taken into account + // in the next digest cycle. + this.$timeout_(() => { + this.active = true; + this.stopEditing(); + }); + } + } +}; + + +/** + * @private + */ +exports.Controller_.prototype.handleDestroy_ = function() { + this.treeCtrlsWatcherUnregister_(); +}; + + +exports.controller('GmfEditfeatureselectorController', exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/module.js new file mode 100644 index 000000000..e19655301 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/editing/module.js @@ -0,0 +1,24 @@ +/** + * @module gmf.editing.module + */ +import gmfEditingEditFeature from 'gmf/editing/EditFeature.js'; +import gmfEditingEditFeatureComponent from 'gmf/editing/editFeatureComponent.js'; +import gmfEditingEditFeatureSelectorComponent from 'gmf/editing/editFeatureSelectorComponent.js'; +import gmfEditingEnumerateAttribute from 'gmf/editing/EnumerateAttribute.js'; +import gmfEditingSnapping from 'gmf/editing/Snapping.js'; +import gmfEditingXSDAttributes from 'gmf/editing/XSDAttributes.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfEditingModule', [ + gmfEditingEditFeature.module.name, + gmfEditingEditFeatureComponent.name, + gmfEditingEditFeatureSelectorComponent.name, + gmfEditingEnumerateAttribute.module.name, + gmfEditingSnapping.module.name, + gmfEditingXSDAttributes.module.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/SavedFilters.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/SavedFilters.js new file mode 100644 index 000000000..c02ff1a7b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/SavedFilters.js @@ -0,0 +1,272 @@ +/** + * @module gmf.filters.SavedFilters + */ +import googAsserts from 'goog/asserts.js'; +import * as olArray from 'ol/array.js'; + +const exports = class { + + /** + * The GeoMapFish service responsible of storing filters that can be applied + * to data sources. A filter consists of: + * + * - a condition + * - a list of directed rules + * - a list of custom rules + * - a data source + * - a name + * + * The filters are saved in the browser local storage, if available. + * Otherwise, they are kept in this service for the duration of the visit. + * + * @param {!angular.Scope} $rootScope Angular rootScope. + * @struct + * @ngInject + * @ngdoc service + * @ngname gmfSavedFilters + */ + constructor($rootScope) { + + /** + * @type {!angular.Scope} + * @private + */ + this.rootScope_ = $rootScope; + + /** + * This service can have a data source id bound to it, which automatically + * populates an array of items that are only bound to this data source. + * @type {?number} + * @private + */ + this.currentDataSourceId_ = null; + + /** + * @type {!Array.} + * @private + */ + this.currentDataSourceItems_ = []; + + /** + * The used by this service to save in the local storage. + * @type {string} + * @private + */ + this.localStorageKey_ = 'gmf_savedfilters'; + + /** + * @type {boolean} + * @private + */ + this.useLocalStorage_ = true; + + try { + if ('localStorage' in window) { + window.localStorage['test'] = ''; + delete window.localStorage['test']; + } else { + this.useLocalStorage_ = false; + } + } catch (err) { + console.error(err); + this.useLocalStorage_ = false; + } + + /** + * @type {!Array.} + * @private + */ + this.items_ = []; + + this.rootScope_.$watchCollection( + () => this.items, + () => { + this.rePopulateCurrentDataSourceItems_(); + } + ); + + if (this.useLocalStorage_) { + this.loadItemsFromLocalStorage_(); + } + + } + + /** + * @return {!Array.} Items + * @export + */ + get currentDataSourceItems() { + return this.currentDataSourceItems_; + } + + /** + * @param {?number} id Current data source id. + * @export + */ + set currentDataSourceId(id) { + this.currentDataSourceId_ = id; + this.rePopulateCurrentDataSourceItems_(); + } + + /** + * @return {!Array.} Items + * @export + */ + get items() { + return this.items_; + } + + /** + * Read the filter items that are saved in the local storage and set them + * as this service's items. + * @private + */ + loadItemsFromLocalStorage_() { + if (window.localStorage[this.localStorageKey_]) { + const items = JSON.parse(window.localStorage[this.localStorageKey_]); + googAsserts.assertArray(items); + this.items_ = items; + } + } + + /** + * Search for an item using a given name and data source id. Returns the + * index if it exists, otherwise -1 is returned. + * @param {string} name Name. + * @param {number} id Data source id. + * @return {number} The index of the item, if it exists. + * @export + */ + indexOfItem(name, id) { + + let item; + let idx = -1; + for (let i = 0, ii = this.items_.length; i < ii; i++) { + item = this.items[i]; + if (item.dataSourceId === id && item.name === name) { + idx = i; + break; + } + } + + return idx; + } + + /** + * @param {!gmf.filters.SavedFilters.Item} item Item. + * @export + */ + save(item) { + + // (1) Add or replace item + const idx = this.indexOfItem(item.name, item.dataSourceId); + if (idx !== -1) { + this.items[idx] = item; + } else { + this.items.push(item); + } + + // (2) Update local storage + if (this.useLocalStorage_) { + this.saveItemsInLocalStorage_(); + } + } + + /** + * @param {!gmf.filters.SavedFilters.Item} item Item. + * @export + */ + remove(item) { + + // (1) Remove the item + const found = olArray.remove(this.items, item); + + // (2) Update local storage + if (found && this.useLocalStorage_) { + this.saveItemsInLocalStorage_(); + } + } + + /** + * Save all items in the local storage. + * @private + */ + saveItemsInLocalStorage_() { + window.localStorage[this.localStorageKey_] = JSON.stringify(this.items); + } + + /** + * @private + */ + rePopulateCurrentDataSourceItems_() { + // (1) Clear existing items + this.currentDataSourceItems_.length = 0; + + // (2) Populate + if (this.currentDataSourceId_ !== null) { + for (const item of this.items) { + if (item.dataSourceId === this.currentDataSourceId_) { + this.currentDataSourceItems_.push(item); + } + } + } + } + +}; + + +exports.module = angular.module('gmfSavedFilters', []); + +exports.module.service('gmfSavedFilters', exports); + + +/** + * The definition of a saved filter item. + * @constructor + * @struct + * @export + */ +exports.Item = function() {}; + + +/** + * The condition of the saved filter item. + * @type {string} + * @export + */ +exports.Item.prototype.condition; + + +/** + * The list of custom rules of the saved filter item. + * @type {!Array.} + * @export + */ +exports.Item.prototype.customRules; + + +/** + * The data source id related to the filter. + * @type {number} + * @export + */ +exports.Item.prototype.dataSourceId; + + +/** + * The list of directed rules of the saved filter item. + * @type {!Array.} + * @export + */ +exports.Item.prototype.directedRules; + + +/** + * A human-readable name given to the saved filter item. + * @type {string} + * @export + */ +exports.Item.prototype.name; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/filterselectorComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/filterselectorComponent.js new file mode 100644 index 000000000..ac6acfdfb --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/filterselectorComponent.js @@ -0,0 +1,757 @@ +/** + * @module gmf.filters.filterselectorComponent + */ + +/** @suppress {extraRequire} */ +import gmfAuthenticationService from 'gmf/authentication/Service.js'; + +import gmfDatasourceDataSourceBeingFiltered from 'gmf/datasource/DataSourceBeingFiltered.js'; + +/** @suppress {extraRequire} */ +import gmfDatasourceHelper from 'gmf/datasource/Helper.js'; + +import gmfDatasourceOGC from 'gmf/datasource/OGC.js'; +import gmfFiltersSavedFilters from 'gmf/filters/SavedFilters.js'; +import googAsserts from 'goog/asserts.js'; + +/** @suppress {extraRequire} */ +import ngeoMessageModalComponent from 'ngeo/message/modalComponent.js'; + +import ngeoMessageNotification from 'ngeo/message/Notification.js'; +import ngeoMessageMessage from 'ngeo/message/Message.js'; + +/** @suppress {extraRequire} */ +import ngeoFilterRuleHelper from 'ngeo/filter/RuleHelper.js'; + +import ngeoFilterComponent from 'ngeo/filter/component.js'; +import * as olEvents from 'ol/events.js'; +import * as olArray from 'ol/array.js'; +import ngeoMapFeatureOverlayMgr from 'ngeo/map/FeatureOverlayMgr.js'; + +import 'bootstrap/js/dropdown.js'; + + +const exports = angular.module('gmfFilterselector', [ + gmfAuthenticationService.module.name, + gmfDatasourceDataSourceBeingFiltered.module.name, + gmfDatasourceHelper.module.name, + ngeoMapFeatureOverlayMgr.module.name, + ngeoMessageNotification.module.name, + ngeoMessageModalComponent.name, + ngeoFilterRuleHelper.module.name, + ngeoFilterComponent.name, + gmfFiltersSavedFilters.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/filters/filterselectorcomponent', require('./filterselectorcomponent.html')); +}); + +exports.value('gmfFilterselectorTemplateUrl', + /** + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} The template url. + */ + ($attrs) => { + const templateUrl = $attrs['gmfFilterselectorTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/filters/filterselectorcomponent'; + }); + + +/** + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.Attributes): string} gmfFilterselectorTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfFilterselectorTemplateUrl($attrs, gmfFilterselectorTemplateUrl) { + return gmfFilterselectorTemplateUrl($attrs); +} + + +/** + * @private + */ +exports.Controller_ = class { + + /** + * @param {!angular.Scope} $scope Angular scope. + * @param {!angular.$timeout} $timeout Angular timeout service. + * @param {angularGettext.Catalog} gettextCatalog Gettext catalog. + * @param {gmfx.datasource.DataSourceBeingFiltered} gmfDataSourceBeingFiltered + * The Gmf value service that determines the data source currently being + * filtered. + * @param {gmf.datasource.Helper} gmfDataSourcesHelper Gmf data + * sources helper service. + * @param {gmf.filters.SavedFilters} gmfSavedFilters Gmf saved filters service. + * @param {gmfx.User} gmfUser User. + * @param {ngeo.message.Notification} ngeoNotification Ngeo notification service. + * @param {!ngeo.map.FeatureOverlayMgr} ngeoFeatureOverlayMgr Ngeo FeatureOverlay + * manager + * @param {!ngeo.filter.RuleHelper} ngeoRuleHelper Ngeo rule helper service. + * @private + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfFilterselectorController + */ + constructor($scope, $timeout, gettextCatalog, gmfDataSourceBeingFiltered, + gmfDataSourcesHelper, gmfSavedFilters, gmfUser, ngeoNotification, + ngeoFeatureOverlayMgr, ngeoRuleHelper + ) { + + // Binding properties + + /** + * @type {boolean} + * @export + */ + this.active; + + $scope.$watch( + () => this.active, + this.handleActiveChange_.bind(this) + ); + + /** + * @type {!ol.Map} + * @export + */ + this.map; + + /** + * @type {string} + * @export + */ + this.toolGroup; + + + // Injected properties + + /** + * @type {!angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = gettextCatalog; + + /** + * The data source that can either be selected from the list or have + * its value set from an external source (for example: the layertree) + * and that requires to be ready before it can be filtered. + * @type {gmfx.datasource.DataSourceBeingFiltered} + * @export + */ + this.gmfDataSourceBeingFiltered = gmfDataSourceBeingFiltered; + + $scope.$watch( + () => this.gmfDataSourceBeingFiltered.dataSource, + this.handleSelectedDataSourceChange_.bind(this) + ); + + /** + * @type {gmf.datasource.Helper} + * @private + */ + this.gmfDataSourcesHelper_ = gmfDataSourcesHelper; + + /** + * @type {gmf.filters.SavedFilters} + * @export + */ + this.gmfSavedFilters = gmfSavedFilters; + + // Close manage modal if the last item is removed. + $scope.$watchCollection( + () => this.gmfSavedFilters.currentDataSourceItems, + () => { + if (this.gmfSavedFilters.currentDataSourceItems.length === 0 && + this.saveFilterManageModalShown) { + this.saveFilterManageModalShown = false; + } + } + ); + + /** + * @type {gmfx.User} + * @private + */ + this.gmfUser_ = gmfUser; + + $scope.$watch( + () => this.gmfUser_.functionalities, + this.handleGmfUserFunctionalitiesChange_.bind(this) + ); + + /** + * @type {ngeo.message.Notification} + * @private + */ + this.ngeoNotification_ = ngeoNotification; + + /** + * @type {!ngeo.map.FeatureOverlay} + * @export + */ + this.featureOverlay = googAsserts.assert( + ngeoFeatureOverlayMgr.getFeatureOverlay() + ); + + /** + * @type {!ngeo.filter.RuleHelper} + * @private + */ + this.ngeoRuleHelper_ = ngeoRuleHelper; + + + // Inner properties + + /** + * @type {boolean} + * @export + */ + this.aRuleIsActive = false; + + /** + * @type {?Array.} + * @export + */ + this.customRules = null; + + /** + * @type {?Array.} + * @export + */ + this.directedRules = null; + + /** + * @type {Array.} + * @export + */ + this.filtrableDataSources = []; + + /** + * @type {Array.} + * @private + */ + this.filtrableLayerNodeNames_ = null; + + /** + * @type {gmfx.datasource.DataSources} + * @private + */ + this.gmfDataSources_ = gmfDataSourcesHelper.collection; + + /** + * @type {Array.} + * @private + */ + this.listenerKeys_ = []; + + /** + * The data source ready to be filtered, after it has been selected and + * prepared. + * @type {?gmf.datasource.OGC} + * @export + */ + this.readyDataSource = null; + + /** + * @type {!gmf.filters.filterselectorComponent.Controller_.RuleCache} + * @private + */ + this.ruleCache_ = {}; + + /** + * @type {boolean} + * @export + */ + this.saveFilterSaveModalShown = false; + + // When the modal closes, reset name + $scope.$watch( + () => this.saveFilterSaveModalShown, + () => { + this.saveFilterName = ''; + } + ); + + /** + * @type {string} + * @export + */ + this.saveFilterName = ''; + + /** + * @type {boolean} + * @export + */ + this.saveFilterManageModalShown = false; + + /** + * @type {boolean} + * @export + */ + this.enableDataSourceRegistration_ = false; + + $scope.$watch( + () => this.enableDataSourceRegistration_, + this.handleEnableDataSourceRegistrationChange_.bind(this) + ); + + /** + * The name of the data source that should be automatically selected + * by this component. + * @type {string|undefined} + * @private + */ + this.defaultFiltrableDataSourceName_; + + // Initialize the data sources registration + this.toggleDataSourceRegistration_(); + } + + + /** + * @private + */ + handleGmfUserFunctionalitiesChange_() { + const usrFunc = this.gmfUser_.functionalities; + if (usrFunc && usrFunc['filterable_layers']) { + this.filtrableLayerNodeNames_ = usrFunc['filterable_layers']; + } else { + this.filtrableLayerNodeNames_ = null; + } + if (usrFunc && + usrFunc['preset_layer_filter'] && + usrFunc['preset_layer_filter'][0] + ) { + this.defaultFiltrableDataSourceName_ = usrFunc['preset_layer_filter'][0]; + } else { + this.defaultFiltrableDataSourceName_ = undefined; + } + this.toggleDataSourceRegistration_(); + } + + + /** + * @private + */ + toggleDataSourceRegistration_() { + const newDataSourceRegistration = !!this.filtrableLayerNodeNames_; + if (this.enableDataSourceRegistration_ !== newDataSourceRegistration) { + this.enableDataSourceRegistration_ = newDataSourceRegistration; + } + } + + + /** + * Called when the active property changes. Toggle data source registration. + * Also, when deactivated, deselect data source. + * @param {boolean} active Active. + * @private + */ + handleActiveChange_(active) { + if (!active) { + this.aRuleIsActive = false; + this.timeout_(() => { + this.gmfDataSourceBeingFiltered.dataSource = null; + }); + } + } + + + /** + * @param {boolean} register Whether register the data sources or not. + * @private + */ + handleEnableDataSourceRegistrationChange_(register) { + const keys = this.listenerKeys_; + + if (register) { + // Listen to data sources being added/removed + keys.push( + olEvents.listen(this.gmfDataSources_, 'add', this.handleDataSourcesAdd_, this), + olEvents.listen(this.gmfDataSources_, 'remove', this.handleDataSourcesRemove_, this) + ); + + // Manage the data sources that are already in the collection + this.gmfDataSources_.forEach(this.registerDataSource_.bind(this)); + + } else { + keys.forEach(olEvents.unlistenByKey); + keys.length = 0; + + // Remove data sources that are in the collection + this.filtrableDataSources.length = 0; + } + } + + + /** + * Called when a data source is added to the collection of ngeo data sources. + * If the data source is 'valid', add it to the list of filtrable data + * sources. + * + * @param {ol.Collection.Event} evt Collection event. + * @private + */ + handleDataSourcesAdd_(evt) { + const dataSource = evt.element; + if (dataSource instanceof gmfDatasourceOGC) { + this.registerDataSource_(dataSource); + } + } + + + /** + * Called when a data source is removed from the collection of ngeo data + * sources. If the data source is 'valid', remove it from the list of + * filtrable data sources. + * + * @param {ol.Collection.Event} evt Collection event. + * @private + */ + handleDataSourcesRemove_(evt) { + const dataSource = evt.element; + if (dataSource instanceof gmfDatasourceOGC) { + this.unregisterDataSource_(dataSource); + } + } + + + /** + * Register a data source if filtrable. If it's the first time that the + * data source is about to be registered, then the `filtrable` property + * is set. Otherwise, it's used. + * + * @param {gmf.datasource.OGC} dataSource Data source + * @private + */ + registerDataSource_(dataSource) { + if (dataSource.filtrable === null) { + dataSource.filtrable = this.isDataSourceFiltrable_(dataSource); + } + + if (dataSource.filtrable) { + this.filtrableDataSources.push(dataSource); + + if (this.defaultFiltrableDataSourceName_ !== undefined && + dataSource.name === this.defaultFiltrableDataSourceName_ + ) { + this.gmfDataSourceBeingFiltered.dataSource = dataSource; + } + } + } + + + /** + * Unregister a data source if it's filtrable. Also, if it's the one + * that was currently selected, deselect it. + * @param {gmf.datasource.OGC} dataSource Data source + * @private + */ + unregisterDataSource_(dataSource) { + if (dataSource.filtrable) { + olArray.remove(this.filtrableDataSources, dataSource); + + if (this.gmfDataSourceBeingFiltered.dataSource === dataSource) { + this.gmfDataSourceBeingFiltered.dataSource = null; + } + } + } + + + /** + * Determines whether the data source is valid for addition (or removal) to + * the list of filtrable data sources or not. + * + * To be filtrable, the data source must: + * + * 1) have its name in the list of filtrable layer node names + * 2) support WFS + * 3) have only one ogcLayers defined + * 4) the ogcLayer must be queryable + * + * If 1) is true but not any of the others, then the server has not been + * configured properly. In this case, a warning notification can be shown. + * + * @param {gmf.datasource.OGC} dataSource GMF data source object + * @param {boolean=} opt_notify Whether to show a warning notification or not + * in case of a data source that has its name is in the list of + * filtrable layer node names but it doesn't match the other requirements. + * Defaults to `true.` + * @return {boolean} Whether the data source is valid to add to the list or + * not. + * @private + */ + isDataSourceFiltrable_(dataSource, opt_notify) { + let filtrable = true; + const gettext = this.gettextCatalog_; + const notify = opt_notify !== false; + const names = googAsserts.assert(this.filtrableLayerNodeNames_); + const msgs = []; + + // (1) The name of the DS must be in list of filtrable layer node names + if (olArray.includes(names, dataSource.name)) { + + // (2) The DS must support WFS + if (!dataSource.supportsWFS) { + msgs.push(gettext.getString( + 'The data source doesn\'t support WFS, which is required ' + + 'to fetch the attributes to build the filter rules.' + )); + } + + // (3) The DS must have only one ogcLayer + if (!dataSource.ogcLayers || !dataSource.ogcLayers.length) { + msgs.push(gettext.getString( + 'The data source must have only 1 ogcLayer defined.' + )); + } else if (!dataSource.ogcLayers[0].queryable) { + // (4) The ogcLayer must be queryable + msgs.push(gettext.getString( + 'The ogcLayer within the data source must be queryable.' + )); + } + + filtrable = !msgs.length; + + // Notify if the name is in list of filtrable layer node names but + // there are missing requirements. + if (notify && !filtrable) { + const p1 = gettext.getString( + `The following data source is marked as being filtrable, + but is missing some requirements: ` + ); + const p2 = `${dataSource.name} (${dataSource.id}).`; + const p3 = gettext.getString( + `Please, contact your administrator about this. + Here are the reasons: ` + ); + msgs.unshift(`${p1} ${p2} ${p3}`); + console.warn(msgs.join(' ')); + this.ngeoNotification_.notify({ + msg: msgs.join(' '), + type: ngeoMessageMessage.Type.WARNING + }); + } + } else { + filtrable = false; + } + + return filtrable; + } + + /** + * @param {?gmf.datasource.OGC} dataSource Newly selected data source + * object. + * @private + */ + handleSelectedDataSourceChange_(dataSource) { + + this.aRuleIsActive = false; + this.customRules = null; + this.directedRules = null; + this.readyDataSource = null; + this.gmfSavedFilters.currentDataSourceId = null; + + // No need to do anything if no data source is selected + if (!dataSource) { + return; + } + + // A data source has been selected. Make sure the component is active. + if (!this.active) { + this.active = true; + } + + this.gmfDataSourcesHelper_.prepareFiltrableDataSource( + dataSource + ).then((dataSource) => { + + // Data source is ready. Get any existing rules or create new ones from + // the attributes + let item = this.getRuleCacheItem_(dataSource); + if (!item) { + item = { + customRules: [], + directedRules: [] + }; + this.setRuleCacheItem_(dataSource, item); + if (dataSource.gmfLayer.metadata && + dataSource.gmfLayer.metadata.directedFilterAttributes && + dataSource.gmfLayer.metadata.directedFilterAttributes.length + ) { + const directedAttributes = + dataSource.gmfLayer.metadata.directedFilterAttributes; + const attributes = googAsserts.assert(dataSource.attributes); + for (const attribute of attributes) { + if (olArray.includes(directedAttributes, attribute.name)) { + item.directedRules.push( + this.ngeoRuleHelper_.createRuleFromAttribute(attribute) + ); + } + } + } + } + + this.customRules = item.customRules; + this.directedRules = item.directedRules; + this.readyDataSource = dataSource; + this.gmfSavedFilters.currentDataSourceId = dataSource.id; + + }); + } + + /** + * @param {ngeo.datasource.DataSource} dataSource Data source. + * @return {?gmf.filters.filterselectorComponent.Controller_.RuleCacheItem} Rule cache item. + * @private + */ + getRuleCacheItem_(dataSource) { + return this.ruleCache_[dataSource.id] || null; + } + + /** + * @param {ngeo.datasource.DataSource} dataSource Data source. + * @param {gmf.filters.filterselectorComponent.Controller_.RuleCacheItem} item Rule cache item. + * @private + */ + setRuleCacheItem_(dataSource, item) { + this.ruleCache_[dataSource.id] = item; + } + + /** + * @export + */ + saveFilterShowModal() { + this.saveFilterSaveModalShown = true; + } + + /** + * @export + */ + saveFilterSave() { + + const name = this.saveFilterName; + const dataSource = googAsserts.assert(this.readyDataSource); + const dataSourceId = dataSource.id; + const alreadyExist = (this.gmfSavedFilters.indexOfItem( + name, dataSourceId) !== -1); + const condition = dataSource.filterCondition; + + const msg = this.gettextCatalog_.getString( + `A filter with the same name already exists. + Do you want to overwrite it?` + ); + if (!alreadyExist || confirm(msg)) { + // (1) Serialize the existing custom and directed rules + const customRules = this.customRules ? + this.ngeoRuleHelper_.serializeRules(this.customRules) : []; + const directedRules = this.directedRules ? + this.ngeoRuleHelper_.serializeRules(this.directedRules) : []; + + // (2) Ask the service to save it + const item = /** @type {!gmf.filters.SavedFilters.Item} */ ({ + condition, + customRules, + dataSourceId, + directedRules, + name + }); + this.gmfSavedFilters.save(item); + + // (3) Close popup, which resets the name + this.saveFilterSaveModalShown = false; + } + } + + /** + * Load a saved filter item, replacing the current rules. + * @param {!gmf.filters.SavedFilters.Item} filterItem Filter item. + * @export + */ + saveFilterLoadItem(filterItem) { + + const dataSource = googAsserts.assert(this.readyDataSource); + + // (1) Reset current rules + this.customRules = null; + this.directedRules = null; + + const customRules = this.ngeoRuleHelper_.createRules( + filterItem.customRules); + const directedRules = this.ngeoRuleHelper_.createRules( + filterItem.directedRules); + + // Timeout, which ensures the destruction of the previous filter component + // and the creation of a new one + this.timeout_(() => { + // (2) Set rules + this.customRules = customRules; + this.directedRules = directedRules; + + // (3) Set condition + dataSource.filterCondition = filterItem.condition; + + // (4) Update cache item + const cacheItem = googAsserts.assert(this.getRuleCacheItem_(dataSource)); + cacheItem.customRules = customRules; + cacheItem.directedRules = directedRules; + }); + } + + /** + * @export + */ + saveFilterManage() { + this.saveFilterManageModalShown = true; + } + + /** + * Remove a saved filter item. + * @param {!gmf.filters.SavedFilters.Item} item Filter item. + * @export + */ + saveFilterRemoveItem(item) { + this.gmfSavedFilters.remove(item); + } + +}; + + +/** + * @typedef {Object.} + */ +exports.Controller_.RuleCache; + + +/** + * @typedef {{ + * customRules: (Array.), + * directedRules: (Array.) + * }} + */ +exports.Controller_.RuleCacheItem; + + +exports.component('gmfFilterselector', { + bindings: { + active: '=', + map: '<', + toolGroup: '<' + }, + controller: exports.Controller_, + templateUrl: gmfFilterselectorTemplateUrl +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/filterselectorcomponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/filterselectorcomponent.html new file mode 100644 index 000000000..927158056 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/filterselectorcomponent.html @@ -0,0 +1,138 @@ +
+ No filtrable layer available! + + + + + + + + + + + +
+ + + +
+
+ +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/module.js new file mode 100644 index 000000000..0b90d8622 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/filters/module.js @@ -0,0 +1,16 @@ +/** + * @module gmf.filters.module + */ +import gmfFiltersFilterselectorComponent from 'gmf/filters/filterselectorComponent.js'; +import gmfFiltersSavedFilters from 'gmf/filters/SavedFilters.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfFiltersModule', [ + gmfFiltersFilterselectorComponent.name, + gmfFiltersSavedFilters.module.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/import.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/import.less new file mode 100644 index 000000000..6a1ae6cd4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/import.less @@ -0,0 +1,153 @@ +@import "~font-awesome/less/variables.less"; +@import "~gmf/less/typeahead.less"; +@import "~gmf/less/vars.less"; +@import "~bootstrap/less/variables.less"; + +gmf-importdatasource { + input[type=file] { + display: none; + } + + .gmf-importdatasource-url-form-group { + background-color: #fff; + } + .btn.has-error { + color: @brand-danger; + } +} + +gmf-wmscapabilitylayertreenode, +gmf-wmtscapabilitylayertree { + display: block; + + a { + color: black; + text-decoration: none; + + &:focus, + &:hover { + text-decoration: none; + } + } + + ul { + margin: 0; + padding: 0; + } + + li { + list-style: none; + padding: 0.2rem; + } + + > ul > li > gmf-wmscapabilitylayertreenode { + margin: 0.5rem 0 0.5rem 1rem; + } +} + +.gmf-importdatasource-layers { + height: ~"calc(100% - 19rem)"; + + > gmf-wmscapabilitylayertreenode, + > gmf-wmtscapabilitylayertree { + background-color: white; + border: 0.1rem solid #ccc; + height: ~"calc(100% - 2rem)"; + padding: 0.5rem 0.5rem 0.5rem 2rem; + overflow-y: auto; + } +} + +.gmf-wmscapabilitylayertreenode-expand-node, +.gmf-wmscapabilitylayertreenode-group, +.gmf-wmscapabilitylayertreenode-no-icon { + margin: auto 0; + width: 1.7rem; +} + +a.gmf-wmscapabilitylayertreenode-expand-node.fa { + display: inline-block; + + &::before { + content: "\f054"; + } + &[aria-expanded="true"]::before { + content: "\f078"; + } +} + +.gmf-wmscapabilitylayertreenode-group:before { + content: "\e600"; + font-family: gmf-icons; +} + +.gmf-wmscapabilitylayertreenode-popover-container { + margin: auto 0; +} + +.gmf-wmscapabilitylayertreenode-popover-content { + ul { + margin: 0; + padding: 0; + } + + li { + list-style: none; + } + + a { + cursor: pointer; + } +} + +.gmf-wmscapabilitylayertreenode-actions { + cursor: pointer; + opacity: 0; + margin: 0 0 0 -1.4rem; +} + +.gmf-wmscapabilitylayertreenode-header { + display: flex; + flex-wrap: wrap; + + &:hover > span > .gmf-wmscapabilitylayertreenode-actions { + opacity: 1; + } +} + +.gmf-wmscapabilitylayertreenode-no-icon { + font-size: 0.7rem; + vertical-align: middle; +} + +.gmf-wmscapabilitylayertreenode-title { + flex: 2; + padding: 0 0.5rem; +} + +.gmf-wmscapabilitylayertreenode-description { + background-color: #fafafa; + border: 0.1rem solid #ddd; + order: 1; + padding: 1rem; + + a { + color: #929292; + cursor: pointer; + font-size: 9pt; + + &:hover { + text-decoration: underline; + } + } +} + +.gmf-wmscapabilitylayertreenode-description-toggle { + display: block; + text-align: right; +} + + +gmf-datasourcegrouptree { + display: block; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/importdatasourceComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/importdatasourceComponent.html new file mode 100644 index 000000000..09bdf142e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/importdatasourceComponent.html @@ -0,0 +1,111 @@ +
+ +
+ +
+ +
+
+
+ + + + + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+ + + + +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/importdatasourceComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/importdatasourceComponent.js new file mode 100644 index 000000000..ea84b24c2 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/importdatasourceComponent.js @@ -0,0 +1,419 @@ +/** + * @module gmf.import.importdatasourceComponent + */ + +/** @suppress {extraRequire} */ +import gmfDatasourceExternalDataSourcesManager from 'gmf/datasource/ExternalDataSourcesManager.js'; + +/** @suppress {extraRequire} */ +import gmfImportWmsCapabilityLayertreeComponent from 'gmf/import/wmsCapabilityLayertreeComponent.js'; + +/** @suppress {extraRequire} */ +import gmfImportWmtsCapabilityLayertreeComponent from 'gmf/import/wmtsCapabilityLayertreeComponent.js'; + +import googAsserts from 'goog/asserts.js'; +import ngeoQueryQuerent from 'ngeo/query/Querent.js'; +import ngeoDatasourceOGC from 'ngeo/datasource/OGC.js'; + +const exports = angular.module('gmfImportdatasource', [ + gmfDatasourceExternalDataSourcesManager.module.name, + gmfImportWmsCapabilityLayertreeComponent.name, + gmfImportWmtsCapabilityLayertreeComponent.name, + ngeoQueryQuerent.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/import/importdatasourceComponent', require('./importdatasourceComponent.html')); +}); + + +exports.value('gmfImportdatasourceTemplateUrl', + /** + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} The template url. + */ + ($attrs) => { + const templateUrl = $attrs['gmfImportdatasourceTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/import/importdatasourceComponent'; + }); + + +/** + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.Attributes): string} gmfImportdatasourceTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfImportdatasourceTemplateUrl($attrs, gmfImportdatasourceTemplateUrl) { + return gmfImportdatasourceTemplateUrl($attrs); +} + + +/** + * @private + */ +exports.Controller_ = class { + + /** + * @param {!jQuery} $element Element. + * @param {!angular.$filter} $filter Angular filter. + * @param {!angular.$injector} $injector Main injector. + * @param {!angular.Scope} $scope Angular scope. + * @param {!angular.$timeout} $timeout Angular timeout service. + * @param {!gmf.datasource.ExternalDataSourcesManager} + * gmfExternalDataSourcesManager GMF service responsible of managing + * external data sources. + * @param {!ngeo.query.Querent} ngeoQuerent Ngeo querent service. + * @private + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfImportdatasourceController + */ + constructor($element, $filter, $injector, $scope, $timeout, + gmfExternalDataSourcesManager, ngeoQuerent) { + + // Binding properties + + /** + * @type {!ol.Map} + * @export + */ + this.map; + + + // Injected properties + + /** + * @type {!jQuery} + * @private + */ + this.element_ = $element; + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {!angular.$timeout} + * @private + */ + this.timeout_ = $timeout; + + /** + * @type {!gmf.datasource.ExternalDataSourcesManager} + * @private + */ + this.gmfExternalDataSourcesManager_ = gmfExternalDataSourcesManager; + + /** + * @type {!ngeo.query.Querent} + * @private + */ + this.ngeoQuerent_ = ngeoQuerent; + + + // Model properties + + /** + * @type {File|undefined} + * @export + */ + this.file; + + /** + * @type {string|undefined} + * @export + */ + this.url; + + + // Inner properties + + /** + * @type {!jQuery} + * @private + */ + this.fileInput_ = $element.find('input[type=file]'); + + /** + * @type {boolean} + * @export + */ + this.hasError = false; + + /** + * @type {?angular.$q.Promise} + * @private + */ + this.hasErrorPromise_ = null; + + /** + * @type {string} + * @export + */ + this.mode = exports.Controller_.Mode.ONLINE; + + /** + * @type {!Array.} + * @export + */ + this.modes = [ + exports.Controller_.Mode.LOCAL, + exports.Controller_.Mode.ONLINE + ]; + + /** + * @type {boolean} + * @export + */ + this.pending = false; + + /** + * @type {!ngeox.unitPrefix} + * @private + */ + this.unitPrefixFormat_ = /** @type {ngeox.unitPrefix} */ ( + $filter('ngeoUnitPrefix')); + + /** + * Current WMS Capabilities that were connected. + * @type {?Object} + * @export + */ + this.wmsCapabilities = null; + + /** + * Current WTMS Capabilities that were connected. + * @type {?Object} + * @export + */ + this.wmtsCapabilities = null; + + /** + * @type {Bloodhound|undefined} + * @private + */ + this.serversEngine_; + + const servers = $injector.has('gmfExternalOGCServers') ? + /** @type {Array.|undefined} */ ( + $injector.get('gmfExternalOGCServers') + ) : undefined; + + if (servers) { + const serverUrls = servers.map(server => server['url']); + this.serversEngine_ = new Bloodhound({ + /** + * Allows search queries to match from string from anywhere within + * the url, and not only from the beginning of the string (which is + * the default, non-configurable behaviour of bloodhound). + * + * Borrowed from: + * https://stackoverflow.com/questions/22059933/twitter-typeahead-js-how-to-return-all-matched-elements-within-a-string + * + * @param {BloodhoundDatum} datum Datum. + * @return {Array.} List of datum tokenizers. + */ + datumTokenizer: (datum) => { + googAsserts.assertString(datum); + const originalDatumTokenizers = Bloodhound.tokenizers.whitespace( + datum); + googAsserts.assert(originalDatumTokenizers); + const datumTokenizers = []; + for (const originalDatumTokenizer of originalDatumTokenizers) { + let i = 0; + while ((i + 1) < originalDatumTokenizer.length) { + datumTokenizers.push( + originalDatumTokenizer.substr( + i, + originalDatumTokenizer.length + ) + ); + i++; + } + } + return datumTokenizers; + }, + queryTokenizer: Bloodhound.tokenizers.whitespace, + identify: false, + local: serverUrls + }); + } + + // Register input[type=file] onchange event, use HTML5 File api + this.fileInput_.on('change', () => { + this.file = this.fileInput_[0].files && this.fileInput_[0].files[0] ? + this.fileInput_[0].files[0] : undefined; + this.scope_.$apply(); + }); + } + + /** + * Called on initialization of the component. + */ + $onInit() { + this.gmfExternalDataSourcesManager_.map = this.map; + + + if (this.serversEngine_) { + // Timeout to let Angular render the placeholder of the input properly, + // otherwise typeahead would copy the string with {{}} in it... + this.timeout_(() => { + googAsserts.assert(this.serversEngine_); + const $urlInput = this.element_.find('input[name=url]'); + const $connectBtn = this.element_.find('button.gmf-importdatasource-connect-btn'); + $urlInput.typeahead({ + hint: true, + highlight: true, + minLength: 1 + }, { + name: 'url', + source: this.serversEngine_.ttAdapter() + }).bind('typeahead:select', (ev, suggestion) => { + this.timeout_(() => { + this.url = suggestion; + this.scope_.$apply(); + $connectBtn.focus(); + }); + }); + }); + } + } + + /** + * Triggers a 'click' on the "Browse" button. + * @export + */ + browse() { + this.hasError = false; + this.element_.find('input[type=file][name=file]').click(); + } + + /** + * Connect to given online resource URL. + * @export + */ + connect() { + const url = googAsserts.assertString(this.url); + const serviceType = ngeoDatasourceOGC.guessServiceTypeByUrl(url); + + this.startWorking_(); + if (serviceType === ngeoDatasourceOGC.Type.WMS) { + this.ngeoQuerent_.wmsGetCapabilities(url).then( + (wmsCapabilities) => { + this.wmsCapabilities = wmsCapabilities; + this.stopWorking_(); + }, + () => { + // Something went wrong... + this.stopWorking_(true); + } + ); + } else if (serviceType === ngeoDatasourceOGC.Type.WMTS) { + this.ngeoQuerent_.wmtsGetCapabilities(url).then( + (wmtsCapabilities) => { + this.wmtsCapabilities = wmtsCapabilities; + this.stopWorking_(); + }, + () => { + // Something went wrong... + this.stopWorking_(true); + } + ); + } else { + // Could not determine the type of url + this.timeout_(() => { + this.stopWorking_(true); + }); + } + } + + /** + * Create data source from file. + * @export + */ + load() { + const file = googAsserts.assert(this.file); + this.gmfExternalDataSourcesManager_.createAndAddDataSourceFromFile(file, (success) => { + if (!success) { + this.hasError = true; + } + }); + } + + /** + * @return {string} The name of the file and human-readable size. + * @export + */ + get fileNameAndSize() { + let nameAndSize = ''; + + const file = this.file; + if (file !== undefined) { + const fileSize = this.unitPrefixFormat_(file.size, 'o'); + nameAndSize = `${file.name}, ${fileSize}`; + } + + return nameAndSize; + } + + + // === Private methods === + + /** + * @private + */ + startWorking_() { + this.pending = true; + this.hasError = false; + + // Clear any previous objects + this.wmsCapabilities = null; + this.wmtsCapabilities = null; + } + + /** + * @param {boolean=} opt_hasError Whether we stopped working because of after + * an error. + * @private + */ + stopWorking_(opt_hasError = false) { + this.pending = false; + if (opt_hasError) { + this.hasError = true; + if (this.hasErrorPromise_) { + this.timeout_.cancel(this.hasErrorPromise_); + } + this.hasErrorPromise_ = this.timeout_(() => { + this.hasError = false; + this.hasErrorPromise_ = null; + }, 3000); + } + } +}; + + +/** + * @enum {string} + */ +exports.Controller_.Mode = { + LOCAL: 'Local', + ONLINE: 'Online' +}; + + +exports.component('gmfImportdatasource', { + bindings: { + 'map': '<' + }, + controller: exports.Controller_, + templateUrl: gmfImportdatasourceTemplateUrl +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/module.js new file mode 100644 index 000000000..78564a0e7 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/module.js @@ -0,0 +1,20 @@ +/** + * @module gmf.import.module + */ +import gmfImportImportdatasourceComponent from 'gmf/import/importdatasourceComponent.js'; +import gmfImportWmsCapabilityLayertreeComponent from 'gmf/import/wmsCapabilityLayertreeComponent.js'; +import gmfImportWmtsCapabilityLayertreeComponent from 'gmf/import/wmtsCapabilityLayertreeComponent.js'; + +import './import.less'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfImportModule', [ + gmfImportImportdatasourceComponent.name, + gmfImportWmsCapabilityLayertreeComponent.name, + gmfImportWmtsCapabilityLayertreeComponent.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmsCapabilityLayertreeComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmsCapabilityLayertreeComponent.html new file mode 100644 index 000000000..1e7127e01 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmsCapabilityLayertreeComponent.html @@ -0,0 +1,99 @@ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmsCapabilityLayertreeComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmsCapabilityLayertreeComponent.js new file mode 100644 index 000000000..d4f3e293a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmsCapabilityLayertreeComponent.js @@ -0,0 +1,135 @@ +/** + * @module gmf.import.wmsCapabilityLayertreeComponent + */ + +/** @suppress {extraRequire} */ +import gmfDatasourceExternalDataSourcesManager from 'gmf/datasource/ExternalDataSourcesManager.js'; + +/** @suppress {extraRequire} */ +import ngeoMessagePopup from 'ngeo/message/Popup.js'; + +import * as olBase from 'ol/index.js'; + +import 'bootstrap/js/collapse.js'; + + +const exports = angular.module('gmfWmscapabilitylayertreenode', [ + gmfDatasourceExternalDataSourcesManager.module.name, + ngeoMessagePopup.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/import/wmsCapabilityLayertreeComponent', require('./wmsCapabilityLayertreeComponent.html')); +}); + + +exports.value('gmfWmscapabilitylayertreenodeTemplateUrl', + /** + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} The template url. + */ + ($attrs) => { + const templateUrl = $attrs['gmfWmscapabilitylayertreenodeTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/import/wmsCapabilityLayertreeComponent'; + }); + + +/** + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.Attributes): string} gmfWmscapabilitylayertreenodeTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfWmscapabilitylayertreenodeTemplateUrl($attrs, gmfWmscapabilitylayertreenodeTemplateUrl) { + return gmfWmscapabilitylayertreenodeTemplateUrl($attrs); +} + + +/** + * @private + */ +exports.Controller_ = class { + + /** + * @param {!gmf.datasource.ExternalDataSourcesManager} + * gmfExternalDataSourcesManager GMF service responsible of managing + * external data sources. + * @private + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfWmscapabilitylayertreenodeController + */ + constructor(gmfExternalDataSourcesManager) { + + // Binding properties + + /** + * WMS Capabilities definition + * @type {!Object} + * @export + */ + this.capabilities; + + /** + * WMS Capability Layer object. + * @type {!Object} + * @export + */ + this.layer; + + /** + * The original server url that was used to build the WMS GetCapabilities + * request. + * @type {string} + * @export + */ + this.url; + + + // Injected properties + + /** + * @type {!gmf.datasource.ExternalDataSourcesManager} + * @private + */ + this.gmfExternalDataSourcesManager_ = gmfExternalDataSourcesManager; + } + + /** + * @param {!Object} layer WMS Capability Layer object + * @export + */ + createAndAddDataSource(layer) { + this.gmfExternalDataSourcesManager_.createAndAddDataSourceFromWMSCapability( + layer, + this.capabilities, + this.url + ); + } + + /** + * @param {!Object} layer WMS Capability Layer object + * @return {number} Unique id for the Capability Layer. + * @export + */ + getUid(layer) { + return olBase.getUid(layer); + } +}; + + +exports.component('gmfWmscapabilitylayertreenode', { + bindings: { + 'capabilities': '<', + 'layer': '<', + 'url': '<' + }, + controller: exports.Controller_, + templateUrl: gmfWmscapabilitylayertreenodeTemplateUrl +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmtsCapabilityLayertreeComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmtsCapabilityLayertreeComponent.html new file mode 100644 index 000000000..577221b95 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmtsCapabilityLayertreeComponent.html @@ -0,0 +1,71 @@ + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmtsCapabilityLayertreeComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmtsCapabilityLayertreeComponent.js new file mode 100644 index 000000000..eb7ba4626 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/import/wmtsCapabilityLayertreeComponent.js @@ -0,0 +1,133 @@ +/** + * @module gmf.import.wmtsCapabilityLayertreeComponent + */ + +/** @suppress {extraRequire} */ +import gmfDatasourceExternalDataSourcesManager from 'gmf/datasource/ExternalDataSourcesManager.js'; + +/** @suppress {extraRequire} */ +import ngeoMessagePopup from 'ngeo/message/Popup.js'; + +import * as olBase from 'ol/index.js'; + +const exports = angular.module('gmfWmtscapabilitylayertree', [ + gmfDatasourceExternalDataSourcesManager.module.name, + ngeoMessagePopup.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('ngeo/import/wmtsCapabilityLayertreeComponent', require('./wmtsCapabilityLayertreeComponent.html')); +}); + + +exports.value('gmfWmtscapabilitylayertreTemplateUrl', + /** + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} The template url. + */ + ($attrs) => { + const templateUrl = $attrs['gmfWmtscapabilitylayertreTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'ngeo/import/wmtsCapabilityLayertreeComponent'; + }); + + +/** + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.Attributes): string} gmfWmtscapabilitylayertreTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfWmtscapabilitylayertreTemplateUrl($attrs, gmfWmtscapabilitylayertreTemplateUrl) { + return gmfWmtscapabilitylayertreTemplateUrl($attrs); +} + + +/** + * @private + */ +exports.Controller_ = class { + + /** + * @param {!gmf.datasource.ExternalDataSourcesManager} + * gmfExternalDataSourcesManager GMF service responsible of managing + * external data sources. + * @private + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfWmtscapabilitylayertreeController + */ + constructor(gmfExternalDataSourcesManager) { + + // Binding properties + + /** + * WMS Capabilities definition + * @type {!Object} + * @export + */ + this.capabilities; + + /** + * List of WMTS Capability Layer objects. + * @type {!Array.} + * @export + */ + this.layers; + + /** + * The original WMTS GetCapabilities url that was used to fetch the + * capability layers. + * @type {string} + * @export + */ + this.url; + + + // Injected properties + + /** + * @type {!gmf.datasource.ExternalDataSourcesManager} + * @private + */ + this.gmfExternalDataSourcesManager_ = gmfExternalDataSourcesManager; + } + + /** + * @param {!Object} layer WMTS Capability Layer object + * @export + */ + createAndAddDataSource(layer) { + const manager = this.gmfExternalDataSourcesManager_; + manager.createAndAddDataSourceFromWMTSCapability( + layer, + this.capabilities, + this.url + ); + } + + /** + * @param {!Object} layer WMTS Capability Layer object + * @return {number} Unique id for the Capability Layer. + * @export + */ + getUid(layer) { + return olBase.getUid(layer); + } +}; + + +exports.component('gmfWmtscapabilitylayertree', { + bindings: { + 'capabilities': '<', + 'layers': '<', + 'url': '<' + }, + controller: exports.Controller_, + templateUrl: gmfWmtscapabilitylayertreTemplateUrl +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/index.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/index.js new file mode 100644 index 000000000..dbc066812 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/index.js @@ -0,0 +1,51 @@ +/** + * @module gmf + */ +const exports = {}; + +/** + * The default template base URL for modules, used as-is by the template cache. + * @type {string} + */ + +/** + * @const + * @export + */ +exports.DATALAYERGROUP_NAME = 'data'; + +/** + * @const + * @export + */ +exports.EXTERNALLAYERGROUP_NAME = 'external'; + +/** + * @const + * @export + */ +exports.COORDINATES_LAYER_NAME = 'gmfCoordinatesLayerName'; + + +/** + * @enum {string} + */ +exports.PermalinkParam = { + BG_LAYER: 'baselayer_ref', + BG_LAYER_OPACITY: 'baselayer_opacity', + EXTERNAL_DATASOURCES_NAMES: 'eds_n', + EXTERNAL_DATASOURCES_URLS: 'eds_u', + FEATURES: 'rl_features', + MAP_CROSSHAIR: 'map_crosshair', + MAP_TOOLTIP: 'map_tooltip', + MAP_X: 'map_x', + MAP_Y: 'map_y', + MAP_Z: 'map_zoom', + TREE_GROUPS: 'tree_groups', + WFS_LAYER: 'wfs_layer', + WFS_NGROUPS: 'wfs_ngroups', + WFS_SHOW_FEATURES: 'wfs_showFeatures' +}; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/SyncLayertreeMap.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/SyncLayertreeMap.js new file mode 100644 index 000000000..f9940876f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/SyncLayertreeMap.js @@ -0,0 +1,460 @@ +/** + * @module gmf.layertree.SyncLayertreeMap + */ +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoLayertreeController from 'ngeo/layertree/Controller.js'; +import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js'; +import * as olBase from 'ol/index.js'; +import olLayerImage from 'ol/layer/Image.js'; +import olLayerTile from 'ol/layer/Tile.js'; + +/** + * Service to create layer based on a ngeo.layertree.Controller with a + * GMFThemesGroup or a GMFThemesLeaf as node object. + * This layer is also used to synchronise a state of ngeo.layertree.Controller + * and its corresponding layer in the map. + * + * @constructor + * @param {angular.Scope} $rootScope Angular rootScope. + * @param {ngeo.map.LayerHelper} ngeoLayerHelper Ngeo Layer Helper. + * @param {ngeo.misc.WMSTime} ngeoWMSTime wms time service. + * @param {gmf.theme.Themes} gmfThemes The gmf Themes service. + * @ngInject + * @ngdoc service + * @ngname gmfSyncLayertreeMap + */ +const exports = function($rootScope, ngeoLayerHelper, ngeoWMSTime, + gmfThemes) { + + /** + * @type {ngeo.map.LayerHelper} + * @private + */ + this.layerHelper_ = ngeoLayerHelper; + + /** + * @type {ngeo.misc.WMSTime} + * @private + */ + this.ngeoWMSTime_ = ngeoWMSTime; + + /** + * @type {gmfThemes.GmfOgcServers} + * @private + */ + this.ogcServersObject_; + + gmfThemes.getOgcServersObject().then((ogcServersObject) => { + this.ogcServersObject_ = ogcServersObject; + }); + + $rootScope.$on('ngeo-layertree-state', (map, treeCtrl, firstParent) => { + this.sync_(/** @type ol.Map */ (map), firstParent); + }); +}; + + +/** + * Create, insert (or update) and return a layer from the GmfGroup or the + * GmfLayer of the given treeCtrl. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @param {ol.Map} map A map that contains the group to insert the not first + * level group layer. + * @param {ol.layer.Group} dataLayerGroup the layer group to insert the first + * level group layer. + * @param {number=} opt_position for first level Group, you can precise the + * position to add the group in the array of layers of the dataLayerGroup. + * @return {ol.layer.Base|ol.layer.Group} a new layer. + * @public + */ +exports.prototype.createLayer = function(treeCtrl, map, dataLayerGroup, opt_position) { + /** + * @type {ol.layer.Base|ol.layer.Group} + */ + let layer = null; + if (treeCtrl.node.children !== undefined && treeCtrl.node.mixed) { + // Mixed groups + layer = this.createGroup_(treeCtrl, map, dataLayerGroup, opt_position); + } else if (treeCtrl.node.children === undefined && treeCtrl.parent.node.mixed) { + // Layers in a mixed group + layer = this.createLeafInAMixedGroup_(treeCtrl, map); + } else if (treeCtrl.node.children === undefined) { + // Layers in a non mixed group + this.initGmfLayerInANotMixedGroup_(treeCtrl, map); + } else if (treeCtrl.depth === 1 && !treeCtrl.node.mixed) { + // First level group non mix + layer = this.createGroup_(treeCtrl, map, dataLayerGroup, opt_position); + } + + if (layer && treeCtrl.node.metadata.opacity) { + layer.setOpacity(treeCtrl.node.metadata.opacity); + } + + return layer; +}; + + +/** + * Synchronise the state of each layers corresponding to the given tree and + * all its children. + * @param {ol.Map} map A map that contains the layers. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @private + */ +exports.prototype.sync_ = function(map, treeCtrl) { + treeCtrl.traverseDepthFirst((treeCtrl) => { + if (treeCtrl.layer && !treeCtrl.node.mixed) { + this.updateLayerState_(/** @type ol.layer.Image|ol.layer.Tile */ (treeCtrl.layer), treeCtrl); + } + }); +}; + + +/** + * Set the active state of a layer based on its treeCtrl state. + * @param {ol.layer.Tile|ol.layer.Image} layer A layer. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @private + */ +exports.prototype.updateLayerState_ = function(layer, treeCtrl) { + const active = treeCtrl.getState() === 'on'; + if (treeCtrl.node.type === 'WMTS') { + layer.setVisible(active); + } else if (!treeCtrl.node.mixed && treeCtrl.depth === 1) { + // First level non mixed group + googAsserts.assertInstanceof(layer, olLayerImage); + const names = []; + const styles = []; + treeCtrl.traverseDepthFirst((treeCtrl) => { + if (treeCtrl.node.children === undefined && treeCtrl.getState() === 'on') { + names.push(treeCtrl.node.layers); + const style = (treeCtrl.node.style !== undefined) ? treeCtrl.node.style : ''; + styles.push(style); + } + }); + if (names.length === 0) { + layer.setVisible(false); + } + /** @type {ol.source.ImageWMS} */ (layer.getSource()).updateParams({ + 'LAYERS': names.reverse().join(','), + 'STYLES': styles.reverse().join(',') + }); + if (names.length !== 0) { + layer.setVisible(true); + } + } else { + // WMS mixed layer + googAsserts.assertInstanceof(layer, olLayerImage); + layer.setVisible(active); + } +}; + + +/** + * Create insert and return a layer group (for not mixed case) or a wmsLayer (for + * mixed case). Take care about the insertion order in the map in case of first + * level group. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @param {ol.Map} map A map that contains the group to insert the not first + * level group layer. + * @param {ol.layer.Group} dataLayerGroup the layer group to insert the first + * level group layer. + * @param {number=} opt_position for first level Group, you can precise the + * position to add the group in the array of layers of the dataLayerGroup. + * @return {ol.layer.Image|ol.layer.Group} a new layer. + * @private + */ +exports.prototype.createGroup_ = function(treeCtrl, map, + dataLayerGroup, opt_position) { + const groupNode = /** @type {gmfThemes.GmfGroup} */ (treeCtrl.node); + let layer = null; + const isFirstLevelGroup = treeCtrl.parent.isRoot; + + let printNativeAngle = true; + if (groupNode.metadata.printNativeAngle !== undefined) { + printNativeAngle = groupNode.metadata.printNativeAngle; + } + + if (isFirstLevelGroup) { // First level group + layer = this.createLayerFromGroup_(treeCtrl, !!groupNode.mixed); + // Insert the layer at the right place + const position = opt_position | 0; + dataLayerGroup.getLayers().insertAt(position, layer); + + } else { // Other Groups, create a group layer only in mixed groups + const inAMixedGroup = !this.isOneParentNotMixed_(treeCtrl); + if (inAMixedGroup) { + layer = this.createLayerFromGroup_(treeCtrl, true); + const layerGroup = /** @type {ol.layer.Group} */ ( + exports.getLayer(treeCtrl.parent)); + layerGroup.getLayers().insertAt(0, layer); + } + } + + layer.set('printNativeAngle', printNativeAngle); + return layer; +}; + + +/** + * Create, insert and return a layer group (for not mixed case) or a wmsLayer + * for mixed case). + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @param {boolean} mixed True for a group layer, false for a WMS layer. + * @return {ol.layer.Image|ol.layer.Group} a new layer. + * @private + */ +exports.prototype.createLayerFromGroup_ = function(treeCtrl, + mixed) { + let layer; + const groupNode = /** @type {gmfThemes.GmfGroup} */ (treeCtrl.node); + if (mixed) { // Will be one ol.layer per each node. + layer = this.layerHelper_.createBasicGroup(); + } else { // Will be one ol.layer for multiple WMS nodes. + const timeParam = this.getTimeParam_(treeCtrl); + const ogcServer = this.ogcServersObject_[groupNode.ogcServer || '']; + googAsserts.assert(ogcServer); + googAsserts.assert(ogcServer.url); + googAsserts.assert(ogcServer.type); + googAsserts.assert(ogcServer.imageType); + layer = this.layerHelper_.createBasicWMSLayer( + ogcServer.url, + '', + ogcServer.imageType, + ogcServer.type, + timeParam, + undefined, // WMS parameters + ogcServer.credential ? 'use-credentials' : 'anonymous' + ); + let hasActiveChildren = false; + treeCtrl.traverseDepthFirst((ctrl) => { + // Update layer information and tree state. + this.updateLayerReferences_(/** @type gmfThemes.GmfLayer */ (ctrl.node), layer); + if (ctrl.node.metadata.isChecked) { + ctrl.setState('on', false); + this.updateLayerState_(/** @type {ol.layer.Image} */ (layer), ctrl); + hasActiveChildren = true; + } + }); + layer.setVisible(hasActiveChildren); + layer.set('layerNodeName', groupNode.name); //Really useful ? + } + return layer; +}; + + +/** + * Create and insert a layer from a leaf in a mixed group. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @param {ol.Map} map A map that contains the group to insert the layer. + * @return {ol.layer.Tile|ol.layer.Image} a new layer. + * @private + */ +exports.prototype.createLeafInAMixedGroup_ = function(treeCtrl, map) { + const gmfLayer = /** @type {gmfThemes.GmfLayer} */ (treeCtrl.node); + let layer; + // Make layer. + if (gmfLayer.type === 'WMTS') { + layer = this.createWMTSLayer_(/** @type gmfThemes.GmfLayerWMTS */ (gmfLayer)); + } else { + const gmfLayerWMS = /** @type gmfThemes.GmfLayerWMS */ (gmfLayer); + const timeParam = this.getTimeParam_(treeCtrl); + const ogcServer = this.ogcServersObject_[/** @type string */ (gmfLayerWMS.ogcServer)]; + googAsserts.assert(ogcServer); + googAsserts.assert(ogcServer.url); + googAsserts.assert(ogcServer.type); + googAsserts.assert(gmfLayerWMS.layers); + googAsserts.assert(ogcServer.imageType); + + const opt_params = {STYLES: gmfLayerWMS.style}; + + layer = this.layerHelper_.createBasicWMSLayer( + ogcServer.url, + gmfLayerWMS.layers, + ogcServer.imageType, + ogcServer.type, + timeParam, + opt_params, // WMS parameters + ogcServer.credential ? 'use-credentials' : 'anonymous' + ); + } + // Update layer information and tree state. + layer.set('layerNodeName', gmfLayer.name); // Really useful ? + this.updateLayerReferences_(gmfLayer, layer); + const checked = gmfLayer.metadata.isChecked === true; + if (checked) { + treeCtrl.setState('on', false); + } + layer.setVisible(checked); + // Insert layer in the map. + const layerGroup = /** @type {ol.layer.Group} */ ( + exports.getLayer(treeCtrl.parent)); + layerGroup.getLayers().insertAt(0, layer); + return layer; +}; + + +/** + * Update a WMS layer with the given treeCtrl node information. Assumes that + * the first parent with ogcServer information is linked to the layer to update + * and that this treeCtrl node is a leafNode. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @param {ol.Map} map A map that contains the layer to update. + * @private + */ +exports.prototype.initGmfLayerInANotMixedGroup_ = function(treeCtrl, map) { + const leafNode = /** @type {gmfThemes.GmfLayer} */ (treeCtrl.node); + const firstLevelGroup = this.getFirstLevelGroupCtrl_(treeCtrl); + googAsserts.assert(firstLevelGroup); + const layer = /** @type {ol.layer.Image} */ (firstLevelGroup.layer); + googAsserts.assertInstanceof(layer, olLayerImage); + // Update layer information and tree state. + this.updateLayerReferences_(leafNode, layer); + if (leafNode.metadata.isChecked) { + treeCtrl.setState('on', false); + this.updateLayerState_(layer, firstLevelGroup); + } else { + treeCtrl.parent.refreshState(); + } +}; + + +/** + * Create and return a Tile layer. + * @param {gmfThemes.GmfLayerWMTS} gmfLayerWMTS A leaf node. + * @return {ol.layer.Tile} a Tile WMTS layer. (Source and capabilities can come + * later). + * @private + */ +exports.prototype.createWMTSLayer_ = function(gmfLayerWMTS) { + const newLayer = new olLayerTile(); + googAsserts.assert(gmfLayerWMTS.url); + googAsserts.assert(gmfLayerWMTS.layer); + this.layerHelper_.createWMTSLayerFromCapabilitites(gmfLayerWMTS.url, + gmfLayerWMTS.layer, gmfLayerWMTS.matrixSet, gmfLayerWMTS.dimensions).then((layer) => { + newLayer.setSource(layer.getSource()); + newLayer.set('capabilitiesStyles', layer.get('capabilitiesStyles')); + }); + return newLayer; +}; + + +/** + * Update properties of a layer with the node of a given leafNode. + * @param {gmfThemes.GmfLayer} leafNode a leaf node. + * @param {ol.layer.Base} layer A layer. + * @private + */ +exports.prototype.updateLayerReferences_ = function(leafNode, layer) { + const id = olBase.getUid(leafNode); + const querySourceIds = layer.get('querySourceIds') || []; + querySourceIds.push(id); + layer.set('querySourceIds', querySourceIds); + + const disclaimer = leafNode.metadata.disclaimer; + if (disclaimer) { + const disclaimers = layer.get('disclaimers') || []; + disclaimers.push(leafNode.metadata.disclaimer); + layer.set('disclaimers', disclaimers); + } +}; + + +/** + * Get the time parameter for a WMS Layer. If it's a group and it doesn't have + * time, get the first time parameter available in any child. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @return {string|undefined} A wms time param. + * @private + */ +exports.prototype.getTimeParam_ = function(treeCtrl) { + let wmsTime; + let timeParam; + const node = treeCtrl.node; + if (node.time) { + wmsTime = node.time; + } else if (node.children) { + treeCtrl.traverseDepthFirst((treeCtrl) => { + if (treeCtrl.node.children === undefined && treeCtrl.node.time) { + wmsTime = treeCtrl.node.time; + return ngeoLayertreeController.VisitorDecision.STOP; + } + }); + } + if (wmsTime) { + const timeValues = this.ngeoWMSTime_.getOptions(wmsTime)['values']; + timeParam = this.ngeoWMSTime_.formatWMSTimeParam(wmsTime, { + start: timeValues[0] || timeValues, + end: timeValues[1] + }); + } + return timeParam; +}; + + +/** + * Return true if a parent tree is mixed, based on its node. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @return {boolean} True is any parent is mixed. False Otherwise. + * @private + */ +exports.prototype.isOneParentNotMixed_ = function(treeCtrl) { + let tree = treeCtrl.parent; + let isOneParentNotMix = false; + do { + isOneParentNotMix = tree.node.mixed === false; + tree = tree.parent; + } + while (tree.parent && !isOneParentNotMix); + return isOneParentNotMix; +}; + + +/** + * Return the first parent, from the root parent, that is not mixed. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @return {ngeo.layertree.Controller} The first not mixed parent. + * @private + */ +exports.prototype.getFirstLevelGroupCtrl_ = function( + treeCtrl) { + let tree = treeCtrl; + while (!tree.parent.isRoot) { + tree = tree.parent; + } + return tree; +}; + + +/** + * Return the layer used by the given treeCtrl. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller. + * @return {ol.layer.Base} The layer. + * @public + */ +exports.getLayer = function(treeCtrl) { + let tree = treeCtrl; + let layer = null; + while (!tree.isRoot && layer === null) { + if (tree.layer) { + layer = tree.layer; + } + tree = tree.parent; + } + return layer; +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfSyncLayertreeMap', [ + gmfThemeThemes.module.name, + ngeoLayertreeController.module.name, + ngeoMiscWMSTime.module.name, +]); +exports.module.service('gmfSyncLayertreeMap', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/TreeManager.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/TreeManager.js new file mode 100644 index 000000000..b959e1fd2 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/TreeManager.js @@ -0,0 +1,601 @@ +/** + * @module gmf.layertree.TreeManager + */ +import gmfBase from 'gmf/index.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoLayertreeController from 'ngeo/layertree/Controller.js'; +import ngeoMessageMessage from 'ngeo/message/Message.js'; +import ngeoMessageNotification from 'ngeo/message/Notification.js'; +import ngeoStatemanagerService from 'ngeo/statemanager/Service.js'; +import * as olArray from 'ol/array.js'; +import * as olEvents from 'ol/events.js'; +import * as olObj from 'ol/obj.js'; + +/** + * Manage a tree with children. This service can be used in mode 'flush' + * (default) or not (mode 'add'). In mode 'flush', each theme, group or group + * by layer that you add will replace the previous children's array. In mode + * 'add', children will be just pushed in this array. The default state can be + * changed by setting the value `gmfTreeManagerModeFlush`, e.g.: + * + * let module = angular.module('app'); + * module.value('gmfTreeManagerModeFlush', false); + * + * This service's theme is a GmfTheme with only children and a name. + * Thought to be the tree source of the gmf layertree directive. + * @constructor + * @struct + * @param {angular.$timeout} $timeout Angular timeout service. + * @param {angular.$injector} $injector Angular injector service. + * @param {angularGettext.Catalog} gettextCatalog Gettext catalog. + * @param {ngeo.map.LayerHelper} ngeoLayerHelper Ngeo Layer Helper. + * @param {ngeo.message.Notification} ngeoNotification Ngeo notification service. + * @param {gmf.theme.Themes} gmfThemes gmf Themes service. + * @param {ngeo.statemanager.Service} ngeoStateManager The ngeo statemanager service. + * @ngInject + * @ngdoc service + * @ngname gmfTreeManager + */ +const exports = function($timeout, $injector, gettextCatalog, ngeoLayerHelper, + ngeoNotification, gmfThemes, ngeoStateManager) { + + /** + * @type {angular.$timeout} + * @private + */ + this.$timeout_ = $timeout; + + /** + * @type {angular.$injector} + * @private + */ + this.$injector_ = $injector; + + /** + * @type {angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = gettextCatalog; + + /** + * @type {ngeo.map.LayerHelper} + * @private + */ + this.layerHelper_ = ngeoLayerHelper; + + /** + * @type {ngeo.message.Notification} + * @private + */ + this.ngeoNotification_ = ngeoNotification; + + /** + * @type {gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + /** + * The root node and its children used to generate the layertree (with the + * same ordre). + * @type {gmfThemes.GmfRootNode} + * @public + */ + this.root = /** @type {gmfThemes.GmfRootNode} */ ({ + children: [] + }); + + /** + * The controller of the (unique) root layer tree. + * The array of top level layer trees is available through `rootCtrl.children`. + * The order doesn't match with the ordre of the displayed layertree. + * @type {ngeo.layertree.Controller} + * @export + */ + this.rootCtrl = null; + + /** + * Number of groups to add to the layertree during one single Angular + * digest loop. + * @type {number} + * @public + */ + this.numberOfGroupsToAddInThisDigestLoop = 0; + + /** + * @type {Array.} + * @private + */ + this.groupsToAddInThisDigestLoop_ = []; + + /** + * @type {angular.$q.Promise} + * @private + */ + this.promiseForGroupsToAddInThisDigestLoop_ = null; + + /** + * @type {ngeo.statemanager.Service} + * @private + */ + this.ngeoStateManager_ = ngeoStateManager; + + /** + * A reference to the OGC servers loaded by the theme service. + * @type {gmfThemes.GmfOgcServers|null} + * @private + */ + this.ogcServers_ = null; + + olEvents.listen(this.gmfThemes_, 'change', this.handleThemesChange_, this); +}; + +/** + * Called when the themes change. Get the OGC servers, then listen to the + * tree manager Layertree controllers array changes. + * The themes could have been changed so it also call a refresh of the + * layertree. + * @private + */ +exports.prototype.handleThemesChange_ = function() { + this.gmfThemes_.getOgcServersObject().then((ogcServers) => { + this.ogcServers_ = ogcServers; + }); + + if (this.rootCtrl && this.rootCtrl.children) { + this.gmfThemes_.getThemesObject().then((themes) => { + this.refreshFirstLevelGroups_(themes); + }); + } +}; + +/** + * Set some groups as tree's children. If the service use mode 'flush', the + * previous tree's children will be removed. Add only groups that are not + * already in the tree. + * @param {Array.} firstLevelGroups An array of gmf theme group. + * @return {boolean} True if the group has been added. False otherwise. + * @export + */ +exports.prototype.setFirstLevelGroups = function(firstLevelGroups) { + this.root.children.length = 0; + this.ngeoStateManager_.deleteParam(gmfBase.PermalinkParam.TREE_GROUPS); + return this.addFirstLevelGroups(firstLevelGroups); +}; + +/** + * Add some groups as tree's children. If the service use mode 'flush', the + * previous tree's children will be removed. Add only groups that are not + * already in the tree. + * @param {Array.} firstLevelGroups An array of gmf theme + * group. + * @param {boolean=} opt_add if true, force to use the 'add' mode this time. + * @param {boolean=} opt_silent if true notifyCantAddGroups_ is not called. + * @return {boolean} True if the group has been added. False otherwise. + * @export + */ +exports.prototype.addFirstLevelGroups = function(firstLevelGroups, + opt_add, opt_silent) { + const groupNotAdded = []; + + firstLevelGroups.slice().reverse().forEach((group) => { + if (!this.addFirstLevelGroup_(group)) { + groupNotAdded.push(group); + } + }); + if (groupNotAdded.length > 0 && !opt_silent) { + this.notifyCantAddGroups_(groupNotAdded); + } + + return groupNotAdded.length === 0; +}; + + +/** + * Update the application state with the list of first level groups in the tree + * @param {Array.} groups firstlevel groups of the tree + * @private + */ +exports.prototype.updateTreeGroupsState_ = function(groups) { + const treeGroupsParam = {}; + treeGroupsParam[gmfBase.PermalinkParam.TREE_GROUPS] = groups.map(node => node.name).join(','); + this.ngeoStateManager_.updateState(treeGroupsParam); + if (this.$injector_.has('gmfPermalink')) { + /** @type {gmf.permalink.Permalink} */(this.$injector_.get('gmfPermalink')).cleanParams(groups); + } +}; + + +/** + * Add a group as tree's children without consideration of this service 'mode'. + * Add it only if it's not already in the tree. + * @param {gmfThemes.GmfGroup} group The group to add. + * @return {boolean} true if the group has been added. + * @private + */ +exports.prototype.addFirstLevelGroup_ = function(group) { + let alreadyAdded = false; + const groupID = group.id; + this.root.children.some((rootChild) => { + if (groupID === rootChild.id) { + return alreadyAdded = true; + } + }, this); + this.groupsToAddInThisDigestLoop_.some((grp) => { + if (groupID === grp.id) { + return alreadyAdded = true; + } + }, this); + if (alreadyAdded) { + return false; + } + + // Add groups in the list of groups to add and be sure that the counter of + // groups to add is reset. + this.groupsToAddInThisDigestLoop_.push(group); + this.numberOfGroupsToAddInThisDigestLoop = 0; + + // Delete previous timeout promise if it exists to do this action only once. + if (this.promiseForGroupsToAddInThisDigestLoop_ !== null) { + this.$timeout_.cancel(this.promiseForGroupsToAddInThisDigestLoop_); + } + + // Add the groups only when there is no more group to come during this digest + // loop. The purpose of this is to preserve a consistent order between the + // layertree (generated by a template) and the layers in the map. + this.promiseForGroupsToAddInThisDigestLoop_ = this.$timeout_(() => { + // Set the number of group to add. + this.numberOfGroupsToAddInThisDigestLoop = this.groupsToAddInThisDigestLoop_.length; + // Add each first-level-groups. + this.groupsToAddInThisDigestLoop_.forEach((grp) => { + this.root.children.unshift(grp); + }); + //Update the permalink + this.updateTreeGroupsState_(this.root.children); + // Reset the groups and the promise state. Don't reset the + // numberOfGroupsToAddInThisDigestLoop, it must persist because the layers + // will be added into the map after that the layertree template is + // generated (so in the next angular loop). + this.groupsToAddInThisDigestLoop_.length = 0; + this.promiseForGroupsToAddInThisDigestLoop_ = null; + }); + + return true; +}; + + +/** + * Retrieve a group (first found) by its name and add in the tree. Do nothing + * if any corresponding group is found. + * @param {string} groupName Name of the group to add. + * @param {boolean=} opt_add if true, force to use the 'add' mode this time. + * @export + */ +exports.prototype.addGroupByName = function(groupName, opt_add) { + this.gmfThemes_.getThemesObject().then((themes) => { + const group = gmfThemeThemes.findGroupByName(themes, groupName); + if (group) { + this.addFirstLevelGroups([group], opt_add, false); + } + }); +}; + + +/** + * Retrieve a group by the name of a layer that is contained in this group + * (first found). This group will be added in the tree. Do nothing if any + * corresponding group is found. + * @param {string} layerName Name of the layer inside the group to add. + * @param {boolean=} opt_add if true, force to use the 'add' mode this time. + * @param {boolean=} opt_silent if true notifyCantAddGroups_ is not called + * @export + */ +exports.prototype.addGroupByLayerName = function(layerName, opt_add, opt_silent) { + this.gmfThemes_.getThemesObject().then((themes) => { + const group = gmfThemeThemes.findGroupByLayerNodeName(themes, layerName); + if (group) { + const groupAdded = this.addFirstLevelGroups([group], opt_add, opt_silent); + this.$timeout_(() => { + const treeCtrl = this.getTreeCtrlByNodeId(group.id); + if (!treeCtrl) { + console.warn('Tree controller not found, unable to add the group'); + return; + } + let treeCtrlToActive; + treeCtrl.traverseDepthFirst((treeCtrl) => { + if (treeCtrl.node.name === layerName) { + treeCtrlToActive = treeCtrl; + return ngeoLayertreeController.VisitorDecision.STOP; + } + }); + + // Deactive all layers in the group if it's not in the tree. + if (groupAdded) { + treeCtrl.setState('off'); + } + + // Active it. + if (treeCtrlToActive) { + treeCtrlToActive.setState('on'); + } + }); + } + }); +}; + + +/** + * Remove a group from this tree's children. The first group that is found ( + * based on its name) will be removed. If any is found, nothing will append. + * @param {gmfThemes.GmfGroup} group The group to remove. + * @export + */ +exports.prototype.removeGroup = function(group) { + const children = this.root.children; + let index = 0, found = false; + children.some((child) => { + if (child.name === group.name) { + return found = true; + } + index++; + }); + if (found) { + children.splice(index, 1); + this.updateTreeGroupsState_(children); + } +}; + + +/** + * Remove all groups. + * @export + */ +exports.prototype.removeAll = function() { + while (this.root.children.length) { + this.removeGroup(this.root.children[0]); + } +}; + + +/** + * Clone a group node and recursively set all child node `isChecked` using + * the given list of layer names. + * @param {gmfThemes.GmfGroup} group The original group node. + * @param {Array.} names Array of node names to check (i.e. that + * should have their checkbox checked) + * @return {gmfThemes.GmfGroup} Cloned node. + * @private + */ +exports.prototype.cloneGroupNode_ = function(group, names) { + const clone = /** @type {gmfThemes.GmfGroup} */ (olObj.assign({}, group)); + this.toggleNodeCheck_(clone, names); + return clone; +}; + + +/** + * Set the child nodes metadata `isChecked` if its name is among the list of + * given names. If a child node also has children, check those instead. + * @param {gmfThemes.GmfGroup|gmfThemes.GmfLayer} node The original node. + * @param {Array.} names Array of node names to check (i.e. that + * should have their checkbox checked) + * @private + */ +exports.prototype.toggleNodeCheck_ = function(node, names) { + if (!node.children) { + return; + } + node.children.forEach((childNode) => { + if (childNode.children) { + this.toggleNodeCheck_(childNode, names); + } else if (childNode.metadata) { + childNode.metadata.isChecked = olArray.includes(names, childNode.name); + } + }); +}; + + +/** + * Display a notification that informs that the given groups are already in the + * tree. + * @param {Array.} groups An array of groups that already in + * the tree. + * @private + */ +exports.prototype.notifyCantAddGroups_ = function(groups) { + const names = []; + const gettextCatalog = this.gettextCatalog_; + groups.forEach((group) => { + names.push(gettextCatalog.getString(group.name)); + }); + const msg = (names.length < 2) ? + gettextCatalog.getString('group is already loaded.') : + gettextCatalog.getString('groups are already loaded.'); + this.ngeoNotification_.notify({ + msg: `${names.join(', ')} ${msg}`, + type: ngeoMessageMessage.Type.INFORMATION + }); +}; + + +/** + * Get a treeCtrl based on it's node id. + * @param {number} id the id of a GMFThemesGroup or a GMFThemesLeaf. + * @return {ngeo.layertree.Controller?} treeCtrl The associated controller or null. + * @public + */ +exports.prototype.getTreeCtrlByNodeId = function(id) { + let correspondingTreeCtrl = null; + if (this.rootCtrl && this.rootCtrl.traverseDepthFirst) { + this.rootCtrl.traverseDepthFirst((treeCtrl) => { + if (treeCtrl.node.id === id) { + correspondingTreeCtrl = treeCtrl; + return ngeoLayertreeController.VisitorDecision.STOP; + } + }); + } + return correspondingTreeCtrl; +}; + + +/** + * Get the OGC server. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @return {gmfThemes.GmfOgcServer} The OGC server. + */ +exports.prototype.getOgcServer = function(treeCtrl) { + if (treeCtrl.parent.node.mixed) { + const gmfLayerWMS = /** @type {gmfThemes.GmfLayerWMS} */ (treeCtrl.node); + googAsserts.assert(gmfLayerWMS.ogcServer); + return this.ogcServers_[gmfLayerWMS.ogcServer]; + } else { + let firstLevelGroupCtrl = treeCtrl; + while (!firstLevelGroupCtrl.parent.isRoot) { + firstLevelGroupCtrl = firstLevelGroupCtrl.parent; + } + const gmfGroup = /** @type {gmfThemes.GmfGroup} */ (firstLevelGroupCtrl.node); + googAsserts.assert(gmfGroup.ogcServer); + return this.ogcServers_[gmfGroup.ogcServer]; + } +}; + + +/** + * Keep the state of each existing first-level-groups in the layertree then + * remove it and recreate it with nodes that come from the new theme and + * the corresponding saved state (when possible, otherwise, juste take the + * corresponding new node). + * FIXME: Currently doesn't save nor restore the opacity. + * @param {Array.} themes the array of themes to be based on. + * @private + */ +exports.prototype.refreshFirstLevelGroups_ = function(themes) { + const firstLevelGroupsFullState = {}; + + // Save state of each child + this.rootCtrl.children.map((treeCtrl) => { + const name = treeCtrl.node.name; + firstLevelGroupsFullState[name] = this.getFirstLevelGroupFullState_(treeCtrl); + }); + + // Get nodes and set their state + const nodesToRestore = []; + // Iterate on the root to keep the same order in the tree as before. + this.root.children.map((node) => { + const name = node.name; + + // Find the right firstlevelgroup in the new theme. + const nodeToRestore = gmfThemeThemes.findGroupByName(themes, name); + if (nodeToRestore) { + // Restore state. + const fullState = firstLevelGroupsFullState[name]; + if (fullState) { + this.setNodeMetadataFromFullState_(nodeToRestore, fullState); + } + nodesToRestore.push(nodeToRestore); + } + }); + + // Readd the firstlevelgroups. + this.setFirstLevelGroups(nodesToRestore); + + // Wait that Angular has created the layetree, then update the permalink. + this.$timeout_(() => { + this.updateTreeGroupsState_(this.root.children); + }); +}; + + +/** + * Return a gmfx.TreeManagerFullState that keeps the state of the given + * treeCtrl including the state of its children. + * @param {ngeo.layertree.Controller} treeCtrl the ngeo layertree controller to + * save. + * @return {gmfx.TreeManagerFullState!} the fullState object. + * @private + */ +exports.prototype.getFirstLevelGroupFullState_ = function(treeCtrl) { + const children = {}; + // Get the state of the treeCtrl children recursively. + treeCtrl.children.map((child) => { + children[child.node.name] = this.getFirstLevelGroupFullState_(child); + }); + + let isChecked, isExpanded, isLegendExpanded; + if (treeCtrl.children.length > 0) { + const nodeElement = $(`#gmf-layertree-layer-group-${treeCtrl.uid}`); + // Set isExpanded only in groups. + if (nodeElement) { + isExpanded = nodeElement.hasClass('in'); + } + } else { + // Set state and isLegendExpanded only in leaves. + isChecked = treeCtrl.getState(); + if (isChecked === 'on') { + isChecked = true; + } else if (isChecked === 'off') { + isChecked = false; + } else { + isChecked = undefined; + } + const legendElement = $(`#gmf-layertree-node-${treeCtrl.uid}-legend`); + if (legendElement) { + isLegendExpanded = legendElement.is(':visible'); + } + } + + return { + children, + isChecked, + isExpanded, + isLegendExpanded + }; +}; + + +/** + * Set a node's metadata with the given fullState. Update also its children + * recursively with the fullState children. + * @param {gmfThemes.GmfGroup|gmfThemes.GmfLayer} node to update. + * @param {gmfx.TreeManagerFullState|undefined} fullState the fullState object + * to use. + * @return {gmfThemes.GmfGroup|gmfThemes.GmfLayer} the node with modification. + * @private + */ +exports.prototype.setNodeMetadataFromFullState_ = function(node, fullState) { + if (!fullState) { + return node; + } + + // Set the metadata of the node children recursively. + if (node.children) { + node.children.map((child) => { + this.setNodeMetadataFromFullState_(child, fullState.children[child.name]); + }); + } + + // Set the metadata with the fullState object information. + const metadata = node.metadata; + metadata.isChecked = fullState.isChecked; + metadata.isExpanded = fullState.isExpanded; + metadata.isLegendExpanded = fullState.isLegendExpanded; + + return node; +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfTreeManager', [ + gmfThemeThemes.module.name, + ngeoLayertreeController.module.name, + ngeoMessageNotification.module.name, + ngeoStatemanagerService.module.name, +]); +exports.module.service('gmfTreeManager', exports); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/common.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/common.less new file mode 100644 index 000000000..a9aac4967 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/common.less @@ -0,0 +1,185 @@ +@import "~font-awesome/less/variables.less"; +@import "~gmf/less/vars.less"; + +.gmf-layertree-root-tools { + text-align: right; + padding: @micro-app-margin; +} + +.gmf-layertree-node { + /** + * Style rules for treenodes in the layertree + */ + margin-left: @app-margin; // left shifting (indentation) + + &.gmf-layertree-depth-1 { + margin: 0 @micro-app-margin @app-margin @micro-app-margin; + } + + ul { + ul { + //nested ul (i.e node groups into node groups should not add extra padding) + padding-right: 0; + li:last-child { + padding-bottom: 0; + } + } + } + + a { + color: @color; + display: inline; + line-height: inherit; + padding-left: 0; + text-decoration: none; + + &.gmf-layertree-expand-node.fa { + color : @color-light; + display: inline-block; + &::before { + content: @fa-var-chevron-right; + } + &[aria-expanded="true"]::before { + content: @fa-var-chevron-down; + } + } + } + + .gmf-layertree-state { + font-family: gmf-icons; + color: @color; + } + + .off { + opacity: 0.5; + } + + .gmf-layertree-leaf, + .gmf-layertree-group { + position: relative; + padding: @micro-app-margin; + display: flex; + + > * { + margin-top: auto; + margin-bottom: auto; + } + } + + .gmf-layertree-leaf .gmf-layertree-state::after { + content: "\e603"; + } + + .gmf-layertree-group { + .gmf-layertree-state::after { + content: "\e600"; + } + .gmf-layertree-layer-icon { + display: none; + } + + &.gmf-layertree-depth-1 { + .gmf-layertree-name { + font-weight: bold; + color: black; + } + } + + &.indeterminate .gmf-layertree-state::after { + content: "\e900"; + } + } + + .gmf-layertree-layer-icon { + &.gmf-layertree-no-layer-icon::after { + font-family: gmf-icons; + content: "\e907"; + width: 100%; + text-align: center; + } + + width: 20px; + padding: 0; + display: flex; + + img { + // don't let the legend icons images to break the layout by being too + // tall or too large + max-width: 100%; + max-height: 20px; + vertical-align: initial; + margin-left: auto; + margin-right: auto; + } + } + + .gmf-layertree-name { + overflow: hidden; + text-overflow: ellipsis; + flex: 2; + padding-left: @half-app-margin; + padding-right: @half-app-margin; + } + + .gmf-layertree-metadata { + a { + padding: 0; + &::after { + content: @fa-var-info; + display: inline; + font-family: FontAwesome; + } + } + } + + .gmf-layertree-zoom { + display: none; + // leave space after text label + padding-left: 4px; + &:hover { + cursor: pointer; + } + } + + .out-of-resolution { + .gmf-layertree-name { + font-style: italic; + } + .gmf-layertree-zoom { + display: inline; + } + &.gmf-layertree-leaf .gmf-layertree-state::after { + content: "\e604"; + } + } + + .gmf-layertree-legend { + margin: 0 @app-margin; + position: relative; + border: 1px solid @main-bg-color; + background-color: lighten(@main-bg-color, 8%); + .off { + opacity: 0.5; + } + a { + display: none; + position: absolute; + right: @half-app-margin; + font-size: 1.1rem; + + &::before { + display: none; + } + + &:hover { + text-decoration: underline; + } + } + p { + margin: 0 0 0 1rem; + } + img { + margin-bottom: 1rem; + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/component.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/component.html new file mode 100644 index 000000000..fbf74ca28 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/component.html @@ -0,0 +1,285 @@ + + + + + +
+ + + {{'Hide legend'|translate}} + +
+
+

{{title|translate}}

+ +
+
+
+ +
    + + + + + + +
+ +
    + +
  • +
  • +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/component.js new file mode 100644 index 000000000..5ab1928c5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/component.js @@ -0,0 +1,796 @@ +/** + * @module gmf.layertree.component + */ +import gmfBase from 'gmf/index.js'; +import gmfDatasourceDataSourceBeingFiltered from 'gmf/datasource/DataSourceBeingFiltered.js'; +import gmfDatasourceExternalDataSourcesManager from 'gmf/datasource/ExternalDataSourcesManager.js'; +import gmfPermalinkPermalink from 'gmf/permalink/Permalink.js'; + +/** @suppress {extraRequire} */ +import gmfLayertreeDatasourceGroupTreeComponent from 'gmf/layertree/datasourceGroupTreeComponent.js'; + +import gmfLayertreeSyncLayertreeMap from 'gmf/layertree/SyncLayertreeMap.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; +import gmfThemeThemes from 'gmf/theme/Themes.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoDatasourceOGC from 'ngeo/datasource/OGC.js'; + +/** @suppress {extraRequire} */ +import ngeoLayertreeComponent from 'ngeo/layertree/component.js'; + +import ngeoLayertreeController from 'ngeo/layertree/Controller.js'; +import ngeoMapLayerHelper from 'ngeo/map/LayerHelper.js'; +import ngeoMiscSyncArrays from 'ngeo/misc/syncArrays.js'; +import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js'; +import olLayerTile from 'ol/layer/Tile.js'; +import olLayerLayer from 'ol/layer/Layer.js'; +import * as olObj from 'ol/obj.js'; +import olSourceImageWMS from 'ol/source/ImageWMS.js'; +import olSourceTileWMS from 'ol/source/TileWMS.js'; +import olSourceWMTS from 'ol/source/WMTS.js'; + +import 'bootstrap/js/collapse.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLayertreeComponent', [ + gmfDatasourceDataSourceBeingFiltered.module.name, + gmfDatasourceExternalDataSourcesManager.module.name, + gmfPermalinkPermalink.module.name, + gmfLayertreeDatasourceGroupTreeComponent.name, + gmfLayertreeSyncLayertreeMap.module.name, + gmfLayertreeTreeManager.module.name, + gmfThemeThemes.module.name, + ngeoLayertreeComponent.name, + ngeoLayertreeController.module.name, + ngeoMapLayerHelper.module.name, + ngeoMiscWMSTime.module.name, +]); + + +// Overrides the path to the layertree template (used by each node, except +// the root node that path is defined by the gmfLayertreeTemplate value. +exports.value('ngeoLayertreeTemplateUrl', + /** + * @param {angular.JQLite} element Element. + * @param {angular.Attributes} attrs Attributes. + * @return {string} Template URL. + */ + (element, attrs) => 'gmf/layertree'); + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/layertree', require('./component.html')); +}); + + +exports.value('gmfLayertreeTemplate', + /** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} Template. + */ + ($element, $attrs) => { + const subTemplateUrl = 'gmf/layertree'; + return '
` + + '
'; + } +); + + +/** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.JQLite, !angular.Attributes): string} gmfLayertreeTemplate Template function. + * @return {string} Template. + * @ngInject + */ +function gmfLayertreeTemplate($element, $attrs, gmfLayertreeTemplate) { + return gmfLayertreeTemplate($element, $attrs); +} + + +/** + * This component creates a layertree based on the c2cgeoportal JSON themes + * source and a {@link ngeo.layertreeComponent}. The controller used by this + * component defines some functions for each node that are created by a default + * template. This default template can be overridden by setting the value + * 'gmf.layertreeTemplateUrl' but you will have to adapt the + * ngeoLayertreeTemplateUrl value too (to define the children's nodes template + * path). + * + * Example: + * + * + * + * + * You can add an attribute 'gmf-layertree-openlinksinnewwindow="::true"' to open + * metadata URLs in a new window. By default, and in the default template, + * links will be opened in a popup (The window.gmfx.openIframePopup function must be available !) + * + * Used UI metadata: + * + * * isChecked: if 'false' the layer visibility will be set to false. + * * iconUrl: layer icon full URL. + * * legendRule: WMS rule used to get a layer icon. + * * isLegendExpanded: if 'true' the legend is expanded by default. + * * metadataUrl: Display a popup with the content of the given URL if + * possible also open a new window. + * + * @htmlAttribute {ol.Map} gmf-layertree-map The map. + * @htmlAttribute {Object|undefined} gmf-layertree-dimensions Global dimensions object. + * @htmlAttribute {boolean|undefined} gmf-layertree-openlinksinnewwindow if true, open + * metadataURLs in a new window. Otherwise open them in a popup. + * + * @ngdoc component + * @ngname gmfLayertreeComponent + */ +exports.component_ = { + controller: 'GmfLayertreeController as gmfLayertreeCtrl', + bindings: { + 'map': '=gmfLayertreeMap', + 'dimensions': '=?gmfLayertreeDimensions', + 'openLinksInNewWindow': '} + * @export + */ + this.dimensions; + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {!ngeo.map.LayerHelper} + * @private + */ + this.layerHelper_ = ngeoLayerHelper; + + /** + * @type {gmfx.datasource.DataSourceBeingFiltered} + * @export + */ + this.gmfDataSourceBeingFiltered = gmfDataSourceBeingFiltered; + + /** + * @type {!gmf.datasource.ExternalDataSourcesManager} + * @export + */ + this.gmfExternalDataSourcesManager = gmfExternalDataSourcesManager; + + /** + * @type {!gmf.permalink.Permalink} + * @private + */ + this.gmfPermalink_ = gmfPermalink; + + /** + * @type {!gmf.layertree.TreeManager} + * @private + */ + this.gmfTreeManager_ = gmfTreeManager; + + const root = gmfTreeManager.root; + googAsserts.assert(root); + + /** + * @type {!gmfThemes.GmfRootNode} + * @export + */ + this.root = root; + + /** + * @type {!gmf.layertree.SyncLayertreeMap} + * @private + */ + this.gmfSyncLayertreeMap_ = gmfSyncLayertreeMap; + + /** + * @type {!ngeo.misc.WMSTime} + * @private + */ + this.ngeoWMSTime_ = ngeoWMSTime; + + /** + * @type {!Object.>} + * @private + */ + this.groupNodeStates_ = {}; + + /** + * @type {boolean|undefined} + * @export + */ + this.openLinksInNewWindow; + + /** + * @type {?ol.layer.Group} + * @private + */ + this.dataLayerGroup_ = null; + + /** + * @type {!Array.} + * @export + */ + this.layers = []; + + /** + * @type {!gmf.theme.Themes} + * @private + */ + this.gmfThemes_ = gmfThemes; + + // enter digest cycle on node collapse + $element.on('shown.bs.collapse', () => { + this.scope_.$apply(); + }); +}; + + +/** + * Init the controller, + */ +exports.Controller_.prototype.$onInit = function() { + this.openLinksInNewWindow = this.openLinksInNewWindow === true; + this.dataLayerGroup_ = this.layerHelper_.getGroupFromMap(this.map, + gmfBase.DATALAYERGROUP_NAME); + + ngeoMiscSyncArrays(this.dataLayerGroup_.getLayers().getArray(), this.layers, true, this.scope_, () => true); + + // watch any change on layers array to refresh the map + this.scope_.$watchCollection(() => this.layers, + () => { + this.map.render(); + }); + + // watch any change on dimensions object to refresh the layers + this.scope_.$watchCollection(() => { + if (this.gmfTreeManager_.rootCtrl) { + return this.dimensions; + } + }, (dimensions) => { + if (dimensions) { + this.updateDimensions_(this.gmfTreeManager_.rootCtrl); + } + }); +}; + + +/** + * @param {ngeo.layertree.Controller} treeCtrl Layer tree controller. + * @private + */ +exports.Controller_.prototype.updateDimensions_ = function(treeCtrl) { + treeCtrl.traverseDepthFirst((ctrl) => { + if (ctrl.node.dimensions) { + const layer = ctrl.layer; + googAsserts.assertInstanceof(layer, olLayerLayer); + this.updateLayerDimensions_(layer, /** @type gmfThemes.GmfGroup|gmfThemes.GmfLayer */ (ctrl.node)); + } + }); +}; + + +/** + * @param {ol.layer.Layer} layer Layer to update. + * @param {gmfThemes.GmfGroup|gmfThemes.GmfLayer} node Layer tree node. + * @private + */ +exports.Controller_.prototype.updateLayerDimensions_ = function(layer, node) { + if (this.dimensions && node.dimensions) { + const dimensions = {}; + for (const key in node.dimensions) { + if (node.dimensions[key] === null) { + const value = this.dimensions[key]; + if (value !== undefined) { + dimensions[key] = value; + } + } else { + dimensions[key] = node.dimensions[key]; + } + } + if (!olObj.isEmpty(dimensions)) { + const source = layer.getSource(); + if (source instanceof olSourceWMTS) { + source.updateDimensions(dimensions); + } else if (source instanceof olSourceTileWMS || source instanceof olSourceImageWMS) { + source.updateParams(dimensions); + } else { + // the source is not ready yet + layer.once('change:source', () => { + googAsserts.assertInstanceof(layer, olLayerLayer); + this.updateLayerDimensions_(layer, node); + }); + } + } + } +}; + + +/** + * Use the gmfSyncLayertreeMap_ to create and get layer corresponding to this + * treeCtrl. The layer will be inserted into the map. The layer can be null + * if the treeCtrl is based on a node inside a mixed node. It this case, the + * layer will be in the first parent declared as a mixed node. + * @param {ngeo.layertree.Controller} treeCtrl tree controller of the node + * @return {ol.layer.Base|ol.layer.Group|null} The OpenLayers layer or group + * for the node. + * @export + */ +exports.Controller_.prototype.getLayer = function(treeCtrl) { + let opt_position; + if (treeCtrl.parent.isRoot) { + this.gmfTreeManager_.rootCtrl = treeCtrl.parent; + // Precise the index to add first level groups. + opt_position = this.gmfTreeManager_.root.children.length - + this.gmfTreeManager_.numberOfGroupsToAddInThisDigestLoop || 0; + } + + const layer = this.gmfSyncLayertreeMap_.createLayer(treeCtrl, this.map, + this.dataLayerGroup_, opt_position); + + if (layer instanceof olLayerLayer) { + const node = /** @type {gmfThemes.GmfGroup|gmfThemes.GmfLayer} */ (treeCtrl.node); + this.updateLayerDimensions_(layer, node); + } + + return layer; +}; + + +/** + * Remove layer from this component's layergroup (and then, from the map) on + * a ngeo layertree destroy event. + * @param {angular.Scope} scope treeCtrl scope. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @export + */ +exports.Controller_.prototype.listeners = function(scope, treeCtrl) { + const dataLayerGroup = this.dataLayerGroup_; + scope.$on('$destroy', () => { + // Remove the layer from the map. + dataLayerGroup.getLayers().remove(treeCtrl.layer); + }); +}; + +/** + * Toggle the state of treeCtrl's node. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @export + */ +exports.Controller_.prototype.toggleActive = function(treeCtrl) { + treeCtrl.setState(treeCtrl.getState() === 'on' ? 'off' : 'on'); +}; + + +/** + * Return the current state of the given treeCtrl's node. + * Return a class name that match with the current node activation state. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @return {string} 'on' or 'off' or 'indeterminate'. + * @export + */ +exports.Controller_.prototype.getNodeState = function(treeCtrl) { + return treeCtrl.getState(); +}; + + +/** + * Update the `timeRangeValue` property of the data source bound to the + * given tree controller using the given time. If the tree controller has + * no data source, it means that it has children and they might have + * data sources. + * + * The setting of the TIME parameter on the layer occurs in the + * `gmf.datasource.Manager` service + * + * LayertreeController.prototype.updateWMSTimeLayerState - description + * @param {ngeo.layertree.Controller} layertreeCtrl ngeo layertree controller + * @param {{start : number, end : number}} time The start + * and optionally the end datetime (for time range selection) selected by user + * @export + */ +exports.Controller_.prototype.updateWMSTimeLayerState = function( + layertreeCtrl, time) { + if (!time) { + return; + } + const dataSource = layertreeCtrl.getDataSource(); + if (dataSource) { + googAsserts.assertInstanceof(dataSource, ngeoDatasourceOGC); + dataSource.timeRangeValue = time; + } else if (layertreeCtrl.children) { + for (let i = 0, ii = layertreeCtrl.children.length; i < ii; i++) { + this.updateWMSTimeLayerState(layertreeCtrl.children[i], time); + } + } +}; + + +/** + * Get the icon image URL for the given treeCtrl's layer. It can only return a + * string for internal WMS layers without multiple childlayers in the node. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @return {string|undefined} The icon legend URL or undefined. + * @export + */ +exports.Controller_.prototype.getLegendIconURL = function(treeCtrl) { + const iconUrl = treeCtrl.node.metadata.iconUrl; + + if (iconUrl !== undefined) { + return iconUrl; + } + + if (treeCtrl.node.children !== undefined) { + return undefined; + } + + const gmfLayer = /** @type {gmfThemes.GmfLayer} */ (treeCtrl.node); + if (gmfLayer.type !== 'WMS') { + return undefined; + } + + const gmfLayerWMS = /** @type {gmfThemes.GmfLayerWMS} */ (gmfLayer); + + const legendRule = gmfLayerWMS.metadata.legendRule; + + if (legendRule === undefined) { + return undefined; + } + + //In case of multiple layers for a gmfLayerWMS, always take the first layer + //name to get the icon + const layerName = gmfLayerWMS.layers.split(',')[0]; + const gmfOgcServer = this.gmfTreeManager_.getOgcServer(treeCtrl); + return this.layerHelper_.getWMSLegendURL( + gmfOgcServer.url, layerName, undefined, legendRule, 20, 20 + ); +}; + + +/** + * Get the legends object ( for each layer) for the given treeCtrl. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @return {Object.} A object that provides a + * layer for each layer. + * @export + */ +exports.Controller_.prototype.getLegendsObject = function(treeCtrl) { + const legendsObject = {}; + if (/** @type gmfThemes.GmfGroup */ (treeCtrl.node).children !== undefined) { + return null; + } + + const gmfLayer = /** @type {gmfThemes.GmfLayer} */ (treeCtrl.node); + const gmfLayerDefaultName = gmfLayer.name; + if (gmfLayer.metadata.legendImage) { + legendsObject[gmfLayerDefaultName] = gmfLayer.metadata.legendImage; + return legendsObject; + } + + const layer = treeCtrl.layer; + if (gmfLayer.type === 'WMTS') { + googAsserts.assertInstanceof(layer, olLayerTile); + const wmtsLegendURL = this.layerHelper_.getWMTSLegendURL(layer); + legendsObject[gmfLayerDefaultName] = wmtsLegendURL; + return wmtsLegendURL ? legendsObject : null; + } else { + const gmfLayerWMS = /** @type {gmfThemes.GmfLayerWMS} */ (gmfLayer); + let layersNames = gmfLayerWMS.layers; + const gmfOgcServer = this.gmfTreeManager_.getOgcServer(treeCtrl); + const scale = this.getScale_(); + // QGIS can handle multiple layers natively. Use Multiple URLs for other map + // servers + if (gmfOgcServer.type === ngeoDatasourceOGC.ServerType.QGISSERVER) { + layersNames = [layersNames]; + } else { + layersNames = layersNames.split(','); + } + layersNames.forEach((layerName) => { + legendsObject[layerName] = this.layerHelper_.getWMSLegendURL(gmfOgcServer.url, layerName, scale); + }); + return legendsObject; + } +}; + + +/** + * Get the number of legends object for this layertree controller. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @return {number} The number of Legends object. + * @export + */ +exports.Controller_.prototype.getNumberOfLegendsObject = function(treeCtrl) { + const legendsObject = this.getLegendsObject(treeCtrl); + return legendsObject ? Object.keys(legendsObject).length : 0; +}; + + +/** + * Return the current scale of the map. + * @return {number} Scale. + * @private + */ +exports.Controller_.prototype.getScale_ = function() { + const view = this.map.getView(); + const resolution = view.getResolution(); + const mpu = view.getProjection().getMetersPerUnit(); + const dpi = 25.4 / 0.28; + return resolution * mpu * 39.37 * dpi; +}; + + +/** + * Opens a gmfx.openIframePopup with the content of the metadata url of a node. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @export + */ +exports.Controller_.prototype.displayMetadata = function(treeCtrl) { + const node = treeCtrl.node; + const metadataURL = node.metadata['metadataUrl']; + if (metadataURL !== undefined) { + // FIXME layertree should not rely on a window function. + const gmfx = window.gmfx; + if (gmfx.openIframePopup) { + gmfx.openIframePopup(metadataURL, node.name, undefined, undefined, false); + } + } +}; + + +/** + * Update the layers order in the map and the treeCtrl in the treeManager after + * a reorder of the first-level groups. Then update the permalink. + * @export + */ +exports.Controller_.prototype.afterReorder = function() { + const groupNodes = this.gmfTreeManager_.rootCtrl.node.children; + const currentTreeCtrls = this.gmfTreeManager_.rootCtrl.children; + const treeCtrls = []; + + // Get order of first-level groups for treectrl and layers; + groupNodes.forEach((node) => { + currentTreeCtrls.some((treeCtrl) => { + if (treeCtrl.node === node) { + treeCtrls.push(treeCtrl); + return; + } + }); + }); + + // Update gmfTreeManager rootctrl children order + this.gmfTreeManager_.rootCtrl.children = treeCtrls; + + // Update map 'data' groupe layers order + this.layers.length = 0; + this.gmfTreeManager_.rootCtrl.children.forEach((child) => { + this.layers.push(child.layer); + }); + + // Update the permalink order + this.gmfPermalink_.refreshFirstLevelGroups(); +}; + + +/** + * @param {gmfThemes.GmfGroup} node Layer tree node to remove. + * @export + */ +exports.Controller_.prototype.removeNode = function(node) { + this.gmfTreeManager_.removeGroup(node); +}; + + +/** + * @export + */ +exports.Controller_.prototype.removeAllNodes = function() { + this.gmfTreeManager_.removeAll(); +}; + + +/** + * @return {number} first level node count. + * @export + */ +exports.Controller_.prototype.nodesCount = function() { + return this.gmfTreeManager_.root.children.length; +}; + +/** + * Return 'out-of-resolution' if the current resolution of the map is out of + * the min/max resolution in the node. + * @param {gmfThemes.GmfLayerWMS} gmfLayer the GeoMapFish Layer. WMTS layer is + * also allowed (the type is defined as GmfLayerWMS only to avoid some + * useless tests to know if a minResolutionHint property can exist + * on the node). + * @return {string|undefined} 'out-of-resolution' or undefined. + * @export + */ +exports.Controller_.prototype.getResolutionStyle = function(gmfLayer) { + const resolution = this.map.getView().getResolution(); + const minResolution = gmfThemeThemes.getNodeMinResolution(gmfLayer); + if (minResolution !== undefined && resolution < minResolution) { + return 'out-of-resolution'; + } + const maxResolution = gmfThemeThemes.getNodeMaxResolution(gmfLayer); + if (maxResolution !== undefined && resolution > maxResolution) { + return 'out-of-resolution'; + } + return undefined; +}; + + +/** + * Set the resolution of the map with the max or min resolution of the node. + * @param {ngeo.layertree.Controller} treeCtrl ngeo layertree controller, from + * the current node. + * @export + */ +exports.Controller_.prototype.zoomToResolution = function(treeCtrl) { + const gmfLayer = /** @type {gmfThemes.GmfLayerWMS} */ (treeCtrl.node); + const view = this.map.getView(); + const resolution = view.getResolution(); + const minResolution = gmfThemeThemes.getNodeMinResolution(gmfLayer); + if (minResolution !== undefined && resolution < minResolution) { + view.setResolution(view.constrainResolution(minResolution, 0, 1)); + } else { + const maxResolution = gmfThemeThemes.getNodeMaxResolution(gmfLayer); + if (maxResolution !== undefined && resolution > maxResolution) { + view.setResolution(view.constrainResolution(maxResolution, 0, -1)); + } + } +}; + + +/** + * Toggle the legend for a node + * @param {string} legendNodeId The DOM node legend id to toggle + * @export + */ +exports.Controller_.prototype.toggleNodeLegend = function(legendNodeId) { + $(legendNodeId).toggle({ + toggle: true + }); +}; + + +/** + * @param {gmf.datasource.OGC} ds Data source to filter. + * @export + */ +exports.Controller_.prototype.toggleFiltrableDataSource = function(ds) { + this.gmfDataSourceBeingFiltered.dataSource = ds; +}; + + +/** + * @param {string} legendNodeId The DOM node legend id + * @return {boolean} Whenever the legend is currently displayed. + * @export + */ +exports.Controller_.prototype.isNodeLegendVisible = function(legendNodeId) { + return $(legendNodeId).is(':visible'); +}; + + +/** + * Determines whether the layer tree controller supports being customized. + * For example, having its layer opacity changed, displaying its legend, etc. + * + * If any requirement is met, then the treeCtrl is considered supporting + * "customization", regardless of what it actually is. + * + * The requirements are: + * + * - must not be the root controller, any of the following: + * - it supports legend + * - it supports having the layer opacity being changed + * + * @param {!ngeo.layertree.Controller} treeCtrl Ngeo tree controller. + * @return {boolean} Whether the layer tree controller supports being + * "customized" or not. + * @export + */ +exports.Controller_.prototype.supportsCustomization = function(treeCtrl) { + return !treeCtrl.isRoot && + ( + this.supportsLegend(treeCtrl) || + this.supportsOpacityChange(treeCtrl) + ); +}; + + +/** + * @param {!ngeo.layertree.Controller} treeCtrl Ngeo tree controller. + * @return {boolean} Whether the layer tree controller supports having a + * legend being shown. + * @export + */ +exports.Controller_.prototype.supportsLegend = function(treeCtrl) { + const node = /** @type {!gmfThemes.GmfGroup} */ (treeCtrl.node); + return !!node.metadata && + !!node.metadata.legend && + !!this.getLegendsObject(treeCtrl); +}; + + +/** + * @param {!ngeo.layertree.Controller} treeCtrl Ngeo tree controller. + * @return {boolean} Whether the layer tree controller supports having its + * layer opacity being changed or not. + * @export + */ +exports.Controller_.prototype.supportsOpacityChange = function(treeCtrl) { + const node = /** @type {!gmfThemes.GmfGroup} */ (treeCtrl.node); + const parentNode = /** @type {!gmfThemes.GmfGroup} */ (treeCtrl.parent.node); + return !!treeCtrl.layer && + ( + ( + treeCtrl.depth === 1 && !node.mixed + ) || + ( + treeCtrl.depth > 1 && parentNode.mixed + ) + ); +}; + +exports.controller('GmfLayertreeController', exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/datasourceGroupTreeComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/datasourceGroupTreeComponent.html new file mode 100644 index 000000000..6502d3378 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/datasourceGroupTreeComponent.html @@ -0,0 +1,68 @@ + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/datasourceGroupTreeComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/datasourceGroupTreeComponent.js new file mode 100644 index 000000000..87eb014de --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/datasourceGroupTreeComponent.js @@ -0,0 +1,141 @@ +/** + * @module gmf.layertree.datasourceGroupTreeComponent + */ +import ngeoDatasourceDataSources from 'ngeo/datasource/DataSources.js'; +import * as olBase from 'ol/index.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLayertreeDatasourceGroupTreeComponent', [ + ngeoDatasourceDataSources.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/layertree/datasourceGroupTreeComponent', require('./datasourceGroupTreeComponent.html')); +}); + + +exports.value('gmfLayertreeDatasourceGroupTreeTemplateUrl', + /** + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} The template url. + */ + ($attrs) => { + const templateUrl = $attrs['gmfLayertreeDatasourceGroupTreeTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/layertree/datasourceGroupTreeComponent'; + }); + + +/** + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.Attributes): string} gmfLayertreeDatasourceGroupTreeTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfLayertreeDatasourceGroupTreeTemplateUrl($attrs, gmfLayertreeDatasourceGroupTreeTemplateUrl) { + return gmfLayertreeDatasourceGroupTreeTemplateUrl($attrs); +} + +/** + * @private + */ +exports.Controller_ = class { + + /** + * @param {!angular.Scope} $scope Angular scope. + * @param {!ngeo.datasource.DataSources} ngeoDataSources Ngeo data sources + * service. + * @private + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfDatasourcegrouptreeController + */ + constructor($scope, ngeoDataSources) { + + // Binding properties + + /** + * @type {!ngeo.datasource.Group} + * @export + */ + this.group; + + + // Injected properties + + /** + * @type {!angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {!ngeox.datasource.DataSources} + * @private + */ + this.dataSources_ = ngeoDataSources.collection; + } + + /** + * @return {string} Group uid. + * @export + */ + getGroupUid() { + return `datasourcegrouptree-${olBase.getUid(this.group)}`; + } + + /** + * Toggle visibility of the group itself, i.e. its visibility state. + * @export + */ + toggle() { + this.group.toggleVisibilityState(); + } + + /** + * Toggle visible property of a data source. + * @param {ngeo.datasource.DataSource} dataSource Data source to toggle the + * visibility + * @export + */ + toggleDataSource(dataSource) { + dataSource.visible = !dataSource.visible; + } + + /** + * Remove all data sources from the `ngeo.datasource.DataSources` collection, which + * will automatically remove them from the Group. The group itself + * is going to be removed as well, destroying this component in the process. + * @export + */ + remove() { + for (let i = this.group.dataSources.length - 1, ii = 0; i >= ii; i--) { + this.dataSources_.remove(this.group.dataSources[i]); + } + } + + /** + * @param {!ngeo.datasource.DataSource} dataSource Data source to remove from + * the `ngeo.DataSources` collection. + * @export + */ + removeDataSource(dataSource) { + this.dataSources_.remove(dataSource); + } +}; + + +exports.component('gmfDatasourcegrouptree', { + bindings: { + 'group': '<' + }, + controller: exports.Controller_, + templateUrl: gmfLayertreeDatasourceGroupTreeTemplateUrl +}); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/desktop.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/desktop.less new file mode 100644 index 000000000..d67730cd5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/desktop.less @@ -0,0 +1,112 @@ +gmf-layertree { + display: block; + padding: 0 @app-margin; + position: absolute; + height: 100%; + width: 100%; + ul { + margin-bottom: 0; + } + > :first-child { + margin-right: @half-app-margin; + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + } +} + +.gmf-layertree-node { + + .gmf-layertree-right-buttons { + display: none; + cursor: pointer; + + .gmf-layertree-node-menu-btn { + display: none; + } + } + + &.gmf-layertree-depth-1 { + //styling first level node for desktop app + background-color: @nav-bg; + box-shadow: 0 0 4px 1px @input-border-focus; + + > ul { + // no padding for the first list in first level nodes + padding-left: 0; + > li:last-child { + padding-bottom: @half-app-margin; + } + } + + &:hover { + .gmf-layertree-sortable-handle-icon { + visibility: visible; + } + } + } + + &.gmf-layertree-dragger { + * { + cursor: url(../../cursors/grabbing.cur), default; + cursor: -webkit-grabbing; + cursor: grabbing; + } + } + + .gmf-layertree-group.gmf-layertree-depth-1 { + background-color: @main-bg-color; + padding: @half-app-margin; + } + + .gmf-layertree-group:hover, + .gmf-layertree-leaf:hover { + .gmf-layertree-right-buttons { + display: block; + } + } + + .gmf-layertree-leaf { + padding-right: @half-app-margin; + } + + .gmf-layertree-legend:hover { + a { + cursor: pointer; + display: inline-block; + } + } + + // leave space for the drag handle + .gmf-layertree-depth-1 a.gmf-layertree-expand-node.fa { + margin-left: @half-app-margin; + } + + .ngeo-sortable-handle { + cursor: url(../../cursors/grab.cur), default; + cursor: -webkit-grab; + cursor: grab; + position: absolute; + left: 0; + top: 0; + height: 100%; + width : @app-margin; + margin: 0; + } + + .gmf-layertree-sortable-handle-icon { + color:#555; + visibility: hidden; + position: absolute; + top: 50%; + right: 0; + transform: translate(-50%, -50%); + } +} + +.gmf-layertree-curr-drag-item { + border: 1px dashed black; + margin: 0 @micro-app-margin @app-margin @micro-app-margin; + box-shadow: 0 0 4px 1px @input-border-focus; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/mobile.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/mobile.less new file mode 100644 index 000000000..4fec3cff8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/mobile.less @@ -0,0 +1,32 @@ +gmf-layertree { + border-top: 1px solid @back-color; +} + +nav.gmf-mobile-nav-left .gmf-layertree-node a[data-toggle] { + //override rule: nav.gmf-mobile-nav-left a[data-toggle] padding-right: 4rem + padding-right: 0; +} + +.gmf-layertree-node { + .ngeo-sortable-handle { + display: none; + } + .extra-actions { + display: none; + } + + [ngeo-popover] { + display: none; + } +} + +.gmf-layertree-node-menu { + border-bottom: 1px solid @back-color; + border-top: 1px solid @back-color; + padding: 1rem 0; + margin: 1rem 0; + + input[type=range] { + margin: 0.8rem 0 0.5rem 0; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/module.js new file mode 100644 index 000000000..d1a76dfe3 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/module.js @@ -0,0 +1,24 @@ +/** + * @module gmf.layertree.module + */ +import gmfLayertreeComponent from 'gmf/layertree/component.js'; +import gmfLayertreeDatasourceGroupTreeComponent from 'gmf/layertree/datasourceGroupTreeComponent.js'; +import gmfLayertreeSyncLayertreeMap from 'gmf/layertree/SyncLayertreeMap.js'; +import gmfLayertreeTimeSliderComponent from 'gmf/layertree/timeSliderComponent.js'; +import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; + +import './common.less'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLayertreeModule', [ + gmfLayertreeComponent.name, + gmfLayertreeDatasourceGroupTreeComponent.name, + gmfLayertreeSyncLayertreeMap.module.name, + gmfLayertreeTimeSliderComponent.name, + gmfLayertreeTreeManager.module.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timeSliderComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timeSliderComponent.js new file mode 100644 index 000000000..2704cee76 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timeSliderComponent.js @@ -0,0 +1,331 @@ +/** + * @module gmf.layertree.timeSliderComponent + */ +import ngeoMiscWMSTime from 'ngeo/misc/WMSTime.js'; + +import 'jquery-ui/ui/widgets/slider.js'; +import 'angular-ui-slider'; +import './timeslider.less'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLayertreeTimeSliderComponent', [ + ngeoMiscWMSTime.module.name, + 'ui.slider', +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/layertree/timesliderComponent', require('./timesliderComponent.html')); +}); + + +/** + * Provide a directive to select a single date or a range of dates with a slider + * Example: + * + * + * + * + * @htmlAttribute {ngeox.TimeProperty} gmf-time-slider-time parameter for initialization. + * @htmlAttribute {function()} gmf-time-slider-on-date-selected Expression evaluated after + * date(s) changed + * @param {angular.$timeout} $timeout angular timeout service + * @param {angular.$filter} $filter angular filter service + * @return {angular.Directive} The directive specs. + * @ngInject + * @ngdoc directive + * @ngname gmfTimeSlider + */ +exports.directive_ = function($timeout, $filter) { + return { + scope: { + onDateSelected: '&gmfTimeSliderOnDateSelected', + time: '=gmfTimeSliderTime' + }, + bindToController: true, + controller: 'gmfTimeSliderController as sliderCtrl', + restrict: 'AE', + templateUrl: 'gmf/layertree/timesliderComponent', + link: /** @type {!angular.LinkingFunctions} */ ({ + pre: function preLink(scope, element, attrs, ctrl) { + ctrl.init(); + + ctrl.sliderOptions['stop'] = onSliderReleased_; + ctrl.sliderOptions['slide'] = computeDates_; + + function onSliderReleased_(e, sliderUi) { + ctrl.onDateSelected({ + time: computeDates_(e, sliderUi) + }); + scope.$apply(); + } + + function computeDates_(e, sliderUi) { + let sDate, eDate, wmstime; + if (sliderUi.values) { + sDate = new Date(ctrl.getClosestValue_(sliderUi.values[0])); + eDate = new Date(ctrl.getClosestValue_(sliderUi.values[1])); + ctrl.dates = [sDate, eDate]; + wmstime = { + start: sDate.getTime(), + end: eDate.getTime() + }; + } else { + sDate = new Date(ctrl.getClosestValue_(sliderUi.value)); + ctrl.dates = sDate; + wmstime = { + start: sDate.getTime() + }; + } + scope.$apply(); + return wmstime; + } + } + }) + }; +}; + + +exports.directive('gmfTimeSlider', exports.directive_); + + +/** + * TimeSliderController - directive controller + * @param {!angular.Scope} $scope Angular scope. + * @param {ngeo.misc.WMSTime} ngeoWMSTime WMSTime service. + * @constructor + * @private + * @ngInject + * @ngdoc controller + * @ngname gmfTimeSliderController + */ +exports.Controller_ = function($scope, ngeoWMSTime) { + + /** + * @type {ngeo.misc.WMSTime} + * @private + */ + this.ngeoWMSTime_ = ngeoWMSTime; + + /** + * Function called after date(s) changed/selected + * @function + * @export + */ + this.onDateSelected; + + + /** + * A time object for directive initialization + * @type {ngeox.TimeProperty} + * @export + */ + this.time; + + /** + * If the component is used to select a date range + * @type {boolean} + * @export + */ + this.isModeRange; + + /** + * Minimal value of the slider (time in ms) + * @type {number} + * @export + */ + this.minValue; + + /** + * Maximal value of the slider (time in ms) + * @type {number} + * @export + */ + this.maxValue; + + /** + * Used when WMS time object has a property 'values' instead of an interval + * @type (?Array) + */ + this.timeValueList; + + /** + * Default Slider options (used by ui-slider directive) + * @type {{ + * range : boolean, + * min : number, + * max : number + * }} + * @export + */ + this.sliderOptions; + + /** + * Model for the ui-slider directive (date in ms format) + * @type {Array.|number} + * @export + */ + this.dates; +}; + + +/** + * Initialise the controller. + */ +exports.Controller_.prototype.init = function() { + this.timeValueList = this.getTimeValueList_(); + + // Fetch the initial options for the component + const initialOptions_ = this.ngeoWMSTime_.getOptions(this.time); + this.isModeRange = this.time.mode === 'range'; + this.minValue = initialOptions_.minDate; + this.maxValue = initialOptions_.maxDate; + this.dates = this.isModeRange ? [initialOptions_.values[0], initialOptions_.values[1]] : + initialOptions_.values; + this.sliderOptions = { + range: this.isModeRange, + min: this.minValue, + max: this.maxValue + }; +}; + +/** + * TimeSliderController.prototype.getTimeValueList_ - Get a list of time value instead + * of using the wmstime interval as a list of possibles values + * @private + * @return {Array} - List of timestamp representing possible values + */ +exports.Controller_.prototype.getTimeValueList_ = function() { + const wmsTime = this.time; + let timeValueList = null; + const minDate = new Date(this.minValue); + const maxDate = new Date(this.maxValue); + + if (wmsTime.values) { + timeValueList = []; + wmsTime.values.forEach((date) => { + timeValueList.push(new Date(date).getTime()); + }); + } else { + const maxNbValues = 1024; + const endDate = new Date(minDate.getTime()); + endDate.setFullYear(minDate.getFullYear() + maxNbValues * wmsTime.interval[0]); + endDate.setMonth(minDate.getMonth() + maxNbValues * wmsTime.interval[1], + minDate.getDate() + maxNbValues * wmsTime.interval[2]); + endDate.setSeconds(minDate.getSeconds() + maxNbValues * wmsTime.interval[3]); + + if (endDate > maxDate) { + // Transform interval to a list of values when the number + // of values is below a threshold (maxNbValues) + timeValueList = []; + for (let i = 0; ; i++) { + const nextDate = new Date(minDate.getTime()); + nextDate.setFullYear(minDate.getFullYear() + i * wmsTime.interval[0]); + nextDate.setMonth(minDate.getMonth() + i * wmsTime.interval[1], + minDate.getDate() + i * wmsTime.interval[2]); + nextDate.setSeconds(minDate.getSeconds() + i * wmsTime.interval[3]); + if (nextDate <= maxDate) { + timeValueList.push(nextDate.getTime()); + } else { + break; + } + } + } + } + return timeValueList; +}; + + +/** + * Compute the closest available date from the given timestamp + * @param {number} timestamp selected datetime (in ms format) + * @return {number} the closest available datetime (in ms format) from the timestamp + * @private + */ +exports.Controller_.prototype.getClosestValue_ = function(timestamp) { + if (timestamp <= this.minValue) { + return this.minValue; + } + + if (timestamp >= this.maxValue) { + return this.maxValue; + } + + if (this.timeValueList) { + // Time stops are defined as a list of values + let index; + let leftIndex = 0; + let rightIndex = this.timeValueList.length - 1; + + while ((rightIndex - leftIndex) > 1) { + index = Math.floor((leftIndex + rightIndex) / 2); + if (this.timeValueList[index] >= timestamp) { + rightIndex = index; + } else { + leftIndex = index; + } + } + + const leftDistance = Math.abs(this.timeValueList[leftIndex] - timestamp); + const rightDistance = Math.abs(this.timeValueList[rightIndex] - timestamp); + + return this.timeValueList[leftDistance < rightDistance ? leftIndex : rightIndex]; + } else { + // Time stops are defined by a start date plus an interval + const targetDate = new Date(timestamp); + const startDate = new Date(this.minValue); + let bestDate = new Date(this.minValue); + const maxDate = new Date(this.maxValue); + let bestDistance = Math.abs(targetDate - bestDate); + + for (let i = 1; ; i++) { + // The start date should always be used as a reference + // because adding a month twice could differ from adding + // two months at once + const next = new Date(startDate.getTime()); + next.setFullYear(startDate.getFullYear() + i * this.time.interval[0]); + next.setMonth(startDate.getMonth() + i * this.time.interval[1], + startDate.getDate() + i * this.time.interval[2]); + next.setSeconds(startDate.getSeconds() + i * this.time.interval[3]); + + if (next > maxDate) { + break; + } + + const distance = Math.abs(targetDate - next); + if (distance <= bestDistance) { + bestDate = next; + bestDistance = distance; + } else { + break; + } + } + + return bestDate.getTime(); + } +}; + + +/** + * Format and localize time regarding a resolution. + * @param {number} time (in ms format) timestamp to format and localize. + * @return {string} Localized date string regarding the resolution. + * @export + */ +exports.Controller_.prototype.getLocalizedDate = function(time) { + return this.ngeoWMSTime_.formatTimeValue(time, this.time.resolution); +}; + + +exports.controller('gmfTimeSliderController', + exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timeslider.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timeslider.less new file mode 100644 index 000000000..ba2174862 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timeslider.less @@ -0,0 +1,51 @@ +@import '~gmf/less/input-range.less'; +@import '~gmf/less/vars.less'; + +.gmf-time-slider { + + // 28 px come from bs popover class .popover-content { padding: 9px 14px; } + min-width: @popover-max-width - 28px; + + .ui-widget-content { + border: none; + } + + .ui-slider-handle { + top: -((@gmf-input-range-thumb-height / 2) - @gmf-input-range-track-height / 2) ; + cursor: @gmf-input-range-cursor; + margin-left: -@gmf-input-range-thumb-width / 2; + box-shadow: @gmf-input-range-thumb-box-shadow; + border: @gmf-input-range-thumb-border; + height: @gmf-input-range-thumb-height; + width: @gmf-input-range-thumb-width; + border-radius: @gmf-input-range-thumb-border-radius; + } + + .ui-slider-horizontal { + height: @gmf-input-range-track-height; + margin: @half-app-margin 0; + border: @gmf-input-range-track-border; + border-radius: @gmf-input-range-track-border-radius; + background-color: @brand-secondary; + } + + .ui-slider-range { + background-color: @brand-primary; + cursor: @gmf-input-range-cursor; + } + + .tooltip { + min-width: 6.5rem; + } +} + +.gmf-time-slider-displayed-dates { + display: flex; + justify-content: space-between; +} + +.gmf-time-slider-start-date, +.gmf-time-slider-end-date { + font-size : @font-size-small; + margin-top: @half-app-margin; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timesliderComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timesliderComponent.html new file mode 100644 index 000000000..4842c52cc --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/layertree/timesliderComponent.html @@ -0,0 +1,34 @@ +
+ +
+ + +
+ +
+
+ {{sliderCtrl.getLocalizedDate(sliderCtrl.dates[0])}} +
+ +
+ {{sliderCtrl.getLocalizedDate(sliderCtrl.dates)}} +
+ +
+ {{sliderCtrl.getLocalizedDate(sliderCtrl.dates[1])}} +
+
+ +
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/base.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/base.less new file mode 100644 index 000000000..0fa230eb6 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/base.less @@ -0,0 +1,99 @@ +/** + * Styles shared between the different apps (mobile and desktop). + */ +@import (inline) '~openlayers/css/ol.css'; +@import (inline) '../../css/reset.css'; +@import '~bootstrap/less/bootstrap.less'; + +@import '~gmf/less/vars.less'; + +html, body { + height: 100%; +} + +body { + overflow: hidden; +} + +footer { + position: relative; + z-index: @above-content-index; +} + +a { + text-decoration: none; +} + +[ng\:cloak], [ng-cloak], .ng-cloak { + display: none !important; +} + +/** + * The blur filter is used to avoid the loading icon to shake on firefox. + * See: https://github.com/FortAwesome/Font-Awesome/issues/671 + */ +.fa-refresh { + filter: blur(0); +} + +.list-group-sm .list-group-item { + padding: @padding-small-vertical @padding-small-horizontal; +} + +.input-sm, select.input-sm { + height: inherit; + line-height: inherit; +} + +i, cite, em, var, address, dfn { + font-style: italic; +} + +.small { + font-size: 90%; +} + +// removes the margin at the bottom of a form-group +// useful for groups with a range +.form-group-nomargin { + margin-bottom: 0; +} + +.control-label { + font-weight: normal; +} + +.modal-content { + border-radius: 0; +} +.modal-body, .modal-header { + padding: 10px; +} +.modal-title { + font-weight: bold; + font-size: inherit; + line-height: 1; +} + +.ui-draggable-handle { + cursor: grab; + cursor: -webkit-grab; + cursor:-moz-grab; +} + +.ui-draggable-dragging { + .ui-draggable-handle { + cursor: move; + } + + iframe { + display: none; + } +} +.ui-resizable { + &.ui-resizable-resizing { + iframe { + display: none; + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/datepicker.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/datepicker.less new file mode 100644 index 000000000..b8086c717 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/datepicker.less @@ -0,0 +1,24 @@ +@datepicker-font-size : 1.1rem; +#ui-datepicker-div { + font-family: @font-family-base; + font-size: @datepicker-font-size; + border-radius: inherit; + box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); + + .ui-datepicker-header { + border-radius: inherit; + } +} + +.ngeo-datepicker { + font-size: @datepicker-font-size; + .ngeo-datepicker-form { + .ngeo-datepicker-start-date, + .ngeo-datepicker-end-date { + display: inline-block; + input { + max-width: 7rem; + } + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/font.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/font.less new file mode 100644 index 000000000..e63ceda49 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/font.less @@ -0,0 +1,16 @@ +/** + * Fonts definition + */ +@font-face { + font-family: "gmf-icons"; + src: url("../../fonts/gmf-icons.eot"); + src: url("../../fonts/gmf-icons.eot?#iefix") format("embedded-opentype"), + url("../../fonts/gmf-icons.woff") format("woff"), + url("../../fonts/gmf-icons.ttf") format("truetype"), + url("../../fonts/gmf-icons.svg#gmf-icons") format("svg"); + font-weight: normal; + font-style: normal; +} + +@import "~font-awesome/less/font-awesome.less"; +@fa-font-path: "../fonts"; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/fullscreenpopup.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/fullscreenpopup.less new file mode 100644 index 000000000..65b7b1a34 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/fullscreenpopup.less @@ -0,0 +1,52 @@ +[ngeo-popup] { + &.popover { + position: fixed; + top: 0; + left: auto; + right: auto; + max-width: calc(~"100vw -" 2 * @app-margin); + width: calc(~"100vw -" 2 * @app-margin); + height: calc(~"100vh -" 2 * @app-margin); + max-height: calc(~"100vh -" 2 * @app-margin); + margin: @app-margin; + /* Like bootstrap modal border-radius */ + border-radius: 6px; + /* Under bootstrap modal */ + z-index: 1040; + } + .popover-title { + background-color: @nav-bg; + border-bottom-color: @color; + color: @color; + .close { + color: @color; + line-height: 0.8; + opacity: 1; + } + } + .popover-content { + height: 90vh; + -webkit-overflow-scrolling: touch; + } +} + +@media (min-width: @screen-sm-min) { + @fullscreenpopup-tablet-width: 12 * @map-tools-size; + @fullscreenpopup-topbar-height: 4.5rem; // Same value as the topbar-height in desktop.less + @fullscreenpopup-tablet-top: @fullscreenpopup-topbar-height + @app-margin + 2 * @map-tools-size; + [ngeo-popup] { + &.popover { + position: fixed; + top: @fullscreenpopup-tablet-top; + left: @nav-width; + max-width: calc(~"100vw -" (2 * @nav-width + 2 * @app-margin)); + width: @fullscreenpopup-tablet-width; + max-height: calc(~"100vh -" (@fullscreenpopup-tablet-top + @app-margin)); + height: @fullscreenpopup-tablet-width + @map-tools-size; + } + .popover-content { + overflow: auto; + height: calc(~"100% -" 4 * @app-margin); + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/icons.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/icons.less new file mode 100644 index 000000000..ae1b110b5 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/icons.less @@ -0,0 +1,61 @@ +/** + * Definitions for icons. + */ +.gmf-icon { + font-style: normal; + &::after, + &::before { + font-family: gmf-icons; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + } + + &.gmf-icon-layers::after { + content: '\e600'; + } + + &.gmf-icon-list::after { + content: '\e602'; + } + + &.gmf-icon-map::after { + content: '\f279'; + } + + &.gmf-icon-map-o::after { + content: '\f278'; + } + + &.gmf-icon-check::after { + content: '\e603'; + } + + &.gmf-icon-circle::after { + content: '\e901'; + } + + &.gmf-icon-line::after { + content: '\e902'; + } + + &.gmf-icon-point::after { + content: '\e903'; + } + + &.gmf-icon-polygon::after { + content: '\e904'; + } + + &.gmf-icon-rectangle::after { + content: '\e905'; + } + + &.gmf-icon-text::after { + content: '\e906'; + } + + &.gmf-icon-search-go::after { + content: '\e908'; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/input-range.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/input-range.less new file mode 100644 index 000000000..007e7378e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/input-range.less @@ -0,0 +1,99 @@ +@gmf-input-range-track-box-shadow : 0.1rem 0.1rem 0.1rem rgba(0, 0, 0, 0), 0 0 0.1rem rgba(13, 13, 13, 0); +@gmf-input-range-track-height: 0.5rem; +@gmf-input-range-track-border: 0.2px solid rgba(1, 1, 1, 0.2); +@gmf-input-range-track-border-radius: 0.1rem; +@gmf-input-range-thumb-height: 2rem; +@gmf-input-range-thumb-width: 1rem; +@gmf-input-range-thumb-border-radius: 0.5rem; +@gmf-input-range-thumb-border: 0.1rem solid rgba(0, 0, 30, 0.2); +@gmf-input-range-thumb-background: #ffffff; +@gmf-input-range-thumb-box-shadow: 0.1rem 0.1rem 0.1rem rgba(0, 0, 49, 0.2), 0 0 0.1rem rgba(0, 0, 75, 0.2); +@gmf-input-range-cursor: pointer; + +input[type=range] { + -webkit-appearance: none; + width: 100%; + padding-right: 0 !important; + padding-left: 0 !important; + border: 0; + background-color: transparent; + + &, + &:focus { + box-shadow: none; + } +} +input[type=range]:focus { + outline: none; +} +input[type=range]::-webkit-slider-runnable-track { + width: 100%; + height: @gmf-input-range-track-height; + cursor: @gmf-input-range-cursor; + box-shadow: @gmf-input-range-track-box-shadow; + background: @brand-primary; + border-radius: @gmf-input-range-track-border-radius; + border: @gmf-input-range-track-border; +} +input[type=range]::-webkit-slider-thumb { + box-shadow: @gmf-input-range-thumb-box-shadow; + border: @gmf-input-range-thumb-border; + height: @gmf-input-range-thumb-height; + width: @gmf-input-range-thumb-width; + border-radius: @gmf-input-range-thumb-border-radius; + background: @gmf-input-range-thumb-background; + cursor: @gmf-input-range-cursor; + -webkit-appearance: none; + margin-top: -7.7px; +} +input[type=range]::-moz-range-track { + width: 100%; + height: @gmf-input-range-track-height; + cursor: @gmf-input-range-cursor; + box-shadow: @gmf-input-range-track-box-shadow; + background: @brand-secondary; + border-radius: @gmf-input-range-track-border-radius; + border: @gmf-input-range-track-border; +} +input[type=range]::-moz-range-progress { + background: @brand-primary; + height: @gmf-input-range-track-height; +} +input[type=range]::-moz-range-thumb { + box-shadow: @gmf-input-range-thumb-box-shadow; + border: @gmf-input-range-thumb-border; + height: @gmf-input-range-thumb-height; + width: @gmf-input-range-thumb-width; + border-radius: @gmf-input-range-thumb-border-radius; + background: @gmf-input-range-thumb-background; + cursor: @gmf-input-range-cursor; +} +input[type=range]::-ms-track { + width: 100%; + height: @gmf-input-range-track-height; + cursor: @gmf-input-range-cursor; + background: transparent; + border-color: transparent; + color: transparent; +} +input[type=range]::-ms-fill-lower { + background: @brand-primary; + border: @gmf-input-range-track-border; + border-radius: 0.2rem; + box-shadow: @gmf-input-range-track-box-shadow; +} +input[type=range]::-ms-fill-upper { + background: @brand-secondary; + border: @gmf-input-range-track-border; + border-radius: 0.2rem; + box-shadow: @gmf-input-range-track-box-shadow; +} +input[type=range]::-ms-thumb { + box-shadow: @gmf-input-range-thumb-box-shadow; + border: @gmf-input-range-thumb-border; + height: @gmf-input-range-thumb-height; + width: @gmf-input-range-thumb-width; + border-radius: @gmf-input-range-thumb-border-radius; + background: @gmf-input-range-thumb-background; + cursor: @gmf-input-range-cursor; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/iphone.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/iphone.less new file mode 100644 index 000000000..77c395072 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/iphone.less @@ -0,0 +1,24 @@ +// Hack for ios Safari browser (UI overlapping on iOS 10) +@media all and (orientation: landscape) { + @ios-margin: 5rem; + + body.ios-margin { + button.gmf-mobile-nav-left-trigger, + button.gmf-mobile-nav-right-trigger, + gmf-search { + margin-top: @ios-margin; + } + + div.ol-zoom { + top: (@app-margin + @map-tools-size + @app-margin) + @ios-margin; + } + + div.ol-rotate { + top: (4 * @map-tools-size + 2 * @app-margin + 3 * @micro-app-margin) + @ios-margin; + } + + button[ngeo-mobile-geolocation] { + top: (3 * @map-tools-size + 2 * @app-margin + 2 * @micro-app-margin) + @ios-margin; + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/map.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/map.less new file mode 100644 index 000000000..5431e002c --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/map.less @@ -0,0 +1,152 @@ +/** + * Styles for the map and OL3 controls. + */ +.ol-rotate, +.ol-zoom { + background-color: transparent; + padding: 0; + button { + margin: 0; + margin-bottom: @micro-app-margin; + height: @map-tools-size; + width: @map-tools-size; + background-color: @map-tools-bg-color; + border: solid 1px @border-color; + color: @map-tools-color; + &:hover { + background-color: @onhover-color; + } + &:focus { + background-color: @map-tools-bg-color; + outline: none; + } + &:active { + outline: none; + } + } + &:hover { + background-color: transparent; + } +} + +/** + * Only affects webkit desktop browsers + */ +@media screen and (-webkit-min-device-pixel-ratio:0) { + .ol-rotate, + .ol-zoom { + button { + &:active { + background-color: @onhover-color; + outline: -webkit-focus-ring-color auto 5px; + } + } + } +} + +.ol-attribution { + display:none; +} + +.ol-scale-line, .ol-scale-line-inner { + background-color: @map-tools-bg-color; + border-color: @border-color; + border-width: 2px; + color: @map-tools-color; +} + +button[ngeo-mobile-geolocation] { + background-color: @map-tools-bg-color; + border: solid 1px @border-color; + color: @map-tools-color; + .fa { + font-size: 2rem; + } +} + +.gmf-theme-selector, +.gmf-backgroundlayerselector { + list-style: none; + + li { + cursor: pointer; + display: flex; + align-items: center; + min-height: 3rem; + border: 1px solid transparent; + padding: @half-app-margin; + + &::before { + // same as fa-fw + width: (18em / 14); + content: ''; + text-align: center; + } + &:hover, + &.gmf-backgroundlayerselector-active, + &.gmf-theme-selector-active { + border-color: @brand-secondary; + background-color: #f5f5f5; + } + &.gmf-backgroundlayerselector-active, + &.gmf-theme-selector-active { + &::before { + font-family: FontAwesome; + content: @fa-var-check; + } + } + + &.gmf-backgroundlayerselector-disabled{ + border-top-color: @map-tools-color; + pointer-events: none; + } + + span.gmf-backgroundlayerselector-opacity-check { + &::after { + width: (18em / 14); + font-family: FontAwesome; + content: @fa-var-check; + text-align: center; + } + } + } + + .gmf-text { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex: 1 1 auto; + width: inherit; + } + + .gmf-thumb { + height: @map-tools-size; + margin: 0 @half-app-margin; + } + + input.gmf-backgroundlayerselector-opacity-slider { + margin: 1rem 0 2rem 0; + padding-left: @half-app-margin !important; + padding-right: @half-app-margin !important; + } +} + +/** Disclaimer and tablet redirect */ +.gmf-app-map-messages { + position: absolute; + bottom: @app-margin; + left: @app-margin; + width: 30rem; + z-index: @above-content-index; + + .alert { + padding: @half-app-margin @app-margin; + margin: @half-app-margin 0 0 0; + } + + .alert-dismissable .close, + .alert-dismissible .close { + right: -0.5rem; + height: inherit; + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/mobile.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/mobile.less new file mode 100644 index 000000000..e69de29bb diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/popover.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/popover.less new file mode 100644 index 000000000..25353df7f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/popover.less @@ -0,0 +1,49 @@ +@popover-nb-col : 12; +@popover-icon-max-width : (@popover-max-width / @popover-nb-col) * 3; +@popover-action-name-max-width : (@popover-max-width / @popover-nb-col) * 5; +@popover-action-max-width : (@popover-max-width / @popover-nb-col) * 4; +@popover-text-color : @color-light; + +.popover { + border-radius: 0; + z-index: @above-content-index; + .popover-content { + ul { + margin-bottom: 0; + /* fix issue with IE11 not sizing correcly the popover box */ + min-width: 180px; + } + + li { + color: @popover-text-color; + list-style: none; + margin-bottom: @half-app-margin; + font-size: @font-size-small; + + &:last-child { + margin: 0; + } + + i { + margin-right: @half-app-margin; + max-width: @popover-icon-max-width - @half-app-margin; + } + + span { + max-width: @popover-action-name-max-width; + } + + a { + color: @popover-text-color; + } + + input { + margin-left: @half-app-margin; + display: inline-block; + max-width: @popover-action-max-width - @half-app-margin; + /* fix issue with IE11 not sizing correcly the popover box */ + padding: 0; + } + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/typeahead.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/typeahead.less new file mode 100644 index 000000000..58ff1355b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/typeahead.less @@ -0,0 +1,28 @@ +.twitter-typeahead { + width: 100%; + height: 100%; + + .tt-hint { + display: none; + } + + .tt-menu { + width: 100%; + overflow-x: hidden; + overflow-y: auto; + background-color: @map-tools-bg-color; + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + border: solid 1px @border-color; + + .tt-suggestion { + text-align: left; + padding: @app-margin; + border-bottom: solid 1px @border-color; + + &:hover, &.tt-cursor { + cursor: pointer; + background-color: @onhover-color; + } + } + } +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/vars.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/vars.less new file mode 100644 index 000000000..ec30fcd16 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/less/vars.less @@ -0,0 +1,41 @@ +@import "~bootstrap/less/variables.less"; + +@search-width: 6 * @map-tools-size; + +@app-margin: 1rem; +@half-app-margin: 0.5rem; +@micro-app-margin: 0.2rem; +@standard-variation: 15%; +@nav-bg: white; +@color: #555; +@color-light: lighten(@color, @standard-variation); +@nav-header-bg: darken(@nav-bg, 50%); +@link-color: hsv(hue(@brand-primary), 40%, 60%); +@map-tools-bg-color: white; +@map-tools-color: black; +@map-tools-size: 4rem; +@onhover-color: darken(@nav-bg, @standard-variation); +@main-bg-color: #e2e3df; // grey light + +// Z-indexes +@below-content-index: 1; +@content-index: 2; +@above-content-index: 3; +@above-menus-index: 4; +@search-index: 5; +@above-search-index: 6; +@above-all: 9999; + + +@nav-width: 32rem; + +@border-radius-base: 0; +@border-radius-small: 0; +@border-color: black; +@input-border-focus: darken(@brand-primary, @standard-variation); + +@brand-primary: #94ac9a; +@brand-secondary: #d3e5d7; +@font-size-small: 0.9em; + +@import "@{THEME}"; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Config.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Config.js new file mode 100644 index 000000000..ef40e5e7e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Config.js @@ -0,0 +1,110 @@ +/** + * @module gmf.lidarprofile.Config + */ + + +const exports = class { + + /** + * Configuration service to configure the gmf.lidarPanelComponent and gmf.lidarprofile instance + * Requires a Pytree service: https://github.com/sitn/pytree + * + * @struct + * @param {angular.$http} $http Angular http service. + * @param {string} pytreeLidarprofileJsonUrl pytree Lidar profile URL. + * @ngInject + * @ngdoc service + * @ngname gmfLidarprofileConfig + */ + constructor($http, pytreeLidarprofileJsonUrl) { + + /** + * @type {angular.$http} + * @private + */ + this.$http_ = $http; + + /** + * @type {string} + */ + this.pytreeLidarprofileJsonUrl = pytreeLidarprofileJsonUrl; + + /** + * @type {boolean} + */ + this.loaded = false; + + /** + * The client configuration. + * @type {gmfx.LidarprofileClientConfig} + */ + this.clientConfig = { + autoWidth: true, + margin: { + 'left': 40, + 'top': 10, + 'right': 200, + 'bottom': 40 + }, + pointAttributes: {}, + pointSum: 0, + tolerance: 5 + }; + + /** + * The configuration from the LIDAR server. + * @type {lidarprofileServer.Config} + */ + this.serverConfig = null; + } + + + /** + * Initialize the service variables from Pytree profile_config_gmf2 route + * @return {angular.$q.Promise} configuration values + * @export + */ + initProfileConfig() { + return this.$http_.get(`${this.pytreeLidarprofileJsonUrl}/profile/config`).then((resp) => { + + this.serverConfig = /** @type {lidarprofileServer.Config} */ ({ + classification_colors: resp.data['classification_colors'] || null, + debug: !!resp.data['debug'], + default_attribute: resp.data['default_attribute'] || '', + default_color: resp.data['default_color'] || '', + default_point_attribute: resp.data['default_point_attribute'] || '', + default_point_cloud: resp.data['default_point_cloud'] || '', + initialLOD: resp.data['initialLOD'] || 0, + max_levels: resp.data['max_levels'] || null, + max_point_number: resp.data['max_point_number'] || 50000, + minLOD: resp.data['minLOD'] || 0, + point_attributes: resp.data['point_attributes'] || null, + point_size: resp.data['point_size'] || 0, + width: resp.data['width'] || 0 + }); + + const attr = []; + for (const key in this.serverConfig.point_attributes) { + if (this.serverConfig.point_attributes[key].visible == 1) { + attr.push(this.serverConfig.point_attributes[key]); + } + } + + const selectedMat = this.serverConfig.point_attributes[this.serverConfig.default_point_attribute]; + + this.clientConfig.pointAttributes = { + availableOptions: attr, + selectedOption: selectedMat + }; + }); + } +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfLidarprofileConfig', []); +exports.module.service('gmfLidarprofileConfig', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Manager.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Manager.js new file mode 100644 index 000000000..21f9b79c9 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Manager.js @@ -0,0 +1,506 @@ +/** + * @module gmf.lidarprofile.Manager + */ +import gmfLidarprofileMeasure from 'gmf/lidarprofile/Measure.js'; +import gmfLidarprofilePlot from 'gmf/lidarprofile/Plot.js'; +import gmfLidarprofileUtils from 'gmf/lidarprofile/Utils.js'; +import ngeoMiscDebounce from 'ngeo/misc/debounce.js'; +import olLayerVector from 'ol/layer/Vector.js'; +import olOverlay from 'ol/Overlay.js'; +import olSourceVector from 'ol/source/Vector.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleStyle from 'ol/style/Style.js'; +import {select} from 'd3-selection'; +const d3 = { + select, +}; + + +const exports = class { + + /** + * Provides a service to manage a D3js component to be used to draw an lidar point cloud profile chart. + * Requires access to a Pytree webservice: https://github.com/sitn/pytree + * + * @struct + * @param {angular.$http} $http Angular http service. + * @param {angular.$filter} $filter Angular filter. + * @param {angularGettext.Catalog} gettextCatalog Gettext catalog. + * @param {ngeo.misc.Debounce} ngeoDebounce ngeo debounce service. + * @ngInject + * @ngdoc service + * @ngname gmflidarprofileManager + */ + constructor($http, $filter, gettextCatalog, ngeoDebounce) { + + /** + * @type {angular.$http} + */ + this.$http = $http; + + /** + * @type {angular.$filter} + */ + this.$filter = $filter; + + /** + * @type {angularGettext.Catalog} + */ + this.gettextCatalog = gettextCatalog; + + /** + * @type {ngeo.misc.Debounce} + * @private + */ + this.ngeoDebounce_ = ngeoDebounce; + + /** + * @type {?angular.$q.Promise} + * @private + */ + this.promise = null; + + /** + * @type {gmf.lidarprofile.Plot} + */ + this.plot = null; + + /** + * @type {gmf.lidarprofile.Measure} + */ + this.measure = null; + + /** + * @type {gmf.lidarprofile.Config} + */ + this.config = null; + + /** + * @type {ol.Map} + * @private + */ + this.map_ = null; + + /** + * The hovered point attributes in D3 profile highlighted on the 2D map + * @type {ol.Overlay} + */ + this.cartoHighlight = new olOverlay({ + offset: [0, -15], + positioning: 'bottom-center' + }); + + /** + * The hovered point geometry (point) in D3 profile highlighted on the 2D map + * @type {ol.layer.Vector} + */ + this.lidarPointHighlight = new olLayerVector({ + source: new olSourceVector({}), + style: new olStyleStyle({ + image: new olStyleCircle({ + fill: new olStyleFill({ + color: 'rgba(0, 0, 255, 1)' + }), + radius: 3 + }) + }) + }); + + /** + * The profile footpring represented as a LineString represented + * with real mapunites stroke width + * @type {ol.layer.Vector} + */ + this.lidarBuffer = new olLayerVector({ + source: new olSourceVector({}) + }); + + + /** + * The variable where all points of the profile are stored + * @type {gmfx.LidarprofilePoints} + */ + this.profilePoints = this.getEmptyProfilePoints_(); + + /** + * @type {boolean} + * @private + */ + this.isPlotSetup_ = false; + + /** + * @type {ol.geom.LineString} + * @private + */ + this.line_; + + /** + * @type {gmf.lidarprofile.Utils} + */ + this.utils = new gmfLidarprofileUtils(); + } + + /** + * @param {gmf.lidarprofile.Config} config Instance of gmf.lidarprofile.Config + * @param {ol.Map} map The map. + */ + init(config, map) { + this.config = config; + this.plot = new gmfLidarprofilePlot(this); + this.measure = new gmfLidarprofileMeasure(this); + this.setMap(map); + } + + /** + * Clears the profile footprint + * @export + */ + clearBuffer() { + if (this.lidarBuffer) { + this.lidarBuffer.getSource().clear(); + } + } + + + /** + * Set the line for the profile + * @param {ol.geom.LineString} line that defines the profile + * @export + */ + setLine(line) { + this.line_ = line; + } + + /** + * Set the map used by the profile + * @param {ol.Map} map The map. + * @export + */ + setMap(map) { + this.map_ = map; + this.cartoHighlight.setMap(map); + this.lidarPointHighlight.setMap(map); + this.lidarBuffer.setMap(map); + } + + /** + * @return {gmfx.LidarprofilePoints} An empty lidarprofile points object. + * @private + */ + getEmptyProfilePoints_() { + return { + distance: [], + altitude: [], + color_packed: [], + intensity: [], + classification: [], + coords: [] + }; + } + + + /** + * Load profile data (lidar points) by successive Levels Of Details using asynchronous requests + * @param {Array} clippedLine an array of the clipped line coordinates + * @param {number} distanceOffset the left side of D3 profile domain at current zoom and pan configuration + * @param {boolean} resetPlot whether to reset D3 plot or not + * @param {number} minLOD minimum Level Of Detail + * @export + */ + getProfileByLOD(clippedLine, distanceOffset, resetPlot, minLOD) { + + const gettextCatalog = this.gettextCatalog; + this.profilePoints = this.getEmptyProfilePoints_(); + + if (resetPlot) { + this.isPlotSetup_ = false; + } + + d3.select('#gmf-lidarprofile-container .lidar-error').style('visibility', 'hidden'); + let pytreeLinestring = this.utils.getPytreeLinestring(this.line_); + + let maxLODWith; + const max_levels = this.config.serverConfig.max_levels; + if (distanceOffset == 0) { + maxLODWith = this.utils.getNiceLOD(this.line_.getLength(), max_levels); + } else { + const domain = this.plot.updateScaleX['domain'](); + pytreeLinestring = ''; + + for (let i = 0; i < clippedLine.length; i++) { + pytreeLinestring += `{${clippedLine[i][0]},${clippedLine[i][1]}},`; + } + pytreeLinestring = pytreeLinestring.substr(0, pytreeLinestring.length - 1); + maxLODWith = this.utils.getNiceLOD(domain[1] - domain[0], max_levels); + + } + + let lastLOD = false; + d3.select('#gmf-lidarprofile-container .lod-info').html(''); + this.config.clientConfig.pointSum = 0; + let profileWidth = 0; + if (this.config.clientConfig.autoWidth) { + profileWidth = maxLODWith.width; + } else { + profileWidth = this.config.serverConfig.width; + } + + const profileWidthTxt = gettextCatalog.getString('Profile width: '); + d3.select('#gmf-lidarprofile-container .width-info').html(`${profileWidthTxt} ${profileWidth}m`); + + for (let i = 0; i < maxLODWith.maxLOD; i++) { + if (i == 0) { + this.queryPytree_(minLOD, this.config.serverConfig.initialLOD, i, pytreeLinestring, distanceOffset, lastLOD, profileWidth, resetPlot); + i += this.config.serverConfig.initialLOD - 1; + } else if (i < maxLODWith.maxLOD - 1) { + this.queryPytree_(minLOD + i, minLOD + i + 1, i, pytreeLinestring, distanceOffset, lastLOD, profileWidth, false); + } else { + lastLOD = true; + this.queryPytree_(minLOD + i, minLOD + i + 1, i, pytreeLinestring, distanceOffset, lastLOD, profileWidth, false); + } + } + } + + + /** + * Request to Pytree service for a range of Level Of Detail (LOD) + * @param {number} minLOD minimum Level Of Detail of the request + * @param {number} maxLOD maximum Level Of Detail of the request + * @param {number} iter the iteration in profile requests cycle + * @param {string} coordinates linestring in cPotree format + * @param {number} distanceOffset the left side of D3 profile domain at current zoom and pan configuration + * @param {boolean} lastLOD the deepest level to retrieve for this profile + * @param {number} width the width of the profile + * @param {boolean} resetPlot whether to reset D3 plot or not, used for first LOD + * @private + */ + queryPytree_(minLOD, maxLOD, iter, coordinates, distanceOffset, lastLOD, width, resetPlot) { + const gettextCatalog = this.gettextCatalog; + const lodInfo = d3.select('#gmf-lidarprofile-container .lod-info'); + if (this.config.serverConfig.debug) { + let html = lodInfo.html(); + const loadingLodTxt = gettextCatalog.getString('Loading LOD: '); + html += `${loadingLodTxt} ${minLOD}-${maxLOD}...
`; + lodInfo.html(html); + } + + const pointCloudName = this.config.serverConfig.default_point_cloud; + const hurl = `${this.config.pytreeLidarprofileJsonUrl}profile/get?minLOD=${minLOD} + &maxLOD=${maxLOD}&width=${width}&coordinates=${coordinates}&pointCloud=${pointCloudName}&attributes=`; + + this.$http.get(hurl, { + headers: { + 'Content-Type': 'text/plain; charset=x-user-defined' + }, + responseType: 'arraybuffer' + }).then((response) => { + if (this.config.serverConfig.debug) { + let html = lodInfo.html(); + const lodTxt = gettextCatalog.getString('LOD: '); + const loadedTxt = gettextCatalog.getString('loaded'); + html += `${lodTxt} ${minLOD}-${maxLOD} ${loadedTxt}
`; + lodInfo.html(html); + } + this.processBuffer_(response.data, iter, distanceOffset, lastLOD, resetPlot); + }, (response) => { + console.error(response); + }); + } + + /** + * Process the binary array return by Pytree (cPotree) + * @param {ArrayBuffer} profile binary array returned by cPotree executable called by Pytree + * @param {number} iter the iteration in profile requests cycle + * @param {number} distanceOffset the left side of D3 profile domain at current zoom and pan configuration + * @param {boolean} lastLOD the deepest level to retrieve for this profile + * @param {boolean} resetPlot whether to reset D3 plot or not + * @private + */ + processBuffer_(profile, iter, distanceOffset, lastLOD, resetPlot) { + const lidarError = d3.select('#gmf-lidarprofile-container .lidar-error'); + + const typedArrayInt32 = new Int32Array(profile, 0, 4); + const headerSize = typedArrayInt32[0]; + + const uInt8header = new Uint8Array(profile, 4, headerSize); + let strHeaderLocal = ''; + for (let i = 0; i < uInt8header.length; i++) { + strHeaderLocal += String.fromCharCode(uInt8header[i]); + } + + try { + + JSON.parse(strHeaderLocal); + + } catch (e) { + if (!this.isPlotSetup_) { + const canvas = d3.select('#gmf-lidarprofile-container .lidar-canvas'); + const canvasEl = canvas.node(); + const ctx = canvasEl.getContext('2d'); + ctx.clearRect(0, 0, canvasEl.getBoundingClientRect().width, canvasEl.getBoundingClientRect().height); + canvas.selectAll('*').remove(); + const errorTxt = this.getHTMLError_(); + lidarError.style('visibility', 'visible'); + lidarError.html(errorTxt); + } + return; + } + + lidarError.style('visibility', 'hidden'); + + const jHeader = JSON.parse(strHeaderLocal); + + // If number of points return is higher than Pytree configuration max value, + // stop sending requests. + this.config.clientConfig.pointSum += jHeader['points']; + if (this.config.clientConfig.pointSum > + this.config.serverConfig.max_point_number) { + console.warn('Number of points is higher than Pytree configuration max value !'); + } + + const attr = jHeader['pointAttributes']; + const attributes = []; + for (let j = 0; j < attr.length; j++) { + if (this.config.serverConfig.point_attributes[attr[j]] != undefined) { + attributes.push(this.config.serverConfig.point_attributes[attr[j]]); + } + } + const scale = jHeader['scale']; + + if (jHeader['points'] < 3) { + return; + } + + const points = this.getEmptyProfilePoints_(); + const bytesPerPoint = jHeader['bytesPerPoint']; + const buffer = profile.slice(4 + headerSize); + for (let i = 0; i < jHeader['points']; i++) { + + const byteOffset = bytesPerPoint * i; + const view = new DataView(buffer, byteOffset, bytesPerPoint); + let aoffset = 0; + for (let k = 0; k < attributes.length; k++) { + + if (attributes[k]['value'] == 'POSITION_PROJECTED_PROFILE') { + const udist = view.getUint32(aoffset, true); + const dist = udist * scale; + points.distance.push(Math.round(100 * (distanceOffset + dist)) / 100); + this.profilePoints.distance.push(Math.round(100 * (distanceOffset + dist)) / 100); + + } else if (attributes[k]['value'] == 'CLASSIFICATION') { + const classif = view.getUint8(aoffset); + points.classification.push(classif); + this.profilePoints.classification.push(classif); + + } else if (attributes[k]['value'] == 'INTENSITY') { + const intensity = view.getUint8(aoffset); + points.intensity.push(intensity); + this.profilePoints.intensity.push(intensity); + + } else if (attributes[k]['value'] == 'COLOR_PACKED') { + const r = view.getUint8(aoffset); + const g = view.getUint8(aoffset + 1); + const b = view.getUint8(aoffset + 2); + points.color_packed.push([r, g, b]); + this.profilePoints.color_packed.push([r, g, b]); + + } else if (attributes[k]['value'] == 'POSITION_CARTESIAN') { + const x = view.getInt32(aoffset, true) * scale + jHeader['boundingBox']['lx']; + const y = view.getInt32(aoffset + 4, true) * scale + jHeader['boundingBox']['ly']; + const z = view.getInt32(aoffset + 8, true) * scale + jHeader['boundingBox']['lz']; + points.coords.push([x, y]); + points.altitude.push(z); + this.profilePoints.altitude.push(z); + this.profilePoints.coords.push([x, y]); + } + aoffset = aoffset + attributes[k]['bytes']; + } + } + + const rangeX = [0, this.line_.getLength()]; + + const rangeY = [this.utils.arrayMin(points.altitude), this.utils.arrayMax(points.altitude)]; + + if (iter == 0 && resetPlot || !this.isPlotSetup_) { + this.plot.setupPlot(rangeX, rangeY); + this.isPlotSetup_ = true; + } + this.plot.drawPoints(points); + } + + /** + * @return {string} The html for errors. + * @private + */ + getHTMLError_() { + const gettextCatalog = this.gettextCatalog; + const errorInfoTxt = gettextCatalog.getString('Lidar profile service error'); + const errorOfflineTxt = gettextCatalog.getString('It might be offline'); + const errorOutsideTxt = gettextCatalog.getString('Or did you attempt to draw a profile outside data extent?'); + const errorNoPointError = gettextCatalog.getString('Or did you attempt to draw such a small profile that no point was returned?'); + return ` +
+

${errorInfoTxt}

+

${errorOfflineTxt}

+

${errorOutsideTxt}

+

${errorNoPointError}

+ `; + } + + /** + * Update the profile data according to D3 chart zoom and pan level + * The update will wait on a 200ms pause on the actions of users before to do the update. + * @export + */ + updateData() { + this.ngeoDebounce_(this.updateData_.bind(this), 200, true)(); + } + + /** + * @private + */ + updateData_() { + const domainX = this.plot.updateScaleX['domain'](); + let map_resolution = this.map_ ? this.map_.getView().getResolution() : 0; + map_resolution = map_resolution || 0; + const clip = this.utils.clipLineByMeasure(this.config, map_resolution, + this.line_, domainX[0], domainX[1]); + + this.lidarBuffer.getSource().clear(); + this.lidarBuffer.getSource().addFeature(clip.bufferGeom); + this.lidarBuffer.setStyle(clip.bufferStyle); + + const span = domainX[1] - domainX[0]; + const maxLODWidth = this.utils.getNiceLOD(span, this.config.serverConfig.max_levels); + const xTolerance = 0.2; + + if (Math.abs(domainX[0] - this.plot.previousDomainX[0]) < xTolerance && + Math.abs(domainX[1] - this.plot.previousDomainX[1]) < xTolerance) { + + this.plot.drawPoints(this.profilePoints); + + } else { + if (maxLODWidth.maxLOD <= this.config.serverConfig.initialLOD) { + this.plot.drawPoints(this.profilePoints); + } else { + this.getProfileByLOD(clip.clippedLine, clip.distanceOffset, false, 0); + + } + } + + this.plot.previousDomainX = domainX; + } + +}; + + +/** + * @type {!angular.Module} + */ +exports.module = angular.module('gmfLidarprofileManager', [ + ngeoMiscDebounce.name, +]); +exports.module.service('gmfLidarprofileManager', exports); + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Measure.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Measure.js new file mode 100644 index 000000000..6b0fc773a --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Measure.js @@ -0,0 +1,174 @@ +/** + * @module ngeo.lidarprofile.Measure + */ +import {mouse, select} from 'd3-selection'; +const d3 = { + mouse, + select, +}; + + +const exports = class { + + /** + * Measure tool for the d3 chart + * @struct + * @param {gmf.lidarprofile.Manager} gmfLidarprofileManagerInstance gmf lidar profile manager instance + */ + constructor(gmfLidarprofileManagerInstance) { + + /** + * @type {gmf.lidarprofile.Manager} + * @private + */ + this.manager_ = gmfLidarprofileManagerInstance; + + /** + * @type {!gmfx.LidarPoint} + * @private + */ + this.pStart_ = {}; + + /** + * @type {!gmfx.LidarPoint} + * @private + */ + this.pEnd_ = {}; + } + + + /** + * Clear the current measure + * @export + */ + clearMeasure() { + this.pStart_ = {}; + this.pEnd_ = {}; + + const svg = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + svg.selectAll('#text_m').remove(); + svg.selectAll('#start_m').remove(); + svg.selectAll('#end_m').remove(); + svg.selectAll('#line_m').remove(); + + svg.on('click', null); + + svg.style('cursor', 'default'); + } + + + /** + * Activate the measure tool + * @export + */ + setMeasureActive() { + const svg = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + svg.style('cursor', 'pointer'); + svg.on('click', this.measureHeigt.bind(this)); + } + + + /** + * Measure and display height after two click on the profile. + */ + measureHeigt() { + const svg = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + const svgCoordinates = d3.mouse(svg.node()); + const canvasCoordinates = d3.mouse(d3.select('#gmf-lidarprofile-container .lidar-canvas').node()); + const margin = this.manager_.config.clientConfig.margin; + const xs = svgCoordinates[0]; + const ys = svgCoordinates[1]; + const tolerance = 2; + const sx = this.manager_.plot.updateScaleX; + const sy = this.manager_.plot.updateScaleY; + const pointSize = 3; + const p = this.manager_.utils.getClosestPoint( + this.manager_.profilePoints, + canvasCoordinates[0], + canvasCoordinates[1], + tolerance, + this.manager_.plot.updateScaleX, + this.manager_.plot.updateScaleY, + this.manager_.config.serverConfig.classification_colors); + + if (!this.pStart_.set) { + + if (p !== undefined) { + this.pStart_.distance = p.distance; + this.pStart_.altitude = p.altitude; + this.pStart_.cx = sx(p.distance) + margin.left; + this.pStart_.cy = sy(p.altitude) + margin.top; + } else { + this.pStart_.distance = sx['invert'](xs); + this.pStart_.altitude = sy['invert'](ys); + this.pStart_.cx = xs; + this.pStart_.cy = ys; + } + + this.pStart_.set = true; + svg.append('circle') + .attr('id', 'start_m') + .attr('cx', this.pStart_.cx) + .attr('cy', this.pStart_.cy) + .attr('r', pointSize) + .style('fill', 'red'); + + } else if (!this.pEnd_.set) { + if (p !== undefined) { + + this.pEnd_.distance = p.distance; + this.pEnd_.altitude = p.altitude; + this.pEnd_.cx = sx(p.distance) + margin.left; + this.pEnd_.cy = sy(p.altitude) + margin.top; + } else { + this.pEnd_.distance = sx['invert'](xs); + this.pEnd_.altitude = sy['invert'](ys); + this.pEnd_.cx = xs; + this.pEnd_.cy = ys; + + } + + this.pEnd_.set = true; + svg.append('circle') + .attr('id', 'end_m') + .attr('cx', this.pEnd_.cx) + .attr('cy', this.pEnd_.cy) + .attr('r', pointSize) + .style('fill', 'red'); + + svg.append('line') + .attr('id', 'line_m') + .attr('x1', this.pStart_.cx) + .attr('y1', this.pStart_.cy) + .attr('x2', this.pEnd_.cx) + .attr('y2', this.pEnd_.cy) + .attr('stroke-width', 2) + .attr('stroke', 'red'); + + } + + if (this.pStart_.set && this.pEnd_.set) { + const dH = this.pEnd_.altitude - this.pStart_.altitude; + const dD = this.pEnd_.distance - this.pStart_.distance; + + const height = Math.round(10 * Math.sqrt(Math.pow(dH, 2) + Math.pow(dD, 2))) / 10; + + if (!isNaN(height)) { + svg.append('text') + .attr('id', 'text_m') + .attr('x', 10 + (this.pStart_.cx + this.pEnd_.cx) / 2) + .attr('y', (this.pStart_.cy + this.pEnd_.cy) / 2) + .text(`${height} m`) + .attr('font-family', 'sans-serif') + .attr('font-size', '14px') + .style('font-weight', 'bold') + .attr('fill', 'red'); + } + this.pEnd_.set = false; + this.pStart_.set = false; + } + } +}; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Plot.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Plot.js new file mode 100644 index 000000000..4e25f8040 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Plot.js @@ -0,0 +1,443 @@ +/** + * @module gmf.lidarprofile.Plot + */ +import olFeature from 'ol/Feature.js'; +import olGeomPoint from 'ol/geom/Point.js'; +import olStyleCircle from 'ol/style/Circle.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleStyle from 'ol/style/Style.js'; +import {axisBottom, axisLeft} from 'd3-axis'; +import {scaleLinear} from 'd3-scale'; +import {event as d3Event, mouse, select} from 'd3-selection'; +import {zoom} from 'd3-zoom'; +const d3 = { + axisBottom, + axisLeft, + mouse, + scaleLinear, + select, + zoom, +}; + + +const exports = class { + + /** + * Provides a service to create an SVG element with defined axis and a LIDAR + * point drawing mechanism. + * + * @struct + * @param {gmf.lidarprofile.Manager} gmfLidarprofileManagerInstance gmf lidar profile manager instance + */ + constructor(gmfLidarprofileManagerInstance) { + + /** + * @type {gmf.lidarprofile.Manager} + * @private + */ + this.manager_ = gmfLidarprofileManagerInstance; + + /** + * d3.scaleLinear X scale. + * @type {Function} + */ + this.scaleX; + + /** + * d3.scaleLinear X scale. + * @type {Function} + */ + this.updateScaleX; + + /** + * d3.scaleLinear Y scale. + * @type {Function} + */ + this.scaleY; + + /** + * d3.scaleLinear Y scale. + * @type {Function} + */ + this.updateScaleY; + + /** + * The material used for the drawing process. Initialized in the setup + * @type {string} + */ + this.material; + + /** + * @type {number} + * @private + */ + this.width_; + + /** + * @type {number} + * @private + */ + this.height_; + + /** + * @type {Array.} + */ + this.previousDomainX = []; + + /** + * @type {boolean} + * @private + */ + this.moved_ = false; + } + + + /** + * Draw the points to the canvas element + * @param {gmfx.LidarprofilePoints} points of the profile + * @export + */ + drawPoints(points) { + let i = -1; + const nPoints = points.distance.length; + let cx, cy; + const ctx = d3.select('#gmf-lidarprofile-container .lidar-canvas').node().getContext('2d'); + const profileServerConfig = this.manager_.config.serverConfig; + + while (++i < nPoints) { + + const distance = points.distance[i]; + const altitude = points.altitude[i]; + const rgb = points.color_packed[i]; + const intensity = points.intensity[i]; + const classification = points.classification[i]; + if (profileServerConfig.classification_colors[classification] && + profileServerConfig.classification_colors[classification].visible) { + + cx = this.updateScaleX(distance); + cy = this.updateScaleY(altitude); + + ctx.beginPath(); + ctx.moveTo(cx, cy); + + if (this.material == 'COLOR_PACKED') { + ctx.fillStyle = `RGB(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`; + } else if (this.material == 'INTENSITY') { + ctx.fillStyle = `RGB(${intensity}, ${intensity}, ${intensity})`; + } else if (this.material == 'CLASSIFICATION') { + ctx.fillStyle = `RGB(${profileServerConfig.classification_colors[classification].color})`; + } else { + ctx.fillStyle = profileServerConfig.default_color; + } + ctx.arc(cx, cy, profileServerConfig.point_size, 0, 2 * Math.PI, false); + ctx.fill(); + } + } + } + + + /** + * Setup the SVG components of the D3 chart + * @param {Array.} rangeX range of the x scale + * @param {Array.} rangeY range of the y scale + * @export + */ + setupPlot(rangeX, rangeY) { + const canvas = d3.select('#gmf-lidarprofile-container .lidar-canvas'); + const canvasEl = canvas.node(); + const ctx = canvasEl.getContext('2d'); + ctx.clearRect(0, 0, canvasEl.getBoundingClientRect().width, canvasEl.getBoundingClientRect().height); + + const margin = this.manager_.config.clientConfig.margin; + const containerEl = d3.select('#gmf-lidarprofile-container').node(); + const containerWidth = containerEl.getBoundingClientRect().width; + const containerHeight = containerEl.getBoundingClientRect().height; + this.width_ = containerWidth - (margin.left + margin.right); + this.height_ = containerHeight - (margin.top + margin.bottom); + + this.material = this.manager_.config.serverConfig.default_attribute; + + canvas.attr('height', this.height_) + .attr('width', this.width_) + .style('background-color', 'black') + .style('z-index', 0) + .style('position', 'absolute') + .style('margin-left', `${margin.left.toString()}px`) + .style('margin-top', `${margin.top.toString()}px`); + + const domainProfileWidth = rangeX[1] - rangeX[0]; + const domainProfileHeight = rangeY[1] - rangeY[0]; + const domainRatio = domainProfileWidth / domainProfileHeight; + const rangeProfileWidth = this.width_; + const rangeProfileHeight = this.height_; + const rangeRatio = rangeProfileWidth / rangeProfileHeight; + + let domainScale; + if (domainRatio < rangeRatio) { + const domainScale = rangeRatio / domainRatio; + const domainScaledWidth = domainProfileWidth * domainScale; + this.scaleX = d3.scaleLinear(); + this.scaleX['domain']([0, domainScaledWidth]); + this.scaleX['range']([0, this.width_]); + this.scaleY = d3.scaleLinear(); + this.scaleY['domain'](rangeY); + this.scaleY['range']([this.height_, 0]); + } else { + domainScale = domainRatio / rangeRatio; + const domainScaledHeight = domainProfileHeight * domainScale; + const domainHeightCentroid = (rangeY[1] + rangeY[0]) / 2; + this.scaleX = d3.scaleLinear(); + this.scaleX['domain'](rangeX); + this.scaleX['range']([0, this.width_]); + this.scaleY = d3.scaleLinear(); + this.scaleY['domain']([ + domainHeightCentroid - domainScaledHeight / 2, + domainHeightCentroid + domainScaledHeight / 2]); + this.scaleY['range']([this.height_, 0]); + } + + const zoom = d3.zoom() + .scaleExtent([-10, 100]) + .translateExtent([[0, 0], [this.width_, this.height_]]) + .extent([[0, 0], [this.width_, this.height_]]) + .on('zoom', this.zoomed.bind(this)); + + zoom.on('end', this.zoomEnd.bind(this)); + + this.previousDomainX = this.scaleX['domain'](); + this.updateScaleX = this.scaleX; + this.updateScaleY = this.scaleY; + + const svg = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + + svg.call(zoom).on('dblclick.zoom', null); + + svg.selectAll('*').remove(); + + svg.attr('width', this.width_ + margin.left) + .attr('height', this.height_ + margin.top + margin.bottom); + + svg.on('mousemove', () => { + this.pointHighlight.bind(this)(); + }); + + + const xAxis = d3.axisBottom(this.scaleX); + const yAxis = d3.axisLeft(this.scaleY) + .tickSize(-this.width_); + + svg.select('.y.axis').selectAll('g.tick line').style('stroke', '#b7cff7'); + + svg.append('g') + .attr('class', 'y axis') + .call(yAxis); + + svg.append('g') + .attr('class', 'x axis') + .call(xAxis); + + svg.select('.y.axis').attr('transform', `translate(${margin.left}, ${margin.top})`); + svg.select('.x.axis').attr('transform', `translate(${margin.left}, ${this.height_ + margin.top})`); + + svg.select('.y.axis').selectAll('g.tick line') + .style('opacity', '0.5') + .style('stroke', '#b7cff7'); + + } + + + /** + * Update the plot data at the end of the zoom process + * @export + */ + zoomEnd() { + if (d3Event.sourceEvent && this.moved_ === false) { + return; + } + this.moved_ = false; + const ctx = d3.select('#gmf-lidarprofile-container .lidar-canvas') + .node().getContext('2d'); + ctx.clearRect(0, 0, this.width_, this.height_); + this.manager_.updateData(); + } + + + /** + * Update the plot axis during the zoom process + * @export + */ + zoomed() { + if (d3Event.sourceEvent && d3Event.sourceEvent.type === 'mousemove') { + this.moved_ = true; + if (d3Event.sourceEvent.movementX == 0 && d3Event.sourceEvent.movementY == 0) { + return; + } + } + + this.manager_.measure.clearMeasure(); + + const tr = d3Event.transform; + const svg = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + const xAxis = d3.axisBottom(this.scaleX); + const yAxis = d3.axisLeft(this.scaleY) + .tickSize(-this.width_); + + const new_scaleX = tr.rescaleX(this.scaleX); + const new_scaleY = tr.rescaleY(this.scaleY); + + svg.select('.x.axis').call(xAxis.scale(new_scaleX)); + svg.select('.y.axis').call(yAxis.scale(new_scaleY)); + + const ctx = d3.select('#gmf-lidarprofile-container .lidar-canvas') + .node().getContext('2d'); + ctx.clearRect(0, 0, this.width_, this.height_); + + svg.select('.y.axis').selectAll('g.tick line') + .style('opacity', '0.5') + .style('stroke', '#b7cff7'); + + this.updateScaleX = new_scaleX; + this.updateScaleY = new_scaleY; + + } + + + /** + * Update the Openlayers overlay that displays point position and attributes values + * @export + */ + pointHighlight() { + + const svg = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + const lidarInfo = d3.select('#gmf-lidarprofile-container .lidar-info'); + const pointSize = this.manager_.config.serverConfig.point_size; + const margin = this.manager_.config.clientConfig.margin; + const tolerance = this.manager_.config.clientConfig.tolerance || 0; + + const canvasCoordinates = d3.mouse(d3.select('#gmf-lidarprofile-container .lidar-canvas').node()); + const classification_colors = this.manager_.config.serverConfig.classification_colors; + + let cx, cy; + const p = this.manager_.utils.getClosestPoint(this.manager_.profilePoints, + canvasCoordinates[0], canvasCoordinates[1], tolerance, this.updateScaleX, this.updateScaleY, classification_colors); + + if (p != undefined) { + + cx = this.updateScaleX(p.distance) + margin.left; + cy = this.updateScaleY(p.altitude) + margin.top; + + svg.selectAll('#highlightCircle').remove(); + + svg.append('circle') + .attr('id', 'highlightCircle') + .attr('cx', cx) + .attr('cy', cy) + .attr('r', pointSize + 1) + .style('fill', 'orange'); + + const pClassification = p.classification || -1; + const pointClassification = classification_colors[pClassification] || {}; + + const html = this.getInfoHTML(p, pointClassification, 1); + + lidarInfo.html(html); + this.manager_.cartoHighlight.setElement(null); + const el = document.createElement('div'); + el.className += 'tooltip gmf-tooltip-measure'; + el.innerHTML = html; + + this.manager_.cartoHighlight.setElement(el); + this.manager_.cartoHighlight.setPosition([p.coords[0], p.coords[1]]); + this.manager_.lidarPointHighlight.getSource().clear(); + const lidarPointGeom = new olGeomPoint([p.coords[0], p.coords[1]]); + const lidarPointFeature = new olFeature(lidarPointGeom); + if (typeof (pointClassification.color) !== undefined) { + + lidarPointFeature.setStyle(new olStyleStyle({ + image: new olStyleCircle({ + fill: new olStyleFill({ + color: `rgba(${pointClassification.color}, 1)` + }), + radius: 3 + }) + })); + } + + this.manager_.lidarPointHighlight.getSource().addFeature(lidarPointFeature); + } else { + this.manager_.lidarPointHighlight.getSource().clear(); + svg.select('#highlightCircle').remove(); + lidarInfo.html(''); + this.manager_.cartoHighlight.setPosition(undefined); + } + } + + + /** + * @param {gmfx.LidarPoint} point the concerned point. + * @param {lidarprofileServer.ConfigClassification} classification_color the classification + * object concerning this point. + * @param {number} distDecimal the number of decimal to keep. + * @return {string} the text for the html info. + * @export + */ + getInfoHTML(point, classification_color, distDecimal) { + const gettextCatalog = this.manager_.gettextCatalog; + const html = []; + const number = this.manager_.$filter('number'); + + const distance = point.distance; + const altitude = point.altitude; + const classification = gettextCatalog.getString(classification_color.name); + const intensity = point.intensity; + + if (distance !== undefined) { + const distanceTxt = gettextCatalog.getString('Distance: '); + html.push(`${distanceTxt + number(distance, distDecimal)}`); + } + if (altitude !== undefined) { + const altitudeTxt = gettextCatalog.getString('Altitude: '); + html.push(`${altitudeTxt + number(altitude, distDecimal)}`); + } + if (classification.length > 0) { + const classificationTxt = gettextCatalog.getString('Classification: '); + html.push(`${classificationTxt + classification}`); + } + if (intensity !== undefined) { + const intensityTxt = gettextCatalog.getString('Intensity: '); + html.push(`${intensityTxt + number(intensity, 0)}`); + } + + return html.join('
'); + } + + + /** + * Change the profile style according to the material color + * @param {string} material value as defined in Pytree attribute configuration + * @export + */ + changeStyle(material) { + this.material = material; + const canvasEl = d3.select('#gmf-lidarprofile-container .lidar-canvas').node(); + const ctx = canvasEl.getContext('2d'); + ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); + this.drawPoints(this.manager_.profilePoints); + } + + + /** + * Show/Hide classes in the profile + * @param {lidarprofileServer.ConfigClassifications} classification value as defined in the Pytree classification_colors + * configuration + * @param {string} material value as defined in Pytree attribute configuration + * @export + */ + setClassActive(classification, material) { + this.manager_.config.serverConfig.classification_colors = classification; + this.changeStyle(material); + } +}; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Utils.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Utils.js new file mode 100644 index 000000000..e0547e8c4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/Utils.js @@ -0,0 +1,373 @@ +/** + * @module gmf.lidarprofile.Utils + */ +import olFeature from 'ol/Feature.js'; +import olGeomLineString from 'ol/geom/LineString.js'; +import olGeomPoint from 'ol/geom/Point.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleRegularShape from 'ol/style/RegularShape.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; +import {saveAs} from 'file-saver'; +import {select} from 'd3-selection'; +const d3 = { + select, +}; + + +const exports = class { + + /** + * Clip a linstring with start and end measure given by D3 Chart domain + * @param {gmf.lidarprofile.Config} config the LIDAR profile config instance + * @param {number} map_resolution the current resolution of the map + * @param {ol.geom.LineString} linestring an OpenLayer Linestring + * @param {number} dLeft domain minimum + * @param {number} dRight domain maximum + * @return {{clippedLine: Array., distanceOffset: number}} Object with clipped lined coordinates and left domain value + */ + clipLineByMeasure(config, map_resolution, linestring, dLeft, dRight) { + + const clippedLine = new olGeomLineString([]); + let mileage_start = 0; + let mileage_end = 0; + + const totalLength = linestring.getLength(); + const fractionStart = dLeft / totalLength; + const fractionEnd = dRight / totalLength; + + let segNumber = linestring.getCoordinates().length - 1; + let counter = 0; + + linestring.forEachSegment((segStart, segEnd) => { + counter += 1; + const segLine = new olGeomLineString([segStart, segEnd]); + mileage_end += segLine.getLength(); + + if (dLeft == mileage_start) { + clippedLine.appendCoordinate(segStart); + } else if (dLeft > mileage_start && dLeft < mileage_end) { + clippedLine.appendCoordinate(linestring.getCoordinateAt(fractionStart)); + } + + if (mileage_start > dLeft && mileage_start < dRight) { + clippedLine.appendCoordinate(segStart); + } + + if (dRight == mileage_end) { + clippedLine.appendCoordinate(segEnd); + } else if (dRight > mileage_start && dRight < mileage_end) { + clippedLine.appendCoordinate(linestring.getCoordinateAt(fractionEnd)); + } else if (dRight > mileage_start && dRight > mileage_end && counter === segNumber) { + clippedLine.appendCoordinate(linestring.getCoordinateAt(fractionEnd)); + } + + mileage_start += segLine.getLength(); + + }); + + const feat = new olFeature({ + geometry: clippedLine + }); + + const lineStyle = new olStyleStyle({ + stroke: new olStyleStroke({ + color: 'rgba(255,0,0,1)', + width: 2, + lineCap: 'square' + }) + }); + + let firstSegmentAngle = 0; + let lastSegementAngle = 0; + + segNumber = clippedLine.getCoordinates().length - 1; + let segCounter = 1; + + clippedLine.forEachSegment((start, end) => { + if (segCounter == 1) { + const dx = end[0] - start[0]; + const dy = end[1] - start[1]; + firstSegmentAngle = Math.atan2(dx, dy); + } + + if (segCounter == segNumber) { + const dx = end[0] - start[0]; + const dy = end[1] - start[1]; + + lastSegementAngle = Math.atan2(dx, dy); + } + segCounter += 1; + + + }); + + const styles = [lineStyle]; + const lineEnd = clippedLine.getLastCoordinate(); + const lineStart = clippedLine.getFirstCoordinate(); + + styles.push( + new olStyleStyle({ + geometry: new olGeomPoint(lineStart), + image: new olStyleRegularShape({ + fill: new olStyleFill({ + color: 'rgba(255, 0, 0, 1)' + }), + stroke: new olStyleStroke({ + color: 'rgba(255,0,0,1)', + width: 1, + lineCap: 'square' + }), + points: 3, + radius: 5, + rotation: firstSegmentAngle, + angle: Math.PI / 3 + }) + }), + new olStyleStyle({ + geometry: new olGeomPoint(lineEnd), + image: new olStyleRegularShape({ + fill: new olStyleFill({ + color: 'rgba(255, 0, 0, 1)' + }), + stroke: new olStyleStroke({ + color: 'rgba(255,0,0,1)', + width: 1, + lineCap: 'square' + }), + points: 3, + radius: 5, + rotation: lastSegementAngle, + angle: 4 * Math.PI / 3 + }) + }) + ); + + return { + clippedLine: clippedLine.getCoordinates(), + distanceOffset: dLeft, + bufferGeom: feat, + bufferStyle: styles + }; + + } + + + /** + * Get a Level Of Details and with for a given chart span + * Configuration is set up in Pytree configuration + * @param {number} span domain extent + * @param {lidarprofileServer.ConfigLevels} max_levels levels defined by a LIDAR server + * @return {{maxLOD: number, width: number}} Object with optimized Level Of Details and width for this profile span + */ + getNiceLOD(span, max_levels) { + let maxLOD = 0; + let width = 0; + for (const key in max_levels) { + const level = parseInt(key, 10); + if (span < level && max_levels[level].max > maxLOD) { + maxLOD = max_levels[level].max; + width = max_levels[level].width; + } + } + return { + maxLOD, + width + }; + } + + + /** + * Create a image file by combining SVG and canvas elements and let the user downloads it. + * @param {gmfx.LidarprofileClientConfig} profileClientConfig The profile client configuration. + * @export + */ + downloadProfileAsImageFile(profileClientConfig) { + const profileSVG = d3.select('#gmf-lidarprofile-container svg.lidar-svg'); + const w = parseInt(profileSVG.attr('width'), 10); + const h = parseInt(profileSVG.attr('height'), 10); + const margin = profileClientConfig.margin; + + // Create a new canvas element to avoid manipulate the one with profile. + const canvas = document.createElement('canvas'); + canvas.style.display = 'none'; + canvas.width = w; + canvas.height = h; + const ctx = canvas.getContext('2d'); + ctx.fillStyle = 'white'; + ctx.fillRect(0, 0, w, h); + + // Draw the profile canvas (the points) into the new canvas. + const profileCanvas = d3.select('#gmf-lidarprofile-container .lidar-canvas').node(); + ctx.drawImage(profileCanvas, margin.left, margin.top, + w - (margin.left + margin.right), h - (margin.top + margin.bottom)); + + // Add transforms the profile into an image. + const exportImage = new Image(); + const serializer = new XMLSerializer(); + const svgStr = serializer.serializeToString(profileSVG.node()); + + // Draw the image of the profile into the context of the new canvas. + const img_id = 'lidare_profile_for_export_uid'; + exportImage.id = img_id; + exportImage.src = `data:image/svg+xml;base64, ${btoa(svgStr)}`; + exportImage.style.setProperty('display', 'none'); + const body = document.getElementsByTagName('body')[0]; + // The image must be loaded to be drawn. + exportImage.onload = () => { + ctx.drawImage(exportImage, 0, 0, w, h); + body.removeChild(document.getElementById(img_id)); + // Let the user download the image. + canvas.toBlob((blob) => { + saveAs(blob, 'LIDAR_profile.png'); + }); + }; + body.appendChild(exportImage); + } + + + /** + * Transforms a lidarprofile into multiple single points sorted by distance. + * @param {gmfx.LidarprofilePoints} profilePoints in the profile + * @return {Array.} An array of Lidar Points. + */ + getFlatPointsByDistance(profilePoints) { + const points = []; + for (let i = 0; i < profilePoints.distance.length; i++) { + const p = { + distance: profilePoints.distance[i], + altitude: profilePoints.altitude[i], + color_packed: profilePoints.color_packed[i], + intensity: profilePoints.intensity[i], + classification: profilePoints.classification[i], + coords: profilePoints.coords[i] + }; + points.push(p); + } + points.sort((a, b) => (a.distance - b.distance)); + return points; + } + + + /** + * Get the data for a CSV export of the profile. + * @param {gmfx.LidarPoint} points a lidar profile points object. + * @return {Array.} Objects for a csv export (column: value). + * @export + */ + getCSVData(points) { + return points.map((point) => { + const row = {}; + for (const key in point) { + const value = point[key]; + if (key == 'altitude') { + row[key] = value.toFixed(4); + } else if (key == 'color_packed' || key == 'coords') { + row[key] = value.join(' '); + } else { + row[key] = value; + } + } + return row; + }); + } + + + /** + * Find the maximum value in am array of numbers + * @param {(Array.|undefined)} array of number + * @return {number} the maximum of input array + */ + arrayMax(array) { + return array.reduce((a, b) => Math.max(a, b)); + } + + + /** + * Find the minimum value in am array of numbers + * @param {Array.|undefined} array of number + * @return {number} the minimum of input array + */ + arrayMin(array) { + let minVal = Infinity; + for (let i = 0; i < array.length; i++) { + if (array[i] < minVal) { + minVal = array[i]; + } + } + return minVal; + } + + + /** + * Transform Openlayers linestring into a cPotree compatible definition + * @param {ol.geom.LineString} line the profile 2D line + * @return {string} linestring in a cPotree/pytree compatible string definition + */ + getPytreeLinestring(line) { + const coords = line.getCoordinates(); + let pytreeLineString = ''; + for (let i = 0; i < coords.length; i++) { + const px = coords[i][0]; + const py = coords[i][1]; + pytreeLineString += `{${Math.round(100 * px) / 100}, ${Math.round(100 * py) / 100}},`; + } + return pytreeLineString.substr(0, pytreeLineString.length - 1); + } + + + /** + * Find the profile's closest point in profile data to the chart mouse position + * @param {gmfx.LidarprofilePoints} points Object containing points properties as arrays + * @param {number} xs mouse x coordinate on canvas element + * @param {number} ys mouse y coordinate on canvas element + * @param {number} tolerance snap sensibility + * @param {Function} sx d3.scalelinear x scale + * @param {Function} sy d3.scalelinear y scale + * @param {lidarprofileServer.ConfigClassifications} classification_colors classification colors + * @return {gmfx.LidarPoint} closestPoint the closest point to the clicked coordinates + */ + getClosestPoint(points, xs, ys, tolerance, sx, sy, classification_colors) { + const d = points; + const tol = tolerance; + const distances = []; + const hP = []; + + for (let i = 0; i < d.distance.length; i++) { + + if (sx(d.distance[i]) < xs + tol && sx(d.distance[i]) > xs - tol && sy(d.altitude[i]) < ys + tol && sy(d.altitude[i]) > ys - tol) { + const pDistance = Math.sqrt(Math.pow((sx(d.distance[i]) - xs), 2) + Math.pow((sy(d.altitude[i]) - ys), 2)); + const cClassif = classification_colors[d.classification[i]]; + if (cClassif && cClassif.visible == 1) { + + hP.push({ + distance: d.distance[i], + altitude: d.altitude[i], + classification: d.classification[i], + color_packed: d.color_packed[i], + intensity: d.intensity[i], + coords: d.coords[i] + }); + distances.push(pDistance); + + } + } + } + + let closestPoint; + + if (hP.length > 0) { + const minDist = Math.min(distances); + const indexMin = distances.indexOf(minDist); + if (indexMin != -1) { + closestPoint = hP[indexMin]; + } else { + closestPoint = hP[0]; + } + } + return closestPoint; + } +}; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/component.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/component.html new file mode 100644 index 000000000..04f9dde39 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/component.html @@ -0,0 +1,16 @@ +
+
+
+ + +
+
+
+
+
+
+
× +
+
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/component.js new file mode 100644 index 000000000..f4688e8ba --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/component.js @@ -0,0 +1,110 @@ +/** + * @module gmf.lidarprofile.component + */ + + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLidarprofile', []); + + +exports.value('gmfLidarprofileTemplateUrl', + /** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} Template. + */ + ($element, $attrs) => { + const templateUrl = $attrs['gmfLidarprofileTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/lidarprofile'; + }); + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/lidarprofile', require('./component.html')); +}); + + +/** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.JQLite, !angular.Attributes): string} gmfLidarprofileTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfLidarprofileTemplateUrl($element, $attrs, gmfLidarprofileTemplateUrl) { + return gmfLidarprofileTemplateUrl($element, $attrs); +} + + +/** + * Provide a component that display a lidar profile panel. + * You can have only one lidarprofile in your page. + * + * Example: + * + * + * + * + * @ngdoc component + * @ngname gmfLidarprofile + */ +exports.component_ = { + controller: 'GmfLidarprofileController', + bindings: { + 'active': '=gmfLidarprofileActive', + 'line': '=gmfLidarprofileLine' + }, + templateUrl: gmfLidarprofileTemplateUrl +}; + +exports.component('gmfLidarprofile', exports.component_); + + +/** + * @private + */ +exports.Controller_ = class { + + /** + * @param {angular.Scope} $scope Angular scope. + * @private + * @ngInject + * @ngdo controller + * @ngname GmfLidarprofileController + */ + constructor($scope) { + + /** + * The Openlayer LineStringt that defines the profile + * @type {ol.geom.LineString} + * @export + */ + this.line; + + /** + * The profile active state + * @type {boolean} + * @export + */ + this.active = false; + + // Watch the line to update the profileData (data for the chart). + $scope.$watch( + () => this.line, + (newLine, oldLine) => { + if (oldLine !== newLine) { + this.active = !!this.line; + } + }); + } +}; + + +exports.controller('GmfLidarprofileController', exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/lidarprofile.less b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/lidarprofile.less new file mode 100644 index 000000000..df4e30a9b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/lidarprofile.less @@ -0,0 +1,60 @@ +@import "~gmf/less/vars.less"; + +@lidarprofile-height: 35rem; +@profile-legend-width: 15rem; +#gmf-lidarprofile-container { + position: relative; + overflow: hidden; + padding: @app-margin; + border-top: solid 1px black; + background-color: white; + height: @lidarprofile-height; + display: flex; + + .lidarprofile { + width: ~"calc(100% - @{profile-legend-width})"; + background-color: #f5f5f5; + } + + .lidar-legend { + list-style-type: none; + width: @profile-legend-width; + padding: @app-margin; + } + + .close { + height: 1rem; + } + + .lidar-error { + visibility: hidden; + position: absolute; + z-index: 10; + margin: @app-margin; + padding-left: 10rem; + padding-top: 10rem; + width: ~"calc(100% - 5rem - @{profile-legend-width})"; + height: ~"calc(@{lidarprofile-height} - 5rem)"; + font-size: 1.5em; + opacity: 1; + background: #e1f1f7; + color: #4b717f; + } + + .lod-info { + max-height: 10rem; + overflow-y: auto; + } +} + +.gmf-lidarprofile-automatic-width { + color: gray; +} + +.gmf-lidarprofile-chart-active main { + height: calc(~'100%' - @lidarprofile-height); +} + +.gmf-tooltip-measure { + font-weight: bold; +} diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/module.js new file mode 100644 index 000000000..9da9c2e97 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/module.js @@ -0,0 +1,22 @@ +/** + * @module gmf.lidarprofile.module + */ +import gmfLidarprofileComponent from 'gmf/lidarprofile/component.js'; +import gmfLidarprofilePanelComponent from 'gmf/lidarprofile/panelComponent.js'; +import gmfLidarprofileConfig from 'gmf/lidarprofile/Config.js'; +import gmfLidarprofileManager from 'gmf/lidarprofile/Manager.js'; + +import './lidarprofile.less'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLidarprofileModule', [ + gmfLidarprofileComponent.name, + gmfLidarprofilePanelComponent.name, + gmfLidarprofileConfig.module.name, + gmfLidarprofileManager.module.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/panelComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/panelComponent.html new file mode 100644 index 000000000..4e22a3e52 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/panelComponent.html @@ -0,0 +1,68 @@ +
+

+ +

+

+ + Draw a line on the map to display the corresponding LIDAR profile. Use double-click to finish the drawing. + +

+
+
+
+ + + +
+
+ + +
+
+
+

Material

+ +
+
+

Classes

+
+ + {{classification.name}} +
+
+
+

Initializing, please wait...

+
+
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/panelComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/panelComponent.js new file mode 100644 index 000000000..29cd28f79 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/lidarprofile/panelComponent.js @@ -0,0 +1,364 @@ +/** + * @module gmf.lidarprofile.panelComponent + */ +import gmfLidarprofileConfig from 'gmf/lidarprofile/Config.js'; +import gmfLidarprofileManager from 'gmf/lidarprofile/Manager.js'; +import gmfProfileDrawLineComponent from 'gmf/profile/drawLineComponent.js'; +import ngeoMiscBtnComponent from 'ngeo/misc/btnComponent.js'; +import ngeoDownloadCsv from 'ngeo/download/Csv.js'; +import ngeoMiscToolActivate from 'ngeo/misc/ToolActivate.js'; +import ngeoMiscToolActivateMgr from 'ngeo/misc/ToolActivateMgr.js'; + + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfLidarprofilePanel', [ + gmfLidarprofileConfig.module.name, + gmfLidarprofileManager.module.name, + gmfProfileDrawLineComponent.name, + ngeoMiscBtnComponent.name, + ngeoDownloadCsv.module.name, + ngeoMiscToolActivateMgr.module.name, +]); + + +exports.value('gmfLidarprofilePanelTemplateUrl', + /** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} Template. + */ + ($element, $attrs) => { + const templateUrl = $attrs['gmfLidarprofilePanelTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/lidarprofilePanel'; + }); + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/lidarprofilePanel', require('./panelComponent.html')); +}); + + +/** + * @param {!angular.JQLite} $element Element. + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.JQLite, !angular.Attributes): string} gmfLidarprofilePanelTemplateUrl + * Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfLidarprofilePanelTemplateUrl($element, $attrs, gmfLidarprofilePanelTemplateUrl) { + return gmfLidarprofilePanelTemplateUrl($element, $attrs); +} + + +/** + * Provide a component that display a lidar profile panel. + * You can have only one lidarprofile in your page. + * + * Example: + * + * + * + * + * You must also have a pytreeLidarprofileJsonUrl constant defined like: + * `module.constant('pytreeLidarprofileJsonUrl', 'https://sample.com/pytree/');` + * + * @ngdoc component + * @ngname gmfLidarprofilePanel + */ +exports.component_ = { + controller: 'gmfLidarprofilePanelController', + bindings: { + 'active': '=gmfLidarprofilePanelActive', + 'map': ' this.active, + (newValue, oldValue) => { + if (oldValue !== newValue) { + this.updateEventsListening_(newValue); + } + }); + + // Watch the line to update the profileData (data for the chart). + $scope.$watch( + () => this.line, + (newLine, oldLine) => { + if (oldLine !== newLine) { + this.update_(); + } + }); + } + + + /** + * @private + */ + $onInit() { + this.profile.init(this.profileConfig_, this.map); + } + + + /** + * @private + */ + initConfigAndActivateTool_() { + this.profileConfig_.initProfileConfig().then((resp) => { + this.ready = true; + this.ngeoToolActivateMgr_.activateTool(this.tool); + }); + } + + + /** + * @param {boolean} activate Activation state of the plugin + * @private + */ + updateEventsListening_(activate) { + if (activate === true) { + if (!this.ready) { + this.initConfigAndActivateTool_(); + } else { + this.ngeoToolActivateMgr_.activateTool(this.tool); + } + } else { + this.clearAll(); + this.ngeoToolActivateMgr_.deactivateTool(this.tool); + } + } + + + /** + * @private + */ + update_() { + this.profile.clearBuffer(); + if (this.line) { + this.profile.setLine(this.line); + this.profile.getProfileByLOD([], 0, true, this.profileConfig_.serverConfig.minLOD); + } else { + this.clearAll(); + } + } + + /** + * Clear the LIDAR profile tool. + * @export + */ + clearAll() { + this.line = null; + this.profile.setLine(null); + this.profile.cartoHighlight.setPosition(undefined); + this.clearMeasure(); + this.resetPlot(); + } + + + /** + * Activate the measure tool + * @export + */ + setMeasureActive() { + this.measureActive = true; + this.profile.measure.clearMeasure(); + this.profile.measure.setMeasureActive(); + } + + + /** + * Clear the current measure + * @export + */ + clearMeasure() { + this.measureActive = false; + this.profile.measure.clearMeasure(); + } + + + /** + * Reload and reset the plot for the current profile (reloads data) + * @export + */ + resetPlot() { + this.profile.clearBuffer(); + if (this.line) { + this.profile.getProfileByLOD([], 0, true, 0); + } + } + + + /** + * Get all available point attributes. + * @return {Array.|undefined} available point attributes. + * @export + */ + getAvailablePointAttributes() { + return this.profileConfig_.clientConfig.pointAttributes.availableOptions; + } + + + /** + * Get / Set the selected point attribute + * @param {lidarprofileServer.ConfigPointAttributes=} opt_selectedOption the new selected point attribute. + * @return {lidarprofileServer.ConfigPointAttributes|undefined} Selected point attribute + * @export + */ + getSetSelectedPointAttribute(opt_selectedOption) { + if (opt_selectedOption !== undefined) { + this.profileConfig_.clientConfig.pointAttributes.selectedOption = opt_selectedOption; + this.profile.plot.changeStyle(opt_selectedOption.value); + } + return this.profileConfig_.clientConfig.pointAttributes.selectedOption; + } + + + /** + * Get the available classifications for this dataset + * @export + * @return {lidarprofileServer.ConfigClassifications} classification list + */ + getClassification() { + return this.profileConfig_.serverConfig.classification_colors; + } + + + /** + * Sets the visible classification in the profile + * @export + * @param {lidarprofileServer.ConfigClassification} classification selected value + * @param {number} key of the classification code + */ + setClassification(classification, key) { + this.profileConfig_.serverConfig.classification_colors[key].visible = classification.visible; + if (this.line) { + this.profile.plot.setClassActive(this.profileConfig_.serverConfig.classification_colors, + this.profileConfig_.serverConfig.default_attribute); + } + } + + + /** + * Export the profile data to CSV file + * @export + */ + csvExport() { + if (this.line) { + const points = this.profile.utils.getFlatPointsByDistance(this.profile.profilePoints) || {}; + const csvData = this.profile.utils.getCSVData(points); + let headerColumns = Object.keys(points[0]); + headerColumns = headerColumns.map((column) => { + return {'name': column}; + }); + this.ngeoCsvDownload_.startDownload(csvData, headerColumns, 'LIDAR_profile.csv'); + } + } + + + /** + * Export the current d3 chart to PNG file + * @export + */ + pngExport() { + if (this.line) { + this.profile.utils.downloadProfileAsImageFile(this.profileConfig_.clientConfig); + } + } +}; + + +exports.controller('gmfLidarprofilePanelController', exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mainmodule.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mainmodule.js new file mode 100644 index 000000000..f6173c0c2 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mainmodule.js @@ -0,0 +1,49 @@ +/** + * @module gmf.mainmodule + */ +import gmfAuthenticationModule from 'gmf/authentication/module.js'; +import gmfBackgroundlayerselectorModule from 'gmf/backgroundlayerselector/module.js'; +import gmfContextualdataModule from 'gmf/contextualdata/module.js'; +import gmfDatasourceModule from 'gmf/datasource/module.js'; +import gmfDisclaimerModule from 'gmf/disclaimer/module.js'; +import gmfDrawingModule from 'gmf/drawing/module.js'; +import gmfEditingModule from 'gmf/editing/module.js'; +import gmfFiltersModule from 'gmf/filters/module.js'; +import gmfImportModule from 'gmf/import/module.js'; +import gmfLayertreeModule from 'gmf/layertree/module.js'; +import gmfLidarprofileModule from 'gmf/lidarprofile/module.js'; +import gmfMapModule from 'gmf/map/module.js'; +import gmfObjecteditingModule from 'gmf/objectediting/module.js'; +import gmfPermalinkModule from 'gmf/permalink/module.js'; +import gmfPrintModule from 'gmf/print/module.js'; +import gmfProfileModule from 'gmf/profile/module.js'; +import gmfRasterModule from 'gmf/raster/module.js'; +import gmfSearchModule from 'gmf/search/module.js'; +import gmfThemeModule from 'gmf/theme/module.js'; +import ngeoMainmodule from 'ngeo/mainmodule.js'; + +const exports = angular.module('gmf', [ + gmfAuthenticationModule.name, + gmfBackgroundlayerselectorModule.name, + gmfContextualdataModule.name, + gmfDatasourceModule.name, + gmfDisclaimerModule.name, + gmfDrawingModule.name, + gmfEditingModule.name, + gmfFiltersModule.name, + gmfImportModule.name, + gmfLayertreeModule.name, + gmfLidarprofileModule.name, + gmfMapModule.name, + gmfObjecteditingModule.name, + gmfPermalinkModule.name, + gmfPrintModule.name, + gmfProfileModule.name, + gmfRasterModule.name, + gmfSearchModule.name, + gmfThemeModule.name, + ngeoMainmodule.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/component.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/component.html new file mode 100644 index 000000000..d77cba00b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/component.html @@ -0,0 +1,5 @@ +
+
diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/component.js new file mode 100644 index 000000000..801b17fe8 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/component.js @@ -0,0 +1,128 @@ +/** + * @module gmf.map.component + */ +import gmfPermalinkModule from 'gmf/permalink/module.js'; +import gmfEditingSnapping from 'gmf/editing/Snapping.js'; +import ngeoMapModule from 'ngeo/map/module.js'; +import ngeoMapFeatureOverlayMgr from 'ngeo/map/FeatureOverlayMgr.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfMapComponent', [ + gmfPermalinkModule.name, + gmfEditingSnapping.module.name, + ngeoMapModule.name, + ngeoMapFeatureOverlayMgr.module.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/map', require('./component.html')); +}); + + +/** + * A "map" directive for a GeoMapFish application. + * + * Example: + * + * + * + * @htmlAttribute {ol.Map} gmf-map-map The map. + * @htmlAttribute {boolean|undefined} gmf-map-manage-resize Whether to update + * the size of the map on browser window resize. + * @htmlAttribute {boolean|undefined} gmf-map-resize-transition The duration + * (milliseconds) of the animation that may occur on the div containing + * the map. Used to smoothly resize the map while the animation is in + * progress. + * @return {angular.Directive} The Directive Definition Object. + * @ngInject + * @ngdoc directive + * @ngname gmfMap + */ +exports.directive_ = function() { + return { + scope: { + 'map': ' + + + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/mousepositionComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/mousepositionComponent.js new file mode 100644 index 000000000..a7a360125 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/map/mousepositionComponent.js @@ -0,0 +1,199 @@ +/** + * @module gmf.map.mousepositionComponent + */ +import googAsserts from 'goog/asserts.js'; +import ngeoMiscFilters from 'ngeo/misc/filters.js'; +import olControlMousePosition from 'ol/control/MousePosition.js'; +import * as olProj from 'ol/proj.js'; + +import 'bootstrap/js/dropdown.js'; + + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfMapMouseposition', [ + ngeoMiscFilters.name, +]); + + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/map/mousepositionComponent', require('./mousepositionComponent.html')); +}); + + +exports.value('gmfMapMousepositionTemplateUrl', + /** + * @param {!angular.Attributes} $attrs Attributes. + * @return {string} The template url. + */ + ($attrs) => { + const templateUrl = $attrs['gmfMapMousepositionTemplateUrl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/map/mousepositionComponent'; + }); + + +/** + * @param {!angular.Attributes} $attrs Attributes. + * @param {!function(!angular.Attributes): string} gmfMapMousepositionTemplateUrl Template function. + * @return {string} Template URL. + * @ngInject + */ +function gmfMapMousepositionTemplateUrl($attrs, gmfMapMousepositionTemplateUrl) { + return gmfMapMousepositionTemplateUrl($attrs); +} + +/** + * Provide a component to display the mouse position coordinates depending + * on the chosen projection. The component also provides a projection picker + * to choose how the coordinates are displayed. + * service. + * + * Example: + * + * + * + * @htmlAttribute {ol.Map} gmf-mouseposition-map The map. + * @htmlAttribute {Array.} + * gmf-mouseposition-projection The list of the projections. + * + * @ngdoc component + * @ngname gmfMouseposition + */ +exports.component_ = { + controller: 'gmfMousepositionController as ctrl', + bindings: { + 'map': '} + * @export + */ + this.projections; + + /** + * @type {!gmfx.MousePositionProjection} + * @export + */ + this.projection; + + /** + * @type {angular.Scope} + * @private + */ + this.$scope_ = $scope; + + /** + * @type {angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = gettextCatalog; + + /** + * @type {angular.JQLite} + * @private + */ + this.$element_ = $element; + + /** + * @type {angular.$filter} + * @private + */ + this.$filter_ = $filter; + + /** + * @type {?ol.control.MousePosition} + * @private + */ + this.control_ = null; +}; + + +/** + * Initialise the controller. + */ +exports.Controller_.prototype.$onInit = function() { + this.$scope_.$on('gettextLanguageChanged', () => { + this.initOlControl_(); + }); + + // Init control once, in case of applications that never set the language. + this.initOlControl_(); +}; + + +/** + * Init the ol.control.MousePosition + * @private + */ +exports.Controller_.prototype.initOlControl_ = function() { + if (this.control_ !== null) { + this.map.removeControl(this.control_); + } + + // function that apply the filter. + const formatFn = function(coordinates) { + const filterAndArgs = this.projection.filter.split(':'); + const filter = this.$filter_(filterAndArgs.shift()); + googAsserts.assertFunction(filter); + const args = filterAndArgs; + args.unshift(coordinates); + return filter.apply(this, args); + }; + + const gettextCatalog = this.gettextCatalog_; + this.control_ = new olControlMousePosition({ + className: 'gmf-mouseposition-control', + coordinateFormat: formatFn.bind(this), + target: angular.element('.gmf-mouseposition-control-target', this.$element_)[0], + undefinedHTML: gettextCatalog.getString('Coordinates') + }); + + this.setProjection(this.projections[0]); + + this.map.addControl(this.control_); +}; + + +/** + * @param {gmfx.MousePositionProjection} projection The new projection to use. + * @export + */ +exports.Controller_.prototype.setProjection = function(projection) { + this.control_.setProjection(olProj.get(projection.code)); + this.projection = projection; +}; + +exports.controller('gmfMousepositionController', + exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/lengthComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/lengthComponent.html new file mode 100644 index 000000000..851c8ea40 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/lengthComponent.html @@ -0,0 +1,30 @@ + + + {{'Set as starting point' | translate}} + + + + {{'Add new point' | translate}} + + + + {{'Terminate' | translate}} + + + + {{'Clear' | translate}} + + + + {{'Close' | translate}} + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/lengthComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/lengthComponent.js new file mode 100644 index 000000000..a0d60a924 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/lengthComponent.js @@ -0,0 +1,300 @@ +/** + * @module gmf.mobile.measure.lengthComponent + */ +import ngeoMiscFilters from 'ngeo/misc/filters.js'; +import ngeoInteractionMeasureLengthMobile from 'ngeo/interaction/MeasureLengthMobile.js'; +import ngeoMiscDecorate from 'ngeo/misc/decorate.js'; +import * as olEvents from 'ol/events.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleRegularShape from 'ol/style/RegularShape.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + +const exports = angular.module('gmfMobileMeasureLength', [ + ngeoMiscFilters.name, +]); + + +exports.value('gmfMobileMeasureLengthTemplateUrl', + /** + * @param {angular.JQLite} element Element. + * @param {angular.Attributes} attrs Attributes. + * @return {string} The template url. + */ + (element, attrs) => { + const templateUrl = attrs['gmfMobileMeasureLengthTemplateurl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/measure/lengthComponent'; + }); + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/measure/lengthComponent', require('./lengthComponent.html')); +}); + + +/** + * Provide a directive to do a length measure on the mobile devices. + * + * Example: + * + *
+ *
+ * + * @htmlAttribute {boolean} gmf-mobile-measurelength-active Used to active + * or deactivate the component. + * @htmlAttribute {number=} gmf-mobile-measurelength-precision the number of significant digits to display. + * @htmlAttribute {ol.Map} gmf-mobile-measurelength-map The map. + * @htmlAttribute {ol.style.Style|Array.|ol.StyleFunction=} + * gmf-mobile-measurelength-sketchstyle A style for the measure length. + * @param {string|function(!angular.JQLite=, !angular.Attributes=)} + * gmfMobileMeasureLengthTemplateUrl Template URL for the directive. + * @return {angular.Directive} The Directive Definition Object. + * @ngInject + * @ngdoc directive + * @ngname gmfMobileMeasureLength + */ +exports.component_ = + function(gmfMobileMeasureLengthTemplateUrl) { + return { + restrict: 'A', + scope: { + 'active': '=gmfMobileMeasurelengthActive', + 'precision': ' { + controller.init(); + } + }; + }; + + +exports.directive('gmfMobileMeasurelength', + exports.component_); + + +/** + * @param {!angular.Scope} $scope Angular scope. + * @param {!angular.$filter} $filter Angular filter + * @param {!angularGettext.Catalog} gettextCatalog Gettext catalog. + * @constructor + * @private + * @struct + * @ngInject + * @ngdoc controller + * @ngname GmfMobileMeasureLengthController + */ +exports.Controller_ = function($scope, $filter, gettextCatalog) { + + /** + * @type {angular.Scope} + * @private + */ + this.scope_ = $scope; + + /** + * @type {angular.$filter} + * @private + */ + this.filter_ = $filter; + + /** + * @type {!angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = gettextCatalog; + + /** + * @type {ol.Map} + * @export + */ + this.map; + + /** + * @type {boolean} + * @export + */ + this.active; + + this.scope_.$watch(() => this.active, (newVal) => { + this.measure.setActive(newVal); + }); + + /** + * @type {number|undefined} + * @export + */ + this.precision; + + /** + * @type {ol.style.Style|Array.|ol.StyleFunction} + * @export + */ + this.sketchStyle = new olStyleStyle({ + fill: new olStyleFill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new olStyleStroke({ + color: 'rgba(0, 0, 0, 0.5)', + lineDash: [10, 10], + width: 2 + }), + image: new olStyleRegularShape({ + stroke: new olStyleStroke({ + color: 'rgba(0, 0, 0, 0.7)', + width: 2 + }), + points: 4, + radius: 8, + radius2: 0, + angle: 0 + }) + }); + + /** + * @type {ngeo.interaction.MeasureLengthMobile} + * @export + */ + this.measure; + + /** + * @type {ngeo.interaction.MobileDraw} + * @export + */ + this.drawInteraction; + + /** + * @type {boolean} + * @export + */ + this.dirty = false; + + /** + * @type {boolean} + * @export + */ + this.drawing = false; + + /** + * @type {boolean} + * @export + */ + this.valid = false; +}; + +/** + * Initialise the controller. + */ +exports.Controller_.prototype.init = function() { + + this.measure = new ngeoInteractionMeasureLengthMobile(this.filter_('ngeoUnitPrefix'), this.gettextCatalog_, { + precision: this.precision, + sketchStyle: this.sketchStyle + }); + + this.measure.setActive(this.active); + ngeoMiscDecorate.interaction(this.measure); + + + this.drawInteraction = /** @type {ngeo.interaction.MobileDraw} */ ( + this.measure.getDrawInteraction()); + + const drawInteraction = this.drawInteraction; + ngeoMiscDecorate.interaction(drawInteraction); + + Object.defineProperty(this, 'hasPoints', { + get() { + return this.drawInteraction.getFeature() !== null; + } + }); + + olEvents.listen( + drawInteraction, + 'change:dirty', + function() { + this.dirty = drawInteraction.getDirty(); + + // this is where the angular scope is forced to be applied. We + // only need to do this when dirty, as going to "no being dirty" + // is made by a click on a button where Angular is within scope + if (this.dirty) { + this.scope_.$apply(); + } + }, + this + ); + + olEvents.listen( + drawInteraction, + 'change:drawing', + function() { + this.drawing = drawInteraction.getDrawing(); + }, + this + ); + + olEvents.listen( + drawInteraction, + 'change:valid', + function() { + this.valid = drawInteraction.getValid(); + }, + this + ); + + this.map.addInteraction(this.measure); +}; + +/** + * Add current sketch point to line measure + * @export + */ +exports.Controller_.prototype.addPoint = function() { + this.drawInteraction.addToDrawing(); +}; + + +/** + * Clear the sketch feature + * @export + */ +exports.Controller_.prototype.clear = function() { + this.drawInteraction.clearDrawing(); +}; + + +/** + * Finish line measure + * @export + */ +exports.Controller_.prototype.finish = function() { + this.drawInteraction.finishDrawing(); +}; + + +/** + * Deactivate the directive. + * @export + */ +exports.Controller_.prototype.deactivate = function() { + this.active = false; +}; + + +exports.controller('GmfMobileMeasureLengthController', + exports.Controller_); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/module.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/module.js new file mode 100644 index 000000000..91c602c3e --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/module.js @@ -0,0 +1,16 @@ +/** + * @module gmf.mobile.measure.module + */ +import gmfMobileMeasureLengthComponent from 'gmf/mobile/measure/lengthComponent.js'; +import gmfMobileMeasurePointComponent from 'gmf/mobile/measure/pointComponent.js'; + +/** + * @type {!angular.Module} + */ +const exports = angular.module('gmfMobileMeasureModule', [ + gmfMobileMeasureLengthComponent.name, + gmfMobileMeasurePointComponent.name, +]); + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/pointComponent.html b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/pointComponent.html new file mode 100644 index 000000000..25b7118f4 --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/pointComponent.html @@ -0,0 +1,6 @@ + + + {{'Close' | translate}} + diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/pointComponent.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/pointComponent.js new file mode 100644 index 000000000..78baca48b --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/measure/pointComponent.js @@ -0,0 +1,354 @@ +/** + * @module gmf.mobile.measure.pointComponent + */ +import gmfRasterRasterService from 'gmf/raster/RasterService.js'; +import googAsserts from 'goog/asserts.js'; +import ngeoInteractionMeasurePointMobile from 'ngeo/interaction/MeasurePointMobile.js'; +import ngeoMiscDebounce from 'ngeo/misc/debounce.js'; +import ngeoMiscDecorate from 'ngeo/misc/decorate.js'; +import * as olEvents from 'ol/events.js'; +import olStyleFill from 'ol/style/Fill.js'; +import olStyleRegularShape from 'ol/style/RegularShape.js'; +import olStyleStroke from 'ol/style/Stroke.js'; +import olStyleStyle from 'ol/style/Style.js'; + +const exports = angular.module('gmfMobileMeasurePoint', [ + gmfRasterRasterService.module.name, + ngeoMiscDebounce.name, +]); + + +exports.value('gmfMobileMeasurePointTemplateUrl', + /** + * @param {angular.JQLite} element Element. + * @param {angular.Attributes} attrs Attributes. + * @return {string} The template url. + */ + (element, attrs) => { + const templateUrl = attrs['gmfMobileMeasurePointTemplateurl']; + return templateUrl !== undefined ? templateUrl : + 'gmf/measure/pointComponent'; + }); + +exports.run(/* @ngInject */ ($templateCache) => { + $templateCache.put('gmf/measure/pointComponent', require('./pointComponent.html')); +}); + + +/** + * Provide a directive to do a point (coordinate and elevation) measure on the + * mobile devices. + * + * Example: + * + *
+ *
+ * + * Where ctrl.measurePointLayers is an object like this: + * + * this.measurePointLayers = [ + * {name: 'srtm', unit: 'm', decimals: 2}, + * {name: 'wind', {unit: 'km/h'}, + * {name: 'humidity'} + * ]; + * + * @htmlAttribute {boolean} gmf-mobile-measurepoint-active Used to active + * or deactivate the component. + * @htmlAttribute {number=} gmf-mobile-measurepoint-coordinatedecimals number + * of decimal to display for the coordinate. + * @htmlAttribute {Array.} + * gmf-mobile-measurepoint-layersconfig Raster elevation layers to get + * information under the point and its configuaration. + * @htmlAttribute {ol.Map} gmf-mobile-measurepoint-map The map. + * @htmlAttribute {ol.style.Style|Array.|ol.StyleFunction=} + * gmf-mobile-measurepoint-sketchstyle A style for the measure point. + * @param {string|function(!angular.JQLite=, !angular.Attributes=)} + * gmfMobileMeasurePointTemplateUrl Template URL for the directive. + * @return {angular.Directive} The Directive Definition Object. + * @ngInject + * @ngdoc directive + * @ngname gmfMobileMeasurePoint + */ +exports.component_ = + function(gmfMobileMeasurePointTemplateUrl) { + return { + restrict: 'A', + scope: { + 'active': '=gmfMobileMeasurepointActive', + 'getCoordinateDecimalsFn': '&?gmfMobileMeasurepointCoordinatedecimals', + 'getLayersConfigFn': '&gmfMobileMeasurepointLayersconfig', + 'map': '=gmfMobileMeasurepointMap', + 'sketchStyle': '=?gmfMobileMeasurepointSketchstyle', + 'format': ' { + controller.init(); + } + }; + }; + + +exports.directive('gmfMobileMeasurepoint', + exports.component_); + + +/** + * @param {angularGettext.Catalog} gettextCatalog Gettext catalog. + * @param {!angular.Scope} $scope Angular scope. + * @param {angular.$filter} $filter Angular filter service. + * @param {gmf.raster.RasterService} gmfRaster gmf Raster service. + * @param {ngeox.miscDebounce} ngeoDebounce ngeo Debounce factory. + * @constructor + * @private + * @ngInject + * @ngdoc controller + * @ngname GmfMobileMeasurePointController + */ +exports.Controller_ = function(gettextCatalog, $scope, $filter, + gmfRaster, ngeoDebounce) { + + /** + * @type {gmf.raster.RasterService} + * @private + */ + this.gmfRaster_ = gmfRaster; + + /** + * @type {ngeox.miscDebounce} + * @private + */ + this.ngeoDebounce_ = ngeoDebounce; + + /** + * @type {angularGettext.Catalog} + * @private + */ + this.gettextCatalog_ = gettextCatalog; + + /** + * @type {angular.$filter} + * @private + */ + this.$filter_ = $filter; + + /** + * @type {ol.Map} + * @export + */ + this.map; + + /** + * @type {boolean} + * @export + */ + this.active; + + $scope.$watch(() => this.active, (newVal) => { + this.measure.setActive(newVal); + this.handleMeasureActiveChange_(); + }); + + const coordinateDecimalsFn = this['getCoordinateDecimalsFn']; + + /** + * @type {number} + * @private + */ + this.coordinateDecimals = coordinateDecimalsFn ? coordinateDecimalsFn() : 0; + + /** + * @type {!Array.} + * @private + */ + this.layersConfig; + + /** + * @type {ol.style.Style|Array.|ol.StyleFunction} + * @export + */ + this.sketchStyle; + + if (this.sketchStyle === undefined) { + this.sketchStyle = new olStyleStyle({ + fill: new olStyleFill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new olStyleStroke({ + color: 'rgba(0, 0, 0, 0.5)', + lineDash: [10, 10], + width: 2 + }), + image: new olStyleRegularShape({ + stroke: new olStyleStroke({ + color: 'rgba(0, 0, 0, 0.7)', + width: 2 + }), + points: 4, + radius: 8, + radius2: 0, + angle: 0 + }) + }); + } + + /** + * @type {string} + */ + this.format; + + /** + * @type {ngeo.interaction.MeasurePointMobile} + * @export + */ + this.measure; + + /** + * @type {ngeo.interaction.MobileDraw} + * @export + */ + this.drawInteraction; + + /** + * The key for map view 'propertychange' event. + * @type {?ol.EventsKey} + * @private + */ + this.mapViewPropertyChangeEventKey_ = null; +}; + + +/** + * Initialise the controller. + */ +exports.Controller_.prototype.init = function() { + this.measure = new ngeoInteractionMeasurePointMobile( + /** @type {ngeox.numberCoordinates} */ (this.$filter_('ngeoNumberCoordinates')), + this.format || '{x}, {y}', + { + decimals: this.coordinateDecimals, + sketchStyle: this.sketchStyle + } + ); + this.measure.setActive(this.active); + ngeoMiscDecorate.interaction(this.measure); + this.drawInteraction = /** @type {ngeo.interaction.MobileDraw} */ (this.measure.getDrawInteraction()); + ngeoMiscDecorate.interaction(this.drawInteraction); + + const layersConfig = this['getLayersConfigFn'](); + googAsserts.assert(Array.isArray(layersConfig)); + this.layersConfig = layersConfig; + + this.map.addInteraction(this.measure); +}; + + +/** + * Deactivate the directive. + * @export + */ +exports.Controller_.prototype.deactivate = function() { + this.active = false; +}; + + +/** + * @param {string} str String to translate. + * @return {string} The translated text. + * @export + */ +exports.Controller_.prototype.translate = function(str) { + return this.gettextCatalog_.getString(str); +}; + + +/** + * Called when the measure becomes active or inactive. Act accordingly: + * - on activate, listen to the map property changes to call for the elevation + * service. + * - on deactivate, unlisten + * @private + */ +exports.Controller_.prototype.handleMeasureActiveChange_ = function() { + if (this.measure.getActive()) { + const view = this.map.getView(); + this.mapViewPropertyChangeEventKey_ = olEvents.listen( + view, + 'propertychange', + this.ngeoDebounce_( + this.getMeasure_.bind(this), 300, /* invokeApply */ true), + this); + this.getMeasure_(); + } else if (this.mapViewPropertyChangeEventKey_) { + olEvents.unlistenByKey(this.mapViewPropertyChangeEventKey_); + this.mapViewPropertyChangeEventKey_ = null; + } +}; + + +/** + * Call the elevation service to get information about the measure at + * the current map center location. + * @private + */ +exports.Controller_.prototype.getMeasure_ = function() { + const center = this.map.getView().getCenter(); + googAsserts.assertArray(center); + const params = { + 'layers': this.layersConfig.map(config => config.name).join(',') + }; + this.gmfRaster_.getRaster(center, params).then((object) => { + const el = this.measure.getTooltipElement(); + const ctn = document.createElement('div'); + const className = 'gmf-mobile-measure-point'; + ctn.className = className; + + for (const config of this.layersConfig) { + const key = config.name; + if (key in object) { + let value = object[key]; + const childEl = document.createElement('div'); + childEl.className = `gmf-mobile-measure-point-${key}`; + const unit = config.unit || ''; + const decimals = config.decimals && config.decimals > 0 || 0; + value = this.$filter_('number')(value, decimals); + childEl.innerHTML = [this.translate(key), ': ', value, ' ', unit].join(''); + ctn.appendChild(childEl); + } + } + + const previousCtn = el.getElementsByClassName(className); + if (previousCtn[0]) { + previousCtn[0].remove(); + } + el.appendChild(ctn); + + }); +}; + + +exports.controller('GmfMobileMeasurePointController', + exports.Controller_); + +/** + * @typedef {{ + * name: string, + * decimals: (number|undefined), + * unit: (string|undefined) + * }} + */ +exports.LayerConfig; + + +export default exports; diff --git a/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/navigation/component.js b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/navigation/component.js new file mode 100644 index 000000000..bc8831b7f --- /dev/null +++ b/geoportal/geoportailv3_geoportal/static-ngeo/ngeo/contribs/gmf/src/mobile/navigation/component.js @@ -0,0 +1,346 @@ +/** + * @module gmf.mobile.navigation.component + */ +import googAsserts from 'goog/asserts.js'; +const exports = angular.module('gmfMobileNav', []); + + +/** + * An "gmf-mobile-nav" directive defining the behavior of a tree-structured menu. + * + * The directive is to be placed on a `nav` element, with the following + * structure: + * + * + * When an element slides in the directive changes the text in the header. + * + * @return {angular.Directive} The Directive Definition Object. + * @ngInject + */ +exports.component_ = function() { + return { + restrict: 'A', + controller: 'gmfMobileNavController as navCtrl', + bindToController: true, + scope: true, + /** + * @param {angular.Scope} scope Scope. + * @param {angular.JQLite} element Element. + * @param {angular.Attributes} attrs Attributes. + * @param {gmf.mobile.navigation.component.Controller_} navCtrl Controller. + */ + link: (scope, element, attrs, navCtrl) => { + navCtrl.init(element); + } + }; +}; + +exports.directive('gmfMobileNav', exports.component_); + + +/** +* @constructor +* @private +* @ngInject +* @ngdoc controller +* @ngname gmfMobileNavController +*/ +exports.Controller_ = function() { + /** + * Stack of slid-in items. + * @private + * @type {Array.} + */ + this.slid_ = []; + + /** + * Currently active sliding box. + * @private + * @type {jQuery} + */ + this.active_ = null; + + /** + * The navigation header. + * @private + * @type {jQuery} + */ + this.header_ = null; + + /** + * The back button in the navigation header. + * @private + * @type {jQuery} + */ + this.backButton_ = null; + + /** + * Export the back function already bound to `this`. This makes sure that + * the function is called on the right context, when it is passed to an + * attribute in a template + * @export + */ + this.back = this.back_.bind(this); +}; + +exports.controller('gmfMobileNavController', exports.Controller_); + + +/** + * Initialize the directive with the linked element. + * @param {angular.JQLite} element Element. + */ +exports.Controller_.prototype.init = function(element) { + const cls = exports.Controller_.ClassName_; + this.active_ = $(element.find(`.${cls.ACTIVE}.${cls.SLIDE}`)); + this.header_ = $(element.find('> header')); + this.backButton_ = $(element.find(`header > .${cls.GO_BACK}`)); + + // watch for clicks on "slide-in" elements + element.find('[data-toggle=slide-in]').on('click', (evt) => { + + const cls = exports.Controller_.ClassName_; + + // the element to slide out is the div.slide parent + const slideOut = $(evt.currentTarget).parents(`.${cls.SLIDE}`); + googAsserts.assert(slideOut.length === 1); + + // push the item to the selected stack + this.slid_.push(slideOut); + + // slide the "old" element out + slideOut.addClass(cls.SLIDE_OUT).removeClass(cls.ACTIVE); + + // element to slide in + const slideIn = $($(evt.currentTarget).attr('data-target')); + googAsserts.assert(slideIn.length === 1); + + // slide the "new" element in + slideIn.addClass(cls.ACTIVE); + + // update the navigation header + this.updateNavigationHeader_(slideIn, false); + + this.active_ = slideIn; + }); + + // watch for clicks on the header "go-back" link + this.backButton_.click(this.back.bind(this)); +}; + + +/** + * @param {!jQuery} active The currently active sliding box. + * @param {boolean} back Whether to move back. + * @private + */ +exports.Controller_.prototype.updateNavigationHeader_ = function( + active, back) { + const cls = exports.Controller_.ClassName_; + this.header_.toggleClass(cls.BACK, back); + + // remove any inactive nav + this.header_.find(`nav:not(.${cls.ACTIVE} +)`).remove(); + + // deactivate the currently active nav + this.header_.find(`nav.${cls.ACTIVE}`).removeClass(cls.ACTIVE) + .addClass(cls.SLIDE_OUT); + + // show the back button when relevant + this.backButton_.toggleClass(cls.ACTIVE, this.slid_.length > 0); + + // create a new nav + const nav = $('