diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dc1e754 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +background-standalone.html diff --git a/LICENSE b/LICENSE index 7b68daf..82883b0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2026 zink +Copyright (c) 2026 Richard Zink Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index fd992eb..addb92e 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,46 @@ # Animated Background -An animated desktop background that runs in a browser. Features: +A browser-based animated desktop background: a WebGL flight scene over +real terrain, driven by the real sun, moon, stars, and live weather. -- Time-of-day simulation with realistic color gradients driven by the - actual sun position (computed from latitude/longitude via SunCalc). -- WebGL flight scene (`vendor/clouds3d.js`): raymarched cloud deck, 3D - terrain from Copernicus DEM, real star sky (Yale BSC + Milky Way), - moon with phases, animated highway car lights and settlement lights - from OpenStreetMap/Overpass at night. -- Night brightness coupled to the moon phase (new moon = minimum, full - moon = maximum), with a configurable minimum so the night is never - pitch-black. -- Live weather widget (Open-Meteo) showing current conditions and a - 4-day forecast (morning, evening, full) at every timestamp. -- Configurable units (metric °C+km/h or imperial °F+mph). -- Configurable language (with English as the base; translations for - German, Italian, Spanish, French, and Russian). -- Configurable color theme (Ash, Gruvbox, Nord) - drop a new - `*.css` file in the same directory and add an entry to `window.THEMES` - to add a new theme. -- Customisable location: set `CONFIG.location.lat/lon`, or let the - browser's geolocation API pick one up automatically (falls back to - the built-in default Passau). -- Optional custom location label (`CONFIG.location.label`) that - overrides the OpenStreetMap reverse-geocoding lookup. -- Configurable digital clock format string using ISO-8601-ish tokens - (YYYY, MM, DD, HH, mm, ss, DDD, DDDD, MMM, MMMM, a, A, sss, T, escape - sequences \n \t \\, and full weekday/month names via the i18n dict). -- Configurable debug panel (toggle collapse/expand with theme, units, - and language dropdowns that apply at runtime). +## Features -## Run with Docker +- **WebGL flight scene** (`vendor/clouds3d.js`): raymarched cloud deck, + 3D terrain mesh from real elevation data (Copernicus DEM), satellite + or street basemap, figure-eight flight path around the configured + location with a vertical bob between **15 and 35 km** flight altitude. +- **Real day/night cycle** driven by the actual sun and moon position + (SunCalc) for the configured latitude/longitude — or an accelerated + 24 h simulation (`CONFIG.day`) for wall-decoration purposes. +- **Realistic night sky**: ~8700 stars from the Yale Bright Star + Catalogue (crisp GL points, size by magnitude, colour by temperature), + rotated with the sidereal rate for the site's latitude, plus a Milky + Way band and a phase-correct moon. +- **Aircraft**: low-poly jets (CC0 model) cruising the region on curved + routes between real airfields, rolling a random destination at every + take-off - sun-lit silhouettes with contrails by day, strobing position + lights by night (all parameters in `CONFIG.flights`). +- **Night lights**: animated car lights along the real motorway/road + network and pale-yellow settlement lights (OSM place nodes; bigger + towns get more and brighter dots), optionally a NASA VIIRS night-lights + satellite overlay. All faded in from dusk, density shaped by a + rush-hour curve. +- **Live weather** (Open-Meteo): current conditions + 4-day forecast + widget; the weather code selects the scene's cloud density and colour + mood (sunny / cloudy / stormy / night). +- **Fully cached, offline-capable**: basemap tiles, elevation grid, + Overpass road/place data, star catalogue and the last weather payload + live permanently in IndexedDB. Once warm, the scene renders fully + offline; a configurable expiry (`CONFIG.tiles.expireDays`) can refresh + basemap tiles periodically. +- **Location-aware**: set `CONFIG.location.lat/lon`; everything + (flight anchor, terrain tiles, sun/moon, weather, star rotation) is + computed from it. If the location is omitted, browser geolocation is + tried, falling back to the built-in default (London). +- Units (°C/°F), six UI languages, CSS-swappable colour themes + (Ash/Gruvbox/Nord), configurable clock format, optional debug panel. + +## Run with Docker (recommended) ```sh docker compose up --build @@ -38,41 +48,131 @@ docker compose up --build Then open . -## Run locally +The bundled nginx config (`default.conf`) is more than a file server: it +provides CORS proxies for the tile sources (`/esri/`, `/carto/`, +`/terrarium/`) that the scene needs for basemap and elevation data. +A plain static server without these proxies (e.g. +`python3 -m http.server 58881`) will run the UI but terrain and map +tiles will fail to load. -The app is a single HTML page. With any static file server: +## Single-file build + +`build.py` bundles everything into one self-contained HTML file +(`background-standalone.html`) — all scripts, the star catalogue and all +theme CSS are inlined, and theme switching keeps working: ```sh -python3 -m http.server 58881 +python3 build.py # -> background-standalone.html (no sibling files needed) ``` -Open . +Runtime *data* is still fetched at load (tiles, Overpass, weather): serve +the file from the Docker image for the full experience; opened via +`file://` or a proxy-less server it renders sky, clouds and UI with an +"OFFLINE"-labelled ground grid instead of basemap tiles. ## Configuration -Edit `config.js` and reload the page: +Edit `config.js` and reload. All keys (with defaults): ```javascript window.CONFIG = { - debug: 0, // 0 = hide debug panel, 1 = show theme: 'ash', // 'ash' | 'gruvbox' | 'nord' - units: 'metric', // 'metric' | 'imperial' - language: 'de', // 'en' | 'de' | 'it' | 'es' | 'fr' | 'ru' + language: 'en', // 'en' | 'de' | 'it' | 'es' | 'fr' | 'ru' timeFormat: 'DD. MMMM, YYYY \u2012 HH:mm:SS', - location: { - lat: 48.5667, // latitude, -90 to +90, north positive - lon: 13.4319, // longitude, -180 to +180, east positive - label: '' // optional custom place name; - // if set, skips reverse-geocoding + debug: 0, // 1 = show right-side debug panel + units: { temperature: 'C' }, // 'C' | 'F' + credits: true, // data-attribution block in info box + renderScale: 1, // 0.3..1 internal 3D resolution + + location: { // drives scene anchor, sun/moon, weather + lat: 51.5074, // -90..+90, north positive + lon: -0.1278, // -180..+180, east positive + label: '' // optional name, skips reverse geocoding }, - orbit: { // omit/null = straight-line flight - radiusKm: 15, // circular flight around location; - // clamped to ~50 km at zoom 11 - clockwise: true // turn direction + + day: { + simulation: false, // true: run 24 h in cycleSeconds; + cycleSeconds: 20, // false: real sun/moon positions + fixedTime: null // 'HH:MM' freezes the sim clock at + // that time of day (cars, clouds, + // weather keep moving); null = flow + }, + weatherSim: false, // true: cycle weather themes, ignore API + weatherSimInterval: 30000, // ms per sim step + + clouds: { top: 0.9, bottom: -0.3 },// cloud deck, world units + // (1 unit = ~12.9 km at z11 / 48.6 deg N) + + orbit: { // null/omit = straight flight + radiusKm: 60, // lemniscate lobe tip (clamped ~190 km) + clockwise: true, + reorient: true, // random heading at each crossing + altBob: { // vertical bob, flight band 15-35 km + enabled: true, // false = constant 25 km + amp: 0.77, // half-band in world units + periodS: 90, // seconds per bob cycle + tilt: 0.3 // pitch reaction to climb/descent + } + }, + fog: { distanceKm: 120 }, // ground haze; 0/false = off + + terrain: { + enabled: true, // false = flat plane + exaggeration: 8, // vertical DEM scale factor + wireframe: false, // debug: orange mesh edges + nightLights: false, // NASA VIIRS city-lights overlay + carLights: true, // moving lights on real roads + cityLights: true // settlement glow dots + }, + + flights: { // see section above; all distances km + enabled: true, + altitudeKm: 14, climbKm: 100, // cruise / climb-descent run + count: 84, speedKmh: 850, speedVar: 0.18, minLegKm: 60, + holdMinS: 50, holdMaxS: 150, // ground hold at destination + wHub: 4, wField: 2, wStrip: 1, // destination roll weights + contrailChance: 0.6, // share of aircraft with a trail + contrailStartKm: 6, // formation altitude + contrailLifeS: 300, // visibility duration + contrailWidthM: 310 // full trail width + }, + + ground: { style: 'satellite' }, // 'satellite' | 'streets' + tiles: { + expireDays: null, // >0: re-fetch basemap tiles after n days + debug: false // tile borders + coords on the ground } }; ``` +## URL hash parameters + +`http://host:58881/#flight=N&fetch=S` + +- `flight=N|NE|E|SE|S|SW|W|NW` — heading of the straight flight corridor + (used when `CONFIG.orbit` is disabled) +- `fetch=N|NE|E|SE|S|SW|W|NW` — direction the tile mosaic is prefetched + ahead of the camera + +## Time format tokens + +``` +YYYY 4-digit year (2026) MM month 01-12 (10) +DD day 01-31 (07) HH hour 00-23 (14) +mm minute 00-59 (35) ss second 00-59 (22) +sss millisecond 000-999 (456) a am/pm (pm) +A AM/PM (PM) + +MMM month short name (Oct, Okt, Ott, ...) +MMMM month full name (October, Oktober, ...) +DDD weekday short name (Mon, Mo, Lu, ...) +dddd weekday full name (Monday, Montag, ...) lowercase! + +Any other character is emitted verbatim (so a literal T in ISO-8601 +needs no special token). +\n newline \t tab \\ literal backslash +``` + ## Adding a new language Edit `i18n.js` and add entries for each existing key under your new @@ -85,65 +185,43 @@ window.TRANSLATIONS['Sunrise']['xx'] = 'MyTranslation'; ## Adding a new theme Drop a new `*.css` file next to the others and add an entry to -`window.THEMES`: +`window.THEMES` in `config.js`: ```javascript window.THEMES['mytheme'] = 'mytheme.css'; ``` -## Time format tokens - -``` -YYYY 4-digit year (2026) -MM month 01-12 (10) -DD day 01-31 (07) -HH hour 00-23 (24h) (14) -mm minute 00-59 (35) lowercase! -ss second 00-59 (22) lowercase! -sss millisecond 000-999 (456) -a am/pm (lowercase) (pm) -A AM/PM (uppercase) (PM) -T literal 'T' - -MMM month short name (Oct, Okt, Ott, ...) -MMMM month full name (October, Oktober, ...) -DDD weekday short name (Mon, Mo, Lu, ...) -DDDD weekday full name (Monday, Montag, ...) - -\n newline -\t tab -\\ literal backslash -``` - ## Files ``` . -├── background.html the page (formerly index.html) +├── background.html the page (UI, weather, day/night driver) ├── config.js user-facing configuration ├── i18n.js translation strings (en/de/it/es/fr/ru) ├── ash.css default color theme ├── gruvbox.css alternative color theme ├── nord.css alternative color theme -├── vendor/ vendored third-party files (no network needed) -│ ├── clouds3d.js WebGL scene: raymarched clouds, 3D terrain, -│ │ real sun/moon/stars, car + city lights +├── vendor/ +│ ├── clouds3d.js WebGL scene renderer (clouds, terrain, sky, lights) │ ├── suncalc.js ISC (SunCalc by mourner) │ ├── stars.json Yale Bright Star Catalogue subset │ └── LICENSE per-library license attributions -├── default.conf nginx server config (port 58881, tile CORS proxies) +├── default.conf nginx config: port 58881 + tile CORS proxies +├── build.py single-file HTML bundler (see "Single-file build") ├── Dockerfile builds nginx:alpine image -└── docker-compose.yml one-service Compose file +├── docker-compose.yml one-service Compose file +└── LICENSE MIT (application code) ``` -## Licenses +## Licenses & data attribution -- **Background application code**: MIT +- **Background application code**: MIT (see `LICENSE`) - **SunCalc** (vendored): ISC - - **Open-Meteo** (weather API): CC BY 4.0 - -- **OpenStreetMap** (basemap tiles, Overpass road/place data): ODbL - - -- **Copernicus DEM** (terrain via terrarium tiles): open data +- **OpenStreetMap** (basemap tiles via ESRI/Carto, Overpass road and + place data): ODbL - +- **Copernicus DEM** (terrain via Mapzen terrarium tiles): open data - **NASA GIBS VIIRS** (optional night-lights overlay): public domain +- **Yale Bright Star Catalogue** (star positions, via `vendor/stars.json`) - **OpenStreetMap Nominatim** (reverse geocoding): ODbL - - \ No newline at end of file + diff --git a/ash.css b/ash.css index 3b33ab6..0c8ad42 100644 --- a/ash.css +++ b/ash.css @@ -1,5 +1,4 @@ -/* Ash palette by zink (this project) - * Original: https://git.familie-zink.org/zink/omarchy-ash-theme +/* Ash palette by Richard Zink (this project) * License: See repository LICENSE * * Generic color system - simple to customize for other themes. diff --git a/background.html b/background.html index 0fecd99..4ea1cec 100644 --- a/background.html +++ b/background.html @@ -12,6 +12,15 @@ var cssFile = window.THEMES && window.THEMES[theme]; var css = document.getElementById('theme-css'); if (css) css.href = cssFile || (window.THEMES && window.THEMES.ash) || 'ash.css'; + // standalone build (build.py): themes are embedded in + // window.__inlineThemeCss and the external link is disabled + if (window.__inlineThemeCss && window.__inlineThemeCss[theme]) { + if (css) css.media = 'not all'; + var s = document.createElement('style'); + s.id = 'theme-css-inline'; + s.textContent = window.__inlineThemeCss[theme]; + document.head.appendChild(s); + } })(); @@ -519,6 +528,7 @@
+ inside an inline block would end it early + return s.replace('' % tag + new = '' % body + if old not in html: + raise SystemExit('build.py: expected tag not found: ' + tag) + return html.replace(old, new, 1) + + +def parse_themes(config_src): + m = re.search(r'window\.THEMES\s*=\s*\{(.*?)\}', config_src, re.S) + if not m: + raise SystemExit('build.py: window.THEMES not found in config.js') + return dict(re.findall(r"'([^']+)'\s*:\s*'([^']+\.css)'", m.group(1))) + + +def main(): + out = sys.argv[1] if len(sys.argv) > 1 else 'background-standalone.html' + html = read('background.html') + + config_src = read('config.js') + themes = parse_themes(config_src) + + # embedded data preamble (before clouds3d's own scripts run) + stars = json.loads(read('vendor/stars.json')) + theme_css = {name: read(fname) for name, fname in themes.items()} + embed = ( + '\n' + % (json.dumps(stars, separators=(',', ':')), + json.dumps(theme_css)) + ) + anchor = '' + html = html.replace(anchor, embed + anchor, 1) + + html = inline_script(html, 'config.js', read('config.js')) + html = inline_script(html, 'i18n.js', read('i18n.js')) + html = inline_script(html, 'vendor/suncalc.js', read('vendor/suncalc.js')) + html = inline_script(html, 'vendor/plane3d.js', read('vendor/plane3d.js')) + html = inline_script(html, 'vendor/clouds3d.js', read('vendor/clouds3d.js')) + + # the default stays but is + # disabled by the inline-theme loader; keep a guarded fallback anyway + html = html.replace('\n 0) FIG8 = buildFigure8(ORBIT_R); // Anchor tile at zoom 11, computed from the user's CONFIG.location with // the same Web Mercator math as the OSM->world transforms (carLonToX/ -// carLatToZ). Fallback if unset: Passau 1100/707. +// carLatToZ). Fallback if unset: central London (tile 1023/761). var _baseLoc = (window.CONFIG && window.CONFIG.location) || {}; -var _baseLat = typeof _baseLoc.lat === 'number' ? _baseLoc.lat : 48.5667; -var _baseLon = typeof _baseLoc.lon === 'number' ? _baseLoc.lon : 13.4319; +var _baseLat = typeof _baseLoc.lat === 'number' ? _baseLoc.lat : 51.5074; +var _baseLon = typeof _baseLoc.lon === 'number' ? _baseLoc.lon : -0.1278; var _baseN = 1 << GROUND_TILE_Z; var _baseRad = _baseLat * Math.PI / 180; var GROUND_BASE_X = Math.floor((_baseLon + 180) / 360 * _baseN); @@ -1804,6 +1804,8 @@ function placeNightTile(tileX, tileY, canvasX, canvasY) { var CAR_CFG = (window.CONFIG && window.CONFIG.terrain) || {}; var CAR_ON = CAR_CFG.carLights !== false; var CITY_ON = CAR_CFG.cityLights !== false; +// re-entrancy guard for the periodic fetch cycles (15 min timer) +var carFetching = false, cityFetching = false; function carCells(idBase, tagRx, s, w, n, e, latStep, lonStep) { var out = []; @@ -1835,6 +1837,85 @@ var CAR_ENDPOINTS = [ 'https://overpass-api.de/api/interpreter', 'https://overpass.kumi.systems/api/interpreter' ]; +// spread first-attempt load across the mirrors per cell index +CAR_QUERIES.forEach(function (e, i) { e.start = i % CAR_ENDPOINTS.length; }); + +// ---- Polite global Overpass gate --------------------------------------- +// Cars, places and airports share ONE gate: at most 2 queries in flight +// and at least 900 ms between starts. Three fetchers bursting their +// grids concurrently used to trip the mirrors' rate limits, which made +// whole layers fail. One opQuery = one HTTP attempt (rotated mirror, +// 30 s client-side timeout so a hanging instance never blocks the gate). +var _opActive = 0, _opLast = 0, _opQueue = []; +function isValidOverpass(t) { + if (!t) return false; + try { + var d = JSON.parse(t); + return !!(d && Array.isArray(d.elements)); + } catch (e) { return false; } +} +function _opPump() { + var now = Date.now(); + while (_opActive < 2 && _opQueue.length && now - _opLast >= 900) { + _opActive++; _opLast = now; _opQueue.shift()(); + } + if (_opQueue.length) setTimeout(_opPump, Math.max(50, 950 - (Date.now() - _opLast))); +} +function opGate() { + return new Promise(function (go) { + _opQueue.push(function () { + go(function () { _opActive--; _opPump(); }); + }); + _opPump(); + }); +} +function opQuery(q, startIdx, attempt) { + var release; + return opGate().then(function (r) { + release = r; + var ep = CAR_ENDPOINTS[((attempt || 0) + (startIdx || 0)) % CAR_ENDPOINTS.length]; + var ctl = null, timer = null; + try { ctl = new AbortController(); timer = setTimeout(function () { ctl.abort(); }, 30000); } catch (e) {} + return fetch(ep, { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: 'data=' + encodeURIComponent(q), + signal: ctl ? ctl.signal : undefined + }).then(function (resp) { + if (timer) clearTimeout(timer); + if (resp.status !== 200) return null; + return resp.text().then(function (t) { + // only ever hand back - and cache - a valid Overpass JSON; + // a stored HTML error page once poisoned a cell forever + return isValidOverpass(t) ? t : null; + }); + }, function () { + if (timer) clearTimeout(timer); + return null; + }).then(function (txt) { + release(); + return txt; + }, function () { + // resp.text() can still reject (abort mid-body) - the gate + // slot MUST be returned or the whole queue deadlocks + release(); + return null; + }); + }); +} +// full retry ladder over all mirrors, 2.5 s pause between failed attempts +function opTry(q, startIdx) { + var MAX = CAR_ENDPOINTS.length * 2; + function go(a) { + if (a >= MAX) return Promise.resolve(null); + return opQuery(q, startIdx, a).then(function (txt) { + if (txt) return txt; + return new Promise(function (r) { setTimeout(r, 2500); }) + .then(function () { return go(a + 1); }); + }); + } + return go(0); +} var CAR_EVERY = 0.16; // world units (~2 km) between ribbon nodes var CAR_W = 0.005; // ribbon half width (world units) var CAR_Y = 0.004; // lift above terrain surface (~50 m) @@ -1900,7 +1981,9 @@ function resamplePoly(pts) { } function fetchMotorways() { - if (!CAR_ON) return; + if (!CAR_ON || carFetching) return; + carFetching = true; + var fresh = 0; // cells that were NOT already cached this cycle var groups = { motorway: [], secondary: [] }; function parseWays(txt) { var data; @@ -1918,9 +2001,6 @@ function fetchMotorways() { if (rp.length > 1) groups[key].push(rp); }); } - function carDelay(ms) { - return new Promise(function (res) { setTimeout(res, ms); }); - } // rebuild ribbons shortly after each arriving cell - the lights grow // in region by region instead of appearing after the whole chain var rebuildT = null; @@ -1935,50 +2015,34 @@ function fetchMotorways() { function loadCell(entry) { return openTileDB().then(function (db) { return tileDbGet(db, entry.id).then(function (rec) { - if (rec && rec.json) { entry._cached = true; return rec.json; } - // two rounds over all endpoints; transient 504s are routine - var MAX_ATTEMPTS = CAR_ENDPOINTS.length * 2; - function tryAttempt(a) { - if (a >= MAX_ATTEMPTS) return null; - var ep = CAR_ENDPOINTS[a % CAR_ENDPOINTS.length]; - return (a === 0 ? Promise.resolve() : carDelay(2500)) - .then(function () { - return fetch(ep, { - method: 'POST', - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - body: 'data=' + encodeURIComponent(entry.q) - }); - }).then(function (r) { - if (!r.ok) return tryAttempt(a + 1); // 504: next attempt - return r.text(); - }, function () { - return tryAttempt(a + 1); // network/CORS error - }).then(function (txt) { - if (txt && db) { - tileDbPut(db, { id: entry.id, json: txt, savedAt: Date.now() }); - } - return txt; - }); - } - return tryAttempt(0); + // validate stored JSON - a poisoned cache record (HTML error + // page saved by an older build) must trigger a refetch + if (rec && rec.json && isValidOverpass(rec.json)) { entry._cached = true; return rec.json; } + return opTry(entry.q, entry.start).then(function (txt) { + if (txt && db) tileDbPut(db, { id: entry.id, json: txt, savedAt: Date.now() }); + return txt; + }); }); }).then(function (txt) { - if (txt) { parseWays(txt); scheduleRebuild(); } + if (txt) { + parseWays(txt); + // cached cells are re-parsed but never trigger a rebuild; + // only freshly fetched data changes the ribbons + if (!entry._cached) { fresh++; scheduleRebuild(); } + } else console.warn('[clouds3d] overpass cell failed: ' + entry.id); }); } - // sequential with breathing room for FETCHED cells; cached cells - // stream through without delay. Failed cells are retried on the next - // page load (successful ones stay cached forever) - var chain = Promise.resolve(); - CAR_QUERIES.forEach(function (entry) { - chain = chain.then(function () { - return loadCell(entry).then(function () { - return carDelay(entry._cached ? 0 : 700); - }); - }); - }); - chain.then(function () { + // cached cells resolve instantly; fresh ones are paced by the global + // gate. Failed cells are retried on the next 15-min cycle + // (successful ones stay cached forever). + runPool(CAR_QUERIES, 2, function (entry) { + return loadCell(entry); + }).then(function () { + carFetching = false; + // a fully cached cycle with no prior failure means the ribbons + // are already in the state this cycle would rebuild - skip it + if (!fresh && carGeo) return; carGeo = groups; buildCarwayVBO(elevGl || (clouds3dState && clouds3dState.gl)); console.log('[clouds3d] car layer: ' + groups.motorway.length + @@ -2007,24 +2071,35 @@ var CITY_CLASS = [ ]; function fetchSettlements() { - if (!CITY_ON) return; - // same tiled pattern as the road queries (a single full-box place - // dump would be ~100k nodes); fine 0.55 x 0.65 deg cells answer in - // seconds even on busy instances - full 1 deg boxes drew 504s + if (!CITY_ON || cityFetching) return; + cityFetching = true; + var fresh = 0; + // fine 0.55 x 0.65 deg cells: every query answers in <20 s, which is + // the only reliable regime on the public mirrors (big boxes server- + // time out at any timeout: value and come back as unparseable junk). + // The shared 2-lane gate keeps the 78-cell grid polite over time. var cells = []; + var ci = 0; for (var la = 46.8; la < 50.09; la += 0.55) { for (var lo = 9.4; lo < 17.29; lo += 0.65) { + var bb = la.toFixed(2) + ',' + lo.toFixed(2) + ',' + + Math.min(50.1, la + 0.55).toFixed(2) + ',' + + Math.min(17.3, lo + 0.65).toFixed(2); + var rx = '["place"~"^(city|town|suburb|village|hamlet)$"]'; cells.push({ id: 'geo/place_' + la.toFixed(2) + '_' + lo.toFixed(2), - q: '[out:json][timeout:45];node["place"~"^(city|town|suburb|village|hamlet)$"](' + - la.toFixed(2) + ',' + lo.toFixed(2) + ',' + - Math.min(50.1, la + 0.55).toFixed(2) + ',' + - Math.min(17.3, lo + 0.65).toFixed(2) + ');out tags;' + start: ci % CAR_ENDPOINTS.length, // spread mirror load + // all three geometry types: many places (esp. German city + // districts) exist only as way/relation, not as a node + q: '[out:json][timeout:40];(node' + rx + '(' + bb + ');' + + 'way' + rx + '(' + bb + ');' + + 'relation' + rx + '(' + bb + '););out center tags;' }); + ci++; } } var list = []; - function delay(ms) { return new Promise(function (r) { setTimeout(r, ms); }); } + var seenB = {}; // bucket -> index in list: dedupe node/way/rel of one place var rebuildT = null; function scheduleRebuild() { if (rebuildT) return; @@ -2038,55 +2113,54 @@ function fetchSettlements() { var data; try { data = JSON.parse(txt); } catch (e) { return; } (data.elements || []).forEach(function (el) { - if (el.type !== 'node' || !el.tags || el.lat == null || el.lon == null) return; + if (!el.tags) return; var rank = PLACE_RANK[el.tags.place]; if (rank == null) return; - var x = carLonToX(el.lon), z = carLatToZ(el.lat); + // nodes carry lat/lon; ways/relations a computed center + var lat = el.lat != null ? el.lat : (el.center && el.center.lat); + var lon = el.lon != null ? el.lon : (el.center && el.center.lon); + if (lat == null || lon == null) return; + var x = carLonToX(lon), z = carLatToZ(lat); if (Math.abs(x) > groundTilesX() / 2 + 2 || Math.abs(z) > groundTilesY() / 2 + 2) return; - list.push({ x: x, z: z, rank: rank, pop: parseFloat(el.tags.population) || 0 }); + var popv = parseFloat(el.tags.population) || 0; + // many cities exist BOTH as a named node and as a place boundary + // relation - merge per ~3 km bucket instead of double-drawing + var key = Math.round(x * 4) + '_' + Math.round(z * 4); + var prev = seenB[key]; + if (prev !== undefined) { + var old = list[prev]; + if (rank < old.rank) old.rank = rank; + if (popv > old.pop) old.pop = popv; + return; + } + seenB[key] = list.length; + list.push({ x: x, z: z, rank: rank, pop: popv }); }); } function loadCell(entry) { return openTileDB().then(function (db) { return tileDbGet(db, entry.id).then(function (rec) { - if (rec && rec.json) { entry._cached = true; return rec.json; } - var MAX_ATTEMPTS = CAR_ENDPOINTS.length * 2; - function tryAttempt(a) { - if (a >= MAX_ATTEMPTS) return null; - var ep = CAR_ENDPOINTS[a % CAR_ENDPOINTS.length]; - return (a === 0 ? Promise.resolve() : delay(2500)) - .then(function () { - return fetch(ep, { - method: 'POST', - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - body: 'data=' + encodeURIComponent(entry.q) - }); - }).then(function (r) { - if (!r.ok) return tryAttempt(a + 1); - return r.text(); - }, function () { - return tryAttempt(a + 1); - }).then(function (txt) { - if (txt && db) tileDbPut(db, { id: entry.id, json: txt, savedAt: Date.now() }); - return txt; - }); - } - return tryAttempt(0); + // validate stored JSON - a poisoned cache record (HTML error + // page saved by an older build) must trigger a refetch + if (rec && rec.json && isValidOverpass(rec.json)) { entry._cached = true; return rec.json; } + return opTry(entry.q, entry.start).then(function (txt) { + if (txt && db) tileDbPut(db, { id: entry.id, json: txt, savedAt: Date.now() }); + return txt; + }); }); }).then(function (txt) { - if (txt) { parse(txt); scheduleRebuild(); } + if (txt) { + parse(txt); + if (!entry._cached) { fresh++; scheduleRebuild(); } + } else console.warn('[clouds3d] place cell failed: ' + entry.id); }); } - var chain = Promise.resolve(); - cells.forEach(function (entry) { - chain = chain.then(function () { - return loadCell(entry).then(function () { - return delay(entry._cached ? 0 : 700); - }); - }); - }); - chain.then(function () { + runPool(cells, 2, function (entry) { + return loadCell(entry); + }).then(function () { + cityFetching = false; + if (!fresh && cityGeo) return; // fully cached cycle - nothing changed cityGeo = list.slice(); buildCityVBO(elevGl || (clouds3dState && clouds3dState.gl)); console.log('[clouds3d] settlements: ' + list.length + ' places -> ' + cityCount + ' lights'); @@ -2112,7 +2186,10 @@ var CAR_VERT_SRC = [ 'float dir = aMeta.y >= 0.0 ? 1.0 : -1.0;', 'vec3 toCam = uCamPos - aPos;', 'vDist = length(toCam);', - 'vApproach = dot(vec3(aMeta.z, 0.0, aMeta.w) * dir, normalize(toCam));', + // NOTE the minus: the flow equation moves a pulse toward DECREASING + // arc length, i.e. actual travel = -tangent for side +1. Without + // the flip, approaching cars would show taillights (red). + 'vApproach = -dot(vec3(aMeta.z, 0.0, aMeta.w) * dir, normalize(toCam));', 'gl_Position = uProj * uView * vec4(aPos, 1.0);', '}' ].join('\n'); @@ -2139,12 +2216,20 @@ var CAR_FRAG_SRC = [ // far distance: fade the lights out smoothly toward ~150 km 'float df = 1.0 - smoothstep(7.0, 12.0, vDist);', 'if (df <= 0.0) discard;', - 'float body = smoothstep(0.0, 0.5, 1.0 - abs(vSide));', + // distance-driven cross-section: widen the bright plateau as the + // ribbon shrinks below a pixel (kills lateral shimmer). ~0.3 at + // >6.5 units (~85 km), flat near the camera. + 'float grow = clamp((vDist - 3.0) * 0.09, 0.0, 0.3);', + 'float body = 1.0 - smoothstep(0.5 + grow, 1.0, abs(vSide));', 'float dir = vSide >= 0.0 ? 1.0 : -1.0;', // cars are slotted pulses; hash1(s) jitters each slot's position // (varying spacing) and a per-slot sine wobble makes every vehicle // crawl or overtake a bit (varying speeds). No trails - points only. 'float flow = vLen / uDash + dir * uTime * uSpeed;', + // pulse width grows with distance (~1.5 px floor at the fade edge) + // so distant cars read as slightly larger, steady lights instead + // of one-pixel flicker + 'float slot = 0.11 + clamp((vDist - 2.5) * 0.05, 0.0, 0.4);', 'float n = floor(flow);', 'float inten = 0.0;', 'for (int k = -2; k <= 2; k++) {', @@ -2154,10 +2239,16 @@ var CAR_FRAG_SRC = [ 'float off = 0.05 + hash1(s) * 0.8;', 'float w = 0.25 * sin(uTime * uSpeed * (1.5 + hash1(s + 7.1) * 4.0) + hash1(s + 3.7) * 6.283);', 'float d = abs(flow - (s + off + w));', - 'inten = max(inten, max(0.0, 1.0 - d / 0.11));', + 'inten = max(inten, max(0.0, 1.0 - d / slot));', '}', '}', - 'if (inten <= 0.0) discard;', + // beyond ~55 km merge the pulses into a steady traffic glow: + // a constant reads as a line of lights, individual slots would + // pop as they cross pixel boundaries + 'float far = smoothstep(4.0, 6.5, vDist);', + 'float steady = clamp(dens * 0.55, 0.0, 0.55);', + 'inten = max(inten * (1.0 - 0.75 * far), steady * far);', + 'if (inten <= 0.001) discard;', 'inten = pow(inten, 1.8);', // approaching the camera -> white headlights, driving away -> red', 'vec3 col = mix(vec3(1.0, 0.12, 0.08), vec3(1.0, 0.96, 0.88),', @@ -2321,7 +2412,7 @@ var CITY_VERT_SRC = [ 'void main() {', 'vDist = length(uCamPos - aPos);', 'vBri = aBri;', - 'gl_PointSize = clamp(aSize * uScale * 750.0 / max(vDist, 0.1), 1.2, 18.0);', + 'gl_PointSize = clamp(aSize * uScale * 750.0 / max(vDist, 0.1), 1.6, 18.0);', 'gl_Position = uProj * uView * vec4(aPos, 1.0);', '}' ].join('\n'); @@ -2349,6 +2440,26 @@ function cityRand(seed) { return x - Math.floor(x); } +// small worker pool: run per-cell fetchers with N concurrent lanes +// (Overpass instances tolerate ~2-3 parallel queries politely) +function runPool(entries, lanes, worker) { + return new Promise(function (resolve) { + var idx = 0, active = 0; + function next() { + if (idx >= entries.length && active === 0) { resolve(); return; } + while (active < lanes && idx < entries.length) { + (function (entry) { + active++; + worker(entry).then(function () { + active--; next(); + }); + })(entries[idx++]); + } + } + next(); + }); +} + // same guard as the car rebuild: after deleting the old city VBO every // still-enabled attrib slot must point at a live buffer, or the next // full-screen draw warns "no buffer is bound to enabled attribute". @@ -2416,6 +2527,395 @@ function buildCityVBO(gl) { } } +// ---- Aircraft traffic --------------------------------------------------- +// Civil aviation between the real aerodromes of the region (OSM +// aeroway=aerodrome, one Overpass query, cached like the road/place +// data). Each aircraft rolls a RANDOM destination airport at take-off +// (hubs weighted via CONFIG.flights wHub/wField/wStrip) and flies a +// gently curved leg there - a quadratic +// Bezier resampled to arc-length, so constant speed means constant +// ground speed - with the full profile: take-off and climb, cruise +// (CONFIG.flights altitudeKm), descent, landing, a short ground hold +// (holdMinS..holdMaxS), then a fresh destination. Low phase hugs the +// terrain mesh (climb/descent start at field elevation, not at sea +// level). By night they blink (white strobes + red beacon), by day they +// cross the sky as sun-shaded low-poly silhouettes with condensation +// trails (see the contrail section for all trail parameters). Traffic +// density is deliberately UNIFORM around the clock - aviation does not +// follow the car rush-hour curve. +// Data (c) OpenStreetMap contributors, ODbL. +var FLT_CFG = (window.CONFIG && window.CONFIG.flights) || {}; +function fltNum(v, d) { return (typeof v === 'number' && isFinite(v)) ? v : d; } +var FLT_ON = FLT_CFG.enabled !== false; +var FLT_ALT_KM = fltNum(FLT_CFG.altitudeKm, 14); +var FLT_Y = FLT_ALT_KM / KM_PER_TILE; // cruise altitude +var FLT_CLIMB_U = fltNum(FLT_CFG.climbKm, 100) / KM_PER_TILE; +var FLT_MAX = Math.max(4, Math.min(240, Math.round(fltNum(FLT_CFG.count, 84)))); +var FLT_SPD = fltNum(FLT_CFG.speedKmh, 850) / 3600 / KM_PER_TILE; +var FLT_SVAR = Math.max(0, Math.min(0.5, fltNum(FLT_CFG.speedVar, 0.18))); +var FLT_MINLEG = fltNum(FLT_CFG.minLegKm, 60) / KM_PER_TILE; +var FLT_HOLD0 = fltNum(FLT_CFG.holdMinS, 50); +var FLT_HOLD1 = Math.max(FLT_HOLD0, fltNum(FLT_CFG.holdMaxS, 150)); +var FLT_W = [fltNum(FLT_CFG.wHub, 4), fltNum(FLT_CFG.wField, 2), fltNum(FLT_CFG.wStrip, 1)]; +var CT_CHANCE = Math.max(0, Math.min(1, fltNum(FLT_CFG.contrailChance, 0.6))); +var CT_START_FRAC = Math.max(0.02, fltNum(FLT_CFG.contrailStartKm, 6) / FLT_ALT_KM); +var CT_T = Math.max(10, fltNum(FLT_CFG.contrailLifeS, 300)); +var CT_HALF_W = Math.max(0.002, fltNum(FLT_CFG.contrailWidthM, 310) / 2000 / KM_PER_TILE); +var CT_MAX = FLT_MAX; +var CT_SEG = 8; // curve resolution per trail +var fltAirs = null; // [{x,z,rank}] - destination pool +var fltData = []; // live aircraft: {v,leg,s,gnd,gndEnd,seed,phase,big} +var fltBuf = null, fltVbo = null, fltCount = 0; +var fltState = []; // per frame render poses +var fltProg = null, fltAttribs = null, fltUniforms = null; +var fltFetching = false; +var _fltLast = -1; + +function fltRand(seed) { + var x = Math.sin(seed * 127.1 + 311.7) * 43758.5453; + return x - Math.floor(x); +} + +// weighted random destination at each take-off (CONFIG.flights w*) +function fltPickDest(from, seed) { + var i, tot = 0, wt = function (a) { + var w = FLT_W[a.rank]; return (w > 0 ? w : 1); + }; + for (i = 0; i < fltAirs.length; i++) if (i !== from) tot += wt(fltAirs[i]); + if (!tot) return -1; + var r = fltRand(seed) * tot; + for (i = 0; i < fltAirs.length; i++) { + if (i === from) continue; + r -= wt(fltAirs[i]); + if (r <= 0) return i; + } + return -1; +} + +// gently curved leg: quadratic Bezier A->B whose control point sits +// 3-14 % of the distance off the straight line (long-radius turns), +// resampled to ARC LENGTH so constant v means constant ground speed +function fltMakeLeg(a, b, seed) { + var A = fltAirs[a], B = fltAirs[b]; + var dx = B.x - A.x, dz = B.z - A.z; + var L = Math.hypot(dx, dz) || 0.01; + var bend = (fltRand(seed * 3.7 + 1.1) - 0.5) * 0.28 * Math.min(L, 30); + var px = -dz / L, pz = dx / L; + var cx = (A.x + B.x) / 2 + px * bend * 2, cz = (A.z + B.z) / 2 + pz * bend * 2; + var n = Math.max(12, Math.min(40, Math.round(L * 3))); + var pts = [], lx = 0, lz = 0, dsum = 0; + for (var i = 0; i <= n; i++) { + var t = i / n, it = 1 - t; + var x = it * it * A.x + 2 * it * t * cx + t * t * B.x; + var z = it * it * A.z + 2 * it * t * cz + t * t * B.z; + if (i > 0) { + var sx = x - lx, sz = z - lz, sl = Math.hypot(sx, sz) || 1; + pts[pts.length - 1].tx = sx / sl; pts[pts.length - 1].tz = sz / sl; + dsum += sl; + } + pts.push({ x: x, z: z, d: dsum, tx: 0, tz: 0 }); + lx = x; lz = z; + } + pts[pts.length - 1].tx = pts[pts.length - 2].tx; + pts[pts.length - 1].tz = pts[pts.length - 2].tz; + return { a: a, b: b, pts: pts, len: dsum }; +} + +// world pos + unit tangent at arc-length dist along a leg +function fltLegAt(leg, dist, out) { + var p = leg.pts, i = 1; + while (i < p.length - 1 && p[i].d < dist) i++; + var p0 = p[i - 1], p1 = p[i]; + var seg = (p1.d - p0.d) || 1; + var f = Math.max(0, Math.min(1, (dist - p0.d) / seg)); + out.x = p0.x + (p1.x - p0.x) * f; + out.z = p0.z + (p1.z - p0.z) * f; + out.tx = p0.tx; out.tz = p0.tz; + return out; +} + +function buildFlights(airports) { + fltAirs = airports; + fltData = []; + fltState = []; + if (!airports || airports.length < 2) { + fltCount = 0; fltBuf = new Float32Array(0); return; + } + var N = FLT_MAX; + for (var i = 0; i < airports.length * 6 && fltData.length < N; i++) { + var from = Math.floor(fltRand(i * 2.71 + 0.3) * airports.length) % airports.length; + var to = fltPickDest(from, i * 5.13 + 7.7); + if (to < 0) continue; + var leg = fltMakeLeg(from, to, i + 1); + if (leg.len < FLT_MINLEG) continue; // skip taxi hops + fltData.push({ + v: FLT_SPD * (1 - FLT_SVAR + 2 * FLT_SVAR * fltRand(i * 3.1)), + leg: leg, + s: leg.len * fltRand(i * 7.7 + 2.2), + gnd: false, + gndEnd: 0, + seed: i + 1, + phase: fltRand(i * 13.3), + big: airports[to].rank === 0 ? 1.2 : (airports[to].rank === 1 ? 1.0 : 0.75) + }); + } + fltCount = fltData.length; + fltBuf = new Float32Array(fltCount * 6); // pos3 + bri + phase + size +} + +// advance every aircraft with the frame clock; the destination is rolled +// FRESH at each take-off, so flows drift organically over the day +function stepFlights(now) { + var dt = _fltLast < 0 ? 0.016 : Math.min(0.25, now - _fltLast); + _fltLast = now; + for (var i = 0; i < fltCount; i++) { + var f = fltData[i]; + if (f.gnd) { + if (now >= f.gndEnd) { + var dest = fltPickDest(f.leg.b, now * 0.017 + f.seed * 91.7); + var nl = dest >= 0 ? fltMakeLeg(f.leg.b, dest, f.seed * 17.3 + now * 0.37) : null; + if (nl && nl.len >= FLT_MINLEG) { + f.leg = nl; f.s = 0; f.gnd = false; + f.big = fltAirs[dest].rank === 0 ? 1.2 : (fltAirs[dest].rank === 1 ? 1.0 : 0.75); + } else { + f.gndEnd = now + 30; // pick collapsed: brief wait, retry + } + } + continue; + } + f.s += f.v * dt; + if (f.s >= f.leg.len) { + f.s = f.leg.len; + f.gnd = true; + f.gndEnd = now + FLT_HOLD0 + (FLT_HOLD1 - FLT_HOLD0) * fltRand(f.seed * 5.3 + now * 0.11); + } + } +} + +// current pose: world x/z, tangent, eased altitude fraction (0..1) +var _fPos = { x: 0, z: 0, tx: 1, tz: 0 }; +function fltPose(f, out) { + var leg = f.leg, cl = Math.min(leg.len * 0.4, FLT_CLIMB_U), a; + if (f.gnd) a = 0; + else if (f.s < cl) a = f.s / cl; + else if (f.s > leg.len - cl) a = (leg.len - f.s) / cl; + else a = 1; + a = a * a * (3 - 2 * a); + fltLegAt(leg, f.s, _fPos); + out.x = _fPos.x; out.z = _fPos.z; out.tx = _fPos.tx; out.tz = _fPos.tz; + out.alt = a; out.s = f.s; out.gnd = f.gnd; out.leg = leg; + return out; +} + +function fetchAirports() { + if (!FLT_ON || fltFetching) return; + fltFetching = true; + var q = '[out:json][timeout:30];(node["aeroway"="aerodrome"](46.8,9.4,50.1,17.3);' + + 'way["aeroway"="aerodrome"](46.8,9.4,50.1,17.3););out center tags;', + id = 'geo/airports_v1'; + openTileDB().then(function (db) { + return tileDbGet(db, id).then(function (rec) { + if (rec && rec.json && isValidOverpass(rec.json)) return rec.json; + return opTry(q, 0).then(function (txt) { + if (txt && db) tileDbPut(db, { id: id, json: txt, savedAt: Date.now() }); + return txt; + }); + }); + }).then(function (txt) { + fltFetching = false; + if (!txt) { console.warn('[clouds3d] aerodrome query failed'); return; } + var data; + try { data = JSON.parse(txt); } catch (e) { return; } + var seenXY = [], airports = []; + (data.elements || []).forEach(function (el) { + var lat = el.lat != null ? el.lat : (el.center && el.center.lat); + var lon = el.lon != null ? el.lon : (el.center && el.center.lon); + if (lat == null || lon == null) return; + var t = el.tags || {}; + var rank = t.iata ? 0 : (t.icao ? 1 : (t.name ? 2 : 3)); + var x = carLonToX(lon), z = carLatToZ(lat); + // collapse runways of one field: aerodromes ~ >4 km apart merge + for (var s2 = 0; s2 < seenXY.length; s2++) { + if (Math.hypot(seenXY[s2].x - x, seenXY[s2].z - z) < 0.3) { + if (rank < seenXY[s2].rank) { seenXY[s2].rank = rank; seenXY[s2].x = (seenXY[s2].x + x) / 2; seenXY[s2].z = (seenXY[s2].z + z) / 2; } + return; + } + } + if (rank > 2) return; // nameless strips: skip + var a = { x: x, z: z, rank: rank }; + seenXY.push(a); airports.push(a); + }); + if (!airports.length) return; + buildFlights(airports); + console.log('[clouds3d] flights: ' + airports.length + ' airfields -> ' + + fltData.length + ' aircraft (destinations rolled per take-off)'); + }); +} + +var FLT_VERT_SRC = [ + 'attribute vec3 aPos;', + 'attribute vec4 aBlink;', // x: brightness, y: blink phase, z: size, w: unused + 'uniform mat4 uProj;', + 'uniform mat4 uView;', + 'uniform vec3 uCamPos;', + 'uniform float uScale;', + 'varying float vBri;', + 'varying float vPhase;', + 'varying float vDist;', + 'void main() {', + 'vDist = length(uCamPos - aPos);', + 'vBri = aBlink.x;', + 'vPhase = aBlink.y;', + 'gl_PointSize = clamp(aBlink.z * uScale * 2.6, 3.0, 6.0);', + 'gl_Position = uProj * uView * vec4(aPos, 1.0);', + '}' +].join('\n'); + +var FLT_FRAG_SRC = [ + 'precision highp float;', + 'uniform float uTime;', + 'uniform float uNight;', + 'varying float vBri;', + 'varying float vPhase;', + 'varying float vDist;', + 'void main() {', + 'float df = 1.0 - smoothstep(10.0, 16.0, vDist);', // ~130-200 km + 'if (df <= 0.0) discard;', + 'vec2 pc = gl_PointCoord - 0.5;', + 'float d = length(pc) * 2.0;', + // small bright disk with a faint halo -> reads as a light even at 3px + 'float core = max(exp(-d * d * 9.0), (1.0 - smoothstep(0.3, 0.55, d)) * 0.5);', + 'if (core <= 0.01) discard;', + // white strobe: fast double-flash every ~1.1 s + 'float t = fract(uTime * 0.9 + vPhase);', + 'float p1 = max(0.0, 1.0 - t * 8.0);', + 'float p2 = max(0.0, 1.0 - abs(t - 0.11) * 8.0);', + 'float flash = p1 * p1 + 0.7 * p2 * p2;', + // red anti-collision beacon: slower single blink + 'float red = 0.35 * pow(max(0.0, sin(uTime * 2.4 + vPhase * 6.283)), 4.0);', + 'vec3 col = vec3(1.0) * flash * 1.7 + vec3(1.0, 0.12, 0.06) * red;', + 'float a = uNight * vBri * df; // day: never drawn', + 'gl_FragColor = vec4(col * core * a, 1.0);', + '}' +].join('\n'); + +// ---- Daytime airliner model pass --------------------------------------- +// Low-poly jet (vendor/plane3d.js, CC0-derived) for the SAME traffic: by +// day the aircraft are sun-shaded silhouettes in a fixed stylized scale - +// nose-to-tail exactly half the contrail width, so jet and trail always +// read as one object at any distance. +var PLANE_VERT_SRC = [ + 'attribute vec3 aPos;', // unit-extent mesh, forward = +Z, up = +Y + 'attribute vec3 aNrm;', + 'attribute float aCol;', // 0 body, 1 glass + 'uniform mat4 uProj;', + 'uniform mat4 uView;', + 'uniform vec3 uOrigin;', // world anchor (cruise position) + 'uniform vec4 uOrit;', // cos(yaw), sin(yaw), sin(pitch), fade + 'uniform float uS;', // model radius in world units + 'varying float vCol;', + 'varying vec3 vN;', + 'void main() {', + 'float cy = uOrit.x, sy = uOrit.y, sp = uOrit.z, cp2 = sqrt(1.0 - sp * sp);', + 'vec3 p = aPos * uS;', + 'p = vec3(p.x, p.y * cp2 + p.z * sp, -p.y * sp + p.z * cp2);', // pitch + 'p = vec3(p.x * cy + p.z * sy, p.y, -p.x * sy + p.z * cy);', // yaw + 'vec3 n = aNrm;', + 'n = vec3(n.x, n.y * cp2 + n.z * sp, -n.y * sp + n.z * cp2);', + 'n = vec3(n.x * cy + n.z * sy, n.y, -n.x * sy + n.z * cy);', + 'vN = n; vCol = aCol;', + 'gl_Position = uProj * uView * vec4(uOrigin + p, 1.0);', + '}' +].join('\n'); + +var PLANE_FRAG_SRC = [ + 'precision highp float;', + 'uniform vec3 uSun;', // world sun direction (x,y,z like __currentSunDir)', + 'varying float vCol;', + 'varying vec3 vN;', + 'void main() {', + 'vec3 alb = vCol < 0.5 ? vec3(0.93, 0.93, 0.95) : vec3(0.14, 0.16, 0.21);', + 'float l = 0.22 + 0.78 * max(0.0, dot(normalize(vN), uSun));', + 'gl_FragColor = vec4(alb * l, 1.0);', + '}' +].join('\n'); + +var planeV = null, planeVbo = null, planeProg = null, planeU = null, planeA = null, planeN = 0; + +// ---- Condensation trails ------------------------------------------------- +// Aircraft above the configured formation altitude (CONFIG.flights +// contrailStartKm) may leave a contrail - contrailChance of them do (the +// ice-humidity window is not everywhere), and the stripe follows the +// curved leg: the leg polyline is walked back contrailLifeS worth of +// ground distance in 8 curve segments and swept into a ribbon +// (contrailWidthM wide). The fragment shader dissolves it into a cloud +// stripe: density patches along the length, wavy eroded edges (per-trail +// noise phase), alpha ramping up toward the head. Fades out with dayf +// (dark exhaust is invisible anyway). +var ctBuf = null, ctVbo = null, ctVerts = 0; +var ctProg = null, ctA = null, ctU = null; + +function _ctVert(x, y, z, u, v, s, p) { + var i = ctVerts * 7; + ctBuf[i] = x; ctBuf[i + 1] = y; ctBuf[i + 2] = z; + ctBuf[i + 3] = u; ctBuf[i + 4] = v; ctBuf[i + 5] = s; ctBuf[i + 6] = p; + ctVerts++; +} + +var CT_VERT_SRC = [ + 'attribute vec3 aPos;', + 'attribute float aU;', // 0 tail .. 1 head + 'attribute float aV;', // -1 .. +1 across the ribbon + 'attribute float aS;', // per-trail strength (gate x day x fade)', + 'attribute float aP;', // per-trail noise phase + 'uniform mat4 uProj;', + 'uniform mat4 uView;', + 'varying float vU;', + 'varying float vV;', + 'varying float vS;', + 'varying float vP;', + 'void main() {', + 'vU = aU; vV = aV; vS = aS; vP = aP;', + 'gl_Position = uProj * uView * vec4(aPos, 1.0);', + '}' +].join('\n'); + +var CT_FRAG_SRC = [ + 'precision mediump float;', + 'varying float vU;', + 'varying float vV;', + 'varying float vS;', + 'varying float vP;', + 'void main() {', + // density patches drifting along the stripe + 'float along = vU * 26.0 + vP * 31.0;', + 'float dens = 0.62 + 0.38 * sin(along) * sin(along * 2.7 + 1.3);', + 'if (dens < 0.0) dens = 0.0;', + // eroded, uneven edges: the stripe narrows and widens along u + 'float wob = 0.45 + 0.55 * (0.5 + 0.5 * sin(along * 3.1 + 7.0));', + 'float side = abs(vV);', + 'float edge = 1.0 - smoothstep(wob * 0.30, wob, side);', + // older tail also thins out across its width + 'edge *= 0.35 + 0.65 * pow(vU, 0.6);', + 'if (edge <= 0.0) discard;', + 'float a = vS * pow(vU, 1.25) * 0.95 * dens * edge;', + 'if (a <= 0.004) discard;', + 'gl_FragColor = vec4(0.95, 0.96, 1.0, a);', + '}' +].join('\n'); + +function decodePlaneVerts() { + if (planeV || !window.__planeVerts) return; + try { + var bin = atob(window.__planeVerts); + var buf = new ArrayBuffer(bin.length); + var u8 = new Uint8Array(buf); + for (var i = 0; i < bin.length; i++) u8[i] = bin.charCodeAt(i); + var f = new Float32Array(buf); + if (f.length % 7 === 0 && f.length > 21) { planeV = f; planeN = f.length / 7; } + } catch (e) { /* malformed data: silently stay point-only */ } +} + // ---- Real-sky: star catalogue + Milky Way ------------------------------ // Yale Bright Star Catalog (vendor/stars.json): 8.7k real stars. // The catalogue stars are rendered as GL_POINTS (crisp discs + glow, @@ -2425,7 +2925,7 @@ function buildCityVBO(gl) { var skyTexCanvas = null, skyTexture = null, skyTexGl = null; var skyPts = null; // { prog, vbo, count, a0, a1, u: {...} } var STAR_PH = 2.9; // phase so the plausible constellations sit high at night -var _skyLat = ((window.CONFIG && window.CONFIG.location && window.CONFIG.location.lat) || 48.5667) * Math.PI / 180; +var _skyLat = ((window.CONFIG && window.CONFIG.location && window.CONFIG.location.lat) || 51.5074) * Math.PI / 180; var SKY_SIN_LAT = Math.sin(_skyLat), SKY_COS_LAT = Math.cos(_skyLat); function kelvinToRGB(k) { @@ -2471,7 +2971,7 @@ var SKYPTS_FRAG = [ 'float d = length(pc) * 2.0;', 'float disc = 1.0 - smoothstep(0.45, 1.0, d);', 'float glow = 0.22 * exp(-d * 2.8);', - 'float twk = 0.85 + 0.15 * sin(uTime * 1.6 + vC.w * 33.0 + vAlt * 451.7 + vC.r * 180.3);', + 'float twk = 0.96 + 0.04 * sin(uTime * 1.6 + vC.w * 33.0 + vAlt * 451.7 + vC.r * 180.3);', 'float altf = smoothstep(-0.02, 0.12, vAlt);', // vC.w = per-star brightness (mag-based, floored so faint stars // stay clearly visible), giving an even overall look @@ -2585,6 +3085,12 @@ function buildSkyTexture(stars) { function loadSkyTexture(gl) { if (skyTexture || skyTexCanvas) return; skyTexGl = gl; + // build.py-generated standalone HTML injects the catalogue into + // window.__starsData so no fetch (and no vendor/ folder) is needed + if (window.__starsData) { + buildSkyTexture(window.__starsData); + return; + } fetch('vendor/stars.json') .then(function (r) { if (!r.ok) throw new Error('stars http ' + r.status); return r.json(); }) .then(function (stars) { buildSkyTexture(stars); }) @@ -2633,6 +3139,13 @@ function initGroundSystem(glCtx) { initNightSystem(glCtx); fetchMotorways(); fetchSettlements(); + fetchAirports(); + // periodic re-runs (same rhythm as the weather poll): cached cells + // short-circuit, so a cycle only ever costs the retries of cells + // that previously failed; running cycles never overlap (flags) + setInterval(fetchMotorways, 15 * 60 * 1000); + setInterval(fetchSettlements, 15 * 60 * 1000); + setInterval(fetchAirports, 15 * 60 * 1000); loadSkyTexture(glCtx); } @@ -3092,6 +3605,243 @@ window.clouds3dRender = function(target) { gl.depthMask(true); } + // ---- Aircraft pass -------------------------------------------------- + // Shared position update (take-off/climb/cruise/descent/land/hold + // profile), then: night = strobe point sprites, day = sun-shaded + // low-poly silhouettes sized to half the contrail width, plus the + // trails themselves. + // Density is uniform over the whole day (flights follow neither the + // car rush curve nor a night cut-off). + if (FLT_ON && fltCount && fltAirs) { + stepFlights(now); + var fl = { x: 0, z: 0, alt: 0, s: 0, tx: 1, tz: 0, gnd: false, leg: null }; + for (var fi = 0; fi < fltCount; fi++) { + var f = fltData[fi]; + fltPose(f, fl); + var gy = carYAt(fl.x, fl.z); + var yF = gy + (FLT_Y - gy) * fl.alt; + var k = fi * 6; + fltBuf[k] = fl.x; fltBuf[k + 1] = yF; fltBuf[k + 2] = fl.z; + fltBuf[k + 3] = f.big; + fltBuf[k + 4] = f.phase; + fltBuf[k + 5] = 1.0; + var st = fltState[fi] || (fltState[fi] = {}); + st.y = yF; st.alt = fl.alt; st.s = fl.s; st.gnd = fl.gnd; st.leg = fl.leg; + st.tx = fl.tx; st.tz = fl.tz; + } + // -- night: blinking lights -- + if (carNight > 0.06) { + if (!fltVbo) fltVbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, fltVbo); + gl.bufferData(gl.ARRAY_BUFFER, fltBuf, gl.STREAM_DRAW); + if (!fltProg) { + var fp = makeProgram(gl, FLT_VERT_SRC, FLT_FRAG_SRC); + if (!fp) { FLT_ON = false; } + else { + fltProg = fp; + fltAttribs = { + pos: gl.getAttribLocation(fltProg, 'aPos'), + blink: gl.getAttribLocation(fltProg, 'aBlink') + }; + fltUniforms = { + proj: gl.getUniformLocation(fltProg, 'uProj'), + view: gl.getUniformLocation(fltProg, 'uView'), + camPos: gl.getUniformLocation(fltProg, 'uCamPos'), + scale: gl.getUniformLocation(fltProg, 'uScale'), + time: gl.getUniformLocation(fltProg, 'uTime'), + night: gl.getUniformLocation(fltProg, 'uNight') + }; + } + } + if (fltProg) { + gl.useProgram(fltProg); + gl.uniformMatrix4fv(fltUniforms.proj, false, proj); + gl.uniformMatrix4fv(fltUniforms.view, false, view); + gl.uniform3f(fltUniforms.camPos, camX, camY, camZ); + gl.uniform1f(fltUniforms.scale, gl.drawingBufferHeight / 600); + gl.uniform1f(fltUniforms.time, now); + gl.uniform1f(fltUniforms.night, Math.min(1, carNight * 1.2)); + gl.enable(gl.DEPTH_TEST); // mountains can pass in front + gl.depthMask(false); + gl.enable(gl.BLEND); + gl.blendFunc(gl.ONE, gl.ONE); + gl.enableVertexAttribArray(fltAttribs.pos); + gl.vertexAttribPointer(fltAttribs.pos, 3, gl.FLOAT, false, 24, 0); + gl.enableVertexAttribArray(fltAttribs.blink); + gl.vertexAttribPointer(fltAttribs.blink, 3, gl.FLOAT, false, 24, 12); + gl.drawArrays(gl.POINTS, 0, fltCount); + gl.disable(gl.BLEND); + gl.depthMask(true); + } + } + // -- day: silhouettes -- + decodePlaneVerts(); + var sunA = window.__currentSunAlt || 0; + var dayf = 1 - Math.min(1, Math.max(0, -sunA / 0.30)); + if (planeN && dayf > 0.02) { + if (!planeVbo) { + planeVbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, planeVbo); + gl.bufferData(gl.ARRAY_BUFFER, planeV, gl.STATIC_DRAW); + } + if (!planeProg) { + var pp = makeProgram(gl, PLANE_VERT_SRC, PLANE_FRAG_SRC); + if (pp) { + planeProg = pp; + planeA = { + pos: gl.getAttribLocation(pp, 'aPos'), + nrm: gl.getAttribLocation(pp, 'aNrm'), + col: gl.getAttribLocation(pp, 'aCol') + }; + planeU = { + proj: gl.getUniformLocation(pp, 'uProj'), + view: gl.getUniformLocation(pp, 'uView'), + origin: gl.getUniformLocation(pp, 'uOrigin'), + orit: gl.getUniformLocation(pp, 'uOrit'), + s: gl.getUniformLocation(pp, 'uS'), + sun: gl.getUniformLocation(pp, 'uSun') + }; + } + } + if (planeProg) { + var sunv = window.__currentSunDir || [0, 1, 0]; + gl.useProgram(planeProg); + gl.uniformMatrix4fv(planeU.proj, false, proj); + gl.uniformMatrix4fv(planeU.view, false, view); + gl.uniform3f(planeU.sun, sunv[0], sunv[1], sunv[2]); + gl.bindBuffer(gl.ARRAY_BUFFER, planeVbo); + gl.enableVertexAttribArray(planeA.pos); + gl.vertexAttribPointer(planeA.pos, 3, gl.FLOAT, false, 28, 0); + gl.enableVertexAttribArray(planeA.nrm); + gl.vertexAttribPointer(planeA.nrm, 3, gl.FLOAT, false, 28, 12); + gl.enableVertexAttribArray(planeA.col); + gl.vertexAttribPointer(planeA.col, 1, gl.FLOAT, false, 28, 24); + gl.enable(gl.DEPTH_TEST); + gl.depthMask(true); // opaque little solids + gl.disable(gl.BLEND); + gl.disable(gl.CULL_FACE); + var S0 = CT_HALF_W * 0.5; // model is unit-extent: tip-to-tail + // = CT_HALF_W = half the contrail width + for (var dj = 0; dj < fltCount; dj++) { + var briJ = fltBuf[dj * 6 + 3]; + if (briJ <= 0) continue; + var px = fltBuf[dj * 6], py = fltBuf[dj * 6 + 1], pz = fltBuf[dj * 6 + 2]; + var ddx = px - camX, ddy = py - camY, ddz = pz - camZ; + var dist = Math.sqrt(ddx * ddx + ddy * ddy + ddz * ddz); + var dfa = 1 - (dist - 10) / 6; + if (dfa > 1) dfa = 1; else if (dfa <= 0.02) continue; + var stj = fltState[dj]; + var yaw = Math.atan2(stj.tx, stj.tz); + var cln = Math.min(stj.leg.len * 0.4, FLT_CLIMB_U); + var pitch = 0; + if (stj.alt > 0.02) { + if (stj.s < cln) pitch = 0.16; + else if (stj.s > stj.leg.len - cln) pitch = -0.16; + } + // fixed physical size: nose-to-tail = half the trail width + var scl = S0; + gl.uniform3f(planeU.origin, px, py, pz); + gl.uniform4f(planeU.orit, Math.cos(yaw), Math.sin(yaw), pitch, 0); + gl.uniform1f(planeU.s, scl); + gl.drawArrays(gl.TRIANGLES, 0, planeN); + } + gl.depthMask(true); + } + } + // -- contrails -- + // Only CONFIG.flights.contrailChance of the aircraft leave a + // persistent stripe (the ice-humidity window is not everywhere), + // and the stripe follows the curved leg: walked backwards from + // the aircraft in fixed steps. + if (dayf > 0.02) { + if (!ctBuf) ctBuf = new Float32Array(CT_MAX * CT_SEG * 6 * 7); + ctVerts = 0; + var _cs = { x: 0, z: 0, tx: 1, tz: 0 }; + var _sk0 = { x: 0, z: 0, px: 0, pz: 0, u: 0 }; + var _sk1 = { x: 0, z: 0, px: 0, pz: 0, u: 0 }; + for (var cj = 0; cj < fltCount; cj++) { + if (ctVerts + CT_SEG * 6 > CT_MAX * CT_SEG * 6) break; + var stc = fltState[cj]; + if (!stc || stc.gnd) continue; + if (fltRand(cj * 3.7 + 0.77) > CT_CHANCE) continue; + // formation gate: above the configured trail altitude, smooth + var gt = (stc.alt - (CT_START_FRAC - 0.06)) / 0.12; + gt = gt < 0 ? 0 : (gt > 1 ? 1 : gt); + gt = gt * gt * (3 - 2 * gt); + if (gt < 0.05) continue; + var tl = Math.min(CT_T * fltData[cj].v, stc.s); + if (tl < 0.05) continue; + fltLegAt(stc.leg, stc.s - tl * 0.5, _cs); + var cdx = _cs.x - camX, cdy = stc.y - camY, cdz = _cs.z - camZ; + var distc = Math.sqrt(cdx * cdx + cdy * cdy + cdz * cdz); + // gentle distance thinning only - trails should stay + // readable across the whole visible sky + var dfc = 1 - (distc - 12) / 12; + if (dfc > 1) dfc = 1; else if (dfc <= 0.02) continue; + var strg = gt * dayf * dfc * 0.9; + var ph = fltData[cj].phase; + var hy = stc.y; + var prev = null, cur = _sk0; + for (var sk = 0; sk <= CT_SEG; sk++) { + var dd = stc.s - tl + tl * (sk / CT_SEG); + if (dd < 0) dd = 0; + fltLegAt(stc.leg, dd, _cs); + cur.x = _cs.x; cur.z = _cs.z; + cur.px = _cs.tz * CT_HALF_W; cur.pz = -_cs.tx * CT_HALF_W; + cur.u = sk / CT_SEG; + if (prev) { + _ctVert(prev.x + prev.px, hy, prev.z + prev.pz, prev.u, 1, strg, ph); + _ctVert(prev.x - prev.px, hy, prev.z - prev.pz, prev.u, -1, strg, ph); + _ctVert(cur.x - cur.px, hy, cur.z - cur.pz, cur.u, -1, strg, ph); + _ctVert(prev.x + prev.px, hy, prev.z + prev.pz, prev.u, 1, strg, ph); + _ctVert(cur.x - cur.px, hy, cur.z - cur.pz, cur.u, -1, strg, ph); + _ctVert(cur.x + cur.px, hy, cur.z + cur.pz, cur.u, 1, strg, ph); + } + prev = cur; cur = (cur === _sk0) ? _sk1 : _sk0; + } + } + if (ctVerts > 0) { + if (!ctVbo) ctVbo = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, ctVbo); + gl.bufferData(gl.ARRAY_BUFFER, ctBuf.subarray(0, ctVerts * 7), gl.STREAM_DRAW); + if (!ctProg) { + var cpm = makeProgram(gl, CT_VERT_SRC, CT_FRAG_SRC); + if (cpm) { + ctProg = cpm; + ctA = { pos: gl.getAttribLocation(cpm, 'aPos'), + u: gl.getAttribLocation(cpm, 'aU'), + v: gl.getAttribLocation(cpm, 'aV'), + s: gl.getAttribLocation(cpm, 'aS'), + p: gl.getAttribLocation(cpm, 'aP') }; + ctU = { proj: gl.getUniformLocation(cpm, 'uProj'), + view: gl.getUniformLocation(cpm, 'uView') }; + } + } + if (ctProg) { + gl.useProgram(ctProg); + gl.uniformMatrix4fv(ctU.proj, false, proj); + gl.uniformMatrix4fv(ctU.view, false, view); + gl.enableVertexAttribArray(ctA.pos); + gl.vertexAttribPointer(ctA.pos, 3, gl.FLOAT, false, 28, 0); + gl.enableVertexAttribArray(ctA.u); + gl.vertexAttribPointer(ctA.u, 1, gl.FLOAT, false, 28, 12); + gl.enableVertexAttribArray(ctA.v); + gl.vertexAttribPointer(ctA.v, 1, gl.FLOAT, false, 28, 16); + gl.enableVertexAttribArray(ctA.s); + gl.vertexAttribPointer(ctA.s, 1, gl.FLOAT, false, 28, 20); + gl.enableVertexAttribArray(ctA.p); + gl.vertexAttribPointer(ctA.p, 1, gl.FLOAT, false, 28, 24); + gl.depthMask(false); + gl.enable(gl.BLEND); + gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); + gl.drawArrays(gl.TRIANGLES, 0, ctVerts); + gl.disable(gl.BLEND); + gl.depthMask(true); + } + } + } + } + // ---- Cloud pass (uMode = 1) -------------------------------------- // Alpha-blend over the framebuffer (terrain mesh + sky+stars). // Depth test/write OFF — the manual discard in the cloud shader diff --git a/vendor/plane3d.js b/vendor/plane3d.js new file mode 100644 index 0000000..590c262 --- /dev/null +++ b/vendor/plane3d.js @@ -0,0 +1,4 @@ +/* Airliner low-poly mesh (599 tris). Derived from 'Passenger Airplane' by Grab3D, + * CC0 (https://grab3d.com) - decimated and flattened for distant viewing. + * Non-indexed interleaved: pos(3) nrm(3) colIdx(1); unit extent 1.0. */ +window.__planeVerts = '5ZnVuMoFiz4gjHe/x7pTPPmSEj6fV30/AAAAADTPRruydYo+Mn93v8e6Uzz5khI+n1d9PwAAAAC0kt062MqJPuJ2d7/HulM8+ZISPp9XfT8AAAAAajBfPDociD4B2XW/vdNNPnV+Sr8K7xM/AAAAAFbdhryeA4Y+cZp0v73TTT51fkq/Cu8TPwAAAAD4dzG8MYqFPuptdb+9000+dX5KvwrvEz8AAAAAuePvuxphgj6JHXS//L+yvDbqxj750ms/AAAAAOyqJDx24II+bR10v/y/srw26sY++dJrPwAAAAAYW3I8iTSFPsOTdL/8v7K8NurGPvnSaz8AAAAAINGmvPWFgj5JHnG/T14cvsipZ70/lXw/AAAAADL8przogoI+lR5xv09eHL7IqWe9P5V8PwAAAAAqr4a8FOaAPmwCcb9PXhy+yKlnvT+VfD8AAAAAY5PVvFXvZz6UlFi/bjCnt3uOMT/Hajg/AAAAAIaT1Twx72c+c5RYv24wp7d7jjE/x2o4PwAAAAArUf482yRsPtaXWb9uMKe3e44xP8dqOD8AAAAAw4dJvUS+WT6VMkG/AAAAAAAAAIAAAAAAAAAAAMOHSb1Evlk+lTJBvwAAAAAAAACAAAAAAAAAAACMhVS9/ElAPuq6LL8AAAAAAAAAgAAAAAAAAAAAfAg2PUZeMT6hzSS/Rt4Vv1E2RD/sS4c+AAAAAO/rgz0ngVA+lg0wv0beFb9RNkQ/7EuHPgAAAAAnlIE9eV5SPssNMr9G3hW/UTZEP+xLhz4AAAAA1uqXvXOsOz50rha/IKwsvxFLO79sn8q9AAAAAAo1hr1pljU+w4UavyCsLL8RSzu/bJ/KvQAAAAAYT0O9GDIiPp7SFb8grCy/EUs7v2yfyr0AAAAAqGujvY6+MD6v1AS/ECskv2aDHj8pBei+AAAAAANoj73A1Sk+N7sKvxArJL9mgx4/KQXovgAAAAD9oI+9vr0pPle5Cr8QKyS/ZoMePykF6L4AAAAAOECxPYACOz7x1QK/b/JvPiTTqT5l8Gk/AAAAAPcRuL1jBjY+rprtvm/ybz4k06k+ZfBpPwAAAADZwJm9gCIfPrtk675v8m8+JNOpPmXwaT8AAAAAvtwtvZBh/j3wjsy+l6y6O8V+Rz0osX8/AAAAAICm67yVZPQ9/3nMvpesujvFfkc9KLF/PwAAAACElW28JFXuPb9xzL6XrLo7xX5HPSixfz8AAAAAE99uPAwM4z3eta2+uxM+O0cR7T0sR34/AAAAABT+7DwgX+k9iOqtvrsTPjtHEe09LEd+PwAAAAAg6i49EcnzPXo9rr67Ez47RxHtPSxHfj8AAAAALddvPHld3z2heZW+9tq0Ou6orTsE/38/AAAAAJxp7TwaweU9ZH6VvvbatDruqK07BP9/PwAAAAA/CS89NkLwPXGElb722rQ67qitOwT/fz8AAAAAGa9uPIJ43z0X7CY/sCZEPvsIb7/z1Zo+AAAAACWP7Dws0eU9Jw0nP7AmRD77CG+/89WaPgAAAADBUC49z0TwPejdKD+wJkQ++whvv/PVmj4AAAAArAFivQc0AD6KhD0/ljibNdOesLsM/38/AAAAAEG7Lb18o/I9KoI9P5Y4mzXTnrC7DP9/PwAAAABiuy09fKPyPSmCPT+WOJs1056wuwz/fz8AAAAAWdWkvaoRID5OhE8/AAAAAAAAAAAAAIA/AAAAAHUUlL14yhU+ToRPPwAAAAAAAAAAAACAPwAAAADcT4C9X7YMPk6ETz8AAAAAAAAAAAAAgD8AAAAAXIwXvUV1BD6L6lc/AAAAAAAAAAAAAIA/AAAAAPyOzbxQYgA+i+pXPwAAAAAAAAAAAACAPwAAAAD9q0+82M/7PYvqVz8AAAAAAAAAAAAAgD8AAAAA4Im5PMTGBz78ql8/AAAAAAAAAAAAAIA/AAAAAM/JCD0AWAs+/KpfPwAAAAAAAAAAAACAPwAAAADRBTI9ZTwQPvyqXz8AAAAAAAAAAAAAgD8AAAAAhxkzvZ8eKD5JfGw/AAAAAAAAAAAAAACAAAAAAIcZM72fHig+SXxsPwAAAAAAAAAAAAAAgAAAAAAKQQ696gUhPtiEbD8AAAAAAAAAAAAAAIAAAAAAUJWXvJ/+JD5aPHE/AAAAAAAAAAAAAACAAAAAAFCVl7yf/iQ+WjxxPwAAAAAAAAAAAAAAgAAAAABeNBq8vXYiPnM/cT8AAAAAAAAAAAAAAIAAAAAAZBKNu/LVLD4Ct3Q/AAAAAAAAAAAAAAAAAAAAAL/7mjOgliw+Ard0PwAAAAAAAAAAAAAAAAAAAAC/+5ozoJYsPgK3dD8AAAAAAAAAAAAAAAAAAAAANxOlO1zejD63NHe/kkCIPcg+Tz2tGn8/AAAAAOM95zlF+Y0+ySd3v5JAiD3IPk89rRp/PwAAAACIsW67z9qNPiYVd7+SQIg9yD5PPa0afz8AAAAAHR+GvFybiT7qbXW/AAAAAAAAAAAAAACAAAAAAB0fhrxcm4k+6m11vwAAAAAAAAAAAAAAgAAAAAAUA4K8uq6IPuptdb8AAAAAAAAAAAAAAIAAAAAA6fTYvGNPhz6PGHG/x7R2tc0Nfr/YC/y9AAAAAJ702DxiT4c+jxhxv8e0drXNDX6/2Av8vQAAAABEGCS93HmDPiujYb/HtHa1zQ1+v9gL/L0AAAAA462mvdAjQz59oBK/AAAAANiDfb/bVA6+AAAAANetpj3QI0M+faASvwAAAADYg32/21QOvgAAAACHIay9AbU+Pje7Cr8AAAAA2IN9v9tUDr4AAAAAAvy+vdSbKz516iU/AAAAAOb8f79baR+8AAAAABD8vj3Umys+deolPwAAAADm/H+/W2kfvAAAAADPe769Mj8rPn82Lz8AAAAA5vx/v1tpH7wAAAAAC4ElvXPSNj5aPHE/AAAAAAAAAAAAAAAAAAAAAAuBJb1z0jY+WjxxPwAAAAAAAAAAAAAAAAAAAAAxgSU9c9I2Plo8cT8AAAAAAAAAAAAAAAAAAAAA0B58vSPJbz5lJEO/fznoMoAke7/mh0a+AAAAAM0efD0byW8+WiRDv3856DKAJHu/5odGvgAAAABih6K98yZWPjG3Ir9/OegygCR7v+aHRr4AAAAAfn/FvewhND4aQh4/AAAAgAAAAAAAAAAAAAAAAH5/xb3sITQ+GkIePwAAAIAAAAAAAAAAAAAAAACLf8U97CE0PuBBHj8AAACAAAAAAAAAAAAAAAAAuq8xOyEoSj5nRnc/Yxt3NwPaC794bFY/AAAAAOg2ALorUEo+8Ex3P2MbdzcD2gu/eGxWPwAAAADzIX67cglKPmlBdz9jG3c3A9oLv3hsVj8AAAAAxwKCPNp/jD7qbXW/9ZEGvrXGdb2BUH2/AAAAAKB+hDzz+Ys+fmx1v/WRBr61xnW9gVB9vwAAAABlgnY8mmyNPuptdb/1kQa+tcZ1vYFQfb8AAAAAZTp6vPJmjT4Bd3W/nN1IPyzIYb5uVRQ/AAAAABQDgrzaf4w+6m11v5zdSD8syGG+blUUPwAAAADZfoS88/mLPn1sdb+c3Ug/LMhhvm5VFD8AAAAAYP2wPAHcjj5BkXK/Las0PyzUGz+qmrm+AAAAADFDmDwirZA+3Ityvy2rND8s1Bs/qpq5vgAAAAAp4aI8HPaQPjypcb8tqzQ/LNQbP6qaub4AAAAAgFMcPed/jz4M51u/FS5Hv3lbHL8FgRY+AAAAAKmJ6DyPb5E+/CFlvxUuR795Wxy/BYEWPgAAAABoueY8AmyRPip2Zb8VLke/eVscvwWBFj4AAAAAxf0kPblegz5vWWG/GrBvv1zsob4eghw+AAAAAJEfEj0FzJE+r6VZvxqwb79c7KG+HoIcPgAAAACOixE9EcqRPl/gWb8asG+/XOyhvh6CHD4AAAAAUq+IPeFCcj7sBj6/4y5tv7Wxmb4sXmg+AAAAAIxjUD2NyZE+4Uw+v+Mubb+1sZm+LF5oPgAAAAB7iyA9O8+UPp+CSL/jLm2/tbGZvixeaD4AAAAAsIA1vMbxnT55lS2/YoSQPvLSdL8WG5s9AAAAANFwvrwtgp0+yLkkv2KEkD7y0nS/FhubPQAAAABrvwe9qSGbPhlLKr9ihJA+8tJ0vxYbmz0AAAAACEOePayIZz7+Vi2/HXBrv1Uwr77qREU+AAAAABbjqT1Aimw+/S0kvx1wa79VMK++6kRFPgAAAAArqH097BSRPlsQJr8dcGu/VTCvvupERT4AAAAAdcyqvQUnYT5hCyG/XX4mtYny5b6tumQ/AAAAADznor1u7FU+nXQiv11+JrWJ8uW+rbpkPwAAAAAw56I9bOxVPpx0Ir9dfia1ifLlvq26ZD8AAAAALEwhPY1anD53owW//YyDvu6+ab9NJKI+AAAAAAXGbDyiHqA+E2MFv/2Mg77uvmm/TSSiPgAAAABPzYkz1qSgPgKiB7/9jIO+7r5pv00koj4AAAAAxiSJvfwSlD4qnda+cIpiv5m17T4r0BY9AAAAAASAl715to8+VOH1vnCKYr+Zte0+K9AWPQAAAABxisu97PJqPk+3475wimK/mbXtPivQFj0AAAAAHQPKvZv/dT7ZcMq+agV0Pz6Y0b2vpZE+AAAAAI5Uz705CUw+tojNvmoFdD8+mNG9r6WRPgAAAABClMe97mk/PjxM1r5qBXQ/PpjRva+lkT4AAAAAafeJvcnHkz4tXKS+xSE1Px/iNL8+Njo8AAAAAPM4n71jd44+yOijvsUhNT8f4jS/PjY6PAAAAADpOJ+9X3eOPjvqo77FITU/H+I0vz42OjwAAAAAOYPQPa3oSD6jZSc/Atv2vgYzQL6WElu/AAAAAJafbzyUG6A+LG4tPwLb9r4GM0C+lhJbvwAAAAC9hdA94OxmPh3AJT8C2/a+BjNAvpYSW78AAAAAhA4tPX9smz6TIj0/T7NlvYqDGb4Ms3w/AAAAAEre6jytGp4+HyQ9P0+zZb2Kgxm+DLN8PwAAAABTSWw8F8CfPhIPPT9Ps2W9ioMZvgyzfD8AAAAAR8GaPamNjD40rUY/AAAAAAAAAAAAAAAAAAAAAJIYhj0P/JE+NK1GPwAAAAAAAAAAAAAAAAAAAACSGIY9D/yRPjStRj8AAAAAAAAAAAAAAAAAAAAAJ/DDPfu3UD5OhE8/AAAAAAAAAAAAAIA/AAAAAJjxwT0Fll8+ToRPPwAAAAAAAAAAAACAPwAAAABRALw9lCZuPk6ETz8AAAAAAAAAAAAAgD8AAAAAF/DDvfu3UD5OhE8/FnoJv3RHK70+sFc/AAAAAIjxwb2W6UM+ToRPPxZ6Cb90Ryu9PrBXPwAAAABGZbi9fVwzPnkSUD8Wegm/dEcrvT6wVz8AAAAAcdqJvduthz6L6lc/AAAAAAAAAAAAAIA/AAAAACFzmb0qDII+i+pXPwAAAAAAAAAAAACAPwAAAAAh7KW9G793PovqVz8AAAAAAAAAAAAAgD8AAAAAmYm5vCirkT78ql8/AAAAAAAAAAAAAIA/AAAAAKvJCL0KaY8+/KpfPwAAAAAAAAAAAACAPwAAAACtBTK9OFCMPvyqXz8AAAAAAAAAAAAAgD8AAAAAst/tPHl8iT7ClGY/AAAAAAAAAAAAAIA/AAAAADpToTxsfIs+wpRmPwAAAAAAAAAAAACAPwAAAAAP/CI80bOMPsKUZj8AAAAAAAAAAAAAgD8AAAAArRkzPUoLdD5JfGw/AAAAAAAAAAAAAAAAAAAAAPswGz2O2no+SXxsPwAAAAAAAAAAAAAAAAAAAAD7MBs9jtp6Pkl8bD8AAAAAAAAAAAAAAAAAAAAAIfYlPaP8Wz5aPHE/AAAAAAAAAAAAAAAAAAAAAGJ8GT2OlGI+WjxxPwAAAAAAAAAAAAAAAAAAAABifBk9jpRiPlo8cT8AAAAAAAAAAAAAAAAAAAAAH0fFvIZocj5aPHE/AAAAAAAAAAAAAAAAAAAAANX07rwE6G0+WjxxPwAAAAAAAAAAAAAAAAAAAADV9O68BOhtPlo8cT8AAAAAAAAAAAAAAAAAAAAAUgeOOycDaT5QsXQ/lDI8PCMu2Lza5H8/AAAAAD9C17uaL2g+ILh0P5QyPDwjLti82uR/PwAAAACls2+8DI5kPhC4dD+UMjw8Iy7YvNrkfz8AAAAAvAeoPX2/UD7S1Rq/c1KyNyHefD8xsh8+AAAAADp6rb11qUs+p8YSv3NSsjch3nw/MbIfPgAAAAC3fq09aKhLPoDGEr9zUrI3Id58PzGyHz4AAAAA8zzEvV4IMz61yDk/u7QluYv9f7+E5g28AAAAAKczxD1d+TI+oJQ6P7u0JbmL/X+/hOYNvAAAAABBocC9FZcyPneMRj+7tCW5i/1/v4TmDbwAAAAA11i3Pc2FIz5Yax8/AAAAAAAAAAAAAACAAAAAANdYtz3NhSM+WGsfPwAAAAAAAAAAAAAAgAAAAADimbc9IHEjPqhhHz8AAAAAAAAAAAAAAIAAAAAAPn6sPT/QGj6CryE/Q21QPxbkEb+osuO9AAAAAJZhrj3Voho+I6QjP0NtUD8W5BG/qLLjvQAAAACEYa49P6IaPtOkIz9DbVA/FuQRv6iy470AAAAARh6rPTNjHD7aICk/AAAAAAAAAAAAAAAAAAAAADX0rD1TPBs+fy0pPwAAAAAAAAAAAAAAAAAAAAA19Kw9UzwbPn8tKT8AAAAAAAAAAAAAAAAAAAAAuli2PX2jJT4TBSs/AAAAAAAAAAAAAAAAAAAAAMjBuD0/5iQ+XCIrPwAAAAAAAAAAAAAAAAAAAADIwbg9P+YkPlwiKz8AAAAAAAAAAAAAAAAAAAAAGyvKPcupOT5NNys/l29yv58BlT6ZJQs+AAAAANmv0j0HFUg+q+oqP5dvcr+fAZU+mSULPgAAAADN6809OuRAPnCdKj+Xb3K/nwGVPpklCz4AAAAAe8/SPagfVz6KnSo/WIyavp7P27r3DnS/AAAAACD6zz1vIFc+QLoqP1iMmr6ez9u69w50vwAAAACS7889xG9bPi66Kj9YjJq+ns/buvcOdL8AAAAAom/LPdMUbT7/uSo/NlZTvhZ9ej8u2FQyAAAAAChnyz3uE20+GRkrPzZWU74WfXo/LthUMgAAAACFKM49Ul5tPoQ3Kz82VlO+Fn16Py7YVDIAAAAAeHbCPWNOgD5t7Sk/AAAAAAAAAAAAAAAAAAAAAGCZvz2/LIA+hwAqPwAAAAAAAAAAAAAAAAAAAABgmb89vyyAPocAKj8AAAAAAAAAAAAAAAAAAAAA1h69PSLQgT6Q2iY/Y35nvy+D2r5uzEe8AAAAALTZuz0xfII+f90mP2N+Z78vg9q+bsxHvAAAAAC+2bs9uXyCPs3TJj9jfme/L4Pavm7MR7wAAAAALuTEPVVPgD6UKSA/AAAAAAAAAAAAAAAAAAAAAAjMwz3Jqn8+n2kgPwAAAAAAAAAAAAAAAAAAAAAIzMM9yap/Pp9pID8AAAAAAAAAAAAAAAAAAAAA4lnJPa+9cj7Bxh8/AAAAgAAAAAAAAAAAAAAAAOJZyT2vvXI+wcYfPwAAAIAAAAAAAAAAAAAAAABmV8k9wcRyPqtnHz8AAACAAAAAAAAAAAAAAAAASCDQPR7zXD6xZx8/LYCdPmpLWTwWkHM/AAAAADKu0D26gFY+tWcfPy2AnT5qS1k8FpBzPwAAAABU89I9hwRdPmhKHz8tgJ0+aktZPBaQcz8AAAAARVvQPX2wRj5kSh8/AAAAAAAAAIAAAAAAAAAAAEVb0D19sEY+ZEofPwAAAAAAAACAAAAAAAAAAAABZc09vF4/PkXkHz8AAAAAAAAAgAAAAAAAAAAAdXi+PfVTKj465B8/AAAAAAAAAAAAAAAAAAAAAG7ouz2c7Co+1MYfPwAAAAAAAAAAAAAAAAAAAABu6Ls9nOwqPtTGHz8AAAAAAAAAAAAAAAAAAAAAkXyvvfGjHz5zgiA/AAAAAAAAAAAAAAAAAAAAAJF8r73xox8+c4IgPwAAAAAAAAAAAAAAAAAAAACRfK+98aMfPnOCID8AAAAAAAAAAAAAAAAAAAAAMIOrvbGbHD4rQic/AAAAAAAAAAAAAAAAAAAAAJVrrr2Bsxo+yk4nPwAAAAAAAAAAAAAAAAAAAACVa669gbMaPspOJz8AAAAAAAAAAAAAAAAAAAAABnewvVaJID5KKio/AAAAAAAAAAAAAAAAAAAAAAZ3sL1WiSA+SioqPwAAAAAAAAAAAAAAAAAAAAAGd7C9VokgPkoqKj8AAAAAAAAAAAAAAAAAAAAANGfFvQGWMj5KNys/AAAAgAAAAAAAAAAAAAAAADRnxb0BljI+SjcrPwAAAIAAAAAAAAAAAAAAAACmwsK9lxUzPrMZKz8AAACAAAAAAAAAAAAAAAAAqpfQvSM9SD5ZNys/AOKevtAQMb05HHO/AAAAAPX8zr2auUw+gBkrPwDinr7QEDG9ORxzvwAAAAC5zM29ZnFIPo0ZKz8A4p6+0BAxvTkcc78AAAAAKX3PvcV9Xj4kuio/AAAAAAAAAAAAAAAAAAAAADNR0r2Gll4+lZ0qPwAAAAAAAAAAAAAAAAAAAAAzUdK9hpZePpWdKj8AAAAAAAAAAAAAAAAAAAAAv6TKvUOWdD6ynSo/AAAAAAAAAAAAAAAAAAAAAL+kyr1DlnQ+sp0qPwAAAAAAAAAAAAAAAAAAAABQ4cW92uJ7PrwXKz8AAAAAAAAAAAAAAAAAAAAAMgzBvbZPgj7rvCg/AAAAAAAAAAAAAAAAAAAAADIMwb22T4I+67woPwAAAAAAAAAAAAAAAAAAAADWeb692KWCPlzRKD8AAAAAAAAAAAAAAAAAAAAARlnAvbjfgT74NyM/AAAAgAAAAAAAAAAAAAAAAEZZwL2434E++DcjPwAAAIAAAAAAAAAAAAAAAABZ4MG9IBqCPhRuIT8AAACAAAAAAAAAAAAAAAAAzWvJvQd+ej4xqR8/AAAAAAAAAAAAAAAAAAAAAMujx70HZ3o+R10fPwAAAAAAAAAAAAAAAAAAAADLo8e9B2d6PkddHz8AAAAAAAAAAAAAAAAAAAAAm7TRvaF1ZD5pSh8/AAAAAAAAAAAAAACAAAAAAJu00b2hdWQ+aUofPwAAAAAAAAAAAAAAgAAAAADI5c69tkpkPqxnHz8AAAAAAAAAAAAAAIAAAAAAMEbSvWgYTj5lSh8/g+q+PZ/ifr9pGOu0AAAAAJB1z70kOk4+t2cfP4Pqvj2f4n6/aRjrtAAAAAACdc+9KjpOPtLGHz+D6r49n+J+v2kY67QAAAAAdAvEvex4ND6/Zx8/Cl90vz9/l77j3g+9AAAAAATrxL1gtDU+2sYfPwpfdL8/f5e+494PvQAAAABPtsa9PZk4PtnGHz8KX3S/P3+XvuPeD70AAAAA+54JPTatJD7rFR2/vTOsvnz2Zz/tY4M+AAAAAODrCD2sBCU+y3Edv70zrL589mc/7WODPgAAAAAat/A8cXEjPjFpHb+9M6y+fPZnP+1jgz4AAAAA35BNPCIkHz5b9hy/AAAAAAAAAIAAAAAAAAAAAN+QTTwiJB8+W/YcvwAAAAAAAACAAAAAAAAAAACicco7MJ4bPhWVHL8AAAAAAAAAgAAAAAAAAAAAMGLnOrqRGz4U+Ru/AAAAAAAAAAAAAAAAAAAAADBi5zq6kRs+FPkbvwAAAAAAAAAAAAAAAAAAAAAwYuc6upEbPhT5G78AAAAAAAAAAAAAAAAAAAAAHTmdPLaVHD4Erxm/qmxQP0uqCroFpRQ/AAAAAIGvljxUGxw+tWUZv6psUD9Lqgq6BaUUPwAAAADQxZY88J4aPsZmGb+qbFA/S6oKugWlFD8AAAAATADrPAIJHD7b2ha/AAAAAAAAAAAAAAAAAAAAALTK6zzYjRo+UN8WvwAAAAAAAAAAAAAAAAAAAAC0yus82I0aPlDfFr8AAAAAAAAAAAAAAAAAAAAARcY5PXc9HT47dBO/AAAAgAAAAAAAAAAAAAAAAEXGOT13PR0+O3QTvwAAAIAAAAAAAAAAAAAAAACWQDk9DGkePj+uE78AAACAAAAAAAAAAAAAAAAAgNNqPV5EJT6WkBK/AAAAgAAAAAAAAAAAAAAAAIDTaj1eRCU+lpASvwAAAIAAAAAAAAAAAAAAAAB49IE9ZKEpPtrgEr8AAACAAAAAAAAAAAAAAAAAQ66WPfS3ND403xK/+8sOPcwdiz4ONXY/AAAAAO52mT3lMzg+biETv/vLDj3MHYs+DjV2PwAAAADI7pI9Si82Pl71Er/7yw49zB2LPg41dj8AAAAA+qOtPRJYSD6O3BK/cCPDPnKtbD8sqco2AAAAAOq8qz13vEg+LCETv3Ajwz5yrWw/LKnKNgAAAAC7Q6k9+j5JPsD3Er9wI8M+cq1sPyypyjYAAAAA9uK2Pdx8Xj6zIBO/AAAAAAAAAIAAAAAAAAAAAPbitj3cfF4+syATvwAAAAAAAACAAAAAAAAAAAA6MLQ9qaFePub5Er8AAAAAAAAAgAAAAAAAAAAAQ9WyPZOzdD60+xK/AAAAAAAAAAAAAAAAAAAAAEPVsj2Ts3Q+tPsSvwAAAAAAAAAAAAAAAAAAAADLDrM9hsh0PgSdEr8AAAAAAAAAAAAAAAAAAAAAIjysPevvgD6kkxO/AAAAAAAAAAAAAAAAAAAAAMnDrj1xToE+moMTvwAAAAAAAAAAAAAAAAAAAADJw649cU6BPpqDE78AAAAAAAAAAAAAAAAAAAAAPuCqPQXbgT7y7Ri//r+Kvc4F07yhU3+/AAAAAFTppz0o14E+dOcYv/6/ir3OBdO8oVN/vwAAAADh7qY9xIqCPqXnGL/+v4q9zgXTvKFTf78AAAAAfvWoPcp6gT5xhhy/AAAAAAAAAAAAAACAAAAAAH71qD3KeoE+cYYcvwAAAAAAAAAAAAAAgAAAAAAfD649nfp7PvhAHb8AAAAAAAAAAAAAAIAAAAAALa2sPZvvbT6Ggx2/qKjKPgxmjDwgDWs/AAAAAMkArT0UFGo+bIMdv6ioyj4MZow8IA1rPwAAAAAeZ689p/5tPjSpHb+oqMo+DGaMPCANaz8AAAAAxkaqPUC1Vz69qR2/AAAAAAAAAAAAAAAAAAAAABlLpz2yOlA+k2UdvwAAAAAAAAAAAAAAAAAAAAAZS6c9sjpQPpNlHb8AAAAAAAAAAAAAAAAAAAAA1hGVPcchRD76fR2/AAAAAAAAAIAAAAAAAAAAANYRlT3HIUQ++n0dvwAAAAAAAACAAAAAAAAAAABV8I89hLU8PkdpHb8AAAAAAAAAgAAAAAAAAAAAEAd1PYTyMT6Wax2/AAAAAAAAAAAAAAAAAAAAAHl/cz16ZzI+dhQdvwAAAAAAAAAAAAAAAAAAAAB5f3M9emcyPnYUHb8AAAAAAAAAAAAAAAAAAAAA0WYnPcZBJj7xFR2/AAAAgAAAAAAAAAAAAAAAANFmJz3GQSY+8RUdvwAAAIAAAAAAAAAAAAAAAACI2yQ9v5gnPvQbHb8AAACAAAAAAAAAAAAAAAAAMpGivEVJID6r2By/AAAAAAAAAAAAAAAAAAAAAKdmpbwj2B4+zNQcvwAAAAAAAAAAAAAAAAAAAACnZqW8I9gePszUHL8AAAAAAAAAAAAAAAAAAAAAp5hAu129Gj7GChy/AAAAAAAAAAAAAAAAAAAAAKeYQLtdvRo+xgocvwAAAAAAAAAAAAAAAAAAAABGZee6upEbPhT5G78AAAAAAAAAAAAAAAAAAAAAS3VTvFstGj77pBq/ce4hPmsvcr/H0pA+AAAAAGQhSbyUqBo+DFUav3HuIT5rL3K/x9KQPgAAAADLpoK8m54aPtPWGb9x7iE+ay9yv8fSkD4AAAAAePXKvLqYHD5pdxi/AAAAAAAAAAAAAAAAAAAAAAoZ0Ly3bxs+UqIYvwAAAAAAAAAAAAAAAAAAAAAKGdC8t28bPlKiGL8AAAAAAAAAAAAAAAAAAAAAIbwhvT0lGz5wVBS/AAAAAAAAAAAAAAAAAAAAAEbtHb0ubRs+qg0UvwAAAAAAAAAAAAAAAAAAAABG7R29Lm0bPqoNFL8AAAAAAAAAAAAAAAAAAAAAAqJOvU1JIj54vRK/AAAAAAAAAAAAAAAAAAAAAKi8Tr3yqSI+cBkTvwAAAAAAAAAAAAAAAAAAAACovE698qkiPnAZE78AAAAAAAAAAAAAAAAAAAAA6cuMvR/zLj4N4BK/AAAAAAAAAAAAAAAAAAAAAOnLjL0f8y4+DeASvwAAAAAAAAAAAAAAAAAAAAAI24u9nmMvPlWKEr8AAAAAAAAAAAAAAAAAAAAAaDGnvcp1QT5w3RK/AAAAAAAAAAAAAAAAAAAAAGgxp73KdUE+cN0SvwAAAAAAAAAAAAAAAAAAAADp+aW9mcdBPh2JEr8AAAAAAAAAAAAAAAAAAAAATRu1vZ4DVz7/hxK/p+FFPqwNIz3B93o/AAAAAIZAsr1RTlc+w5oSv6fhRT6sDSM9wfd6PwAAAADEx7O9HiBbPgybEr+n4UU+rA0jPcH3ej8AAAAABb63vUiCbT4thxK/kHKcPYBAfz9irJO5AAAAAEzatL3rZW0+RpwSv5BynD2AQH8/YqyTuQAAAADClbS9MGNtPv36Er+Qcpw9gEB/P2Ksk7kAAAAA1MOuvXFOgT6agxO/AAAAAAAAAAAAAAAAAAAAANTDrr1xToE+moMTvwAAAAAAAAAAAAAAAAAAAADUw669cU6BPpqDE78AAAAAAAAAAAAAAAAAAAAAC4enveCXgj6n0Re/bQhxPzq0qL79+I89AAAAAO0TqL0oioI+8gUXv20IcT86tKi+/fiPPQAAAAB4gqi9QeSBPq3RF79tCHE/OrSovv34jz0AAAAAjPWovcp6gT5xhhy/AAAAAAAAAAAAAAAAAAAAAN+Epr0+HYE+32ocvwAAAAAAAAAAAAAAAAAAAADfhKa9Ph2BPt9qHL8AAAAAAAAAAAAAAAAAAAAAp5yrvWREdT4UJB2/AAAAAAAAAIAAAAAAAAAAAKecq71kRHU+FCQdvwAAAAAAAACAAAAAAAAAAADZfK69pm91PqQOHb8AAAAAAAAAgAAAAAAAAAAAyB6qvYm9Wz5JIx2/AAAAAAAAAAAAAAAAAAAAAOIirr03+14+oRAdvwAAAAAAAAAAAAAAAAAAAADiIq69N/tePqEQHb8AAAAAAAAAAAAAAAAAAAAANaifvX+mST4gEh2/AAAAAAAAAAAAAACAAAAAADWon71/pkk+IBIdvwAAAAAAAAAAAAAAgAAAAACBBpm9585CPgpoHb8AAAAAAAAAAAAAAIAAAAAANcKCvYqNOD6RHh2/AAAAAAAAAAAAAAAAAAAAAEbahL35gjc+4xMdvwAAAAAAAAAAAAAAAAAAAABG2oS9+YI3PuMTHb8AAAAAAAAAAAAAAAAAAAAAjGw+vbJZKz7beB2/DpYBP4MwVD+T73M+AAAAAOQhP70zCys+fRwdvw6WAT+DMFQ/k+9zPgAAAAA0Vji9JwIqPvscHb8OlgE/gzBUP5Pvcz4AAAAAE/Aju/TAJD5N0Xy8ndp+v/2Rwb0FGJK4AAAAAExPCbtTaCA+DIqBvZ3afr/9kcG9BRiSuAAAAAC21va6GyMePv7jq72d2n6//ZHBvQUYkrgAAAAAAFf4OQHuBD7pPRw+AAAAAAAAAAAAAAAAAAAAAABX+DkB7gQ+6T0cPgAAAAAAAAAAAAAAAAAAAAAAV/g5Ae4EPuk9HD4AAAAAAAAAAAAAAAAAAAAAET2rPQhUDj7rwEa+a8tevv7deb/3nYO6AAAAAED5AT5sOwQ+W5mLO2vLXr7+3Xm/952DugAAAACwbQM+Zd0DPnugOD1ry16+/t15v/edg7oAAAAAi9EqPggKFz6lFUO+AAAAAAAAAAAAAAAAAAAAAFriKj40WRY+pIPMPQAAAAAAAAAAAAAAAAAAAABa4io+NFkWPqSDzD0AAAAAAAAAAAAAAAAAAAAAIwCAPjvxHz4JxCy+cdLsOwTjf798Tey8AAAAAM/pkz7SXxs+nd+Pu3HS7DsE43+/fE3svAAAAAAr2os+UWgaPk67xzxx0uw7BON/v3xN7LwAAAAA9TGqPiSSMT4/BA6+ZqF+v2OC070/QRI7AAAAAEJrqj5nfiw+UnQxvmahfr9jgtO9P0ESOwAAAACsa6o+cXYsPgNzMb5moX6/Y4LTvT9BEjsAAAAA7xDVPoI5ND7QGUq+nGzHvWGCF7y+xX4/AAAAAOE41T6M7zA+0RlKvpxsx71hghe8vsV+PwAAAADkONU++O8wPtAZSr6cbMe9YYIXvL7Ffj8AAAAA0oMKP/YOQD7fnHu+e2jFvs2CHL39AGy/AAAAAGIwDj/2ZkE+T+iAvntoxb7Nghy9/QBsvwAAAAAikwo/hHk9PhKbe757aMW+zYIcvf0AbL8AAAAAeCQ1P3kwUD5eA6K+NY/BPrfsFj1M0Gw/AAAAAOJ8Kj8aEEw+8DiZvjWPwT637BY9TNBsPwAAAAB0iSo/vBFKPgw5mb41j8E+t+wWPUzQbD8AAAAAU3NKP4uPWD7+2rG+iLBRvwt6rr3iORE/AAAAABN9Sj+aGFc+/9qxvoiwUb8Leq694jkRPwAAAAAmHFQ/xetYPiDvlb6IsFG/C3quveI5ET8AAAAA4LdfP51qYj75fbq+344Fv1HSWL/ZodE9AAAAAC+5Xz8ebmE+TIW+vt+OBb9R0li/2aHRPQAAAAArv18/5F5hPkWHvr7fjgW/UdJYv9mh0T0AAAAAWdNgP3CnYj79Oau+dSJ0v5gRmj6MLZC5AAAAAHXSYD/nmGI+u0GyvnUidL+YEZo+jC2QuQAAAADFz2A/TnhiPrgcr751InS/mBGaPowtkLkAAAAA5TdlP2WGhD5888S+XWwZPUXX8D30Cn4/AAAAACgzZT99P4Q+uerEvl1sGT1F1/A99Ap+PwAAAACWZGU/ACCEPrnqxL5dbBk9RdfwPfQKfj8AAAAAvOxnP2+Frj736cm+1/zPvXQxoT3L4H2/AAAAAGj7Zz83aK8++NrJvtf8z710MaE9y+B9vwAAAAC1GGg/7CSvPlDmyb7X/M+9dDGhPcvgfb8AAAAAoS9oPydXsT4j1Lq+AAAAgAAAAAAAAAAAAAAAAKEvaD8nV7E+I9S6vgAAAIAAAAAAAAAAAAAAAAARHWg/6ImyPuQcvL4AAACAAAAAAAAAAAAAAAAALDVoP20BtD7e7MO+nDIpPWVKej9Z21I+AAAAAP80aD8p/LM+y9PDvpwyKT1lSno/WdtSPgAAAABwPWg/eAC0PqLrw76cMik9ZUp6P1nbUj4AAAAAQxh8OrhIFD6EOBq+vtF+v8x3xD3favS4AAAAAByTKDr93xA++Octvr7Rfr/Md8Q932r0uAAAAAAp/NQ5fVcOPhLYO76+0X6/zHfEPd9q9LgAAAAAvwH2vWyVLT6Otye9dRykvfSXfT9BDOO9AAAAAKEf572SDCk+96avvXUcpL30l30/QQzjvQAAAADSWOq9VfkjPmECBL51HKS99Jd9P0EM470AAAAA2Ob+vYy+Gj4nO+49AAAAgAAAAAAAAAAAAAAAANjm/r2Mvho+JzvuPQAAAIAAAAAAAAAAAAAAAACXaw2+GD8kPpbjyT0AAACAAAAAAAAAAAAAAAAAiM1UvmziIT4Ku6Y9k8cVv/+QTr9qWqY9AAAAAEpUYb5vUCk+Y+OFPZPHFb//kE6/alqmPQAAAABTeXu+lHEzPmIApryTxxW//5BOv2papj0AAAAA9xKVvhcVKT43GCE9AAAAgAAAAAAAAAAAAAAAAPcSlb4XFSk+NxghPQAAAIAAAAAAAAAAAAAAAAAlMZ2+KlsvPogyuDwAAACAAAAAAAAAAAAAAAAA5Zuqvs58KD7GczG+5VH3uwX+fz9RIvY6AAAAAP9exb7W0Cc+IHcLveVR97sF/n8/USL2OgAAAABYoKq+gR8oPtzggzzlUfe7Bf5/P1Ei9joAAAAAnpbwvgrLMD7NEvW9hRXjvYLFfT+kY5E9AAAAAFpz7b6c0S8+ZkLGvYUV472CxX0/pGORPQAAAAARPdW+KZgwPqxNCb2FFeO9gsV9P6RjkT0AAAAAWxosv4FYRz4N8VS+Bn56Pp6gcD8ku3O+AAAAAMHsGr/3qUM+z9wcvgZ+ej6eoHA/JLtzvgAAAABVAxW/DFRBPmvIDb4Gfno+nqBwPyS7c74AAAAA7f4vv/0NTD7GQlG+BmQHv8+r2b23jlc/AAAAAKCKKr+L3Ek+mtVDvgZkB7/Pq9m9t45XPwAAAACLIzW/Ol1QPlyjXb4GZAe/z6vZvbeOVz8AAAAAgwNUv06VXD4yP5G+AAAAgAAAAAAAAAAAAAAAAIMDVL9OlVw+Mj+RvgAAAIAAAAAAAAAAAAAAAABI9lO/8plePhNak74AAACAAAAAAAAAAAAAAAAAE8dfv4s8YD5Ah76+AAAAAAAAAAAAAAAAAAAAABPHX7+LPGA+QIe+vgAAAAAAAAAAAAAAAAAAAABsy1+/OzBgPsmHvr4AAAAAAAAAAAAAAAAAAAAAU91gv+IqYz6Kkbe+AAAAgAAAAAAAAAAAAAAAAFPdYL/iKmM+ipG3vgAAAIAAAAAAAAAAAAAAAABJ8GC/iB9kPk8ovb4AAACAAAAAAAAAAAAAAAAAbsRlv4gRhD6OZrS+mCv6vvIsXz/ZNxE9AAAAALCiZb/C6oM+HAutvpgr+r7yLF8/2TcRPQAAAAC+aWW/txyEPuO1q76YK/q+8ixfP9k3ET0AAAAA0mdov+WDsT4gnb2+lDl8v+hVGj3Y5yo+AAAAABYiaL+VjK4+Y7q5vpQ5fL/oVRo92OcqPgAAAAD+IWi/J9OvPvoCur6UOXy/6FUaPdjnKj4AAAAAdzVov/2Fsj6Aise+5TYJPo+LfD8es8C9AAAAABA+aL8kebM+rK29vuU2CT6Pi3w/HrPAvQAAAAAZKmi/FHGzPk/Jvb7lNgk+j4t8Px6zwL0AAAAAgwNUP06VXD43P5G+AAAAgAAAAAAAAAAAAAAAAIMDVD9OlVw+Nz+RvgAAAIAAAAAAAAAAAAAAAACX6VM/RW9gPqBxm74AAACAAAAAAAAAAAAAAAAAM7u1Pk69Gz60EU2+AAAAAAAAAIAAAAAAAAAAADO7tT5OvRs+tBFNvgAAAAAAAACAAAAAAAAAAADPibU+Tr0bPkkgLb4AAAAAAAAAgAAAAAAAAAAAp7i0PmsuHj58tgC+AAAAAAAAAAAAAAAAAAAAAM6VtT5rLh4+lFnlvQAAAAAAAAAAAAAAAAAAAADOlbU+ay4ePpRZ5b0AAAAAAAAAAAAAAAAAAAAAvFa1PqxvJD4D0Nq9AAAAAAAAAAAAAAAAAAAAALxWtT6sbyQ+A9DavQAAAAAAAAAAAAAAAAAAAAB8Ubg+rG8kPjNP0b0AAAAAAAAAAAAAAAAAAAAAfFG4Pu6wKj7tody9AAAAgAAAAAAAAAAAAAAAAHxRuD7usCo+7aHcvQAAAIAAAAAAAAAAAAAAAAApDbs+7rAqPpRZ5b0AAACAAAAAAAAAAAAAAAAAxOe6PgoiLT7dLg2+AAAAAAAAAAAAAAAAAAAAACYZuz4KIi0+SSAtvgAAAAAAAAAAAAAAAAAAAAAmGbs+CiItPkkgLb4AAAAAAAAAAAAAAAAAAAAAfFG4vmsuHj6X72u+AAAAAAAAAAAAAAAAAAAAACoNu75rLh4+xJNnvgAAAAAAAAAAAAAAAAAAAAAqDbu+ay4ePsSTZ74AAAAAAAAAAAAAAAAAAAAAfFG4vqxvJD70mHG+AAAAAAAAAIAAAAAAAAAAAHxRuL6sbyQ+9JhxvgAAAAAAAACAAAAAAAAAAAA8TLu+rG8kPozYbL4AAAAAAAAAgAAAAAAAAAAAKg27vu6wKj7Ek2e+AAAAAAAAAAAAAAAAAAAAAFHqu77usCo+EopZvgAAAAAAAAAAAAAAAAAAAABR6ru+7rAqPhKKWb4AAAAAAAAAAAAAAAAAAAAAxee6vgoiLT6wEU2+AAAAAAAAAAAAAAAAAAAAACgZu74KIi0+RSAtvgAAAAAAAAAAAAAAAAAAAAAoGbu+CiItPkUgLb4AAAAAAAAAAAAAAAAAAAAAJoEHP20RLT5PxFK+AAAAgAAAAAAAAAAAAAAAACaBBz9tES0+T8RSvgAAAIAAAAAAAAAAAAAAAADXmQc/bREtPru1cr4AAACAAAAAAAAAAAAAAAAA2ZMHP4mCLz47Qji+AAAAAAAAAAAAAAAAAAAAAGwCCD+Jgi8+7ktGvgAAAAAAAAAAAAAAAAAAAABsAgg/iYIvPu5LRr4AAAAAAAAAAAAAAAAAAAAA7SsIP8vDNT4xkJG+AAAAAAAAAAAAAAAAAAAAAGKzBz/LwzU+ATeZvgAAAAAAAAAAAAAAAAAAAABiswc/y8M1PgE3mb4AAAAAAAAAAAAAAAAAAAAAbAIIPwwFPD7Dj4++AAAAgAAAAAAAAAAAAAAAAGwCCD8MBTw+w4+PvgAAAIAAAAAAAAAAAAAAAADZkwc/DAU8PpyUlr4AAACAAAAAAAAAAAAAAAAAJoEHv20RLT6QU4m+AAAAAAAAAIAAAAAAAAAAACaBB79tES0+kFOJvgAAAAAAAACAAAAAAAAAAADXmQe/bREtPrS1cr4AAAAAAAAAgAAAAAAAAAAAbAIIv4mCLz7pS0a+AAAAAAAAAAAAAAAAAAAAANmTB7+Jgi8+N0I4vgAAAAAAAAAAAAAAAAAAAADZkwe/iYIvPjdCOL4AAAAAAAAAAAAAAAAAAAAAYrMHv8vDNT5t/TK+AAAAAAAAAAAAAAAAAAAAAGKzB7/LwzU+bf0yvgAAAAAAAAAAAAAAAAAAAAACNga/y8M1PgY9Lr4AAAAAAAAAAAAAAAAAAAAAAjYGvwwFPD5j5jO+AAAAgAAAAAAAAAAAAAAAAAI2Br8MBTw+Y+YzvgAAAIAAAAAAAAAAAAAAAAAr2AS/DAU8PjdCOL4AAACAAAAAAAAAAAAAAAAA3uoEvyh2Pj5IxFK+AAAAAAAAAAAAAAAAAAAAAC3SBL8odj4+tLVyvgAAAAAAAAAAAAAAAAAAAAAt0gS/KHY+PrS1cr4AAAAAAAAAAAAAAAAAAAAAp6MtPy6UPz7q772+AAAAAAAAAAAAAAAAAAAAANBFLD8ulD8+AMK7vgAAAAAAAAAAAAAAAAAAAADQRSw/LpQ/PgDCu74AAAAAAAAAAAAAAAAAAAAAp6MtP3DVRT6YxMC+AAAAAAAAAIAAAAAAAAAAAKejLT9w1UU+mMTAvgAAAAAAAACAAAAAAAAAAABIJiw/cNVFPmRkvr4AAAAAAAAAgAAAAAAAAAAA0EUsP7EWTD4Awru+AAAAAAAAAAAAAAAAAAAAAD3XKz+xFkw+Jr20vgAAAAAAAAAAAAAAAAAAAAA91ys/sRZMPia9tL4AAAAAAAAAAAAAAAAAAAAAg1gsP82HTj73gK6+AAAAAAAAAAAAAAAAAAAAANM/LD/Nh04+QYievgAAAAAAAAAAAAAAAAAAAADTPyw/zYdOPkGInr4AAAAAAAAAAAAAAAAAAAAAhFgsvxIjPT6Hj46+AAAAgAAAAAAAAAAAAAAAAIRYLL8SIz0+h4+OvgAAAIAAAAAAAAAAAAAAAADTPyy/EiM9Pj2Inr4AAACAAAAAAAAAAAAAAAAA0UUsvy6UPz5+ToG+AAAAAAAAAAAAAAAAAAAAAD7XK78ulD8+V1OIvgAAAAAAAAAAAAAAAAAAAAA+1yu/LpQ/PldTiL4AAAAAAAAAAAAAAAAAAAAAvq0rv3DVRT6Qvba+AAAAAAAAAAAAAAAAAAAAAEkmLL9w1UU+YWS+vgAAAAAAAAAAAAAAAAAAAABJJiy/cNVFPmFkvr4AAAAAAAAAAAAAAAAAAAAAP9crv7EWTD4jvbS+AAAAgAAAAAAAAAAAAAAAAD/XK7+xFkw+I720vgAAAIAAAAAAAAAAAAAAAADSRSy/sRZMPv3Bu74AAACAAAAAAAAAAAAAAAAAhqc5vfYXvz33RsC9sK30OAAAgD/K2OK2AAAAAJz7Pr2qGL89laymPbCt9DgAAIA/ytjitgAAAADaWgK98Re/PebfCD6wrfQ4AACAP8rY4rYAAAAAOCimvVtHyz0hY/+9pXQBvPT9fz/xW0c5AAAAAC34qL3RLMs9A/WsPaV0Abz0/X8/8VtHOQAAAACr5529KDvLPfESKT6ldAG89P1/P/FbRzkAAAAAcsa7vQao1j1UyuO9AAAAAAAAAAAAAAAAAAAAACXKvb0GqNY9IML7MQAAAAAAAAAAAAAAAAAAAAAlyr29BqjWPSDC+zEAAAAAAAAAAAAAAAAAAAAAcsa7PQao1j1UyuM9AAAAAAAAAAAAAAAAAAAAACXKvT0GqNY9owjlsQAAAAAAAAAAAAAAAAAAAAAlyr09BqjWPaMI5bEAAAAAAAAAAAAAAAAAAAAAzxS2vUEN5z1TD1e+AAAAAAAAgD8AAAAAAAAAAHPywL1BDec9MzEvvgAAAAAAAIA/AAAAAAAAAABBZce9QQ3nPRPj8b0AAAAAAACAPwAAAAAAAAAA4t2RPUEN5z3/OYY+AAAAAAAAAAAAAAAAAAAAAPOOpj1BDec9HJF1PgAAAAAAAAAAAAAAAAAAAADzjqY9QQ3nPRyRdT4AAAAAAAAAAAAAAAAAAAAAHjpyvTBPBj6I+ZC+AAAAAAAAgD8AAAAAAAAAALuslL0wTwY+fM+IvgAAAAAAAIA/AAAAAAAAAADFw6m9ME8GPktLer4AAAAAAACAPwAAAAAAAAAADmrNPTBPBj6j4/exAAAAAAAAgD8AAAAAAAAAAOU7yz0wTwY+Iov2vQAAAAAAAIA/AAAAAAAAAABOqcQ9ME8GPpKQMr4AAAAAAACAPwAAAAAAAAAA3ojJvcAXGT5KqwUyAAAAAAAAgD8AAAAAAAAAAD9lx73AFxk+FuPxPQAAAAAAAIA/AAAAAAAAAABw8sC9wBcZPjQxLz4AAAAAAACAPwAAAAAAAAAA846mPcAXGT4ckXU+AAAAAAAAgD8AAAAAAAAAAM8Utj3AFxk+Uw9XPgAAAAAAAIA/AAAAAAAAAABz8sA9wBcZPjMxLz4AAAAAAACAPwAAAAAAAAAA2bO1vV5KIT57+yS+AAAAAAAAAIAAAAAAAAAAANmztb1eSiE+e/skvgAAAAAAAACAAAAAAAAAAAByxru9XkohPlTK470AAAAAAAAAgAAAAAAAAAAA2bO1PV5KIT57+yQ+AAAAgAAAAAAAAAAAAAAAANmztT1eSiE+e/skPgAAAIAAAAAAAAAAAAAAAAByxrs9XkohPlTK4z0AAACAAAAAAAAAAAAAAAAASr5kvaMAJz45/2g+guYDOrv/fz/xHzm7AAAAANTs6ryxCCc+whd5PoLmAzq7/38/8R85uwAAAAArRCw9b/wmPkYLdT6C5gM6u/9/P/EfObsAAAAAdvs+vQ0SLT5qrKa9VBjGOAAAgD8Utwu3AAAAAFmnOb1nEi0+0kbAPVQYxjgAAIA/FLcLtwAAAACcA+K8DxItPhjLDD5UGMY4AACAPxS3C7cAAAAAI1WbPhmdvj2IeNC9R9M2PQDZXTysuH8/AAAAACAbmz7/mcE9iHjQvUfTNj0A2V08rLh/PwAAAAA085o++g7DPXN20L1H0zY9ANldPKy4fz8AAAAAloWTPhmdvj2IeNC9AAAAAAAAAIAAAAAAAAAAAJaFkz4Znb49iHjQvQAAAAAAAACAAAAAAAAAAAAAcpM+oYG7PYh40L0AAAAAAAAAgAAAAAAAAAAA2fOePh2ryz1Hsau9AAAAAAAAAAAAAAAAAAAAAO11nT7jo9M9E2SrvQAAAAAAAAAAAAAAAAAAAADtdZ0+46PTPRNkq70AAAAAAAAAAAAAAAAAAAAAL4ChPr4a0T2p+oq9AAAAAAAAAAAAAAAAAAAAAMd4nz5Pr9s9LfKKvQAAAAAAAAAAAAAAAAAAAADHeJ8+T6/bPS3yir0AAAAAAAAAAAAAAAAAAAAA3JWiPtygsj3kz3C9AAAAAAAAAAAAAIA/AAAAANLNoj6hgbs95M9wvQAAAAAAAAAAAACAPwAAAADclaI+ZmLEPeTPcL0AAAAAAAAAAAAAgD8AAAAAKzWVPqXfjj3kz3C9AAAAAAAAAAAAAAAAAAAAAFxtlz7KY2U9489wvQAAAAAAAAAAAAAAAAAAAABcbZc+ymNlPePPcL0AAAAAAAAAAAAAAAAAAAAA9I+mPk/14z3kz3C9AAAAAAAAAIAAAAAAAAAAAPSPpj5P9eM95M9wvQAAAAAAAACAAAAAAAAAAABvTKQ+6f3uPeTPcL0AAAAAAAAAgAAAAAAAAAAAJZyGPsBe1z3jz3C9AAAAAAAAAIAAAAAAAAAAACWchj7AXtc9489wvQAAAAAAAACAAAAAAAAAAAD3koU+ELbJPePPcL0AAAAAAAAAgAAAAAAAAAAAowOiPopBeD1KN5S9AAAAAAAAAAAAAIA/AAAAAOPmpD6Fm4U9SjeUvQAAAAAAAAAAAACAPwAAAACTRac+hiiRPUo3lL0AAAAAAAAAAAAAgD8AAAAAJpWHPoYokT1JN5S9AAAAAAAAAAAAAIA/AAAAANXziT6Fm4U9STeUvQAAAAAAAAAAAACAPwAAAAAW14w+ikF4PUk3lL0AAAAAAAAAAAAAgD8AAAAADoOrPp58yz04/5a9AAAAAAAAAIAAAAAAAAAAAA6Dqz6efMs9OP+WvQAAAAAAAACAAAAAAAAAAAC7WKo+ZNraPTj/lr0AAAAAAAAAgAAAAAAAAAAAaPKIPnJt9T04/5a9AAAAAAAAAIAAAAAAAAAAAGjyiD5ybfU9OP+WvQAAAAAAAACAAAAAAAAAAAByZoY+xQPpPTj/lr0AAAAAAAAAgAAAAAAAAAAAnW6TPrZVVj04/5a9timKvURZLz9ktzk/AAAAAFxtlz5mz0c9a6eOvbYpir1EWS8/ZLc5PwAAAAAis5s+Ny1LPWunjr22KYq9RFkvP2S3OT8AAAAA+/CHPilz+T1rp469AAAAAAAAAAAAAIA/AAAAAL43hT7PLOw9a6eOvQAAAAAAAAAAAACAPwAAAACmMYM+qAfdPWunjr0AAAAAAAAAAAAAgD8AAAAAxEmuPjZi4T2FkgG9AAAAAAAAAAAAAIA/AAAAAGMArD7jfvI9hZIBvQAAAAAAAAAAAACAPwAAAACZ7Kg+Sb8APoWSAb0AAAAAAAAAAAAAgD8AAAAAi5mSPjjcND2DkgG9BS7HvebJfD9kv/49AAAAAFxtlz6STRo96uTePAUux73myXw/ZL/+PQAAAAA6z5w+O4sePejk3jwFLse95sl8P2S//j0AAAAAReuDPv/EBD7r5N48AAAAAAAAAAAAAIA/AAAAAO58gD720Pg96+TePAAAAAAAAAAAAACAPwAAAACI4Hs+w7zlPevk3jwAAAAAAAAAAAAAgD8AAAAAQ7SxPiAL5z2a9qY9AAAAAAAAAAAAAIA/AAAAAGoTrz5itvo9mvamPQAAAAAAAAAAAACAPwAAAADoias+6fkFPpr2pj0AAAAAAAAAAAAAgD8AAAAA4eCRPlbZFz2a9qY9yqXIvdymfj+MpfY8AAAAAFxtlz7W4xY9Lwf/PcqlyL3cpn4/jKX2PAAAAACJ5Jw+STIbPS8H/z3Kpci93KZ+P4yl9jwAAAAAC56DPnVfBT4vB/89AAAAAAAAAAAAAIA/AAAAAB8igD6tw/k9Lwf/PQAAAAAAAAAAAACAPwAAAAC6Fns+8mPmPS8H/z0AAAAAAAAAAAAAgD8AAAAA62OwPtvd5D12NhM+AAAAAAAAAAAAAIA/AAAAALbkrT5Zjfc9djYTPgAAAAAAAAAAAACAPwAAAAB7iKo+D/cDPnY2Ez4AAAAAAAAAAAAAgD8AAAAA5yeSPtYBIz12NhM+AAAAAAAAAAAAAAAAAAAAAFxtlz4EOyo9N6QdPgAAAAAAAAAAAAAAAAAAAABcbZc+BDsqPTekHT4AAAAAAAAAAAAAAAAAAAAAArasPlBk9D03pB0+AAAAAAAAAIAAAAAAAAAAAAK2rD5QZPQ9N6QdPgAAAAAAAACAAAAAAAAAAAAOh6k+NPQBPjekHT4AAAAAAAAAgAAAAAAAAAAATY5/PpWw4j03pB0+AAAAAAAAAIAAAAAAAAAAAE2Ofz6VsOI9N6QdPgAAAAAAAACAAAAAAAAAAAB9pHw+XXvPPTekHT4AAAAAAAAAgAAAAAAAAAAAqx2cPntwOj2Sexw+AAAAAAAAAAAAAAAAAAAAANmfoD5qYUU9knscPgAAAAAAAAAAAAAAAAAAAADZn6A+amFFPZJ7HD4AAAAAAAAAAAAAAAAAAAAA4muoPrp7/z2Sexw+AAAAAAAAAAAAAAAAAAAAAIvHpD4quAU+knscPgAAAAAAAAAAAAAAAAAAAACLx6Q+KrgFPpJ7HD4AAAAAAAAAAAAAAAAAAAAAlsl+PqKBuz2Sexw+AAAAAAAAAAAAAACAAAAAAJbJfj6igbs9knscPgAAAAAAAAAAAAAAgAAAAAAGtn8+aMCoPZJ7HD4AAAAAAAAAAAAAAIAAAAAAydesPg4GmD1hsBY+AAAAAAAAAAAAAIA/AAAAAHkprj7daqk9YbAWPgAAAAAAAAAAAACAPwAAAAB/m64+ooG7PWGwFj4AAAAAAAAAAAAAgD8AAAAA9RuHPi2CdD0gtBY+jSwyvTEbWb3BZX8/AAAAAEsJhz674nM9YbAWPo0sMr0xG1m9wWV/PwAAAACJjIo+2dJcPWGwFj6NLDK9MRtZvcFlfz8AAAAANsmKPkyXAz78GQs+AAAAAAAAAAAAAIA/AAAAAIVWhz793Ps9/BkLPgAAAAAAAAAAAACAPwAAAAAfgoQ+PBLuPfwZCz4AAAAAAAAAAAAAgD8AAAAAmliqPgjxiD2EH/E9AAAAAAAAAAAAAAAAAAAAAJpYqj4I8Yg9hB/xPQAAAAAAAAAAAAAAAAAAAADicqw+PK2YPYQf8T0AAAAAAAAAAAAAAAAAAAAAXG2XPqZCCz6EH/E9AAAAAAAAAAAAAAAAAAAAAPr8kj7NYgo+hB/xPQAAAAAAAAAAAAAAAAAAAAD6/JI+zWIKPoQf8T0AAAAAAAAAAAAAAAAAAAAAhVaHPo5Mdj2EH/E9AAAAAAAAAAAAAAAAAAAAAIVWhz6OTHY9hB/xPQAAAAAAAAAAAAAAAAAAAACFVoc+jkx2PYQf8T0AAAAAAAAAAAAAAAAAAAAACSucPsX91z3mJ/E9AAAAAAAAAAAAAIA/AAAAABGwmj6/JNs95ifxPQAAAAAAAAAAAACAPwAAAAACFZk+fhTdPeYn8T0AAAAAAAAAAAAAgD8AAAAAGgybPq4GrT1Y8Qk+AAAAAAAAAAAAAAAAAAAAABoMmz6uBq09WPEJPgAAAAAAAAAAAAAAAAAAAAAaDJs+rgatPVjxCT4AAAAAAAAAAAAAAAAAAAAAo6aXPmlrsj1YChI++uCBvpd8dz95HQU9AAAAAEumlz7larI9rAwSPvrggb6XfHc/eR0FPQAAAABFTJg+BhmzPdENEj764IG+l3x3P3kdBT0AAAAAe9GVPivxwT3RDRI+AAAAAAAAAAAAAAAAAAAAAKOplT58TME9WAoSPgAAAAAAAAAAAAAAAAAAAAB70ZU+K/HBPdENEj4AAAAAAAAAAAAAAAAAAAAANP2YPkJgmT0oF/w9AAAAAAAAAIAAAAAAAAAAADT9mD5CYJk9KBf8PQAAAAAAAACAAAAAAAAAAABpx5g+QmCZPZAq/T0AAAAAAAAAgAAAAAAAAAAALtCbPjSSnT0oF/w9AAAAAAAAAIAAAAAAAAAAAC7Qmz40kp09KBf8PQAAAAAAAACAAAAAAAAAAACinZs+m0idPZAq/T0AAAAAAAAAgAAAAAAAAAAAuhuePnhgpT0oF/w9AAAAAAAAAIAAAAAAAAAAALobnj54YKU9KBf8PQAAAAAAAACAAAAAAAAAAACF8p0+KdakPZAq/T0AAAAAAAAAgAAAAAAAAAAA+pifPgnarz0oF/w9AAAAAAAAAIAAAAAAAAAAAPqYnz4J2q89KBf8PQAAAAAAAACAAAAAAAAAAAAVfp8+sh+vPZAq/T0AAAAAAAAAgAAAAAAAAAAA8xmgPnm7uz0oF/w9AAAAAAAAAIAAAAAAAAAAAPMZoD55u7s9KBf8PQAAAAAAAACAAAAAAAAAAACdEKA+kue6PZAq/T0AAAAAAAAAgAAAAAAAAAAAFo+fPu6Vxz0oF/w9AAAAAAAAAAAAAACAAAAAABaPnz7ulcc9KBf8PQAAAAAAAAAAAAAAgAAAAABumJ8+B8LGPZAq/T0AAAAAAAAAAAAAAIAAAAAAIwmePmn70T0oF/w9AAAAAAAAAAAAAACAAAAAACMJnj5p+9E9KBf8PQAAAAAAAAAAAAAAgAAAAAAIJJ4+EUHRPZAq/T0AAAAAAAAAAAAAAIAAAAAAV+CbPpgg2T2QKv09AAAAAAAAAAAAAAAAAAAAAFfgmz6YINk9kCr9PQAAAAAAAAAAAAAAAAAAAABX4Js+mCDZPZAq/T0AAAAAAAAAAAAAAAAAAAAARROZPoBt3T2QKv09AAAAAAAAAAAAAAAAAAAAAOBhoD6GDgc+JPzyPQAAAAAAAAAAAAAAAAAAAADgYaA+hg4HPiT88j0AAAAAAAAAAAAAAAAAAAAAUBOWPgKj3T2QKv09AAAAAAAAAAAAAAAAAAAAAGnHmD4HsQo+JPzyPQAAAAAAAAAAAAAAAAAAAABpx5g+B7EKPiT88j0AAAAAAAAAAAAAAAAAAAAAFz2TPqi62T2QKv09AAAAAAAAAAAAAAAAAAAAADUDkT7z5wg+JPzyPQAAAAAAAAAAAAAAAAAAAAA1A5E+8+cIPiT88j0AAAAAAAAAAAAAAAAAAAAAEQWKPm3qAT4k/PI9AAAAAAAAAAAAAAAAAAAAABEFij5t6gE+JPzyPQAAAAAAAAAAAAAAAAAAAABHLoo+lS8CPowP9D0AAAAAAAAAAAAAAAAAAAAA0L+EPu7a7T2MD/Q9AAAAAAAAAAAAAAAAAAAAAPgvgz7ACOM9KBf8PQAAAAAAAAAAAAAAAAAAAAD4L4M+wAjjPSgX/D0AAAAAAAAAAAAAAAAAAAAANgeBPu71xD0oF/w9AAAAAAAAAAAAAAAAAAAAADYHgT7u9cQ9KBf8PQAAAAAAAAAAAAAAAAAAAACNEIE+1cnFPZAq/T0AAAAAAAAAAAAAAAAAAAAAE5KBPjG/pT0oF/w9AAAAAAAAAIAAAAAAAAAAABOSgT4xv6U9KBf8PQAAAAAAAACAAAAAAAAAAAC8iIE+GJOmPZAq/T0AAAAAAAAAgAAAAAAAAAAA66SEPqziiT2QKv09RsfzvjdNIz/v9Bq/AAAAAGi/kD4ZX6U90gz0PUbH8743TSM/7/QavwAAAAA06JA+KdakPST88j1Gx/O+N00jP+/0Gr8AAAAAAPqVPixMmT0oF/w9AAAAAAAAAIAAAAAAAAAAAAD6lT4sTJk9KBf8PQAAAAAAAACAAAAAAAAAAAB0x5U+w5WZPZAq/T0AAAAAAAAAgAAAAAAAAAAAkJyUvnE+sD2BeNC9AAAAAAAAAAAAAAAAAAAAAJCclL5xPrA9gXjQvQAAAAAAAAAAAAAAAAAAAACQnJS+cT6wPYF40L0AAAAAAAAAAAAAAAAAAAAAOjSYvrkgyz2BeNC9V41dPBCXNr3buH+/AAAAAK5Qmb4Jmck9bnbQvVeNXTwQlza927h/vwAAAAB085i+sTjKPYF40L1XjV08EJc2vdu4f78AAAAAOjSYvoniqz2BeNC9AAAAAAAAAIAAAAAAAAAAADo0mL6J4qs9gXjQvQAAAAAAAACAAAAAAAAAAACbP5i+wH+ZPVqxq70AAAAAAAAAgAAAAAAAAAAA7XWdvl9foz0MZKu9gAwYvzzmSb8GqyK+AAAAAIFwm75GWJ09V7GrvYAMGL885km/BqsivgAAAADCiJi++QCOPZj6ir2ADBi/POZJvwarIr4AAAAAx3ifvvRTmz0l8oq9AAAAAAAAAAAAAACAAAAAAMd4n770U5s9JfKKvQAAAAAAAAAAAAAAgAAAAACgzZy+fCmTPZj6ir0AAAAAAAAAAAAAAIAAAAAA++Kgvu/J1D3Xz3C9AAAAAAAAAAAAAIA/AAAAAB/wob7T68w9189wvQAAAAAAAAAAAACAPwAAAADclaK+ZmLEPdfPcL0AAAAAAAAAAAAAgD8AAAAAJZyGvoOknz3Zz3C9AAAAAAAAAAAAAAAAAAAAACWchr6DpJ892c9wvQAAAAAAAAAAAAAAAAAAAAD3koW+Mk2tPdnPcL0AAAAAAAAAAAAAAAAAAAAAePqavpp1AT7Xz3C9AAAAAAAAAAAAAAAAAAAAAKRknr6Axv49189wvQAAAAAAAAAAAAAAAAAAAACkZJ6+gMb+PdfPcL0AAAAAAAAAAAAAAAAAAAAAb0ykvlgFiD3Wz3C9AAAAAAAAAAAAAAAAAAAAAEiKob6D7n091s9wvQAAAAAAAAAAAAAAAAAAAABIiqG+g+59PdbPcL0AAAAAAAAAAAAAAAAAAAAAFSWbvhQiAz5DN5S9AAAAAAAAAAAAAIA/AAAAADu4nr7d9gA+QzeUvQAAAAAAAAAAAACAPwAAAACjA6K+feL6PUM3lL0AAAAAAAAAAAAAgD8AAAAAaPKIvtCVgT0z/5a9AAAAAAAAAAAAAAAAAAAAAGjyiL7QlYE9M/+WvQAAAAAAAAAAAAAAAAAAAAByZoa+ff+NPTP/lr0AAAAAAAAAAAAAAAAAAAAAnW6TvjPsBT4y/5a9AAAAAAAAAAAAAAAAAAAAAFxtl76qtQY+Mv+WvQAAAAAAAAAAAAAAAAAAAABcbZe+qrUGPjL/lr0AAAAAAAAAAAAAAAAAAAAAR3Sovn3/jT0y/5a9AAAAAAAAAAAAAACAAAAAAEd0qL59/409Mv+WvQAAAAAAAAAAAAAAgAAAAABR6KW+0JWBPTL/lr0AAAAAAAAAAAAAAIAAAAAA+/CHvilz+T1mp469AAAAAAAAAIAAAAAAAAAAAPvwh74pc/k9ZqeOvQAAAAAAAACAAAAAAAAAAACRQou+DiwCPmanjr0AAAAAAAAAgAAAAAAAAAAAi5mSvjjcND13kgG99ONRNZ1WxLUAAIA/AAAAADf1jb4FIEA9eJIBvfTjUTWdVsS1AACAPwAAAAAMrom+D2tSPXiSAb3041E1nVbEtQAAgD8AAAAAxEmuvjZi4T13kgG9AAAAAAAAAAAAAIA/AAAAAD6yr77o0M49d5IBvQAAAAAAAAAAAACAPwAAAAD1K7C+oYG7PXeSAb0AAAAAAAAAAAAAgD8AAAAAReuDvv/EBD7/5N48AAAAAAAAAIAAAAAAAAAAAEXrg77/xAQ+/+TePAAAAAAAAACAAAAAAAAAAACHGYi+raELPgHl3jwAAAAAAAAAgAAAAAAAAAAA4eCRvlbZFz2g9qY9Dpu2NbvQKrYAAIA/AAAAAP2KjL4MzCQ9oPamPQ6btjW70Cq2AACAPwAAAAAtoIe+2tI5PaD2pj0Om7Y1u9AqtgAAgD8AAAAAQ7SxviAL5z2g9qY9AAAAAAAAAAAAAIA/AAAAAJpSs76Os9E9oPamPQAAAAAAAAAAAACAPwAAAACC3rO+ooG7PaD2pj0AAAAAAAAAAAAAgD8AAAAAC56DvnVfBT42B/89AAAAAAAAAIAAAAAAAAAAAAueg751XwU+Ngf/PQAAAAAAAACAAAAAAAAAAADZ3Ie+TFcMPjYH/z0AAAAAAAAAgAAAAAAAAAAA5yeSvtYBIz15NhM+AAAAAAAAAAAAAIA/AAAAAE4Wjb7PTi89eTYTPgAAAAAAAAAAAACAPwAAAABvaoi+eEhDPXk2Ez4AAAAAAAAAAAAAgD8AAAAA62Owvtvd5D15NhM+AAAAAAAAAAAAAIA/AAAAAIrtsb52l9A9eTYTPgAAAAAAAAAAAACAPwAAAABzcrK+ooG7PXk2Ez4AAAAAAAAAAAAAgD8AAAAATY5/vrBSlD06pB0+AAAAAAAAAAAAAAAAAAAAAE2Of76wUpQ9OqQdPgAAAAAAAAAAAAAAAAAAAAB9pHy+54enPTqkHT4AAAAAAAAAAAAAAAAAAAAAy2ucvg33Dz46pB0+AAAAAAAAAAAAAAAAAAAAABk5ob49DQ0+OqQdPgAAAAAAAAAAAAAAAAAAAAAZOaG+PQ0NPjqkHT4AAAAAAAAAAAAAAAAAAAAADoepvrk1Zj06pB0+AAAAAAAAAAAAAAAAAAAAAAimpb4Zvkw9OqQdPgAAAAAAAAAAAAAAAAAAAAAIpqW+Gb5MPTqkHT4AAAAAAAAAAAAAAAAAAAAAlsl+vqKBuz2Vexw+AAAAAAAAAIAAAAAAAAAAAJbJfr6igbs9lXscPgAAAAAAAACAAAAAAAAAAAAGtn++3ELOPZV7HD4AAAAAAAAAgAAAAAAAAAAAi8ekviq4BT6Vexw+AAAAAAAAAAAAAAAAAAAAAOJrqL66e/89lXscPgAAAAAAAAAAAAAAAAAAAADia6i+unv/PZV7HD4AAAAAAAAAAAAAAAAAAAAA2Z+gvmphRT2Vexw+AAAAAAAAAAAAAAAAAAAAAKsdnL57cDo9lXscPgAAAAAAAAAAAAAAAAAAAACrHZy+e3A6PZV7HD4AAAAAAAAAAAAAAAAAAAAAME6kvuxMBD5ksBY+y1QzPSmEWr2+Y3+/AAAAAH+9p75Cx/w9I7QWPstUMz0phFq9vmN/vwAAAABu0ae+5hH9PWSwFj7LVDM9KYRavb5jf78AAAAAXxyBvixDzT3/GQs+AAAAAAAAAAAAAIA/AAAAANdngr4IVt49/xkLPgAAAAAAAAAAAACAPwAAAAAfgoS+PBLuPf8ZCz4AAAAAAAAAAAAAgD8AAAAAXG2Xvu77QD2KH/E9AAAAAAAAAAAAAAAAAAAAAPr8kr5Te0Q9ih/xPQAAAAAAAAAAAAAAAAAAAAD6/JK+U3tEPYof8T0AAAAAAAAAAAAAAAAAAAAAhVaHvv3c+z2KH/E9AAAAAAAAAAAAAAAAAAAAAIVWh7793Ps9ih/xPQAAAAAAAAAAAAAAAAAAAACFVoe+/dz7PYof8T0AAAAAAAAAAAAAAAAAAAAAWr6tvixDzT2KH/E9AAAAAAAAAIAAAAAAAAAAAFq+rb4sQ809ih/xPQAAAAAAAACAAAAAAAAAAABHLq6+ooG7PYof8T0AAAAAAAAAgAAAAAAAAAAA2V+RvjlMoz2kKfE9QFGUOwbqHbsj/38/AAAAAFVOkL7tiqg97SfxPUBRlDsG6h27I/9/PwAAAACWhI++0nauPe0n8T1AUZQ7BuoduyP/fz8AAAAAUlOfvpZbrj3uJ/E9VOCyO524Pzu+/n8/AAAAAEyInr5pcqg97SfxPVTgsjuduD87vv5/PwAAAADgeJ2+ylKjPdYl8T1U4LI7nbg/O77+fz8AAAAABhubvuM/yj0r3Ak+Dw6tPrNgib5J72a/AAAAABoMm76W/Mk9XPEJPg8OrT6zYIm+Se9mvwAAAAAx85u+qj3FPd74CT4PDq0+s2CJvknvZr8AAAAAe9GVvivxwT3VDRI+AAAAgAAAAAAAAAAAAAAAAHvRlb4r8cE91Q0SPgAAAIAAAAAAAAAAAAAAAACKWZa+yI7DPbAMEj4AAACAAAAAAAAAAAAAAAAARUyYvgYZsz3VDRI+2z8jvrSm2b5UGGQ/AAAAAFsXmL7axLI9sAwSPts/I760ptm+VBhkPwAAAABcbZe+ooG7PR1fFD7bPyO+tKbZvlQYZD8AAAAAUBOWvmxCQz2WKv09AAAAAAAAAAAAAAAAAAAAAFATlr5sQkM9lir9PQAAAAAAAAAAAAAAAAAAAABQE5a+bEJDPZYq/T0AAAAAAAAAAAAAAAAAAAAA2HiOvmzMUT2WKv09AAAAAAAAAAAAAAAAAAAAANh4jr5szFE9lir9PQAAAAAAAAAAAAAAAAAAAADYeI6+bMxRPZYq/T0AAAAAAAAAAAAAAAAAAAAA5PKHvtBDdD2WKv09AAAAAAAAAAAAAAAAAAAAAOTyh77QQ3Q9lir9PQAAAAAAAAAAAAAAAAAAAADk8oe+0EN0PZYq/T0AAAAAAAAAAAAAAAAAAAAA3kqDvixAkz2WKv09AAAAAAAAAAAAAAAAAAAAAN5Kg74sQJM9lir9PQAAAAAAAAAAAAAAAAAAAADeSoO+LECTPZYq/T0AAAAAAAAAAAAAAAAAAAAAjRCBvm05sT2WKv09AAAAAAAAAAAAAAAAAAAAAI0Qgb5tObE9lir9PQAAAAAAAAAAAAAAAAAAAACNEIG+bTmxPZYq/T0AAAAAAAAAAAAAAAAAAAAAvIiBvipw0D2WKv09AAAAAAAAAAAAAAAAAAAAALyIgb4qcNA9lir9PQAAAAAAAAAAAAAAAAAAAAC8iIG+KnDQPZYq/T0AAAAAAAAAAAAAAAAAAAAA66SEvpcg7T2WKv09AAAAAAAAAAAAAAAAAAAAAOukhL6XIO09lir9PQAAAAAAAAAAAAAAAAAAAADrpIS+lyDtPZYq/T0AAAAAAAAAAAAAAAAAAAAAFz2Tvqi62T0q/PI9AAAAAAAAAAAAAACAAAAAABc9k76outk9KvzyPQAAAAAAAAAAAAAAgAAAAACLCpO+D3HZPZIP9D0AAAAAAAAAAAAAAIAAAAAAUBOWvgKj3T0q/PI9AAAAAAAAAAAAAAAAAAAAAFATlr4Co909KvzyPQAAAAAAAAAAAAAAAAAAAACF3ZW+AqPdPZIP9D0AAAAAAAAAAAAAAAAAAAAARROZvoBt3T0q/PI9AAAAAAAAAAAAAAAAAAAAAEUTmb6Abd09KvzyPQAAAAAAAAAAAAAAAAAAAAC54Ji+GLfdPZIP9D0AAAAAAAAAAAAAAAAAAAAAV+Cbvpgg2T0q/PI9AAAAAAAAAAAAAAAAAAAAAFfgm76YINk9KvzyPQAAAAAAAAAAAAAAAAAAAAAit5u+6KrZPZIP9D0AAAAAAAAAAAAAAAAAAAAAIwmevmn70T2SD/Q9AAAAAAAAAAAAAAAAAAAAAPqYn745Kcc9Lhf8PQAAAAAAAAAAAAAAAAAAAAD6mJ++OSnHPS4X/D0AAAAAAAAAAAAAAAAAAAAAnRCgvrEbvD2WKv09AAAAAAAAAAAAAAAAAAAAAJ0QoL6xG7w9lir9PQAAAAAAAAAAAAAAAAAAAACdEKC+sRu8PZYq/T0AAAAAAAAAAAAAAAAAAAAAbpifvj1BsD2WKv09AAAAAAAAAAAAAAAAAAAAAG6Yn749QbA9lir9PQAAAAAAAAAAAAAAAAAAAABumJ++PUGwPZYq/T0AAAAAAAAAAAAAAAAAAAAACCSevjPCpT2WKv09AAAAAAAAAAAAAAAAAAAAANuPq74sQJM9KvzyPQAAAAAAAAAAAAAAAAAAAADbj6u+LECTPSr88j0AAAAAAAAAAAAAAAAAAAAAc6ykvjhIZT0uF/w9bvI3PunvVL9IdQY/AAAAAEGtpL6lTWU9lRz8PW7yNz7p71S/SHUGPwAAAACn1aS+1lxmPZYq/T1u8jc+6e9Uv0h1Bj8AAAAAhdedvrxmSj2WKv09AAAAAAAAAAAAAAAAAAAAAIXXnb68Zko9lir9PQAAAAAAAAAAAAAAAAAAAACF152+vGZKPZYq/T0AAAAAAAAAAAAAAAAAAAAAFSWbPjR+YT1KN5S9AAAAgAAAAAAAAIC/AAAAAFxtlz5SkF49SjeUvQAAAIAAAAAAAACAvwAAAAA7uJ4+ECtqPUo3lL0AAACAAAAAAAAAgL8AAAAAJpWHPrza5T1JN5S9AAAAAAAAAAAAAIA/AAAAAFfShT4drdg9STeUvQAAAAAAAAAAAACAPwAAAAC7vIQ+hWDKPUk3lL0AAAAAAAAAAAAAgD8AAAAA+6KpPs8s7D1sp469AAAAAAAAAAAAAAAAAAAAAL7ppj4pc/k9bKeOvQAAAAAAAAAAAAAAAAAAAAC+6aY+KXP5PWynjr0AAAAAAAAAAAAAAAAAAAAAieScPkkyGz0vB/89AAAAgAAAAAAAAIC/AAAAAFxtlz7W4xY9Lwf/PQAAAIAAAAAAAACAvwAAAADxJaI+R/MnPS8H/z0AAACAAAAAAAAAgL8AAAAAHyKAPq3D+T0vB/8902qttg5jOTYAAIA/AAAAALoWez7yY+Y9Lwf/PdNqrbYOYzk2AACAPwAAAAB75nc+VF7RPTEH/z3Taq22DmM5NgAAgD8AAAAAarOqPvEE7z1hsBY+AAAAAAAAAAAAAAAAAAAAAG7Rpz7mEf09YbAWPgAAAAAAAAAAAAAAAAAAAABu0ac+5hH9PWGwFj4AAAAAAAAAAAAAAAAAAAAAgReZPiUImj2EH/E9AAAAgAAAAAAAAIC/AAAAAFxtlz5CYJk9hB/xPQAAAIAAAAAAAACAvwAAAABGsZo+WfmbPYQf8T0AAACAAAAAAAAAgL8AAAAABeWOPqKBuz2EH/E9AAAAAAAAAAAAAIA/AAAAAP0Ojz4O2bQ9hB/xPQAAAAAAAAAAAACAPwAAAABKi48+/HGuPYQf8T0AAAAAAAAAAAAAgD8AAAAA3JWivtygsj3Xz3C9AAAAAAAAAAAAAIA/AAAAANCYob72q6Y9189wvQAAAAAAAAAAAACAPwAAAADHeJ++9FObPdfPcL0AAAAAAAAAAAAAgD8AAAAAFSWbvhQiAz5DN5S9AAAAAAAAAAAAAIA/AAAAADu4nr7d9gA+QzeUvQAAAAAAAAAAAACAPwAAAACjA6K+feL6PUM3lL0AAAAAAAAAAAAAgD8AAAAApjGDvpn7mT1lp469PrZwtsIJkjUAAIA/AAAAAJvygb6Maqo9ZaeOvT62cLbCCZI1AACAPwAAAADhhoG+oYG7PWanjr0+tnC2wgmSNQAAgD8AAAAAvummvjQgez1kp469AAAAAAAAAAAAAACAAAAAAL7ppr40IHs9ZKeOvQAAAAAAAAAAAAAAgAAAAAAomKO+TVZlPWSnjr0AAAAAAAAAAAAAAIAAAAAAieScvhC1FD42B/89AAAAAAAAAAAAAIA/AAAAAPElor7QhBE+Ngf/PQAAAAAAAAAAAACAPwAAAADf/aa+TFcMPjYH/z0AAAAAAAAAAAAAgD8AAAAA8AKCvg4GmD1ksBY+AAAAAAAAAAAAAIA/AAAAAECxgL7daqk9ZLAWPgAAAAAAAAAAAACAPwAAAAA6P4C+ooG7PWSwFj4AAAAAAAAAAAAAgD8AAAAAbtGnvrvicz1ksBY+AAAAAAAAAAAAAACAAAAAAG7Rp7674nM9ZLAWPgAAAAAAAAAAAAAAgAAAAAAwTqS+2dJcPWSwFj4AAAAAAAAAAAAAAIAAAAAA6yqcvn/i1z2KH/E9AAAAAAAAAAAAAIA/AAAAAO11nb7jo9M9ih/xPQAAAAAAAAAAAACAPwAAAACUhZ6+23fOPYof8T0AAAAAAAAAAAAAgD8AAAAAkgOUPtWJBT7ocIo9uT48OVswfj8TLvO9AAAAAESilD7YPgc+mf6mPbk+PDlbMH4/Ey7zvQAAAABINpo+CVcHPtCbqD25Pjw5WzB+PxMu870AAAAA+LaTPg/YDD5GLtQ9AAAAAAAAAAAAAAAAAAAAAPi2kz4P2Aw+Ri7UPQAAAAAAAAAAAAAAAAAAAACYepQ+/U0NPsbb2z0AAAAAAAAAAAAAAAAAAAAAlSiTPpQr8j1Cjc+9Wj3WPEsdfj+sQvK9AAAAALY9kj5EJvg9SjCevVo91jxLHX4/rELyvQAAAADoHJI+bGUOPlAvlT1aPdY8Sx1+P6xC8r0AAAAANfuTPvovCT6kTOC9AAAAAAAAAIAAAAAAAAAAADX7kz76Lwk+pEzgvQAAAAAAAACAAAAAAAAAAAA34pI+IdwJPo2m1L0AAAAAAAAAgAAAAAAAAAAAcj2TPm5NGz4UQ8+9AAAAAAAAAIAAAAAAAAAAAHI9kz5uTRs+FEPPvQAAAAAAAACAAAAAAAAAAACFi5I+j5IcPmVOur0AAAAAAAAAgAAAAAAAAAAAcmGaPjPrIT6l67298Ww8vLUEfj/FO/29AAAAAJh6lD4lyyE+Aby9vfFsPLy1BH4/xTv9vQAAAAD4tpM+E0EiPoAOtr3xbDy8tQR+P8U7/b0AAAAAUp6bPngQIz70jai9AAAAAAAAAAAAAAAAAAAAAFKemz54ECM+9I2ovQAAAAAAAAAAAAAAAAAAAADBI5s+E0EiPoAOtr0AAAAAAAAAAAAAAAAAAAAAJ9eaPk2PKT5Eoli9AAAAAAAAAAAAAAAAAAAAACfXmj5Njyk+RKJYvQAAAAAAAAAAAAAAAAAAAABHNpo+GcInPhN8ir0AAAAAAAAAAAAAAAAAAAAAkgOUvkR37T03oli9AAAAAAAAAAAAAAAAAAAAAJIDlL5Ed+09N6JYvQAAAAAAAAAAAAAAAAAAAAALo5S+sgXqPYroiL0AAAAAAAAAAAAAAAAAAAAAge2Svn3GCj4ptLE9HgCyPkZSbj/iyeS9AAAAADjXkr5TTe4930iUvR4Asj5GUm4/4snkvQAAAACB7ZK+R4TuPVaUk70eALI+RlJuP+LJ5L0AAAAAFhqUvrZQFD6zC/Y9AAAAAAAAAAAAAAAAAAAAABYalL62UBQ+swv2PQAAAAAAAAAAAAAAAAAAAAAWGpS+tlAUPrML9j0AAAAAAAAAAAAAAAAAAAAANfuTvijpJT5vbP49AAAAAAAAAAAAAACAAAAAADX7k74o6SU+b2z+PQAAAAAAAAAAAAAAgAAAAAAy4pK+ejElPqbF8j0AAAAAAAAAAAAAAIAAAAAAXG2XvoyrNj6S3fg9AAAAAAAAAAAAAACAAAAAAFxtl76MqzY+kt34PQAAAAAAAAAAAAAAgAAAAAAWGpS+PIA2PrML9j0AAAAAAAAAAAAAAIAAAAAAUp6bviwZOT7BrcY9AAAAAAAAAAAAAAAAAAAAAFKem74sGTk+wa3GPQAAAAAAAAAAAAAAAAAAAADBI5u+kOg5Pk0u1D0AAAAAAAAAAAAAAAAAAAAARgSbvmj2MD7v//A7AAAAAAAAAAAAAAAAAAAAADD5mr5r1zY+FBdiPQAAAAAAAAAAAAAAAAAAAAAw+Zq+a9c2PhQXYj0AAAAAAAAAAAAAAAAAAAAATfiRul9Pkj4TCkW/AJ1/vxNwYL37U4U7AAAAAJuVq7oVRZM+eNpKvwCdf78TcGC9+1OFOwAAAACxd6u6D0OTPr/ZSr8AnX+/E3BgvftThTsAAAAAVacpOn+9iT57yEC/F3F4P//Vbz5QB2y9AAAAADPJIzpgwok+RNdAvxdxeD//1W8+UAdsvQAAAAD5S4I5pa6LPiWOPr8XcXg//9VvPlAHbL0AAAAA406jPvDCnT4AAIC/UuQ9vymwKz+TFwM7AAAAAHFRoz70qp0+THFuv1LkPb8psCs/kxcDOwAAAABKsaU+VFGgPnRscr9S5D2/KbArP5MXAzsAAAAAJ1KqPt0Rnz7s0n6/RdmNvkeL7ry83XW/AAAAAFFgqj4ai54+7NJ+v0XZjb5Hi+68vN11vwAAAAAgYKo+FoyePujSfr9F2Y2+R4vuvLzddb8AAAAA8uWwPkkdoD4n2Ha/L+Fiv6aV5z6ijcw9AAAAAOeIrz7Uip8+Fpl7vy/hYr+mlec+oo3MPQAAAAB9gq8+s3+fPlece78v4WK/ppXnPqKNzD0AAAAAYfewPk47nz7zK3W/AAAAAAAAAAAAAAAAAAAAAMprsT5zip8+qjh3vwAAAAAAAAAAAAAAAAAAAADKa7E+c4qfPqo4d78AAAAAAAAAAAAAAAAAAAAA6LRUOeLhjT6GE2y/mH5+v6nl1z1I/8o8AAAAAO7wTzkL3I0+DBNsv5h+fr+p5dc9SP/KPAAAAABxQVE5mN2NPgwTbL+Yfn6/qeXXPUj/yjwAAAAAfqE7vsoWlD528GG/4Npsv3BwtL71ARA+AAAAANXSN7601ZU+bH1Zv+DabL9wcLS+9QEQPgAAAADegT++y56UPkCmZ7/g2my/cHC0vvUBED4AAAAAGeimviC+nj5us3+/q9m+vhB3ID2aVm0/AAAAAOX3pr7RJ54+brN/v6vZvr4QdyA9mlZtPwAAAACv96a+7CiePmmzf7+r2b6+EHcgPZpWbT8AAAAAX0GtvuRTnz7GbX2/AAAAAAAAAAAAAAAAAAAAAPBMrb7b5Z4+xm19vwAAAAAAAAAAAAAAAAAAAADwTK2+2+WePsZtfb8AAAAAAAAAAAAAAAAAAAAAROiwvkLLnz7zK3W/CY9OPwfzEz9XgPo9AAAAAELesL4WvZ8+eit1vwmPTj8H8xM/V4D6PQAAAAAQ5LC+O/OfPj+Ydb8Jj04/B/MTP1eA+j0AAAAAiJNhvAKtgz406A2/AAAAgAAAAAAAAAAAAAAAAIiTYbwCrYM+NOgNvwAAAIAAAAAAAAAAAAAAAAAjWIS8Aq2DPqY8Gb8AAACAAAAAAAAAAAAAAAAAxi2GPAKtgz6q3ya/AAAAAAAAAAAAAAAAAAAAAPNXhDwCrYM+pjwZvwAAAAAAAAAAAAAAAAAAAADzV4Q8Aq2DPqY8Gb8AAAAAAAAAAAAAAAAAAAAAQI6APDWOnD6U00S/DVVsP/Wowr5Y1We9AAAAAIh1mDzrYpw+KxM4vw1VbD/1qMK+WNVnvQAAAABK7KU8lTmaPunzKb8NVWw/9ajCvljVZ70AAAAAz902vD/Snj57CRC/9OsuPWPDf79cfqS7AAAAALe1hrwfx54+lzcXv/TrLj1jw3+/XH6kuwAAAABKRJ68Q9GePhlsIb/06y49Y8N/v1x+pLsAAAAA038YvAb3pj4J1B6/AAAAgAAAAAAAAAAAAAAAANN/GLwG96Y+CdQevwAAAIAAAAAAAAAAAAAAAAAZ32C8BvemPlS0JL8AAACAAAAAAAAAAAAAAAAAXTINvNxkrD4DbiO/HJ/2PuBqXj9Yu+o9AAAAADdiDLwuYaw+um0jvxyf9j7gal4/WLvqPQAAAAA5RUe8SlavPmLFKr8cn/Y+4GpeP1i76j0AAAAAAWQbu6kUtT7ZGma/To86PAiR4Lwf43+/AAAAAIY9GLuFSLY+CR9mv06POjwIkeC8H+N/vwAAAACh4Bg73Me1PssZZr9Ojzo8CJHgvB/jf78AAAAA0Tg8PCZ5zD6ciEa/pYI5P4RTJ7/MkF8+AAAAAHRdNTyC9c8+z/VAv6WCOT+EUye/zJBfPgAAAAALSxg8gSHSPpMzPL+lgjk/hFMnv8yQXz4AAAAA38oGO1+v4j4riz2/AAAAgAAAAAAAAAAAAAAAAN/KBjtfr+I+K4s9vwAAAIAAAAAAAAAAAAAAAACv8e+6BfLyPn1/RL8AAACAAAAAAAAAAAAAAAAAQhWqutvkDz9Xj1a/Z/9/P+9xgbsMbNU6AAAAALY3tLqxIgw/nIVTv2f/fz/vcYG7DGzVOgAAAAAdJqe6q7MFP3LOcr9n/38/73GBuwxs1ToAAAAAHOBSu8EsGz9wLHO/+vEzuK2zfL+h1yM+AAAAANm1bLqKDxo/AAx6v/rxM7its3y/odcjPgAAAABevGo6ig8aP/MLer/68TO4rbN8v6HXIz4AAAAA8r51uhgcHj8iHmG/eX2OPjvGc78LowC+AAAAABe/KbsYHB4/FQ5iv3l9jj47xnO/C6MAvgAAAABrgIK7DUIfP4iMa795fY4+O8ZzvwujAL4AAAAA5JYKO3LJHz+NAWS/AAAAAAAAAAAAAAAAAAAAAHGeSDpyyR8/oz1jvwAAAAAAAAAAAAAAAAAAAABxnkg6cskfP6M9Y78AAAAAAAAAAAAAAAAAAAAAf9V4OaDhIT8BJ3C/l/vruzn+f79oscc6AAAAAAatmjpo4iE/OAJtv5f767s5/n+/aLHHOgAAAAAUtsE60+IhP6mTa7+X++u7Of5/v2ixxzoAAAAAl3zVr55ApD6Ii6i7AAAAAAAAAAAAAAAAAAAAAExV0LqeQKQ+vUuguwAAAAAAAAAAAAAAAAAAAABMVdC6nkCkPr1LoLsAAAAAAAAAAAAAAAAAAAAACxOgOkKwoj6Mqwa8BXhvPVqndz9ZVnw+AAAAAOc1obvFsaI+0xTfuwV4bz1ap3c/WVZ8PgAAAABggp67HKyiPlcr2rsFeG89Wqd3P1lWfD4AAAAAw3D1O8SQoD6qUrI7oWJXP0LzBD8YVRk+AAAAACM9ETyhxp8+2BNJO6FiVz9C8wQ/GFUZPgAAAAAYqhk8ocafPrNfOzmhYlc/QvMEPxhVGT4AAAAAdsxQP8FBYT491o6+AAAAAAAAAAAAAAAAAAAAAMgmUT9SSWE+vfmOvgAAAAAAAAAAAAAAAAAAAADIJlE/UklhPr35jr4AAAAAAAAAAAAAAAAAAAAA1CBSPyVhYD6F9JG+AAAAAAAAAAAAAAAAAAAAAMbQUT9i0mA+zt6SvgAAAAAAAAAAAAAAAAAAAADG0FE/YtJgPs7ekr4AAAAAAAAAAAAAAAAAAAAA8+NRP8/OWj5BIY++OoPGPCeheT/BqGE+AAAAABQ8Uj/FNFs+NhaQvjqDxjwnoXk/wahhPgAAAACfXlI/kLtbPglIkb46g8Y8J6F5P8GoYT4AAAAA4/JPv+LVYT5L8Y++AAAAgAAAAAAAAAAAAAAAAOPyT7/i1WE+S/GPvgAAAIAAAAAAAAAAAAAAAAAo4U+/AidiPmChkL4AAACAAAAAAAAAAAAAAAAA3HNPv6+fYD4F8ZG+AAAAAAAAAAAAAAAAAAAAAIbET78+AmE+H9ySvgAAAAAAAAAAAAAAAAAAAACGxE+/PgJhPh/ckr4AAAAAAAAAAAAAAAAAAAAAP6JPv4sDWz5MHo++W1/mvNndeT828Fw+AAAAAPyfT78gAls+fxqPvltf5rzZ3Xk/NvBcPgAAAADBSk+/hnlbPlkSkL5bX+a82d15PzbwXD4AAAAAYUHJN9tMkD4kVXe/AAAAAAAAAAAAAAAAAAAAAGTTUTvyCZA+zlZ3vwAAAAAAAAAAAAAAAAAAAABk01E78gmQPs5Wd78AAAAAAAAAAAAAAAAAAAAA/OJRu9YMhj69q3e/AAAAAAAAAAAAAAAAAAAAAInMxrvmzIY+7KV3vwAAAAAAAAAAAAAAAAAAAACJzMa75syGPuyld78AAAAAAAAAAAAAAAAAAAAASW85PFL2iz4t23e/LfkvvLv2kz3yUH+/AAAAAKg+MDyzS4k+gfN3vy35L7y79pM98lB/vwAAAAC5yRU8qK+HPkoBeL8t+S+8u/aTPfJQf78AAAAAj1QwPFpdiT4Oeni/AAAAAAAAAAAAAAAAAAAAAKDfFTxPwYc+14d4vwAAAAAAAAAAAAAAAAAAAACg3xU8T8GHPteHeL8AAAAAAAAAAAAAAAAAAAAAeutiuwWrkD4aP3i/AAAAAAAAAAAAAAAAAAAAAOEMAThXpo8+2Wh4vwAAAAAAAAAAAAAAAAAAAADhDAE4V6aPPtloeL8AAAAAAAAAAAAAAAAAAAAAD1I1tw23hj7is3i/AAAAAAAAAAAAAAAAAAAAAEW5Mbvs74Y+drJ4vwAAAAAAAAAAAAAAAAAAAABFuTG77O+GPnayeL8AAAAAAAAAAAAAAAAAAAAANrQdO/Xbjj7353e/AAAAAAAAAAAAAAAAAAAAAGM+lTvqS44+Vux3vwAAAAAAAAAAAAAAAAAAAABjPpU76kuOPlbsd78AAAAAAAAAAAAAAAAAAAAAkO6Uuyzuhz5NI3i/AAAAAAAAAIAAAAAAAAAAAJDulLss7oc+TSN4vwAAAAAAAACAAAAAAAAAAADYusy7/c2IPkAceL8AAAAAAAAAgAAAAAAAAAAA/MM1PheTID7fv2e9AAAAAAAAAAAAAAAAAAAAANB2Nj4XkyA+fS1yvQAAAAAAAAAAAAAAAAAAAADQdjY+F5MgPn0tcr0AAAAAAAAAAAAAAAAAAAAA0HY2PheTID5BUl29AAAAAAAAAAAAAAAAAAAAANB2Nj4XkyA+QVJdvQAAAAAAAAAAAAAAAAAAAABH2jM+KIAdPn7zZ70AAAAAAAAAAAAAAAAAAAAA8Uo3PkdcGz6sNE69AAAAgAAAAAAAAAAAAAAAAPFKNz5HXBs+rDROvQAAAIAAAAAAAAAAAAAAAAD+lzQ+R1wbPnYAWb0AAACAAAAAAAAAAAAAAAAApao+PrSQqz2tNE69AAAAAAAAAAAAAAAAAAAAAMv6Oj60kKs9DkFKvQAAAAAAAAAAAAAAAAAAAADL+jo+tJCrPQ5BSr0AAAAAAAAAAAAAAAAAAAAAOFM4PvGWHT0ZJHq9AAAAAAAAAAAAAACAAAAAADhTOD7xlh09GSR6vQAAAAAAAAAAAAAAgAAAAACB8To+CW0XPX1GfL0AAAAAAAAAAAAAAIAAAAAAQxo5PrGSDj0XwXS9AAAAgAAAAAAAAAAAAAAAAEMaOT6xkg49F8F0vQAAAIAAAAAAAAAAAAAAAADL+jo+sZIOPR7Edr0AAACAAAAAAAAAAAAAAAAAHyA8PhWwCT3E8mC9WRTIPj77Mr5OW2e/AAAAAGY0Oj5cZQg9TAVkvVkUyD4++zK+TltnvwAAAACOSDo+MR41PbCIbL1ZFMg+Pvsyvk5bZ78AAAAAx0Q8PlRGLj2J4Ve9AAAAAAAAAAAAAAAAAAAAAM+wOT5URi49ieFXvQAAAAAAAAAAAAAAAAAAAADPsDk+VEYuPYnhV70AAAAAAAAAAAAAAAAAAAAAurU8Pumt5jzQen294dsUv8GoQD4voEo/AAAAAK+RPz6LMuc8piN1veHbFL/BqEA+L6BKPwAAAABImD8+h6TnPM8ddb3h2xS/wahAPi+gSj8AAAAAs1o+PiQF0zw28V29AAAAAAAAAAAAAAAAAAAAALNaPj4kBdM8NvFdvQAAAAAAAAAAAAAAAAAAAACzWj4+JAXTPDbxXb0AAAAAAAAAAAAAAAAAAAAAVsAiPohi2jxtpXm9AAAAgAAAAAAAAAAAAAAAAFbAIj6IYto8baV5vQAAAIAAAAAAAAAAAAAAAABWwCI+62P0PPzefb0AAACAAAAAAAAAAAAAAAAAPzVTPohi2jxupXm9AAAAgAAAAAAAAAAAAAAAAD81Uz6IYto8bqV5vQAAAIAAAAAAAAAAAAAAAAA/NVM+62P0PP7efb0AAACAAAAAAAAAAAAAAAAAI1g9PibisD19LXK9AAAAAAAAAAAAAAAAAAAAAPCyPD6HGq49oy9wvQAAAAAAAAAAAAAAAAAAAADwsjw+hxquPaMvcL0AAAAAAAAAAAAAAAAAAAAAPho9PtOFtT0Buly9Q7pYv+drBj8ELLI9AAAAADMlPT7tobU9qmJcvUO6WL/nawY/BCyyPQAAAACknz0+dcS3PQOKY71Duli/52sGPwQssj0AAAAAmjzePV4b9T28xXK9ZHdavwIfBT9rbBU9AAAAAA7l3D24q/I9gRtsvWR3Wr8CHwU/a2wVPQAAAADOMd09u9zyPQKKY71kd1q/Ah8FP2tsFT0AAAAAbaTcPS0W/D1+6mK9oF8BPzoxJD8SyBM/AAAAAHoA3T177Ps9Ay9jvaBfAT86MSQ/EsgTPwAAAAD9bt09gNr8PWcBZr2gXwE/OjEkPxLIEz8AAAAAZF84vheTID7Cz3m9AAAAAAAAAAAAAAAAAAAAAGRfOL4XkyA+ws95vQAAAAAAAAAAAAAAAAAAAADQdja+F5MgPnctcr0AAAAAAAAAAAAAAAAAAAAAQ8g0viuAHT4w1HW9WYSdviO4cr/ZCaQ9AAAAAEfaM74ogB0+O4xnvVmEnb4juHK/2QmkPQAAAABvFDW+rC4ePtMfWr1ZhJ2+I7hyv9kJpD0AAAAApao+vrSQqz2GpYC9AAAAgAAAAAAAAAAAAAAAAKWqPr60kKs9hqWAvQAAAIAAAAAAAAAAAAAAAADL+jq+tJCrPVWfgr0AAACAAAAAAAAAAAAAAAAA2ZM/vrSQqz0kXnK9AAAAgAAAAAAAAAAAAAAAANmTP760kKs9JF5yvQAAAIAAAAAAAAAAAAAAAACmHzy+tJCrPfoSfb0AAACAAAAAAAAAAAAAAAAA7GE4vghtFz3NC1a9Rg0iNgAAgL/xzJm2AAAAAIHxOr4GbRc9PjlTvUYNIjYAAIC/8cyZtgAAAACTgz2+BW0XPaPmVb1GDSI2AACAv/HMmbYAAAAAuzk3vrGSDj3Yv2e9AAAAAAAAAAAAAAAAAAAAAH26N76xkg49uD1gvQAAAAAAAAAAAAAAAAAAAAB9uje+sZIOPbg9YL0AAAAAAAAAAAAAAAAAAAAAs1o+vlRGLj2CjnG9AAAAgAAAAAAAAAAAAAAAALNaPr5URi49go5xvQAAAIAAAAAAAAAAAAAAAADHRDy+VEYuPS6ed70AAACAAAAAAAAAAAAAAAAAurU8vvRxJD3Ken29R6e0OfmNf7/sg3G9AAAAAK8vOb70cSQ9wmV9vUentDn5jX+/7INxvQAAAAAVYDa+ovYjPQ4tdb1Hp7Q5+Y1/v+yDcb0AAAAASJg/voik5zzoYVq9AAAAAAAAAAAAAAAAAAAAAKQmP74kBdM82L9nvQAAAAAAAAAAAAAAAAAAAACkJj++JAXTPNi/Z70AAAAAAAAAAAAAAAAAAAAAs1o+viQF0zwv8V29maQzPx4fer7FVCs/AAAAABdVPL5uVcU8b+tovZmkMz8eH3q+xVQrPwAAAAAjfjq+d43HPPs6cL2ZpDM/Hh96vsVUKz8AAAAAPzVTvuc7Dz3Y6WC9AAAAAAAAAAAAAACAAAAAAD81U77nOw892OlgvQAAAAAAAAAAAAAAgAAAAAA/NVO+qDIHPUnaVb0AAAAAAAAAAAAAAIAAAAAAVsAivuc7Dz3Z6WC9AAAAAAAAAAAAAACAAAAAAFbAIr7nOw892elgvQAAAAAAAAAAAAAAgAAAAABWwCK+qDIHPUvaVb0AAAAAAAAAAAAAAIAAAAAAI1g9vibisD13LXK9AAAAAAAAAAAAAAAAAAAAAFb9Pb7GqbM9nS9wvQAAAAAAAAAAAAAAAAAAAABW/T2+xqmzPZ0vcL0AAAAAAAAAAAAAAAAAAAAAi47gvYp9+D0Bf1m9AAAAAAAAAAAAAAAAAAAAAECo4L2MnvM9e9FbvQAAAAAAAAAAAAAAAAAAAABAqOC9jJ7zPXvRW70AAAAAAAAAAAAAAAAAAAAAa3bcvWv39j0WUF+9AAAAAAAAAAAAAACAAAAAAGt23L1r9/Y9FlBfvQAAAAAAAAAAAAAAgAAAAAA5/9q9IbX2PUDHaL0AAAAAAAAAAAAAAIAAAAAAxH/tuvkaCT6uWTk/WXtSNgAAgL8VLJy2AAAAABAOoDr6Ggk+9TI5P1l7UjYAAIC/FSyctgAAAAC0gu06+RoJPrv5OT9Ze1I2AACAvxUsnLYAAAAA0xkDO8nFBz7GjDo/AAAAAAAAAAAAAAAAAAAAAFt3bDPJxQc+5q86PwAAAAAAAAAAAAAAAAAAAABbd2wzycUHPuavOj8AAAAAAAAAAAAAAAAAAAAAQ1aUu5vkBT7+VDo/AAAAAAAAAAAAAAAAAAAAAAGQoDsCrQM+G2M6PwAAAAAAAAAAAAAAAAAAAAABkKA7Aq0DPhtjOj8AAAAAAAAAAAAAAAAAAAAAAZCgOxMslD0bYzo/AAAAAAAAAIAAAAAAAAAAAAGQoDsTLJQ9G2M6PwAAAAAAAACAAAAAAAAAAAA2Zzk7EyyUPdPqOj8AAAAAAAAAgAAAAAAAAAAAMTRnu9a81zw3JDk/AAAAAAAAAAAAAAAAAAAAAO97BbvWvNc8f8I4PwAAAAAAAAAAAAAAAAAAAADvewW71rzXPH/COD8AAAAAAAAAAAAAAAAAAAAA3sW8uuAjwDw3Bjk/AAAAgAAAAAAAAAAAAAAAAN7FvLrgI8A8NwY5PwAAAIAAAAAAAAAAAAAAAAAgPGoz4CPAPO3sOD8AAACAAAAAAAAAAAAAAAAACVZwOu5utjwEtDk/1Fs/v+tGvr2EYSi/AAAAAF/5jrlW2bc8Ags6P9RbP7/rRr69hGEovwAAAAAnhTm68rX8PJfdOT/UWz+/60a+vYRhKL8AAAAAsqSBOgX18TwycTo/AAAAAAAAAAAAAAAAAAAAAAGhgboF9fE8MnE6PwAAAAAAAAAAAAAAAAAAAAABoYG6BfXxPDJxOj8AAAAAAAAAAAAAAAAAAAAAGgWuOkdYlTyHmDg/iuEUP5GZP74YrEq/AAAAADUUaDujGZY8qgE5P4rhFD+RmT++GKxKvwAAAACEymY7J8GVPF8BOT+K4RQ/kZk/vhisSr8AAAAAEbMpO/nlhTz/JDo/AAAAAAAAAAAAAAAAAAAAABGzKTv55YU8/yQ6PwAAAAAAAAAAAAAAAAAAAAARsyk7+eWFPP8kOj8AAAAAAAAAAAAAAAAAAAAAEtF8vFmvizy4yDg/AAAAAAAAAAAAAAAAAAAAABLRfLwoHqA8m5M4PwAAAAAAAAAAAAAAAAAAAAAS0Xy8KB6gPJuTOD8AAAAAAAAAAAAAAAAAAAAAiNF8PCgeoDybkzg/AAAAAAAAAAAAAAAAAAAAAIjRfDz2jLQ8uMg4PwAAAAAAAAAAAAAAAAAAAACI0Xw89oy0PLjIOD8AAAAAAAAAAAAAAAAAAAAAVcjLPbmPdD4XaSM/kgl6v0eQW77DmQS8AACAP+BmzT2o0HA+08sjP5IJer9HkFu+w5kEvAAAgD99Bc49aUNvPje6JD+SCXq/R5BbvsOZBLwAAIA/I/XNPXNDbz7sxyU/6CV6v9aQWb562e+7AACAPxE6zT3E0HA+UrYmP+gler/WkFm+etnvuwAAgD8Qk8s93I90PhMZJz/oJXq/1pBZvnrZ77sAAIA/SGDGPev6ez4VGSc/zwJwvyESsr7pEe27AACAP8yewz0Cun8+V7YmP88CcL8hErK+6RHtuwAAgD/KhsI9oaOAPvHHJT/PAnC/IRKyvukR7bsAAIA/4pjCPZ+jgD48uiQ/tRNwv96ysb4vtAy8AACAP2XQwz34uX8+1ssjP7UTcL/esrG+L7QMvAAAgD+OncY91/p7PhlpIz+1E3C/3rKxvi+0DLwAAIA/yEPJPVBFeD4XQSU/MyJ5v3mIBL7MwUI+AACAPweGxz1o9nM+WmgjPzMieb95iAS+zMFCPgAAgD88Gsk9D0twPhTLIz8zInm/eYgEvszBQj4AAIA/CbXJPfHFbj5cuSQ/jC16v2sDWb7uZPK7AACAP8KkyT3WxW4+78YlP4wter9rA1m+7mTyuwAAgD+j7cg9x0pwPjO1Jj+MLXq/awNZvu5k8rsAAIA/DVHHPRH2cz7gFyc/wGNxv7pxqb4xHRc9AACAP983wj1qOXs+2xcnP8Bjcb+6cam+MR0XPQAAgD+khb89s+R+Pii1Jj/AY3G/unGpvjEdFz0AAIA/XnS+Pek0gD7jxiU/AgFwvxIasr7+uQC8AACAP2mGvj3uNIA+UbkkPwIBcL8SGrK+/rkAvAAAgD8bt789y+R+PgzLIz8CAXC/Ehqyvv65ALwAAIA/63TCPZs5ez5ZaCM/fTu4Opi5wj4qw2y/AACAP4Cdxr3X+ns+GWkjP307uDqYucI+KsNsvwAAgD9S0MO9+Ll/PtbLIz99O7g6mLnCPirDbL8AAIA/1JjCvZ+jgD48uiQ/xeNvP2e3sr7TfAC8AACAP8OGwr2ho4A+8cclP8Xjbz9nt7K+03wAvAAAgD+/nsO9Arp/Ple2Jj/F428/Z7eyvtN8ALwAAIA/O2DGvev6ez4VGSc/Ro9nPyFGor67DZI+AACAPwqTy73cj3Q+ExknP0aPZz8hRqK+uw2SPgAAgD8EOs29xNBwPlK2Jj9Gj2c/IUaivrsNkj4AAIA/FvXNvXNDbz7sxyU/2CB6PzPtWb4cafK7AACAP3AFzr1pQ28+N7okP9ggej8z7Vm+HGnyuwAAgD/TZs29qNBwPtPLIz/YIHo/M+1Zvhxp8rsAAIA/T8jLvbmPdD4XaSM/WIFPv8wjET95Tha+AACAP7RDyb1SRXg+F0ElP1iBT7/MIxE/eU4WvgAAgD/edMK9mzl7PlloIz9YgU+/zCMRP3lOFr4AAIA/B7e/vcvkfj4MyyM/FwFwP6kZsr4kiwC8AACAP1yGvr3uNIA+UbkkPxcBcD+pGbK+JIsAvAAAgD9XdL696TSAPuPGJT8XAXA/qRmyviSLALwAAIA/l4W/vbPkfj4otSY/p2NxP4Nyqb7dDBc9AACAP9E3wr1qOXs+2xcnP6djcT+Dcqm+3QwXPQAAgD8HUce9EfZzPuAXJz+nY3E/g3Kpvt0MFz0AAIA/lu3IvcdKcD4ztSY/jC16P2sDWb7uZPK7AACAP7Skyb3WxW4+78YlP4wtej9rA1m+7mTyuwAAgD/8tMm98cVuPly5JD+MLXo/awNZvu5k8rsAAIA/LxrJvQ9LcD4UyyM/A2J6v9DyGD47uBS+AACAPwCGx71o9nM+WmgjPwNier/Q8hg+O7gUvgAAgD82oLE9hnl0PmbxGb8DYnq/0PIYPju4FL4AAIA/L3ayPf+4cD7Rjhm/XUB+v6SBlb23abo9AACAP1lfsz2FK28+f6AYv11Afr+kgZW9t2m6PQAAgD8BJbQ9DyxvPsySF79dQH6/pIGVvbdpuj0AAIA/Ipm0PX26cD5ZpBa/N6Fkv5g9S74Jt84+AACAP7hTtD1le3Q+ckEWvzehZL+YPUu+CbfOPgAAgD+NB7E9vOh7PjBBFr83oWS/mD1Lvgm3zj4AAIA/KBmvPRipfz7Joxa/K4d4vxdQaL6gWZ89AACAP5PGrT1Km4A+HZIXvyuHeL8XUGi+oFmfPQAAgD/UGa09GZuAPs6fGL8rh3i/F1BovqBZnz0AAIA/mC+tPQqofz4/jhm/AAp5v/K1Xr74E6M9AACAP2Wcrj1h53s+IfEZvwAKeb/ytV6++BOjPQAAgD8+erE9LDF4PksZGL8ACnm/8rVevvgToz0AAIA/LkKtPestdD7q5Bm/6kJ+v56tk72//7o9AACAP+8Srj02hnA+0IEZv+pCfr+erZO9v/+6PQAAgD+6+q49rAFvPluTGL/qQn6/nq2Tvb//uj0AAIA/mMCvPVIAbz7ChRe/Dkh+vyAXk73ntbk9AACAP6w2sD16gnA+n5cWvw5Ifr8gF5O957W5PQAAgD9K9689PSl0PlE1Fr8OSH6/IBeTvee1uT0AAIA/x7ysPd9mez71NRa/dhV5v0ruXL56Tag9AACAP7Daqj38Dn8+BZkWv3YVeb9K7ly+ek2oPQAAgD9Djak9wUmAPnmHF792FXm/Su5cvnpNqD0AAIA/yN+oPTtKgD4TlRi/ig15v/Q6Xr4dWKQ9AACAPzfvqD2iEX8+OoMZv4oNeb/0Ol6+HVikPQAAgD+hT6o9RGp7PpXlGb+KDXm/9Dpevh1YpD0AAIA/apyuvWHnez4h8Rm/+wh5Pz6/Xr7jRKM9AACAP50vrb0KqH8+P44Zv/sIeT8+v16+40SjPQAAgD/gGa29GZuAPs6fGL/7CHk/Pr9evuNEoz0AAIA/pcatvUqbgD4dkhe/Xwh5Pza/Xb7w2ag9AACAPzMZr70YqX8+yaMWv18IeT82v12+8NmoPQAAgD+fB7G9vOh7PjBBFr9fCHk/Nr9dvvDZqD0AAIA/xFO0vWV7dD5yQRa/YT1+P5Bjlr0wuLo9AACAPzqZtL19unA+WaQWv2E9fj+QY5a9MLi6PQAAgD8GJbS9DyxvPsySF79hPX4/kGOWvTC4uj0AAIA/ZF+zvYUrbz5/oBi/qT9+P3ohlr1iJro9AACAPzp2sr3/uHA+0Y4Zv6k/fj96IZa9Yia6PQAAgD9BoLG9hnl0PmbxGb+pP34/eiGWvWImuj0AAIA/PXqxvS0xeD5LGRi/B4RmPz1dmr5WhKA+AACAP6ZPqr1Eans+leUZvweEZj89XZq+VoSgPgAAgD8876i9ohF/PjqDGb8HhGY/PV2avlaEoD4AAIA/1N+ovTtKgD4TlRi/Tp14P0DJZr4wl589AACAP1WNqb3BSYA+eYcXv06deD9AyWa+MJefPQAAgD+82qq9/A5/PgWZFr9OnXg/QMlmvjCXnz0AAIA/2bysvd9mez71NRa/iflkP/eeS75lFs0+AACAP1X3r709KXQ+UTUWv4n5ZD/3nku+ZRbNPgAAgD/FNrC9eoJwPp+XFr+J+WQ/955LvmUWzT4AAIA/ncCvvVIAbz7ChRe/RkF+P/Yilb0RZro9AACAP8X6rr2sAW8+W5MYv0ZBfj/2IpW9EWa6PQAAgD/6Eq69NoZwPtCBGb9GQX4/9iKVvRFmuj0AAIA/tObOPU+sbT433xM/8vR5v/f/XL79iw+8AACAP70E0T1bzWg+kV8UP/L0eb/3/1y+/YsPvAAAgD/V0tE92MhmPm+VFT/y9Hm/9/9cvv2LD7wAAIA/XnHNPY15Zj5vlRU/qAB7vxBYSb4AAAAAAACAP15xzT2NeWY+G6MWP6gAe78QWEm+AAAAAAAAgD+Rpsw9MHNoPvnYFz+oAHu/EFhJvgAAAAAAAIA/rubOPU+sbT7uwgw/cdhvvzXVfb5cc3w+AACAP5C7yD2CVHk+7sIMP3HYb7811X2+XHN8PgAAgD+JGcU9dTN+PpRCDD9x2G+/NdV9vlxzfD4AAIA/qfnAPYlmfT6UQgw/BOVvv0O8sr4AAAAAAACAP9eAvz1MYH8+tgwLPwTlb79DvLK+AAAAAAAAgD/XgL89TGB/Pgv/CT8E5W+/Q7yyvgAAAAAAAIA/jhnFPXUzfj6SZfo+Q8Rwv3FRrb5N7fK8AACAP4+7yD2CVHk+3mT5PkPEcL9xUa2+Te3yvAAAgD8jXcw9YIBzPvve/T5DxHC/cVGtvk3t8rwAAIA/rObOPU+sbT4UOOI+9PR5v8//XL6VhQ+8AACAP7UE0T1bzWg+yDjjPvT0eb/P/1y+lYUPvAAAgD/O0tE92MhmPoSk5T709Hm/z/9cvpWFD7wAAIA/VnHNPY15Zj6EpOU+qAB7vxBYSb4AAAAAAACAP1ZxzT2NeWY+3L/nPqgAe78QWEm+AAAAAAAAgD+Jpsw9MHNoPpcr6j6oAHu/EFhJvgAAAAAAAIA/s+bOPU+sbT6C/9M+U9lvv0LYfb7YYnw+AACAP4i7yD2CVHk+gv/TPlPZb79C2H2+2GJ8PgAAgD+OGcU9dTN+Ps7+0j5T2W+/Qth9vthifD4AAIA/rvnAPYlmfT7O/tI+F+Vvv9q7sr4Gazs3AACAP9WAvz1MYH8+EpPQPhflb7/au7K+Bms7NwAAgD/PgL89TGB/Prp3zj4X5W+/2ruyvgZrOzcAAIA/jRnFPXUzfj4237Q+Q8Rwv29Rrb6U7fK8AACAP427yD2CVHk+gt6zPkPEcL9vUa2+lO3yvAAAgD8hXcw9YIBzPp1YuD5DxHC/b1GtvpTt8rwAAIA/subOPU+sbT64sZw+3vR5vzcBXb47vw+8AACAP7sE0T1bzWg+bLKdPt70eb83AV2+O78PvAAAgD/M0tE92MhmPigeoD7e9Hm/NwFdvju/D7wAAIA/VXHNPY15Zj4oHqA+qAB7vxBYSb4AAAAAAACAP1VxzT2NeWY+gDmiPqgAe78QWEm+AAAAAAAAgD+Hpsw9MHNoPjulpD6oAHu/EFhJvgAAAAAAAIA/qubOPU+sbT4meY4+zNhvv5XVfb6VbXw+AACAP427yD2CVHk+JnmOPszYb7+V1X2+lW18PgAAgD+MGcU9dTN+PnJ4jT7M2G+/ldV9vpVtfD4AAIA/rfnAPYlmfT5yeI0+aONvv+XEsr7+aTu3AACAP82Avz1MYH8+tgyLPmjjb7/lxLK+/mk7twAAgD/UgL89TGB/Pl/xiD5o42+/5cSyvv5pO7cAAIA/kxnFPXUzfj61sV4+bsRwv45Qrb4r4/K8AACAP427yD2CVHk+TbBcPm7EcL+OUK2+K+PyvAAAgD8gXcw9YIBzPoWkZT5uxHC/jlCtvivj8rwAAIA/sObOPU+sbT66Vi4+HvV5v+v8XL6udg+8AACAP7IE0T1bzWg+IVgwPh71eb/r/Fy+rnYPvAAAgD/K0tE92MhmPpgvNT4e9Xm/6/xcvq52D7wAAIA/U3HNPY15Zj6YLzU++QB7v8dRSb4AAAAAAACAP1NxzT2NeWY+SGY5PvkAe7/HUUm+AAAAAAAAgD+Mpsw9MHNoPsA9Pj75AHu/x1FJvgAAAAAAAIA/sObOPU+sbT6U5RE+N9lvvxXXfb60ZXw+AACAP4y7yD2CVHk+lOURPjfZb78V132+tGV8PgAAgD+SGcU9dTN+Pi3kDz432W+/Fdd9vrRlfD4AAIA/svnAPYlmfT4t5A8+fONvv33Esr4AAAAAAACAP8yAvz1MYH8+tgwLPnzjb799xLK+AAAAAAAAgD/MgL89TGB/PgbWBj5842+/fcSyvgAAAAAAAIA/kRnFPXUzfj76Sac9bsRwv49Qrb5j4/K8AACAP4u7yD2CVHk+K0ejPW7EcL+PUK2+Y+PyvAAAgD8fXcw9YIBzPpgvtT1uxHC/j1CtvmPj8rwAAIA/qObOPU+sbT4NKA099fR5v8v/XL5thQ+8AACAP7EE0T1bzWg+qS0VPfX0eb/L/1y+bYUPvAAAgD/K0tE92MhmPoaLKD319Hm/y/9cvm2FD7wAAIA/UnHNPY15Zj6Hiyg9+QB7v8dRSb4AAAAAAACAP1JxzT2NeWY+R2Y5PfkAe7/HUUm+AAAAAAAAgD+Mpsw9MHNoPiTETD35AHu/x1FJvgAAAAAAAIA/tebOPU+sbT66G9s78dhvv9rXfb4ZaXw+AACAP4q7yD2CVHk+uhvbO/HYb7/a132+GWl8PgAAgD+KGcU9dTN+PtTumjvx2G+/2td9vhlpfD4AAIA/qvnAPYlmfT7T7po7geRvvwG/sr4AAAAAAACAP9GAvz1MYH8+BJHysYHkb78Bv7K+AAAAAAAAgD/RgL89TGB/PhXWhruB5G+/Ab+yvgAAAAAAAIA/iRnFPXUzfj7onl29O8Rwv6VRrb7s5PK8AACAP4m7yD2CVHk+haRlvTvEcL+lUa2+7OTyvAAAgD8kXcw9YIBzPqvTQb07xHC/pVGtvuzk8rwAAIA/rubOPU+sbT5nhc+93/R5vzUBXb4gvw+8AACAP7YE0T1bzWg+mILLvd/0eb81AV2+IL8PvAAAgD/I0tE92MhmPqvTwb3f9Hm/NQFdviC/D7wAAIA/UXHNPY15Zj6r08G9+QB7v8dRSb4AAAAAAACAP1FxzT2NeWY+Sma5vfkAe7/HUUm+AAAAAAAAgD+Kpsw9MHNoPly3r735AHu/x1FJvgAAAAAAAIA/rebOPU+sbT7YMwS+3Nhvv7XWfb57a3w+AACAP4i7yD2CVHk+2DMEvtzYb7+11n2+e2t8PgAAgD+IGcU9dTN+PkA1Br7c2G+/tdZ9vntrfD4AAIA/qfnAPYlmfT5ANQa+geRvvwG/sr4AAAAAAACAP8+Avz1MYH8+twwLvoHkb78Bv7K+AAAAAAAAgD/PgL89TGB/PmdDD76B5G+/Ab+yvgAAAAAAAIA/iBnFPXUzfj5xdEK+O8Rwv6VRrb7o5PK8AACAP4i7yD2CVHk+2HVEvjvEcL+lUa2+6OTyvAAAgD8jXcw9YIBzPqKBO747xHC/pVGtvujk8rwAAIA/rObOPU+sbT5qz3K+HvV5v+78XL7Ydg+8AACAP64E0T1bzWg+As5wvh71eb/u/Fy+2HYPvAAAgD/G0tE92MhmPoz2a74e9Xm/7vxcvth2D7wAAIA/T3HNPY15Zj6M9mu++QB7v8dRSb4AAAAAAACAP09xzT2NeWY+3L9nvvkAe7/HUUm+AAAAAAAAgD+Ipsw9MHNoPmXoYr75AHu/x1FJvgAAAAAAAIA/pebOPU+sbT5IoIe+TthvvwHUfb6Zdnw+AACAP467yD2CVHk+SKCHvk7Yb78B1H2+mXZ8PgAAgD+HGcU9dTN+PvugiL5O2G+/AdR9vpl2fD4AAIA/qPnAPYlmfT7+oIi+7uNvvxbCsr4AAAAAAACAP8eAvz1MYH8+vAyLvu7jb78WwrK+AAAAAAAAgD/HgL89TGB/PhYojb7u42+/FsKyvgAAAAAAAIA/tSTFPWQzfj5fwKa+uq1wv5murb7uXQS9AACAP+DLyD1oVHk+F8GnvrqtcL+Zrq2+7l0EvQAAgD8QY8w9SoBzPgpHo766rXC/ma6tvu5dBL0AAIA/4QbPPfKqbT657r6+uAd5vzJvar7whhO9AACAP84r0T34y2g+Au69vrgHeb8yb2q+8IYTvQAAgD8Ow9E9mcdmPiWCu764B3m/Mm9qvvCGE70AAIA/amDNPah8Zj5VgLu+hd58v413H75Sefk7AACAPytxzT05fGY+YWW5voXefL+Ndx++Unn5OwAAgD8E5cw9PXVoPjP6tr6F3ny/jXcfvlJ5+TsAAIA/ukrOPaapbT5zKM2+7xdsvwr5Z75caKA+AACAP9mQyD2BUnk+FCjNvu8XbL8K+We+XGigPgAAgD9jz8Q9ljF+PsUozr7vF2y/CvlnvlxooD4AAIA/t6rAPTdrfT7EI86+HlBvv46Ztb6FiZE8AACAP8b7vj0OZX8+NY/Qvh5Qb7+OmbW+hYmRPAAAgD+E0r49b2V/Pimq0r4eUG+/jpm1voWJkTwAAIA/R+rAPRgufj59Suy+yD9zvzBrn74EOGC8AACAP8YqxD1tTnk+gEvtvsg/c78wa5++BDhgvAAAgD+Ousc9cXpzPm3R6L7IP3O/MGufvgQ4YLwAAIA/+EHDPfWfbT4zPQK/4Jx+v8o1lb3J4pc9AACAPz5FxD1RwGg+/LwBv+Ccfr/KNZW9yeKXPQAAgD++ScU99rtmPh2HAL/gnH6/yjWVvcnilz0AAIA/keLAPb+ZZj4yfAC/7Z1+v5F3lL1sLJg9AACAP9KDwT2RmGY+W93+vu2dfr+Rd5S9bCyYPQAAgD9u88E94o9oPlNy/L7tnX6/kXeUvWwsmD0AAIA/hLvIvYJUeT5UWRg/Wvp1P8sogr7BouE9AACAP5zmzr1PrG0+VFkYP1r6dT/LKIK+waLhPQAAgD+yBNG9W81oPvnYFz9a+nU/yyiCvsGi4T0AAIA/habMvTBzaD752Bc/VQF7P49KSb4XGUS3AACAP0xxzb2NeWY+G6MWP1UBez+PSkm+FxlEtwAAgD9Scc29jXlmPm+VFT9VAXs/j0pJvhcZRLcAAIA/qwTRvVvNaD4uyQg/9yd6PwGMWb4NSSi5AACAP6Lmzr1PrG0+00gIP/cnej8BjFm+DUkouQAAgD8YXcy9YYBzPuGFCj/3J3o/AYxZvg1JKLkAAIA/jLvIvYJUeT7eZPk+tN1vP37jsr7vuLy4AACAP34Zxb11M34+kmX6PrTdbz9+47K+77i8uAAAgD8UmMO99huAPk3R/D603W8/fuOyvu+4vLgAAIA/xoC/vUxgfz5N0fw+/uNvP7/Bsr4AAAAAAACAP8aAv71MYH8+pez+Pv7jbz+/wbK+AAAAAAAAgD+l+cC9iWZ9PjCsAD/+428/v8GyvgAAAAAAAIA/hbvIvYJUeT5LLOs+B/p1Pyopgr7MteE9AACAP6Pmzr1PrG0+SyzrPgf6dT8qKYK+zLXhPQAAgD+yBNG9W81oPpcr6j4H+nU/KimCvsy14T0AAIA/hqbMvTBzaD6XK+o++QB7P8dRSb4AAAAAAACAP01xzb2NeWY+3L/nPvkAez/HUUm+AAAAAAAAgD9Ncc29jXlmPoSk5T75AHs/x1FJvgAAAAAAAIA/swTRvVvNaD7/C8w+8Sd6P3OMWb5t0Sy5AACAP6rmzr1PrG0+SwvLPvEnej9zjFm+bdEsuQAAgD8aXcy9YYBzPmeFzz7xJ3o/c4xZvm3RLLkAAIA/h7vIvYJUeT6C3rM+NN5vP8/gsr7DG9G4AACAP4YZxb11M34+Nt+0PjTebz/P4LK+wxvRuAAAgD8dmMO99huAPvFKtz403m8/z+CyvsMb0bgAAIA/zoC/vUxgfz7xSrc+kuRvP6m+sr4AAAAAAACAP86Av71MYH8+SWa5PpLkbz+pvrK+AAAAAAAAgD+m+cC9iWZ9PgTSuz6S5G8/qb6yvgAAAAAAAIA/h7vIvYJUeT7vpaU+uvl1P4wpgr5ox+E9AACAP6vmzr1PrG0+76WlPrr5dT+MKYK+aMfhPQAAgD+0BNG9W81oPjulpD66+XU/jCmCvmjH4T0AAIA/h6bMvTBzaD47paQ++QB7P8dRSb4AAAAAAACAP05xzb2NeWY+gDmiPvkAez/HUUm+AAAAAAAAgD9Occ29jXlmPigeoD75AHs/x1FJvgAAAAAAAIA/tQTRvVvNaD6khYY+3Cd6P/6NWb5g3CK5AACAP6Xmzr1PrG0+8ISFPtwnej/+jVm+YNwiuQAAgD8cXcy9YYBzPgv/iT7cJ3o//o1ZvmDcIrkAAIA/iLvIvYJUeT5NsFw+j95vP+nesr746PO4AACAP44Zxb11M34+tbFePo/ebz/p3rK++OjzuAAAgD8emMO99huAPiyJYz6P3m8/6d6yvvjo87gAAIA/z4C/vUxgfz4siWM+geRvPwG/sr4AAAAAAACAP8+Av71MYH8+3L9nPoHkbz8Bv7K+AAAAAAAAgD+o+cC9iWZ9PlKXbD6B5G8/Ab+yvgAAAAAAAIA/iLvIvYJUeT4pP0A+jvl1P3Upgr471OE9AACAP63mzr1PrG0+KT9APo75dT91KYK+O9ThPQAAgD+vBNG9W81oPsE9Pj6O+XU/dSmCvjvU4T0AAIA/g6bMvTBzaD7BPT4+BQF7P9dQSb7YGES3AACAP1Bxzb2NeWY+SmY5PgUBez/XUEm+2BhEtwAAgD9Wcc29jXlmPpovNT4FAXs/11BJvtgYRLcAAIA/tgTRvVvNaD6Q/gE+9yd6PwGMWb4QSSi5AACAP63mzr1PrG0+Ufr/Pfcnej8BjFm+EEkouQAAgD8jXcy9YYBzPmDxCD73J3o/AYxZvhBJKLkAAIA/ibvIvYJUeT4sR6M9j95vP+nesr7L6PO4AACAP48Zxb11M34++0mnPY/ebz/p3rK+y+jzuAAAgD8fmMO99huAPun4sD2P3m8/6d6yvsvo87gAAIA/0IC/vUxgfz7p+LA9aONvP+XEsr6jaTu3AACAP8qAv71MYH8+Sma5PWjjbz/lxLK+o2k7twAAgD+p+cC9iWZ9PjgVwz1o428/5cSyvqNpO7cAAIA/ibvIvYJUeT7EyVQ9QPl1P9Ypgr4F5uE9AACAP7Tmzr1PrG0+xMlUPUD5dT/WKYK+BebhPQAAgD+wBNG9W81oPijETD1A+XU/1imCvgXm4T0AAIA/g6bMvTBzaD4nxEw9qAB7PxBYSb4AAAAAAACAP1Fxzb2NeWY+S2Y5PagAez8QWEm+AAAAAAAAgD9Rcc29jXlmPoqLKD2oAHs/EFhJvgAAAAAAAIA/twTRvVvNaD5s4hC88Sd6P3OMWb6e0Sy5AACAP67mzr1PrG0+3/gwvPEnej9zjFm+ntEsuQAAgD8eXcy9YYBzPubVBrvxJ3o/c4xZvp7RLLkAAIA/i7vIvYJUeT6CpGW9j95vP+nesr7L6PO4AACAP5EZxb11M34+5J5dvY/ebz/p3rK+y+jzuAAAgD8hmMO99huAPglBSr2P3m8/6d6yvsvo87gAAIA/0oC/vUxgfz4JQUq9kuRvP6m+sr4AAAAAAACAP9KAv71MYH8+R2Y5vZLkbz+pvrK+AAAAAAAAgD+q+cC9iWZ9PmsIJr2S5G8/qb6yvgAAAAAAAIA/i7vIvYJUeT6MtKu9ufl1P4spgr7Ex+E9AACAP6/mzr1PrG0+jLSrvbn5dT+LKYK+xMfhPQAAgD+4BNG9W81oPlq3r725+XU/iymCvsTH4T0AAIA/jKbMvTBzaD5at6+9+QB7P8dRSb4AAAAAAACAP1Jxzb2NeWY+SGa5vfkAez/HUUm+AAAAAAAAgD9Scc29jXlmPqnTwb35AHs/x1FJvgAAAAAAAIA/sgTRvVvNaD7dGhS+DSh6P3WKWb5EPjK5AACAP7Dmzr1PrG0+RBwWvg0oej91ilm+RD4yuQAAgD8gXcy9YYBzPg0oDb4NKHo/dYpZvkQ+MrkAAIA/hbvIvYJUeT7XdUS+j95vP+nesr6y6PO4AACAP4sZxb11M34+b3RCvo/ebz/p3rK+sujzuAAAgD8bmMO99huAPvicPb6P3m8/6d6yvrLo87gAAIA/zIC/vUxgfz74nD2+leRvP5i+sr6gajs3AACAP9OAv71MYH8+SGY5vpXkbz+YvrK+oGo7NwAAgD+y+cC9iWZ9PtGONL6V5G8/mL6yvqBqOzcAAIA/jbvIvYJUeT795mC+uvl1P4wpgr5ox+E9AACAP7Hmzr1PrG0+/eZgvrr5dT+MKYK+aMfhPQAAgD+6BNG9W81oPmXoYr66+XU/jCmCvmjH4T0AAIA/jabMvTBzaD5l6GK+VQF7P49KSb4XGUS3AACAP1Rxzb2NeWY+3L9nvlUBez+PSkm+FxlEtwAAgD9bcc29jXlmPoz2a75VAXs/j0pJvhcZRLcAAIA/tATRvVrNaD7Ik4++9yd6PwOMWb4sXCi5AACAP6vmzr1OrG0+e5SQvvcnej8DjFm+LFwouQAAgD8gXcy9YYBzPmEajL73J3o/A4xZvixcKLkAAIA/7cvIvWhUeT4Xwae+sLNvPzjEs756qlm2AACAP7wkxb1kM34+X8CmvrCzbz84xLO+eqpZtgAAgD9jocO98BuAPqpUpL6ws28/OMSzvnqqWbYAAIA/74m/vW1gfz5LVaS+xt1vPwzjsr7RKRu6AACAP5WIv71qYH8+4zmivsbdbz8M47K+0SkbugAAgD8zAMG9p2Z9PhLOn77G3W8/DOOyvtEpG7oAAIA/SBLJvQlUeT7D+bW+2qV2P0MxgL6Au8I9AACAP1Uhz72iq20+5/m1vtqldj9DMYC+gLvCPQAAgD8gRNG9icxoPrL6tr7apXY/QzGAvoC7wj0AAIA/C+XMvT11aD4z+ra+Jd98P+ZnH76V/vg7AACAPytxzb05fGY+YWW5viXffD/mZx++lf74OwAAgD9zYM29qHxmPlWAu74l33w/5mcfvpX++DsAAIA/j23PvXnJaD7hHNW+ZxN7P6SuR768eQ08AACAP5N0zb2oqG0+gB3WvmcTez+krke+vHkNPAAAgD9FS8u9pH1zPsai0b5nE3s/pK5Hvrx5DTwAAIA/1irEvW1OeT6AS+2+fL5xPxG/p74+HPo8AACAP1HqwL0YLn4+fUrsvny+cT8Rv6e+Phz6PAAAgD+v07+9mRmAPoLe6b58vnE/Eb+nvj4c+jwAAIA/WrC7vSFsfz7v0um+18BvP3gasr5eSDI9AACAPy0VvL1La38+7bfnvtfAbz94GrK+XkgyPQAAgD9CAL69R3F9PlZM5b7XwG8/eBqyvl5IMj0AAIA/ftjAvfJLeT7vhPu+hdxmP9OKSb7z+sQ+AACAP6ruxb3yoW0+poX7voXcZj/Tikm+8/rEPgAAgD+1WMa94cFoPsCG/L6F3GY/04pJvvP6xD4AAIA/ePPBveKPaD5Tcvy+7Z1+P5F3lL1sLJg9AACAP9uDwb2RmGY+W93+vu2dfj+Rd5S9bCyYPQAAgD+b4sC9v5lmPjJ8AL/tnX4/kXeUvWwsmD0AAIA/z52aPIeajj7exmM/SNOlvj9yCz/nB0a/AACAPw3bsjyVg44+mm1jP0jTpb4/cgs/5wdGvwAAgD/YV8o8pUqOPuIKYz9I06W+P3ILP+cHRr8AAIA/DDoNPQ5biD41bGY/HNh0P3ihgL5aXBi+AACAPxQRDT3qb4c+RCJnPxzYdD94oYC+WlwYvgAAgD9uwgw9QXeGPpnUZz8c2HQ/eKGAvlpcGL4AAIA/vm1/PDAihT5BNWw/7gvwPph2C79q/TE/AACAP6/gTTxp64Q+cqVsP+4L8D6Ydgu/av0xPwAAgD/kCRs8DpeEPocNbT/uC/A+mHYLv2r9MT8AAIA/dLOgOxSsiz4X3Gc/X9x0v6uHfD4+rB8+AACAPzamoDv+hYw+Iy9nP1/cdL+rh3w+PqwfPgAAgD+SvZ87DFaNPnd/Zj9f3HS/q4d8Pj6sHz4AAIA/W/62PMJ0jD5OaWU/JgduvvqPOD+rICe/AACAP5G6wjyFV4w+vDdlPyYHbr76jzg/qyAnvwAAgD9mds48QzqMPigGZT8mB26++o84P6sgJ78AAIA/JPXePFSciD4N02c/GPuovphvSL/t/Qa/AACAPxe+3jwgJIg+XS1oPxj7qL6Yb0i/7f0GvwAAgD+thN48KxGIPpA8aD8Y+6i+mG9Iv+39Br8AAIA/istwPA6Shz4paGo/UeNQvuWcUr+01Qe/AACAPxijaDxSkYc+R3VqP1HjUL7lnFK/tNUHvwAAgD+oCGA8BJ6HPqt4aj9R41C+5ZxSv7TVB78AAIA/Ki9MPLEIjD6cJ2c/6uzsPnIqVD9yGaG+AACAPx8wojw/W4o+F7VnP+rs7D5yKlQ/chmhvgAAgD9INZc7xwiNPniEZT/q7Ow+cipUP3IZob4AAIA/0InbPBAkjT7QbWI/zRSzvtzYVr+5KNW+AACAP1xg8jwZ7Yw+twtiP80Us77c2Fa/uSjVvgAAgD+Wm/k8FdKMPlj2YT/NFLO+3NhWv7ko1b4AAIA/kTAIPQ6zhD5vP2g/H3bmvjx/Ob9kmQW/AACAPxP0Bz3FjIQ+RV1oPx925r48fzm/ZJkFvwAAgD+UXwc9lmyEPp57aD8fdua+PH85v2SZBb8AAIA/ZqQFPFCwgz4Xz2w/N9/VvTvwUb/rCRC/AACAP78Z6TslvYM+bdJsPzff1b078FG/6wkQvwAAgD+xN8k7geODPk/CbD8339W9O/BRv+sJEL8AAIA/tagtPZQEjD5apGA/W9T0vm9CSL8ya8y+AACAP3NEKj2fUYw+35lgP1vU9L5vQki/MmvMvgAAgD8OjCc9UKSMPv58YD9b1PS+b0JIvzJrzL4AAIA/cdlgPcbTjT6uuFg/djUZv8ogPb8qqp6+AACAP5A/Yj1hzo0+4pNYP3Y1Gb/KID2/KqqevgAAgD/m92M9yLyNPrZzWD92NRm/yiA9vyqqnr4AAIA/U+OSPVVWhD5Gglg/WZhIvyjgCr87EJu+AACAP9kHkz2zD4Q+ubVYP1mYSL8o4Aq/OxCbvgAAgD+Ny5I9p+SDPsbvWD9ZmEi/KOAKvzsQm74AAIA/2ClyPeKKhD61QGA/ZJstv1a7Hb+VG82+AACAP6dQcD1fsYQ+LFVgP2SbLb9Wux2/lRvNvgAAgD82cW49ZuGEPvdiYD9kmy2/Vrsdv5Ubzb4AAIA/7ftKPWKIiz74El4/PGpqvN/4fz88amo7AACAP+cZTj2Fios+HLBdPzxqarzf+H8/PGpqOwAAgD/aN1E9p4yLPj9NXT88amq83/h/PzxqajsAAIA/h2JsPZguiz7WVlo/sB0GP+0d8j7KXTW/AACAPwfncD1xkYo+11daP7AdBj/tHfI+yl01vwAAgD9oa3U9RfSJPtRYWj+wHQY/7R3yPspdNb8AAIA/iM+APeHAhj4m9Fs/vApiPtT3d78o1+k9AACAP3bxfj2nw4Y+wlJcP7wKYj7U93e/KNfpPQAAgD/aQ3w9bcaGPluxXD+8CmI+1Pd3vyjX6T0AAIA/oEhePZ4biT41iF4/XFYyvpeqhb4mEXM/AACAP2wDWT1zrok+7YxeP1xWMr6XqoW+JhFzPwAAgD+rjlM9eTuKPk2QXj9cVjK+l6qFviYRcz8AAIA/LtZCPXfsjD79ols/PKEoP7aILr808qI+AACAP8r1SD1w8ow+mt5aPzyhKD+2iC6/NPKiPgAAgD+tFU89dfiMPjoaWj88oSg/toguvzTyoj4AAIA/4jWJPXo+hj6GG1g/375Iv2DcCr/uVZq+AACAP6oGjT3z5IQ+yBRYP9++SL9g3Aq/7lWavgAAgD9wEI49/HyEPuYbWD/fvki/YNwKv+5Vmr4AAIA/5OJ1PZS5gz7U914/97Fnvryyd7/0++W9AACAP7ZqcD07t4M+R7JfP/exZ768sne/9PvlvQAAgD9LF289MbmDPpLUXz/3sWe+vLJ3v/T75b0AAIA/fb92PQ8GjT6mfFY/hxM2v+3jKr93l2G+AACAP41KdT1tVI0+K1FWP4cTNr/t4yq/d5dhvgAAgD8CoXQ9B4+NPpgaVj+HEza/7eMqv3eXYb4AAIA/nb+OPf0bjD48DFA/29I1v7kUKr8LSG6+AACAPwyzjz1Z3Ys+yAhQP9vSNb+5FCq/C0huvgAAgD8jH5Q9LauKPu8NUD/b0jW/uRQqvwtIbr4AAIA/cAagPUnKgz4tcVM/r/4Ev2l+V7/3PRa+AACAP5E4nj2hxoM+GEhUP6/+BL9pfle/9z0WvgAAgD+qapw9+cKDPgUfVT+v/gS/aX5Xv/c9Fr4AAIA/FSuIPSOOij4IB1U/DUY3vzhuKb+xr2O+AACAP2mIhz2FvYo+/AFVPw1GN784bim/sa9jvgAAgD+pAoc9IOuKPvHzVD8NRje/OG4pv7GvY74AAIA/9sSPPSWsij5rzFE/zkc3vxloKb/+4WO+AACAP5A6kD1Uk4o+B8JRP85HN78ZaCm//uFjvgAAgD+VtJA9gXaKPtC7UT/ORze/GWgpv/7hY74AAIA/ovuaPRlJhj7slVI/J1F2P6wDsz32G4Q+AACAP6EVmj14R4Y+aAFTPydRdj+sA7M99huEPgAAgD+YL5k91kWGPuhsUz8nUXY/rAOzPfYbhD4AAIA/rYeMPc5eiT4UCVU/p5s4vxeHKr/9+0K+AACAP2lZij179ok+DghVP6ebOL8Xhyq//ftCvgAAgD+6SZI9Qr6IPhhoUz+nmzi/F4cqv/37Qr4AAIA/NoiHPcUZjD4vd1A/sCM2v8HQKr8Fr2G+AACAP7wZiD10DIw+n1BQP7AjNr/B0Cq/Ba9hvgAAgD/j0Ig9H/KLPpMuUD+wIza/wdAqvwWvYb4AAIA/tNShPaR1gz6NYVA/nqBev8+M476FHly+AACAP9DCoT3PSoM+4ZZQP56gXr/PjOO+hR5cvgAAgD9wcaE9WzyDPvnOUD+eoF6/z4zjvoUeXL4AAIA/J/SOPcGJhT5DgFY/hSsnvt67C75XI3o/AACAPxxaiz3B04Y+DYRWP4UrJ77euwu+VyN6PwAAgD8MfYc9wBCIPoeFVj+FKye+3rsLvlcjej8AAIA/W4+vvBdChT5YP2s/BUTvvqzqDL8XGzE/AACAPzJNx7yESYU+AMJqPwVE776s6gy/FxsxPwAAgD8GtN68uUGFPnFAaj8FRO++rOoMvxcbMT8AAIA/XuYMveb1iT6472Q/itB6v8dbLr4r2de9AACAP1W8DL04w4o+cTFkP4rQer/HWy6+K9nXvQAAgD9qjwy9/o6LPr1yYz+K0Hq/x1suvivZ170AAIA/9GpTvJa0jj7kc2Q/ev2lPlNjCz+SCUa/AACAP1EhIrxRuI4+1MdkP3r9pT5TYws/kglGvwAAgD+WRN67YpWOPgYRZT96/aU+U2MLP5IJRr8AAIA/l+2guwpEiD7Sj2o/DMZvPz6Flz6cCkA+AACAPyYBobvgaYc+tzxrPwzGbz8+hZc+nApAPgAAgD8mFKG7tY+GPpfpaz8Mxm8/PoWXPpwKQD4AAIA/l6HAvA3Yhz5u/Wg/7YP5vqL/+b4iVDk/AACAP0eBzLwy3Ic+4r5oP+2D+b6i//m+IlQ5PwAAgD/bX9i84N+HPjSAaD/tg/m+ov/5viJUOT8AAIA/6+7evG4viz4MpGU/MFOzPoLMVr8SJtW+AACAP7Sp3rwIkYs+gkNlPzBTsz6CzFa/EibVvgAAgD8l+92817CLPgooZT8wU7M+gsxWvxIm1b4AAIA/3qpcvB+8jD7PdWY/jaVcPuTKYb/wk9a+AACAP2cUWLxhu4w+BoBmP42lXD7kymG/8JPWvgAAgD9vEVS8mraMPk2NZj+NpVw+5Mphv/CT1r4AAIA/BNJLvKCUiD4C2Gk/QFY3vzeJBT5xhi8/AACAP/wvorw8W4o+GLVnP0BWN783iQU+cYYvPwAAgD/pp5u7htKEPuZBbD9AVje/N4kFPnGGLz8AAIA/tfbtvPNUhD6YbWk/iSTiPsibPL9OEAO/AACAP3ggAr22OYQ+WudoP4kk4j7Imzy/ThADvwAAgD9xzQO9sTmEPj3QaD+JJOI+yJs8v04QA78AAIA/23kIvdV4iz72eWI/CrnwPib9R7+nRdK+AACAP5rfB71SvIs+z0RiPwq58D4m/Ue/p0XSvgAAgD/7NAa9mgmMPtYZYj8KufA+Jv1Hv6dF0r4AAIA/f0DFu7WPjT6z4mQ/WEmTPbnMZ7+GKNa+AACAP7YFtbt/fo0+6PpkP1hJkz25zGe/hijWvgAAgD9E0qe7UmeNPogYZT9YSZM9ucxnv4Yo1r4AAIA/mJ5svQUZhT6MaWA/UpstP/y5Hb/6H82+AACAPxJxbr1m4YQ+92JgP1KbLT/8uR2/+h/NvgAAgD+DUHC9X7GEPixVYD9Smy0//Lkdv/ofzb4AAIA/HzSSvUbZgz7vKlk/LKBIP1PWCr/5Cpu+AACAP33Lkr2n5IM+xu9YPyygSD9T1gq/+QqbvgAAgD/JB5O9sw+EPrm1WD8soEg/U9YKv/kKm74AAIA/ae5lvcmfjT6dWVg/UDEZP6kkPb++p56+AACAP8X3Y73IvI0+tnNYP1AxGT+pJD2/vqeevgAAgD9sP2K9Yc6NPuKTWD9QMRk/qSQ9v76nnr4AAIA/EMslvXT0jD7SUGA/jqfwPu8MSL+XHdK+AACAP+uLJ71QpIw+/nxgP46n8D7vDEi/lx3SvgAAgD9PRCq9n1GMPt+ZYD+Op/A+7wxIv5cd0r4AAIA/CY1xvX7Rhj7CK14/Ie4pPlv4e7+FC3m9AACAP8U6dL26zoY+Kc1dPyHuKT5b+Hu/hQt5vQAAgD9u6Ha998uGPo1uXT8h7ik+W/h7v4ULeb0AAIA/K7mDvTV+hz5+XFo/HaWBviYqYj7QHXG/AACAP8h7gb2uHIg+zltaPx2lgb4mKmI+0B1xvwAAgD+hc3695LmIPtFaWj8dpYG+JipiPtAdcb8AAIA/OK9dvSOViz7GwVs/eyjGPtk4Zz8J+j2+AACAP2eRWr0Fk4s+pSRcP3soxj7ZOGc/Cfo9vgAAgD+Ec1e95pCLPoOHXD97KMY+2ThnPwn6Pb4AAIA/ekhevZ0biT41iF4/Q1tAPqvvi77/gnE/AACAP+0fY71he4g+a4BeP0NbQD6r74u+/4JxPwAAgD/S7me9+NmHPlt4Xj9DW0A+q++Lvv+CcT8AAIA/18+EvRV+gz7s/Vs/LTPuPowRWz833me+AACAP6JGh739boM+ZT9bPy0z7j6MEVs/N95nvgAAgD+FvYm96V+DPuGAWj8tM+4+jBFbPzfeZ74AAIA/x9NvvSkjiz6WGFg/jdCxPrUiwL5wAVy/AACAP9idZr1gSow+sBNYP43QsT61IsC+cAFcvwAAgD+VhmS9qn6MPsoVWD+N0LE+tSLAvnABXL8AAIA/45spvc+8jD4Fr14/PHo7P7eyBr+QT92+AACAP23+Ir3dpow+s29fPzx6Oz+3sga/kE/dvgAAgD+RXyG9d46MPnqqXz88ejs/t7IGv5BP3b4AAIA/xeCXvchHhD6YiFY/rVlNP6gRDr8jsmG+AACAP8K6mL0GDoQ+I25WP61ZTT+oEQ6/I7JhvgAAgD/3fpm9l+KDPo9LVj+tWU0/qBEOvyOyYb4AAIA/0BykvUb8hD7TElA/BntMPz97D78eB2C+AACAP9ofo719XIU+BQtQPwZ7TD8/ew+/HgdgvgAAgD/mYp+9ybCGPtoLUD8Ge0w/P3sPvx4HYL4AAIA/ldKCveJFjT4QGlM/CUIHP8WjTT94w4y+AACAPx0xgL3lao0+6vFTPwlCBz/Fo00/eMOMvgAAgD8yH3u95I+NPsLJVD8JQgc/xaNNP3jDjL4AAIA/ZjqUvTLNhj45BFU/uEJNPxqPDr8LB16+AACAPw+rlL0Zp4Y+EQFVP7hCTT8ajw6/CwdevgAAgD/7HJW9qISGPqP4VD+4Qk0/Go8OvwsHXr4AAIA/kOabvUmGhj6D21E/7n9MP8KLD7+yFV++AACAP0+cm70Hr4Y+HMlRP+5/TD/Ciw+/shVfvgAAgD+qM5u9Vt2GPnu9UT/uf0w/wosPv7IVX74AAIA/a2GNvdjmij7zalI/Z4rjPL23fj/dqcS9AACAP48QjL1T+Yo+4NZSP2eK4zy9t34/3anEvQAAgD+vv4q9zQuLPspCUz9niuM8vbd+P92pxL0AAIA/0oOQvcMciD7WB1U/EXRMP7CaD7/yKV++AACAPyNfkr38dIc+BwZVPxF0TD+wmg+/8ilfvgAAgD+lSZK9Qr6IPhtoUz8RdEw/sJoPv/IpX74AAIA/YHGhvVw8gz75zlA/uaJeP9mF475HGVy+AACAP8DCob3PSoM+4ZZQP7miXj/ZheO+RxlcvgAAgD+k1KG9pHWDPo1hUD+5ol4/2YXjvkcZXL4AAIA/09CIvR/yiz6TLlA/vxk2P3HeKr+RiWG+AACAP6oZiL1zDIw+n1BQP78ZNj9x3iq/kYlhvgAAgD8miIe9xRmMPi93UD+/GTY/cd4qv5GJYb4AAIA/E+l9vathij44gVY/4KY7vlZkHj6wh3i/AACAP244g70lOYk+XYNWP+CmO75WZB4+sId4vwAAgD/7fIe9wBCIPoeFVj/gpju+VmQePrCHeL8AAIA/';